百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

安全攻防七:CSRF/SSRF,为啥避免了XSS,还是“被发送”了一条微博

zhezhongyun 2025-03-25 19:33 91 浏览

前面我们说了 2 种常见的 Web 攻击:XSS 和 SQL 注入。它们分别篡改了原始的 HTML 和 SQL 逻辑,从而使得黑客能够执行自定义的功能。那么除了对代码逻辑进行篡改,黑客还能通过什么方式发起 Web 攻击呢?

我们还是先来看一个例子。在平常使用浏览器访问各种网页的时候,是否遇到过,自己的银行应用突然发起了一笔转账,又或者,你的微博突然发送了一条内容?

在我们了解了 XSS 之后,你可能会联想到,这是银行或者微博中出现了某个 XSS 漏洞。但问题是,你今天并没有访问过银行或者微博的页面,所以并没有“被 XSS”的机会。这时,你想到,会不会是你今天访问的其他网页里存在一些恶意的攻击,实现了你不知道的转账和发博行为呢?

CSRF攻击如何产生的

当我们在访问一个 Web 页面的时候,并不是我们自己去获取页面信息,而是浏览器去获取了这些信息,并将它们进行了展示。这就说明,你允许浏览器代表你去和 Web 的服务端进行交互。为了能够准确地代表你的身份,浏览器通常会在 Cookie 中存储一些必要的身份信息。所以,在我们使用一个网页的时候,只需要在首次访问的时候登录就可以了。

从用户体验上来说,这当然是非常方便的。但是,黑客正是利用这一点,来编写带有恶意 JavaScript 脚本的网页,通过“钓鱼”的方式诱导你访问。然后,黑客会通过这些 JavaScript 脚本窃取你保存在网页中的身份信息,通过仿冒你,让你的浏览器发起伪造的请求,最终执行黑客定义的操作。而这一切对于你自己而言都是无感知的。这就是 CSRF(Cross-Site Request Forgery,跨站请求伪造)攻击。

接下来,我们就以银行转账为例子,来详细讲解一下这个攻击过程。

当你在银行页面发起一笔转账时,这个过程其实是通过一个转账接口来完成的。这个接口的内容可能包括下面这些内容:

  • 接口地址:http://bank.com/transfer ;
  • HTTP 方法:POST;
  • 接口参数:to(目标账户)、amount(金额)。

在转账之前,你肯定进行了一次登录。这样一来,这个转账接口就可以通过你之前存储在 Cookie 中的相关字段来完成认证了。所以,这个接口参数中不需要包含任何身份认证相关的信息。也正是因为如此,这个接口满足了 CSRF 攻击的基本条件:

  • 使用 Cookie 进行认证;
  • 参数中不包含任何隐私信息。

于是,黑客可以构造一个如下的空白网页。我们假设这个网页的地址为 hacker.com。


  
    
<script> document.forms[0].submit(); </script>

在 HTML 中,<script>标签内的 JavaScript 脚本会在打开网页的时候自动执行。因此,一旦用户访问了这个 hacker.com 的页面,它就会自动提交 form 表单,向http://bank.com/transfer这个接口(假设为转账接口)发起一个 POST 请求。

其中,to 和 amount 这两个参数,代表着用户向黑客的账号转账 10000 元。只要这个用户之前登录过 bank.com,并且账户余额大于 10000 元,那么黑客就能够成功地收到这 10000 元的转账了。在这个网页中,的标签带有“hidden”属性,所以这整个过程对于用户来说都是不可见的。如下图所示:

通过 CSRF 攻击,黑客能做什么

和 XSS 一样,CSRF 也可以仿冒用户去进行一些功能操作的请求,比如修改密码、转账等等,相当于绕过身份认证,进行未授权的操作。

值得一提的是,尽管黑客通过 CSRF 能进行的操作没有 XSS 丰富,但 CSRF 在传播和攻击成本上都低于 XSS。这也就是说,即使你的网页中没有任何注入漏洞,但只要接口配置不当,就能够被 CSRF 利用。而黑客也只需要在自己的域名中,搭建一个诱导性的网页,就可以让任何访问网页的用户都遭受到 CSRF 攻击。而且,用户每天需要访问大量的网页,根本没有办法确认每一个网页的合法性。而从严格意义上来说,用户根本没有办法防止 CSRF 攻击。因此,我们只能从应用本身入手去加强防护。

如何进行 CSRF 防护

那究竟该怎么进行 CSRF 防护呢?我们有两种方法。

  • 行业内标准的 CSRF 防护方法是 CSRFToken

