OWASP TOP10 漏洞详解

前言

        该内容是 OWASP TOP 10 的学习笔记,笔记内容来源 B 站龙哥的视频【12.Top漏洞10:服务器请求伪造_哔哩哔哩_bilibili】

一、访问控制崩溃

概念

        未对通过身份验证的用户实施恰当的访问控制。攻击者可以利用这些缺陷访问未经授权的功能或数据,例如:访问其他用户的账户、查看敏感文件、修改其他用户的数据、更改访问权限等。

从表现形式来看,访问控制崩溃也就是我们常说的越权漏洞

越权分为两种

        ①、水平越权:A,B 两个用户权限是相同的,但是 A 可以访问 B 的信息。

        ②、垂直越权(向上垂直):A 是普通用户,B 管理员用户,A 可以执行 B 的权限。 

简单的方法描述

  • 通过修改 URL、内部应用程序状态或 HTML 页面绕过访问控制检查,或简单地使用自定义的 API 攻击工具。
  • 允许将主键更改为其他用户的记录,例如查看或编辑他人的账户。
  • 特权提升。在不登录的情况下假扮用户,或以用户身份登录时充当管理员。
  • 以未通过身份验证的用户身份强制浏览的通过身份验证时才能看到得页面、或作为标准用户访问具有相关权限的页面、或 API 没有对 POST、PUT 和 DELETE 强制执行访问控制。

【注: POST、PUT、DELETE 等操作是相当危险的,用户在使用的时候一定要进行身份验证】

防范

        访问控制只有在受信服务器端代码或没有服务器的 API 中有效,这样攻击者才无法修改访问控制检查或元数据。

①、除公有资源外、默认情况下拒绝访问(最小权限原则)

②、严格判断权限,用户只能操作属于自己的内容。

③、记录失败的访问控制,并在适当时向管理员告警(如:重复故障)。

④、对 API 和控制器的访问进行速率限制,以最大限度地降低自动化攻击工具的危害。

⑤、当用户注销后,服务器上的 JWT ( JSON Web Token)令牌应该失效。

二、敏感数据泄露

概念

        很多 Web 应用程序和 API 都无法正确保护敏感数据,例如:财务数据、医疗数据和 PII 数据(个人身份信息)。攻击者可以很容易的获取到,并造成破坏,因此,我们需要对敏感数据加密,这些数据包括传输过程中的数据、存储的数据。通过窃取或修改未加密的数据来实施信用卡诈骗、身份盗窃或其他犯罪行为。

存在的原因

①、数字系统越来越多,用户个人信息收集后存储分散,业务使用中管理不规范

②、随着企事业单位规模的扩大,员工数量逐步增加,信息安全意识参差不齐,可能存在违规使用、随意下载用户个人信息的行为

防范

①、加强员工意识,禁止上传代码到 github 等网站。

②、谨慎使用第三方云服务,不要把工作相关的存放到云端。

③、禁止使用工作邮箱注册非工作相关网站。

三、SQL 注入

概念

        注入是指 web 应用对用户输入数据的合法性没有判断或过滤不严,攻击者可以在 web 应用程序中事先定义好的查询语句的结尾添加额外的执行语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

SQL注入

        所谓 SQL 注入,就是通过把 SQL 命令插入到 web 表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意 SQL 命令目的的入侵行为。

        也就是说,服务器要用户提交一个数据,可是攻击者要么直接提交一个命令,要么提交一个数据后,还在数据后面加上一个命令。

正常的流程是这样

如果这里对 id 参数的内容过滤不严格的话,可能会被攻击者利用,造成 SQL 注入

SQL 注入的原因

        SQL 命令可以进行查询、插入、删除等操作,直接将这些命令拼接起来。所以你提交这些命令后,就可以间接操作数据库了。

详细学习数据库:【SQL 注入总结(详细)_sql注入语句and1=1 '1=1-CSDN博客】

SQL 注入的分类

①、基于数据类型的分类

        a、字符串类型注入

        b、整形注入

②、基于程度和顺序的注入

        a、一阶注射

        b、二阶注射

③、基于从服务器接收到的响应

