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 |
|
Solution
题面限定只有一行有漏洞,并额外提示 bug 和 vuln 都要修。
- 前面四行是标准的先转义再拼接写法:
mysql_real_escape_string负责把$_POST['data']里的引号等字符转义;题面明确说明数据库连接已经建立(该函数需要一个活动连接才能工作),所以这段拼接没有缺陷。 - 真正承载输入 → 输出的只有末尾那一个
<form ...>标签:它一边把$_SERVER['PHP_SELF']输出进 HTML,一边决定表单用什么方法回传。两个缺陷正好都落在这同一行,对应题面的一行有漏洞加上 bug/vuln 都要修。
$_SERVER['PHP_SELF'] 是当前脚本的路径,会把用户可控的
PATH_INFO 一并包含进来。攻击者可以请求:
1 | /missions/playit/extbasic/7/index.php/"><script>alert(1)</script> |
此时 PHP_SELF 的值就是
/missions/playit/extbasic/7/index.php/"><script>alert(1)</script>,被原样拼进
action="..." 后会提前闭合属性并注入脚本标签,形成反射型
XSS:
1 | <form name="grezvahfvfnjuvavatovgpu" action="/missions/playit/extbasic/7/index.php/"><script>alert(1)</script>" method="get"> |
修法是用 htmlspecialchars() 把 <
> " ' 等字符转成 HTML
实体再放进属性;闭合用的引号被转义后无法逃逸:
1 | action="<?=htmlspecialchars($_SERVER['PHP_SELF'])?>" |
这里 PHP_SELF
只出现在输出上下文里,按输出位置转义即可,它并没有参与 SQL 拼接。
处理逻辑读的是 $_POST['data']:
1 | if(!empty($_POST['data'])) |
但表单写的是 method="get",会把 data
作为查询参数写入 URL,$_POST['data']
永远为空,if 分支进不去,INSERT
从不执行。这是功能层面的 bug。把表单方法改成 method="post"
即可:
1 | method="post" |
把两处修复合回原行,注意保留页面原有的
<?=$_SERVER['PHP_SELF']?> 写法:
1 | <form name="grezvahfvfnjuvavatovgpu" action="<?=htmlspecialchars($_SERVER['PHP_SELF'])?>" method="post"> |
playit 类别统一提交到
POST /missions/extbasic/template.php,字段为
formkey(每次加载关卡页都会变)、lvl、pass。提交必须带上
Referer: .../playit/extbasic/7/,否则服务端返回
Invalid Referer 且不计完成;formkey
是一次性的,抓页面后立刻提交要在同一流程里完成。
1 | #!/usr/bin/env python3 |
运行输出:
1 | $ cd <hts-workspace> && uv run python challenges/hts-playit/extbasic-7/solve.py |
被接受的提交会在响应里给出指向第 8 关的 GoOn.gif
链接;profile 的 Extbasic: 一行由
(1) (2) (3) (4) (5) (6) 变为
(1) (2) (3) (4) (5) (6) (7),类别总览里第 7 关也从
<font class="incomplete"> 换成完成样式。
一个易错点是把标签写成
action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>"(在
PHP 标签内侧留空格)会被判错。页面里的原始写法是
<?=$_SERVER['PHP_SELF']?>,提交端按这一规范形态比对,修正应原地包裹,且不引入额外空格。
Key points
- 输出转义要按上下文选函数:拼进 HTML 属性用
htmlspecialchars,拼进 SQL 才用mysql_real_escape_string,两者不能互相替代。 $_SERVER['PHP_SELF']含有用户可控的 PATH_INFO,直接回显就是反射型 XSS;现代写法是用action=""让表单提交回当前 URL,确需显示路径时再转义。- 表单
method必须和处理端读取的超全局数组一致:get对$_GET、post对$_POST,错配会让处理分支永远进不去。 - 同一行可以同时承载多个缺陷:本例的
<form ...>既输出了未转义数据(vuln),又选错了请求方法(bug)。 - playit 提交按原样区分空格与大小写,修正片段应与页面给出的原始写法保持一致,不得重排格式。