
웹취약점 점검에서 개발한 웹에 대하여 점검을 진행하였고, 여러 취약점들을 발견하였다.
발견한 취약점들을 대상으로 시큐어 코딩을 진행하고자 한다.
이번 대상은 주요정보통신기반시설 분석·평가 가이드 20번 항목 - 자동화 공격 이다.
자동화 공격 취약점이 발견된 항목은 다음과 같다.
| URL | 파라미터 | 메뉴 |
|---|---|---|
| http://jmseok.com/web/board/freewrite_proc.php | input_title, input_name, input_pass, input_cont | 자유게시판 > 게시글 작성 |
| http://jmseok.com/web/board/free_edit.php | input_pass | 자유게시판 > 게시글 수정/삭제 |
| http://jmseok.com/web/board/memwrite_proc.php | input_title, input_name, input_pass, input_cont | 회원게시판 > 게시글 작성 |
자유게시판의 게시글 작성의 경우, 자동화 공격을 방어하기 위해 CAPTCHA를 적용하는 방식을 선택하였다.
① captcha 이미지 생성 페이지 작성
// captcha.php
<?php
session_start();
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$captcha = '';
for ($i = 0; $i < 5; $i++) {
$captcha .= $chars[random_int(0, strlen($chars) - 1)];
}
$_SESSION['captcha'] = $captcha;
$image = imagecreatetruecolor(85, 40);
$background = imagecolorallocate($image, 240, 240, 240);
$textColor = imagecolorallocate($image, 30, 30, 30);
imagefilledrectangle($image, 0, 0, 85, 40, $background);
imagestring($image, 5, 17, 12, $captcha, $textColor);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
1) CAPTCHA에 사용할 문자 지정
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
2) 5자리 랜덤 문자열 생성
$captcha = '';
for ($i = 0; $i < 5; $i++) {
$captcha .= $chars[random_int(0, strlen($chars) - 1)];
}
3) 생성된 CAPTCHA 값을 세션에 저장
$_SESSION['captcha'] = $captcha;
4) CAPTCHA 이미지 생성
// 가로 85px, 세로 40px
$image = imagecreatetruecolor(85, 40);
// 배경색 및 글자색 설정
$background = imagecolorallocate($image, 240, 240, 240);
$textColor = imagecolorallocate($image, 30, 30, 30);
// 이미지 배경 채우기
imagefilledrectangle($image, 0, 0, 85, 40, $background);
// CAPTCHA 문자열 출력
imagestring(
$image,
5, // 글꼴 크기
17, // X 좌표
12, // Y 좌표
$captcha,
$textColor
);
// PNG 이미지로 응답
header('Content-Type: image/png');
imagepng($image);
// 이미지 메모리 해제
imagedestroy($image);
② 게시글 작성 페이지에, 생성된 CAPTCHA 이미지를 출력하는 부분 추가
// free_write.php (일부)
<div class="edit-row">
<label for="captcha"><img src="captcha.php" alt="CAPTCHA"></label>
<input id="captcha" name="captcha" type="text" placeholder="좌측의 보안문자 입력" required>
</div>
| free_write.php 수정 결과 |
|---|
![]() |
| ▲ 게시글 작성 페이지에, 캡차 이미지 및 보안문자 입력칸 추가 |
③ 게시글 저장 페이지에, CAPTCHA 검증 로직 추가
// freewrite_proc.php
session_start();
$captcha = $_POST['captcha'] ?? '';
if (!isset($_SESSION['captcha']) || strtoupper(trim($captcha)) !== $_SESSION['captcha']) {
echo "<script>
alert('보안문자가 일치하지 않습니다.');
history.back();
</script>";
exit;
}
unset($_SESSION['captcha']);
사용자가 입력한 CAPTCHA 값과, 서버에 저장된 세션값을 비교
▷ 일치하는 경우에만, 게시글을 등록
CAPTCHA 검증 이후 세션값을 삭제함으로써, 동일한 CAPTCHA 재사용 방지
④ 게시글 작성 시, CAPTCHA 값 검증
| 파이썬 자동화 스크립트 실행 |
|---|
![]() |
| ▲ CAPTCHA 값 불일치시, 게시글 작성 불가 |
자유게시판 - 비밀번호의 경우, 값의 범위가 숫자 4자리였기 때문에 Brute Force 공격에 취약하였다.
게시판의 특성을 고려하여, 해당 부분은 비밀번호의 숫자 4자리 제한을 없애는 정도로 조치하였다.
(기존)
// free_write.php (일부)
<div class="edit-row">
<label for="input_pass">비밀번호</label>
<input id="input_pass" name="input_pass" type="password" maxlength="4" placeholder="숫자 4자리">
</div>
// freewrite_proc.php (일부)
if (!(ctype_digit($input_pass) && strlen($input_pass) == 4)) {
echo "<script>
alert('비밀번호는 숫자 4자리로 입력해주세요');
history.go(-1);
</script>";
exit;
}
(수정 후)
// free_write.php (일부)
<div class="edit-row">
<label for="input_pass">비밀번호</label>
<input id="input_pass" name="input_pass" type="password" placeholder="비밀번호 입력">
</div>
// freewrite_proc.php (일부)
if (empty($input_pass)) {
echo "<script>
alert('게시글 비밀번호를 입력해주세요');
history.go(-1);
</script>";
exit;
}
회원게시판의 게시글 작성의 경우,
회원ID를 기준으로 최근 1분 이내의 작성된 글이 3개를 초과하면, 게시글 작성이 제한되며 1분 후에 작성이 가능하도록 조치하였다.
① 회원게시판 테이블 구조
| memboard 테이블 |
|---|
![]() |
| ▲ 게시글 작성 시, 자동으로 현재 시간이 저장됨 |
② 게시글 저장 페이지에, 최근 작성한 게시물 개수 조회 로직 추가
// memwrite_proc.php (일부)
$sql = "select write_time from memboard where user_id = '$user_id' order by write_time desc limit 3";
$result = mysqli_query($con, $sql);
$times = [];
while ($row = mysqli_fetch_assoc($result)) {
$times[] = strtotime($row['write_time']);
}
if (count($times) >= 3) {
$last_time = $times[0];
$third_time = $times[2];
if (($last_time - $third_time) <= 60 && (time() - $last_time) < 60) {
echo "<script>
alert('짧은 시간 내에 다수의 게시물이 작성되었습니다.\\n잠시 후 시도해주세요');
history.go(-1);
</script>";
exit;
}
}
③ 최근 게시글 작성 개수 검증
| 회원게시판 > 게시글 작성 |
|---|
![]() |
| ▲ 최근 게시물 3개 초과 시, 게시물 작성이 제한 |
| 파이썬 자동화 스크립트 실행 |
|---|
![]() |
| ▲ CAPTCHA 검증 로직으로 인해, 자동화 공격 불가능 |
| 파이썬 자동화 스크립트 실행 |
|---|
![]() |
| ▲ 1분 내 최대 3개까지만 게시글 작성 가능, 초과시 작성 제한 |