왜 사용자 비밀번호를 저장합니까?


10

웹 응용 프로그램의 사용자 암호를 안전하게 저장하는 방법을 묻는 질문이 종종 있습니다 (RDBMS를 사용하여 Facebook 또는 Twitter에 대해 이야기하고 있지 않습니다). 일반적인 대답은 "암호를 입력 한 다음 TDES 또는 SHA512와 같은 강력한 알고리즘으로 해시합니다"입니다.

내 질문은 : RDBMS 사용자로서, 대부분의 엔진에는 내장 인증 메커니즘이 있기 때문에 암호 저장 문제가 전혀 발생하지 않는 이유는 무엇입니까?

예를 들어 일부 사용자 X가 내 웹 응용 프로그램에서 계정 사용자 암호 Y를 만들려면 다음 쿼리를 어떻게 잘못 발행합니까?

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

그런 다음 내 응용 프로그램 내에서 사용자는 자신의 자격 증명을 사용하여 데이터베이스에 대한 연결을 열 수 있으며 모든 암호 관리를 귀찮게 할 필요가 없습니다.

이 방법에는 여러 가지 장점이 있습니다.

  • RDBMS가 암호화 알고리즘을 변경해야한다고 결정하면 보안 업데이트를 적용하기 위해 아무 것도 만질 필요가 없습니다.
  • 사용자 인증을 쉽게 관리 할 수 ​​있습니다. 사용자가 관리자 역할로 승격되면 해당 그룹에 사용자를 추가하면됩니다.
  • SQL 주입은 이제 의미가 없습니다. 데이터베이스의 각 사용자 (예 : SO와 같은 포럼, 새 게시물 추가, 게시물에 응답, 게시물에 대한 주석 작성 및 편집 / 삭제)와 같이 각 사용자에게 허용하려는 것을 정확하게 허용하는 권한을 관리합니다. / answers / comments);
  • 사용자 계정 "익명"은 인증되지 않은 내 응용 프로그램 연결에 사용할 수 있습니다.
  • 각 사용자는 그가 제공 한 데이터의 소유자입니다.

그러나이 주제에 대해 거의 모든 질문에 대해 이것이 수행 해야하는 방식이 아니라는 일반적인 합의가있는 것 같습니다. 내 질문은 : 왜?

참고 : 세 번째 포인트에 의해 허용되는 정책 PostgreSQL을, 그리고 보안 정책 마이크로 소프트 SQL 서버한다. 나는이 개념들이 새로 나온다는 것을 알고 있지만 어쨌든 지금 여기에 기술 된 기술이 사용자 계정을 처리하는 표준 방법이 아닌 이유는 무엇입니까?


2
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Paul White 9

또한 일반적인 대답은 잘못되었습니다. 비밀번호를 소금에 절인 다음 bcrypt 또는 argon2와 같은 느린 알고리즘으로 비밀번호를 해시해야합니다 .
Tgr

답변:


27

많은 응용 프로그램의 경우 개별 사용자 계정이 데이터베이스에 연결되는 것을 원하지 않습니다. 사용자 / 암호 / 권한 / 권한은 모두 응용 프로그램 계층에서 처리되며 단일 전용 서비스 계정을 사용하여 데이터베이스 백엔드에 연결합니다.

DBA로서 데이터베이스 수준에서 중간 규모의 공용 웹 응용 프로그램의 10,000 명의 활성 사용자 또는 갑자기 인기있는 일부 앱의 2 백만 이상 사용자를 관리하고 싶지 않습니다.

실제로 이것은 응용 프로그램 개발자와 데이터베이스 개발자 / DBA의 철학 차이입니다.

많은 / 대부분의 응용 프로그램 개발자는 앱 기능 및 / 또는 비즈니스 규칙의 주요 측면에 대한 책임을 데이터베이스 계층으로 전달하고 싶지 않습니다. 대신 데이터베이스를 단순히 데이터를 저장하고 검색하는 도구로 간주합니다.

어떤 경우에는 근시 일 수 있습니다. 많은 RDBMS에는 앱 개발자의 삶을 훨씬 쉽게 만들 수있는 멋진 기능이 있습니다 (행 수준 보안, 열 인덱스, 파일 스트림 스토리지 등).

그러나 이러한 더 멋진 기능 중 일부는 최신 버전에서만 사용할 수 있으며 조직이 기존 환경을 항상 빠르게 업그레이드하지는 않습니다 ( 2014 년이 차트 참조 ).

그리고 다른 경우에는 응용 프로그램 계층에서 이러한 것들을 처리하는 것이 바람직합니다 (데이터베이스 플랫폼 이식성뿐만 아니라 주장이 과장된 것이라고 생각합니다).


2
비즈니스 로직이 애플리케이션 또는 데이터베이스에서 진행되는지에 대한 '거룩한 전쟁'이 존재합니다. 모든 비즈니스 로직 (특히 보안)이 데이터베이스에있는 (저장 프로 시저, 뷰 등을 사용하여) 응용 프로그램을 구축 한 경우, 아무도 직접 연결하여 문제를 해결할 수 없으므로 데이터베이스 보안 메커니즘을 활용해야한다는 주장이있을 수 있습니다. 보안. 사용자 정의 테이블에서 보안 메커니즘 (예 : 로그인 / 암호)을 '재 구축'하지 않아야한다는 데 전적으로 동의합니다. Active Directory / O365 보안이 이미있는 경우 왜 그렇게합니까?
Nick.McDermaid

1
@ Nick.McDermaid 저는 DB와 응용 프로그램 사이에 비즈니스 로직을 적절히 혼합하여 미래 개발자가 진행중인 상황에 대한 실마리를 가질 가능성을 없애고 아무도 열광하지 않기 때문에 직업 보안을 유지하는 데 도움이됩니다. 그것을 관리하기에 충분합니다.
Der Kommissar

거기에 웹 서비스와 바람둥이 응용 프로그램 서버를 던져 IBM에서 일할 수 있습니다
Nick.McDermaid

8

구분선은 그 시점에서 약간 모호 해지고 있지만 데이터베이스 수준의 사용자와 권한은 데이터의 일부가 아닌 스키마의 일부로 간주하며 일반적으로 응용 프로그램은 스키마를 수정할 장소가 없습니다 ( 항상 그렇듯이이 규칙에 대한 예외).

오히려 새로운 사용자가 필요하고 오래된 사용자가 떠날 때 스키마 개체 (로그인, 사용자 및 권한)를 관리하는 데 필요한 권한을 응용 프로그램에 부여하지 않습니다. 해당 응용 프로그램이 해킹되면 공격자가 해당 권한에 액세스 할 수 있기 때문입니다. 데이터베이스를 더 쉽게 열 수 있습니다. MS SQL Server에서는 완전히 포함 된 데이터베이스를 사용하지 않는 한 로그인은 서버 수준의 개체이므로 단일 응용 프로그램 데이터베이스 이외의 권한을 더 위험에 노출시켜야합니다.

또한 데이터베이스 수준에 응용 프로그램 별 사용자 계정이 있더라도 인증되지 않은 요청을 처리하려면 응용 프로그램 수준의 사용자 계정이 필요합니다. 즉, 응용 프로그램 사용자가 성공적으로 인증되기 전에 응용 프로그램이 데이터베이스의 정보를 필요로하는 경우 시작 / 로그인 화면에 상태 정보를 표시 하시겠습니까?).

또한 데이터베이스 엔진 간의 이식성이 목표라면 (아마도 앱이 mysql과 postgres 모두에서 실행되기를 원할까요?) 응용 프로그램은 각 엔진의 표준이 아니기 때문에 각 엔진의 사용자 / 로그인 관리 기능을 추상화해야합니다. -그러한 노력을 기울이는 경우 엔진이 제공하는 가장 일반적인 기능 세트를 수락하는 대신 암호를 직접 구현하고 원하는 관리 옵션을 얻을 수 있습니다.


1
자, "애플리케이션은 스키마를 변경해서는 안된다"는 제 생각에는 제가 제안한 기술에 대한 첫 번째 좋은 지적입니다. 그러나 새 사용자를 만들 수있는 익명 계정은 가장 기본적인 액세스 권한을 가진 새 사용자 만 만들면됩니다. 관리자만이 사용자를 승격시키고 사용자를 떨어 뜨릴 수 있습니다. 응용 프로그램에서 원하는 것 같습니다 :-) 일반 데이터는 익명의 사용자에게 표시되므로 인증이 필요하지 않은 콘텐츠 에이 연결을 사용할 수 있습니다. 이식성 또한 좋은 점이지만, 이제는 사용자 명령이 표준의 일부라고 생각합니다 (몇 년 전은
아니 었습니다

이 설정을 사용하면 해커가 익명 사용자로 데이터베이스에 액세스하면 원하는 수의 사용자를 만들 수 있지만 보안 문제는 아니지만 다음 중 하나를 사용하여 데이터베이스를 부 풀릴 수 있습니다. 생성 된 계정, 즉 (그는 너무 어쨌든 표준 인터페이스를 사용하여 할 수있는,이 방법 느린하지만 것 : p)를 성가신 그러나 다시 어떤 보안 문제가 될 것입니다
파비안 Pijcke

3
보안 관점에서 데이터베이스 수준의 사용자가 더 나을 것이라는 데 동의합니다. 그러나 기본적으로 5 천만 명의 등록 된 사용자가있는 온라인 상점에서는 관리 할 수 ​​없습니다. 각각은 데이터베이스 사용자 여야합니다. 또한 : 일반적으로 연결 풀을 사용하는 웹 응용 프로그램에서는 제대로 작동하지 않습니다.
a_horse_with_no_name

6

질문을 휴식

왜 사용자 비밀번호를 저장합니까?

가장 간단한 대답은 그렇게해야한다는 것입니다. 여전히 다른 방법으로 비밀번호를 저장합니다. 데이터베이스의 내장 시스템을 사용하여 스토리지를 관리하기 만하면됩니다. 따라서 방법은 데이터베이스만큼 좋습니다. 그것은 당신이 달리 할 수있는 것보다 여전히 낫지 만 스토리지를 피하지는 않습니다. 실제로 코딩 스토리지를 피하는 것입니다.

또한 더 좋지 않을 수도 있습니다. 데이터베이스를 손상시키고 파일 사본을 얻는 경우 테이블에 직접 액세스 할 수 있습니다. 따라서 훌륭한 암호 관리 시스템을 사용하는 데는 별다른 의미가 없습니다. 누군가 비밀번호 또는 해시 비밀번호가 포함 된 시스템 레벨 테이블에 액세스 할 수 있으면 파일에 직접 액세스 할 수도 있습니다. 이미 데이터가있을 때 암호 해독에 신경 쓰지 않는 이유는 무엇입니까? 데이터를 쉽게 암호화 할 수있는 것은 아닙니다. 각 사용자는 액세스 할 수 있어야합니다. 따라서 사용자 수준 암호화는 제대로 작동하지 않습니다.

하지만 당신이 정말로 묻는 것

데이터베이스에 이미 응용 프로그램 수준 인증 체계가있을 때 응용 프로그램 수준 인증 체계를 사용하는 이유는 무엇입니까?

보안

더 안전한 버전을 작성할 가능성을 무시하고 다른 사람들은 여러 가지 이유를 제안했습니다. 나는 일반적으로 동의합니다. 그러나 아직 아무도 언급하지 않은 또 다른 것이 있습니다. 데이터베이스의 보안을 손상시키고 있습니다.

이 시스템에서 애플리케이션의 모든 사용자는 데이터베이스 사용자 및 비밀번호를 갖습니다. 물론, 제한된 사용자이지만 여전히 데이터베이스에 연결할 수있는 사용자입니다. 행 수준 보안을 사용하더라도 최종 사용자는 여전히 데이터베이스 연결 정보를 알 수 있습니다. 사용자가 테이블 수준의 액세스 권한을 얻을 수있는 익스플로잇이 있다면 데이터베이스를 열어 공격 할 수 있습니다. 그리고 일부 악용은 그 이상으로 관리자 액세스를 넘어 섰습니다.

보안 양파 층에서 일반적인 시스템은 다음과 같습니다.

  • 데이터베이스-특정 머신의 연결 만 허용합니다.
  • 데이터베이스, 특정 사용자 / 암호 조합으로 만 연결을 허용합니다.
  • 응용 프로그램으로부터의 연결을 허용하는 데이터베이스 권한이있는 서버.
  • 응용 프로그램은 서버에서 실행됩니다.
  • 응용 프로그램에는 제한된 권한을 가진 데이터베이스 연결 정보가 있습니다.
  • 응용 프로그램은 데이터베이스를 수정하기 전에 사용자를 인증합니다 (새 계정 만들기는 제외).

이 시스템에서 :

  • 최종 사용자는 매우 낮은 권한으로 데이터베이스에서 작동하는 사용자 / 암호 조합을 알고 있습니다.
  • 서버를 구성하거나 승인 된 서버 인 것처럼 가장하기 만하면됩니다.

전체 응용 프로그램 수준의 보안이 손실되었습니다. 그리고 우리는 자발적으로 데이터베이스 계층의 일부를 포기했습니다. 따라서 두 가지 익스플로잇 만 필요합니다.

  1. 인증 된 서버를 스푸핑하거나 손상시킵니다.
  2. 제한된 권한 계정의 액세스 권한을 늘리십시오.

이 두 가지 작업을 수행 할 수 있으면 데이터베이스에 액세스 할 수 있습니다. 그래서 우리는 3 계층에서 2 계층으로 이동합니다. 일반 시스템의 세 번째 계층은 데이터베이스에 연결하려면 유효한 사용자가 필요하다는 것입니다.

이러한 계정을 많이 관리하게됩니다. 실수하면 어떻게 되나요? 사용자 X를 특정 행으로 제한하는 대신 중요한 테이블에 대한 모든 액세스 권한을 부여합니다. 이러한 종류의 작업은 일반적으로 수동으로 수행되며 그 중 몇 가지만 있으므로 감사하기가 쉽습니다. 그러나 시스템에서 각각 고유 한 액세스 권한을 가진 수천 또는 수백만 또는 수십억의 사용자 계정을 수행 할 수 있습니다.

그 문제에 대해 데이터베이스 시스템이 수백만 또는 수십억 명의 사용자로 확장됩니까? 그렇다면 규칙 수는 어떻습니까? 각 사용자가 액세스 할 수있는 것과 액세스 할 수없는 것에 대해 수백 가지 이상의 규칙을 적용하면 최대 10 억 명의 사용자까지 확장 할 수 있습니까? 일반적으로 소규모 시스템을 사용하여 대규모로 만듭니다. 반드시 작동하지는 않습니다. 성장함에 따라 시스템 제한이있을 수 있습니다.


5

설명하는 내용은 인증을 처리하지만 권한 부여 (사용자가 액세스 할 수있는 데이터)는 사용하지 않거나 가장 간단한 사용 사례에서만 처리합니다.

stackexechange를 사용하여 예제를 계속하려면 : 삭제 된 게시물을 높은 담당자에게만 표시하려면 어떻게해야합니까? 따라서 액세스 규칙의 경우 여전히 코드의 논리가 필요합니다. 대부분의 개발자는 데이터베이스 규칙과 응용 프로그램 액세스 규칙간에 액세스 논리를 공유하는 대신 동일한 위치에두기를 선호합니다.

또한 사용자 정보를 저장하는 테이블이 필요합니다. 사용자는 단순한 사용자 이름 + 비밀번호가 아닙니다. 그는 이메일, 평판 등을 가지고 있습니다. 따라서 사용자 테이블이 여전히 필요하며 액세스 할 수있는 경우 데이터베이스 사용자 테이블과 동기화되어 있어야합니다.

솔루션을 사용하면 암호 열을 생략 할 수 있습니다. 암호 입력은 어렵지 않습니다. 암호를 처리 / 해시하는 방법에 대한 라이브러리와 설명서가 있습니다.

다른 요점 : 어떻게 연결 풀을 생성 하시겠습니까? 나는 jdbc (java <-> db) 만 알고 있으며 연결을 얻으려면 사용자 이름 + 암호를 제공해야 풀링 할 수 있습니다.

나는 기존의 방식보다 구현하기가 더 어려워지고 더 복잡해질 몇 가지 다른 점을 생각했습니다.

  • 비밀번호 복구 처리
  • 초기 구현 후 2 년 동안 제품 관리자가 oauth 체계에 대한 지원을 추가하거나 이중 요소 인증을 허용하도록 요청합니다.

CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)첫 번째 질문에 답하는 것과 같은 것이 있습니다. 더 이상 users 테이블이 필요 없다고 말한 적이 없으며 db user 테이블과의 동기화를 보장하는 것은 다소 까다 롭지 만 가능합니다. 논의 된 기술의 핵심은 보안입니다. 연결 풀에 관해서는 OCaml과 함께 일하며 연결 ​​풀이 필요한 이유를 모르겠습니다. 나는 현재 쿠키 값을 연결을 반환하는 0-ary 함수에 연결하는 해시 맵을 사용합니다 :-)
Fabian Pijcke

