[javascript] JSON 사용시 유의 사항

개발 노트 2009. 9. 8. 14:30 posted by 무병장수권력자


작성자 : 김문규
최초 작성일 : 2009. 9. 8

JSON은 기본적인 데이터 표현 형식으로 간주하기 때문에 별도의 의심없이 사용하는 경우가 많습니다. 하지만, 경우에 따라서는 스크립트 공격의 대상이 될 수 있기 때문에 주의를 요합니다. JSON은 스트링(string) 입니다. 이를 객체로 만들기 위해서는 eval이라는 함수를 이용해서 변환이 이루어지게 마련입니다. 문제는 여기서 발생합니다.

eval은 스트링을 해석해서 실행하기 때문에 때로는 악성스크립트를 실행할 수 있는 창구 역할을 할 수도 있게 됩니다.
<script>
var a = 'var a=\"wow~!\";alert(a)';
eval(a);
</script>

재밌게도 a에 적혀 있는 문장이 그대로 실행된다는 사실을 확인하실 수 있습니다. 만일 a가 악의를 가진 공격성 스크립트였다면? 뭐 당하는 거지요.

그래서, IBM에서는 다음과 같은 안을 개발자 문서에서 제시하고 있습니다.

JSON 사용을 보안화 할 것

JSON 은 JavaScript의 하위 세트에 기반하기 때문에, 악성 코드를 포함하고 있는 스크립트 콘텐트이다. 하지만, JSON은 할당과 호출을 배제한 JavaScript의 안전한 하위 세트이다. 따라서, 많은 JavaScript 라이브러리들은 eval() 함수를 사용하여 JSON을 JavaScript 객체로 변환한다. 이를 활용하려면, 공격자들은 잘못 형성된 JSON 객체들을 그러한 라이브러리들로 보내서 eval() 함수가 악성 코드를 실행하도록 한다. JSON의 사용을 보안화 하는 여러 방법이 있다. 첫 번째 방법은 RFC 4627에 정의된 정규식을 사용하여 JSON 데이터에 활성 부분이 포함되지 않도록 하는 것이다. Listing 8은 정규식으로 JSON 스트링을 검사하는 방법이다.


Listing 8. 정규식으로 JSON 스트링 검사하기
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
text.replace(/"(\\.|[^"\\])*"/g, ' '))) &&
eval('(' + text + ')');

보다 안전한 대안은 JSON 파서를 사용하여 JSON 데이터를 파싱하는 것이다. JSON의 문법은 매우 단순하기 때문에, 성능의 차이 없이 이 같은 파서를 쉽게 구현할 수 있다.