데스크탑 애플리케이션에서 데이터베이스 보안을 어떻게 처리합니까?


12

약 10 년 동안 저는 SQL Server 데이터 저장소를 사용하여 다양한 사내 데스크톱 클라이언트 응용 프로그램에서 일했습니다. 거의이 프로젝트를 시작하지 않았으며 대부분은 인계 작업입니다.

사방 상수를 보였다 한 가지가이 응용 프로그램은 공통 데이터베이스에에게 권한을 부여하는 데 사용하는 하나의 글로벌 SQL Server 사용자 계정, 그리고 일부 순진한 상황에서 Yes (예)가 사용 된 것이 었 sa내가 일반적으로 수정 가능한 경우에 시도 사용자 계정을 .

응용 프로그램이 데이터베이스에 액세스하는 데 사용하는이 사용자 이름과 암호를 실제로 숨길 수는 없습니다. 이들은 일반적으로 ini또는 config파일에 저장 되거나 실행 파일 자체에 구워 질 수 있습니다. 모든 경우에, 그들은 약간 파고 있으면 사용자에게 표시됩니다. 어떤 경우에는 실제로 config파일을 사용 했지만 암호화했지만, 물론 암호화 키는 실행 파일에 저장해야했습니다. 에서 볼 수 있습니다 config) 파일입니다.

이러한 모든 시스템에는 응용 프로그램에 사용자 인증 시스템이 내장되어 있지만 물론 응용 프로그램 자체를 통해 관리되었으므로 사용자 정보가 데이터베이스에 저장되었습니다. 응용 프로그램은 액세스 수준에 따라 수행 할 수있는 작업을 제한했지만 데이터베이스에 연결하고 임시 쿼리를 실행할 수 있다면 모든 종류의 문제입니다.

이 문제를 해결하기 위해 다른 시스템이 무엇을하는지 알고 싶습니다. 내가 아는 옵션은 다음과 같습니다.

  1. SQL Server의 보안 메커니즘을 사용하여 사용자 및 역할 목록을 유지 관리하고 데스크톱 응용 프로그램이 T-SQL 쿼리를 통해 사용자를 추가 및 제거하도록합니다.
  2. 데이터베이스에 직접 연결하는 대신 서버에서 실행되는 일종의 웹 서비스를 작성하고 거기에 인증 로직을 넣습니다. 모든 요청이 보안 유효성 검사를 수행하도록하십시오.

첫 번째 옵션은 데이터베이스에서 사용자를 분리하여 사용자가 더 이상 일류 엔터티가 아니므로 외래 키 관계 등으로 참조 할 수 없기 때문에 추악합니다.

두 번째는 주요 성능 문제와 많은 추가 작업처럼 보이며 NHibernate와 같은 ORM 매퍼를 쉽게 사용할 수는 없습니다 (제 생각에).

누구든지 이것에 경험이 있습니까? 모범 사례?

편집하다

좀 더 생각해 보면 SQL Server 인증이 실제로이 문제를 해결할 수 있습니까? 예를 들어 작업 표를 편집 할 수 있도록 사용자가 작업 표 레코드를 삽입하고 업데이트 할 수 있어야하는 경우 작업 표 세부 정보 테이블의 다른 행에 대한 액세스를 SQL Server가 허용 할 방법이 없으므로 다른 사람의 작업 표를 읽고 쓸 수 있습니다.


바인딩 주제; NHibernate와 같은 ORM을 사용하지 않는 것은 문제가되지 않습니다. 웹 서비스를 예로 사용하면 데이터를 XML에 효율적으로 바인딩 할 수있는 여러 가지 방법이 있습니다.
jasonk

어쨌든 ORM을 비즈니스 오브젝트와 DB 엔티티 사이의 직접 맵핑으로 사용해서는 안되며, 이는 취약한 인터페이스를 만드는 나쁜 접근 방식입니다. 원시 DB 엔터티를 가져와 필요한 데이터 만 클라이언트에 반환하는 비즈니스 계층에 요청합니다.
gbjbaanb

@gbjbaanb-오늘 오후에 전체 아키텍처를 변경하겠습니다. :)
Scott Whitlock

누군가 당신이 그것을 변경하기 전에 당신을 해킹 할 때까지 기다릴 수 있다고 생각하지만, 밝은면에서는 최소한 당신의 상사가 재건축 자금을 조달하는 데 아무런 문제가 없을 것입니다 :-)
gbjbaanb

