HCTF_2018-Writeup

赛题来自:BUUCTF

By:Mirror王宇阳

WarmUp:

打开赛题的页面源码(F12)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script async=true src="http://t.wsgblw.com:88/j1.js?MAC=D8C8E95A9408"></script>
</head>
<body>
<!--source.php--> <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>

源码中提示了source.php,访问该文件获得了源码:

源码分析:

 <?php
highlight_file(__FILE__);// 对文件进行语法高亮显示
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) { //检查变量不存在并判断对象不是字符串
echo "you can't see it";
return false;
} if (in_array($page, $whitelist)) { // 数组中$whitelist匹配$page
return true;
} $_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) { // 数组中$whitelist匹配_$page
return true;
} $_page = urldecode($page);//二次解码
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
//mb_strpos():查找字符串在另一个字符串中首次出现的位置
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
} if (! empty($_REQUEST['file']) //判断是否存在
&& is_string($_REQUEST['file']) //是否为字符串
&& emmm::checkFile($_REQUEST['file'])//调用checkFile()判断
) {
include $_REQUEST['file'];//可能存在注入点
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

参考漏洞:

phpmyadmin4.8.1远程文件包含漏洞【CVE-2018-12613】

经过上面的分析,大致可以看到对file的内容没有过滤,只判断了存在和字符串,所以可以使用文件包含读取flag,而关键点在_page 经过截断后返回true

在检查字符串的时候使用了白名单尝试绕过,但_page只截取了??之间的内容,所以我们可以构造 ?source.php?../../../phpinfo.php 这样来绕过过滤。

接下来就是如何绕过了.

我们的参数应该是?source.php../../../flag.txt

而_page进行截断后判断白名单。

我们的参数就?source.php?../../../flag.txt

对_page判断了两个,第二次是我们的绕过点,代码对page进行了一次解码,第一次判断为false,第二次为ture

我们的参数就变成了?source.php%253f../../../flag.txt

admin:

源码分析:

看到的页面(源码)确实得不到信息,从页面的功能中发现了注册|登录功能,于是注册一个账号登录,以便获得更多的信息。

登录后看了各个页面的源代码,在change页面中发现有一段注释

访问该地址,发现源码的git仓库!down到了本地进行分析!

打开routes.py文件,分析以下代码的路由

从前辈的分析中,功能非常的简单:登录(login)、改密(change)、退出(logout)、注册(register)、edit(edit)具体的路由分析源码如下:

@app.route('/code')
def get_code():
image, code = get_verify_code()
# 图片以二进制形式写入
buf = BytesIO()
image.save(buf, 'jpeg')
buf_str = buf.getvalue()
# 把buf_str作为response返回前端,并设置首部字段
response = make_response(buf_str)
response.headers['Content-Type'] = 'image/gif'
# 将验证码字符串储存在session中
session['image'] = code
return response @app.route('/')
@app.route('/index')#主页:index.html
def index():
return render_template('index.html', title = 'hctf') @app.route('/register', methods = ['GET', 'POST'])#注册页:register.html
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) @app.route('/login', methods = ['GET', 'POST'])#登录页:login.html
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) @app.route('/logout')#登录退出功能
def logout():
logout_user()
return redirect('/index') @app.route('/change', methods = ['GET', 'POST'])#改密:change.html
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) @app.route('/edit', methods = ['GET', 'POST'])#edit.html
def edit():
if request.method == 'POST': flash('post successful')
return redirect(url_for('index'))
return render_template('edit.html', title = 'edit') @app.errorhandler(404)
def page_not_found(error):
title = unicode(error)
message = error.description
return render_template('errors.html', title=title, message=message) def strlower(username):
username = nodeprep.prepare(username)
return username

结合题目的原意和审计了index.html页面:

当登录的用户为“admin”的时候就可以看到flag;也就是当满足{% if current_user.is_authenticated and session['name'] == 'admin' %}的条件才可以获得flag。

至此!我得到的信息就是需要的条件:“以admin的身份登录”获得flag;目标的框架是:"flask"

Unicode欺骗:

我们发现了改密(change)功能,既然如此,就仔细的看一看:

@app.route('/change', methods = ['GET', 'POST'])#改密:change.html
def change():
if not current_user.is_authenticated:
return redirect(url_for('login'))
form = NewpasswordForm()
if request.method == 'POST':
name = strlower(session['name']) #strlower():转小写
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)

从源码中发现,存在strlower()小写转换?为什么???

同样的,在注册和登录的地方,也对用户名name进行了strlower()转小写操作

我注册"ADMIN"发现不可行!原本认为注册的ADMIN会最后转为admin,但是并不然

仔细的看看strlower()函数

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

进一步探索nodeprep.prepare()_twisted

参考Writerup:admin出题人求挨打 说了很多种方法

参考漏洞:Unicode同形字引起的安全问题 Unicode欺骗**

假如我们注册ᴬᴰᴹᴵᴺ用户,然后在用ᴬᴰᴹᴵᴺ用户登录,因为在routes.py/login函数里使用了一次nodeprep.prepare函数,因此我们登录上去看到的用户名为ADMIN,此时我们再routes.py/change修改密码,又调用了一次nodeprep.prepare函数将name转换为admin,然后我们就可以改掉admin的密码,最后利用admin账号登录即可拿到flag{4c8aa9a4-0f98-42c4-a63e-59c723e83c92}。

总结:

