打造一款日志分析工具
一、简介
作为一名安全从业者,网络安全事件的应急响应工作是必不可少的,那么在应急支撑时,针对大量的日志数据便需要借助自动化工具实现快速的归类检测,并提取出所需的关键日志数据。本篇文章主要通过利用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(*) 的时候,需要把数据一行一行…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...