文件上传漏洞的定义
文件长传漏洞是指攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马、病毒、恶意脚本或这Webshell等。
文件上传漏洞条件
- 上传的文件能被Web服务器当做脚本来执行
- 我们能够访问到上传文件的路径
服务器上传文件命名规则
- 第一种:上传文件名和服务器命名一致
- 第二种:上传文件名和服务器命名不一致(随机、时间日期命名等),但是后缀一致
- 第三种:上传文件名和服务器命名不一致(随机、时间日期命名等),后缀也不一致
漏洞成因
由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致用户可以越过其本身权限向服务器上传可执行的动态脚本文件。
一般我们会利用文件上传漏洞上传一句话木马,然后菜刀连接过去webshell。要想获取webshell,必需让我们上传的文件当成脚本文件执行,所以文件上传漏洞通常会和文件包含漏洞和文件解析漏洞一起利用。
文件上传中的可控点
POST /DVWA/vulnerabilities/upload/ HTTP/1.1 Host: 127.0.0.1 Content-Length: 5108 Cache-Control: max-age=0 Origin: http://127.0.0.1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJUcYpiAjyVAzt5yA Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Referer: http://127.0.0.1/DVWA/vulnerabilities/upload/ Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.8 Cookie: security=low; PHPSESSID=plp6nm81is9eotcvfo3td8thp4 Connection: close ------WebKitFormBoundaryJUcYpiAjyVAzt5yA Content-Disposition: form-data; name="MAX_FILE_SIZE" 100000 ------WebKitFormBoundaryJUcYpiAjyVAzt5yA Content-Disposition: form-data; name="uploaded"; filename="timg.jpg" Content-Type: image/jpeg ?? JFIF H H ? C "" $(4,$&1'-=-157:::#+?D?8C49:7? C 7%%77777777777777777777777777777777777777777777777777? ? ?" ? ? < !1A"Qa?25Tqs惭#B伇%3R懥$b?? ? ? ? 騦O?昘? 無舧??X讃鞳氾簂O跁? QC +琸仅w?碑髭?遲 ???X?園gX讃鞳氾篯c]锏>k捐F溵t€灡跓5遲齝]锏>k捐['?:驶?|讅吁峸驹瑨浩贿*<讅觰峸驹瑸??飣]鱇琸仅w?d諤OX鞳氾篯c]锏>k捐k'?#]锏>k鹃浩贿j|讅婿J??飣]鱉?摞S婊顔I=c_味w?X鞳氾?2浩贿j|讅?F贿j|讅兄J?? }]鱅 ?qC筷(v洟1OjU鼸4@VI^?pwk?枂箥-惮B薫!闻椄輐-?3樒?TS?ィ挩c兙+nH蚥34?溒0椓'ON苎籖?+€Od??虹?l晽VJ?Od鯧K 嫔?Σ钌瑏瑲刷汥Bg7N鉧~h?5勈骽歧??Ml-偐癯`嚥)桰?I$?妠R崇筷(TV)鞪蠟 ā怹p?臋藩F玗$A?肴,n[謕弟輊縨媩B w瑘t叜m??H檌钜?? "﹖r熪~h%闕荛cs咁"綆Зtn得?镺╩<O#V?挒j陂r鬁?(28?涫 ?zoE旒W I胰"s躻qM核猋s辙踃?Um眯AW7T7T牞l哒J协}oG杵Zk?興*?k贓宦\nS @罔S硙Jb々??k-m!Ζd鄈n鬾"n岚粀顶I 8?jび+I笰嚹塽t? u惻M;篒d{嵥嵲Z?n檞k悋t?貗爲%薧??妠N崇筷(dV)鞪繛 ā~$呮)Y#t-7^烝X蕣H?n追_婒展郱?$匆礀Fn譡duY頇幐(H箰{味V36<位芠sY蘘⊿f|n称??璓?FK劝?<q脜P^F丳鞟? ?d?隊:(郯鎁f)\旯?nX涟?*$t?杠炩爗A7貶軤Z鸀錇?? ("腬)┾闈?┹D頫? P><嵏挖縭︶z散特? H? ?徟id宲7頭艈狁GN茊 2?Y癶K標;?蠺P狴镃^.\p煡鎠澦虚﹔45胑难4:?>x母v畷?7冚{ 埍_FW岚蛖被jl紱?q粢毆F鎬炑@P胾o|b<e?舢8G厛?/ |V3濘?琶]徽?Xj?op诌魽Q禁?侧們懜锖馕?Ym鮍N朔8?H,盿lR筷(0嵟渐W筮?惨?K⒛e? #逾iOG;楠c?鏇鑳驯 Dwq遁羉bj肤G? 娪?<Mk..諞愱I軤)祍:€>褍蘭N忥s$F踢揁塽瞇 嬷m儡)轸lG{黼-5PP郸0\l@??猼峽佧_f嫄?劙zz'-$|J储帓?? 愣b?Y^pe谾?h|\Q紴雛?C{rTmoL?籎驻lm蝅???PuP掴缘M灖餧v夼M屇铓??d挚#}応车帋HK3磦-蒣諺2zV?伝N儝梧?濬毖?w[1鏳E?觔6?~歳]t欈E鬦镡J]閿Vsy栮 爬騈街@A泘狢东?寢鞖倭??蹭鑰"?D袟<工k瓛@^)?繛 庤蘐 3嵇?關 澁焙骈酪?朅#E厤愪荜様VF咶锈(笰>冋?蟻梎袥璿留緵1悒n薣刟懶al崙唨蹫騏?硬★杅]逯?姑(汳N蒯vX€癿瑒??佈?3&疰c媆玉 頕1戜gg?@芜?锚k陉kz0'I踼H'焸紜崛?|糌?2?0s%臂??娪栖条_桻<oV姄H?;饭`|uQI1?x倥?┡?·閐依诹e遴y"宒s?p?捳p? 簴U梴仟轆<-V?c*~椬u赌OG隯肀%[侭)廌:9 ? k汮鴊戾鳡腷竻F ji?輲練? 脝bN姃z'M<靮妯粌橃妻逗-_a?尰;H繆筲1|9覥IQ408枑#???槙4??)s?@貄V~ e?u嗎c ?鉺+c:灋荩?N嫆?O 櫬? λΛ緄澂? 揓[-J:熾?姛鎢= QB⒈Oi拯鼾Et`BO衁 W/拮?cng 絆? 姙92鹡F??t筤姑韉4La芽涽AkP蝮殉?麜?;存 ;E_oi蜙.w$e瞯ZE佌櫎<kc!軍歛狡毁X敉teθ"|Ls3Xh袙K浌袿滈縡昝A{怗+???呡虜|qd?8闕豯妳蝧A(#滈`/嗒j)櫥q銾雬e崅啟&=弓n?D碞sA 轿攂s裈懭;絣闤?0=窥瞲?0傋7此鳡閎妳攽桤飊彗`卩rW钙 fO3籥筞掊煆A?/{?蹭裖PG}l摴4$Gv雮l蟀@骝??$蘌3??0踕F)?繛 ā?pu]懅睿貸涡?A>閼憓%滕 qfe燹芟舮?F鱑0啋{伈?"D\嬢敖伕鏆0cy衱?#癴?樘f遣-餈?祷惰豮E??T>8吵Kk⑩灡畞?5T挵A)MXE?石〃鏩蘾vm@; 7嵂麵3^琺m?獙"燢H写`? i篙莮H"栁$8?|祦慸絹6nm?A娏僡s衷藭?釵p颺/嬹?堅=厅8蛋'Rz?Le@.x$蚝姶CR?貌??u庋?%古A醵贽泿+c襜逛[ˋ?酭SM#匾c#q穪Yh豌爹杲+琱8??郿菶箓贾P蔳?8胐汯釘澬帺`貟竨Q ( s璻嚚?3鮌簑涥=?I$€躎幋嵇?j壟-謺= QP7O?v摄qt?me o致&lO硑?誾?-鑉匕誼4蝹V溅膕银W?tq腎镠禍冄醏;报?d_L屎帹J纚裭炵D忠?g`-餢焊烠\??幵w栀膽?嵯 椤ip悅7讱f魄8?式砇鰑.YF:B摚攲靘阇倪A ,?熼?7? ?CT鴫?盳蔿[?詘+ 疋嫲T革V隆睬?犲籓"y 駫季:h捺?鬼鍉_韞孯本粶F郫H??榌[b? 9w蚞@粄@崏@}<s猕7a)Is.?€乁7膀|?韢??7[给 &偤\6?樜R ??涪艑JX郲 9??绠瓓枬畉?<?|??rFGl北栋A濰??扞 I$?1MqJ蠟 è『#???阱p醕e覿m呌蓃(8罬KS%<蹵???荡騖ギ稵胀xk?€S跳?崽/@?l?G+铈巊R冇ⅹ檫Sv?]?ㄓr?{%??v)丟(t?坖-俣硒? N偾燽戶UL滹镶<敌冗P肀氦?V壹蕉潬鋹n ?姮ET鉛D蜽?|ys婇鴟??&?歳?押?9幁qv桿8??[赕.iK奝鷝?"7cu伃?牁9僛;B<<Qt曺溋V3?{^(姪0?,O姞?乵 颾?I%KL苡6'J蟪.IWT?R蠽2纸溵兖沧`盧S4??oZ繻N吇奓F靛抎??勰琭!T晔瑟惠u┿m暪椹?b钞込 ?q@譒扝I$?扝臡盳繛 è/{YK婝V崇筷*炇?)狣躧儧w$騆伮2偖JY矰lPK爗衵??籧uウ锦^S脫=礩鹲[闖溊1W欅罡?屬爈y5???姼t蹄QL挢?y??殙聼彞壓Y肞?G?*?俩+s? ?日酺U氓玛?覑賄ME婤逩?懘?{M坠hめP菗??#A钁鲫?胡?3贬昦涝>:fZ盼:劾(?坈sa蘭轿涨歭B澩AWK鄡溮)扏扞$ $扏扞$b驹嵇?N+鞪蠟 āv@?偏涃t?m?€繹惊0磾?I?侚豯U?幦??€喑K?F?巑C乂尐格+藀犄A%舜裭0蘒???'H]适7蒩t1?hE鶢鄥拍dVU6&]伟裁阖¥樓軪宑2T?兖T图??遰u篻?Rhm?巋#ItB?I$?扞I$?姏鈺= QB騃$S穞扐+禘?s?€c,:?II$?lQt祇侤AI$?&邯贶NJ摡庸$怶扟.?H亿$?d7q!q狪 k慾I b?d扏埐d扏扞$? ------WebKitFormBoundaryJUcYpiAjyVAzt5yA Content-Disposition: form-data; name="Upload" Upload ------WebKitFormBoundaryJUcYpiAjyVAzt5yA--
其实对于整个HTTP请求包来说,所有内容都是用户可控的,只是请求包中的几个点有可能是后台服务器的检测重点,在上面的请求内容中,加粗加大的红色字体为可能的后台检测重点,主要有几处:
1. Content-Length,即上传内容大小
2. MAX_FILE_SIZE,即上传内容的最大长度
3. filename,即上传文件名
4. Content-Type,即上传文件类型
5. 请求包中的乱码字段,即是所上传文件的内容
6. 有可能存在请求包中的可控点还有上传路径,只是上面的示例中没有出现
文件上传的过滤方式
1、客户端JavaScript检验(一般只检验文件的扩展名)
应用程序在前端使用JavaScript检测上传文件的扩展名。
绕过方式:1、直接禁用本地js,不让其做检测.2、抓包,修改文件后缀名类型,绕过检测限制。
2、服务端后端检测
(1)文件类型content-type字段校验
MIME的作用:使客户端软件,区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。web服务器使用MIME来说明发送数据的种类, web客户端使用MIME来说明希望接收到的数据种类。
绕过思路:抓包,将Content-Type修改为服务端允许的类型。
(2)文件头类型检测
这个检测是利用getimagesize()函数来检测上传内容是否为图像以及图像大小。
文件头就是文件特定的标志,如二进制PE文件的4D5A,bmp文件的424D,zip文件的504B0304,各种常见文件的文件头类型大家可以查找了解一下,常见图片文件头如下:
gif: GIF89a
jpg,jpeg: FF D8 FF
png: 89 50 4E 47 0D 0A
绕过思路:上传木马恶意文件时,先使用编辑工具在数据最前面添加图片的文件头进行伪造,即可绕过。
(3)服务端文件扩展名检测
文件提交到后端,后端的函数对上传文件的后缀名进行检测,比如黑名单检测不允许上传.php、.asp后缀名格式的文件;白名单检测只允许上传.jpg格式的文件。
1、文件名大小写绕过(AsP, pHp等等)
2、黑白名单列表绕过(php、php2、php3、php5、phtml、asp、aspx、ascx、
ashx、cer、asa、jsp、jspx)cdx,
3、特殊文件名绕过
修改数据包里的文件名改为 test.php. 或者 test.asp_ (下划线是空格)由于
这种命名格式在windows系统里是不允许的。所以在绕过上传之后windows系统
会自动去掉 点和空格。Unix/Linux系统没有这个特性。
4、0x00截断绕过
5、.htaccess文件攻击(结合黑名单攻击)
主要介绍第五种绕过办法:
.htaccess文件攻击
如果Web服务器是Apache且黑名单没有对.htaccess做限制,那么可以上传.htaccess配置文件到目录中覆盖Apache的设置,可以通过配置执行webshell。
.htaccess文件攻击即结合黑名单攻击服务器的 .htaccess文件 。
通过move_uploaded_file函数把自己写的 .htaccess文件覆盖掉服务
器上的,这样就可以解析定义名单了。
.htaccess文件用处:
通过.htaccess文件调用php解释器去解析一个文件名中只要包含
“haha”这个字符串的任意文件,无论你文件名是什么样子,只要包
含”haha”这个字符串,都可以被以php的方式来解析。
.htaccess文件内容:
<FilesMatch “haha”>
SetHandler application/x-httpd-php
</FilesMatch>
黑名单绕过思路:可以从服务器的解析特性进行分析,如特殊可解析后缀php3,php7,phtml,jspx等 如特殊的解析方式陌生后缀名,带换行后缀名,双后缀名等解析差异造成的漏洞。 还可以从混淆方面出发,后缀名大小写,点绕过,空格绕过,以及上传.htaccess配置控制文件权限和::$DATA数据流的使用
白名单绕过思路:MIME绕过,修改文件类型为白名单可接受的类型,以及%00,0x00截断绕过,这种场景针对save_path可控。
00截断原理其实很巧妙,利用场景是文件保存路径可控,这样一来我们上传的文件符合白名单就行,真正动手的地方在文件保存路径出,可以放上自己的webshell文件,然后在webshell文件后面添加%00,或0x00,再加一些字符,这样一来,系统在解析碰到00就会截断,后面字符就不起作用,只剩下前面的webshell文件名,就可以在url中进行访问了。%00和0x00的使用区别在于提交get请求时,是%00,会进行url自动解码动作,然后进入验证函数。0x00则是post请求直接进入验证函数。
(3)服务端文件内容检测
比较厉害的防护检测,就是针对内容做检测,这种防护能力比较强,但也不是不能绕过。自始至终,攻防都是在对抗中螺旋演进的。
这种检测防护基本都是从webshell具有的代表性敏感字符?或者危险敏感函数。
绕过思路:从特殊敏感字符开始进行Fuzz测试,探测webshell中有多少必要的字符存在被替换,如果构成webshell执行的字符
被替换得较多,剩下未过滤的字符的难以支撑webshell执行,可以换个角度利用系统,调用脚本语言,如<script language='php'>system('ls');<script>。
还有一种更强的基于内容检测机制,对上传的图片进行二次渲染,参考代码如下
//判断文件后缀与类型,合法才进行上传操作 if(($fileext == "jpg") && ($filetype=="image/jpeg")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefromjpeg($target_path); if($im == false){ $msg = "该文件不是jpg格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagejpeg($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; }
主要就是后端调用了php的GD库,利用imagecreatefromjpeg()函数提取了文件中的图片数据,然后再重新渲染,这样图片中插入的恶意代码就会被过滤掉了,经过测试发现,不管是直接修改文件头制作图片马,还是利用copy命令制作的图片马,都无法避免其中的一句话被过滤掉。
绕过思路:借鉴二进制中钩子的思想,其实就是想在上传图片中找一块"地方",存储webshell,这块"地方"要求在后端处理后没有被过滤掉。那就上传一个正常的文件,然后下载下来,diff一下,查看哪些位置没有被改动过,然后添加webshell进行尝试。
服务器解析漏洞
Apache解析漏洞
漏洞原理
Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如 test.php.owf.rar “.owf”和”.rar” 这两种后缀是apache不可识别解析,apache就会把wooyun.php.owf.rar解析成php。
漏洞形式
http://www.xxxx.xxx.com/test.php.php123
其余配置问题导致漏洞
(1)如果在 Apache 的 conf 里有这样一行配置 AddHandler php5-script .php 这时只要文件名里包含.php 即使文件名是 test2.php.jpg 也会以 php 来执行。
(2)如果在 Apache 的 conf 里有这样一行配置 AddType application/x-httpd-php .jpg 即使扩展名是 jpg,一样能以 php 方式执行。
(3)Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
我们利用CVE-2017-15715,上传一个包含换行符的文件。注意,只能是\x0A,不能是\x0D\x0A,所以我们用hex功能在1.php后面添加一个\x0A:
然后访问/1.php%0A,即可发现已经成功getshell:
IIS5.x-6.x解析漏洞
使用iis5.x-6.x版本的服务器,大多为windows server 2003,网站比较古老,开发语句一般为asp;该解析漏洞也只能解析asp文件,而不能解析aspx文件。
目录解析(6.0)
形式:http://www.xxx.com/xx.asp/xx.jpg
原理: 服务器默认会把.asp,.asa目录下的文件都解析成asp文件。
文件解析
形式:http://www.xxx.com/xx.asp;.jpg
原理:服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件了。
解析文件类型
IIS6.0 默认的可执行文件除了asp还包含这三种 :
/test.asa
/test.cer
/test.cdx
畸形解析漏洞(test.jpg/*.php)
在IIS7.0中,默认Fast-CGI开启状况下,我们往图片里面写入下面的代码:<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[x])?>')?>将文件保存成test.jpg格式,上传到服务器,假设上传路径为/upload,上传成功后,直接访问/upload/test.jpg/x.php,此时神奇的畸形解析开始发挥作用了。test.jpg将会被服务器当成php文件执行,所以图片里面的代码就会被执行。
Nginx解析漏洞
解析:(任意文件名)/(任意文件名).php | (任意文件名)%00.php
描述:目前Nginx主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php
的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。
还有一种是对低版本的Nginx可以在任意文件名后面添加%00.php进行解析攻击。
文件上传的防御
1、文件上传的目录设置为不可执行
2、判断文件类型(使用白名单的方式,对于图片的处理,可以使用压缩函数或resize函数,在处理图片的同时破坏图片中可能包含的HTML代码)
3、使用随机数改写文件名和文件路径
4、单独设置文件服务器的域名
5、隐藏文件路径,将用户上传文件的路径保存在数据库中,并且在需要的时候再去读取加载。