-
SQL注入介绍
结构化查询语言(SQL)主要用于与数据库交互的文本语言,SQL Injection就是利用某些数据库的外部接口将用户数据插入到实际的数据库操作语言中,从而达到入侵数据库乃至操作系统的目的,主要由于程序对用户输入的数据没有进行严格的过滤,导致非法数据库查询语句执行。
SQL注入攻击具有很大的危险,可以利用它读取、修改或者删除数据库内的数据,获取数据库中的用户名和密码等敏感信息,甚至可以获得数据库员的权限,SQL Injection也很难防范,无法通过安装系统补丁或进行简单的安全配置进行自我保护,一般防火墙也无法拦截SQL Injection攻击。http://127.0.0.1/user.php?username=angel' or '1=1
这样的SQL可以登录系统。因为添加了一个恒等。
http://127.0.0.1/user.php?username=angel' /*
http://127.0.0.1/user.php?username=angel' #在SQL中,"/*","#" 可以将后面的语句注释掉。
-
PrepareStatement+Bind-variable
对Java、JSP开发的应用,可以使用PrepareStatement+Bind-variable来防止SQL注入,
php5开始,扩展mysqli中支持PrepareStatement,在使用这类语言作为数据库开发时,强烈建议使用PrepareStatement+Bind-variable来实现,尽量不要使用拼接的SQL。 -
使用应用程序提供的转换函数
mysql c api:使用mysql_real_escape_string() API调用。
mysql++ :使用escape和quote修饰符。
php : 使用mysqli,支持PrepareStatement.
perl DBI :使用placeholders或者quote方法。
ruby DBI:使用placeholders或者quote方法。pymysql为例, 它在执行sql前,会对sql中的特殊字符进行转义,如
字符转义:
def escape_string(value, mapping=None):
"""escape_string escapes value but not surround it with quotes.
Value should be bytes or unicode.
"""
if isinstance(value, unicode):
return _escape_unicode(value)
assert isinstance(value, (bytes, bytearray))
value = value.replace('\\', '\\\\')
value = value.replace('\0', '\\0')
value = value.replace('\n', '\\n')
value = value.replace('\r', '\\r')
value = value.replace('\032', '\\Z')
value = value.replace("'", "\\'")
value = value.replace('"', '\\"')
return value
执行sql的正确方法,不要在sql中拼接参数,字符转义只会针对参数args
execute(query, args=None)
django/sqlalchemy
orm框架都是使用pymysql/MySQL-python等库,并且都使用execute(query,args)调用,将sql与参数分开传入。
sql注入检测工具
sqlmap
- 自定义函数进行校验
如果现有转换函数仍然不能满足要求,需要自己编写函数进行输入效验,输入验证是一个很复杂的问题,输入验证的途径可以分为以下几种:
整理数据使之变得有效。
拒绝已知的非法输入 。
只接受已知的合法输入。
采用正则表达式来对用户提供的输入数据进行严格的检测和验证。
function safeRequest ($ParaName,$ParaType)
{
/---传入参数----/
/* ParaName:参数名称-字符型/
/ ParaType:参数类型-数字型(1表示参数是数字或字符,0表示参数为其他)/
if ($ParaType == 1)
{
$re = “/[^\w+$]/”;
}
else
{
$re = “/(|\’ | (%27)|;|(%3b)|=|(%3d)|(|(%28)|)|(%29)|(/)|(%2f%2a)|(\ */)|(%2a%2f)|+|(%2b)|<|(%3c)|>|(%3e)|(--)|[|%5b|]|%5b)/”;
}
if (preg_match($re,$PareName)>0)
{
echo (“参数不符合要求,请重新输入!”);
return 0;
}
else
{
return 1;
}
}