English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
이 튜토리얼에서는 일반적인 데이터베이스 취약점을 어떻게 수정할 수 있는지 배울 것입니다.
SQL注入은 공격자가 브라우저를 통해 애플리케이션 서버로 전달되는 데이터(예: 웹 폼 입력)에 악의적인 SQL 코드를 주입하거나 실행하는 공격입니다.
감사 정보와 같은 민감한 정보를 공개할 수 있으며, 사용자의 전화번호, 이메일 주소, 신용카드 정보 등을 포함할 수 있습니다. 공격자는 이를 통해 인증 절차를 회피하고 전체 데이터베이스에 대한 접근 권한을 얻을 수 있습니다. 그 작동 방식을 알아보겠습니다.
다음은 Web 애플리케이션에서 사용자 이름과 비밀번호로 사용자 인증을 하는 간단한 SQL 예제입니다.
SELECT * FROM users WHERE username='username_val' AND password='password_val';
여기서는,username_val및password_val각각 사용자가 입력한 사용자 이름과 비밀번호를 나타냅니다. 사용자가 'john'으로 사용자 이름을 입력하고, ' 123”와 같은 비밀번호 값을 입력하면, 결과 문장은 다음과 같습니다:
SELECT * FROM users WHERE username='john' AND password='123;
그러나 가정해 보겠습니다. 사용자가 공격자라면, 입력 필드에 유효한 사용자 이름과 비밀번호를 입력하지 않고 다음과 같은 값을 입력했습니다: ' OR 'x'='x
이 경우, 위의 SQL 쿼리는 다음과 같이 구성됩니다:
SELECT * FROM users WHERE username='' OR 'x'='x' AND password='' OR 'x'='x';
이 문장은 유효한 SQL 문장입니다. WHERE 'x'='x'는 항상 true이므로, 쿼리는 다음과 같이 반환됩니다:users테이블의 모든 행입니다. 공격자가 작은 조치만으로 데이터베이스의 모든 감사 정보에 쉽게 접근할 수 있음을 볼 수 있습니다.
如果users如果表很大,并且包含数百万或更多行,则该单个语句还可能通过使系统资源超载而导致拒绝服务攻击(DoS攻击),并使您的应用程序对合法用户不可用。
警告:如果你的脚本生成一个DELETE또는UPDATE쿼리를 수행하면 SQL注入의 후遗症를 무시하거나 더 나아질 수 있습니다. 공격자는 테이블에서 데이터를 제거하거나 모든 행을 영구적으로 변경할 수 있습니다.
항상 사용자 입력을 확인하고, 어떤 가정도 하지 마세요. 사용자 입력으로부터 SQL 문장을 직접 구성하지 마세요. PHP와 MySQL을 사용하는 경우 mysqli_real_escape_string() 함수를 사용하여 SQL 문장에서 사용할 수 있는 합법적인 SQL 문자열을 생성할 수 있습니다.
이는 PHP와 MySQL을 사용하여 사용자 인증을 수행하는 매우 기본적인 예제로, 사용자에서 입력을 받을 때 SQL注入을 방지하는 방법을 보여줍니다.
<?php // 세션 시작 session_start(); /* MySQL 서버 연결을 시도합니다. MySQL 서버를 기본 설정으로 실행 중이라고 가정하세요(사용자 'root'는 비밀번호가 없습니다) */ $link = mysqli_connect("localhost", "root", "", "demo"); // 연결을 확인하세요 if($link === false){ die("에러: 데이터베이스에 연결할 수 없습니다."); } // 사용자 입력을 대체하여 보안을 유지하세요 $username_val = mysqli_real_escape_string($link, $_POST['username']); $password_val = mysqli_real_escape_string($link, $_POST['password']); if(isset($username_val, $password_val)){ // SQL 쿼리 실행을 선택하려면 $sql = "SELECT * FROM users WHERE username='" . $username_val . "' AND password='" . $password_val . "'"; if($result = mysqli_query($link, $sql)){ if(mysqli_num_rows($result) == 1{ // 사용자가 인증되었습니다. 여기서 작업을 수행해 주세요 $row = mysqli_fetch_array($result); /*세션 변수에 저장된 값을 저장합니다 이를 통해 나중에 동일한 세션 참조에서 사용할 수 있도록 저장합니다 */ $_SESSION['user_id'] = $row['user_id']; $_SESSION['first_name'] = $row['first_name']; header('Location: welcome.html'); } echo "에러! 잘못된 사용자 이름이나 비밀번호입니다."; } } echo "에러: 문제가 발생했습니다. 다시 시도해 주세요."; } } // 연결을 닫기 mysqli_close($link); ?>
ヒント:테스트 애플리케이션에서 수신한 데이터의 크기와 타입 또는 내용을 확인하고, 시스템 자원이 활용되지 않도록 적절한 제한을 시행합니다。