MySQL审计

发布时间:2017-12-27 23:37:29编辑:admin阅读(5648)

    线上的数据库,开发可以直接navicat软件直接操作。一旦发生数据泄露,后果严重。需要禁止使用navicat,使用命令行操作,并且能记录每个开发执行的SQL语句。


    在跳板机上面写了一个shell脚本,开发只能通过执行shell脚本,来连接数据库

    环境如下:

    跳板机-->centos7-->192.168.78.133

    MySQL-->centos6.5-->192.168.78.128


    1.在跳板机安装php,mysql

    yum -y install php mariadb-server mariadb mariadb-devel

    启动数据库

    systemctl start mariadb

    2.创建数据库和表

    进入数据库
    mysql -u root
    创建数据库
    CREATE DATABASE audit DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    use audit;
    创建表
    CREATE TABLE `tbl_sql_record` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `rds` varchar(30) NOT NULL DEFAULT '' COMMENT '实例名',
      `username` varchar(30) NOT NULL DEFAULT '' COMMENT '用户名',
      `content` text NOT NULL COMMENT 'sql命令',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      PRIMARY KEY (`id`),
      KEY `title` (`create_time`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='sql记录表';

    3.MySQL服务器创建只读账号

    GRANT Select ON *.* TO zhangsan@'%' IDENTIFIED BY "123456";
    flush privileges;

    4.接下来的操作,都在跳板机上面

    编辑php文件,用来将sql语句转换为json

    vim /opt/1.php

    内容如下:

    <?php
    array_shift($argv);
    $str=implode(' ',$argv);
    $sql=json_encode($str);
    echo $sql;

    编辑shell脚本

    vim /opt/sql_con.sh

    内容如下:

    #!/bin/bash
    
    #MySQL主机列表
    db_base='192.168.78.128'
    
    #默认端口号
    PORT='3306'
    #输出页面
    OPTION=`whiptail --title "连接MySQL" --menu "请选择MySQL" 20 40 10 \
    "1" "db_base" \
    "2" "退出程序" \
    3>&1 1>&2 2>&3`
    
    #数字匹配
    if [ $? = 0 ]; then
        case $OPTION in
        1)
            HOST=$db_base
            RDS="db_base"
        ;;
        *)
            echo "程序退出"
            exit
        ;;
        esac
        #用户名和密码输入框
        USERNAME=$(whiptail --title "RDS 用户认证" --inputbox "请输入用户名?" 10 60 3>&1 1>&2 2>&3)
        PASSWORD=$(whiptail --title "RDS 密码认证" --passwordbox "请输入密码" 10 60 3>&1 1>&2 2>&3)
        #显示RDS所有数据库,-N不显示标题
        data=$(/usr/bin/mysql -h $HOST -u $USERNAME -p$PASSWORD -P$PORT -N -e 'show databases' > /tmp/"$USERNAME"_data.txt)
        if [ $? != 0 ];then
            echo -e "\033[31m 用户验证失败,程序退出 \033[0m"
            exit
        fi
        echo -e "\033[32m 数据库列表: \033[0m"
        echo "===================="
        #过滤掉默认的数据库
        cat /tmp/"$USERNAME"_data.txt | grep -E -v 'information_schema|mysql|performance_schema'
        #grep -E -v 'information_schema' $data
        echo "===================="
        echo -e "\033[32m 请输入sql语句或者exit退出 \033[0m"
    
    
        #执行sql语句方法
        query(){
            #mysql>提示符
            read -p  "mysql> " SQL
            #判断输入不为空或者exit
            if [ "$SQL" != "" ] && [ "$SQL" != "exit" ];then
                #当输入\G时,替换为\\g
                sql_ex=$(echo "$SQL" | sed 's@\G;$@\\G;@g')
                #判断sql是否包含select
                result=$(echo $sql_ex | grep -i "select")
                #判断结果,不为空,表示匹配
                if [[ "$result" != "" ]];then
                    #增加显示返回的行数和执行时间,select语句使用FOUND_ROWS()方法显示返回的行数,timestampdiff返回2个时间的差值
                    sql_query="set @d=now();""$sql_ex"";SELECT FOUND_ROWS() as affected_lines;select timestampdiff(second,@d,now()) as execution_time;"
                else
                    #delete,insert,update...其他语句使用ROW_COUNT()方法显示影响的行数
                    sql_query="set @d=now();""$sql_ex"";SELECT ROW_COUNT() as affected_lines;select timestampdiff(second,@d,now()) as execution_time;"
                fi
                #执行insert sql语句
                /usr/bin/mysql -h $HOST -u $USERNAME -p$PASSWORD -P$PORT -e "$sql_query"
                #当执行不成功时,提示错误
                if [ $? != 0 ];then
                    echo -e "\033[31m sql执行错误 \033[0m"
                else
                    #插入数据库
                    #sql语句转换为json
                    content=$(/usr/bin/php /opt/1.php "$sql_ex")
                    #当前时间
                    statime=`date +%Y-%m-%d" "%H:%M:%S`
                    #insert语句,双引号需要转义,content已经转义为json了
                    insert="insert into audit.tbl_sql_record set rds=\"$RDS\",username=\"$USERNAME\",content=$content,create_time=\"$statime\"";
                    #执行insert语句
                    /usr/bin/mysql -u root -e "$insert"
                fi
            fi
        }
        #当sql不等于exit时,循环执行方法
        while [[ $SQL != "exit" ]]
        do
             query
        done
    fi

    执行shell脚本,执行sql语句

    3.gif

    登录跳板机

    进入本机的mysql,创建远程授权账号,方便navicat查看sql执行记录

    mysql -u root
    grant all PRIVILEGES on *.* to owner@'%' identified by 'owner@123';
    flush privileges;

    使用navicat新建连接

    图片.png

    查看数据表

    图片.png


关键字