Portswigger-Web cache poisoning to exploit a DOM vulnerability via a cache with strict cacheability criteria

problem link

풀이

웹 캐시 포이즈닝으로 익스플로잇 가능한 DOM-based 취약점이 있다. 유저가 약 1 분에 한 번씩 홈페이지를 방문한다. 캐시에는 캐시 가능한 응답을 결정하기 위해 엄격한 기준이 있으므로 캐시 동작을 자세히 연구해야 한다. 방문자의 브라우저에 alert(document.cookie)를 실행시켜라.

페이지에 접속하면 Free shipping to United Kingdom 라는 문구가 눈에 띈다. 위치를 이용해서 동적으로 문구를 생성할 것 같다. 내 IP는 UK가 아닌데 왜 이런 문구가 나왔는지 의문이 든다.

사용하는 자바스크립트를 보면 geolocate.js 파일이 있다. 이 코드가 Free shipping to United Kingdom 문구를 화면에 뿌리는 역할을 한다. 함수 인자로 받은 URL로 요청을 보내고, 여기서 위치 정보를 가져온다.

JSON 요청과 응답은 다음과 같다. {"country": "United Kingdom"} 에서 country에 XSS 페이로드를 넣으면, 위 코드에 의하면 별 필터링없이 실행될 것 같다.

어디서 initGeoLocate 함수를 호출하고, 어떤 인자를 넣는지 찾아보았다. HTML에 포함된 script에서 호출한다. 인자는 data.host를 이용한다. data.host의 /resources/json/geolocate.json 경로에서 데이터를 받아온다.

data.host란 무엇인가 찾아보면 동일 HTML의 위쪽에서 정의된다.

    data = {
        "host":"ac071f031fab5ebd80b46a2300f800c1.web-security-academy.net",
        "path":"/",
    }

host를 조작할 수 있는지 알고 싶다.

Param Miner를 이용하여 헤더를 찾아보니 x-forwarded-host 라는 숨겨진 헤더를 찾았다. 또한 이는 캐시 포이즈닝이 가능했다.

x-forwarded-host 헤더가 있을 때와 없을 때를 비교해보면, x-forwarded-host 의 내용이 host의 값으로 들어간다는 것을 알 수 있다.

x-forwarded-host 헤더를 조작하여 원래 위치 정보를 얻어오는 서버 대신 공격자의 서버에서 위치 정보를 가져오게 할 수 있다. 페이로드를 넣은 JSON을 주면 XSS 시킬 수 있겠다.

공격자 서버에서 페이로드를 넣은 json을 응답하도록 했다. Access-Control-Allow-Origin: * 를 넣어 CORS 문제가 없도록 하는 것에 주의한다.

하지만 XSS 페이로드가 잘 들어갔음에도 실행이 되지 않았다. 전부 렌더링이 된 후 나중에 데이터를 가져와서 그런가 script 태그 속 코드가 실행되지 않았다.

이는 DOM에 텍스트를 추가하기 위해 innerHTML을 이용하는데, 이 API로 끼워넣은 script 태그는 실행되지 않기 때문이다. innerHTML

img 태그를 이용하여 실행하는 방향으로 바꾸었다. XSS가 되는 것을 확인하였다.

캐시 버스터를 삭제하고 타겟을 공격하면 성공한다.

참고로 응답에 Set-Cookie 헤더가 있으면 캐시가 되지 않는다고 한다. 세션 쿠키가 이미 설정되어 있는 상태에서 캐시 포이즈닝을 해야한다.

이 취약점은 사용자가 조작할 수 있는 헤더를 그대로 믿고 사용해서 발생했다. 숨겨진 헤더지만 헤더 인젝션으로 찾아낼 수 있다는 점을 간과했다.


tags: writeup, web-cache-poisoning, xss, reflected xss, dom-based-xss, wstg-clnt-01, wstg-inpv-01, business-logic-vul, wstg-busl-02, host-header-injection, wstg-inpv-17, web hacking