네이버스마트 에디터를 이용하여 게시판을 만들어보려고 하니 XSS 대한 공부를 해야 할 거 같다.
크로스 사이트 스크립트란
사이트 간 스크립팅(또는 크로스 사이트 스크립팅, 영문 명칭 cross-site scripting, 영문 약어 XSS)은 웹 애플리케이션에서 많이 나타나는 취약점의 하나로 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점이다.
주로 여러 사용자가 보게 되는 게시판에 악성 스크립트가 담긴 글을 올리는 형태로 이루어진다.
이 취약점은 웹 애플리케이션이 사용자로부터 입력 받은 값을 제대로 검사하지 않고 사용할 경우 나타난다.
이 취약점으로 해커가 사용자의 정보(쿠키, 세션 등)를 탈취하거나, 자동으로 비정상적인 기능을 수행할 수 있다.
주로 다른 웹사이트와 정보를 교환하는 식으로 작동하므로 사이트 간 스크립팅이라고 한다.
기능을 테스트한 걸 적어둔다. 아직 완벽하게 다 기능 구현을 이해 못한거 같다.
구글링해서 찾은 코드와 여러 자료를 참조하여 함수를 만들어보고 있는 중이다.
입력 데이터
MySQL DB에 저장된 내용(html_encode 함수 이용)
<?php class bbsClass {
function html_encode($str){ // SQL 과 XSS 공격을 모두 막는 함수 // htmlentities는 문자열에서 모든 HTML을 제거한다. 한글이 깨질수 있다. // ENT_QUOTES : 홑따옴표와 겹따옴표 모두 변환 // htmlspecialchars, htmlentities 두개다 기본 euc-kr을 지원하지 않는다. return htmlentities($this->mysql_fix_string($str), ENT_QUOTES, "UTF-8"); }
function mysql_fix_string($str){ global $db; // escape variables for security // mysqli_real_escape_string() 함수는 SQL 문에서 특수 문자열을 이스케이프한다. // $firstname = mysqli_real_escape_string($con, $_POST['firstname']); if(get_magic_quotes_gpc()) $str = stripslashes($str); return mysqli_real_escape_string($db,$str); }
function html_decode($str){ return htmlspecialchars_decode(stripslashes($str)); }
function xss_clean($data){ // html_decode 함수의 일종 // 출처 : https://stackoverflow.com/questions/1336776/xss-filtering-function-in-php // Fix &entity\n; $data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data); $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data); $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data); $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
// Remove any attribute starting with "on" or xmlns $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
// Remove javascript: and vbscript: protocols $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data); $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data); $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span> $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
// Remove namespaced elements (we do not need them) $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
do { // Remove really unwanted tags $old_data = $data; $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data); } while ($old_data !== $data);
// we are done... return $data; }
}//end class bbsClass
|
검색하다보니 HTML Purifier 를 이용한 필터링을 하는 걸 추천하는거 같다.
http://htmlpurifier.org/ 에서 파일을 다운로드하여 압축을 푼다.
HTML Purifier 4.10.0 버전이 PHP5, PHP7 지원한다고 적혀있다.
기능을 테스트 해보니 $html_decode 함수인거 같다.
https://gist.github.com/kijin/5829736 에 사용법이 잘 설명되어 있다.