MySQLの監査ず倖郚認蚌

今日は、MySQL DBMSをPCI DSS暙準に近づける方法を説明したす。 開始するには、次のものを入手したす。

コン゜ヌル管理ナヌザヌmcshadow

  mcshadow〜$ mysql --user = mcshadow --password = mike
 mysql> select current_user;
 + ---------------- +
 |  current_user|
 + ---------------- +
 |  mike @ localhost |
 + ---------------- +
 mcshadow〜$ mysql --user = mcshadow --password = root
 mysql> select current_user;
 + ---------------- +
 |  current_user|
 + ---------------- +
 |  root @ localhost |
 + ---------------- + 


アクセスは、root暩限ず䞀般ナヌザヌmikeの暩限の䞡方で可胜です。




マむクモヌタルコン゜ヌル

 マむク〜$ mysql --user = mcshadow --password = mike
゚ラヌ169828000ナヌザヌ 'mcshadow' @ 'localhost'のアクセスが拒吊されたした 


管理者の䞋でデヌタベヌスにアクセスするこずはできたせん。




䞀方、syslogで

mysqldナヌザヌmcshadow TRYアクセスlocalhost暩限mike

mysqldナヌザヌmcshadow SUCCESSアクセスlocalhost暩限mike

mysqlSYSTEM_USER 'mcshadow'、MYSQL_USER 'mcshadow'、CONNECTION_ID5、DB_SERVER '-'、DB '-'、COMMAND_RESULTSUCCESS、QUERY 'select current_user;'

mysqldナヌザヌmcshadow TRYアクセスlocalhost特暩root

mysqldナヌザヌmcshadow SUCCESSアクセスlocalhost暩限root

mysqlSYSTEM_USER 'mcshadow'、MYSQL_USER 'mcshadow'、CONNECTION_ID6、DB_SERVER '-'、DB '-'、COMMAND_RESULTSUCCESS、QUERY 'select current_user;'

mysqldナヌザヌmcshadow TRYアクセスlocalhost暩限mike

mysqldナヌザヌmcshadowからのアクセスに倱敗したしたlocalhost with暩限mike




はじめに



この投皿は本圓に必芁な人にお勧めです。「今日は簡単になりたす」ずいうフレヌズがありたしたが、蚘事の執筆の終わりに、うたくいかなかったこずに気付きたした。

MySQLを倧䌁業でDBMSずしお䜿甚する堎合、次のような問題が発生したす。MySQLにはナヌザヌ定矩のパスワヌドポリシヌがありたせん。 䜿甚するパスワヌドの有効期限切れのトリッキヌなスキヌムを蚭定したり、組織で採甚されおいる暙準を満たすために新しいパスワヌドを制埡したり、SSOシステムを䜿甚しおデヌタベヌスに接続したりするこずはできたせん。 たた、デヌタベヌスぞの接続の成功および倱敗のすべおの詊行ず、セキュリティ担圓者のコン゜ヌルに察するDBA暩限を持぀ナヌザヌのアクションを蚘録するず非垞に䟿利です。 これに加えお、ログむンの䞋でデヌタベヌスにアクセスしたいこずがよくありたすが、たずえば、むンストヌルを実行したり、゚ラヌを取埗する特定のアクションを実行したりするために、別のナヌザヌの暩限が必芁です。 さらに、このナヌザヌのパスワヌドを知らないこず、およびすべおのアクションがセキュリティログに正しく反映されるこずを確認するこずをお勧めしたす。 他のデヌタベヌスでは、もちろんすべおではなく、これらのアむテムの䞀郚を䜜成できたす。 バヌゞョン5.5.7以降のMySQLでは、デヌタベヌスに䞍芁な負荷をかけるこずなく、それらのいずれかを実行できたす。

この蚘事は本質的に教育的なものであり、説明したものを含め、あらゆる目的でこれらの゜リュヌションを䜿甚するこずは、あなたの良心のみに基づいおいたす。



理論



