目录
SQL 注入攻击
SQL 注入是一种网络攻击手段,攻击者通过在 Web 应用程序的输入字段中插入恶意 SQL 代码,试图访问、篡改或删除数据库中的数据。这种攻击通常发生在应用程序未对用户输入进行充分验证或过滤的情况下。
举个例子,例如,假设有一个简单的登录表单,用户需要输入用户名和密码。在后端,应用程序使用 SQL 查询来检查数据库中是否存在匹配的用户记录:
# 不安全的示例,不要在实际项目中使用
username = request.POST['username']
password = request.POST['password']
sql = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
应用程序直接将用户输入的 username
和 password
插入到 SQL 查询中。这使得攻击者可以通过在输入字段中插入恶意 SQL 代码来尝试 SQL 注入攻击。如下:
admin'-- # -- 是sql中的注释
SQL 查询变为:
SELECT * FROM users WHERE username='admin'--' AND password=''
“--”使得查询的其余部分(AND password=''
)被注释掉,使得查询的其余部分(AND password=''
)被注释掉。
如果分类型的话,这里介绍SQL注入有四种类型:字符串型、数字型、参数化型、盲注型。
字符串型
基于字符串拼接的注入 ['' OR 1=1 -- ''"]
示例:应用程序接受用户输入用户名,用于查询用户信息SQL语句中:
query = "SELECT * FROM users WHERE username = '" + username + "'"
若程序没正确对用户输入验证和转义,攻击者可输入 ' OR 1=1 --
为用户名,将导致SQL查询:
SELECT * FROM users WHERE username = '' OR 1=1 -- ''"
数字型
基于数字类型的注入 [1 OR 1=1]
query = "SELECT * FROM users WHERE age = " + age
同理,若程序没正确对用户输入验证和处理,攻击者可输入 18 OR 1=1
作为年龄。
SELECT * FROM users WHERE age = 18 OR 1=1
参数化型
基于参数化查询的注入 [%s]
query = "SELECT * FROM users WHERE username = %s"
攻击者可以输入 ' OR 1=1 --
作为用户名:
SELECT * FROM users WHERE username = '' OR 1=1 --
盲注型
SLEEP
query = "SELECT * FROM products WHERE id = " + product_id
攻击者可输入 ' OR SLEEP(10) --
作为产品ID(攻击者可通过观察应用程序响应时间推断出查询是否成功),将导致SQL查询变为:
SELECT * FROM products WHERE id = ' OR SLEEP(10) --'
python解决SQL注入
为了防止 SQL 注入攻击,您应该始终对用户输入进行验证和过滤。在 Python 和许多其他编程语言中,可以使用参数化查询(parameterized queries)或预编译语句(prepared statements)来确保用户输入不会被解释为 SQL 代码。例如,使用 Python 的 SQLite 库,您可以这样做:
import sqlite3
# 安全的示例
username = request.POST['username']
password = request.POST['password']
conn = sqlite3.connect('my_database.db')
cursor = conn.cursor()
sql = "SELECT * FROM users WHERE username=? AND password=?"
cursor.execute(sql, (username, password))
使用 ?
占位符代替直接插入用户输入。然后,将用户输入作参数传递给 execute()
函数。这样,即使用户输入包含恶意 SQL 代码,也不会被解释为 SQL 代码,从而防止了 SQL 注入攻击。
当然,合理地控制输入也是一种方法,比如校验长度,检验字符是否合法等等。
Python的web开发框架Django有着强大的ORM操作。Django ORM 防止 SQL 注入攻击的主要方式包括:使用参数化查询来生成和执行 SQL 语句,自动转义用户输入中的特殊字符,提供高级查询 API 以更安全地编写数据库查询,以及实现数据库无关性,使开发者无需关心特定数据库的 SQL 方言和安全性问题。这些特性使得 Django ORM 能有效地降低 SQL 注入攻击的风险。
CSRF 跨站伪造攻击
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种网络攻击手段,攻击者通过诱导用户在没有意识的情况下执行非预期的操作。这种攻击通常发生在用户已经登录目标网站,攻击者利用用户的登录状态发起恶意请求,从而达到攻击目的。
攻击原理:攻击者构造一个恶意链接或者嵌入恶意代码的第三方网站,诱导用户点击或访问。当用户点击链接或访问网站时,浏览器会自动带上目标网站的登录凭证(如Cookie),发起恶意请求,致非预期操作。(概况:诱导点击恶意链接,盗用类似Cookie凭证发起非预期操作)
假设有一个银行网站,用户可以通过访问 http://bank.com/transfer?to=Bob&amount=100
进行转账操作。攻击者可以构造一个恶意链接,当用户点进这个恶意网址时,引诱用户点击:
<a href="http://bank.com/transfer?to=Attacker&amount=10000" target="_blank">
点击领取优惠券
</a>
一旦用户点击这个链接时,如果用户已经登录银行网站,浏览器会带上银行网站的Cookie发起请求,导致用户在不知情的情况下完成了转账操作。(通常发生在表单上)
为了防范CSRF攻击,通常采用以下方法:
-
使用CSRF Token:在提交表单时,服务器生成一个随机的Token,存储在Session中,并将Token放在表单的隐藏字段中。当用户提交表单时,服务器会验证Token是否匹配,从而防止跨站请求。(python的Django就是用这个)
-
使用SameSite Cookie属性:设置Cookie的SameSite属性为Strict或Lax,使浏览器在跨站请求时不会发送Cookie,从而防止CSRF攻击。
-
验证Referer:检查请求的Referer是否来自可信的源,但这种方法并不完全可靠,因为Referer可能被篡改或禁用。
Django防止CSRF手段
Django框架已经内置了CSRF保护机制,只需要在设置中启用中间件即可:
# settings.py
MIDDLEWARE = [
# ...
'django.middleware.csrf.CsrfViewMiddleware', # 确保此中间件已启用
# ...
]
在HTML模板中,使用{% csrf_token %}
生成CSRF Token:
<form method="post">
{% csrf_token %}
<!-- 其他表单字段 -->
<input type="submit" value="提交">
</form>
处理表单请求时,框架会自动验证CSRF Token,如果验证失败,将拒绝处理请求。
CSRF攻击只会在表单上吗?
那不是。
CSRF攻击主要发生在表单提交的操作上,因为表单通常用于执行敏感操作,如登录、注册、修改密码、转账等。但实际上,CSRF攻击并不仅限于表单,它可以发生在任何可以执行操作的HTTP请求上
比如(1)通过GET请求触发的操作:虽然GET请求应该是幂等的,但有些网站可能会使用GET请求执行操作。攻击者可以通过构造恶意链接或者使用<img>
标签发起GET请求,从而触发CSRF攻击。
<img src="http://example.com/delete?id=1" width="0" height="0" style="display:none;">
当用户访问包含这个<img>
标签的网页时,浏览器会尝试加载图片,实际上是自动发起一个GET请求到http://example.com/delete?id=1
。同样,如果用户已经登录到example.com
且服务器没有进行CSRF防护,这个请求可能会导致用户在不知情的情况下删除ID为1的文章。
(2)通过AJAX发起的请求:攻击者可在第三方网站上使用JS发起AJAX请求,尝试执行操作。虽然同源策略限制了跨域请求,但攻击者仍可尝试绕过限制,或利用浏览器漏洞发起请求。
<script>
function csrfAttack() {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://example.com/update");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.withCredentials = true; // 尝试发送Cookie
xhr.send("id=1&content=Hacked");
}
csrfAttack();
</script>
尝试发起CSRF攻击的JavaScript示例。当用户访问包含这段代码的网页时,浏览器会自动执行csrfAttack()
函数,发起一个AJAX POST请求到http://example.com/update
,尝试修改ID为1的文章内容为"Hacked"。
XSS 跨站脚本攻击
XSS(Cross-Site Scripting,跨站脚本攻击)是一种网络攻击手段,攻击者通过在目标网站上注入恶意脚本,当其他用户访问该网站时,恶意脚本会在用户的浏览器上执行,从而窃取用户数据、劫持用户会话等。
XSS攻击主要分为两类:存储型XSS和反射型XSS。
(1)存储型XSS:攻击者将恶意脚本提交到目标网站的数据库中,当其他用户访问包含恶意脚本的页面时,浏览器会执行恶意脚本。
<script>/* 恶意代码 */</script>
(2)反射型XSS:攻击者将恶意脚本放在URL参数中,诱导用户点击。当用户点击链接时,服务器将恶意脚本返回到用户浏览器,浏览器执行恶意脚本。
http://example.com/search?q=<script>/* 恶意代码 */</script>
在 Django 模板中,默认情况下,所有变量都会被自动转义。这意味着特殊字符(如尖括号、引号等)会被替换为 HTML 实体,从而防止恶意脚本执行。当然对用户输入进行验证和过滤才是至关重要。
{{ hh }}
其他攻击
会话劫持(Session Hijacking):攻击者窃取用户的会话 ID 或 Cookie,以冒充用户身份访问受保护的资源。
Distributed Denial of Service(DDoS):攻击者通过大量请求来使目标服务器过载,导致正常用户无法访问网站。
远程文件包含(Remote File Inclusion, RFI)和本地文件包含(Local File Inclusion, LFI):攻击者利用 Web 应用程序的漏洞,将恶意文件包含到服务器上,以执行恶意代码或窃取敏感信息。
点击劫持(Clickjacking):攻击者使用透明层或 iframe 欺骗用户点击看似无害的元素,实际上触发了恶意操作。
等等