Web Shell Analyzerは、Webシェルと思われるファイルを識別、デコード、タグ付けするために構築されたクロスプラットフォームのスタンドアロンバイナリです。Web Shell Analyzerは、Web Shell Scannerプロジェクト(http://github.com/tstillz/webshell-scan)の上位版であり、こちらは正規表現によるファイルスキャンのみを行い、デコードや属性分析は行いません。
本スキャナに付属する正規表現および組み込みのデコードルーチンは、ディスク上のすべてのWebシェルを検出することを保証するものではなく、誤検出を特定する可能性があります。また、本番環境で実行する前に、アナライザをテストし、その影響を評価することを推奨します。アナライザにはいかなる保証もありません。自己責任でご使用ください。
PHP、ASP/X Webシェルをサポートしています。JSP/X、CFM およびその他のタイプは開発中です。スキャンされるすべてのファイルは、PREアクションおよび/またはPOSTアクションを通じて実行できます。
PreDecodeActions 関数の背後にある考え方は、正規表現を使用してマッチする文字列やパターンを特定し、その生のマッチ内容を取得し、定義されたデコード/クリーンアップ手順を実行し、最終的な出力を分析エンジンに送り返して再スキャン/処理することです。
その非常に簡単な例がBase64デコードです。base64エンコードされたWebシェルに対する検出ロジックを確認するには、まずbase64のすべての層を削除する必要があります。これを行うには、次のようなPreDecodeActionを使用できます。
{
Name: "PHP_Base64Decode",
Regex: *regexp.MustCompile(`(?i)(?:=|\s+)(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))`),
DataCapture: *regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`),
PreDecodeActions: []cm.Action{
{Function: cm.StringReplace, Arguments: []interface{}{"\"", "", -1}},
{Function: cm.StringReplace, Arguments: []interface{}{"'", "", -1}},
},
Functions: []cm.Base_Func{cm.DecodeBase64},
},
上記のブロックを見ると、最初に関数名、マッチングに使用する正規表現、データキャプチャ用正規表現(何をキャプチャするか、何にマッチさせるかを調整したい場合がある)、そして PreDecodeActions があります。この場合、関数 cm.DecodeBase64 がマッチしたテキストに適用される前に、システムはまず " と ' を削除します。
PostDecodeActions はその逆で、デコードが実行された後に出力をチェックします。このモデルを使用すると、無限のPRE/POST関数およびデコード関数を持つ複数のカスタムデコーダを作成し、ほとんどのWebシェル分析ニーズに対応できます。
検出とは、名前と説明を伴う正規表現です。このモデルの背後にある考え方は、検出をモジュール化かつスケーラブルにし、実際の検出とコンテキストを保持することです。 検出は属性と同じ形式を共有しますが、属性は検出を生成できず、既存の検出にコンテキストを追加することしかできません。以下の検出ロジックの例を見てみましょう。
{
Name: "Generic_Embedded_Executable",
Description: "Looks for magic bytes associated with a PE file",
Regex: *regexp.MustCompile(`(?i)(?:(?:0x)?4d5a)`),
},
正規表現から、マジックヘッダーバイト 4D 5A に基づいて埋め込まれたWindows PEファイルを探していることがわかります。見つかった場合、検出が行われ、ファイルのJSONレポートが生成されます。
現在、検出はファイル拡張子に基づいて、またはすべてのファイルタイプに対して汎用的に適用されます。たとえば、PHPのデコードルーチンは cm.GlobalMap.Function_Php の下に定義され、属性のタグは cm.GlobalMap.Tags_Php の下に定義されます。
関数 cm.GlobalMap.Function_Generics と cm.GlobalMap.Tags_Generics の下のタグは、すべてのWebシェル拡張子に対して包括的に適用されます。
属性タグ付けは、既存のWebシェル検出に「コンテキスト」を追加するために私が作成した新しい概念です。属性単独では、現在のところ単独で検出を生成することはできません。従来のスキャンエンジンでは、Webシェルが検出された場合にのみアラートを発し、そのWebシェルが潜在的に持つ機能(属性)に関する追加コンテキストはほとんど提供されません。属性タグは検出ロジックと同じように機能しますが、検出が特定された後にのみ表示され、単独で検出を生成することはできません。以下の例のロジックを見てみましょう。
cm.GlobalMap.Tags_Php = []cm.TagDef{
{
Name: "PHP_Database_Operations",
Description: "Looks for common PHP functions used for interacting with a database.",
Regex: *regexp.MustCompile(`(?i)(?:'mssql_connect\|mysql_exec\()`),
Attribute: true,
},
}
構造体 Tags_Php の下に、新しいPHPタグを作成したことがわかります。スキャン中にマッチが見つかると、Attribute フラグがチェックされ、True に設定されている場合、検出されたWebシェルには、以下の出力例に示すように、頻度とマッチしたテキストブロックとともにタグ PHP_Database_Operations がJSONレポートに追加されます。
{
"filePath": "/testers/1.php",
"size": 66109,
"md5": "6793d8ebab93e5a0f91e5a331221f331",
"timestamps": {
"birth": "2019-02-03 02:02:22",
"created": "2020-07-29 02:50:15",
"modified": "2019-02-03 02:02:22",
"accessed": "2020-07-29 02:51:07"
},
"matches": {
"FilesMAn": 5,
"FilesMan": 29,
"cmd": 20,
"eval(": 4,
"exec(": 2,
"ipconfig": 1,
"netstat": 2,
"passthru(": 1,
"shell_exec(": 1
},
"decodes": {
"Generic_Base64Decode": 40,
"Generic_Multiline_Base64Decode": 165
},
"tags": {
"Generic_Embedding_Code_C": {
"bind(": 2,
"listen(": 2
},
"PHP_Banned_Function": {
"exec(": 3,
"get_current_user(": 1,
"getmyuid(": 1,
"link(": 7,
"listen(": 2,
"passthru(": 1,
"realpath(": 1,
"set_time_limit(": 1
},
"PHP_Database_Operations": {
"mysql_query(": 1
},
"PHP_Disk_Operations": {
"@chmod(": 1,
"@filegroup(": 4,
"@fileowner(": 4,
"@rename(": 2,
"fopen(": 7,
"fwrite(": 6
}
}
}
これらのタグは、Webシェルが何をできるかを定義するだけでなく、インシデント対応コンサルタントがライブレスポンス対応を実施する際に、次にどこを調査すべきかの出発点を提供するのに役立ちます。
なし! OS用のバイナリをダウンロードし、スキャンしたいディレクトリを指定するだけで(他の引数はオプション)、すぐに使用できます。
引数なしで wsa を実行すると、以下のオプションが表示されます。
/Users/beastmode$ ./wsa
Options:
-dir string
Directory to scan for web shells
-pretty
If set to true, the analyzer will output the results in a json indented form
-raw_contents
If a match is found, grab the raw contents and base64 + gzip compress the file into the JSON object.
-size int
Specify max file size to scan (default is 10 MB) (default 10)
-verbose
If set to true, the analyzer will print all files analyzer, not just matches
唯一必須の引数は dir です。必要に応じて他のプログラムのデフォルトを上書きできます。
アナライザの出力はコンソール(標準出力)に書き込まれます。以下に例を示します(最良の結果を得るには、stdoutをJSONファイルにリダイレクトし、オフラインでレビュー/後処理してください)。
Linux: ./wsa -dir /opt/www
Windows: wsa.exe -dir C:\Windows\Inetput\wwwroot
### STDOUTとWebシェルファイル全体をエンコードおよび圧縮する場合:
Linux: ./wsa -dir /opt/www -raw_contents=true > scan_results.json
アナライザが完了すると、以下の例に示すように、スキャン全体のメトリクスがSTDOUTに出力されます。
{"scanned":311,"matches":122,"noMatches":189,"directory":"/webshell-master/php","scanDuration":1.4757737378333333,"systemInfo":{"hostname":"Beast","envVars":[""],"username":"beastmode","userID":"501","realName":"The Beast","userHomeDir":"/Users/beastmode"}}