nginx的安全之通过nginx+lua的waf防火墙防sql注入和cc攻击

nginx的安全之通过nginx+lua的waf防火墙防sql注入和cc攻击

基于nginx架构的安全场景

1.常见的恶意行为

2.常见的应用层攻击搜狐段

3.nginx防攻击策略

4.场景:nginx+lua的安全waf防火墙


常见的恶意行为
爬虫行为和恶意抓取、资源盗用
基础防盗链功能-目的不让恶意用户能轻易的爬取网站对外数据

secure_link_module对数据安全性提高加密验证和时效性,适合核心重要数据

access_module-对后台部分用户服务的数据进行ip防控

常见的攻击手段
后台密码撞库-通过猜测密码字典不断对后台系统进行登陆性尝试,从而获取后台登陆密码

方法1:后台登陆密码复杂度
方法2:access_module对后台提供ip防控
方法3: 预警机制

文件上传漏洞:
利用如头像、附近等可以上传的接口将恶意代码植入服务器中
再通过url去访问来执行恶意代码

http://www.chinasoft.com/upload/1.jpg/1.php

nginx将1.jpg作为php代码执行

防范方法:
当访问upload路径且为php结尾的文件时return 403禁止

location ^ ~ /upload{
    root /opt/app/images;
    if ($request_filename ~* (.*)\.php){
        return 403;
    }
}

常见的攻击手段之sql注入
sql注入-利用未过滤/未审核用户输入的攻击方法,让应用程序运行本不该运行的sql代码

1.通过nginx+lua的waf防火墙防sql注入
sql注入场景
用户发起http请求 --> nginx+lua --> php(fastcgi接口) --> mariadb(执行sql)

sql注入模拟

环境准备
安装php和mysql
[root@node1 nginx]# yum install -y mariadb mariadb-server php php-fpm php-mysql

启动数据库
[root@node1 nginx]# systemctl start mariadb
[root@node1 nginx]# mysql -uroot -p

创建数据库,建表,插入用户信息
MariaDB [(none)]> create database info charset=utf8;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> use info;
Database changed
MariaDB [info]> create table users(id int(11) unsigned,username varchar(64),password varchar(64),email varchar(64));
MariaDB [info]> insert into users(id,username,password,email) values(1,'jack',md5('123'),'jack@163.com');


修改nginx配置

[root@node1 conf.d]# cat sql_inject_test.conf 
server {
    listen       80;
    server_name  localhost;

    location / {
    alias /opt/app/code;
        index  index.php index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        fastcgi_param  SCRIPT_FILENAME  /opt/app/code/$fastcgi_script_name;
        include        fastcgi_params;
    }

}

启动php-fpm程序
[root@node1 conf.d]# php-fpm -D
[root@node1 conf.d]# ps -ef|grep php-fpm
root      20808      1  0 18:45 ?        00:00:00 php-fpm: master process (/etc/php-fpm.conf)
apache    20809  20808  0 18:45 ?        00:00:00 php-fpm: pool www
apache    20810  20808  0 18:45 ?        00:00:00 php-fpm: pool www
apache    20811  20808  0 18:45 ?        00:00:00 php-fpm: pool www
apache    20812  20808  0 18:45 ?        00:00:00 php-fpm: pool www
apache    20813  20808  0 18:45 ?        00:00:00 php-fpm: pool www
root      20815  20768  0 18:45 pts/1    00:00:00 grep --color=auto php-fpm

编写打印php环境信息的页面,可以判断环境是否搭建成功
[root@node1 conf.d]# cat /opt/app/code/info.php 
<?php
phpinfo();
?>
2.测试页面准备:

登陆页面html
[root@node1 code]# cat /opt/app/code/login.html 
<html>
<head>
    <title>jeson sql注入演示</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<form action="validate.php" method="post">
    <table border="1" cellpadding="0" cellspacing="0">
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"></td>
        </tr>

        <tr>
            <td>密码</td>
            <td><input type="text" name="password"></td>
        </tr>
        <tr>
            <td><input type="submit" name="提交"></td>
            <td><input type="reset" name="重置"></td>
        </tr>
    </table>
