HTTP를 통해 안전하게 비밀번호를 보내는 방법은 무엇입니까?
로그인 화면에서 사용자가 자신의 사용자 이름과 비밀번호를 사용하여 양식을 제출하면 비밀번호는 일반 텍스트로 전송됩니다 (POST를 사용하더라도 틀린 경우 수정하십시오).
문제는 통신 데이터를 도청 할 수있는 제 3 자로부터 사용자와 비밀번호를 보호하는 올바른 방법은 무엇입니까?
HTTPS가 문제에 대한 해결책이라는 것을 알고 있지만 표준 HTTP 프로토콜 (POST 요청)을 사용하여 최소한의 보안 수준을 유지할 수있는 방법이 있습니까? (아마도 자바 스크립트를 사용하는 방법)
편집 중요한 것들을 생략했을 수도 있습니다.
내가 한 페이지는 PHP 생성 로그인 페이지입니다. 물론 HTTP GET 요청에서 HTML 파일로 사용자에게 전송됩니다. 서버와 클라이언트간에 (@Jeremy Powel) 연결이 설정되어 있지 않으므로 핸드 셰이 킹 프로토콜을 만들 수 없습니다. 그리고 전체 프로세스가 사용자에게 투명하게 표시되기를 원합니다. 그는 암호를 다루지 않고 암호를 제출하고 싶습니다.
감사.
SSL을 사용하여 HTTP를 사용하면 인생이 훨씬 쉬워지고 스마트 한 사람들 (적어도 나보다 똑똑한 사람들)은 수년간이 기밀 커뮤니케이션 방법을 면밀히 조사해 왔습니다.
보안 인증은 광범위한 주제입니다. 간단히 말해서 @ jeremy-powell이 언급했듯이 항상 HTTP 대신 HTTPS를 통해 자격 증명을 보내는 것을 선호합니다. 보안 관련 두통이 많이 발생합니다.
TSL / SSL 인증서는 요즘 꽤 저렴합니다. 실제로 돈을 전혀 쓰지 않으려면 무료 인증 기관인 letsencrypt.org 가 무료 입니다.
한 단계 더 나아가서 백그라운드에서 letsencrypt 를 호출 하는 caddyserver.com 을 사용할 수 있습니다 .
이제 HTTPS를 중단하면 ...
POST 페이로드 또는 GET 매개 변수를 통해 로그인 및 비밀번호를 보내면 안됩니다. 대신 다음과 같이 구성된 권한 부여 헤더 (기본 액세스 인증 체계)를 사용하십시오.
- 사용자 이름과 비밀번호는 콜론으로 구분 된 문자열로 결합됩니다 (예 : username : password).
- 결과 문자열은 76 문자 / 라인으로 제한되지 않는 Base64의 RFC2045-MIME 변형을 사용하여 인코딩됩니다.
- 인증 방법과 공백 ( "Basic")이 인코딩 된 문자열 앞에 놓입니다.
출처 : Wikipedia : 인증 헤더
조금 복잡해 보일 수도 있지만 그렇지 않습니다. 이 기능을 제공하는 훌륭한 라이브러리가 많이 있습니다.
인증 헤더를 사용해야하는 몇 가지 이유가 있습니다.
- 표준입니다
- 간단합니다 (사용 방법을 익힌 후).
- 다음과 같이 URL 수준에서 로그인 할 수 있습니다.
https://user:password@your.domain.com/login
(예 : Chrome은 자동으로Authorization
헤더 로 변환합니다 )
중요 :
아래의 의견에서 @zaph가 지적한 것처럼 민감한 정보를 GET 쿼리로 보내는 것은 서버 로그에서 끝날 수 있으므로 좋지 않습니다.
You can use a challenge response scheme. Say the the client and server both know a secret S. Then the server can be sure that the client knows the password (without giving it away) by:
- Server sends a random number, R, to client.
- Client sends H(R,S) back to the server (where H is a cryptographic hash function, like SHA-256)
- Server computes H(R,S) and compares it to the client's response. If they match, the server knows the client knows the password.
Edit:
There is an issue here with the freshness of R and the fact that HTTP is stateless. This can be handled by having the server create a secret, call it Q, that
only the server knows. Then the protocol goes like this:
- Server generates random number R. It then sends to the client H(R,Q) (which cannot be forged by the client).
- Client sends R, H(R,Q), and computes H(R,S) and sends all of it back to the server (where H is a cryptographic hash function, like SHA-256)
- Server computes H(R,S) and compares it to the client's response. Then it takes R and computes (again) H(R,Q). If the client's version of H(R,Q) and H(R,S) match the server's re-computation, the server deems the client authenticated.
To note, since H(R,Q) cannot be forged by the client, H(R,Q) acts as a cookie (and could therefore be implemented actually as a cookie).
Another Edit:
The previous edit to the protocol is incorrect as anyone who has observed H(R,Q) seems to be able to replay it with the correct hash. The server has to remember which R's are no longer fresh. I'm CW'ing this answer so you guys can edit away at this and work out something good.
If your webhost allows it, or you will need to deal with sensitive data, then use HTTPS, period. (It's often required by the law afaik).
Otherwise if you want to do something over HTTP. I would do something like this.
- The server embeds its public key into the login page.
- The client populates the login form and clicks submit.
- An AJAX request gets the current timestamp from the server.
- Client side script concatenates the credentials, the timestamp and a salt (hashed from analog data eg. mouse movements, key press events), encrypts it using the public key.
- Submits the resulting hash.
- Server decrypts the hash
- Checks if the timestamp is recent enough (allows a short 5-10 second window only). Rejects the login if the timestamp is too old.
- Stores the hash for 20 seconds. Rejects the same hash for login during this interval.
- Authenticates the user.
So this way the password is protected and the same authentication hash cannot be replayed.
About the security of the session token. That's a bit harder. But it's possible to make reusing a stolen session token a bit harder.
- The server sets an extra session cookie which contains a random string.
- The browser sends back this cookie on the next request.
- The server checks the value in the cookie, if it's different then it destroys the session, otherwise all is okay.
- The server sets the cookie again with different text.
So if the session token got stolen, and a request is sent up by someone else, then on the original user's next request the session will be destroyed. So if the user actively browsing the site, clicking on links often, then the thief won't go far with the stolen token. This scheme can be fortified by requiring another authentication for the sensitive operations (like account deletion).
EDIT: Please note this doesn't prevent MITM attacks if the attacker sets up their own page with a different public key and proxies requests to the server. To protect against this the public key must be pinned in the browser's local storage or within the app to detect these kind of tricks.
About the implementation: RSA is probably to most known algorithm, but it's quite slow for long keys. I don't know how fast a PHP or Javascript implementation of would be. But probably there are a faster algorithms.
I would use a server-side and client-side Diffie-Hellman key exchange system with AJAX or multiple form submits(I recommend the former), although I don't see any good implementations thereof on the internet. Remember that a JS library can always be corrupted or changed by MITM. Local storage can be used to help combat this, to an extent.
You can use SRP to use secure passwords over an insecure channel. The advantage is that even if an attacker sniffs the traffic, or compromises the server, they can't use the passwords on a different server. https://github.com/alax/jsrp is a javascript library that supports secure passwords over HTTP in the browser, or server side (via node).
HTTPS is so powerful because it uses asymmetric cryptography. This type of cryptography not only allows you to create an encrypted tunnel but you can verify that you are talking to the right person, and not a hacker.
Here is Java source code which uses the asymmetric cipher RSA (used by PGP) to communicate: http://www.hushmail.com/services/downloads/
호스트에 ssl을 사용할 수 있습니다 letsencrypt https://letsencrypt.org/ 와 같은 ssl에 대한 무료 프로젝트가 있습니다.
참고 URL : https://stackoverflow.com/questions/1582894/how-to-send-password-securely-over-http
'programing tip' 카테고리의 다른 글
Foundation에서 요일을 어떻게 알 수 있습니까? (0) | 2020.08.03 |
---|---|
reactjs 앱에 부트 스트랩 CSS와 JS를 포함시키는 방법은 무엇입니까? (0) | 2020.08.03 |
메이븐 빌드에서 junit 테스트를 병렬로 실행합니까? (0) | 2020.08.02 |
스칼라 배우 : 수신 대 반응 (0) | 2020.08.02 |
FireFox, Safari 및 Chrome을 사용하여 클립 보드에 텍스트 복사 / 붙여 넣기 (0) | 2020.08.02 |