2021. 8. 23. 23:41ㆍLayer7/Layer7_Web Hacking
SSRF
우리가 보내는 요청을 서버에서 특정 IP에서만 접속이 가능하도록 IP 필터링하여 지정된 페이지에 서버에서만 접근할 수 있도록 제한할 수 있다.
이때 IP를 우회하여 요청을 보내는 기법이 Server Side Request Forgery (SSRF) 취약점이다.
우리가 서버에게 요청을 보내게 되는데, 그 요청에서 서버가 다른 내부 서버 내의 파일이나 데이터를 가져오는 등 내부 서버를 이용한다.
즉, 조직 내부적으로 사용하는 서버의 경우 보안상의 이유로 IP 필터링과 같이 외부에서의 접근을 막아놓는 경우가 많다. 일반 사용자는 웹 서버에만 접근이 허용되는 경우가 많다.
정상적인 경우에는 Internal Server에 요청을 못 보내지만, 내부 서버에 접속이 가능한 웹 서버를 이용할 수 있다.
일반 사용자가 웹 서버에 악성 요청을 보내면 웹 서버가 Internal Server에 요청하게 되어 요청이 실행되고 그 결과를 웹 서버가 우리 눈으로 볼 수 있게 돌려준다.
다시 말해, 원래 일반 사용자가 접속이 불가능한 Internal Server에 일반 사용자 대신 웹 서버가 요청을 한다. 그리고 그 결과를 다시 사용자에게 돌려주는 취약점이다.
일반적인 경우에는 Internal Server에 웹 서버에서 요청을 하기 때문에 웹 서버의 IP를 신뢰할 수 있는 IP라고 허용하는 경우가 많은데, SSRF를 이용하여 우리 대신 웹 서버가 요청을 해준다면 아무런 인증 없이도 내부 서버에 접속이 가능하다는 것이다.
Dreamhack - SSRF
웹 서버 안에서 127.0.0.1에서 내부 서버가 열리는 것을 볼 수 있다.
포트 번호는 1500번과 1800번 사이에 랜덤 값이므로 브루트 포싱해야 한다.
url 파라미터는 가져올 이미지의 주소이므로, 플래그의 주소를 넣으면 플래그를 내부 서버에서 가져올 것이다.
소스 코드는 위와 같이 작성했다.
위와 같이 localhost와 127.0.0.1을 필터링하고 있기 때문에 내부 서버에 요청을 보내려면 IP 주소 난독화를 해야 한다.
2130706433은 127.0.0.1와 같은 의미로, 대신 사용하면 필터링을 우회할 수 있다.
1717번 포트에 내부 서버가 열린 것을 알 수 있다.
Image viewer에 요청을 할 때 url 파라미터를 내부 서버의 IP와 포트로 수정한다.
이때 화면에 깨진 이미지가 표시된다.
우클릭해서 열면 주소창에 Base64로 적힌 것을 발견할 수 있다.
이를 디코딩하면 다음과 같이 나온다:
서버의 디렉토리가 표시되었다. / 바로 밑에 flag.txt가 있는 것을 볼 수 있다.
url을 위와 같이 flag.txt로 고쳤다.
또다시 깨진 이미지를 확인해 보고, 적혀 있던 Base64를 디코딩하여 flag.txt의 내용을 얻을 수 있었다.
Webhacking.kr - 52
내부 서버에 웹 서버의 IP 만으로 접속을 할 수 있으므로 웹 서버에 있는 proxy라는 페이지를 이용하여 간접적으로 admin page에 접속해야 한다.
proxy 페이지는 이와 같이 page 파라미터로 넘겨준 페이지에 요청을 보내며 결과를 출력해 준다.
admin으로써 로그인을 해야 하는데, 소스 코드를 보니 SQL 인젝션이 가능하다.
admin'#와 같이 입력하고 비밀번호에 아무 값을 넣으면 admin으로써 로그인이 된다.
그러나 IP 주소가 필터링되어 위와 같이 뜬다.
로그인을 할 때 요청을 보면 Authorization라는 헤더가 있는데, Base64로 인코딩 된 내용을 보면 이는 로그인했을 때의 ID와 패스워드를 :으로 구분한 값이다.
HTTP Request Smuggling
proxy 페이지를 통해 admin으로 로그인을 해야 IP 필터링을 우회하여 admin으로서 로그인에 성공할 수 있는데,
proxy 페이지에서 /admin에 SQL 인젝션 한 값으로 로그인을 하는 요청을 보내야 한다.
이때 이용하는 것이 HTTP Request Smuggling 취약점인데, 이는 HTTP 요청에 또 다른 요청을 심어놓아 실행하는 것이다.
즉, 우리는 지금 proxy 페이지를 통해 /admin에 접속할 수 있는데, 이때 로그인 정보를 넘겨주어 admin으로 로그인하는 요청을 보내야 하는 것이다.
GET /proxy.php?page=/ HTTP/1.1
Host: webhacking.kr:10008
Cookie: PHPSESSID=kfigo8tj13jaju1sbjbug8vcdv
요청이 위와 같이 보내질 때, 우리는 일단 ?page= 부분을 조작해서 /가 아니라 /admin을 요청하도록 한다.
다만, /admin으로 바꾸면 로그인 정보를 보내지 않아 로그인을 할 수 없다.
따라서 로그인 정보(ID와 패스워드)는 Authorization 헤더를 통해 넘어가므로 다음과 같이 새로운 요청을 작성한다.
admin/ HTTP/1.1
Authorization: Basic YWRtaW4nIzoxMTEx (SQL 인젝션 구문인 admin'#:123를 Base64로 인코딩한 값)
Cookie: PHPSESSID=kfigo8tj13jaju1sbjbug8vcdv
asd:
위와 같은 내용이 원래 요청에 들어가면 다음과 같이 한 요청이 되어버린다:
GET /proxy.php?page=/admin/ HTTP/1.1
Authorization: Basic YWRtaW4nIzoxMTEx
Cookie: PHPSESSID=kfigo8tj13jaju1sbjbug8vcdv
asd: HTTP/1.1
Host: webhacking.kr:10008
Cookie: PHPSESSID=kfigo8tj13jaju1sbjbug8vcdv
이때 page로는 admin을 요청하고, Authorization, Cookie 헤더에 로그인에 꼭 필요한 데이터를 주고, asd:로 새로운 헤더를 생성하여 원래 존재했던 HTTP/1.1을 무력화한다.
다만 이를 보내려면 URL 인코딩을 해야 한다.
줄 바꿈은 %0d만으로는 안 되고 %0d%0a를 해야 줄 바꿈으로 인식하므로 주의한다.
페이로드
/admin/%20HTTP/1.1%0d%0aAuthorization:%20Basic%20YWRtaW4nIzoxMTEx%0d%0aCookie:%20PHPSESSID=kfigo8tj13jaju1sbjbug8vcdv%0d%0aasd:%20/
위와 같이 보내면 admin으로 로그인된 상태에서 내부 서버에 웹 서버의 IP 주소로 요청을 보내게 되어 플래그를 얻을 수 있다.
메인 사진 출처: Unsplash
© 남찬우, 2021
'Layer7 > Layer7_Web Hacking' 카테고리의 다른 글
SQL Injection II (0) | 2021.08.29 |
---|---|
JavaScript, PHP (0) | 2021.08.27 |
SQL Injection (0) | 2021.08.18 |
XSS, CSRF, Command Injection (0) | 2021.08.11 |
Proxy, Cookie (0) | 2021.08.09 |