Nginx 日志的重要性和必要性
比如下面这条 Nginx 站点日志:
[223.91.102.30] - - [14/Dec/2022:20:37:17 +0800] "GET /timthumb/aHR0cHM6Ly93d3cuaW15ZGwuY29tL3dwLWNvbn
RlbnQvdXBsb2Fkcy8yMDIyLzA0L1ItQy00LmpwZw/w/375/h/250/q/70/zc/1/a/c/spm/0780ccf9c8e93cee803e452c4b16c548.jpg HTTP/1.1" 200 21986 "https://www.imydl.com/linux/16348.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.46" Gzip=- BR=-
[223.91.102.30] - - [14/Dec/2022:20:37:18 +0800] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 92 "https://***.***.com/wp-admin/post.php?post=16xxx&action=edit" "Mozilla/5.0 (Win
dows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0" Gzip=- BR=1.25
上面这段日志记录的就是正在 WordPress 后台撰写的一条记录,可以看到是在 Firefox 浏览器里进行的,其他的文章 ID、 WordPress 后台链接都被记录在日志里了。
如何管理 Nginx 日志?
上面我们讲到了 Nginx 日志的重要性和必要性,也给大家通过示例演示了如何查看日志,接着我们再来讲讲如何更好的管理和运用 Nginx 日志。
说到 Nginx 日志管理,其实只需要保持 Nginx 默认日志配置就可以了,无论你是宝塔面板还是 LNMP 环境默认 Nginx 都是会开着日志记录的,以宝塔面板为例,每个网站的的配置文件结尾部分可以看到如下图所示的类似语句就是 Nginx 日志开启:
只要你不删除这段,理论上 Nginx 就会记录日志的,Nginx 提供了非常灵活的日志控制,甚至可以指定某些文件链接、目录链接等等的请求不记录日志,如上图中 access_log /dev/null;意思就是关闭记录日志,一般用在 CSS/JS 等文件类型上,毕竟这类文件被请求的频率是非常高的,都记录下来实际意义也不大。总之就是可以非常灵活的控制 Nginx 日志,甚至自定义一套属于自己专属的日志格式都是可以的(不建议新手这么做,标准化的好处还是很大的,除非你对日志非常熟悉和了解)。
Nginx 日志并不是开启后就可以放任不管了,前文明月提到过曾经碰到过一个客户就是放任不管 Nginx 日志造成日志文件体积几十个 G,占用了服务器大量的空间,这就是放任的后果,没点儿经验的还找不到空间被占用的原因!开启了 Nginx 日志功能后一定要记得给你的系统添加一个定时分割日志的定时任务,无论是宝塔还是 LNMP 都提供有这个功能的,如宝塔面板——计划任务的任务类型里的“日志切割”就是了,配置也是非常的简单,如下图所示:
Nginx日志安全分析脚本
功能
- 统计Top 20 地址
- SQL注入分析
- 扫描器告警分析
- 漏洞利用检测
- 敏感路径访问
- 文件包含攻击
- Webshell
- 寻找响应长度的url Top 20
- 寻找罕见的脚本文件访问
- 寻找302跳转的脚本文件
Usage
设置报告保存地址 outfile
设置日志分析目录 access_dir
设置日志名称 access_log
上代码:
#!/usr/bin/env bash echo "" echo " ========================================================= " echo " \ Nginx日志安全分析脚本 V1.0 / " echo " ========================================================= " echo " # 支持Nginx日志分析,攻击告警分析等 " echo " # author:smsec " echo -e "\n" #此脚本是参考nmgxy/klionsec修改而来,重新添加了一些特征,只用来临时救急,还是推荐到ELK或者Splunk中分析 #功能 ###统计Top 20 地址 ###SQL注入分析 ###SQL注入 FROM查询统计 ###扫描器/常用黑客工具 ###漏洞利用检测 ###敏感路径访问 ###文件包含攻击 ###HTTP Tunnel ###Webshell ###寻找响应长度的url Top 20 ###寻找罕见的脚本文件访问 ###寻找302跳转的脚本文件 #如果存在多个access文件或者有多个access.x.gz 建议先zcat access*.gz >> access.log文件中 #设置分析结果存储目录,结尾不能加/ outfile=/tmp/logs #如果目录以存在则清空,未存在则新建目录 if [ -d $outfile ]; then rm -rf $outfile/* else mkdir -p $outfile fi #设置nginx日志目录,结尾必须加/ access_dir=/var/log/nginx/ #设置文件名,如果文件名为access那么匹配的是access*文件 access_log=access #判断日志文件是否存在 num=$(ls ${access_dir}${access_log}* | wc -l) >/dev/null 2>&1 if [ $num -eq 0 ]; then echo '日志文件不存在' exit 1 fi echo -e "\n" # 验证操作系统是debian系还是centos OS='None' if [ -e "/etc/os-release" ]; then source /etc/os-release case ${ID} in "debian" | "ubuntu" | "devuan") OS='Debian' ;; "centos" | "rhel fedora" | "rhel") OS='Centos' ;; *) ;; esac fi if [ $OS = 'None' ]; then if command -v apt-get >/dev/null 2>&1; then OS='Debian' elif command -v yum >/dev/null 2>&1; then OS='Centos' else echo -e "\n不支持这个系统\n" echo -e "已退出" exit 1 fi fi # 检测ag软件有没有安装 if ag -V >/dev/null 2>&1; then echo -e "\e[00;32msilversearcher-ag已安装 \e[00m" else if [ $OS = 'Centos' ]; then yum -y install the_silver_searcher >/dev/null 2>&1 else apt-get -y install silversearcher-ag >/dev/null 2>&1 fi fi #如果检测别的日志请手动替换偏移,例如awk的$7代表url,$9代表状态码,$10代表长度,本脚本是以nginx日志为基础 echo "分析结果日志:${outfile}" echo "Nginx日志目录:${access_dir}" echo "Nginx文件名:${access_log}" echo -e "\n" echo -e "\e[00;31m[+]TOP 20 IP 地址\e[00m" ag -a -o --nofilename '((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}' ${access_dir}${access_log}* | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/top20.log echo -e "\n" echo -e "\e[00;31m[+]SQL注入攻击分析\e[00m" #在SQL注入中排除掉了一些扫描css/js/png图片类等无用告警,并且重点筛选状态码200或者500的告警 ag -a "xp_cmdshell|%20xor|%20and|%20AND|%20or|%20OR|select%20|%20and%201=1|%20and%201=2|%20from|%27exec|information_schema.tables|load_file|benchmark|substring|table_name|table_schema|%20where%20|%20union%20|%20UNION%20|concat\(|concat_ws\(|%20group%20|0x5f|0x7e|0x7c|0x27|%20limit|\bcurrent_user\b|%20LIMIT|version%28|version\(|database%28|database\(|user%28|user\(|%20extractvalue|%updatexml|rand\(0\)\*2|%20group%20by%20x|%20NULL%2C|sqlmap" ${access_dir}${access_log}* | ag -v '/\w+\.(?:js|css|html|jpg|jpeg|png|htm|swf)(?:\?| )' | awk '($9==200)||($9==500) {print $0}' >${outfile}/sql.log awk '{print "SQL注入攻击" NR"次"}' ${outfile}/sql.log | tail -n1 echo "SQL注入 TOP 20 IP地址" ag -o '(?<=:)((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}' ${outfile}/sql.log | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/sql_top20.log # 重点关注from查询,是否存在脱裤行为,排除扫描行为 echo "SQL注入 FROM 查询" cat ${outfile}/sql.log | ag '\bfrom\b' | ag -v 'information_schema' >${outfile}/sql_from_query.log awk '{print "SQL注入FROM查询" NR"次"}' ${outfile}/sql_from_query.log | tail -n1 echo -e "\n" echo -e "\e[00;31m[+]扫描器scan & 黑客工具\e[00m" ag -a "acunetix|by_wvs|nikto|netsparker|HP404|nsfocus|WebCruiser|owasp|nmap|nessus|HEAD /|AppScan|burpsuite|w3af|ZAP|openVAS|.+avij|.+angolin|360webscan|webscan|XSS@HERE|XSS%40HERE|NOSEC.JSky|wwwscan|wscan|antSword|WebVulnScan|WebInspect|ltx71|masscan|python-requests|Python-urllib|WinHttpRequest" ${access_dir}${access_log}* | ag -v '/\w+\.(?:js|css|jpg|jpeg|png|swf)(?:\?| )' | awk '($9==200)||($9==500) {print $0}' >${outfile}/scan.log awk '{print "共检测到扫描攻击" NR"次"}' ${outfile}/scan.log | tail -n1 echo "扫描工具流量 TOP 20" ag -o '(?<=:)\d+\.\d+\.\d+\.\d+' ${outfile}/scan.log | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/scan_top20.log echo -e "\n" echo -e "\e[00;31m[+]敏感路径访问\e[00m" ag -a "/_cat/|/_config/|include=|phpinfo|info\.php|/web-console|JMXInvokerServlet|/manager/html|axis2-admin|axis2-web|phpMyAdmin|phpmyadmin|/admin-console|/jmx-console|/console/|\.tar.gz|\.tar|\.tar.xz|\.xz|\.zip|\.rar|\.mdb|\.inc|\.sql|/\.config\b|\.bak|/.svn/|/\.git/|\.hg|\.DS_Store|\.htaccess|nginx\.conf|\.bash_history|/CVS/|\.bak|wwwroot|备份|/Web.config|/web.config|/1.txt|/test.txt" ${access_dir}${access_log}* | awk '($9==200)||($9==500) {print $0}' >${outfile}/dir.log awk '{print "共检测到针对敏感文件扫描" NR"次"}' ${outfile}/dir.log | tail -n1 echo "敏感文件访问流量 TOP 20" ag -o '(?<=:)\d+\.\d+\.\d+\.\d+' ${outfile}/dir.log | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/dir_top20.log echo -e "\n" echo -e "\e[00;31m[+]漏洞利用检测\e[00m" ag -a "%00|/win.ini|/my.ini|\.\./\.\./|/etc/shadow|%0D%0A|file:/|gopher:/|dict:/|WindowsPowerShell|/wls-wsat/|call_user_func_array|uddiexplorer|@DEFAULT_MEMBER_ACCESS|@java\.lang\.Runtime|OgnlContext|/bin/bash|cmd\.exe|wget\s|curl\s|s=/index/\think" ${access_dir}${access_log}* | awk '($9==200)||($9==500) {print $0}' >${outfile}/exploit.log awk '{print "漏洞利用探测" NR"次"}' ${outfile}/exploit.log | tail -n1 echo "漏洞利用检测 TOP 20" ag -o '(?<=:)\d+\.\d+\.\d+\.\d+' ${outfile}/exploit.log | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/exploit_top20.log echo -e "\n" echo -e "\e[00;31m[+]webshell\e[00m" ag -a "=whoami|dbname=|exec=|cmd=|\br57\b|\bc99\b|\bc100\b|\bb374k\b|adminer.php|eval\(|assert\(|%eval|%execute|tunnel\.[asp|php|jsp|aspx]{3,4}|makewebtaski|ma\.[asp|php|jsp|aspx]{3,4}|\bup\.[asp|php|jsp|aspx]{3,4}|cmd\.[asp|php|jsp|aspx]{3,4}|201\d\.[asp|php|jsp|aspx]{3,4}|xiaoma\.[asp|php|jsp|aspx]{3,4}|shell\.[asp|php|jsp|aspx]{3,4}|404\.[asp|php|jsp|aspx]{3,4}|tom\.[asp|php|jsp|aspx]{3,4}|k8cmd\.[asp|php|jsp|aspx]{3,4}|ver[0-9]{3,4}\.[asp|php|jsp|aspx]{3,4}|\.aar|[asp|php|jsp|aspx]{3,4}spy\.|o=vLogin|aioshell|admine|ghost\.[asp|php|jsp|aspx]{3,4}|r00ts|90sec|t00ls|editor\.aspx|wso\.[asp|aspx]{3,4}" ${access_dir}${access_log}* | awk '($9==200)||($9==500) {print $0}' >${outfile}/webshell.log awk '{print "共检测到webshell行为" NR "次"}' ${outfile}/webshell.log | tail -n1 echo "Webshell TOP 20" ag -o '(?<=:)\d+\.\d+\.\d+\.\d+' ${outfile}/webshell.log | sort | uniq -c | sort -nr | head -n 20 | tee -a ${outfile}/webshell_top20.log echo -e "\n" echo -e "\e[00;31m[+]HTTP Tunnel\e[00m" #Regeorg代理特征 ag -a "cmd=disconnect|cmd=read|cmd=forward|cmd=connect|127.0.0.1" ${access_dir}${access_log}* | awk '($9==200)||($9==500) {print $0}' | tee -a ${outfile}/tunnel.log awk '{print "共检测到隧道行为" NR "次"}' ${outfile}/tunnel.log | tail -n1 echo -e "\n" echo -e "\e[00;31m[+]Top 20 url响应长度\e[00m" # 查找url响应长度最长的url排序,目的是有没有下载服务器的一些打包文件 len=$(cat ${access_dir}${access_log}* | awk '{print $10}' | sort -nr | head -n 20) echo $len | awk 'BEGIN{ RS=" " }{ print $0 }' | xargs -i{} ag -a --nocolor '\d+\s{}\s' ${access_dir}${access_log}* | awk '{print $7,$10}' | sort | uniq | sort -k 2 -nr | tee -a ${outfile}/url_rsp_len.log echo -e "\n" echo -e "\e[00;31m[+]罕见的脚本文件访问\e[00m" echo "访问量特别特别少的脚本文件极有可能是webshell" cat ${access_dir}${access_log}* | awk '($9==200)||($9==500) {print $7}' | sort | uniq -c | sort -n | ag -v '\?' | ag '\.php|\.jsp|\.asp|\.aspx' | head -n 20 | tee -a ${outfile}/rare_url.log echo -e "\n" echo -e "\e[00;31m[+]302跳转\e[00m" echo "此目的是寻找一些登录成功的脚本文件" cat ${access_dir}${access_log}* | awk '($9==302)||($9==301) {print $7}' | sort | uniq -c | sort -n | ag -v '\?' | ag '\.php|\.jsp|\.asp|\.aspx' | head -n 20 | tee -a ${outfile}/302_goto.log echo -e "\n"
使用方法
./nginx_check.sh
欢迎关注“三沐数安”,请分享给更多的网安爱好者,大家一起研究网络安全技术。三沐专注于数据安全建设和网络安全建设,解决您身边的网络安全问题,成为您的安全好帮手。
原文始发于微信公众号(三沐数安):实用分享,Nginx日志安全分析脚本
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论