틈틈히 웹고트 풀어보기로 결심!

3~4년만에 설치해봤는데 이거 하나도 모르겠내..

 

모르는건 힌트도 보고 검색도 하고 이리저리 고민도 하면서 풀어봐야겠내요

웹고트를 접속하게 되면 왼쪽 메뉴 중에 General이라는 메뉴가 있습니다.

눌러보면 Http Basics와 Http Splitting 이라고 있는데 Http basics는 Paros나 WebScarab 같은 툴을 이용해서

http request랑 response의 헤더를 구경해보라고 있는 페이지 같더라구요

가뿐하게 넘어가고 Http Splitting을 풀기 위해 눌러줍니다.

 

 

....... 영어를 해석해야하는 큰 문제가 생겼습니다..

대충 눈치껏 보면 이 레슨은 두 개의 스테이지로 되있고 첫 번째 스테이지는 HTTP Splitting 공격에 대한 거고

두 번째 스테이지는 Cache Poisoning에 대한 거 같내요.

다음 단락은 대충 캐리지 리턴(CR)이랑 라인 피드(LF)를 이용해서 200 OK를 강제로 보내라는 것 같내요

그러면 스테이지2가 열린다고... 스테이지2를 성공하면 메뉴에 초록색 체크가 생기고..

CR과 LF를 암복호화 할 때 아마 PHP Charset Encoder 라는 사이트가 유용할 거라고 하는 것 같내요

해석이 틀릴 수도 있지만 대강 이런 맥락인 듯 합니다.

 

우선 제대로된 기초가 없기 때문에 Http Splitting이 뭐고 Cache Poisoning이 뭔지 검색해봤습니다...

간단하게 적어보자면

 

Http Splitting : HTTP Response Splitting 공격은 웹 어플리케이션이 HTTP response가 분리될 수 있는 보안 취약점을 가지고 있다면

응답 메시지를 조작하여 Proxy 서버를 공격자의 의도대로 조작할 수 있는 공격 방식입니다. 공격받은 Proxy 서버를 사용하는