5
연결 풀은 성능을 향상시키기 위해 구현됩니다. 이들을 사용하면 각 사용자 요청에 대한 연결을 설정할 필요가 없습니다 (따라서 tcp 링크 + 모든 연결 및 데이터베이스와 인증 교환을 작성할 때 CPU / IO / 대기 시간을 절약 할 수 있습니다). 정책 정의와 관련하여 데이터베이스는 이미 한 번 확인한 경우에도 모든 데이터 액세스에 대한 액세스 권한을 지속적으로 확인합니다. 또한 '액세스 거부 또는 금지'는 '확인, 결과 없음'과 동일하지 않습니다. 보안 담당자가 OK 버전을 선호하는지 확실하지 않습니다.
Thierry

3
Fabian, 연결 풀링은 모든 규모의 기본 요소이며 실제로는 사용하지 않는 것으로 간주되지 않는 기본값입니다. 연결 풀링 ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling )을 통한 600x 성능 향상 및 4,000x 이상의 성능 향상 연결 풀링 ( progress.com/tutorials/jdbc/… ). 그것은 몇 배의 크기 차이이며, "좋은"것이 아니며, 앱이 없으면 중단 될 것입니다.
Ivan McA

1
재미있는 숫자. 실제로 연결 풀을 사용하지 않는 응용 프로그램은 본 적이 없습니다. 그러나 나는 그들이 그렇게 많은 속도를 내기를 알지 못했습니다. 연결 풀에서 얻을 수있는 또 다른 측면은 리소스 제어입니다. 덕분에 한 번에 모두 연결하려고하는 클라이언트가 크게 증가하면 응용 프로그램이 느려지지만 데이터베이스에 큰 영향을 미치지 않습니다 (풀이 제대로 구성된 경우). .
Thierry

