TryHackMe 第7天 | Web Fundamentals (二)

news2024/10/9 20:28:06

继续介绍一些 Web hacking 相关的漏洞。

IDOR

IDOR (Insecure direct object reference),不安全的对象直接引用,这是一种访问控制漏洞。

当 Web 服务器接收到用户提供的输入来检索对象时 (包括文件、数据、文档),如果对用户输入数据过于信任,Web 服务器没有对输入进行验证以确认所请求的对象属于提出请求的用户,就会出现这种类型的漏洞。

比如有如下 URL,其对应页面如下所示:

该页面展示的是对应 id 的订单信息,此处 id 为 1234,在 URL 中也有所体现。

此时将 URL 改为 1000,正常来说,应该无法访问到,因为 id 为 1000 的订单并非由我们生成。但是由于该 Web 服务器无条件信任用户输入,它返回了 id 为 1000 的订单信息:

基于上述例子,我们可以知道 URL 中传输的数值很可能是 IDOR 漏洞的入口。有些时候,这些数值会经过编码,如 Base64 编码;有些时候,这些数值会经过 Hash 处理。面对这种数值,想验证是否存在 IDOR,只需要反推出原始数值后,修改,再进行编码或 Hash 监控页面响应即可。

更特殊的情况是,我们无法反推出原始数值。那么我们可以创建两个账户,将这些账户对应的数值进行交换。如果可以成功访问到另一个账户的个人信息,则可以说明存在 IDOR 漏洞。

当然,前面提到的都是出现在 URL 中的漏洞入口,实际上 IDOR 也可能出现在其他地方,只要有参数传递且和用户信息有关的地方,都可能存在 IDOR 漏洞。

File inclusion

文件包含 包括了 本地文件包含 (Local file inclusion)、远程文件包含 (Remote file inclusion) 和 目录遍历 (directory traversal)。

当我们向 Web 服务器请求一个文件时,它的运行逻辑可能是这样的:

然而,如果 Web 服务器对用户输入完全信任,从不验证,那么用户就可以传递任意输入,从而导致漏洞发生。

文件包含可能会导致代码、凭证或其他重要文件泄露,此外如果攻击者可以通过其他渠道向 Web 服务器上传文件的话,那么就可以利用该文件与 文件包含 漏洞形成联动,以获得 RCE 漏洞 (Remote command execution)。

目录遍历

目录遍历 也被称为 路径遍历,它允许攻击者操作 Web 应用程序的 URL 来定位和访问那些存储在应用程序根目录之外的文件或目录。

在 PHP 语言中,用于读取文件内容的函数有许多,比较常见的就是 file_get_contents 函数。但是该函数不是引起目录遍历的主要原因,主要原因是未对输入进行验证或过滤

前面提到过正常访问 Web 应用中的文件过程图,假如未对用户输入进行过滤和验证,用户就可以利用 目录遍历 漏洞来读取其他文件:

如上图所示,用户在本应接收文件的参数后面构造了 “../../../../etc/passwd” 字符串。这表示 PHP 中的文件读取函数将从当前目录开始,往上级目录跳 4 次,然后获取 /etc 文件夹中的 passwd 文件。

下面是 操作系统 中常见的重要文件路径表:

Location描述
/etc/issue记录了在登陆提示符前打印的信息或系统标识
/etc/profile控制全系统默认变量,如 导出变量、文件创建掩码 (umask)、终端类型、用于显示新邮件到达时间的邮件信息
/proc/version指定了 Linux 内核版本
/etc/passwd拥有访问系统权限的所有注册用户
/etc/shadow包含系统用户密码信息
/root/.bash_history记录了 root 用户的命令历史记录
/var/log/dmessage包含全局系统信息,包括系统启动时记录的信息
/var/mail/root所有给 root 用户的邮件
/root/.ssh/id_rsa服务器上 root 用户或任何已知有效用户的 SSH 私钥
/var/log/apache2/access.log访问 Apache 服务的请求数
C:\boot.ini包含计算机 BIOS 固件的启动选项

本地文件包含 (LFI)

