Http authentication

From 탱이의 잡동사니
Jump to navigation Jump to search

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

  1. define _GNU_SOURCE
  1. include <stdio.h>
  2. include <stdbool.h>
  3. include <evhtp.h>
  1. 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