데브포일 홈
DEV MODE - 실서버 영향 없음 📦 배포 관리
보안 기초 & 배포 준비
+250 XP
LEVEL 50 QUEST

보안 기초 & 배포 준비

SQL Injection, XSS, CSRF 방지부터 HTTPS 설정과 보안 체크리스트까지

SQL Injection 방지
SQL Injection이란?
공격자가 입력 필드에 SQL 코드를 삽입하여 데이터베이스를 조작하는 공격입니다. SaaS에서는 한 고객의 취약점이 모든 테넌트의 데이터를 위험에 빠뜨립니다.
위험한 코드 vs 안전한 코드
DANGER - 절대 이렇게 하지 마세요!
// 절대 금지! SQL Injection 취약! $email = $_POST['email']; $password = $_POST['password']; // 사용자 입력을 직접 쿼리에 넣으면 안 됩니다! $sql = "SELECT * FROM users WHERE email = '$email' AND password = '$password'"; $result = $db->query($sql); // 공격자가 이렇게 입력하면? // email: admin@test.com' OR '1'='1' -- // 결과: 비밀번호 없이 로그인 성공!
SAFE - PDO Prepared Statements 사용
// 안전한 방법: PDO Prepared Statements $stmt = $db->prepare( "SELECT * FROM users WHERE email = :email" ); $stmt->execute([':email' => $_POST['email']]); $user = $stmt->fetch(); // 비밀번호 검증은 password_verify()로! if ($user && password_verify($_POST['password'], $user['password_hash'])) { // 로그인 성공 $_SESSION['user_id'] = $user['id']; $_SESSION['tenant_id'] = $user['tenant_id']; }
안전한 CRUD 예제 - 테넌트 격리 포함
<?php namespace App\Models; class Conversation { private \Core\Database $db; /** * 대화 목록 조회 - 반드시 tenant_id로 필터링! */ public function getByTenant(int $tenantId, int $limit = 50): array { return $this->db->fetchAll( "SELECT id, session_id, message_count, satisfaction, status, created_at FROM ai_conversations WHERE tenant_id = :tenant_id ORDER BY created_at DESC LIMIT :limit", [':tenant_id' => $tenantId, ':limit' => $limit] ); } /** * 새 대화 저장 - 트랜잭션으로 카운터도 함께 업데이트 */ public function create(int $agentId, int $tenantId, array $data): string { return $this->db->transaction(function($db) use ($agentId, $tenantId, $data) { // 대화 저장 $id = $db->insert( "INSERT INTO ai_conversations (agent_id, tenant_id, session_id, messages, message_count) VALUES (:agent_id, :tenant_id, :session_id, :messages, 1)", [ ':agent_id' => $agentId, ':tenant_id' => $tenantId, ':session_id' => $data['session_id'], ':messages' => json_encode($data['messages']), ] ); // 에이전트 대화 카운터 증가 $db->execute( "UPDATE ai_agents SET total_conversations = total_conversations + 1 WHERE id = :id AND tenant_id = :tenant_id", [':id' => $agentId, ':tenant_id' => $tenantId] ); return $id; }); } }
XSS (Cross-Site Scripting) 방지
XSS 공격이란?
공격자가 악성 JavaScript를 웹 페이지에 삽입하여 다른 사용자의 세션, 쿠키, 개인정보를 탈취하는 공격입니다. SaaS 대시보드에 XSS가 있으면, 고객의 API 키와 비즈니스 데이터가 유출됩니다.
방지 방법 1: htmlspecialchars 함수
<?php /** * 안전한 출력 헬퍼 함수 * 모든 사용자 입력값 출력 시 반드시 사용! */ function e(?string $value): string { return htmlspecialchars($value ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8'); } ?> <!-- 뷰 파일에서의 사용 --> <h2>고객사: <?= e($tenant['company_name']) ?></h2> <p>담당자: <?= e($user['name']) ?></p> <p>이메일: <?= e($user['email']) ?></p> <!-- 공격자가 회사명에 <script>alert('XSS')</script>를 넣어도 --> <!-- e() 함수가 &lt;script&gt;로 이스케이프하여 안전 -->
방지 방법 2: CSP (Content Security Policy) 헤더
브라우저에게 허용된 리소스만 로드하도록 지시하는 HTTP 헤더입니다.
<?php /** * 보안 헤더 설정 미들웨어 * 모든 응답에 보안 헤더를 추가합니다 */ class SecurityHeaders { public function handle(): void { // XSS 방지: 인라인 스크립트 차단, 허용된 도메인만 header("Content-Security-Policy: " . "default-src 'self'; " . "script-src 'self' https://cdn.jsdelivr.net; " . "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " . "font-src 'self' https://fonts.gstatic.com; " . "img-src 'self' data: https:; " . "connect-src 'self' https://api.openai.com" ); // MIME 타입 스니핑 방지 header("X-Content-Type-Options: nosniff"); // Clickjacking 방지 header("X-Frame-Options: DENY"); // XSS 필터 활성화 header("X-XSS-Protection: 1; mode=block"); // Referrer 정보 최소화 header("Referrer-Policy: strict-origin-when-cross-origin"); // HTTPS 강제 (HSTS) header("Strict-Transport-Security: max-age=31536000; includeSubDomains"); } }
🔒
여기까지는 미리보기입니다
보안 기초 & 배포 준비
무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.
Google로 3초 만에 시작 →🧵 Threads로 시작무료 공개 강의 둘러보기 (Lv.1~3)