WordPressのREST APIの脆弱性
2月当初から話題になっているWordPressの脆弱性の検証を調べてみました。
2月の2週目の頭くらいに改竄速報さんが荒ぶってまして、その原因がこのWordPressの脆弱性をついたWeb改ざんのようです。
改ざん被害について、Web改竄速報さんがまとめてくれています。
2017年2月に発生した「WordPress」の脆弱性に対する攻撃についてのレポート
とても簡単なリクエストで改ざんされるので、情報が公開されてから、日本のものを含め、大量のWebサイトが改ざんされました。
各所で注意喚起がなされています。
WordPress の脆弱性対策について:IPA 独立行政法人 情報処理推進機構
WordPressの脆弱性に関する注意喚起[みんなでしっかりサイバーセキュリティ]
運用している方はすぐに最新のもにアップデートしましょう。
技術的な内容については下記の記事(徳丸さんのブログ)が詳しいです。
リクエストのパラメータでエラーを起こすと、書き込み権限のチェックが正常に行われず、記事の更新が実行されてしまうようです。
この脆弱性があるのでWordPressの4.7と4.7.1です。REST APIがデフォルトで有効になっており、当該バージョンであれば、攻撃が成功する可能性が高いです。
・脆弱性検証
簡単にできるので、ちょっと検証してみました。バージョンはWordPressの4.7.1です。
インストールして、改ざんように記事を用意しました。
この記事に対して、攻撃を行います。
POSTリクエストのパラメータは「?id=1A」みたいに「記事のID(数字) + {文字}」のようになります(数字が入るはずの場所に文字を混入させてエラーを起こす。)
POSTのボディに改ざんするデータをJSON形式で渡します。(今回は記事の内容を「Hacked by me」に改ざんします)
改ざんされました。
ちなみに、ここでPHPやjavascriptのコードを書いても消されてしまいます。なので、バックドアの設置とか、サーバ自体への攻撃は難しいようです。その辺は結構しっかりしてるみたいですね。
ただ、コードを直に書けるプラグインなどが入っていれば攻撃は行われるようです。
上記の記事では PHPコードを記事内で実行するためのプラグインとしてInsert PHP や Exec-PHP などと紹介されています。
ということで、検証してみたのですが、せっかくなので、別のプラグインで試してみます(というか、Insert PHP がうまくいかなかった)。
「inline-javascript」というプラグインを入れて、javascriptを実行してみます。
内容は下記のような感じ。
[inline]
<script type="text/javascript">
alert('Hacked!!!');
</script>
[/inline]
で、改ざんします。
できました。
試した内容は以上ですが、コード実行関係のプラグインは他にも色々ありそうです。今回の脆弱性はプラグインではなく、WordPress本体のものです。Wordpressのアップデートを実施しましょう。できなければ、次善策としてREST APIの無効化ですかね。
これだけ大きく被害があり、話題になれば、対策しない人のほうが少ないんじゃないかなんて思いますが、環境によってはコード実行まで行われますので、そうした環境を狙った攻撃が行われていく可能性があります。
アップデートしましょう。それだけです。
Dionaeaハニーポット
低対話型のハニーポットであるDioanaeに関するメモです。
低対話型のサーバーハニーポットとしては一番完成度が高いそうで、とりあえず試しにやってみるならこれ、というところじゃないでしょうか。
ともあれ、自分でインストールを試みたものの、古いのか、うまくいかないものが多かったので、備忘録的に残しておきます。
・Dionaeaについて
低対話型のサーバーハニーポット。エミュレートするプロトコルは以下の通り。
- Server Message Block (SMB)
- Hypertext Transfer Protocol (HTTP)
- File Transfer Protocol (FTP)
- Trivial File Transfer Protocol (TFTP)
- Microsoft SQL Server (MSSQL)
- Voice over IP (VoIP)
多分下記のページが本家(検索するしても出てこない……)
Dionaea – A Malware Capturing Honeypot
このページのインストール手順のgitのリンクが既にお亡くなりになっているようで、こちらのインストール手順だとうまくいかない。
リポジトリを追加して、apt-getでインストールする方法もありましたが、そちらも消えているようでリポジトリが見つかりませんでした( Installation — dionaea 0.6.0 documentation )。
インストールはこの辺を参考にしました。
上の記事のコマンド通りで問題なく入りました。
インストール後、設定ファイルをいじります。
まず、ログに関する設定から。「logging」の中のそれぞれのlevelを必要なものだけ吐き出すよう、変更します。
default = {
levels = "all,-debug"
} errors = {
levels = "error"
}
次に、待ち受けるインターフェースの設定。「listen」のインターフェースに待ち受けるIPアドレスを入れます。
mode = "manual"
addrs = { eth0 = ["xx.xx.xx.xx"] }
この設定を入れないまま起動すると、自分の環境ではローカルループバックで待ち受けていました。
それから、dionaeaを動かすようのユーザを作成します。
# groupadd dionaea
# useradd -g dionaea -s /usr/sbin/nologin dionaea
# chown -R dionaea:dionaea /opt/dionaea/
以上でDionaeaを起動します。Dオプションをつけるとデーモンとしてバックグラウンドで起動するようです。
# /opt/dionaea/bin/dionaea -c /opt/dionaea/etc/dionaea/dionaea.conf -w /opt/dionaea -u dionaea -g dionaea -D
止める際は……コマンドは用意されていないんですかね。プロセスをKillしましょう。
環境はCentOS7でDocker上にUbuntuをベースとしてインストールしました。
ちなみにDockerだと、こういうのもありました。
GitHub - DinoTools/dionaea-docker
今回はインストールからと思い、試してはいません。
ちょっと情報が古いものが多く、手間取りました。Dioanae自体はもう結構前からあるハニーポットなので、仕方ないですかね。そろそろ新しいものが出てきてもいいんじゃないかとか思いつつ。
HTTPなどはGlastopfなどのWeb型のハニーポットもありますし、Dioanaeに飽きたら、そのあたりもやってみたいと思います。
飽きるまでは、しばらくDioanaeを稼働させておいてみようかと思います。
SECCON 2016!
会社の方々とチームで参加しました。
去年も参加したのですが、今年のSECCONは一味違いましたね。とてもCTFらしい問題ばかりでした。
昨年の問題を復習し、対策していたのですが、何一つとして役に立たなかったですね。
今年の問題SECCONらしい問題と言えば、SECCON TOWERくらいじゃないでしょうか。
他の方の解き方を見ると、画像を取得、機械学習で分析、デコードといった感じでした(まあ、そうだよな)。今どきのセキュリティ人材は機械学習くらいできなきゃダメなんですね。
こういう出題者を殴りたくなるような(いい意味で)問題こそSECCONの醍醐味だと思うのですが、これ以外は割と他のCTFでもありそうな一般的な問題ばかりでした。
ツールにかけるだけとか、頭をひねれば一発とか、とにかく時間をかけてQRコードを読み続ければフラグにたどりつけるみたいなイージーな問題はどこかにいってしまったようです。
■Vigenere
最初の問題で、これはそれほど難しくありません。Vigenère cipherだとご丁寧に Wikipedia つきで言ってくれてます。Vigenère cipher とはなんぞや、というとただの換字式暗号です。平文の各文字に対して鍵を順次一文字ずつ取り出し、平文の一文字と鍵の一文字を暗号表に当てはめれば暗号文の一文字が取り出せます。
問題の暗号は以下の通り。
k: ????????????
p: SECCON{???????????????????????????????????}
c: LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ
k=key, p=plain, c=cipher, md5(p)=f528a6ab914c1ecf856a1d93103948fe
鍵の最初5文字は平文と暗号文から暗号表をたどれば出てきます。鍵は「VIGENER?????」です。
残りは5文字なので、これくらいなら総当たりで解けます。
鍵と暗号文から平文を生成する復号用のスクリプトを作成します。鍵の?にはA~Zに{}を含めた28文字を与え、その28*5のパターンの鍵からcを復号した平文のmd5を「f528a6ab914c1ecf856a1d93103948fe」と比較し、マッチしたものを出力します。
で、フラグが出ます。
くそコードは省略します。
■Memory Analysis
メモリダンプが落ちてきて変なプロセスがアクセスしているWebサイトを突き止めろという THE・フォレンジックな問題です。
こちらもご丁寧にHintにメモリフォレンジックの定番ツールである Volatility が紹介されています。
ただ、私のようなフォレンジック超初心者にはCUIツールは使いこなせないので、 KaniVola を使います。
KaniVolaはThe Volatility FrameworkのWindows用GUIインターフェースです。CLIであるVolatilityを実行する際に指定する複数のオプションを、少ない操作で入力し実行結果を簡単に保存できることを目的としています。
ということで、GUIでポチポチ選択すると適切なオプションを選んでくれてVolatilityのコマンドをたたいてくれるというツールです。いちいち調べたりせず、何も考えずそれらしいものを選択して実行するだけなので、とても簡単です。
さて、問題のメモリダンプを解析しましょう。問題は以下の通り。
Memory Analysis
Find the website that the fake svchost is accessing.
You can get the flag if you access the website!!
Webサイトと言っているので、ネットワーク関連を調べます。「connection」を選択し、実行します。
Offset(V) Local Address Remote Address Pid
---------- ------------------------- ------------------------- ---
0x8213bbe8 192.168.88.131:1034 153.127.200.178:80 1080
80番で怪しげな通信先につなげに行っています。次にsvchostがどうのこうの言っているので、プロセスも見てみましょう。「pstree」を選択し、実行します。
Name Pid PPid Thds Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
~~~
.... 0x81f0dbe0:spoolsv.exe 1644 672 15 133 2016-12-06 14:27:10 JST+0900
.... 0x81f65da0:svchost.exe 1776 672 2 23 2016-12-06 14:27:10 JST+0900
..... 0x8225bda0:IEXPLORE.EXE 380 1776 22 385 2016-12-06 14:27:19 JST+0900
...... 0x8229f7e8:IEXPLORE.EXE 1080 380 19 397 2016-12-06 14:27:21 JST+0900
~~~
先ほどのIPへアクセスしているプロセスID「1080」のプロセスの親にsvchost(PID: 1776 )がいますので、こいつが「the fake svchost」じゃないかと予想できます。
つまりIPアドレス「153.127.200.178」が設問にあるプロセスがアクセスしているWebサイトだとわかりました。
ここで、このアドレスをブラウザで打ち込んでみると、nginxのサイトが立っていることが分かりました。でもそれだけ。どうやらURLが必要なようです。
このままVolatilityで調べることも可能なのでしょうが、フォレンジック雑魚の私にはどのコマンドを打てばいいのか分からりません。
ということで別のツールを使います。
bulk_extractor という、メモリからファイルを抽出できるツールです。ダウンロードしてインストールしてもいいですが、REMnuxに入っています。
REMnux: A free Linux Toolkit for Reverse-Engineering and Analyzing Malware
REMnuxで先ほどのメモリダンプに対してbulk_extractorを実行します。
bulk_extractor forensic_100.raw ./out
これで ./out ディレクトリにメモリダンプから抽出されたファイルが出力されます。
中身を見るとパケットファイルがあり、これをWireSharkで見てみます。
先ほどのIPで絞ってもいいですし、HTTPでフィルタをかけてもそのIPしか出てきません。
で、そのIPのドメインは「crattack.tistory.com」となっており、なんのサイトか調べると、なにやら韓国語のサイトが出てきました。このドメインを逆引きしても先ほどのIPにはならず、それぞれのIPのwhois情報も違っていることが分かります。
そこで、先ほどのIPにこのドメインのURLを組み合わせるたものへアクセスします。
http:// 153.127.200.178/entry/Data-Science-import-pandas-as-pd
これでフラグが書かれたファイルが落ちてきました。
私はいくつかのツールを動かしただけなのであまりがっつり解析しなくても正解できるフォレンジック入門者にはうってつけの問題ではないでしょうか。
ただ、私にとってはHintに紹介されたVolatilityよりもbulk_extractorのほうが使い勝手がいいように感じました。(コマンド一つで問題がパケット解析になるので)
以上2問を解いた後、ほかの問題をつまみ食いしながらどの問題にも歯が立たず、SECCON TOWERを眺めていたら時間になりました。
冒頭にも書きましたが、去年とSECCONの問題の傾向か変わったようで、来年以降どうなるかはわかりません。少なくとも今回で、デバッガや逆アセンブラを使えるようになり、バイナリとお友達になる必要性は感じました。
UEFI + GPT 環境でのデュアルブート(Windows 10 & Ubuntu16.04)
ここしばらく、Linuxをメインで使えるマシンがほしいなと思いながらいたのですが、ようやくデュアルブートに成功したので、その時のメモです。
ポイントとしては、
①インストールメディアをUEFIで起動する
②ブートローダをインストールする位置
の2点です。
ここを参考にしました。↓
・ 手順
- リカバリ
- パーティションの切り分け
- Windows 10 へアップグレード
- Ubuntu のインストールメディアの作成
- Ubuntu の起動
- Ubuntu のインストール
以上です。
かいつまんで、ポイントだけ。
1. 一度デュアルブートに失敗し、WindowsもUbunutu も起動しなくなったためにこれをする必要がありました。買ってすぐのPCでも、リカバリ用」のディスクなどはちゃんと用意しておきましょう。ちなみに私のPCは工場出荷状態ではWindows 7です。
2. パーティションは先にUbuntu をインストールする分を空けておく。Windowsでディスクの縮小をして、ハードディスクに空きの容量を確保しておきます。
3. 一度アップグレードしていたので、リカバリしても再度アップグレードができます。Windows 10のアップグレードですが、やるならUbuntu をインストールする前のほうが確実かと思います。Windows 10 はアップデートの際にリカバリ用のパーティションを作るそうで、それが原因でUbuntu が起動しなくなるというトラブルが起こり得るようです。回避方法や復旧方法もあるでしょうが、先にアップグレードはしておいたほうが無難かと思います。
4. ISOファイル( Ubuntuの入手 | Ubuntu Japanese Team )をダウンロードして、DVDなら適当なソフトで焼く。あるいはUSBにインストール。私は UNetbootin を使ってその辺に転がってた2GのUSBメモリにインストールしました。Ubuntuなら2Gでもぎりぎり入ります。
5. まず、Windows 10の「高速スタートアップ」を無効にしましょう。これをしないと、BIOSやブートデバイスの切り替えができません。
コントロールパネル
⇒ 電源オプション
⇒「電源ボタンの動作を選択する」
⇒「現在利用可能ではない設定を変更します」
⇒「高速スタートアップを有効にする」のチェックボックスを外す
⇒ 変更の保存
再起動して、ブート時に何かしらのキーを押してブートデバイスを選択します。
ここで、最初のポイントです。UEFI環境で外部デバイスからOSを起動しようとすると、起動するデバイスの選択肢が2つ現れます。
私の場合「UEFI : USB Reader」と「USB Reader」のような感じでした。ここでUEFIではないほうを選んでしまうと、場合によっては Windows も Ubuntu も起動しなくなります。UEFIからメディアを起動すると、Ubunut の場合、黒いGRUBのブートメニューが表示されます。
UbuntuTips/Install/UEFI - Ubuntu Japanese Wiki
Liveイメージで起動時にCUI画面で白文字のgrubメニューが現れる。(UEFIモードで起動している)
Liveイメージで起動時に紫のスプラッシュ画面で起動し、GUIとインストーラーが立ち上がる。(Legacyモードで起動している)
ちゃんとUEFIで起動していることを確認しましょう。
6. 最後にUbuntu のインストールです。普通にOSをインストールする手順通りです。「インストールの種類」で「それ以外」を選択し、パーティションをカスタマイズします。と言っても、2で開けておいたスペースにインストールするだけです。私は適宜「/」、「/boot」「/home」などにお好みで振り分けてください。
ここで重要なポイントはブートローダの位置です。デフォルトではディスクの先頭(「/dev/sda」など)が選択されていますが、これを、EFIタイプのパーティションの位置に変更します。(私の場合「/dev/sda1」。)
あらかじめ、GPartedでパーティションを確認すると「EFI System Partition」とラベルがついていました。あまり詳しくは知りません。
PCハードウェア強化ラボ:第4回 2Tbytes超ディスクをシステム用ディスクとして利用する (3/3) - @IT
先頭に「EFI システム パーティション」という100Mbytesのパーティションがあるが、これはGPT形式のディスクにおいて、ブート・コードを保存しておく場所である。
だ、そうです。
多くのデュアルブートの説明では「/boot」のパーティションに一緒にブートローダをインストールし、起動後MBRからそのパーティションを呼び出し、ブートメニューを開くような設定になっているようなのですが、GPTではそれができないため、今回の方法を取ることになりました。
私の環境では以上でデュアルブート環境が出来上がりました。
起動するとGRUBが立ち上がり、Ubuntu と Windows 10 が選択できるようになっています。(今のところ両OS問題なく動いています)
場合によっては参考に挙げたサイトで行っているような Boot Repair を使った修復作業などが必要になることもあるようです。
以上、個人的に一つ、悲願を達成できたので、メモとして残しました。デュアルブートは私のような「UEFI? GPT? 何それ、おいしいの?」というレベルの人は行わないほうがいいかと思います。
今は仮想化などの技術も進んでますし、「Windows Subsystem for Linux」なども出てきましたしね。まあ、一昔前の壊れてもいいやPCでハードディスク容量も余ってたので。
以上です。
cowrieでssh・telnetのハニーポット運用
ハニーポッター 第一弾
とりあえずSSHハニーポットのcowrieを立ててみました。
↓こいつです。
cowrieはコヤスガイという意味だそうです。Google先生が言ってました。
環境としては、Windows10のノートPCにVirualboxでCentOS 7をインストールし、その上のDocker上のCentOS 6でcowrieを動かしています。
低対話型のハニーポットを動かすのに、わざわざそこまで多重化する意味ないのでは、と思われるかもしれませんが、全くその通りです。
まあ、Dockerの操作の練習も兼ねてます。
インストールはそれほど難しくはありません。ググれば割と情報はあります。
↓この辺とか。
ハニーポットCowrieをCentOS7に入れてみた。 - Shioshishio
とりあえず、requrimentsをすべてインストールして、実行するだけのお手軽設計です。
少し詰まったのは、Docker上で動かしたContOSのイメージに入っていたのが、Python2.6だったことで、cowrieはPython2.7じゃないと動かないようです。まあ、何かしらの方法でアップデートすればいいんです。
最近telnetもサポートしたそうなので、せっかくですので、動かしてみます。設定ファイルをいじります。
# ============================================================================
# Telnet Specific Options
# ============================================================================
[telnet] # Enable Telnet support, disabled by default
enabled = true # IP addresses to listen for incoming Telnet connections.
#
# (default: 0.0.0.0) = any IPv4 address
#listen_addr = 0.0.0.0
# (use :: for listen to all IPv6 and IPv4 addresses)
#listen_addr = ::
# Port to listen for incoming Telnet connections.
#
# (default: 2223)
listen_port = 2223 # Source Port to report in logs (useful if you use iptables to forward ports to Cowrie)
reported_port = 23
これで起動すればsshはポート2222番、telnetはポート2223番で動いてくれます。
これをDockerのポートフォワードでそれぞれ22番、23番につなぎなおしました。
以上で、cowrieの起動は完了です。
この後、外からsshはつながるがtelnetがつながらないという事象が発生。なんだかんだ設定をごちゃごちゃいじってたら今はうまく動いてくれています(多分)。
確認した点としては、
- CentOS 7のfirewalld(デフォルトではsshは通すようになっている)
- WindowsのFirewall
- Windowsのほかプログラムが邪魔していないか
あたりですかね。結局何が問題だったかいまいちわかっていません。とりあえず、Windows 10はよくわからないものがいっぱい動いているので、サーバとか立てないほうがいいってことはよくわかりました。
とりあえずこれで動いてくれています。
2,3日動かしてみて、割と攻撃は来ています。ボット化するスクリプトを落として来たりとかですね。
ログがjsonで出てくるので、うまくパースして解析したいんですが、面倒くさい頑張ります。
面白い攻撃が来たら、(気が向いたら)ここにでも書きます。
追記・2016/0927
うまく動いてくれてると思っていたのですが、telnetの動作が怪しいです。ログを見ると、セッションを張ったログはあるのですが、その後の挙動がない……。
cowrieのtelnetはあまり情報がないので、どうすればいいか、ちょっとわからないです。
とりあえず試行錯誤してみます。sshは問題なさそうです。