├── Changes ├── MANIFEST ├── MANIFEST.bak ├── Makefile.PL ├── README.md ├── example ├── example.acess ├── fwban.pl ├── ngixban.pl ├── summary.pl └── synban.pl ├── ignore.txt ├── lib └── App │ └── Waf.pm ├── t ├── 00-load.t ├── manifest.t ├── pod-coverage.t └── pod.t └── xt └── boilerplate.t /Changes: -------------------------------------------------------------------------------- 1 | Revision history for App-Waf 2 | 3 | 0.08 2018-02-01/16 4 | * bug fix. 5 | 6 | 0.07 2017-07-14/16 7 | * fix iptables can't find bug 8 | * add scane for SYN attack and ban for IPs 9 | 10 | 0.06 2016-12-13/18 11 | * add Parameter fault tolerance. 12 | 13 | 0.05 2016-11-18/18 14 | * pod doc fix. 15 | 16 | 0.04 2016-11-18/18 17 | * bug fixes. 18 | 19 | 0.03 2016-11-17/19 20 | * add iptables banip practice example. 21 | * add nginx banip practice example. 22 | 23 | 0.02 2016-11-16/19 24 | * add summery output for sort of type. 25 | * practice examples an example sub. 26 | 27 | 0.01 2016-11-14/19 28 | *First version, released on an unsuspecting world. 29 | 30 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | Changes 2 | example/banip.pl 3 | example/example.acess 4 | example/logsecm.pl 5 | ignore.txt 6 | lib/App/Waf.pm 7 | lib/App/Waf.pm.tdy 8 | Makefile.PL 9 | MANIFEST This list of files 10 | README 11 | README.md 12 | t/00-load.t 13 | t/manifest.t 14 | t/pod-coverage.t 15 | t/pod.t 16 | xt/boilerplate.t 17 | -------------------------------------------------------------------------------- /MANIFEST.bak: -------------------------------------------------------------------------------- 1 | Changes 2 | example/banip.pl 3 | example/example.acess 4 | example/logsecm.pl 5 | ignore.txt 6 | lib/App/Waf.pm 7 | lib/App/Waf.pm.tdy 8 | Makefile.PL 9 | MANIFEST This list of files 10 | README 11 | README.md 12 | t/00-load.t 13 | t/manifest.t 14 | t/pod-coverage.t 15 | t/pod.t 16 | xt/boilerplate.t 17 | -------------------------------------------------------------------------------- /Makefile.PL: -------------------------------------------------------------------------------- 1 | use 5.006; 2 | use strict; 3 | use warnings; 4 | use ExtUtils::MakeMaker; 5 | 6 | WriteMakefile( 7 | NAME => 'App::Waf', 8 | AUTHOR => q{ORANGE }, 9 | VERSION_FROM => 'lib/App/Waf.pm', 10 | ABSTRACT_FROM => 'lib/App/Waf.pm', 11 | LICENSE => 'Perl', 12 | PL_FILES => {}, 13 | MIN_PERL_VERSION => 5.006, 14 | CONFIGURE_REQUIRES => { 15 | 'ExtUtils::MakeMaker' => 0, 16 | 'File::ReadBackwards' => 0, 17 | }, 18 | BUILD_REQUIRES => { 19 | 'Test::More' => 0, 20 | }, 21 | PREREQ_PM => { 22 | #'ABC' => 1.6, 23 | #'Foo::Bar::Module' => 5.0401, 24 | }, 25 | 26 | META_MERGE => { 27 | 'meta-spec' => { version => 2 }, 28 | resources => { 29 | repository => { 30 | type => 'git', 31 | url => 'https://github.com/bollwarm/app-waf.git', 32 | web => 'http://ijz.me', 33 | }, 34 | }, 35 | }, 36 | 37 | 38 | dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, 39 | clean => { FILES => 'App-Waf-*' }, 40 | ); 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # app-waf 2 | 3 | ## 一个简单的waf模块。A sample Web Application Firwork using Perl and RE ban for suspicous web access 4 | 5 | 用来实时探测web 非法访问,统计非法访问的ip ,web状态,访问url,来源web url。结合iptables可以实现实现实时封禁。 6 | 7 | ## 实例说明 见example目录(包括日志) 8 | 9 | use App::Waf; 10 | my $filename = "example.acess";#日志文件 11 | my $numlines = 50000; #要处理的行数,从后读。 12 | my $line=tail($filename,$$numlines); 13 | my ($log,$zcount,$zip,$zrequrl,$zstatus,$siteurl)=initCount($line); 14 | 15 | print "==============Attack Summary ==================\n"; 16 | print "\nThe total attack count: $zcount \n"; 17 | print "\nThe count from source IP: \n\n"; 18 | print "$_\=> $zip->{$_} \n" for(sort keys %{$zip}); 19 | print "The count From request Url: \n\n"; 20 | print "$_\=> $zrequrl->{$_} \n" for(sort keys %{$zrequrl}); 21 | print "\n\nThe count From Http Status: \n\n"; 22 | print "$_\=> $zstatus->{$_} \n" for(sort keys %{$zstatus}); 23 | print "\n\nThe count From Site Url: \n\n"; 24 | print "$_\=> $siteurl->{$_} \n" for(sort keys %{$siteurl}); 25 | 26 | ## 结合nginx 和 iptables 进行实时banip的实例(example/banip.pl) 27 | 28 | 加入crontab 每5分钟执行一次。 29 | 30 | echo "*/5 * * * * perl $dir/example/ngixban.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root 31 | echo "*/5 * * * * perl $dir/example/synban.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root 32 | 33 | ## 结果展示 34 | 35 | +++++++++++++++++++++++++ban for SYN attact+++++++++++++++++++++ 36 | 37 | Fri Jul 14 15:46:02 2017 Ban The IP :173.173.199.246 38 | Fri Jul 14 15:46:02 2017 :band 173.173.199.246 39 | Fri Jul 14 15:46:02 2017 73.6.1.122 SYN攻击次数: 6 40 | Fri Jul 14 15:46:02 2017 103.56.116.150 SYN攻击次数: 2 41 | Fri Jul 14 15:47:01 2017 173.173.199.246 SYN攻击次数: 19 42 | Fri Jul 14 15:47:01 2017 Ban The IP :173.173.199.246 43 | Fri Jul 14 15:47:01 2017 baned 173.173.199.246 44 | Fri Jul 14 15:47:01 2017 103.56.116.150 SYN攻击次数: 1 45 | Fri Jul 14 15:48:01 2017 173.173.199.246 SYN攻击次数: 19 46 | Fri Jul 14 15:48:01 2017 Ban The IP :173.173.199.246 47 | Fri Jul 14 15:48:01 2017 baned 173.173.199.246 48 | Fri Jul 14 15:48:01 2017 103.56.116.150 SYN攻击次数: 1 49 | Fri Jul 14 15:49:01 2017 173.173.199.246 SYN攻击次数: 17 50 | Fri Jul 14 15:49:01 2017 Ban The IP :173.173.199.246 51 | Fri Jul 14 15:49:01 2017 band alread! 52 | 53 | ==============Attack Summary ================== 54 | 55 | The total attack count: 131 56 | 57 | The count from source IP: 58 | 59 | 103.248.223.116=> 19 60 | 103.37.3.202=> 2 61 | 106.39.200.46=> 3 62 | 107.151.213.123=> 1 63 | 115.148.98.127=> 2 64 | 180.76.6.51=> 99 65 | 59.42.147.17=> 4 66 | 64.16.214.100=> 1 67 | 68 | The count From request Url: 69 | 70 | /?cat=%0acat%20/etc/passwd%0a&paged=3=> 1 71 | /?cat=%22%26cat%20/etc/passwd%26%22&paged=3=> 1 72 | /?cat=%22;print(md5(acunetix_wvs_security_test));%24a%3d%22&paged=2=> 1 73 | /?cat=%22;print(md5(acunetix_wvs_security_test));%24a%3d%22&paged=3=> 1 74 | /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d%5c&paged=2=> 1 75 | /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d%5c&paged=3=> 1 76 | /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d&paged=2=> 1 77 | /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d&paged=3=> 1 78 | /?cat=%26cat%20/etc/passwd%26&paged=3=> 1 79 | /?cat=%60cat%20/etc/passwd%60&paged=3=> 1 80 | /?cat=%7ccat%20/etc/passwd%23&paged=3=> 1 81 | /?cat='%26cat%20/etc/passwd%26'&paged=3=> 1 82 | /?cat=';print(md5(acunetix_wvs_security_test));%24a%3d'&paged=2=> 1 83 | /?cat=';print(md5(acunetix_wvs_security_test));%24a%3d'&paged=3=> 1 84 | /?cat=(select(0)from(select(sleep(15)))v)/*'%2b(select(0)from(select(sleep(15)))v)%2b'%22%2b(select(0)from(select(sleep(15)))v)%2b%22* 85 | /&paged=3=> 4 86 | /?cat=.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./etc/passwd&paged=3=> 1 87 | /?cat=..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afetc/passwd&paged=3=> 1 88 | 89 | -------------------------------------------------------------------------------- /example/example.acess: -------------------------------------------------------------------------------- 1 | 180.76.6.51 - - [14/Nov/2016:14:26:53 +0800] "GET /horde/util/barcode.php?type=../../../../../../../../../../../etc/passwd%00 HTTP/1.1" 404 201 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 2 | 180.76.6.51 - - [14/Nov/2016:14:26:53 +0800] "GET /util/barcode.php?type=../../../../../../../../../../../etc/passwd%00 HTTP/1.1" 404 197 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 3 | 180.76.6.51 - - [14/Nov/2016:14:27:26 +0800] "GET /sdk/../../../../../../../../../../../../../etc/passwd HTTP/1.1" 400 588 "-" "-" 4 | 180.76.6.51 - - [14/Nov/2016:14:27:28 +0800] "GET /?page=../../../../../../../../../etc/passwd%00.jpg HTTP/1.1" 200 7032 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 5 | 180.76.6.51 - - [14/Nov/2016:14:29:31 +0800] "GET /?cat=../../../../../../../../../../etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 6 | 180.76.6.51 - - [14/Nov/2016:14:29:33 +0800] "GET /?cat=../../../../../../../../../../etc/passwd%00.jpg&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 7 | 180.76.6.51 - - [14/Nov/2016:14:29:38 +0800] "GET /?cat=/../..//../..//../..//../..//../..//etc/passwd%00.jpg&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 8 | 180.76.6.51 - - [14/Nov/2016:14:29:46 +0800] "GET /?cat=../..//../..//../..//../..//../..//../..//../..//../..//etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 9 | 180.76.6.51 - - [14/Nov/2016:14:29:47 +0800] "GET /?cat=../.../.././../.../.././../.../.././../.../.././../.../.././../.../.././etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 10 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=invalid../../../../../../../../../../etc/passwd/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././.&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 11 | 180.76.6.51 - - [14/Nov/2016:14:29:54 +0800] "GET /?cat=/%5c../%5c../%5c../%5c../%5c../%5c../%5c../etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 12 | 180.76.6.51 - - [14/Nov/2016:14:29:59 +0800] "GET /?cat=../../../../../../../../../../windows/win.ini&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 13 | 180.76.6.51 - - [14/Nov/2016:14:30:01 +0800] "GET /?cat=../../../../../../../../../../boot.ini&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 14 | 103.248.223.116 - - [14/Nov/2016:14:05:27 +0800] "GET /uploads/plus/search.php?keyword=11&typeArr[%60@%27%60and%28SELECT%201%20FROM%28select%20count%28*%29,concat%28floor%28rand%280%29*2%29,%28SELECT/*%27*/concat%280x5f,userid,0x5f,pwd,0x5f%29%20from%20dede_admin%20Limit%200,1%29%29a%20from%20information_schema.tables%20group%20by%20a%29b%29]=1 HTTP/1.1" 404 221 "-" "Python-urllib/2.7" 15 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=(select(0)from(select(sleep(15)))v)/*'%2b(select(0)from(select(sleep(15)))v)%2b'%22%2b(select(0)from(select(sleep(15)))v)%2b%22*/&paged=3 HTTP/1.1" 404 4083 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 16 | 180.76.6.51 - - [14/Nov/2016:14:29:49 +0800] "GET /?cat=if(now()%3dsysdate()%2csleep(15)%2c0)/*'XOR(if(now()%3dsysdate()%2csleep(15)%2c0))OR'%22XOR(if(now()%3dsysdate()%2csleep(15)%2c0))OR%22*/&paged=3 HTTP/1.1" 200 7011 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 17 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=(select(0)from(select(sleep(15)))v)/*'%2b(select(0)from(select(sleep(15)))v)%2b'%22%2b(select(0)from(select(sleep(15)))v)%2b%22*/&paged=3 HTTP/1.1" 404 4083 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 18 | 180.76.6.51 - - [14/Nov/2016:14:26:53 +0800] "GET /horde/util/barcode.php?type=../../../../../../../../../../../etc/passwd%00 HTTP/1.1" 404 201 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 19 | 180.76.6.51 - - [14/Nov/2016:14:26:53 +0800] "GET /util/barcode.php?type=../../../../../../../../../../../etc/passwd%00 HTTP/1.1" 404 197 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 20 | 180.76.6.51 - - [14/Nov/2016:14:27:26 +0800] "GET /sdk/../../../../../../../../../../../../../etc/passwd HTTP/1.1" 400 588 "-" "-" 21 | 180.76.6.51 - - [14/Nov/2016:14:27:28 +0800] "GET /?page=../../../../../../../../../etc/passwd%00.jpg HTTP/1.1" 200 7032 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 22 | 180.76.6.51 - - [14/Nov/2016:14:29:31 +0800] "GET /?cat=../../../../../../../../../../etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 23 | 180.76.6.51 - - [14/Nov/2016:14:29:31 +0800] "GET /?cat=%26cat%20/etc/passwd%26&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 24 | 180.76.6.51 - - [14/Nov/2016:14:29:33 +0800] "GET /?cat=../../../../../../../../../../etc/passwd%00.jpg&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 25 | 180.76.6.51 - - [14/Nov/2016:14:29:38 +0800] "GET /?cat=/../..//../..//../..//../..//../..//etc/passwd%00.jpg&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 26 | 180.76.6.51 - - [14/Nov/2016:14:29:39 +0800] "GET /?cat=.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./.%5c%5c./etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 27 | 180.76.6.51 - - [14/Nov/2016:14:29:43 +0800] "GET /?cat=/etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 28 | 180.76.6.51 - - [14/Nov/2016:14:29:46 +0800] "GET /?cat=../..//../..//../..//../..//../..//../..//../..//../..//etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 29 | 180.76.6.51 - - [14/Nov/2016:14:29:47 +0800] "GET /?cat=../.../.././../.../.././../.../.././../.../.././../.../.././../.../.././etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 30 | 180.76.6.51 - - [14/Nov/2016:14:29:48 +0800] "GET /?cat='%26cat%20/etc/passwd%26'&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 31 | 180.76.6.51 - - [14/Nov/2016:14:29:49 +0800] "GET /?cat=..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afetc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 32 | 180.76.6.51 - - [14/Nov/2016:14:29:50 +0800] "GET /?cat=%22%26cat%20/etc/passwd%26%22&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 33 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=invalid../../../../../../../../../../etc/passwd/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././.&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 34 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=%0acat%20/etc/passwd%0a&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 35 | 180.76.6.51 - - [14/Nov/2016:14:29:53 +0800] "GET /?cat=%60cat%20/etc/passwd%60&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 36 | 180.76.6.51 - - [14/Nov/2016:14:29:53 +0800] "GET /?cat=file:///etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 37 | 180.76.6.51 - - [14/Nov/2016:14:29:54 +0800] "GET /?cat=/%5c../%5c../%5c../%5c../%5c../%5c../%5c../etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 38 | 180.76.6.51 - - [14/Nov/2016:14:29:54 +0800] "GET /?cat=%7ccat%20/etc/passwd%23&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 39 | 180.76.6.51 - - [14/Nov/2016:14:30:01 +0800] "GET /?cat=;cat%20/etc/passwd;&paged=3 HTTP/1.1" 200 5149 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 40 | 180.76.6.51 - - [14/Nov/2016:14:26:49 +0800] "GET /inexistent_file_name.inexistent0123450987.cfm HTTP/1.1" 404 217 "-" "" 41 | 180.76.6.51 - - [14/Nov/2016:14:27:09 +0800] "GET /_layouts/scriptresx.ashx?culture=en-us&name=SP.JSGrid.Res&rev=laygpE0lqaosnkB4iqx6mA%3D%3D§ions=Allz HTTP/1.1" 404 204 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 42 | 180.76.6.51 - - [14/Nov/2016:14:27:14 +0800] "GET /tomcat-docs/appdev/sample/web/hello.jsp?test= HTTP/1.1" 404 213 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 43 | 180.76.6.51 - - [14/Nov/2016:14:27:28 +0800] "GET /?search= HTTP/1.1" 200 5327 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 44 | 180.76.6.51 - - [14/Nov/2016:14:27:29 +0800] "GET /?search=%3Cscript%3Ealert(1)%3C%2Fscript%3E HTTP/1.1" 200 5327 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 45 | 180.76.6.51 - - [14/Nov/2016:14:29:42 +0800] "GET /?cat=;print(md5(acunetix_wvs_security_test));&paged=3 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 46 | 180.76.6.51 - - [14/Nov/2016:14:29:43 +0800] "GET /?cat=';print(md5(acunetix_wvs_security_test));%24a%3d'&paged=3 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 47 | 180.76.6.51 - - [14/Nov/2016:14:29:44 +0800] "GET /?cat=%22;print(md5(acunetix_wvs_security_test));%24a%3d%22&paged=3 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 48 | 180.76.6.51 - - [14/Nov/2016:14:29:49 +0800] "GET /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d&paged=3 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 49 | 180.76.6.51 - - [14/Nov/2016:14:29:51 +0800] "GET /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d%5c&paged=3 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 50 | 180.76.6.51 - - [14/Nov/2016:14:29:52 +0800] "GET /?cat=;print(md5(acunetix_wvs_security_test));&paged=2 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 51 | 180.76.6.51 - - [14/Nov/2016:14:29:53 +0800] "GET /?cat=';print(md5(acunetix_wvs_security_test));%24a%3d'&paged=2 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 52 | 180.76.6.51 - - [14/Nov/2016:14:29:54 +0800] "GET /?cat=%22;print(md5(acunetix_wvs_security_test));%24a%3d%22&paged=2 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 53 | 180.76.6.51 - - [14/Nov/2016:14:29:59 +0800] "GET /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d&paged=2 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 54 | 180.76.6.51 - - [14/Nov/2016:14:29:59 +0800] "GET /?cat=%24%7b%40print(md5(acunetix_wvs_security_test))%7d%5c&paged=2 HTTP/1.1" 404 4083 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 55 | 180.76.6.51 - - [14/Nov/2016:14:29:53 +0800] "GET /?cat=file:///etc/passwd&paged=3 HTTP/1.1" 200 5149 "www.example.cn" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 56 | 180.76.6.51 - - [14/Nov/2016:14:26:49 +0800] "GET /inexistent_file_name.inexistent0123450987.cfm HTTP/1.1" 404 217 "-" "" 57 | 180.76.6.51 - - [14/Nov/2016:14:27:09 +0800] "GET /_layouts/scriptresx.ashx?culture=en-us&name=SP.JSGrid.Res&rev=laygpE0lqaosnkB4iqx6mA%3D%3D§ions=Allz HTTP/1.1" 404 204 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 58 | 180.76.6.51 - - [14/Nov/2016:14:27:14 +0800] "GET /tomcat-docs/appdev/sample/web/hello.jsp?test= HTTP/1.1" 404 213 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 59 | 180.76.6.51 - - [14/Nov/2016:14:27:28 +0800] "GET /?search= HTTP/1.1" 200 5327 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 60 | 106.39.200.46 - - [14/Nov/2016:10:38:44 +0800] "GET /wwwroot.rar HTTP/1.1" 404 194 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0" 61 | 180.76.6.51 - - [14/Nov/2016:14:27:00 +0800] "GET /jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system:type%3DServerInfo HTTP/1.1" 404 203 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 62 | 180.76.6.51 - - [14/Nov/2016:14:27:00 +0800] "GET /jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system:type%3DServer HTTP/1.1" 404 203 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 63 | 180.76.6.51 - - [14/Nov/2016:14:27:03 +0800] "GET /jmx-console/ HTTP/1.1" 404 195 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 64 | 180.76.6.51 - - [14/Nov/2016:14:27:03 +0800] "GET /jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.deployer:service%3DBSHDeployer HTTP/1.1" 404 203 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 65 | 180.76.6.51 - - [14/Nov/2016:14:27:16 +0800] "GET /phpmyadmin/main.php HTTP/1.1" 404 198 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 66 | 180.76.6.51 - - [14/Nov/2016:14:27:33 +0800] "GET /phpmyadmin2/main.php HTTP/1.1" 404 199 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 67 | 180.76.6.51 - - [14/Nov/2016:14:27:36 +0800] "GET /admin/phpmyadmin/main.php HTTP/1.1" 404 200 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36" 68 | 64.16.214.100 - - [14/Nov/2016:15:26:25 +0800] "GET /phpmyadmin/scripts/setup.php HTTP/1.0" 404 226 "-" "-" 69 | 106.39.200.46 - - [14/Nov/2016:11:49:34 +0800] "GET /cache/wwwroot.php HTTP/1.1" 404 197 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0" 70 | 106.39.200.46 - - [14/Nov/2016:11:49:38 +0800] "GET /cache/wwwroot.jsp HTTP/1.1" 404 197 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0" 71 | 59.42.147.17 - - [14/Nov/2016:13:07:21 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 72 | 59.42.147.17 - - [14/Nov/2016:13:07:21 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 73 | 59.42.147.17 - - [14/Nov/2016:13:07:22 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 74 | 59.42.147.17 - - [14/Nov/2016:13:07:22 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 75 | 103.248.223.116 - - [14/Nov/2016:14:08:35 +0800] "POST http://www.example.cn/include/ckeditor/plugins/pagebreak/images/inCahe.php HTTP/1.1" 404 250 "http://www.example.cn" "Mozilla/5.0" 76 | 103.248.223.116 - - [14/Nov/2016:14:09:07 +0800] "POST http://www.example.cn/images/swfupload/images/uploadye.php HTTP/1.1" 404 234 "http://www.example.cn" "Mozilla/5.0" 77 | 103.248.223.116 - - [14/Nov/2016:14:09:18 +0800] "POST http://www.example.cn/uploads/xm.php HTTP/1.1" 404 212 "http://www.example.cn" "Mozilla/5.0" 78 | 103.248.223.116 - - [14/Nov/2016:14:09:32 +0800] "POST http://www.example.cn/cache/wooyun.php HTTP/1.1" 404 214 "http://www.example.cn" "Mozilla/5.0" 79 | 103.248.223.116 - - [14/Nov/2016:14:09:42 +0800] "POST http://www.example.cn/include/ckeditor/plugins/pagebreak/images/inCahe.php HTTP/1.1" 404 250 "http://www.example.cn" "Mozilla/5.0" 80 | 103.248.223.116 - - [14/Nov/2016:14:09:50 +0800] "POST http://www.example.cn/data/s.php HTTP/1.1" 404 208 "http://www.example.cn" "Mozilla/5.0" 81 | 103.248.223.116 - - [14/Nov/2016:14:11:04 +0800] "POST http://www.example.cn/html/cache.php HTTP/1.1" 404 212 "http://www.example.cn" "Mozilla/5.0" 82 | 103.248.223.116 - - [14/Nov/2016:14:11:15 +0800] "POST http://www.example.cn/data/cache.php HTTP/1.1" 404 212 "http://www.example.cn" "Mozilla/5.0" 83 | 103.248.223.116 - - [14/Nov/2016:14:11:24 +0800] "POST http://www.example.cn/uploads/cache.php HTTP/1.1" 404 215 "http://www.example.cn" "Mozilla/5.0" 84 | 103.248.223.116 - - [14/Nov/2016:14:11:37 +0800] "POST http://www.example.cn/html/wen.php HTTP/1.1" 404 210 "http://www.example.cn" "Mozilla/5.0" 85 | 103.248.223.116 - - [14/Nov/2016:14:11:59 +0800] "POST http://www.example.cn/uploads/wen.php HTTP/1.1" 404 213 "http://www.example.cn" "Mozilla/5.0" 86 | 103.248.223.116 - - [14/Nov/2016:14:11:59 +0800] "POST http://www.example.cn/templets/wen.php HTTP/1.1" 404 214 "http://www.example.cn" "Mozilla/5.0" 87 | 103.248.223.116 - - [14/Nov/2016:14:12:02 +0800] "POST http://www.example.cn/data/wen.php HTTP/1.1" 499 0 "http://www.example.cn" "Mozilla/5.0" 88 | 103.248.223.116 - - [14/Nov/2016:14:12:05 +0800] "POST http://www.example.cn/html/page.php HTTP/1.1" 404 211 "http://www.example.cn" "Mozilla/5.0" 89 | 103.248.223.116 - - [14/Nov/2016:14:12:09 +0800] "POST http://www.example.cn/data/page.php HTTP/1.1" 404 211 "http://www.example.cn" "Mozilla/5.0" 90 | 103.248.223.116 - - [14/Nov/2016:14:12:10 +0800] "POST http://www.example.cn/uploads/page.php HTTP/1.1" 404 214 "http://www.example.cn" "Mozilla/5.0" 91 | 103.248.223.116 - - [14/Nov/2016:14:12:15 +0800] "POST http://www.example.cn/templets/page.php HTTP/1.1" 404 215 "http://www.example.cn" "Mozilla/5.0" 92 | 103.248.223.116 - - [14/Nov/2016:14:12:38 +0800] "POST http://www.example.cn/data/data/index.php HTTP/1.1" 404 217 "http://www.example.cn" "Mozilla/5.0" 93 | 107.151.213.123 - - [14/Nov/2016:16:00:49 +0800] "GET /wp-content/uploads/wooh.php HTTP/1.1" 404 225 "http://www.googlebot.com/bot.html" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" 94 | 115.148.98.127 - - [14/Nov/2016:17:24:53 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 95 | 115.148.98.127 - - [14/Nov/2016:17:24:54 +0800] "POST /data/s.php HTTP/1.1" 404 208 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 96 | 103.37.3.202 - - [14/Nov/2016:19:28:30 +0800] "POST /data/s.php HTTP/1.1" 404 233 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" 97 | 103.37.3.202 - - [14/Nov/2016:19:28:31 +0800] "POST /data/s.php HTTP/1.1" 404 233 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" 98 | -------------------------------------------------------------------------------- /example/fwban.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use App::Waf; 4 | 5 | # 设置日志文件和需要解析的文件大小,一般是web日志,$threshold为封禁的阈值 6 | # 可以根据实际情况调节大小 7 | 8 | my $filename = "/web/logs/access.log"; 9 | my $numlines = 10000; 10 | my $threshold = 200; 11 | 12 | =pod 13 | ## 结合nginx 和 iptables 进行实时banip的实例(example/banip.pl) 14 | 15 | ## 加入crontab 每5分钟执行一次。 16 | 17 | =code<`echo "*/5 * * * * perl $dir/banip.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root`> 18 | ## 以下设置nginx格式,包括nginx封禁的文件和重启nginx 19 | ## 需要的pid格式。 20 | 21 | =cut 22 | 23 | my $nginx_home = "/usr/local/nginx"; 24 | my $ngixBanfile = $nginx_home . '/conf/conf.d/blockip.conf'; 25 | my $ngixPidfile = $nginx_home . '/logs/nginx.pid'; 26 | 27 | my $line = tail( $filename, $numlines ); 28 | 29 | ( $log, $zcount, $zip, $zrequrl, $zstatus, $siteurl ) = initCount($line); 30 | 31 | for ( sort { $zip->{$b} <=> $zip->{$a} } keys %{$zip} ) { 32 | 33 | print "$_ : $zip->{$_} \n" if $zip->{$_} > $threshold; 34 | 35 | iptabBan( $_, $ngixBanfile, $ngixPidfile ) if $zip->{$_} > $threshold; 36 | 37 | } 38 | 39 | =pod 40 | sub iptabBan { 41 | 42 | # must be root user; 43 | # 必须root用户才可以操作iptables,当然也必须有iptables服务跑动着 44 | 45 | my $IP = shift; 46 | 47 | my $ips = `/sbin/iptables-save`; 48 | my @ipsline = split /\n/sm, $ips; 49 | my $dist = 0; 50 | for (@ipsline) { 51 | 52 | $dist = 1 if ( /$IP/ and /INPUT/ and /DROP/ ); 53 | 54 | } 55 | unless ($dist) { 56 | `/sbin/iptables -I INPUT -s $IP -j DROP`; 57 | my $btime = localtime( time() ); 58 | print "$btime :band $IP \n"; 59 | } 60 | else { 61 | 62 | print "band alread!\n"; 63 | 64 | } 65 | 66 | } 67 | =cut 68 | -------------------------------------------------------------------------------- /example/ngixban.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use App::Waf; 4 | 5 | # 设置日志文件和需要解析的文件大小,一般是web日志,$threshold为封禁的阈值 6 | # 可以根据实际情况调节大小 7 | 8 | my $filename = "/web/logs/access.log"; 9 | my $numlines = 10000; 10 | my $threshold = 200; 11 | 12 | =pod 13 | ## 结合nginx 和 iptables 进行实时banip的实例(example/banip.pl) 14 | 15 | ## 加入crontab 每5分钟执行一次。 16 | 17 | =code<`echo "*/5 * * * * perl $dir/banip.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root`> 18 | ## 以下设置nginx格式,包括nginx封禁的文件和重启nginx 19 | ## 需要的pid格式。 20 | 21 | =cut 22 | 23 | my $nginx_home = "/usr/local/nginx"; 24 | my $ngixBanfile = $nginx_home . '/conf/conf.d/blockip.conf'; 25 | my $ngixPidfile = $nginx_home . '/logs/nginx.pid'; 26 | 27 | my $line = tail( $filename, $numlines ); 28 | 29 | ( $log, $zcount, $zip, $zrequrl, $zstatus, $siteurl ) = initCount($line); 30 | 31 | for ( sort { $zip->{$b} <=> $zip->{$a} } keys %{$zip} ) { 32 | 33 | print "$_ : $zip->{$_} \n" if $zip->{$_} > $threshold; 34 | 35 | nginxBan( $_, $ngixBanfile, $ngixPidfile ) if $zip->{$_} > $threshold; 36 | 37 | 38 | } 39 | 40 | =pod 41 | sub nginxBan { 42 | 43 | my $btime = localtime( time() ); 44 | my ( $ip, $conf, $pid ) = @_; 45 | my $bid = 0; 46 | open my $nFD, "<", $conf or die("Can not open the file!$!\n"); 47 | while (<$nFD>) { 48 | print "DEBUG ::nginxBan :: $conf IN $_" if $DEBUG; 49 | $bid = 1 if /$ip/; 50 | } 51 | close $nFD; 52 | 53 | open my $nFD, ">>", $conf or die("Can not open 1 the file!$!\n"); 54 | 55 | unless ($bid) { 56 | print "$btime,banip $ip\n"; 57 | print $nFD "deny $ip\;\n"; 58 | $pid = `cat $pid`; 59 | chomp $pid; 60 | `/usr/bin/kill -HUP $pid`; 61 | } 62 | 63 | close $nFD; 64 | 65 | } 66 | =cut 67 | -------------------------------------------------------------------------------- /example/summary.pl: -------------------------------------------------------------------------------- 1 | use App::Waf; 2 | 3 | my $filename = "example.acess"; 4 | 5 | # change with you practice log pash,such as : 6 | #$filename = "/var/logs/httpd/access.log"; 7 | my $numlines = shift; 8 | 9 | my $line = tail( $filename, $numlines ); 10 | 11 | my ( $log, $zcount, $zip, $zrequrl, $zstatus, $siteurl ) = initCount($line); 12 | 13 | print "==============Attack Summary ==================\n"; 14 | print "\nThe total attack count: $zcount \n"; 15 | print "\nThe count from source IP: \n\n"; 16 | print "$_\=> $zip->{$_} \n" for ( sort keys %{$zip} ); 17 | print "The count From request Url: \n\n"; 18 | print "$_\=> $zrequrl->{$_} \n" for ( sort keys %{$zrequrl} ); 19 | print "\n\nThe count From Http Status: \n\n"; 20 | print "$_\=> $zstatus->{$_} \n" for ( sort keys %{$zstatus} ); 21 | print "\n\nThe count From Site Url: \n\n"; 22 | print "$_\=> $siteurl->{$_} \n" for ( sort keys %{$siteurl} ); 23 | 24 | #print $log; 25 | -------------------------------------------------------------------------------- /example/synban.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use App::Waf; 4 | 5 | # 设置日志文件和需要解析的文件大小,一般是web日志,$threshold为封禁的阈值 6 | # 可以根据实际情况调节大小 7 | 8 | =pod 9 | ## 结合nginx 和 iptables 进行实时banip的实例(example/banip.pl) 10 | 11 | ## 加入crontab 每5分钟执行一次。 12 | 13 | =code<`echo "*/5 * * * * perl $dir/banip.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root`> 14 | 15 | =cut 16 | 17 | my $cmd=q(/usr/sbin/ss -a|grep SYN-RECV|perl -lane 'print $F[-1]'|perl -pe 's/:.*$//'); 18 | my @sync_ps_count=`$cmd`; 19 | my %ipcount; 20 | my $threshold=8; 21 | my $btime=localtime time; 22 | for(@sync_ps_count){ 23 | 24 | chomp; 25 | $ipcount{$_}++; 26 | } 27 | 28 | for(sort {$ipcount{$b}<=>$ipcount{$a}} keys %ipcount) { 29 | 30 | print "$btime $_ SYN攻击次数: $ipcount{$_} \n"; 31 | 32 | # Count are more than shreshold, Then Ban it through iptables; 33 | 34 | if ($ipcount{$_} > $threshold) { 35 | 36 | print "$btime Ban The IP :$_ \n"; 37 | 38 | iptabBan($_); 39 | } 40 | 41 | } 42 | 43 | =pod 44 | sub iptabBan { 45 | 46 | # must be root user; 47 | # 必须root用户才可以操作iptables,当然也必须有iptables服务跑动着 48 | 49 | my $IP = shift; 50 | 51 | my $ips = `/sbin/iptables-save`; 52 | my @ipsline = split /\n/sm, $ips; 53 | my $dist = 0; 54 | for (@ipsline) { 55 | 56 | $dist = 1 if ( /$IP/ and /INPUT/ and /DROP/ ); 57 | 58 | } 59 | unless ($dist) { 60 | `/sbin/iptables -I INPUT -s $IP -j DROP`; 61 | my $btime = localtime( time() ); 62 | print "$btime :band $IP \n"; 63 | } 64 | else { 65 | 66 | print "band alread!\n"; 67 | 68 | } 69 | 70 | } 71 | =cut 72 | -------------------------------------------------------------------------------- /ignore.txt: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.old 3 | Build 4 | Build.bat 5 | META.* 6 | MYMETA.* 7 | .build/ 8 | .git/ 9 | _build/ 10 | cover_db/ 11 | blib/ 12 | inc/ 13 | .lwpcookies 14 | .last_cover_stats 15 | nytprof.out 16 | pod2htm*.tmp 17 | pm_to_blib 18 | App-Waf-* 19 | App-Waf-*.tar.gz 20 | -------------------------------------------------------------------------------- /lib/App/Waf.pm: -------------------------------------------------------------------------------- 1 | package App::Waf; 2 | 3 | use 5.006; 4 | use strict; 5 | use warnings; 6 | require Exporter; 7 | 8 | =encoding utf8 9 | =head1 NAME 10 | 11 | App::Waf - A sample Web Application Firewall, 12 | analysis the web logs for illegal attempt in real time。 13 | summary the source IP and other tpyes infomations ,using 14 | this infomations for ban whith iptables. 15 | 16 | 通过解析web访问日志,实时统计非法访问,结合防火期等进行 17 | 主动式防御。 18 | 19 | =head1 VERSION 20 | 21 | Version 0.08 22 | 23 | =cut 24 | 25 | our $VERSION = '0.08'; 26 | 27 | our @ISA = qw(Exporter); 28 | our @EXPORT = qw(tail initCount iptabBan nginxBan); 29 | 30 | =head1 SYNOPSIS 31 | =head2 实例 32 | 33 | use App::Waf; 34 | my $filename = "example.acess";#日志文件 35 | my $numlines = 50000; #要处理的行数,从后读。 36 | my $line=tail($filename,$$numlines); 37 | ($log,$zcount,$zip,$zrequrl,$zstatus,$siteurl)=initCount($line); 38 | print "==============Attack Summary ==================\n"; 39 | print "\nThe total attack count: $zcount \n"; 40 | print "\nThe count from source IP: \n\n"; 41 | print "$_\=> $zip->{$_} \n" for(sort keys %{$zip}); 42 | print "The count From request Url: \n\n"; 43 | print "$_\=> $zrequrl->{$_} \n" for(sort keys %{$zrequrl}); 44 | print "\n\nThe count From Http Status: \n\n"; 45 | print "$_\=> $zstatus->{$_} \n" for(sort keys %{$zstatus}); 46 | print "\n\nThe count From Site Url: \n\n"; 47 | print "$_\=> $siteurl->{$_} \n" for(sort keys %{$siteurl}); 48 | 49 | =head2 结合nginx 和 iptables 进行实时banip的实例(example/banip.pl) 50 | 51 | 加入crontab 每5分钟执行一次。 52 | 53 | echo "*/5 * * * * perl $dir/banip.pl >> bianip.logs 2>&1 " >> /var/spool/cron/root 54 | 55 | =head1 SUBROUTINES/METHODS 56 | 57 | =head2 tail() 58 | 59 | IN: $logfile,$count; 60 | 61 | OUT: return the the latest $count lines of the $logfile. 62 | 63 | =head2 initCount() 64 | 65 | IN: the content of need to cheack and count. 66 | 67 | OUT: all types count result. 68 | 69 | =cut 70 | 71 | use File::ReadBackwards; 72 | 73 | my $DEBUG = 0; 74 | 75 | my @validurl = ( 76 | 'rfd.php\?include_file', 77 | '\.\./', 78 | 'select.+(from|limit)', 79 | '(?:(union(.*?)select))', 80 | 'having|rongjitest', 81 | 'sleep\((\s*)(\d*)(\s*)\)', 82 | 'benchmark\((.*)\,(.*)\)', 83 | 'base64_decode\(', 84 | '(?:from\W+information_schema\W)', 85 | '(?:(?:current_)user|database|schema|connection_id)\s*\(', 86 | '(?:etc\/\W*passwd)', 87 | 'into(\s+)+(?:dump|out)file\s*', 88 | 'group\s+by.+\(', 89 | 'xwork.MethodAccessor', 90 | '(?: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|concat|alert|showmodaldialog)\(', 91 | 'xwork\.MethodAccessor', 92 | '(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/', 93 | 'java\.lang', 94 | '\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[', 95 | '\<(iframe|script|body|img|layer|div|meta|style|base|object|input)', 96 | '(onmouseover|onerror|onload)\=', 97 | '\.(bak|inc|old|mdb|sql|backup|java|class)$', 98 | '\.(svn|htaccess|bash_history)', 99 | '(vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar', 100 | '(phpmyadmin|jmx-console|jmxinvokerservlet)', 101 | '/xmlrpc.php', 102 | '/\.git/config', 103 | '/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\w+).(php|jsp|asp)', 104 | 105 | ); 106 | 107 | sub tail { 108 | 109 | my ( $filename, $linenum ) = @_; 110 | print "DEBUG :: tail() :: IN : $filename,$linenum \n" if $DEBUG; 111 | my $bw = File::ReadBackwards->new($filename) 112 | or die "can't read $filename $!"; 113 | $linenum=1000 unless $linenum; 114 | my $count = 0; 115 | my @lines; 116 | 117 | while ( defined( my $line = $bw->readline ) ) { 118 | push @lines, $line; 119 | $count++; 120 | if ( $count == $linenum ) { last } 121 | } 122 | 123 | @lines = reverse @lines; 124 | return \@lines; 125 | } 126 | 127 | sub initCount { 128 | 129 | my $line = shift; 130 | my @re = @validurl; 131 | my $kcount = shift; 132 | my ( $zcount, $zip, $zrequrl, $zstatus, $siteurl ); 133 | my $rawlog; 134 | 135 | for (@re) { 136 | my $result = scarlog1( $_, $line ); 137 | my ( $mycount, $mylog ) = count($result); 138 | my $key = $_; 139 | $rawlog .= $mylog->{$key} if $mylog->{$key}; 140 | 141 | $zcount += $mycount->{$key}->[0] if $mycount->{$key}->[0]; 142 | print 143 | "DEBUG\:: initCount()\::OUT $key $mycount->{$key}->[0] $zcount \n" 144 | if $DEBUG; 145 | $zip->{$_} += $mycount->{$key}->[1]->{$_} 146 | for ( keys %{ $mycount->{$key}->[1] } ); 147 | $zrequrl->{$_} += $mycount->{$key}->[2]->{$_} 148 | for ( keys %{ $mycount->{$key}->[2] } ); 149 | 150 | if ($DEBUG) { 151 | print 152 | "DEBUG\:: initCount()\::OUT $key $zrequrl->{$_} $_\=> $mycount->{$key}->[2]->{$_} \n" 153 | for ( keys %{ $mycount->{$key}->[2] } ); 154 | } 155 | $zstatus->{$_} += $mycount->{$key}->[3]->{$_} 156 | for ( keys %{ $mycount->{$key}->[3] } ); 157 | $siteurl->{$_} += $mycount->{$key}->[4]->{$_} 158 | for ( keys %{ $mycount->{$key}->[4] } ); 159 | 160 | } 161 | if ($DEBUG) { 162 | print "DEBUG\:: initCount()\::OUT\::\$zrequrl $_\=>$zrequrl->{$_}\n" 163 | for ( keys %{$zrequrl} ); 164 | } 165 | return ( $rawlog, $zcount, $zip, $zrequrl, $zstatus, $siteurl ); 166 | } 167 | 168 | sub count { 169 | 170 | my $result = shift; 171 | 172 | my ( $mcount, %rawlog ); 173 | my $count = 0; 174 | for ( keys %{$result} ) { 175 | my ( %ip, %requrl, %status, %siteurl ); 176 | 177 | next if $result->{$_} eq ""; 178 | $rawlog{$_} .= $result->{$_}; 179 | my @seclogs = split /\n/ms, $result->{$_}; 180 | for (@seclogs) { 181 | $count++; 182 | print "DEBUG\:: count()\::IN $_\n" if $DEBUG; 183 | my ( $ip, $requrl, $status, $siteurl ) = (split)[ 0, 6, 8, 10 ]; 184 | $ip{$ip}++ if $ip; 185 | $requrl{$requrl}++ if $requrl; 186 | $status{$status}++ if $status; 187 | $siteurl{$siteurl}++ if $siteurl; 188 | print 189 | "DEBUG\:: count()\::OUT $ip\=>$ip{$ip} $requrl\=>$requrl{$requrl} $status\=>$status{$status} $siteurl\=>$siteurl{$siteurl} \n" 190 | if $DEBUG; 191 | } 192 | 193 | $mcount->{$_} = [ $count, \%ip, \%requrl, \%status, \%siteurl ]; 194 | 195 | } 196 | 197 | return $mcount, \%rawlog; 198 | } 199 | 200 | sub scarlog1 { 201 | 202 | my ( $patter, $lines ) = @_; 203 | 204 | my %result; 205 | 206 | my $code = 'for(@{$lines}) {'; 207 | $code .= 'if (m#'; 208 | $code .= qr($patter); 209 | $code .= '#) {$result{' . q($patter) . '}.=$_}}'; 210 | eval $code; 211 | die "Error ---: $@\n Code:\n$code\n" if ($@); 212 | 213 | #print "DEBUG scarlog1 :: OUT :: $_: $result{$_}\n" for(keys %result); 214 | return \%result; 215 | } 216 | 217 | sub iptabBan { 218 | 219 | # must be root user; 220 | # 必须root用户才可以操作iptables,当然也必须有iptables服务跑动着 221 | 222 | my $IP = shift; 223 | 224 | my $ips = `/sbin/iptables-save`; 225 | my @ipsline = split /\n/sm, $ips; 226 | my $dist = 0; 227 | for (@ipsline) { 228 | 229 | $dist = 1 if ( /$IP/ and /INPUT/ and /DROP/ ); 230 | 231 | } 232 | unless ($dist) { 233 | `/sbin/iptables -I INPUT -s $IP -j DROP`; 234 | my $btime = localtime( time() ); 235 | print "$btime :band $IP \n"; 236 | } 237 | else { 238 | 239 | print "band alread!\n"; 240 | 241 | } 242 | 243 | } 244 | 245 | 246 | sub nginxBan { 247 | 248 | my $btime = localtime( time() ); 249 | my ( $ip, $conf, $pid ) = @_; 250 | my $bid = 0; 251 | open my $nFD, "<", $conf or die("Can not open the file!$!\n"); 252 | while (<$nFD>) { 253 | print "DEBUG ::nginxBan :: $conf IN $_" if $DEBUG; 254 | $bid = 1 if /$ip/; 255 | } 256 | close $nFD; 257 | 258 | 259 | unless ($bid) { 260 | print "$btime,banip $ip\n"; 261 | print $nFD "deny $ip\;\n"; 262 | $pid = `cat $pid`; 263 | chomp $pid; 264 | `/usr/bin/kill -HUP $pid`; 265 | } 266 | 267 | 268 | } 269 | 270 | =head1 AUTHOR 271 | 272 | ORANGE, C<< >> 273 | 274 | =head1 BUGS 275 | 276 | Please report any bugs or feature requests to C, or through 277 | the web interface at L. I will be notified, and then you'll 278 | automatically be notified of progress on your bug as I make changes. 279 | 280 | 281 | =head1 SUPPORT 282 | 283 | You can find documentation for this module with the perldoc command. 284 | 285 | perldoc App::Waf 286 | 287 | 288 | You can also look for information at: 289 | 290 | =over 4 291 | 292 | =item * RT: CPAN's request tracker (report bugs here) 293 | 294 | L 295 | 296 | =item * AnnoCPAN: Annotated CPAN documentation 297 | 298 | L 299 | 300 | =item * CPAN Ratings 301 | 302 | L 303 | 304 | =item * Search CPAN 305 | 306 | L 307 | 308 | =back 309 | 310 | 311 | =head1 ACKNOWLEDGEMENTS 312 | 313 | 314 | =head1 LICENSE AND COPYRIGHT 315 | 316 | Copyright 2016 ORANGE. 317 | 318 | This is free software; you can redistribute it and/or modify 319 | it under the same terms as the Perl 5 programming language system itself. 320 | 321 | =cut 322 | 323 | 1; # End of App::Waf 324 | -------------------------------------------------------------------------------- /t/00-load.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | plan tests => 1; 8 | 9 | BEGIN { 10 | use_ok( 'App::Waf' ) || print "Bail out!\n"; 11 | } 12 | 13 | diag( "Testing App::Waf $App::Waf::VERSION, Perl $], $^X" ); 14 | -------------------------------------------------------------------------------- /t/manifest.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Author tests not required for installation" ); 9 | } 10 | 11 | my $min_tcm = 0.9; 12 | eval "use Test::CheckManifest $min_tcm"; 13 | plan skip_all => "Test::CheckManifest $min_tcm required" if $@; 14 | 15 | ok_manifest(); 16 | -------------------------------------------------------------------------------- /t/pod-coverage.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Author tests not required for installation" ); 9 | } 10 | 11 | # Ensure a recent version of Test::Pod::Coverage 12 | my $min_tpc = 1.08; 13 | eval "use Test::Pod::Coverage $min_tpc"; 14 | plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" 15 | if $@; 16 | 17 | # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, 18 | # but older versions don't recognize some common documentation styles 19 | my $min_pc = 0.18; 20 | eval "use Pod::Coverage $min_pc"; 21 | plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" 22 | if $@; 23 | 24 | all_pod_coverage_ok(); 25 | -------------------------------------------------------------------------------- /t/pod.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Author tests not required for installation" ); 9 | } 10 | 11 | # Ensure a recent version of Test::Pod 12 | my $min_tp = 1.22; 13 | eval "use Test::Pod $min_tp"; 14 | plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; 15 | 16 | all_pod_files_ok(); 17 | -------------------------------------------------------------------------------- /xt/boilerplate.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | use 5.006; 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | plan tests => 3; 8 | 9 | sub not_in_file_ok { 10 | my ($filename, %regex) = @_; 11 | open( my $fh, '<', $filename ) 12 | or die "couldn't open $filename for reading: $!"; 13 | 14 | my %violated; 15 | 16 | while (my $line = <$fh>) { 17 | while (my ($desc, $regex) = each %regex) { 18 | if ($line =~ $regex) { 19 | push @{$violated{$desc}||=[]}, $.; 20 | } 21 | } 22 | } 23 | 24 | if (%violated) { 25 | fail("$filename contains boilerplate text"); 26 | diag "$_ appears on lines @{$violated{$_}}" for keys %violated; 27 | } else { 28 | pass("$filename contains no boilerplate text"); 29 | } 30 | } 31 | 32 | sub module_boilerplate_ok { 33 | my ($module) = @_; 34 | not_in_file_ok($module => 35 | 'the great new $MODULENAME' => qr/ - The great new /, 36 | 'boilerplate description' => qr/Quick summary of what the module/, 37 | 'stub function definition' => qr/function[12]/, 38 | ); 39 | } 40 | 41 | TODO: { 42 | local $TODO = "Need to replace the boilerplate text"; 43 | 44 | not_in_file_ok(README => 45 | "The README is used..." => qr/The README is used/, 46 | "'version information here'" => qr/to provide version information/, 47 | ); 48 | 49 | not_in_file_ok(Changes => 50 | "placeholder date/time" => qr(Date/time) 51 | ); 52 | 53 | module_boilerplate_ok('lib/App/Waf.pm'); 54 | 55 | 56 | } 57 | 58 | --------------------------------------------------------------------------------