零基础Web渗透实战:SQL注入、文件上传与逻辑漏洞复现指南

零基础Web渗透实战:SQL注入、文件上传与逻辑漏洞复现指南 1. 项目概述从零到一的实战渗透路径看到这个标题很多对网络安全感兴趣的朋友可能会觉得“接单赚钱”很诱人但又被“Web渗透”、“漏洞复现”这些专业术语吓到担心自己零基础跟不上。别急这正是我写这篇长文的目的。我干了十多年安全从自己摸索到带团队深知这条路最缺的不是高深理论而是能把复杂操作掰开揉碎、一步步带着走的实战指南。所谓的“零基础小白跟着做”绝不是一句空话它意味着每一个命令、每一个点击、每一个判断背后的逻辑我都会给你讲透。这篇文章就是带你亲手“挖”出三个真实的、有代表性的Web漏洞复现它们理解它们最终让你拥有独立分析和尝试的基础能力。这不仅是技术学习更是一次完整的“白帽”思维训练——知道黑客怎么想你才能更好地防御。为什么是这三个案例因为它们覆盖了Web渗透中最常见、也最经典的几种漏洞类型SQL注入、文件上传漏洞、以及逻辑漏洞。这就像学武功先扎马步、练直拳一样是基本功。掌握了这些你再去接触更复杂的漏洞组合或新型漏洞就会有一种“哦原来是这个原理的变种”的豁然开朗感。我会使用最普及的工具比如Burp Suite、SQLMap在虚拟机搭建的靶场环境里操作确保你的电脑环境安全也确保学习过程合法合规。我们的目标不是攻击任何真实网站而是在受控的实验室环境里锻炼那双能发现问题的“眼睛”和能验证问题的“手”。2. 环境准备与靶场搭建打造你的专属安全实验室在真正动手“挖洞”之前我们必须把“战场”准备好。想象一下木匠没工作室厨师没厨房肯定是干不成活的。对我们来说这个工作室就是一个完全隔离、可随意折腾的虚拟网络环境。2.1 虚拟机与靶机选择安全与便利的基石我强烈推荐使用虚拟机来构建整个学习环境。原因很简单安全、干净、可快照恢复。你可以在里面随意安装可能带有风险的工具或运行有漏洞的程序而完全不影响你宿主机的正常工作。VMware Workstation Player个人免费或VirtualBox都是极佳的选择。我个人更习惯用VMware稳定性好一点。靶机就是我们用来练习的“靶子”。对于新手直接从网上下载现成的漏洞靶场镜像是最快最省事的方式。这里我推荐两个DVWA (Damn Vulnerable Web Application)大名鼎鼎的“该死的脆弱Web应用”专为安全测试学习设计。它集成了SQL注入、文件上传、命令执行等十多种常见漏洞并且可以自由调整安全等级从低到高非常适合循序渐进地学习。OWASP Juice Shop一个用现代JavaScript框架Node.js, Angular编写的漏洞靶场漏洞类型非常新且全面界面也漂亮能接触到很多OWASP Top 10中较新的漏洞场景。注意永远不要在未经授权的真实网站上进行任何测试这是法律红线也是职业道德的底线。我们的所有操作都仅限于本地或授权靶场。以DVWA为例搭建步骤非常清晰下载一个集成了DVWA的虚拟机镜像比如Metasploitable 2或3或者单独的DVWA虚拟机文件。用VMware或VirtualBox导入这个虚拟机。启动虚拟机通常它会自动配置好网络和Web服务。你需要记下靶机的IP地址在虚拟机里用ifconfig或ip addr命令查看。在你的宿主机浏览器里输入靶机的IP地址加上DVWA的路径如http://192.168.1.100/dvwa/就能看到登录界面了。默认用户名是admin密码是password。2.2 攻击机与必备工具安装武装你的工具箱攻击机就是我们发起测试的机器。为了方便我们可以直接用另一个虚拟机安装Kali Linux。Kali是一个渗透测试专用的Linux发行版里面预装了海量的安全工具开箱即用。在Kali里有几个工具是我们案例中会反复用到的核心武器Burp Suite Community Edition社区版Web渗透测试的“瑞士军刀”。它作为代理能拦截、查看、修改你和网站之间所有的HTTP/HTTPS请求和响应。理解Burp是用好它的关键——它不直接攻击而是让你能“看清”和“操纵”流量。社区版对于学习和基础测试完全够用。SQLMap自动化的SQL注入检测与利用工具。它能帮你发现一个URL参数是否存在注入点并能自动获取数据库名、表名、甚至数据内容。对于新手它是理解SQL注入原理的绝佳辅助但切忌把它当黑盒魔法要明白它每一步在做什么。浏览器与插件推荐使用Firefox或Chrome并安装FoxyProxy插件来方便地切换代理设置以及HackBar插件用于快速构造和发送一些简单的Payload。安装好Kali后确保攻击机和靶机在同一个虚拟网络比如VMware的NAT或桥接模式下能够互相ping通。这样你的“攻击实验室”就搭建完毕了。2.3 网络配置与代理设置打通流量监控的任督二脉这是让Burp Suite发挥作用的关键一步。很多新手卡在这里就是因为流量没导对。在Kali中启动Burp Suite在Proxy-Options标签下确保代理监听器Proxy Listeners是开启的通常默认监听本机127.0.0.1的8080端口。在你的浏览器宿主机或Kali里的都可以但建议在Kali里操作更直接中配置代理服务器。地址指向运行Burp的机器如果Burp在Kali里就填Kali的IP如果在宿主机就填127.0.0.1端口填8080。用浏览器访问靶机DVWA的地址。此时Burp会拦截到第一个请求。你需要在Burp的Proxy-Intercept标签下点击Forward放行直到浏览器成功加载出DVWA页面。最关键的一步访问http://burp或你设置的监听地址加端口如http://127.0.0.1:8080下载Burp的CA证书。然后将这个证书导入到你的浏览器中在浏览器设置里搜索“证书”或“安全”找到管理证书的地方导入并信任它。这一步是为了让浏览器信任Burp代理的HTTPS连接否则很多HTTPS网站会无法访问。完成这些后打开Intercept is on按钮再用浏览器访问任何页面你会发现请求都被Burp暂停拦截了你可以查看甚至修改它再决定是否放行。这就是我们后续分析漏洞的基础。3. 案例一SQL注入漏洞实战——从手动探测到自动化利用SQL注入SQL Injection堪称Web安全的“万恶之源”历史悠久却依然常见。它的原理是网站后端程序将用户输入的数据未经充分检查或过滤直接拼接到SQL查询语句中执行导致攻击者可以构造特殊的输入Payload来改变原SQL语句的逻辑从而窃取、篡改或删除数据库数据。3.1 漏洞原理与手动探测像侦探一样寻找线索我们以DVWA的SQL注入关卡安全级别设为Low为例。这个关卡模拟了一个简单的用户ID查询功能。第一步正常交互观察在输入框输入1点击提交页面返回了用户ID为1的用户信息如First name, Surname。用Burp拦截这个请求我们看到它可能是一个GET请求URL类似http://靶机IP/dvwa/vulnerabilities/sqli/?id1SubmitSubmit。这里id参数很可能被直接用于数据库查询。第二步基础试探我们的目标是试探这个id参数是否被“干净地”拼接进了SQL语句。经典的试探方法是注入一个单引号‘。我们将Burp拦截的请求中的id1修改为id1‘然后放行。如果页面返回了数据库错误信息如“You have an error in your SQL syntax...”这就是一个强烈的信号——我们的单引号破坏了原SQL语句的语法说明输入没有被过滤存在注入点第三步逻辑判断确认有注入点后我们需要判断注入的类型和可用的查询方式。尝试输入id1‘ and ‘1’‘1和id1‘ and ‘1’‘2。前者逻辑永真应返回和id1相同的结果后者逻辑永假应返回空或错误。如果结果符合预期说明这是一个基于字符串的注入点且我们可以用and逻辑来构造条件。第四步信息搜集利用数据库的内置函数我们可以逐步获取信息。例如判断当前数据库用户id1‘ and user()‘dvwa‘----是SQL注释符用于注释掉原查询后面的部分避免语法错误判断数据库版本id1‘ and substring(version(),1,1)‘5‘--猜测版本号第一位是5查询当前数据库名id1‘ union select 1, database()--使用union联合查询前提是前后查询的列数要一致这需要先猜解列数这个过程就像在黑暗中摸索每一步都要根据服务器的反馈来调整策略。手动探测虽然慢但能让你深刻理解SQL注入的本质。3.2 使用SQLMap进行自动化利用效率工具的正确打开方式手动探测证明了漏洞存在但要想高效地拖取数据我们可以借助SQLMap。但切记SQLMap是一个强大的工具而不是一个“一键黑客”按钮。你必须理解它的参数和输出。在Kali终端中针对我们的靶场一个基础的探测命令如下sqlmap -u http://靶机IP/dvwa/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSID你的会话ID; securitylow-u指定目标URL。--cookie因为DVWA需要登录后才能访问漏洞页面所以我们必须提供当前有效的Cookie可以从浏览器开发者工具或Burp中复制。securitylow是DVWA用于设置安全等级的Cookie。运行后SQLMap会先进行一系列测试然后告诉你是否存在注入点、是什么类型的注入。确认后你可以使用以下参数进行深入利用--dbs枚举所有数据库。-D dvwa指定目标数据库为dvwa。--tables枚举dvwa数据库中的所有表。-T users指定目标表为users。--columns枚举users表的所有列。-C user,password指定要导出的列。--dump导出指定列的数据。例如获取dvwa数据库中users表数据的完整命令可能是sqlmap -u http://靶机IP/dvwa/vulnerabilities/sqli/?id1SubmitSubmit --cookie... -D dvwa -T users --dump实操心得使用SQLMap时一定要结合-v参数如-v 3提高输出详细程度这样你能看到它具体发送了哪些Payload是如何判断的。这比单纯拿到数据更有学习价值。另外对于有WAFWeb应用防火墙的站点SQLMap也提供--tamper参数来使用脚本对Payload进行混淆这是进阶内容。3.3 漏洞修复与深度思考知其然更知其所以然复现漏洞不是终点理解如何修复才能完成闭环。SQL注入的根本防御原则是“数据与代码分离”即永远不要信任用户输入不要拼接SQL语句。1. 参数化查询预编译语句这是最有效、最根本的解决方案。以PHP的PDO为例// 错误做法拼接 $query SELECT * FROM users WHERE id . $_GET[id]; // 正确做法参数化 $stmt $pdo-prepare(SELECT * FROM users WHERE id :id); $stmt-execute([id $_GET[id]]);数据库引擎会先将SQL语句的模板SELECT * FROM users WHERE id ?编译好然后将用户输入的id值纯粹当作“数据”传入无论它里面包含什么SQL关键字都不会被当作代码执行。2. 输入验证与过滤在参数化查询的基础上可以增加一层防御。例如如果id预期是数字那么在接受参数时就用intval()函数强制转换为整数$id intval($_GET[id]);。对于字符串可以定义严格的白名单字符集。3. 最小权限原则连接数据库的账户不应该拥有DROP,DELETE等高危权限通常只赋予SELECT权限这能在漏洞被利用时限制破坏范围。通过这个案例你不仅学会了一种攻击方法更重要的是建立了一种思维模式看到用户输入点就要下意识地思考“这里的数据会去哪里会被如何解析”。4. 案例二文件上传漏洞实战——绕过前端的“纸老虎”文件上传功能在Web应用中无处不在从更换头像到提交作业。如果服务器对上传的文件检查不严攻击者就能上传一个恶意的脚本文件如PHP的Webshell从而获得在服务器上执行命令的能力。这个漏洞的危害性极高常常能直接获取服务器控制权。4.1 漏洞原理与基础绕过突破第一道防线我们进入DVWA的文件上传File Upload漏洞模块安全级别Low。这个级别几乎没有任何防护。第一步正常上传页面就是一个简单的表单让你选择文件并上传。我们准备一个最简单的PHP Webshell文件shell.php内容如下?php eval($_POST[cmd]);?这段代码的意思是通过POST参数cmd接收我们传递的命令并用eval()函数执行。选择这个文件点击上传成功页面返回了文件路径例如http://靶机IP/dvwa/hackable/uploads/shell.php。第二步访问与利用我们使用浏览器或Burp的Repeater模块访问这个上传成功的地址。然后我们向这个地址发送一个POST请求在Body里带上cmdsystem(‘whoami’);。如果服务器返回了当前Web服务的运行用户如www-data恭喜你你已经拿到了一个Webshell可以在服务器上执行系统命令了。这太简单了因为Low级别没有做任何检查。现实中至少会有一个前端检查。4.2 前端验证绕过与MIME类型欺骗见招拆招将DVWA安全级别调到Medium。此时如果你再尝试上传shell.php页面会提示“文件类型不正确”。我们打开浏览器的开发者工具F12查看上传表单的HTML代码可能会发现类似accept“.jpg,.png”的属性或者有JavaScript代码在提交前检查文件后缀名。绕过方法1直接修改请求Burp Suite这是最有效的方法。我们正常选择一个shell.php文件但在点击上传前打开Burp的拦截功能。上传时Burp会拦截到POST请求。这个请求的Body中会有一个Content-Disposition部分其中包含了文件名。我们直接在这里将filename“shell.php”修改为filename“shell.jpg.php”或filename“shell.php.jpg”。然后放行请求。服务器端如果只检查后缀名最后一个点之后的部分.jpg就可能被绕过。更常见的是我们改为shell.php%00.jpg利用旧版PHP的截断漏洞但现代版本已修复或者直接改成shell.pHp大小写绕过如果服务器检查不区分大小写。绕过方法2修改MIME类型在Burp拦截的请求中还有一个Content-Type字段例如Content-Type: application/octet-stream。对于PHP文件可能是application/x-php。我们可以将其修改为图片的MIME类型如Content-Type: image/jpeg。如果服务器只通过MIME类型来判断文件是否合法就会被欺骗。绕过方法3双写后缀如果服务器采用简单的字符串替换试图删除.php后缀我们可以构造shell.pphphp。当它删除中间的php后剩下的部分恰好又组合成了.php。注意事项这些绕过技巧的成功与否完全取决于服务器端检查逻辑的严密程度。实战中需要结合错误信息、返回差异等进行模糊测试Fuzzing尝试各种可能的Payload。4.3 服务端内容检查与高级绕过真正的较量将DVWA调到High安全级别。此时服务器端会进行更严格的检查可能包括检查文件扩展名黑名单/白名单。检查文件的真实类型通过文件头魔数如FF D8 FF E0是JPEG图片的开头。检查文件内容是否包含危险函数如eval,system。绕过方法制作图片马Image Shell这是对付内容检查的常用手段。原理是一个文件可以同时是合法的图片和包含恶意代码的脚本。准备一张正常的图片比如test.jpg。准备我们的Webshell文件shell.php。在Linux终端下使用命令合成cat test.jpg shell.php shell.jpg.php。这样生成的新文件文件头是图片的魔数后面附带了PHP代码。上传这个shell.jpg.php文件。文件类型检查会认为它是图片从而通过。关键在于我们能否找到执行这个PHP代码的途径。如果服务器存在“本地文件包含”LFI漏洞我们可以通过包含这个图片文件来执行其中的PHP代码。例如存在一个URL参数?pagexxx我们可以尝试?page../uploads/shell.jpg.php。这个案例告诉我们防御文件上传漏洞必须是多层次的前端验证仅用于提升用户体验绝不能作为安全依据。白名单验证只允许.jpg,.png,.pdf等明确安全的扩展名。文件头检查验证文件内容的真实类型是否与扩展名匹配。重命名上传后用随机生成的文件名如UUID替换原文件名并去掉扩展名或强制改为安全扩展名。隔离存储将上传的文件存储在Web根目录之外通过后端脚本如PHP的readfile()来读取和提供下载防止直接解析执行。禁用执行权限在存储上传文件的目录通过服务器配置如.htaccess或Nginx配置禁止执行脚本文件。5. 案例三逻辑漏洞实战——业务流中的“隐形杀手”逻辑漏洞Business Logic Vulnerability与前面两种技术型漏洞不同它不依赖于特定的技术栈如SQL、文件解析而是利用应用程序业务逻辑设计上的缺陷。这类漏洞往往更难通过自动化工具发现需要测试人员真正理解业务像用户一样思考甚至像“攻击者”一样思考。我们以DVWA的“暴力破解”模块为例但其本质是一个认证逻辑缺陷。5.1 漏洞原理与手动测试寻找流程中的断点DVWA的Brute Force模块安全级别Low模拟了一个简单的登录框。通常防御暴力破解的措施有验证码、账户锁定、复杂密码要求、登录延迟等。但在Low级别这些都没有。手动测试思路观察响应使用Burp拦截一次失败的登录请求和成功的登录请求。对比两者的HTTP响应状态码、响应长度、返回信息。有时失败时返回“密码错误”成功时跳转到新页面这种差异非常明显。利用Intruder模块Burp Suite的Intruder模块是进行自动化参数测试如暴力破解、模糊测试的神器。我们将拦截到的登录POST请求发送到Intruder。设置攻击位置在Intruder的Positions标签清除所有自动标记然后手动选中密码参数的值如password123中的123点击Add §将其标记为Payload位置。配置Payload切换到Payloads标签我们可以加载一个常用的弱口令字典Kali自带路径如/usr/share/wordlists/rockyou.txt.gz需解压。选择这个字典文件。发起攻击点击Start attack。Intruder会用字典里的密码逐个替换我们标记的位置并发送请求。分析结果攻击完成后列表会显示所有请求和响应。我们需要找到一个能区分成功和失败的标志。最直观的是看Status状态码成功可能是302跳转失败是200和Length响应长度成功和失败的页面长度通常不同。通过排序很容易找出那个响应长度与众不同的请求其对应的Payload就是正确的密码。这个过程演示了最基础的暴力破解。但逻辑漏洞远不止于此。5.2 业务逻辑缺陷挖掘绕过限制与越权操作逻辑漏洞的精髓在于“利用程序本意之外的路径”。我们设想几个场景这些可能在更复杂的靶场如Juice Shop中找到场景一绕过次数限制某个登录功能错误3次后要求输入验证码。但验证码的校验可能发生在客户端JavaScript或者验证码的Session在第一次验证成功后并未销毁。攻击者可以先正常失败3次触发验证码然后重置会话如删除Cookie或使用新的浏览器会话程序可能又重新从0开始计数从而绕过了限制。场景二条件竞争漏洞在用户注册、兑换优惠券等“先检查后操作”的场景中容易发生。例如“邀请好友注册得积分”功能后端先查询用户是否已邀请过该好友检查如果没有则增加积分并标记已邀请操作。如果攻击者同时并发发送多个相同的邀请请求在极短的时间内多个请求可能都通过了“检查”因为数据库还未被第一个请求更新从而重复获得积分。场景三不安全的直接对象引用IDOR这是越权访问的典型。例如查看个人订单的URL是/order?id1001。攻击者尝试将id改为1002竟然成功看到了别人的订单信息。这是因为后端只验证了用户是否登录但没有验证当前登录的用户是否有权限查看id1002的订单。防御方法是在每次数据访问时都进行严格的权限校验“这个资源是否属于当前用户”。场景四业务流程绕过例如一个网购流程为1.加入购物车 - 2.填写地址 - 3.支付。如果攻击者直接通过构造URL访问第3步的支付页面并传递一个极低的价格参数如total0.01而服务端又没有从可信的会话中重新计算总价就可能以超低价完成支付。5.3 工具辅助与防御之道自动化与设计思维对于逻辑漏洞自动化工具能帮的忙相对有限但Burp Suite的Repeater重放和Sequencer会话随机性分析有时能派上用场。更重要的是手动测试思维发散。测试方法论理解业务彻底弄明白这个功能是做什么的正常流程是怎样的。绘制流程图画出正常的数据流和状态变迁。寻找异常路径问自己“如果我在这一步做别的事会怎样”“如果我跳过这一步呢”“如果我重复这一步呢”“如果我以不同身份用户/管理员做这件事呢”测试边界和极端情况输入超长字符串、负数、零、特殊字符、重复提交、高并发提交等。防御逻辑漏洞的核心服务端状态管理所有重要的状态如购物车总价、流程步骤必须在服务端维护和校验绝不能信任客户端传递的参数。完整的权限校验链对于任何数据访问操作都必须执行“认证授权”确保用户只能访问其权限范围内的资源。幂等性设计对于可能重复执行的操作如支付要设计成幂等的即多次执行产生的结果与一次执行相同防止重复扣款或重复发放。业务安全评审在代码评审时不仅要评审代码安全性也要评审业务逻辑的安全性。安全团队应尽早介入产品设计。6. 报告编写与实战心得从技术到价值的转化当你通过上述方法成功复现了漏洞这仅仅是技术层面的成功。如何将你的发现转化为被认可的价值甚至产生收益下一步至关重要——编写一份专业的漏洞报告。这对于在漏洞赏金平台如HackerOne、补天、漏洞盒子提交漏洞或是向客户/公司内部汇报都是必备技能。6.1 漏洞报告的核心要素清晰、可复现、有深度一份好的漏洞报告能让接收方通常是开发人员或安全团队快速理解问题、确认危害、并着手修复。它通常包含以下部分标题简明扼要地概括漏洞如“XX系统用户登录处存在SQL注入漏洞可导致数据库信息泄露”。漏洞等级根据漏洞的利用难度、影响范围、潜在危害自行评估一个等级如高危、中危、低危、信息级。可以参考CVSS通用漏洞评分系统进行相对客观的评分。受影响URL/组件明确指出存在漏洞的具体页面或API接口。漏洞描述用清晰的语言说明漏洞是什么。避免只说“这里有SQL注入”而要说明“在/search页面的keyword参数中用户输入未被过滤直接拼接至SQL语句导致注入”。复现步骤这是报告的灵魂。必须提供详细、完整、可操作的步骤让任何技术人员都能按照你的步骤100%复现漏洞。格式如下步骤1访问http://example.com/login。步骤2在用户名输入框输入admin‘ --。步骤3密码任意输入如123。步骤4点击登录。步骤5观察结果成功以admin身份登录无需正确密码。 请附上关键步骤的截图或视频链接请求与响应数据在复现步骤中提供Burp拦截到的原始HTTP请求和响应数据可脱敏敏感信息这能提供最直接的证据。漏洞原理分析简要分析漏洞产生的原因这体现了你的技术深度。例如“后端代码直接使用字符串拼接方式构造SQL语句String sql “SELECT * FROM users WHERE username‘” username “’ AND password‘” password “’”;当用户名输入admin‘ --时注释掉了密码检查部分。”修复建议提供具体、可行的修复方案。这非常加分。例如“建议使用参数化查询预编译语句来修复此SQL注入漏洞。Java示例使用PreparedStatementPHP示例使用PDO的prepare和execute。”其他信息测试所用的工具、浏览器版本、测试时间等。6.2 从学习到接单的路径积累、展示、沟通对于想通过安全技能兼职或接单的朋友我有几个务实的建议第一步扎实基础建立作品集在你熟练掌握本文案例这类基础漏洞后不要停步。去挑战更复杂的靶场如PortSwigger的Web Security Academy、HackTheBox的Web靶机在CTF比赛中锻炼实战思维。将你的学习过程和漏洞复现记录写成技术博客。GitHub是一个绝佳的展示平台你可以将你的靶场环境搭建脚本、自定义的扫描工具、漏洞分析笔记整理成仓库。一个内容充实、更新频繁的GitHub主页和博客就是你最好的简历。第二步参与众测积累信誉国内外的漏洞赏金平台众测是新手起步的绝佳场所。从一些小型项目或低危漏洞开始提交。一开始报酬可能不高甚至只有感谢信但重要的是积累有效提交记录和平台信誉分。每一次高质量的漏洞报告都是在为你背书。认真对待每一次提交严格按照平台格式要求编写报告积极与项目方沟通。记住沟通能力和专业态度与技术能力同等重要。第三步拓展人脉与视野加入安全社区如FreeBuf、先知社区、SecWiki、关注安全大会、参与线上/线下沙龙。多与他人交流了解行业动态和实际需求。很多时候兼职机会就来自于社区朋友的推荐。你也可以尝试在一些自由职业者平台上创建 profile明确标注你的安全测试技能。最后也是最重要的提醒法律与道德是红线永远只在获得明确授权的范围内进行测试。未经授权的测试就是攻击是违法行为。持续学习安全技术日新月异今天的方法明天可能就失效了。保持好奇心和学习习惯。耐心与坚持从零基础到能独立接单需要一个过程。可能会遇到长时间找不到漏洞的挫败期可能会被客户或平台拒绝。把每一次测试都当作一次学习和提升的机会你的技术、经验和眼界会在这个过程中稳步增长。这条路没有捷径但每一步都算数。从亲手复现第一个漏洞开始你就已经踏上了这条充满挑战与乐趣的征程。祝你探索顺利。