PH pullh
입문 블로그 / 첫 프로젝트에서 꼭 알아야 할 보안 감각
웹과 데이터 6분 Beginner

첫 프로젝트에서 꼭 알아야 할 보안 감각

보안은 전문가의 전유물이 아니다. 초보자도 첫 프로젝트에서 반드시 지켜야 할 기본 수칙이 있다.

보안 첫감 커버 이미지

초보자는 종종 내 프로젝트는 작으니까 괜찮겠지라고 생각한다. 하지만 작은 프로젝트일수록 실수도 단순하고 치명적일 수 있다.

보안을 깊게 공부하기 전에, 절대 코드에 두지 말아야 하는 것과 사용자 입력을 어떻게 다뤄야 하는지만 알아도 큰 차이가 난다.

공개된 주소를 두드리는 요청의 대부분은 사람이 아니라 자동화된 도구다. 이들은 프로젝트가 유명한지 따지지 않는다. 열려 있는 주소를 순서대로 확인할 뿐이다.

기본 보안은 습관에서 시작한다

비밀번호나 API 키를 코드에 그대로 올리지 않는 것, 사용자 입력을 그대로 믿지 않는 것, 관리자 기능을 누구나 접근 가능하게 두지 않는 것만으로도 입문 프로젝트의 위험이 크게 줄어든다.

보안은 나중에 붙이는 추가 기능이 아니라, 처음부터 이 값은 공개해도 되는가를 묻는 습관과 가깝다.

비밀값을 코드 밖으로 빼는 최소 작업

가장 흔하고, 가장 되돌리기 어려운 실수가 키를 코드에 적어 커밋하는 것이다. 나중에 지워도 커밋 기록에는 남기 때문에, 그 키는 이미 노출된 것으로 봐야 한다. 처음부터 분리해 두는 것이 훨씬 싸다.

BEFORE

API_KEY = "sk-live-3f9a2c..."
DB_PASSWORD = "admin1234"

한 번 push되면 되돌릴 수 없다고 생각하는 편이 안전하다.

AFTER

# .env  (반드시 .gitignore에 추가)
API_KEY=sk-live-3f9a2c...
DB_PASSWORD=admin1234

# app.py
import os
API_KEY = os.environ["API_KEY"]

값을 옮기는 것보다 .gitignore에 넣는 것을 먼저 하십시오. 순서가 반대면 의미가 없다.

여기서 os.environ[...]를 쓴 것도 이유가 있다. 값이 없으면 프로그램이 바로 죽는다. get으로 받아 기본값을 두면, 키가 빠진 채로 조용히 실행되다가 훨씬 이상한 곳에서 문제가 터진다. 설정이 빠졌을 때는 시끄럽게 실패하는 편이 낫다.

같이 두면 좋은 파일

.env는 커밋하지 않되, 어떤 키가 필요한지 적은 .env.example은 커밋하십시오. 값 없이 이름만 적어 두면 됩니다. 나중에 다른 컴퓨터에서 받을 때 이 파일이 실행 문서 역할을 합니다.

사용자 입력을 믿지 않는다는 말의 뜻

입력 검증이라고 하면 형식 확인만 떠올리기 쉬운데, 실제로 중요한 것은 입력이 코드로 해석되지 않게 하는 것이다. 가장 자주 인용되는 형태가 아래다.

위험한 방식

query = "SELECT * FROM users WHERE name = '" + name + "'"
cur.execute(query)

name에 따옴표가 들어오는 순간, 사용자가 쿼리의 문장 구조를 바꿀 수 있게 된다.

안전한 방식

cur.execute("SELECT * FROM users WHERE name = ?", (name,))

값과 문장을 분리해서 넘긴다. 무엇이 들어오든 값으로만 취급된다.

화면에 출력할 때도 원리는 같다. 사용자가 쓴 글을 그대로 HTML에 끼워 넣으면 그 안의 태그가 실행된다. 그래서 입력은 받을 때 검사하고, 내보낼 때 이스케이프한다는 두 단계로 나눠 기억해 두면 좋다. 대부분의 프레임워크가 이 두 가지를 기본으로 제공하니, 직접 문자열을 붙이는 코드를 쓰고 있다면 그 자리가 위험한 자리다.

입문 프로젝트 보안 체크

  • 비밀키와 비밀번호를 코드에 직접 넣지 않는다.
  • .env를 만들기 전에 .gitignore부터 만든다.
  • 사용자 입력은 길이와 형식을 검증한다.
  • 쿼리와 화면 출력에 입력을 문자열로 이어 붙이지 않는다.
  • 에러 메시지에 민감한 내부 정보를 그대로 노출하지 않는다.
  • 관리자 화면과 일반 사용자 화면을 구분한다.

에러 화면과 관리자 경로

남은 두 항목도 손이 거의 안 가는 것들이다. 하나는 에러 화면이다. 개발 중에 켜 두는 디버그 모드는 예외가 나면 코드와 변수 값을 화면에 그대로 보여 준다. 개발할 때는 편하지만 공개된 주소에서는 내부 구조를 알려 주는 안내판이 된다. 파일 경로, 사용 중인 라이브러리 버전, 때로는 설정값까지 노출된다. 배포용 설정에서는 반드시 꺼야 하고, 사용자에게는 짧은 안내 문구만 보이면 된다.

다른 하나는 관리자 경로다. 주소를 아는 사람만 들어올 것이라는 가정이 흔한데, 이건 보호가 아니다. 흔한 경로 이름은 자동으로 훑어진다. 관리자 기능이 있다면 주소를 숨기는 대신 로그인을 요구하는 편이 맞다. 로그인 붙이는 것이 부담이라면, 그 기능을 배포본에서 아예 빼고 로컬에서만 쓰는 것도 방법이다.

이 두 가지와 앞의 비밀값 분리, 입력 처리까지가 입문 프로젝트에서 챙길 목록의 전부다. 항목이 적어 보이지만 실제로 사고가 나는 지점의 상당 부분이 여기에 몰려 있다.

어디까지 하면 충분한가

여기서 선을 그어 두는 것이 중요하다. 입문 프로젝트에 암호학이나 침투 테스트를 공부해서 적용할 필요는 없다. 오히려 직접 구현하려 드는 쪽이 위험하다. 비밀번호를 저장하는 방식을 스스로 설계하거나, 토큰 검증 로직을 직접 짜는 것은 초보 단계에서 거의 확실히 틀린다. 그 영역은 검증된 라이브러리에 맡기는 것이 정답이다.

반대 방향의 과잉도 있다. 아직 사용자가 나 하나뿐인 로컬 연습 프로젝트에 로그인, 권한 관리, 감사 로그를 먼저 붙이는 경우다. 이건 보안이 아니라 미루기다. 공개되지 않은 코드에 대한 위험은 사실상 없고, 그 시간에 기능을 하나 더 만드는 편이 낫다.

판단 기준은 하나다. 이 프로젝트에 주소가 생겼는가. 인터넷에서 접근 가능한 순간부터 이 글의 체크리스트가 유효해지고, 그전까지는 비밀값 분리 정도만 습관으로 들여 두면 된다. 그리고 그 습관은 나중에 붙이기보다 지금 들이는 편이 훨씬 싸다.

이미 올렸다면

키를 커밋한 것을 뒤늦게 알았다면, 파일을 지우는 것보다 해당 키를 발급처에서 폐기하고 새로 만드는 것이 먼저입니다. 기록에서 지우는 작업은 그다음입니다.

작은 프로젝트라도 공개될 수 있다면, 이미 보안을 생각해야 하는 프로젝트다.

웹과 데이터

더 볼 것

비밀값이 커밋에 섞이는 문제는 첫 주의 Git에서 .gitignore와 함께 보는 편이 이해가 빠릅니다. 배포 시점에 함께 챙길 것들은 한 번의 배포가 바꾸는 것에 정리해 두었습니다.

이 글의 포인트

  • 보안은 큰 서비스에서만 필요한 것이 아니다.
  • 비밀값 분리와 입력 검증은 초보자도 바로 적용할 수 있다.
  • 입력을 문자열로 이어 붙이는 자리가 대체로 위험한 자리다.
  • 암호와 인증은 직접 만들지 말고 검증된 라이브러리에 맡긴다.
  • 이 정보가 공개돼도 괜찮은가를 묻는 습관이 첫걸음이다.

Next Read

콘솔창이 덜 무서워지는 첫 10가지 습관

터미널은 초보자에게 낯설지만, 몇 가지 기본 동작만 익히면 훨씬 든든한 작업 공간이 된다.