English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
웹 페이지를 통해 사용자 입력 데이터를 가져와 MySQL 데이터베이스에 삽입하는 경우, SQL注入 보안 문제가 발생할 수 있습니다.
이 장에서는 SQL注入을 방지하는 방법과 SQL에注入된 문자를 필터링하는 스크립트를 소개합니다.
SQL注入란, 웹 폼 제출이나 입력 도메인이나 페이지 요청의 쿼리 문자열에 SQL 명령어를 삽입하여, 결국 서버가 악의적인 SQL 명령어를 실행하는 데 기만하는 것입니다.
사용자 입력을 항상 신뢰하지 마세요. 사용자가 입력한 데이터는 모두 보안이 없다고 인정해야하며, 사용자 입력 데이터를 필터링 처리해야 합니다.
아래 예제에서 입력한 사용자 이름은 알파벳, 숫자 및 언더스코어로 구성되어야하며, 사용자 이름 길이는 8 부터 20 자리 간:
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) { $result = mysqli_query($conn, "SELECT * FROM users WHERE username=$matches[0] } else { echo "username 입력 오류"; }
특수 문자를 필터링하지 않았을 때 발생하는 SQL 상황을 확인해 보겠습니다:
// $name에 필요하지 않은 SQL 문이 삽입되었습니다 $name = "Qadir'; DELETE FROM users;"; mysqli_query($conn, "SELECT * FROM users WHERE name='{$name}');
위의注入 문에서는 $name 변수에 대한 필터링을 하지 않았으며, $name에 필요하지 않은 SQL 문이 삽입되어 users 테이블의 모든 데이터가 지워질 수 있습니다.
PHP의 mysqli_query()는 여러 개의 SQL 문을 동시에 실행할 수 없지만, SQLite와 PostgreSQL는 여러 개의 SQL 문을 동시에 실행할 수 있습니다. 따라서 이러한 사용자 데이터를 엄격히 검증해야 합니다.
SQL注入을 방지하기 위해 주의해야 할 몇 가지 중요 사항이 있습니다:
1.사용자 입력을 신뢰하지 마시고, 정규 표현식을 통해 검증하거나 길이를 제한하고, 대문자와 양쪽 따옴표-"을 대체하는 등.
2.동적 SQL을 사용하지 마시고, 파라미터화된 SQL이나 스토리지 프로시저를 사용하여 데이터 쿼리 및 저장을 수행해야 합니다.
3.관리자 권한의 데이터베이스 연결을 사용하지 마시고, 각 응용 프로그램에 제한된 권한의 데이터베이스 연결을 사용해야 합니다.
4.기밀 정보를 직접 저장하지 마시고, 암호화하거나 hash로 비밀번호와 민감한 정보를 처리해야 합니다.
5.응용 프로그램의 이상 정보는 가능한 한 적은 정보를 제공해야 하며, 원래 오류 정보를 포장하는 개별 오류 정보를 사용하는 것이 좋습니다.
6.SQL注入의 검출 방법은 보통 보조 소프트웨어나 웹 플랫폼을 사용하여 검출하며, 소프트웨어는 jsky와 같은 SQL注入 검출 도구를 사용하고, 웹 플랫폼은 亿思 웹 보안 플랫폼 검출 도구나 MDCSOFT SCAN과 같은 도구를 사용합니다. MDCSOFT-IPS는 SQL注入, XSS 공격 등을 효과적으로 방어할 수 있습니다.
스크립트 언어(Perl, PHP와 같은)에서는 사용자 입력 데이터를 대체하여 SQL注入을 방지할 수 있습니다.
PHP의 MySQL 확장은 mysqli_real_escape_string() 함수를 제공하여 특수 입력 문자를 대체합니다.
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysqli_real_escape_string($conn, $name); mysqli_query($conn, "SELECT * FROM users WHERE name='{$name}');
좋아하는 조건문에서 사용자가 입력한 값이 "_"와 "%"를 포함하고 있으면 이런 일이 발생할 수 있습니다: 사용자는 "abcd_"를 검색하고 싶었지만, 검색 결과에는 "abcd_"와 "abcde"와 "abcdf" 등이 포함됩니다; 사용자는 ""30%"(주의: 30%)이면 문제가 발생할 수 있습니다.
PHP 스크립트에서는 addcslashes() 함수를 사용하여 이러한 상황을 처리할 수 있습니다. 예제를 보여드립니다:
$sub = addcslashes(mysqli_real_escape_string($conn, "%something_"), "%_"); // $sub == \%something\_ mysqli_query($conn, "SELECT * FROM messages WHERE subject LIKE '{$sub}%';
addcslashes() 함수는 지정된 문자 앞에 역삽호를 추가합니다.
문법 형식:
addcslashes(string,characters)
파라미터 | 설명 |
---|---|
string | 필수 사항. 확인할 문자열을 지정합니다. |
characters | 선택 사항. addcslashes()가 영향을 미치는 문자나 문자 범위를 지정합니다. |
구체적인 적용은 다음을 참조하세요:PHP addcslashes() 함수