매개 변수없이 SQL 주입 방지


109

여기서는 코드에서 매개 변수화 된 SQL 쿼리를 사용하는 방법에 대해 또 다른 논의를하고 있습니다. 토론에는 두 가지 측면이 있습니다. 나와 다른 사람들은 항상 매개 변수를 사용하여 SQL 주입으로부터 보호해야한다고 말하는 사람과 필요하다고 생각하지 않는 다른 사람을 말합니다. 대신 SQL 삽입을 피하기 위해 모든 문자열에서 단일 아포스트로피를 두 개의 아포스트로피로 바꾸려고합니다. 우리의 데이터베이스는 모두 Sql Server 2005 또는 2008을 실행하고 있으며 코드베이스는 .NET Framework 2.0에서 실행됩니다.

C #으로 간단한 예를 들어 보겠습니다.

나는 이것을 사용하기를 원한다.

string sql = "SELECT * FROM Users WHERE Name=@name";
SqlCommand getUser = new SqlCommand(sql, connection);
getUser.Parameters.AddWithValue("@name", userName);
//... blabla - do something here, this is safe

다른 사람들은 이것을하기를 원하지만 :

string sql = "SELECT * FROM Users WHERE Name=" + SafeDBString(name);
SqlCommand getUser = new SqlCommand(sql, connection);
//... blabla - are we safe now?

SafeDBString 함수는 다음과 같이 정의됩니다.

string SafeDBString(string inputValue) 
{
    return "'" + inputValue.Replace("'", "''") + "'";
}

이제 쿼리의 모든 문자열 값에 SafeDBString을 사용하는 한 안전해야합니다. 권리?

SafeDBString 함수를 사용하는 데는 두 가지 이유가 있습니다. 첫 번째는 석기 시대부터 수행 된 방식이고 두 번째는 데이터베이스에서 실행되는 정확한 쿼리를 볼 수 있기 때문에 SQL 문을 디버그하는 것이 더 쉽습니다.

그럼. 내 질문은 SQL 주입 공격을 피하기 위해 SafeDBString 함수를 사용하는 것이 실제로 충분한 지 여부입니다. 이 안전 조치를 위반하는 코드의 예를 찾으려고 노력했지만 그 예를 찾을 수 없습니다.

이걸 깰 수있는 사람이 있나요? 어떻게 하시겠습니까?

편집 : 지금까지 회신을 요약하려면 :

  • 아직 Sql Server 2005 또는 2008에서 SafeDBString을 다루는 방법을 찾지 못했습니다. 좋은 것 같아요?
  • 여러 응답에서 매개 변수화 된 쿼리를 사용할 때 성능 향상을 얻을 수 있다고 지적했습니다. 그 이유는 쿼리 계획을 재사용 할 수 있기 때문입니다.
  • 또한 매개 변수화 된 쿼리를 사용하면 유지 관리하기 쉬운 더 읽기 쉬운 코드가 제공된다는 데 동의합니다.
  • 또한 다양한 버전의 SafeDBString, 문자열에서 숫자로의 변환 및 문자열에서 날짜로의 변환을 사용하는 것보다 항상 매개 변수를 사용하는 것이 더 쉽습니다.
  • 매개 변수를 사용하면 날짜 나 십진수로 작업 할 때 특히 유용한 자동 유형 변환을 얻을 수 있습니다.
  • 그리고 마지막 으로 JulianR이 쓴 것처럼 스스로 보안을 시도하지 마십시오 . 데이터베이스 공급 업체는 보안에 많은 시간과 비용을 소비합니다. 우리가 더 잘할 수있는 방법은 없으며 그들의 일을하려고 노력해야 할 이유도 없습니다.

그래서 아무도 SafeDBString 함수의 간단한 보안을 깰 수 없었지만 다른 많은 좋은 주장을했습니다. 감사!


