matryer / goblueprints

Source code for Go Programming Blueprints
1.48k stars 356 forks source link

Chapter 3: Denial of Service vulnerability #80

Open mtlynch opened 2 years ago

mtlynch commented 2 years ago

Chapter 3 accepts arbitrary uploads from remote users, but it doesn't limit the size of the upload.

https://github.com/matryer/goblueprints/blob/aae50b4b30fa6dfd73e3c411b3bfe1972294be61/chapter3/chat/upload.go#L12

A malicious user could upload a very large file and exhaust server RAM or fill the disk.

A possible fix is to use http.MaxBytesReader to limit the size of the upload to some reasonable maximum for image files (e.g. 10 MiB).

Calling ParseMultipartForm with an explicit RAM limit also protects the server from exhausting RAM trying to process large uploads:

const maxImageBytes = 10 << 20 // 10 MiB

func uploaderHandler(w http.ResponseWriter, req *http.Request) {
    // Read a maximum of maxImageBytes, plus a little extra room for multipart fields.
    r.Body = http.MaxBytesReader(w, r.Body, maxImageBytes +1024)
    if err := r.ParseMultipartForm(maxImageBytes); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    userID := req.FormValue("userid")
    ...