고급 PHP 프로그래밍 – 웹 보안 – 0 – SQL 인젝션 방지

고급 PHP 프로그래밍 - 웹 보안 - 0 - SQL 인젝션 방지
고급 PHP 프로그래밍 – 웹 보안 – 0 – SQL 인젝션 방지

고급 PHP 프로그래밍 – 웹 보안 – SQL 인젝션 방지

안녕하세요~ 😊
이번 시간에는 PHP 프로그래밍에서 절~대 빠뜨리면 안 되는 중요한 주제,
바로 SQL 인젝션(SQL Injection) 방지 방법에 대해 알아볼 거예요!

SQL 인젝션은 마치 입력창을 통해 침입하는 해커의 트로이 목마 같은 존재랍니다.
겉으론 평범한 입력처럼 보여도, 그 안에 악의적인 명령어가 숨어있을 수 있어요.

그럼 지금부터! 이런 공격을 막고 안전한 웹사이트를 만들기 위해 어떤 방법이 있는지
하나하나 알기 쉽게 설명드릴게요~ 👨‍💻🛡️


SQL 인젝션이란 무엇인가요?

SQL 인젝션은 공격자가 사용자의 입력값을 조작해서
SQL 쿼리문을 변형하거나 탈취·삭제 등의 악의적 명령을 실행하게 만드는 공격 방식이에요.

예를 들어 로그인 창에서 다음과 같은 쿼리가 있다고 가정해볼게요:

$id = $_POST['id'];
$pw = $_POST['pw'];
$sql = "SELECT * FROM users WHERE id = '$id' AND password = '$pw'";

그리고 사용자가 아이디에 다음을 입력하면?

id: admin' --
pw: (아무거나)

결과적으로 SQL은 이렇게 바뀌어요:

SELECT * FROM users WHERE id = 'admin' --' AND password = ''

--는 주석 처리이기 때문에 뒷부분은 무시되고, 비밀번호 없이도 로그인이 될 수 있어요! 😱


SQL 인젝션의 위험성

위험 요소 설명
데이터 유출 고객 정보, 계정 정보 노출
데이터 변조 가격, 등급, 포인트 등 조작 가능
데이터 삭제 DROP TABLE users 같은 명령 가능
서버 권한 탈취 DB 접속 계정으로 서버 명령 실행 가능성

SQL 인젝션은 단순한 장난이 아니라,
실제 기업의 존망을 결정할 수 있는 중대한 보안 위협이에요.


어떻게 방지할 수 있을까요?

🔐 1. Prepared Statement (준비된 문장) 사용하기

가장 강력하고 권장되는 방법은 PDO 또는 MySQLiprepared statement를 사용하는 거예요.

✅ PDO 예제

$db = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');

$stmt = $db->prepare("SELECT * FROM users WHERE id = :id AND password = :pw");
$stmt->bindParam(':id', $id);
$stmt->bindParam(':pw', $pw);
$stmt->execute();

$result = $stmt->fetchAll();

👉 입력값을 자동으로 이중 따옴표 처리하고, SQL과 데이터 분리해서
인젝션이 절대로 먹히지 않아요!


🔐 2. mysqli의 바인딩 사용

$conn = new mysqli("localhost", "root", "", "testdb");

$stmt = $conn->prepare("SELECT * FROM users WHERE id = ? AND password = ?");
$stmt->bind_param("ss", $id, $pw);
$stmt->execute();

$result = $stmt->get_result();

ss는 문자열(string) 2개를 의미해요.
bind_param은 타입까지 지정하므로 타입 안정성도 확보할 수 있어요.


🔍 3. 사용자 입력값 검증 및 필터링

입력값을 단순히 SQL에 넣기 전에,
형식이 맞는지, 이상한 문자열이 있는지를 먼저 확인하는 것도 중요해요!

$id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_STRING);
  • 이메일이라면 FILTER_VALIDATE_EMAIL
  • 숫자라면 FILTER_VALIDATE_INT
  • 문자열이라면 addslashes() 등으로 이스케이프 처리도 고려해요 (하지만 임시방편!)

🚫 4. 직접 SQL 조립 금지!

아래와 같은 코드 스타일은 절대로 사용하면 안 돼요!

$sql = "SELECT * FROM users WHERE id = '$id' AND password = '$pw'";

이런 방식은 외부 입력값이 그대로 들어가기 때문에,
SQL 인젝션에 속수무책이에요. 이제는 구시대의 유산으로 생각하시면 돼요!


실전 예제: 안전한 로그인 처리

$db = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');

$id = $_POST['id'];
$pw = $_POST['pw'];

$stmt = $db->prepare("SELECT * FROM users WHERE id = :id AND password = :pw");
$stmt->execute([':id' => $id, ':pw' => $pw]);

$user = $stmt->fetch();

if ($user) {
    echo "로그인 성공!";
} else {
    echo "아이디 또는 비밀번호가 틀렸습니다.";
}

사용자의 입력값이 아무리 조작되더라도,
쿼리문 구조는 절대 흔들리지 않아요!


추가 보안 팁 🛡️

항목 설명
DB 계정 권한 최소화 SELECT 전용 계정을 분리해서 사용
에러 메시지 노출 금지 쿼리 오류를 사용자에게 직접 보여주지 않기
입력 길이 제한 비정상적으로 긴 입력 방지
로깅 이상 요청 탐지 및 기록
웹방화벽(WAF) 적용 패턴 기반으로 SQL 인젝션 차단 가능

마무리 요약 🎯

구분 보안 효과
PDO prepared statement ★★★★★ (최강 추천)
mysqli prepared statement ★★★★☆
filter_input 검증 ★★★☆☆
직접 SQL 문자열 조립 ☆☆☆☆☆ (절대 금지!)

마무리하며 😊

SQL 인젝션은 한 줄의 삽입문으로 데이터베이스를 털어버릴 수 있는 위험한 공격이에요.
하지만 PHP에서는 PDO나 mysqli의 prepared statement를 사용하면
그 어떤 인젝션도 뚫을 수 없는 강력한 방어선을 구축할 수 있답니다!

이제부터는 여러분의 코드에서도 require, $_POST, query 대신
“보안”을 먼저 생각하는 습관을 만들어보세요.
웹 보안은 예방이 최선이고, 방심은 금물이랍니다! 🔒✨

다음 시간에는 크로스사이트 스크립팅(XSS) 방지 방법에 대해 함께 알아볼게요~
오늘도 안전하고 멋진 코딩 되세요! 💪💻🧠🛡️

답글 남기기