16
당신의 동료들은 아주 멀리 떨어져 있습니다. 그들에게 자신의 입장을 뒷받침하는 한 권의 문헌을 찾도록 도전하십시오. 신석기 전의 주장은 우스꽝스럽고 상황이 바뀌고 석기 시대에 갇힌 사람 만이 적응하지 못할 것입니다.
annakata

1
글쎄요, 적어도 당신의 동료들은 서로 다른 형태의 해킹 중 하나로부터 보호합니다 ... 그들은 모든 매개 변수화 된 쿼리가 작동한다고 확신합니까? (나는 아닙니다 ...)
Arjan Einbu

1
어떤 취약점도 그들을 설득하지 못합니다. 여러 가지 취약점 (요구하는 것) 및 기타 문제를 가져와 매개 변수가 해당 문제를 해결하고 팀이 기능의 일부를 제공하기 위해 엄청난 양의 코드를 작성해야한다는 점을 하나씩 지적하는 경우 그들을이기십시오. 행운을 빕니다.
Robert Gowland

3
작은 따옴표가 없어도 논리로 코드를 끊을 수 있습니다. 사용자 이름 "test OR 1 = 1"을 사용해보십시오. 사용자 이름 test가있는 행만이 아니라 모든 행이 반환됩니다!
Bridge

1
한숨. 저는 업계로서 우리가 이런 종류의 비전문적 인 행동을 계속해서 용인하는 방법을 이해하지 못합니다.
jeroenh

답변:


83

정답은 다음과 같습니다.

스스로 보안을 시도하지 마십시오 . 신뢰할 수있는 어떤 사용은 업계 표준 라이브러리는 당신이해야 할 노력보다는하는지에 사용할 수 있습니다 노력하고 그것을 스스로 할 수 있습니다. 보안에 대해 어떤 가정을하든 틀릴 수 있습니다. 자신의 접근 방식이 안전 해 보이지만 (기껏해야 흔들리는 것처럼 보임) 무언가를 간과하고있는 위험이 있으며 보안과 관련하여 그 기회를 정말로 취하고 싶습니까?

매개 변수를 사용하십시오.


Re "신뢰할 수있는 업계 표준 라이브러리를 사용하십시오"-.NET 용으로 추천 할 수 있습니까? DB에 따라 둘 이상 : SQLServer, MySQL, PostgreSQL? 나는 SQL-sanitizer를 찾았지만 운이 좋지 않았기 때문에 가능한 한 최선을 다해 내 자신의 것을 구현해야했습니다 (의심의 여지가 없습니다).
PSU

72

그리고 누군가가 가서 '대신 "를 사용합니다. 매개 변수는 IMO, 유일한 안전한 방법입니다.

또한 날짜 / 숫자에 대한 많은 i18n 문제를 방지합니다. 01/02/03은 언제입니까? 123,456은 얼마입니까? 서버 (app-server 및 db-server)가 서로 동의합니까?

위험 요소가 설득력이 없다면 성능은 어떻습니까? RDBMS는 매개 변수를 사용하면 쿼리 계획을 재사용하여 성능을 향상시킬 수 있습니다. 문자열만으로는 이것을 할 수 없습니다.


나는 포맷팅과 성능 논쟁을 시도했지만 여전히 확신하지 못한다.
Rune Grimstad

5
실제로 SQL Server는 매개 변수 사용 여부에 관계없이 쿼리 계획을 다시 사용할 수 있습니다. 다른 주장에 동의하지만 대부분의 경우 매개 변수화 된 SQL에 대한 성능 주장은 더 이상 작동하지 않습니다.
tnyfst

1
@tnyfst : 매개 변수 값의 모든 조합에 대해 쿼리 문자열이 변경 될 때 실행 계획을 재사용 할 수 있습니까? 나는 그것이 가능하다고 생각하지 않았습니다.
John Saunders

