HackThisSite - Extended Basic Mission 07

Challenge

修正一个 PHP 页面里同时带有 bug 和漏洞的那一行,提交修正后的整行。

关卡页给出的是一段数据录入代码,要求:There is only one line that has a vuln, correct it. The output does not have to be valid XHTML and assume that a mysql connection has been made already. There is a bug as well as a vuln. You MUST fix both.

1
2
3
4
5
6
7
8
9
10
11
<?php
if(!empty($_POST['data']))
{
$data = mysql_real_escape_string($_POST['data']);
mysql_query("INSERT INTO tbl_data (data) VALUES ('$data')");
}
?>
<form name="grezvahfvfnjuvavatovgpu" action="<?=$_SERVER['PHP_SELF']?>" method="get">
<input type="text" name="data" />
<input type="submit" />
</form>

Solution

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
53
54
55
#!/usr/bin/env python3
"""HackThisSite Extended Basic 7 (playit) live solver.

The level prints a tiny PHP page and asks for the one line that carries both a
bug and a vulnerability:

<form name="grezvahfvfnjuvavatovgpu" action="<?=$_SERVER['PHP_SELF']?>" method="get">

* vuln: ``$_SERVER['PHP_SELF']`` is echoed raw into the ``action`` attribute, so
a path like ``/x.php/"><script>alert(1)</script>`` is reflected as markup and
becomes XSS. ``htmlspecialchars()`` fixes it.
* bug: the form submits with ``method="get"`` while the handler only reads
``$_POST['data']``, so the INSERT never runs. ``method="post"`` fixes it.

The corrected line is posted to ``/missions/extbasic/template.php`` together with
the per-load ``formkey`` and ``lvl``. A ``Referer`` pointing at the level page is
mandatory, otherwise the endpoint answers ``Invalid Referer`` and the attempt does
not count. The session cookie comes from ``HTS_COOKIE`` and is never persisted.
"""
import os
import re
import urllib.parse
import urllib.request

UA = ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/131.0.0.0 Safari/537.36")
BASE = "https://www.hackthissite.org"
LEVEL = BASE + "/missions/playit/extbasic/7/"
TEMPLATE = BASE + "/missions/extbasic/template.php"
CK = os.environ["HTS_COOKIE"]

ANSWER = (
'<form name="grezvahfvfnjuvavatovgpu" '
'action="<?=htmlspecialchars($_SERVER[\'PHP_SELF\'])?>" method="post">'
)

def get(url):
req = urllib.request.Request(url, headers={"Cookie": CK, "User-Agent": UA})
return urllib.request.urlopen(req, timeout=30).read().decode("utf-8", "replace")

def main():
page = get(LEVEL)
formkey = re.search(r'name="formkey" value="([^"]+)"', page).group(1)
data = urllib.parse.urlencode(
{"formkey": formkey, "lvl": "7", "pass": ANSWER}).encode()
req = urllib.request.Request(
TEMPLATE, data=data,
headers={"Cookie": CK, "User-Agent": UA,
"Content-Type": "application/x-www-form-urlencoded",
"Referer": LEVEL})
resp = urllib.request.urlopen(req, timeout=30).read().decode("utf-8", "replace")
print("go-on link to level 8:", "/missions/playit/extbasic/8" in resp)

if __name__ == "__main__":
main()