복붙노트

[SQL] 파라미터 문은 모든 SQL 주입을 중지 할 수 있습니까?

SQL

파라미터 문은 모든 SQL 주입을 중지 할 수 있습니까?

그렇다면, 왜 그렇게 많은 성공적인 SQL 인젝션은 여전히있다? 그냥 몇 가지 개발자가 매개 변수화 문을 사용하기에 너무 벙어리 때문에?

해결법

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

    1.나는이 질문에 대한 나의 의견에 게시했다고 링크는 아주 잘 문제를 설명합니다. 나는 아래, 왜 문제가이 지속에 내 감정을 정리했습니다 :

    나는이 질문에 대한 나의 의견에 게시했다고 링크는 아주 잘 문제를 설명합니다. 나는 아래, 왜 문제가이 지속에 내 감정을 정리했습니다 :

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

    2.그들은 자신을 모르는 가능성 때문에 - 기사 SQL 공격을 중지 매개 변수화 된 쿼리에 대해 말할 때 그들은 정말 "그것은, 왜 묻지 않는 않습니다"의 경우가 종종 이유, 설명하지 않습니다. 나쁜 교육자의 확실한 표시는 그들이 뭔가를 모르는 인정 할 수없는 일이다. 그러나 나는 탈선한다. 내가 말할 때 나는 혼동하는 완전히 이해할 수 간단하다 발견했다. 동적의 SQL 쿼리를 상상

    그들은 자신을 모르는 가능성 때문에 - 기사 SQL 공격을 중지 매개 변수화 된 쿼리에 대해 말할 때 그들은 정말 "그것은, 왜 묻지 않는 않습니다"의 경우가 종종 이유, 설명하지 않습니다. 나쁜 교육자의 확실한 표시는 그들이 뭔가를 모르는 인정 할 수없는 일이다. 그러나 나는 탈선한다. 내가 말할 때 나는 혼동하는 완전히 이해할 수 간단하다 발견했다. 동적의 SQL 쿼리를 상상

    sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password
    

    간단한 SQL 주입 될 수 있도록 바로 OR 1 = 1-- '로 사용자 이름을 넣어 이 효과적으로 SQL 쿼리를 만들 것입니다 :

    sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password
    

    이것은 그들이 이름이 참으로 동일시, 부울 인 ( '') 또는 1 = 1 비어있어 여기서 모든 고객을 선택했다. 그런 다음 사용 - 쿼리의 나머지 부분을 주석. 이것은 단지 모든 고객 테이블을 인쇄, 또는 로깅, 그것은 종종 관리자가 될 수있는 첫 번째 사용자의 권한으로 로그인 할 경우, 그것으로 원하는대로 할 것 그래서.

    이제 쿼리가 같은 코드와 다르게 그것을 할 파라미터 :

    sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
    
    parameters.add("User", username)
    parameters.add("Pass", password)
    

    여기서 사용자 이름과 암호는 관련 입력 된 사용자 이름과 암호를 가리키는 변수는

    지금이 시점에서, 당신이 전혀 아무것도 변경되지 않습니다, 생각 될 수있다. : 효과적으로 쿼리를 만드는 - 확실히 당신은 여전히 ​​아무도 OR 1 = 1 '과 같은 사용자 이름 필드 뭔가에 넣어 수

    sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
    

    그리고 이것은 유효한 인수처럼 보인다. 그러나, 당신은 잘못된 것입니다.

    방법 매개 변수가있는 쿼리 작업은 SQLQuery 인 쿼리로 전송되어 있으며, 데이터베이스는 다음이 쿼리를 수행 할 작업을 정확하게 알고, 그리고 것입니다 그것은 단순히 값으로 사용자 이름과 암호를 삽입합니다. 이 데이터베이스가 이미 쿼리를 수행 할 작업을 알고 있기 때문에 그들은, 쿼리에 영향을 수 없음을 의미합니다. 거짓을 제공해야하며, 빈 암호, - 그래서이 경우에는의 사용자 이름 "아무도 OR 1 = 1 '"를 찾을 것입니다.

    하지만 이것은 완전한 해결책이 아니라,이 같은 XSS 공격과 같은 다른 문제를 영향을 미치지 때문에 여전히 데이터베이스에 자바 스크립트를 넣을 수 있기 때문에 입력 검증은 여전히, 수행해야합니다. 이 페이지에 판독 경우, 어떤 출력 검증에 따라, 일반 자바 스크립트로 표시합니다. 그래서 정말 좋은 점은 여전히 ​​입력 유효성 검사를 사용하면된다, 그러나 어떤 SQL 공격을 중지 매개 변수화 된 쿼리 또는 저장 프로 시저를 사용합니다.

  3. ==============================

    3.그럼 좋은 질문입니다. 대답은 결정보다 더 확률 내가 작은 예제를 사용하여, 내 시야를 설명하려고합니다.

    그럼 좋은 질문입니다. 대답은 결정보다 더 확률 내가 작은 예제를 사용하여, 내 시야를 설명하려고합니다.

    이 우리의 조회에 매개 변수를 사용하거나 회피 SQL 인젝션 (SQLI)하기 위해 매개 변수를 저장 프로 시저를 사용하는 것이 좋습니다 그물에 많은 참조. 나는 SQLI에 대한 마법의 지팡이없는 당신에게 (예를 들어)이 저장 프로 시저를 표시합니다. 책임은 여전히 ​​프로그래머에 남아 있습니다.

    테이블 '사용자'에서 사용자 행을 얻을 것이다 저장 프로 시저 다음 SQL Server를 고려 :

    create procedure getUser
     @name varchar(20)
    ,@pass varchar(20)
    as
    declare @sql as nvarchar(512)
    set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
               'from Users '+
               'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
    execute(@sql)
    

    당신은 매개 변수로 사용자 이름과 암호를 전달하여 결과를 얻을 수 있습니다. 암호를 치죠 것은 정상적인 호출이 될 것이다 (다만이 예제의 편의를 위해) 무료 텍스트입니다 :

    DECLARE @RC int
    DECLARE @name varchar(20)
    DECLARE @pass varchar(20)
    
    EXECUTE @RC = [dbo].[getUser] 
       @name = 'admin'
      ,@pass = '!@Th1siSTheP@ssw0rd!!'
    GO
    

    그러나 여기서 우리는 공격자가 다음을 실행할 수 있도록, 저장 프로 시저 내부의 프로그래머가 사용하는 나쁜 프로그래밍 기술을 가지고 :

    DECLARE @RC int
    DECLARE @name varchar(20)
    DECLARE @pass varchar(20)
    
    EXECUTE @RC = [TestDB].[dbo].[getUser] 
       @name = 'admin'
      ,@pass = 'any'' OR 1=1 --'
    GO
    

    위의 매개 변수는 저장 프로 시저 및 마침내 실행될 SQL 명령에 인수로 전달 될 것입니다 :

    select usrID, usrUName, usrFullName, usrRoleID 
    from Users 
    where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'
    

    요식 사용자로부터 다시 모든 행을 얻을 것이다

    여기서 문제는 우리가 원칙을 따라도 "저장 프로 시저를 작성하고 매개 변수로 검색 할 필드를 통과"를 SQLI 여전히 수행된다는 점이다. 우리가 저장 프로 시저 내에서 우리의 나쁜 프로그래밍 연습을 복사하기 때문입니다. 이 문제에 대한 해결책은 다음과 같이 우리의 저장 프로 시저를 다시 작성하는 것입니다 :

    alter procedure getUser
     @name varchar(20)
    ,@pass varchar(20)
    as
    select usrID, usrUName, usrFullName, usrRoleID 
    from Users 
    where usrUName = @name and usrPass = @pass
    

    내가 말하려고하는 것은 개발자가 SQLI 공격이 그에 따라 자신의 코드를 보호하기 위해 다음과 방법을 수행 할 수 있으며, 무엇을 먼저 배워야한다는 것입니다. 맹목적으로 '모범 사례'를 다음 항상 안전한 방법이 아니다 ... 우리는 너무 많은 '최고의 practices'- 실패를 왜 어쩌면이입니다!

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

    4.예, 준비된 명령문의 사용은 적어도 이론적으로는 모든 SQL 주입을 중지합니다. 실제로, 파라미터 문은 예를 들어, 실제 준비된 명령문,하지 않을 수 있습니다 이 가장자리의 경우 공격에 노출 그래서 PHP의 PDO는 기본적으로 그것들을 에뮬레이트합니다.

    예, 준비된 명령문의 사용은 적어도 이론적으로는 모든 SQL 주입을 중지합니다. 실제로, 파라미터 문은 예를 들어, 실제 준비된 명령문,하지 않을 수 있습니다 이 가장자리의 경우 공격에 노출 그래서 PHP의 PDO는 기본적으로 그것들을 에뮬레이트합니다.

    당신이 진짜 준비된 문을 사용하는 경우, 모든 것이 안전합니다. 음, 같은 당신이 예를 들어 테이블 이름을 준비 할 수없는 대한 반응으로 쿼리로하지 CONCATENATE 안전하지 않은 SQL을 같이 적어도.

    예, 교육의 주요 포인트는 여기에, 그리고 레거시 코드베이스. 많은 자습서 탈출 사용하고 사람들은 쉽게 불행하게도, 웹에서 제거 할 수 없습니다.

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

    5.나는 프로그래밍 절대하지 않도록; 예외는 항상있다. 내가보기 엔 저장 프로 시저 및 명령 객체를 권장합니다. 내 다시 땅의 대부분은 SQL Server와 함께,하지만 난 때때로 MySQL과 게임을한다. 캐시 된 쿼리 계획을 포함하여 저장 프로 시저에 많은 이점이있다; 예,이 매개 변수와 인라인 SQL로 수행 할 수 있습니다,하지만 주입 공격에 대한 더 많은 가능성을 열어과의 분리에 도움이되지 않습니다. 내 응용 프로그램은 일반적으로 단지 저장 프로 시저를 밝혔다에 대한 실행 권한이 나를 위해 그것은 데이터베이스를 확보하는 것이 훨씬 쉽다. 직접 테이블 /보기 권한이 없이는 아무것도 주입하는 것이 훨씬 더 어렵다. 응용 프로그램의 사용자가 하나가 손상된 경우에만 미리 정의 된 정확하게 실행할 수있는 권한이있다.

    나는 프로그래밍 절대하지 않도록; 예외는 항상있다. 내가보기 엔 저장 프로 시저 및 명령 객체를 권장합니다. 내 다시 땅의 대부분은 SQL Server와 함께,하지만 난 때때로 MySQL과 게임을한다. 캐시 된 쿼리 계획을 포함하여 저장 프로 시저에 많은 이점이있다; 예,이 매개 변수와 인라인 SQL로 수행 할 수 있습니다,하지만 주입 공격에 대한 더 많은 가능성을 열어과의 분리에 도움이되지 않습니다. 내 응용 프로그램은 일반적으로 단지 저장 프로 시저를 밝혔다에 대한 실행 권한이 나를 위해 그것은 데이터베이스를 확보하는 것이 훨씬 쉽다. 직접 테이블 /보기 권한이 없이는 아무것도 주입하는 것이 훨씬 더 어렵다. 응용 프로그램의 사용자가 하나가 손상된 경우에만 미리 정의 된 정확하게 실행할 수있는 권한이있다.

    내 두 센트.

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

    6.나는 "바보"언급하지 않았다.

    나는 "바보"언급하지 않았다.

    나는 자습서 문제를 생각합니다. 인라인 값으로 SQL을 설명 어떤 대부분의 SQL 자습서, 책, 전혀 바인드 매개 변수를 언급하지. 이 자습서에서 배우는 사람들은 바로 그것을 배울 수있는 기회가 없습니다.

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

    7.대부분의 코드는 보안을 염두에두고, 관리 작성 기능을 (팔 수있는 볼 특히 뭔가)와 (훨씬 더 열심히 판매입니다) 보안 / 안정성 / 신뢰성을 추가하는 사이에 선택의 여지가 주어지지 않기 때문에 그들은 거의 변함를 선택합니다 전자. 보안은 문제가된다 단지 관심사입니다.

    대부분의 코드는 보안을 염두에두고, 관리 작성 기능을 (팔 수있는 볼 특히 뭔가)와 (훨씬 더 열심히 판매입니다) 보안 / 안정성 / 신뢰성을 추가하는 사이에 선택의 여지가 주어지지 않기 때문에 그들은 거의 변함를 선택합니다 전자. 보안은 문제가된다 단지 관심사입니다.

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

    8.예, 한 데이터베이스 드라이버 제공 가능한 모든 SQL의 문자에 대한 자리 표시로. 대부분의 준비된 명령문 드라이버는하지 않습니다. 말, 당신은 필드 이름 또는 값의 배열에 대한 자리를 찾을 수 없을 것입니다. 어느 손으로 쿼리를 맞게 연결 수동으로 포맷을 사용하여 다시 떨어 개발자를 만들 것입니다. 예측 결과에.

    예, 한 데이터베이스 드라이버 제공 가능한 모든 SQL의 문자에 대한 자리 표시로. 대부분의 준비된 명령문 드라이버는하지 않습니다. 말, 당신은 필드 이름 또는 값의 배열에 대한 자리를 찾을 수 없을 것입니다. 어느 손으로 쿼리를 맞게 연결 수동으로 포맷을 사용하여 다시 떨어 개발자를 만들 것입니다. 예측 결과에.

    그건 내가 PHP 내 MySQL의 래퍼를 만든 이유가 지원하는 대부분의 배열과 식별자를 포함하여, 동적 쿼리에 추가 할 수 있습니다 리터럴.

    당신이 볼 수 있듯이, 실제로는 당신이 바보하지 않은 경우에도 모든 쿼리 파라미터가 그냥 불가능합니다.

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

    9.먼저 첫 번째 질문에 대한 내 대답은 : 네, 지금까지의 내가 아는 한, 매개 변수화 된 쿼리를 사용하여, SQL 인젝션은 더 이상 할 수 없습니다. 당신의 다음 질문에, 나는 모르겠습니다 만 이유에 당신에게 내 의견을 제공 할 수 있습니다 :

    먼저 첫 번째 질문에 대한 내 대답은 : 네, 지금까지의 내가 아는 한, 매개 변수화 된 쿼리를 사용하여, SQL 인젝션은 더 이상 할 수 없습니다. 당신의 다음 질문에, 나는 모르겠습니다 만 이유에 당신에게 내 의견을 제공 할 수 있습니다 :

    나는 그것이보다 쉽게 ​​생각 값이 삽입으로 "그냥"(어떤 논리적 인 점검에 어쩌면 따라 다름) 일부 다른 부분 함께 CONCATENATE으로 SQL 쿼리 문자열을 작성합니다. 그냥 쿼리를 생성하고 실행합니다. 또 다른 장점은 (에코, 출력 또는 무엇이든) SQL 쿼리 문자열을 인쇄 한 후 데이터베이스 엔진에 수동 쿼리 문자열을 사용할 수 있다는 것입니다.

    준비된 문 작업 할 때, 당신은 항상 적어도 한 단계 더있다 : 당신은 (물론, 매개 변수 포함) 쿼리를 작성해야 당신은 서버에 쿼리를 준비해야 당신은 당신의 쿼리에 사용할 실제 값으로 매개 변수를 바인드 할 필요가 당신은 쿼리를 실행해야합니다.

    즉 다소 특히 종종 매우 수명이 긴 것을 입증 일부 "신속하고 더러운"작업에 대한 더 많은 작업 (프로그램에 그렇게 간단하지)의 ...

    친애하는,

    상자

  10. ==============================

    10.SQL 인젝션에서 응용 프로그램을 보호하려면 다음 단계를 수행합니다 :

    SQL 인젝션에서 응용 프로그램을 보호하려면 다음 단계를 수행합니다 :

    1. 구속 입력 단계. 저장 프로 시저 2. 매개 변수를 단계. 단계 동적 SQL과 3. 매개 변수를 설정합니다.

    http://msdn.microsoft.com/en-us/library/ff648339.aspx 참조

  11. ==============================

    11.SQL 인젝션 데이터와 코드가 동일한 채널을 통해 제공되며, 데이터 코드 착각 코드 주입의 큰 문제점의 일부이다. 데이터이고 코드가 무엇 무엇을 매개 변수화 된 쿼리에 대한 컨텍스트를 사용하여 쿼리를 형성하여이를 방지.

    SQL 인젝션 데이터와 코드가 동일한 채널을 통해 제공되며, 데이터 코드 착각 코드 주입의 큰 문제점의 일부이다. 데이터이고 코드가 무엇 무엇을 매개 변수화 된 쿼리에 대한 컨텍스트를 사용하여 쿼리를 형성하여이를 방지.

    일부 특정의 경우에,이 충분하지 않습니다. 다수의 DBMS에서는 동적 DBMS 레벨에서 SQL 인젝션 결함을 도입하여 SQL 프로 시저를 실행하는 것이 가능하다. 악용되는 과정에서 SQL 주입을 방지하지 않습니다 매개 변수화 된 쿼리를 사용하여 이러한 저장 프로 시저를 호출. 또 다른 예는이 블로그 포스트에서 볼 수 있습니다.

    더 일반적으로, 개발자는 잘못 기능을 사용합니다. 제대로 완료되면 일반적으로 코드는 다음과 같은 :

    db.parameterize_query("select foo from bar where baz = '?'", user_input)
    

    일부 개발자들은 실제로 우리가 찾고있는 안전 보장을 제공하는 상기 데이터 / 코드 구분을하지 않는 매개 변수가있는 쿼리를 함께 문자열을 연결 한 후 사용합니다 :

    db.parameterize_query("select foo from bar where baz = '" + user_input + "'")
    

    매개 변수화 된 쿼리의 올바른 사용은 SQL 주입 공격에 대한 매우 강한,하지만 꿰 뚫을 수없는, 보호 기능을 제공합니다.

  12. ==============================

    12.설사 준비된 문이 제대로 전반에 걸쳐 사용되는 웹 응용 프로그램의 자신의 코드, SQL 주입 취약점은 여전히 ​​존재하는 경우 데이터베이스 코드 구성 요소 구조 안전하지 않은 방식으로 사용자 입력으로부터 질의. 다음은 SQL에 취약 저장 프로 시저의 예입니다 @name 파라미터 주사 :

    설사 준비된 문이 제대로 전반에 걸쳐 사용되는 웹 응용 프로그램의 자신의 코드, SQL 주입 취약점은 여전히 ​​존재하는 경우 데이터베이스 코드 구성 요소 구조 안전하지 않은 방식으로 사용자 입력으로부터 질의. 다음은 SQL에 취약 저장 프로 시저의 예입니다 @name 파라미터 주사 :

    CREATE PROCEDURE show_current_orders
    (@name varchar(400) = NULL)
    AS
    DECLARE @sql nvarchar(4000)
    SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
    ‘searchstring = ‘’’ + @name + ‘’’’;
    EXEC (@sql)
    GO
    

    어플리케이션은 저장에 사용자 제공 이름 값을 통과하더라도 안전한 방식으로 절차는 절차 자체는 바로이 점을 연결합니다 따라서 동적 쿼리 및 취약합니다.

  13. from https://stackoverflow.com/questions/6786034/can-parameterized-statement-stop-all-sql-injection by cc-by-sa and MIT license