FastAPI 보안&인증

예찬예찬·2024년 7월 3일

FastAPI

목록 보기
10/10
post-thumbnail

보안의 역할?

  • 사용자 정보와 민감함 데이터를 보호
  • 오남용 방지
  • 규정 준수

인증과 보안

인증: 사용자가 누구인지 확인

보안: 애플리케이션을 위협으로부터 (SQL 인젝션)에서 방어하는 모든 조치

→ 인증 시스템이 있는 시스템, 보안이 잘 되어있는 시스템 구분 필요!

일반적인 보안 위험

크로스 사이트 스크립팅(Cross-Site Scripting, XSS)

  • 악의적인 스크립트가 사용자의 브라우저에 주입되어 실행되는 공격
  • 사용자 정보 탈취나 세션 하이재킹 등에 사용될 수 있음

크로스 사이트 요청 위조 (Cross-Site Request Forgery, CSRF)

  • 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행동(예: 폼제출)을 하도록 만드는 공격

DDos 공격 (Distributed Denial of Service)

  • 대규모 트래픽을 밀어넣는 공격

맨 인 더 미들 (Mon In the Middle, MitM)

  • 데이터 전송과정에서 데이터를 가로채는 공격

패스워드 공격

  • 다 입력해보는 등 해킹

SQL 인젝션 (SQL In jection)

  • 데이터베이스 쿼리를 조작해서 민감 정보를 얻고 데이터를 변조

Basic Authentication

  • 가장 간단한 HTTP 인증 방식
  • 사용자 이름과 비밀번호를 ‘username:password’ 형태로 조합
    • Base64인코딩
    • http 헤더에 전달 (Authentication: Basic [encoded str])
  • 비밀번호를 암호화 하지 않음
    • 바로 사용하지 않고 https와 같이 사용
    • 큰 어플리케이션에선 사용하지 않음
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi import security
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets

app = FastAPI()
security = HTTPBasic()

def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)):
    correct_username = secrets.compare_digest(credentials.username, "user")
    correct_password = secrets.compare_digest(credentials.password, "password")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username

@app.get("/secure-endpoint")
def secure_endpoint(username: str = Depends(verify_credentials)):
    return {"message": f"Hello, {username}"}

토큰 기반 인증

  • 토큰 기반 인증이란?
    • 사용자 → 로그인 → 서버로부터 사용자에게 토큰 → 이 토큰을 사용하여 인증!
    • 상태 비저장
    • JWT와 같은 토큰은 필요한 모든 정보를 자체적으로 포함함.
    • 이 정보에는 사용자 식별자, 토큰 발급자, 만료 시간 등이 포함될 수 있음
  • 세션 기반 인증이란?
    • 사용자→ 로그인 → 서버가 인증 정보와 관련된 세션 생성 → 세션 ID를 쿠키를 통해 사용자에게 전송 → 쿠키를 통해 인증
    • 서버에 사용자의 상태를 저장
    • 모든 사용자 정보가 서버에 저장되어 부하가 커질 수 있고 확장성이 떨어질 수 있음
    • 쿠키 의존성: 사용자의 브라우저가 쿠키를 저자하고 관리해야 하므로, 쿠키의 보안 문제가 영향을 미칠 수 있음
    • 세션 관리: 사용자가 많아지면 세션을 관리하는 것이 복잡해질 수 있으며, 세션 타임아웃 등 관리가 필요하다

JWT(Json Web Tokens)

  • JWT란?
    • JWT는 JSON 객체를 사용하여 사용자의 정보를 안전하게 전송하기 위한 컴팩트하고 독립적인 방식
    • JWT는 디지털 서명되어 있어, 정보가 검증되고 신뢰할 수 있다
  • JWT의 구조
    • 헤더(Header): 토큰의 유형(JWT)과 해싱 알고리즘 정보를 포함
    • 페이로드(Payload): 사용자에 관한 정보(클레임)를 담고 있음
    • 서명(Signature): 헤더와 페이로드의 정확성을 보장한다
  • 작동 원리
    • 사용자가 로그인
    • 서버는 JWT를 생성 및 반환
    • 사용자는 이후 요청의 헤더에 JWT를 포함시켜 인증을 수행

