Post

Filtering / Escape

입력 필터링

입력 필터링 작업은 세 단계로 구분하는 것이 좋다.

  1. 입력을 구분하는 단계
  2. 입력을 필터링하는 단계
  3. 필터링된 데이터와 오염된 데이터를 구별하는 단계
입력을 구분하는 단계

세션 데이터 저장소는 서버에 저장되기는 하지만 이를 입력으로 간주하는 것이 안전하며 DB의 데이터도 마찬가지다. 일반적으로 사용하는 외부 입력 출처를 정리하면 이 정도가 된다.

  • $\_GET
  • $\_POST
  • $\_REQUEST
  • $\_COOKIE
  • $argv
  • php://stdin
  • php://input
  • file IO
  • remote DB
  • remote API
입력을 필터링하는 단계

유효하지 않은 데이터는 그냥 버린다. 규칙에 맞추기 위해 유효하지 않은 데이터를 수정해서 그대로 사용하면 안된다. 예를 들면 ../../을 막기 위해 str\_replace('..', '.', $\_POST['filename']);을 사용하는건 쉽게 우회된다. 또한, 가능한 경우를 화이트 리스트로 정의하고 입력을 이에 따라 처리해야 한다. 정리하면,

필터링은 화이트 리스트로 작성된 조건에 부합하지 않는 데 이터를 버리는 방식으로 수행하는 것이 좋다. 이메일 등 다양한 입력 필터링에는 filter\_var() / filter\_input()을 사용한다.

필터링된 데이터와 오염된 데이터를 구별하는 단계

필터링된 데이터와 아직 신뢰할 수 없는 데이터를 구분하기 위해 필터링된 데이터를 모두clean 이라는 컨테이너에 담는 것이 좋다.

예를 들어 PHP에서는 배열 $clean을 사용할 수 있다. clean 은 항상 비어있는 상태로 초기화해야 한다는 것에 유의.

clean에 넣기 전에 확실히 필터링하고, clean 안의 데이터는 모두 필터링된 데이터로 간주하는 습관을 들인다. 단, 완전히 안전한 데이터로 간주해서는 안되는게 아직 이스케이프 하지 않았기 때문이다. 이스케이프는 따로 처리한다.

출력 이스케이프

필터링이 조건에 맞지 않는 데이터를 버리는 것이라면, 이스케이프는 특수문자 앞에 \ 등을 붙여 특수문자로 해석되는 것을 피하도록 하는 것을 말한다. 출력 이스케이프 작업도 필터링처럼 세 단계로 구분하는 것이 좋다.

  1. 출력을 구분하는 단계
  2. 출력을 이스케이프하는 단계
  3. 이스케이프된 데이터와 그렇지 않은 데이터를 구분하는 단계
출력을 구분하는 단계

보통 클라이언트에 보내는 출력, DB에 보내는 출력으로 구분할 수 있다.

출력을 이스케이프하는 단계

어딘가로 전송할 데이터는 그에 맞게 이스케이프하는 함수가 존재하는지, 여러개 존재한다면 어느 것이 가장 좋은지를 비교해보고 사용한다. 실제로 이스케이프가 필요하지 않은 id 등도 어쨌든 출력이라면 일관성 있게 이스케이프하는 것이 좋다. DB에 데이터를 보내야 하는 경우PDO의 prepared statement 를 사용하는 편이 좋다. PDO를 사용하지 않는 경우 DB에 보낼 데이터를 이스케이프하는 함수로는 데이터베이스에서 지원해주는 함수를 사용하는 것이 좋다.

이스케이프된 데이터와 그렇지 않은 데이터를 구분하는 단계

필터링 데이터와 마찬가지로 컨테이너를 하나 만들고 이스케이프된 데이터를 컨테이너에 담는 것이 좋다. 컨테이너는 clean과 마찬가지로 항상 비어있는 상태로 초기화해야 한다. e.g. 클라이언트에 보낼 데이터는 이스케이프하고 나서 $html 배열에 담는다. 쉘 입력은 $shell 배열에 담는다.

This post is licensed under CC BY 4.0 by the author.