4
쿼리 텍스트가 이전 쿼리 텍스트와 동일하면 쿼리 계획이 재사용됩니다. 따라서 EXACT SAME 쿼리를 두 번 보내면 다시 사용됩니다. 그러나 공백이나 쉼표 등 만 변경하면 새로운 쿼리 계획을 결정해야합니다.
marc_s

1
@Marc : 나는 당신이 완전히 옳다고 확신하지 않습니다. SQL Server 캐싱 휴리스틱은 약간 이상합니다. 구문 분석기는 텍스트에서 상수를 식별 할 수 있으며 SQL 문자열을 인위적으로 사용 매개 변수로 변환 할 수 있습니다. 그런 다음이 새로운 매개 변수화 된 쿼리의 텍스트를 캐시에 삽입 할 수 있습니다. 후속 유사한 SQL은 캐시에서 일치하는 매개 변수화 된 버전을 찾을 수 있습니다. 그러나 매개 변수화 된 버전이 원래 SQL 버전이 캐시되는 대신 항상 사용되는 것은 아닙니다. SQL이 두 가지 접근 방식 중에서 선택해야하는 엄청난 성능 관련 이유가 있다고 생각합니다.
AnthonyWJones

27

논쟁은 승리하지 않습니다. 취약점을 찾아 내면 동료는 SafeDBString 함수를 변경하여이를 설명한 다음 다시 안전하지 않다는 것을 증명하도록 요청할 것입니다.

매개 변수화 된 쿼리가 확실한 프로그래밍 모범 사례라는 점을 감안할 때 더 안전하고 성능이 좋은 방법을 사용하지 않는 이유를 설명하는 데에는 증명의 부담이 있어야합니다.

문제가 모든 레거시 코드를 다시 작성하는 것이라면 모든 새 코드에서 매개 변수화 된 쿼리를 사용하고 해당 코드에서 작업 할 때 이전 코드를 사용하도록 리팩토링하는 것이 쉬운 방법입니다.

제 생각에는 실제 문제는 자부심과 고집입니다. 그리고 그것에 대해 당신이 할 수있는 일이별로 없습니다.


19

우선, "교체"버전의 샘플이 잘못되었습니다. 텍스트 주위에 아포스트로피를 넣어야합니다.

string sql = "SELECT * FROM Users WHERE Name='" + SafeDBString(name) & "'";
SqlCommand getUser = new SqlCommand(sql, connection);

이것이 매개 변수가하는 또 다른 일입니다. 값을 따옴표로 묶어야하는지 여부에 대해 걱정할 필요가 없습니다. 물론이를 함수에 빌드 할 수는 있지만 함수에 많은 복잡성을 추가해야합니다. 'NULL'을 null로, 'NULL'을 문자열로 또는 숫자와 숫자 사이의 차이를 아는 방법 많은 숫자를 포함하는 문자열입니다. 버그의 또 다른 소스 일뿐입니다.

또 다른 한 가지는 성능입니다. 매개 변수화 된 쿼리 계획은 종종 연결된 계획보다 더 잘 캐시되므로 쿼리를 실행할 때 서버를 한 단계 절약 할 수 있습니다.

또한 작은 따옴표를 이스케이프하는 것만으로는 충분하지 않습니다. 많은 DB 제품은 공격자가 이용할 수있는 문자 이스케이프를위한 대체 방법을 허용합니다. 예를 들어 MySQL에서는 백 슬래시로 작은 따옴표를 이스케이프 할 수도 있습니다. 그래서 다음 "name"값은 SafeDBString()함수 만으로 MySQL을 날려 버릴 것입니다 . 작은 따옴표를 두 배로하면 첫 번째는 여전히 백 슬래시로 이스케이프되어 두 번째는 "활성"상태가되기 때문입니다.

x \ 'OR 1 = 1;-


