복붙노트

[SQL] 어떻게 준비 문은 SQL 주입 공격으로부터 보호 할 수 있습니까?

SQL

어떻게 준비 문은 SQL 주입 공격으로부터 보호 할 수 있습니까?

어떻게 준비된 명령문은 우리가 SQL 주입 공격을 방지하는 데 도움이?

위키 백과는 말합니다 :

나는 아주 잘 이유를 볼 수 없습니다. 쉬운 영어와 몇 가지 예에 간단한 설명 어떤 것입니까?

해결법

  1. ==============================

    1.아이디어는 매우 간단합니다 - 쿼리 및 데이터는 별도로 데이터베이스 서버로 전송됩니다. 그게 다야.

    아이디어는 매우 간단합니다 - 쿼리 및 데이터는 별도로 데이터베이스 서버로 전송됩니다. 그게 다야.

    는 SQL 주입 문제의 뿌리는 코드와 데이터의 혼합이다.

    사실, 우리의 SQL 쿼리는 합법적 인 프로그램입니다. 그리고 우리는 즉석에서 일부 데이터를 추가, 동적으로 이러한 프로그램을 만들 수 있습니다. 따라서, 데이터가 프로그램 코드를 방해 할 수 있고, 심지어, 그것을 변경 모든 SQL 인젝션 예 쇼로 (PHP / MySQL은 모든 예) :

    $expected_data = 1;
    $query = "SELECT * FROM users where id=$expected_data";
    

    일반 쿼리를 생성합니다

    SELECT * FROM users where id=1
    

    이 코드 동안

    $spoiled_data = "1; DROP TABLE users;"
    $query        = "SELECT * FROM users where id=$spoiled_data";
    

    악의적 시퀀스를 생성 할

    SELECT * FROM users where id=1; DROP TABLE users;
    

    우리가 프로그램 본체에 직접 데이터를 추가하고 프로그램의 일부가, 데이터가 프로그램을 변경할 수 있도록하고, 전달 된 데이터에 따라 때문에 작동, 우리는 하나 일반 출력 또는 사용자가 삭제 한 테이블이있을 것이다.

    준비된 명령문의 경우 우리는 우리의 프로그램을 변경하지 않지만, 그것은 그대로 유지 즉, 점입니다.

    우리는 먼저 서버에 프로그램을 전송하는

    $db->prepare("SELECT * FROM users where id=?");
    

    데이터가 약간의 변수로 치환된다 파라미터 또는 자리했다.

    정확히 같은 쿼리는 어떤 데이터없이 서버로 전송합니다! 그리고 우리는 기본적으로 쿼리 자체에서 분리 된 두 번째 요청으로 데이터를 전송하고 있습니다 :

    $db->execute($data);
    

    그래서 우리의 프로그램을 변경하고 어떤 해를 할 수 없습니다. 매우 간단합니다 - 그렇지?

    유일한 것은 내가 항상 모든 설명서에 생략 된 것을 추가해야합니다 :

    준비된 문은 데이터 만 리터럴을 보호 할 수 있지만, 다른 쿼리 부분을 사용할 수 없습니다. 예를 들어, 필드 이름 - - 우리는 역학적 식별자를 추가 말을하면 그래서, 준비된 문은 우리를 도울 수 없다. 나 자신을 반복하지 않도록 나는 최근에이 문제를 설명했습니다.

  2. ==============================

    2.여기에 예제를 설정하는 SQL은 다음과 같습니다

    여기에 예제를 설정하는 SQL은 다음과 같습니다

    CREATE TABLE employee(name varchar, paymentType varchar, amount bigint);
    
    INSERT INTO employee VALUES('Aaron', 'salary', 100);
    INSERT INTO employee VALUES('Aaron', 'bonus', 50);
    INSERT INTO employee VALUES('Bob', 'salary', 50);
    INSERT INTO employee VALUES('Bob', 'bonus', 0);
    

    분사 클래스는 SQL 인젝션에 취약합니다. 쿼리가 동적으로 사용자 입력과 함께 붙여 넣습니다. 쿼리의 목적은 밥에 대한 정보를 표시하는 것이 었습니다. 사용자 입력에 따라 급여 나 보너스, 어느. 그러나 악의적 인 사용자가이 조작은 An의 등가 '또는 사실'에 시침하여 쿼리를 손상 입력받는 where 절 모든 것이 숨어 있어야했다 아론에 대한 정보를 포함하여 반환되도록.

    import java.sql.*;
    
    public class Inject {
    
        public static void main(String[] args) throws SQLException {
    
            String url = "jdbc:postgresql://localhost/postgres?user=user&password=pwd";
            Connection conn = DriverManager.getConnection(url);
    
            Statement stmt = conn.createStatement();
            String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='" + args[0] + "'";
            System.out.println(sql);
            ResultSet rs = stmt.executeQuery(sql);
    
            while (rs.next()) {
                System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount"));
            }
        }
    }
    

    이 실행되는 경우 제 정상적인 사용 및 악성 분사 제와 함께이다 :

    c:\temp>java Inject salary
    SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary'
    salary 50
    
    c:\temp>java Inject "salary' OR 'a'!='b"
    SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary' OR 'a'!='b'
    salary 100
    bonus 50
    salary 50
    bonus 0
    

    당신은 사용자 입력 문자열을 연결하여 SQL 문을 구축하지 않아야합니다. 뿐만 아니라 주입이 취약하지만, 서버에 영향을 캐싱하고있다뿐만 아니라 (성명 변경, 그래서 덜을 얻을 바인드 예 반면 SQL 문 캐시 히트 항상 같은 문을 실행한다).

    여기서 주입이 종류 않도록 결합 예이다 :

    import java.sql.*;
    
    public class Bind {
    
        public static void main(String[] args) throws SQLException {
    
            String url = "jdbc:postgresql://localhost/postgres?user=postgres&password=postgres";
            Connection conn = DriverManager.getConnection(url);
    
            String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?";
            System.out.println(sql);
    
            PreparedStatement stmt = conn.prepareStatement(sql);
            stmt.setString(1, args[0]);
    
            ResultSet rs = stmt.executeQuery();
    
            while (rs.next()) {
                System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount"));
            }
        }
    }
    

    더 paymentType 일치하는 문자열이 없기 때문에 악성 코드가 작동하지 않는 이전 예제 쇼와 같은 입력으로이 실행 :

    c:\temp>java Bind salary
    SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?
    salary 50
    
    c:\temp>java Bind "salary' OR 'a'!='b"
    SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?
    
  3. ==============================

    3.기본적으로, 준비된 문으로 잠재적 인 해커로부터 오는 데이터는 데이터로 처리됩니다 - 그것은 응용 프로그램의 SQL와 혼합 될 수 및 / 또는 전달 된 데이터에 직접 배치 할 때 일어날 수있는 SQL (으로 해석 할 방법이 없습니다 당신의 응용 프로그램의 SQL).

    기본적으로, 준비된 문으로 잠재적 인 해커로부터 오는 데이터는 데이터로 처리됩니다 - 그것은 응용 프로그램의 SQL와 혼합 될 수 및 / 또는 전달 된 데이터에 직접 배치 할 때 일어날 수있는 SQL (으로 해석 할 방법이 없습니다 당신의 응용 프로그램의 SQL).

    쿼리가 실제로 실행되는 시간에 - 준비된 문은 먼저 SQL 쿼리를 "준비"효율적인 쿼리 계획을 찾기 위해, 그리고 아마도 나중에 양식에서 와서 실제 값을 보낼 수 있기 때문이다.

    더 좋은 정보를 원하시면 여기 :

    준비된 문 및 SQL 인젝션

  4. ==============================

    4.나는 대답을 읽어 여전히 문 준비의 본질을 조명 키 점을 강조 할 필요를 느꼈다. 사용자 입력이 참여이다 쿼리 하나의 데이터베이스에 두 가지 방법을 고려 :

    나는 대답을 읽어 여전히 문 준비의 본질을 조명 키 점을 강조 할 필요를 느꼈다. 사용자 입력이 참여이다 쿼리 하나의 데이터베이스에 두 가지 방법을 고려 :

    순진한 접근

    일부 SQL 문자열의 일부와 한을 병합 사용자 입력은 SQL 문을 생성합니다. 이 경우 사용자는 실행을 위해 데이터베이스로 전송됩니다 악의적 인 SQL 명령을 포함 할 수 있습니다.

    String SQLString = "SELECT * FROM CUSTOMERS WHERE NAME='"+userInput+"'"
    

    예를 들어, 악의적 사용자 입력 고객 SELECT * "이상임 SQLString 이어질 수 WHERE NAME = '제임스; DROP 표 고객;'

    때문에 악의적 인 사용자에 SQLString는 2 일 ( "DROP 표 고객")이 해를 입힐 것이 문을 포함하고 있습니다.

    문 준비

    이 경우에 의한 질의 및 데이터를 분리하기 위해, 사용자 입력은 실행되지 않는다 이에 따라 SQL 문으로 처리하지 않고, 않는다. 그것은 악의적 인 SQL 코드가 어떤 해를 입힐하지 않을 것이다 주입하는 것이 이러한 이유입니다. 은 "DROP 표 고객"그래서 위의 경우에 실행되지 않을 것입니다.

    요컨대, 사용자의 입력 정보를 통해 도입 준비된 문 악성 코드가 실행되지 않을 것이다!

  5. ==============================

    5.당신이 작성하고 DBMS에 준비된 문을 보낼 때, 그것은 실행을 위해 SQL 쿼리로 저장합니다.

    당신이 작성하고 DBMS에 준비된 문을 보낼 때, 그것은 실행을 위해 SQL 쿼리로 저장합니다.

    당신이 나중에 바인드 쿼리에 대한 데이터 등의 DBMS를 사용하는 실행 (파라미터)에 대한 쿼리 매개 변수로 데이터입니다. DBMS에 당신이 이미 컴파일 된 SQL 쿼리에 추가로 결합 데이터를 사용하지 않습니다; 단순히 데이터입니다.

    이 방법은 준비된 문을 사용하여 SQL 주입을 수행하기 위해 근본적으로 불가능하다. 매우 준비된 명령문의 자연과 DBMS와의 관계는이를 방지 할 수 있습니다.

  6. ==============================

    6.입력 매개 변수 쿼리를 형성하지 않기 때문에 SQL Server에서 준비된 문을 사용하여 사출 증거는 확실히이다. 그것은 실행 된 쿼리 동적 쿼리 없음을 의미합니다. 는 SQL 주입 취약점 문의 예.

    입력 매개 변수 쿼리를 형성하지 않기 때문에 SQL Server에서 준비된 문을 사용하여 사출 증거는 확실히이다. 그것은 실행 된 쿼리 동적 쿼리 없음을 의미합니다. 는 SQL 주입 취약점 문의 예.

    string sqlquery = "select * from table where username='" + inputusername +"' and password='" + pass + "'";
    

    입력 이름 변수의 값이 '또는 1 = 1 같은 경우 지금 -이 쿼리는 지금이된다 :

    select * from table where username='a' or 1=1 -- and password=asda
    

    그리고 나머지는 후 주석 -, 그것은 실행되지 아래로 준비된 명령문의 예제를 사용으로 우회 없구요 있도록.

    Sqlcommand command = new sqlcommand("select * from table where username = @userinput and password=@pass");
    command.Parameters.Add(new SqlParameter("@userinput", 100));
    command.Parameters.Add(new SqlParameter("@pass", 100));
    command.prepare();
    

    그래서 효과에 당신은 따라서 SQL 주입을 피하고, 다른 매개 변수를 보낼 수 없습니다 ...

  7. ==============================

    7.핵심 문구가 올바르게 이스케이프 할 필요가있다. 당신이 등 대시, 아포스트로피, 시세, 던져하려고 사람에 대해 걱정할 필요가 없다는 것을 의미하는 것이 ...

    핵심 문구가 올바르게 이스케이프 할 필요가있다. 당신이 등 대시, 아포스트로피, 시세, 던져하려고 사람에 대해 걱정할 필요가 없다는 것을 의미하는 것이 ...

    그것은 모두 당신을 위해 처리됩니다.

  8. ==============================

    8.

    ResultSet rs = statement.executeQuery("select * from foo where value = " + httpRequest.getParameter("filter");
    

    하자 당신이 그 서블릿에서 당신 권리가 가정합니다. 악의적 인 사람이 '필터'에 대한 잘못된 값을 통과하면 당신은 당신의 데이터베이스를 해킹 수 있습니다.

  9. ==============================

    9.구분 기호 문제 - # 1 원인 루트

    구분 기호 문제 - # 1 원인 루트

    우리는 문자열을 구분하는 인용 부호를 사용하며 문자열의 일부로, 그것은 불가능 때때로을 해석하기 때문에 SQL 주입이 가능합니다. 우리는 문자열 데이터에서 사용할 수 없습니다 구분 기호를 가지고 있다면, SQL 주입이 발생하지 못했네. 구분 기호의 문제를 해결하는 것은 SQL 주입 문제를 제거합니다. 구조 쿼리는 그렇게.

    근본 원인 # 2 - 인간의 자연, 사람들은 교활하고 일부 교활 사람들 악성 그리고 모든 사람들의 메이크업 실수

    SQL 주입의 다른 근본 원인은 인간의 본성이다. 프로그래머를 포함한 사람들은 실수를합니다. 당신은 구조화 된 쿼리에 실수를 할 때, SQL 주입 시스템이 취약하지 않습니다. 당신은 구조화 된 쿼리를 사용하지 않는 경우, 실수는 SQL 주입 취약점을 생성 할 수 있습니다.

    구조화 어떻게 쿼리는 SQL 주입의 근본 원인을 해결

    구조적 쿼리는 하나 개의 문장에서 SQL 명령을 넣어 별도의 프로그래밍 문에 데이터를 넣어으로 구분 문제를 해결합니다. 프로그래밍 문은 필요한 분리를 만들 수 있습니다.

    구조적 쿼리는 중요한 보안 구멍을 만드는 것을 인간의 오류를 방지합니다. 구조 쿼리를 사용할 때 실수를 인간에 관해서는, SQL 주입이 일어날 수 없습니다. 이 구조화 된 쿼리를 포함하지 않는 SQL 주입을 방지하는 방법이 있습니다,하지만 정상적인 인간의 오류가 SQL 주입 적어도 일부 노출에 일반적으로 리드를 접근한다. 구조적 쿼리는 SQL 주입으로부터 안전 실패 할 수 있습니다. 당신은 다른 프로그램과 동일한 구조 쿼리와 거의 세계의 모든 실수를 할 수 있지만, 당신이 만들 수 있다는 것도 SQL 주입에 의해 통해 찍은 ssstem로 전환 할 수 없습니다. 사람들은 SQL 주입을 방지하기 위해 올바른 방법입니다 말씀을 전합니다 이유입니다.

    그래서, 당신은 그것을 가지고가, SQL 주입의 원인과 그들이 사용하는 경우이를 불가능하게 자연을 구성 쿼리.

  10. from https://stackoverflow.com/questions/8263371/how-can-prepared-statements-protect-from-sql-injection-attacks by cc-by-sa and MIT license