저장 프로 시저를 레코드를 업데이트하는 유일한 방법으로 사용하고 proc를 실행하는 사용자를 쿼리의 일부로 사용하여 사용자가 다른 사람의 레코드를 업데이트하지 못하게 할 수 있습니다. 참조 CURRENT_USER
gbjbaanb

답변:


9

웹 서비스 계층을 추가하는 것이 문제의 올바른 해결책 일 것입니다.

기본 데이터베이스 구현에서 클라이언트를 분리하면 장기적으로 도움이 될 것입니다.

웹 서비스 계층을 추가한다고해서 반드시 성능이 저하 될 필요는 없습니다 ...

실제로, 적절한 API를 사용하면 웹 서비스는 WAN을 통한 여러 번의 왕복 여행을 요구하지 않고 데이터 센터 LAN 내에서 여러 데이터베이스 쿼리를 일괄 처리함으로써 실제로 성능을 향상시킬 수 있습니다.

물론 웹 서비스 계층은 종종 수평으로 확장 될 수 있으며 변경 알림 메커니즘을 비롯하여 데이터베이스 쿼리에 적절한 캐싱을 추가 할 수 있습니다.

서버 계층은 원격 클라이언트에서 실행되는 앱으로는 보장 할 수없는 보안을 추가합니다. 클라이언트에서 실행되는 모든 것을 "해킹"할 수 있으며 어떤 식 으로든 신뢰할 수있는 것으로 간주해서는 안됩니다. 프리젠 테이션 로직 만 클라이언트에 배치하고 완전히 제어 할 수있는 하드웨어에 중요한 것을 호스트해야합니다.

귀하의 앱에 대해 잘 모르지만 웹 앱은 자연스럽게 여러 계층으로 나뉘며 프리젠 테이션 코드는 지속성 계층과 분리되어 하나 이상의 비즈니스 로직 수준으로 구분됩니다. 이것이 내 앱에 대한 추론을 훨씬 쉽게하고 기능을 추가하거나 수정하는 것이 훨씬 빠릅니다. 어쨌든 레이어가 분리되어 있으면 프레젠테이션 레이어를 클라이언트에 유지하고 나머지는 서버에서 제어하는 ​​것이 비교적 쉽습니다.

따라서 "웹 서비스"계층을 도입하지 않고도 문제를 해결할 수는 있지만 표준 데이터베이스 보안 구현의 허점을 채우기 위해 필요한 모든 저장 프로 시저 (또는 이와 동등한)를 작성할 때 작성하는 것이 더 나을 것입니다. 적절한 단위 테스트를 작성할 수있는 서버 측 애플리케이션.


성능 병목 현상이 필요하지는 않지만 아키텍처에 추가 계층을 추가하므로 유지 관리가 훨씬 많이 필요합니다.
Scott Whitlock

3
계층을 추가하지만 반드시 유지 관리 할 필요는 없습니다. 클라이언트가 아닌 서비스에 배치 된 모든 논리를 사용하면 사용자가 클라이언트 응용 프로그램을 업데이트하지 않고도 변경 내용을 '롤아웃'할 수 있습니다.
GrandmasterB

5

jmoreno의 답변과 마찬가지로, 저장 프로 시저에 대한 EXECUTE 권한을 제외한 모든 것에 대한 사용자 액세스를 거부 한 다음 소유권 체인을 활용하여 저장 프로 시저가 테이블에서 필요한 작업을 수행하도록 할 수 있습니다.

자세한 내용은 여기를 참조하십시오 https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx

사용자가 자신의 사용자 이름 / 암호 클라이언트 쪽을 입력하면이를 저장하고 모든 저장 프로 시저 호출에 매개 변수로 보냅니다. 그런 다음 원하는 작업을 수행하기 전에 테이블에 저장된 값과 비교하여 값을 확인할 수 있습니다.

보안의 마지막 단어는 아니지만 PC에 일반 로그인이 있거나 권한을 위해 AD 그룹을 사용할 수있는 능력이 제한되거나 AD 자체에 대한 액세스가 제한적인 경우 필요할 수 있습니다.


2

한 가지 방법은 AD 그룹과 저장 프로 시저를 사용하여 사용자가 수행 할 수있는 작업을 제한하는 것입니다 (예 : 작업 표 DB). 사용자의 ID는 DB 엔진에 의해 제공되며 사용자는 DB 테이블에 직접 액세스 할 수 없으며 로그인 ID를 기반으로 쿼리를 실행 한 sp에 대해서만 액세스 할 수 있습니다.

물론 이것이 항상 실현 가능한 것은 아니지만 가능합니다. 최선의 접근 방식은 요구 사항과 리소스에 따라 다릅니다.


이것은 내가 고려하지 않은 것입니다. 그것이 잘 맞는지 잘 모르겠지만 작동합니다.
Scott Whitlock

1

'웹 서비스'라고 암시하는 것을 n- 계층 아키텍처 라고 합니다. 일반적으로 보안 또는 구성 문제가 발생할 가능성이있는 경우 (예 : 여러 사무실에 응용 프로그램을 배포하는 경우)에 사용됩니다. 그러나 '웹 기반'일 필요는 없습니다. 많은 사람들이 다른 프로토콜로 작업합니다.

클라이언트와 데이터베이스 (및 기타 리소스) 간의 중개자 역할을하는 응용 프로그램 서버를 만듭니다. 응용 프로그램 서버는 응용 프로그램 기반 인증을 처리하고 클라이언트를 대신하여 작업을 수행합니다. 사실, 이상적으로는 클라이언트에서 SQL을 수행하지 않고 앱 서버에서 메소드를 호출하는 것이 이상적입니다. 응용 프로그램 서버는 모든 데이터 조작을 처리합니다.

이 접근법에는 여러 가지 이점이 있습니다. 클라이언트에서 데이터베이스 연결 및 드라이버를 구성 할 필요가 없습니다. 데이터베이스 사용자, 비밀번호 및 서버를 저장하지 마십시오. 클라이언트 구성도 필요하지 않습니다. 코드에서 올바른 URL 또는 주소를 가리켜보십시오. 또한 응용 프로그램 서버에서 'logic'을 사용하면 다른 응용 프로그램을 개발할 때 반복 할 필요가 없습니다. 동일한 유형의 클라이언트가 다른 응용 프로그램 서버를 재사용 할 수 있습니다.


더 좋은 것은 누군가가 당신의 데스크탑 (또는 웹 기반의 웹 서버에서)을 해킹하는 경우 공격자는 OS에 대한 모든 액세스 권한을 가질 수 있지만 여전히 DB에 액세스 할 수는 없습니다. 따라서 그들은 "select * from users"를 파이프로 파일로 가져 가서 자신의 여가를 깨뜨리고 CEO가 보안 시스템이 손상된 이유를 미디어에 설명 할 수 없습니다. 실행 액세스 만 허용하는 DB에서 sprocs를 사용하는 경우 공격자는 앱을 해킹 할 수 있으며 여전히 전체 사용자 데이터베이스를 가져올 수 없습니다.
gbjbaanb

1

기술이 조금 바뀌 었습니다. 각 사용자를 데이터베이스 자체에 대해 인증하고 데이터베이스 역할을 사용하는 경우 이제 적어도 SQL Server에서 업데이트 가능 뷰라는 것을 사용하여이 문제를 해결할 수 있습니다.

다음 SomeTable은 해당 테이블의 각 행이 직원과 연결된 위치 라는 테이블에 대한 업데이트 가능한 뷰의 모습 입니다. 직원은 자신과 연결된 행을 볼 수 있어야하고 HR 역할의 구성원은 다음과 같은 모든 행을 볼 수 있어야합니다.

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

그런 다음 모든 사용자에게 보기 ( vwSomeTable) 에 대한 읽기 및 쓰기 권한 부여하고 테이블 ( SomeTable) 에 대한 권한을 부여하지 않습니다 .

이것을 다음과 같이 테스트 할 수 있습니다.

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... 행만 반환해야합니다. 또는:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... 모든 행을 반환합니다. 이 테스트를 수행하려면 다른 사람으로 실행 권한이 필요합니다.

뷰가 업데이트 가능하므로 행이 행에 연결되어 있으면 일반 사용자 조차도이 작업을 수행 할 수 있습니다 Employee.

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'

0

인증서 기반 인증을 사용하는 것은 공유 SQL 계정을 구현하는 "올바른"방법입니다. 목표는 이런 종류의 암호 사용을 제거하는 것입니다.

최신 정보:

나는 그 질문을 오해했다고 생각합니다. DB 사용자 이름과 암호를 응용 프로그램 구성에 넣거나 응용 프로그램 자체에 백업하는 대안을 찾으려고 노력해야한다고 생각했습니다.

