英文:
Does Go sanitize URLs for web requests?
问题
我正在实现一个简单的Go语言Web服务器。由于我没有Web开发经验,这对我来说是一个严肃的问题。
假设我正在使用修改过的loadPage
函数来提供网页,代码来自这里:
func loadPage(title string) []byte {
filename := title
body, _ := ioutil.ReadFile(filename)
return body
}
func handler(w http.ResponseWriter, req *http.Request) {
content := loadPage(req.URL.Path[1:])
fmt.Fprintf(w, "%s", content)
}
从技术上讲,这使我能够以以下形式发送请求:
http://example.com/../../etc/passwd
而代码会愉快地提供/etc/passwd文件,但实际上并没有。这是否意味着Go的http包或http协议本身对../
有某种保护,还是我做错了什么,导致存在安全漏洞?
英文:
I was implementing a simple web server in Go. As I have no experience in web development, this striked as a serious question for me.
Let's say I'm serving web pages with a modified loadPage
function from here
func loadPage(title string) []byte {
filename := title
body, _ := ioutil.ReadFile(filename)
return body
}
func handler(w http.ResponseWriter, req *http.Request) {
content := loadPage(req.URL.Path[1:])
fmt.Fprintf(w, "%s", content)
}
Technically this allows me to write a request in a form of
http://example.com/../../etc/passwd
and the code would happily serve the /etc/passwd file, but it does not. Does this mean that there is some sort of protection against ../
in the Go http package or http protocol itself, or am I just doing something wrong and it is a security hole?
答案1
得分: 10
net/http
在其HTTP请求多路复用器ServeMux
中执行此操作:
> ServeMux还负责对URL请求路径进行清理,将包含.或..元素的任何请求重定向到一个等效的不包含.-和..-的URL。
相关的函数是私有函数cleanPath(p string) string
,它调用了path.Clean
:
1415 np := path.Clean(p)
path.Clean
执行了适当的删除操作:
97 case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
98 // ..元素:删除到最后一个/
99 r += 2
100 switch {
101 case out.w > dotdot:
102 // 可以回溯
103 out.w--
104 for out.w > dotdot && out.index(out.w) != '/' {
105 out.w--
106 }
如果路径没有根路径,还有一个额外的情况,但是上面的cleanPath
函数确保路径已经是根路径,如果路径中没有斜杠,则在要清理的路径前面添加一个斜杠。
英文:
net/http
does this in its HTTP request multiplexer, ServeMux
:
> ServeMux also takes care of sanitizing the URL request path, redirecting any request containing . or .. elements to an equivalent .- and ..-free URL.
The relevant function is the private func cleanPath(p string) string
, which calls path.Clean
:
1415 np := path.Clean(p)
path.Clean
does the appropriate removals:
97 case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
98 // .. element: remove to last /
99 r += 2
100 switch {
101 case out.w > dotdot:
102 // can backtrack
103 out.w--
104 for out.w > dotdot && out.index(out.w) != '/' {
105 out.w--
106 }
There's an additional case if the path isn't rooted, but cleanPath
above ensures it is so, by prepending a forward-slash to the path to be cleaned if there isn't one already.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论