· 最近在学习sql注入,把最近学到的知识做一下总结,防止以后忘记。
一、SQL注入的原理
sql注入就是用户通过输入的数据,被当成SQL语句执行,来获取更多的数据、更大的权限。
通过一个小例子来理解:
一个正常的登录表单,输入正确的账号和密码,程序就会查询数据库。如果存在此用户且密码正确,将会登录成功;如果密码不正确,则会其实密码或账号错误。
下来采用用户" 'or 1=1 -- ",密码随便填写,在点击登陆后,发现可以正常登录。当然这样的漏洞现在已经很难找到了,在这里只是举一个简单的例子。
这是为什么呢,我们猜想一下,本来输入正确的用户名和密码,需要到数据库中去查询用户,判断用户是否存在且其密码是否正确。大胆的想一下,本来正确的数据库查询语句为:
select count(*) from admin where username='用户' and password='输入的密码'
如果用户名和密码正确,返回结果为1,大于0,能正常登录,如果密码和用户名错误,返回结果为0,小于0,不能正常登录。
接下来我们看一下特殊的用户" 'or 1=1 -- " ,最终执行的sql语句为:
select count(*) from admin where username=' ' or 1=1 -- ' and password ='输入的密码'
“--”后面的sql被注释掉了,不能执行,where uernane = '账户' or 1=1始终为真,最后上面的sql语句执行的结果等于是把admin表中的用户统计了一便,返回值肯定大于1,所以不管密码是什么,始终能登录成功。
注意:
mysql中有三钟注释方式1)#:注释从“#”字符到行尾 2)--:注释从“--”序列到行尾。需要注意的是,此注释后面需要跟上一个或多个空格 3)/**/:注释从/*到后面*/中间的字符
二、判断sql注点
如果通过一下三个步骤全部满足,则程序就可能存在sql注入漏洞。
假设url为http:172.0.0.1/test.php?id=1,可以猜想SQL语句为:
select * from table where id = 1
1) http:172.0.0.1/test.php?id=1' and 1=1
sql语句为:select * from table where id=1,这样的语句肯定会出错,导致程序无法执行,从而使页面出现异常。
2)http:172.0.0.1/test.php?id=1 and 1=1\
sql语句为:select * from table where id=1 and 1=1,返回正常的页面,没有任何差异。
3)http:172.0.0.1/test.php?id=1 and 1=2
sql语句为:select * from table where id=1 and 1=2,语句执行正常,但无法查询数据。返回的数据和原始页面有差异。
以上三个条件都满足的,则程序可能存在注入异常。当然判断注点的三个步骤不能是我想的,我也是个初学者,都是别人总结好的,只要记住就行。
三、sql注入实践
首先需要搭建学习sql注入的网站,我选则的是dvwa,在网上搜一下,就能搜到,安装方法讲的很清楚,我就不罗嗦了。
登录以后,需要将dvwa的安全等级调到low级别。
1、找到SQL Injection,我们安找上学的,判断它有没有注入漏洞。
输入1,提交后,返回了正确的数据
输入1',结果返回:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1''' at line 1
看到这里,就高兴了,在这里存在sql注入漏洞。
2、我们尝试一下,看能不能获取到表中的所有数据,试一下,输入1 or 1=1,结果只得到了一个数据
接下来,把id 当做一个字符串试一下,输入1' or '1' = '1,结果查询到了表中的所有数据。
要注意的是输入的参数是字符型还是数字型,数字型不需要单引号闭合,而字符型需要字符型需要单引号来闭合。
3、测试查询表中的列数。通过order by num
依次输入“1' order by 1 -- ” "1' order by 2 --" "1' order by 3 -- ",可以看到输入前两个可以返回正常的值,当输入“1’ order by 3 -- ”,没有返回正常的值,报了一个错, Unknown column '3' in 'order clause'。由此可以判断,表一共有两列。
4、查询判断列名
第一步,尝试输入“1' and 1=2 union select 1,2 -- ” ,得到以下结果
由此可判断出first name 为第一列,surname为第二列
4、通过数据库内置函数user(),database(),version(),查询数据库的用户、数据的名称
尝试输入“1' and 1=2 union select user(),database() -- ”,得到结果