복붙노트

[SQL] .NET에서 동적 SQL에서 살균 테이블 / 열 이름? (방지 SQL 인젝션)

SQL

.NET에서 동적 SQL에서 살균 테이블 / 열 이름? (방지 SQL 인젝션)

좀 동적 SQL을 생성하고 내 코드가 SQL 주입으로부터 안전한지 확인하고 싶습니다.

여기에 인수를 위해서가 생성되는 방법에 대한 최소한의 예입니다 :

var sql = string.Format("INSERT INTO {0} ({1}) VALUES (@value)",
    tableName, columnName);

위, TABLENAME이 COLUMNNAME이, 그리고 @value에 바인딩 어떤에서 신뢰할 수없는 소스에서 왔습니다. 자리를 사용하고 있기 때문에 @value은 SQL 주입 공격으로부터 안전하고, 무시할 수 있습니다. (명령은 SqlCommand를 통해 실행된다.)

그러나 TABLENAME 및 COLUMNNAME은 자리로 묶여 주입 공격에 취약 그에하다 할 수 없습니다. 이것을 "진정한 동적"시나리오 때문에, 가능한 TABLENAME 또는 COLUMNNAME 전혀 허용 된 사이트 목록이 없습니다.

문제는 이렇게이다 :

표준이 있는가, 내장 방법 및 / 또는 살균 TABLENAME 및 COLUMNNAME를 확인하려면? (등도록 SqlConnection, 또는 헬퍼 클래스)하지 않으면 제 3 자 라이브러리를 사용하지 않고이 작업을 수행 할 수있는 좋은 방법은 무엇입니까?

노트:

최신 정보:

그냥 이걸 발견하고 다소 재미라고 생각 : (? EF4) .NET4에서 SqlFunctions.QuoteName 기능이 있습니다. 좋아, 정말 나를 여기에 도움이되지 않습니다 ...

해결법

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

    1.당신은도록 SqlConnection을 사용하고 있기 때문에, 가정이는 SQL Server 데이터베이스 것입니다.

    당신은도록 SqlConnection을 사용하고 있기 때문에, 가정이는 SQL Server 데이터베이스 것입니다.

    그 가정을 감안할 때, 당신은 MSDN에 정의 된 SQL 서버 식별자 규칙을 다음과 정규 표현식을 사용하여 테이블과 필드 이름을 확인할 수 있습니다. 나는 정규 표현식에 완전하고 완전한 초보자 오전 동안, 나는 가까이 와야이 하나를 발견했다 :

    [\p{L}{\p{Nd}}$#_][\p{L}{\p{Nd}}@$#_]*
    

    그러나 정규 표현식은 SQL 서버 키워드를 해결하지 않으며 (당신이 더 큰 문제되지 않았 음을 표시 있지만) 그것은 테이블 및 / 또는 열이 실제로 존재하는지 확인하지 않습니다.

    이 내 응용 프로그램이라면, 내가 먼저 최종 사용자가 세미콜론을 포함 된 요청을 거부하여 주입을 수행하려는되지 않았습니다 보장 것이다 ().

    다음으로, 나는를 결정하기 위해 INFORMATION_SCHEMA.TABLES에 대해 쿼리를 스키마가 지정된 경우, 분할이 기간에 의해 테이블 ​​이름, 볼 ( '[,] ") 유효한 이름 구분 기호를 제거하고 실행하여 테이블의 존재를 확인할 것 테이블의 존재.

    예를 들면 :

    SELECT 1 
    FROM   INFORMATION_SCHEMA.TABLES 
    WHERE  TABLE_NAME = 'tablename' 
    AND    TABLE_SCHEMA = 'tableschema'
    

    당신이 매개 변수를 사용하여이 쿼리를 작성하는 경우, 당신은 더 주입으로부터 자신을 보호해야합니다.

    마지막으로, 단지 테이블이 유효하다고 판정 된 후에 컬럼 (들)의 타당성을 결정하기 INFORMATION_SCHEMA.COLUMNS을 사용하여 일련의 유사한 단계를 수행하여, 각 열 이름의 존재를 확인할 것이다.

    아마, SQL Server에서이 테이블 유효 열 목록을 가져 오는 각 요청 열이 내 코드 내 목록에되었는지 확인합니다. 그 방법은 오류에 있던 정확히 열을 말해 사용자에게 그 피드백을 제공 할 수있다.

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

    2.당신은 여전히이 조사하고 있는지 확실하지 않습니다,하지만 DbCommandBuilder 클래스는이 목적을위한 방법의 QuoteIdentifier을 제공합니다. 이것의 주요 이점은 그것이 데이터베이스에 의존하고 정규식 엉망 포함되지 않습니다.

    당신은 여전히이 조사하고 있는지 확실하지 않습니다,하지만 DbCommandBuilder 클래스는이 목적을위한 방법의 QuoteIdentifier을 제공합니다. 이것의 주요 이점은 그것이 데이터베이스에 의존하고 정규식 엉망 포함되지 않습니다.

    .NET 4.5으로, 당신은 당신이 당신 DbConnection 개체를 사용하여 위생적으로 테이블 및 열 이름을하는데 필요로하는 모든 것을 갖추고 있습니다 :

    DbConnection connection = GetMyConnection(); // Could be SqlConnection
    DbProviderFactory factory = DbProviderFactories.GetFactory(connection);
    
    // Sanitize the table name
    DbCommandBuilder commandBuilder = factory.CreateCommandBuilder();
    
    string tableName = "This Table Name Is Long And Bad";
    string sanitizedTableName = commandBuilder.QuoteIdentifier(tableName);
    
    IDbCommand command = connection.CreateCommand();
    command.CommandText = "SELECT * FROM " + sanitizedTableName;
    
    // Becomes 'SELECT * FROM [This Table Name Is Long And Bad]' in MS-SQL,
    // 'SELECT * FROM "This Table Name Is Long And Bad"' in Oracle, etc.
    

    (- 어쩌면 응용 프로그램 구성이나 하드 코딩 된 곳에서 데이터 공급자의 이름에서 사전 4.5, 당신은 당신의 DbProviderFactory를 얻을 수있는 다른 방법이 필요합니다.)

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

    3.SQL Server의 경우,이 식별자를 소독하기 위해 매우 간단합니다 :

    SQL Server의 경우,이 식별자를 소독하기 위해 매우 간단합니다 :

    // To make a string safe to use as an SQL identifier :
    // 1. Escape single closing bracket with double closing bracket
    // 2. Wrap in square brackets
    string.Format("[{0}]", identifier.Replace("]", "]]"));
    

    괄호에 싸여, 의지 식별자로하지 작업이 빈 / 널 (null) 문자열입니다 유일한 탈출하면.

  4. from https://stackoverflow.com/questions/9651582/sanitize-table-column-name-in-dynamic-sql-in-net-prevent-sql-injection-attack by cc-by-sa and MIT license