일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 공룡책
- 소프티어
- 2024회고
- ExceptionResolver
- Test code
- Service 계층 테스트
- Test Doulbe
- 테크쇼
- proxyFactory
- 자바
- modelmapper
- Junit 5
- 직장인 회고
- JPA
- 인프콘2023
- enumSet
- 2025 계획
- OS
- Spring
- Java
- FCM
- db
- Server
- Coputer Science
- 갓생
- mapstruct
- 일상
- softeer
- Test
- MySQL
- Today
- Total
공부내용공유
모바일 Refresh Token 보안( XSS / CSRF ) 본문
서론
현재 진행중인 프로젝트에서는 JWT 토큰으로 인가를 사용하고 있고 Access Token 과 Refresh Token으로 보안을 조금 더 강화시켰다.
로그인 파트를 내가 구현하지는 않아서 처음에는 신경쓰지 않고 있다가 프로젝트 베타 테스트를 하면서 문득 Refresh Token 만으로 보안이 충분한가? 라는 생각이 들었고 여러 자료들을 보고 정리하면서 내 나름의 결론을 내리고 프로젝트 고도화를 할 때 팀원들과 상의할 예정이다.
본론
현재 프로젝트에서는 사용자가 로그인을 하면 Access Token 과 Refresh Token을 만들어 보내주고 클라이언트에서는 Async Storage 에 저장을 하는 형태이다.
public String createAccessToken(String account, long idx, Collection<? extends GrantedAuthority> roles) {
Claims claims = Jwts.*claims*().setSubject(account); // sub: account 형태로 저장
claims.put("id", idx);
claims.put("roles", roles);
Date now = new Date();
return Jwts.*builder*()
.setHeaderParam("type","jwt")
.setClaims(claims) //Payload에 Private Claim을 담기 위함
.setIssuedAt(now) //발급시간
.setExpiration(new Date(System.*currentTimeMillis*() + accessTime))
.signWith(SignatureAlgorithm.*HS256*, secretKey)
.compact();
}
public String createRefreshToken() {
Date now = new Date();
return Jwts.*builder*()
.setHeaderParam("type","jwt")
.setIssuedAt(now) //발급시간
.setExpiration(new Date(System.*currentTimeMillis*() + refreshTime))
.signWith(SignatureAlgorithm.*HS256*, refreshSecretKey)
.compact();
}
이런식으로 token 2개를 보내 client 에서 저장을 한다. 이때 Client 가 어디에 저장하냐는 굉장히 중요한 문제로 저장하는 곳에 따라 가능한 공격에 대해 대비를 해야한다.
대표적인 공격으로는 2가지가 있다.
- XSS ( Cross Site Scripting)
- CSRF (Cross Site Request Foregery)
XSS
- 악의적인 사용자가 웹 애플리케이션의 취약점을 이용하여 다른 사용자들에게 악의적인 스크립트를 삽입하거나 실행하는 공격 방법
- XSS 공격은 주로 사용자의 입력값을 적절하게 필터링하지 않고 웹 페이지에 출력할 때 발생
- 악의적인 사용자가 웹 페이지의 입력 필드에 스크립트 코드를 삽입하면, 해당 스크립트가 웹 페이지에 표시된 모든 사용자들의 브라우저에서 실행될 수 있다.
XSS 유형
- 반사형
- 악성 script 코드를 URL 에 포함시켜 사용자가 누르게 유도
- 사용자가 누르면 script 코드가 작동해 사용자 정보를 해커에게 전달
- 저장형
- 악성 스크립트를 서버에 저장
- 악성 스크립트가 저장되어 있는 데이터 (게시물, 프로필…)를 사용자가 클릭
- 악성 스크립트 코드가 작동하고 사용자 데이터를 해커에게 전달
- DOM 기반
- 악성 스크립트가 담긴 URL 을 사용자가 클릭한다.
- 사용자가 정상 HTML 문서를 받는다.
- 브라우저가 HTML 을 읽다가 URL 에 있는 악성 스크립트를 읽는다.
- 사용자 데이터를 해커에게 전달한다.
반사형과 DOM 기반의 차이점
반사형은 해당 URL 을 서버에 보내지만 DOM 기반은 최초 HTML 문서를 받고 해당 URL 에 악성 스크립트를 심는다.
그래서 서버에 다시 요청할 필요없이 바로 악성스크립트 코드가 실행된다.
CSRF
해커가 악의적인 사이트를 만들고 사용자에게 전달을 한다. 사용자가 해당 사이트에 접속하게 되면 해커가 목표로 하는 사이트에 요청을 보낸다.
이때 사용자가 그 사이트에 로그인 되어 있어 쿠키가 있다면 유저 요청이 실행되고 해커는 유저의 리소스에 접근할 수 있다.
문제점들
XSS 의 경우 스크립트로 local storage 나 cookie 에 접근하여 token을 탈취하는 방식이고
CSRF 는 로그인 한 유저의 cookie 가 있음을 이용해 요청을 목적 사이트에 날리는 방식이다.
현재 프로젝트는 모바일 어플리케이션 이고 cookie 를 사용하지 않는다. (모바일에서도 cookie 를 사용할 수 있으나 web 에서만큼 활용할 수 없다.)
만약 web 브라우저를 사용하고 token 을 쿠키에 저장하는 방식이라면
- XSS
- http only 설정
- 입력 내용 필터링
- 출력 내용 필터링
- CSRF
- CSRF Token
- Cookie Referer Check
- Cookie Same Site
등으로 방어할 수 있다. 이 글에서는 현재 프로젝트 보안에 대한 고민 정리 및 조사 글이므로 자세히 다루지는 않겠다.
그래서 XSS 공격에 대해 mobile 이 위험한가에 대해 조사해 보았다.
리액트 네이티브 작동 방식
React Native의 기본 개념은 자바스크립트 코드와 네이티브 코드(Android의 경우 Java/Kotlin, iOS의 경우 Objective-C/Swift)를 결합하여 같이 작동하게 한다.
즉 JS 를 사용하기에 XSS 공격에 취약할 수 있다는 생각이 들었다.
구글링을 하면서 React 가 기본적으로 String 변수가 views 에서 자동으로 벗어나기 때문에 대부분의 XSS 에서 안전하다고 보았다.
그러나 완전히 안전하진 않았다. 스택 오버플로우에는 React 를 사용하더라도 XSS 공격을 당할 수 있는 3가지 케이스가 있다고 하였다.
XSS via dangerously SetInnerHTML
html을 저런식으로 사용하는 코드가 있다면 그 안 내용에는 JS 를 포함 해서는 안된다.
XSS via a.href attribute
javascript:code
base 64 encoded data
이렇게 href 안에 코드 혹은 encoded data 를 넣는식으로 XSS 공격을 할 수 있다.
XSS via attacker controlled props
prop 안에 js 코드를 넣고 공격을 할 수 있다.
What does it mean when they say React is XSS protected?
결론
Token 에서 시작했다가 가능한 공격들을 공부하였다. 팀원들에게 공유하고 어플리케이션 보안에 대해 같이 상의해보고 고칠 부분이 있으면 고칠 예정이다.