Python을 이용해 네이버 로그인을 구현하기 위한 분석 내용입니다. 일단 네이버 로그인을 할 때 https 통신을 이용해서 정보를 주고 받기 때문에 Wireshark와 같은 툴을 사용해 패킷을 가져오더라도 암호화가 되어 있어서 그 내용을 알기 어렵습니다. 물론 인증서에 대한 키 값을 알고 있다면 쉽게 복호화가 가능합니다. 또한 Paros나 Burp Suite와 같은 프록시 툴을 사용한다면 중간에 어떤 요청이 들어갔는지를 알아 낼 수 있습니다. 하지만 네이버는 프록시 툴을 이용하더라도 로그인 정보를 알 수 없게 만들었습니다. 여기에서는 어떠한 방식으로 구현을 했는지를 살펴보도록 하겠습니다.
여기에서는 특별한 프로그램을 사용하지 않고 Chrome에서 기본으로 제공하는 기능만을 사용해서 분석을 하겠습니다.
먼저 네이버의 로그인 화면입니다. 여기에서 일단 요청을 보냈을 때 ID와 PW 정보를 포함해서 보내는지를 간단하게 확인하기 위해서 ID와 PW에 각각 'test'를 입력하고 로그인을 누릅니다.
Chrome의 Network 기능을 이용하면 어떤 요청이 있었는지를 확인합니다.
보다시피 id와 pw에는 빈 값이 들어있고, encpw 필드에서 매우 긴 값이 있는 것을 볼 수 있습니다. encpw라고 필드 명이 되어 있는 것으로 보아 계정 정보를 암호화한 필드라고 예상을 할 수 있습니다. 이제 이 예상이 맞는지를 확인해보도록 하겠습니다.
로그인 화면의 소스코드를 살펴보도록 하겠습니다.
소스코드의 form 부분을 보시면 제출을 했을 때 confirmSubmit 함수를 호출하는 것을 확인할 수 있습니다. confirmSubmit 함수에 대한 내용은 아래 코드와 같습니다.
function confirmSubmit() { var id = $("id"); var pw = $("pw"); var encpw = $("encpw"); //if(id.value == "" && encpw.value == "") { if(id.value == "") { show("err_empty_id"); hide("err_empty_pw"); hide("err_common"); id.focus(); return false; //} else if(pw.value == "" && encpw.value == "") { } else if(pw.value == "") { hide("err_empty_id"); show("err_empty_pw"); hide("err_common"); pw.focus(); return false; } try{ $("ls").value = localStorage.getItem("nid_t"); }catch(e){} return encryptIdPw(); }
이 코드를 살펴보면 id 필드나 pw 필드가 비어 있을 때 비어 있다는 에러 메시지를 출력하고, id와 pw 값이 있다면 encryptIdPw 함수를 호출합니다. encryptIdPw 함수의 소스코드는 아래와 같습니다.
function encryptIdPw() { var id = $("id"); var pw = $("pw"); var encpw = $("encpw"); var rsa = new RSAKey; if (keySplit(session_keys)) { rsa.setPublic(evalue, nvalue); try{ encpw.value = rsa.encrypt( getLenChar(sessionkey) + sessionkey + getLenChar(id.value) + id.value + getLenChar(pw.value) + pw.value); } catch(e) { return false; } $('enctp').value = 1; id.value = ""; pw.value = ""; return true; } else { getKeyByRuntimeInclude(); return false; } return false; }
이 코드를 살펴보면, 'rsa'라는 변수명이 등장하는 것을 보실 수 있습니다. 그리고 encpw 필드의 값을 rsa.encrypt 부분을 통해서 설정하고 있는 것을 볼 수 있습니다. 즉 네이버는 로그인을 할 때, evalue와 nvalue 값을 rsa의 공개키로 사용을 하고, sessionKey, id 필드 값과 pw 필드 값과 각각의 길이 정보를 이용해서 rsa로 암호화를 하는 것을 알 수 있습니다. 참고로 evalue, nvalue, sessionKey의 경우에는 keySplit 함수에서 값이 설정됩니다.
function keySplit(a) { keys = a.split(","); if (!a || !keys[0] || !keys[1] || !keys[2] || !keys[3]) { return false; } sessionkey = keys[0]; keyname = keys[1]; evalue = keys[2]; nvalue = keys[3]; $("encnm").value = keyname; return true }
그리고 keySplit 함수의 인자로 들어가는 session_keys의 경우에는 xhr로 받아오는 것을 확인할 수 있습니다.
즉 정리하자면, 네이버의 경우에는 로그인을 할 때 세션키와 공개키를 xhr로 받아오고, 아이디, 비밀번호 그리고 세션키 정보를 이용해서 RSA로 암호화를 한 후에 그것을 요청으로 보낸다는 것을 알 수 있습니다.
'컴퓨터 > 사이트 분석' 카테고리의 다른 글
티스토리 방문자 통계 및 유입로그 분석 (0) | 2015.12.22 |
---|