Bypass host validation with Parameter Pollution

오늘은 host validation 로직 우회 때 사용했던 간단한 팁 하나 공유해봅니다. 뭐 누구나 아는 내용이라 별거 없긴 하지만, 기록으로 남겨두어야 나중에 한번에 관련 내용들을 정리할 때 쉽게 찾고 사용할 수 있어서 블로그 글로 작성해둡니다.

HTTP Parameter Pollution

HTTP Parameter Pollution은 보통 HPP로 줄여서 부르는데, URL이나 Form data 등에 동일한 이름의 파라미터를 복수로 삽입하여 보안적인 문제를 만드는 방법을 의미합니다.

정상 케이스

/search?queyr=abcd

HPP

/search?queyr=abcd&query=cccc

이러한 Pollution은 RFC에도 어떻게 처리해야하는지 기준도 없고, 서비스 어플리케이션 마다 처리하는 기준도 약간씩 다릅니다. 그렇지만 일반적인 Application 에선 아래와 같이 Array로 처리되는 경우가 많습니다.

[ req ]
/search?query=abcd&query=cccc
[ backend ]
queury = [abcd,cccc]

이를 통해서 보안 로직, 사용자 입력이 기대하는 값과 다른 값 / 포맷을 넣어줄 수 있게 되며, 이는 서비스 구성에 따라서 deserialize 취약점이나 IDOR 취약점으로 연결되는 경우가 많습니다.

OWASP-HPP

Bypassing!

어쨌던 오늘 HPP에 대해 자세히 다룰껀 아니니, 간단하게 이를 활용한 우회 패턴에 대해서만 작성해봅니다. 앞서 이야기드렸듯이 많은 어플리케이션들은 이를 array로 처리하는데, 서비스 앱이 여러가지 라이브러리나 여러 개발자가 공동 작업한 경우 이러한 충돌되는 값을 바라보고 처리하는 방식이 달라집니다.

많은 라이브러리들은 array 패턴을 각각 element 단위로 짤라서 검증 로직을 거치겠지만 이를 직접 사용(un-type lang에선 가능하니)하여 string 처럼 쓴다면 여러가지 보안 로직을 우회하는데 사용할 수 있게 됩니다.

예시를 하나 들어보면.. url 이란 파라미터에 대해 허용된 도메인인지 검증하는 로직이 있다고 합니다. 이 때 공격자가 url 파라미터를 아래와 같이 중복하여 2개 보내는 경우..

Request

/?url=https://trusted.domain&url=@untrusted.domain

백엔드에선 높은 확률로 array로 처리할겁니다. 만약 각각의 element를 검증하는 형태로 있다고 해도, 실제로 값을 쓰는 부분에서 하나의 string 처럼 쓰게 된다면 최종 url 파라미터의 값은 아래와 같이 콤마를 포함한 url 값이 될겁니다.

Backend

url: https://trusted.domain,@untrusted.domain

당연히… @ 앞부분은 어떤 특수문자도 허용할 수 있기 때문에 실제 host인 untrusted.domain을 바라보게 되어 공격자가 trusted.domain만 허용 가능한 페이지에 untrusted.domain을 삽입할 수 있는 결과가 발생합니다.

https://trusted.domain,@untrusted.domain => untrusted.domain

실제로 아래 URL을 브라우저로 접근하면 제 페이지가 나타나겠죠.

https://www.google.com,@www.hahwul.com --headers