X-masCTFのWriteUp
こんにちは。グレープ粗茶です。今回は、x-masCTFに参加しました。
[web]Sequel Fun
Sequel Fun 25 Points SOLVED So I found this login page, but I forgot the credentials :(
Remote server: http://challs.xmas.htsp.ro:11006 Author: Milkdrop
貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation
この問題では、まずchromeなどのデベロッパツールからhtmlのソースを閲覧すると、サーバーサイドのソースを見る方法が記されている。
index.php
<?php if (isset ($_GET['source'])) { show_source ("index.php"); die (); } ?> <head> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div class="container"> <?php include ("config.php"); if (isset ($_GET['user']) && isset ($_GET['pass'])) { $user = $_GET['user']; $pass = $_GET['pass']; if (strpos ($user, '1') === false && strpos ($pass, '1') === false) { $conn = new mysqli ($servername, $username, $password, $dbname); $result = mysqli_query ($conn, "SELECT * FROM users WHERE user='" . $user . "' AND pass='" . $pass . "'", MYSQLI_STORE_RESULT); // TO-DO: Remove elf:elf account if ($result === false) { echo "<b>Our servers have run into a query error. Please try again later.</b>"; } else { if ($result->num_rows !== 0) { $row = mysqli_fetch_array ($result, MYSQLI_ASSOC); echo "<h1>You are logged in as: " . $row["user"] . "</h1><br>"; echo "<b class='flag'>"; if ($row ["uid"] === "0") echo $flag; else echo "Welcome elf!"; echo "</b>"; } else { echo "<b>Login fail.</b>"; } } } else { echo "<b>I don't like the number 1 :(</b>"; } } else { echo '<form class="center"> <h1>Santa Login:</h1> <label>Username:</label> <input type="text" name="user" autocomplete="off"><br> <label>Password:</label> <input type="password" name="pass" autocomplete="off"><br> <input type="submit" value="Connect"> </form>'; } ?> </div> <br> <script src="/js/snow.js"></script> <!-- ?source=1 --> </body> 貼り付け元 <http://challs.xmas.htsp.ro:11006/?source
これらから、SQLを操作しているソースであることが確認でき、sqlinjectionの問題と判断する。
"SELECT * FROM users WHERE user='" . $user . "' AND pass='" . $pass . "'",
シングルコーテーションの数が合うように設定すると、ペイロードは、
?user=aa&pass=aa' OR 'a'='a
となる。
[web]Roboworld
Roboworld 50 Points SOLVED A friend of mine told me about this website where I can find secret cool stuff. He even managed to leak a part of the source code for me, but when I try to login it always fails :(
Can you figure out what's wrong and access the secret files?
Remote server: http://challs.xmas.htsp.ro:11000 Files: leak.py Author: Reda
貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation
leak.py
from flask import Flask, render_template, request, session, redirect import os import requests from captcha import verifyCaptchaValue app = Flask(__name__) @app.route('/') def index(): return render_template("index.html") @app.route('/login', methods=['POST']) def login(): username = request.form.get('user') password = request.form.get('pass') captchaToken = request.form.get('captcha_verification_value') privKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" #redacted r = requests.get('http://127.0.0.1:{}/captchaVerify?captchaUserValue={}&privateKey={}'.format(str(port), captchaToken, privKey)) #backdoored ;))) if username == "backd00r" and password == "catsrcool" and r.content == b'allow': session['logged'] = True return redirect('//redacted//') else: return "login failed" @app.route('/captchaVerify') def captchaVerify(): #only 127.0.0.1 has access if request.remote_addr != "127.0.0.1": return "Access denied" token = request.args.get('captchaUserValue') privKey = request.args.get('privateKey') #TODO: remove debugging privkey for testing: 8EE86735658A9CE426EAF4E26BB0450E from captcha verification system if(verifyCaptchaValue(token, privKey)): return str("allow") else: return str("deny")
index.html
<head> <script> function captchaGenerateVerificationValue() { //Devnote: //Oops I broke the captcha verification function //so it will just generate random stuff for the verification value //hope no one notices :O var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var charactersLength = characters.length; result = "" for ( var i = 0; i < 10; i++ ) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } document.getElementById("captcha").value = result } </script> </head> Login: <form method="post" action="/login"> Username: <input type="text" name="user" /><br> Password: <input type="password" name="pass" /><br> Captcha: <input id="captcha" onchange="captchaGenerateVerificationValue()" type="checkbox" name="captcha_verification_value" value="" /> I am not a robot <br> <input type="submit" value="Login" /><br>
認証サイトのバイパス方法
leak.pyの認証処理内にはif文が三つあり、これらを抜ける必要がある。
検索しているとどうやら何をしても127.0.0.1と解釈してしまう事象が発生してしまうようだった。 (※引用) 試しにしたのURLへとアクセスしてみると、'deny'と表示される。 これはleak.py一つ目のif文をすでに通過している事が分かる。 http://challs.xmas.htsp.ro:11000/captchaVerify
Leak.pyに記述されているデバック用のプライベートキーを利用して先ほどのサイトにゲットパラメータとして送信してみる。
http://challs.xmas.htsp.ro:11000/captchaVerify?privateKey=8EE86735658A9CE426EAF4E26BB0450E
すると、'allow'が返ってくる。
解答ペイロード
まずleak.py内で認証サイトにアクセスするのは以下の文となる。
r = requests.get('http://127.0.0.1:{}/captchaVerify?captchaUserValue={}&privateKey={}'.format(str(port), captchaToken, privKey))
確認としてユーザがブラウザから値を指定できるのはchapchaToken,のみとなる。
つまり、このcapchaToken内に"デバッグ用のprivateKey"を指定してあげればよい。
なので、ブラウザのデベロッパもしくはburp suite,などのプロキシツールを利用して、capchaTokenが代入される"capcha_verification_value"内に攻撃文を入れる。
つまり
Value="&privateKey=8EE86735658A9CE426EAF4E26BB0450E#"
とすれば、最終的にprivatekeyが理想の場所に入ってくれる。 注意点(´;ω;`)
問題を解くことに集中してケアレスミスしないでね(自戒)
上のペイロードと一緒にusernameとpassも指定しないとログインできません。
backdoored ;))) if username == "backd00r" and password == "catsrcool" and r.content == b'allow':
これでログインすると、フラグが記載された動画を閲覧することができます。
一番最初dirbなどで探そうとしたのはダメでした。 ディレクトリ名が"単語_ランダムな文字列"で構成されてました(笑)
以降解けなかった問題
[web]Execute No Evil 50 Points
2 hours, 54 minutes, 56 seconds remaining (1) New Message: "Hey dude. So we have this database system at work and I just found an SQL injection point. I quickly fixed it by commenting out all the user input in the query. Don't worry, I made the query so that it responds with boss's profile, since he is kind of the only person actively using this database system, and he always looks up his own name, lol. Anyway, guess we'll go with this til' the sysadmin comes and fixes the issue."
Huh, so hear no evil, see no evil, ... execute no evil?
Remote server: http://challs.xmas.htsp.ro:11002 Author: Milkdrop
貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation
こちらも?Source=1と入力することでソースファイルを閲覧することができた。 しかしながら、getで名前を受け取るもそれをすべてコメントアウトしているという状況であった。 これをどう回避するのか全く分からなかった
(追伸) writeup曰く、mysqlにはコメントを用いてバージョンの場合分けを書けるらしい。
図作成
いままでフローチャートなどを作ったことが無かったので、試しに作ってみました。 www.draw.io