安全架构系列文章
SQL注入原理及防范
前言
一、sql注入是什么?
SQL注入是通过客户端的输入把SQL命令注入到一个应用的数据库中,从而执行恶意的SQL语句。
*
什么意思呢?我们来打个比方:我们有一个登录框,需要输入用户名和密码对吧,然后我们的密码输入 'or ‘123’ = '123 这样的。
我们在查询用户名和密码是否正确的时候,本来执行的sql语句是:select * from user where username = ‘’
and password = ‘’. 这样的sql语句,现在我们输入密码是如上这样的,然后我们会通过参数进行拼接,拼接后的sql语句就是:
select * from user where username = ‘’ and password = ’ ’ or ‘123’ =
‘123 ‘; 这样的了,那么会有一个or语句,只要这两个有一个是正确的话,就条件成立,因此 123 = 123
是成立的。因此验证就会被跳过。这只是一个简单的列子,比如还有密码比如是这样的:’; drop table user;,
这样的话,那么sql命令就变成了: select * from user where username = ‘’ and password
= ‘’; drop table user;’ , 那么这个时候我们会把user表直接删除了。
sql被攻击的原因是:sql语句伪造参数,然后对参数进行拼接后形成xss攻击的sql语句。最后会导致数据库被攻击了。
二、防范方法
- 我们可以使用预编译语句(PreparedStatement,这样的话即使我们使用sql语句伪造成参数,到了服务端的时候,这个伪造sql语句的参数也只是简单的字符,并不能起到攻击的作用。
- 数据库中密码不应明文存储的,可以对密码使用md5进行加密,为了加大破解成本,所以可以采用加盐的方式。
1.Java处理
1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
如:where username=#{username},如果传入的值是111,那么解析成sql时的值为where username="111", 如果传入的值是id,则解析成的sql为where username="id".
2、$将传入的数据直接显示生成在sql中。
如:where username=${username},如果传入的值是111,那么解析成sql时的值为where username=111;
如果传入的值是;drop table user;,则解析成的sql为:select id, username, password, role from user where username=;drop table user;
3、#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
4、$方式一般用于传入数据库对象,例如传入表名.
5、一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。
6、在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。
2 .NET处理
使用SqlParameter,不要直接拼接参数到sql字符串中
public UserInfoModel Login(UserInfoModel model)
7 {
8 UserInfoModel userInfoModel = null;
9 string sql = @"select UserName, Password from UserInfos
10 where UserName=@UserName and Password=@Password";
11 SqlParameter[] paras =
12 {
13 new SqlParameter("@UserName",model.UserName),
14 new SqlParameter("@Password",model.Password)
15 };
16 DataRow row = DBHelper.GetDataRow(sql, paras);
17 if (row != null)
18 {
19 userInfoModel = new UserInfoModel();
20 userInfoModel.UserName = row["UserName"].ToString();
21 userInfoModel.Password = row["Password"].ToString();
22 }
23 return userInfoModel;//true false
24 }
总结
使用各语言的sql预编译处理功能,即可很好的防范SQL注入,我们需要有sql注入攻击的意识,不要手动写字符串拼接sql进行执行。否则,后果很严重。