본문 바로가기
my_lesson/_SQL

SQL - Injection

by boolean 2016. 2. 25.
728x90

SQL Injection 인젝션 방지

SQL Injection(SQL 인젝션)은 우리의 DB를 망칠 수 있는 방법이다. 


웹에서 SQL문을 사용해서 DB에 있는 정보를 빼오거나 지우거나 수정할 수 있다. 

기본으로 SQL 인젝션이라고 하는데, 웹에서 DB를 검색하거나 작업할 때 SQL명령어를 함께 넣어주는 작업을 말한다. 


사용자가 악성적인 SQL명령어를 웹페이지의 inputbox 같은 곳에 넣아주는 것이다. 삽입된 SQL명령어는 웹홈페이지를 손상시킬 수 있는 가능성이 있다. 


예를 들어


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


서버에서 위와 같은 코드가 있다고 하자.

사용자의 ID값을 받아서 DB의 Users테이블에서 아이디와 같은 값을 찾는 코드이다. 


여기에 id를 넣어야 하지만 만약에 "tester or 1=1" 값을 넣게 된다면 서버에서 받는 SQL 명령어는 다음과 같을 것이다. 


SELECT * FROM Users WHERE UserId = tester or 1=1


SQL문법을 봤을 때 유효한 형식이다. 그렇기 때문에 먼저 ID가 tester인 값과 or 연산자로 인해 WHERE 1=1 이 이기 때문에 모든 결과를 다 보여주게 된다.  

그렇게 되면 다른 사용자의 ID값과 패스워드 등 개인적인 정보까지 유출될 수 있다. 


조금 더 실질적인 예로 서버에 다음과 같은 코드가 있다고 하자.


User Name:

Password:

uName = getRequestString("UserName");
uPass = getRequestString("UserPass");

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


사용자로 부터 ID와 PW(패스워드)를 받아서 SQL문을 실행하는 형식이다. 


위와 같은 경우는 name과 password 칸에 "or ""="를 넣어서 인젝션 할 수 있다. 


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


SQL문법적으로 봤을 때 유효한 문법이다. 여기서 모든 User테이블의 레코드를 돌려주게 되는데, WHERE ""="" 가 참 값을 갖기 때문이다. 




DB의 레코드 값만 불러오는 것이 아니라 직접 명령어를 넣을 수 있다. 


만약 서버에 다음과 같은 코드가 있다고 할 때, 


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


아래와 같이

User id:

tester;  DROP TABLE Suppliers


이렇게 SQL 문이 실행하게 된다. 

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


곧 ID값을 불러오고 Suppliers의 테이블은 날려버리게 되는 것이다 .


이러한 인젝션 공격을 방지하기 위해 ;, = 같은 문자를 못 넣게 하는 방법이 있다. 


하지만 그렇게 되면 사용자에게 제약이 되므로 SQL parameter 값을 넣고 SQL query를 실행하게 해주는 것이다. 


게시판을 만들거나 SQL 쿼리를 사용하게 될 때 봤었던 방법이다. 


ASP.NET 의 예를 보면


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


과 같은 코드로 @ SQL parameter를 사용해서 값을 넣고 db를 실행한다. 


꼭 @ 가 사용되는 것이 아니라 다른 언어마다 다른 parameters를 사용한다. 

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();


ASP.NET INSERT INTO 문:


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();


위의 예들과 같이 Parmeters를 사용해서 SQL 인젝션을 방지할 수 있다. 


웹의 기본~!


'my_lesson > _SQL' 카테고리의 다른 글

SQL - UPDATE  (1) 2016.02.25
SQL - DELETE  (0) 2016.02.25
SQL - LIKE  (0) 2016.02.25
SQL - IN  (0) 2016.02.25
SQL - BETWEEN  (0) 2016.02.25

댓글