모든 사용자는 조작된 페이지를 보게 될 수 있습니다. (출처 : http://getroot.tistory.com/14)

간단히 말하면 HTTP Request를 보냈을 때 서버가 응답해주는 HTTP response의 내용을 입력값을 통해 인위적으로 조작할 수 있다는 것을 말하는 것 같습니다. 한 마디로 특정 값을 입력 했을 때 정상적인 응답 값을 두 개 혹은 그 이상 받아올 수 있는 거죠. 아무래도 사용자가 입력한 값을 제대로 검증하지 않으면 생기는 취약점인듯 합니다.

 

 

Cache Poisoning : 여러 사용자가 사용하는 웹캐시 또는 단일 사용자의 브라우저캐시에서 악의적인 목적으로 생성된 응답을 캐시하는 경우

 그 영향이확대됨. 프록시서버에서 흔히 볼 수 있는 것과 같이 공유 웹캐시에 응답이 캐시되는 경우, 해당 캐시의

 모든 사용자가  캐시항목이 없어질 때까지 악성콘텐트를 계속받음 (출처 : 구글링에서 구한 pdf 파일)

 정확하진 않지만 아마 Http Splitting 같은 공격을 통해 해당 서버의 캐시를 감염(?)시키면 감염된 캐시가 서버에서

 없어지지 않는 이상 그 서버를 사용하는 사용자들은 특정 페이지에 지속적으로 접근이 되게 되는 것 같내요.

 꽤 여러 종류가 존재하는 듯하고 기본적인 개념만 이해되고 아직은 정확한 개념을 잡질 못하겠내요

 문제를 풀어보면서 또 알아봐야겠내요.

이제 어느 정도 첫 스테이지의 의도가 파악이 되는 것 같내요

입력 값을 통해 CR과 LF를 이용해서 정상적인 http response 값을 두 개 이상 받아오게 하면 성공하지 않을까 싶습니다.

일단 정상적인 응답일 때 http 200 OK가 어떻게 생긴지 보면

HTTP/1.1 200 OK

이렇게 생겼다고 합니다. 문제를 대충 해석한거긴 하지만 문제에선 그저 이 메시지만 보내면 된다고 하니 그냥 바로 보내봤습니다.

 

 

역시나 아무런 반응이 없내요

아무래도 문제에서 알려주는 CR과 LF를 사용해야 할 듯한데 CR과 LF의 아주아주 대략적인 개념은 이렇습니다.

CR(Carriage Return) : 커서를 커서가 있는 행의 제일 앞으로 당긴다.

LF(Line-Feed) : 커서를 커서가 있는 행의 아랫줄로 옮긴다.

둘의 기능을 합치면 우리가 흔히 알고 있는 New Line(아마도 개행?)이라는 기능이 된다고 합니다.

뉴라인에 대한 표기가 OS별로 다르다고 하는데요 흔히 쓰는 Windows는 CR+LF를 사용하고

Like Unix 같은 경우는 LF만 사용해도 된다고 합니다. Mac의 경우에는 CR만 사용해도 되구요.

간추려서 써놨지만 이 내용을 좀 더 자세히 알고 싶으신 분은 https://kldp.org/node/46637 이 곳을 참고하시면 되겠습니다 ~

 

그럼 다시 스테이지로 돌아와서 CR과 LF를 포함시켜 입력을 해보겠습니다.

윈도우 환경이기 때문에 CRLF를 사용해야겠내요. 그렇다고 그냥 입력창에 CRLF를 입력하게 되면 아무일도 일어나지 않습니다.

이런 특수한 값을 웹 입력창에 넣으려면 아무래도 특수한 기호가 있어야겠내요

다행이 문제에 친절하게 그 값이 뭔지 알려주고 있습니다. CR은 %0d이고 LF는 %0a라고 써있내요

실제로 이 값들은 암복호화 사이트나 툴에서 그냥 엔터를 치고 urlencode해보면 나오는 값입니다.

근데 툴 마다 다른건지 모르겠지만 CR값을 좀처럼 구할 수는 없겠더라구요..보통은 LF로만 인식이 되는듯 합니다.

정말 값을 찾고 싶은데 잘 모르겠다 하시면 url인코딩이 아마 ASCII와 비슷한걸로 알고 있습니다.. 참고하시면 될듯 하내요

 

이제 CRLF의 암호화 값을 HTTP/1.1 200 OK와 같이 입력해보겠습니다.

 

%0d%0aHTTP/1.1 200 OK

라고 입력하고 Search!를 눌러줍니다.

 

그러면 위 사진같이 잘했다고 성공적인 공격이었다고 칭찬해줍니다.

스테이지1은 풀렸지만 단순히 CRLF만 추가해줬을 뿐인데 왜 클리어가 된건지 알아봤습니다.

 

이 스테이지의 기능을 간단히 보면 Search! 버튼을 눌렀을 때 입력칸에 있는 값을 redirect 시키는 기능이 있습니다.

.....음 테스트하는 도중에 알게 된건데 특별히 HTTP/1.1 200 OK라는 값을 안줘도 위 메시지가 나오내요..

이번 웹고트 버전 문제인지는 모르겠는데 CRLF가 있고 아무값이나 입력해도 스테이지1은 성공으로 인식을 합니다..
(현재 사용중인 웹 고트 버전은 5.4 버전입니다.)

어쨌든 Search!를 눌렀을 때 요청하는 http header와 응답받는 http header를 봐보겠습니다.

 

먼저 http request 값입니다.

Paros로 본거구요. 깜빡하고 아래부분을 안찍었는데 아래부분에는

 

language=%250d%250aHTTP%2F1.1+200+OK&SUBMIT=Search%21

라는 값이 보내지고 있습니다. 보면 아무래도 입력칸에서 입력받은 값은 language라는 값으로 보내지는 것 같내요

%250d와 %250a는 CRLF가 두 번 urlencoding 된 값입니다. 그 외 깨진거 같은 값들도 다 urlencoding 된 값이구요.

그리고 아래 사진에 보이는 값들을 보면..여러 정보들이 헤더를 통해 전달되는 걸 알 수가 있습니다.

포스팅하면서 필요한 부분만 빼고 헤더 값에 대한 자세한 내용은 따로 적지 않겠습니다. 검색하면 수두룩하게 나오는 내용이니..

 

다음은 http response 값입니다.

일단은 다른값들은 다 모른척하고 Location 값만 보겠습니다.

이동되는 주소를 보면 http request 때 보내졌던 값을 포함한 URL로 지정되어있습니다.

인코딩 되었던 값들이 다시 처음 입력했던 값으로 돌아온 걸 볼 수 있는데요

이 때 서버는 %0d%0a를 인식하게 됩니다.

그렇게 되면 아마 서버는 아래사진처럼 인식을 하게 될 겁니다.

이렇게 인식을 하게 되면 서버단에서는 HTTP/1.1 302와 HTTP/1.1 200 OK 두 값을 모두 정상적인 값으로 인식하고

클라이언트단에 응답값을 보내게 됩니다. 지금은 단순히 HTTP/1.1 200 OK라는 값만 보냈지만

몇 가지 헤더값을 추가하고 보내게 되면 해당페이지에 공격자가 원하는 내용을 출력시킬 수 있게됩니다.

다른 블로그를 보면 여러 답안들이 나오는데 그 답안들을 참고해서 설명을 조금 써볼게요

(출처 : http://getroot.tistory.com/14)

 

HTTP/1.1 302 Moved Temporarily

Date: Wed, 24 Dec 2003 15:26:41 GMT

Location: http:// victim.com /by_lang.jsp?lang=foobar

Content-Length: 0

 

HTTP/1.1 200 OK

Content-Type: text/html

Content-Length: 19

<html>Getroot</html>

기본적으로 php에서든 jsp에서든 redirect를 사용하면 HTTP 응답 코드를 301 혹은 302로 응답하게 됩니다.

그러니까 위 헤더 정보들은 소스상에서 redirect를 만난 후 서버가 보내준 http response 값이 되겠내요

Date는 뭐 그냥 시간이니 일단은 넘어가겠습니다.

그리고 Location.. 아까 파로스로 캡쳐한 사진에서 설명한 부분입니다.

사용자가 입력한 값이 소스코드 내용에 의해서 URL과 합쳐지고 그 합쳐진 URL이 써있는 부분입니다.

Location 바로 밑에 Content-Length라는 헤더 값이 있는대요

이 부분부터가 공격자가 악의적으로 입력한 값들입니다.

그러니까 최초 입력값을 넣을 때 foobar 뒤에는 %0d%0a가 있었던 것입니다.

여기서 궁금한게 Content-Length가 어떤 역할을 하길래 공격 코드에 등장한 걸까 하는 점이었습니다.

검색해보니 대략적으로 Content-Length라는 값에 의미는

HTTP Header 뒤에 오는 값의 크기(byte)라고 합니다.

그러니까 위 코드에서 보면 Content-Length: 0 이 의미하는 건 더 이상 출력할 내용이 없다. 정도 되겠내요

그 후 서버단은 아무것도 출력을 안하는 걸로 인식을 하고 있다가 HTTP/1.1 200 OK 라는 값을 만나고 당연히 그 값을 정상적으로 인식을 하게 됩니다.

그러면 이 때 부터는 공격자가 원하는데로 출력할 수 있는 권한을 갖게 되는거구요

위 코드에서는 단순히 'Getroot'라는 단어를 출력하는걸로 끝이지만 충분히 Getroot가 아닌 다른 악의적인 내용을 넣을 수도 있습니다.

웹고트의 문제인건지 모르겠으나 저는 저 코드뿐만아니라 검색해서 나오는 대부분의 답을 그대로 사용해보아도

Getroot 화면이 따로 뜨진 않더라구요.. PC문제인건지 웹고트 자체 문제인건지는 모르겠내요..

 

어쨌든 이렇게만 하면 단순한 http Splitting 공격을 성공하고 스테이지2가 열립니다.

 

대략적으로 메시지를 보면 ..

HTTP Splitting은 성공했고 .. 이제 공격대상 캐시를 감염시켜라라는 거 같내요

그 뒤 내용은 얼추 해석은 되는데 여기에 쓰자니 부끄러워 안쓰겠습니다........

 

어쨋든 스테이지2인 cache poisoning 공격을 성공해 클리어 하려면 Http splitting 공격으로 위조된 페이지가 기존에 저장되어

있던 캐시의 수정날짜 보다 이후여야하고 현재 시간보다도 미래의 날짜여야 합니다.

기존 캐시의 수정날짜를 알아내려면 Paros나 Webscarab 같은 툴을 사용해서 HTTP Header 값 중에

if-modified-since 라는 값을 찾으면 됩니다.

하지만 해당 문제를 그냥 해결하는게 목적이라면 굳이 그 시간을 알아내지 않아도 됩니다.

그냥 현재 시간보다 미래의 시간을 사용하면 되니까요..

if-modified-since 값이나 그냥 먼 미래의 시간을 이용해서 캐시 감염 공격을 하는 방법은 생각보다 간단했습니다.

우선 if-modified-since의 값을 찾아내보면 이런식으로 작성이 되어있습니다.

Fri, 12 Apr 2014 02:56:30 GMT

이 형식을 유지해야 정상적으로 인식이 되고 응답을 하게 됩니다.

그럼 이 값을 어떻게 이용하느냐는 아까 Http Splitting을 할 때 입력했던 값들 사이에 같이 넣고 URL인코딩을 해주면 됩니다.

단, 이름은 if-modified-since가 아니라 Last-Modified 로 입력을 해주면 됩니다.

 

foobar

Content-Length: 0

 

HTTP/1.1 200 OK

Content-Type: text/html

Last-Modified: Fri, 12 Apr 2099 02:56:30 GMT

Content-Length: 19

<html>Getroot</html>

 

날짜를 빨간 부분처럼 먼 미래로 설정하시면 됩니다.

위 값들을 그냥 URL 인코딩을 하게 되면 일반적으로 CRLF가 아닌 그냥 LF로만 인코딩이 되서 %0d%0a가 아닌 %0a로만 나옵니다.

 

foobar%0AContent-Length%3A+0%0A%0A%0AHTTP%2F1.1+200+OK%0AContent-Type%3A+text%2Fhtml%0ALast-Modified%3A+Fri%2C+12+Apr+2099+02%3A56%3A30+GMT%0AContent-Length%3A+19%0A%3Chtml%3EGetroot%3C%2Fhtml%3E

 

이 %0a를 메모장이나 다른 편집기들을 사용해서 %0d%0a로 변환해줍니다.

그러면 최종적으로 입력해야할 값이 나오게됩니다.

 

foobar%0d%0aContent-Length%3A+0%0d%0a%0d%0a%0d%0aHTTP%2F1.1+200+OK%0d%0aContent-Type%3A+text%2Fhtml%0d%0aLast-Modified%3A+Fri%2C+12+Apr+2099+02%3A56%3A30+GMT%0d%0aContent-Length%3A+19%0d%0a%3Chtml%3EGetroot%3C%2Fhtml%3E

 

이제 이 값을 스테이지2의 입력칸에 넣어주고 Search! 버튼을 눌러주면 이번 문제는 모두 해결이 됩니다.

 

 

이 한 문제 해결하고 일하면서 틈틈히 잘 모르는 내용들 하나하나 찾아보면서 하니 거의 이틀이라는 시간이 지났내요..

알고나면 생각보다 간단하고 쉬운 내용들인데 하나하나 찾아가면서 이해하고 풀어보고 하니 시간이 상당히 걸리내요

모르는 내용이 상당히 많았고 .. 잘못된 내용을 적으면 안되기에 이리저리 검색도 많이해보면서 했지만 중간중간 이상하게 설명된 부분이 있을 것 같내요

특히나 cache poisoning 부분은 글을 보면 알겠지만 내용이 많이 없습니다..

틀린부분이나 수정해야할 부분이 있다거나 추가되야할 내용이 있는거 같다 싶으시면 댓글 달아주세요 !

 

다음 문제는 언제 풀고 언제 글을 쓸지 ..

 

 

+ Recent posts