SQL注入基础之有回显的注入流程和简单的SQL注入检测程序

SQL注入基础、有回显的注入流程和简单的SQL注入检测程序

声明:请不要进行非授权的SQL注入行为

注入原理

SQL注入(SQL Injection) 是一种常见的网络安全漏洞,攻击者通过在Web应用程序的输入字段中插入恶意的SQL代码,试图篡改或控制后端数据库的查询逻辑,从而获取敏感信息、篡改数据或执行其他恶意操作。
SQL注入的原理是基于Web应用程序在构建SQL查询时,未能正确处理用户输入,导致恶意代码被误认为是SQL语句的一部分并执行。
例如:

select 用户输入 from grade where id =1;

当用户输入为

database()-- //--后有一个空格,表示sql语句的注释符(这里的-- 注释在实际进行注入会被url编码为--+)

整体的查询语句就变成

select database()-- from grade where id =1;

实际上生效的代码为

select database()

database()还不是特别的敏感,但是如果是

select password from passwd where id = 123-- from grade where id =1;

查询数据库表中的信息就会导致信息泄露,甚至拿到管理员的密码(但是一般密码会被hash存储)

注入流程

1.有回显

比如在dvwa靶场里输入 1' 很明显有报错提示,那很有可能有sql注入,有回显报错信息的也是最简单的注入情况。

2.判断数字型还是字符型

直观点看:

select * from users where id = 1;//数字型
select * from users where id = '1';//字符型

数字型的检测方法——分别输入:
1 and 1=1————正常返回
1 and 1=2————失败返回
字符型的检测方法——分别输入:
1' and '1'='1————正常返回
1' and '1'='2————失败返回
拿dvwa靶场的low级别的sql注入来说,这是一个字符型的注入:
输入1' and '1'='1 返回:

输入1' and '1'='2 返回:

前一个成功了,后一个失败了,所以后一个啥也没有显示。
字符型和数字型其实就是带不带引号的问题,那么为什么要这么关注这个问题呢?因为
比如字符型:
select * from users where id = '用户输入';
用户输入 1 and 1=1
生效的是select * from users where id = '1 and 1=1';
引号里的一长串的东西会被解析为'1'一般来说就是字符串第一个数字
实际上生效的等价于生效的是

select * from users where id = '1 and 1=1';

如果你在字符型的注入输入1 and 1=2即使and后面不成立也会正常显示页面便是上面说的道理。

2.判断列数

在输入框中输入1' order by 2--+

在输入框中输入1' order by 3--+时出现了报错,那么只有两列

3.联合查询

在判断完列数之后看看哪些列的数值会被回显:
输入-1' union select 1,2--+
注意前半部分需要是一个不能被查到的,这里使用-1,因为一般网页上只会回显第一列,需要前半部分的查询失效以便后面的union查询生效

这里发现两列都会被回显。列1对应First Name,列2对应Surname。
3.1查询database名称
使用-1' union select 2,database()--+

3.2查询表名称
使用-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'--+查询表名

3.3查询列名称
使用-1' union select 1,group_concat(column_name) from information_schema.columns where table_name='guestbook' and table_schema='dvwa'--+查询字段名

3.4查询数据
现在数据库、表名、字段名都有便可以直接查询,使用-1' union select 1,name from guestbook--+

以上是最基本最简单的SQL注入的流程,除此之外还有布尔盲注、时间盲注、报错注入等。

检测SQL注入的简单python程序

import re

def preprocess_sql(sql):
    """对SQL语句进行预处理"""
    sql = sql.strip()  # 去除首尾空白字符
    sql = sql.lower()  # 转换为小写
    return sql

def detect_sql_injection(sql):
    """检测SQL注入风险"""
    # 预处理SQL语句
    sql = preprocess_sql(sql)

    # 定义常见的SQL注入特征正则表达式
    patterns = [
        r"'",  
        r'"',  
        r";",  
        r"--",  
        r"\/\*",  
        r"\*\/",
        r"union", 
        r"or\s+1=1",  
        r"and\s+1=1",
        r"sleep\(",  
        r"benchmark\("
    ]

    # 检测SQL语句中是否存在上述特征
    for pattern in patterns:
        if re.search(pattern, sql):
            return True

    return False

def main():
    # 接收输入的SQL语句
    sql = input("请输入SQL语句:")

    # 检测SQL注入风险
    if detect_sql_injection(sql):
        print("检测到SQL注入风险!")
        # 根据检测到的特征提供可能的攻击类型和建议的防御措施
        if "--" in sql or "/*" in sql or "*/" in sql:
            print("该语句中包含注释符号,可能是试图绕过SQL语句的正常逻辑。")
        if "union" in sql:
            print("该语句中包含union关键字,可能是试图联合查询数据库信息。")
        if "or 1=1" in sql or "and 1=1" in sql:
            print("该语句中包含逻辑运算符,可能是试图获取所有数据。")
        print("\n建议的防御措施:")
        print("1. 使用参数化查询,确保SQL语句的结构与数据分离。")
        print("2. 对所有输入进行严格的验证,确保输入数据符合预期的格式和类型。")
        print("3. 为应用程序的数据库账户分配最小必要的权限。")
    else:
        print("未检测到SQL注入风险。")

if __name__ == "__main__":
    main()

比如我输入:select * from username where id = 1' and '1'='2--+

posted @ 2025-01-19 23:10  十六块大西瓜  阅读(347)  评论(0)    收藏  举报