Web安全防范:
注入攻击
# 假设我们的程序是一个学生信息查询程序,其中的某个视图函数接
# 收用户输入的密码,返回根据密码查询对应的数据。我们的数据库由一
# 个db对象表示,SQL语句通过execute()方法执行:
@app.route('/students')
def bobby_table():
password = request.args.get('password')
cur = db.execute("SELECT * FROM students WHERE password='%s';" % password)# 获取密码。
# SELECT * FROM students WHERE password='' or 1=1 --;'获取表student全部数据。
# SELECT * FROM students WHERE password=''; drop table students; --; 删除表student所有数据。
results = cur.fetchall()
return results
防范措施:
使用ORM、验证输入类型、参数化查询(db.execute('SELECT * FROM students WHERE password=?, password))。转义特殊字符,比如引号、分号和横线等。
XSS(Cross-Site Scripting,跨站脚本):
# 表现形式:
# 这个视图函数接收用户通过查询字符串传入的数据,未做任何处理就把它直接插入到返回的响应主体中,返回给# 客户端。
pp.route('/hello')
def hello():
name = request.args.get('name')
response = '<h1>Hello, %s!</h1>' % name
# 用户输入:
http://example.com/hello?name=<script>alert('Bingo!');</script>
# 返回:
<h1>Hello, <script>alert('Bingo!');</script>!</h1>
# 能够执行alert()函数就意味着通过这种方式可以执行任意JavaScript代码,或者HTML和CSS。
# 通过JS指向危险网站:
<script>window.location.href="http://attacker.com";</script>
防范措施:
a.HTML转义
from jinja2 import escape
@app.route('/hello')
def hello():
name = request.args.get('name')
response = '<h1>Hello, %s!</h1>' % escape(name)
# 用户输入JS转义为:
<script>alert('Bingo!')</script>,
# 变为
<script>alert("Bingo!")</sript>
b.验证用户输入
# 用户输入个人资料中的个人网站地址:
<a href="{{ url }}">Website</a>
# 其中{{url}}部分表示会被替换为用户输入的url变量值。如果不对URL进行验证,那么用户就可以写入
# JavaScript代码,比如“javascript:alert('Bingo!')
<a href="javascript:alert('Bingo!');">Website</a>
# 当用户单击这个链接时,就会执行被注入的攻击代码。
程序还允许用户自己设置头像图片的URL。这个图片通过下
面的方式显示:
<img src="{{ url }}">
# {{url}}部分表示会被替换为用户输入的url变量值。如果不
# 对输入的URL进行验证,那么用户可以将url设
# 为“123"onerror="alert('Bingo!')”,最终的<img>标签就会变为:
# <img src="123" onerror="alert('Bingo!')">
# 在这里因为src中传入了一个错误的URL,浏览器便会执行onerror属
# 性中设置的JavaScript代码。