みなさん、こんにちは、私の名前はVahagn Vardanyanです(多くの人が考えるように、タイプミスはありません:))、私はDSecでSAPシステムのセキュリティ研究者として働いています。この短い記事では、SAPその結果、重要なビジネス情報にアクセスできます。
SAP NWの各新バージョンでは、アプリケーションのセキュリティが強化されており、脆弱性によりシステムが完全に侵害されることはありません。 ただし、いくつかのセキュリティ問題を一緒に使用すると、攻撃者が目標を達成できる場合があります。 今日は、多数の脆弱性を使用してSAP NWを侵害する方法について説明します。
この記事では、最初にシステムから情報を取得する可能性について、情報漏洩に基づく脆弱性の悪用について、次に特権の昇格について説明します。 すべての脆弱性は、最新バージョン(調査時点)のSAP(SAP NW AS JAVA 7.4)で発見されました。 まあ、それは始まった。

はじめに
SAP AS JAVAサーバーには、C:\ usr \ sap \%SID%\ J00 \ j2ee \ cluster \ apps \ sap.comフォルダーに格納されている多くの標準アプリケーションがあります。%SID%はSAPシステムのSIDです。 したがって、テストシステムにはSID DM0があります。
以下のスクリーンショットから、SAP NWの標準アセンブリには1400を超えるコンポーネント(完全なアセンブリをインストールすると2000を超えるコンポーネントが存在する)があり、さまざまな権限を持つSAPユーザーが呼び出すことができることがわかります。

呼び出すことができる各コンポーネントには、web.xmlおよびportalapp.xmlファイルに記述されている特定のアクセスレベルがあります。 コンポーネントへのアクセス権には4種類あります。

当然、外部からアクセス可能であり、権限のないユーザーがアクセスできるため、no_safety権限を持つサーブレット、アプリケーション、およびコンポーネント、または事前定義された権限を持たないコンポーネントに関心があります。
最初の脆弱性に移りましょう。
情報漏えいの脆弱性
構成ファイルを検索した後、アクセス権の説明を含む記述子ファイル
<property name="SafetyLevel" value="no_safety"/>
または完全に存在しません。 webdynproコンポーネントtc〜rtc〜coll.appl.rtc〜wd_chatが見つかりました。 設定ファイルは次のとおりです。

次のアドレスでこのサービスに連絡できます。
http:/ SAP_IP:SAP_PORT / webdynpro / resources / sap.com / tc〜rtc〜coll.appl.rtc〜wd_chat /チャット#
ページを開き、メッセージを送信するための機能を確認します。 とりわけ、受信者(ユーザー)を追加する機能があります。

参加者の追加エントリをクリックすると、承認なしでユーザーを検索するためのウィンドウが表示されます。

Jon Snowという名前のユーザーとログインJ.Snowを持つユーザーがリストに含まれていたことは非常に興味深いことです。
うーん...この脆弱性を使用しているように見えます。SAPユーザーログインのリストを取得できます。 ただし、これはシステムを危険にさらすのに十分ではありません。間違ったパスワードを3〜5回入力すると、アカウントがブロックされるためです。 それでは、他の脆弱性を探しましょう。
SQLインジェクション
脆弱性が発見された次の匿名サービスはUDDISecurityServiceです。
SAPサーバーでは、このサービスは次の場所にあります。C:\ usr \ sap \ DM0 \ J00 \ j2ee \ cluster \ apps \ sap.com \ tc〜uddi \ servlet_jsp \ UDDISecurityService \
構成ファイルからわかるように、サービスは匿名でも利用できます。

servlet-classタグは、SOAP要求を使用してこのサーブレットへのアクセスを取得できることを示します。 ここで、SOAP要求の構造を見つけるタスクに直面しています。 要求の構造は、このサービスが記述されているwsdlファイルを見つけることで見つけることができることが知られています。 UDDISecurityImplBeanエントリを含むwsdlファイルを見つける必要があることがわかりました。 トータルコマンダーを使用して、検索を実行します。