我们知道,CSRF 是通过自动提交表单的形式来发起攻击的。所以,在前面转账的例子中,黑客可以通过抓包分析出 http://bank.com/transfer 这个接口所需要的参数,从而构造对应的 form 表单。因此,我们只需要在这个接口中,加入一个黑客无法猜到的参数,就可以有效防止 CSRF 了。这就是 CSRF Token 的工作原理。它的工作流程如下图所示:

因为 CSRF Token 是每次用户正常访问页面时,服务端随机生成返回给浏览器的。所以,每一次正常的转账接口调用,都会携带不同的 CSRF Token。黑客没有办法进行提前猜测,也就没有办法构造出正确的表单了。

  • 通过二次验证来加强防护

回想一下,当你进行各类支付操作的时候,银行网页通常会要求你输入支付密码。你可能会觉得奇怪,明明自己已经登录了,为什么还需要输入一个独立的支付密码呢?这其实和 CSRF Token 的原理一样:这个独立的支付密码是需要用户输入的,只存在于用户的记忆中,因此,也是黑客无法获取到的参数。

怎么理解呢?假如说,黑客通过 CSRF 攻击,替你发起了一笔转账。在支付的时候,银行会发起一个全新的页面,让你验证支付密码。这个时候你发现,这个支付请求不是你本人发起的,那你肯定不会输入支付密码来完成验证。所以,在用户进行支付这样的敏感操作时,应用通常会要求用户提供一些私密的信息,就是为了对 CSRF 攻击进行防护。

你现在对 CSRF 的攻击和防护,应该有了一个大概的了解。简单来说,CSRF 其实就是黑客利用浏览器存储用户 Cookie 这一特性,来模拟用户发起一次带有认证信息的请求,比如转账、修改密码等。防护 CSRF 的原理也很简单,在这些请求中,加入一些黑客无法得到的参数信息即可,比如 CSRF Token 或者独立的支付密码等。掌握了这些内容,其实 CSRF 的知识基本上就差不多了。

SSRF:同样的原理,发生在服务端又会发生什么

在 CSRF 中,黑客通过诱导用户访问某个网站,让用户的浏览器发起一个伪造的请求。那么,如果服务端发起了这个伪造的请求,又会发生什么呢?

我们知道,服务端也有代理请求的功能:用户在浏览器中输入一个 URL(比如某个图片资源),然后服务端会向这个 URL 发起请求,通过访问其他的服务端资源来完成正常的页面展示。

这个时候,只要黑客在输入中提交一个内网 URL,就能让服务端发起一个黑客定义的内网请求,从而获取到内网数据。这就是 SSRF(Server Side Request Forgery,服务端请求伪造)的原理。而服务端作为内网设备,通常具备很高的权限,所以,这个伪造的请求往往因为能绕过大部分的认证和授权机制,而产生很严重的后果。

比方说,当我们在百度中搜索图片时,会涉及图片的跨域加载保护,百度不会直接在页面中加载图片的源地址,而是将地址通过 GET 参数提交到百度服务器,然后百度服务器请求到对应的图片,再返回到页面展示出来。

