XSS攻击通常都是通过跨站指令代码攻击网站的后台漏洞。它和信息隐性代码攻击攻击的目标不同。前者是透过从Web前端输入信息至网站,导致网站输出了被恶意控制的网页内容,使得系统安全遭到破坏。而后者则是输入了足以改变系统所执行之SQL语句内容的字串,使得系统最终达到攻击的目的。
但从一般角度来看,这两种攻击手法基本上是相通的。他们都是透过系统对前端输入信息检验不严谨,利用刻意制造出来的输入信息,来让系统产生不在预期内的有害行为。
要更彻底地防止网站受到跨站指令代码攻击和信息隐性代码攻击,系统就必须对于客户端输入信息做到足够的检核并保护好网页内容,避免产生意外的有害行为。
过滤输入信息有效吗?
当要防备这类型的攻击时,大多数人直觉想到的方式,便是对使用者所提供的输入信息进行过滤。在面对信息隐性代码攻击时,许多人会想到针对输入信息中,可能会含有的SQL关键字串或字元进行过滤,例如,使用者的输入信息中若含有特殊符号例如单引号,那么便可能制造出危险的SQL语句,因此,许多程序设计者便会想到要针对特殊符号进行过滤,来杜绝信息隐性代码的攻击。而这种过滤的方法,其实不难规避,例如,针对单引号,有心人士还是可以利用信息库服务器支持的特殊写法,将单引号字元替换成其他的型式,使得escape的程序失效。
同样的,面对跨站指令代码攻击,许多程序设计者首先会想到的,也是针对有可能造成疑虑的使用者信息进行过滤。例如,针对尖括号、或者SCRIPT字串进行过滤,如果使用者的输入信息中含有可疑的字符串,则进行改写或禁止使用。这种针对特定的目标进行筛选过滤的方式,可以称为黑名单式的过滤,因为,程序是先列出不能出现的对象清单,然后进行过滤。
当然,在跨站指令代码攻击中,如果想利用黑名单式的过滤方式,当然也是行不通的。因为,单是javascript这个字串,有心人士就可以产生在HTML中等价、但是字串形式不为javascript的写法。例如,使用#x的十六进位字元表示方式,来表示javascript这个字串中的每一个字元。由于改写形式太多了,这使得想要利用黑名单的方式,几乎是不可能的事。
因此,无论何种攻击,想要有更严密的防备,在信息的过滤上,都应该采取白名单式的过滤。而这正和黑名单相反,它不是列出不被允许的对象,而是列出可被接受的对象。
以正向表列的方式管制
在面对信息隐性代码攻击时,我们建议针对每个栏都明确定义出它该有的形式,例如日期栏就只能出现数字和斜线,而ID栏仅能出现英文字母及底线等等。如此一来想要透过信息植入有害的组成,就不是那么容易可以办到了。
对于同样需要对输入信息进行检核的跨站指令代码攻击来说,要做到输入信息的过滤,最好的策略也是基于白名单来过滤。例如,允许使用者输入HTML语法的地方,若仅允许输入图片。这么一来,想要规避过滤的规则,难度就比较高了。
当然,采取较严格的白名单政策,程序在编辑难度上比较高,此外,允许使用者信息输入的形式也就更为受限,但这是为了安全必须付出的代价。
将网页内容编代码,提升防御力
除了针对输入信息进行白名单式的过滤之外,针对输出的页面内容进行编码,也是能派上用场的技巧。输入信息的过滤是针对可疑的信息进行防范,而针对输入进行编码,则是让可能造成危害的信息变成无害的。
有许多程序语言都推出了防范跨站指令代码攻击的程序库,协助程序设计者针对HTML输出内容进行编码。例如PHP的htmlentities()或是htmlspecialchars()、ASP的Server.HTMLEncode()、ASP.NET的Server.HtmlEncode()等等。让专门的程序库来处理输入内容的编码,也可以减少程序设计者自行开发的额外成本,同时也能提供更为完善的防备考虑。
彻底分析程序代码可能的弱点
在编写程序时,如果能够留意输入信息的输出,以及输出页面内容的编码,相信可以增加不少防范的强度。但是,针对既有的代码,若存在跨站指令代码攻击的漏洞,又该如何察觉并进行防范呢?基本上,你可以采取一个系统性的分析方法。
如果要审视你的代码是否具有跨站指令代码攻击的问题,首先,你必须要列出你的网站程序中所有接收自使用者端送出信息的地方。包括网站程序所读取表格中的每个栏位、来自于网址中的查询字串、cookies值、HTTP的标头等等。因为,不要忘了,所有来自于使用者的信息“都是不被信任的”。
找到了每个接收使用者端信息的地方后,便可以逐一追踪每个信息在应用程序中的流向,检验所接收到的信息,最终是否会反映到输出的页面结果中。这中间,你可能直接把接收来的信息稍微加工后,就当做输出结果送出去,先把所接收到的信息储存在信息库或档案中,于日后才做为输出结果送出。
如果找出来的信息最终会成为输出页面的一部份,那就应该检查这份信息是否足够“干净”,也就是说,你是否有针对这份信息进行足够的过滤或在输出时加上了编码的动作。如果没有,那这份信息就有可能成为跨站指令代码攻击被发动的点。也就是说,你应该针对这份信息的输入及输出,进行相对应的处理。透过以上的步骤,有助于你审视既有的程序代码的问题。
除此之外,检查你的JavaScript程序中,动用到innerHTML以及document.write()的地方,是否有安全疑虑。另外,在JavaScript程序中使用eval(),同样有可能造成安全问题。eval()函数允许在浏览器上直接将传入该函数的参数做为JavaScritp算式或是可执行的语句。如果eval()所接收的参数值,是来自于使用者输入的信息,那么可以造成的危机就大了,这也就是为什么都建议不要使用eval()的原因,因为太容易形成安全性的漏洞了。
跨站指令代码攻击的确是十分难以防守的攻击形式,一旦不小心,就有可能造成很严重的安全事故。希望可以透过这里,带给你基本的认知。关于跨站指令代码攻击其中还充满许多高深的探讨和技巧,不在本文范围之内,有兴趣的朋友可以留言咨询博主。