Web Cache Poisoning Attack, 다시 재조명 받다(with Header base XSS)

Cache Posoning Attack은 꾀나 전통적인? 공격 방법입니다. Cache에 공격자가 의도한 데이터를 남겨 다른 사용자로 하여금 비정상적인 요청을 수행하게 하죠. (대표적으로 DNS Cache Poisoning)

Web에서도 Cache를 사용하는데요, 관련해서 올 8월에 PortSwigger 팀에서 관련해서 글(https://portswigger.net/kb/papers/7q1e9u9a/web-cache-poisoning.pdf )을 게시했었고, 지인에게 내용 공유받아 정리해봅니다.

Web Cache?

캐싱은 서비스 속도 향상을 위해서 데이터를 미리 저장해두고, 사용자에게 제공하는 형태입니다. 지금 이야기드릴 웹 서버의 캐시 말고도 우리가 사용하는 브라우저에도 캐시가 적용되고 웹 데이터를 빠르게 로드하기 위해 로컬 피씨에 이미지나, 자바스크립트 등의 데이터를 저장하고 있습니다. 사용자는 웹 페이지 접근 시 인터넷을 통해 이미지를 받아오는게 아닌, 로컬에서 이미지를 가져오기 때문에 속도면에서 굉장히 이득이 되죠.

이런 캐시는 한번 내용이 저장되면 캐시를 무시하는 액션을 받지 않는 이상 저장된 데이터를 사용자에게 제공합니다. 웹 서버의 캐시 또한 데이터를 캐싱하고 사용자에게 빠르게 제공하는데 의미가 있습니다.

대표적으로 CDN(Content Delivery Network) 서비스들이 있고 이들은 이미지나 일부 코드를 저장하고 사용자에게 빠르게 제공해줍니다.

웹 서버들은 어떤 요청에서 캐시되고 어떤 데이터를 제공해줄지 기록하는데, 이 때 요청을 식별하는(캐시를 불러와야할 요청인지?) 값이 Cache Key 입니다. 캐시 키 는 웹 요청에서 일부를 떼어내어서 Request 일부와 이에 상응하는 Response를 저장하는데요, Request의 모든 부분을 확인하지는 않습니다.

보통 Path, Host 정도를 신뢰하기 때문에 페이지에 테스틀 위해 반복적으로 붙을 때 헤더를 붙여주거나 Path를 바꿔가며 테스트하죠(의미없는 파라미터 추가 ㅋㅋ)

GET /test HTTP/1.1
Host www.hahwul.com
Cooki: test=1

Attack Point, How to Test?

캐시나 포이즈닝 공격 모두 자료가 많아서 구글링 좀 해보시면 많은 자료가 있습니다. 또한 웹 공격, 네트워크 공격에서 자주 소개되는 내용이라 익숙하실텐데요, 말 그대로 캐시에 악의적인 데이터를 남겨서 다른 사용자가 의도하지 않은 동작을 하도록 캐시를 오염?? 시키는 공격입니다.

구글링하면 좋은 그림 많이 나오니 대충 보고 지나갑시다.

테스트 방법을 좀 정리해보는데 이정도 순서로 테스트하면 어떨가 합니다.

1. Cache Key로 사용되지 않는 헤더, 파라미터 등 데이터 식별
2. 해당 값이 Response에 미치는 영향 체크
3. (영향을 끼치는 경우) 공격코드가 Response되도록 Cache 저장(단순히 해당 값에 공격코드를 넣고 요청 전달)

하나 예시로 살펴보면 PortSwigger 팀이 redhat쪽 리포팅했던 내용인데, Request

GET /en?cb=1 HTTP/1.1
Host: www.redhat.com
X-Forwarded-Host: canary

Response

HTTP/1.1 200 OK
Cache-Control: public, no-cache
…
<meta property="og:image" content="https:// canary /cms/social.png" />

요런식으로 og 태그의 데이터가 사용자 입력으로 부터 받아지는걸 체크했고, “> 같이 XSS 코드로 Reflected 시켜 XSS 취약점을 발생시켰습니다. 이럴 경우 일반 웹 페이지에서 해당 헤더 없이 페이지를 접근해도.. Request

GET /en?dontpoisoneveryone=1 HTTP/1.1
Host: www.redhat.com

Response

HTTP/1.1 200 OK
…
<meta property="og:image" content="https://a."><script>alert(1)</script>"/>

구문이 삽입됩니다.

Live service에 테스트하긴 위험하지 않을까?

우선은 위험한게 맞습니다. 다른 사용자에 대해서 로직을 틀어버릴 수 있는거라 실 서비스에선 테스트하지 않는 게 좋아보이긴합니다. 다만 아까 위에서 캐시의 규칙에 대해 잘 보셨다면 영향가지 않는선에서 테스트할 수 있는 방법이 있습니다.

기본적으로 캐싱은 Host, Path 데이터를 기준으로 키를 잡습니다. 그 이야기인 즉슨 Host, Path가 동일한 사용자에 대해서 영향이 가는것이기 떄문에 path에 일반 사용자가 접근하기 어려운 값들을 넣어서 테스트하는 분석가만 확인한다면 직접적인 영향은 없을 것 같습니다. (그래도 되도록이면 prod 환경은 제외하는데… 정신 건강에 좋을듯, 버그 바운티라면 뭐 어쩔 수 없고)

GET /test?thisiscachepoisoning HTTP/1.1
Host: www.hahwul.com
AttackVector: <svg/onload=alert(45)>

이런식으로 파라미터에 의미없는 값을 넣어주어, 정확하게 저 url을 사용하는 사용자 이외에는 캐시가 오염되지 않도록 해주면 크게 걱정없이 테스트가 가능할 것 같습니다.

How easy is it?

결국 위에서 이야기한 내용들을 테스트하려면 어마어마한 노가다 작업이 필요합니다. (Key에 포함되지 않고 Response를 제어하는 파라미터, 헤더 등 값을 찾아야함…) 그래서 PortSwigger 쪽은 Burp extension(Param minor)를 만들어서 테스트한 것 같고, 각자 테스트 환경에 Cache Key, Response 데이터 변조에 대해 테스트 가능한 환경이 있어야 편리할 것 같습니다. (이전에 Param minor가 새로 올라왔을 때 뭔가 했더니 이거였었군요..)

ZAP은.. 코드 완성도는 얼마나 될지 모르겠지만, 시간되면 가볍게 만들어서 공유드리겠습니다 : )