本地文件包含 漏洞通常是由于开发人员缺乏安全意识导致的。在 PHP 中,容易引起该漏洞的函数有 include、require、include_once、require_once 等函数,这些函数的作用一般都是将已有文件插入到当前文件中,可以方便开发人员复用文件。在此重点讨论 PHP 中的 LFI 漏洞,当然这不代表使用其他语言时不会出现 LFI 漏洞。

情况 1

在 index.php 中,有这样一串代码:

<?PHP 
	include($_GET["lang"]);
?>

它表示从 GET 请求中获取  lang 参数,并将参数中的文件包含进来。比如,当访问 index.php?lang=EN.php 时,就会将英文版的页面返回回来;而如果访问 index.php?lang=CN.php 则会返回中文版的页面。

此时有攻击者构造了这样的 URI :index.php?lang=/etc/passwd ,由于开发人员未对输入做任何过滤,也未在 include 函数中指定包含目录,此时,/etc/passwd 文件就被包含了进来:

情况 2

开发人员在栽了个跟头后,在 include 函数中指定了目录:

<?PHP 
	include("languages/". $_GET['lang']); 
?>

这样,就只能访问 languages 目录下的不同语言的页面了。事实是,虽然有用但不多。

攻击者发现直接传入 index.php?lang=/etc/passwd 没用了,于是再构造了一个 URI:index.php?lang=../../../../etc/passwd。

攻击者又一次得逞了。

情况 3

在前两个情况中,我们一直在进行白盒测试。假如现在我们进行黑盒测试,这种情况下,错误信息就十分重要。

现在我们只能得到如上的报错信息。根据这个报错,我们可以推断出:

  1. include 函数指定了路径 /includes,且添加了 .php 后缀。
  2. 当前 Web 应用的根目录为 /var/www/html

对于第 2 个推断,我们可以依然使用 ../../../../etc/passwd 来利用。但是由于这次,它不仅指定路径,还指定了后缀名:

在 PHP 5.3.4 以下版本,可以使用 空字节 进行截断 (如 URL 编码中的 %00 和 十六进制中的 0x00)。它的原理在于,%00 和 0x00 都会被解析为 NULL,而当一个字符串在解析时出现 NULL 时,NULL 后的字符就会被丢弃。

情况 4

依然黑盒测试。现在倒好,/etc/passwd 这一文件被过滤了。这种情况有两种方法解决:

  1. %00 截断。只不过有 PHP 版本要求。
  2. 在文件名后加 /. 符号

第一个方法前面说过,重点讲讲第二个方法。

以 cd 命令为例,如果我们输入 cd ..,它会将我们带到上一个目录中;而如果输入 cd .,则会停留在原目录中。同样的,如果我们输入 /etc/passwd/..,它会跳到 /etc 目录中;而如果我们输入 /etc/passwd/.,它依然会停留在原目录,并且匹配不上 /etc/passwd 这一字符串。

情况 5

依然黑盒。现在开发人员过滤掉了 ../ 字符串,其将 ../ 替换为了空字符串:

我们可以尝试使用 双写法 绕过:....//....//....//....//etc/passwd。双写法 原理如下图所示:

如果在过滤时只过滤一次,那么我们写两次时,就只会过滤掉其中一次,剩下那次依然可以正常保留。

经过 双写法 之后,得到结果:

情况 6

依然黑盒。现在在输入时必须给上指定的文件夹:

这种解法也算是简单,只需构造出如下 URI:THM-profile/../../../../etc/passwd 即可:

远程文件包含 (RFI)

远程文件包含 是可以在 Web 应用中包含远程文件的漏洞。与 LFI 相似,RFI 也是未对用户输入进行过滤和验证时发生的,它允许攻击者在函数中注入外部 URL。RFI 的一个前提是:allow_url_fopen 选项必须开启。

RFI 的风险高于 LFI,因为 RFI 漏洞允许攻击者在服务器上实现 RCE。除此之外,RFI 攻击成功的后果还有:

  • 敏感信息泄露
  • 跨站脚本攻击 (Cross-site scripting, XSS)
  • 拒绝服务攻击 (Denial of service, DoS)

