[PortSwigger] Server-side request forgery (SSRF)

Lab: Basic SSRF against the local server

Server-side request forgery의 첫 문제이다. 간단히 말하자면 내가 원하는 대로 server가 제 3자에게 request를 보내도록 조작하는 것이다.

 

이번 문제에서는 온라인 쇼핑몰이 있고, 재고를 조회할 수 있는 기능이 있다고 한다. 재고를 조회하기 위해서는 서버에서 외부 api와 연결해야 한다. 이때 외부 api와 연결하기 위해 보내는 POST request에서 api의 url을 내가 원하는 url로 변경시켜서 결과적으로는 서버가 다른 url에 연결하도록 만들면 된다. carlos를 지워야 한다!

첫 화면이다. 일반적인 온라인 쇼핑몰과 같은 모습이다.

상품 설명이 있고 아래에 재고를 조회할 수 잇는 버튼이 존재한다.

조회 버튼을 눌러서 burp suite로 POST 요청을 확인했다. Request의 아래 부분에 있는 stockApi를 조작하면 될 것 같다.

먼저 stockApi를 http://localhost/admin으로 바꿨다. 성공적으로 접속했다!

Response에서 user를 삭제하는 url을 확인할 수 있었다.

stockApi를 http://localhost/admin/delete?username=carlos로 바꿨다. 성공적으로 삭제했다.

flag를 찾고 있었는데 삭제했더니 바로 풀렸다..? SSRF를 시작하는 간단한 문제였다~

 

 

Lab: Basic SSRF against another back-end system

이번 문제는 저번 문제와 비슷하지만 다른 백엔드 시스템에 request를 전달해야 한다. 따라서 ip가 localhost가 아니라 192.168.0.X 형태이고, X를 알아내야 하는 추가적인 일이 생겼다.

아까와 같이 재고 파악하는 POST 요청을 가져왔다.

재고 파악하는 요청에서는 192.168.0.1로 보낸 것을 확인할 수 있었다.

실제로 X를 1로 맞췄을 때만 정상적으로 response가 왔고, 나머지는 다 에러가 발생했다.

이번에는 admin 페이지를 접속하기 위한 ip 주소를 알아내보자. 이를 위한 url은 http://192.168.0.X:8080/admin이 된다.

브포를 돌려주니 X가 84일 때 admin 페이지에 접속할 수 있었다!

따라서 http://192.168.0.84:8080/admin/delete?username=carlos를 보내줬다.

성공~

 

Lab: SSRF with blacklist-based input filter

이전 문제들과 비슷하다! 그런데 이번엔 몇가지 필터링이 적용된 듯하다.

 

문제 설명에 따르자면 localhost, 127.0.0.1, /admin 등이 막힌다고 한다.

http://localhost/admin

POST 요청을 얻어내기 까지는 이전과 동일하게 진행했다. 가장 먼저 기본적으로 localhost/admin 으로 보내봤는데 당연히 막혔다.

http://127.0.0.1/admin

127.0.0.1/admin 역시 막혔다!

http://127.1/admin

127.0.0.1이나 127.1이나 ping으로 확인해봤을 때 동일한 걸 확인했다. 그런데도 막히고 있다.. admin 부분까지 바꿔줘야 할 듯하다.

http://127.1/%61%64%6d%69%6e

admin을 url encoding으로 %61%64%6d%69%6e으로 바꿔서 넣어줬다! 그런데도 막히고 있다..!!

그래서 마지막으로 %61%64%6d%69%6e을 한번 더 url encoding하여 %25%36%31%25%36%34%25%36%64%25%36%39%25%36%65로 만들었다. 그랬더니 필터링을 통과해서 admin 페이지를 불러올 수 있었다!

내가 보낸 url이 변환되는 과정은 위와 같다.

이전 문제들과 동일하게 delete?username=carlos를 추가해서 user를 삭제해줬다.

성공~

 

Lab: SSRF with whitelist-based input filter

이번엔 withelist 필터링이다. 즉 특정 키워드가 들어가야 한다는 것이다.

localhost/admin

그냥 해봤더니 stock.weliketoshop.net이 들어가야 한다고 한다!

위의 블로그에서 URL parsing에 대해 알아봤다.

이를 참고해서 host명에 localhost와 stock.weliketoshop.net을 @로 묶어서 써줬다.

localhost@stock.weliketoshop.net

그랬더니 일단 필터링은 통과하는 것을 확인할 수 있었다! 그런데 우리가 원하는 것은 localhost만이 host명이 되는 것이다.

localhost#@stock.weliketoshop.net

따라서 #으로 뒤에는 주석처럼 처리하려고 했는데, 그랬더니 또 해당 호스트가 포함되어야 한다고 한다.

localhost%23@stock.weliketoshop.net

#을 url encoding해서 %23으로 해도 마찬가지다..

localhost%2523@stock.weliketoshop.net

아까 admin도 두번 encoding 해줬듯이, 이번에 #도 double url encoding으로 %2523으로 만들어줬다. 그랬더니 필터링도 통과하면서 localhost만을 host로 보았다!

http%3A%2F%2Flocalhost%2523%40stock.weliketoshop.net%2Fadmin%2Fdelete%3Fusername%3Dcarlos

결국 admin으로 들어가 carlos를 없애도록 했다.

http://localhost#@stock.weliketoshop.net/admin/delete?username=carlos

성공~ 이번 문제는 url parsing에 대해서 다시 한번 짚고 넘어가면서 double encoding, 호스트 명에서 @, # 등의 역할에 대해 알 수 있었던 좋은 문제였다.

 

Lab: SSRF with filter bypass via open redirection vulnerability

이번에는 리다이렉트 시키는 기능을 통해 공격해보고자 한다.

check stock 아래 부분에 Next product 버튼이 보인다.

클릭해서 Request를 봤더니 nextProduct에 인자로 path가 들어간다. 이때 여기에 path로 다음 상품이 아닌 admin 페이지로 리다이렉트하게끔 만들면 된다!

Requset는 check stock 시의 POST requset를 가져왔다. 보다시피 호스트명이 고정되어 있기에 리다이렉트 할 수 있도록 nextProduct의 path에 admin 페이지를 넣어줘야 한다.

지우기 성공!

간단한 문제였다.

 

 

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