アイジア

CTF, 情報セキュリティの学んだことメモ

ksnctf 14 John

ksnctfの14問目を解いていきます。 ksnctf.sweetduet.info

問題文には/etc/passwdのようなフィールドが羅列してあり、user99に、

DictionaryIsHere.http//ksnctf.sweetduet.info/q/14/dicti0nary_8Th64ikELWEsZFrf.txt

とあります。dicti0nary_8Th64ikELWEsZFrf.txtにはよく使われる英単語が並んでおり、問題タイトルは「John」ということで、John the Ripperを使った辞書攻撃をやってみます。

辞書攻撃

dicti0nary_8Th64ikELWEsZFrf.txt(dictionary.txtに改名)とuser00~user20までのシャドウファイルをpasswd_shadowとして保存し、Johnで辞書攻撃を行います。

sudo john passwd_shadow --wordlist=dictionary.txt

解析はすぐに終わります。「john --show passwd_shadow」でクラックの結果を見ることができます。

f:id:favoritte15:20181120154320p:plain
1文字目のパスワードを縦に見るとフラグになっていました。抽出するには以下のコマンドを使います。

john --show passwd_shadow | cut -b 8

ksnctf 13 Proverb

ksnctf.sweetduet.info pwnの問題です。Tera Termでサーバにログインします。
f:id:favoritte15:20181119165224p:plain
フラグを読みだす権限はなく、proverbを実行するとproverb.txtから読みだしたことわざが出力されます。

シンボリックリンク攻撃

フラグを読みだすにはシンボリックリンクの仕様を利用します。シンボリックリンクとは、簡単に言えばファイルに別名をつけることです。ショートカットやハードリンクと違い元のファイルを現在のディレクトリで実行します。これを利用してflag.txtを読み出します。つまり、
①/tmp/(サブディレクトリ)にproverbのシンボリックリンクを作成
②flag.txtをproverb.txtにリネームして/tmp/(サブディレクトリ)にシンボリックリンクを作成
③proverbのシンボリックリンクを実行してflag.txtを出力させる
という流れになります。
f:id:favoritte15:20181119182148p:plain
フラグが読み出せました。

ksnctf 12 Hypertext Preprocessor

ksnctf.sweetduet.info

f:id:favoritte15:20181119155650p:plain
時刻っぽい何かを表示するウェブサイト。さっぱりわからなかったので調べたらCVE-2012-1823というPHP脆弱性らしいです。

CGI版PHPにリモートからスクリプト実行を許す脆弱性(CVE-2012-1823) | 徳丸浩の日記

CVE-2012-1823 ~ ksnctf #12 Hypertext Preprocessor ~ - Qiita

ksnctf 11 Riddle

ksnctfの11問目を解いていきます。リバースエンジニアリングの問題です。 ksnctf.sweetduet.info

実行と解析

f:id:favoritte15:20181115222445p:plain

Riddle.exeを実行すると、簡単な質問(答えは1問目「Human」,2問目「Greenland」, 3問目「42」)の後唐突にフラグを聞かれます。分からないのでIDAで開いて解析を行います。 f:id:favoritte15:20181115222719p:plain

exeファイルの挙動は、下のテキストにクイズの答えを入力すると「Correct!」、不正解だと「Wrong...」と表示されるというものでした。その文字列を出力する周辺に、正解文字列との比較を行っている処理がある可能性が高いので、まずはヒントになる文字列を探します。 f:id:favoritte15:20181115223039p:plain

右上のNames windowに「Wrong」が、すぐ上に「Correct」「Conglatulation」という文字列があります。ダブルクリックすると左のウィンドウが遷移します。 f:id:favoritte15:20181115223250p:plain

