문제

요구 사항 중 하나는 사용자가 데이터베이스를 직접 쿼리하는 SQL 쿼리를 입력할 수 있어야 하는 프로젝트(개인, ASP.net 웹 사이트, https로 비밀번호로 보호됨)가 있습니다.이러한 쿼리를 허용하는 동시에 쿼리가 데이터베이스 자체를 손상시키는 것을 방지하고 액세스/업데이트할 수 없는 데이터에 액세스하거나 업데이트하는 것을 방지할 수 있어야 합니다.

나는 구현을 위해 다음과 같은 규칙을 생각해 냈습니다.

  1. 다음과 같은 DB 사용자를 사용하십시오. 오직 테이블 선택/보기 및 테이블 업데이트에 대한 권한이 있습니다. 따라서 삭제/변경/잘라내기/삽입/삭제와 같은 다른 명령은 실행되지 않습니다.
  2. 명령문이 "Select" 또는 "Update"라는 단어로 시작하는지 확인하십시오.
  3. 작은따옴표, 공백 및 문자로 묶이지 않은 명령문에 세미콜론 인스턴스가 없는지 Regex를 사용하여 확인하십시오.(여기서는 두 번째 쿼리를 포함할 수 있는 유일한 방법은 입력 문자열의 일부가 아닌 세미콜론으로 첫 번째 쿼리를 끝내는 것이라고 생각합니다.)
  4. 사용자에게 쿼리/업데이트 중인 테이블, 조인 등에 포함된 테이블에 액세스할 수 있는 권한이 있는지 확인합니다(Regex 사용).여기에는 모든 하위 쿼리가 포함됩니다.(이 작업을 수행하는 방법의 일부는 사용자가 데이터베이스에 실제로 존재하지 않는 테이블 이름 집합을 사용하는 것이며 쿼리 구문 분석의 일부는 올바른 해당 테이블 이름을 쿼리로 대체하는 것입니다.) .

내가 놓친 게 있나요?

목표는 사용자가 적합하다고 생각하는 방식으로 액세스 권한이 있는 테이블을 쿼리/업데이트하고 DB를 손상시키려는 우발적이거나 악의적인 시도를 방지하는 것입니다.(그리고 사용자가 SQL을 생성해야 한다는 요구 사항이 있으므로 내가 알고 있는 내장 도구를 사용하여 쿼리를 매개변수화하거나 쿼리를 정리할 방법이 없습니다.)

도움이 되었습니까?

해결책

글쎄, 당신은 이미 충분한 사람들이 당신에게 말하고 있습니다 "이걸하지 마라", 그들이 당신을 설득 할 수 없다면, 여기에 몇 가지 아이디어가 있습니다.

선을 포함시키고 나쁜 것을 배제하려고하지 마십시오
(적절한 용어는 생각합니다 화이트리스트 vs 블랙리스트 ) 그 의미로, 내 말은 던질 악하거나 무효 한 물건을 찾지 마십시오. (글을 쓰거나 위장 할 수있는 방법이 너무 많습니다) 대신 포함 할 유효한 것들 그리고 다른 모든 것을 버립니다.

당신은 이미 다른 의견에서 사용자 친화적 인 테이블 이름 목록을 찾고 있으며 실제 스키마 테이블 이름을 대체한다고 언급했습니다. 이것이 제가 말하는 것입니다. 만약 당신이 이것을 할 것이라면, 필드 이름으로도하십시오.

그래도 여전히 어떤 종류의 그래픽 UI에 기대고 있습니다. 여기에서 볼 테이블을 선택하고 여기에서보고 싶은 필드를 선택하고, 드롭 다운을 사용하여 Where 절을 구축하는 등을 만들지 만 여전히 쉬운 일입니다.

다른 팁

이것은 주사 예방 관점뿐만 아니라 나쁜 생각입니다. 실수로 모든 데이터베이스 리소스 (Memory/CPU)를 호그하는 쿼리를 실수로 실행하는 것이 더 쉽지 않은 사용자는 실제로 쉽게 서비스 거부 공격을 초래합니다.

만약 너라면 ~ 해야 하다 이를 허용하면 이러한 쿼리에 대해 완전히 별도의 서버를 유지하고 복제를 사용하여 생산 시스템의 정확한 미러에 가깝게 유지하는 것이 가장 좋습니다. 물론 업데이트 요구 사항과 함께 작동하지 않습니다.

