웹 서버는 Stateless 프로토콜인 HTTP 를 사용하기 때문에 웹사이트에서 인증을 관리하기 위한 방안이 필요하다.

로그인을 한 유저들에 대해 권한이 필요한 매 요청마다 재로그인을 시킬수는 없는 일이다.

그렇기 때문에 웹사이트는 일반적으로 유저의 접속 정보를 관리하기 위한 몇가지 방안을 사용한다.

 

1. Session 기반 인증

세션 기반인증을 위해 Session 과 Cookie 가 사용된다. 다음 Flow 로 인증 절차가 진행된다.

 

 - 유저가 로그인을 하고 세션이 서버 메모리 상에 저장된다. 이 때 세션을 식별하기 위한 Session Id 를 기준으로 정보를 저장한다.

 - 브라우저에 쿠키로 Session Id 가 저장된다.

 - 쿠키에 정보가 담겨있기 때문에 브라우저는 해당 사이트에 대한 모든 Request 에 Session Id 를 쿠키에 담아 전송한다.

 - 서버는 클라이언트가 보낸 Session Id 와 서버 메모리로 관리하고 있는 Session Id 를 비교하여 Verification 을 수행한다.

 

Session 기반 인증은 다음과 같은 장단점을 갖는다.

 

+ 세션 기반 인증 방식은 구현이 상당히 명확하다는 장점이 있다. 또한 실제 서버에서 로그인 상태 확인이 굉장히 유용하다.

+ 상대적으로 안전하다. 서버측에서 관리하기 때문에 클라이언트 변조에 영향받거나 데이터의 Stale (손상) 우려가 없다.

- 유저들의 세션에 대한 정보를 서버 메모리에 들고 있게 된다는 부담이 있다.

- 서버 메모리에 세션 정보가 저장되기 때문에 Scale Out / Scale In 이 부담이 될 수 있으며, 결국에는 유저 상태에 무관하게 동작할 수 있도록 Data-Driven 아키텍처가 요구된다.

- 멀티 디바이스 환경에서 로그인 시 신경써줘야할 부분들이 생긴다. 

 

2. Token 기반 인증

Token 기반 인증의 방법으로 많은 웹 서버들은 JWT(JSON Web Token) 을 사용한다.

Token 기반 인증 방식과 Session 기반 인증 방식의 가장 큰 차이점은 유저의 정보가 서버에 저장되지 않는다는 점이다.

Flow 는 다음과 같다.

 

 - 유저가 로그인을 하고 서버에 세션을 이용해서 정보를 기록하는대신, Token 을 발급한다.

 - 클라이언트는 발급된 Token 을 저장한다 (일반적으로 local storage 에 저장한다.)

 - 클라이언트는 요청 시 저장된 Token 을 Header 에 포함시켜 보낸다. 

 - 서버는 매 요청시 클라이언트로부터 전달받은 Header 의 Token 정보를 Verification 한 뒤, 해당 유저에 권한을 인가한다.

 

Flow 에서 차이를 확인할 수 있듯, Session 기반 서버가 서버측에 정보를 기록하는 반면, Token 기반 인증은 Token 에 대한 Verification 만 수행할 뿐 저장은 클라이언트에서 수행한다.

Token 기반 인증은 다음과 같은 장단점을 갖는다.

 

+ 클라이언트에 저장되기 때문에 서버의 메모리에 부담이 되지않으며 Scale 에 있어 대비책을 고려할 필요가 없다

+ 멀티 디바이스 환경에 대한 부담이 없다.

- 상대적으로 Stale (손상) 의 위험이 크다.

- 결국 구현을 하다보면 서버측에 token blacklist 를 관리하게 될 가능성이 있고 그렇게 되면 서버측 메모리의 소모가 발생하게 된다

- Token 은 일반적으로 Session ID 보다 길다.

- XSS 공격에 취약할 수 있어 가능한 민감한 정보는 포함시키지 않을 필요가 있다.

 

최근에는 Scaling 이슈와 멀티 디바이스 이슈로 Token 방식이 좀 더 핫한 느낌이지만, Session 방식도 여전히 많이 쓰인다.

두 방식 모두 장단점이 있기 때문에 적합한 구조를 선택하는 것이 좋겠다.

 

 

