MySQL防范SQL注入风险
0、导读
在MySQL里,如何识别并且避免发生SQL注入风险
1、关于SQL注入
互联网很危险,信息及数据安全很重要,SQL注入是最常见的入侵手段之一,其技术门槛低、成本低、收益大,颇受各层次的黑客们所青睐。
一般来说,SQL注入的手法是利用各种机会将恶意SQL代码添加到程序参数中,并最终被服务器端执行,造成不良后果。
例如,我们访问接口 http://imysql.com/user.php?userid=123 来根据userid获取用户信息,假设程序中是这么处理的:
$sql = “SELECT * FROM user WHERE userid = $_GET[userid]“;
上面这段代码看起来既low有很xx对吧,尤其是在双引号里面还可以直接引用数据类型变量,所以说php是世界上最好的语言一点不为过,哈哈(其实我早期也写过几年php的)。
这时候,如果我们传递进去的参数改成这样:http://imysql.com/user.php?userid=123 or 1=1,这就会导致SQL条件永远成立,所有的数据都会被读取出来。又或者可以传递这样的参数:http://imysql.com/user.php?userid=123 or if(now()=sysdate(),sleep(5),1),这时候不但所有的数据都会被读取到,也会让这个SQL执行完毕后再等待5秒才能返回,黑客可据此来判断这个SQL注入探测是否成功。
在上面这个例子中,其实我们只需要对用户输入的参数进行简单的类型判断和控制,即可快速避免被注入的风险,例如改成下面这样就可以了:
$userid = intval(strim($_GET[‘userid’]));
$sql = “SELECT * FROM user WHERE userid = “ . mysql_real_escape_string($userid);
可见,至少基础的SQL注入并不难防范,只要在各个层面都做足工作就可以。而简单的SQL盲注(就是乱拳打死老师傅的玩法)已经可以采用sqlmap之类的辅助工具来做了,完全不需要人工执行。
2、如何防范
上面提到过sqlmap,它既可以作为SQL盲注的工具,也可以在新项目上线前内部扫一次,提前发现潜在漏洞,及时修补,反过来为我们所用。其他可以检测sql注入漏洞的知名扫描工具有:SQLIer、SQLID、SQL Power Injector、SQLNinja。
我们也可以自己通过频繁扫描当前执行的SQL列表,根据一些关键字来判断是否发生了SQL注入或潜在风险,常见的关键字有:
SLEEP() — 一般的SQL盲注都会伴随SLEEP()函数出现,而且一般至少SLEEP 5秒以上
MID()
CHAR()
ORD()
SYSDATE()
SUBSTRING()
DATABASES()
SCHEMA()
USER()
VERSION()
CURRENT_USER()
LOAD_FILE()
OUTFILE/DUMPFILE
INFORMATION_SCHEMA
TABLE_NAME
fwrite()/fopen()/file_get_contents() — 这几个是PHP文件操作函数
我们可以以较高频率检查当前的活跃SQL命令,一旦发现上述关键字,可以立即记录下来并触发告警,通知管理员及时人工确认处理,甚至也可以先直接自动杀掉这些SQL查询(可以用 pt-kill 工具来做到这点,也可以自行开发),以防万一,少给黑客留机会。
还有,我们建议把选项 safe-update/sql_safe_updates 设置为 1,防止没有任何 WHERE 条件的误操作更新,将全表数据都写错。
3、其他建议
防范SQL注入只是数据安全保护工作很小的一部分,只要做好基本功就可以防住至少80%以上的SQL注入探测。
在app server层,以PHP开发语言为例,除了上面提到的规范用户输入类型外,还可以改成用 sprintf() 函数来格式化构造 SQL 语句,也可以一定程度防范SQL注入。还可以修改 php cgi 程序的运行属主为普通用户,最起码不能使用 root 用户,避免因为代码层不严谨导致被黑客上传可执行 php 程序代码文件。还可以把php中的远程文件调用权限关闭,把选项 allow_url_fopen、allow_url_include 均设置为 off,并限定php可以打开的文件目录,不允许跨区域访问敏感文件。
除了在代码层面做好数据类型判断、用户输入判断外,还可以在web server层加上过滤策略,比如在nginx上启用WAF插件。或者,也可以购买IDC运营商、云主机提供商提供的商业解决方案。对于重视数据安全的企业来说,花点钱保平安更为重要。
4、附录
下面是一些常见SQL注入参考案例:
案例1:SELECT * FROM t WHERE a LIKE ‘%xxx%’ OR (IF(NOW=SYSDATE(), SLEEP(5), 1)) OR b LIKE ‘1=1‘;
案例2:SELECT * FROM t WHERE a > 0 AND b IN(497 AND (SELECT * FROM (SELECT(SLEEP(20)))a));
案例3:SELECT * FROM t WHERE a=1 and b in (1234,(SELECT (CASE WHEN (5=5) THEN SLEEP(5) ELSE 5*(SELECT 5 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END)));
建议继续学习:
- STRUTS2类型转换错误导致OGNL表达式注入漏洞分析 (阅读:9119)
- 程序员疫苗:代码注入 (阅读:6759)
- 使用参数化查询防止SQL注入漏洞 (阅读:2751)
- Android安全–加强版Smali Log注入 (阅读:2747)
- javascript依赖注入 (阅读:2385)
- XML实体注入漏洞安全警告 (阅读:2294)
- bash代码注入的安全漏洞 (阅读:2114)
- JavaScript里的依赖注入 (阅读:2081)
- 解决 SQL 注入的另类方法 (阅读:1503)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:叶金荣 来源: iMySQL
- 标签: 注入
- 发布时间:2016-04-05 10:17:11
- [68] Go Reflect 性能
- [68] 如何拿下简短的域名
- [67] Oracle MTS模式下 进程地址与会话信
- [62] IOS安全–浅谈关于IOS加固的几种方法
- [61] 图书馆的世界纪录
- [60] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [56] 视觉调整-设计师 vs. 逻辑
- [49] 给自己的字体课(一)——英文字体基础
- [48] 读书笔记-壹百度:百度十年千倍的29条法则