一直想写一下这个话题,但是每次都忘记没有时间写;
在最开始问题的出现,是以前的一个客户说,
你们为什么要用 put/delete 方法?这很不安全;我随便上传个文件都能上传,这样服务器中毒风险很高。
从运维安全方面来说,的确,能随便上传个有毒脚本上去不就被执行了吗?
那么索性就禁用 put/delete 方法。
这个观点先不讨论,先看规范。
在 RFC1945 /1996 年 http 1.0 中定义了三种请求方法:GET、POST、HEAD
在 RFC 2616 /1999年 http 1.1中定义了八种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
图片来自互联网
为什么不安全呢?
options 方法会暴露服务器信息,如中间件版本、支持的 http 方法
put 方法,从自身机制来说是不带验证机制的,可以利用 put 入侵服务器,上传 webshell 或者恶意脚本,然后就可以获得服务器权限
delete 方法,可以删除服务器上特定的资源文件,进行恶意攻击
那为什么要增加这么多方法呢?
可以说是为了语义化,为了构建 restful 架构吗
那 restful 是什么
是一种风格和思想
restful的好处是什么?
简单来说,你看到一个 url 的时候就知道他是做什么的。就好比饿了么美团,看到服装是不是就知道他是哪家哪派的。
其他的就是一些规范请求过程和结果,对资源描述与视图的松耦合,便于集成,提高互相操作性、水平扩展性等等
就使用 get/post 的话,那么新增是叫太子,更新叫太子,删除也叫太子,查询也可以叫太子,那么别人来看的时候,这个太子是干啥的?现在都什么年代了,资源都共享了,那么就需要一个规范,好比交通规则一样,建立好了大家都方便。
那 restful 的 put/delete 不安全怎么办?
restful 中的 url 只管指定资源,http 动词进行不同的操作。
这里简单说一下现在网站的区别
以前网站大多数都是使用 get、post 方法,比如一些企业官网、政府网等等。这次还要引用到一个词,SEO,像企业官网、政府网、博客等等,要想在网上被搜索到,那么网站的架构通过服务端渲染好,然后丢给浏览器。这样做 SEO 就方便,然后在拿点米推推磨。
现在另外一类型网站,工具型网站,比如什么什么管理系统,在管理系统里面,现在很多都想整合资源,但是不同管理系统都是不同家做的,那么怎么办?那是不是得有个交通规则,大家遵守就能整合了对吧。在工具型效率型网站,大多都是使用的 restful 架构。
某某:put/delete 它不安全
现在很多系统或者app,是不是都需要登陆,还要验证码?这是为了什么?因为登陆之后服务器会给你一个密钥,然后你去访问里面的所有数据都需要带上这个,就好比你开车去杭州、上海、江苏、深圳、湖南,你都得带上驾照,你没这个就不让走(严格意义上来说是必须带的,但是也有不遵循的哈),你没这个不行,前面也有说到一个问题,url指定资源,通过不同动词操作,那么你如果put,put没有上传文件地方你怎么上传?用一个get的方法,你修改成put,url都是指定资源,怎么去上传与修改呢?前提没有密钥的话请求都请求不到任何东西,要想干点任何坏事总得先搞开门吧。如果可以我们可以私下来探讨一下,我也很感兴趣。
数据都出来了不是很容易被爬虫?
很多的管理系统和效率工具型应用,采用的都是前后端分离,这是什么意思呢?就好比一个人穿衣服,你扒了别人的衣服,能得到别人的人吗,是不是。但是如果别人愿意都给你,那你就能得到他了。就好比女孩子好不好看,好看的都会多看几眼。在网站上,如果不是服务端渲染你就做不了 SEO。那就别人就不能在茫茫人海中看到你,谁叫你不好看。要想好看总得花钱吧。
在一般系统里面都会指定你只能上传什么文件,虽然这不能完全预防,但是明显的执行文件是可以避免的。
然后在总结一下这几种方法,来自网上
请求方法 | 安全性 | 幂等性 | 作用 |
Get | 安全 | 幂等 | 获取表示 变更时获取表示(缓存) |
Post | 不安全 | 不幂等 | 服务端的实例号创建资源 创建子资源 |
Put | 不安全 | 幂等 | 客户端的实例号创建资源 替换的方式更新资源 |
Patch | 不安全 | 不幂等 | 部分更新资源 |
Delete | 不安全 | 幂等 | 删除资源 |
在网上看到一个17年的回答:
问题:
这两天因为公司运维部门把服务器的options请求干掉了,导致我们web前端不能使用cors跨域请求。他们的理由是不安全只允许get 和post请求。
回答:
密码学方面的安全问题是由HTTPS来保证的,另外http有 authentication 的 reqeust header 来提供授权的问题。这个层面的安全和 http method 是没有关系的。
HTTP 协议层面的安全其实指的是语义上安全(即这个操作不会产生副作用),另外一个语义是幂等性。从这个层面来说,PUT 是不安全的,因为 put 的语义是整体替换或者创建新资源,会产生副作用;但是它是幂等的,执行一次和 n 次的结果是一样的。
另外,你提到的验证应该是属于 e-tag 这类的验证吧,属于标识资源有没有修改,是否可缓存相关的验证,和安全无关。
因为早期的时候 http 主要是配合 html 使用的,html 中的 form 早期只支持 get,post,所以 put 一直没有出现在实际使用中。现在有些已经浏览器已经允许 html 的 from 使用 PUT 和 DELETE 了,AJAX 则是很早很早就支持 PUT 和 DELETE 了。
总结一下:方法的区别只是语义化上的,在安全上没有啥风险,如果有风险像阿里腾讯是不是早就被攻击的不行了,对不对。在使用到 get/post/put/delete/option 的方法的时候,关注他有没有密钥,有多少层验证机制可以保证密钥安全,登陆的时候防范严不严谨,因为后面都需要对应的密钥才能获取所有的资源。
以上是个人的一些看法,从简单的方面来说,没有深入讲某一个点。对于这个观点大家有不同意见可以一起讨论一下。从网络到数据传输,现在这个时代的安全防范不是由哪一方做的足够好就不会被攻击了,这是不可能的。只能说在不同岗位各自做最好的防护,提高攻击难度。