必要な情報を含むファイルがサーバー上で見つかりました。 wsdl構造を持っているため、特別なユーティリティを使用してSOAPリクエストに変換できます。 このファイルには、applyPermissionとdeletePermissionByIdの2つのメソッドが記述されていることがわかりました。

2番目のメソッド(deletePermissionById)を選択し、SOAPリクエストを生成してSAPサーバーに送信します。

答えは次のとおりです。

答えは200番目のコードを返しましたが、送信されたデータを処理するロジックは理解できません。 このプログラムのすべての機能に「慣れる」には、SAOP要求を処理するサーバーでJAVAコードを見つける必要があります。 そして、このリクエストの処理の説明を含むjarファイルを見つけ、サーバー上の次の場所に配置します。
C:\ usr \ sap \%SID%\ J00 \ j2ee \ cluster \ apps \ sap.com \ tc〜uddi \ EJBContainer \ applicationjars \ tc〜esi〜uddi〜server〜ejb〜ejbm.jar
ファイルを逆コンパイルすると、次のクラスが表示されます。

要求処理自体は、UDDISecurityBeanクラスで行われます。

deletePermissionByIdリクエストを送信すると、 deletePermision関数を呼び出すPermissionsDao()コンストラクターがどのように表示されるかがわかります。 PermissionsDaoクラスに移動します。

SOAPリクエストを介して送信されたデータは、フィルタリングなしでSAPサーバーデータベースにアクセスするために使用されます。 SQLインジェクションがあると想定できます。 これを確認するには、SQLインジェクション用の特別なクエリを送信し、SAPサーバーデータベースのログを確認する必要があります。 データベースログファイルは、デフォルトでフォルダーCにあります。\ usr \ sap \%SID%\ J00 \ j2ee \ cluster \ server0 \ log \ system \デフォルトでdatabase_NN.N.logと呼ばれます。Nは0〜9の数字です。包括的に。
次のリクエストを送信します。

答えでは、200番目のコードも取得します。

ただし、データベースログでは次のことがわかります。

これで、SAPデータベースへの匿名SQLインジェクションがあると断言できます。 サーバーからログを削除し、次のリクエストを送信します。 サーバーのログにエラーがない場合、SQLクエリの構造は正しいです。

エラーはありません。

新しいタスクは、たとえばJon Snowのパスワードハッシュなど、SAPデータベースから重要なデータを取得するのに役立つクエリを見つけることです。 SAP NW AS JAVAのドキュメントから、ユーザーデータ(ユーザー名、名前、パスワードハッシュ)がUME_STRINGSテーブルに格納されていることがわかっています。
UME_STRINGSからすべてのデータを取得するクエリは次のようになります。


ご覧のとおり、このSQLインジェクションの脆弱性はエラーベースではなく、このサーブレットで使用され、sleep()関数をサポートしないアダプターです。 テーブル乗算方式を使用してクエリ処理時間を増やし、この脆弱性を時間ベースのSQLインジェクションに変えます。 これを行うには、すべてのSAPサーバーにデータが常に含まれるテーブルを見つけます。 このようなテーブルはJ2EE_CONFIGで 、コンポーネントの構成情報が保存されます。
次のリクエストを送信しましょう。

要求を受信したサーバーは、以前に2つのテーブル( UME_STRINGSとJ2EE_CONFIG)を乗算して、データベースからデータを抽出しようとします。 テーブルには大量のデータが含まれているため、サーバーに一時的な負荷がかかります。

そして、32秒後に答えが得られます。 そして-完了:時間ベースのSQLインジェクション。

管理者ハッシュの取得
前述のように、ハッシュされたパスワードは、次の構造を持つUME_STRINGSテーブルに保存されます。