방금 연결 풀에 대한 자세한 정보를 검색했으며 웹 사이트가 초당 100 개 이상의 연결을 처리하자마자 이것이 유효한 지점이라는 데 동의합니다. PostgreSQL의 모든 연결은 약 10MiB의 RAM을 먹는 것으로 보입니다! 나는 그렇게 생각하지 않았다.
Fabian Pijcke

1

한 가지 다른 점 : 많은 [1] 웹 응용 프로그램을 사용하면 응용 프로그램 자체를 통해 온라인으로 사용자 계정을 등록하고 만들 수 있습니다. 이는 익명의 사용자 (가장 권한이 가장 적은 사용자)가 사용자를 만들고 권한을 부여 할 수있는 권한을 가져야한다는 것을 의미합니다.

OK, 부여 할 수있는 권한을 제한하고 더 높은 수준의 사용자에게 더 많은 부여 옵션을 제공하는 것이 가능할 수 있습니다 (단지 권한은 "단지 권한"이 아닌지 잘 모르겠습니다). 그러나 여전히 모든 사람이 해킹 할 수 있도록 부여 권한이있는 것을 온라인에 배치하는 것을 의미합니다. 내가 그렇게하면 내 DBA가 나를 좋아하지 않을 것이라고 확신합니다. :)

한 수준 에서이 문제가 발생한다는 것을 알고 있지만 웹 앱이 DB 사용자를 관리하지 못하게하면 특히 데이터 삭제에 대한 방어 계층이 있습니다.

또한 풀링되거나 재사용 된 DB 연결을 사용하지 못하게됩니다.

[1] 대부분은 말하지만 백업 할 인물은 아닙니다.

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