④、基于错误的 SQL 注入

⑤、联合查询的类型

⑥、堆查询注入

⑦、SQL 盲注

        a、基于布尔 SQL 盲注

        b、基于时间的 SQL 盲注

        c、基于报错的 SQL 盲注

SQL 注入的产生点

  • 通过用户输入的表单域的注入。例如:post 里面的参数
  • 通过 cookie 注入
  • 通过服务器变量注射(HTTP 头部)

【所有能与用户进行交互的地方都可能存在注入】

SQL 注入的常见检测字符

  • '        (单引号)
  • "       (双引号)
  • --+    (注释)
  • #       (注释)
  • and   (与)
  • or      (或)
  • xor    (非)

SQL 注入的思路

        1、判断是否存在注入,注入是字符类型还是数字类型

        2、猜解 SQL 查询语句中的字段数

        3、确定显示的字段顺序

        4、获取当前数据库

        5、获取数据库中的表

盲注测试的思路

        1、判断是否存在注入,注入是字符型还是数字型

        2、猜解 SQL 查询语句中的字段数

        3、猜解当前数据库名

        4、猜解当前数据库中的表名

        5、猜解表中的字段名

        6、猜解数据

防范

        1、关闭 SQL 错误回显

        2、使用成熟的 waf

        3、前端输入字符白名单验证(长度、类型等)

        4、SQL 服务运行于专门的账号,并且使用最小权限

        5、对输入的特殊字符使用转义处理

四、不安全的设计

漏洞产生原因

        在开发软件时,在关键身份验证、访问控制、业务逻辑和关键流部位没有进行安全的设计。

漏洞利用

        业务逻辑的显性体现:

        1、支付逻辑

        2、密码找回

        3、验证码暴力破解

        4、验证码客户端回显

        5、验证码重复使用

        6、验证码绕过

        7、验证码自动识别

支付逻辑漏洞

        所有涉及购买、支付等方面的功能处就有可能存在支付漏洞

挖掘

        寻找网站的支付系统、或兑换系统,抓包判断有没有敏感信息可以修改

利用

        1、修改支付价格                                6、多重替换支付

        2、修改支付状态                                7、重复支付

        3、修改购买数量                                8、最小额支付

        4、修改优惠券、积分                         9、最大额支付问题

        5、修改支付接口                                10、无限制试用

案例

        这里通过修改 state 的值,可以修改密码,在本来需要原密码的基础上,修改 state 值为 1,系统默认认为随意输入的密码为真,导致存在任意密码重置的逻辑漏洞。

五、安全配置不当

        安全配置错误是最常见的安全问题,这通常是由于不安全的默认配置、不完整的临时配置、开源云存储、错误的 HTTP 标头配置以及包含敏感信息的详细错误信息所造成的。因此,我们不仅需要对所有的操作系统、框架、库和应用程序进行安全配置,而且必须及时修补和升级它们。

可能出现的风险点

  • 应用程序启用或者安装了不必要的安全功能
  • 默认账户名和密码没有修改
  • 应用软件已过期或出了新版本未更新
  • 应用程序服务器,应用程序框架等未进行安全配置
  • 错误处理机制被披露大量敏感信息
  • 对于更新的系统,禁用或不安全地配置安全功能

案例一

        Tomcat 服务器是一个免费的开放源代码的 web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。

案例二

        Apache ActiveMQ 是 Apache 软件基金会所研发的开放源代码消息中间件;由于 ActiveMQ 是一个纯 Java 程序,因此只需要操作系统支持 Java 虚拟机,ActiveMQ 便可执行。ActiveMQ 是一个完全支持 JMS 1.1 和 J2EE 1.4 规范的 JMSProvider 实现,尽管 JMS 规范出台已经是很久的事情了,但是 JMS 在当今的 J2EE 应用中间仍然扮演者特殊的地位。

该中间件存在的漏洞

1、ActiveMQ 物理路径泄露漏洞

2、ActiveMQ PUT 任意文件上传漏洞

3、ActiveMQ 反序列化漏洞(CVE-2015-5254)

4、ActiveMQ 信息泄露漏洞(CVE-2017-15709)