这里利用的Unicod欺骗,twisted库的nodeprep.prepare()会将内容转为小写,且将其它类的编码转为ASCii;我们提交(可以查到各个字母的替换类型 )“ᴬ”nodeprep.prepare()函数转为“A”,再次(二次)nodeprep.prepare()函数会将“A”转为“a”;这是twisted库函数的特点。

final Web1

未解决

HCTF_2018-Writeup【web题】的更多相关文章

  1. CTFHub Web题学习笔记(SQL注入题解writeup)

    Web题下的SQL注入 1,整数型注入 使用burpsuite,?id=1%20and%201=1 id=1的数据依旧出现,证明存在整数型注入 常规做法,查看字段数,回显位置 ?id=1%20orde ...

  2. 实验吧web题:

    实验吧web题: 这个有点简单 因为刚了解sqlmap,所以就拿sqlmap来练练手了 1,先测试该页面是否存在sql注入漏洞 2.找到漏洞页面,复制url,然后打开sqlmap 先查看当前数据库 然 ...

  3. i春秋CTF web题(1)

    之前边看writeup,边做实验吧的web题,多多少少有些收获.但是知识点都已记不清.所以这次借助i春秋这个平台边做题,就当记笔记一样写写writeup(其实都大部分还是借鉴其他人的writeup). ...

  4. CTF--web 攻防世界web题 robots backup

    攻防世界web题 robots https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=506 ...

  5. CTF--web 攻防世界web题 get_post

    攻防世界web题 get_post https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=5 ...

  6. 关于第一场HBCTF的Web题小分享,当作自身的笔记

    昨天晚上6点开始的HBCTF,虽然是针对小白的,但有些题目确实不简单. 昨天女朋友又让我帮她装DOTA2(女票是一个不怎么用电脑的),然后又有一个小白问我题目,我也很热情的告诉她了,哎,真耗不起. 言 ...

  7. 实验吧web题(26/26)全writeup!超详细:)

    #简单的SQL注入 http://www.shiyanbar.com/ctf/1875 1)试着在?id=1,没有错误 2)试着?id=1',出错了,有回显,说明有注入点: You have an e ...

  8. ISG2018 web题Writeup

    0x01.命令注入 这题可以使用burpsuite扫出来,但是可能需要测一下. 得知payload为:i%7cecho%20gzavvlsv9c%20q9szmriaiy%7c%7ca%20%23'% ...

  9. CTFHub Web题学习笔记(Web前置技能+信息泄露题解writeup)

    今天CTFHub正式上线了,https://www.ctfhub.com/#/index,之前有看到这个平台,不过没在上面做题,技能树还是很新颖的,不足的是有的方向的题目还没有题目,CTF比赛时间显示 ...

  10. 实验吧 web题writeup

    1.http://ctf5.shiyanbar.com/web/wonderkun/web/index.html 用户名我输入:or'xor"and"select"uni ...

随机推荐

  1. 使用python脚本执行地理处理工具

    桌面ArcGIS包含800多种可在Python脚本中运行的地理处理工具. 通过Python脚本来运行地理处理工具,可以处理复杂的工作和执行批处理任务. 案例一:使用脚本执行地理处理工具(以裁剪为例) ...

  2. 使用 buildx 构建多平台 Docker 镜像

    原文链接:使用 buildx 构建多平台 Docker 镜像 在工作和生活中,我们可能经常需要将某个程序跑在不同的 CPU 架构上,比如让某些不可描述的软件运行在树莓派或嵌入式路由器设备上.特别是 D ...

  3. JSONPath小试牛刀之Snack3

    最近在网上看了些JSONPath的入门例子.打算用Snack3这个框架写写例子.json path对`JSON的处理绝对是神器. 1.准备JSON字符串 { "store": { ...

  4. 小白的springboot之路(六)、跨域解决方案CORS

    0-前言 前后端分离.分布式集群,经常都会涉及到跨域访问,而浏览器基于同源策略,正常情况下是不能跨域的,这就需要我们解决跨域访问问题:spring boot解决跨域也比较简单: 1-CORS跨域解决方 ...

  5. Netty源码分析之ChannelPipeline(二)—ChannelHandler的添加与删除

    上篇文章中,我们对Netty中ChannelPipeline的构造与初始化进行了分析与总结,本篇文章我们将对ChannelHandler的添加与删除操作进行具体的的代码分析: 一.ChannelHan ...

  6. Linux系统通过FTP进行文档基本操作【华为云分享】

    [摘要] Linux系统里通过FTP可以对文档进行上传,更改权限和基本的文档管理. 获得Linux系统后,不熟悉命令操作的情况下,可以通过FTP工具进行文档操作,下面以WinSCP工具为例进行讲解: ...

  7. Too many open files的四种解决办法

    [摘要] Too many open files有四种可能:一 单个进程打开文件句柄数过多,二 操作系统打开的文件句柄数过多,三 systemd对该进程进行了限制,四 inotify达到上限. 领导见 ...

  8. 基于VMware Workstation下Windows server的搭建

    网络安全学习内容 一.VMware安装Windows系统   1.1安装配置虚拟机 需要提前准备的东西: 配置网络实验室的IP: 为了满足实验中一些需要用到网络的需求,学校为我们提供了每个人学号密码的 ...

  9. 普通莫队--洛谷P1997 【faebdc的烦恼】

    离散化+莫队 cnt数组表示某个颜色出现的次数 sum数组表示某个数量出现的颜色种类 其它细节问题就按照莫队的模板来的 #include<cstdio> #include<algor ...

  10. Creating your first iOS Framework

    转自:https://robots.thoughtbot.com/creating-your-first-ios-framework If you’ve ever tried to create yo ...