1. 程式人生 > 實用技巧 >[程式碼審計] fengcms1.32從詳細漏洞分析到漏洞利用

[程式碼審計] fengcms1.32從詳細漏洞分析到漏洞利用

一、基礎

mysql配置檔案預設順序從下列檔案中讀取:/etc/mysql/my.cnf  --> /etc/my.cnf  --> ~/.my.cnf

日誌

  二進位制日誌:binlog,主要用於資料還原,在主從模式中可用於資料複製,實現主從同步。重要!建議將二進位制日誌與資料檔案存放於不同裝置。

  中繼日誌:relay log,用於主從模式中接收主節點的二級制檔案,實現主從同步。

  事務日誌:分為重做日誌(redo log)和回滾日誌(undo log)。redo保證事務永續性,儲存事務發生後執行後的資料版本,用來恢復事務提交後未寫入資料檔案的資料。undo保障原子性,儲存事務發生前的資料版本,用於回滾。

  錯誤日誌:

    MariaDB [(none)]> show global variables like 'log_error' \G;
    *************************** 1. row ***************************
    Variable_name: log_error
    Value: /var/log/mariadb/mariadb.log
    1 row in set (0.00 sec)

  慢查詢日誌:查詢執行時長超過指定時長(long_query_time)的查詢,即為慢查詢

    

二、備份、恢復

2.1 備份型別

根據備份時,資料庫伺服器是否線上:
  冷備:cold backup
  溫備:warm backup
  熱備:hot backup

根據備份的資料集:
  完全備份:full backup
  部分備份: partial backup

根據備份時的介面(直接備份資料檔案還是通過mysql伺服器匯出資料):
  物理備份:直接複製(歸檔)資料檔案的備份方式;physical backup
  邏輯備份:把資料從庫中提出出來儲存為文字檔案;logical backup

根據備份時是備份整個資料還是僅備份變化的資料:
  完全備份:full backup

  增量備份:incremental backup
  差異備份:differential backup

2.2 備份恢復演示

2.2.1 mysqldump+binary log

 mysqldump工具前置條件:邏輯備份,需要開啟二進位制日誌,支援InnoDB熱備、MyISAM溫備、Aria溫備 

語法

mysqldump [options] [db_name [tbl_name ...]]

  shell> mysqldump [options] db_name [tbl_name ...]      # 恢復時需要手動建立資料庫
  shell> mysqldump [options] --databases db_name ...     # 恢復時不需要手動建立資料庫
  shell> mysqldump [options] --all-databases          # 恢復時不需要手動建立資料庫

options:
--lock-all-tables:請求鎖定所有表之後再備份
--lockl-tables:請求鎖定單個數據庫所有表之後再備份
--single-transaction: 備份時啟用一個大的事務完成的備份,能夠對InnoDB儲存引擎實現熱備
-E,--events:備份指定資料庫相關的所有事件排程器
-R,--routines:備份指定資料庫相關的所有儲存過程和儲存函式
--triggers:備份表相關的觸發器
--master-data:
    0:不記錄
    1:記錄為CHANGE MASTER TO語句
    2:記錄為註釋的CHANGE MASTER TO語句
--flush-logs:鎖定表完成後,執行日誌滾動

 

備份

先記錄現在的Position,以便恢復時還原

  MariaDB [(none)]> show master status\G;
  *************************** 1. row ***************************
  File: mysql-bin.000003
  Position: 7791967
  Binlog_Do_DB:
  Binlog_Ignore_DB:
  1 row in set (0.00 sec)

對於InnoDB儲存引擎來說,mysqldump支援熱備,可以直接使用命令進行備份:

  mysqldump -uroot --single-transaction --databases hellodb > hellodb.sql

對於MyISAM儲存引擎來說,mysqldump不支援熱備,需要先鎖定要備份的資料庫的表,在進行備份:

  mysqldump -uroot --lock-tables[--lock-all-tables] --databases hellodb > hellodb.sql

恢復:

  # mysql < hellodb.sql

  # mysqlbinlog --start-position=106 --stop-position=7791967 mysql-bin.000003 |mysql hellodb

2.2.2 lvm-snapshot

  原理就是基於lvm快照進行備份,沒看懂。略

 