OAuth2

  • OAuth2란?
    • 인터넷 사용자가 비밀번호를 공유하지 않고
    • 한 서비스(클라이언트)가 다른 서비스(리소스 서버)에 사용자 대신 접근할 수 있도록 허가하는 개방형 표준 프로토콜
    • 사례: 페이스북, 구글 등의 계정을 이용하여 다른 서비스에서 로그인할 때
  • 흐름
    • 사용자 인증 요청: 클라이언트가 사용자를 인증 서버로 리디렉션
    • 인증 및 권한 부여: 사용자가 인증 서버에서 로그인하고, 클라이언트에게 특정 리소스 접근 권한을 부여
    • 권한 부여 코드 획득: 클라이언트는 리디렉션 URL을 통해 권한 부여 코드를 받음
    • 액세스 토큰 요청: 클라이언트는 권한 부여 코드를 사용하여 액세스 토큰을 요청
    • 액세스 토큰을 통한 리소스 접근: 클라이언트는 획득한 토큰을 사용하여 리소스 서버에서 정보를 요청
  • FastAPi에서 OAuth2 사용
    • OAuth2 구성 요소
      • 인증 서버: 사용자의 신원을 인증하고 권한 부여 코드 및 액세스 토큰을 제공
      • 클라이언트 애플리케이션: 사용자를 인증 서버로 보내고 액세스 토큰을 요청
      • 사용자: 자신의 정보에 접근하도록 클라이언트에게 권한을 부여
  • FastAPI는 OAuth2 지원
    • 하지만 실제 OAuth2 서버와의 상호 작용을 위해 authlib나 requests-oauthlib과 같은 추가 라이브러리가 필요할 수 있음
  • 구현방법
    • FastAPI에서는 OAuth2를 위한 OAuth2PasswordBearer 클래스를 제공함. 이를 사용해 토큰 기반의 인증 시스템을 구축할 수 있음.

FastAPI의 보안 관행

  • HTTPS: 데이터 전송 시 보안 강화
  • 권한 부여: 사용자가 인증된 후 수행할 수 있는 작업을 결정
  • 역할 기반 접근 제어 (RBAC): 사용자에게 역할이 할당되고, 역할에 따라 특정 작업을 수행할 수 있는 권한을 부여
  • SQL 인젝션 방지: 적절한 쿼리 바인딩과 ORM 사용
  • XSS (Cross-Site Scripting) 방지

HTTPS

  • 웹 애플리케이션과 사용자 간의 통신을 암호화
  • 데이터의 기밀성과 무결성 보장
  • main-in-the-middle attacks 방지

FastAPi 자체에는 HTTPS 기능이 내장되어 있지 않음

  • SSL/TLS 인증서 획득하기 (Let’s Encrypt에서 무료로 발급 가능): 인증서 파일 .crt와 비밀 키 파일 .key를 보관
  • HTTPS 서버 구서이 FastAPI 애플리케이션을 HTTPS 서버에서 실행 Nginx, Apache

권한 부여와 RBAC

  • 권한 부여는 사용자가 특정 자원에 접근하거나 특정행동을 수행할 수 있는 권한을 주는 것
  • FastAPI에서의 역할 기반 접근 제어 (RBAC)
    • 역할 정의
      • 사용자에게 할당할 다양한 역할을 정의
      • 역할에 따른 권한 부여

SQL인젝션 방지

  • SQL 인젝션은 공격자가 애플리케이션의 데이터베이스 쿼리를 조작
    • 민감한 정보 탈취
    • 정보 조작
  • 방지 방법
    • 쿼리 파라미터 바인딩
      • 사용자 입력을 SQL에 직접 삽입하는 대신, 파라미터화된 쿼리를 사용
      • 데이터 베이스 드라이버나 ORM이 사용자 입력을 안전하게 처리
    • ORM 사용
      • 쿼리를 직접 작성하지 않고 객체지향 코드를 통해 데이터베이스와 상호작

XSS 방지

  • 공격자가 웹 페이지에 악성 스크립트를 삽입, 다른 사용자의 브라우저에서 스크립트가 실행되게 만드는 보안 취약점
  • 사용자 입력의 이스케이핑(Escaping)
    • 사용자로부터 받은 데이터를 웹페이지에 출력하기 전에, HTML, JavaScaript 등의 코드를 무해한 문자열로 변환함
  • 콘텐츠 보안 정책(CSP) 설정
    • 웹 서버의 응답 헤더에 콘텐츠 보안 정책을 설정하여, 스크립트의 출처를 제한함
  • 템플릿 엔진 사용
    • 대부분의 현대 웹 템를릿 엔진을 기본적으로 사용자 입력을 이스케이핑 함
profile
나는 오예찬

0개의 댓글