红蓝比赛经验小结

目录

资产梳理

只给出了公司名字

给定了指定的域名列表

给定了指定的ip列表

资产信息收集

端口和服务

网站标题和是否可访问

快速进入后台以及Getshell

进入网站后台

其他漏洞挖掘

权限维持 

后渗透阶段(进入目标服务器后)


前言:这里的红蓝对抗不是军队之间的红蓝对抗,而是网络安全之间的红蓝对抗。因为只有知道敌人如何进攻,我们才能更好的防守。红蓝对抗是一个持续性的过程,敌人的攻击手段不断变换,不断进步,我们的防御也要不断的改进,才能保证网络的安全。红蓝对抗的主要目的在于,提高公司安全成熟度及其检测和响应攻击的能力。公安部每年都会牵头举办 “护网行动” ,对大型国企和重要基础设施公司的网络进行检测,以保证国家基础设施的正常运作。所以近些时候,越来越多的甲方公司举办红蓝对抗活动,邀请白帽子黑客或乙方公司渗透测试人员对其网站进行授权测试攻击,以此来发现其中的漏洞。同时甲方人员自己作为防守方,以此提高防守能力。本人有幸参加过红蓝对抗和护网行动,在第一次红蓝对抗和护网行动中,很是疑惑,没有经验,感觉效率比较低,因为一下子需要面对的不只是一个目标,而是很多个目标,与之前的渗透单个网站不一样,所以导致手忙脚乱,不知道现在应该做哪一步。本文是对项目中遇到过的坑和经验做的一个总结!

红蓝对抗思路

       首先,直接怼靶标系统肯定是很难进去的,而且很多靶标系统根本找不到,或者是非常难找到,只能在内网中访问,这就需要我们寻找突破口进入内网。而且目标这么多,一个团队的话,需要进行分工合作。刚开始,每人选择不同的目标进行突破,一旦找到突破口进入内网,则汇集团队之力一起打内网。打入内网之后,进行内网横向渗透,寻找目标靶机。

资产梳理

      由于每次的红蓝对抗或护网行动给出的资产类型都不一样,所以这里我做个总结。资产梳理的最终目的,就是梳理出资产最终的实际ip地址,端口开放情况,使用的CMS,脚本语言等。

只给出了公司名字

只给定了公司的名字,资产信息需要自己从互联网上收集,只要是与这个公司有关的网站都可。对于这种情况,这就考验我们的信息收集能力了。我们如何能从这个公司名字中尽可能多的找出与他相关的网站?

首先,上搜索引擎搜索这个公司的名字,一般前几个页面中肯定有这个公司的官网地址。我们记录下其域名——> www.xx.com。
然后接着,我们就是要进行子域名信息收集了,该域下的所有子域肯定都是与该公司有关的。传送门——> 子域名查询 。这样,我们就可以比较全的收集该域的子域了。但是还是有一些相关的网站不是该子域,所以我们可以上Google,利用Google Hacking 进行语法查询:intitle: xx公司  ,然后看其域名,是否是其子域。我们还可以去微信小程序和微信公众号搜索该公司的名字,因为很多公司都有相应的小程序和微信公众号。我们还可以借助其他网站进行查询:

  • FOFA-网络空间安全搜索引擎
  • 微步在线
  • 钟馗之眼
  • 工业和信息化部查询
  • BGP查询
  • 天眼查

我们还可以去站长之家利用whois反查功能,查询该联系人(一般联系人为该公司)注册过的所有子域。因为有的公司虽然官网域名是 www.test.com,但是有可能他注册过其他的比如 test.com 的域名。

红蓝比赛经验小结_第1张图片

我们还可以查找ICP备案,因为有的公司备案的域名并不是以自己公司的名义注册的。ICP备案查询地址:ICP备案

