Python 注入防御:SQLi 与 XSS 的实战规避技巧

在 Python 开发中,注入攻击如 SQL 注入(SQLi)和跨站脚本(XSS)是常见的安全威胁。SQLi 允许攻击者通过恶意输入操纵数据库查询,而 XSS 则让攻击者在用户浏览器执行恶意脚本。这些攻击可能导致数据泄露、账户劫持或系统瘫痪。本文将逐步介绍实战规避技巧,帮助您构建更安全的 Python 应用。所有建议基于行业最佳实践,确保真实可靠。

1. SQL 注入(SQLi)防御技巧

SQLi 攻击通常发生在拼接 SQL 字符串时,攻击者注入恶意代码。以下是关键规避方法:

  • 技巧1:使用参数化查询(预编译语句)
    永远避免直接拼接用户输入到 SQL 语句中。使用参数化查询,数据库引擎会将输入视为数据而非代码。在 Python 中,常见库如 sqlite3psycopg2(用于 PostgreSQL)支持占位符(如 ?%s)。

    Python 代码示例(使用 sqlite3):

    import sqlite3
    
    # 安全:参数化查询
    def safe_query(user_input):
        conn = sqlite3.connect('example.db')
        cursor = conn.cursor()
        # 使用 ? 占位符,输入被自动转义
        cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (user_input['username'], user_input['password']))
        result = cursor.fetchall()
        conn.close()
        return result
    
    # 危险:避免这种方式(拼接字符串)
    # cursor.execute("SELECT * FROM users WHERE username = '" + user_input['username'] + "' AND password = '" + user_input['password'] + "'")
    

  • 技巧2:使用 ORM(对象关系映射)框架
    ORM 如 SQLAlchemy 或 Django ORM 自动处理参数化,减少手动 SQL 编写。它们将查询抽象为对象操作,降低注入风险。

    Python 代码示例(使用 SQLAlchemy):

    from sqlalchemy import create_engine, Column, String
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    class User(Base):
        __tablename__ = 'users'
        username = Column(String, primary_key=True)
        password = Column(String)
    
    # 安全:ORM 查询
    engine = create_engine('sqlite:///example.db')
    Session = sessionmaker(bind=engine)
    session = Session()
    
    def safe_orm_query(username):
        # ORM 自动参数化输入
        user = session.query(User).filter(User.username == username).first()
        return user
    

  • 额外技巧

    • 输入验证:使用库如 re(正则表达式)检查用户输入格式(例如,只允许字母数字)。
    • 最小权限原则:数据库账户仅授予必要权限,避免使用 root 账户。
2. 跨站脚本(XSS)防御技巧

XSS 攻击发生在用户输入被直接输出到 HTML 页面时,攻击者注入恶意脚本。防御核心是确保所有输出被正确编码或转义。

  • 技巧1:输出编码
    在输出用户数据到 HTML 时,必须进行编码(如将 < 转义为 &lt;)。Python Web 框架如 Flask 或 Django 内置自动转义功能。

    Python 代码示例(使用 Flask 和 Jinja2 模板):

    from flask import Flask, render_template_string
    
    app = Flask(__name__)
    
    # 安全:使用模板引擎自动转义
    @app.route('/safe')
    def safe_xss():
        user_input = "<script>alert('XSS')</script>"  # 恶意输入示例
        # Jinja2 自动转义 HTML
        return render_template_string('<p>{{ input }}</p>', input=user_input)
    
    # 危险:避免直接输出(如使用 Markup 或手动拼接)
    # from markupsafe import Markup
    # return Markup('<p>' + user_input + '</p>')  # 可能绕过转义
    

  • 技巧2:使用内容安全策略(CSP)
    CSP 通过 HTTP 头限制脚本来源,防止恶意脚本执行。在 Python 中,用框架中间件轻松实现。

    Python 代码示例(使用 Django 的 CSP 中间件): 首先安装库:pip install django-csp

    # settings.py
    MIDDLEWARE = [
        # ...其他中间件
        'csp.middleware.CSPMiddleware',
    ]
    
    CSP_DEFAULT_SRC = ["'self'"]  # 只允许同源脚本
    CSP_SCRIPT_SRC = ["'self'"]   # 限制脚本来源
    
    # 视图函数中,正常输出用户数据(Django 模板自动转义)
    from django.shortcuts import render
    def safe_view(request):
        user_data = request.GET.get('data', '')
        return render(request, 'template.html', {'data': user_data})
    

  • 额外技巧

    • 输入过滤:在接收端使用库如 bleach 清理 HTML 输入(移除危险标签)。
    • 避免 innerHTML:在 JavaScript 中,避免直接设置 innerHTML;优先使用 textContent
3. 总结与最佳实践
  • 综合防御:SQLi 和 XSS 都源于信任用户输入。始终遵循“不信任输入”原则:验证输入、参数化查询、编码输出。
  • 工具推荐
    • SQLi 防御:优先使用 ORM 或参数化查询库。
    • XSS 防御:依赖框架(如 Flask/Django)的自动转义,并启用 CSP。
    • 测试工具:使用 OWASP ZAP 或 Bandit(Python 安全扫描器)进行代码审计。
  • 持续学习:关注 OWASP Top 10(开放式 Web 应用安全项目)更新,确保应用符合最新标准。

通过以上技巧,您可以显著降低注入攻击风险。实践中,结合代码审查和安全测试,构建健壮的 Python 应用。如有具体场景问题,欢迎进一步咨询!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