" XSS易容術---bypass之編碼混淆篇+輔助腳本編寫"
一、前言
本文原創作者:vk,本文屬i春秋原創獎勵計劃,未經許可禁止轉載!
很多人對於XSS的了解不深。
一提起來就是:“哦,彈窗的”、”哦,偷cookie的。”
騷年,你根本不知道什麽是力量。雖然我也不知道,哈哈。
好了,不瞎扯了,進入今天的主題:
XSS易容術---bypass之編碼混淆
二、正文
1、總括
很多時候,我們的一些關鍵字被過濾。
直接閉合前面payload,插入測試語句<script>alert(/xss/)</script>,
是彈不出窗的。
原因有很多,過濾方式也有很多,所以繞過的姿勢自然也不少。
但並不是什麽情況都能繞過的,例如:
1 2 3 |
<div>
<?php echo htmlspecialchars($_POST[ ‘xss‘ ]); ?>
</div>
|
接收過來的數據,被php函數htmlspecialchars處理
這個函數是轉實體,轉實體後,你再怎麽折騰,也繞過不了。
2、xss常用的編碼
第一個,html實體編碼,例如:alert()
第二個,進制類,例如:\x61\x6c\x65\x72\x74\x60\x78\x73\x73\x60,某些時候,也有不帶x,例如:\5c\6a
第三個,Unicode,例如:\u0061\u006c\u0065\u0072\u0074\u0060\u4e2d\u6587\u4e5f\u53ef\u4ee5\u0060
第四個,純轉義,例如:\‘ \" \< \> ,這樣的在特殊字符前加\進行轉義。
先變個魔術,猜猜這樣的代碼能不能成功彈窗。
1 |
<img src= # onerror=eval("\x61\x6c\x65\x72\x74\x28\x2fxss/)")>
|
|
|不
|準
|偷
|看
|
|
|
|
好吧,可以彈窗如圖:
那這樣呢:
1 |
<img src= "javascript:alert(1)" >
|
|
|
|
|不
|準
|偷
|看
|
|
|
|
|
|
|
是不行的哦!你可以自己試試
是不是顛覆了你的xss觀。
什麽?js偽協議不能用了?
哈哈,其中奧妙無窮,跟我一起來探索吧。
3、編碼的正確使用姿勢。
3.1 總論
我相信很多人都知道,是有那麽幾個編碼是運用在xss的bypass裏的(bypass就是繞過)
但是具體怎麽用,什麽時候用,在哪裏用,並不清楚。
這可是有講究的,瞎用的話瀏覽器可不幫你解析。
除非你有這個工具:
它會告訴你什麽時候,用什麽編碼,輔助你學習。
什麽?這個工具在哪?
額,沒錯,這是筆者自己寫的,在後面會放出源碼~~
好了廢話不多說,總結如下:
3.2 編碼運用總結
html標簽中:
- html中當然會支持html實體編碼,例如=,也有<
- 支持十六進制,但是要以&#x開頭,其中x大寫小寫無所謂。
- 支持十進制,要以&#開頭,註意,沒有x哦。
- 支持數字部分高位補充0,例如=,=這兩是一樣的。
- 可能你已經發現了,後綴有沒有; 都無所謂
javascript中:
- eval函數裏,支持十六進制,但是要以 \x 開頭,x只能小寫!必須兩位,例如:\x5c
- eval函數裏,支持八進制,但是要以 \ 開頭。必須兩位,例如:\134
- eval函數裏,還支持\u前綴的unicode,本質是:16進制的ascii碼。必須是四位,例如:\u005c
註意了,這個可和html實體編碼不一樣,對格式比較嚴格,不能隨便在數字部分補充0。
聰明的童鞋可能已經發現了:
為什麽第一個說的是html標簽,第二個沒說script標簽呢?
以為js代碼不一定要在script標簽中啊。
比如這個:
1 |
<img src= # onerror=alert(/xss/)>
|
這就是在on事件中。
這樣會出現什麽有意思的事情呢?
細心的同學也許發現了,沒錯,是混合雙打:
img是html標簽,裏面用html編碼是沒問題的,而on事件裏面可以直接解析js代碼,
於是我使用eval函數,然後用js支持的編碼替換內容,一樣可以成功彈窗。
復雜使用起來就如一開始那副圖那樣,用了多種編碼。
也可以這樣:
書上還有說css裏支持\開頭的十六進制,但是筆者實驗沒有成功。Orz(ps:書比較舊,現在瀏覽器不支持很正常)
4、獻上輔助腳本源碼(html+js)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>xss編碼轉換器</title> <script> //提示框 function tips(param){ str=document.getElementById(‘tip‘); switch(param){ case "&#": str.innerHTML="提示:這個前綴只在html標簽裏才有效哦"; break; case "bfstrin": str.innerHTML="提示:對對,就是這裏,輸入需要編碼的字符吧,例如:alert()"; break; case "bfstrout": str.innerHTML="提示:寫好要轉碼的字符了吧,選擇前綴後綴,以及位數哦。"; break; case "\\x": str.innerHTML="提示:這個前綴在eval裏面有效哦,註意:必須選擇16進制。"; break; case "\\u": str.innerHTML="提示:這個前綴在eval裏面有效哦,註意:必須選擇16進制,只能是四位(自動改好)。"; break; case "\\": str.innerHTML="提示:這個在css裏面有效哦,但是只要ie6以前的瀏覽器才支持,Orz。"; break; case "%": str.innerHTML="提示:這個放在url裏有效哦,%bf%27可是能幹掉GBK的。"; break; case " ": str.innerHTML="提示:這個。。你竟然不要前綴了。"; break; case "af": str.innerHTML="提示:這個只能配合&#用,而且可有可無。"; break; case "jz": str.innerHTML="提示:想換什麽進制,eval只支持8進制和16進制,html標簽支持10進制和16進制。"; break; case "num": str.innerHTML="提示:html實體編碼(&#)裏面,ascii碼前面可以任意插0,別的都不行。"; break; case "go": str.innerHTML="提示:期待很久了吧,那啥,那個,失敗了也和我沒關系。。"; break; case "no": str.innerHTML="提示:別,千萬別,別按這個按鈕,地球會毀滅。"; break; } } //獲取參數 function getparam(){ var bf=document.getElementById(‘bf‘).value; var af=document.getElementById(‘af‘).value; var jz=document.getElementById(‘jz‘).value; var num=document.getElementById(‘num‘).value; var param=[]; param[0]=bf; param[1]=af; param[2]=jz; param[3]=num; return param; } //取數,轉ascii function enasc(){ enstr=document.getElementById(‘bfstr‘).value; var bfstrarr=new Array(); for(i=0;i<enstr.length;i++){ tmpstr=enstr.substr(i,1); bfstrarr[i]=tmpstr.charCodeAt(); } return bfstrarr; } //編碼主函數 function enxsscode(){ var param=getparam(); var bfstrarr=enasc(); var destr=""; for(i=0;i<bfstrarr.length;i++){ bfstrarr[i]=bfstrarr[i].toString(param[2]); //換進制 var bu=0; if(param[0]=="\\u") bu=4-String(bfstrarr[i]).length+1; else bu=param[3]-String(bfstrarr[i]).length+1; if(param[2]==16 && param[0]=="&#") destr+=param[0]+"x"+new Array(bu).join(‘0‘)+""+bfstrarr[i]+""+param[1]; else if(param[2]==16 && param[0]=="\\u"){ destr+=param[0]+new Array(bu).join(‘0‘)+""+bfstrarr[i]+""+param[1]; }else{ destr+=param[0]+new Array(bu).join(‘0‘)+""+bfstrarr[i]+""+param[1]; } var afstr=document.getElementById(‘afstr‘); afstr.value=destr; } } </script> </head> <style> #bg{ text-align: center; margin:0 auto; border:2px ridge red; width:1200px; height:700px; } #header{ background: #2f2f2f; border-bottom: 7px solid #a1cc33; height:60px; padding-top: 10px; } #left{ float: left; border: 2px solid black; width: 500px; height: 500px; margin-left: 50px; margin-top: 20px; } #right{ float: right; border: 2px solid black; width: 500px; height: 500px; margin-right: 50px; margin-top: 20px; } #mid{ float: left; border: 2px solid green; width: 70px; height: 500px; margin-left: 10px; margin-top: 20px; } #tip{ margin-top: 15px; margin-bottom: 0px; height: 20px; text-align: center; color: red; } .param{ margin-left: 2px; width: 55px; } </style> <body> <div id="bg"> <div id="header"> <h1 >XSS編碼轉換器</h1>-made by vk </div> <!--主體 --> <form action="" method="post"> <div id="tip"> 提示:左邊區域輸入待轉碼的字符 </div> <div id="left"> <textarea name="bfstr" id="bfstr" cols="30" rows="10" ></textarea> </div> <div id="mid"> <p >前綴:<br></p> <select name="bf" id="bf" class="param"> <option value="&#">&#</option> <option value="\u">\u</option> <option value="\x">\x</option> <option value="\">\</option> <option value="%">%</option> <option value=" "> </option> </select> <br><br> 後綴: <input type="text" id="af" name="af" value=";" class="param" /> <br><br> 進制: <select name="jz" id="jz" class="param"> <option value="8">8</option> <option value="10">10</option> <option value="16">16</option> </select> <br><br> 位數: <input type="text" id="num" name="num" value="4" class="param" /> <br><br> <input type="button" id="" name="" value="編碼-->" class="param" /> <br><br> <input type="button" id="" name="" value="<--解碼" class="param"/> <br><br> <input type="button" id="" name="" value="jsfuck" class="param" /> </div> <div id="right"> <textarea name="afstr" id="afstr" cols="30" rows="10" ></textarea> </div> </form> </div> </body> </html>
" XSS易容術---bypass之編碼混淆篇+輔助腳本編寫"