안녕하세요, AV8D~ 오늘 공유하고 싶은 주제는 프론트엔드 웹
보안입니다. 웹
보안의 중요성은 자명하며, 모든 인터넷 기업이 피할 수 없는 주제입니다. Web
安全。web
安全的重要性不言而喻,是所有互联网企业都绕不开的话题。
在web前端领域,尽管浏览器已经在系统层面帮我们做了诸多的隔离和保护措施,但是网页代码开放式的特点和html、JS
的语言特性使得黑客们依然有非常多的可乘之机,Google、facebook
等等都有各自的漏洞悬赏机制,力求在黑客之前发现和修复漏洞,将企业损失降到最低。
web安全是老生常谈的话题,但是常说常新,今天就再次梳(c)理(v)一遍前端的一些web攻击手段,让大家看完这篇文章之后可以学到:
XSS
的全称是 Cross-Site Scripting
,跨站脚本攻击。是指通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。通俗一点讲,就是黑客想法设防地让用户在访问的网页里运行自己写的攻击代码,一旦成功运行,黑客就有可能干出以下勾当:
cookies
,从而拿到用户的敏感信息;DDos
攻击;根据攻击的来源,XSS
可以大体分为持久型攻击和非持久型攻击(当然也有分反射型、存储型和Dom型的,我个人更愿意选择第一种分类,因为更便于理解)。
非持久型XSS的特点在于即时性,它不需要存储在服务器中,通过巧妙地构造一个带恶意代码的URL,然后引导用户点击访问,即可实现攻击。
举一个简单的小栗子,假设有个网站如下。
细心的你发现这个页面会把url
上面的q
参数内容放到网页中,而你打开调试台看到网页的代码实现如下:
<h1 id="query-key"></h1><span>查询结果如下</span>// ...<script> const reg = new RegExp("(^|&)q=([^&]*)(&|$)", "i"); const res = window.location.search.substr(1).match(reg); if (res != null) { const query = decodeURIComponent(res[2]); document.getElementById('query-key').innerHTML = query; };</script>复制代码
发现它没有对query
做过滤,而且直接用innerHTML
方法插入到了DOM
中,你看完差点笑出声:一点安全意识都没有!那假如你想针对这个网站设计一个URL
来让用户点击后发起一个XSS
攻击,从而拿到用户的cookies
数据,你会怎么做呢?
那还不是非常的so easy
,反手就可以写出一条XSS
的链接出来:
http://abcd.com?q=<script>alert(document.cookie)</script>复制代码
这样网页会把q
参数中的script标签插入到DOM中执行,进而弹出提示框。
思路肯定是没问题的,不过你可能会发现不起效果,这是因为浏览器针对script
等一些危险标签的插入做了拦截过滤,当然了这难不倒我们,毕竟咱们也不能把我要干坏事写在脸上,这不尊重对手,所以咱们换种委婉一点的写法就行了:
http://abcd.com?q=<img src="" onerror="alert(document.cookie)" />复制代码
因为是插入一张图片,浏览器一般不会过滤拦截,然后我们把src
置空使其触发onerror
html 및 JS
의 언어 특성으로 인해 해커가 허용할 수 있습니다. 여전히 활용할 수 있는 기회가 많이 있습니다. Google, Facebook
등은 모두 자체 취약점 포상금 메커니즘을 갖고 있어 해커보다 먼저 취약점을 발견하고 해결하여 기업 손실을 최소화하기 위해 노력합니다. . 웹 보안은 일반적인 주제이지만 항상 새로운 내용입니다. 오늘 저는 모든 사람이 이 기사를 읽은 후 배울 수 있도록 (c) (v) 몇 가지 프런트엔드 웹 공격 방법을 다시 한 번 정리하겠습니다.
XSS
의 전체 이름은 크로스 사이트 스크립팅 공격인 Cross-Site Scripting
입니다. 웹 개발 과정에서 남겨진 취약점을 악용하고 교묘한 방법으로 웹 페이지에 악성 명령어 코드를 주입해 사용자가 공격자가 악의적으로 제작한 웹 프로그램을 로드하고 실행할 수 있게 하는 것을 말한다. 일반인의 관점에서 보면 해커는 사용자가 방문하는 웹 페이지에서 자체 공격 코드를 실행하도록 강화하려고 합니다. 일단 성공적으로 실행되면 해커는 다음을 수행할 수 있습니다.
DDos
공격 감지 XSS
는 크게 지속적 공격과 비지속적 공격으로 나눌 수 있습니다. 유형 공격(물론 반사 유형, 저장 유형, Dom 유형이 있는데 개인적으로는 이해하기 쉽기 때문에 첫 번째 분류를 선택하는 것을 선호합니다).
위의 <code>q
매개변수를 사용한다는 것을 알 수 있습니다. url 콘텐츠가 웹 페이지에 배치되고, 디버깅 콘솔을 열고 웹 페이지의 코드가 다음과 같이 구현된 것을 확인합니다. 🎜Content-Security-Policy: script-src 'self'复制代码🎜
쿼리
를 필터링하지 않는 것을 발견했습니다. code>를 작성하고 innerHTML
메소드를 사용하여 직접 삽입합니다. DOM
에 도달하면 읽은 후 거의 웃음을 터뜨립니다. 보안에 대한 인식이 전혀 없습니다! 그런 다음 사용자가 XSS
공격을 클릭하고 실행하여 사용자의 쿠키
데이터를 얻을 수 있도록 이 웹 사이트에 대한 URL
을 디자인하려는 경우 어떤 일이 이루어질 것인가? 🎜🎜그건 그다지 쉽지
않습니다. XSS
링크를 백핸드로 작성할 수 있습니다. 🎜FETCH POST http://xxx.com/user/helloWorld.jpg复制代码🎜이런 식으로 웹페이지에
q
가 입력됩니다. 매개변수에 있는 script 태그가 DOM에 삽입되어 실행되며 프롬프트 상자가 나타납니다. 🎜🎜아이디어에는 확실히 문제가 없지만, 브라우저가 script
와 같은 일부 위험한 태그의 삽입을 차단하여 필터링했기 때문에 효과적이지 않을 수 있습니다. , 결국 우리는 내가 나쁜 짓을 할 것이라고 얼굴에 쓸 수 없습니다. 이것은 상대를 존중하지 않으므로 좀 더 완곡한 표현으로 바꾸자: 🎜const img = new Image(); img.onload = () => { // 如果img不是来自缓存,那么只有在图片加载完成触发onload之后,才能拿到实际的witdh值 console.log(img.width); } img.src = 'http://xxx.com/user/helloWorld.jpg';// 如果存在缓存,在这里可以立即读取到图片的 witdh 值,否则会打印 0console.log(img.width);复制代码🎜 그림을 삽입하기 때문에 브라우저는 일반적으로 그림을 필터링하거나 가로채지 않습니다. 그런 다음
src
를 비워 두어 onerror
이벤트를 트리거하고 악의적인 스크립트를 간접적으로 실행합니다. . 완료! 🎜🎜지속적 공격🎜🎜비지속적 공격의 단점을 발견할 수 있는데, 즉 공격하기 전에 먼저 사용자에게 URL을 보여주고 클릭을 유도해야 한다는 것입니다. 악성링크 노출! 너무 귀찮은데 영구적인 해결책이 있을까요? 🎜🎜웹사이트의 데이터베이스에 악성코드를 저장할 수 있는 방법을 찾을 수 있다면, 이 웹사이트에서 내 악성 데이터에 접근하는 모든 이용자들이 피해를 입는 것은 아닐까요? 🎜🎜따라서 웹사이트의 댓글 영역이 필터링되지 않고 안전하지 않은 경우 댓글을 통해 악성 스크립트를 백엔드 서버에 제출하면 이 댓글 페이지를 방문하는 모든 사용자가 내 코드를 실행할 수 있습니다. 공격 목적을 달성합니다. 🎜🎜한 사용자가 댓글에 악성 코드를 작성하여 백그라운드에 제출했습니다: 🎜
当B用户访问这个评论页面时,网页就会加载A的评论,进而触发恶意代码(而此时B用户其实啥都没做,他只是非常乖巧地打开了这个非常正规的网站,然后他就中招了):
因此我们可以总结一下持久型XXS的特点:
介绍完概念,我们可以知道要想抵御XSS攻击,大概可以从两方面入手:
1、使用HTML转义。对外部插入的内容要永远保持警惕。
对所有外部插入的代码都应该做一次转义,将script
,& < > " ' /
等危险字符做过滤和转义替换,同时尽量避免使用innerHTML
,document.write
,outerHTML
,eval
等方法,用安全性更高的textContent
,setAttribute
等方法做替代;
2、开启CSP防护。内容安全策略(CSP)的设计就是为了防御XSS攻击的,通过在HTTP头部中设置Content-Security-Policy
,就可以配置该策略,如果将CSP设置成一下模式:
Content-Security-Policy: script-src 'self'复制代码
那么该网站将:
这将有效地防范XSS的攻击,当然他也非常严格,可能会对自身的业务开发也造成一定限制,更多关于CSP的内容可以查看MDN。
3、设置HttpOnly。当然这已经是属于降低XSS危害的方法,对于所有包含敏感信息的cookie,都应该在服务端对其设置httpOnly
,被设置了httpOnly
的cookie字段无法通过JS获取,也就降低了XSS攻击时用户凭据隐私泄漏的风险。
又是一个耳熟能详,面试常问的知识点。
CSRF(Cross-site request forgery)中文名称跨站请求伪造,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
简单介绍一下CSRF的攻击流程:
最后在受害者不知情的情况下,恶意网站向目标网站以受害者身份执行了一些带权限的操作,给受害者带来一系列危害和损失。
这个过程很好理解,篇幅有限,这里就不举例子做详细的解释了。
至于浏览器存在跨域限制,那么恶意网站如何对目标网站发起请求的问题,这属于如何解决跨域限制的知识点,在这里可以简单总结为以下方法:
img
标签链接不受浏览器的跨域限制,因此可以直接以img的形式发起请求;知道了整个攻击的流程,那么我们就可以着手看看在哪些阶段可以对CSRF攻击做防御工作。
1、 SameSite Cookie
제3자에 의한 요청이 관련 쿠키를 포함할 수 없는 경우 모든 문제가 해결된 것 같습니다. 다행히 브라우저는 쿠키에 대해 SameSite
속성을 제공합니다. 이는 쿠키가 도메인 간 요청과 함께 전송되지 않음을 나타냅니다. 이 제안은 Google에서 제안한 것입니다. 유일한 단점은 아직 시험 단계에 있으며 호환성 문제가 있다는 것입니다. SameSite
的属性,该属性表示 Cookie 不随着跨域请求发送。该提案有google提出,美中不足的是目前还在试行阶段,存在兼容性问题。
2、CSRF Token
既然浏览器暂时无法帮我们解决所有问题,那就自己想办法把身份校验机制搞复杂一点,只靠cookie没有安全保障,那就再加一个校验维度进来。SCRF Token就是这样一种解决方案。
这个方案流程就是:在用户访问网站时,后台服务器根据算法再生成一个Token,然后把这个Token放在seesion中,当网站发起请求时,不仅要携带cookie凭证,还要把这个Token也带上,后台一起校验之后确认身份再执行操作。由于SCRF Token是放在session中,因此当第三方网站发起请求时,无法拿到这个SCRF Token,故身份校验不再通过,就达到了防御攻击的效果。
3、同源检测
由于CSRF都是通过三方网站发起,因此我们如果能判断服务器每次收到的请求来自哪些网站,就可以过滤那些存在安全风险的网站发起的请求,降低被攻击的风险。
Referer
和Origin
是http请求的头部字段之一,用来标志该请求是从哪个页面链接过来的。因此后台服务器可以通过检查该字段是否是来自自己的网站链接,来避免第三方网站发起CSRF攻击。但是同源检测的可靠性并不高,比如在302重定向的时候,为了保护来源,http请求不会携带Origin
字段,而Referer
Referer
및 Origin
은 http 요청의 헤더 필드 중 하나이며 요청이 연결된 페이지를 나타내는 데 사용됩니다. 따라서 백엔드 서버는 이 필드가 자체 웹 사이트의 링크인지 확인하여 타사 웹 사이트가 CSRF 공격을 실행하는 것을 방지할 수 있습니다. 그러나 원본 감지의 신뢰성은 높지 않습니다. 예를 들어 302 리디렉션에서 소스를 보호하기 위해 http 요청은 Origin
필드를 전달하지 않고 Referer 필드가 영향을 받습니다. 참조자 정책 규칙이 제한되어 전송되지 않습니다. <h2 data-id="heading-10"></h2>4. 2단계 인증 추가<p></p> 일부 위험한 요청 작업(예: 계정 삭제, 현금 인출, 이체)의 경우 휴대폰 또는 이메일 인증 코드 인증과 같은 사용자의 2차 인증을 추가하여 인증 횟수를 줄일 수 있습니다. CSRF로 인한 피해. <h3 data-id="heading-11"></h3>3. 일부 사례<p></p>1) Google Digital Garage는 Google의 온라인 교육 제품입니다. 외국 보안 엔지니어가 CSRF 공격을 통해 웹 사이트의 개인 계정을 삭제하는 방법을 블로그에 소개했습니다. <p></p>2) 이 글에서는 페이스북 웹사이트의 보안 취약점과 CSRF를 통한 보안 보호를 우회하여 계정 탈취를 달성하는 방법을 소개합니다. <p></p>XS-Leaks<ul>
<li>어쨌든 앞서 소개한 두 가지 웹 공격 방법은 이미 많은 사람들에게 친숙하고 잘 알려져 있는 친구들도 있을 것 같아요. 이 기사의 마지막 장에서는 덜 일반적일 수 있지만 대중의 관심을 끌기 시작한 웹 공격 방법인 XS-Leaks를 소개합니다. </li>
<li>1. XS 누출이란 무엇입니까? </li>
</ul>XS-누수는 사이트 간 누출입니다. XS-Leaks는 HTTP 캐시를 쿼리하는 메커니즘을 사용하여 리소스 캐시를 판단하여 현재 사용자의 관련 정보를 추론합니다. XS-Leaks에 대해 처음 들어보신 분이라면 왜 일반적인 HTTP 리소스 캐싱이 사용자 정보 유출을 일으킬 수 있는지 놀라실 것입니다. <p></p>Chrome 브라우저 팀은 개발자 웹사이트에 기사를 게시하여 버전 86 이후의 브라우저는 이전 캐싱 메커니즘으로 인해 개인정보 유출이 발생할 수 있으므로 파티션(도메인 이름)별로 요청 캐시 리소스 메커니즘을 관리하기 시작할 것이라고 밝혔습니다. <p></p>이전에는 Chrome 브라우저의 요청 캐싱 전략이 매우 간단했습니다. <ul>
<li>1. 사용자가 페이지 A를 방문하여 이미지 리소스를 요청하면 브라우저는 이미지를 캐시하고 URL을 저장합니다. <li>2. 그런 다음 사용자는 페이지 B를 방문합니다. 이 페이지도 위의 그림을 사용하는 경우 브라우저는 먼저 이 리소스가 캐시로 인해 캐시되었는지 쿼리합니다. 이 사진을 지나서 브라우저는 캐시된 리소스를 직접 사용합니다. <li>
</ul>캐시된 리소스에는 도메인 이름 제한이 없으므로 모든 웹사이트는 캐시된 리소스를 공유하므로 이를 사용하여 사용자가 특정 웹사이트를 방문했는지 여부를 감지할 수 있습니다. 악성 웹사이트 통과 특정 리소스 요청을 시작하고 리소스가 캐시에서 나오는지 확인하여 사용자의 검색 기록을 유추합니다. 예를 들어, 내 웹사이트에서 Nuggets 로고 이미지(또는 기타 고유한 리소스)를 요청하는 경우 이 이미지가 캐시에서 가져온 것으로 판단되면 사용자가 Nuggets 웹사이트를 방문했음을 알 수 있습니다. <p><img style="max-width:90%" class="lazyload" src="https://img.php.cn/upload/article/000/000/052/125e7905ab64dcdfb36da35e7198954b-5.png" data- style="max-width:90%" data- style="max-width:90%" alt="JavaScript 소개: 프런트엔드 보안에 대해 얼마나 알고 있나요?" >XS-Leaks는 위의 원칙과 유사합니다. 쿼리에 결과가 있는지 감지하여 일부 사용자 데이터를 얻기 위해 HTTP 캐시를 쿼리하는 메커니즘을 사용합니다. XS-Leaks 공격의 주요 단계는 다음과 같습니다. </p>🎜🎜1. 특정 웹사이트의 캐시된 리소스를 삭제합니다. 🎜🎜2. 브라우저에서 웹사이트를 강제로 새로고침하세요. 🎜🎜3. (1)에서 삭제한 리소스를 브라우저가 캐시하는지 확인하세요. 🎜🎜🎜🎜🎜<p>举一个小栗子,假如我们想知道当前访问我们网站的用户是否是某社交网站(假设链接为http://xxx.com)昵称为<code>@helloWorld
的用户,利用XS-Leaks攻击应该怎么做呢?
首先我们可以先将这名@helloWorld
的用户头像图片从社交网站上扒下来,假设该图片链接长这样: http://xxx.com/user/helloWorld.jpg
。
为了避免用户因为浏览了社交网站的一些页面(比如帖子列表页),请求过helloWorld的头像导致的缓存影响判断目的,当用户访问我们的页面时,我们需要先想办法清空这张头像的浏览器缓存。那么怎么能强制清楚一张图片的缓存呢?
FETCH POST http://xxx.com/user/helloWorld.jpg复制代码
没错,通过发起一个POST请求,就可以清除浏览器对这张图片的缓存(感兴趣的小伙伴可以看看这篇文章)。
接下来通过iframe
或者<link ref=rerender href="http://xxx.com/user" />
等方式悄悄发起一个请求,访问社交网站的个人信息页面http://xxx.com/user
(这个页面包含用户的头像图片)。
紧接着只需要再请求一次头像http://xxx.com/user/helloWorld.jpg
,判断其是否来自缓存,如果是,那不就说明了刚才请求的个人信息页面包含了这张图片,就可以推断出该名用户就是@helloWorld
了。
那么问题又来了:如何判断一个请求来自缓存呢?
方法还是很多的,一种方法是通过读取img的宽高属性,来判断图片是否来自缓存:
const img = new Image(); img.onload = () => { // 如果img不是来自缓存,那么只有在图片加载完成触发onload之后,才能拿到实际的witdh值 console.log(img.width); } img.src = 'http://xxx.com/user/helloWorld.jpg';// 如果存在缓存,在这里可以立即读取到图片的 witdh 值,否则会打印 0console.log(img.width);复制代码
至此一次XS-Leaks攻击就完成了。我们也可以请求一些带权限的链接来判断用户是否拥有某个网站的特权身份等等。虽然这个小栗子看起来危害不大,只是做到了当前用户和目标网站账号的关联,但是不要小看黑客们的脑洞,一个看起来不起眼的漏洞很可能会带来巨大损失。
这里给大家分享一个关于XS-Leaks的github地址,里边记录了与XS-Leaks相关的攻击方式、知识和实际案例,帮助大家更深刻地理解概念和攻击手段。
介绍了那么多,是时候总结一下XS-Leaks的一些防范措施了。可以看到XS-Leaks也是从第三方网站中发起攻击的,而且都是通过向目标网站发起请求而达到攻击目的,是不是和CSRF的攻击方式很相似?
没错,CSRF的防御手段同样可以让XS-Leaks对带鉴权的请求访问无效,从而降低危险。当然有些时候这种攻击其实并不需要鉴权就能达成目的,因此CSRF的防御手段并不能做到完美抵御,所以在浏览器层面增加缓存分区就显得非常有必要了:
XS-Leaks利用了浏览器缓存的漏洞实现了攻击,但是其实不仅仅浏览器可以缓存,web服务器也是可以有缓存的,服务器缓存是把请求过的资源暂且放在一个专门的缓存服务器(例如CDN)上,当下一个用户访问同样的资源时就可以直接从缓存服务器上拿到响应,从而减轻Web服务器的压力。
那假如我们可以把攻击代码通过某种方式放在CDN等缓存服务器中,那发起了相同资源请求的用户就都会拿到这份恶意代码从而遭受攻击,这不就实现了XS-Leaks的“存储型攻击”?
缓存服务器通过cache-key
来确定两个用户访问的是否是同一个资源,而这个cache-key
通常由请求方法、路径、query、host头组成。假如一个web服务器有如下请求响应:
该响应中将请求头X-Forwarded-Host
的值直接拼接到meta标签的content属性中,由此产生了XSS攻击的漏洞,因此我们通过发起一个如下请求:
GET /en?dontpoisoneveryone=1 HTTP/1.1Host: www.redhat.com X-Forwarded-Host: a."><script>alert(1)</script>复制代码
服务器就会返回如下响应,并缓存到缓存服务器中:
HTTP/1.1 200 OK Cache-Control: public, no-cache … <meta property="og:image" content="https://a."><script>alert(1)</script>"/>复制代码
由于X-Forwarded-Host
不属于cache-key
的一部分,因此当其他用户发起/en
请求时,服务器都会认为是请求同一个资源从而应用缓存策略,将上面的恶意响应直接响应给用户,造成攻击。
上述的例子来自于BlackHat2020议题之Web缓存投毒这篇文章,文章非常详细地介绍了Web服务器缓存攻击的原理和案例,有兴趣的小伙伴也可以看看。
尽管已经有这么多的措施来应对和抵御web的各种攻击,但依旧有一个又一个的安全漏洞被黑客们发现和攻破,强如Google,页面简洁如Google Search的网站,依然在2019年遭到了XSS攻击。而这次攻击却只需要一行代码:
<noscript><p title="</noscript><img src=x onerror=alert(1)>">复制代码
大致的原因是Google在转义插入文本时,使用了HTML提供的template
标签,使用template
是个很不错的选择,因为它可以用来解析HTML,并且在解析过程中不会触发JavaScript脚本执行。然而template
是JavaScript Disabled环境,而noscript在允许JavaScript和禁止JavaScript环境下的解析是不同的,这导致了这段恶意代码经过解析和sanitize之后仍然存在风险,最后成功实现了XSS攻击。有兴趣的小伙伴可以看看这篇关于这次XSS攻击的文章。
类似的“旁门左道”的攻击方式其实还很多,比如我们经常会用到的SVG
图片,SVG的结构和HTML结构非常相似,通过forginObject
标签我们还可以把script
或者其他HTML标签插入到SVG图片中,假如web服务器允许用户上传任意SVG图像,那么就会存在持久型XSS攻击的安全风险。HTML转义有时候也并非一两行代码就能搞定,当我们碰到类似文本编辑需要保留用户粘贴内容样式的时候,如何在保留这些html的同时规避XSS的风险就值得我们仔细斟酌设计。
众所周知,我们在开发网页的时候基本不会遇到HTML的语法报错问题,因为HTML的解析引擎有着非常强大的容错机制,以至于不管你怎么写,浏览器都能帮你把文档解析渲染出来。然而这种容错性和复杂的解析逻辑也使得XSS能够不断找到新的攻击方式。
事实上,当我在用某网站在线制作前面章节的两张交互图的时候,就“无意中”触发了我里边的img
代码,直接弹出了对话框,这也从侧面说明了web安全其实在很多开发团队中并没有得到足够多的重视,然而诸多的攻击案例告诉我们,我们的网站一旦遭受了攻击其损失可能是不可估量的,因此我们对于web安全,我们不能只是嘴上说说,纸上谈兵,或者只是当做面试的一个八股文知识点,而是应该时刻保持警惕,警钟长鸣才行。
受限于篇幅和精力,本次就先分享上述三个比较常见的web攻击手段,希望之后能够给大家分享更多关于web安全方面的知识和案例。
相关免费学习推荐:JavaScript(视频)
위 내용은 JavaScript 소개: 프런트엔드 보안에 대해 얼마나 알고 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!