우선, 그것은 단지 나쁜 습관입니다. 입력 유효성 검사는 항상 필요하지만 항상 불확실합니다.
더 나쁜 것은 블랙리스트 유효성 검사는 항상 문제가 있습니다. 허용하는 값 / 형식을 명시적이고 엄격하게 정의하는 것이 훨씬 낫습니다. 물론 이것이 항상 가능한 것은 아니지만 어느 정도는 항상 이루어져야합니다.
주제에 대한 일부 연구 논문 :
- http://www.imperva.com/docs/WP_SQL_Injection_Protection_LK.pdf
- http://www.it-docs.net/ddata/4954.pdf (공개, 마지막 것은 내 것이 었습니다;))
- https://www.owasp.org/images/d/d4/OWASP_IL_2007_SQL_Smuggling.pdf (더 이상 사용할 수없는 이전 문서를 기반으로 함)
요점은 모든 블랙리스트 (및 너무 허용적인 화이트리스트)를 우회 할 수 있다는 것입니다. 내 논문의 마지막 링크는 인용문 이스케이프조차 우회 할 수있는 상황을 보여줍니다.
이러한 상황이 귀하에게 해당되지 않더라도 여전히 나쁜 생각입니다. 또한 앱이 사소한 것이 아니라면 유지 관리와 일정량의 거버넌스를 처리해야합니다. 항상 어디서나 올바르게 수행되도록하려면 어떻게해야합니까?
이를 수행하는 적절한 방법 :
- 화이트리스트 유효성 검사 : 유형, 길이, 형식 또는 허용되는 값
- 블랙리스트를 원하시면 바로 진행하십시오. 견적 이스케이프는 좋지만 다른 완화의 맥락에서 볼 수 있습니다.
- Command 및 Parameter 개체를 사용하여 준비 및 유효성 검사
- 매개 변수화 된 쿼리 만 호출합니다.
- 더 나은 방법은 저장 프로 시저를 독점적으로 사용하는 것입니다.
- 동적 SQL을 사용하지 말고 문자열 연결을 사용하여 쿼리를 작성하지 마십시오.
- SP를 사용하는 경우 테이블에 직접 액세스하지 않고 필요한 SP 만 실행하도록 데이터베이스의 권한을 제한 할 수도 있습니다.
- 전체 코드베이스가 SP를 통해서만 DB에 액세스하는지 쉽게 확인할 수도 있습니다.
좋습니다.이 답변은 질문 업데이트와 관련이 있습니다.
"누군가가이 삭제 방법에 대한 SQL 주입 공격을 마운트하는 특정 방법을 알고 있다면 나는 그것을보고 싶습니다."
이제 MySQL 백 슬래시 이스케이프 외에도 실제로 MSSQL에 대해 이야기하고 있다는 점을 고려하면 실제로 SQL에서 코드를 삽입하는 3 가지 가능한 방법이 있습니다.
sSanitizedInput = " '"& Replace (sInput, "'", " ''") & " '"
이 모든 것이 항상 유효하지는 않으며 주변의 실제 코드에 크게 의존한다는 점을 고려하십시오.
- 2 차 SQL 주입- 이스케이프 처리 후 데이터베이스에서 검색된 데이터를 기반으로 SQL 쿼리가 다시 작성되는 경우 데이터는 이스케이프되지 않은 상태로 연결되며 간접적으로 SQL 주입 될 수 있습니다. 보다
- 문자열 자르기-(조금 더 복잡함)-시나리오는 사용자 이름과 비밀번호라는 두 개의 필드가 있고 SQL이 두 필드를 연결하는 것입니다. 그리고 두 필드 (또는 첫 번째 필드)에는 길이에 대한 엄격한 제한이 있습니다. 예를 들어 사용자 이름은 20 자로 제한됩니다. 이 코드가 있다고 가정합니다.
username = left(Replace(sInput, "'", "''"), 20)
그런 다음 얻는 것은 사용자 이름이며 이스케이프 처리 된 다음 20 자로 잘립니다. 여기서 문제는 20 번째 문자 (예 : 19a 이후)에 내 따옴표를 붙이고 이스케이프 따옴표 (21 번째 문자에서)를 잘라냅니다. 그런 다음 SQL
sSQL = "select * from USERS where username = '" + username + "' and password = '" + password + "'"
앞서 언급 한 잘못된 사용자 이름과 결합하면 암호가 이미 따옴표 밖에 있고 페이로드가 직접 포함됩니다.
3. 유니 코드 밀수가 - 특정 상황에서, 높은 수준의 유니 코드 문자를 전달하는 것이 가능하다는 것을 보이는 견적 같은, 그러나 아니다 - 그것은 갑자기 데이터베이스에 도달 할 때까지 이있다 . 검증 할 때 견적이 아니므로 쉽게 진행됩니다 ... 자세한 내용은 이전 응답을 참조하고 원본 연구에 링크하십시오.
간단히 말해서, 쿼리를 스스로 이스케이프하지 마십시오. 당신은 뭔가 잘못 될 수밖에 없습니다. 대신 매개 변수화 된 쿼리를 사용하거나, 어떤 이유로 그렇게 할 수없는 경우이를 수행하는 기존 라이브러리를 사용하십시오. 스스로 할 이유가 없습니다.
-------------------질문을 받고 오랜만이라는 걸 알지만 ..
'인수 인용'절차에 대한 공격을 시작하는 한 가지 방법은 문자열 자르기를 사용하는 것입니다. MSDN에 따르면 SQL Server 2000 SP4 (및 SQL Server 2005 SP1)에서 너무 긴 문자열은 조용히 잘립니다.
문자열을 인용하면 문자열의 크기가 증가합니다. 모든 아포스트로피가 반복됩니다. 그런 다음 SQL의 일부를 버퍼 외부로 밀어 넣는 데 사용할 수 있습니다. 따라서 where 절의 일부를 효과적으로 제거 할 수 있습니다.
이것은 아마도 모든 검사를 수행하지 않기 위해 'update'문을 남용 할 수있는 'user admin'페이지 시나리오에서 가장 유용 할 것입니다.
따라서 모든 인수를 인용하기로 결정한 경우 문자열 크기에 어떤 일이 발생하는지 알고 잘림이 발생하지 않는지 확인하십시오.
매개 변수를 사용하는 것이 좋습니다. 항상. 데이터베이스에 적용 할 수 있으면 좋겠어요. 그리고 부작용으로 더 많은 명령문이 동일하게 보이기 때문에 더 나은 캐시 히트를 얻을 가능성이 더 큽니다. (이것은 Oracle 8에서 확실히 사실입니다)
-------------------필자는 처음부터 쿼리를 작성하는 것이 유일한 해답 인 '고급 검색'기능을 처리 할 때이 기술을 사용했습니다. (예 : 사용자가 제품 속성에 대한 제한 조건의 무제한 세트를 기반으로 제품을 검색하고 열과 허용 된 값을 GUI 제어로 표시하여 사용자의 학습 임계 값을 줄일 수 있도록합니다.)
그 자체로 안전한 AFAIK입니다. 그러나 다른 응답자가 지적했듯이 백 스페이스 이스케이프를 처리해야 할 수도 있습니다 (적어도 ADO 또는 ADO.NET을 사용하여 쿼리를 SQL Server에 전달할 때는 아니지만 모든 데이터베이스 또는 기술을 보증 할 수는 없습니다).
문제는 어떤 문자열에 사용자 입력 (항상 잠재적으로 악성)이 포함되어 있는지, 어떤 문자열이 유효한 SQL 쿼리인지 확인해야한다는 것입니다. 함정 중 하나는 데이터베이스의 값을 사용하는 경우입니다.이 값은 원래 사용자가 제공 한 것입니까? 그렇다면 이스케이프해야합니다. 내 대답은 SQL 쿼리를 구성 할 때 가능한 한 늦게 (하지만 나중에는 안됩니다!) 위생 처리를 시도하는 것입니다.
그러나 대부분의 경우 매개 변수 바인딩이 더 간단합니다.
-------------------입력 위생은 당신이 반쯤하려는 것이 아닙니다. 엉덩이 전체를 사용하십시오. 텍스트 필드에 정규식을 사용하십시오. 숫자를 적절한 숫자 유형으로 캐스트하고 작동하지 않는 경우 유효성 검사 오류를보고합니다. 입력에서 '-와 같은 공격 패턴을 검색하는 것은 매우 쉽습니다. 사용자의 모든 입력이 적대적이라고 가정합니다.
-------------------당신이 아는 것처럼 어쨌든 그것은 나쁜 생각입니다.
다음과 같이 문자열에서 따옴표를 이스케이프하는 것과 같은 것은 어떻습니까?
교체 결과 : \ ''
백 슬래시가 첫 번째 따옴표를 이스케이프하면 두 번째 따옴표가 문자열을 끝낸 것입니다.
-------------------간단한 대답 : 가끔 작동하지만 항상 작동하지는 않습니다. 수행 하는 모든 작업 에 화이트리스트 유효성 검사를 사용 하고 싶지만 이것이 항상 가능한 것은 아니라는 것을 알고 있으므로 최선의 추측 블랙리스트를 사용해야합니다. 마찬가지로 모든 항목 에서 매개 변수화 된 저장된 procs를 사용하고 싶지만 다시 한 번 이것이 항상 가능한 것은 아니므로 매개 변수와 함께 sp_execute를 사용해야합니다.
사용할 수있는 블랙리스트를 처리 할 수있는 방법이 있습니다 (그리고 일부 화이트리스트도).
괜찮은 글이 여기에 있습니다 : http://www.owasp.org/index.php/Top_10_2007-A2
이 작업을 신속하게 수행하여 실제 위치를 확보 할 시간을 제공해야하는 경우 수행하십시오. 하지만 당신이 안전하다고 생각하지 마세요.
-------------------SQL 주입으로부터 안전하기 위해 예외없이 두 가지 방법이 있습니다. 준비된 문 또는 실용화 된 저장 프로 시저
-------------------매개 변수화 된 쿼리를 사용할 수있는 경우 항상이를 사용해야합니다. 필요한 것은 하나의 쿼리가 네트워크를 통해 빠져 나가고 DB가 위험에 처하는 것입니다.
-------------------예, 누군가 SET QUOTED_IDENTIFIER OFF를 실행 하고 큰 따옴표를 사용할 때까지 바로 작동 합니다.
편집 : 악의적 인 사용자가 인용 식별자를 끄는 것을 허용하지 않는 것만 큼 간단하지 않습니다.
SQL Server 용 SQL Server Native Client ODBC 드라이버 및 SQL Server 용 SQL Server Native Client OLE DB 공급자는 연결시 QUOTED_IDENTIFIER를 자동으로 ON으로 설정합니다. ODBC 데이터 원본, ODBC 연결 특성 또는 OLE DB 연결 속성에서 구성 할 수 있습니다. SET QUOTED_IDENTIFIER의 기본값은 DB-Library 애플리케이션에서 연결하는 경우 OFF입니다.
저장 프로 시저가 만들어지면 SET QUOTED_IDENTIFIER 및 SET ANSI_NULLS 설정이 캡처되어 해당 저장 프로 시저의 후속 호출에 사용됩니다 .
SET QUOTED_IDENTIFIER는 ALTER DATABASE의 QUOTED_IDENTIFER 설정 에도 해당합니다.
SET QUOTED_IDENTIFIER는 구문 분석 시간에 설정됩니다 . 구문 분석시 설정은 SET 문이 일괄 처리 또는 저장 프로 시저에있는 경우 코드 실행이 실제로 해당 지점에 도달했는지 여부에 관계없이 적용됨을 의미합니다. SET 문은 문이 실행되기 전에 적용됩니다.
QUOTED_IDENTIFIER는 사용자가 알지 못하는 사이에 여러 가지 방법으로 작동하지 않을 수 있습니다. 인정합니다-이것은 당신이 찾고있는 총기 익스플로잇은 아니지만 꽤 큰 공격 표면입니다. 물론, 큰 따옴표도 이스케이프 처리했다면-우리가 시작했던 곳으로 돌아 왔습니다. ;)
-------------------다음과 같은 경우 방어가 실패합니다.
- 쿼리에 문자열이 아닌 숫자가 필요합니다.
- 다음을 포함하여 작은 따옴표를 나타내는 다른 방법이 있습니다.
- \ 039와 같은 이스케이프 시퀀스
- 유니 코드 문자
(후자의 경우 교체를 완료 한 후에 만 확장되어야합니다.)
-------------------Patrick, 모든 입력, 심지어 숫자 입력에 작은 따옴표를 추가하고 있습니까? 숫자 입력이 있지만 주위에 작은 따옴표를 넣지 않으면 노출이 발생합니다.
-------------------사용자 입력을 완전히 삭제하는 것은 얼마나 추악한 코드일까요! 그런 다음 SQL 문에 대한 투박한 StringBuilder입니다. 준비된 명령문 방법은 훨씬 더 깨끗한 코드를 생성하며 SQL 주입의 이점은 정말 멋진 추가 기능입니다.
또한 왜 바퀴를 재발 명합니까?
-------------------작은 따옴표를 두 개의 작은 따옴표로 변경하는 대신 아포스트로피, 따옴표로 변경하거나 완전히 제거하지 않는 이유는 무엇입니까?
어느 쪽이든, 그것은 약간의 문제입니다 ... 특히 합법적으로 작은 따옴표를 사용할 수있는 것 (이름과 같은)이있을 때 ...
참고 :이 방법은 또한 앱에서 작업하는 모든 사람이 입력이 데이터베이스에 도달하기 전에 항상 입력을 삭제하는 것을 기억한다고 가정합니다. 이는 대부분의 경우 현실적이지 않을 것입니다.
-------------------문자열에 대해 작동하는 솔루션을 찾을 수 있지만 숫자 조건 자의 경우 숫자로만 전달되는지 확인해야합니다 (간단한 검사는 int / double / decimal로 구문 분석 할 수 있다는 것입니다).
많은 추가 작업입니다.
-------------------작동 할 수도 있지만 나에게는 약간 멍청한 것 같습니다. 대신 정규식에 대해 테스트하여 각 문자열이 유효한지 확인하는 것이 좋습니다.
-------------------예, 가능하다면 ...
주제를 연구 한 후, 제안한대로 삭제 된 입력이 안전하다고 생각하지만 다음 규칙에 따라야합니다.
사용자로부터 오는 문자열 값이 문자열 리터럴 이외의 다른 값이되도록 허용하지 않습니다 (예 : "여기에 추가 SQL 열 이름 / 표현식 입력 :"구성 옵션을 제공하지 마십시오). 문자열 이외의 값 유형 (숫자, 날짜, ...) : 기본 데이터 유형으로 변환하고 각 데이터 유형의 SQL 리터럴에 대한 루틴을 제공합니다.
- SQL 문은 유효성 검사에 문제가 있습니다.
당신이 중 하나를 사용
nvarchar
/nchar
열 (와 접두어 문자열 리터럴N
로가는) 또는 한계 값varchar
/char
ASCII 문자를 열 전용 (예 : 던져 예외 SQL 문을 만들 때)- 이렇게하면 CHAR (700)에서 CHAR (39) 로의 자동 아포스트로피 변환을 피할 수 있습니다 (및 기타 유사한 유니 코드 해킹).
항상 실제 열 길이에 맞게 값 길이의 유효성을 검사합니다 (더 길면 예외 발생).
- 잘림시 발생한 SQL 오류를 우회 할 수있는 SQL Server에 알려진 결함이 있습니다 (자동 잘림으로 이어짐).
당신
SET QUOTED_IDENTIFIER
은 항상ON
- 주의하십시오. 이것은 구문 분석 시간에 적용됩니다. 즉, 액세스 할 수없는 코드 섹션에서도 적용됩니다.
이 4 가지 사항을 준수하면 안전해야합니다. 이들 중 하나라도 위반하면 SQL 주입 방법이 열립니다.
출처
https://stackoverflow.com/questions/22079869