반응형

문제 링크

https://portswigger.net/web-security/ssrf/lab-ssrf-with-whitelist-filter

 

 

목표 & 사용 도구

목표: admin 인터페이스에 접근하여 carlos 계정을 삭제하는 것입니다.

 

사용도구: Burp Suite

 

 

사전 지식

[URL 파싱에서의 @ 기호]
@기호는 사용자의 정보와 실제 접속할 호스트를 구분하는 기호로 사용됩니다.예를들어 https://user:pw@test.com/mypage URL 파싱할때 user:pw는 인증 정보, 즉 자격증명에 사용되고 실제로 접속하는 웹 사이트는 test.com 이 됩니다. 이런식으로 사용되는 @ 기호의 경우 현재는 거의 사용되지 않고 문법만 남아있는 상태라고 합니다.

[URL 파싱에서의 #(Fragment) 기호]
URL 파싱에서 # 기호는 웹 문서의 내부의 특정 섹션이나 리소스를 가리킬 때 사용하는 기호 입니다. 웹 브라우저가 서버에 요청을 보낼  때 # 기호 뒤의 값들은 요청에 포함되지 않고 클라이언트 측에서 처리됩니다. 

 

 

문제 설명

해당 랩을 해결하기 위해서는 check stock URL을 admin 인터페이스로 바꿔 접근한 뒤 carlos 계정을 삭제해야 한다고 합니다. 하지만 개발자가 SSRF 방어 로직을 사용 중이라고 하며 우회할 필요가 있다고 합니다.

 

 

문제 풀이

  • ACCESS THE LAB을 클릭하여 랩에 접속합니다.

 

  • 웹 사이트에 접속한 뒤 게시물 중 하나를 택해서 View details를 클릭하여 게시물로 이동합니다.

 

  • Check stock 버튼을 클릭합니다.

 

  • Check stock 버튼을 클릭했을 때의 요청을 Burp Suite의 Repeater 기능에 세팅합니다.

 

  • 세팅한 요청을 전송해 보면 아래와 같이 재고 결과가 나오는 것을 확인할 수 있습니다.

 

  • stockApi 파라미터 값을 admin 인터페이스 주소로 바꾸고 요청을 보내면 호스트가 stock.weliketoshop.net 이어야 한다는 응답 메시지를 반환하며 필터링이 되고 있는 것을 알 수 있습니다. 

 

  • @ 기호를 사용할 수 있는지 확인하기 위해서 해당 기호를 사용합니다. 서버가 stock.weliketoshop.net에 접근하게 만들고 접근 불가능 응답이 반환되지 않으며 @ 기호를 사용할 수 있다는 것을 알 수 있습니다.

[페이로드]
stockApi=http://localhost@stock.weliketoshop.net:8080/admin

[설명]
@ 기호는 사용자 정보와 실제 접속할 호스트를 나눈다고 설명했었습니다. 따라서 stockApi 파라미터에 페이로드를 삽입하게 되면 서버는 호스트를 stock.weliketoshop.net으로 인식하게 됩니다.

페이로드를 분석해 보면 http://localhost@stock.weliketoshop.net:8080/admin중 localhost@stock.weliketoshop.net 부분에서 localhost가 자격 증명에 사용되는 인증 정보가 되고 호스트가 stock.weliketoshop.net이 됩니다. 응답을 보면 알 수 있듯이 호스트가  stock.weliketoshop.net이기 때문에 접근이 불가능한 응답 메시지를 반환하지 않고 있는 것을 볼 수 있습니다.
(missing parameter 메시지의 경우 stock.weliketoshop.net:8080으로 요청을 보냈을때 파라미터가 없으면 반환하는 메시지 입니다.)

 

  • 이번엔 @ 기호 앞에 # 기호를 삽입했을 때 응답을 보면 호스트를 stock.weliketoshop.net으로 인식하지 못해 필터링에 걸리게 되는 것을 볼 수 있습니다.

[설명]
stockApi 파라미터 값을 URL 파싱 하는 과정에서 # 기호 뒤에 값이 Fragment로 처리되고 있기 때문에 호스트를 stock.weliketoshop.net으로 인식하지 못하는 것입니다.

 

  • 이전 단계의 페이로드에서 @기호 앞에 # 기호를 이중 인코딩한 값을 삽입하고 요청을 전송하면 필터링을 우회하여 admin 인터페이스에 접근이 가능하게 됩니다.

[페이로드]
http://localhost%25%32%33@stock.weliketoshop.net:8080/admin

[설명]
# 기호를 이중 인코딩 하지 않은 페이로드인 
http://localhost#@stock.weliketoshop.net:8080/admin 
을 사용하여 요청을 전송하게 되면 # 기호 뒤의 값들은 stockApi 파라미터 값을 URL 파싱 하는 과정에서 Fragment 처리가 되어 서버로 전송되지 않기 때문에 호스트가 stock.weliketoshop.net로 인식되지 않아 필터링에 걸리게 됩니다.

하지만 # 기호를 이중 인코딩을 하고 요청을 보내면 form 데이터를 처리하는 과정에서 %25%32%33을 디코딩 하게 되고 서버가 입력 값을 검증할 때 비교하는 값은 
http://localhost%23@stock.weliketoshop.net:8080/admin 
이 됩니다. 즉 %23은 # 기호가 아닌 그냥 문자열 취급을 받기 때문에 %23뒤에는 Fragment 처리가 되지 않습니다. 이 과정에서 @ 기호를 기준으로 앞부분은 사용자 인증 정보 뒷부분은 실제 접속 호스트로 해석하게 됩니다.

서버는 @ 기호로 인해 호스트가 stock.weliketoshop.net인 것으로 확인했기 때문에 필터링 검사를 통과시키게 됩니다. 이때 또 중요한 점이 있는데 서버가 stockApi 파라미터 값을 받아서 실제 요청을 전송할 때 URL이 디코딩 되어 %23이 한번 더 디코딩 되고 # 기호로 해석되는 것으로 보인다는 점입니다.

정리하면 stockApi 값 검사 과정에서 호스트가 stock.weliketoshop.net으로 해석되어 필터링을 통과하고 실제 요청을 하는 과정에서 %23이 한 번 더 디코딩 되어 # 기호처럼 해석됩니다. 이 경우 http://localhost#@stock.weliketoshop.net:8080/admin 이 되고 # 기호 뒤에는 Fragment 처리가 되어 localhost의 admin 인터페이스에 접근이 가능해집니다. 따라서 외부에서 접근이 불가능한 내부 주소를 서버가 대신 요청하여 접근을 가능하게 했으므로 SSRF 취약점이 존재한다는 것을 알 수 있습니다.

 

  • 응답에서 Raw를 클릭하고 carlos 계정 삭제 버튼을 찾은 뒤 해당 URL을 복사합니다.

 

  • stockApi 파라미터에 복사했던 carlos 계정 삭제 URL을 admin 인터페이스 경로에 추가하여 요청을 전송합니다. 

 

  • 이전 과정을 끝내고 웹 사이트로 돌아가 보면 문제가 클리어 된 것을 볼 수 있습니다.

 

  • admin 인터페이스에 다시 접속해 보면 실제로 carlos의 계정이 삭제된 것을 볼 수 있습니다.

반응형

+ Recent posts