0x01 关于 nginx
1 2 3 4 5
| 配置灵活,简单,运行时占用系统资源较少,功能模块繁多,可扩展性极强,基于 C ,整个工具大小1M左右 支持高并发,仅限于全部为纯静态文件的情况下,因为最终还要取决于后端 [ 脚本和数据库 ] 的实际处理速度 默认 nginx 会自动选择最佳的网络I/O模型,和nginx不同的是,apache默认就会使用select模型,效率较低 上面这些话的意思也就是说,你的C要牛逼到一定的程度,不然,想做深度二次开发基本是扯淡,真心挺佩服毛子的 更多说明,请直接参考官方文档...
|
0x02 正确理解 linux 对文件,目录,[ 读 写 执行 ]
权限的真正含义,这东西不能靠干说,因为根本理解不扎实,大家可以自己在系统中创建两个普通用户,不停地切换目录文件权限,以深入仔细体会,后面网站目录权限设置要用到这些基础,如果连这些都搞不清,想灵活应用就难了,耐心点,等透彻理解之后,你就会发现真TM简单
目录 读[r / 4]
写[w / 2]
执行[x / 1]
1 2 3
| 读: ls , dir ... 表示可查看该目录下的文件列表 写: rm , mv, cp, mkdir ,touch ... 表示可在该目录下创建,删除,修改文件或者子目录,不过在这之前,一定要先有执行权限,不然进都进不去,又怎么写呢 执行: cd ... 表示可进入该目录
|
文件 读[r / 4]
写[w / 2]
执行[x / 1]
1 2 3
| 读: cat , tac , more , less ,head , tail ... 表示可查看该文件中的内容 写: vi , nano , echo ... 只表示可对文件中的 内容 进行增删改,删除文件还要取决于当前用户对该文件所在目录是否有写权限 执行: 可执行文件,shell脚本... 在linux中任何文件都可以有执行权限,但只有可执行文件和脚本才能真正执行
|
0x03 nginx 容易出现问题的一些点,只要不是直接可以远程利用的,暂不必过于紧张:
1 2 3 4
| nginx 本身可能存在的一些漏洞,如,各类 敏感信息泄露,RCE,DDOS [根据目前已公开的暂未知]... 各种配置错误,如,目录遍历造成的敏感信息泄露,低版本的解析漏洞... 也有躺枪的可能,第三方模块和库漏洞,如,心脏滴血... ...
|
0x04 常用功能
1 2 3
| web [ 各类常规web服务功能,如虚拟主机,基本认证... ] 负载均衡 [ 反向代理 ] 缓存 [ web缓存 ]
|
0x05 在开始说nginx之前,我们先来简单理解下select模型
,poll 模型
和epoll 模型
,后续有空咱们会再单独拿出来细说,毕竟不是这次的重点,所以只能先简单科普下,能理解大致工作流程即可
IO多路复用
1 2 3 4 5
| 三种模型同属IO多路复用机制,即同时监视多个描述符,一旦某个描述符读或写就绪,就通知相应的程序进行对应的读写操作 通俗来讲,就是单个进程可以同时处理多个网络连接的IO,原理即通过select,poll,epoll函数不断轮询所负责的所有socket 当某个socket处于就绪状态,就通知指定的用户进程去处理,但select,poll,epoll本质上又都是同步I/O 因为他们都需要在读写事件就绪后自己负责进行读写,也就是说,整个读写过程是处于阻塞状态的 而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷到用户空间
|
select 模型
1 2 3 4
| select目前几乎支持所有的平台,同步IO处理读写会一直处于阻塞状态,select就是这样,调用select函数后会一直处于阻塞状态,直到有描述符就绪 但select缺点之一就是,单个进程能够监视的文件描述符的数量有大小限制 在linux上一般为1024,虽然可以通过修改宏定义或者重新编译内核的方式提升这一限制,但这样也会造成效率低下 select对socket进行扫描时属于线性扫描,即逐个轮询,效率较低
|
poll模型
1 2 3 4
| poll本质上和select区别不太大,它将用户传入的数组拷贝到内核空间,然后轮询每个描述符对应的设备状态 如果设备就绪,则在设备等待队列中加入一项并继续遍历,如果遍历完所有描述符后没有发现就绪设备 则挂起当前进程,直到设备就绪或者超时,被唤醒后它又要再次遍历描述符,整个过程经历了多次无用的遍历 另外,它不再使用select"key-value"的传递方式,且pollfd没有最大数量限制
|
epoll模型
1 2 3 4 5 6 7 8 9
| 属于select和poll的增强改进版,epoll对文件描述符的操作有两种模式 LT模式: 当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件 下次调用epoll_wait时,会再次响应应用程序并通知此事件,效率相对来讲较高 ET模式: 当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件 如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件
|
0x06 此次演示环境,如下:
1 2
| CentOS6.8 x86_64 最小化,带基础库安装 eth0: 192.168.3.42 eth1: 192.168.4.14 eth2: 192.168.5.14 nginx-1.12.2.tar.gz
|
0x07 下载,编译安装 nginx 1.12.2 ,注意,这里暂时就用最新版的稳定版本,实际生产环境中版本可以稍低一些,稳定为主,选择版本时应尽量避开一些已知的高危漏洞版本
创建nginx运行账户,尽量以伪用户身份来运行nginx服务,切记,千万不要直接用root权限来运行nginx,否则别人拿到的webshell权限很可能直接是root权限的 [ 如果你后面的的fastcgi服务端 [php-fpm] 和 nginx使用的是同一用户身份来运行,就很容造成这种情况 ]
1
| # useradd -s /sbin/nologin -M nginx
|
先安装好所需的各中依赖库和编译器,下载 nginx-1.12.2.tar.gz 源码包
1 2 3 4
| # yum install pcre pcre-devel openssl openssl-devel gcc gcc-c++ automake zlib zlib-devel -y # wget http://nginx.org/download/nginx-1.12.2.tar.gz # tar xf nginx-1.12.2.tar.gz # cd nginx-1.12.2
|
源码级修改nginx默认版本号,虽然,还可以后续在配置文件中改,但那个改的毕竟不彻底,它只是简单的把详细的版本号给去掉了,nginx
字样还留着呢,其实,这里你改成 apache
也许会更具迷惑性,因为通过在url中转换大小写请求依然是可以试出来目标机器到底是linux还是windows平台,大家看到,我这里是直接改成了IIS 8.5
,正常来讲 IIS 8.5
所对应的系统平台应该是windows server 2012R2
,但如果别人此时试出来我的机器却是linux平台,很可能就会产生怀疑,因为linux平台是不可能装IIS的,起码暂时是不能的,如果你这里换成apache也许对方就信了,因为apache在linux平台部署再正常不过,然后入侵者,可能就会去尝试一些和apache相关的漏洞,也就是说,你把入侵者引向了一条根本不通的路,另外,有很多获取web服务器banner的扫描工具,基本也都是靠截取的http响应头中server
字段的内容 真正靠服务器指纹识别的那种不算
,这样一来,也顺便把别人的工具都蒙骗了,反正,尽可能在信息搜集阶段就扰乱入侵者的视线,因为有些漏洞只针对特定类型,特定版本,这样可以一定程度上扰乱对方的判断和后续的渗透方式
查看nginx支持的所有模块,可根据自己的实际需求选择性的启用,对于一些曾经爆过严重漏洞的模块,要格外仔细小心,每个功能模块在其官方文档中都有详细说明及使用样例,具体可参考 http://nginx.org/en/docs/
开始编译安装nginx,具体编译参数,如下
1 2 3
| # ./configure --prefix=/usr/local/nginx-1.12.2 --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module # make && make install # ln -s /usr/local/nginx-1.12.2/ /usr/local/nginx
|
编译安装没问题以后,我们先大致看看 nginx 的基本目录结构,初步了解下里面的文件工具都是干什么用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| # tree -L 2 /usr/local/nginx ├── client_body_temp ├── conf nginx 配置文件目录 │ ├── fastcgi.conf 后端动态脚本接口配置,如,php,java... │ ├── fastcgi.conf.default │ ├── fastcgi_params │ ├── fastcgi_params.default │ ├── koi-utf │ ├── koi-win │ ├── mime.types │ ├── mime.types.default │ ├── nginx.conf nginx 主配置文件 │ ├── nginx.conf.bak │ ├── nginx.conf.default │ ├── scgi_params │ ├── scgi_params.default │ ├── uwsgi_params │ ├── uwsgi_params.default │ └── win-utf ├── fastcgi_temp ├── html nginx 站点目录 │ ├── 50x.html │ └── index.html ├── logs nginx 自身日志目录 │ ├── access.log 访问日志 │ └── error.log 错误日志 ├── proxy_temp ├── sbin nginx 服务管理工具 │ └── nginx ├── scgi_temp └── uwsgi_temp
|
再来查看nginx的详细版本,可以看到,我们刚刚在源码中修改的版本号,此时已经生效了
1
| # /usr/local/nginx/sbin/nginx -v
|
关于nginx服务管理工具本身的一些用法
1
| # /usr/local/nginx/sbin/nginx -V 查看编译时的详细参数,如果当初nginx不是你编译的
|
1 2 3 4 5 6 7 8
| # cat /usr/local/nginx/logs/error.log nginx错误日志,nginx在运行中有任何错误,都可以尝试去该日志文件中查找原因 # /usr/local/nginx/sbin/nginx -h 查看nginx管理工具使用帮助 # /usr/local/nginx/sbin/nginx 启动nginx服务 # netstat -tulnp | grep ":80" 查看nginx进程是否存在 # /usr/local/nginx/sbin/nginx -s quit 关闭nginx服务 # /usr/local/nginx/sbin/nginx -s reload 平滑重启nginx # echo "/usr/local/nginx/sbin/nginx" >> /etc/rc.local 加入自启动 # cd /usr/local/nginx/conf/ && mv nginx.conf nginx.conf.bak && egrep -v "^$|#" nginx.conf.default > nginx.conf 简化配置文件
|
0x08 装完以后,我们就开始真正配置nginx,下面是关于nginx.conf
中各标签段用途的简要说明,注意,在配置nginx时,所有语句结尾必须有分号,基本配置语法
main区
1 2 3
| worker_processes 1; error_log logs/error.log error; pid logs/nginx.pid
|
事件区
可以在此区域指定处理模型,如,epoll或select
1 2 3 4 5
| events { worker_connections 1024; multi_accept on; use epoll; }
|
http 区
主要用来配置和http自身相关的一些参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; autoindex off; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
|
0x09 配置基于各种类型的虚拟主机,在nginx中,每一个server标签段即表示一个虚拟主机即一个站点
,也就是说,在同一台机器上可以同时有N个虚拟主机,只需要在后面接着一直加server段即可,注意,如果客户端直接用ip访问,默认nginx会读取第一个server标签段的配置进行响应,因为nginx无法通过请求头中的host内容来确定是哪个虚拟主机,如果你不在host中指定域名,它默认就会选择第一个
先处理好nginx.conf
1
| # vi /usr/local/nginx/conf/nginx.conf
|
1 2 3
| worker_processes 1; error_log logs/error.log error; pid logs/nginx.pid
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| events { worker_connections 1024; multi_accept on; use epoll; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; autoindex off; include extra/bwapp.conf; include extra/dvws.conf; include extra/drupal7.conf; include extra/status.conf; include extra/rwrites.conf; }
|
配置基于域名的虚拟主机,通常都是指需要直接暴露在公网中的站点,即所谓的各种子域
1 2 3 4
| # mkdir /usr/local/nginx/conf/extra # mkdir /usr/local/nginx/html/bwapp # echo "<h2>Hello bwapp ^_^</h2>" > /usr/local/nginx/html/bwapp/index.html # vi /usr/local/nginx/conf/extra/bwapp.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| server { listen 80; server_name bwapp.org test.bwapp.org; location / { root html/bwapp; index index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html/bwapp; } }
|
1 2
| # /usr/local/nginx/sbin/nginx -t # /usr/local/nginx/sbin/nginx
|
配置基于端口的虚拟主机,主要供内部人员办公使用,如各类oa…访问不同的端口即会访问到不同的站点目录
1 2 3 4
| # mkdir /usr/local/nginx/html/dvws # echo "<h2>Hello dvws ^_^</h2>" > /usr/local/nginx/html/dvws/index.html # cp /usr/local/nginx/conf/extra/bwapp.conf /usr/local/nginx/conf/extra/dvws.conf # vi /usr/local/nginx/conf/extra/dvws.conf
|
1 2 3 4 5 6 7 8 9 10 11 12
| server { listen 81; server_name test.dvws.org; location / { root html/dvws; index index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html/dvws; } }
|
1 2
| # /usr/local/nginx/sbin/nginx -t # /usr/local/nginx/sbin/nginx -s reload
|
配置基于ip的虚拟主机,需要一台服务器上同时有多个ip,
1 2 3 4
| # mkdir /usr/local/nginx/html/drupal7 # echo "<h2>Hello drupal7 vuln ^_^</h2>" > /usr/local/nginx/html/drupal7/index.html # cp /usr/local/nginx/conf/extra/bwapp.conf /usr/local/nginx/conf/extra/drupal7.conf # vi /usr/local/nginx/conf/extra/drupal7.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| server { listen 192.168.3.42:82; server_name test.drupal7.org; location / { root html/drupal7; index index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html/drupal7; } }
|
1 2
| # /usr/local/nginx/sbin/nginx -t # /usr/local/nginx/sbin/nginx -s reload
|
0x10 利用nginx自身提供的状态模块,来监控指定机器的nginx服务运行状态,如下,直接新建一个server标签段,访问指定的域名即可查看对应nginx服务状态
1
| # vi /usr/local/nginx/conf/extra/status.conf
|
1 2 3 4 5 6 7 8
| server { listen 80; server_name test.status.org; location / { stub_status on; access_log off; } }
|
1 2
| # /usr/local/nginx/sbin/nginx -t # /usr/local/nginx/sbin/nginx -s reload
|
0x11 详细配置nginx访问日志格式,日志格式最好定义在http区段中,而access_log最好放在每个server标签段中,为了便于后续审查分析,这里需要同时记录POST
和COOKIE
中的数据 [可能会造成日志量激增]
,因为绝大多数入侵都是基于post请求和cookie机制的,光靠GET
很难真正记录到什么有用的东西
1
| # vi /usr/local/nginx/conf/nginx.conf
|
1 2 3 4 5 6 7
| http { ... log_format main '$remote_addr - $remote_user [$time_local] ' ' "$request" $request_body $status $body_bytes_sent ' ' "$http_referer" "$http_user_agent" "$http_x_forwarded_for" "$dm_cookie" '; ... }
|
1
| # vi /usr/local/nginx/conf/extra/bwapp.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| server { set $dm_cookie ""; if ($http_cookie ~* "(.+)(?:;|$)") { set $dm_cookie $1; } listen 80; server_name bwapp.org test.bwapp.org; location / { root html/bwapp; index index.html; } access_log logs/access_bwapp.log main; error_page 500 502 503 504 /50x.html; location = /50x.html { root html/bwapp; } }
|
0x12 利用shell实现自动轮询nginx访问日志,即,所谓的定时日志切割,下面是按天切,根据你自己的实际需求也可按小时切,按分钟切,相应的改下脚本和定时任务的时间设置即可
1 2 3 4 5 6 7 8 9
| Dateformat=`date +%Y%m%d -d -1day` Basedir="/usr/local/nginx" Nginxlogdir="$Basedir/logs" Logname="access_bwapp" [ -d $Nginxlogdir ] && cd $Nginxlogdir||exit 1 [ -f ${Logname}.log ]||exit 1 /bin/mv ${Logname}.log ${Dateformat}_${Logname}.log $Basedir/sbin/nginx -s reload
|
把刚刚的脚本加到系统计划任务中,实现日志自动轮询切割
1 2 3 4 5 6
| # chmod +x nginx_log.sh # date -s "2014-09-23" # /bin/sh nginx_log.sh # hwclock --hctosys # crontab -e 00 01 * * * /root/nginx_log.sh
|
0x13 测试url重写功能是否已经可用典型应用,如,伪静态,域名跳转,禁止访问敏感目录
,尽量把不同站点的日志放在对应的server标签段中,防止日志单文件过大
1 2
| permanent 永久跳转,实际中用的较多 redirect 临时跳转
|
1
| # vi /usr/local/nginx/conf/extra/rwrites.conf
|
1 2 3 4 5
| server { listen 80; server_name rewrite.org; rewrite ^/(.*) https://klionsec.github.io/$1 permanent; }
|
1 2
| # /usr/local/nginx/sbin/nginx -t # /usr/local/nginx/sbin/nginx -s reload
|
0x14 关于 rewrite 基本语法,并非今天的重点,我们后续再单独详细说明
1
| rewrite regex replacement [flag]
|
0x15 nginx的fastcgi_pass模块 [ CGI 即通用网关接口 ]
和 php-fpm 之间的一些工作细节
1 2 3 4 5 6 7
| nginx的fastcgi主要负责把web服务器和动态脚本进行分离 也就是说 nginx 只要检测到是动态脚本 [ 在nginx.conf判断文件后缀 ] 就直接抛给fastcgi [ 实际上是fastcgi_pass ] 然后fastcgi客户端 [ 即fastcgi_pass ] 会再丢给fastcgi服务端 [ php-fpm ] wrapper 的意思就是用来监听某个socket,只要监听到指定的socket就自动调用php解析器去处理 说白点,fastcgi 其实就是一个接口,一个和其他应用程序之间通信的接口 顾名思义,在后端脚本 [ 可以是 java,php,.net...] 和 web服务器上都务必要先存在这么一个接口 之后,两端便通过这个接口进行各种数据通信,即所谓的C/S架构,nginx 为客户端[ fastcgi_pass ],后端脚本进程为服务端[ php-fpm ]
|
0x16 让nginx和php进行联动,当发现是php的后缀就抛给nginx的fastcgi_pass,再由fastcgi_pass丢给php-fpm去处理
1
| # vi /usr/local/nginx/conf/extra/bwapp.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| server { set $dm_cookie ""; if ($http_cookie ~* "(.+)(?:;|$)") { set $dm_cookie $1; } listen 80; server_name bwapp.org test.bwapp.org; root html/bwapp; location / { index index.html index.php; } location ~.*\.php?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } access_log logs/access_bwapp.log main; # access_log off; error_page 500 502 503 504 /50x.html; location = /50x.html { root html/bwapp; } }
|
0x17 严格控制站点目录权限,对于每个站点所在目录,属主,属组全部丢给root,然后目录一律755,文件一律644,因为上传目录还需要能让用户写,所以要把属主改为nginx,等会儿只需要用nginx来控制上传目录中的php文件不能解析即可
1 2 3 4
| # chown -R root.root /usr/local/nginx/html/bwapp/ # find /usr/local/nginx/html/bwapp/ -type f | xargs chmod 644 # find /usr/local/nginx/html/bwapp/ -type d | xargs chmod 755 # chown -R nginx.nginx /usr/local/nginx/html/bwapp/upload
|
0x18 把用户的所有数据全部死死控制在我们所指定的上传目录中,然后禁止用户在上传目录下执行后端脚本,这里默认是递归应用的,也就是说,即使用户想办法在upload目录下创建了子目录,把webshell传到了子目录里,也依然是无法执行的,当然,不仅仅是上传目录,所有你不想让执行后端脚本的目录,都可以把它加进去,这些配置务必全部加在server标签段的头部位置,注意,下面的配置也全部都是加到server标签段中的,另外,我们要时刻谨记,从客户端过来的一切数据都是有害的
,这也是你后续做任何防御的基本准则
1
| # vi /usr/local/nginx/conf/extra/bwapp.conf
|
1 2 3 4 5 6 7
| server { ... location ~ /(attachments|upload|static)/.*\.(php|php5|php4|cgi|jsp)?$ { # 你可以把所有可执行的脚本后缀都加进去,注意,linux严格区分大小写 deny all; } ... }
|
0x19 有时,当你发现,某单个ip瞬间访问过频,很可能就是别人在扫描,此时可直接先用nginx快速封ip,如果单单只是针对web的,大可不必用iptables来搞
1 2 3 4 5
| server { ... deny 192.168.3.0/24; ... }
|
0x20 拒绝各种危险请求方法,这里的HEAD方法也可根据实际需求,做适当取舍,下面的意思就是除了GET,POST,HEAD请求方法之外,别的方法一律禁止
1 2 3 4 5 6 7
| server { ... if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 403; } ... }
|
0x21 防止各类敏感文件泄露或被下载,下面有些文件后缀可自行根据实际业务需求进行取舍,并非一定要加上所有类型,这里只是简单样例
1 2 3 4 5 6 7
| server { ... location ~* .(txt|conf|bash_history|bash_profile|bashrc|xml|bak|sql|log|gz|zip|svn|git|inc|mdf|sh)$ { deny all; } ... }
|
0x22 重定向到所有服务端错误到指定的404页面,尽量不要在前端留下任何错误,上线之前把所有的debug功能全部关闭,有错误,直接打log
1 2 3 4 5 6 7 8
| server { ... error_page 500 502 503 504 /404.html; location = /404.html { root html/bwapp; } ... }
|
0x23 防止跨目录,把webshell限死在当前站点目录下,让其上一级目录都翻不了,方法很简单,在每个站点根目录下,新建一个.user.ini文件,加入以下语句,open_basedir为当前站点目录的绝对路径,注意此文件权限,只有root能写,另外,关于.user.ini文件用途请直接参考php官方说明
1 2 3 4
| # vi /usr/local/nginx/html/bwapp/.user.ini open_basedir=/usr/local/nginx/html/bwapp:/tmp/:/proc/ # chown root.root .user.ini # chmod 644 .user.ini
|
0x24 降低溢出风险,在awvs官方站点中有针对此项的详细说明
1 2 3 4 5 6 7 8 9 10 11 12 13
| server { ... client_body_buffer_size 1K; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k; client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10; ... }
|
0x25 尽可能防止各种恶意爬取及非正常访问,避免造成部分敏感信息泄露
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| server { ... if ($http_user_agent ~ "Lua"){ return 403; } if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) { return 403; } if ($http_user_agent ~ ^$) { return 403; } ... }
|
0x26 限制各类搜索引擎蜘蛛的抓取频率,先在http标签段中定义好,再在server标签段中引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| http{ ... limit_req_zone $anti_spider zone=anti_spider:60m rate=100r/m; # 每分钟只能处理100个请求 ... } server{ ... limit_req zone=anti_spider burst=5 nodelay; if ($http_user_agent ~* "baiduspider|bingbot|Yahoo! Slurp|msnbot") { # 可以把你知道的所有的搜索引擎蜘蛛都加上 set $anti_spider $http_user_agent; } ... }
|
0x27 简单的防sql注入[实战中极不建议这么干]
,可以自行把各种注入语句里面的关键字都加进去,单单这样,还是很容易被bypass掉,比如,大小写
,有些朋友可能会说,加个i
不就行了,确实,这样是不区分大小写了,不过最好不要直接在nginx配置中这样搞,极易误报,而且设置白名单非常麻烦,这里仅仅只是为了告诉大家,可以用nginx这么玩,但自己真正部署的时候就不要这么干了,毕竟这防不住啥,推荐直接自行去定制各种开源waf
1 2 3 4 5 6 7
| server { ... if ($request_uri ~* (.*)(insert|select|delete|update|count|\*|%|master|truncate|declare|\'|\;|and|or|\(|\)|exec)(.*)$ ) { rewrite ^(.*) https://klionsec.github.io redirect; } ... }
|
0x28 也可以尝试实时从nginx 访问日志
中,快速捕捉各类敏感web攻击特征并预警,详情可参考本博客的另一篇文章 入侵取证 [ web日志分析初步 ]
0x29 合理配置robots.txt文件,尽量不要把一些敏感比较信息,如,各种账号密码,敏感参数,各种web,vpn入口等…都暴露给各种搜索引擎,另外,各类用于测试的探针如,phpinfo之流
,就不用多说了吧,全部清干净,被人扫目录扫出来,前面有些东西就白干了
0x30 尽可能隐藏住后台,不要用太大众的名字或者网站域名什么的,反正别让用户能随便猜到就行,限制用户直接从公网访问到网站后台,可以在nginx中获取用户原始ip,然后判断只允许指定的内网段才能访问后台
0x31 利用lsyncd实时监控指定用户上传目录中的create事件
,然后,过滤出可执行后缀脚本文件,打成zip,再配合百度WebShell检测引擎提供的扫描接口https://scanner.baidu.com 上传zip,初步实现全自动秒删webshell,据朋友反应,实际的检测效果还算不错
0x32 最后,定期去关注nginx官方发布的各种高危补丁,适时修补即可
0x33 更多,待续…
小结:
实际部署过程中做好这些最基本的防御措施即可,nginx自身能做事情确实还有很多,但完全想利用nginx实现一个准waf的效果,毕竟不太现实,也真的没那必要,如果对安全性真的有特别要求,建议大家还是自行去深度定制各类开源waf,说这么多,只是想告诉大家,真正的防御并不是盲目的人云亦云,漫无目的的象征性做做样子,你自己也要时刻跟进入侵者的各种猥琐攻击手法,仔细不停地复现分析,适时针对性改进防御策略才行,在安全的字典里,没有一劳永逸,有的是只是永无休止的对抗,唯一的办法就是未雨绸缪,只有比敌人更勤奋,才有占得先机的可能,另外,这里说的单单也只是针对nginx,大家都很清楚,安全本来就是一个面,只是一个节点的安全,根本就算不上安全,另外,关于脚本自身的安全以后还会有非常大篇幅说明,web
,作为入侵者的首选途径,也是我们的重点防御对象,如果真正防住了web,基本就防住了绝大部分的外部入侵,话说回来,这一切还都是建立在对方没有手握各种远程0day的情况下,如果人人都像NSA那样,基本也就没啥是安全的了,只需一个端口,就直接捅到你怀疑人生
,当然,你的实际价值肯定要先远远要超过买0day的钱,别人才有可能会用0day,毕竟这个东西基本上就是一次性的,万一被被别人的蜜罐套走了,岂不得不偿失,这里突然想起别人说过的一句话0day固然可怕,但,你还不配
,哈哈……说一千道一万,nginx的主要作用还是为了更好的提供web服务[ 一切还以满足实际业务需求和高性能为主 ]
,总不能一味地为了安全连钱都不挣了吧,好好活下去比什么都重要,今天不自觉废话稍微有点儿多了,大家不要建议哈,祝好运 ^_^