定位到jsf-api-2.1.28.jar!/javax/faces/webapp/FacesServlet#service
debug, 跟进 this.lifecycle.execute(context);
public void service(ServletRequest req, ServletResponse resp) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)resp;this.requestStart(request.getRequestURI());if (!this.isHttpMethodValid(request)) {response.sendError(400);} else {......FacesContext context;if (!this.initFacesContextReleased) {context = FacesContext.getCurrentInstance();if (null != context) {context.release();}this.initFacesContextReleased = true;}context = this.facesContextFactory.getFacesContext(this.servletConfig.getServletContext(), request, response, this.lifecycle);try {ResourceHandler handler = context.getApplication().getResourceHandler();if (handler.isResourceRequest(context)) {handler.handleResourceRequest(context);} else {this.lifecycle.execute(context);this.lifecycle.render(context);}}
跟进this.phases[i].doPhase
,这里会有循环遍历多个Phase
对象去调用doPhase方法
文章插图
继续跟进到
this.execute
public void doPhase(FacesContext context, Lifecycle lifecycle, ListIterator<PhaseListener> listeners) {context.setCurrentPhaseId(this.getId());PhaseEvent event = null;if (listeners.hasNext()) {event = new PhaseEvent(context, this.getId(), lifecycle);}Timer timer = Timer.getInstance();if (timer != null) {timer.startTiming();}try {this.handleBeforePhase(context, listeners, event);if (!this.shouldSkip(context)) {this.execute(context);}
在execute方法逻辑内 , 先通过facesContext.getExternalContext().getRequestMap();
拿到一个RequestMap其中的值为ExternalContextImpl
对象 , 该对象中包含了上下文、request、response等整体信息 。后续跟进 viewHandler.restoreView(facesContext, viewId);
文章插图
继续跟进
getstate
文章插图
下面是一处关键点 , 通过刚才我们提到的
ExternalContextImpl
, 从中对应的requestParameterMap
中的key取出我们传入的payload,默认情况下是javax.faces.Viewstate
, 之后该值作为形参带入doGetState
方法内文章插图
下面是漏洞出发点的反序列化逻辑部分
先Base64解码 , 解码后通过
this.guard
的值是否为null判断是否有加密 , 有加密的话会去调用this.guard.decrypt
进行解密 , 之后ungzip解压文章插图
之后将该流转换为ApplicationObjectInputStream并有一个timeout的判断逻辑 , 最后直接反序列化
文章插图
存在加密的情况的话可能会有以下的配置
<context-param><param-name>javax.faces.STATE_SAVING_METHOD</param-name><param-value>client</param-value></context-param><env-entry><env-entry-name>com.sun.faces.ClientStateSavingPassword</env-entry-name><env-entry-type>java.lang.String</env-entry-type><env-entry-value>[some secret password]</env-entry-value></env-entry>
或<context-param><param-name>com.sun.faces.ClientSideSecretKey</param-name><param-value>[some secret password]</param-value></context-param>
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- elasticsearch聚合之bucket terms聚合
- 东南第一佳味天下之美的菜系是
- 孔雀为什么被称为百鸟之王
- 我儿王腾有大帝之姿是什么梗?
- “黑绷带的力量” 首先,它有一个奇怪的名字,叫“黑绷带” 其次,在看产品介绍之初,它是一款晚霜。
- 什么口罩不具备安全防护作用
- 我的世界漏斗与漏斗之间怎么相连(我的世界漏斗上怎么放东西)
- 云原生之旅 - 11)基于 Kubernetes 动态伸缩 Jenkins Build Agents
- C#多线程之线程基础篇
- 我是特种兵之利刃出鞘吃豆腐脑是第几集?