또한 JulianR은 아래에 좋은 점을 제시합니다. 절대로 보안 작업을 직접 시도하지 마십시오 . 그것은 미묘한 방법으로 보안 프로그래밍 잘못 너무 쉽게 표시를철저한 테스트를 거쳐도 작동 . 그런 다음 시간이 지나고 1 년이 지난 후 6 개월 전에 시스템에 금이 갔음을 알게되었고 그때까지는 알지 못했습니다.

항상 플랫폼에 제공되는 보안 라이브러리에 최대한 의존하십시오. 그들은 생계를 위해 보안 코드를 수행하는 사람들이 작성하고, 관리 할 수있는 것보다 훨씬 더 잘 테스트되며, 취약점이 발견되면 공급 업체에서 서비스를받습니다.


5
대체 기능은 아포스트로피를 추가합니다
Rune Grimstad

5
그러면 버그의 또 다른 원인 일뿐입니다. NULL을 null 값으로 사용하는 것과 NULL을 텍스트 문자열로 사용하는 것의 차이점을 어떻게 알 수 있습니까? 아니면 숫자 입력과 숫자를 포함하는 문자열 사이?
Joel Coehoorn

좋은 지적. 문자열과 날짜에 대해서만 함수를 사용해야하므로주의해야합니다. 이것이 매개 변수를 사용하는 또 다른 이유입니다! 예이!
Rune Grimstad

10

그래서 다음과 같이 말합니다.

1) 내장 된 항목을 다시 구현하려는 이유는 무엇입니까? 바로 사용할 수 있고 사용하기 쉬우 며 이미 글로벌 규모로 디버깅되었습니다. 향후 버그가 발견되면 아무 작업도하지 않아도 매우 빠르게 수정되어 모든 사람이 사용할 수 있습니다.

2)에 자리에없는 어떤 프로세스를 보장 당신이 결코 SafeDBString에 전화를 그리워? 단 한 곳에서 놓치면 전체 문제가 발생할 수 있습니다. 이러한 것들을 얼마나 눈에 띄게 할 것이며, 받아 들여진 정답을 쉽게 찾을 수있을 때 그 노력이 얼마나 낭비되는지 고려하십시오.

3) Microsoft (DB 및 액세스 라이브러리 작성자)가 SafeDBString 구현에서 알고있는 모든 공격 벡터를 얼마나 확실하게 처리 했습니까?

4) SQL의 구조를 읽는 것이 얼마나 쉬운가? 이 예제에서는 + 연결을 사용하고 매개 변수는 더 읽기 쉬운 string.Format과 매우 유사합니다.

또한 실제로 실행 된 것을 알아내는 방법에는 두 가지가 있습니다. 자체 LogCommand 함수, 보안 문제없는 간단한 함수 , 또는 데이터베이스가 실제로 진행되고 있다고 생각하는 작업을 파악하기 위해 SQL 추적을 살펴보세요.

LogCommand 함수는 간단합니다.

    string LogCommand(SqlCommand cmd)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine(cmd.CommandText);
        foreach (SqlParameter param in cmd.Parameters)
        {
            sb.Append(param.ToString());
            sb.Append(" = \"");
            sb.Append(param.Value.ToString());
            sb.AppendLine("\"");
        }
        return sb.ToString();
    }

옳든 그르 든, 보안 문제없이 필요한 정보를 제공합니다.


1
그는 아마도 문자열 연결을 통해 XML과 SQL을 포함한 모든 작업을 수행하는 데 익숙한 오래된 VBSCRIPT 프로그래머 무리를 다루어야 할 것입니다. 이들은 API 사용에 두려워하는 사람들이 될 것입니다. 그들과 함께 할 수있는 일은 많지 않습니다. 적어도 인간적인 것은 없습니다.
John Saunders

1
실제 매개 변수를 적용 할 방법이 없다는 점을 제외하고 항목 # 2에 +1.
Joel Coehoorn

7

