模糊JSON服務(wù),特別是使用Python,Ruby和JavaScript等動(dòng)態(tài)腳本語(yǔ)言實(shí)現(xiàn)的服務(wù)通常是一項(xiàng)富有成效的工作。 然而,我的觀察是,在測(cè)試過(guò)程中,這種情況很少做得很好。 在這篇博文中,我想給你一個(gè)關(guān)于我如何傾向于這樣做的簡(jiǎn)要說(shuō)明。 不用說(shuō),我使用我自己的工具箱,因?yàn)樗菍iT為此設(shè)計(jì)的,但如果這是您的想法,您可以使用自己的工具。 讓我們開(kāi)始吧。
JSON Web服務(wù)是以JSON文檔作為輸入的簡(jiǎn)單Web服務(wù)。 它們可以從您喜愛(ài)的云基礎(chǔ)設(shè)施(如AWS,Azure和Google Cloud)廣泛獲得,可用于手機(jī),手表,電視和冰箱。 幾乎所有東西都與JSON通信。 這種豐富的原因是因?yàn)榕c其他文檔格式(如XML,YAML,INI等)不同,JSON相對(duì)簡(jiǎn)單,緊湊并且不容易出現(xiàn)奇怪的錯(cuò)誤。 所有現(xiàn)代編程語(yǔ)言和環(huán)境都支持JSON的屬性和易用性。
在很多編程語(yǔ)言中,例如JavaScript,以及Ruby和Python的擴(kuò)展,JSON都是一流的公民。 這意味著JSON文檔不僅僅是外來(lái)的對(duì)象模型,而且是自然的對(duì)象,因此它們可以像任何其他普通對(duì)象一樣被訪問(wèn)。 例如,請(qǐng)考慮以下請(qǐng)求:
POST /path/to/service HTTP/1.1
Host: service
Content-Length: xxxx
Content-Type: application/json
{
"profile": {
"name": "Bob",
"age": 40
}
}
為了訪問(wèn)屬性“profile”中的字段“name”,開(kāi)發(fā)人員可能會(huì)在JavaScript中執(zhí)行如下操作:
// this is what you will normally see in ES5
updateProfile(body.profile.name, body.profile.age)
// ...or in modern ES6 may even look like this which looks a bit safer
const { profile={} } = body
const { name, age } = profile
updateProfile(name, age)
請(qǐng)注意,“姓名”和“年齡”字段均直接從“個(gè)人資料”中提取。 還注意到我們沒(méi)有驗(yàn)證這兩個(gè)領(lǐng)域的類型,也沒(méi)有對(duì)它們進(jìn)行規(guī)范化。 雖然在這個(gè)例子中這太方便了,但絕大多數(shù)公開(kāi)代碼并不太可能。
利用這一點(diǎn)在很大程度上取決于服務(wù)和“updateProfile”函數(shù)的實(shí)際功能。 因此,我們可以遵循的沒(méi)有特定的開(kāi)發(fā)風(fēng)格。 我們無(wú)法貼上一些已知的壞字,希望看到快速的結(jié)果。 相反,我們需要分析應(yīng)用程序行為并推斷可能發(fā)生的情況以及是否有機(jī)會(huì)進(jìn)行開(kāi)發(fā)。 這是我們需要卷起袖子并開(kāi)始模糊的地方。 模糊什么和如何?
顯然,我們需要為名稱和年齡道具嘗試不同的值。 而且,我們需要嘗試一些意想不到的容器值,例如數(shù)組和對(duì)象。 例如,updateProfile函數(shù)可能會(huì)預(yù)期一個(gè)對(duì)象,例如{first,last}而不是一個(gè)字符串。 這些檢查可能被實(shí)現(xiàn),而不考慮如何使用“updateProfile”函數(shù)以及從JSON主體反序列化的數(shù)據(jù),結(jié)果,它有助于代碼中的分支,其中可能包含當(dāng)名稱字段僅僅是 串。 這些是我們需要通過(guò)模糊自動(dòng)嘗試的事情。
我將在此練習(xí)中使用AppBandit,但如果您想編寫自己的置換器,您還可以使用Fuzzer甚至自己的工具。 我已經(jīng)為AppBandit和HTTPView做了這個(gè),所以我不想浪費(fèi)我的周期,因此我為什么要使用這些工具。
我們啟動(dòng)AppBandit并打開(kāi)一個(gè)新的Fuzzer選項(xiàng)卡。 在內(nèi)部,我們需要像下面的截圖一樣設(shè)置基本請(qǐng)求。 在這種情況下,我們沒(méi)有做任何事情。 這只是準(zhǔn)備下一階段的指南。
現(xiàn)在我們需要配置JSON文檔,以便我們可以對(duì)不同的組合進(jìn)行置換。 為此,我們將使用JSON Fuzz生成器。 導(dǎo)航到正文并從下拉列表中選擇JSON模糊。 在第一個(gè)領(lǐng)域,我們需要設(shè)置我們的文檔。 在第二個(gè)領(lǐng)域,我們將設(shè)置您的有效載荷。
如果我們只在有效載荷字段中輸入一個(gè)簡(jiǎn)單的字符串,它將按原樣使用。 例如,如果有效載荷是“測(cè)試”,那么JSON模糊生成器將生成兩個(gè)文檔,如下所示:
{
"profile": {
"name": "test",
"age": 40
}
}
and
{
"profile": {
"name": "Bob",
"age": "test"
}
}
但是,這不會(huì)幫助我們找到任何漏洞,因此我們將使用其他一些生成器來(lái)提取更多價(jià)值。 讓我們使用一個(gè)字典生成器,我們可以從下拉列表中選擇。 從字典的下拉列表中選擇FuzzDB,然后選擇“攻擊/ json / JSON_Fuzzing.txt”。 請(qǐng)記住,AppBandit默認(rèn)不會(huì)嵌入任何這些字典。 當(dāng)你需要它們時(shí),它們將被當(dāng)場(chǎng)下載。
現(xiàn)在我們已經(jīng)加載了列表,我們也可以編輯它,以便我們可以包含我們自己的有效載荷。 隨意添加任何你認(rèn)為可能有用的東西。 更多的有效載荷我們擁有更好的模糊性。 這就是說(shuō),你可以預(yù)覽如何在箭頭按鈕的幫助下生成有效載荷。 請(qǐng)注意,目前我們正在以JSON格式正確引用有效負(fù)載,這意味著它們將被解釋為字符串。
這不是我們想要的。 我們想要的是使用原始JSON,并且要做到這一點(diǎn),我們需要選擇“Parse payload”和“Ignore payload parsing errors”選項(xiàng)。 現(xiàn)在它可以正確生成,如下圖所示。
我們完成了這個(gè)。 退出發(fā)生器彈出窗口并使用箭頭按鈕循環(huán)訪問(wèn)取樣的模糊器有效負(fù)載。 注意如何正確生成一切。
在我們點(diǎn)擊播放按鈕之前,我喜歡配置更多選項(xiàng)。 將請(qǐng)求超時(shí)設(shè)置為更方便的一項(xiàng),并將最大連接數(shù)增加到60,以便我們可以更快地完成這項(xiàng)工作。
有時(shí),應(yīng)用程序可能因某種原因而行為不當(dāng)。 不要失望。 如果發(fā)生這種情況,請(qǐng)單擊Fork按鈕以創(chuàng)建當(dāng)前配置的精確副本并執(zhí)行另一個(gè)測(cè)試。 這很容易。
現(xiàn)在我們完成了。 測(cè)試立即完成。 下一步是分析結(jié)果,看看服務(wù)是否有什么奇怪的事情發(fā)生。 這背后沒(méi)有科學(xué)。 您只需要瀏覽結(jié)果集以找出不當(dāng)行為,并且如果您使用AppBandit重新發(fā)送工具重復(fù)此操作,以便您可以進(jìn)一步確認(rèn)并進(jìn)一步探索/利用。
我知道我沒(méi)有深入研究一旦發(fā)現(xiàn)問(wèn)題后應(yīng)該怎么做。 如果您仔細(xì)考慮,這是一個(gè)開(kāi)放式問(wèn)題。 與SQL注入或跨站點(diǎn)腳本和本地文件包含不同,這不是預(yù)定義的漏洞。 換句話說(shuō),我們可以注入一些有趣的字符來(lái)實(shí)現(xiàn)某種代碼執(zhí)行。 但是,使用正確的JSON負(fù)載,我們可以控制可能導(dǎo)致漏洞的代碼。 盡管目前我無(wú)法透露任何真實(shí)世界的情景,但我們當(dāng)然看到很多情況下,這種方法會(huì)產(chǎn)生有趣和可利用的結(jié)果。
原文:https://secapps.com/blog/2018/03/fuzzing-json-web-services