web安全之XSS基礎-常見編碼科普


0x01常用編碼

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

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

javascript的八進制跟十六進制:

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

jsunicode編碼:

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

url編碼 base64編碼:

如把尖括號編碼[ < ]  -----> url: %22  base64: Ig==

0x02 html實體編碼

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

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

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

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

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

<img src="[代碼]">

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

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

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

那么我們可以在這里 閉合雙引號 寫事件: 

onerror=[html language="實體編碼"][/html][/html]

比如我現在彈個窗:

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

原code:

<img src="x" onerror="alert(1)">

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

但是為什么這里我沒有用jsunicode 以及 js八進制跟js十六進制呢!

瀏覽器是不會在html標簽里解析js中的那些編碼的!所以我們在onerror=后面放js中的編碼是不會解析 你放進去是什么 解析就是什么!

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

那么再來講一下另外一個案例:

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

所以造成了xss!

我們提交的值如下:

%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><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中的編碼了!

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

0x03 新增的實體編碼與瀏覽器的工作原理

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

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

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

&colon; => [冒號]

&NewLine; => [換行]

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

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

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

數字前面是可以加多個0的

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

這句代碼能夠執行么?

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

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

解析器-詞法分析器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更加靈活!

0x04 javascript編碼

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

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

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

如:

eval()  setTimeout()   setInterval()

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

var search = "可控點";

document.getElementById().innerHTML=search;

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

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

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

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

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

我就用chrome console來演示吧!

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

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

為什么這里不用16進制 跟unicode編碼!是因為 八進制的相對而言最短!

 


 

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

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

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

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

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

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

下面再說說jsunicode編碼:

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

上圖:

0x05 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 onerror=alert(1)>

然后成功彈窗!

如下圖:

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM