打造一款日志分析工具
一、简介
作为一名安全从业者,网络安全事件的应急响应工作是必不可少的,那么在应急支撑时,针对大量的日志数据便需要借助自动化工具实现快速的归类检测,并提取出所需的关键日志数据。本篇文章主要通过利用python语言编写一款web日志的分析工具。
代码地址:https://github.com/get0shell/ALogFry
工具运行效果:
python3 ALogFry.py

二、设计模式
该web日志分析工具的整个流程包括以下环节:

检测文件: 用来检测是否有日志文件,以及输出文件是否存在
数据提取: 用来提取日志数据中的IP、时间以及uri等关键数据
数据处理: 基于规则提取攻击日志,并对攻击日志中关键数据做合并统计
数据输出: 输出数据处理后的数据,并存储于输出文件
三、开发实战
3.1 检测文件
该模块功能主要作用为日志分析前的文件检测,该工具相关涉及两个文件夹,分别为logs和log。
log目录下主要存储检测输出的数据结果,工具运行后先会检测log目录是否存在,
1)如果存在则检测目录下是否存在文件,如果存在文件则为上一次检测生成的结果文件,进行删除
2)如果不存在该目录,则新建一个log目录
if os.path.exists('./log'):pathDir = os.listdir('./log/')for allDir in pathDir:p = os.path.join('./log/' + allDir)os.remove(p)
else:os.mkdir('./log')
logs目录必须存在,用来存放需要分析的日志文件,工具运行后会检测该目录下的文件,如果无文件则会提示
lpathDir = os.listdir('./logs')
if len(lpathDir) < 1:print("logs目录下无日志文件!!!")
else:pass
3.2 数据提取
检测文件完成后会对logs目录下的日志文件进行遍历提取,提取出每行日志后,利用split()方法对字符串进行分割,分割后以列表的形式进行存在,因为本次工具主要针对web日志中get请求的日志进行分析,以此IP为列表第0个成员,时间为列表第3和第4个成员组成,请求方法为第5个成员,而url为第6个成员。当然,如果日志中接入了post的数据体,可以针对所在的列表位数进行获取,本次工具中不再赘述。

