SQL 튜토리얼

SQL 홈 SQL 소개 SQL 구문 SQL 선택 SQL 선택 고유 SQL 어디에 SQL 및, 또는, 아님 SQL 순서 SQL 삽입 SQL Null 값 SQL 업데이트 SQL 삭제 SQL 상위 선택 SQL 최소 및 최대 SQL 개수, 평균, 합계 SQL 좋아요 SQL 와일드카드 SQL 입력 SQL 사이 SQL 별칭 SQL 조인 SQL 내부 조인 SQL 왼쪽 조인 SQL 권한 조인 SQL 전체 조인 SQL 자체 조인 SQL 유니온 SQL 그룹화 기준 SQL SQL 존재 모든 SQL SQL 선택 대상 선택에 SQL 삽입 SQL 케이스 SQL 널 함수 SQL 저장 프로시저 SQL 주석 SQL 연산자

SQL 데이터베이스

SQL DB 생성 SQL 삭제 DB SQL 백업 DB SQL 테이블 생성 SQL 삭제 테이블 SQL 변경 테이블 SQL 제약 조건 SQL이 널이 아님 SQL 고유 SQL 기본 키 SQL 외래 키 SQL 확인 SQL 기본값 SQL 인덱스 SQL 자동 증분 SQL 날짜 SQL 보기 SQL 주입 SQL 호스팅 SQL 데이터 유형

SQL 참조

SQL 키워드 MySQL 함수 SQL 서버 기능 MS 액세스 기능 SQL 빠른 참조

SQL 예제

SQL 예제 SQL 퀴즈 SQL 연습 SQL 인증서

SQL 주입


SQL 주입

SQL 주입은 데이터베이스를 파괴할 수 있는 코드 주입 기술입니다.

SQL 인젝션은 가장 일반적인 웹 해킹 기술 중 하나입니다.

SQL 인젝션은 웹 페이지 입력을 통해 SQL 문에 악성 코드를 배치하는 것입니다.


웹 페이지의 SQL

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

SELECTselect 문자열에 변수(txtUserId)를 추가하여 문장 을 생성하는 다음 예를 보자 . 변수는 사용자 입력(getRequestString)에서 가져옵니다.

예시

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

이 장의 나머지 부분에서는 SQL 문에서 사용자 입력을 사용할 때의 잠재적인 위험에 대해 설명합니다.


1=1을 기반으로 하는 SQL 주입은 항상 참입니다.

위의 예를 다시 보자. 코드의 원래 목적은 주어진 사용자 ID로 사용자를 선택하는 SQL 문을 만드는 것이었습니다.

사용자가 "잘못된" 입력을 입력하는 것을 방지할 방법이 없다면 사용자는 다음과 같이 "똑똑한" 입력을 입력할 수 있습니다.

사용자 ID:

그러면 SQL 문은 다음과 같이 표시됩니다.

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

OR 1=1 이 항상 TRUE 이기 때문에 위의 SQL은 유효하며 "Users" 테이블의 모든 행을 반환 합니다.

위의 예가 위험해 보입니까? "Users" 테이블에 이름과 암호가 포함되어 있으면 어떻게 됩니까?

위의 SQL 문은 다음과 거의 동일합니다.

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;

해커는 단순히 105 OR 1=1을 입력 필드에 삽입하여 데이터베이스의 모든 사용자 이름과 암호에 액세스할 수 있습니다.



""=""에 기반한 SQL 주입은 항상 True입니다.

다음은 웹 사이트에서 사용자 로그인의 예입니다.

사용자 이름:

비밀번호:

예시

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 ""="를 사용자 이름 또는 암호 텍스트 상자에 삽입하여 데이터베이스의 사용자 이름과 암호에 액세스할 수 있습니다.

사용자 이름:

비밀번호:

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

결과

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

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


일괄 SQL 문을 기반으로 하는 SQL 주입 

대부분의 데이터베이스는 일괄 처리된 SQL 문을 지원합니다.

SQL 문의 일괄 처리는 세미콜론으로 구분된 둘 이상의 SQL 문의 그룹입니다.

아래 SQL 문은 "Users" 테이블의 모든 행을 반환한 다음 "Suppliers" 테이블을 삭제합니다.

예시

SELECT * FROM Users; DROP TABLE Suppliers

다음 예를 보십시오.

예시

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

그리고 다음 입력:

사용자 ID:

유효한 SQL 문은 다음과 같습니다.

결과

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

보호를 위해 SQL 매개변수 사용

SQL 인젝션으로부터 웹 사이트를 보호하기 위해 SQL 매개변수를 사용할 수 있습니다.

SQL 매개변수는 실행 시 제어된 방식으로 SQL 쿼리에 추가되는 값입니다.

ASP.NET 면도기 예제

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

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

ASP.NET의 SELECT 문:

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

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

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