XSS與字符編碼的那些事兒

0x00基本介紹


提起XSS 想到的就是插入字符字符編碼與各種解析了!

這也就是各種xss編碼插件跟工具出世的原因!之前不懂瀏覽器是如何對我們編碼過的代碼進行解析的時候就是一頓亂插!

各種編碼 各種插 沒把編碼還原就算了 還原了就算運氣好!後來到PKAV經過二哥和短短的調教後纔算是弄清楚了一點編碼與解析方面的知識!

現在也算是運用自如了把!

現在介紹一下在xss中最經常用到的編碼

html實體編碼(10進制與16進制):

如把尖括號編碼[ < ]  -----> html十進制: &#60;  html十六進制:&#x3c;

javascript的八進制跟十六進制:

如把尖括號編碼[ < ]  -----> js八進制:\74  js十六進制:\x3c

jsunicode編碼:

如把尖括號編碼[ < ]  ----->jsunicode:\u003c

url編碼 base64編碼:

如把尖括號編碼[ < ]  -----> url: %3C  base64: PA==

0x01 html實體編碼


html實體編碼本身存在的意義是防止與HTML本身語義標記的衝突。

但是在XSS中卻成爲了我們的一大利器,但是也不能盲目的使用!

html中正常情況只識別:html10進制,html16進制!

現在介紹一下我們應該如何在xss過程中靈活的使用各種編碼呢?

比如現在你的輸出點在這:

<img src="[代碼]">

在這裏過濾了script  < > / \ http: 以及各種危險字符 比如創建一個html節點什麼的!

有的站只允許你引用一個img文件夾裏的圖片 但是圖片是你可以控的 可以通過抓包來修改的!

我們如果想加載外部js 或者一個xss平臺的鉤子我們應該怎麼寫呢?

那麼我們可以在這裏 閉合雙引號 寫事件: οnerrοr=[html language="實體編碼"][/html][/html]

比如我現在彈個窗:

<img src="x" οnerrοr="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

原code:

<img src="x" οnerrοr="alert(1)">

這裏我用的是html十進制編碼 也可以使用十六進制的html實體編碼!

但是爲什麼這裏我沒有用jsunicode 以及 js八進制跟js十六進制呢!

瀏覽器是不會在html標籤裏解析js中的那些編碼的!所以我們在οnerrοr=後面放js中的編碼是不會解析 你放進去是什麼 解析就是什麼!

大多數網站是不會&#號的,如果過濾了怎麼辦呢?

那麼再來講一下另外一個案例:  enter image description here

源碼如下:  enter image description here

頁面中的Go按鈕中包含一個a標籤 輸入的值會存在於a標籤的href屬性中,href中用了javascript僞協議,可以在href跳轉時執行js代碼!

所以造成了xss!

我們提交的值如下:

wooyun%26%23x27,alert(1)%2b%26%23x27

由於頁面對單引號 & 符號 以及 #符號過濾!但是html中可以識別html實體編碼!但是實體編碼是由&#組成!

這個時候&#已經被過濾 我們只能通過url編碼來對 & # 兩個符號進行編碼!再讓瀏覽器解碼成 &# 然後拼接x27 最後就成爲了單引號的html16進制編碼!

解碼後:我們的提交值爲:

',alert(1)'

href代碼爲:

<a href="javascript:location='./3.3.php?offset='+document.getElementById('pagenum').value+'&searchtype_yjbg=yjjg&searchvalue_yjbg='">GO</a>

ps:在之前說了html標籤中識別html實體編碼,並且會在html頁面加載時會對編碼進行解碼!那麼&#x27 已經是單引號了 但是並不會閉合! 然後在點擊過程中執行javascript代碼 這個時候由於html裏&#x27被解析成單引號但是沒閉合 這個時候js被執行 這個我們提交的在html加載時解析成了字符串單引號但是不能閉合之前的引號 因爲現在是把我們提交的編碼了的單引號 當成字符串來顯示 但是現在他是存在於a標籤中的href裏的 href鏈接裏的地址是javascript僞協議,我們現在點擊的時候 會執行裏面的代碼 關鍵來了 這個時候我們之前被當做字符串的單引號 被再次解析 這個時候就沒任何過濾規則來過濾它 程序也沒那麼智能 之前當做字符串的單引號起作用了 javascript不知道他是個字符串 它只知道瀏覽器解析成了什麼 他就帶入進去!就在這個時候我們的字符串單引號就成功的閉合了!當點擊go時 我們的代碼執行!

上面這個例子講了html編碼 以及特殊情況下的編碼那麼再講下當你的輸入點存在於script標籤中的時候!我們就應該用js中的編碼了!

既然知道是如何解析的了 那麼便又有了以下新的想法!

0x02 新增的實體編碼,變異以及瀏覽器的某些工作原理


通常程序做 XSS 防禦的時候會考慮到一些 HTML 編碼的問題,會攔截或轉義 " \ 這樣的東西 那麼我的雙引號跟尖括號就被攔截了!

但基礎這種黑名單方式可能出現的問題:

1. 不認識 HTML5 新增的實體命名編碼,如

&colon; => [冒號]
&NewLine; => [換行]





case: <a href="javasc&NewLine;ript&colon;alert(1)">click</a>

2.對 HTML 編碼的解析規則不夠熟悉,就像十進制和十六進制編碼的分號是可以去掉的。

還有,數字編碼前面加「0」,這也是一條很好的繞過 WAF 的向量。

如下圖(我去掉了後面的分號 另外在每個數字前加了一個零):  enter image description here

數字前面是可以加多個0的 閒的蛋疼的基友可以自己試下!

<a href="javasc&NewLine;ript&colon;alert(1)">click</a> 

這句代碼能夠執行麼?