그러나 나는 다시 말하고 싶다 : 이것은 단지 작동하지 않을 것이다. 사용자가 임시 쿼리를 실행할 수 있다면 데이터베이스를 보호 할 수 없습니다.

이 물건은 어떻습니까? Select가 exec라고 상상해보십시오.

select convert(varchar(50),0x64726F70207461626C652061)

내 장의 반응은 계정 권한을 설정하는 데 집중해야한다는 것입니다. RDBMS 보안 문서를 철저히 살펴보면 도움이 될 수있는 기능이 잘 될 수 있습니다 (예 : Oracle의 가상 개인 데이터베이스는 이러한 종류의 시나리오에 유용 할 수 있음).

특히, "Regex 사용 (Regex 사용)을 확인하는 아이디어는 사용자가 조정/업데이트, 조인 등에 포함 된 테이블에 액세스 할 수있는 권한이 있는지 확인하십시오." 데이터베이스에 이미 내장 된 보안 기능을 다시 구현하려고하는 것 같습니다.

당신이 놓친 것은 응용 프로그램에서 구멍을 찾는 공격자의 독창성입니다.

나는 당신이 이것을 허용한다면 모든 구멍을 닫을 수 없다는 것을 사실상 보증 할 수 있습니다. 당신이 모르는 데이터베이스 엔진에 버그가있을 수 있지만, 시스템에서 혼란에 빠지기 위해 안전한 SQL 문을 허용하는 작업을 수행합니다.

요컨대 : 이것은 기념비적으로 나쁜 생각입니다!

다른 사람들이 알 수 있듯이, 최종 사용자가 이것을하도록하도록하는 것은 좋은 생각이 아닙니다. 요구 사항은 실제로 사용자가 실제로 Ad-Hoc SQL을 필요로하는 것이 아니라 처음에는 예방하지 않는 방식으로 데이터를 얻고 업데이트하는 방법이라고 생각합니다. 쿼리를 허용하려면 Joel이 제안한대로 "읽기 전용"데이터베이스를 유지하지만 Microsoft Reporting Services 또는 Data Dynamics Active Reports와 같은보고 응용 프로그램을 사용하여 사용자가 AD-HOC 보고서를 설계하고 실행할 수 있습니다. 둘 다 사용자에게 "그들의"데이터에 대한 필터링보기를 제시 할 수있는 방법이 있다고 생각합니다.

업데이트의 경우 더 까다 롭습니다. 기존 도구를 모릅니다. 한 가지 옵션은 개발자가 플러그인을 빠르게 작성하여 데이터 업데이트를위한 새로운 양식을 노출시킬 수 있도록 애플리케이션을 설계하는 것입니다. 플러그인은 UI 양식, 현재 사용자가 실행할 수 있는지 확인하기위한 코드 및이를 실행하기위한 코드를 노출해야합니다. 응용 프로그램은 모든 플러그인을로드하고 사용자가 액세스 할 수있는 양식을 노출시킵니다.

이벤트는 보안 기술과 같은 보안입니다 동적 LINQ는 코드 주입 문제로부터 안전하지 않습니다. 그리고 당신은 저수준 액세스를 제공하는 것에 대해 이야기하고 있습니다.

쿼리를 소독하고 권한을 조정하더라도 CPU 집약적 인 쿼리를 전송하여 DB를 동결 할 수있을 것입니다.

따라서 "보호 옵션"중 하나는 메시지 상자를 표시하는 것입니다. 제한된 객체에 액세스하거나 나쁜 부작용을 유발하는 모든 쿼리는 사용자 계정에 대해 로그인하고 즉시 관리자에게보고됩니다..

또 다른 옵션 - 더 나은 대안을 찾으십시오 (즉, 데이터를 처리하고 데이터를 업데이트 해야하는 경우 API를 안전하게 노출시키지 않겠습니까?)

하나의 (아마도 과잉) 옵션은 감소 된 SQL 언어에 컴파일러를 사용할 수 있습니다. SELECT 문 만 허용하는 수정 된 SQL 문법과 함께 JAVACC를 사용하는 것과 같은 것은 쿼리를 받고 컴파일하면 컴파일하면 실행할 수 있습니다.

C#을 위해 알고 있습니다 반어 그러나 그것을 사용하지 않았습니다.

