SQL注入

1)攻击原理

在编写SQL语句时,如果直接将用户传入的数据作为参数使用字符串拼接的方式插入到SQL查询中,那么攻击者可以通过注入其他语句来执行攻击操作,这些攻击操作包括可以通过SQL语句做的任何事:获取敏感数据、修改数据、删除数据库表……

2)攻击示例

假设我们的程序是一个学生信息查询程序,其中的某个视图函数接收用户输入的密码,返回根据密码查询对应的数据。我们的数据库由一个db对象表示,SQL语句通过execute()方法执行:

@app.route('/students')
def bobby_table():
    password = request.args.get('password')
    cur = db.execute("SELECT * FROM students WHERE password='%s';" % password)
    results = cur.fetchall()
    return results

注意:在实际应用中,敏感数据需要通过表单提交的POST请求接收,这里为了便于演示,我们通过查询参数接收。
我们通过查询字符串获取用户输入的查询参数,并且不经过任何处理就使用字符串格式化的方法拼接到SQL语句中。在这种情况下,如果攻击者输入的password参数值为“’or 1=1–”,即http://example.com/students?paspassword='or 1=1–,那么最终视图函数中被执行的SQL语句将变为:

SELECT*FROM students WHERE password=''or 1=1--';

这时会把students表中的所有记录全部查询并返回,也就意味着所有的记录都被攻击者窃取了。更可怕的是,如果攻击者将password参数的值设为“’;drop table students;–”,那么查询语句就会变成:

SELECT*FROM students WHERE password=''drop table students;--';

执行这个语句会把students表中的所有记录全部删除掉。附注 在SQL中,“;”用来结束一行语句;“–”用来注释后面的语句,类似Python中的“#”。

3)主要防范方法

1)使用ORM可以一定程度上避免SQL注入问题,我们将在第5章学习使用ORM。
2)验证输入类型。比如某个视图函数接收整型id来查询,那么就在URL规则中限制URL变量为整型。
3)参数化查询。在构造SQL语句时避免使用拼接字符串或字符串格式化(使用百分号或format()方法)的方式来构建SQL语句。而要使用各类接口库提供的参数化查询方法,以内置的sqlite3库为例:

db.execute('SELECT*FROM students WHERE password=?',password)

4)转义特殊字符,比如引号、分号和横线等。使用参数化查询时,各种接口库会为我们做转义工作。附注 你可以访问OWASP的SQL注入页面( https://www.owasp.org/index.php/SQL_Injection )了解详细的攻击原理介绍的防范措施。

作者:admin  创建时间:2025-02-10 16:30
最后编辑:admin  更新时间:2025-05-15 17:13