不知道那些不是很清楚瀏覽器工作原理的基友,在最開始有沒有懷疑這段代碼能不能執行!

起碼我最開始 懷疑過!即使編碼被解析回來了 換行了還能執行麼!

當時就去問了我的好基友 XX大神[一位跟短短一樣擁有着跟常用不一樣的思維 在我們看來是很不同於正常人的人]

然後大神給了我一份比較詳細的瀏覽器工作原理 很長很長!

我就把最主要的copy下來貼上吧!

解析器-詞法分析器 Parser-Lexer combination

解析可以分爲兩個子過程——語法分析及詞法分析

詞法分析就是將輸入分解爲符號,符號是語言的詞彙表——基本有效單元的集合。對於人類語言來說,它相當於我們字典中出現的所有單詞。

語法分析指對語言應用語法規則。

解析器一般將工作分配給兩個組件——詞法分析器(有時也叫分詞器)負責將輸入分解爲合法的符號,解析器則根據語言的語法規則分析文檔結構,從而構建解析樹,詞法分析器知道怎麼跳過空白和換行之類的無關字符。

然後我的理解是這樣的:

<a href="javasc&NewLine;ript&colon;alert(1)">click</a>

首先html編碼被還原出來 然後就成了換行 跟冒號

<a href="javasc
ript:alert(1)">click</a>  

爲什麼換行後還能夠執行 是因爲瀏覽器中的解析器中詞法分析器 起的作用會跳過空白跟換行之類的無效字符。

然後就構造成了一個完整的語句

<a href="javascript:alert(1)">click</a> 

代碼執行!

看完那些之後瞬間心裏覺得原來跟原理性相關的東西真的很重要!能夠讓你寫 xss payload更加靈活!

0x03 javascript編碼


javascript中只識別幾種編碼:Jsunicode js8進制 js10進制

就拿下面這個例子來講吧!

第一種情況 你輸入的值存入某個變量 然後最後出現在某個能把字符串當做js代碼來執行的函數裏!

如:

eval()  setTimeout()   setInterval()

以上都是會將字符串當做js代碼執行的函數! 如果是以下情況:

var search = "可控點";
document.getElementById().innerHTML=search;

以上情況很多都是出現在你搜索後 然後顯示的 你所查詢的關鍵字

如果過濾了 <> ' " & % 等等這些!然後再輸出到頁面上!

按理說這樣是安全了!但是我們把輸入的值改成 jsunicode 編碼

如 我們改成 <img src=x οnerrοr=alert(1)> 然後進行js八進制編碼  然後服務器端接受後 經過過濾器 沒有發現該過濾的就進入到了innerHTML中

現在我們來看看 輸出是什麼效果!

我就用chrome console來演示吧!  enter image description here

看到了把 經過js的解碼 我們的代碼又還原回來了 並且注入到了網頁中!這時候代碼執行!成功彈窗!

在js中是可以用jsunicode js16進制 js8進制的!

爲什麼這裏不用16進制 跟unicode編碼!是因爲 八進制的相對而言最短!

在xss中字符數的長短 也是一個很重要的問題!越短越好!

在asp的站中插XSS代碼的時候,存儲型 會因爲你數據庫中字段的長度不夠

而存不進去 然後報錯!這種情況經常發生!所有養成用最少的字符 來達到你的目的 是最好的!

既然提到了js中的十六進制編碼 跟js中的unicode編碼 那麼也上兩張圖吧!

十六進制在js中是\x[16hex] 來表示的 如:<  \x3c  enter image description here

大家看到跟八進制的用法也是一樣的!只不過多了一個字符X 雖然我很喜歡這個字符 但是我更喜歡八進制的短小精悍!

下面再說說jsunicode編碼:

他的表示方式是這樣的:\uxxxx \uxxx < 轉碼後: /u003c

上圖:  enter image description here

0x04 base64編碼


到目前爲止 我遇到使用base64編碼的情況 大多數是這樣!

<a href="可控點">
<iframe src="可控點">

在這種情況下 如果過濾了<> ' " javascript 的話 那麼要xss可以這樣寫 然後利用base64編碼!

<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>

這樣當test A鏈接點擊時 就會以data協議 頁面以html/text的方式解析 編碼爲base64 然後單點擊a鏈接時 base64的編碼就被還原成我們原本的

<img src=x οnerrοr=alert(1)>

然後成功彈窗!

如下圖:

enter image description here  在iframe裏也同樣可以使用!大家自己測試把!

0x05 閒扯


web前端的世界真的太難讓人捉摸透!

其實好多阻擋在面前的就是那些原理性的東西!懂了就好了!

看着二哥挖掘反射型xss 讓我感覺很像js代碼審計!

用二哥的話來說,首先你js的功底得比寫js的人功力要高 然後你就比較容易挖掘到xss!所以我感覺js比xss來說相當重要!二哥一直寫了六七年的js 才練就今天的功力!所以我特別堅信這句話!

一般測試xss首先我會先測試一些反射型!提交幾個非法字符 然後看過濾成什麼了!然後再打開chrome console 然後再追蹤當前網頁中 以及網頁所引用文件中的一些關鍵字!比如這個輸入框的id =xxxx 然後我就一直追蹤下去!如果某個數組 或者變量 的值把它傳入進去了 然後就一直追蹤下去 一直找到源頭!把代碼都看一邊 如果能繞過的話 自己在chrome稍稍調試下就能挖掘出來了!

當然這種方法也是二哥教!二哥跟短短一直都是我膜拜的對象!短短跟我講了講 瀏覽器的解析,二哥講了 dom的渲染 js的解析以及等等 說不完的一些技巧!

頓時趕腳 挖掘XSS是那麼的容易!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章