具体代码如下:
for lallDir in lpathDir:h = os.path.join('./logs/' + lallDir)with open(h, 'rt', encoding='utf-8') as f:for i in f:# 对字符串进行分割,分割之后以列表形式存在n = i.split()ip = n[0]time = n[3] + n[4]method = n[5]uri = n[6]
3.3 数据处理
针对提取出的日志数据需要进行恶意攻击日志的检测,那么开始之前,需要提前准备好检测工具所具有的功能对应的规则语句。本次工具编写主要针对xss攻击、命令执行、SQL注入、敏感文件以及webshell连接进行检测,因此首先准备对应的正则匹配规则。具体详细规则根据需要可以细化。
xss = "script<alert|script.*alert|img.*src=|document.domain"
comm = "whoami|ifconfig|ipconfig|wget.*http|dir|curl.*ifs|wget.*ifs|uname|think.*invokefunction|echo|net%20user|net user|phpinfo"
sqlinj = "select.*count|select.*limit|select.*regexp|select.*master|group%20by|group by|union.*select|select.*xp_cmdshell|select.*from"
file = "web.xml|database.properties|config.xml|web_config.xml|known_hosts|htpasswd|DS_Store|boot.ini|win.ini|my.ini|etc/passwd|etc/shadow|httpd.conf|.sql|.svn|.bak"
webshell = "shell.jsp|ant.jsp|server.jsp|i.jsp|shell.php|ant.php|server.php|i.php|shell.asp|ant.asp|server.asp|i.asp"
同时再申明几个int类型变量,初始值为0,用来统计不同类型的攻击数量
x = c = s = e = w = 0
上述完成之后开始对攻击语句进行检测,利用正则re.search()方法实现,这块需要注意使用re.I,可以忽略大小写,将匹配到的日志继续存放在log下对应的txt文档中,同时每检测出一次x变量+1次
# XSS攻击检测
if re.search(xss, uri, re.I):with open('./log/xss.txt', 'at', encoding='utf-8') as f:f.writelines(i)x += 1
检测完成之后,如果申明的统计变量x大于0,则证明存在该攻击日志,则需要对该类攻击下的攻击IP进行处理
1)申明一个空列表,用来存放攻击IP
2)查询该类攻击日志的文档,提取其中的攻击IP并添加到列表
3)对攻击IP列表进行去重处理
if x > 0:ip_list = []print('存在xss攻击:' + str(x) + '次')with open('./log/xss.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)ip_new = list(set(ip_list))
3.4 数据输出
通过数据处理操作后,则对结果进行输出,那么上面数据处理代码中可以看到对于存在该类型攻击以及攻击次数会进行打印输入,同时对于统计去重后的攻击IP也会进行输出。完成之后将该类型攻击日志进行遍历打印输出,方便直接查看。
print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/xss.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:# 利用splitlines()去除换行符print(i.splitlines())
除了打印出输出的数据以外,每种攻击类型的详细日志数据也可以直接在txt文档中查看。
3.5 工具实现
通过上述四个模块的编写,基于python实现的web日志分析工具便完成了,当然以上整体实现只是通过xss攻击检测进行演示,其他类型攻击检测效果同理。具体代码如下:
# @Author : alan
# @File : ALogFry.pyimport re
import osxss = "script<alert|script%3Ealert|img src=|img%20src=|document.domain"
comm = "whoami|ifconfig|ipconfig|wget.*http|dir|curl.*ifs|wget.*ifs|uname|think.*invokefunction|echo|net%20user|net user|phpinfo"
sqlinj = "select.*count|select.*limit|select.*regexp|select.*master|group%20by|group by|union.*select|select.*xp_cmdshell|select.*from"
file = "web.xml|database.properties|config.xml|web_config.xml|known_hosts|htpasswd|DS_Store|boot.ini|win.ini|my.ini|etc/passwd|etc/shadow|httpd.conf|.sql|.svn|.bak"
webshell = "shell.jsp|ant.jsp|server.jsp|i.jsp|shell.php|ant.php|server.php|i.php|shell.asp|ant.asp|server.asp|i.asp"
x = c = s = e = w = 0
if os.path.exists('./log'):pathDir = os.listdir('./log/')for allDir in pathDir:p = os.path.join('./log/' + allDir)os.remove(p)
else:os.mkdir('./log')pathDir = os.listdir('./log/')for allDir in pathDir:p = os.path.join('./log/' + allDir)os.remove(p)
lpathDir = os.listdir('./logs')
if len(lpathDir) < 1:print("logs目录下无日志文件!!!")
else:for lallDir in lpathDir:h = os.path.join('./logs/' + lallDir)with open(h, 'rt', encoding='utf-8') as f:for i in f:# 对字符串进行分割,分割之后以列表形式存在n = i.split()ip = n[0]time = n[3] + n[4]method = n[5]uri = n[6]# XSS攻击检测if re.search(xss, uri, re.I):with open('./log/xss.txt', 'at', encoding='utf-8') as f:f.writelines(i)x += 1# 命令执行攻击检测if re.search(comm, uri, re.I):with open('./log/comm.txt', 'at', encoding='utf-8') as f:f.writelines(i)c += 1# sql注入攻击检测if re.search(sqlinj, uri, re.I):with open('./log/sqlinj.txt', 'at', encoding='utf-8') as f:f.writelines(i)s += 1# 敏感文件攻击检测if re.search(file, uri, re.I):with open('./log/file.txt', 'at', encoding='utf-8') as f:f.writelines(i)e += 1# webshell连接攻击检测if re.search(webshell, uri, re.I):with open('./log/webs.txt', 'at', encoding='utf-8') as f:f.writelines(i)w += 1if x > 0:ip_list = []print('存在xss攻击:' + str(x) + '次')with open('./log/xss.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)# print(ip_list)ip_new = list(set(ip_list))print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/xss.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:# 利用splitlines()去除换行符print(i.splitlines())# os.remove(r'../plug/logs/log/xss.txt')if c > 0:ip_list = []print('存在命令执行攻击:' + str(c) + '次')with open('./log/comm.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)# print(ip_list)ip_new = list(set(ip_list))print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/comm.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:print(i.splitlines())if s > 0:ip_list = []print('存在sql注入攻击:' + str(s) + '次')with open('./log/sqlinj.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)ip_new = list(set(ip_list))print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/sqlinj.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:print(i.splitlines())if e > 0:ip_list = []print('存在敏感文件攻击:' + str(e) + '次')with open('./log/file.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)ip_new = list(set(ip_list))print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/file.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:print(i.splitlines())if w > 0:ip_list = []print('存在webshell连接攻击:' + str(w) + '次')with open('./log/webs.txt', 'rt', encoding='utf-8') as f:for i in f:n = i.split()ip = n[0]ip_list.append(ip)ip_new = list(set(ip_list))print("攻击ip:")for i in range(len(ip_new)):print(ip_new[i])with open('./log/webs.txt', 'rt', encoding='utf-8') as f:print("详细攻击日志:")for i in f:print(i.splitlines())
四、结语
以上便是一个基于python实现的web日志分析工具的逻辑和代码,当然代码还是可以优化的,本次编写为了方便使用全都写到一个py脚本中了。具体检测规则可以根据个人需要进行新增和优化完善,也希望能够在应急分析中有作用,后续代码会慢慢优化更新。
‘rt’, encoding=‘utf-8’) as f:
print(“详细攻击日志:”)
for i in f:
print(i.splitlines())
最后
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,有需要的小伙伴,可以【扫下方二维码】免费领取:

