홍익대학교 이윤규 교수님의 네트워크 보안 강의 (2022)를 정리했습니다.
접근제어 (Access control)의 두가지 개념
인증 (Authentication)
사용자의 identification을 확인해서 접속을 허용함 (아이디/패스워드, 생체 인증)
인가 (Authorization)
인증 된 이후, 특정 동작을 할 수 있게끔 권한을 부여함.(특정 리소스에 접근할 수 있는 권한을 부여함)
인가의 예시)
카카오,네이버 통합 로그인
트위터 계정으로 twitpic 사용하는 경우 (트위픽이 나의 트위터의 계정을 사용할 수 있게 권한을 줌)
네이버 카페의 회원등급
구글 드라이브의 접근 제한
OAuth 2.0
- 인가를 위해 사용하는 프레임워크
- 한 애플리케이션에서, 다른 애플리케이션에 어떤 리소스, 데이터 혹은 기능에 대한 엑세스 권한을 부여할 때 사용된다.
- 예) 트위터를 사용 중, 트위터 계정을 이용해 twitpic을 이용하는 경우.
- IETF(Internet Engineering Task Force)의 *RFC 6749에 선언되어 있다.
- RFC = Request for Comments
OAuth 2.0을 이용해 인가하는 과정 (ex) 카카오 통합 로그인)
위의 2번 과정에서 사용자에게 보여지는 화면.
OAuth 2.0의 Flow (총 3개)
1. Authorization Code Flow (OAuth 2.0의 가장 대표적인 흐름.)
*반드시 위의 절차를 따를 필요는 없다. 이렇게 설계하면 문제가 발생하지 않는다는 '표준'이다.
원래 어플리케이션 : ABC
ABC의 권한을 인가받으려는 애플리케이션 : XYZ
- 앱 XYZ가 앱 ABC와 연결할 것인지 사용자에게 물어본다.
- (사용자 허용 후) 앱 XYZ가 인가 서버의 인가 엔드포인트(Authorization endpoint)에 인가 요청을 보낸다.
여기서 endpoint는 컨셉츄얼한 개념인데, 포트번호가 될 수도 있고 서버의 물리적인 개념 등이 될 수 있다. - 인가 서버가 인가 페이지를 앱 ABC에 반환한다.
(대충 XYZ가 권한을 사용할 것을 허용할 것인지..) - 앱이 인가 페이지를 유저에게 띄운다.
- 유저가 인가 요청을 허용하면, 아이디/패스워드로 로그인 하게 한 후 다시 인가 엔드포인트로 간다.
- 인가 서버가 앱 XYZ에 단발성 인가 코드를 준다.
- 앱 XYZ는 받은 인가 코드를 가지고 인가 서버의 토큰 엔드포인트로 가서 액세스 토큰을 요청한다.
- 앱 XYZ에 인가 서버가 액세스 토큰을 발행한다. (이제 앱 XYZ가 앱 ABC의 정보를 받을 수 있게 되었다.)
- A~D : 실제 정보를 받는 구간. 액세스 토큰을 가지고 사용자의 데이터에 접근한다.
왜 굳이 이렇게 절차를 구분해놨을까? 왜 인가 코드를 받은 후에 액세스 토큰을 받아야 되지? 한번에 주면 안되나?
-> authorization endpoint와 token endpoint의 역할을 구분하기 위함이다. 액세스 토큰의 경우, 쉽게 사람들이 접근하면 안 되는 중요한 부분이기 때문에 클라이언트가 액세스 토큰을 직접 요청하고, 직접 갖고 있으면은 문제가 생길 수가 있다. 즉, 완전히 보안을 보장할 수가 없게 된다. 그래서 다른 엔드 포인트를 통해서 인가 코드를 받고, 다른 엔드 포인트로 요청을 해서 액세스 토큰를 받음으로써 안전성을 높인 것이다.
2. Client Credentials Flow
OAuth 2.0에서 클라이언트는 두가지 타입으로 나뉠 수 있다.
- Credential Type : 비밀 값을 안전하게 저장할 수 있는 경우. (웹 브라우저, 서버)
- Public Type : 코드 자체에 비밀 값이 들어갈 수 있는 경우. (자바 스크립트)
클라이언트가 Credential한 경우에 OAuth2.0의 흐름이다.
가정 : 서버는 이미 클라이언트 앱이 뭔지 알고 있고 인증이 가능하며 하나의 유저로 취급한다.
리소스를 요청하는 과정이기 때문에 사용자로부터 허용을 받는 과정이 없다. token request를 하고, endpoint에서 access token을 받고, access token으로 리소스를 받아서 사용한다.
3. Refresh Token Flow (유효기간이 존재하는 토큰)
유효기간이 정해져있어 다시 토큰을 리프레시 해야하는 경우이다. 한 번 토큰을 발급받은 다음에 다시 리프레시를 하는 경우, 리프레시 토큰을 제시하면 앞의 절차 없이 바로 액세스 토큰을 발급 받을 수 있다. 마찬가지로 발급받은 엑세스 토큰 가지고 리소스에 접근할 수가 있다. 재인증시에 활용한 토큰을 리프레시 토큰이라고 한다.
OpenID Connect (OIDC)
통합 로그인을 위한 인증 프로토콜.
OAuth2.0은 '권한만' 처리하기 위해서 만들어진 표준 프로토콜이고, OpenID의 경우 사용자의 정보를 관리하고 인증하는 것에 더 초점이 맞춰져 있다. OAuth2.0에 좀 더 advanced하게 얹은, 발전시켜서 확장한 개념이라고 보면 된다. ID token이라는 개념이 추가된다. 정리하자면 OAuth 2.0과 같은 흐름을 갖지만, 추가적으로 ID, 이름, 로그인 시간, ID 토큰 만료시간의 개념을 추가해서 사용자의 인증 개념을 더욱 추가한 프로토콜이다. OAuth2.0의 경우 베이스 라인 표준이며, 구현 레벨에서 사용할 때는 이 프로토콜을 사용한다고 보면 된다.
OAuth 2.0 : 제 3자의 API 사용 인가가 목적.
OIDC : 통합 인증이 목적.
정리하면, OAuth2.0가 있고 위에 레이어를 더 얹은 개념으로 OIDC를 사용한다고 보면 된다.
OIDC Token을 받는 과정
OIDC는 OAuth2.0의 확장으로써 과정은 동일한데 아이디 토큰의 개념만 달라졌다고 생각하면 된다. OAuth2.0은 사용자 인증을 제공하지 않고, 액세스 토큰으로 권한을 부여해 리소스에 접근할 수 있게 했지만, OIDC의 경우 인가 서버에 작동하는 인증 시스템 자체를 기반으로 해서 클라이언트가 사용자를 판단할 수 있게 해주는 시스템이다.그래서 클라이언트는 인증 서버에 직접 클라이언트 id, 클라이언트 암호 인증 코드를 안전하게 전송을 하게 되고, 인증 서버는 데이터를 확인하고 액세스 토큰과 id 토큰으로 응답을 하는 방식이다.
이 과정에서 이 Authorization endpoint는 일종의 웹 api서 필수 요청되는 매개 변수로 리스펀스 타입을 요구를 한다. 즉, Authorization endpoint의 Web API에 response_type을 파라미터로 보내게 된다. 파라미터로 타입을 지정해서 보내야 OIDC를 사용한다고 볼 수 있다. 이때 ID token을 지정해서 보내게 된다. ID token을 요청하기 위해선 매개변수 상에서 openid를 반드시 포함해야한다. ID token dycjdtl, scope에 openid가 포함되어있지 않다면 ID token은 발행되지 않는다. (OIDC 프로토콜을 사용하고 있지 않다고 받아들인다.)
ID token을 받기 위해선 request parameter의 scope에 openid를 포함시켜야 한다.
ID token은 사용자가 구체적인 정보를 얻을 수 있게 해주는 역할을 한다. 내가 End-User을 인증하는 데 있어서 클라이언트 서버에 내 정보를 입력할 필요가 없게 된다. 생년월일, 핸드폰과 같은 개인 정보가 포함된 게 oidc의 ID Token이다. 내가 클라이언트에 다시 정보를 입력해서 인증할 필요 없이 ID token을 받아옴으로써 정보를 다 받을 수 있다. 즉, 내가 쓰려고 하는 서비스가 인가 서버로부터 서버에 존재하는 개인정보를 가지고 올 수 있도록 허락하는 과정이다. 그 정보를 ID token의 형태로 제공한다. JSON Web Token, JWT 형태로 구현된다.
ID Token의 내용엔 header, Payload, Signature 라고 하는 세 가지 부분이 담겨 있다. 그래서 클라이언트는 Payload 부분에 인코드 된 사용자 정보들을 얻어서 사용을 하게 되는 거죠. 인코딩 된 정보를 받아서, 디코드한 후 Payload 부분에 있는 정보를 사용한다.
Payload의 필드에는 이름, 성, 성별, 생년월일과 같은 개인정보가 들어있고 이를 기본적인 claim 범위라고 한다. 이는 서버마다 각각 다르다. 토큰발행자(iss), 사용자 구분자(sub), 토큰 발행시간(iat), 토큰 만료시간(exp)와 같은 정보도 들어가있다. 만약 더 많은 사용자 정보를 원하는 경우, ID Token을 request할 때, scope에 더 많은 정보를 요청하면 된다.
OIDC의 Flow
1. response_type = code (scope에 openid가 포함되어 있는 경우. 가장 generic한 경우)
scope에 반드시 openid가 포함되어 있어야 한다. (그래야 ID token을 받을 수 있다.)!
2.response_type = code (scope에 openid가 포함되어 있지 않은 경우.)
scope에 openid를 포함시키지 않았으므로 ID Token이 발행되지 않았다. OAuth 2.0과 같다.
3. response_type = token
)
Access token만 발행된다. OIDC에서 사용되는 흐름은 아니다.
4. respose_type=id_token
액세스와 관계 없이 유저의 계정 정보만 필요한 경우이다.
인증 vs 인가
인증 : 시스템에 액세스할 수 있는 사람 혹은 대상을 제한한다. (너가 이 사람이 맞니?)
인가 : 인증된 사용자에 대해서 행동을 제한한다. (너 이거 하도록 허락 받았니?)
인가의 경우 access control의 한 형태이다.
위에서 네트워크 프로토콜 상의 인가를 살펴 보았는데, 운영체제 상에서 인가를 살펴볼 것이다.
OS Authorization
운영체제에서의 인가는 두가지 타입으로 나뉜다.
- Acess Control Lists (ACLs)
- Capabilities
Access Control을 행렬 개념으로 볼 수 있다.
가로축 (행) : 주체 (사용자)
세로축 (열) : 대상 (리소스)
예를 들어서 천 명의 사용자가 있고 천 개의 리소스가 있는 경우 100만 개의 요소가 있는 matrix가 만들어진다. 매우 복잡하고, 자원 낭비가 매우 심하다. (빈 공간이 많이 생기기 때문에). 이를 효율적으로 만들기 위해서 grouping을 사용한다. 사용자들을 일반 사용자 그룹, 관리자 그룹, 라이트 사용자 그룹과 같이 특정 그룹으로 묶어서 그룹 별로 특정한 역할을 준다. 그룹별로 사용자를 나눌 수 있고, 역할별로 나눠서 권한을 줄 수 있다. 역할에 따라서 일정기간 동안에 특정 리소스에 대한 접근 권한을 부여한다. 이런 방법을 통해서 대규모 사용자를 효율적으로 컨트롤 할 수 있다.
엑세스에서 정보를 접근해야 되는데 가로로 접근할 건지, 세로로 접근할 건지에 따라 탐색 방법이 매우 다르게 된다. 각 그룹 별 사용자들이 어떤 권한을 갖고 있는지 보고 싶을 수도 있고, 혹은 각 리소스 별로 누가 쓸 수 있는지 보고 싶을 수 있다. 이렇게 정보에 접근하는 관점을 어느 쪽에 갖느냐에 따라 ACLs과 Capabilities 두가지로 나뉜다.
Access Control Lists
자원(리소스) 중심. 열 (column)의 관점.각 데이터 별로 사용자 권한을 저장하고 제어한다.
"이 데이터를 사용할 수 있는 사람은 누구니?"
- 사용자 수에 비해서 리소스가 많은 경우에 유리하다. 일반적으로 개인 PC와 같은 환경에서 유리하다. (사용자는 많아야 n명이지만, 리소스의 경우 수만개가 넘기 때문이다.)
- 리소스에 비해서 사용자 수가 많은 환경에서는 불리하다.
- 유닉스 기반 시스템(리눅스, 맥), 안드로이드, ios에서 사용된다. 윈도우의 경우 ACL기반에 advanced된 메커니즘을 사용한다.
- 데이터 지향 보호(data-oriented protection)이다.
- 사용자가 많고 계속해서 바뀔 때, 사용자가 권한을 일정기간 다른사람에게 위임하고 싶을 때 불리하다.
유닉스 시스템에서의 접근 제한
권한을 나타내는 부분에 16비트를 사용하고 처음 4비트는 파일 종류, 3비트는 특수 권한, 나머지 9비트가 권한 부분이다.
권한 부분의 9비트는 사용자, 그룹, 기타로 나뉘어진다.
drwxrwxrwx
d : 파일 종류 (디렉토리) / rwxrwxrwx : 권한 부분. rwx/rwx/rwx. 모든 사용자 그룹에 대해서 읽고(r), 쓰고(w), 실행(x)할 수 있다.
파일 종류가 -인 경우는 일반 파일이다.
커널이 어떻게 보면 이제 authorization의 감독자(superviser)역할을 한다. 사용자 ID가 0인 경우가 root이다. root 권한을 갖게 되면 모든 접근이 가능하기 때문에 주의해야한다. 공격자가 root 권한을 얻을 경우 침입했다는 흔적까지 제거할 수 있기 때문이다.
ACLs 기반에서는 파일이 아니라 사용자가 이 파일에 접근할 수 있는지 정보가 들어있기 때문에, 사용자의 권한을 임시로 바꿔주는게 쉽지 않다. (해당하는 모든 파일에 사용자를 기록해야 하기 때문에). 그리하여 suid라는 명령을 이용해 잠시동안 root 권한을 준다. 예를 들어, A라는 프로그램을 잠시 사용하고 싶을 경우, suid 명령어를 사용하면 일반사용자에게 A프로그램을 사용하는 동안에만 루트권한을 준다. A 프로그램 종료시 다시 원래 사용자 계정으로 돌아오게 된다. 잘못 사용할시 보안에 문제가 생길 수 있다는 단점이 있다.
Capabilities
사용자 중심. 열(row)관점. 각 사용자 계정별로 접근 가능한 객체와 접근 가능 여부를 명시한다.
"이 사람은 어떤 리소스에 접근할 수 있니?"
- 리소스 수에 비해 사용자 수가 많은 경우에 유리하다. 웹 서버와 같이 사용자 수가 계속해서 늘어나는 경우에 유리하다.
- 권한 위임이 쉽다는 장점이 있다.
- ex) '내 권한을 9시부터 10시까지 잠시 A에게 위임했다가 다시 돌려줘' 와 같이 계정끼리의 권한 위임도 가능하다.
- 특정 파일에 대해서 누가 접근 가능한지 알기가 힘들다. 즉, 파일을 제어하고 컨트롤하는 것이 쉽지 않다. (다른 사용자가 사용중이라서 삭제가 불가능한 경우 생각하면 된다.) *불가능하진 않지만 찾기 어려워서 비효율적이다.
데이터베이스에 대한 Access Control
웹 서버를 통해서 요청이 들어왔을 때, DB에 있는 정보들을 얼마만큼 끌어오고, 어떤 것들을 요청하고 해줄 수 있을지 transaction을 제어하는 부분이 db에 대한 컨트롤 부분이 된다.
오라클, my sql 같은 데이터베이스 시스템들은 자체적인 액세스 컨트롤 매커니즘을 다 쓰고 있어요. acl이나 capability를 딱 정해서 쓰는 게 아니라 이런 메커니즘들을 섞어서 자체적인 메커니즘을 사용한다. 단순히 접근권한만 나타내는 것이 아니라, 통계적인 추론, 컨트롤도 가능할 수 있게 하는 기능을 제공한다. (훨씬 더 복잡한 메커니즘 사용)
브라우저에 대한 Access Control
웹 콘텐츠들이 안전한지 알 수 있기 때문에 안전하기 쓰기 위해서 액세스 컨트롤이 필요하다.
- 동일한 출처 정책 (Same origin policy) : 웹페이지 상의 콘텐츠를 사용할 때, 원래 도메인에서 만들어진 것이 확인이 됐을 때만 사용할 수 있다.
- 샌드박스 : 코드를 제한된 환경 안에서만 구현한다. 안에서만 실행을 함으로써 브라우저 밖에 있는 정보들에 엑세스 할 수 없게 한다. 제한된 접근 권한만 있는 버츄얼 머신에서 코드를 실행함으로써 다른 콘텐츠들에 접근할 수 없게끔 접근을 컨트롤한다
'ETC > 네트워크 보안' 카테고리의 다른 글
네트워크 보안 Ch.번외 (0) | 2023.04.10 |
---|---|
네트워크 보안 Ch.11 Software Security (1) | 2023.04.10 |
네트워크 보안 Ch.10 Software Security (0) | 2023.04.10 |
네트워크 보안 Ch.9 Network Security (1) | 2023.04.10 |
네트워크 보안 Ch.8 Network Security (0) | 2023.04.10 |