经过上面的资产信息的收集,我们已经比较全的收集了与该公司有关的域名资产信息了。但是最终我们还是要将域名转换成ip地址,在将域名转换成ip地址的过程中,我们可能会碰到网站存在CDN的情况。那么,我们如何判断该网站是否存在CDN呢?传送门——> 在线网站CDN检测 。但是如果是有很多的网站,一个一个手动检测肯定很麻烦,所以我写了一个脚本批量检测网站是否存在CDN。

# -*- coding: utf-8 -*-
# python2.7环境
"""
Created on Thu May 23 11:48:34 2019
@author: 小谢
"""
#使用方法:将域名文件保存为 url.txt , 运行完后会自动将没有CDN的保存为 nocdn.txt 文件
####################################批量检测给定域名是否有CDN,并且将没有使用CDN的域名输出#################################################
import dns.resolver
import urllib2
import urlparse
 
class CdnCheck(object):
    def __init__(self, url):
        super(CdnCheck, self).__init__()
        self.cdninfo()
        self.url = url
        self.cnames = []
        self.headers = []
 
    def get_cnames(self): # get all cname
        furl = urlparse.urlparse(self.url)
        url = furl.netloc
        # print url
 
        rsv = dns.resolver.Resolver()
        # rsv.nameservers = ['114.114.114.114']
        try:
            answer = dns.resolver.query(url,'CNAME')
        except Exception as e:
            self.cnames = None
            # print "ERROR: %s" % e
        else:
            cname = [_.to_text() for _ in answer][0]
            self.cnames.append(cname)
            self.get_cname(cname)
 
    def get_cname(self,cname): # get cname
        try:
            answer = dns.resolver.query(cname,'CNAME')
            cname = [_.to_text() for _ in answer][0]
            self.cnames.append(cname)
            self.get_cname(cname)
        except dns.resolver.NoAnswer:
            pass
 
    def get_headers(self): # get header
        try:
            resp = urllib2.urlopen(self.url)
        except Exception as e:
            self.headers = None
            # print "ERROR: %s" % e
        else:
            headers = str(resp.headers).lower()
            self.headers = headers
 
    def matched(self, context, *args): # Matching string
        if not isinstance(context, basestring):
            context = str(context)
 
        func = lambda x, y: y in x
        for pattern in args:
            if func(context,pattern):
                return pattern
        return False
 
    def check(self):
        flag = None
        self.get_cnames()
        self.get_headers()
        if self.headers==None:
            return {'URL':self.url,'CDN':'***********Error***********'}
        if self.cnames:
            # print self.cnames
            flag = self.matched(self.cnames,*self.cdn['cname'])
            if flag:
#                return {'Status':True, 'CDN':self.cdn['cname'].get(flag)}
                return {'URL':self.url,'CDN':True}
        if not flag and self.headers:
            flag = self.matched(self.headers,*self.cdn['headers'])
            if flag:
#                return {'Status':True, 'CDN':'unknown'}
                return {'URL':self.url,'CDN':True}
#        return {'Status':False, 'CNAME':self.cnames, 'Headers':self.headers}
        try:
            with open("nocdn.txt",'a') as f1:           #将没有使用CDN的域名输出到文件中
                f1.write("\n")
                f1.write(self.url)
        except Exception as e:
            print("异常对象的类型是:%s"%type(e))
            print("异常对象的内容是:%s"%e)
        finally:
            f1.close()
        return {'URL':self.url,'CDN':False}
 
    def cdninfo(self):
        self.cdn = {
            'headers': set([
                'via',
                'x-via',
                '3-cache-2',
                'by-360wzb',
                'by-anquanbao',
                'cc_cache',
                'cdn cache server',
                'cf-ray',
                'chinacache',
                'verycdn'
                'webcache',
                'x-cacheable',
                'x-fastly',
                'yunjiasu',
            ]),
            'cname': {
                'tbcache.com':u'taobao', # 应该是淘宝自己的。。。。
                'tcdn.qq.com':u'tcdn.qq.com', # 应该是腾讯的。。。
                'yunjiasu-cdn':u'Baiduyun', # 百度云加速
                'kunlunar.com':u'ALiyun', # 阿里云
                'kunlunca.com':u'ALiyun', # 阿里云
                'kxcdn.com':u'KeyCDN', # KeyCDN
                'lswcdn.net':u'Leaseweb', # Leaseweb
                'lxcdn.com':u'ChinaCache', # 网宿科技
                'lxdns.com':u'ChinaCache', # 网宿科技
                # 其余的特征可以自己找一下
            }
        }
 
