| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 보안공부
- 성능평가지표
- List
- 루키즈33기
- 수업복습
- git push -u
- 데이터분포
- 함수
- pandas
- tunder client
- 지도학습
- 꽉뚝짝 시장
- dropna
- 레이블인코딩
- Linked List
- 클래스
- 생성형AI
- 루키즈
- OT후기
- 블록(Block)
- sqld
- gdgm
- SK쉴더스
- Package
- 방콕
- node.js
- echo 명령어
- 태국
- 패키지
- 예외처리
Archives
- Today
- Total
개발 블로그
[웹 보안] 방어 기법 적용 본문
🐢 안녕하세요, 카메입니다.
저번에 공격 실험을 수행했던 취약한 웹 페이지를 오늘은 여러 방어 기법들을 적용하여 취약점을 막는 실습을 하려고 합니다.
방어 1: Prepared Statement 적용 (로그인 페이지)
sudo nano /var/www/html/login_secure.php<?php
$conn = mysqli_connect("localhost", "webuser", "webpass123", "web_security");
if (isset($_POST['login'])) {
$user = $_POST['username'];
$pass = $_POST['password'];
// Prepared Statement 사용
$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE username=? AND password=?");
mysqli_stmt_bind_param($stmt, "ss", $user, $pass);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
echo "<h3>입력한 값:</h3>";
echo "<p>아이디: $user</p>";
echo "<p>비밀번호: $pass</p>";
if (mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_assoc($result);
echo "<h2 style='color:green;'>로그인 성공! 환영합니다, " . $row['username'] . "님</h2>";
} else {
echo "<h2 style='color:red;'>로그인 실패! 아이디 또는 비밀번호가 틀렸습니다.</h2>";
}
}
?>
<html>
<head><title>로그인 (보안 적용)</title></head>
<body>
<h1>로그인 페이지 (Prepared Statement 적용)</h1>
<form method="POST">
아이디: <input type="text" name="username"><br><br>
비밀번호: <input type="text" name="password"><br><br>
<button type="submit" name="login">로그인</button>
</form>
</body>
</html>
방어 2: 입력값 검증 및 필터링 적용 (검색 페이지)
sudo nano /var/www/html/search_secure.php<?php
$conn = mysqli_connect("localhost", "webuser", "webpass123", "web_security");
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
// 입력값 필터링: 특수문자 이스케이프
$keyword_safe = mysqli_real_escape_string($conn, $keyword);
// 추가 필터링: SQL 키워드 차단
$blocked = array('UNION', 'SELECT', 'ORDER BY', 'DROP', 'DELETE', 'INSERT', '--', '#');
$is_blocked = false;
foreach ($blocked as $word) {
if (stripos($keyword, $word) !== false) {
$is_blocked = true;
break;
}
}
echo "<h3>입력한 검색어: $keyword</h3>";
if ($is_blocked) {
echo "<h2 style='color:red;'>차단됨! 허용되지 않는 입력이 감지되었습니다.</h2>";
} else {
$query = "SELECT * FROM board WHERE title LIKE '%$keyword_safe%'";
$result = mysqli_query($conn, $query);
if ($result && mysqli_num_rows($result) > 0) {
echo "<table border='1' cellpadding='8'>";
echo "<tr><th>ID</th><th>제목</th><th>내용</th><th>작성자</th></tr>";
while ($row = mysqli_fetch_assoc($result)) {
echo "<tr>";
echo "<td>" . $row['id'] . "</td>";
echo "<td>" . $row['title'] . "</td>";
echo "<td>" . $row['content'] . "</td>";
echo "<td>" . $row['author'] . "</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "<p>검색 결과가 없습니다.</p>";
}
}
}
?>
<html>
<head><title>게시판 검색 (보안 적용)</title></head>
<body>
<h1>게시판 검색 (입력값 검증 적용)</h1>
<form method="GET">
검색어: <input type="text" name="keyword">
<button type="submit">검색</button>
</form>
</body>
</html>
방어 3: Prepared Statement 적용 (Blind 페이지)
sudo nano /var/www/html/blind_secure.php<?php
$conn = mysqli_connect("localhost", "webuser", "webpass123", "web_security");
if (isset($_GET['id'])) {
$id = $_GET['id'];
// 입력값 검증: 숫자만 허용
if (!ctype_digit($id)) {
echo "<h3>입력한 ID: $id</h3>";
echo "<h2 style='color:red;'>차단됨! ID는 숫자만 입력할 수 있습니다.</h2>";
} else {
$stmt = mysqli_prepare($conn, "SELECT * FROM board WHERE id=?");
mysqli_stmt_bind_param($stmt, "i", $id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
echo "<h3>입력한 ID: $id</h3>";
if ($result && mysqli_num_rows($result) > 0) {
echo "<h2 style='color:green;'>게시글이 존재합니다.</h2>";
} else {
echo "<h2 style='color:red;'>게시글이 존재하지 않습니다.</h2>";
}
}
}
?>
<html>
<head><title>게시글 조회 (보안 적용)</title></head>
<body>
<h1>게시글 조회 (입력값 검증 + Prepared Statement 적용)</h1>
<form method="GET">
게시글 ID: <input type="text" name="id">
<button type="submit">조회</button>
</form>
</body>
</html>
동작 확인: 방어 테스트
이제 이전에 성공했던 공격들을 방어 버전에서 다시 시도하여 확인합니다.
테스트 1: http://localhost/login_secure.php

' OR 1=1 -- / aaa → 이번에는 로그인 실패가 뜹니다.
테스트 2: http://localhost/search_secure.php

' UNION SELECT 1,username,password,4 FROM users -- → "차단됨!" 메시지가 뜹니다.
테스트 3: http://localhost/blind_secure.php

1 AND 1=1 → "숫자만 입력할 수 있습니다" 메시지가 뜹니다.
'Study > Web Security' 카테고리의 다른 글
| [웹 보안] WAF(ModSecurity) 설치 및 적용 (0) | 2026.05.26 |
|---|---|
| [웹 보안] 공격 실험 (0) | 2026.05.26 |
| [웹 보안] 취약한 웹 페이지 작성 (0) | 2026.05.26 |
| [웹 보안] 데이터베이스 준비 (0) | 2026.05.26 |
| [웹 보안] 환경 구축 (VMware + Ubuntu + LAMP) (0) | 2026.05.26 |