防范

  • 按照加固手册加固。(密码策略等)
  • 搭建最小化平台,该平台不包含任何不必要的功能、组件、文档和示例。移除或不安装不适用的功能和框架。
  • 临时文件要及时删除

安全配置不当漏洞可以和其他漏洞进行组合

        这里安全配置不当,已经将 2017 年的安全配置不当与 XML 外部实体(XXE)漏洞两种漏洞类型进行了组合。下面就来看一下我们的 XXE 漏洞的原理及如何防范。

XXE 概念

        当应用程序解析 XML 文件时包含了对外部实体的引用,攻击者传递恶意包含 XML 代码的文件,读取指定的服务器资源。

        在上面的代码中,XML 外部实体 ‘XXE’ 被赋予的值为:file://etc/passwd。在解析 XML 文档的过程中,关键字 SYSTEM 会告诉 XML 解析器,xxe 实体的值将从其后的 URL 中读取,并把读取的内容替换 entityex 出现的地方,所以 xxe 的值会被替换为 URL(file://etc/passwd)内容值(也就是 passwd 文件的内容)。

        假如 SYSTEM 后面的内容可以被用户控制,那么用户就可以随意替换为其他内容,从而读取服务器本地文件(file://etc/psswd)或者远程文件(http://www.baidu.com/abc.txt),想读什么文件就读什么文件。

防范

  • 尽可能使用简单的数据结构(如:JSON),避免对敏感数据进行序列化
  • 及时修复或更新应用程序或底层操作系统使用的所有 XML 处理器和库。同时,通过依赖项检测,将 SOAP 更新到 1.2 版本或更高版本
  • 在服务器端实施积极的(“白名单”)输入验证、过滤和清除,以防止在 XML 文档、标题或节点中出现恶意数据
  • 验证 XML XSL 文件(XSD文件规范了XML文件需要遵循的格式)上传功能是否使用 XSD 验证(用来验证 xml 文件格式是否正确)或者其他类似验证方法来验证上传的 XML 文件。
  • 尽管在许多集成环境中,手动代码审查是大型、复杂应用程序的最佳选择,但是 SAST 工具可以检测源代码中的 XXE 漏洞。如果无法实现这些控制,请考虑使用虚拟修复程序、API 安全网关或 WEB 应用程序防火墙(WAF)来检测、监控和防止 XXE 攻击。

六、安全配置不当

概念

        通常,通过错误使用应用程序的身份认证和会话管理功能,攻击者能够破译密码、密钥或会话令牌,或者利用其他开发缺陷来暂时性或永久性冒充其他用户的身份。

        在开发 web 应用程序时,开发人员往往只关注 web 应用程序所需的功能,所以常常会建立自定义的认证和会话方案。但是要正确实现这些方案却是很难的。结果就在退出、密码管理、超时、密码找回、账户更新等方面存在漏洞。

可能出现的风险点

  • 允许暴力破解密码或账号
  • 允许默认的、弱的或众所周知的密码,例如 “admin/123456” 或 “admin/admin”。
  • 使用明文、加密或弱散列密码。
  • 缺少或失效的多因素身份验证。
  • 暴露 URL 中的会话 ID (例如 URL 重写)。
  • 旧密码泄露
  • 会话 ID 使用时间过长

防范

  • 在可能的情况下,实现多因素身份验证,以防止自动、凭证填充、暴力破解和被盗凭据再利用攻击。
  • 检查弱口令,模拟爆破操作
  • 限制或逐渐延迟失败的登录尝试。记录所有失败信息并在凭据填充、暴力破解或其他攻击检测时提醒管理员。
  • 使用服务器端安全的内置会话管理器,在登录后生成高度复杂的新随机会话 ID。会话 ID 不能在 URL 中,可以安全地存储和当登出、闲置、绝对超时后使其失效。

七、使用含有已知漏洞组件

概念

        组件(例如:库、框架和其他软件模式)拥有和应用程序相同的权限。如果应用程序中含有已知漏洞的组件被攻击者利用,可能会造成严重的数据丢失或服务器接管。同时,使用含有已知漏洞的组件的应用程序和 API 可能会破坏应用程序防御、造成各种攻击并产生严重影响。

场景

  • 软件易受攻击,不再支持或者过时。这包括 :OS、Web 服务器、应用程序服务器、数据库管理系统(DBMS)、应用程序、API 和所有的组件、运行环境和库。
  • 没有对更新的、升级的或打过补丁的组件进行兼容性测试。

防范

  • 移除不使用的依赖、不需要的功能、组件、文件和文档。
  • 仅从官方渠道安全的获取组件,并使用签名机制来降低组件被篡改或加入恶意漏洞的风险。
  • 持续监控 CVE 和 NVD 等是否发布已使用组件的漏洞信息(可以使用软件分析工具来自动完成此功能)

八、软件和数据完整性失效

概念

        软件和数据完整性故障与不能防止完整性违规的代码和基础设施有关。一个例子是应用程序依赖来自不受信任的来源、存储库和内容交付网络(CDN)的差距、库或模块。不安全的 CI/CD 管道可能会导致未授权访问、恶意代码或系统受损。最后,许多应用程序现在包括自动更新功能,其中更新在没有充分完整性验证的情况下被下载并应用于以前受信任的应用程序。攻击者可能会上传自己的恶意程序并在受害者主机上运行。另一个例子是对象或数据被编码或序列化为攻击者可以看到和修改的结构,容易受到不安全的反序列化。

防范

        1、使用数字签名或类似机制来验证软件或数据来自预期来源且未被更改(软件在网上会有哈希值,我们可以把下载下来的软件去计算它的哈希值,如何计算出来的值和官方给的一样,那就证明下载下来的软件没问题)

        2、确保使用安全工具验证组件不包含已知漏洞

        3、确保未签名或未加密的序列化数据不会在没有检查或数字签名的情况下发送到不受信任的客户端

九、不足的日志记录和监控

概念

        不足的日志记录和监控,以及事件响应缺失或无效的集成,使攻击者能够进一步攻击系统、保持持续性或转向更多系统,以及篡改、提取或销毁数据。

        大多数缺陷研究显示,缺陷被检测出的时间超过 200 天,且通常通过外部检测方检测,而不是通过内部流程或监控检测。

场景

  • 未记录可审计性事件,如:登录、登录失败和高额交易。
  • 告警和错误事件未能产生或产生不足的和不清晰的日志信息。
  • 日志信息仅在本地存储
  • 没有利用相应系统和 API 的日志信息来监控可疑活动。
  • 对于实时或准实时的攻击,应用程序无法检测、处理和告警。

案例

如何改进

  • 确保所有登录、访问控制失败、输入验证失败能够被记录到日志中去,并保留足够的用户上下文信息,以识别可疑或恶意账户,并为后期取证预留足够时间。
  • 确保日志以一种能被集中日志管理解决方案使用的形式生成。
  • 确保高额交易有完整性控制的审计信息,以防止篡改或删除。
  • 例如审计信息保存在只能进行记录增加的数据库表中。建立有效的监控和告警机制,使可疑活动在可接受的时间内被发现和应对。

十、服务器请求伪造

        SSRF(服务器端请求伪造)是指攻击者能够从易受攻击的 Web 应用程序发送精心设计的请求对其他网站进行攻击。一般情况下,SSRF 攻击的目标是从外网无法访问的内部系统

        利用一个可以发起网络请求的服务,当做跳板来攻击其它服务,简单来说就是:A 让 B 帮忙访问 C

SSRF 的成因

        SSRF 形成的原因大都是由于服务器端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。SSRF 是利用存在缺陷的 web 应用作为代理去攻击远程和本地的服务器。

        也就是说,对于为服务器提供服务的其他应用没有对访问进行限制,如果我构造好我的访问包,那我就有可能利用目标服务对他的其他服务器应用进行调用。

SSRF 常见危害

        1、可以对服务器所在内网、本地进行端口扫描,获取一些服务的信息等

        2、目标网站本地敏感数据的读取

        3、内外网主机应用程序漏洞的利用

        4、内外网 web 站点漏洞的利用

防范

  • 过滤返回信息,验证远程服务器对请求的响应,是比较容易的方法。比如 web 应用获取某种类型的文件,那么可以在把返回结果展示给用户之前先验证返回信息是否符合标准。
  • 统一错误信息,避免用户根据错误信息来判断远程服务器端口状态。
  • 限制请求的端口为 HTTP 常用端口,比如 80、443、8080、8090
  • 黑名单内网 IP ,避免应用被用来获取内网数据,攻击内网。
  • 禁用不需要的协议。仅仅允许 HTTP 和 HTTPS 请求。可以防止类似于 file://  、ftp:// 等引起的问题

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

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

相关文章

【Linux】环境基础开发工具使用——gcc/g++使用

Linux编译器-gcc/g使用 1. 背景知识 1. 预处理(进行宏替换 ) 2. 编译(生成汇编 ) 3. 汇编(生成机器可识别代码) 4. 连接(生成可执行文件或库文件 ) 2. gcc如何完成 格式 gcc [ 选项 ] 要编译的文件 [ 选…

阿德勒、荣格、埃里克森、霍妮、弗洛姆、沙利文的新精神分析理论

新精神分析理论,强调自我的自主性及其整合与调节功能,强调文化和社会因素对人格的重大影响。 一、阿德勒的个体心理学 阿德勒,是一个男人努力克服自卑感的优秀样板。阿德勒写了《超越与自卑》。 阿德勒,向意识层面扩展精神分析…

c++11的重要特性3

目录 1、lambda表达式 C98中的一个例子 lambda表达式的 lambda表达式语法 函数对象与lambda表达式 3、可变参数模板 递归获取 逗号表达式展开参数包 2、包装器 function包装器 bind 1、lambda表达式 C98中的一个例子 在C98中,如果想要对一个数据集合中的元素进…

NetSuite 自定义记录类型的权限控制

在近期的一个定制项目中,遭受了一次用户洗礼。有个好奇宝宝把我们的一个自定义类型的表记录进行了删除,导致一个重要功能失败。算是给我们扎实上了一课。自定义类型的权限也需要重视起来。所以,今朝我们记录下这个设置,同时写给未…

C++ setw() 函数

C setw() 函数 分类 编程技术 C setw() 函数用于设置字段的宽度,语法格式如下: setw(n) n 表示宽度,用数字表示。 setw() 函数只对紧接着的输出产生作用。 当后面紧跟着的输出字段长度小于 n 的时候,在该字段前面用空格补齐&…

《QT实用小工具·十五》多种样式的开关控件

1、概述 源码放在文章末尾 目前实现了三种样式的开关控件按钮&#xff0c;如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef IMAGESWITCH_H #define IMAGESWITCH_H/*** 图片开关控件 * 1. 自带三种开关按钮样式。* 2. 可自定义开关图片。*/#include <QWid…

SpringBoot新增员工模块开发

需求分析与设计 一&#xff1a;产品原型 一般在做需求分析时&#xff0c;往往都是对照着产品原型进行分析&#xff0c;因为产品原型比较直观&#xff0c;便于我们理解业务。 后台系统中可以管理员工信息&#xff0c;通过新增员工来添加后台系统用户。 新增员工原型&#xf…

Vue中如何使用Tailwind CSS样式?多次引用不成功?具体步骤怎么做?

一、安装Tailwind CSS和依赖 在你的Vue项目中安装Tailwind CSS及其依赖。你可以使用npm或yarn来安装。 npm install tailwindcsslatest postcsslatest autoprefixerlatest # 或者yarn add tailwindcsslatest postcsslatest autoprefixerlatest 二、初始化Tailwind CSS np…

Linux常用命令-网络管理

文章目录 ping基本用法主要选项常见用途和理解输出注意事项 ifconfig基本用法配置网络接口示例高级功能 netstat基本用法常用选项示例注意事项 wget主要特点基本用法常见选项 示例注意事项 curl主要特点基本用法常见选项 示例注意事项 参考资料在线文档和手册图书在线教程和指南…

YOLO-World:实时开放词汇对象检测(论文+代码)

目录 一、YOLO-World摘要以及主要贡献 1.1摘要 1.2主要贡献 二、YOLO-World模型创新点总结 2.1YOLO Detector 2.2Text Encoder 2.3Re-parameterizable Vision-Language PAN 2.4核心创新点总结 三、如何应用 3.1推理预测 3.2自定义词汇推理 3.3自定义词汇类别…

Struts2的入门:新建项目——》导入jar包——》jsp,action,struts.xml,web.xml——》在项目运行

文章目录 配置环境tomcat 新建项目导入jar包新建jsp界面新建action类新建struts.xml,用来配置action文件配置Struts2的核心过滤器&#xff1a;web.xml 启动测试给一个返回界面在struts.xml中配置以实现页面的跳转&#xff1a;result再写个success.jsp最后在项目运行 配置环境 …

C++从入门到精通——类的定义及类的访问限定符和封装

类的定义及类的访问限定符和封装 前言一、类的定义类的两种定义方式成员变量命名规则的建议示例 二、类的访问限定符和封装访问限定符访问限定符说明C为什么要出现访问限定符例题 封装例题 前言 类的定义是面向对象编程中的基本概念&#xff0c;它描述了一类具有相同属性和方法…

Atlas 200 DK开发者套件的网络连接

一、参考资料 Atlas 200 DK官方文档 二、常用操作 1. Micro SD制卡 在windows系统上&#xff0c;一键制卡的步骤与Atlas 200I DK类似&#xff0c;但步骤更简单&#xff0c;详细步骤请参考&#xff1a;Windows系统制卡 2. Atlas 200 DK与PC机通信 2.1 准备工作 准备一根安…

一些好玩的东西

这里写目录标题 递归1.递归打印数组和链表?代码实现原理讲解二叉树的 前 中 后 序位置 参考文章 递归 1.递归打印数组和链表? 平常我们打印数组和链表都是 迭代 就好了今天学到一个新思路–>不仅可以轻松正着打印数组和链表 , 还能轻松倒着打印(用的是二叉树的前中后序遍…

vue事件代理

数据代理 Object.defineProperty 常见属性值 get和set函数 理解数据代理 Vue中的数据代理 Vue中的数据代理小结 事件处理 v-bind 事件处理小结 数据代理 Object.defineProperty 常见属性值 <body> <script type"text/javascript"> let person{n…

C++:逻辑运算符-非与或(19)

!非!a如果a为假&#xff0c;那么当前他就是真&#xff0c;如果a是真&#xff0c;那么他直接就是假&&与a&&ba与b都为真&#xff0c;那么就是真&#xff0c;如果两个里面有一个为假那么就是假||或a||ba或b有一个为真&#xff0c;那么就是真 非&#xff08;!&…

(学习日记)2024.03.31:UCOSIII第二十八节:消息队列常用函数

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

Golang并发模型-Pipeline模型、Fan-in Fan-out模型

这段时间由于项目的需要&#xff0c;本人正在研究关于如何优雅的进行go的并发&#xff0c;以下是结合资料和视频的结果&#xff0c;文末会给出参考资料 Go语言的并发模型主要通过goroutine和channel实现&#xff0c;通过这个我们可以更有效地使用IO和CPU 这里我们围绕生成一个…

LRU的原理与实现(java)

介绍 LRU的英文全称为Least Recently Used&#xff0c;即最近最少使用。它是一种内存数据淘汰算法&#xff0c;当添加想要添加数据而内存不足时&#xff0c;它会优先将最近一段时间内使用最少的数据淘汰掉&#xff0c;再将数据添加进来。 原理 LRU的原理在介绍中就已经基本说…

linux基础篇:Linux操作系统vi编辑器讲解与常用操作

Linux操作系统vi编辑器讲解与常用操作 一、vi编辑器介绍 vi编辑器是一款功能强大的文本编辑器&#xff0c;广泛应用于Unix和类Unix系统。它是由Bill Joy在1976年开发的&#xff0c;后来演变成vim&#xff08;vi improved&#xff0c;即“改进版的vi”&#xff09;编辑器。vi编…