www.morihi-soc.net

誰もが安心して使える、安全なインターネットを目指して

ハニーポット観察記録(47)「ECShop に対する SQL インジェクション攻撃」

どうも。ハニーポッターの森久です。

今年もやってきました、2月1日から3月18日(サイバー)はサイバーセキュリティ月間です。
私もセキュリティ技術者の一人として、普及啓発に関わっていきたいと思います。

なお今回のブログ記事だけでなく、2月16日に長野県で開催される【第4回】サイバーセキュリティ勉強会2019 in 塩尻にて、ハニーポットに関する発表をさせていただきます。
私以外にも多くの方が発表されるため、濃い一日になること必死です。ご都合のつく方はぜひご参加いただければと思います。

さて今回は、私の管理する環境で ECShop の脆弱性を狙った SQL インジェクション攻撃を見つけたので紹介します。
ハニーポットを運用するハニーポッターであれば共感していただけるかと思いますが、ハニーポットでは珍しい攻撃です。
ECShop はEC サイトを構築するための CMS の1つです。日本語による構築方法や使い方の紹介などをほとんどみかけないため、あまり日本では使われていないようです。
それにもかかわらずハニーポットで攻撃を検知したということは、グローバルでは使われており、攻撃者に狙われているということでしょう。

攻撃サンプル

※一部の情報を意図的に伏せています。

ヘッダを見ると、明らかにリファラ(Referer)に不自然な文字列が指定されていますね。
通常、リファラには、ブラウジングの最中で直前に閲覧していた Web サイトの URL が入ります。
そのためリファラの情報を収集、蓄積、分析すると、閲覧者がどこの Web サイトから訪問することが多いかとか、検索サイトでどういう単語を検索して訪問してくるとかといったことがわかります。

しかし、上記の攻撃サンプルのリファラは URL ではないため、送信者は別の意図があって指定しているといえます。

