
웹취약점 점검에서 개발한 웹에 대하여 점검을 진행하였고, 여러 취약점들을 발견하였다.
발견한 취약점들을 대상으로 시큐어 코딩을 진행하고자 한다.
이번 대상은 주요정보통신기반시설 분석·평가 가이드 15번 항목 - CSRF 이다.
CSRF 취약점이 발견된 항목은 다음과 같다.
| URL | 파라미터 | 메뉴 |
|---|---|---|
| http://jmseok.com/web/my/mypageedit_proc.php | input_pw, input_pw2 | 회원정보 수정 |
[1. CSRF 토큰]
CSRF Token
- 서버 → 예측 불가능한 랜덤 토큰을 생성
- 해당 토큰을 정당한 경로로 클라이언트에게 전달
- 이후, 클라이언트는 요청시 → 해당 토큰을 함께 전송
- 서버에서 토큰 일치 여부를 검증
[2. Referer 체크]
요청 헤더의 출처를 확인하여, 정당한 경로로부터 전송된 요청인지 검증
[3. 인증 정보 추가]
중요 정보 변경시, 기존 비밀번호를 입력하는 등의 인증 정보 추가 & 검증
CSRF 토큰 기반 방어는 공격자가 토큰 값을 알 수 없다는 가정을 전제로 하므로, XSS 취약점이 존재하는 경우 해당 가정이 깨져 방어 효과가 저하된다.
따라서 XSS 취약점이 존재하지 않는다는 것을 전제로 적용되어야 하며, 두 취약점은 함께 대응하는 것이 바람직하다.
XSS 대응방안은 앞서 정리 하였으므로 (시큐어 코딩 - XSS), XSS 취약점이 제거되었다는 전제 하에 CSRF Token 시큐어 코딩을 수행하였다.
흐름 정리
1. 회원정보 수정 페이지 (mypage_edit.php) 접속시 CSRF Token 발행
2. mypage_edit.php 에서 "회원정보 변경" 요청시, 앞서 발행받은 Token을 포함하여 요청을 전송
3. 회원정보 수정처리 페이지 (mypageedit_proc.php) 에서 전달받은 CSRF Token 검증 수행
① 회원정보 수정 페이지 - CSRF Token 발행 기능 추가
// mypage_edit.php
if(!isset($_SESSION["csrf_token"]))
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
② 회원정보 수정페이지 - 회원정보 변경시 CSRF Token 전송
// mypage_edit.php
<form class="mypage-edit-form" method="post" action="mypageedit_proc.php">
<input type="hidden" name="csrf_token" value="<?= $_SESSION["csrf_token"] ?>">
<div class="mypage-edit-row">
<label>아이디</label>
<input value="<?php echo $row["user_id"]?>" disabled>
</div>
<div class="mypage-edit-row">
<label for="input_pw">비밀번호</label>
<input type="password" id="input_pw" name="input_pw" placeholder="새 비밀번호 입력">
</div>
<div class="mypage-edit-row">
<label for="input_pw2">비밀번호 확인</label>
<input type="password" id="input_pw2" name="input_pw2" placeholder="비밀번호 확인">
</div>
<div class="mypage-edit-row">
<label for="input_name">사용자명</label>
<input id="input_name" name="input_name" placeholder="<?php echo $row["user_name"]?>">
</div>
<div class="mypage-edit-row">
<label for="input_mail">이메일(선택)</label>
<input id="input_mail" name="input_mail" placeholder="<?php echo $row["user_mail"]?>">
</div>
<div class="mypage-edit-actions">
<input type="submit" value="수정완료">
<button type="button" onclick="history.back()">이전</button>
</div>
</form>
③ 회원정보 수정 처리 페이지 - CSRF Token 검증 수행
// mypageedit_proc.php : CSRF Token 비교 및 검증
if (!isset($_SESSION["csrf_token"]) or !isset($_POST["csrf_token"]) or (!hash_equals($_SESSION["csrf_token"], $_POST["csrf_token"]))) {
echo "<script>
alert('잘못된 요청입니다.');
history.go(-1);
</script>";
exit;
}
① 회원정보 수정 페이지(mypage_edit.php) 접속
| CSRF Token 발행 확인 |
|---|
![]() |
② 회원정보 수정 요청시, CSRF Token 전달
| CSRF Token 전달 |
|---|
![]() |
③ 회원정보 수정 처리 페이지(mypageedit_proc.php)에서 CSRF Token 검증 수행
| CSRF Token 검증에 실패할 경우, 해당 요청은 수행 X |
|---|
![]() |