업데이트 문으로 막대한 손상을 입을 수 있습니다.

나는 이것과 비슷한 프로젝트를 가지고 있었고, 우리의 솔루션은 사용자를 매우 성가신 마법사를 통해 선택할 수 있도록하는 것이었지만 쿼리 자체는 응용 프로그램 코드에 의해 무대 뒤에서 구성됩니다. 창조하기가 매우 힘들지만 적어도 우리는 마침내 실행 된 코드를 통제했습니다.

문제는 사용자를 신뢰하는가입니다.사용자가 시스템에 로그인해야 하고 HTTPS를 사용하고 XSS 공격에 대한 예방 조치를 취했다면 SQL 주입은 더 작은 문제입니다.합법적인 사용자를 신뢰한다면 제한된 계정으로 쿼리를 실행하는 것만으로도 충분합니다.수년 동안 저는 웹에서 MyLittleAdmin을 실행해 왔지만 아직 문제가 발생하지 않았습니다.

적절하게 제한된 SQL 계정에서 실행하는 경우 select Convert(varchar(50),0x64726F70207461626C652061)는 그리 멀리 가지 않으며 데이터베이스 요청에 짧은 시간 제한을 설정하여 리소스 호깅 쿼리로부터 방어할 수 있습니다.사람들은 여전히 ​​잘못된 업데이트를 할 수 있지만, 그러면 사용자를 신뢰하는가가 다시 나타납니다.

데이터베이스를 웹에 연결하는 데는 항상 위험 관리가 필요하지만 이것이 바로 백업의 목적입니다.

실제로 고급 쿼리를 수행 할 필요가없는 경우 "업데이트, 삭제, 선택"이있는 드롭 다운 목록과 같은 특정 선택 만 허용하는 UI를 제공 할 수 있습니다. 그러면 다음 DDL은 사용 가능한 테이블 등의 목록으로 자동 채워집니다. SQL Management Studio의 쿼리 빌더와 유사합니다.

그런 다음 서버 사이드 코드에서 이러한 UI 요소 그룹을 SQL 문으로 변환하고 매개 변수 쿼리를 사용하여 악성 콘텐츠를 중지합니다.

이것은 끔찍한 나쁜 연습입니다. 나는 당신이하고 싶은 모든 것을 처리하기 위해 소수의 저장된 절차를 만들고, 더 고급 쿼리조차도 만들 것입니다. 사용자에게 제시하고 원하는 것을 선택하고 매개 변수를 전달하십시오.

내 위의 대답도 매우 좋습니다.

나는 Joel Coehoorn과 Sqlmenace에 동의하지만, 우리 중 일부는 "요구 사항"을 가지고 있습니다. Ad Hoc Queries를 보내는 대신 ASP.NET에서 발견 된 MS 샘플 응용 프로그램과 같이 시각적 쿼리 빌더를 작성하지 않겠습니까? 링크.

나는 Joel의 요점에 반대하지 않습니다. 그는 맞습니다. 사용자가 있으면 (여기서 사용자에게 이야기하고 있음을 기억하십시오. 그들은 시행하고 싶은 것에 대해 덜 신경 쓰일 수 있습니다) 던지기 쿼리는 "비즈니스 로직 계층"이없는 앱과 같습니다. 특정 결과가 일치하지 않을 때 답변 할 추가 질문은 말할 것도 없습니다. 기타 지원 응용 프로그램 결과.

다음은 또 다른 예입니다

해커는 실제 테이블 이름을 알 필요가 없습니다.

sp_msforeachtable 'print ''?''' 

인쇄 대신 드롭이됩니다

많은 대답은 그것이 나쁜 생각이지만 요구 사항이 주장하는 것입니다. 그래도 "어쨌든해야한다면"제안에 언급되지 않은 하나의 gotcha가 있습니다. 실행하기가 너무 쉽습니다

UPDATE ImportantTable
SET VitalColumn = NULL

그리고 중요한 것을 놓치십시오

WHERE UserID = @USER_NAME

전체 테이블에 대한 업데이트가 필요한 경우 추가하기가 쉽습니다.

WHERE 1 = 1

Where 절을 요구한다고해서 악의적 인 사용자가 나쁜 일을하는 것을 막지는 않지만 우발적 인 전체 테이블 변경을 줄여야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top