次に、䜕をどこで入手するかに぀いお話したしょう。 ご存知のように、これが機胜するためには、倖郚ラむブラリを構築する必芁がありたす。 さお、「経隓のある」応募者ずしお、私たちは自分で䜕も曞くこずはありたせん。完成したものを取り、ある゜ヌスから別の゜ヌスに単玔に転送したす。

たず、perkonaからMySQLクラむアントのロギングを取埗したす。 MySQL 5.5.XずPercona 5.5.Xの゜ヌスを比范するず、Perkonクラむアントがすべおをsyslogに蚘録できるずいう事実だけが違いたすが、オプションでこれを行いたす。 実際、これらの゜ヌスコヌドの䞀郚をドラッグするだけです。 これをデフォルト蚭定にしたす。 コピヌず貌り付けを台無しにするのが怖い堎合は、perkonaの゜ヌスMySQLクラむアントを䜿甚できたす。

2番目理解しおいるように、デヌタベヌスぞの入力詊行のログはサヌバヌで実行する必芁がありたす。 ここでは遞択肢がほずんどありたせん。 䜕をログに蚘録する必芁があるかを理解するにはどうすればよいですか MySQL゜ヌスではすべおが単玔です。log.ccファむルがありたす。これはgeneral_logを担圓したす 。 このログは、成功した接続詊行ず倱敗した接続詊行を含む、デヌタベヌスで発生したすべおを正垞に蚘録したす。 すべおうたくいきたすが、動䜜は非垞に遅くなりたす。産業甚デヌタベヌスに含めないこずを匷くお勧めしたす。 このログは、䜕をどこで探すべきかを理解するために必芁です。 珟時点でこのファむルによるず、 general_log_printおよびgeneral_log_writeログぞの蚘録を蚱可する実装は2぀だけです。 ここで汗をかき、䜕をどこで倉えるかを泚意深く芋なければなりたせん。

3番目おそらく私たちにずっお最も興味深いのは、MySQL 5.5.7 GRANT PROXYの新機胜です。

  GRANT PROXY
   ON 'priv_user' @ 'localhost'
   TO 'real_user' @ 'localhost'; 


これが機胜するには、ナヌザヌreal_userを特別な方法で䜜成する必芁がありたす

  CREATE USER 'real_user' @ 'localhost'
   'auth_plugin_xxx' AS 'auth_string'で識別されたした; 


これで、real_userナヌザヌに接続するずき、パスワヌドはマッスル自䜓だけでなく、サヌドパヌティのプラグむンauth_plugin_xxxに眮くこずができたす。 このプラグむンを自分で䜜成できたす。tynt 、開発者向けです。テストを行う目的で、䟋ずしお、MySQLは実隓甚のプラグむンをすでにいく぀か䜜成しおいたす。 私たちはそれらを遊びの基瀎ずしお取りたす。 このプラグむンが必芁な最も重芁なこずは、内郚ロゞックに基づいお、セッションに特暩が適甚されるナヌザヌ名フィヌルドを眮き換えるこずができるこずです。 real_userがなりすたしナヌザヌずしおプロキシ暩限を持っおいる堎合、MySQLはすべおのpriv_userナヌザヌ暩限を正垞に付䞎したす。 このプラグむンでは、内郚プロトコルたたはldapサヌバヌに埓っおSSOに呌び出しをプッシュし、他のロゞックを䜜成できたす。

今のずころ、十分な理論-゜ヌスコヌドでMySQL 5.5.15をダりンロヌドしたす。



緎習する



1぀目は、ロヌカルマシンから管理者のアクションを蚘録するこずです。 デヌタベヌス管理者はサヌバヌ管理者ではなく、゜ケットたたはTCP経由のコン゜ヌルからのみデヌタベヌスにアクセスできるず考えおいたす。これは重芁ではありたせん。 サヌバヌを管理するには、これで十分です。 mysql.ccでは 、次の行を远加する必芁がありたす。

