CPDoS(Cache Poisoned Denial of Service) Attack for Korean

최근에 CPDos에 대한 이야기가 핫합니다. HTTP Desync Attack 때 이미 경험했던 부분이지만, 여러모로 이슈화 되다보니 일적으로나 개인적으로나 테스트를 좀(강제로..) 해보게 되었네요.

아무튼 오늘은 CPDoS에 대해서 간략하게 글로 남겨두려고 합니다. (알비노왁스가 페이팔에 이 취약점으로 제보했었는데, 관련 write-up 작성한다고 하니 올라오면 꼭 봐보시길 바래요!)

What is CPDoS?

웹 캐시 포이즈닝을 이용한 DoS 취약점으로 CDN 등에 존재하는 웹 리소스를 깨진 데이터로 캐싱시켜 다수의 사용자에게 서비스를 사용하지 못하도록 하는 공격 방법입니다. 보통 캐시 포이즈닝이나, 디싱크 어택 관련해서 테스트하다보면 이런 케이스가 있었는데, 이슈화 되고 이걸 취약점으로 인정해줄지는 몰랐었네요..

아무튼 알비노왁스는 이걸가지고 9600$를 받았으니 본격적으로 노려볼만 합니다. (저정도 금액은 페이팔이여서 준 것 같고, 다른 버그바운티 서비스는 별로 안줄 느낌이긴 합니다)

Web Cache Poisoning?

이전에 쓴 블로그 글이 하나 있습니다. 참고하시면 좋을 것 같고 간략하게 요약해서 작성해봅니다. CDN등 리소스를 처리하는 서버들은 효율성을 위해서 이미지나 자바스크립트 등을 캐시하고 본인의 서버에 가지고 있다가 사용자에게 빠르게 넘겨줍니다.

특정 헤더나 파라미터 값들을 이용해서 잘못된 데이터를 캐시 시키고, 이를 이용해서 XSS나 다른 취약점을 트리거 시키는데 사용될 수 있죠.

CPDoS1 - HHO(HTTP Header Oversize)

첫번째는 헤더를 Overwirte하는 방법입니다. 캐시되는 과정에서 일부 헤더를 통해서 의도하지 않은 액션을 유도할 수 있는데, 이런 방법 중 헤더가 아주 많은 경우에 에러가 발생하게 됩니다. 보통 Burp suite의 Param Minor 으로 디싱크 어택 테스트할 때 flow 등으로 이력을 보면 보이는데, 헤더가 큰 경우 400에러가 발생합니다.

[ request ]

GET /js/jquery.js
Host: teststestse
HAHWUL_TEST12: 1111
HAHWUL_TEST13: 1111
HAHWUL_TEST14: 1111
HAHWUL_TEST15: 1111
HAHWUL_TEST16: 1111
HAHWUL_TEST17: 1111
HAHWUL_TEST18: 1111
HAHWUL_TEST19: 1111
HAHWUL_TEST111: 1111
HAHWUL_TEST112: 1111
HAHWUL_TEST113: 1111
HAHWUL_TEST114: 1111
HAHWUL_TEST115: 1111
HAHWUL_TEST116: 1111
HAHWUL_TEST117: 1111
HAHWUL_TEST1118: 1111
HAHWUL_TEST119: 1111
HAHWUL_TEST122: 1111
HAHWUL_TEST123: 1111
HAHWUL_TEST124: 1111
HAHWUL_TEST125: 1111
HAHWUL_TEST126: 1111
HAHWUL_TEST127: 1111

[ response ]

400 Error

일반적인 환경에선 별 영향없는 부분이지만, 일부 캐시 서버는 이 400에러를 캐싱합니다. 그러다보니 비슷한 지역군에 있는 사람들은 캐시된 결과를 리턴받게 되고 400에러 값을 받아서 서비스에 지장이 생기게 됩니다.

단순한 예로, jquery.js 파일이 400으로 떨어지기만 해도, 보통의 웹 사이트의 대다수 기능은 작동하지 않게 됩니다. 이런 방식을 HHO라고 합니다.

CPDoS2 - HMC(HTTP Meta Character)

두번째는 캐리지 리턴을 이용한 방법입니다. 간혹 헤더 중 캐리지 리턴 같은 메타 문자로 인해 잘못된 캐시가 발생하게 됩니다. 결국은 이런 경우 사용자에게 에러가 포함된 Response가 떨어지게 되고, 결국 서비스에 지장이 생기게 됩니다.

대표적인 문자로는.. \n\r\a\t 등이 있습니다. 이건 저런 종류 이외에도 훨씬 많으니 참고하시길 바랍니닷.

CPDoS3 - HMO(HTTP Method Override)

마지막으로 HMO입니다. 이 방법은 X-HTTP-Method-Override 헤더를 이용한 방법입니다. 간혹 디싱크에서 유용한 헤더인데, 이름에서 바로 알 수 있듯이 요청의 헤더를 오버라이딩하는 헤더입니다. 이 헤더를 처리하게 되면 백엔드 서버가 요청을 전송할 때 강제로 헤더를 변경해서 전송하게 됩니다.

결국은 공격자가 이 헤더를 통해 캐시 서버가 GET을 통해 데이터를 가져오지 않고 POST를 요청시키게 되면 잘못된 데이터(이상하거나, 에러거나)를 캐시하게 되고 결국 사용자에게 영향이 발생하게 됩니다. 예를들면, 이런 케이스이죠.

[ request ]

GET /js/jquery.js
Host: teststestse
X-HTTP-Method-Override: POST

[ back-end req ]

POST /js/jquery.js

cached response

400, 405, 500, Etc error..

이후 일반 사용자들은..

<script src="~~~/js/jquery.js"></script>

=>

[ response ]

400 Error

로 인해 서비스에 영향이 발생합니다.

Vulnerable Common Service?

HTTP ImplementationCache Apache HTTPD Apache TS Nginx Squid Varnish Akamai Azure CDN77 CDNSun Cloudflare CloudFron Fastly G-Core Labs KeyCDN StackPath
Apache HTTPD + (ModSecurity) HHO, HMC
Apache TS
Nginx + (ModSecurity) HHO
IIS (HHO) (HHO) (HHO) (HHO) HHO, HMC (HHO)
Tomcat HHO
Squid
Varnish HHO, HMC
Amazon S3 HHO
Google Cloud Storage
Github Pages HHO, HMC
Gitlab Pages HMC
Heroku HHO
ASP.NET (HHO) (HHO) (HHO) (HHO) (HHO), (HMC) (HHO)
BeeGo HMC
Django (HHO), (HMC)
Express.js HMC
Flask (HMO) HMO, (HHO), (HMC)
Gin HMC
Laravel (HHO), (HMC)
Meteor.js HMC
Play 1 HMO HMO HMO HMO HHO, HMO HMO
Play 2 HHO, HMC
Rails (HHO), (HMC)
Spring Boot HHO
Symfony (HHO), (HMC)

How to Protect

좋은 방법은 위에서 이야기한 헤더(X-HTTP-Method-Override)를 처리하지 않고 400 에러 등 에러 정보를 캐시하지 않는 것입니다. 사용자에게 정상적인 파일만 줄 수 있도록 캐시서버에서 대응이 필요합니다.

  • Not Processed X-HTTP-Method-Override
  • Not Cache Error page

Reference

https://cpdos.org/ https://www.infoworld.com/article/3249687/how-to-implement-a-delegatinghandler-for-x-http-method-override-in-web-api.html