相关文章:
打造一款日志分析工具
一、简介 作为一名安全从业者,网络安全事件的应急响应工作是必不可少的,那么在应急支撑时,针对大量的日志数据便需要借助自动化工具实现快速的归类检测,并提取出所需的关键日志数据。本篇文章主要通过利用python语言编写一款web日…...
网络编程基础知识
套接字类型:1.字节流套接字(stream) 2.数据报接套接字(datagram) 3.原始套接字(raw) 端口:1.周知端口: 0~1023 2.注册端口: 1024~49151 3.动态端口: 49152~65535 OSI七层协议结构应用层表示层会话层...
2023北京老博会(CBIAIE全国老年产业必参盛会)
CBIAIE北京老博会|把握政策导向,迎合市场需求,引导销售渠道建设,搭建国际化的商业平台; 2023第十届中国(北京)国际老年产业博览会(CBIAIE北京老博会) The 2023 tenth China (Beijin…...
【字典转模型 Objective-C语言】
一、点按钮,弹出的这个效果,这实际上是个Label, 这实际上是一个Label,点按钮弹出的这个效果, 设置一个Label的背景色、前景色、透明度、等等, 让它加进来,然后通过动画让它隐藏掉, 这就是,这个效果的实现思路, 咱们这个效果,先稍微往后放一放, 这个并不是重点…...
【LeetCode】剑指 Offer(6)
目录 写在前面: 题目:剑指 Offer 12. 矩阵中的路径 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 写在前面ÿ…...
论文投稿指南——中文核心期刊推荐(法律)
【前言】 🚀 想发论文怎么办?手把手教你论文如何投稿!那么,首先要搞懂投稿目标——论文期刊 🎄 在期刊论文的分布中,存在一种普遍现象:即对于某一特定的学科或专业来说,少数期刊所含…...
Qt音视频开发15-动态切换解码内核的设计
一、前言 动态切换解码内核这个需求也是源自客户的真实需求,既然是动态切换,那肯定是运行期间切换,而不是通过改变标志位重新编译程序来切换,最开始做的就是这种方式,这样就是实现起来简单,但是用起来不够…...
concurrent-map 和 sync.Map,我该选择哪个?
官方的map并不是线程安全的,如果我们在多线程中并发对一个map进行读写操作,是会引发panic的。解决方案除了使用锁来对map进行保护外,还有两种方式:一,开源项目 concurrent-map 提供了可以用来做并发安全的map二&#x…...
华为OD机试 - 最少数量线段覆盖| 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...
【蓝桥集训】第五天——递推
作者:指针不指南吗 专栏:Acwing 蓝桥集训每日一题 🐾或许会很慢,但是不可以停下来🐾 文章目录1.砖块递推算法是一种简单的算法,通过已知条件,利用特定关系得出中间推论,逐步递推&…...
qnx的网络知识记录
1、网络驱动加载http://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.core_networking/topic/drivers_Loading.html使用mount挂载io-pkt模块mount -Tio-pkt /lib/dll/devnp-e1000.sonicinfo 命令可以查看网卡的各种状态,包括phy的状态2、iopktiopkt的介…...
【Vue/基础知识】Vue基础知识(一)
如果觉得我的分享有一定帮助,欢迎关注我的微信公众号 “码农的科研笔记”,了解更多我的算法和代码学习总结记录。或者点击链接扫码关注 【Vue/基础知识】Vue基础知识(一) 1、v-show 和 v-if 指令的共同点和不同点? 共…...
Iceberg实战踩坑指南
第 1 章 介绍 Apache Iceberg 是一种用于大型分析数据集的开放表格,Iceberge 向 Trino 和 Spark 添加了使用高性能格式的表,就像 Sql 表一样。 Iceberg 为了避免出现不变要的一些意外,表结构和组织并不会实际删除,用户也不需要特…...
预告|2月25日 第四届OpenI/O 启智开发者大会昇腾人工智能应用专场邀您共启数字未来!
如今,人工智能早已脱离科幻小说中的虚构想象,成为可触及的现实,并渗透到我们的生活。随着人工智能的发展,我们正在迎来一个全新的时代——数智化时代。数据、信息和知识是这个时代的核心资源,而人工智能则是这些资源的…...
UnRaid虚拟机安装OpenWrt软路由
文章目录0、前言1、Openwrt虚拟机安装1.1、前提,需要先在UnRaid中开启虚拟机:1.2、下载OpenWrt虚拟机镜像并上传至UnRaid共享文件夹1.3、创建OpenWrt虚拟机2、开启并设置OpenWrt虚拟机2.1、修改OpenWrt管理ip2.2、OpenWrt的上网设置0、前言 最近折腾了很…...
开发日记-lombok
开发日记-lombok环境问题解决方案:1 Data注解失效 无法正常生成 get和set方法2 RequiredArgsConstructor(onConstructor _(Lazy)) 符号_无法识别环境 idea2020.1lombok1.18.24jdk1.8 问题 Data注解失效 无法正常生成 get和set方法RequiredArgsConstructor(onCons…...
Web3中文|2023年zk赛道爆发,即将推出的Polygon zkEVM有多重要?
2月15日,以太坊第2层解决方案提供商Polygon终于公布了备受期待的扩展更新,其零知识以太坊虚拟机(zkEVM)主网的测试版定于3月27日发布。 据官方消息报道,自去年10月上线测试网以来,已取得许多重要的里程碑&…...
【自然语言处理】主题建模:Top2Vec(理论篇)
主题建模:Top2Vec(理论篇)Top2Vec 是一种用于 主题建模 和 语义搜索 的算法。它自动检测文本中出现的主题,并生成联合嵌入的主题、文档和词向量。 算法基于的假设:许多语义相似的文档都可以由一个潜在的主题表示。首先…...
【ICLR 2022】重新思考点云中的网络设计和局部几何:一个简单的残差MLP框架
文章目录RETHINKING NETWORK DESIGN AND LOCAL GEOMETRY IN POINT CLOUD: A SIMPLE RESIDUAL MLP FRAMEWORKPointMLP残差点模块几何仿射模块精简版模型:PointMLP-elite实验结果消融实验RETHINKING NETWORK DESIGN AND LOCAL GEOMETRY IN POINT CLOUD: A SIMPLE RESI…...
《MySQL学习》 count(*) 原理
一 . count(*)的实现方式 MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count() 的时候会直接返回这个数,效率很高; 而 InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
