Http authentication: Difference between revisions
Jump to navigation
Jump to search
(→Basic) |
(→Basic) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 6: | Line 6: | ||
* Anonymous(익명) | * Anonymous(익명) | ||
* BASIC | * BASIC authorization | ||
* DIGEST | * DIGEST authorization | ||
* SSL | * SSL client authorization | ||
* | * Form base authorization | ||
* OAuth | * OAuth | ||
Line 15: | Line 15: | ||
인증정보를 포함하지 않는 요청도 인증 방식에 포함된다. 리소스에 대해 모든 엑세스 권한을 부여한다. | 인증정보를 포함하지 않는 요청도 인증 방식에 포함된다. 리소스에 대해 모든 엑세스 권한을 부여한다. | ||
== Basic == | == Basic authentication == | ||
Basic | Basic authentication(BA) 인증. 클라이언트에 사용자 이름과 암호를 Base64 로 된 문자열을 요청한다. 간편하며 널리 쓰이지만, 패킷 도청에 매우 취약하다. | ||
=== Feature === | === Feature === | ||
Line 37: | Line 37: | ||
* Client Side | * Client Side | ||
=== Example === | |||
<source lang=c> | |||
// main.c | |||
#define _GNU_SOURCE | |||
#include <stdio.h> | |||
#include <stdbool.h> | |||
#include <evhtp.h> | |||
#define DEF_BASIC_REALM "pchero21.com mailservice" // basic realm info | |||
/** | |||
\brief reply unauth error with realm info. | |||
*/ | |||
void reply_unauth_error(evhtp_request_t* r) | |||
{ | |||
// set realm info | |||
evhtp_headers_add_header(r->headers_out, evhtp_header_new("WWW-Authenticate", "Basic realm=" DEF_BASIC_REALM, 0, 0)); | |||
evhtp_headers_add_header(r->headers_out, evhtp_header_new("Content-Length", "0", 0, 0)); | |||
evhtp_send_reply(r, EVHTP_RES_UNAUTH); | |||
return; | |||
} | |||
bool check_basic_auth(evhtp_request_t* r) | |||
{ | |||
evhtp_connection_t* conn; | |||
const char* auth_hdr; | |||
if(r == NULL) { | |||
fprintf(stderr, "Wrong input parameter.\n"); | |||
return false; | |||
} | |||
conn = evhtp_request_get_connection(r); | |||
if(conn == NULL) { | |||
fprintf(stderr, "Could not get connection info.\n"); | |||
return false; | |||
} | |||
if(conn->request->headers_in == NULL) { | |||
fprintf(stderr, "Could not get correct connection info.\n"); | |||
return false; | |||
} | |||
// Get Base64 encoded Authorization info | |||
auth_hdr = evhtp_kv_find(conn->request->headers_in, "Authorization"); | |||
if(auth_hdr == NULL) { | |||
fprintf(stderr, "Could not get auth info.\n"); | |||
return false; | |||
} | |||
// Authorization: Basic SOME_BASE_64_ENCODED_STRING | |||
fprintf(stdout, "Requested authorization info. auth_hdr[%s]\n", auth_hdr); | |||
return true; | |||
} | |||
void testcb(evhtp_request_t *req, void *a) | |||
{ | |||
const char *str = a; | |||
int ret; | |||
printf("test callback.\n"); | |||
ret = check_basic_auth(req); | |||
if(ret == false) { | |||
reply_unauth_error(req); | |||
return; | |||
} | |||
evbuffer_add_printf(req->buffer_out, "%s", str); | |||
evhtp_send_reply(req, EVHTP_RES_OK); | |||
} | |||
int main(int argc, char** argv) | |||
{ | |||
evbase_t *evbase = event_base_new(); | |||
evhtp_t *htp = evhtp_new(evbase, NULL); | |||
evhtp_set_cb(htp, "/simple/", testcb, "simple"); | |||
evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024); | |||
event_base_loop(evbase, 0); | |||
evhtp_unbind_socket(htp); | |||
evhtp_free(htp); | |||
event_base_free(evbase); | |||
return 0; | |||
} | |||
</source> | |||
Sample | |||
<pre> | |||
$ ./main & | |||
... | |||
$ curl -vX GET http://127.0.0.1:8081/simple/ --user pchero:1234 | |||
* Hostname was NOT found in DNS cache | |||
* Trying 127.0.0.1... | |||
* Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0) | |||
* Server auth using Basic with user 'pchero' | |||
> GET /simple/ HTTP/1.1 | |||
> Authorization: Basic cGNoZXJvOjEyMzQ= | |||
> User-Agent: curl/7.35.0 | |||
> Host: 127.0.0.1:8081 | |||
> Accept: */* | |||
> | |||
test callback. | |||
Requested authorization info. auth_hdr[Basic cGNoZXJvOjEyMzQ=] | |||
< HTTP/1.1 200 OK | |||
< Content-Length: 6 | |||
< Content-Type: text/plain | |||
< | |||
* Connection #0 to host 127.0.0.1 left intact | |||
-------------------------------------------------------------- | |||
$ curl -vX GET http://127.0.0.1:8081/simple/ | |||
* Hostname was NOT found in DNS cache | |||
* Trying 127.0.0.1... | |||
* Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0) | |||
> GET /simple/ HTTP/1.1 | |||
> User-Agent: curl/7.35.0 | |||
> Host: 127.0.0.1:8081 | |||
> Accept: */* | |||
> | |||
test callback. | |||
Could not get auth info. | |||
< HTTP/1.1 401 Unauthorized | |||
< WWW-Authenticate: Basic realm=pchero21.com mailservice | |||
< Content-Length: 0 | |||
< Content-Type: text/plain | |||
< | |||
* Connection #0 to host 127.0.0.1 left intact | |||
</pre> | |||
== See also == | == See also == |
Latest revision as of 11:27, 10 August 2016
Overview
http authentication 내용 정리.
Basic
HTTP 에서 사용할 수 있는 인증 방법은 다음과 같다.
- Anonymous(익명)
- BASIC authorization
- DIGEST authorization
- SSL client authorization
- Form base authorization
- OAuth
Anonymous
인증정보를 포함하지 않는 요청도 인증 방식에 포함된다. 리소스에 대해 모든 엑세스 권한을 부여한다.
Basic authentication
Basic authentication(BA) 인증. 클라이언트에 사용자 이름과 암호를 Base64 로 된 문자열을 요청한다. 간편하며 널리 쓰이지만, 패킷 도청에 매우 취약하다.
Feature
- BA인증은 전송 단계에서 아무런 암호화 보안을 제공하지 않는다. 단순히 Base64로 인코딩을 할 뿐이며, 어떠한 암호화나 해쉬화가 되지 않는다. 이 때문에 자주 HTTP에서는 이를 다른 암호화 기술과 함께 혼용하여 사용한다.
- Base64로 인코딩된 값은 쉽게 디코딩이 가능하다. 비밀번호가 그대로 노출된다. 때문에 쉽게 사용자 정보를 알아내어 악용할 수 있다.
- BA인증 필드는 HTTP 요청 헤더에 포함되기 때문에, 필요한 경우, WEB 브라우저 자체에서 인증정보(username/password)를 캐시로 저장할 수 있다. 캐시되는 기간과 정책은 각각의 브라우저마다 다르다.
- HTTP 에서는 웹서버의 Log out 메소드를 지원하지 않는다. 하지만 보안 캐시를 삭제하는 몇가지 방법들이 있다. 그 중 한가지 방법으로 사용자를 다른 URL 로 redirect 하여 보안 정보를 더 이상 사용할 수 없는 정보로 업데이트하게끔 유도하는 것이다.
- BA 인증과 관련한 캐싱/기간/정책 등은 브라우저마다 다를 수 있다.
- 프록시나 중개자가 개입하는 경우, 정상적인 동작을 보장하지 않는다.
- 가짜 서버의 위장에 취약하다.
Protocol
다음과 같은 내용으로 프로토콜이 진행된다.
- Client 는 서버로
- Server side
- Client Side
Example
<source lang=c> // main.c
- define _GNU_SOURCE
- include <stdio.h>
- include <stdbool.h>
- include <evhtp.h>
- define DEF_BASIC_REALM "pchero21.com mailservice" // basic realm info
/**
\brief reply unauth error with realm info. */
void reply_unauth_error(evhtp_request_t* r) {
// set realm info evhtp_headers_add_header(r->headers_out, evhtp_header_new("WWW-Authenticate", "Basic realm=" DEF_BASIC_REALM, 0, 0)); evhtp_headers_add_header(r->headers_out, evhtp_header_new("Content-Length", "0", 0, 0)); evhtp_send_reply(r, EVHTP_RES_UNAUTH); return;
}
bool check_basic_auth(evhtp_request_t* r) {
evhtp_connection_t* conn; const char* auth_hdr; if(r == NULL) { fprintf(stderr, "Wrong input parameter.\n"); return false; } conn = evhtp_request_get_connection(r); if(conn == NULL) { fprintf(stderr, "Could not get connection info.\n"); return false; } if(conn->request->headers_in == NULL) { fprintf(stderr, "Could not get correct connection info.\n"); return false; } // Get Base64 encoded Authorization info auth_hdr = evhtp_kv_find(conn->request->headers_in, "Authorization"); if(auth_hdr == NULL) { fprintf(stderr, "Could not get auth info.\n"); return false; } // Authorization: Basic SOME_BASE_64_ENCODED_STRING fprintf(stdout, "Requested authorization info. auth_hdr[%s]\n", auth_hdr); return true;
}
void testcb(evhtp_request_t *req, void *a) {
const char *str = a; int ret;
printf("test callback.\n"); ret = check_basic_auth(req); if(ret == false) { reply_unauth_error(req); return; } evbuffer_add_printf(req->buffer_out, "%s", str); evhtp_send_reply(req, EVHTP_RES_OK);
}
int main(int argc, char** argv) {
evbase_t *evbase = event_base_new(); evhtp_t *htp = evhtp_new(evbase, NULL); evhtp_set_cb(htp, "/simple/", testcb, "simple");
evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024); event_base_loop(evbase, 0); evhtp_unbind_socket(htp); evhtp_free(htp); event_base_free(evbase); return 0;
} </source>
Sample
$ ./main & ... $ curl -vX GET http://127.0.0.1:8081/simple/ --user pchero:1234 * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0) * Server auth using Basic with user 'pchero' > GET /simple/ HTTP/1.1 > Authorization: Basic cGNoZXJvOjEyMzQ= > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8081 > Accept: */* > test callback. Requested authorization info. auth_hdr[Basic cGNoZXJvOjEyMzQ=] < HTTP/1.1 200 OK < Content-Length: 6 < Content-Type: text/plain < * Connection #0 to host 127.0.0.1 left intact -------------------------------------------------------------- $ curl -vX GET http://127.0.0.1:8081/simple/ * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0) > GET /simple/ HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8081 > Accept: */* > test callback. Could not get auth info. < HTTP/1.1 401 Unauthorized < WWW-Authenticate: Basic realm=pchero21.com mailservice < Content-Length: 0 < Content-Type: text/plain < * Connection #0 to host 127.0.0.1 left intact
See also
- http://sonim1.tistory.com/100 - HTTP 를 이용한 인증방식 - BASIC, DIGEST, SSL, FORM
- https://en.wikipedia.org/wiki/Basic_access_authentication - Basic access authentication
- http://iloveulhj.github.io/posts/http/http-basic-auth.html - [HTTP] 기본 인증
- http://behonestar.tistory.com/35 - HTTP Digest 인증