</form>
</body>
</html>

验证页面validate.php
[root@node1 code]# cat /opt/app/code/validate.php 
<?php
    $conn = mysql_connect("localhost", "root", '');
    mysql_select_db("info", $conn) or die('the database you selected is not exists');
    $name = $_POST['username'];
    $pwd = $_POST['password'];
    $sql = "select * from users where username = '$name' and password=md5('$pwd')";
    echo $sql."<br /><br />";
    $query = mysql_query($sql);
    $arr = mysql_fetch_array($query);

    if ($arr) {
        echo "login success!\n";
        echo $arr[1];
        echo $arr[3]."<br /><br />";
    }else{
        echo "login failed!";
    }
?>

3.测试登陆和注入:
普通的登陆
登陆成功,or
1=1在sql中条件成立# 号代表注释 4.nginx+lua防火墙 下载ngx_lua_waf插件并且移动到指定目录: [root@node1 code]# mkdir /etc/nginx/waf yum install -y git git clone https://github.com/loveshell/ngx_lua_waf.git [root@node1 data]# mv ngx_lua_waf /etc/nginx/waf/ 配置nginx.conf [root@node1 waf]# cat /etc/nginx/nginx.conf user nginx; worker_processes 4; worker_cpu_affinity auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; worker_rlimit_nofile 35535; events { worker_connections 10240; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$request_uri"'; lua_package_path "/etc/nginx/waf/ngx_lua_waf/?.lua"; lua_shared_dict limit 10m; init_by_lua_file /etc/nginx/waf/ngx_lua_waf/init.lua; access_by_lua_file /etc/nginx/waf/ngx_lua_waf/waf.lua; access_log off; sendfile on; #tcp_nopush on; #tcp_nodeny on; keepalive_timeout 65; gzip on; gzip_disable "MSIE [1-6]\."; gzip_http_version 1.1; include /etc/nginx/conf.d/*.conf; } 修改waf的路径 [root@node1 waf]# vim /etc/nginx/waf/ngx_lua_waf/config.lua RulePath = "/etc/nginx/waf/ngx_lua_waf/wafconf/" 重启nginx [root@node1 waf]# /usr/sbin/nginx -s reload 测试登陆功能是否正常,此时可以看到,我们输入' or 1 = 1 #还是能够正常登陆 原因是没有指定的规则匹配,所以waf不拦截 编辑post规则 [root@node1 waf]# vim /etc/nginx/waf/ngx_lua_waf/wafconf/post \sor\s+ # 添加对or的拦截规则,如果是空格+or+空格或者其他字符则拦截 select.+(from|limit) (?:(union(.*?)select)) having|rongjitest sleep\((\s*)(\d*)(\s*)\) benchmark\((.*)\,(.*)\) base64_decode\( (?:from\W+information_schema\W) (?:(?:current_)user|database|schema|connection_id)\s*\( (?:etc\/\W*passwd) into(\s+)+(?:dump|out)file\s* group\s+by.+\( xwork.MethodAccessor (?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( xwork\.MethodAccessor (gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ java\.lang \$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ \<(iframe|script|body|img|layer|div|meta|style|base|object|input) (onmouseover|onerror|onload)\= 重启nginx,再次尝试' or 1 = 1 # 用户名登陆可以看到已经拦截下来了 5.测试ccdeny的功能 cc攻击是指对某个接口进行超载访问从而达到拒绝服务攻击的效果 ①不添加waf规则的时候,对网站进行ab压力测试,再次访问是没有问题的 [root@node1 waf]# ab -n 2000 -c 2 http://192.168.3.177/login.html This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.3.177 (be patient) Completed 200 requests Completed 400 requests Completed 600 requests Completed 800 requests Completed 1000 requests Completed 1200 requests Completed 1400 requests Completed 1600 requests Completed 1800 requests Completed 2000 requests Finished 2000 requests Server Software: nginx/1.12.1 Server Hostname: 192.168.3.177 Server Port: 80 Document Path: /login.html Document Length: 2078 bytes Concurrency Level: 2 Time taken for tests: 0.227 seconds Complete requests: 2000 Failed requests: 0 Write errors: 0 Non-2xx responses: 2000 Total transferred: 4458000 bytes HTML transferred: 4156000 bytes Requests per second: 8793.91 [#/sec] (mean) Time per request: 0.227 [ms] (mean) Time per request: 0.114 [ms] (mean, across all concurrent requests) Transfer rate: 19142.22 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 0 Processing: 0 0 0.1 0 2 Waiting: 0 0 0.1 0 2 Total: 0 0 0.1 0 2 Percentage of the requests served within a certain time (ms) 50% 0 66% 0 75% 0 80% 0 90% 0 95% 0 98% 1 99% 1 100% 2 (longest request) [root@node1 waf]# curl -I http://192.168.3.177/login.html HTTP/1.1 200 OK Server: nginx/1.12.1 Date: Thu, 18 Jan 2018 12:06:00 GMT Content-Type: text/html Content-Length: 545 Last-Modified: Thu, 18 Jan 2018 11:22:02 GMT Connection: keep-alive ETag: "5a60835a-221" Accept-Ranges: bytes ②添加waf对ccdeny的规则 # 编辑config.lua把 [root@node1 waf]# vim /etc/nginx/waf/ngx_lua_waf/config.lua RulePath = "/etc/nginx/waf/ngx_lua_waf/wafconf/" attacklog = "on" logdir = "/usr/local/nginx/logs/hack/" UrlDeny="on" Redirect="on" CookieMatch="on" postMatch="on" whiteModule="on" black_fileExt={"php","jsp"} ipWhitelist={"127.0.0.1"} ipBlocklist={"1.0.0.1"} CCDeny="on" # 开启ccdeny的功能 CCrate="100/60" # 限制每分钟100次访问 重新加载nginx,正常访问接口没有问题 [root@node1 waf]# /usr/sbin/nginx -s reload [root@node1 waf]# curl -I http://192.168.3.177/login.html HTTP/1.1 200 OK Server: nginx/1.12.1 Date: Thu, 18 Jan 2018 12:08:56 GMT Content-Type: text/html Content-Length: 545 Last-Modified: Thu, 18 Jan 2018 11:22:02 GMT Connection: keep-alive ETag: "5a60835a-221" Accept-Ranges: bytes 通过ab工具对网站进行压力测试,再次访问就变成503了 [root@node1 waf]# ab -n 2000 -c 2 http://192.168.3.177/login.html This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.3.177 (be patient) Completed 200 requests Completed 400 requests Completed 600 requests Completed 800 requests Completed 1000 requests Completed 1200 requests Completed 1400 requests Completed 1600 requests Completed 1800 requests Completed 2000 requests Finished 2000 requests Server Software: nginx/1.12.1 Server Hostname: 192.168.3.177 Server Port: 80 Document Path: /login.html Document Length: 2078 bytes Concurrency Level: 2 Time taken for tests: 0.254 seconds Complete requests: 2000 Failed requests: 1799 # 可以看到大部分的请求都被拦截了 (Connect: 0, Receive: 0, Length: 1799, Exceptions: 0) Write errors: 0 Non-2xx responses: 2000 Total transferred: 1140644 bytes HTML transferred: 800865 bytes Requests per second: 7866.49 [#/sec] (mean) Time per request: 0.254 [ms] (mean) Time per request: 0.127 [ms] (mean, across all concurrent requests) Transfer rate: 4381.28 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 0 Processing: 0 0 0.2 0 3 Waiting: 0 0 0.1 0 3 Total: 0 0 0.2 0 3 Percentage of the requests served within a certain time (ms) 50% 0 66% 0 75% 0 80% 0 90% 0 95% 0 98% 1 99% 1 100% 3 (longest request) [root@node1 waf]# curl -I http://192.168.3.177/login.html HTTP/1.1 503 Service Temporarily Unavailable Server: nginx/1.12.1 Date: Thu, 18 Jan 2018 12:09:27 GMT Content-Type: text/html Content-Length: 213 Connection: keep-alive

 

posted @ 2018-01-18 20:19  reblue520  阅读(2067)  评论(0编辑  收藏  举报