설명
외부에서 제어되는 텍스트를 str.format, str.format_map 또는 표준 string.Formatter의 포맷 문자열로 전달하면 공격자가 치환 필드를 정의할 수 있습니다. Python의 중괄호 포맷 문법은 임의의 Python 표현식을 실행하지는 않지만, 포맷 인자나 매핑으로 전달된 값에서 속성과 인덱스를 연속해서 탐색할 수 있습니다.
잠재적 영향
- 포맷 인자나 매핑에서 접근 가능한 내부 값이 노출될 수 있습니다.
- 로그나 응답 메시지의 출력 구조가 조작될 수 있습니다.
- 잘못된 필드나 포맷 지정자로 인해 예외가 발생할 수 있습니다.
해결 방법
- 포맷 문자열은 상수로 고정하고 신뢰할 수 없는 값은 위치 또는 키워드 인자나
format_map의 매핑 값으로만 전달합니다. - 여러 메시지가 필요하면 유한한 허용 목록을 통해 서버에서 관리하는 상수 템플릿을 선택합니다.
- 신뢰할 수 없는 텍스트를 표준 중괄호 포맷 문법에서 리터럴로 렌더링해야 한다면 포맷 처리 전에
{와}를 모두 이중으로 바꿉니다. 가능하면 고정 템플릿을 우선 사용합니다.
예시
변경 전
python
template = request.args.get("template")
return template.format_map({"user": {"name": "alice"}})
변경 후
python
user = request.args.get("user")
return "hello {user}".format_map({"user": user})
설명:
- 변경 전: 사용자 입력이 치환 필드와 속성 또는 인덱스 접근을 결정하므로
{user[name]}과 같은 입력으로 매핑 내부 값을 출력할 수 있습니다. - 변경 후: 포맷 문자열은 상수이며 사용자 입력은 매핑 값으로만 전달됩니다.
적용 시 주의사항
- 외부 입력을 포맷 문자열과 분리하고, 템플릿을 선택하는 허용 목록은 신뢰할 수 있는 코드에서 관리합니다.
- 중괄호를 이스케이프할 때는
{와}를 모두 처리합니다. %방식 포맷과 별도 템플릿 엔진은 문법과 안전 조건이 다르므로 해당 API에 맞게 입력을 처리합니다.