매개 변수화 된 쿼리를 사용하면 SQL 주입에 대한 보호 이상의 기능을 얻을 수 있습니다. 또한 더 나은 실행 계획 캐싱 가능성을 얻을 수 있습니다. SQL Server 쿼리 프로파일 러를 사용하는 경우 '데이터베이스에서 실행되는 정확한 SQL'을 계속 볼 수 있으므로 SQL 문을 디버깅하는 측면에서도 실제로 손실되는 일이 없습니다.


MySQL은 매개 변수 값이 삽입 된 매개 변수화 된 쿼리도 기록합니다.
Bill Karwin

5

저는 SQL 주입 공격을 피하기 위해 두 가지 접근 방식을 모두 사용했으며 확실히 매개 변수화 된 쿼리를 선호합니다. 연결된 쿼리를 사용했을 때 라이브러리 함수를 사용하여 변수 (mysql_real_escape_string과 같은)를 이스케이프 처리했으며 독점 ​​구현에서 모든 것을 다루었 음을 확신하지 못할 것입니다 (당신도 그렇듯이).


2
mysql_real_escape_string ()이 \ x00, \ x1a, \ n \ r '및 "을 이스케이프하기 때문에 +1. 또한 문자 집합 문제도 처리합니다. OP의 동료 순진한 함수는 그 어떤 것도 수행하지 않습니다!
Bill Karwin

4

매개 변수를 사용하지 않고는 사용자 입력의 유형 검사를 쉽게 수행 할 수 없습니다.

SQLCommand 및 SQLParameter 클래스를 사용하여 DB 호출을 수행하는 경우 실행중인 SQL 쿼리를 계속 볼 수 있습니다. SQLCommand의 CommandText 속성을 살펴보십시오.

저는 매개 변수화 된 쿼리가 사용하기 매우 쉬울 때 SQL 주입을 방지하는 롤-자신 만의 접근 방식을 항상 의심합니다. 둘째, "항상 그렇게 해왔다"고해서 그것이 올바른 방법이라는 의미는 아닙니다.


3

이것은 당신이 문자열을 전달할 것이라는 것이 보장되는 경우에만 안전합니다.

어떤 지점에서 문자열을 전달하지 않으면 어떨까요? 숫자 만 전달하면 어떨까요?

http://www.mywebsite.com/profile/?id=7;DROP DATABASE DB

궁극적으로 :

SELECT * FROM DB WHERE Id = 7;DROP DATABASE DB

문자열 또는 숫자입니다. 문자열은 SafeDbString으로 이스케이프됩니다. 숫자는 Int32이며 데이터베이스를 삭제할 수 없습니다.
Andomar

숫자는 다루기가 더 쉽습니다. 쿼리에서 사용하기 전에 매개 변수를 int / float / whatever로 변환하기 만하면됩니다. 문제는 문자열 데이터를 받아야 할 때입니다.
Rune Grimstad

Andomar-손으로 SQL 문을 구성하는 경우 의도 된 "유형"은 중요하지 않습니다. SQL에 숫자를 매우 쉽게 삽입 할 수 있습니다. 룬-이것은 SQL 주입을 수동으로 해결하는 모든 뉘앙스를 기억하기 위해 개별 개발자에게 너무 많이 의존하고 있다고 생각합니다. "매개 변수 사용"이라고 말하면 매우 간단하며 잘못 될 수 없습니다.
joshcomley

@Andomar : NULL은 어떻습니까? 아니면 숫자처럼 보이는 문자열?
Joel Coehoorn

2

모든 것에 저장 프로 시저 또는 함수를 사용하므로 질문이 발생하지 않습니다.

SQL을 코드에 넣어야하는 곳에서는 매개 변수를 사용합니다. 반대자들에게 자신보다 현명한 해커가 있고 그들을 능가하려는 코드를 깨는 더 나은 인센티브를 가지고 있음을 상기 시키십시오. 매개 변수를 사용하면 불가능하며 어렵지 않습니다.


좋아, 매개 변수를 사용하여 SQL 주입을 수행하는 방법은 무엇입니까?
John Saunders