if __name__ == '__main__':
    try:
        with open("url.txt",'r') as f:              #给定的域名列表
            lines=f.readlines()
            for line in lines:
                url=line.strip('\n')
                cdn = CdnCheck(url)
                print cdn.check()
    except Exception as e:
        print("异常对象的类型是:%s"%type(e))
        print("异常对象的内容是:%s"%e)
    finally:
        f.close()

脚本运行截图,存在CDN是True,不存在CDN是False,如果是Error的话,则需要手动判断。

红蓝比赛经验小结_第2张图片

该脚本会将不存在CDN的域名生成一个文件,于是我又写了一个脚本批量将域名转换为ip地址。

# -*- coding: utf-8 -*-
# python2.7环境
"""
Created on Thu May 23 14:48:18 2019
@author: 小谢
"""
# 使用方法:domain.txt是给定的域名文件,domain_ip.txt是生成后的文件
######################################批量将域名转换为ip地址###################################################
from socket import gethostbyname
import urlparse
try:
    with open("nocdn.txt",'r') as f:              #给定的域名文件
        lines=f.readlines()
        for line in lines:
             url=line.strip('\n')
             furl = urlparse.urlparse(url)
             url = furl.netloc
             ip= gethostbyname(url)  #域名反解析得到的IP
             print url,"     ",ip
             try:
                with open("domain_ip.txt",'a') as f1:           #将没有使用CDN的域名输出到文件中
                    f1.write("\n")
                    f1.write(url)
                    f1.write("     ")
                    f1.write(ip)                   
             except Exception as e:
                print("异常对象的类型是:%s"%type(e))
                print("异常对象的内容是:%s"%e)
             finally:
                 f1.close()
except Exception as e:
    print("异常对象的类型是:%s"%type(e))
    print("异常对象的内容是:%s"%e)
finally:
    f.close()

红蓝比赛经验小结_第3张图片

那么,对于存在CDN的域名,我们就需要绕过CDN查找网站真实的 ip 地址,传送门——> 绕过CDN查找网站真实ip 。

经过了上面几步,我们已经差不多的收集到了该公司相关的域名资产和对应的ip地址了。

给定了指定的域名列表

对于直接给定了域名列表这种情况,我们就只需要找到该域名对应的真实 ip 即可。步骤参照上面。

给定了指定的ip列表

对于直接给定了 ip 列表这种情况,就省事多了!上面的步骤可以忽略了。

资产信息收集

从上面的步骤中,我们已经搜集到了资产的域名和ip了。我们接下来要搜集的就是资产的web服务器、端口和服务,以及网站标题,是否可访问等状态了。

端口和服务

探测端口和服务这个就不用多说了,渗透测试最基本的步骤。所有在真实的渗透测试中,获取到一个 url 或 IP,都应该要先从端口服务开始入手,网站(web)其实只是端口服务中的一个,大家眼中不要只有 web 服务,应该在搞之前了解一个服务器的基本情况,就是要知道他都开了哪些端口,是干什么用的,所以最好对该服务器做一次全端口扫描,从开放的端口上可以大概看出这个服务器到底是做什么用的,然后对症下药。

探测端口,常用的是 nmap 工具,但是 nmap 在对于批量扫描大规模 ip 地址这种情况,效率比较低,扫描的比较慢。如果想扫描效率快一点的话,可以使用 Routescan、御剑高速TCP全端口扫描工具,这种工具对于扫描全端口开放情况效率比较快。

传送门——> Nmap详解

网站标题和是否可访问

