REST API 호출에 비밀번호 넣기


31

암호를 설정 / 재설정하는 데 사용되는 REST API가 있다고 가정하십시오. 이것이 HTTPS 연결을 통해 작동한다고 가정합시다. 이 암호를 호출 경로에 넣지 말아야 할 충분한 이유가 있습니까? 또한 BASE64로 암호화한다고 가정 해 봅시다.

예를 들어 다음과 같이 비밀번호를 재설정합니다.

http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD

BASE64는 암호화가 아니라는 것을 알고 있지만이 경우에는 숄더 서핑의 비밀번호 만 보호하려고합니다.


61
GET에 대한 부작용을 제안하고 있습니까? 그것은 바로 프로토콜 위반입니다.
Esben Skov Pedersen

27
resetpassword/OLDPASSWD/NEWPASSWD리소스가 아니기 때문에 실제로 REST 가 아닙니다. 프로세스의 호출입니다. 모든 것을 URL에 넣을 필요는 없습니다.
usr

5
@ Esben : 누가 GET이라고 말했습니까? OP는 결코 말하지 않았다.
dagnelies

3
사실, 그는 질문에 없었습니다. 그러나 Netch의 답변에 대한 그의 의견은 "결국 POST를 사용해야 할 것 같아"라고 말합니다. 따라서 우리는 그가 원래 GET에 대해 의도 한 것 / 물었다 고 가정 할 수 있습니다. Esben이 지적한 바와 같이, 그것은 나쁜 것입니다. GET은 읽기 전용이어야합니다.
Mawg

4
암호 재설정 메커니즘의 많은 함정을 설명하는통찰력있는 기사 는 사례를 더 잘 이해하는 데 도움이 될 수 있습니다.
9000

답변:


76

좋은 서버는 URL (종종 '?'뒤에 변수 부분이 없음), 소스 IP, 실행 시간을 포함하여 전송 된 모든 요청을 기록합니다.이 로그 (광범위한 관리자 그룹에서 잠재적으로 읽음)를 포함 하시겠습니까? 비밀번호로 정보를 안전하게 보호 하시겠습니까? Base64는 그들에 대한 스토퍼가 아닙니다.


42
이것이 POST를 사용하는 가장 큰 이유는 아닙니다. 보안상의 이유입니다. 그러나 Esben이 이미 언급 한 바와 같이 GET으로 상태를 변경하는 것은 그러한 휴식 서비스를 위반하는 것입니다.
Pinoniq

2
@BartFriederichs : 및 브라우저 기록은 URL을 기억합니다. 그리고 시도하려는 모든 비밀번호에 대한 링크가있는 웹 페이지를 만들고 Googlebot이 실제 요청을 수행하도록하여 익명으로 많은 비밀번호를 시험해보십시오.
RemcoGerlich

2
"Esben allready가 의견을봤을 때, GET으로 상태를 변경하는 것은 그러한 Rest 서비스를 위반하는 것입니다."나는 그 의견도 알아 차 렸지만, 이것이 GET 요청이라고 말하는 사람은 어디에도 없습니다. 결국 URI에 정보를 포함시키고 여전히 POST 할 수 있습니다. URI가 실제로 리소스의 이름을 지정하지 않기 때문에 실제로 RESTful 하지 않습니다.
Joshua Taylor

안녕하세요, 좋은 대답이지만 " '뒤에 변수 부분이 없습니까?"에 동의하지 않습니다 ... 전체 URL을 저장하는 많은 사람들이 있습니다 !!!
dagnelies

2
"GET으로 상태를 변경하는 것은 이러한 Rest 서비스를 위반하는 것입니다"-REST에 너무 익숙해지지 않도록합시다. GET으로 상태를 변경하는 것은 HTTP 위반입니다 .
Dan Ellis

69

당신이 제안하는 것은 안전하거나 RESTful하지 않습니다.

@Netch는 이미 로그 관련 문제에 대해 언급했지만 HTTP로 전송 된 비밀번호를 표시한다는 점에서 또 다른 문제가 있습니다.

