웹 디렉터리 안의 백업은 소스 유출입니다
이 글의 내용
큰 파일을 고치기 전에 자연스러운 몸짓은 먼저 복사해 두는 것입니다. cp index.php index.php.vor-aenderung, 그리고 작업. 그 파일이 웹 서버가 공개하는 디렉터리에 놓이면, 소스 코드 전체가 방금 평문으로 내려받을 수 있게 된 것입니다 — 데이터베이스 접속 정보, 비밀값, 그 파일에 든 모든 것이 말입니다.
아파치가 index.php를 PHP로 돌리는 것은 그것이 .php로 끝나기 때문입니다. index.php.vor-aenderung는 .php로 끝나지 않습니다. .vor-aenderung로 끝나고, 아파치는 그런 것을 들어 본 적이 없어 기본 동작대로 바이트를 보냅니다.
대부분이 쓰는 규칙, 그리고 그것이 왜 부족한가
흔한 방어는 확장자 금지 목록입니다: .bak, .orig, .save, .sql, .old. 머리에 떠오른 파일은 잡습니다. 여기서 시험해 보니 그 목록은 probe.bak에는 옳은 답을 주고 아래 하나하나에는 틀린 답을 주었습니다:
index.php.vor-xyz— 실제로 그렇게 일어났습니다index.php.2026-08-19index.php.kopiestyle.css.altindex.php.1
전부 200으로 나갔습니다. 아무도 떠올리지 못한 이름 짓기 방식이 실제로 쓰이는 방식입니다. 백업은 그때 무슨 일을 하고 있었는지에 따라 이름이 붙기 때문입니다.
자르는 방향을 뒤집기
제대로 되는 규칙은 어느 확장자가 금지인지 묻지 않습니다. 구조에 관한 물음을 던집니다. 이 파일 이름이 끝이 아닌 자리에 소스 코드 확장자를 담고 있는가?
그렇다면 그것은 실행되도록 만들어진 무언가의 사본이며, 뒤에 붙은 꼬리가 무엇이라고 말하든 상관없습니다. index.php.anything가 맞습니다. style.css.anything도 맞습니다. 그 패턴은 아직 아무도 지어내지 않은 이름까지 덮고, 그것이 요점 전부입니다.
오늘 돌아가는 서버에 맞대어 확인하니 위 다섯 이름 모두 이제 403을 돌려줍니다. 존재하지 않는 것들까지 그렇습니다 — 규칙은 파일이 아니라 모양을 거부합니다.
예외, 그리고 그것이 가르치는 것
여기서 정당한 파일 이름 하나가 바로 그 모양입니다. 미리 압축한 파일은 style.css.1787777226.gz로 쓰이고, 확장자가 일부러 가운데 있습니다. 그래서 규칙은 숫자로만 된 조각 뒤에 .gz가 오는 경우에 대해 좁은 예외 하나를 품고, 그 파일은 마땅히 200을 돌려줍니다.
이런 규칙은 보통 그런 예외에서 어긋나므로, 이 예외를 안전하게 만드는 것이 무엇인지 적어 둘 값어치가 있습니다. 소스를 되가져올 index.php.something.gz를 지어낼 수 없을 만큼 좁습니다. 가운데 조각이 숫자만이어야 하기 때문입니다. 더 넓은 예외 — ".gz로 끝나는 모든 것" — 였다면 규칙 전체를 도로 내준 셈이 되었을 것입니다.
그리고 가장 단순한 조언은 이 모든 것을 불필요하게 만드는 그것입니다. 백업은 공개되는 디렉터리 밖에 두십시오. 규칙은 그것을 잊는 날을 위한 그물이지, 사본이 어디에 떨어지는지 신경 쓰지 않아도 된다는 허가가 아닙니다.