@Saunders : 1 단계는 DB의 매개 변수 처리 기능에서 버퍼 오버 플로우 버그를 찾는 것입니다.
Brian

2
아직 찾았나요? 매일 수십만 명의 해커가 공격하는 상업용 DB에서? 주머니가 매우 깊다고 알려진 소프트웨어 회사에서 만든 것? 가능하다면 이름으로 소송을 인용 할 수 있습니다.
John Saunders

1
물론 SPROC가 sp_ExecuteSQL 대신 연결 및 EXEC를 사용하는 경우 문제가 다시 발생합니다 ... (너무 많이 잘못해서 할인을받을 수 없습니다 ...)
Marc Gravell

2

보안 문제에 대해 크게 동의합니다.
매개 변수를 사용하는 또 다른 이유는 효율성 때문입니다.

데이터베이스는 항상 쿼리를 컴파일하고 캐시 한 다음 캐시 된 쿼리를 재사용합니다 (이는 후속 요청에 대해 분명히 더 빠름). 매개 변수를 사용하는 경우 다른 매개 변수를 사용하더라도 데이터베이스는 매개 변수를 바인딩하기 전에 SQL 문자열을 기반으로 일치하므로 캐시 된 쿼리를 재사용합니다.

그러나 매개 변수를 바인딩하지 않으면 SQL 문자열이 모든 요청 (다른 매개 변수가 있음)에서 변경되며 캐시에있는 것과 일치하지 않습니다.


2

이미 주어진 이유 때문에 매개 변수는 아주 좋은 생각입니다. 그러나 매개 변수를 만들고 나중에 쿼리에서 사용하기 위해 변수에 이름을 할당하는 것은 삼중 간접 문제이므로 사용하는 것을 싫어합니다.

다음 클래스는 SQL 요청을 빌드하는 데 일반적으로 사용할 stringbuilder를 래핑합니다. 그것은 당신이 할 수 적 매개 변수를 만들 필요없이 paramaterized 쿼리를 작성 하면 SQL에 집중할 수 있습니다. 코드는 다음과 같습니다.

var bldr = new SqlBuilder( myCommand );
bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId, SqlDbType.Int);
//or
bldr.Append("SELECT * FROM CUSTOMERS WHERE NAME LIKE ").FuzzyValue(myName, SqlDbType.NVarChar);
myCommand.CommandText = bldr.ToString();

동의하길 바랍니다. 코드 가독성이 크게 향상되었으며 출력은 적절한 매개 변수화 된 쿼리입니다.

수업은 다음과 같습니다.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace myNamespace
{
    /// <summary>
    /// Pour le confort et le bonheur, cette classe remplace StringBuilder pour la construction
    /// des requêtes SQL, avec l'avantage qu'elle gère la création des paramètres via la méthode
    /// Value().
    /// </summary>
    public class SqlBuilder
    {
        private StringBuilder _rq;
        private SqlCommand _cmd;
        private int _seq;
        public SqlBuilder(SqlCommand cmd)
        {
            _rq = new StringBuilder();
            _cmd = cmd;
            _seq = 0;
        }
        //Les autres surcharges de StringBuilder peuvent être implémenté ici de la même façon, au besoin.
        public SqlBuilder Append(String str)
        {
            _rq.Append(str);
            return this;
        }
        /// <summary>
        /// Ajoute une valeur runtime à la requête, via un paramètre.
        /// </summary>
        /// <param name="value">La valeur à renseigner dans la requête</param>
        /// <param name="type">Le DBType à utiliser pour la création du paramètre. Se référer au type de la colonne cible.</param>
        public SqlBuilder Value(Object value, SqlDbType type)
        {
            //get param name
            string paramName = "@SqlBuilderParam" + _seq++;
            //append condition to query
            _rq.Append(paramName);
            _cmd.Parameters.Add(paramName, type).Value = value;
            return this;
        }
        public SqlBuilder FuzzyValue(Object value, SqlDbType type)
        {
            //get param name
            string paramName = "@SqlBuilderParam" + _seq++;
            //append condition to query
            _rq.Append("'%' + " + paramName + " + '%'");
            _cmd.Parameters.Add(paramName, type).Value = value;
            return this; 
        }

        public override string ToString()
        {
            return _rq.ToString();
        }
    }
}

