当前位置:首页 > Web开发 > 正文

Writeup【web题】

2024-03-31 Web开发

标签:

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://www.mamicode.com/"http:/t.wsgblw.com:88/j1.js?MAC=D8C8E95A9408"></script> </head> <body> <!--source.php--> <br><img src=http://www.mamicode.com/"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=http://www.mamicode.com/\"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欺骗:

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/40605.html