
文件上传是Web应用的必备功能之一!
如果服务器配置不当或者没有进行足够的过滤,Web ⽤户就可以上传任意⽂件,包括恶意脚本⽂件,exe 程序等等,这就造成了⽂件上传漏洞。
漏洞的成因
服务器配置不当
Web 应⽤开放了文件上传功能,没有对上传的⽂件做⾜够的限制和过滤。
在程序开发部署时,没有考虑到系统的特性或组件的漏洞,从⽽导致限制被绕过。
漏洞危害
上传漏洞最直接的威胁就是上传任意⽂件,包括恶意脚本、程序等。
直接上传后门文件,导致网站沦陷。
通过恶意⽂件,利⽤其他漏洞拿到管理员权限(提权),导致服务器沦陷。
通过文件上传漏洞获取的网站后门,叫WebShell。
WebShell是一个网站的后门,是一个命令解释器。通过Web方式(HTTP协议)传递命令消息到服务器,并且继承了Web用户的权限,在服务器端执行命令。
WebShell从本质上讲,就是服务器端可运行的脚本文件,后缀名通常为:
.php.asp.aspx.jsp...WebShell通常接收来自于Web用户的命令,然后在服务器端执行!
网站木马、木马后门、网马
小马:或一句话木马,与中国菜刀配合。
特点:短小精悍,功能强大!
三大基本功能:文件管理、虚拟终端、数据库管理
中国菜刀、蚁剑、冰蝎,CKnife ......




一句话木马:


10版本:




16版本:
蚁剑:

大马:与小马相比,代码量比较大。
Windows Server 2008







GetShell
GetShell是获取WebShell的过程或结果!
文件上传漏洞的利用是GetShell的主要方式,但不是唯一手段。
文件上传漏洞的攻防
黑名单策略,类似一个列表,在列表中写一些规则和条件。
黑名单就是非法条件,白名单就是合法条件。
黑名单:
$deny_ext =array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".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");代码审计:
对文件上传做过滤
限制文件类型