UME_STRINGS.PIDテーブルには、ユーザー名が格納されます。
UME_STRINGS.ATTR = 'j_password'は、ユーザーが作成され、SAP AS JAVAスタックに存在することを示します。
UME_STRINGS.VALは、ログインがUME_STRINGS.PIDに記録されているユーザーからのパスワードハッシュを保存します。
フィールドUME_STRINGS.VALに含まれるデータを選択する必要があることがわかりました。 インジェクションの基本的なSQLクエリは次のようになります。
SELECT COUNT(*) FROM J2EE_CONFIG, UME_STRINGS WHERE UME_STRINGS.ATTR='j_password' AND UME_STRINGS.PID LIKE '%J.Snow%' AND UME_STRINGS.VAL LIKE '%'
パスワードはハッシュされた形式でSAPデータベースに保存されることがわかっています。ハッシュアルゴリズムは次のようになります。
サッシャ
SSHA
SHA
SHA-512
つまり パスワードハッシュには、次のような文字が含まれる場合があります。
1234567890QWERTYUIOPASDFGHJKLZXCVBNM*.,{}#+:-=qwertyuiopasdfghjklzxcvbnm/{SPACE}
それらを繰り返し処理し、選択した文字がパスワードのハッシュ文字と一致する場合、リクエストの遅延が発生します。

応答は1秒間遅延します。

このプロセスを自動化することにより、ユーザーJon Snowからハッシュを取得します。
{SHA-512, 10000, 24}YXNkUVdFMTIzzbAIcuqnw5RzpmdgZ38PWjhBeaGzHkV6XINN7ZDqxqgr0nYxfCaE5ncdK7kzzkzryJAn42qv9YlY034Llr4b8Rv1534chnIf1i8jZE6ylzTV5XuzvUlaXQ==

ご覧のとおり、パスワードはSHA-512アルゴリズムによってハッシュされています。 3番目の脆弱性がなければ、研究はこれで終了したでしょう。
暗号エラー、特権のエスカレーション
この脆弱性は偶然発見されました:-)
SQLインジェクションを使用して、ユーザーJon Snowのパスワードハッシュを取得しました。
{SHA-512, 10000, 24}YXNkUVdFMTIzzbAIcuqnw5RzpmdgZ38PWjhBeaGzHkV6XINN7ZDqxqgr0nYxfCaE5ncdK7kzzkzryJAn42qv9YlY034Llr4b8Rv1534chnIf1i8jZE6ylzTV5XuzvUlaXQ==
うーん。 ご覧のとおり、ハッシュの最後に==文字があります。 そして、base64decodeを実行するとどうなりますか?


なに? どうやって? パスワード これが本当にJonのパスワードであるかどうかを確認する方法は1つしかありません。J.SnowログインとasdQWE123パスワードを使用してポータルにログインします。

やった! 私は管理者です! しかし、どのように? パスワードがデータベース内でbase64形式であるという事実に関連するものを理解する必要があります。
検索の結果、次のフォルダーにあるファイルsap.com〜tc〜sec〜ume〜core〜impl.jarが見つかりました: C:\ usr \ sap \ DM0 \ J00 \ j2ee \ cluster \ bin \ ext \ com.sap .security.core.sda \ lib \ private 。 ユーザーのパスワードのハッシュ、有効性の確認、ユーザーのブロックなどを担当する関数が含まれています。 主なクラスの1つはPasswordHashです。 このクラスをさらに詳しく考えてみましょう。

2つのコンストラクターがあり、そのうちの1つ
public PasswordHash(String user, String password) { this._user = user; this._password = password; this._extra = null; }
ご覧のとおり、内部変数userおよびpasswordを初期化します 。
パスワードからハッシュを取得するには、 PasswordHashクラスの別のgetHash関数が使用されます。

114行目からわかるように、この関数はcreateHashWithIterations関数を呼び出します。この関数は、ハッシュを生成するための入力としてランダムな値を取ります。 createHashWithIterations(salt)関数に行きましょう