REST를 사용하여 GET 요청을 수행하면 URL의 다른 요소가보다 세분화 된 요소를 나타냅니다. URL은 재설정 암호의 일부인 OLDPASSWD의 NEWPASSWD 부분을 반환하는 것처럼 읽습니다. 그것은 의미 상 의미가 없습니다. GET을 사용하여 데이터를 저장해서는 안됩니다.

당신은 이런 식으로해야합니다 :

POST https://www.example.com/user/joe/resetpassword/
{oldpasswd:[data], newpasswd:[data]}

데이터를 작성하고 있기 때문에 POST, 스니핑을 원하지 않기 때문에 https.

(이것은 실제로 보안 수준이 낮습니다. 절대적으로해야합니다.)


2
이것이 클라이언트 측의 비밀번호를 해시하는 것을 의미하지 않습니까? 이것이 권장됩니까?
Rowan Freeman

1
참고 : 암호 (길이 등) 요구 사항을 적용 할 수 없습니다. 보안 관행이 빈번하고 때로는 일부 엔터티에 의해 요구 되기는하지만 귀하의 경우에는 문제가되지 않을 수 있습니다.
Paul Draper

8
새 레코드를 만들지 않고 기존 레코드를 업데이트하는 경우가 많으므로 POST가 아니라 PUT이어야합니다.

4
이것은 매우 RESTful하지 않습니다. resetpassword는 하위 리소스는 물론 리소스가 아닙니다. 그러나 /user/joe/password조금 더 좋지만 최적은 아닙니다.
whirlwin

12
@CamilStaps 아니, 당신은 사용할 수 PUT있기 때문에, PUT나무 등입니다. 암호가 변경되었습니다 때 secret까지 supersecret성공적으로, 다음 같은 요청은 그래서, 두 번째 시간을 실패합니다 POST여기에 올바른 것입니다. 물론 @whirlwin이 말했듯 이이 리소스의 이름이 잘못되었습니다.
Residuum

60

제안 된 제도는 여러 분야에서 문제가있다.

보안

URL 경로는 자주 기록됩니다. 해싱되지 않은 암호를 경로에 넣는 것은 좋지 않습니다.

HTTP

인증 / 권한 정보가 Authorization 헤더에 나타납니다. 또는 잠재적으로 브라우저 기반의 경우 쿠키 헤더입니다.

휴식

resetpasswordURL 과 같은 동사 는 일반적으로 비 표현 상태 이전 패러다임의 명확한 신호입니다. URL은 리소스를 나타내야합니다. GET 무엇을 의미 resetpassword합니까? 아니면 삭제?

API

이 체계에는 항상 이전 비밀번호를 알아야합니다. 더 많은 경우를 허용 할 것입니다. 예를 들어 비밀번호가 손실됩니다.


잘 알려진 체계 인 기본 또는 다이제스트 인증을 사용할 수 있습니다 .

PUT /user/joe/password HTTP/1.0
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: text/plain
Host: www.example.com

NEWPASSWD

경로에 매우 민감한 정보를 넣지 않으며 HTTP 및 REST 규칙을 따릅니다.

다른 인증 모드 (예 : 확인 된 채널을 통해 비밀번호를 재설정하기 위해 전송 된 일부 토큰)를 허용해야하는 경우 다른 사항을 변경하지 않고도 다른 인증 헤더를 사용할 수 있습니다.


4

보안 외에도이 문제는 매우 RESTful 한 접근 방식이 아니라는 것입니다.

OLDPASSWDNEWPASSWD 자원 계층 구조에서 아무것도, 심지어 악화 서 있지 않는 작업이 멱등하지 않습니다.

따라서 POST동사 로만 사용할 수 있으며 리소스 경로에 두 개의 비밀번호를 포함해서는 안됩니다.


1
새 레코드를 만들지 않고 기존 레코드를 업데이트하는 경우가 많으므로 POST가 아니라 PUT이어야합니다.

2
@CamilStaps 비밀번호를 설정 한 것일 수 있습니다. 그러나 이전 암호도 확인해야하므로 조작이 비등 성이므로 PUT동사로 실격됩니다. 작업하기 위해 rejigged 될 수 PUT있지만 현재 형태로는 작동하지 않습니다.
biziclop

OLDPASSWD는 인증 정보이므로 URL에 포함되어서는 안됩니다.

반드시 인증이 아닌 기존 비밀번호를 명시 적으로 요청하는 것이 일반적입니다.
biziclop

3

문제는 요청에서 일반 텍스트 비밀번호를 사용하지 않는 것입니다. 편안한 웹 서비스 요구 사항을 충족시키는 두 가지 옵션이 있습니다.

1. 클라이언트 측 해싱

  • 예를 들어 hash (password + salt)와 같은 비밀번호를 저장하고 있다고 생각합니다.
  • 클라이언트 측에서 소금으로 새 비밀번호를 해시 할 수 있습니다.
  • 즉, 클라이언트 측에 새 솔트를 만들고 해시를 만듭니다 (예 : hash (newPassword + newSalt)).
  • 새로 생성 된 해시와 소금을 편안한 웹 서비스로 보냅니다.
  • 이전 비밀번호를 hash (oldPassword + oldSalt)로도 전송

2. 암호화

  • / otk / john과 같은 사용자를위한 "일회성 키"(otk) 리소스를 만듭니다.
  • 이 리소스는 안전한 임의의 고유 한 일회용 키를 반환합니다.
  • 당신의 편안한 웹 서비스는 ID 95648915125와의 다음 안전한 통신을 위해이 임의의 otk를 저장해야합니다
  • otk를 사용하여 새 비밀번호와 기존 비밀번호를 암호화하십시오 (예 : AES) 보안상의 이유로 이전 비밀번호와 새 비밀번호에 대해 두 개의 별도 otks를 사용해야합니다.
  • ID가 95648915125 인 비밀번호 변경 자원으로 암호화 된 비밀번호를 전송하십시오.
  • 하나의 otk 및 ID 조합은 한 번만 작동 할 수 있으므로 비밀번호를 변경 한 후 해당 조합을 삭제해야합니다.
  • 더 나은 옵션 : Basic-Auth로 현재 / 이전 암호를 보냅니다.

참고 : 두 옵션 모두 HTTPS가 필요합니다!


1
비밀번호 교환을 이중 암호화 (OTK 및 HTTPS를 사용한 암호화 체계)하는 이유는 무엇입니까? HTTPS에 포함되지 않은 공격 경로는 무엇입니까?
Bart Friederichs

1
유일한 목적은 가능한 서버 로그를 피하는 것입니다. HTTPS를 사용하더라도 HTTP 요청 본문 (예 : 일반 텍스트 새 비밀번호)을 기록 할 수도 있습니다. 다른 가능한 공격은 특히 내부 목적으로 사용되는 자체 서명 인증서의 사용입니다.
maz258

2

비밀번호 재설정 작업의 기능은 무엇입니까?

  1. 뭔가 바뀝니다.
  2. 설정된 값이 있습니다.
  3. 일부 사용자 만 수행 할 수 있습니다 (사용자, 관리자 또는 둘 중 하나에 대한 다른 규칙이있을 수 있음).

여기서 1 포인트는 GET을 사용할 수 없음을 의미합니다. 비밀번호 변경 작업을 나타내는 자원을 비밀번호 변경을 처리하는 자원을 나타내는 URI에 POST하거나 새 비밀번호를 나타내는 무언가를 비밀번호를 나타내는 URI에 PUT 또는 무언가를 나타내는 것 (예 : 해당 비밀번호가 기능인 사용자).

일반적으로 POST는 어색 할 수 있기 때문에 나중에 게시 할 수 없습니다. 나중에 GET 할 수없고 암호를 얻을 수 없습니다.

따라서 포인트 2는 POST 된 새로운 비밀번호를 나타내는 데이터가됩니다.

포인트 3은 요청을 승인해야 함을 의미합니다. 즉, 사용자가 현재 사용자 인 경우 현재 비밀번호를 확인해야합니다 (해시 기반 도전과 같은 경우 반드시 현재 비밀번호를받을 필요는 없음) 보내지 않고 지식을 증명하는 데 사용되었습니다).

URI는 그러므로 같은 것을해야한다 <http://example.net/changeCurrentUserPassword>또는 <http://example.net/users/joe/changePassword>.

POST 데이터 및 사용중인 일반 권한 부여 메커니즘에서 현재 비밀번호를 수신하기로 결정할 수 있습니다.

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