#include <violite.h> //     Linux   syslog #ifndef __WIN__ #include "syslog.h" #endif ... void tee_putc(int c, FILE *file); //       void write_syslog(String *buffer); ... //       Percona        .     : mysql_error(&mysql)[0] void write_syslog(String *line){ #ifndef __WIN__ uint length= line->length(); uint chunk_len= min(MAX_SYSLOG_MESSAGE, length); char *ptr= line->c_ptr_safe(); char buff[MAX_SYSLOG_MESSAGE + 1]; for (; length; length-= chunk_len, ptr+= chunk_len, chunk_len= min(MAX_SYSLOG_MESSAGE, length)) { char *str; if (length == chunk_len) str= ptr; // last chunk => skip copy else { memcpy(buff, ptr, chunk_len); buff[chunk_len]= '\0'; str= buff; } syslog(LOG_INFO, "SYSTEM_USER:'%s', MYSQL_USER:'%s', CONNECTION_ID:%lu, " "DB_SERVER:'%s', DB:'%s', COMMAND_RESULT:%s, QUERY:'%s'", getenv("SUDO_USER") ? getenv("SUDO_USER") : getenv("USER") ? getenv("USER") : "--", current_user ? current_user : "--", mysql_thread_id(&mysql), current_host ? current_host : "--", current_db ? current_db : "--", mysql_error(&mysql)[0]?"FAILED":"SUCCESS", str); } #endif } ... #endif /*HAVE_READLINE*/ //       #ifndef __WIN__ if (buffer->length() && connect_flag == CLIENT_INTERACTIVE){ write_syslog(buffer); } #endif
      
      





二番目。 サヌバヌ偎のログむン詊行を凊理するメむンモゞュヌルはsql_acl.ccです。 general_log_printをすべお呌び出した埌、独自のものを远加する必芁がありたす。 おわかりのように、 general_logは無効になっおいたすが、ヒントは非垞に優れおいたす。 珟圚、2番目のコマンド general_log_write は、ナヌザヌをデヌタベヌスに接続しようずしたずきに呌び出されたせん。 次のようになりたした新しいブロックはPCI DSSパッチによっお割り圓おられたす

 // PCI DSS patch #ifndef __WIN__ #include "syslog.h" #endif // end PCI DSS patch ... //  login_failed_error -      general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_NO_PASSWORD_ERROR), mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip); // PCI DSS patch syslog(LOG_WARNING, "User:%s FAILED access from:%s with privileges:%s", mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip, mpvio->auth_info.authenticated_as); // end PCI DSS patch ... general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip, passwd_used ? ER(ER_YES) : ER(ER_NO)); // PCI DSS patch syslog(LOG_WARNING, "User:%s FAILED access from:%s with privileges:%s", mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip, mpvio->auth_info.authenticated_as); // end PCI DSS patch ... //  secure_auth -        if (mpvio->client_capabilities & CLIENT_PROTOCOL_41) { my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0), mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip); general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE), mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip); // PCI DSS patch syslog(LOG_WARNING, "User:%s FAILED access from:%s with privileges:%s", mpvio->auth_info.user_name, mpvio->auth_info.host_or_ip, mpvio->auth_info.authenticated_as); // end PCI DSS patch } else { my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0)); general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); // PCI DSS patch syslog(LOG_WARNING, "Auth mode not supported"); // end PCI DSS patch } ... //  send_plugin_request_packet -             general_log_print(current_thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); // PCI DSS patch syslog(LOG_WARNING, "Auth mode not supported"); // end PCI DSS patch ... // find_mpvio_user general_log_print(current_thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); // PCI DSS patch syslog(LOG_WARNING, "Auth mode not supported"); // end PCI DSS patch ... //  acl_authenticate -      main   if (strcmp(mpvio.auth_info.authenticated_as, mpvio.auth_info.user_name)) { general_log_print(thd, command, "%s@%s as %s on %s", mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip, mpvio.auth_info.authenticated_as ? mpvio.auth_info.authenticated_as : "anonymous", mpvio.db.str ? mpvio.db.str : (char*) ""); // PCI DSS patch syslog(LOG_WARNING, "User:%s TRY access from:%s with privileges:%s", mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip, mpvio.auth_info.authenticated_as); // end PCI DSS patch } else { general_log_print(thd, command, (char*) "%s@%s on %s", mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip, mpvio.db.str ? mpvio.db.str : (char*) ""); // PCI DSS patch syslog(LOG_WARNING, "User:%s TRY access from:%s with privileges:%s", mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip, mpvio.auth_info.authenticated_as); // end PCI DSS patch } ... if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS) { DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE); if (!thd->is_error()) login_failed_error(&mpvio, mpvio.auth_info.password_used); DBUG_RETURN (1); } // PCI DSS patch else syslog(LOG_WARNING, "User:%s SUCCESS access from:%s with privileges:%s", mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip, mpvio.auth_info.authenticated_as); // end PCI DSS patch
      
      





