1. 시작하며
개발이나 정보 보안을 공부하다 보면 서버 사이드 & 클라이언트 사이드 라는 용어를 자주 사용한다.
가장 대표적인 예시를 들어보자면 PHP는 서버 사이드에서 동작하는 언어이고, javascript는 클라이언트 사이드에서 동작하는 언어다.
필자가 가르치는 학생들 중에서도 이러한 차이를 구분하지 못하는 친구들이 많았는데, 이러한 개념을 정화하게 짚고 넘어가는것이 굉장히 중요하다.
2. 개념잡기
서버 사이드란 서버에서 동작한다는 뜻이고, 클라이언트 사이드란 클라이언트에서 동작한다는 의미다.
여기서 우리는 서버와 클라이언트의 차이가 무엇인지부터 이해해야 더 나아갈 수 있다.
2-1. 서버와 클라이언트
서버와 클라이언트는 수요와 공급의 관계라 생각해볼 수 있다.
서버는 클라이언트가 요구하는 어떤 서비스를 제공하기 위해 응답 대기상태로 존재하다가 클라이언트의 요청이 들어오면 적절한 인증과정을 거쳐 권한이 있는 클라이언트에게 인가된 정확한 정보를 제공한다.
클라이언트는 서버에게 어떤 질의(쿼리)를 요청하고, 데이터를 리턴받는다.
정말 대표적인 개념으로 웹 서버를 생각해볼 수 있다.
웹 서버 또는 WAS는 대기상태로 클라이언트의 응답을 기다린다. 클라이언트는 브라우저를 통해 적절한 권한이 있음을 인증하고, 서버에 필요로하는 데이터를 요청한다.
2-2. 서버 사이드와 클라이언트 사이드
자 그러면 이제 우리는 서버 사이드와 클라이언트 사이드에 대해 이해할 준비를 마쳤다.
서버 사이드란, 서버에서 동작하며 클라이언트의 어떤 요청에 대해 응답을 생성하고 반환하는 동작 또는 언어를 의미한다.
어떤 WAS에 hello.php 라는 PHP 페이지가 있고, 로그인한 사용자가 hello.php 라는 페이지에 접근하면 ‘hello <사용자 이름>’ 이라는 문자열을 응답한다고 생각해보자.
가장 먼저 서버는 클라이언트가 로그인에 사용한 계정과 비밀번호 정보를 가지고 DB에 질의할것이다. 이 인증정보가 데이터 베이스에 존재하나요? 하고 말이다. 만약 DB에 정확하게 일치하는 정보가 존재한다면 사용는 로그인에 성공한다.
이때 이러한 모든 작업은 클라이언트 사이드가 아니라 WAS의 뒷단에서 발생한다. 사용자가 클라이언트 단에서 한 일은 로그인 페이지에서 적절한 인증정보를 입력한 것 뿐이다. 이 인증정보를 분석하는 것은 모두 서버에서 동장한 것이라는 의미다.
자 그렇다면 클라이언트 사이드라는 것은 어떤 의미일까?
말그대로 클라이언트의 웹 브라우저에서 코드를 읽고 어떤 기능들이 실행된다는 의미다. 예를 들면 오른쪽 클릭이 금지된 웹 페이지나, 복사하기 아이콘을 클릭하면 컨텐츠가 복사되는 등의 이런 기능들 말이다.
물론 이러한 기능들을 모두 서버단에서 처리할 수도 있겠지만, 클라이언트 단으로 빼는 중요한 이유가 있다.
바로 부하 분산이다. 서버가 모든 기능을 전담해 수많은 클라이언트로부터 그 수많은 다양한 요청을 처리하려면 너무나 많은 부하가 발생한다.
따라서 기능의 일부를 클라이언트의 컴퓨터에게로 떠넘기는 것이다. 웹 서버 접근 시 최초 js 파일을 다운로드 시키고 이 코드가 동작하도록 설계만하면 아주 효과적으로 서버의 부하를 분산시킬 수 있는 것이다.
2-3. 서버 사이드와 클라이언트 사이드의 차이
서버 사이드 언어와 클라이언트 사이드 언어는 위에서 설명한 차이때문에 많은 차이가 발생하는데, 다음 몇 가지 예시를 들어보겠다.
- 서버 사이드 언어로 작성된 코드나 파일은 일반적으로 클라이언트 단에서는 확인하거나 수저할 수 없다.
- 물론 웹셸을 업로드 하거나, 페이지에 취약점이 있거나 한다면 서버 기능을 악용해 데이터를 확인 가능하다.
- 클라이언트 사이드 언어인 자바스크립트는 클라이언트에서 코드 내용을 확인할 수 있으며 또 마음대로 변조할 수 있다.
여기서 클라이언트 사이드의 한계점이 발생한다.
바로 로그인, 인증과 같은 민감 정보를 체크하는 로직을 클라이언트에 사용할 수 없다는것이다. 이러한 모든 정보와 로직은 클라이언트에서 확인할 수 있고 또 변조가능하기 때문에 손쉽에 우회(bypass) 가능하기 때문이다.
3. 보안적으로 취약한 클라이언트 사이드 언어
한 가지 예를 들어보자. 어떤 웹 서버의 admin.php 에서는 관리자로 로그인할 수 있는 기능이 있다. 관리자 로그인에 성공하면 관리페이지로 넘어갈 수 있다.
그런데 인증 로직은 javascript로 작성했다. 그러면 어떻게 될까?
위 사진과 같은 상황이 발생할 수 있다는 말이다.
정말 무섭지 않을 수 없다. 계정 정보가 그대로 노출되는 페이지라니!
3-1. javascript 코드 변조하기
자, 여기까지 읽은 독자들이라면 javascript 코드가 서버로부터 클라이언트로 다운로드 되고, 이후 클라이언트에서 동작한다는 사실을 이제는 이해할 것이다. 자 그러면 클라이언트에서 코드를 수정할수도 있지 않을까? 당연하게도 가능하다.
단, 조건이 존재한다. js 코드가 이미 로드되고 난 후에는 아무리 수정해봐야 수정한 코드가 동작하지 않는다.
따라서 프록시 도구를 사용해서 js가 로드되는 시점을 잡고 해당 코드를 drop하거나 변조할 수 있다.
위 그림과 같이 server의 response 를 intercept해서 correctPassword 변수를 modulated_password로 바꿨다. 결과를 확인해보자
js 코드가 변조되었고, 또 변조된 비밀번호로 인증이 가능한것을 확인할 수 있다.
3-2. javascript 코드 override 하기
프록시 말고 browser 단에서도 js 코드를 변조할 수 있다.(아마 변조 기능을 제공하는 플러그인도 있지 않을까?) 바로 override 기능이다.
위 처럼 브라우저 단에서 코드를 오버라이드 할수도 있고, 아니면 로컬 경로에 js파일들을 다운로드해서 수정한 후 import 시킬 수 있다.
4. 마무리하며
이번 포스팅에서는 서버 사이드와 클라이언트 사이드에 대해 다루어 보았다.
이 포스팅을 잘 따라온 독자라면 이제 서버와 클라이언트의 동작에 대해 잘 이해했을거라는 생각이 든다.
더불어 클라이언트 사이드 코드에 민감한 정보나 로직이 존재한다면 얼마나 취약한지도 잘 이해했을거라 생각한다.