要成功实施 RFI,攻击者的服务器必须可以同目标 Web 服务器通信。攻击者在其服务器上托管恶意文件,然后通过 HTTP 请求将恶意文件注入至对应函数中,并在目标 Web 应用上执行恶意文件。

下图展示了 RFI 的利用过程:


修复

关于 文件包含 漏洞的修复建议如下:

  1. 将系统和服务(包括 Web 应用框架)升级为最新版本
  2. 关闭 PHP 报错,以避免泄露 Web 程序的路径和其他信息
  3. 配置 WAF (Web application firewall,网络应用程序防火墙)
  4. 若 Web 应用不需要远程调用文件的功能的话,就将它禁用。如 allow_url_fopen 和 allow_url_include
  5. 仔细分析 Web 应用,只允许使用需要的协议和 PHP 函数
  6. 不要相信用户的输入,并确保进行适当的输入验证
  7. 对文件名和路径设置黑白名单管理

挖掘 LFI 漏洞

碰到一个 Web 应用时,要通过什么步骤发现存在 LFI 漏洞呢?

  1. 找到一个入口点,可以是 GET、POST、Cookie 甚至 HTTP 头
  2. 输入有效的输入,查看 Web 服务器的运行情况
  3. 输入无效的输入,比如特殊字符或常用文件名。在输入无效输入后查找错误,以披露 Web 应用的当前路径;如果没有错误,那么试错可能是最好的选择
  4. 了解是否有输入验证或是否有任何过滤
  5. 尝试注入有效条目以读取敏感文件

Challenge

上面写着输入表单崩溃了,只能通过 POST 请求发送 file 参数才可以正常运行。

那就直接 Burpsuite 抓包,转换请求方式,发送,得到 flag:

本关提示只有 admin 才可以访问该页面。通过上面的抓包可以发现,Cookie 中有一个字段 THM 取值为 Guest,将其改为 admin 会返回什么结果呢:

可以看到,修改 Cookie 是有效的,那么就猜测后端是接收 Cookie 后,将值对应的文件包含起来。现在将 Cookie 使用 /etc/passwd 进行测试:

与我们的猜想大致,通过报错可以推断出它对输入进行了处理,限制了文件夹以及添加了后缀名。还可以注意到 PHP 版本为 5.2,因此可以使用 %00 截断来绕过后缀名。而限制文件夹则可以使用 ../ 来绕过。

这样我们就构造了一个 URI:../../../../etc/flag2 来获取当前关卡的 flag:

 

这一关没有提示,只有这样的输入框。我们直接输入 /etc/flag3 来看看返回结果:

从报错中可以推断出:

  1. 给输入指定了后缀名。
  2. 过滤了 / 和 数字。
  3. PHP 使用版本为 5.2

此处没有指定文件夹名,只限制了后缀名,故可以直接使用 %00 截断。主要问题是过滤了 / 和 数字,第一时间尝试使用 双写法 绕过,发现失效了:

看来这次过滤不止一次。看来输入框是比较难弄了。在抓包时,我们发现 Cookie 依然有 THM 字段,因此尝试能不能通过 Cookie 利用漏洞。

没有反应。那就尝试更换请求方式:

可以看到使用 POST 请求后,/ 和 数字都没有被过滤了。但是居然没有直接显示结果,看来还是有指定文件夹限制,只是没有展示出来吧。因此构造一个 URI:../../../etc/flag3%00 即可:

本关卡提示说,要利用 RFI 漏洞实现 RCE,获取到目标的 hostname。

那基本思路就是在攻击方写一个 PHP 脚本获取 hostname:

然后搭建一个 python 的轻型 HTTP 服务来让目标 Web 服务器访问。

这样就可以获得目标机的 hostname。 

Intro to SSRF

SSRF (Server-side request forgery),服务端请求伪造。这是一个允许恶意用户让 Web 服务器向攻击者选择的资源发出额外或经过编辑的 HTTP 请求的漏洞。

SSRF 有两种类型,一种是常规 SSRF,它可以将数据返回到攻击者的屏幕上;另一种是盲 SSRF,即没有信息返回到攻击者屏幕上。

SSRF 会导致:

  • 访问未经授权的区域
  • 访问 客户/组织 的数据
  • 扩展至内网的能力
  • 揭示身份验证令牌/凭据