1

아주 짧은 시간 동안 SQL 주입 문제를 조사해야했기 때문에 '안전한'값을 만드는 것은 실제로 데이터에 아포스트로피를 넣을 수있는 상황에 대한 문을 닫는다는 의미이기도합니다. 누군가의 이름은 어떻습니까? , 예 : O'Reilly.

그러면 매개 변수와 저장 프로 시저가 남습니다.

그리고 예, 항상 코드가 항상 수행되는 방식뿐만 아니라 지금 알고있는 가장 좋은 방식으로 코드를 구현해야합니다.


이중 아포스트로피는 SQL 서버에서 단일 아포스트로피로 변환되므로 O'Reilly는 Name = 'O''Reilly'로 변환됩니다.
Rune Grimstad

그렇다면 사용자가 데이터를보고 싶을 때 아포스트로피를 제거하는 해당 기능이 있습니까?
quamrana

필요 없음. 이스케이프 시퀀스를 사용하면 구문 분석기가 문자열의 끝이 아닌 작은 따옴표를 볼 수 있습니다. 파싱 ​​할 ''때 리터럴 '로 간주되므로 문자열이 내부적으로 문자 시퀀스로 표시 O'Reilly됩니다. 그것이 DB가 저장, 검색, 비교하는 것 등입니다. 이스케이프 한 후 사용자에게 데이터를 표시하려면 이스케이프되지 않은 문자열의 복사본을 옆에 보관하십시오.
cHao

1

다음은 동료를 설득하는 데 도움이 될 수있는 몇 가지 기사입니다.

http://www.sommarskog.se/dynamic_sql.html

http://unixwiz.net/techtips/sql-injection.html

개인적으로 나는 어떤 동적 코드도 내 데이터베이스에 닿지 않도록하여 모든 접촉이 sps (동적 SQl을 사용하는 것이 아님)를 통해 이루어져야합니다. 이것은 내가 사용자에게 권한을 부여한 것을 제외하고는 수행 할 수 없으며 내부 사용자 (관리 목적으로 프로덕션 액세스 권한을 가진 극소수 제외)가 내 테이블에 직접 액세스하여 혼란을 일으키거나 데이터를 훔치거나 사기를 저지를 수 없다는 것을 의미합니다. 금융 애플리케이션을 실행하는 경우 이것이 가장 안전한 방법입니다.


1

깨질 수 있지만 수단은 정확한 버전 / 패치 등에 따라 다릅니다.

이미 제기 된 것은 악용 될 수있는 오버플로 / 잘림 버그입니다.

또 다른 미래의 수단은 다른 데이터베이스와 유사한 버그를 찾는 것입니다. 예를 들어 MySQL / PHP 스택은 특정 UTF8 시퀀스를 사용하여 교체 함수를 조작 할 수 있기 때문에 이스케이프 문제가 발생했습니다. 교체 함수가 도입 되도록 속일 수 있습니다. 삽입 문자 .

하루가 끝나면 대체 보안 메커니즘은 예상에 의존 하지만 의도 하지 않았습니다. 기능 기능 합니다. 기능이 코드의 의도 된 목적이 아니기 때문에 일부 발견 된 기이 한 기능이 예상되는 기능을 손상시킬 가능성이 높습니다.

레거시 코드가 많은 경우, 교체 방법은 긴 재 작성 및 테스트를 피하기위한 임시 방편으로 사용될 수 있습니다. 새 코드를 작성하는 경우 변명의 여지가 없습니다.


1

