Go语言项目容器化导致的ServerSideMIMESniff
answerdev/answer 是基于go语言编写的一个问答平台(类似于知乎),前几周在审计该项目时,发现该系统的图片上传功能点存在一个有趣的漏洞。
该系统的图片上传功能点的工作原理大致如下:
- step1. 用户上传图片文件,将文件存储在本地文件系统中
- step2. 当需要访问图片时,使用gin框架提供的静态资源服务器将用户上传的图片文件作为静态资源返回给用户
internal/router/static_router.go // RegisterStaticRouter register static api router func (a *StaticRouter) RegisterStaticRouter(r *gin.RouterGroup) { r.Static("/uploads", a.serviceConfig.UploadPath) }
为了防止用户上传恶意文件,该系统的文件上传功能设置了一个后缀白名单, 用户只能上传白名单中后缀的文件
internal/service/uploader/upload.go FormatExts = map[string]imaging.Format{ ".jpg": imaging.JPEG, ".jpeg": imaging.JPEG, ".png": imaging.PNG, ".gif": imaging.GIF, ".tif": imaging.TIFF, ".tiff": imaging.TIFF, ".bmp": imaging.BMP, }
起初,我在本地搭建了该项目,对文件上传功能和静态资源服务的进行了测试:我尝试上传文件内容为 , 文件后缀为 ".bmp" ".tif" ".tiff" 的文件,然后通过静态资源服务访问这些文件,我发现返回的响应报文中Content-Type 分别为 image/bmp image/tiff image/tiff ,这些MIME都是正常的图片类型,无法使得浏览器将响应报文中的内容作为html来解析,从而造成XSS 。
但是,神奇的是当我使用 answer 官方提供的docker镜像来搭建answer时: docker run -d -p 9080:80 -v answer-data:/data --name answer answerdev/answer:latest
再次上传同样的文件,然后访问文件,发现返回的http响应报文的Content-Type 竟然变为了 text/html !
step1. 上传图片文件
step2. 访问文件
罪魁祸首 mime 标准库
之所以go实现的静态资源服务器会出现这种将 bmp/tif/tiff 等后缀的图片文件的Content-Type设置为text/html的情况,是因为go语言的mime标准库的实现有问题。
go语言实现的静态资源服务器在返回文件时,大致会执行以下步骤:
- step1. 调用mime.TypeByExtension()函数来根据文件后缀获取对应的Content-Type
- step2. 如果mime.TypeByExtension()函数返回的Content-Type为空字符串,则会进行Server-Side MIME Sniff ,即根据文件内容来判断对应的Content-Type
而mime.TypeByExtension()函数的实现实际上是依赖于外部的mime.types文件的,其本身所维护的文件后缀与 Content-Type 的映射关系非常有限
/usr/local/go/src/mime/type.go // TypeByExtension returns the MIME type associated with the file extension ext. // The extension ext should begin with a leading dot, as in ".html". // When ext has no associated type, TypeByExtension returns "". // // Extensions are looked up first case-sensitively, then case-insensitively. // // The built-in table is small but on unix it is augmented by the local // system"s MIME-info database or mime.types file(s) if available under one or // more of these names: // // /usr/local/share/mime/globs2 // /usr/share/mime/globs2 // /etc/mime.types // /etc/apache2/mime.types // /etc/apache/mime.types // // On Windows, MIME types are extracted from the registry.
在容器化过程中,为了追求最小化攻击面、更小的镜像体积,往往会使用alpine系列镜像,而该系列镜像中并没有以上所列的mime.types文件: /usr/local/share/mime/globs2 /usr/share/mime/globs2 /etc/mime.types /etc/apache2/mime.types /etc/apache/mime.types
例如:
/Users/rickshang/Code/SecurityResearch/InTheLab/content_type_lab/golang/fuzzer/main.go package main import ( "fmt" "mime" ) func main() { exts := []string{".bmp", ".gif", ".jpeg", ".jpg", ".png", ".svg", "ico", ".tif", ".tiff", ".webp"} for _, ext := range exts { content_type := mime.TypeByExtension(ext) fmt.Printf("ext:%s content_type:%+v ", ext, content_type) } }
本地运行: go run main.go ext:.bmp content_type:image/bmp ext:.gif content_type:image/gif ext:.jpeg content_type:image/jpeg ext:.jpg content_type:image/jpeg ext:.png content_type:image/png ext:.svg content_type:image/svg+xml ext:.ico content_type:image/x-icon ext:.tif content_type:image/tiff ext:.tiff content_type:image/tiff ext:.webp content_type:image/webp
使用golang官方镜像:golang:1.19-alpine 容器化之后运行: docker run -it --rm -v /Users/rickshang/Code/SecurityResearch/InTheLab/content_type_lab/golang/fuzzer/main.go:/code/main.go -w /code golang:1.19-alpine go run main.go ext:.bmp content_type: ext:.gif content_type:image/gif ext:.jpeg content_type:image/jpeg ext:.jpg content_type:image/jpeg ext:.png content_type:image/png ext:.svg content_type:image/svg+xml ext:.ico content_type: ext:.tif content_type: ext:.tiff content_type: ext:.webp content_type:image/webp
话句话说,如果你的静态资源服务器是基于go语言的mime标准库来实现的,那么你的静态资源服务器在使用alpine镜像容器化之后很可能会出现这种将bmp/tif/tiff等后缀的图片文件的Content-Types识别为text/html的情况,进而导致存储型XSS漏洞。 总结
该漏洞有趣的点在于,它揭示了安全问题与环境的关系: 测试环境下没有安全问题,不代表生产环境下也没有安全问题。
容器化在追求最小化攻击面的同时也引入了新的攻击面,go语言mime标准库的问题便是典型的例子。 依赖外部文件的标准库实现 -----> 容器化----->外部文件缺失----> 标准库功能出现安全问题 修复方案
go语言 mime标准库维护的内置的mime类型映射关系非常有限: go/src/mime/type.go var builtinTypesLower = map[string]string{ ".avif": "image/avif", ".css": "text/css; charset=utf-8", ".gif": "image/gif", ".htm": "text/html; charset=utf-8", ".html": "text/html; charset=utf-8", ".jpeg": "image/jpeg", ".jpg": "image/jpeg", ".js": "text/javascript; charset=utf-8", ".json": "application/json", ".mjs": "text/javascript; charset=utf-8", ".pdf": "application/pdf", ".png": "image/png", ".svg": "image/svg+xml", ".wasm": "application/wasm", ".webp": "image/webp", ".xml": "text/xml; charset=utf-8", }
方案一: 打包镜像时将如下mime.types文件拷贝到容器中: /usr/local/share/mime/globs2 /usr/share/mime/globs2 /etc/mime.types /etc/apache2/mime.types /etc/apache/mime.types
方案二: 在实现图片上传功能时,不要将mime标准库内置表之外的后缀类型添加到白名单中,例如: .bmp .ico .tif .tiff
方案三: 使用nginx作为静态资源服务器 进一步的研究其他语言的静态资源服务器容器化后是否存在同样的问题? 容器化是否会引入其他新的安全问题?
from https://tttang.com/archive/1880/
2018年4月普吉岛自由行漫游卡伦观景台艺术社区大象园2018年4月18日。我在网上看到普吉岛卡伦海滩有一个观景台,在大海对面的山顶上,可以俯瞰下面的大小卡塔卡伦三大海滩卡伦海滩还有一个艺术社区,聚集了很多泰国画家建造的画室画廊另有卡
全球品牌大事记(2022年11月)全球品牌大事记,是品牌联盟发展研究中心的常规研究项目。从2022年3月起,品牌联盟对当月发生的全球品牌大事进行观察梳理和总结,并联合中新经纬共同编制及公布。全球品牌大事记,旨在帮助
展示品牌未来纯电车型样貌标致概念车CES展首发爱卡汽车海外新车原创近日,据媒体消息,标致全新概念车Inception将在明年1月5日的2023年美国拉斯维加斯消费电子展(CES)上首发。据悉,标致将通过Inception概念车
韩国队压哨改写命运,历史首次三支亚洲球队晋级世界杯十六强再次展现我们的激情和努力,加上一点点运气,我们就能创造奇迹。金英权的赛前豪言,在韩国与葡萄牙的比赛中完美兑现。凭借伤停补时的进球,韩国人在最后一刻改写了命运2比1绝杀葡萄牙,进球数
跟着大师去旅游意大利蒂沃利小镇哈德良皇帝的别墅在纽约大都会博物馆里,有两根大理石柱子,创作于约公元117138年罗马中期帝国的哈德良(Hadrianic)时期。这两根柱子的三面都用浅浮雕的长春藤藤蔓装饰,是罗马建筑中大量使用彩
西安秦始皇帝陵铜车马博物馆项目标签设计公司上海中森止境设计工作室位置中国类型建筑材料混凝土清水混凝土玻璃标签西安陕西分类博物馆展览类建筑文化建筑美丽乡村新农村新农村自建房项目概况ProjectOvervie
提醒!这种水果是药物公敌!竟会和多种药物相互作用天气渐寒,又到了吃西柚的好季节。但是药师提醒,西柚是公认的药物公敌,会和已知的近百种心血管药物相互作用,长期服药的市民要警惕,小心美味变毒药。西柚又叫葡萄柚,因其肉嫩多汁,口感酸甜
经常吃宵夜会怎么样,科学吃宵夜就选植清爽近年来,随着大都市生活节奏加快工作压力增大,加班后来顿宵夜,已经成为当代年轻人释放压力的方式之一。烧烤火锅大排档宵夜的美食种类繁多,慢慢地肚儿也圆了,身上的肉肉也多了,长期这样的油
透析并发症No。1关于高磷血症的几个必读关键点高磷血症是慢性肾脏病(CKD)最常见的并发症之一,广泛存在于CKD35期患者中,尤其是维持性血液透析患者。高磷血症的治疗除限制饮食磷摄入和规律透析外,血液透析患者更需要服用磷结合剂
一个普通玩家对开心庄园游戏的评测,看是不是真的能赚钱?开心庄园是一款经营性游戏,比较稳定,所以基本不用考虑公司跑路,文章有点长,一定要看到最后哦。先说第一点只种植收割作物付出的时间及收益种植作物界面游戏前十次是不限制每天收割次数的,只
魔兽世界等游戏停服,玩家虚拟财产损失谁担责?前言近几年,由于游戏市场更迭迅速,产品热度持续时间不足,一些网络游戏营收不断走低,加之游戏版权授权费用较高等原因导致游戏运营方在版权到期后选择游戏停服。11月17日,暴雪中国战网官