Example

如上图所示,这显示了攻击者如何完全控制 Web 服务器请求页面。Expected Request 是 Web 服务器希望接收的内容,红色部分则是网站用于获取信息的 URL。攻击者可以通过将红色区域修改为他们想要的 URL 来实现 SSRF。

上图展示了攻击者如何使用目录遍历控制路径访问指定 URL。当 website.thm 接收到 ../ 这样的信息时,意味着要向上移动一个目录,就会删除请求中的 /stock 部分,并将最终请求转换为 /api/user。

在上图中,攻击者可以控制请求的子域名。注意此处以 &x 为结尾,它可以阻止剩余路径内容附加到攻击者 URL 末尾,并将剩余路径内容作为查询字符串上的参数。

回归到原始请求上,即攻击者可以强制 Web 服务器请求攻击者选定的服务器。通过此种方式,我们可以捕获到发送给攻击者指定域名的请求头。这些请求头种可能包含由 website.thm 发送的认证凭据或 API 密钥。

下面是一次简单展示:

本题中,攻击者可以控制请求的子域名,flag 就在 https://server.website.thm/flag?id=9 这个 URL 中。这种情况如前面所示,我们直接访问在可控制输入的地方输入 URL,并在后面加上 &x 参数。

注意最底下的那一行小字,它表示了当前正在请求的 URL。

按下回车,flag 返回回来。

Finding SSRF

1. 当完整的 URL 作为参数显示在地址栏中:

2. 表单的隐藏字段中:

3. 部分 URL,比如 主机名:

4. 只有路径的 URL:

面对可能存在 SSRF 漏洞的地方,我们需要反复试验才能找到有效负载。如果使用的是盲 SSRF,其输出不会反馈在屏幕上,因此需要使用外部 HTTP 日志工具来监控请求,比如 requestbin.com,又或者是 我们自己的 HTTP 服务器 或 BurpSuite 的 Collaborator 客户端。

Defeating common SSRF defenses

意识到 SSRF 漏洞风险的且安全意识较高的开发人员可能会在 Web 应用中实施检查,以确保请求的资源符合特定规则。通常有三种方法:

Deny list

拒绝列表 指除了列表中指定的资源或与特定模式匹配的资源外,所有请求都被接受。Web 应用可以使用拒绝列表保护 敏感端点、IP地址 或 不被公众访问的域,同时仍允许访问其他位置。限制访问的一个特定端点就是 localhost,它可能会包含服务器性能数据或更多敏感信息。但攻击者可通过使用其他 localhost 引用 (如 0、0.0.0.0、0000、127.1、127.*.*.*、2130706433、017700000001)或具有解析到 IP 地址 127.0.0.1 的 DNS 记录 (如 127.0.0.1.nip.io)的子域来绕过拒绝列表。

此外在云环境中,阻止对 IP 地址 169.254.169.254 也是有用的。因为该 IP 地址包含已部署云服务器的元数据,其中可能包含敏感信息。攻击者可以通过在自己的域上注册一个子域,并将 DNS 记录指向 IP 地址 169.254.169.254,从而绕过这一限制。

Allow list

允许列表 指除了出现在列表中或符合特定模式匹配的资源外,所有请求都被拒绝。比如参数中使用的 URL 必须以 https://website.thm 开头的规则,那么攻击者可以在其自己的域名上创建一个子域(如 https://website.thm.attackers-domain.thm)来快速规避这一规则。

Open redirect

如果上述的方法不起作用,还可以使用 开放式重定向 (Open redirect)。

开放式重定向 是服务器上的一个端点,网站访问者会被自动重定向到另一个网站地址,比如 https://website.thm/link?url=https://tryhackme.com。创建这种端点是为了记录访问者点击该链接的次数,以用于广告/营销目的。

但假如这里面存在一个潜在的 SSRF 漏洞,且其严格的规则只允许以 https://website.thm/ 开头的 URL,那么攻击者可以利用上述功能将内部 HTTP 请求重定向到攻击者选择的域上。

Practical

现在有一个网站页面,它有两个目录。一个是 /private 目录,但它无法在当前 IP 地址上被访问:

