주입 공격 클래스에서 PHP SQL 주입 공격이 눈에 띄게 나왔다. 대부분의 웹사이트가 이에 취약합니다. 연구에 따르면 공격의 50% 이상은 SQL 인젝션을 사용하여 웹에서 수행되었습니다. 이 기사에서는 SQL 주입이 수행되는 방법과 PHP 애플리케이션에서 이를 방지할 수 있는 방법에 대해 설명합니다.
SQL 주입(SQLi)이란 무엇입니까?
먼저 SQL 인젝션에 대해 알아보겠습니다. SQL 주입(SQLi) 해커가 실행된 SQL 명령을 위조하여 백엔드에서 실행 중인 SQL 문을 변경하는 접근 방식입니다. 이러한 형태의 주입은 해당 형태의 입력 필드를 통해 수행되며 데이터베이스에 끔찍한 여파를 초래합니다. 결국 데이터베이스에서 매우 민감한 정보가 공개됩니다. 해커가 SQL 명령을 주입하여 데이터베이스에 대한 제어권을 얻으면 데이터베이스에서 데이터를 삽입, 업데이트 또는 삭제할 수 있는 권한을 갖게 됩니다.
SQL 주입 공격은 코드가 보안 방식으로 작성되지 않을 때 발생합니다. 그들 중 일부는 보안 코딩으로 작성된 것처럼 보이지만 여전히 SQLi에 자리를 내주고 있습니다:
- 공백 문자 및 유형 처리의 잘못된 필터링
- 위생되지 않고 부적절하게 인코딩된 데이터를 데이터베이스에 전달
- 코드와 데이터의 혼합
- 따옴표를 사용하여 문자열 구분
요컨대, 사용자 입력이 제대로 검증되지 않으면 데이터베이스에서 사용자 데이터를 악의적으로 해석하게 됩니다. 사용자 입력을 프론트 엔드에서 직접 가져와 쿼리에 삽입하는 경우에도 손상이 발생할 수 있습니다.
SQLi로 이어지는 또 다른 문제는 데이터베이스 유형 및 버전에 대한 세부 정보를 얻기 위해 악의적인 사용자가 악용할 수 있는 오류가 사용자에게 표시된다는 것입니다. 따라서 SQL 주입 공격을 유발하는 익스플로잇을 배포합니다.
PHP SQL 삽입이란 무엇입니까?
안전하지 않은 코드의 예
다음 취약한 PHP 코드를 사용하여 PHP SQL 주입 공격의 개념을 이해합시다.
<?php
$username = $_POST[‘uname'];
$pass = $_POST[‘password'];
$sql = "SELECT * FROM user_table WHERE username='".$username."' AND userpwd='".$pass"';";
?>
위의 코드는 유효성 검사 없이 직접 사용자 입력을 수락하고 데이터베이스에서 실행되는 SQL 쿼리에 직접 삽입합니다. 해커는 또한 결과가 true인 논리적 쿼리를 삽입할 수 있습니다. 이는 결국 로그인에 성공하여 심각한 보안 손상을 초래할 수 있습니다.
또한 사용자에게 오류가 표시되는 또 다른 시나리오를 고려하십시오.
<?php
…
…
elseif($mysqli->error)
{
print($mysqli->error);
}
?>
이 시나리오에서는 사용자 화면에 오류 로그를 인쇄하는 대신 오류 로그를 저장할 수 있는 데이터베이스를 유지하고 나중에 웹 사이트가 대상이 된 횟수를 확인하는 데 사용하는 것이 좋습니다. SQLi .
보안 코드의 예
PHP SQL 삽입을 방지하기 위한 보안 코딩의 예 다음과 같은 방식으로 이러한 논리적 쿼리에 대한 사용자 이름과 암호의 유효성을 검사할 수 있습니다.
<?php
Function checkUserInput($str)
{
return
str_replace(array("‘",""", "'", ‘"‘),array("‘","""'",""",$str));
}
$username = checkUserInput($_POST[‘uname']);
$pass = checkUserInput($_POST[‘password']);
?>
이러한 방식으로 사용자 입력은 SQL 쿼리에 추가되기 전에 유효성을 검사할 수 있습니다. PHP SQL 주입을 방지하는 또 다른 방법은 준비된 명령문(PHP Data Objects(PDO))을 사용하는 것입니다. 이것은 SQL 문을 반복적으로 실행할 수 있는 효율적인 접근 방식입니다. PDO는 매개변수화된 쿼리를 사용하기 쉽게 만드는 방법을 제공합니다. 또한 코드의 가독성과 이식성을 향상시키고 MySQL 데이터베이스뿐만 아니라 다른 유형의 데이터베이스에서도 작동합니다. PDO는 사용자 입력으로 처리할 부분과 데이터베이스 명령으로 나머지 부분을 정의합니다.
MySQL 데이터베이스용 PDO의 예제 코드 스니펫은 다음과 같습니다.
//DB credentials
define(‘DB_HOST','localhost');
define(‘DB_USER','John_Reaper');
define(‘DB_PASS','[email protected]@$$w0rd$');
define(‘DB_NAME','users');
if(isset($_GET[‘id']))
{
$id = $_GET[‘id'];
if(is_numeric($id) == true)
{
try
{
$dbh = new PDO(‘DBHOST;DB_NAME','DB_USER','DB_PASS');
$dbh->setAttribute(PDO::AFTER_ERRMODE, PDO::ERRMODE_EXCEPTION);
$q = "SELECT username FROM users WHERE id = :id";
$sth = $dbh->prepare($q);
$sth->bindParam(‘:id',$id);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_ASSOC);
$res = $sth->fetchColumn();
print(htmlentities($res));
$dbh = null;
}
catch(PDOException $e)
{
error_log(‘PDOException - ‘.$e->getMessage(),0);
http_response_code(500);
die(‘Connection to database unsuccessful');
}
}
else
{
http_response_code(400);
die(‘Error processing malformed request');
}
}
PHP SQL 삽입을 방지하는 방법
따라서 다음 모범 사례를 구현하여 SQL 주입으로부터 웹사이트를 보호할 수 있습니다.
- JavaScript를 사용하여 프런트 엔드에서 또는 PHP를 사용하여 백엔드에서 사용자 입력을 검증합니다.
- 사용자에게 오류를 표시하지 않습니다. 대신 오류를 파일에 기록하고 공격자가 액세스할 수 없도록 만듭니다. 또한 사용자에게 표시되는 오류 메시지는 매우 일반적이어야 하며 데이터베이스에 대한 정보를 노출하지 않아야 합니다.
- 사용자 입력으로 처리되어야 하는 SQL 쿼리의 일부를 지정하는 매개변수화된 쿼리 사용
- 사용하지 않는 저장 프로시저는 쉽게 악용될 수 있으므로 제거하여 SQL 주입을 방지합니다.
- 공격자가 인증을 우회하는 경우 손상을 피하기 위해 적절한 사용자에게 적절한 권한을 부여합니다.
PHP SQL 주입에 대한 궁극적인 보호
Astra와 같은 방화벽을 사용하면 SQLi에 대한 내성을 높일 수 있습니다. SQLi 외에도 Astra Security Suite는 100개 이상의 공격으로부터 웹사이트를 보호합니다. 그 중 일부는 불량 봇, XSS, CSRF 등입니다.
당사의 맬웨어 스캐너는 10분 이내에 웹사이트를 스캔하는 것으로 알려져 있습니다. 그리고 후속 스캔에 더 적은 시간(1분 미만)이 걸립니다. 보안 감사 및 침투 테스트를 통해 Astra의 엔지니어는 각 코드 라인을 수동으로 스캔하여 웹사이트의 취약점을 찾아 수정하여 보안을 뚫을 수 없도록 만듭니다.
오늘 Astra 데모를 받아보세요!