技术讨论 | 如何绕过并利用Bucket的上传策略和URL签名
简介
Bucket上传策略是一种直接从客户端向Bucket(存储空间)上传数据的便捷方式。通过上传策略中的规则以及与访问某些文件的相关逻辑,我们将展示如何拿到完整的Bucket对象列表,同时能够修改或删除Bucket中的现有文件。
什么是Bucket策略
(如果你早已经知道了什么是Bucket策略和URL签名,那么你完全可以直接跳转到下面的“利用”部分)
Bucket策略是一种将内容直接上传到基于云端的大型存储区(如Google云端存储或AWS S3)的安全方式。我们的想法是创建一个定义有检验是否允许文件上传的策略,随后使用密钥对策略进行签名,并将策略和签名提交给客户端。
然后,客户端可以直接将文件上传到Bucket,Bucket存储会验证上传的内容和策略是否匹配。如果匹配,则上传文件。
上传策略与URL预签名
在开始之前,我们需要明确指出有多种方法可以访问Bucket中的对象。使用POST请求访问Bucket时,POST策略(AWS)和POST对象 (谷歌云存储)方式只允许上传内容。
另一种称为URL预签名(AWS)或URL签名(Google云端存储)的方式就不仅仅是可以修改对象。我们是否可以PUT、DELETE或GET 默认的私有对象,这取决于预签名逻辑定义的HTTP方式。
在定义内容类型(Content-Type)、访问控制和文件上传时,URL预签名与POST策略相比会相对宽松。使用错误的自定义逻辑也会更频繁地执行URL签名,如下所示。
这里有很多允许某人访问上传内容的方法,其中一个是AssumeRoleWithWebIdentity ,类似于POST策略,区别在于你可以获得由预定义的IAM Role(身份和访问管理角色)创建的临时安全凭证(ASIA *)。
如何发现上传策略或URL签名
这是使用POST方法的上传请求,如下所示:
该策略使用的是ba64编码的JSON,如下所示:
{"expiration":"2018-07-31T13:55:50Z","conditions": [{"bucket": "bucket-name"},["starts-with", "$key", "acc123"],{"acl": "public-read"},{"success_action_redirect":"https://dashboard.example.com/"},["starts-with", "$Content-Type", ""],["content-length-range", 0, 524288]]}
在AWS S3上的类似于下面的URL签名:
https://bucket-name.s3.amazonaws.com/?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA…
就像谷歌云存储一样:
HTTPS ://storage.googleapis.com/uploads/images/test.png?Expires=1515198382&GoogleAccessId=example%40example.iam.gserviceaccount.com&Signature=dlMA---
上传策略的利用
如果我们想要发现策略中的错误,并对其进行利用,那么我们需要定义一些不同的属性:
l Access = Yes-在上传后,我们是否可以以某种方式访问该文件。在策略中ACL是否被定义为public-read或者能够接收上传文件的URL预签名。在策略中上传但未定义ACL的对象默认为私有。
l Inline=Yes-如果你能够修改content-disposition文件,那么我们可以在内联中提供内容。如果策略中根本没有定义,那么文件则以内联方式提供。
1. starts-with $key是空的
例:
["starts-with", "$key",""]
可以上传文件到Bucket中的任何位置,覆盖任何对象。你可以将key属性设置为任何内容,并且接受该策略。
注意:在某些情况下,这种利用很困难。例如,只有一个Bucket用于上传从未公开的或以后会使用的名为UUID(通用唯一标识符)的对象。在这种情况下,我们不知道要覆盖哪些文件,并且无法知道Bucket中其他对象的名称。
2. starts-with $key不包含路径分隔符或为所有用户都用相同的路径
例:
["starts-with", "$key","acc_1322342m3423"]
如果策略的 $key部分包含一个已定义的部分,但是没有路径分隔符,我们可以将内容直接放在Bucket的根目录中。如果 Access=Yes和 Inline=Yes,并取决于content-type的类型(参见#3和#4),我们则可以通过安装AppCache-manifest来窃取其他用户上传的URL(AppCache中的相关漏洞是由我和 @avlidienbrunn以及@filedescriptor分别发现的)。
如果上传对象的路径对所有用户都是相同的,那这个问题也一样适用。
3. starts-with $Content-Type为空
例:
["starts-with","$Content-Type", ""]
如果Access=Yes 和Inline=Yes,我们就可以在Bucket域上传text/html并提供此服务,如#2所示,我们可以使用它来运行javascript或在此路径上安装AppCache-manifest,这意味着在此路径下访问的所有文件都将泄露给攻击者。
4.使用starts-with $Content-Type定义内容类型
例:
["starts-with","$Content-Type", "image/jpeg"]
这个和#3一样,我们可以添加一些内容来使第一个内容类型成为一个未知的mime类型,随后追加text/html,文件将被认作为text/html类型:
Content-type: image/jpegz;text/html
此外,如果S3-Bucket托管在公司的子域中,通过利用上述策略,我们还可以通过上传HTML文件在域上运行javascript。
最有意思的部分是在沙盒域上通过上传内容来利用网站。
使用自定义逻辑利用URL签名
URL签名是在服务器端签名并提交给客户端,以允许它们上传、修改或访问内容。最常见的问题是网站构建自定义逻辑来检索它们。
首先,要了解怎么利用已签名的URL,重要的是要知道在默认情况下,如何获取Bucket根目录下已签名的且可以显示Bucket的文件列表的GET-URL。这和使用公开列表Bucket的情况基本相同,不同之处在于此Bucket肯定包含其他用户的私有数据。
请记住,当我们知道Bucket中的其它文件时,我们也可以为它们请求URL签名,这就让我们拥有了访问私密文件的权限。
因此,我们目标始终是尝试获根目录或已知的另一个文件。
错误的自定义逻辑的示例
以下是一些示例,其中逻辑通过发出已签名的GET-URL实际暴露了Bucket的根路径。
1.使用get-image这个端点对Bucket进行完全可读访问
有以下要求:
https://freehand.example.com/api/get-image?key=abc&document=xyz
提供以下URL签名:
https://prodapp.s3.amazonaws.com/documents/648475/images/abc?X-Amz-Algorithm=AWS4-HMAC-SHA256…
但是,端点在签名之前对URL进行了规范化,因此通过遍历路径,我们实际上可以指向Bucket的根目录:
https://freehand.example.com/api/get-image?key=../../../&document=xyz
结果:
https://prodapp.s3.amazonaws.com/?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA…
这个URL提供了Bucket中全部文件的列表。
2.因正则表达式解析URL签名请求,导致可完全获取读权限
这是另外一个示例,以下请求是在网站上的端点上获取所需的对象的URL签名:
POST /api/file_service/file_upload_policies/s3_url_signature.jsonHTTP/1.1
Host: sectest.example.com
{"url":"https://example-bucket.s3.amazonaws.com/dir/file.png"}
它会解析URL并将其部分附加到URL签名,你将会得到这个:
{"signedUrl":"https://s3.amazonaws.com/example-bucket/dir/file.png?X-Amz-Algorithm=AWS4-HMAC..."}
可以使用s3.amazonaws.com上的子域和路径访问S3-bucket。在这种情况下,服务器端逻辑规则会将URL更改为基于路径的Bucket URL。
通过欺骗URL extraction,你可以发送如下内容:
{ “url” :“https://.x./example-bucket”}
它会返回一个URL签名,如下所示:
{"signedURL":"https://s3.amazonaws.com//example-beta?X-Amz-Algorithm=AWS4-HMAC..."}
此URL将显示Bucket的完整文件列表。
3.滥用临时的URL签名链接
这个示例来自两年前,是我发现的第一个和URL签名有关的问题。
在网站上,当你上传文件时,你首先在 secure.example.com下创建了一个随机密钥:
POST /api/s3_file/ HTTP/1.1
Host: secure.example.com
{"id":null,"random_key":"abc-123-def-456-ghi-789","s3_key":"/file.jpg","uploader_id":71957,"employee_id":null}
然后,你会返回:
HTTP/1.1 201 CREATED
{"employee_id":null,"s3_key": "/file.jpg", "uploader_id": 71957,"random_key":"abc-123-def-456-ghi-789", "id": null}
这意味着,以下的URL:
https://secure.example.com/files/abc-123-def-456-ghi-789
然后会重定向到:
Location:https://example.s3.amazonaws.com/file.jpg?Signature=i0YZ…
然后,可以发送以下的s3_key内容:
"random_key":"xx1234","s3_key":"/"
之后,会有以下URL:
https://secure.example.com/files/xx1234
重新定向到:
Location:https://example.s3.amazonaws.com/?Signature=i0YZ…
至此,我现在就拥有了他们Bucket的文件列表。该网站使用一个Bucket来存储他们的所有数据,包含他们拥有的每一个文档和文件。当我尝试提取文件列表时,发现Bucket非常庞大,文件数量可以用百万来计算。因此我直接将这个漏洞通报给了该公司,以下是他们的回复:
建议
应根据每个文件上传请求或至少对每个用户生成一个对应的上传策略。
l $key应该有完整的定义:有一个唯一的、随机的名称以及随机的路径。
l 最好将content-disposition定义为attachment。
l acl 应该优先选择 private 或者不要定义。
l content-type应该明确设置(不使用 starts-with)或者不要设置。
另外,永远不要基于用户的请求参数创建URL签名,否则就会出现如上所示的情况。
我见过的最糟的情况是:
https://secure.example.com/api/file_upload_policies/multipart_signature?to_sign=GET%0A%0A%0A%0Ax-amz-date%3AFri%2C%2009%20Mar%202018%2000%3A11%3A28%20GMT%0A%2Fbucket-name%2F&datetime=Fri,%2009%20Mar%202018%2000:11:28%20GMT
你确实给了它你要签名的请求,并且它也回复了你所要求的签名:
0zfAa9zIBlXH76rTitXXXuhEyJI =
这可以用来制作获取URL签名的请求:
curl -H "Authorization: AWSAKIAJAXXPZR2XXX7ZXXX:0zfAa9zIBlXH76rTitXXXuhEyJI=" -H "x-amz-date:Fri, 09 Mar 2018 00:11:28 GMT" https://s3.amazonaws.com/bucket-name/
相同的签名方法不仅仅适用于S3,它使得你能够将你想要的每一个请求签署到AWS-key被允许使用的任何AWS服务。
技术讨论 | 如何绕过并利用Bucket的上传策略和URL签名相关推荐
- 存储桶上传策略和签名 URL的绕过及利用
本文中带有自己一些拙见,读者若存在相关问题或者有其他想法的,欢迎在评论区交流探讨.原文:https://labs.detectify.com/2018/08/02/bypassing-exploiti ...
- 绕过黑名单检查实现文件上传1 ——合天网安实验室学习笔记
实验链接 文件上传指将客户端数据以文件形式封装,通过网络协议发送到服务器端.在服务器端解析数据,最终在服务端硬盘上作为真实的文件保存.了解文件上传漏洞产生的原因,掌握漏洞的利用方法. 链接:http: ...
- ctf题目php文件上传如何绕过_ctf基本的文件上传与绕过学习
绕过客户端校验前台脚本检测扩展名上传webs hell 原理: 当用户在客户端选择文件点击上传的时候,客户端还没有向服务器发送任何 消息,就对本地文件进行检测来判断是否是可以上传的类型,这种方式称为前 ...
- 利用 Spring MVC 上传多文件到指定目录 spring upload files
本篇文章,我们会教你通过eclipse构建一个创建一个Java web项目并转为maven工程,实现用spring mvc将所选文件上传到指定目录 开发环境: 1.JDK 1.7 2.Maven 3. ...
- 利用PostMan 模拟上传/下载文件(亲测)
来源:利用PostMan 模拟上传/下载文件 - 王若伊_恩赐解脱 - 博客园 我们经常用postman模拟各种http请求.但是有时候因为业务需要,我们需要测试上传下载功能.其实postman也是很 ...
- 如何将本地文件利用git工具上传到github仓库中(超详细+最新版)
https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 如有转载,请注明出处(如不注明,盗者必究) 如何将本地文件利用 ...
- 绕过content-type检测文件类型上传webshell
声明:以下内容均来自"实验吧"免费公益渗透平台,该平台至今仍旧在维护,估计~~,为此把以前保留的笔记拿来分享下. [实验目的] 1) 理解绕过Content-Type检测文件 ...
- stm32f103c8t6+ESP8266利用onenet平台上传数据到云平台,再利用云平台远程下发命令给单片机控制LED灯亮灭
stm32f103c8t6+ESP8266利用onenet平台上传数据到云平台,再利用云平台远程下发命令给单片机控制LED灯亮灭 接触stm32已经有一年半的时间了,从最开始的stm32F103ZET ...
- 利用Go语言上传图像并生成缩略图
承前文:Go语言中对图像进行缩放 //利用Go语言上传图像并生成缩略图 func upload(w http.ResponseWriter, req *http.Request, link strin ...
最新文章
- 谷歌CEO皮猜致歉,被解雇的AI伦理研究员:根本没有认错
- JavaScript常见集合操作
- vscode for mac怎样关闭自动更新
- java中子类可否抛出两个父类抛出的异常的子类_父类的多个构造方法各自抛出不同的异常,子类的构造方法应该抛出哪个/些异常?...
- 【Android开发日记】妙用 RelativeLayout 实现3 段布局
- python自学看什么书-python自学看什么书
- 查看exe代码_【安全风险通告】Windows Type 1字体解析远程代码执行漏洞安全风险通告...
- 【每日算法Day 87】今天我脱单了,所以大家不用做题了!
- 【渝粤教育】电大中专计算机职业素养 (7)作业 题库
- CSS中文字体如宋体/微软雅黑的英文名称写法
- C语言计算圆周率PI的代码
- win10易升_电脑win7系统免费自动升级至win10系统,获得持续软件和安全更新
- OpenJudge NOI题库 入门 116题 (三)
- vba 涉及合并取消合并单元格
- Flutter代码可插拨/解耦方案
- 京东物流一体化供应链建设实践
- 【谷粒学院】001-项目概述、Mybatis Plus入门
- java--类单继承多实现,接口多继承
- 为什么PHICH配置信息和下行带宽dl-bandwith必须在PBCH MIB上广播
- 一些关于TIA博图软件使用规范
热门文章
- ArcGIS教程:填挖的工作原理
- [欧洲之行]比利时布鲁塞尔
- 两种图像骨架提取算法的研究原理及实现
- win8系统保护服务器,Win8整合SmartScreen升级功能保护系统安全
- C++字符串操作函数strstr,strcmp,strlen,strcpy,strcat,strok
- PHP 日本商标查询,文字商标查询是否侵权
- 使用TIMESTAMPDIFF计算两个时间戳之间的时间间隔
- 对于工作学习的一些感想
- 麦克风里有电流声,杂音怎么办
- CSS中position的relative和absolute.