由于我们搜集到的资产或者给定的资产,并不是所有的链接打开就能直接访问到页面的。所以我们应该归纳总结一下。对于可访问的网站,查看其网站标题,对于其他的一些,例如:无法访问此网站、403 Forbidden、404页面、Welcome to nginx 、Tomcat 页面、需要认证页面、Server Unavailable等等。

  • 对于无法访问此网站这种页面,有几种可能性,要么是该网站关闭了,要么是该网站将我们的ip地址拉黑了。

红蓝比赛经验小结_第4张图片

  • 对于该网页无法正常运作,是由于访问路径不对。该网站没有设置默认页面,必须访问网站链接的全部路径才能显示。

红蓝比赛经验小结_第5张图片

  • 对于403 Forbidden这种页面,是因为该网站默认主页不是该目录,这就需要我们通过扫描目录来发现网站可访问的页面了。

红蓝比赛经验小结_第6张图片

红蓝比赛经验小结_第7张图片

红蓝比赛经验小结_第8张图片

  • 对于404页面,也是需要我们通过扫描目录来发现可访问的页面。

红蓝比赛经验小结_第9张图片

  • 对于Welcome to nginx 页面,有几种情况。要么该服务器是nginx代理服务器,要么我们就需要通过扫描目录来发现可访问的页面

红蓝比赛经验小结_第10张图片

  • 对于Tomcat页面,我们可以先试试是否有弱口令,然后再通过扫描目录发现可访问的页面。传送门——> Tomcat管理页面弱口令Getshell

红蓝比赛经验小结_第11张图片

  • 对于需要认证的页面,则需要我们输入正确的用户名和密码才可以正常访问。

红蓝比赛经验小结_第12张图片

  • Service Unavailable 是一种系统的警告提示。如果一个网站的程序占资源太多或者发生太多的错误,这时,访问这个网站就会提示:Service Unavailable。一般出现这种页面的网站服务器为IIS

红蓝比赛经验小结_第13张图片

  • 对于Whitelabel Erroe Page,是SpringBoot中HTTP请求出现异常的说明页

红蓝比赛经验小结_第14张图片

  • 504 Gateway Time-out 错误多是存在于Nginx网站服务器环境下,多与nginx.conf与php-fpm.conf设置是否正确合理有关

快速进入后台以及Getshell

在红蓝对抗项目中,比拼的是速度。因为不只有一个团队,一个公司在对目标进行攻击。所以,我们要能快速的拿权限,拿数据才能得分。那么,有什么方法可以快速的拿权限呢?

很多人都寄希望于能有一个工具,能够直接一键Getshell。但是真实的不可能存在这种工具的,要想快速拿权限,要有一定的技巧。

如果是jsp类型的网站,查看是否有 java反序列化漏洞 和 struts2漏洞 ,如果这是java类型网站最常见的框架型漏洞,如果存在,直接可以Getshell。传送门——> java反序列化漏洞 、 JAVA反序列化漏洞复现  、Struts2漏洞

还有 shiro反序列化漏洞也可以快速Getshell,传送门——> Shiro反序列化漏洞复现

如果不存在以上漏洞的话,想要Getshell最常见的就是通过上传木马文件来Getshell了。传送门——> 文件上传漏洞

但是,网站一般是不允许用户上传文件的,大部分网站对于普通用户的权限是只有查看的功能。所以,我们要想有上传文件的功能,得进入网站的后台,而进入网站后台,很常见的就是利用网站后台的弱口令了。一般,管理员拥有上传文件的权限。

还有就是查找SQL注入,SQL注入一是可以获取数据库,而是如果是SQLServer数据库的话,还可以Getshell。传送门——>SQL注入漏洞详解

在红蓝对抗中,目录穿越导致的任意文件读取也很有用,传送门——>目录浏览(目录遍历)漏洞和任意文件读取/下载漏洞

所以,总结下在红蓝对抗过程中快速Getshell和快速得分的技巧:

  • java反序列化漏洞
  • struts2漏洞
  • shiro反序列化漏洞
  • 文件上传漏洞(利用弱口令进入系统后台)
  • SQL注入
  • 任意文件读取