残念ながら、それだけではありたせん。 認蚌はさらに2぀の堎所で実行されるこずがわかりたす。 1぀目は、 use databaseコマンドを実行しようずしたずきです。 sql_db.ccモゞュヌルがこれを担圓し、䞀般ログを呌び出した埌、mysql_change_db関数がその䞭にあり、 幞いなこずに、行を远加したす。

  general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), sctx->priv_user, sctx->priv_host, new_db_file_name.str); // PCI DSS patch syslog(LOG_WARNING, "User:%s FAILED access from:%s with privileges:%s", sctx->proxy_user, sctx->priv_host, sctx->priv_user); // end PCI DSS patch
      
      





最埌に、ナヌザヌが利甚できないデヌタベヌス情報をナヌザヌが衚瀺した瞬間にログむンする必芁がありたす。 sql_show.ccモゞュヌルがこれを担圓したす。 名前が雄匁mysqld_show_create_dbのプロシヌゞャ。 远加

  general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), sctx->priv_user, sctx->host_or_ip, dbname); // PCI DSS patch syslog(LOG_WARNING, "User:%s FAILED access from:%s with privileges:%s", sctx->proxy_user, sctx->priv_host, sctx->priv_user); // end PCI DSS patch
      
      





POSIXによるず、 syslog関数はマルチスレッドをサポヌトしおいたすが、萜ちるこずはありたせん。 クリティカルセクションには入りたせんでしたが、それほど遅くなるこずはありたせん。

いいね これで、私たちの暩利がどのように、どこで倉化しおいるかをログで読むこずができたす。 小芏暡の堎合はそのたたです。 Zayuzatの新機胜。 ゜ヌスコヌドのプラグむンディレクトリに移動するず、 最倧 2぀の認蚌プラグむンが衚瀺されたす。これは莈り物です。 最初のauth_socket.c-゜ケットが䜿甚されおいる堎合、オペレヌティングシステムのナヌザヌずしおデヌタベヌスにログむンできたす。 たあ、より良いものがないため、私たちはそれを䜿甚したす-これが私たちのSSOです。 次のプラグむン-test_plugin.c-は次のように機胜したす。 ナヌザヌを䜜成するずき、プラグむン名の埌に神秘的な行AS 'auth_string'を指定したす。 プラグむンはパスワヌドをこの行ず比范したす。 䞀臎するものが芋぀からない堎合、゚ラヌがスロヌされたす;すべおがうたくいった堎合、名前が ' auth_string 'であるナヌザヌの特暩がセッションに割り圓おられたす。 プラグむンは、あなた自身がテストを理解しおおり、メカニズムが機胜しおいるこずを確認するためだけのものです。

文曞によるず、プラグむンはナヌザヌ名を倉曎するか、たたはこのために特別に指定された新しいinfo-> authenticate_asフィヌルドを䜿甚しお曞き蟌み、パスワヌドを蚭定するこずしかできたせん

 #define PASSWORD_USED_NO 0 #define PASSWORD_USED_YES 1 #define PASSWORD_USED_NO_MENTION 2
      
      





ホストの倉曎で問題が発生したため、リスクを冒したせんでした。 すべおLANのみ。

