Boston Key Party 2015 write up
Boston Key Party 2015に参加してみました。
難しそうだから大して点数稼げないだろうなーと思っていましたが、
案の定10点・25点問題しかできませんでしたとさ(*´ω`*)
BU Central(10)
the flag is party
この問題の存在に気づくのに30分くらいかかった。
FLAG:party
Park Street(10)
What is the OpenFlow table modification message type to add a new flow?
FLAG:OFPFC_ADD
Prudential(25)
I dont think that sha1 is broken. Prove me wrong.
<html> <head> <title>level1</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php require 'flag.php'; if (isset($_GET['name']) and isset($_GET['password'])) { if ($_GET['name'] == $_GET['password']) print 'Your password can not be your name.'; else if (sha1($_GET['name']) === sha1($_GET['password'])) die('Flag: '.$flag); else print '<p class="alert">Invalid password.</p>'; } ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 1</a> </div> <form method="get"> <input type="text" required name="name" placeholder="Name"/><br/> <input type="text" required name="password" placeholder="Password" /><br/> <input type="submit"/> </form> </section> </body> </html>
sha1関数は引数に配列を渡すとFALSEを返すので、nameとpasswordを配列にするとフラグが取れる。
ただし$_GET['name'] == $_GET['password']
に引っかかるとNGなので、nameとpasswordにはそれぞれ違う文字列を入れる。
FLAG:I_think_that_I_just_broke_sha1
Symphony(25)
A less than four characters number, bigger than 999? Maybe the bug is elsewhere.
<html> <head> <title>level2</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php require 'flag.php'; if (isset($_GET['password'])) { if (is_numeric($_GET['password'])){ if (strlen($_GET['password']) < 4){ if ($_GET['password'] > 999) die('Flag: '.$flag); else print '<p class="alert">Too little</p>'; } else print '<p class="alert">Too long</p>'; } else print '<p class="alert">Password is not numeric</p>'; } ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 2</a> </div> <form method="get"> <input type="text" required name="password" placeholder="Password" /><br/> <input type="submit"/> </form> </section> </body> </html>
is_numeric関数は指数表記も通すので、1e3
とか入れればOK。
FLAG:B4SE10_IS_F0R_LOSERS
Northeastern Univ.(25)
Of course, a timing attack might be the answer, but Im quite sure that you can do better than that.
<html> <head> <title>level3</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php require 'flag.php'; if (isset($_GET['password'])) { if (strcmp($_GET['password'], $flag) == 0) die('Flag: '.$flag); else print '<p class="alert">Invalid password.</p>'; } ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 3</a> </div> <form method="get"> <input type="text" required name="password" placeholder="Password" /><br/> <input type="submit"/> </form> </section> </body> </html>
strcmp関数は引数に文字列以外を渡すと0を返す。
従って、Prudential同様に配列にすればOK。
FLAG:Still_better_than_the_d0uble_equals
Museum of Fine Arts(25)
Because cryptography is hard, we only implemented a hand-made PRNG. What could possibly go wrong?
<html> <head> <title>level4</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php session_start(); require 'flag.php'; if (isset ($_GET['password'])) { if ($_GET['password'] == $_SESSION['password']) die ('Flag: '.$flag); else print '<p class="alert">Wrong guess.</p>'; } // Unpredictable seed mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)); ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 4</a> </div> <ul class="list"> <?php for ($i=0; $i<3; $i++) print '<li>' . mt_rand (0, 0xffffff) . '</li>'; $_SESSION['password'] = mt_rand (0, 0xffffff); ?> </ul> <form method="get"> <input type="text" required name="password" placeholder="Next number" /><br/> <input type="submit"/> </form> </section> </body> </html>
mt_rand関数で生成された3つの整数から、4つ目の整数を予測して答える問題。
乱数の種さえわかってしまえばOKなので、システム時間から遡って総当たりで調べる。
<?php $hint = 0; fscanf(STDIN, "%d", $hint); $seed = microtime(); while(TRUE){ mt_srand(($seed ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)); if(mt_rand(0, 0xffffff) == $hint){ for($i = 0; $i < 3; $i++){ echo(mt_rand(0, 0xffffff));echo("\n"); } break; }else{ $seed--; } } ?>
FLAG:It_s33ms_that_PRNG_are_hard_too_after_all
Longwood Medical(25)
Because we dont trust mysqli_real_escape_string, we wrote our own military-grade sanitization method.
<html> <head> <title>level5</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php require 'flag.php'; if (isset ($_GET['login']) and isset ($_GET['password'])) { $name = $_GET['login']; $password = $_GET['password']; if (ctype_alnum ($name) and ctype_alnum ($password)) { $request = 'SELECT login FROM user where login = ' . $name . ' AND password = ' . $password . ';'; $db = new SQLite3 (sha1($flag).'.db', SQLITE3_OPEN_READONLY); // Ghetto anti-database-download $result = $db->querySingle ($request); $db->close (); if ($result === FALSE) echo '<p class="alert">"Invalid login or password</p>'; else die('Flag: ' . $flag); } else echo '<p class="alert">Invalid chars detected</p>'; } ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 5</a> </div> <form method="get"> <input type="text" required name="login" placeholder="Name"/><br/> <input type="text" required name="password" placeholder="Password" /><br/> <input type="submit"/> </form> </section> </body> </html>
querySingleは結果がない場合はNULLを返し、クエリがエラーになったときにFALSEを返す。
nameとpasswordを数値にすればエラーにならないので、nameとpasswordに数字を入れる。
FLAG:Did_you_know_that_in_french_a_chiken_makes_the_sound_quotquotquotquot?
Brigham Circle(25)
<html> <head> <title>level6</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php require 'flag.php'; if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE) echo '<p class="alert">You password must be alphanumeric</p>'; else if (strpos ($_GET['password'], '--') !== FALSE) die('Flag: ' . $flag); else echo '<p class="alert">Invalid password</p>'; } ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 6</a> </div> <form method="get"> <input type="text" required name="password" placeholder="Password" /><br/> <input type="submit"/> </form> </section> </body> </html>
ereg関数はNULLバイトセーフではないので、"a\0--"
とか送ればOK。
FLAG:OK_Maybe_using_rexpexp_wasnt_a_clever_move