AI prompts
base on nginx WebShell/内存马,更优雅的nignx backdoor # 全链路内存马系列之 nginx 内存马
![](img/webshellattckchain.jpg)
其他内存马
- [ebpf 内核马](https://github.com/veo/ebpf_shell)
- [websocket 内存马](https://github.com/veo/wsMemShell)
- ### 注意
本项目不含有完整的利用工具,仅提供无害化测试程序、防御加固方案,以及研究思路讨论
- ### 测试程序使用方式
测试环境:Nginx 1.18.0
下载测试程序 [releases](https://github.com/veo/nginx_shell/releases)
将下载的so放至目标服务器上,修改 nginx.conf 配置文件在第一行添加以下内容,path为路径
```
load_module path/ngx_http_cre_module.so;
```
然后重载nginx
```
nignx -s reload
```
POST HTTP header `vtoken: whoami` (测试程序只允许使用 `whoami` 命令)
**如果无结果返回,可尝试增加header数量**
![](img/run.jpg)
![](img/run2.jpg)
- ### 编译方式
```
wget https://nginx.org/download/nginx-1.18.0.tar.gz
tar -zxvf nginx-1.18.0.tar.gz
cd nginx-1.18.0
git clone https://github.com/veo/nginx_shell.git
./configure --with-compat --add-dynamic-module=./nginx_shell/
make modules
```
编译后的so文件位于 nginx-1.18.0/objs/ngx_http_cre_module.so
- ### 一、技术特点
1. 无需临时编译(传统的 nignx so backdoor 需要临时编译)
2. 兼容 1.9.11 以后的所有版本
3. 无需额外组件支持
- ### 二、技术缺点
1. 有so文件落地
2. 需要 nignx -s reload 权限
- ### 三、技术原理
nginx module 支持动态加载so,通过 __attribute ((constructor))的方式绕过nginx module version check,可以编译出适应所有nginx版本的module。
使用header_filter可以取得命令执行的参数,通过body_filter可以返回命令执行后的结果
- ### 四、研究中遇到的问题
1. 绕过nginx对于module的版本检测
通过 __attribute ((constructor))的方式绕过
2. 编写的module要兼容大部分版本
使用较早版本的函数,不使用高版本新增函数
3. 目标编译参数 --without-http-cache 不一致会导致 ngx_http_request_s 结构体变化,程序无法正常使用
编译了两个版本支持不同的编译环境
- ### 五、防御加固方案
1. 监测Nginx Module的加载,Nginx进程的行为
2. 查杀落地文件
3. 收敛 nignx -s reload 权限", Assign "at most 3 tags" to the expected json: {"id":"6791","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"