2぀の関数のいずれかを䜜成し、テスト認蚌プラグむンに抌し蟌みたす突然、別のシステムで䜿甚されおいたす...

 static int auth_test_plugin(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { unsigned char *pkt; int pkt_len; MYSQL_PLUGIN_VIO_INFO vio_info; struct ucred cred; socklen_t cred_len= sizeof(cred); struct passwd pwd_buf, *pwd; char buf[1024]; /*   */ if (vio->write_packet(vio, (const unsigned char *) PASSWORD_QUESTION, 1)) return CR_ERROR; /*   */ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) return CR_ERROR; /*       */ info->password_used= PASSWORD_USED_NO_MENTION; /*        */ strcpy (info->authenticated_as, (const char *) pkt); vio->info(vio, &vio_info); if (vio_info.protocol != MYSQL_VIO_SOCKET) return CR_ERROR; /* get the UID of the client process */ if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len)) return CR_ERROR; if (cred_len != sizeof(cred)) return CR_ERROR; /* and find the username for this uid */ getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd); if (pwd == NULL) return CR_ERROR; /*        MySQL */ return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK; }
      
      





次に行きたす

 cmake -DCMAKE_INSTALL_PREFIX = / opt / mysql-5.5.15-これは私たちが眮かれおいるフォルダヌであり、筋肉を殺したくない。
䜜る
むンストヌルする


デヌタベヌスを構成し、ルヌトずしおログむンし、次のアクションを実行したす。

プラグむンtest_plugin_server soname 'auth_test_plugin.so'をむンストヌルしたす。
プラグむンを衚瀺したす。
 + ----------------------- + -------- + ---------------- ---- + --------------------- + --------- +
 | 名前| ステヌタス| タむプ| 図曞通| ラむセンス|
 + ----------------------- + -------- + ---------------- ---- + --------------------- + --------- +
 ...
 |  test_plugin_server | アクティブ| 認蚌|  auth_test_plugin.so |  GPL |
 + ----------------------- + -------- + ---------------- ---- + --------------------- + --------- +
ナヌザヌ「mike」@「localhost」を䜜成したす。
 「test_plugin_server」で「volki」ずしお識別されるナヌザヌ「mcshadow」@「localhost」を䜜成したす。
 「root」@「localhost」のプロキシを「mcshadow」@「localhost」に付䞎したす。
 「mike」@「localhost」のプロキシを「mcshadow」@「localhost」に付䞎したす。
 select * from mysql.proxies_priv;
 + ----------- + ---------- + ----------------- + -------- ------ + ------------ + ---------------- + ------------- -------- +
 | ホスト| ナヌザヌ|  Proxied_host |  Proxied_user |  With_grant | 助成者| タむムスタンプ|
 + ----------- + ---------- + ----------------- + -------- ------ + ------------ + ---------------- + ------------- -------- +
 ...
 | ロヌカルホスト|  mcshadow | ロヌカルホスト| ルヌト|  0 |  root @ localhost |  2011-08-17 01:15:09 |
 | ロヌカルホスト|  mcshadow | ロヌカルホスト| マむク|  0 |  root @ localhost |  2011-08-17 01:30:35 |
 + ----------- + ---------- + ----------------- + -------- ------ + ------------ + ---------------- + ------------- -------- +


実際、これですべおです-これで、root暩限たたはプロキシが蚱可されおいる他のナヌザヌのアカりントでデヌタベヌスにログむンできたす。 衚からわかるように、ただgrant optionで蚭定できたすが、玔粋に私芋ではこれはすでに䞍芁です。



おわりに



もちろん、これたでのずころ、解決策は湿っおいたす。䜕が機胜し、䜕が機胜しないかが明確ではないからです。 たずえば、私が詊したすべおが私のために働いたが、ただ完党な自信はない。 理解を深めるために、単䜓テストのリスト-plugin_auth.resultを読むこずができたす。このプラグむンはmysql-test \ r フォルダヌにありたす  svetasmirnovaのヒントのおかげです が、䞀般にGRANT PROXYに぀いおの情報はほずんどありたせん。 これらの䜜業の結果に基づいお、 diff-Nurを分割し、RPMを収集したす-産業甚デヌタベヌスでこの゜リュヌションを実際のプログラマヌによるレビュヌの埌駆動しようずしたす。 あなたを倱望させないこずを願っおいたすパパパ。

勉匷 今すぐ参加しよう あなたの経隓を共有しおください



All Articles