你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.20.2 windows/amd64
这个问题在最新版本中是否重现?
是的。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\colin\AppData\Local\go-build
set GOENV=C:\Users\colin\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\colin\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\colin\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20.2
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=J:\Data\Projects\fpProxy\go.mod
set GOWORK=J:\Data\Projects\fpProxy\go.work
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\colin\AppData\Local\Temp\go-build4117129570=/tmp/go-build -gno-record-gcc-switches
你做了什么?
我正在处理一些非常旧的软件,在某些情况下,这些软件会在发送HTTP请求时不去除Request URI中的空白字符。在我们将代理更改为基于Go之后,这些请求无法在应用程序和文件服务器之间被代理接收。
当在应用程序和Go代理服务器之间放置Python或Fiddler代理时,这些请求会突然开始正常工作。我能想到的唯一想法是,它们在通过时对请求进行清理。
我进行了深入的研究,发现在读取请求时, parseRequestLine
的工作假设是请求行中的每个元素都由单个空格字符分隔,如RFC中所定义的那样。当它拆分时,HTTP协议会在其前面多出一个空格。这意味着它会因为格式错误的协议而报错。我知道这种行为并不是RFC严格支持的,但我希望看到它反映出其他软件是如何处理的。
测试这个的最简单的方法是向一个Go HTTP服务器发送 GET /test HTTP/1.0
和 GET /test HTTP/1.0
等变体,后者将返回400 Bad Request错误。
为了演示显示带有空格前缀的协议来自哪里,我复制了当前的 parseRequestLine
,然后将协议输入到 ParseHTTPVersion
中
https://go.dev/play/p/8F2Q9A5Fhx1
你期望看到什么?
'GET', 'http://www.nabiscoworld.com/shock/nbgrm.dcr', 'HTTP/1.0'
你看到了什么?
'GET', 'http://www.nabiscoworld.com/shock/nbgrm.dcr', ' HTTP/1.0'
Malformed proto
8条答案
按热度按时间u4dcyp6a1#
CC @neild
0dxa2lsx2#
解:理想情况下,如果有这样的功能就更好了,可以让他们通过但被转义。
mctunoxg3#
我知道这种行为并不是RFC严格支持的,但我希望看到它反映出其他软件是如何处理的。
通常情况下,Go语言的
net/http
会尽量遵循RFCs,除非这种偏差被广泛使用。你能举一些广泛使用的客户端的例子,这些客户端需要这种行为吗?也许能提供更多关于为什么在这些客户端中无法修复它的细节?wfsdck304#
这是一个棘手的问题——它并不常用,过去15+年里几乎所有的客户端都不应该这样做,但我们发现一些Adobe Shockwave游戏(大约20-25年前的游戏)中存在错误的使用。
这种行为在其他我尝试过的软件中也有体现——Fiddler、Python、Apache等都处理得很好(事实上,http://go.dev/网站本身认为它是有效的)。我一直很难找到关于为什么它们一开始就支持它的文档,我能找到的唯一资料是1998年URI Generic Syntax RFC中的“语法符号和通用元素”部分,但当2005年的当前RFC出现时,它已经被删除了。
<first>/<second>;<third>?<fourth>
组件名称用尖括号括起来,尖括号外的任何字符都是字面分隔符。应忽略空白。这些描述是非正式的,不定义语法要求。
显然,考虑到我们的使用场景,支持这个功能是值得考虑的,但我也理解你为什么不选择这样做。
hjzp0vay5#
Just to add some more samples of it working Using OpenSSL to test, go.dev worked with any number of spaces
I tried to find other examples of nginx and apache, but I couldn't get any request to work openssl with nginx.org or facebook.com, everything was rejected, I am sure I am doing something wrong.
All sites rejected anything starting with a space, but every site I tried that I could get to work normally worked with multiple spaces between Method and URI and URI and Protocol and Protocol to end.
9ceoxa926#
我们使用Golang来解析网络安全中的原始http请求,有一个简单的SQL注入示例,无法通过http.ReadRequest解析。
当然,这不是一个通用的http请求,但我们希望用Go做更多的事情😁
j7dteeu87#
看起来我们应该拒绝让解析器变得更宽松。
k5ifujac8#
看起来我们应该拒绝让解析器变得过于宽松。我的意思是,我们需要更宽松的解析器来使Golang能够解析这些非一般请求。😂
我们想要从http查询中获取键值对 "id" = "1" 或 "1=2"。