Код-ревью Middle Инъекции: SQL, NoSQL, команды обновлено
Ревью: обработчик на Go с базой и командой
Вопрос
Найдите уязвимости в HTTP-обработчике.
func handler(w http.ResponseWriter, r *http.Request) {
user := r.URL.Query().Get("user")
host := r.URL.Query().Get("host")
q := fmt.Sprintf("SELECT id, email FROM users WHERE login = '%s'", user)
row := db.QueryRow(q)
var id int
var email string
row.Scan(&id, &email)
out, _ := exec.Command("sh", "-c", "ping -c 1 "+host).Output()
fmt.Fprintf(w, "%d %s %s", id, email, out)
}
Коротко
В Go параметры передаются плейсхолдерами драйвера ($1 для PostgreSQL, ? для MySQL), а команды через exec.Command с отдельными аргументами без шелла. Игнорирование ошибок тоже бывает уязвимостью: обработчик продолжает работу в неожиданном состоянии.
Что должен найти ревьюер
- Безопасностьстрока 4SQL-инъекция:
fmt.Sprintfвклеиваетuserв запрос. Нужноdb.QueryRow("... WHERE login = $1", user). - Ошибкастрока 8Ошибка
Scanигнорируется: при отсутствии пользователя ответ с нулевыми значениями. - Безопасностьстрока 9Инъекция команд:
sh -cс конкатенациейhost. Нужноexec.Command("ping", "-c", "1", host)и проверка, что host это IP или допустимое имя. - Ошибкастрока 9Ошибка выполнения команды игнорируется.
- Безопасностьстрока 10Нет авторизации: кто угодно получает email любого пользователя по логину.
Разбор
В Go параметры передаются плейсхолдерами драйвера ($1 для PostgreSQL, ? для MySQL), а команды через exec.Command с отдельными аргументами без шелла. Игнорирование ошибок тоже бывает уязвимостью: обработчик продолжает работу в неожиданном состоянии.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.