go 通过参数值延续绕过多边界检查的mime

5cnsuln7  于 6个月前  发布在  Go
关注(0)|答案(7)|浏览(46)

你正在使用的Go版本是什么( go version )?

$ go version
go version go1.16.4 darwin/amd64

这个问题在最新版本中是否会重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/sym01/Library/Caches/go-build"
GOENV="/Users/sym01/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/sym01/Workspace/Go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/sym01/Workspace/Go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.16.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/cr/jbhvnrzx39s46k8btfr1s2_r0000gp/T/go-build52418455=/tmp/go-build -gno-record-gcc-switches -fno-common"

你做了什么?

https://play.golang.org/p/JLYLXf40j8y

你期望看到什么?

net/http 对于 multipart/form-data 有默认的安全实现,不允许多边界。
go/src/mime/mediatype.go
第188行到第191行:
| | if_, exists:=pmap[key]; exists { |
| | // 重复的参数名是错误的。 |
| | return"", nil, errors.New("mime: duplicate parameter name") |
| | } |
例如,它将停止解析带有 header Content-Type: multipart/form-data;boundary="boundary";boundary="another-boundary" 的表单。

你看到了什么?

由于对RFC 2231的支持,我们可以通过带有 header Content-Type: multipart/form-data;boundary="boundary";boundary*0="another";boundary*1="-boundary" 来绕过这个安全检查。这种不正确的实现可以被用于绕过某些安全机制,如Web应用防火墙。

wvmv3b1j

wvmv3b1j2#

是否有一些RFC或其他权威来源表明当前的实现是错误的?RFC 2231使用Content-Type作为示例,并没有表明boundary参数被排除在外。

nkkqxpd9

nkkqxpd93#

是的,以下Content-Type是正常的,应该被支持。

Content-Type: message/external-body; access-type=URL;
 URL*0="ftp://";
 URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"

但是对于以下Content-Type呢?哪个URL应该被视为正确的?

Content-Type: message/external-body; access-type=URL;
 URL="ftp://evil.com/path/to/xxx";
 URL*0="ftp://";
 URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"

RFC 2231没有指示哪个是正确的,但Go总是会选择第二个URL。

imzjd6km

imzjd6km4#

啊,我懂了。问题在于我们无法检测到重复的参数名称,当其中一个被指定为RFC 2231续行时。(抱歉,我误解了你的初始示例并理解了这个问题。)

o4tp2gmn

o4tp2gmn5#

我们有两个测试用例,用于明确验证当一个参数同时出现在RFC 2231和传统形式中时,RFC 2231形式具有优先级。
这些测试用例来自:
http://test.greenbytes.de/tech/tc2231/#attfnboth
http://test.greenbytes.de/tech/tc2231/#attfnboth2
RFC 5987 第4.2节指出:
头字段规范需要定义是否允许具有相同parmname组件的多个参数示例,以及它们应该如何处理。此规范建议使用扩展语法的参数具有优先级。这将允许生产者在不破坏尚未理解扩展语法的接收方的情况下同时使用这两种格式。
来自greenbytes.de测试用例的测试结果表明,大多数浏览器选择了RFC 2231编码的值。我认为当前的行为与解释重复参数的常见做法一致。

zengzsys

zengzsys6#

是的,我完全同意你的观点。这是一个兼容性和安全性之间的权衡。
这个问题更像是一个建议,而不是一个bug。

gkn4icbw

gkn4icbw7#

我遇到了类似的问题,但是是针对实际的电子邮件头部,示例:

Content-Type: multipart/alternative; boundary="----RTIR0GV26TDW15Q5CVX979LBL6XN18"; boundary="----RTIR0GV26TDW15Q5CVX979LBL6XN18"

有一个提议,但在没有修复的情况下已关闭: #28618

相关问题