CSDN博客

img ghj1976

Internet开发人员的验证和安全技术(8570)

发表于2000/12/7 8:26:00  1569人阅读

 

微软公司
1997年10月10日
目录

简介

如果你是一名使用Microsoft® Internet Information Server (IIS,Internet信息服务器) 3.0的开发人员,理解IIS如何使用验证(Authentication扮演(Impersonation技术控制你的Web服务器的安全是十分重要的。当在Microsoft的Internet开发人员支持小组工作时,我发现我们处理的问题中有四分之一与我们称之为许可权(permissions)的主题有关。进一步讲,如果开发人员对验证的实现内幕在概念上有更多的了解的话,这些问题中的大部分都能够被避免。验证只是一个简单的确定用户身份的过程。当一个用户被肯定确认后, Windows NT®随即能够控制该用户可以访问的资源。当不是具有特别的技术色彩时,验证和安全易于混淆。对IIS如何控制安全的准确理解将帮助你创建更有活力的站点和避免常见、费时的问题。

本文解释了有关IIS的Windows NT安全,所以你能够有效地解决与安全有关的问题。我们的内容包括三种验证形式,它们的差异,对你的Web服务器关键区域的几种访问控制方式,以及重要的但被普遍误解的“委托(delegation)”概念。对于任何使用IIS建立数据委托驱动的Web站点的人员,必须理解授权。理解Windows NT如何处理不同的用户将节省你在排除疑难时耗费的成天甚至成周的时间。

ACLs, NTLM以及其它定义

在开始前,我们先定义一些常见术语:

  • 访问控制表(ACLs,Access Control Lists)   每个ACL是一个访问控制入口(Access Control Entries)列表,访问控制入口规定了NTFS(New Technology File System)硬盘上的Windows NT所使用的访问和审核信息。Windows NT通过访问ACLs确定已被授予访问特定资源(文件和文件夹)权限的用户,以及用户能够得到的权限,包括读、写和执行。在文件或文件夹资源上单击鼠标右键,选择Properties(属性),然后单击Securities(安全)页的Permissions(权限)按钮,可以查看该资源的ACLs。
  • Windows NT 盘问/响应(Challenge/Response   这是一个Windows NT 验证过程。在用户或服务(如IIS)试图通过网络访问另一台Windows NT计算机存储的任何资源(诸如查询一台服务器上的一个共享资源)时都会发生盘问/响应。盘问/响应也能被IIS用来在用户浏览Web站点时进行验证。
  • NTLM  这是Windows NT使用的盘问/响应验证机制。NTLM代表Windows NT LAN Manager,因为它最早开发和使用于Microsoft LAN Manager, Microsoft最早的一种网络产品。
  • SAM   SAM (Security Account Manager,安全帐户管理器)是存储用户和组帐户信息的数据库。SAM中并不包含密码,但是它存储了密码散列表(后面将进行说明)。SAM存储在注册表的HKEY_LOCAL_MACHINE/SAM和HKEY_LOCAL_MACHINE/Security/SAM 子树中。不必惊讶,SAM经常是黑客的主要目标。

扮演(Impersonation)

在不同的情况下,IIS会假扮成不同的用户。在Windows NT计算机上的所有操作的处理都是运行在一个有效的Windows NT帐户上的。当一个程序或处理(类似于IIS)代表一个用户运行时,它可以说是运行在该用户的安全上下文(security context中。安全上下文的用途是使代表用户运行的处理对文件和资源的访问权不能超过用户在本地运行一个处理时所获得的访问权。当IIS代表一个用户运行时,就说它扮演了该用户。

IIS设计将Web请求作为自动的服务进行处理。要实现这一点,IIS需要运行在一个有效的用户安全上下文中。IIS需要对两种请求作出反应:匿名请求(Anonymous Request)验证的请求(Authenticated Request)。在匿名请求中, IIS对用户情况一无所知。而在验证的请求中,IIS能够准确了解请求资源的用户。因为匿名请求和验证式请求在进行时都不会对用户出现对话框或其它标识,所以使用何种方法并不总是一眼就能发现的。但是,对我们开发人员应该总能知道使用何种方式,这是必须的。IIS扮演的帐户,以及更大范围而言,到IIS的处理能力,主要依赖于所使用的请求类型。

匿名请求

该种方式不需要从用户得到任何信息。默认情况下,当浏览器对一个页面发出Web请求时, IIS首先尝试不进行用户验证处理请求。要作到这一点,IIS将扮演一个特定的Windows NT 帐户—IUSR_machinename (IUSR_machinenamemachinename是IIS的主机计算机名)。该帐户在安装IIS时创建。如果IIS扮演IUSR_machinename帐户时能够访问请求的资源,则该Web页面将能够被匿名用户访问。

IUSR_machinename帐户的密码和Internet Service Manager(Internet服务管理器)中输入的密码不匹配是匿名访问时发生的一个常见问题。当IIS试图扮演IUSR_machinename帐户时,它会提交在Windows NT服务器的匿名登录文本框输入的密码。如果密码不正确,IIS将无法使用IUSR_machinename帐户。而一旦匿名访问失败,IIS将会对所有用户进行验证。因为验证过程没有提示,所以站点的验证可能会失败,但原因却往往不明显。就此我已经告诉过许多遇到奇怪的安全问题的Web站点管理员,因为他们的站点对每个用户进行验证,而他们却根本不知道这一点。如果你的页面访问其它诸如数据库或客户端组件(比如DLLs)等资源,使用的验证类型将会有很大不同。

验证的请求

对用户身份的肯定确认是必要的。当IIS无法使用IUSR_machinename帐户时,IIS将尝试验证并随后扮演用户以便确定该用户是否可以访问请求的资源。IIS可以使用两种方法进行用户验证:盘问/响应验证和基本验证。这些方法在本文的后面进行讨论。验证的Web访问通常最适合一个公司的Intranet或其内部包含的,经过细致定义的工作组。不过即使这样,仍然还要考虑一些限制。

控制验证方法,以及关心的原因

IIS Service Manager(IIS服务管理器)工具是配置IIS进行WWW、FTP和Gopher服务的主要场所。不需要对WWW属性对话框的选项了解过多的细节,我们只需要关心几个关键项。默认情况下,密码验证选项组中选择了匿名和盘问/响应验证。第三种方法是基本验证,将在后面说明。让我们看看几种控制对你的Web服务器进行访问的方式。

  • “允许匿名(Allow Anonymous)”选项框
    如果选择了允许匿名(Allow Anonymous,IIS将通过扮演匿名登录帐户(默认为IUSR_machinename)尝试访问请求的资源。当IUSR_machinename帐户被自动创建后,它会被分配一个随机密码,并被添加到Guests组,赋予guest权限。选择或取消选择允许匿名是允许和禁止匿名访问整个Web服务器的最佳方法。当取消选择允许匿名后,只有具有有效、可验证(使用基本验证或挑战/响应验证) Windows NT帐户的用户能够得到服务。使用这种方式设置IIS通常只适用于团体或成员性的设置,这时验证访问你的站点的所有用户很重要。
  • 改变文件和文件夹的权限
    NTFS级的权限在IIS也得到支持,所以对文件和文件夹进行单独的权限设置能够在更小粒度上控制能被访问的页面。一个控制访问的常见方法如下:可被所有人查看的页面放置到一个文件夹中,而限制只能被站点管理员查看的页面放置到另一个文件夹。右键单击限制权限的文件夹,然后选择Properties/Securities/Permissions。因为我们的目标是保证IIS不能使用IUSR_machinename帐户匿名访问限制权限的文件夹,所以应从访问列表中删除Everyone组和IUSR_machinename帐户。将文件放置于两个不同的文件夹确保使用了维护两个组的权限方式,这比一个文件接一个文件的进行权限维护要容易的多。

基于ASP代码的安全

使用ASP代码,你能够实现更为专门的安全功能(这比刚刚描述的功能要有趣的多)。例如,一些令人讨厌的用户会捣乱你的站点。而由于他们的IP地址可以由服务器活动日志中得到,所以你能够使用下面的代码禁止该地址访问:

<%If request.servervariables("REMOTE_ADDR") = "200.200.157.4" then

Response.Buffer = TRUE

Response.Status = ("401 Unauthorized")

Response.End

End If%>

在Active Server Page内部具有许多变量可提供有关发送请求的浏览器的信息,以及有关IIS自身的信息。(要得到服务器变量的详细列表,请参阅Active Server pages联机帮助。)例如, LOGON_USER命令对于验证用户会返回其Domain/Username,对匿名用户返回空格。然后你能够使用服务器端代码检查特定用户并将他们定向到其它页面。我曾经见到过某些公司使用该技术将竞争对手拒之于他们的Web站点之外。

Windows NT挑战/响应(Challenge/Response)

Windows NT挑战/响应是确定发送请求的人员的最安全的方式。挑战/响应的处理流程是所有使用IIS的人员必须掌握的。(我们实际是围绕着Windows NT委托(delegation)过程进行,但在挑战/响应后有委托的最好说明。)

现在说明一个完全不同的技术: "散列(Hash)"

Windows NT挑战/响应验证过程中并不通过网络发送密码,因为密码可能会被截获和破译。Windows NT使用的是一个类似于绞肉机的不可逆算法。输入内容后得到一个散列内容。Windows NT使用Internet标准MD4散列算法生成16字节(128位)的散列值。(理论上)不可能使用散列值和算法在数学上逆转加密过程而得到原密码。也就是说,密码作为了一个“私人密钥(private key)”。只有拥有该密钥的人才能产生一个特定的散列值。Windows NT域控制器有一个数据库存储了由用户密码产生的用户散列值,但并未存储用户密码。 (注意密码和散列值的分离不会使域控制器减少受到黑客攻击的可能,因为有时散列值也可以用作密码的等效物。)

IIS与挑战/响应验证过程

如果下面条件满足时,IIS将使用挑战/响应验证:

  • 如果Internet服务管理器的WWW属性对话框的“允许匿名”选项没有被选中,IUSR帐户没有足够的许可权访问所请求的资源,或者执行代码禁止访问。
  • 在Internet服务管理器的WWW属性对话框中选择Windows NT Challenge/Response
  • 浏览器在挑战/响应验证方式下发送请求 (当前浏览器中只有Internet Explorer支持挑战/响应验证)

当我们说IIS尝试验证用户时,IIS所做的工作非常简单。它向浏览器发回一个"HTTP 401 Access Denied"消息,以及它接受的验证方法列表。与一个高级俱乐部的保镖非常相似, IIS这时会说:"You can't get what you want without identifying yourself. By the way, I accept the following methods of identification.(没有确认您的身份,您不能获得所需要的内容。另外,我支持下列验证方法)"。IIS接受的两种验证方法是挑战/响应验证和基本验证。具体使用哪种方法取决于在IIS的Internet服务管理器WWW属性对话框中的选择。如果两种验证方法都被启用,对于Internet Explorer将一定会使用挑战/响应验证,而对其它浏览器则会使用基本验证。

图1从包的角度显示了如何在没有看到用户密码的情况下对他(她)进行Windows 挑战/响应验证。

图1. Windows NT 挑战/响应验证过程

使用随机散列的挑战信息的原因

增加使用密码散列值加密挑战信息的额外步骤,而不是将简单的散列值传送到域,可以使散列值更难以被截获破译而作为密码使用。因为挑战需要用户密码散列值来产生新的散列值,它证实了用户至少拥有用户散列值 (而且可能还有用户密码)。所有的这些不用通过电线传送密码。实质上,密码成为了私人密钥而随机值成为了不断变化的公共密钥。

委托(Delegation)!

委托是大多数实现Windows NT安全和IIS验证的人员所遗漏的内容,甚至当委托对于其考虑的安全Web服务器环境十分关键的人员,或是简单希望Web服务器能够运行的人员也是如此。当IIS Web服务器扮演一个使用挑战/响应验证的用户时,IIS服务器并没有用户的密码或密码散列值。IIS只看到了传送到域控制器的加密的挑战。当使用ASP页访问另一台Windows NT计算机(比如远程数据库服务器)的资源时很可能遇到这种情况。远程服务器向IIS发送挑战信息以验证自己所扮演的用户,而IIS由于无法使用用户散列值加密任何发送给它的挑战信息,所以无法进行验证。因而远程服务器被禁止访问,而你的数据库驱动的Web页将运行失败。这是Windows NT 4.0 (和以前版本)安全模型的一个限制,不是IIS的原因。使用Windows NT挑战/响应验证,一个依靠扮演的进程将无法像一个文本文件一样访问另一台Windows NT计算机上的太多内容。

如果你希望确定何时需要考虑委托,而如果Web服务器拥有用户密码或散列值,请询问自己。在政策上,你应“根据财力(follow the money)”。在委托上,你应“根据密码(follow the password)”!

对此可以有一个类比,行政主管委托一个秘书代其签名并在其它方面替其行使职责。当用户使用挑战/响应验证时,用户无法委托IIS完全按照其利益工作。这个特别的限制可能在Windows NT 5.0发布后会得到完美解决,因为那时Windows NT集成了Kerberos 验证系统 (该系统为MIT的Athena 项目(Project Athena)开发)。

基本验证(Basic Authentication)

大多数人害怕使用基本验证,这是由于启用基本验证后用户所面对的界面所引起的:

选择该验证方式后,密码不经数据加密就在网络传送。某些想危害你的系统的安全的人员可以使用一个协议分析器(protocol analyzer)在验证过程中截获用户密码。用户验证的详细资料请参阅联机帮助。

你确信要继续?

这个消息的确像看起来的一样糟糕。用户名何密码使用64位(Base-64)编码。即使对于黑客新手,虽然他们仍然要访问你的网络并使用一个TCP/IP包探测器(TCP/IP packet-sniffer)截获网络协议包,64位的加密却是易于破解的。结果黑客们不大可能会攻击你的站点,除非你这里是一个非常吸引人的目标(比如银行)。

我所接触过的大多数Web管理员都了解挑战/响应验证和基本验证的差异,但还是互换性的对待它们。基本验证总是向用户显示对话框要求用户输入用户名和密码。然后输入的信息被发送到IIS,IIS使用该用户名和密码执行一个本地登录命令(Log on locally)命令在所在计算机进行本地登录。因为这时IIS已得到了该用户的密码,所以它能够响应远程系统的挑战信息,这样就消除了委托的问题。(一个实际位于Web服务器的用户使用基本验证,而使用挑战/响应的用户仍能够通过网络访问Web服务器)。实际上,用户权限“从网络访问该计算机(Access this computer from the network”和“本地登录(Log on locally”是需要特别设置的,而且也与所使用的验证方法有关。要设置这些权限,使用域用户管理器(User Manager for Domains)工具,然后在策略(Policies菜单中选择用户权限(User rights

虽然有一些缺陷,但有两种环境还是应该使用基本验证:

  • 你需要验证使用非Internet Explorer浏览器的用户。例如, Netscape Navigator只理解基本验证。如果你选择了挑战/响应验证和基本验证,对于Internet Explorer将一定会使用Windows NT挑战/响应验证,而对于Navigator则会选择基本验证。如果你的数据是敏感数据,这是一个严重的涉及安全的问题。
  • 你的站点对用户进行验证,同时你的ASP页访问其它Windows NT计算机的资源。经典的方式是通过使用ActiveX数据对象(ActiveX Data Objects)的ASP页访问位于远程Windows NT计算机的数据库。为了避免委托的影响,应确保所有请求的资源位于IIS本身所在的计算机上,而如果这不现实的话,就使用基本验证。

普通验证场景

无论何时当使用Windows NT挑战/响应验证一个Internet用户时,当IIS使用UNC (Universal Naming Convention,统一命名约定)路径访问位于网络中或本地的Windows NT 资源时都要考虑委托这个因素。当然,所有的本地资源当该用户拥有正确的NTFS级权限时就能够访问。

UNC 路径

当一个ASP页的代码访问的数据库使用的是基于文件的数据源(比如Access的.MDB文件),而且位置是通过一个UNC路径确定时,会出现一个常见的有关委托的错误。即使资源位于本地,使用UNC标明位置会使Windows NT认为其位于网络中的其他某地。UNC路径由Windows NT网络子系统处理。Windows NT与其各组件有很大的分离,以致如果你逐渐进入网络子系统,直到其它涉及的Windows组件,你会位于网络之外。这导致了一个令人糊涂、但却相当有趣的情景:使用挑战/响应验证的IIS计算机正在访问使用UNC路径的本地资源。在效果上,它从自身请求验证,是无法完成请求的。要解决这个问题,应使用IIS计算机上的绝对路径(例如,C:/folder/resource.ext)。

委托,不!

另外还有一个与委托失败相仿,但实际与委托毫无关系的更为难以确定的有关安全的失败。它发生在一个三级计算机层次(浏览器到Windows NT/IIS服务器到Windows NT 远程资源)。要确定是否错误是委托相关的,应检查是否事务被验证。如果是,问题差不多确定就是委托相关的。不过,如果页面被匿名访问,问题可能是IIS计算机本地的匿名帐户造成的。这很容易发生,因为IUSR_machinename帐户是在本地创建的。IIS扮演IUSR_machinename帐户并尝试访问远程计算机上的资源。挑战信息被传送后,IIS使用IUSR_machinename密码散列值对挑战信息进行正确的加密。不过,由于远程信息会试图使用其本地SAM数据库和本地域控制器验证密码,而由于远程Windows NT 计算机和域控制器都没有记录该帐户,因此不可能验证这些信息。

要避免这个问题,可以尝试下面的方法:

  • 在远程系统中创建一个复制的IUSR_machinename帐户,并确保具有相同的密码。如果在IIS服务器试图访问的计算机上存在一个相同的本地帐户,它不需要一个域控制器的帮助就能验证提交的散列值。即使这两个帐户是在物理上分离的帐户,如果它们的信息匹配,验证还是会发生。你能够侥幸使用这个技术是因为Windows NT所使用的散列算法会对不同用户的两个相同密码产生相同的密码散列值。在UNIX中,不会有这种情况。UNIX引入了一个被称为“salt”的值,这样具有相同密码的两个用户会产生不同的散列值。当你希望IUSR_machinename帐户只能访问你的站点的特定远程资源时,最好设置一个复制的本地帐户。如果某人能够饶过匿名帐户密码,他们也只能访问网络中存在本地帐户的计算机。当然,其缺点在于如果匿名用户需要访问多个远程资源,你会面临管理员的噩梦,因为所有的帐户及其密码必须同步保存。
  • 设置匿名登录帐户为域帐户。要作到这一点,从本地IIS计算机上删除IUSR_machinename 帐户,并在域控制器上创建一个新帐户。然后进入Internet服务管理器的WWW属性对话框,在用户名(Username文本框中以Domain/Username格式(例如,BigDomain/JoeUser)输入用户信息。管理员这是最简单的方法,但是当帐户信息被危及后,侵入者将在网络中获得巨大的访问权限。由于一些原因,我曾经和许多担心IUSR_machinename帐户成为黑客攻击目标的网络管理员进行过讨论。实际上,盗用一个匿名登录帐户名和密码不会比盗用CEO的帐户和密码容易,所以我更喜欢这种方法。
  • SQL Server 具有独一无二的能力实现与其它计算机的非验证联接,可以有效地饶过Windows NT安全。如果安全问题并不是大问题(小型、私有Intranet通常非常安全),你可能希望通过TCP/IP联接到SQL server。SQL server会监视网络传输并对TCP/IP请求直接作出反应,将taking Windows NT out of the loop. SQL具有自己的安全层,所以使用该功能你仍然能够实现一个良好的安全配置。要使用该功能,在安装SQL时在Security对话框中选择TCP/IP sockets

是否需要“安全对话框”的问题!

一些Web开发人员不希望用户在每次访问他们的站点时都必须输入姓名和密码。所以到底何时用户需要提示一个对话框输入他(她)的姓名和密码呢?

当使用Windows NT 挑战/响应验证时,Internet Explorer将自动而且不可视的发送当前用户的登录名、域名和散列值到Web服务器。Internet Explorer不需要请求就进行这些操作,因为发送加密的挑战信息不会带来任何的安全风险。在这时会发生两件事:

  • 如果IIS计算机发送的信息能够被域控制器进行验证,用户不需要可视化的提示就能得到验证。
  • 如果IIS未能识别浏览器发送的域名,那它将不知道需要验证的信息来自何处。这种情况对于Internet用户比Intranet用户更为常见,因为在家中的用户很少位于一个域中(而且即使如果是域用户,其域控制器可能也无法被IIS计算机访问)。Internet Explorer将提示用户输入新的姓名和密码,从效果上讲,"给我一些能够使用的信息(Give me some information that I can use)。" 如果一个在家工作的雇员试图访问一个设置安全的站点,他将需要输入他的姓名(按照BigDomain/JoeUser的形式)和密码以使IIS能够得到正确的域信息。在验证Internet的用户时以这种方式明确说明域名总是必要的。

在基本验证方式中,用户将被提示出现一个登录对话框。你或许可以猜测一下原因。你将要做的事可能会危及你的Windows NT帐户和密码。所有的浏览器都明确的指出:如果你输入了信息并按下OK,你必须知道你在做什么。我个人在一个安全的集成网络中使用基本验证并没有问题,但如果没有诸如Secure Sockets Layer(安全套接字)的附加安全层我将不会在Internet上使用基本验证。Secure Sockets Layer在使用HTTPS://而不是HTTP://的特殊配置Web服务器上被调用。用户再次需要明确说明所提交的带有某个域控制器的信息。

黑客与你的站点

在我更进一步的说明之前,我需要声明不做承诺:是的,积极的年轻黑客会读到这篇文章并得到启发,但是,相信我,对于黑客有许多比本文更好的信息来源。确保你的站点真正安全的最佳方法是了解站点的弱点何在(没有人能比黑客更了解站点的薄弱之处)。在一个Web站点上有几个区域可能被黑客尝试攻击或浏览。很明显,在他们的手边拥有一个具有管理员权限的用户名和密码是最佳的方法。得到一个用户的密码散列值也一样好,因为密码散列值有时可作为“密码等效物”使用。密码散列值可通过加密挑战信息而用于回答挑战。这样做会赋予入侵者“从网络访问该计算机(Access this computer from the network”权限。要被赋予“本地登录(Log on locally”权限,入侵者仍然需要实际的密码。

一些程序已经被编写出来特别用于抽取和破解Windows NT 域控制器SAM数据库的密码散列值。PWDump.exe和NTCrack.exe 都是在Internet上免费的且被系统管理员和黑客使用的该类程序。PWDump.exe程序用于将SAM数据库的用户散列值和帐户信息转写到一个文本文件中。系统管理员使用PWDump 在混合环境中(比如UNIX和Windows NT共存)同步网络服务器间的密码列表,避免了在不同操作系统间使用不同的密码。黑客使用PWDump和NTCrack对一个网络执行恶意攻击。黑客们通常自己不会运行PWDump,因为运行该程序需要有管理员级的权限(而如果一名黑客已经拥有管理员密码,他也不需要运行PWDump)。不具有对网络的管理员级访问权的黑客可以创建一个特洛伊木马(Trojan-horse)程序并将其通过e-mail发送给一个不受怀疑的用户。如果该用户以管理员权限登录后运行e-mail 中的附带程序,该程序将悄然无声地复制SAM数据库后将文本文件通过e-mail传送给黑客。(最近我收到的一封电子邮件附带的程序说: "click here"。我可以让你猜猜如果我点击那里会发生什么。)

即使黑客得到了PWDump的输出结果,他们仍然没有任何密码。他们使用NTCrack 对密码散列值表实行强行攻击。NTCrack能够从英文字典中搜寻所有单词,使用数字和字母大小写进行复杂的变换,在通常的Pentium计算机中运行数小时,产生上百万个单词和短语的所有可能散列值。然后它将文件中的散列值与从PWDump检索到的散列值进行匹配,确定产生该散列值的密码。记住即使MD4散列算法理论上是不可逆的,但NTCrack是基于一个事实:人们趋向于选择易于记忆的密码。如果NTCrack不得不按照Windows NT14个字符(包括数字、符号和大小写)的最大密码长度强行攻击所有可能的密码散列值,搜索过程在Pentium 120计算机上将要耗费几十亿年。(我不知是否有人曾经计算过在Pentium Pro计算机上所要耗费的时间,但我想在一定的短时期内还是安全的。) 如果你希望得到有关安全要素的更多的信息,请在Internet上搜索NTCrack或PWDump的内容。我个人喜欢在我的系统中使用NTCrack以确保密码列表是安全的以及我的用户选择了安全的密码。 

结束语

我希望现在你对于影响Web开发的Windows NT安全的因素有了更好的认识。本主题面向站点最常见的使用验证和动态传输、数据库驱动内容。本文讨论了安全的内部基础和委托。以后的文章将建立在对这些内容的理解之上,并提出更为特定的配置因素和问题。如果你已经对IIS为完成工作所做的一切有了较好的了解,你将会把工作完成的更好。

编程愉快。

 
0 0

相关博文

我的热门文章

img
取 消
img