7

I'm trying to solve a challenge on a CTF, with PHP sessions. The goal is to make check.php echo $_PASSWORD.

I do not have access to the files themselves, and therefore I cannot edit them.

My proposed solution is:

  1. We want the session to be locked for 20 seconds, therefore we need to make eat.php run that much time.
  2. At the same time, we need to run check.php, having it set $time and then wait for the session to be unlocked.
  3. Now we need to unlock the session, which means we need to stop eat.php.
  4. check.php will continue running, the following expression: $time+20!=$_SESSION['time'] will be false, and PHP will echo $_PASSWORD.

Is my proposal possible? If it is, how would you implement it? I'd also like to hear about other directions for solving this problem.

get.php:

<?php
setcookie('id',uniqid());
?>

eat.php:

<?php
$cookie=$_POST['cookie'];
session_save_path('/home/mawekl/timetravel/');
session_start();
echo 'You ate: '.htmlspecialchars($cookie);
echo "\n<br>";
$_SESSION['cookie']=$cookie;
$_SESSION['time']=time();
?> 

check.php:

<?php
$cookie=$_COOKIE['id'];
$time=time();
session_save_path('/home/mawekl/timetravel/');
session_start();
if ($cookie!=$_SESSION['cookie'])
    die('Wrong cookie');
if ($time+20!=$_SESSION['time'])
    die('You must eat cookie after 20 seconds from now, but you ate it '.($time-$_SESSION['time']).' seconds ago');
echo $_PASSWORD;
?> 
techraf
  • 9,141
  • 11
  • 44
  • 62
Roee H
  • 139
  • 1
  • 5
  • 1
    Do you have access to the files? – Tom Jun 12 '16 at 21:03
  • 2
    I thought I was pretty clear about that.. No access whatsoever – Roee H Jun 12 '16 at 21:05
  • Do you have *any* access to the server? If you can deploy *other* scripts or code accessible via the webserver then blocking the session and hence the execution of check.php at session_start() is trivial. But in most such scenarios you could read the code and hence the value represented by $_PASSWORD directly. – symcbean Jun 12 '16 at 22:21
  • Negative, as OP mentioned in the post. – Tom Jun 12 '16 at 22:22
  • Op only said they had no access to these files. – symcbean Jun 12 '16 at 22:24
  • I can only send requests to theses pages. – Roee H Jun 12 '16 at 22:25
  • 2
    a. Are these request all served from the same server? Or is it possible one server has a slow clock? b. How do the eat.php response times vary to a very large value of $_POST['cookie']? – thexacre Jun 12 '16 at 23:47
  • 1
    Why can't you call `eat.php` and then call `check.php` 20 seconds later? Is the session discarded if you do that? – Sjoerd Jun 13 '16 at 07:23
  • 2
    @Sjoerd You misread the challenge. The challenge is to have the cookie set 20 seconds INTO THE FUTURE. – Tom Jun 13 '16 at 07:33

1 Answers1

1

I might be wrong of course, since I don't know the solution, but here's my analysis.

get.php can be completely ignored, as you can make up a random id cookie value.

We might not have all the necessary information. Does the server run Apache or something else? Which PHP version was used? Is there a description for the challenge (they often contain obscure hints)?

As it stands, I see only two realistic ways of approaching this that: injecting data into that $_SESSION['time'] variable, or making check.php pause after $time=time(); and before $time+20!=$_SESSION['time'].

Looking for injection vulnerabilities in PHP, I only found CVE-2006-3016 (PHP 5.1) but it contains very few details and they'd have to run a very old PHP version anyway. Last year someone also reported a session injection vulnerability, but it seems not to be applicable. This avenue does not seem very feasible.

This leaves the pausing trick. I was thinking of something like this:

  1. Open a lot of connections and let them request eat.php with large $_POST['cookie'] values to make it take a lot of time to write all the sessions.
  2. Request check.php, which will hang until step 1 is complete. Vary the amount of requests done in step 1 until it takes exactly 20 seconds.

This would require the server to do multithreading, since it needs to leave check.php in a sleeping state and perform a bunch of eat.php requests in the background.

The issue with this is that each eat.php needs to write to the same session, or it wouldn't block at all in check.php (since there would be no thread locking the session that check.php tries to read). But if each successive eat.php completion updates the $_SESSION['time'] value to something more recent, it is not going to have an old time value. So this does not work either. (It could perhaps work if PHP blocks on any session still being written to, then another session could be updated in eat.php and still leave check.php hanging, but this seems unlikely so I haven't explored the possibility.)

In short, we need more information and perhaps even access to a challenge environment. From my perspective, it seems impossible without another vulnerability (e.g. sending false NTP updates).

To answer your question

Yes, your proposed solution would probably work. Just one issue: how would you actually manage to make it do this? ;)

Luc
  • 31,973
  • 8
  • 71
  • 135