대신 클라이언트 측 인증서를 사용하여 애플리케이션에서 비밀번호 관리 문제를 제거 할 수 있습니다. 인증서 자체로는 충분하지 않으므로 인증서 해지와 같은 작업을 수행 할 수있는 배포 및 관리 시스템이 있어야합니다.

참조 : http://en.wikipedia.org/wiki/Public-key_infrastructure


이것에 대한 더 많은 정보를 제공 할 수 있습니까? 원래 질문의 의도와 직교하는 것처럼 들리지만 흥미 롭습니다.
Scott Whitlock

0

새로운 데스크톱 보안 솔루션을 구축하기 위해 다음과 같은 웹 서비스 솔루션을 선택했습니다.

개발자와 별도의 환경에서 데스크톱 응용 프로그램 실행 파일을 컴파일합니다. 그리고 데이터베이스에 기록 된 실행 파일에서 HASH를 계산하십시오.

응용 프로그램을 실행하는 데 필요한 모든 정보, DB 암호, 연결 문자열 정보, 사용자 권한 등을 제공하는 하나의 웹 서비스 ...

애플리케이션 당 단일 DB 로그인을 사용하고 레코드를 감사 할 수 있도록 세션 변수에 데이터베이스에 사용자 세부 사항을 기록합니다.

DLL은 데스크톱 응용 프로그램에서 웹 서비스로의 모든 통신을 처리합니다.이 통신은 DLL에 토큰 빌드를 통해서만 액세스 할 수 있습니다.

웹 서비스에서 응용 프로그램 DB 암호를 얻을 수 있도록 DLL은 런타임에서 DLL 호출자 HASH를 계산하고 DLL 토큰을 확인하는 웹 서비스에 매개 변수로 전달하고 배포시 기록 된 실행 가능 런타임에 HASH를 계산 한 실행 런타임을 웹 서비스에 전달합니다. 응용 프로그램은 단일 네트워크 공유 설치에서만 사용할 수 있습니다.

그렇게함으로써 우리가 가장 우려했던 보안 문제에 대한 좋은 솔루션이며 몇 가지 설계 결함을 잘 알고 있습니다. 이 구현을 거의 마무리하고 있으며 지금까지 결과에 만족합니다.

편집 : 디지털 서명 및 X.509 인증서를 사용하여 해시 아이디어를 대체 할 수 있습니다.


1
눈부신 보안 구멍이 어디에 있는지는 분명합니다. 당신이 말한 DLL은 클라이언트 시스템에 있으며 서버 코드가 DLL의 합법적 사본이나 해킹 / 악의적 / 가짜 파일과 통신하고 있는지 확인할 수있는 방법이 없습니다. 방금 추가 보안을 추가하지 않고도 많은 작업을 수행했습니다. 악의적 인 사람이 필요로하는 모든 토큰과 알고리즘은 모두보고자하는 사람을 위해 DLL에 있습니다.
Scott Whitlock

@ScottWhitlock, 예, 동의합니다. DLL을 난독 처리하고 HTTPS를 통과하는 트래픽을 조사하고 있습니다. 우리는 그것을 개선하려고 노력하고 있습니다. 나는 그것을 개선하는 방법에 대한 의견을 정말로 원합니다. 그러나이 솔루션은 이미 네트워크 파일에 저장된 일반 텍스트 암호를 포함하여 현재 시스템의 많은 문제를 해결합니다. 또한 웹 서비스를 통해 델파이 및 클리퍼 (하버) 클라이언트를 포함하여 여기에서 사용하는 모든 클라이언트 언어로 많은 코드를 재사용 할 수 있습니다!
Vitor Arbex

시스템에서 사용자가 로그인하여 웹 서비스에 의해 인증 될 수 있습니다. HTTPS 사용을 가정하면 충분하지 않습니까? 사용자는 자신이 누구인지 알고 웹 서비스를 제어하므로 클라이언트 소프트웨어를 신뢰할 필요가 없으므로 웹 서비스는 지정된 사용자에게 볼 수있는 정보 만 제공해야합니다. 그들이 고객을 리버스 엔지니어링하고 자신의 글을 쓴 경우에도 어떤 피해를 입을 수 있습니까? 귀하의 웹 서비스 만이 DB 암호를 알고 있으므로 안전해야합니다.
Scott Whitlock
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.