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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With