가능한 경우 항상 매개 변수화 된 쿼리를 사용하십시오. 이상한 문자를 사용하지 않는 간단한 입력도 데이터베이스의 필드에 대한 입력으로 식별되지 않으면 SQL 주입을 이미 생성 할 수 있습니다.

따라서 데이터베이스가 입력 자체를 식별하는 작업을 수행하도록하세요. 그렇지 않으면 이스케이프되거나 변경 될 수있는 이상한 문자를 실제로 삽입해야 할 때 문제를 줄일 수 있습니다. 입력을 계산할 필요가 없기 때문에 결국 귀중한 런타임을 절약 할 수도 있습니다.


1

나는 '스스로하는 것이 왜 나쁜지'의 측면을 다루는 다른 답변을 보지 못했지만 SQL Truncation 공격을 고려하십시오. .

도 있습니다 QUOTENAME당신이 PARAMS를 사용하도록 설득 할 수없는 경우 도움이 될 수있는 T-SQL 기능. 탈출 한 qoute 문제를 많이 (모두?) 포착합니다.


1

2 년 후 , 나는 recidivated ... 매개 변수가 고통 스럽다고 생각하는 사람이라면 누구나 내 VS Extension, QueryFirst 를 사용해 볼 수 있습니다. 실제 .sql 파일 (Validation, Intellisense)에서 요청을 편집합니다. 매개 변수를 추가하려면 '@'로 시작하여 SQL에 직접 입력하면됩니다. 파일을 저장할 때 QueryFirst는 쿼리를 실행하고 결과에 액세스 할 수 있도록 래퍼 클래스를 생성합니다. 매개 변수의 DB 유형을 조회하고 생성 된 Execute () 메소드에 대한 입력으로 찾을 수있는 .net 유형에 매핑합니다. 더 간단 할 수 없습니다. 올바른 방법으로 수행하는 것은 다른 방법보다 훨씬 빠르고 쉽습니다. SQL 주입 취약점을 생성하는 것은 불가능하거나 적어도 비뚤어지게 어렵습니다. DB에서 열을 삭제하고 애플리케이션에서 컴파일 오류를 즉시 확인할 수있는 것과 같은 다른 킬러 이점이 있습니다.

법적 고지 사항 : 나는 QueryFirst를 썼습니다


0

매개 변수화 된 쿼리를 사용하는 몇 가지 이유는 다음과 같습니다.

  1. 보안-데이터베이스 액세스 계층은 데이터에서 허용되지 않는 항목을 제거하거나 이스케이프하는 방법을 알고 있습니다.
  2. 우려 사항 분리-내 코드는 데이터를 데이터베이스가 좋아하는 형식으로 변환하는 책임이 없습니다.
  3. 중복성 없음-이 데이터베이스 형식화 / 이스케이프를 수행하는 모든 프로젝트에 어셈블리 나 클래스를 포함 할 필요가 없습니다. 클래스 라이브러리에 내장되어 있습니다.

0

SQL 문의 버퍼 오버 플로우와 관련된 취약점 (어떤 데이터베이스인지 기억이 나지 않습니다)은 거의 없었습니다.

제가 말하고 싶은 것은 SQL-Injection은 "인용문에서 벗어나는 것"이 ​​아니라 다음에 무엇이 올지 전혀 모른다는 것입니다.


0

또 다른 중요한 고려 사항은 이스케이프 및 이스케이프되지 않은 데이터를 추적하는 것입니다. 데이터가 raw-Unicode, & -encoded, formatted HTML 등인시기를 제대로 추적하지 못하는 것처럼 보이는 수많은 응용 프로그램, 웹 및 기타가 있습니다. ''인코딩 된 문자열 과 그렇지 않은 문자열을 추적하는 것이 어려워 질 것임이 분명합니다 .

변수의 유형을 변경하게 될 때도 문제가됩니다. 예전에는 정수 였지만 이제는 문자열입니다. 이제 문제가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.