查看源代码,发现只对文件类型进行检测:
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 ) ) { echo 'Your image was not uploaded.';}else { // Yes! echo "{$target_path} succesfully uploaded!";}}else { // Invalid file echo 'Your image was not uploaded. We can only accept JPEG or PNG images.';}}上传的⽂件没有重命名Content-Type 类型⽩名单判断Content-Type 类型客户端可控(客户端⽤户可以修改此类型)可以利⽤Burp Suite 抓包、改包

⽂件后缀名和⽂件内容检测
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 'Your image was not uploaded.'; else { // Yes! echo "{$target_path} succesfully uploaded!"; } } else { // Invalid file echo 'Your image was not uploaded. We can only accept JPEG or PNG images.'; }}代码审计:
检测Token 值,防⽌数据包重放⽂件重命名⽂件后缀名⽩名单检测Content-Type 类型⽩名单检测⽂件内容头部检测⼆次渲染,⽣成新⽂件删除缓存⽂件图片木马:
图⽚⽊⻢没有办法直接利⽤,需要配合其他漏洞。但是需要知道的是,图⽚⽊⻢中包含了恶意代码!
copy imgName/b+yjh/a newImgName制作图片木马:
合并:正常图片+一句话木马




上传成功,需要利用此漏洞,需要结合其他漏洞,比如,文件包含!

其他方法:
windows 7或windows 2008下




完全防御


源代码
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 phpImagick 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 "${target_file} succesfullyuploaded!"; } else { // No echo 'Your image was not uploaded.'; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo 'Your image was not uploaded. We can only accept JPEG orPNG images.'; }}// Generate Anti-CSRF tokengenerateSessionToken();?>代码审计:
检测Token 值,防⽌数据包重放⽂件重命名⽂件后缀名⽩名单检测Content-Type 类型⽩名单检测⽂件内容头部检测⼆次渲染,⽣成新⽂件删除缓存⽂件Content-Type:用于定义网络文件的类型和网页的编码,告诉文件接收方将以什么形式、什么编码读取这个文件!
⽂件上传漏洞利用的条件
前提条件
Web 服务器开启⽂件上传功能,Web ⽤户可以使⽤该功能。Web ⽤户(www-data|apache)对⽬标⽬录具有可写权限,甚⾄具有执⾏权限。⼀般情况下,Web ⽬录都有执⾏权限。"完美利⽤" 意味着⽂件可以执⾏,也就是说代码可以被服务器解析。服务器开启了PUT ⽅法。GetShell 的⼀些影响因素
以 upload-labs 来探讨相关问题

Pass-01:

其他可执⾏的⽂件后缀名
php
php|php5|php4|php3|php2|php1html
html|htm|phtml|phtasp
asp|aspx|asa|asax|ascx|ashx|asmx|.cerjsp
jsp|jspa|jspx|jsw|jsv|jspf|.jtml.htaccess 攻击
.htaccess 是 Apache 服务器分布式配置⽂件,通过它可以实现Web服务器中的文件的解析方式、重定向等配置!
如果某⼀个⽬录下存在该⽂件, .htaccess ⽂件中的配置会覆盖掉 Apache 全局配置⽂件!(可以实现将扩展名.jpg/.png等文件当作PHP文件解析!)
httpd.conf 的配置,作⽤域是当前⽬录及其⼦⽬录有效。
此处想象空间⾮常⼤。
- 开启.htaccess的配置
Options FollowSymLinks AllowOverride None 改为Options FollowSymLinks AllowOverride All
- mod_rewrite.so的注释去掉,开启rewrite模块!
LoadModule rewrite_module modules/mod_rewrite.so- .htaccess文件上传配置
两种方法将其他扩展名的文件当作代码来解析:
指定文件名
指定文件后缀
将 .jpg ⽂件当做 PHP ⽂件解析
AddType application/x-httpd-php .jpg匹配固定的⽂件名
SetHandler application/x-httpd-php⽂件名中包含php 关键字
4.php.png
AddHandler php5-script php系统特性
忽略⼤⼩写
1. 脚本程序对⼤⼩写敏感,PHP 和php 是完全不同的两个⽂件后缀名。2. Windows 系统对⼤⼩写不敏感。忽略⽂件名末尾的点
# windows[info.php.] -> [info.php]忽略⽂件名末尾的空格
# windows[info.php ] -> [info.php]数据流 ::$DATA
# windows# 数据流会被系统忽略[info.php::$DATA] -> [info.php]文件截断上传
PHP特性:00截断
当PHP的版本低于5.3.4时,会把%00当作结束符,导致后面的数据直接忽略!
(当函数读到 0x00(%00) 时,会认为文件已经结束!)
理解:
比如上传:tony.php%00.jpg
- .jpg是合法后缀名
- 服务器端在保存.jpg时,函数会认为%00是终止符,于是保存的是tony.php!
注意:可以将%00进行URL编码
竞争条件文件上传
多个线程在没有进行锁操作或者同步操作的情况下同时访问同一个共享代码、变量、文件等,运行的结果依赖于不同线程访问数据的顺序!
理解:
不作同步或锁操作:
一个线程允许上传任意文件,另一个线程检查文件是否包含WebShell等!
存在文件已经上传,但检查不是太及时!中间存在时间差,这个时候,就可以被利用!
总结
绕过
- 前端JS检测绕过
// 删除检测代码(浏览器插件可以实现)// 修改为允许上传的文件后缀名,BP抓包,修改为可执行的文件,再放行!2 .文件后缀绕过
// 修改服务器的配置文件,允许能够解析可执行的文件!// Apache的解析顺序,从右到左,直到能够识别!// test.php.xxxx,如果xxxx不能识别,但识别了.php,就当php文件解析!- 文件类型绕过
Content-Type // 修改为允许的上传类型(通过客户端传输,可以修改!)- PHP%00截断
PHP版本小于5.34,PHP的magic_quotes_gpc为Off状态!
- 竞争条件绕过
利用BP中的Intruder功能不断发送上传文件的请求,消耗服务器端的资源,让检查线程不能及时检查上传是否合法!
防御
- 白名单限制上传的类型(客户端检测)
- 服务器端文件检测
- 对上传的文件进行随机重命名,指定文件的扩展名!
- 对上传的文件,就行权限管理,可以去掉文件可执行权限!
......