How to Protect? & Conclusion

Checked Header Base XSS & Other vulnerability point 이거 안하는 회사도? 은근 있을 것 같습니다만, 해주는게 좋습니다. Cache Poisoning 말고도 영향 있는 부분들이 있어서…

결국은 영향력이 발생하는 부분은 Header 데이터가 본문에 어떻게 삽입되느냐입니다. 분석을 하시는 기업보안담당자라면, 한번 더 생각해보는 계기가 되었으면 좋겠네요.

Use Vary Header Vary 헤더는 PC웹 환경과 모바일 웹 환경 구별을 위해 많이 사용하는 헤더인데요, Vary 헤더가 붙은 경웨 User-Agent까지 식별해서

Vary: User-Agent

이렇게 하면 User-Agent 헤더에 대해서도 검증하게 되죠. 자세한 내용은 모질라랑 구글쪽 문서 참고해주세요.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary https://developers.google.com/search/mobile-sites/mobile-seo/dynamic-serving?hl=ko

결국은 이 문제에 대한 근본적인 해결 방안은 자주 보안 테스팅을 하고 위협을 제거하는 것 같습니다. (그렇다고 캐시를 쓰지 말라고 하는건 좀 그렇잖아요) Header로 부터 오는 공격도 공격자가 아주 좋아할 먹잇감이니 신경써서 체크하면 좋을 것 같단 생각이 듭니다.

12월은 매우 정신 없던 달이였던 것 같습니다. 뭐 한것도 없느데 순식간에 마지막날이 되었네요.. 아마 시간을 보아하니 이글이 올해 마지막 글일 것 같습니다. 해피뉴이어!

Reference

https://portswigger.net/kb/papers/7q1e9u9a/web-cache-poisoning.pdf https://blog.cloudflare.com/cache-poisoning-protection/ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary https://developers.google.com/search/mobile-sites/mobile-seo/dynamic-serving?hl=ko https://blog.finjan.com/web-cache-poisoning/