「Correct」も「Wrong...」も「Conglatulation」sub_401980というサブルーチンで使われているのでこれが正解文字列との判定処理だと思われます。sub_401980をダブルクリックして詳細を見ていきます。
f:id:favoritte15:20181119130348p:plain
実際に「Wrong...」とダイアログを表示する処理を行っているのは「loc_E1A7D」というルーチンであるようです。ここにジャンプする命令の直前の比較命令(cmp)を分析することでフラグが分かりそうです。
ここからは静的解析だけでは厳しいのでここから実際にプログラムを動かして解析していきます。
f:id:favoritte15:20181119131326p:plain
f:id:favoritte15:20181119131457p:plain
f:id:favoritte15:20181119131515p:plain
上の画像のようにE1A7Dにジャンプする命令にブレークポイントを仕掛けます(右クリック->[Add Breakpoint])。 仕掛けたら実際にプログラムを実行します。F9を押すとIDAがプログラムをロードし、もう一度F9を押すとRiddle.exeが実行されるので「What is the flag?」の問まで進めます。ここではとりあえず「FLAG_」と入力してブレークポイントに当たります。 f:id:favoritte15:20181119131918p:plain
最初のブレークポイントは0x15と入力文字列の数(EAX)を比べています。フラグの文字数は21文字であることが分かりました。
f:id:favoritte15:20181119133256p:plain
入力文字列が21文字になるように「FLAG_ABCDEFGHIJKLMNOP」と入力し、2番目のブレークポイントに当たります。直前の比較命令において、edxには「0D1BFFBF」が入っていますがこれが何の値かわかりません。
f:id:favoritte15:20181119134234p:plain
見た感じこのsub_E17D0というサブルーチンでこの値が入力文字列をもとにしてつくられているみたいです。

XOR命令を探せ

簡単なリバースエンジニアリングの問題においてこの手の変換処理はXORでやっていることが多いので、サブルーチンでそれを探します。ただし、
オペランドレジスタがどちらも同じ→そのレジスタの値を0にしているだけ
オペランドにスタックの位置を表すレジスタ(esp, ebp)が含まれている→サブルーチンの補正とかのための処理
なのでここでは無視します。そうして探していくと以下の命令が見つかりました。
f:id:favoritte15:20181119143232p:plain

xor [eax+esi], cl

ここのXOR命令、入力文字数分だけ繰り返されています。最高に怪しいポイント。くり返し実行してECXの値を見ていくと[eax+esi]のアドレスには順に0xF9, 0xB3,0x5A,0x4A,0x18,0xEA, 0x5D, 0x36, 0x99, 0xE2, 0x6, 0x3F, 0xA1, 0x20, 0x47, 0x1F, 0xF5, 0x86, 0xA3, 0xAC, 0x7が格納されます。

FLAG→0x46 0x4C 0x41 0x47
[eax+esi]→0xF9, 0xB3 ,0x5A ,0x4A
この値をそれぞれXORすると「0xBF,0xFF, 0x1B, 0x0D」になり先ほどのEDXの値(0D1BFFBF)と一致します。やはりXORで文字列が変換されているようです。
この場所で4文字ずつ比較を5回行い20文字分を照合しています。その後、

f:id:favoritte15:20181119153027p:plain
↑ここの部分で0xC7でXORした最後の文字と0xACを比較しています。 メカニズムが分かったのでここからプログラムを書いてフラグを求めます。

#include <stdio.h>

int main(){
    char a[22] = {0xF9, 0xB3, 0x5A, 0x4A, 0x18, 0xEA, 0x5D, 0x36, 0x99, 0xE2, 0x6, 0x3F, 0xA1, 0x20, 0x47, 0x1F, 0xF5,
    0x86, 0xA3, 0xAC, 0xC7};
    char b[22] = {0xBF, 0xFF, 0x1B, 0x0D, 0x47, 0xA7, 0x18, 0x4F, 0xCB, 0xD6, 0x5C, 0x59, 0x95, 0x61, 0x73, 0x57,0xB3,
    0xD1, 0x94, 0x9F, 0xAC};
    char flag[22];
    
    int i;
    for(i=0; i<21; i++){
        flag[i] = a[i]^b[i];
    }
    printf("%s\n", flag);   
}

ksnctf 9 Digest is secure!

ksnctfの9問目を解いていきます。

ksnctf.sweetduet.info

ダイジェスト認証とは

Digest認証 - Wikipedia

Digest認証の挙動 - Qiita

ダイジェスト認証はベーシック認証と同じくHTTP認証方式の一つです。ベーシック認証がBase64を使用するのに対して、ダイジェスト認証はMD5というハッシュ関数を使うことでよりセキュアな認証を実現できます。ベーシック認証と違って、ダイジェスト認証はパスワードをネットワーク上に流しません。その代わり、responseという値をサーバに送ります。responseを求めるための式は以下の通りです。