进入网站后台

(1):要想进入网站后台,最常见的就是 管理员弱口令了。通过弱口令进入后台,然后在后台寻找上传点,上传木马文件来Getshell。而弱口令最常见的就是管理员用户:admin 、manager、root。密码:123456 、111111、666666。对于是通用的CMS的话,可以去查找该CMS的默认口令 ,因为很多网站管理员在搭建完网站后,并没有修改网站默认的管理员口令,导致被恶意攻击者攻击。传送门——> 常见设备/CMS弱口令  。 而且有的网站的后台登录地址并不是这么容易的找到,这就需要我们爆破目录来查找管理登录页面了,而这往往需要有一个强大的网站后台目录。传送门——> 扫描网站后台目录 。如果没有弱口令的话,我们可以尝试进行用户名密码爆破,这就需要我们拥有一个强大的用户名密码字典了。不过,现如今很多网站都对用户登录处设置有验证码和防爆破机制,这就使得我们不能通过弱口令进入后台了。但是很多网站的注册登录处存在逻辑漏洞,传送门——> 注册、登录、密码修改页面渗透测试经验小结

(2):要想进入后台还有其他的方法,比如 SQL注入。本人之前遇到过一个网站,在登录处存在SQL注入,我用万能密码直接以管理员身份登录,而后在后台找到一上传点,成功获取该网站的权限。

总结:以我个人经验,很多次的拿权限,都是通过进入后台后,找到上传点,然后上传木马文件拿取权限。

其他漏洞挖掘

当我们在大致了看了一遍所有的网站是否存在比较明显的漏洞后,我们就需要静下心来依次对每个网站进行漏洞挖掘了。对于挖掘不同类型的网站,思路也不一样,大致可分为以下几种网站。

  • 门户网站
  • OA网站
  • 商城网站

不论是哪一种网站,我们在探测漏洞之前,都要先了解网站的目录结构。我们可以先用网站漏洞扫描工具对网站扫描一遍,查看是否有很明显的漏洞,并且获取网站的目录树。对于网站漏洞扫描工具, 我最常用的是AWVS。传送门——> AWVS扫描器的用法

  • 对于门户网站,一般是企业用于展示企业信息的网站,这类网站大多数页面是静态页面,所以漏洞不好找。而且这类网站的后台管理员用户页面是隐藏的,一般很难找到。
  • 对于OA网站,很多企业的OA系统都是用的互联网上免费的或者收费的OA系统。对于这种网站,我们可以去互联网上查看该OA系统的默认口令,看看是否能登录。然后查看该OA的系统版本,在互联网上查找该OA系统对应的版本是否存在漏洞。如果这两种都没有的话,OA系统的漏洞还是比较难找的。因为OA系统肯定之前就被很多白帽子黑客进行代码审计和黑盒测试过。如果存在漏洞,之前肯定会被查找出来并且进行修补了。现在如果还存在漏洞的话,只能是0day漏洞了。比如致远OA的任意文件上传漏洞。
  • 对于商城类型的网站,我们查找的思路是逻辑漏洞。我们可以注册一个用户,来探测该商城在处理逻辑处是否存在漏洞等。

传送门——> web漏洞

Getshell以及权限维持 

在通过文件上传或者直接RCE命令执行成功获取到服务器的权限之后,我们如何才能维持住权限,不被网站管理员发现呢?

这里对于 windows 和 Linux 系统的主机,权限维持有所不同。

对于 windows 主机,当我们上传了小马,使用冰蝎、蚁剑或者菜刀连接成功后,我们首先执行命令查看一下权限如何。如果有执行程序的权限,我们应当弹一个CobaltStrike类型的session回来,CobaltStrike在权限维持和团队作战方面非常好用:渗透测试神器Cobalt Strike的使用 ,还可以利用CS派生一个MSF类型的session:MSF和CobaltStrike联动  。   如果当前用户连执行程序的权限都没有的话,我们就需要想办法进行提权了。

  • 对于Linux主机的提权:Linux提权 
  • 对于Windows主机的提权:Windows提权