另一个是 /customers/new-account-page,这是新版的用户账户页面,允许用户选择头像:

首先我们查看这些图像的信息,通过开发者工具可以看到图像的字段中包含了它们的路径:

而当某一图像被选择为头像时,它就用 data URI 显示了,其中使用了 Base64 编码:

现在我们尝试修改图片路径为 /private:

然后把这个修改过的图片更新为自己的头像后发现:

URL 不能以 private 开始。那我们就不以 private 开始,同时最后得到的就是 private  中的内容,即构造一个 URL 为 x/../private:

再次将修改后的图片更新为头像,发现一串 base64 编码:

将其解码后,得到 flag:

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

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

相关文章

【可视化大屏】Python Flask框架介绍

为了能显示真实数据&#xff0c;使用flask快速搭建了一个web应用&#xff0c;然后连接数据库&#xff0c;读取数据库里的数据来进行大屏可视化显示&#xff08;btw&#xff1a;数据是从车主之家网站上爬虫爬的&#xff09; 家人们&#xff01;记得使用专业版的pycharm&#xf…

在忘记密码的情况下重新访问手机?5种忘记密码解锁Android手机的方法

无需密码即可访问Android手机。 即使你忘记了密码&#xff0c;你也可以解锁你的Android手机&#xff0c;但你通常需要将手机恢复出厂设置。 您可以通过执行出厂恢复或使用“查找我的设备”网站解锁大多数Android手机。 如果你不再有密码&#xff0c;这里有五种解锁安卓手机的…

sqli-labs less-17密码重置报错注入

密码重置报错植入 来到首页面我们看到页面提示【password reset】&#xff0c;说明这是更改密码的注入&#xff0c;也就是说我们知道一个账户名&#xff0c;修改他的密码&#xff0c;所以我们可以在passwd处进行注入。 闭合方式 添加单引号 有报错 可以知道闭合方式为单引号…

【JavaEE】——初始网络原理

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;局域网 1&#xff1a;概念 二&#xff1a;局域网的连接方式 1&#xff1a;网线直连 …

Qt实现Halcon窗口显示当前图片坐标

一、前言 Halcon加载图片的窗口&#xff0c;不仅能放大和缩小图片&#xff0c;还可以按住Ctrl键显示鼠标下的灰度值&#xff0c;这种方式很方便我们分析缺陷的灰度和对比度。 二、实现方式 ① 创建显示坐标和灰度的widget窗口 下图的是widget部件&#xff0c;使用了4个label控…

前端如何让页面上的文字“立”起来

前言 最近看到了一个很有意思的 CSS 效果&#xff0c;如下图&#xff0c;是一个文字立起来 阴影 的效果&#xff0c;觉得比较有意思&#xff0c;所以分享给大家~ 实现 基础样式 首先我们把基础的文字和样式编写出来&#xff0c;代码如下 效果如下&#xff1a; 伪元素 ->…

香橙派如何连接网络,及wiringOP库

1.使用nmcli dev wifi命令扫描周围的 WiFi热点 2.找到需要连接的WiFi 输入nmcli dev wifi connect wifi_name password wifi_passwd 其中wifi_name是你的WiFi名字&#xff0c;wifi_passwd是WiFi的密码 3.wiringOP库 包含#include <wiringPi.h> 首先使用wiringPiSet…

[OS] 再探Kernel Threads -2

内核线程&#xff08;Kernel Thread&#xff09;创建和执行机制&#xff1a; 在 Linux 内核中&#xff0c;内核线程&#xff08;kthread&#xff09; 是一种特殊类型的线程&#xff0c;专门用于执行内核任务。与用户态的进程和线程不同&#xff0c;内核线程不具有用户空间&…

计算机的错误计算(一百一十六)

摘要 计算机的错误计算&#xff08;一百一十&#xff09;分析了&#xff08;二&#xff09;中例1循环迭代错误计算的原因。应读者建议&#xff0c;本节将用错数讨论其例2的错误计算原因。 例1. 已知 计算 在 的错数&#xff0c;并用实例分析计算过程中的错误数字数量。…

leetcode-哈希篇1

