8

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?

2
  • 1
    Better to use the built-in fileserver: http://golang.org/pkg/net/http/#FileServer. Apart from protecting you from malicious requests like you're worried about, it'll also serve the files with right mime types. Commented Apr 25, 2014 at 6:46
  • @Anonymous this was just an example for the specific quests, I'm actually doing a lot more with the request. Commented Apr 25, 2014 at 6:57

1 Answer 1

12

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.

Sign up to request clarification or add additional context in comments.

1 Comment

It is interesting that cleanPath checks for empty string and prepending a slash because that seems to not be possible as input to the function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.