184行目で、 出力変数が初期化され、入力されたユーザーパスワードのバイトが格納されます。
185行目は、パスワードバイトと112行目で生成されたランダムソルトで構成される新しい変数pass_n_saltを作成します。
次に、行191でhashWithIterations関数が呼び出されます 。この関数はinputとpass_n_saltの 2つのパラメーターを取ります。 バイト単位のasdQWE123パスワードがoutputに格納されていることに注意してください。

とても興味深い。 各行を個別に検討します。
238行目は変数outputを初期化し、 データ変数からのデータが書き込まれます( データ変数の最初のバイトはパスワードasdQWE123です)。
241行目は、データのハッシュ処理を行うMessageDigestクラスのmd変数に初期化されます。
243行目は、ハッシュループ_iterations = 10000を開始します。
244-245行目では、 SHA-512アルゴリズムを使用してデータをハッシュし、 データ変数に書き込みます。
行246、 出力変数は無効化されます。
行247、変数パス (asdQWE123)からのデータが出力変数に書き込まれます。
248行目では、データからのデータが 出力変数の最後に書き込まれます。
出力変数の構造は次のとおりです。

このロジックはすべて10,000回実行され、サイクルの最後のステップで、パスワードが出力変数の先頭に追加され、パスワードがデータを保存した後です。 したがって、出力変数の最初のバイトは、キャッシュされていないパスワードで構成されます。
脆弱なコードセクションのブロック図:
pass = plain_pass
出力= [プレーンパス] + [ランダムバイト]
i = 0
データ= sha_512(出力)
出力= [NULL]
出力= [プレーンパス] + [データ]
(i)i = i + 1
i == 10000の場合
exit_from_loop
出力== "asdQWE123blablabla"
プログラマーの間違いは、forループの最後のステップでデータをハッシュしなかったことです。 この脆弱性はすでに解決されており、修正は次のようになります。
pass = plain_pass
出力= [プレーンパス] + [ランダムバイト]
i = 0
出力= [プレーンパス] + [データ]
データ= sha_512(出力)
(i)i = i + 1
i == 10000の場合
exit_from_loop

ご覧のとおり、SAPはステップの順序を変更しており、 出力変数が最初に初期化され、次に変数データハッシュが初期化されます 。
おわりに
そこで、これらの脆弱性を修正するためにSAPがリリースしたセキュリティノートを見てみましょう。
ユーザーの開示、ログイン-SAP nota 2255990 、脆弱性は2016年5月8日に修正されました。 すでにCVE-shack CVE-2016-3973(CVSS v3 7.5)があります。
SAPの脆弱なバージョンのリスト:

SQLインジェクションを修正するために、SAPセキュリティノート2101079がリリースされ、2016年2月9日にCVE-2016-2386(CVSS v3 9.1)で修正されました。
SAPの脆弱なバージョンのリスト:

パスワードハッシュの誤った実装による脆弱性は、ノート2191290で扱われます。 このノートは2016年1月12日、CVE-2016-1910(CVSS v3 5.3)にリリースされました。
SAPの脆弱なバージョンのリスト:

もちろん、ある人はある種の「曲がったサーバー」をインストールしてバグを見つけたと言うかもしれませんが、このためにSAP-aユーザーのリストの開示に関する統計しかありません。 スキャンは、インターネット経由でアクセス可能な7348 SAPサーバーで実行されました。

各ポートの統計

合計で、約1013台のサーバー(約14%)が情報開示の脆弱性に対して脆弱であることが判明しました

さて、SQLインジェクションの脆弱性が存在する可能性のあるサーブレットのアクセシビリティの統計に関するもう1つのプレート(パッチがまだインストールされていない場合)

合計-2174サーバー、約30%
それでは、何をする必要がありますか?
パッチを適用する必要があります、管理者仲間。
はい、そして最後に:もしあなたが私たちと一緒に働き、さらにもっとすばらしいバグを見つけたいなら、 ここに履歴書を送ってください