flawopen.com/JSON 파싱/JSON.parse() vs eval()
JSON.parse()는 eval()보다 안전한가요?
입력을 메모라고 생각해 보세요. JSON.parse()는 구조화된 양식의 필드를 읽지만, eval()은 메모를 실행할 지시문으로 인터프리터에 넘깁니다. JSON.parse()는 JSON 문법을 따르며 텍스트 안의 JavaScript를 실행하지 않습니다. 그래도 파싱 결과는 사용 전에 검증해야 합니다.
// 신뢰할 수 없는 데이터를 프로그램 소스 코드로 해석하지 마세요.
const data = eval("(" + untrustedJson + ")");
const data = JSON.parse(untrustedJson);
// JSON을 데이터로 파싱합니다. 잘못된 JSON은 SyntaxError를 발생시킵니다.
이 질문이 나오는 이유
JSON.parse()가 널리 사용되기 전에는 JSON 텍스트가 JavaScript 표현식 문법과 겹친다는 이유로 일부 오래된 JavaScript 코드가 eval()로 JSON을 읽었습니다. 이 방식은 JavaScript 프로그램을 평가하므로 공격자가 제어하는 입력이 JSON 값으로 제한되지 않고 코드로 취급될 수 있습니다. JSON을 읽을 때는 JSON 파서를 사용하세요.
JSON.parse()가 보호하지 않는 것
JSON.parse()는 업무 규칙을 검증하거나 작업을 승인하지 않으며, 파싱한 값을 HTML, SQL, 셸 명령 또는 URL에 안전하게 사용할 수 있도록 바꾸지 않습니다. 예상 데이터 구조를 검증하고 문맥에 맞는 출력 인코딩이나 매개변수화 API를 사용하세요. reviver를 전달하면 애플리케이션이 제공한 콜백이 파싱 중 실행됩니다. 신뢰할 수 있고 단순하게 유지하며 공격자가 제어하는 값에 따른 부작용을 피하세요.
자주 묻는 질문
JSON 텍스트 자체는 데이터로 파싱되며 JavaScript로 실행되지 않습니다. 다만 애플리케이션이 reviver를 제공하면 이 신뢰된 콜백이 파싱된 값마다 호출되어 코드를 실행할 수 있습니다. 공격자가 제어하는 데이터가 실행 가능한 콜백 로직을 선택하거나 만들게 하지 마세요.
아니요. 파싱 결과를 애플리케이션의 예상 스키마와 권한 규칙에 따라 확인하세요. HTML에는 출력 인코딩을, SQL에는 매개변수화 쿼리를 사용하세요. 파싱은 이런 문맥에 맞는 데이터 정제가 아닙니다.