A1 = ユーザ名 : realm : パスワード A2 = HTTPのメソッド : コンテンツのURI response = MD5( MD5(A1) : nonce : nc : cnonce : qop : MD5(A2) )

名称 意味
realm 認証が必要なサーバ側のエリア名
nonce サーバ側で生成するランダムな値(1回の認証ごとに発行)
nc カウンタ
cnonce クライアント側で生成するランダムな値(1回の認証ごとに発行)
qop 認証のセキュリティレベルの設定(基本はauth、auth-intで最高レベルの保護)

このMD5(A1), nonce, nc, cnonce, qop, MD5(A2)が分かれば認証は成功することになります。

パケット解析

MD5(A1), nonce, nc, cnonce, qop, MD5(A2)を見つけるためにq9.pcapをWiresharkで開いて解析していきます。
f:id:favoritte15:20181114194638p:plain

1行目(No.7):クライアントがサーバにアクセスします。
2行目(No.9):サーバが401(要認証)レスポンスを返します。その際、www_authenticateヘッダを含めます。 3行目(No.14):クライアントがwww_authenticateヘッダを含めて再びサーバにアクセスします。
f:id:favoritte15:20181114195141p:plain

response="c3077454ecf09ecef1d6c1201038cfaf"

このresponseの値は通常逆変換できないのですがそれだと問題が解けないのでMD5の逆変換サイトを使って復元できるようになっています。

Best MD5 Decrypter - Hash Toolkit

response=MD5(c627e19450db746b739f41b64097d449:bbKtsfbABAA=5dad3cce7a7dd2c3335c9b400a19d6ad02df299b:00000001:9691c249745d94fc:auth:31e101310bcd7fae974b921eb148099c)

ここまでの情報を用いて認証を突破します。nonceとcnonceはアクセスするごとに変化するのでその値をキャプチャしてresponseを改変します。

①ブラウザでhttp://ctfq.sweetduet.info/~q9/flag.htmlへアクセスします。 ②Fiddlerを起動して、[Rules]->[Automatic Breakpoints]->[Before Requests]をクリックしてブレークポイントを設置。 ③ブラウザでユーザ名をq9にしてログインを行います。

今、nonce=UXEeI616BQA=4a74de17d9620e922002f5f50008b601cb1241c8, cnonce=0e898e984de43bb4なので、

response=MD5(c627e19450db746b739f41b64097d449:UXEeI616BQA=4a74de17d9620e922002f5f50008b601cb1241c8:00000001:0e898e984de43bb4:auth:31e101310bcd7fae974b921eb148099c)=da79f06e4e32e16499e380a84456cbed

Request HeadersウィンドウのSecurityヘッダのAuthorizationを右クリック->[Edit Header]でresponseを求めたMD5のハッシュにします。 すると認証に選択し、フラグがブラウザに表示されます。

ksnctf 8 Basic is secure?

ksnctf8問目を解いていきます。結論から言うとBasic認証はセキュアではありません。 ksnctf.sweetduet.info

Basic認証とは

Basic認証は最も簡易なHTTP認証方式です。Basic認証が必要なWebページにアクセスするとIDとパスワードを入力するダイアログが表示されます。
f:id:favoritte15:20181114154624j:plain
認証情報は、
(ID):(平文のパスワード)
Base64エンコードしてネットワーク上に流れます。以上のことを踏まえて問題を解いていきます。

パケットキャプチャ

問題のpcapファイルをダウンロードしてWiresharkで開きます。中身は以下のようになっています。
f:id:favoritte15:20181114155033p:plain
このままでは少し見づらいのでフィルタをかけてHTTPパケットのみを表示します。
f:id:favoritte15:20181114155414p:plain
上にある入力バーに「http」と入力するとhttpパケットのみを絞り込むことができます。右側のHTTPステータスコードを見ていけばどのような通信が行われていたかわかります。
1行目(No.7):クライアントがctfq.sweetduet.info/~q8にアクセスしています。
2行目(No.9):サーバ側が認証要求を出しています。
3行目(No.13):クライアントがもう一度Webサイトにアクセスしています。
4行目(No.16):クライアントの認証が通り、Webサイトのコンテンツを返しています。

3行目のパケットを詳細にみていきます。
f:id:favoritte15:20181114160047p:plain
フラグを発見できました。