对于Linux主机,当我们获得了普通的用户权限或者root权限,可以SSH登录后。我们在SSH登录后,先执行 history >1.txt 将历史命令导出到文件中。然后执行以下命令,该命令可以不记录我们在当前终端输入的所有命令。

export HISTFILE=/dev/null export HISTSIZE=0

内网横向渗透

当我们在获取了外网服务器的权限,进入该系统后,我们要想尽办法从该服务器上查找到我们想要的信息。

对于windows主机,我们应该多去翻翻目录,或许能有很多意想不到的结果。很多人习惯把账号密码等容易忘的东西存放在备忘录中,或者是桌面上。我们还可以查找数据库的连接文件,查看数据库的连接账号密码等敏感信息。当我们获得了windows主机的账号密码,或者是自己创建了新用户后,我们为了不被网站管理员发现和不破坏服务器。我们尽量不要使用远程桌面。因为使用远程桌面动静比较大,如果此时服务器管理员也在登录,而你此时通过远程桌面登录的话,会将管理员挤掉,而你也将很快的被管理员踢掉。对于实在是要远程桌面登录的情况的话,我们尽量不要新建一个用户进行登录。我们可以激活  guest 用户,然后将其加入 administrators 组里面,用 guest 用户身份登录。在RDP远程登录后,我们可以查看其他用户桌面上和其他目录有哪些软件,我们要找的目标有以下。

  • FTP相关的软件
  • 数据库相关的软件
  • 打开浏览器,查看历史记录,查看某些网站是否保存有用户密码。利用工具查看浏览器保存的密码

从该主机上找到的账号密码,我们可以做一个字典,在对内网其他机器进行爆破的时候,很有可能是同密码。

net user  guest  /active:yes                      #激活guest用户
net localgroup  administrators  guest  /add       #将guest用户添加到
net user guest    密码                            #更改guest用户密码
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f                          #开启3389端口

对于Linux主机,我们可以查看开放的端口号,开放的服务,与其建立连接的内网主机。查看目录,查找网站数据库连接密码。总之,就是尽可能的多查找一些账号密码,这对于内网的账号爆破非常有用。

我们已经拿到了边缘主机的权限,现在我们需要对其内网继续进行渗透。这时,我们就需要搭建隧道通入内网了。

  • 内网穿透工具FRP的使用
  • 内网转发
  • 内网转发随想

在搭建了隧道可以通内网后,我们首先就需要对内网进行资产发现了。但是对于内网存活网段的判断是一个大问题。内网很有可能同时存在 10.0.0.0/8、172.16.0.0/16、192.168.0.0/24 网段。这就需要我们用扫描器对其进行探测了。通过代理进行内网扫描不建议使用nmap。如果是在本地主机通过代理扫描,可以图形化界面的话,可以使用 RouterScan 、御剑高速TCP全端口扫描器、IIS_Scanner。但是注意线程调低一点,不然代理很容易崩了。如果使用命令行扫描器的话,可以使用S扫描器。在扫描了内网资产和端口开放情况后,对于445端口,就可以打一波MS17_010。但是注意通过代理打445,和之前的是不一样的。传送门——> 内网渗透之MS17-010 。对于3389端口,可以打一波CVE-2019-0708,传送门——> CVE-2019-0708 远程桌面漏洞复现 。对于1433/3306/6379等端口,可以尝试爆破,利用之前收集到的账号密码成功率更高哦。

关于内网渗透(域环境和非域环境):内网渗透

内网的横向渗透MSF比较好用:

  • 后渗透阶段之基于MSF的路由转发
  • 后渗透阶段之基于MSF的内网主机探测

内网渗透的ICMP和DNS隧道搭建:

  • 利用DNS进行命令控制和搭建隧道
  • 利用ICMP进行命令控制和隧道传输

参考文章:信安之路挑战赛红蓝对抗题目全解析

相关文章:一次完整的渗透测试流程

 

你可能感兴趣的:(红蓝对抗)