При разработке систем, в которых у пользователя есть возможность авторизации и отправки сообщений, существует ряд уязвимостей, с помощью которых можно организовать XSS-атаку путем внедрения JavaScript для отсылки cookies (или URL с идентификатором сессии).
Типичными способами являются следующие:
1. Самый очевидный и наиболее просто блокируемый: вставка тега <script> (отслеживается регулярным выражением вида
preg_replace('|<script(.*?)</script(.*?)>|is','',$buffer)
2. Добавление тега с обработчиком JavaScript-события (конструкции вида <div onMouseOver=”alert(’test’)”></div>. Такие регулярные выражения можно отследить следующим куском кода:
$events = array('onLoad','onClick'); // массив событий
$count=preg_ match_all('|<\w+(\s+[^>]*)>|s',$buffer,$matches);
for ($i=0; $i<$count; $i++) {
$oldbuf=$matches[0][$i];
foreach ($events as $curevent) {
preg_replace('|\s+'.$curevent.'=".*?"|is','',$matches[1][$i]); // вместо '' можно вставить какое-нибудь уведомление о замене
preg_replace('|\s+'.$curevent.'=\'.*?\'|is','',$matches[1][$i]);
preg_replace('|\s+'.$curevent.'=\S*|is','',$matches[1][$i]);
}
$buffer=str_replace($oldbuf,$matches[0][$i],buffer); // замена исходной строки на очищенную от некорретных обработчиков
}
3. Добавление JavaScript в адрес ссылки или рисунка: (<a href=”javascript:alert(’test’)”></a>).
Корректируется следующим регулярными выражениями:
preg_replace('|<a href="\w+script:.*?"[^>]+>.*?</a>|is','',$buffer);
preg_replace('|<a href=\'\w+script:.*?\'[^>]+>.*?</a>|is','',$buffer);
preg_replace('|<a href=\w+script:\S*[^>]+>.*?</a>|is','',$buffer);
4. Добавление JavaScript в url внутри параметра style, например: <div sytle=”background: url(’javascript:alert(\’test\’)')”></div>
Корректируется следующим куском кода:
$count=preg_ match_all('|<\w+(\s+[^>]*)>|s',$buffer,$matches);
for ($i=0; $i<$count; $i++) {
$oldbuf=$matches[0][$i];
preg_replace('|\s+style=".*?"|is','',$matches[1][$i]); // вместо '' можно вставить какое-нибудь уведомление о замене
preg_replace('|\s+style=\'.*?\'|is','',$matches[1][$i]);
preg_replace('|\s+style=\S*|is','',$matches[1][$i]);
$buffer=str_replace($oldbuf,$matches[0][$i],buffer); // замена исходной строки на очищенную от некорретных обработчиков
}
Но кроме этих, довольно широко известных способов реализации XSS, имеется еще ряд малоизвестных особенностей, которые следует учитывать:
1. Броузер MSIE позволяет писать название протокола не только слитно, но и через символы табуляции (а также, возможно, перевода строки), т.е. ссылка вида <a href=”javas cript:alert(’test’)”>Тест</a> в нем будет работоспособна. Поэтому имеет смысл сначала проводить удаление символов табуляции внутри ссылок
2. В броузере MSIE, кроме JavaScript, существует еще и Visual Basic Script, который также может быть внедрен в URL ссылок и рисунков. Он обозначается vbscript (код в примере 3 написан с учетом его возможного наличия).
3. Если пользователю разрешается добавлять прикрепленные файлы и они сохраняются на диск в доступном для просмотра с помощью броузера месте с расширениями .htm, .html , то возможна атака следующего типа: в HTML-файл помещается код JavaScript, и затем атакуемому с помощью средств социальной инженерии предлагается перейти по ссылке, ведущей на этот файл напрямую, вместо того, чтобы скачать его скриптом.
Кроме того, даже если существует проверка на то, что загружаемый файл является графическим, внедрение JavaScript-кода в файл все равно возможно через так называемые EXIF-параметры (например. вместо имени автора можно прописать <script>alert(’test’)</script>), если файл сохраняется на диск с расширениями .html или .htm.
Примечание: предложенные здесь варианты решения являются упрощенными и для серьезных проектов я порекомендовал бы написать полноценный парсер HTML-кода, а не обходиться регулярными выражениями.