사실 보안쪽에 문외한이다보니 처음 배웠을 때 아주 생소한 개념이었다.

하지만 백엔드에 종사하다보니 얼마나 중요한지 알게되었고, 다시 한번 정리를 해보았다.

 

 

사실 Threat Modeling 이라는 단어는 비단 IT에서만 쓰는 용어는 아니고, 위험 요소에 대해 평가해보는 전반에 걸쳐 사용되는 언어이다.

하지만 IT 용어로써 Threat Modeling 이란 MS 사에서 대중화한 개념으로 잠재적인 위협을 모델링하고 이를 완화할 수 있도록 할 수 있는 프로세스를 말한다.

가령, 구조적 취약점이나 방화벽 등 보안장치의 부재와 같은 위협들이 모델링의 대상이 될 수 있다. 

위협 모델링의 목적은 시스템의 특성과 방어 시스템을 고려했을 때 어떤 부분에 있어서 방어가 필요하고 보안상 취약할 수 있는지 가능성을 찾는 것으로 특히 특정한 위협포인트에 대해 미지수일 경우 가능한 취약점을 찾는 것이 되겠다.

또한 공격자의 입장을 시뮬레이션해보고 공격 측면(Attack Surfaces) 을 찾아내는 일이 포함된다.

 

그렇기 때문에 Threat Modeling 이 가능하려면 먼저 다음을 알아야 한다.

    - 시스템의 구조 (Architecture)

    - 시스템의 보안 상태

    - 보호해야하는 가치있는(Valueable) 자산이 무엇인지

    - 가능한 공격자 후보군

위협요소 탐지를 위한 Threat Modeling 방법론으로 주로 언급되는 4가지를 정리해본다.

 

  1. STRIDE : 다음의 머릿글자만 딴 약어이며 다음 6가지에 대한 위협을 측정한다.

Spoofing(공격자가 권한이 있는 사용자인척 위장하는 공격 방식)

Tampering(목적을 위해 시스템 내부 데이터를 악의적 수정해서 공격)

Repudiation(악의적 활동 이후에 해당 활동에 대해 부인하는 것)

Information Disclosure(보호된 정보에 대한 노출)

Denial of Service(서비스에 대한 믿을 수 있는 접근을 바탕으로 한 공격. 분산해서 공격하는 것을 DDoS라 한다.)

 

  2. DREAD : 다음의 머릿글자만 딴 약어이다. MS 에서는 현재 제공되고 있지 않는 것으로 보이지만 OpenStack 등에서는 여전히 쓰이고 있는 방법이라 한다.

Damage Potential(취약점이 노출되었을 경우 발생 가능한 피해량)

Reproducibility(재공격 당하기 쉬운 정도)

Exploitability(공격을 하기 위해 필요한 공수)

Affected Users(위협이 얼마나 많은 유저에게 노출되는지)

Discoverability(얼마나 위협을 탐지하기 쉬운지)

위의 수치의 평균을 Risk 로 정의한다.

 

  3. P.A.S.T.A : Process for Attack Simulation and Threat Analysis 의 약어로 비즈니스 컨텐츠 및 기술 요구 사항에 따라 7단계로 프로세스가 구성된다. 방법의 목적은 직접 위협 요소를 검증하고 위협 요소들에 대해 점수를 부여해서 분석하고 완화시키기 위한 방법을 개발자에게 제시하는 것이다.

 

  4. VAST : Visual, Agile, and Simple Threat modeling 의 약어로 인프라 및 시스템 전체에 대한 모델링이 필요하며 Agile 프로세스에 위협 모델링 정보를 Visualize 할 수 있는 부분을 포함한다. 그렇기 때문에 전문적 지식없이 간단하게 진행되며 그를 지원해줄 수 있는 어플리케이션이 요구된다.

 

개발자 입장에서는 놓치기 쉬운 측면이고 정책적인 부분 또한 강하지만 OWASP(Open Web Application Security Project) 에서도 강조하고 있는 보안 위험을 대하는 구조화된 접근 방식이다.

