검색/백엔드 코드를 고칠 때 업로드와 사용자 입력을 통한 공격 막기

백엔드 코드를 고칠 때 업로드와 사용자 입력을 통한 공격 막기

업로드 파일, 아카이브, 요청 데이터를 다루는 백엔드 코드를 AI가 수정할 때 쓴다. 외부 데이터가 어디로 가는지 추적하고, 쓰기 전에 검증하고, 비슷한 모든 코드 경로에 같은 수정을 적용한 뒤, 보안 체크리스트와 lint·테스트 통과로 마무리한다.

이 AI 규칙을 사용하려면
## 수정 전에 외부 데이터의 흐름을 추적하고 비슷한 코드 경로 찾기 사용자가 인증된 경우에도 업로드된 파일, 아카이브 내용, 요청 매개변수, 매니페스트, 메타데이터, 기기 식별자는 공격자가 제어할 수 있다고 가정한다. 보안에 민감한 코드 경로를 변경하기 전에 다음을 수행한다. 1. 신뢰할 수 없는 데이터가 어디로 들어오고 어떻게 변환되는지, 그리고 도달할 수 있는 모든 파일, 프로세스, 데이터베이스, 렌더링, 리디렉션, 네트워크 작업을 식별한다. 2. 동일한 작업을 수행하는 유사 구현을 찾는다. 대체 형식, API와 웹 보기, 바이너리와 소스 흐름, 기존 호출 위치를 포함한다. 3. 보기와 처리기에 임시 검사를 흩어 놓지 말고 중앙 집중식 보안 도우미를 재사용하거나 확장한다. 4. 과거 취약점 패턴을 확인할 수 있다면 검토하며, 특히 하나의 경로만 보호한 불완전한 수정에 주의한다. 5. 가져오기와 로컬 규칙의 일관성을 유지한 다음, 필요한 린트 검사와 범위를 좁힌 테스트가 성공적으로 종료될 때까지 실행한다. 동등한 경로가 여전히 취약한 작업에 도달할 수 있다면 보안 수정은 불완전하다. ## 요청 데이터와 업로드를 입구에서 검증하고 로그인과 권한 요구하기 원시 입력이 경로, 명령 인수, 쿼리 값, 리디렉션, 렌더링된 문자열, 외부 호스트가 되기 전에 검증한다. - 형식이 지정된 양식이나 스키마를 기본 검증 계층으로 사용한다. - 유효한 값의 집합이 정해진 매개변수에는 유한 선택 필드를 사용한다. - 필드별 거부 논리를 검증 계층에 두고, 검증에 실패하면 표준 오류 응답을 반환한다. - 식별자를 경로나 조회에 사용하기 전에 정확한 형식에 맞는지 검증한다. - 업로드의 매직 바이트, 크기 제한, 확장자 허용 목록을 확인한다. 확장자만으로는 충분하지 않다. - 매니페스트와 메타데이터의 값을 신뢰할 수 없는 입력으로 취급한다. 민감한 처리기는 적용 가능한 모든 제어를 사용해야 한다. - 인증 - 역할 또는 권한 기반 인가 - 명시적인 HTTP 메서드 제한 - 브라우저에서 시작된 상태 변경에 대한 CSRF 보호 템플릿 이스케이프를 비활성화하거나 신뢰할 수 없는 콘텐츠를 안전하다고 표시해서는 안 된다. 자동 이스케이프 템플릿 외부에서 출력을 구성할 때는 대상 문맥에 맞게 값을 인코딩한다. ## 파일 경로와 ZIP/TAR 압축 해제를 정해진 폴더 안에 두기 파일 시스템 경로에는 두 계층의 보호를 사용한다. 1. 경로 순회 구간, 절대 경로, 인코딩을 이용한 우회, 잘못된 문자와 같은 위험한 원시 형식을 거부한다. 2. 경로를 구성한 뒤 정규 경로로 해석하고 의도한 루트 내부에 있는지 확인한다. 작업에서 일반 파일을 예상하는 경우 파일 시스템 객체를 읽기 전에 심볼릭 링크, 명명된 파이프, 장치 파일, 기타 예상하지 못한 형식을 거부한다. TAR 압축을 해제할 때는 다음을 따른다. - 실행 환경에서 제공하며 각 항목을 개별적으로 처리하고 형식을 인식하는 압축 해제 필터를 우선 사용한다. 이 필터는 경로 순회, 절대 경로, 장치 파일, 대상 밖으로 나가는 링크를 거부해야 한다. - 이름만 확인하거나 `abspath`만 사용하는 검사에 의존해서는 안 된다. 이러한 검사는 심볼릭 링크를 해석하지 못한다. - 안전한 기본 필터를 사용할 수 없다면 심볼릭 링크와 하드 링크를 거부하고, `realpath`로 대상을 해석한 뒤 각 항목을 추출하기 직전에 검증한다. - 두 단계 사이에서 파일 시스템 상태가 바뀔 수 있으므로 일괄 검증 후 일괄 추출하는 방식을 피한다. ZIP 압축을 해제할 때는 다음을 따른다. - 추출 전에 모든 항목 이름에서 경로 순회 여부를 검증한다. - 제안된 대상을 해석하고 압축 해제 루트 내부에 있는지 확인한다. - 해당 항목이 두 검사를 모두 통과한 뒤에만 추출한다. 실패한 모든 보호 검사는 `continue`, `return`, `raise` 중 하나로 안전하지 않은 작업을 중단해야 한다. 실행을 막지 않고 경고만 기록하는 것은 보안 제어가 아니다. ## SQL이나 셸 명령처럼 쓰이는 곳에 맞게 사용자 입력을 무해하게 만들기 - 하위 프로세스 인수를 목록으로 전달한다. 신뢰할 수 없는 입력을 셸 명령 문자열에 절대로 삽입하지 않는다. - 매개변수화된 ORM 또는 쿼리 빌더 작업을 사용한다. 문자열 서식으로 SQL을 절대로 구성하지 않는다. - 자동 이스케이프 문맥 외부에서 렌더링하기 전에 사용자가 제어하는 콘텐츠를 이스케이프한다. - SVG와 같은 능동 형식은 표시하기 전에 무해화한다. - 로그 삽입 공격을 막기 위해 사용자에서 파생된 로그 필드의 줄바꿈과 제어 문자를 제거한다. - 응답 헤더에 넣기 전에 안전한 파일 이름을 생성한다. - 검증된 상대 리디렉션 대상만 허용한다. - 외부 요청을 보내기 전에 호스트를 해석하고 검증하며, 루프백, 사설, 링크 로컬, 멀티캐스트, 기타 금지된 주소 범위를 거부한다. 하나의 범용 무해화 도구 대신 문맥별 검증을 적용한다. 데이터베이스 필터에 안전한 값도 파일 이름, 셸 명령, HTML 조각, 로그 항목, 리디렉션, URL에서는 안전하지 않을 수 있다. ## 보안 체크리스트로 마무리하고 항목마다 근거 제시하기 파일 입출력 또는 사용자 입력과 관련된 모든 변경에서 적용 가능한 항목을 확인한다. - [ ] 경로를 구성하기 전에 원시 입력을 검증한다. - [ ] 구성한 경로를 정규 경로로 해석하고 의도한 루트 내부에 유지한다. - [ ] 읽기 전에 예상하지 못한 링크, 파이프, 파일 형식을 거부한다. - [ ] 추출 전에 아카이브 항목을 개별적으로 검증한다. - [ ] 셸 인수를 문자열 삽입 없이 전달한다. - [ ] 렌더링되는 값을 이스케이프하고 능동 콘텐츠를 무해화한다. - [ ] 외부 호스트와 리디렉션 대상을 제한한다. - [ ] 사용자에서 파생된 로그 값을 무해화한다. - [ ] 데이터베이스 접근에 매개변수화된 작업을 사용한다. - [ ] 모든 거부 분기가 위험한 작업을 차단한다. - [ ] 동등한 코드 경로에 동일한 수정을 적용한다. - [ ] 범위를 좁힌 테스트가 허용 입력, 거부 입력, 우회 시도를 다룬다. - [ ] 린트 검사와 관련 테스트가 종료 코드 0으로 완료된다. 완료한 각 검사의 근거를 보고하고 검증하지 못한 경로를 명시한다.