Web刷题之PolarD&N(简单)
1.swp
考点:敏感文件、preg_match()函数绕过
什么是swp文件:
vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件。这个文件是一个临时交换文件,用来备份缓冲区中的内容。如果原文件名是data,那么swp文件名就是.data.swp。如果文件正常退出,则此文件自动删除。需要注意的是如果你并没有对文件进行修改,而只是读取文件,是不会产生swp文件的。强行关闭vim时,vim自动生成一个swp文件,当源文件被意外删除时,可以利用swp文件恢复源文件。
依据题目的提示,可能存在swp文件,用kali dirsearch工具扫一扫
function jiuzhe($xdmtql){ //接受一个xdmtql变量 return preg_match('/sys.*nb/is',$xdmtql); //匹配变量 } $xdmtql=@$_POST['xdmtql']; //判断变量是否为数组类型,不为数组类型往下判断 if(!is_array($xdmtql)){ //利用jiuzhe函数进行匹配输入的值 if(!jiuzhe($xdmtql)){ if(strpos($xdmtql,'sys nb')!==false){ //绕过 preg_match函数后匹配变量,匹配到的话输出flag echo 'flag{*******}'; }else{ echo 'true .swp file?'; } }else{ echo 'nijilenijile'; //匹配到/sys.*nb/is的话输出 } }
考虑如何同时绕过pre_match()和strpos()函数,不pre_match()让匹配到,一个又要strpos()匹配到。是个回溯问题,由于pre_match()函数处理的字符长度有限,如果超过这个长度就会返回false也就是没有匹配到,所以我们写一段代码,让pre_match()函数报错,绕过该函数,这样strpos()函数就可以顺利的匹配到我们的字符串从而输出flag
import requests url = 'http://59103954-e786-4a4b-9a2d-380a80e0a6b9.www.polarctf.com:8090/' data = { 'xdmtql': 'sys nb' + 'a' * 1000000 } res = requests.post(url=url, data=data) print(res.text)
flag{4560b3bfea9683b050c730cd72b3a099}
2.简单rce
题目
解题
- 命令执行函数
system()
passthru()
exec()
shell_exec()
popen()/proc_open()
- 读取文件命令
与cat命令功能相似的命令:
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
- 空格替代
上面的代码将输出:
This is a test file with test text.
?sys=echo(file_get_contents('/flag'));
3.蜜雪冰城吉警店
题目提示我们点第九款单子,于是在控制台中随意修改一处id为9
先随便点点试试
控制台中发现了id,随便修改一个id为9
4.召唤神龙
直接F12查看界面源码, 在main.js文件中发现一串文字, 猜测是jsfuck(源于brainfuck)
flag{fdf9a88ec4fdd9e3dedaafeece5cc248}
JSFuck
- 在线加密网站:http://www.jsfuck.com/
- 在线解密网站:http://codertab.com/JsUnFuck
5.seek flag
访问发现flag3:c0ad71dadd11}
bp抓包,在响应头中发现flag2:3ca8737a70f029d
我们注意到在返回包中有个Set-Cookie, 我们尝试将id改为1发包, 得到flag1:flag{7ac5b
拼接三段flag得到最终结果:flag{7ac5b3ca8737a70f029dc0ad71dadd11}
6.jwt
进入网页,显示登陆或者注册
点击注册,随便注册一个号
点击个人中心抓包
将抓到的JWT值通过c-jwt-cracker工具破解密钥,得到密钥是SYSA
jwt在线加密解密工具
https://www.json.cn/jwt/用jwt在线加密解密工具进行伪造
首先将抓包得到的jwt复制到编码区域,输入刚才破解的密钥进行解码
将username修改为admin,进行身份伪造,点击编码,得到新的jwt值,用新的jwt值替换bp抓包得到的jwt值
flag{ec39c705cfb5295f9dddcedc819a1659}
7.login
进入页面发现是个查询界面
第一时间想到了sql注入,试了试发现没有注入点
打开F12,发现给了一个学号
bp抓包,修改学号密码最后两位进行爆破
发现02-11的页面有回显,将回显拼接起来得到flag
flag{dlcg}
8.iphone
进入页面有下面一段文字和一个按钮
.点击enter按钮显示必须用iphone或者ipad才能看到admin菜单
bp抓包,在网上找了个ipad的User-Agent,替换原来的
Mozilla/5.0 (iPad; CPU OS 12_4_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Mobile/15E148 Safari/604.1
成功得到flag
flag{ba4c2f175f0dba2f2974e676c6dfbbab}
9.浮生日记
试试双写绕过
">alert("xss")
">闭合value标签
成功弹窗
得到 flag
flag{747b11f075d2f6f0d599058206190e27}
10. $$
分析代码
首先,代码接收GET参数c,赋值给变量$a。然后,如果c存在,就会进行正则表达式匹配。如果匹配到任何禁止的字符,就会输出“oh on!!!”并终止。否则,执行eval("var_dump($$a);");。
目标是通过eval执行来输出$flag变量的内容,而flag变量在include的flag.php文件中。所以,我需要让var_dump($$a);输出$flag。这里$$a意味着可变变量,即$a的值作为变量名。例如,如果$a是"flag",那么$$a就是$flag。
首先,我需要找到一个方法让$a的值等于"flag",但又不直接出现'flag'这四个字符。或者,通过其他方式间接引用到$flag变量。
考虑到PHP中的变量变量,或许可以用其他变量来间接获取。例如,如果存在一个变量其值为'flag',那么$$a可以指向$flag。但问题是,如何构造$a的值而不使用被过滤的字符。
比如,利用PHP的字符串解析特性。例如,通过变量名中的某些特性,如使用{}或者复杂变量表达式,但大括号被过滤了。
或者,考虑使用反斜杠来转义某些字符,但反斜杠也被过滤了。
或者,使用没有过滤的运算符,比如.号被过滤,所以无法进行字符串连接。
或者,考虑字符编码转换,比如使用十六进制或八进制表示,但数字被过滤了,所以无法直接使用。
比如,'flag'的十六进制是\x66\x6c\x61\x67,但传入时可能用双引号,但引号被过滤了,无法使用。
或者,使用异或运算来生成字符串,但PHP中如何执行异或?比如,在PHP中,两个字符串进行异或运算,但需要符号^,而^被过滤了。
或者,考虑超全局变量中的某些数组。比如,超全局变量$GLOBALS是一个包含所有全局变量的数组。那么,如果能访问$GLOBALS['flag'],那么就可以得到$flag的值。但问题是如何构造$a的值。
假设,我可以让$a等于"GLOBALS['flag']",但这样的话,$$a会被解释为可变变量,即$GLOBALS['flag'],但这可能需要不同的写法。或者,可能需要用更复杂的结构。
但是,构造这样的字符串需要考虑被过滤的字符,比如单引号被过滤了,所以无法使用'。因此,无法构造GLOBALS['flag']这样的字符串,因为包含单引号。
那是否有其他方式?比如,使用变量名替代或者其它方法?
另外,变量名中是否允许使用{}?比如,可变变量可以通过${a}的形式,但大括号被过滤了,所以也不行。
另一个思路是,PHP允许在可变变量中使用某些表达式,但需要未被过滤的字符。
比如,如果$a的值是"_GET",那么$$a就会变成$_GET。但这里的下划线被过滤了,所以无法使用。
那是否有其他超全局变量没有被过滤?比如,$GLOBALS不包含下划线?或者,可能还有其他的变量?
或者,是否有办法通过其他方式间接获取$flag的值?
例如,如果我能执行var_dump(get_defined_vars());,那么可以输出所有变量,其中可能包含$flag。但如何构造这个表达式?
当前代码中执行的是eval("var_dump($$a);");所以,如果$a的值是"GLOBALS",那么$$a就是$GLOBALS,从而var_dump($GLOBALS),这样会输出所有全局变量,包括$flag。
试一试payload:
?c=GLOBALS
flag{9f8a2133f0cad361ff6d22a445c2531a}
11.爆破
进入页面有一段代码
代码分析:
-
检查 pass 参数:
- 如果 URL 中包含 pass 参数,脚本会对它进行 MD5 加密。
- 如果没有提供 pass 参数,脚本会显示源代码。
-
第一个条件检查:
substr($pass, 1, 1) === substr($pass, 14, 1) && substr($pass, 14, 1) === substr($pass, 17, 1)
这里验证了 md5($pass) 加密后的字符串的第 2 个字符(索引为 1),第 15 个字符(索引为 14),以及第 18 个字符(索引为 17)是否相同。
-
第二个条件检查:
(intval(substr($pass, 1, 1)) + intval(substr($pass, 14, 1)) + substr($pass, 17, 1)) / substr($pass, 1, 1) === intval(substr($pass, 31, 1))
- 这部分要求对 md5($pass) 的第 2、15、18 个字符进行整数转换,并进行加法操作。
- 然后,结果除以第 2 个字符(字符的整数值)并与第 32 个字符(索引为 31)的整数值比较。
-
如果条件都成立,包括 flag.php 并输出 $flag。
可以编写一个简单的程序来暴力破解这个条件
import hashlib def check_password(pass_candidate): # 计算MD5哈希值 hashed = hashlib.md5(pass_candidate.encode()).hexdigest() # 检查第一个条件:第 2、15、18 个字符相同 if hashed[1] == hashed[14] == hashed[17]: # 将第 2、15、18 个字符转换为整数 num1 = int(hashed[1], 16) num2 = int(hashed[14], 16) num3 = int(hashed[17], 16) # 检查第二个条件 if (num1 + num2 + num3) / num1 == int(hashed[31], 16): return True return False # 尝试不同的密码 for i in range(1000000): # 这里尝试 0 到 999999 的数字作为密码 pass_candidate = str(i) if check_password(pass_candidate): print(f"Found password: {pass_candidate}") break
成功得到flag
flag{8277e0910d750195b448797616e091ad}
12. XFF
HTTP请求IP伪造
适用范围:
用于在某些特定情况下,只允许特定IP才能访问的页面,后端逻辑不严谨通过前端请求头来判断IP地址;
利用方式:
通过burp或者其他抓包工具添加以下下任意一个请求头,根据实际情况而定
X-Forwarded-For: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-Client-IP: 127.0.0.1
flag{847ac5dd4057b1ece411cc42a8dca4b7}
13.rce1
ping html{ height:100%; } body{ padding: 0; margin: 0; background: url(1.png); background-size: 100% 100%; position: absolute; }
就过滤了个空格,能拿到flag算我输
IP :代码是一道命令执行的题目,并且过滤了空格,看题目有个ip,考虑拼接符输入命令:
| 只执行第二个命令
|| 先执行第一个命令若成功则继续执行第二个命令
& 不管第一个命令是否执行成功都会执行第二个命令
&& 必须两个命令都成功才能执行
; 类似&
ping -c 4 {$ip}这很熟悉了,输入127.0.0.1;ls,返回一个fllllaaag.php
?ip=127.0.0.1;ls
直接输入127.0.0.1;cat${IFS}fllllaaag.php,就返回一个问号,查看源代码
flag{a3949821f7627a7fd30ab0722ff9b318}
常见的绕过空格的方法包括使用${IFS}、%09(tab的url编码)、或者用重定向符号之类的。或者使用不带空格的参数写法。
经测试%09这题无法绕过,用重定向符号127.0.0.1;cat
?file=/tmp/sess_65o295g198t733ujs5lld77v60
name=
常用读取命令
name=
name=
name=
这里sort和cat命令无法读取到
flag{43306e8113f53ece238c0a124432ce19}
19.Don't touch me
进页面只有一行字
源码发现有一行注释,提示了一个目录
访问发现多了一个按钮,但是按钮没法点
将按钮的disabled属性删除
新的页面源码最后又提示了一个目录
flag{0cee5a97f12b172ceeea2e9f67b7413e}
20.robots
直接访问/robots.txt ,发现有个fl0g.php页面不希望我们访问
访问得到flag
flag{2f37589152daf6f111b232ef4aea1304}
21. php very nice
打开网页源代码,由下图的代码,可见本题涉及到反序列化以及变量覆盖。
因此考虑传递GET参数a来构造序列字符串。
由上图中的代码,在Example类中定义了一个public成员变量,并在魔术函数__destruct中调用了敏感函数 eval
此外,出现了反序列化函数 unserialize 的调用,传入 GET 参数 a
综合上述情况,考虑通过构造参数Payload来覆盖成员变量的值,触发命令执行,获取flag
?a=O:7:"Example":1:{s:3:"sys";s:17:"system('tac f*');";}
flag{202cb962ac59075b964b07152d234b70}
22.ezupload
显然有文件上传漏洞,我们先上传个一句话木马
显示只支持上传GIF图片
我们将一句话木马后缀改为.gif,bp抓包,再把后缀改为php试试
成功上传
蚁剑连接,在/var/www/目录下发现flag.php文件
flag{ffffffffllllaaggg_!!!}
23.cookie欺骗
显示只有admin用户才能得到flag,直接bp抓包
cookie中有个user变量,将值改为admin
flag{10e35c76602b330149ef009e0b484d8f}
24.upload
上传一个一句话木马发现.php后缀被过滤,上传图片马bp抓包改后缀名发现也不行
源码发现有个注释
打开发现源码
$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 . '文件夹不存在,请手工创建!'; } }
直接修改后缀名为.pphphp,双写绕过
打开图片,成功上传
25.干正则
parse_str函数会将查询字符串解析到变量中。例如,如果id是"a=123",那么变量$a会被覆盖为123。这里可能存在变量覆盖的漏洞,因为用户输入的id参数会被解析到当前作用域的变量中。
通过parse_str函数的漏洞覆盖变量$a,使其成为数组并使$a[0]等于www.polarctf.com。
构造GET参数id=a[0]=www.polarctf.com,这样parse_str会将$a转换为数组,满足后续条件判断。
$ip参数(来自cmd)不能包含flag.php,否则会被拦截。
方法一:我们通过Shell变量拼接绕过检测。
构造cmd参数值为;a=flag;b=.php;tac $a$b,该命令在Shell中拼接后实际执行tac flag.php,但原始字符串不含flag.php,绕过正则检查。
方法二:利用通配符*绕过检测
flag{e44882416c9fa79cc5a6a51e6e19cdbc}
26.cool
system,flag,php都被过滤,直接用passthru函数加通配符
27.uploader
本题的重点仍是文件上传,只是期间需要加上一步自主的文件上传。
打开环境,审查代码,发现在上传文件之后会自动生成一个以MD5散列值命名的目录,并将上传的文件置于其中。
因此考虑自主设计上传逻辑,笔者采用的是脚本编写的方式。
上传成功后,找出所需的MD5散列值,对 url 进行拼接,随后进行 Webshell 交互,此处依然采用了脚本的方式。
用py写个文件上传脚本
import requests import sys import io if sys.stdout.encoding != 'UTF-8': sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') url = 'http://eb5650f0-676d-4c8d-a23a-3128ab942fef.www.polarctf.com:8090/' # 替换成你的服务器地址 files = {'file': open('D:\网安\一句话木马\yjh.php', 'rb')} # 将文件名替换为你想上传的文件 response = requests.post(url, files=files) print(response.text)
拿到$sandbox和filename,拼接得到文件路径
http://6ae68957-2bd0-497c-9498-41aa32394ab7.www.polarctf.com:8090/fc476b1aae619597a9871112304f2d63
连接蚁剑,拿flag
flag{256d5ca173f463165db6ed366b597da8}
28.覆盖
flag{e44882416c9fa79cc5a6a51e6e19cdbc}
29.PHP反序列化初试
代码分析:
首先发现Easy类中有魔术函数 __wakeup() ,实现的是对成员变量 $name 的回显。
观察下方发现, unserialize() 函数将触发该魔术函数的执行,因此考虑构造序列字符串传入该类的成员变量 $name 中,以触发命令执行。
exp:
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:6:"tac f*";s:3:"env";N;}}
flag{08a46a069bd77e33531bb2ab244f4196}
30.机器人
得到了flag的前半段,这里还有个目录不给爬,猜测敏感文件在这个目录下
拼接得到完整flag
flag{4749ea1ea481a5d56685442c8516b61c}
31.扫扫看
让我们扫一扫,直接dirsearch扫描一下
扫到一个flag.php,访问该目录
源码发现注释中有flag
flag{094c9cc14068a7d18ccd0dd3606e532f}
32.debudao
打开网页有个搜索框,尝试xss注入发现有xss漏洞但是没什么用,没发现sql注入
源码中发现有个flag,但是提交是假的
flag{72077a55w312584wb1aaa88888cd41af}
33.审计
按照题目的要求,输入的xxs参数的值必须是数字,且md5值必须是0e开头,第三位是数字。
已知的一些Magic Hash包括:
- 240610708的md5是0e462097431906509019562988950854
- s878926199a的md5是0e545993274517709034328855841020
240610708刚好满足题目要求
flag{1bc29b36f623ba82aaf6724fd3b16718}
34.upload1
上传一个一句话木马,显示只能上传图片类型的文件
上传图片马,bp抓包把后缀名改为.php,直接上传成功了
连接蚁剑,拿到flag
flag{adbf5a778175ee757c34d0eba4e932bc}
35.rapyiquan
不能出现_,可以用[或者_的URL编码%5f绕过
c[md或者c%5fmd
经测试都可以
后面的正则匹配可以用\绕过检测
payload:?c[md=sort f\lag.php
flag{cf7d0e14fbf7845e50d53a478d3d10eb}
36.bllbl_ser1
查看源代码
反序列化漏洞
exp
-
- 空格替代
- 读取文件命令