打造一款日志分析工具
一、简介
作为一名安全从业者,网络安全事件的应急响应工作是必不可少的,那么在应急支撑时,针对大量的日志数据便需要借助自动化工具实现快速的归类检测,并提取出所需的关键日志数据。本篇文章主要通过利用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(*) 的时候,需要把数据一行一行…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