这个过程中,百度服务器实际上会向另外一个 URL 地址发起请求(比如,上图中的http://s1.sinaimg.cn)。利用这个代理发起请求的功能,黑客可以通过提交一个内网的地址,实现对内网任意服务的访问。这就是 SSRF 攻击的实现过程,也就是我们常说的“内网穿透”。

通过 SSRF 攻击,黑客能做什么

了解了 SSRF 攻击的过程之后,我们知道,在服务端不做任何保护措施的情况下,黑客可以利用 SSRF 向内网发起任意的 HTTP 请求。那么,这些请求会产生什么样的后果呢?我总结了一下,主要会有这样两种动作:内网探测和文件读取。

  • 1.内网探测

内外网一般是隔离的。所以,黑客在外网环境中,是无法知道内网有哪些服务器,这些服务器又分别提供了哪些服务。但是,通过一个加载图片的 SSRF 漏洞,黑客就能够对内网进行探测。这是怎么做到的呢?别着急,我们慢慢来看。

在前面百度搜图的例子中,我们请求的地址是:
https://image.baidu.com/search/detail?objurl=
http://s1.sinaimg.cn/picture.jpg。因为
http://s1.sinaimg.cn/picture.jpg会正常返回一个图片,所以网页会展示出来对应的图片。

我们假定这样一个服务端逻辑:在这个请求过程中,服务端会判断 objurl 返回数据的 Content Type 是否为 image/jpeg。那么,可能的返回结果就有三种:

  • “是”,则展示图片;
  • “不是”,则返回“格式错误”;
  • 无响应,则返回“找不到图片”。

基于这三种返回逻辑,黑客可以构造一个恶意的请求地址:
https://image.baidu.com/search/detail?objurl=127.0.0.1:3306。如果服务器返回“格式错误”,则代表服务端本地的 3306 端口可用;如果返回“找不到图片”,则代表不可用。我们知道,3306 是 MySQL 对应的端口号,因此,根据这个返回的信息,黑客就能够知道服务端本地是否开启了一个 MySQL 服务。接下来,黑客只需要不断重复这个过程,尝试不同的 IP 和端口号,就能够一点一点探测出整个内网的结构。

  • 2.文件读取

服务器除了对图片的代理不做合法性判断之外,对很多其他的代理也不做判断,而是直接将代理的结果返回到前端。我们称这种情况为“有回显的 SSRF”。在这种情况下,黑客不仅能够知道请求是否成功了,还能够知道具体返回的内容。这时候你肯定会好奇,黑客究竟是怎么做到呢?

在 URI 中,开头的 http:// 和 https:// 代表需要使用什么协议去进行请求。除了 HTTP 之外,URI 还有很多种协议可以选择,比如 file:// 就是直接读取本地的文件。通过输入 file://etc/passwd,黑客就能够通过一个请求获取到本地的 passwd 文件,从而知道本地有哪些用户。经过不断地尝试,黑客就能够把整个服务器中的文件内容都给拉取出来,这其中包括密钥、源码等极度敏感的信息。

一般情况下,黑客会通过 SSRF 攻击拿到了服务端的源码,然后通过对源码的分析,找到了一个 SQL 注入的漏洞,再利用 SSRF 发起对内网的 SQL 注入攻击,从而拿到了内网的命令执行权限。

如何进行 SSRF 防护

因为 SSRF 漏洞起源于业务的正常功能需求(比如百度图片的图片请求等等)。因此,我们很难真正消除它。尽管如此,我还是会为你介绍几种常见的防护手段,来尽可能地提高应用的安全性。这些常见的手段主要包括:白名单限制、协议限制和请求端限制。

  • 白名单的限制

白名单的限制永远是最简单、最高效的防护措施。SSRF 中的白名单,就是对用户提交上来的目标 URL 进行限制。比如,只允许是同一个域名下的 URL。你可以理解为,让百度图片的代理服务只允许代理 baidu.com 的 URL。但是,很多时候,因为业务功能的设计,白名单的限制并不可行。比如,上述百度图片的例子,这个功能的设计思路就是,baidu.com 这个域名下能够请求各类域名下的图片资源(比如上述例子中的 sinaimg.cn)。

  • 协议和资源类型等进行限制

在这种时候,我们可以对协议和资源类型等进行限制。比如:对于使用协议,我们只允许 HTTP 或者 HTTPS 协议;对于返回的内容,我们只允许图片格式的内容。通过这些限制,虽然不能完全阻止黑客发起 SSRF 攻击,但也大大降低了黑客能够造成的危害。

  • 请求端限制

除此之外,因为 SSRF 最终的结果,是接受代理请求的服务端发生数据泄漏。所以,SSRF 防护不仅仅涉及接收 URL 的服务端检测,也需要接受代理请求的服务端进行配合。在这种情况下,我们就需要用到请求端限制,它的防护措施主要包括两个方面。

第一,为其他业务提供的服务接口尽量使用 POST,避免 GET 的使用。因为,在 SSRF 中(以及大部分的 Web 攻击中),发起一个 POST 请求的难度是远远大于 GET 请求的。因为默认的请求方式是 GET,而发起 POST 请求,需要在发起 HTTP 请求的时候进行配置。很多安全漏洞中不包含能够配置协议的地方。在上述百度图片的例子中,黑客显然就只能发起 GET 请求。如果某个敏感服务是 POST 的,黑客就无法请求到相关资源了。

第二,为其他业务提供的服务接口,最好每次都进行验证。通过 SSRF,黑客只能发起请求,并不能获取到服务端存储的验证信息(如认证的 key 和 secret 等)。因此,只要接受代理请求的端对每次请求都进行完整的验证,黑客无法成功通过验证,也就无法完成请求了。

总结

我们介绍了 CSRF 和 SSRF 这两种攻击方式。其中,CSRF 是黑客控制用户的浏览器发起伪造的请求,SSRF 则是黑客控制服务端发起伪造的请求。通过伪造的请求,黑客可以伪造用户或者服务器的身份,越权获取数据或者发起请求。应用中的请求接口越敏感,黑客能够造成的伤害就越大。

除此之外,CSRF 和 SSRF 产生于正常的业务功能逻辑中,因此,我们没有办法从根本上组织黑客发起伪造的请求。但是,你可以通过加强接口的安全验证,来避免伪造请求造成影响。在 CSRF 中,我们可以通过 CSRF Token 或者二次验证等操作来加强防护。这样,黑客无法获取到隐私信息,也就无法发起连续的请求了。在 SSRF 中,我们则需要限制可请求的域名,来限制黑客能够访问到的资源。另外,目标服务端,也需要加强接口的验证,来避免伪造请求成功通过授权。

相关推荐

3 分钟!AI 从零开发五子棋全过程曝光,网友:这效率我服了

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8...

一行代码实现display&quot;过渡动画&quot;原理

作者:Peter谭老师转发链接:https://mp.weixin.qq.com/s/XhwPOv62gypzq5MhhP-5vg写本文的起因上篇文章,提到如何让display出现过渡动画,却没有仔...

脑洞:琼恩·雪诺、蝙蝠侠和魔形女的灵魂宠物了解一下

AlekseiVinogradovisaRussianfreelancedigitalartistwhoshareshisskillsandtalentwith120k...

浏览器的渲染机制、重绘、重排

1、什么是重排和重绘网页生成过程:HTML被HTML解析器解析成DOM树css则被css解析器解析成CSSOM树结合DOM树和CSSOM树,生成一棵渲染树(RenderTree)生成布局(flo...

托福写作高频考题写作思路&amp;词汇丨考虫独家

科技话题与媒体话题是托福写作的常考话题很多考生对这两类话题里的专有词汇表达也许很不了解所以今天就跟随考虫托福写作老师刘云龙老师一起来学习在这些话题的写作里你可以使用哪些有用的表达。希望大家有收获!记得...

在优麒麟上使用 Electron 开发桌面应用

使用Web标准来创建桌面GUI,上手快、成本低、跨平台、自适应分辨率,这些都是Electron的优势。作者/来源:优麒麟Electron是由Github开发,用HTML、CSS和...

php手把手教你做网站(三十八)jquery 转轮盘抽奖,开盲盒

抽奖和开盲盒性质一样的都是通过ajax读取后台的随机数据。1、转轮盘本来是想直接绘图实现轮盘,但是没有找到怎么填充文字,只好把轮盘弄成了背景图,通常用于游戏抽道具,商城积分抽奖,公司年末员工抽奖点击抽...

用 CSS 整活!3D 轮播图手把手教学,快乐代码敲出来

兄弟们,今天咱来搞点好玩的——用CSS整一个3D轮播图!咱野生程序员就是要在代码里找乐子,技术和快乐咱都得要!代码是写不完的,但咱能自己敲出快乐来,走起!一、先整个容器,搭个舞台咋先写一个...

实现一个超酷的 3D 立体卡片效 #前端开发

今天我们来实现一个超酷的3D立体卡片效果。正常情况下就是一个普通的图片展示卡片,鼠标悬停的时候图片会跳出卡片,并将影子投射到背景卡片上,在视觉上有一个3D立体感。html主要分成3个部分:容器→背景层...

Vue 3 Teleport与Suspense:解决UI难题的两个&quot;隐藏大招&quot;

模态框的"层级噩梦"与Teleport的救赎"这个模态框怎么又被父容器截断了?"团队协作开发后台系统时,小张第N次遇到这个问题。多层嵌套的组件结构里,弹窗被overfl...

让交互更加生动!有意思的鼠标跟随 3D 旋转动效

今天,群友问了这样一个问题,如下所示的鼠标跟随交互效果,如何实现:简单分析一下,这个交互效果主要有两个核心:借助了CSS3D的能力元素的旋转需要和鼠标的移动相结合本文,就将讲述如何使用纯CSS...

填坑:transform元素导致zindex失效终极方法

今天遇到了使用css3动画的元素层级被放大置顶的问题,ios浏览器上没问题,安卓原生浏览器和安卓微信上有问题。使用了css3动画的元素z-index失效,兄弟元素设置多高的z-index都盖不住解决办...

诡异的层级错乱:一个被transform隐藏的CSS陷阱

周五下午三点十七分,设计部突然发来紧急截图——原本应该悬浮在顶部的导航菜单,此刻正诡异地被下方的轮播图遮挡。我盯着屏幕上错乱的层级关系,手指下意识地敲下z-index:9999,心里清楚这不过是程序...

动画篇--碎片动画

本文授权转载,作者:Sindri的小巢(简书)前言从最开始动笔动画篇的博客,至今已经过去了四个多月。这段时间回头看了看自己之前的动画文章,发现用来讲解动画的例子确实不那么的赏心悦目。于是这段时间总是想...

Nature:大洋转换断层处的拉张构造与两阶段地壳增生

Nature:大洋转换断层处的拉张构造与两阶段地壳增生转换断层是三种基本的板块边界之一,全球总长度超过48000km(Bird,2003),它们的发现为板块构造理论的建立奠定了重要的基础(Wil...