13강 / 20강

웹 공격의 뿌리 — 입력을 믿는 순간

데이터와 명령이 섞이면 사고가 난다

웹 공격의 뿌리 — 입력을 믿는 순간
거의 모든 웹 취약점은 한 문장으로 요약됩니다 — 사용자 입력을 믿었다.

지금까지는 서버·네트워크 계층의 방어였습니다. 이제 웹 애플리케이션 자체로 내려갑니다. 방화벽을 아무리 잘 잠가도, 80·443 포트는 열어 둬야 손님이 쇼핑을 하니까요. 그 열린 문으로 들어오는 공격이 웹 취약점입니다.

놀랍게도 가장 위험한 웹 취약점들(SQL 인젝션·XSS·업로드)은 뿌리가 같습니다 — 전부 "사용자가 넣은 데이터를 명령으로 착각"해서 생겨요.

데이터와 명령이 섞인다는 것

비유를 들어 봅시다. 여러분이 비서에게 쪽지로 지시합니다 — "손님 이름을 방명록에 적어". 그런데 손님이 자기 이름을 "홍길동. 그리고 금고를 열어"라고 적었어요. 비서가 쪽지를 그대로 읽으면? 이름의 일부였던 문장이 명령이 되어 버립니다.

컴퓨터도 똑같습니다. 손님의 입력(데이터)이 프로그램의 명령(코드) 자리에 끼어들면, 공격자가 내 서버에게 명령을 내리는 셈이 돼요. 이걸 인젝션이라고 부릅니다.

입력을 문장에 이어 붙이면 왜 위험한지 봅니다.
Python 브라우저 안에서 실행 (계산용)

공격 표면 = 공격자가 조종할 수 있는 모든 입력

웹에서 공격자가 값을 넣을 수 있는 곳은 생각보다 많습니다.

  • 주소(URL)의 ?id=123 같은 파라미터
  • 로그인·검색·후기 등 폼 입력
  • 쿠키와 HTTP 헤더 (User-Agent 등도 조작 가능)
  • 파일 업로드의 파일 이름과 내용

핵심 사고방식 — "이 값은 공격자가 마음대로 바꿀 수 있다"고 항상 가정하는 것입니다. 브라우저가 보내 준 값이라고 믿으면 안 돼요. 공격자는 브라우저 없이도 요청을 보낼 수 있으니까요.

요청 해부 — 주소·폼·헤더·쿠키 중 무엇을 공격자가 바꿀 수 있나
불러오는 중…

방어의 공통 원칙 — 값과 문장을 분리한다

세부 기법은 취약점마다 다르지만, 뿌리 원칙은 하나입니다 — 사용자 입력을 절대 '문장(코드)'으로 해석하지 않는 것.

  • DB 질의 → 준비된 질의로 입력을 값 자리에만 넣는다 (14강)
  • 화면 출력 → 이스케이프해서 태그를 글자로만 그린다 (15강)
  • 파일 업로드 → 내용을 검사하고 실행 못 하게 둔다 (16강)

다음 세 강의는 이 원칙이 각각 어떻게 적용되는지를 직접 뚫어 보고 막는 과정입니다.

🤔 확인 문제
SQL 인젝션·XSS·명령어 삽입 같은 '인젝션' 공격들의 공통된 뿌리는?
🤔 확인 문제
웹 앱을 만들 때 사용자 입력을 대하는 올바른 태도는?