2.2.3 xtrabackup

  xtrabackup工具使用前景:物理備份,需要下載(https://www.percona.com/)、開啟二進位制日誌,支援InnoDB熱備,增量備份;MyISAM溫備,不支援增量

語法:

$ innobackupex --user=DBUSER --password=SECRET /path/to/backup/dir/
$ innobackupex --user=LUKE  --password=US3TH3F0RC3 --stream=tar ./ | bzip2 -
$ xtrabackup --user=DVADER --password=14MY0URF4TH3R --backup --target-dir=/data/bkps/

 

備份:

全量備份:innobackupex --user=root /backup/

  使用innobakupex備份時,其會呼叫xtrabackup備份所有的InnoDB表,複製所有關於表結構定義的相關檔案(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相關檔案,同時還會備份觸發器和資料庫配置資訊相關的檔案。這些檔案會被儲存至一個以時間命令的目錄中。

增量備份:innobackupex --incremental /backup --incremental-basedir=BASEDIR

  其中,BASEDIR指的是完全備份所在的目錄,此命令執行結束後,innobackupex命令會在/backup目錄中建立一個新的以時間命名的目錄以存放所有的增量備份資料。另外,在執行過增量備份之後再一次進行增量備份時,其--incremental-basedir應該指向上一次的增量備份所在的目錄。增量備份僅能應用於InnoDB或XtraDB表,對於MyISAM表而言,執行增量備份時其實進行的是完全備份。

準備:

一般情況下,在備份完成後,資料尚且不能用於恢復操作,因為備份的資料中可能會包含尚未提交的事務或已經提交但尚未同步至資料檔案中的事務。因此,此時資料檔案仍處理不一致狀態。“準備”的主要作用正是通過回滾未提交的事務及同步已經提交的事務至資料檔案也使得資料檔案處於一致性狀態。

對於完全備份,直接執行: innobackupex --apply-log  /backup/2020-12-22_16-20-33/

對於增量備份,只能同步已提交事務,不能同步位提交事務(--redo-only),並需要先“準備”全量備份的資料,在依次按時間順訊準備各個增量的資料

於是,操作就變成了:
# innobackupex --apply-log --redo-only BASE-DIR

接著執行:
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

而後是第二個增量:
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

恢復:

innobackupex --copy-back  /path/to/BACKUP-DIR

 

三、主從複製

3.1 原理

主伺服器工作流程:

       主伺服器的dump執行緒負責接收從伺服器的二進位制日誌檔案請求併發送給對方

從伺服器工作流程

        從伺服器的I/O執行緒負責向主伺服器請求二進位制檔案,並記錄與中繼日誌檔案中

        從伺服器的SQL執行緒負責讀取中繼檔案中的sql語句,進行重放,以此達到資料同步的效果(上面備份的時候已經提到過了二進位制檔案記錄的是所有sql語句,所以從伺服器拿來過後進行重新執行一遍就OK了~)

另外主從伺服器的server id 不可重複,二進位制檔案中會標明serverid mysql的工作機制遇到同樣的serverid 是不會進行重放的,以此避免迴圈複製

3.2 配置

一、主節點
1、啟用二進位制日誌
log-bin=/mydata/binlogs/master-bin
log-bin-index=

2、為master選擇一個在當前複製架構中惟一的server-id
server-id=1

3、為保障主從複製時的事務安全
sync_binlog=1

4、建立一個具有複製許可權的使用者帳號
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repluser'@'hostname' IDENTIFIED BY 'repluser_pass';
mysql> FLUSH PRIVILEGES;

 

二、從節點
1、啟用中繼日誌(並關閉二進位制日誌)
relay-log=/mydata/relaylogs/relay-bin
relay-log-index=

2、為slave選擇一個在當前複製架構中惟一的server-id
server-id=11

3、連線至主伺服器
mysql> CHANGE MASTER TO MASTER_HOST='', MASTER_USER='', MASTER_PASSWORD='', MASTER_LOG_FILE='', MASTER_LOG_POS=#;
mysql> START SLAVE;

 

三、讀寫分離

 禁止從節點具有“寫操作”許可權

  read-only=ON

注意:僅能限制那不具有SUPER許可權使用者無法執行寫操作;

想限制所有使用者:
  mysql> FLUSH TABLES WITH READ LOCK;

 

四、複製過濾器

  master:
binlog_do_db=
binlog_ignore_db=

  slave:
replicate_do_db=
replicate_ignore_db=

replicate_do_table= db_name.table_name
replicate_ignore_table=

replicate_wild_do_table=
replicate_wild_ignore_table=

 

五、半同步複製

需要新增外掛,半同步複製原理為,在儲存資料時,主節點儲存完成後需要等待至少一個從節點同步完成後在反饋使用者儲存完成。
  主伺服器:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
mysql> SET GLOBAL rpl_semi_sync_master_enabled=ON;
mysql> SET GLOBAL rpl_semi_sync_master_timeout=1000;

  從伺服器:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=ON;
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;

在主伺服器驗正半同步複製是否生效:
mysql> SHOW GLOBAL STATUS LIKE '%semi%';

一旦某次等待超時,會自動降級為非同步