文件上傳漏洞的定義
文件長傳漏洞是指攻擊者上傳了一個可執行的文件到服務器並執行。這里上傳的文件可以是木馬、病毒、惡意腳本或這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、隱藏文件路徑,將用戶上傳文件的路徑保存在數據庫中,並且在需要的時候再去讀取加載。