공격자는 공격을 시작하기 전에 애플리케이션의 취약성(Vulnerability)을 파악하고 공략해야 함
≫ 취약성 : 악의적 의도를 가지고 원치 않는 작업을 수행하는 데 이용할 수 있는 약점
인증과 권한 부여의 취약성
- 인증 (Authentication) : 애플리케이션이 이를 이용하려는 사람을 식별하는 프로세스
어떤 사용자나 존재가 앱을 이용하려고 하면 추가 접근을 허가하기 전에 먼저 이들의 ID를 확인해야 함
실제 앱에서는 익명 액세스를 지원할 때도 있지만 대부분은 식별된 사용자만 데이터를 이용하거나 특정 작업을 수행할 수 있음 - 권한부여 또는 인가 (Authorization) : 인증된 호출자가 특정 기능과 데이터에 대한 이용 권리가 있는지 확인하는 프로세스
예) 대부분의 인증된 사용자는 자금을 이체할 수 있지만 자신의 계좌에서만 가능
세션 고정 (Session fixation)
- 세션 고정 취약성 : 웹 애플리케이션의 더 구체적이고 심각한 약점
- 이 취약성이 존재하면 공격자는 이미 생성된 세션 ID를 재이용해 유효한 사용자를 가장할 수 있음
- 이 취약성은 웹 애플리케이션이 인증 프로세스 중에 고유한 세션 ID를 할당하지 않아 기존 세션 ID가 재사용될 가능성이 있을 때 발생함
- 악용하려면 먼저 유효한 세션 ID를 획득한 후 피해자의 브라우저가 이를 이용하게 해야 함
sequenceDiagram
participant A as 공격자
participant W as 웹사이트
participant V as 피해자
A->>W: 유효한 세션 ID 요청
W->>A: 세션 ID 발급
A->>V: 세션 ID 포함된 링크 전송
Note over V,A: 피싱 이메일, 맬웨어 등 사용
V->>W: 세션 ID를 사용하여 로그인
W->>V: 로그인 성공
Note over V,W: 세션 ID는 이제 피해자의 인증 정보와 연결됨
A->>W: 알고 있는 세션 ID를 사용하여 접근
W->>A: 피해자로 인식, 세션 탈취 성공
Note over A,W: 공격자는 이제 피해자의 권한으로 행동할 수 있음
XSS 교차 사이트 스크립팅
- 서버에 노출된 웹 서비스로 클라이언트 쪽 스크립트를 주입해 다른 사용자가 이를 실행하도록 하는 공격
- 사용자가 공격에 노출된 웹 페이지를 방문하면 삽입된 악성 스크립트가 사용자의 브라우저에서 실행되어 사용자의 세션 쿠키를 탈취하거나, 개인 정보를 수집하고, 심지어 사용자를 대신하여 악의적인 행동을 수행할 수 있음
- 원치 않는 외래 스크립트의 실행을 방지하기 위해 이용하기 전이나 심지어 저장하기 전에도 요청을 적절하게 '소독(sanitization)'하는 과정이 필요함
- 이 취약성이 악용되면 계정 가장(세션 고정과 결합)이나 DDos와 같은 분산 공격 참여 등의 결과가 발생할 수 있음
sequenceDiagram
participant U as 사용자
participant A as 공격자
participant W as 웹 애플리케이션
A->>U: 악성 스크립트 포함 링크 전송
Note over U,A: 피싱 이메일, 메시지 등을 통해
U->>W: 링크 클릭 & 요청 전송
Note over W: 요청에 악성 스크립트 포함
W->>U: 악성 스크립트 포함 응답
Note over U: 브라우저에서 스크립트 실행
U->>A: 스크립트에 의한 정보 유출 (예: 쿠키)
CSRF (사이트 간 요청 위조)
- CSRF 공격은 특정 서버에서 작업을 호출하는 URL을 추출해 애플리케이션 외부에서 재사용할 수 있다고 가정
- 서버가 요청의 출처를 확인하지 않고 무턱대고 실행하면 모든 곳에서 요청이 실행될 수 있음
- 공격자는 CSRF를 통해 동작을 숨겨서 사용자가 서버에서 원치않는 동작을 실행하도록 할 수 있음
- 일반적으로 공격자는 CSRF를 이용해 시스템의 데이터를 변경하는 동작을 실행
sequenceDiagram
participant U as 사용자
participant B as 브라우저
participant A as 악의적 사이트
participant W as 웹 애플리케이션
U->>W: 로그인 & 세션 생성
Note over U,W: 사용자는 웹 애플리케이션에 로그인함
U->>A: 악의적 사이트 방문
A->>B: 악성 요청 포함 웹 페이지 제공
Note over A,B: 이미지 태그를 이용한 요청 등
B->>W: 악성 요청 전송 (사용자의 쿠키와 함께)
Note over W: 웹 애플리케이션은 요청이 사용자로부터 온 것으로 판단
W->>W: 요청 처리 (예: 비밀번호 변경, 송금 등)
CSRF 발생 시나리오
"시민뱅크" : 가상의 온라인 은행 서비스
- 이 서비스를 사용하려면 사용자는 사용자의 이름과 비밀번호를 사용하여 로그인해야 하며, 송금과 같은 금융 거래를 수행할 수 있음
- 사용자 "홍길동"은 이 은행의 고객으로, 자주 온라인 뱅킹 서비스를 이용
- 공격자의 준비 : 공격자 "김해커"는 시민뱅크 사용자들이 로그인한 상태에서 자신의 조작된 웹 페이지를 방문하도록 유도하기 위해 피싱 이메일을 준비
이 이메일에는 "금융 시장의 최신 동양을 확인하세요!"라는 제목과 함께 김해커가 만든 악성 웹 페이지로 연결되는 링크가 포함되어 있음 - 피싱 이메일 발송 : 홍길동은 자신의 이메일에서 김해커가 보낸 메시지를 받고, 궁금증에 링크를 클릭
- 악성 요청 실행 : 링크를 클릭하면, 홍길동의 브라우저는 김해커의 악성 웹 페이지로 리다이렉트됨
이 페이지에는 홍길동이 로그인한 상태에서 시민뱅크에 대한 숨겨진 송금 요청을 자동으로 전송하는 JavaScript 코드가 포함되어 있음 - 이 요청은 홍길동의 브라우저에서 시민뱅크의 송금 API를 호출하게 하며, amount와 toAccount 파라미터는 김해커가 지정한 값을 사용
- 악성 송금 실행 : 홍길동의 브라우저가 이 요청을 실행할 때, 시민뱅크는 홍길동이 이미 로그인한 상태이고, 브라우저에 저장된 쿠키를 통해 인증된 사용자로부터의 요청으로 간주됨
따라서, 시민뱅크는 요청된 송금을 처리하고 홍길동의 계좌에서 김해커의 계좌로 1000달러가 이체됨 - 공격 발견 : 나중에 홍길동은 자신의 계좌 잔액이 예상치 못하게 감소한 것을 확인하고 은행에 연락하여 이상한 송금 거래를 알게 됨
<img
src="https://citizenbank.com/transfer?amount=1000&toAccount=~"
style="display:none;"
>
- 악성 웹 페이지에 포함된 JavaScript 코드 (김해커의 계좌로 1000달러를 이체하는 송금 요청 전송)
웹 애플리케이션의 주입 (injection) 취약성
- 주입 공격은 광범위한 공격 방식 !
- 공격자는 시스템에 특정 데이터를 유입하는 취약성을 이용
- 공격의 목표는 시스템에 피해를 주고, 원치 않는 방법으로 데이터를 변경하거나 원래는 접근할 수 없는 데이터를 검색하는 것
주입 공격의 유형
- XSS도 주입 취약성의 하나
- 시스템에 피해를 가할 목적의 클라이언트 쪽 스크립트 주입
- SQL 주입, Xpath 주입, os 명령 주입 등
주입은 피해 시스템의 데이터 변경, 삭제, 무단 이용을 유발하는 중요한 취약성 유형
주입 공격 발생 시나리오
웹 애플리케이션에서 사용자의 로그인을 처리하는 곳에, 사용자 이름과 비밀번호를 입력받아 다음과 같은 SQL 쿼리를 실행하는 코드가 있음
정상 쿼리 :
SELECT *
FROM users
WHERE username = '[사용자 입력]'
AND password = '[비밀번호 입력]';
- 정상적인 경우 사용자는 자신의 username과 password를 입력하고, 이 쿼리는 해당 사용자의 정보를 데이터베이스에서 조회하여 로그인을 처리
SQL 주입 공격 :
공격자가 사용자 이름 입력 칸에 ' OR '1'='1 과 같은 값을 입력하고 비밀번호 입력란은 비워둔다면,
위의 SQL 쿼리는 다음과 같이 변형되어 실행됨
SELECT * FROM users WEHRE username = '' OR '1'='1' AND password = '';
- '1'='1'은 항상 참이 되므로, 데이터베이스 내의 모든 사용자를 선택하게 되어 결과적으로 공격자는 비밀번호를 모르더라도 첫 번째로 조회되는 사용자로 로그인 할 수 있게 됨
민감한 데이터의 노출 처리
1. 구성 파일
- 실제 개발된 시스템에서는 모든 환경에서 민감한 데이터 값을 볼 수 없어야 하고, 적어도 운영 환경에서는 소수의 사람만 개인 데이터에 접근할 수 있어야 함
- 이러한 값을 스프링 프로젝트의 application.properties 또는 application.yml 파일 등의 구성 파일에서 설정하면 소스 코드를 볼 수 있는 모든 사람이 이러한 개인 값에 접근할 수 있음 + 소스 코드의 버전 관리 시스템에서도 이러한 값의 변경 기록이 저장됨
2. 로그
- 민감한 데이터에 대해 다음과 같은 경우도 발생
- 애플리케이션에서 콘솔에 기록
- 스츨렁크(Splunk)나 엘라스틱서치(Elasticsearch) DB에 저장하는 로그 정보
- 로그에 기록해서는 안 될 정보를 포함하면 안 됨 !!
예)
[오류] 요청의 서명이 잘못되었습니다. 사용할 올바른 키는 X입니다.
[경고] 사용자 이름 X와 암호 Y를 이용하여 로그인하지 못했습니다. 사용자 이름 X의 ~...
[정보] 사용자 X가 올바른 암호 Y를 이용하여 로그인 하였습니다.
3. HTTP 상태 코드
{
"상태" : 500,
"오류" : "내부 서버 오류",
"메시지" : "IP 주소 10.2.5.8/8080에 대한 연결이 발견되지 않음", "경로" : "/product/add"
}
- 예) 500 에러의 메시지에 IP 주소가 공개됨
- 공격자는 이 주소를 보고 네트워크 구성을 파악하고 최종적으로 인프라의 VM을 통제하는 방법을 찾아낼 수 있음
- 이 데이터만 가지고 공격을 시작할 수는 없지만, 노출된 다른 정보를 계속 수집/조합하면 결국 시스템 공격을 성공할 수 있음
메서드 접근 제어 부족
- 애플리케이션의 메서드나 API에 대한 접근 제어가 적절히 구현되지 않아 무단으로 중요한 기능을 실행할 수 있는 취약점
- 스프링 시큐리티를 사용하는 스프링 애플리케이션에서는 @PreAuthorize, @Secured 등의 어노테이션을 이용하여 메서드 수준에서 세밀한 접근 제어를 설정할 수 있음
≫ 이러한 접근 제어를 통해 특정 권한을 가진 사용자만이 메서드를 실행할 수 있도록 제한할 수 있음 - 애플리케이션 수준에도 한 계층에만 권한 부여를 적용해서는 안됨 : 때에 따라서는 특정 기능을 아예 호출할 수 없게 해야 함
예) 현재 인증된 사용자의 이용 권리에 허용되지 않는 경우
메서드 접근 제어 부족 발생 시나리오
AccountController, AccountService, AccountRepository를 가진 간단한 계정 관리 애플리케이션 가정
이 애플리케이션에서는 사용자의 계정 정보를 조회하고 수정할 수 있음
- AccountController는 사용자의 HTTP 요청을 처리하여 AccountService의 메서드를 호출
- AccountService는 비즈니스 로직을 수행하고, 필요한 경우 AccountRepository를 통해 데이터베이스와의 상호작용을 담당
- AccountRepository는 Spring Data JPA를 사용하여 데이터베이스에 접근하는 메서드를 제공
메서드 접근 제어 부족 문제 :
예) AccountService의 updateAccountDetails() 메서드
사용자의 계정 정보를 업데이트하는 중요한 기능 메서드
→ 접근 제어 부족 문제가 발생한다면, 비인가 사용자도 계정 정보를 변경할 수 있게 됨
public class AccountService {
public void updateAccountDetails(Account account) {
// 계정 정보 업데이트 로직
}
}
스프링 시큐리티를 이용한 해결 방안 :
스프링 시큐리티를 사용하여 updateAccountDetails() 메서드를 호출할 수 있는 사용자를 제한
예) @PreAuthorize 어노테이션을 사용하여 해당 메서드를 "ADMIN" 역할을 가진 사용자만 접근할 수 있도록 설정
@PreAuthorize("hasRole('ADMIN')")
public void updateAccountDetails(Account account) {
// 계정 정보 업데이트 로직
}
sequenceDiagram
participant U as 사용자
participant C as AccountController
participant S as AccountService
participant R as AccountRepository
participant Sec as Spring Security
U->>C: 계정 정보 업데이트 요청
C->>Sec: 접근 권한 확인
Sec->>C: 권한 부여 (ADMIN)
C->>S: updateAccountDetails() 호출
S->>R: 데이터베이스 업데이트
R->>S: 업데이트 완료
S->>C: 서비스 처리 완료
C->>U: 업데이트 응답
TransactionController가 추가된 경우
sequenceDiagram
participant U as 사용자
participant TC as TransactionController
participant TS as TransactionService
participant AR as AccountRepository
participant Sec as Spring Security
U->>TC: 계좌 이체 요청
alt 권한이 부족한 경우
TC->>Sec: 접근 권한 확인
Sec->>TC: 권한 거부
TC->>U: 이체 실패 응답
else 권한이 충분한 경우
TC->>Sec: 접근 권한 확인
Sec->>TC: 권한 부여
TC->>TS: executeTransaction() 호출
TS->>AR: 계좌 정보 업데이트
AR->>TS: 업데이트 완료
TS->>TC: 서비스 처리 완료
TC->>U: 이체 성공 응답
end
'spring' 카테고리의 다른 글
HTTPS vs HTTP (0) | 2024.11.02 |
---|---|
로깅(Logging) (0) | 2024.09.20 |
영속성 전이 (0) | 2024.09.15 |
다대일 단/양방향 매핑 (0) | 2024.09.15 |
연관관계 매핑 종류 / 방향 (0) | 2024.09.15 |