什么是SQL注入

SQL注入在早期的互联网系统中很常见,大多数是因为程序员没有考虑到sql注入的问题,没有对sql语句的参数进行过滤而直接使用字符串拼接的方式来传值,这就给SQL注入造成了可能。

不能公开做违法乱纪的事,所以我自己写了个示例程序,来重现一下当时遇到的安全问题。
首先是sql注入

简单的登录表单页面

执行登录验证操作的程序

数据库

启动Tomcat服务器,访问项目

输入用户名和密码,假设我们不知道密码,这里故意输错密码,随便输入一个错误的密码,
点击登录

我们回到登录页面,测试一下sql注入

点击登录,发现登录成功!

我们在不知道用户名和密码的情况下成功的登录到了登录成功后的页面,实现了sql注入。
问题主要出在执行登录程序的数据库查询的sql语句

1
SELECT * FROM user WHERE username='"+userName+"' AND password='"+passWord+"'"

使用这种拼接的方式容易给攻击者注入的机会,这里拼接上我们传进来的用户名和密码,我在登录表单那里输入的数据拼接进来后变成这样

1
SELECT * FROM user WHERE username='' or 1=1 #' AND password='1234567890'

可以看到前面的符号 ‘ 把我们把用户名值切断掉,让数据库查询条件变成查询用户名为空字符串的,此时数据库虽然没有匹配的记录,但是我们在后面再拼接上 or 1=1 这样就可以把数据库中user表的所有记录都查询出来,然后输入#号会把后面的sql语句都注释掉不执行
最终执行的sql语句变成这样:

1
SELECT * FROM user WHERE username='' or 1=1

我们成功注入 or 1=1 并且跳转到登录成功后的页面,这种注入还可以让我们执行任意sql语句,比如执行删除语句把整个数据库数据都删除!

如果程序中的sql拼接改成这样

1
SELECT * FROM user WHERE username="+userName+" AND password="+passWord

那我们的sql注入就需要多加个’号

1
'' or 1=1 #

对应mysql数据库,注释符是用#号,如果是其他数据库,比如SQL Server数据库,我们要使用两个 - 符号即可注释掉后面的sql语句。sql拼接的这种语句很容易让攻击者注入,只需要多试几次就可以实现注入。

为了防止这种常见的低级注入,我们不要使用拼接sql的方式来查询数据库。我发现目前的教科书和学校教的web编程课程中都没有提到类似的安全性问题,为了便于学生理解,很多都是使用sql拼接,我觉得关于web安全这点在学习过程中一定要时刻注意,防止犯一些低级错误。
要始终牢记,用户的输入永远都是不可信的,一定要做校验和转换。
像hibernate这类ORM框架已经替我们实现好了这一点,如果要自己用jdbc写的话,建议使用PreparedStatement进行传参数的方式防止sql注入。
从网络安全的角度去思考问题,有助于开发出比较健壮相对比较安全的网站。对提高自身编程水平也是有帮助的。如果从事web开发,这种安全问题其实也是必须要指定并且尽量去避免的。
框架虽然帮我们实现了这些功能但是我们还是要去学习他,我们可以学习框架的设计思想,达到提高自己的目的。
比较常见的web攻击除了sql注入,还有xss等。我在后续的文章中会讲到。

0%