Skip to content

18. Injection


1. Injection

  • 인젝션은 데이터베이스를 파괴할 수 있는 코드 주입 기술이다.
  • 인젝션은 가장 일반적인 웹 해킹 기술 중 하나이다.
  • 인젝션은 웹 페이지 입력을 통해 SQL 문에 악성 코드를 배치하는 것이다.


2. SQL in Web Pages

  • SQL 인젝션은 일반적으로 사용자에게 사용자 이름/사용자 ID와 같은 입력을 요청하고 이름/ID 대신 사용자가 데이터베이스에서 무의식적으로 실행할 SQL 문을 제공할 때 발생한다.


  • 다음의 선택 문자열에 변수(txtUserId)를 추가하여 SELECT 문을 생성하는 것을 살펴보자.
  • 변수는 사용자 입력(getRequestString)에서 가져온다.


txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserID = " + txtUserId;


3. SQL Injection Based on 1=1 is Always True

  • 위의 예를 다시 보자.
  • 코드의 원래 목적은 주어진 사용자 ID로 사용자를 선택하는 SQL 문을 만드는 것이었다.
  • 만약 사용자의 잘못된 입력을 방지할 방법이 없다면 사용자는 다음과 같이 입력할 수도 있다.


001


  • 그러면 SQL 문은 다음과 같이 표시된다.


SELECT * FROM Users WHERE UserID = 105 OR 1=1;


  • 위의 SQL은 유효하며, OR 1=1이 항상 참이기 때문에 Users 테이블의 모든 행을 반환한다.
  • 만약 Users 테이블에 이름과 암호가 포함되어 있었으면 위험했을 것이다.


4. SQL Injection Based on ""="" is Always True

  • 다음은 웹 사이트에서 사용자 로그인의 예를 보여준다.


002


uName = getRequestString("username");
uPass = getRequestString("userpassword");

sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass + '"'
SELECT * FROM Users WHERE Name = "John Doe" AND Pass = "myPass"


  • 해커는 단순히 " OR ""="를 사용자 이름 또는 암호 텍스트 상자에 삽입하여 데이터베이스의 사용자 이름과 암호에 액세스할 수 있다.


003


  • 서버의 코드는 다음과 같은 유효한 SQL 문을 생성한다.


SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""


  • OR ""=""는 항상 참이므로 위의 SQL은 유효하며 Users 테이블의 모든 행을 반환한다.


5. SQL Injection Based on Batched SQL Statements

  • 대부분의 데이터베이스는 일괄 SQL 문을 지원한다.
  • SQL 문의 일괄 처리는 ;(세미콜론)으로 구분된 둘 이상의 SQL 문의 그룹이다.


  • 다음의 SQL 문은 Users 테이블의 모든 행을 반환한 다음 Suppliers 테이블을 삭제한다.


SELECT * FROM Users; DROP TABLE Suppliers


  • 다음의 예를 살펴보자.


txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;


  • 그리고 다음과 같이 입력한다.


004


  • 유효한 SQL 문은 다음과 같다.


SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers;


6. User SQL Parameters for Protection

  • SQL 인젝션으로부터 웹 사이트를 보호하기 위해 SQL 매개변수를 사용할 수 있다.
  • SQL 매개변수는 실행 시 제어된 방식으로 SQL 쿼리에 추가되는 값이다.


txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL, txtUserId);


  • 매개변수는 SQL 문에서 @로 표시된다.
  • SQL 엔진은 각 매개변수가 해당 열에 대해 올바른지 확인하고 실행할 SQL의 일부가 아닌 문자 그대로 처리되는지 확인한다.


txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName, Address, City) Values (@0, @1, @2)";
db.Execute(txtSQL, txtNam, txtAdd, txtCit);


7. Examples

  • 다음은 일부 일반적인 웹 언어로 매개변수화된 쿼리를 작성하는 방법을 보여준다.


1) SELECT STATEMENT IN ASP.NET

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0", txtUserId);
command.ExecuteReader();


2) INSERT INTO STATEMENT IN ASP.NET

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName, Address, City) Values (@0, @1, @2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0", txtNam);
command.Parameters.AddWithValue("@1", txtAdd);
command.Parameters.AddWithValue("@2", txtCit);
command.ExecuteNonQuery();


3) INSERT INTO STATEMENT IN PHP

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();

References