leetcode-217 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;true 解释&#xff1a; 元素 1 在下标…

电脑操作技巧:如何恢复永久删除的婚礼照片

我们的生活充满了褪色和模糊的快照&#xff0c;是我们记忆的剪贴簿。尽管我们很想记住事情并坚持快乐的回忆&#xff0c;但随着时间的推移&#xff0c;它们会被冲走。为了避免这种情况并记住这些记忆&#xff0c;我们以照片的形式捕捉瞬间。这有助于缓解和分享那些快乐的时刻。…

C语言编译与链接(29)

文章目录 前言一、翻译环境和执行环境二、翻译环境预处理(预编译)编译词法分析语法分析语义分析 汇编链接 三、运行环境总结 前言 本篇同样是一篇修炼内功的文章   很重要&#xff01;它将会让你对程序的构建运行有一个更深的认识 一、翻译环境和执行环境 在ANSI C的任何一种…

[uni-app]小兔鲜-08云开发

uniCloud可以通过JS开发服务端,包含云数据库, 云函数, 云存储等功能, uniCloud可结合 uni-ui 组件库使用 效果展示: <picker>城市选择组件不支持h5端和APP端, 所以我们使用 <uni-data-picker>组件进行兼容处理 <uni-data-picker>的数据使用云数据库的数据 云…

指针(7)

目录 1. sizeof和strlen的对⽐ 1.1 sizeof 1.2 strlen sizeof 和 strlen 总结&#xff1a; 2. 数组和指针 2.1 ⼀维数组 2.2 字符数组 1. sizeof和strlen的对⽐ 1.1 sizeof 计算的是使⽤类型创建的变量所占内存空间的⼤⼩。sizeof不在乎你里面放的什么。sizieof是操作符…

基于springboot人力资源管理系统源码

项目技术&#xff1a;SpringBoot 运行环境&#xff1a;jdk1.8idea/eclipsemaven3mysql5.6 项目描述&#xff1a; 系统包括&#xff0c;员工管理&#xff0c;奖惩管理&#xff0c;合同管理&#xff0c;薪酬管理&#xff0c;培训管理&#xff0c;绩效评估等功能

x++、++x的一些问题

x、x在字面上无非就说一个先前置递增然后再运算&#xff0c;另一个是运算完再递增&#xff0c;是不是有些许模棱两可的感觉&#xff0c;接下来引用一个简单的for循环就能够大致理解&#xff1a; 先是x&#xff1a; int i0,x0;for(i0;(i)<5;){xi;printf("%d\n",x)…

影刀RPA实战:Excel排序、替换与格式

1.实战目标 今天继续介绍影刀RPA操作Excel的指令&#xff0c;内容替换&#xff0c;数据排序与单元格格式设置&#xff0c;这几个功能在日常工作中使用率还是比较频繁的。我们可以使用影刀来处理这些重复繁琐的工作。 2.内容替换 我们手动替换内容时 打开Excel文件&#xff1…

【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart

1. 后端传参重命名&#xff08;后端参数映射&#xff09; 某些特殊情况下&#xff0c;前端传递的参数 key 和我们后端接收的 key 可以不一致&#xff0c;比如前端传了一个 time 给后端&#xff0c;而后端是使用 createtime 字段来接收的&#xff0c;这样就会出现参数接收不到的…

第二十二天|回溯算法| 理论基础,77. 组合(剪枝),216. 组合总和III,17. 电话号码的字母组合

回溯算法理论基础 1.题目分类 2.理论基础 什么是回溯算法 回溯和递归是相辅相成的。 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯法的效率 回溯法其实就是暴力查找&#xff0c;并不是什么高效的算法。 因为回溯的本质是穷举&#xff0c;穷举所有可…

销冠的至高艺术:让自己不像销售

若想在销售领域脱颖而出&#xff0c;首先是让自己超越传统销售的框架&#xff0c;成为客户心中不可多得的行业顾问与信赖源泉。这不仅是身份的蜕变&#xff0c;更是影响力与信任度质的飞跃。 销冠对客户只吸引不骚扰&#xff0c;不讲自己卖什么&#xff0c;只讲自己能解决什么…