7.3 正确的防御sql注入
只对用户的输入做escape是不够的,黑客的注入攻击总能找到绕过黑名单过滤的方法。
7.3.1 使用预编译语句
防御sql注入的最佳方式,就是使用预编译语句,绑定变量。
各种不同的语言中,用法各异:
Java EE, use PreparedStatement()
.NET, use SqlCommand() or OleDbCommand()
PHP, use bindParam()
Hibernate, use createQuery()
SQLite, use sqlite3_prepare()
7.3.2 使用存储过程
需要注意的是,存储过程也可能会有注入问题,需尽量避免在存储过程中使用动态的SQL语句,如果无法避免,则应严格执行输入过滤。
7.3.3 检查数据类型
检查输入数据的数据类型,在很大程度上可以对抗sql注入。例如,限制用户的输入只能是int。
7.3.4 使用安全函数
可以参考OWASP ESAPI,由安全专家编写:
ESAPI.encoder().encodeForSQL(new OracleCodec(), queryparam);
最后,从数据库自身的角度,应该使用最小权限原则,避免web应用直接使用root、dbowner等高权限账户直接连接数据库。
7.4 其他注入攻击
注入攻击产生的原因是应用违背了“数据与代码分离”原则。
7.4.1 XML注入
参考http://www.51testing.com/html/47/352747-814931.html
修补方案是对用户输入的“语言本身的保留字符”进行转义。
7.4.2 代码注入
代码注入与命令注入都是由一些不安全的函数或者方法引起的。最常见的是eval()注入:
$myvar = "varname"; $x = $_GET(‘arg‘); eval("\$myvar = $x;");
攻击者可以通过如下payload实施代码注入:
/index.php?arg=1;phpinfo()
Java中可以通过engine.eval实施代码注入,JSP的动态include也能导致代码注入,严格来说,PHP、JSP的动态include(文件包含漏洞)导致的代码执行,都可以算是一种代码注入。
如果代码注入的是system函数,就能造成命令注入。
对抗这些注入时,应该禁用eval()、system()等函数,否则应该对用户输入做处理。
7.4.3 CRLF注入
这是利用换行符\r\n进行注入,其十六进制为0x0d、0x0a。它的危害是插入日志数据、更改HTTP头等。
原文:http://quiterr.blog.51cto.com/10710132/1701952