[9. 자동화 공격]

Minseok Jo·2026년 8월 27일

웹 시큐어코딩

목록 보기
9/11
post-thumbnail

웹취약점 점검에서 개발한 웹에 대하여 점검을 진행하였고, 여러 취약점들을 발견하였다.
발견한 취약점들을 대상으로 시큐어 코딩을 진행하고자 한다.

이번 대상은 주요정보통신기반시설 분석·평가 가이드 20번 항목 - 자동화 공격 이다.

자동화 공격 취약점이 발견된 항목은 다음과 같다.

URL파라미터메뉴
http://jmseok.com/web/board/freewrite_proc.phpinput_title,
input_name,
input_pass,
input_cont
자유게시판 >
게시글 작성
http://jmseok.com/web/board/free_edit.phpinput_pass자유게시판 >
게시글 수정/삭제
http://jmseok.com/web/board/memwrite_proc.phpinput_title,
input_name,
input_pass,
input_cont
회원게시판 >
게시글 작성

0. 자동화 공격 대응 방안

  • 게시글 등록, 비밀번호 검증 등 반복 요청이 가능한 주요 기능에 CAPTCHA를 적용하여, 자동화 도구를 통한 요청을 제한
  • 동일 사용자, 계정 또는 IP에서 일정 시간 내 과도한 요청이 발생할 경우, Rate Limiting을 적용하여 요청 횟수 제한
  • 비밀번호 검증 실패가 일정 횟수를 초과할 경우 일정 시간 동안 추가 인증 시도를 차단
  • 비밀번호는 충분한 길이와 복잡도를 갖도록 정책 강화


1. 시큐어 코딩

[1. 자유게시판 - 게시글 작성]

자유게시판의 게시글 작성의 경우, 자동화 공격을 방어하기 위해 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 값 불일치시, 게시글 작성 불가




[2. 자유게시판 - 비밀번호 추출]

자유게시판 - 비밀번호의 경우, 값의 범위가 숫자 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;
}
  • 기존의 경우, 게시글의 비밀번호를 숫자 4자리로 제한

(수정 후)

// 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;
}
  • 비밀번호 값의 범위 제한 삭제




[3. 회원게시판 - 게시글 작성]

회원게시판의 게시글 작성의 경우,
회원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;
    }
}
  • 최근(1분 내) 작성된 게시물이 3개 초과 시, 게시글 작성이 제한
  • 제한 시, 마지막 게시글 작성으로부터 1분이 지나야 재작성 가능

③ 최근 게시글 작성 개수 검증

회원게시판 > 게시글 작성
▲ 최근 게시물 3개 초과 시, 게시물 작성이 제한


2. 보안 조치 결과

[1. 자유게시판]

파이썬 자동화 스크립트 실행
▲ CAPTCHA 검증 로직으로 인해, 자동화 공격 불가능



[2. 회원게시판]

파이썬 자동화 스크립트 실행
▲ 1분 내 최대 3개까지만 게시글 작성 가능, 초과시 작성 제한


0개의 댓글