다음을 참고하자 - (https://www.owasp.org/index.php/Threat_Modeling_Cheat_Sheet)

 

위협 모델링은 운영이 편리하고 취약점을 공유할 수 있는 부분이 큰 장점으로, 그에 따라 위험을 공유하고 같이 협력해서 대처할 수 있다는 큰 장점이 있다.

하지만 중요함에도 이를 적절하고 의미있게 실행하기는 쉽지 않은데, Best Practice 가 많지 않고 향후 위협 가능성보다는 현재의 위협에 초점을 두고 취약점 위주의 분석이 주가 되기 때문이다.

 

개발자 뿐만 아니라 시스템 전반에 걸친 모두의 협력이 지속적으로 이루어져야 가능한 부분이 아닐까 생각이 든다.

 

 

JWT 란 JSON Web Token 의 약어로 필요한 모든 정보와 검증을 위한 Signature 를 포함하는 JSON 객체를 통해 만들어내는 토큰의 일종이다.

웹표준으로 지정되면서 계정에 대한 인증 및 API 사용에 있어서 권한 확인을 위한 Security Token 으로 사용된다.

 

토큰은 지정한 객체(주로 인증 정보가 된다.)를 JSON 화하여 만든 데이터를 암호화하고, 특정 키를 이용해 서명하게 된다. 따라서 발급된 토큰은 해당 서버 / 서비스가 인증한 Token 이라는 의미가 되고, 이는 권한 인증에 있어 Key 로 사용할 수 있게 된다.

 

JWT 토큰은 Header 와 Payload, Signature 의 3가지 부분을 포함한다.

자세한 설명은 다음을 참고하자.

(https://velopert.com/2389)

 

 

JWT 를 사용한 일반적인 인증 절차는 다음과 같다.

 

 (1) 허용된 API 로 토큰을 발급. 주로 회원가입 / 로그인 API 만을 Token 없이 접근 가능하도록 설계하고, 해당 API 들에서 토큰을 발급해준다.

 (2) JWT Token 이 발급된다.

 (3) 클라이언트는 모든 요청에 Token 을 Header 에 포함시켜서 전달한다.

 (4) 서버는 유효한 JWT 토큰의 경우 인증하고 API 의 사용을 승인시키지만 아닐 경우 401 오류를 표시한다.

 

이는 일반적인 Token 을 이용한 API 프로세스와 동일하다.

 

JWT 의 장점은 다음과 같다.

 - 간편한 사용 및 인증 절차

 - Horizontal Scalable

 - REST API 에 최적화된 키 인증 방식

 - Expired date 정보의 포함

 - 관리와 서버 부하에 있어 부담이 적음

 

반면 다음과 같은 단점도 있다.

 - 인증 정보가 커질 수록 토큰의 크기가 커진다

 - 모든 요청에 토큰 정보가 포함되므로 Token 의 크기가 Message 의 크기보다 커질 경우 비효율적인 통신 구조가 된다.

 

 

다음 예제는 JWT 토큰을 이용한 인증절차를 가장 알기 쉽고 직관적인 예제를 통해 설명한다.

구현이 처음이라면 강추 하는 예제이다.

 

https://medium.com/swlh/spring-boot-security-jwt-hello-world-example-b479e457664c

 

Spring Boot Security + JWT Hello World Example

In this tutorial, we will be developing a Spring Boot application that makes use of JWT authentication for securing an exposed REST API…

medium.com

 


HTTP 와 HTTPS 의 차이점에 대해 면접 볼 때 질문 받은 적이 있었다.
당시 많이 긴장하고 해당 면접에 대해 Deep 한 질문들이 나오던 와중에 받은 질문이어서 보안을 위한 HTTP 라는 정도로 얼버무린 기억이 있는데,
만약 다음에 질문받게되면 깔끔하고 완벽하게 답변할 수 있도록 정리해보았다.


HTTP 란 일반적으로 웹 서버 통신을 위한 프로토콜이다.
HTTPS 란 정확히 어떤 것일까?
간략하게 정리하자면, HTTPS 란 "암호화된 통신을 제공하는 HTTP" 를 일컫는다.

HTTP 를 이용해 클라이언트와 서버가 통신을 할때, 암호화 통신을 위한 키를 설정하고 통신을 하게 된다.

이 때 사용되는 암호화 방식은 공개키 암호화방식을 사용하며, 데이터를 암호화하는데 2개의 키를, 복호화하는데 한개의 키를 사용한다.

HTTP 프로토콜을 사용하면 공격자가 패킷을 가로챌 경우, 평문이기 때문에 해당 데이터를 갈취하고, 변조해서 공격이 가능하다. (Man in the middle)
이에 반해 HTTPS 프로토콜을 사용하면, 패킷이 중간에 탈취되더라도 공격자가 메시지를 알아내고 암호화까지 하여 변조하는데, 일반적으로 천문학적인 시간을 소모하게 된다.

이처럼 암호화된 통신을 함으로써 안전한 구조를 가져갈 수 있지만, 공개키 암호화와 복호화 과정은 많은 비용을 수반한다.
따라서 HTTPS 통신은 HTTP 에 비해 느릴 수밖에 없으며, 보통 선택적으로 사용하게 된다.

예를들어 금융정보 및 기밀 또는 민감한 개인정보들의 경우에는 HTTPS 로, 그와 상관없는 UI 처리 및 일반 컨텐츠 관련 정보는 HTTP 로 처리하는게 정석적이다.




Hashing 이란 임의의 데이터를 고정된 길이의 구분되는 데이터로 매핑하는 과정을 말한다.


해시 알고리즘은 Computer Science 전반에 걸쳐 사용되는데 암호학적 Hash 또는 자료구조로써 해시테이블에서 구별된 인덱스를 나타내기 위한 도구로도 사용된다.


해시 알고리즘의 특징은 다음과 같다.


(1) 단방향(One-way) : 해시 알고리즘은 데이터를 단방향으로 변경하며, 그 역연산은 계산이 사실상 불가능하다. 

이는 수학적으로 "One-way Function" 을 사용하기 때문이며, 이 함수는 충분히 큰 가능한 경우의 수에 대해 다항 시간 안에 입력을 구하기 어렵게 한다.


* 물론 현재 수학적으로 정의된 One-way Function 이 실제 일방향인지는 증명되지 않았다. 그렇기 때문에 해시 알고리즘은 뚫린 알고리즘이 있을 수 있다.

만약 수학적으로 One-way Function 이 실제로 역방향 연산이 불가능한지가 증명된다면 가장 큰 수학적 난제가 풀리는 상황이며, 이는 P != NP 문제를 증명하는 셈이 된다.



(2) 임의성(Randomness) : 해시 알고리즘은 일정한 포맷을 기준으로 데이터의 변경에 따라 유추할 수 없게 임의로 인코딩된다. 

값 하나만 바뀌어도 전체 해시 값은 이전과 아예 다른 방향으로 패턴이 만들어진다.



(3) 공개된 함수(Hash function) : 해시 알고리즘은 아무나 알수없는 키값을 가지는 것이 아닌 모두에게 공유된 해시 함수(Hash function)을 사용한다. 이 말은 공격하는 측도 함수를 알고 있다는 뜻이다. 

대신 암호화와 다른 부분이므로 매우 빠른 속도로 함수가 수행된다.



Hash Algorithm 은 단방향인만큼 해커가 공격 시에 역추적을 시도하는 일은 거의 없다. 


대신 주로 공격할 때에는 입력값을 다변화해서 Brute-Force 를 적용하거나 특정 키를 바탕으로 범위를 축소하는 방향으로 공격이 이루어진다.


이런 점을 보완하기 위해 대부분의 Hash Algorithm 은 알고리즘을 여러번 수행하거나 해시와 암호화 알고리즘을 같이 병행해서 수행하거나 임의의 키값(Salt) 를 추가하기도 한다.



반면, 암호화 알고리즘은 양방향성을 지닌다.


암호화 알고리즘을 위해선 암호화(Encrypt)에 쓰이는 Key 가 필요하며, Key 와 사용자 데이터를 알고리즘을 통해 묶어서 암호문을 생성해낸다.

역으로 암호문은 Key 를 통해 복호화(Decrypt)되며 사용자 데이터를 꺼낼 수 있게 주어진다.


암호화는 해시 알고리즘과 달리 데이터의 인덱싱보다는 전달에 의미를 두기 때문에 좀 더 복잡하며 보안을 위한 다양한 방법이 수반된다.


실제 보안에서는 암호학적 해시 알고리즘은 암호화에 주로 같이 사용된다.


유명한 암호화 해시 알고리즘으로는 SHA-1, SHA-256, SHA-512, MD5 등이 있으며, 해시 값을 만들어내는 Hash function 자체로는 Murmur hash 가 있다. 



 


 SQL Injection 은 웹에서 DB에 접근하는 쿼리 자체에 공격을 가하는 것으로 해커들이 많이 이용하는 기법 중 하나이다

주로 학부과정의 컴퓨터 보안 시간에 기본적으로 다루는 내용이지만, 실제로 볼 일이 많이 없다가 대응해야할 일이 생겨서 정리해보았다. 


SQL Injection 을 이용해서 대표적으로 다음과 같은 방식의 공격이 사용된다.


(1)  인증 우회(Auth Bypass)

 : SQL 쿼리문의 TRUE/FALSE 논리 연산 오류를 이용해서 인증 쿼리문이 무조건 TRUE가 나오게끔 하는 방식이다. Select count(*) from member where uid=’입력된 아이디’ and pw = ‘입력된 비밀번호에서 입력된 아이디부분에 ‘ or 1=1# 과 같은 내용을 삽입하면 뒤의 내용이 주석처리 되면서 무력화 시킬 수 있다.


(2)  Data disclosure (데이터 노출)

 : 서버가 반환하는 Error 등을 참고해 정보를 파악해서 각 Column과 자료형을 알아내는 방식이다. www.example.com?idx=1’ having 1=1# 과 같은 방식으로 날리는 쿼리 파라미터를 분석한 뒤, 위와 같이 요청했을 때 반환되는 에러메시지를 분석해서 테이블을 유추한다. Error Based / Union Based 와 같은 공격이 이런 방식을 이용한다. 에러 메시지가 뜨지 않는 경우 Delay 함수등을 Inject 하여 응답시간으로 동작을 유추한다.

 : 그 외에도 Procedure 호출 이나 명령어 삽입 등의 공격도 있다.



 위의 내용은 SQL Injection 의 원론적인 부분이고 실무에서 쓰는 프레임워크들은 대부분 SQL Injection 에 대해 방어코드가 기본적으로 되어있다

하지만 그래도 개발자로써 기본적으로 숙지해야할 보안의 기본적인 원칙들은 다음과 같다.


(1)  Validation : 자유롭게 입력가능한 값에 대한 Validation 이 필수적이다.


(2)  Parameter : 특히 API등에서도 Parameter 는 특수문자나 SQL 명령어가 입력될 수 없도록 필터링이 필요하다. 물론 더 문제인건 입력받는 Parameter를 바로 DB로 전달하는 것이다


(3)  Prepared : SQL 입력이 되는곳은 Prepared Statement 를 통한 처리나 ORM 등을 통해 매핑시켜서 사용하는 것이 안전하다.


(4)  권한 : 데이터 다루는 권한은 최소한으로 부여한다.


(5)  에러메시지는 노출하지 않는다.


(6)  동적 SQL의 사용은 지양한다.

 



 OpenID와 Oauth 모두 인증을 위한 오픈 스탠더드 프로토콜로, 이를 이용하면, Facebook과 같은 인터넷 서비스의 기능을 다른 어플리케이션 등에서도 사용할 수 있다.


OAuth 사용 이전에도 다른 어플리케이션에 사용자의 아이디와 암호가 노출되지 않도록 하는 API 접근 위임이 가능한 여러 접근 방법이 있었지만 서로 통일되어있지 않았었고, 표준으로써 제정된 것이 OpenID와 Oauth 인증방식이다.


 OpenID와 Oauth 방식은 몇가지 공통점과 차이점을 갖고 있다. 일단 알아야 할 것은 두방식 모두 로그인과는 조금 다른 권한이라는 것을 의미하는 것이다.


 그 중에서도 OpenID의 주요 목적이 인증(Authentication)이라면 OAuth의 주요 목적은 허가(Authorization)이다.


 OpenID는 Login과는 다르지만 본질적으로 볼때는 로그인하는 행동과 같다. OpenID Provider로부터 사용자의 인증과정을 처리하며 Relying Party(여러 서비스)가 OpenID Provider에게 인증을 위임하는 것이다.


 물론 OAuth에도 인증 절차가 있지만 OAuth의 근본적인 목적은 해당 API를 사용할 수 있는 권한이 있는 사용자인지를 확인하는 것이다. 물론 OAuth를 사용자 인증의 방법으로 사용할 수는 있지만 근본적은 목적 자체가 다르다.


 


 아래는 Oauth 인증과정을 그림으로 표현한 것이다.

 

<원본 : http://oauth.net/core/diagram.png>


이를 정리하면 OAuth의 인증과정은 간단히 다음과 같다.


1. Request Token의 요청과 발급


2. 사용자 인증 페이지 호출


3. 사용자 로그인 완료


4. 사용자의 권한 요청 및 수락


5. Access Token 발급


6. Access Token을 이용해서 서비스 정보를 요청



OAuth 인증 방식은 단순히 기능 사용에 대한 인증을 부여하는 방식이고 그 외에 어떤 권한도 부여하지 않는다.
즉 기능 사용만을 위한 최소한의 효율적인 보안을 유지하는 방식이다.

OAuth 방식을 사용하면, 실제 보안 채널을 유지하는 것보다 개발 비용과 운영 비용을 줄이는 효과가 있으며 서비스적인 입장으로써는 타서비스에 연동함으로써 유저의 진입을 좀 더 쉽게 기획할 수도 있다.
이러한 비용적 효율성들덕분에 OAuth 인증 방식으로 패러다임이 많이 전환되어있는 추세이다.


출처 : 

https://d2.naver.com/helloworld/24942 

http://oauth.net


SSL 이란 Security Socket Layer 의 약자로  Netscape에서 서버와 브라우저 간 보안을 위해 만든 프로토콜이다. SSL은 CA(Certificate Authority)라 불리는 서드 파티로부터 서버와 클라이언트의 인증을 하는데 사용된다. 서버와 클라이언트 간의 통신 과정은 다음과 같다.


(1) 클라이언트가 SSL로 암호화된 페이지를 요청한다(https)


(2) 서버는 Public key를 인증서와 함께 전송한다.


(3) 클라이언트는 인증서가 Trusted root CA(인증기관)로부터 서명된 것인지, 날짜 등이 유효한지를 확인한다.


(4) 인증을 확인한 클라이언트는Public key로 URL, http 데이터들과 자신의 대칭키을 암호화하여 전송한다.


(5) 서버는 인증서에 대한 Private key로 요청을 복호화하고 전달받은 대칭키로 응답을 암호화해서 전송한다.


(6) 브라우저는 대칭키로 응답을 복호화해서 사용자에게 보여준다.


 이렇게 대칭키를 공개키 암호화방식으로 암호화해서 전송한 후 대칭키로 통신하는 프로토콜을 SSL 방식이라고 한다.


 이 과정에서 사용되는 서명(Signing)이란 특정 메시지를 작성했다는 것을 인증하는 역할이다. 서명의 과정은 다음과 같다.


(1) 해쉬 생성


(2) Private key로 해쉬 암호화


(3) 암호화된 해쉬와 서명된 인증서를 메시지에 추가


(4) 받는 사람은 따로 해쉬를 생성


(5) 받은 메시지에 포함된 해쉬를 Public key를 이용해서 복호화


(6) 4, 5번 과정에서 생성된 해쉬를 비교한다.


 다음은 이 과정을 정리한 SSL 의 워크플로우를 나타낸 그림이다. 아래의 그림에서 1, 2, 3번 과정은 위의 설명 이전의 과정이 된다.



이처럼 SSL은 공개키로 대칭키를 전달하고 실제 암호화 및 해독 작업은 대칭키로 하여 비용과 안정성 측면에서 이점을 갖는 표준 보안 방식을 말한다. 공개키 암호화 방식은 대칭키 암호화 방식보다 훨씬 안정적이지만 속도가 훨씬 느리다. 


사이트에 대한 인증서 문제는 요청한 사이트가 ‘진짜’ 인지를 인증기관을 통해 검증받기 위해서 생긴다. 인증받은 신뢰할 수 있는 사이트의 경우 SSL 통신이 진행된다. 



+ Recent posts