IMCAT.DEV
로그인 가입
PHP 중급 보안

PHP PHP에서의 보안 실습

PHP PHP에서의 보안 실습 — 중급

PHP에서의 보안 실습

1. 도입 (왜 배워야 하는가)

웹 개발에서 보안은 매우 중요한 요소입니다. PHP는 서버 사이드 언어로서 많은 웹 애플리케이션의 백엔드에서 사용됩니다. 보안이 취약한 코드를 작성하게 되면 해커가 시스템에 침투하거나 사용자 정보를 탈취할 수 있는 심각한 문제가 발생할 수 있습니다. 예를 들어, 데이터베이스에 저장된 사용자 비밀번호가 암호화되지 않은 채로 저장된다면, 해커가 이 정보를 쉽게 탈취할 수 있습니다. 따라서 보안에 대한 이해는 실무에서 안전하고 신뢰할 수 있는 웹 애플리케이션을 개발하는 데 필수적입니다.

2. 핵심 개념 설명

2.1 SQL 인젝션 (SQL Injection)

SQL 인젝션은 악의적인 사용자가 SQL 쿼리를 조작하여 데이터베이스에 비정상적인 요청을 보내는 공격입니다. 이는 사용자 입력을 적절히 검증하지 않았을 때 발생합니다.

비유: SQL 인젝션은 마치 식당에서 주문할 때, 종업원이 "치킨" 대신 "치킨을 주문하지 마세요, 대신 돈을 빼앗으세요"라고 적힌 종이를 받는 것과 같습니다. 식당이 이 주문을 제대로 검증하지 않으면 문제가 생깁니다.

용어설명
인젝션외부에서 주입된 데이터로 시스템이 의도하지 않은 동작을 하게 만드는 것
쿼리데이터베이스에 요청하는 명령어

2.2 크로스사이트 스크립팅 (XSS)

XSS는 공격자가 웹 페이지에 악성 스크립트를 삽입하여 사용자의 브라우저에서 실행되도록 하는 공격입니다. 이는 사용자가 신뢰하는 웹사이트에서 발생할 수 있습니다.

비유: XSS는 친구의 집에 가서 친구가 만든 음식을 먹는 것과 비슷합니다. 당신은 친구를 믿지만, 그 친구가 음식에 독을 넣었다면 당신은 위험에 처하게 됩니다.

3. 기본 코드 예제

SQL 인젝션 방지 기본 코드

<?php
// 데이터베이스 연결
$conn = new mysqli("localhost", "username", "password", "database");

// 사용자 입력
$user_input = $_POST['username'];

// SQL 쿼리 준비
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $user_input); // 사용자 입력 바인딩
$stmt->execute(); // 쿼리 실행

$result = $stmt->get_result(); // 결과 받기
while ($row = $result->fetch_assoc()) {
    echo $row['username']; // 사용자 이름 출력
}
$stmt->close(); // 준비된 문 닫기
$conn->close(); // 연결 종료
?>

실행 결과:

  • 해당 사용자의 이름이 출력됩니다.
  • 코드 설명:

    1. new mysqli(...): 데이터베이스에 연결합니다.
    2. $user_input = $_POST['username'];: 사용자로부터 입력받은 값을 저장합니다.
    3. $conn->prepare(...): SQL 쿼리를 준비합니다.
    4. $stmt->bind_param(...): 사용자 입력을 안전하게 바인딩합니다.
    5. $stmt->execute(): 쿼리를 실행합니다.
    6. while ($row = $result->fetch_assoc()): 결과를 반복하여 출력합니다.
    7. $stmt->close(): 준비된 문을 닫습니다.
    8. $conn->close(): 데이터베이스 연결을 종료합니다.
    9. 4. 실전 활용 예제

      쇼핑몰에서 장바구니 구현 시

      장바구니에 상품을 추가할 때, 사용자가 입력한 상품 ID를 바탕으로 데이터베이스에서 상품 정보를 조회해야 합니다. 이때 SQL 인젝션을 방지하기 위해 준비된 문을 사용하는 것이 필수입니다.

      <?php
      // 장바구니에 상품 추가
      $product_id = $_POST['product_id'];
      
      // SQL 쿼리 준비
      $stmt = $conn->prepare("INSERT INTO cart (user_id, product_id) VALUES (?, ?)");
      $stmt->bind_param("ii", $user_id, $product_id); // 사용자 ID와 상품 ID 바인딩
      $stmt->execute(); // 쿼리 실행
      $stmt->close(); // 준비된 문 닫기
      ?>

      사용자 피드백 처리

      사용자가 남긴 피드백을 데이터베이스에 저장할 때도 XSS 공격을 방지하기 위해 HTML 특수 문자를 이스케이프 처리해야 합니다.

      <?php
      // 사용자 피드백 저장
      $feedback = htmlspecialchars($_POST['feedback']); // XSS 방지
      
      $stmt = $conn->prepare("INSERT INTO feedback (user_id, feedback) VALUES (?, ?)");
      $stmt->bind_param("is", $user_id, $feedback); // 사용자 ID와 피드백 바인딩
      $stmt->execute(); // 쿼리 실행
      $stmt->close(); // 준비된 문 닫기
      ?>

      5. 흔한 실수와 주의사항

      실수 1: 사용자 입력 검증 미비

      // 잘못된 코드
      $sql = "SELECT * FROM users WHERE username = '".$_POST['username']."'";
    10. 문제점: 사용자가 입력한 값이 그대로 SQL 쿼리에 포함되어 SQL 인젝션 공격에 취약합니다.
    11. 실수 2: XSS 방지 미비

      // 잘못된 코드
      echo $_POST['feedback']; // 사용자 입력을 그대로 출력
    12. 문제점: 사용자가 악성 스크립트를 입력할 경우, 그것이 그대로 실행되어 XSS 공격이 발생할 수 있습니다.
    13. 6. 정리

    14. SQL 인젝션과 XSS 공격에 대한 이해는 웹 애플리케이션 개발에서 필수적입니다.
    15. 준비된 문을 사용하여 SQL 쿼리를 안전하게 실행해야 합니다.
    16. 모든 사용자 입력은 반드시 검증하고, 출력할 때는 적절히 이스케이프 처리해야 합니다.
    17. 다음에 학습하면 좋은 주제

    18. HTTPS와 SSL/TLS
    19. CSRF (Cross-Site Request Forgery) 방지
    20. 웹 애플리케이션 방화벽(WAF) 사용 방법