[{"data":1,"prerenderedAt":210},["ShallowReactive",2],{"blog:\u002Fblog\u002Fheader-trust":3,"blog-around:\u002Fblog\u002Fheader-trust":192,"blog-others:\u002Fblog\u002Fheader-trust":203},{"id":4,"title":5,"body":6,"cover":176,"date":177,"description":178,"draft":179,"extension":180,"meta":181,"navigation":182,"path":183,"readingMinutes":184,"seo":185,"stem":186,"tags":187,"updated":176,"__hash__":191},"blog\u002Fblog\u002Fheader-trust.md","Подмена Referer, Host и X-Forwarded-For: почему нельзя верить заголовкам",{"type":7,"value":8,"toc":166},"minimark",[9,18,21,26,29,32,35,39,42,45,49,52,55,83,87,90,93,97,100,104,110,116,122,133,139],[10,11,12,13,17],"p",{},"Каждый запрос к сайту сопровождается заголовками — служебными строками, которые сообщают серверу, откуда пришёл посетитель, какой у него браузер, по какому адресу он обращается. Браузер заполняет их автоматически, и из-за этого легко забыть главное: ",[14,15,16],"strong",{},"заголовки присылает клиент",". Любой, кто отправляет запрос не из браузера, а из скрипта, может написать в них что угодно.",[10,19,20],{},"Пока заголовки используются для статистики, это не проблема. Проблема начинается, когда на их основе приложение принимает решения: начислить бонус, пропустить в админку, сформировать ссылку.",[22,23,25],"h2",{"id":24},"referer-я-пришёл-от-партнёра","Referer: «я пришёл от партнёра»",[10,27,28],{},"Заголовок Referer показывает страницу, с которой посетитель перешёл на сайт. Многие обменники используют его в партнёрских программах: пришёл с сайта партнёра — заявка записывается на партнёра, ему начисляется процент.",[10,30,31],{},"Если начисление зависит только от Referer, партнёрскую выплату можно «заработать», вообще не приводя клиентов: достаточно отправлять запросы с нужным значением заголовка. Деньги уходят за трафик, которого не было.",[10,33,34],{},"Вторая типичная ошибка — защита от CSRF, основанная только на Referer. CSRF — это атака, при которой чужой сайт заставляет браузер вошедшего пользователя выполнить действие в вашем приложении. Проверка «запрос пришёл с нашего домена» по одному Referer ненадёжна: браузеры и расширения иногда вырезают этот заголовок, и разработчики, чтобы не ломать сайт, начинают пропускать запросы без него. Защита превращается в формальность.",[22,36,38],{"id":37},"host-ссылка-для-сброса-пароля-ведёт-не-туда","Host: ссылка для сброса пароля ведёт не туда",[10,40,41],{},"Заголовок Host сообщает, к какому домену обращается клиент. Приложения часто используют его, чтобы собирать абсолютные ссылки — например, в письме «Сбросить пароль».",[10,43,44],{},"Если сервер принимает любой Host и подставляет его в ссылку, злоумышленник может инициировать сброс пароля для чужой учётной записи, указав в заголовке свой домен. Письмо уйдёт настоящему владельцу аккаунта — с настоящим оформлением, но со ссылкой на чужой сервер. Один клик — и секретный токен сброса оказывается у атакующего. Это называют отравлением заголовка Host.",[22,46,48],{"id":47},"x-forwarded-for-чужой-ip-адрес","X-Forwarded-For: чужой IP-адрес",[10,50,51],{},"Когда сайт стоит за балансировщиком или CDN, приложение видит не адрес посетителя, а адрес прокси. Настоящий IP передаётся в заголовке X-Forwarded-For. Но если приложение читает этот заголовок, не проверяя, кто его прислал, посетитель может вписать туда любой адрес.",[10,53,54],{},"Последствия зависят от того, где используется IP:",[56,57,58,65,71,77],"ul",{},[59,60,61,64],"li",{},[14,62,63],{},"белые списки IP для админки"," — злоумышленник «представляется» адресом офиса;",[59,66,67,70],{},[14,68,69],{},"ограничение частоты запросов"," — каждая попытка подбора пароля приходит «с нового адреса», и лимит не срабатывает;",[59,72,73,76],{},[14,74,75],{},"геоблокировка"," — запрет для определённых стран обходится одной строкой;",[59,78,79,82],{},[14,80,81],{},"журналы"," — в логах остаются выдуманные адреса, и расследование инцидента идёт по ложному следу.",[22,84,86],{"id":85},"origin-и-user-agent","Origin и User-Agent",[10,88,89],{},"Заголовок Origin надёжнее Referer для проверки источника запросов из браузера, но и его легко подделать вне браузера. Он полезен как дополнительный сигнал, а не как пропуск.",[10,91,92],{},"User-Agent — строка с названием браузера — подделывается тривиально. Решения вида «запросы от нашего мобильного приложения узнаём по User-Agent» не защищают ни от чего.",[22,94,96],{"id":95},"как-понять-есть-ли-проблема-у-вас","Как понять, есть ли проблема у вас",[10,98,99],{},"Начните с инвентаризации: найдите в коде все места, где читаются Referer, Host, X-Forwarded-For, Origin и User-Agent, и для каждого ответьте на вопрос — что произойдёт, если значение подделано? Если ответ «ничего, это только для статистики» — всё в порядке. Если «начислится бонус», «пропустит в админку» или «изменится ссылка в письме» — это место нужно переделать. Отдельно проверьте конфигурацию nginx и список доверенных прокси в приложении: они должны совпадать с реальной схемой вашей инфраструктуры.",[22,101,103],{"id":102},"как-защищаться","Как защищаться",[10,105,106,109],{},[14,107,108],{},"Подписывать реферальные ссылки."," Партнёр получает ссылку с параметром, подписанным HMAC — криптографической подписью на секретном ключе сервера. Начисление происходит только по ссылке с верной подписью, а не по заголовку.",[10,111,112,115],{},[14,113,114],{},"CSRF — только токенами."," Каждая форма и каждый запрос, меняющий данные, должны нести токен, который сервер выдал этому пользователю. В Laravel это работает из коробки — важно не отключать проверку «для удобства». Дополнительно помогают cookie с атрибутом SameSite.",[10,117,118,121],{},[14,119,120],{},"Фиксированный канонический домен."," Абсолютные ссылки в письмах собираются из адреса в конфигурации приложения, а не из Host. На уровне nginx запросы с неизвестным Host лучше отклонять отдельным серверным блоком по умолчанию.",[10,123,124,127,128,132],{},[14,125,126],{},"Доверять X-Forwarded-For только от своих прокси."," В nginx для этого есть модуль real_ip: директива ",[129,130,131],"code",{},"set_real_ip_from"," перечисляет адреса ваших балансировщиков или CDN, и только от них заголовок принимается. В Laravel аналогичную роль играет список доверенных прокси. Всё остальное — адрес соединения, а не то, что написал клиент.",[10,134,135,138],{},[14,136,137],{},"Не принимать решений о доступе по заголовкам."," Вход в админку — по паролю и второму фактору, а белый список IP — лишь дополнительный барьер, настроенный на уровне сервера, где адрес нельзя подделать.",[140,141,142,145],"blockquote",{},[10,143,144],{},"Всё, что пришло в запросе, написал клиент. Заголовки — это сведения, а не доказательства.",[146,147,148,151,154,157,163],"ol",{},[59,149,150],{},"Реферальные начисления — только по ссылкам с подписью HMAC.",[59,152,153],{},"CSRF — токенами и SameSite-cookie, без опоры на Referer.",[59,155,156],{},"Ссылки в письмах — из конфигурации, неизвестный Host — отклонять в nginx.",[59,158,159,160,162],{},"X-Forwarded-For — только от доверенных прокси через ",[129,161,131],{},".",[59,164,165],{},"Доступ — пароль и 2FA; IP-фильтр — на уровне сервера и только как дополнительный слой.",{"title":167,"searchDepth":168,"depth":168,"links":169},"",2,[170,171,172,173,174,175],{"id":24,"depth":168,"text":25},{"id":37,"depth":168,"text":38},{"id":47,"depth":168,"text":48},{"id":85,"depth":168,"text":86},{"id":95,"depth":168,"text":96},{"id":102,"depth":168,"text":103},null,"2026-10-28","HTTP-заголовки присылает клиент, а значит, их можно написать любыми. Разбираем, где доверие к Referer, Host и X-Forwarded-For превращается в дыру — от реферальных выплат до сброса пароля.",false,"md",{},true,"\u002Fblog\u002Fheader-trust",6,{"title":5,"description":178},"blog\u002Fheader-trust",[188,189,190],"HTTP","заголовки","nginx","QjC05egt5ihnIHi1InFllT4gdG1gb0AUt9rNkE-qBeg",[193,198],{"title":194,"path":195,"stem":196,"date":197,"children":-1},"SQL-инъекции: как в 2026-м всё ещё воруют базы","\u002Fblog\u002Fsql-injection","blog\u002Fsql-injection","2026-10-29",{"title":199,"path":200,"stem":201,"date":202,"children":-1},"Как чаще всего взламывают сайты: семь дверей, которые забывают закрыть","\u002Fblog\u002Fhow-sites-get-hacked","blog\u002Fhow-sites-get-hacked","2026-10-27",[204,208,209],{"path":205,"title":206,"date":207},"\u002Fblog\u002Fphp-rce-october-2026","Две критические дыры в ядре PHP: почему обновляться нужно в тот же день","2026-10-30",{"path":195,"title":194,"date":197},{"path":200,"title":199,"date":202},1793381757141]