注目すべきは「a:2:{」から始まる文字列です。PHP でプログラミングをしている人は馴染みがあるかもしれませんね。
これは PHP において、変数やデータといったオブジェクトをバイトストリームで表した文字列です。以後、シリアル化された文字列と呼びます。
シリアライズについて詳しく知りたい方は PHP マニュアルの「オブジェクトのシリアライズ」や「serialize() 関数」のページを参照してください。

ECShop のソースコードを解析したわけではありませんが、リファラを処理するプログラムに脆弱性が存在し、シリアル化された文字列が評価されてしまい、なんらかの被害が発生します。
どのような被害を受けるのかは SQL インジェクションの内容にかかっているので、詳しくみていきましょう。

SQL インジェクションを紐解く

シリアル化された文字列を見ていくと、union select という文字列が見えますね。これはデータベースの select 文であり、1,0x272f2a,3,4・・・と列名が指定されています。その中でも9番目のデータは長く、意味がありそうです。

0x から始まる文字列は HEX(16進数)で表現されたデータです。人間が読み取るには、些か難易度が高いので Ascii 文字列に変換してみましょう。

今回は私が作成した、複数のエンコード・デコードに対応しローカル環境で使える「strscript : ブラウザで完結! 文字列操作スクリプト」を使います。strscript は GitHub で公開しています。
https://github.com/morihisa/strscript

strscript は1つの HTML ファイルなので、手元にダウンロードした後、ブラウザで開いて使うことができます。
チェックボックスを HEX とデコードを選択して、うりゃ!ボタンをクリックします。
HEX であることを示す 0x を除いた文字列をデコードした結果を次に示します。

左側のテキストエリアがデコード対象の文字列で、右側のテキストエリアがデコードした結果の文字列です。

デコードした結果を見ると、$asd という変数名と、assert()関数が確認できますね。
ここで重要なのは assert()関数です。これはデバッグ目的で使われる関数で、与えられた PHP コードを評価し、TRUE か FALSE でプログラミングエラーを表示することなどに使われます。
つまり PHP として解釈された場合は、デコードした結果に含まれる assert()関数の引数である base64_decode() 関数が実行されることになります。
base64_decode() 関数はその名の通り BASE64 でエンコードされた文字列をデコードする関数です。
strscript で、この関数で指定されている文字列をデコードしてみましょう。チェックボックスを HEX から BASE64 に変更してから、うりゃ!してください。結果を次に示します。

デコードした結果を見ると、今度は file_put_contents()関数が出てきました。

この関数は引数の1番目にファイル名(ここでは function.inc.php)、2番目にファイルの内容を指定して、ファイルを作成する関数です。なお今回は base64_decode() 関数が指定されているので、実際に作成されるファイルの内容は、この関数が実行された後の内容になります。

さてそろそろ慣れてきたと思いますが、 base64_decode() 関数の中身をデコードしてみましょう。先程と同様に BASE64 でデコードした結果を次に示します。

やっと正体が分かりましたね。これは PHP のコマンド実行機能を持つバックドアプログラムです。
少し特殊な作りをしていますので、プログラムの内容を1行ごとに見ていきます。

まず A というクラスがコマンド実行の本体です。test という変数に含まれている内容を eval()関数で評価しますが、これはデストラクタで実行されます。
デストラクタを説明するのはちょっと難しいのですが、クラスを使い終わったときに必ず実行される関数であると説明しておきます。いわゆる終了時の処理を記述します。

続いて、バックドアプログラムが実行するコマンドを受け取る $test 変数が指定されています。これは POST データで struggle という名前のパラメータの値を受け取り、BASE64 でデコードした後の文字列が格納されます。
$len 変数は、$test 変数の文字列の長さを計算して格納しています。
$pp 変数は、$test 変数と $len 変数を使って、シリアル化された文字列を作成しています。

シリアル化された文字列は、データを一意に保存・復元できるように規定されているため、シリアル化するときと、シリアル化を元に戻すときが別々の環境であっても同じ内容となります。

最後に $test_unser 変数は $pp をシリアル化を元に戻すために使われています。実は変数の右辺に持ってこずとも unserialize() 関数は動作しますが、コーディングスタイルの問題でしょう。

file_put_contents() 関数で作成される function.inc.php は PHP のコマンド実行機能を持つバックドアプログラムであることがわかっていただけたかと思います。

ただし、今回のような内容はハニーポットで検知している他の攻撃で見るバックドアプログラムよりも手が込んでいます。他の攻撃では、上記のようなコマンド実行時にシリアル化してデストラクタで実行するというような手順が含まれることがありません。
実行するコマンドの文字列を受け取ったら、そのまま eval() 関数で実行することが大多数です。

可能性の1つですが、ファイルの内容をこういった普通のプログラムのようにしておくことで、アンチウイルスソフトによる検知逃れを狙ったのかもしれません。事実、上記の内容を保存した PHP ファイルを VirusTotal で調査すると、不審なファイルであるという判定はされませんでした(2019年2月1日時点)。

バックドアへのアクセス

function.inc.php のファイルの内容を解説しましたが、攻撃者はどのようなコマンドを実行しようとしていたのでしょうか。

冒頭で紹介した攻撃サンプルと同じ送信元から、次のアクセスがありました。

※一部の情報を意図的に伏せています。

攻撃サンプルのときは、User-Agent が Java のプログラムのような文字列が指定されていましたが、ここでは Chrome のような文字列が指定されています。もっとも Chrome/49.0.2623.87 は、2016年3月にリリースされたバージョンなので、自動更新機能が備わっている Chrome で2019年2月現在においても使っていることが不自然です。

POST のボディ部分を見ると、struggle はバックドアプログラムに含まれていたパラメータ名ですね。

右辺は HTTP の仕様で = を % エンコードしてありますが、BASE64 のデータです。そこで %3D を = に書き換えて strscript でデコードしてみます。結果を次に示します。

はい。PHP の echo() 関数で cms という文字列を表示しようとしたということが分かります。

おそらく上記のリクエストに対する応答で cms という文字列が確認できたら、バックドアの作成が成功していることがわかるため、攻撃の成否判定をしていると考えられます。

残念ながら、WOWHoneypot には今回の攻撃をおもてなしするためのマッチ&レスポンスルールがなかったので、ハニーポットのログに残っていたのはここまででした。

まとめ

今回は ECShop を狙った SQL インジェクション攻撃を紹介しました。

SQL インジェクション攻撃の内容は、PHP の assert() 関数や file_put_contents() 関数など複数の手順を踏んで、PHP のコマンド実行機能を持ったバックドアプログラムを作成することでした。

またバックドアプログラムは、シリアル化とデスタラクタを使用するという特殊な作り方をしていました。

アクセス履歴からは、攻撃が成功したのかどうかを確認するリクエストまでを確認しました。

もしも ECShop の古いバージョンを使用している場合は、Web サーバ内部に不審なファイルが作成されていないか確認し、最新のバージョンにアップデートすることを推奨します。

なお作成されるファイルはアンチウイルスソフトで検出できない可能性があるので注意してください。

以上です。それでは。

Written by 森久

2月 1st, 2019 at 9:53 pm