Go, в чём суть реализации уязвимости c помощью перестановки `defer response.Body.Close()`?
Есть такой обработчик, как я понимаю реализация уязвимости связана с тем, что тело ответа закрывается до проверки ошибки. Но я не очень понимаю почему это должно работать, ведь тело всё равно закрыто, не зависимо до ли после проверки.
func HandleRequest(client http.Client, request *http.Request)
(*http.Response, error) {
response, err := client.Do(request)
defer response.Body.Close()
if err != nil {
return nil, err
}
}
Мне известно, что полное отсутствие строки defer response.Body.Close() приводит к гарантированным проблемам, но не могу придумать как протестировать выше упомянутую уязвимость
Ответы (1 шт):
defer response.Body.Close() означает, что response.Body.Close() должно быть выполнено в точке выхода из функции. Ни о каком закрытии тела до проверки ошибки речь не идёт.
Проблема здесь в другом - в случае ошибки response может быть nil, и выполнение отложенной инструкции в ветке if err != nil {... return ...} таком случае приведет к панике из-за обращения к нулевому указателю.
panic: runtime error: invalid memory address or nil pointer dereference
Пример: https://go.dev/play/p/vEiUFPgLYxf
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
)
func main() {
client := http.Client{}
url, _ := url.Parse("https://no.such.host")
request := &http.Request{
Method: "GET",
URL: url,
}
response, err := client.Do(request)
defer response.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Request failed: %s\n", err.Error())
}
io.Copy(os.Stdout, response.Body)
}