前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >看各路神仙如何大战MySQL insecure warning报警有感

看各路神仙如何大战MySQL insecure warning报警有感

作者头像
沃趣科技
发布2018-03-26 11:50:27
1.5K0
发布2018-03-26 11:50:27
举报
文章被收录于专栏:沃趣科技沃趣科技

一、问题由来

mysql在5.6.5上开始在命令行中直接填入用户密码会提示错误,例如:

$./mysql -h10.10.30.18 -uwoqutech -pwoqutech -ss -e 'select @@server_id'Warning: Using a password on the command line interface can be insecure.330618

如果你要写一个脚本调用mysql命令来获得server_id的值,这个Warning的信息绝对是你的噩梦。

提示这个安全原因本来无可厚非,但是坑爹的是,没有任何一个参数或者开关能关闭这个Warning。

2012年liu wei同学就提交了这个bug,到了2017年的今天,还是没有解决。期间有n多人开骂,其中Van Stokes骂的最经典:

How about this insane idea....
How about MySQL quits trying to save the world from itself and REMOVE THIS STUPID WARNING MESSAGE. It's NONE OF YOUR BUSINESS if I want to use a password on the command line or not. So quit worrying about it. Remove the warning. We don't need to be nannied to death by the likes of you.

翻译过来就是:

你们脑子秀逗了,赶紧把这个傻×报警信息清理掉,再不清理麻烦就大了!

骂归骂,也有很多人提供了对应的解决方案,甚至包括修改MySQL的汇编代码来解决。

二、人间大炮一级准备:脚本自己解决

最简单的,mysql自己不解决,我们脚本里面可以过滤。拿到这两行信息以后,通过grep -v或者各自程序语言去过滤掉这个错误信息。 但是每个脚本都需要有额外的逻辑来处理这个信息,也是大家非常不爽的原因。

Karl Nicoletti就很不爽:

Does the MySQL development team have ANY idea how many man-hours of work they have inflicted on DBAs and developers relying on command line input responses that DO NOT return the word "Warning" or "Error" in the case of successful execution???  I alone will be spending at least 100 hours to upgrade and test all our in-house maintenance, and installation scripts to work around this idiotic warning. Maybe, just MAYBE you could use the word "NOTE:" instead of "Warning:"??? Better yet, provide an option, --no-cmd-line-warning that would shut the damn thing off?

三、人间大炮二级准备:MYSQL_PWD,mysql_config_editor解决

还好,有一些其他的解决方案也可以解决这个问题。

mysql_config_editor

利用mysql_config_editor来保存用户名密码,避免输出Warning信息

mysql_config_editor set --login-path=woqutech --host=10.10.30.18 --user=woqutech --passwordmysql --login-path=woqutech  -e "select @@server_id"

这种方式必须手工输入密码,在脚本里面用也非常坑爹。

MYSQL_PWD

通过设置MYSQL_PWD变量来避免输出Warning信息

$MYSQL_PWD='woqutech' ./mysql  -h10.10.30.18 -uwoqutech  -ss -e 'select @@server_id'330618

这种方式相对接受度比较高。

四、人间大炮三级准备:源码解决

既然MySQL是开源的,那我们当然希望通过源码解决拉, 源码其实很简单

void print_cmdline_password_warning(){  static my_bool password_warning_announced= FALSE;  if (!password_warning_announced)  {    fprintf(stderr, "Warning: Using a password on the command line "            "interface can be insecure.\n");    (void) fflush(stderr);   password_warning_announced= TRUE;  }}

阿里的印风就提交了一个patch 供大家参考。

五、人间大炮发射:汇编解决

源码解决方案的问题在于需要维护自己的版本,每次MySQL新的版本发布都需要重新打patch,并重新编译。

还有什么其他的办法列,Andrew McGill和Perry Harrington提供了在汇编层面解决这个问题的办法!

5.1 删除汇编中Warning信息

Andrew McGill使用的是perl,解决方案如下

perl -p -i -e 's/(Warning: Using a password on the command line interface can be insecure..)/"\0"x(length($1))/es' /usr/local/mysql/bin/mysql

简单解释一下:

  • mysql程序编译出来就是一个汇编的代码
  • \0代表是空字符,"\0"x(length($1)表示多个空字符,不会打印任何字符
  • Andrew McGill利用perl将Warning: Using a password on the command line interface can be insecure.的信息都替换为空,也就不会打印Warning信息了。

5.2print_cmdline_password_warning函数逻辑修改

Perry Harrington提供了一种匪夷所思的汇编代码修改方式:

原版在测试环境下不可用:printf '\x75' | dd of=./mysql bs=1 seek=$((16#$(objdump --disassemble -F mysql |grep password_warning|grep je|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g'))) count=1 conv=notrunc
可用版本:printf '\xeb' | dd of=./mysql bs=1 seek=$((16#$(objdump --disassemble -F mysql |grep password_warning|grep jne|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g'))) count=1 conv=notrunc

这个需要解释一下

  • print_cmdline_password_warning函数中会判断password_warning_announced是否为FALSE,由于password_warning_announced是静态变量,再次进入这个函数将不会打印错误信息,函数代码如下:
  /** * This function should be called to print a warning message * if password string is specified on the command line. */

void print_cmdline_password_warning(){  static my_bool password_warning_announced= FALSE;

  if (!password_warning_announced)  {    fprintf(stderr, "Warning: Using a password on the command line "            "interface can be insecure.\n");    (void) fflush(stderr);    password_warning_announced= TRUE;  }}
  • 汇编代码中只需要把判断password_warning_announced的逻辑修改成直接跳转,就可以不打印出来了。

怎么修改列,通过objdump 可以查看到print_cmdline_password_warning函数的逻辑如下:

000000000044d980 <print_cmdline_password_warning> (File Offset: 0x4d980):  44d980:       55                      push   %rbp  44d981:       48 89 e5                mov    %rsp,%rbp  44d984:       53                      push   %rbx  44d985:       48 83 ec 08             sub    $0x8,%rsp  44d989:       80 3d e0 aa 59 00 00    cmpb   $0x0,0x59aae0(%rip)        # 9e8470 <_ZZ30print_cmdline_password_warningE26password_warning_announced> (File Offset: 0x5e8470)  44d990:       75 2f                   jne    44d9c1 <print_cmdline_password_warning+0x41> (File Offset: 0x4d9c1)  44d992:       48 8b 1d 07 00 4c 00    mov    0x4c0007(%rip),%rbx        # 90d9a0 <_DYNAMIC+0xd50> (File Offset: 0x50d9a0)  44d999:       48 8d 3d 40 c7 08 00    lea    0x8c740(%rip),%rdi        # 4da0e0 <special_opt_prefix_lengths+0x40> (File Offset: 0xda0e0)  44d9a0:       ba 49 00 00 00          mov    $0x49,%edx  44d9a5:       be 01 00 00 00          mov    $0x1,%esi  44d9aa:       48 8b 0b                mov    (%rbx),%rcx  44d9ad:       e8 26 df fb ff          callq  40b8d8 <fwrite@plt> (File Offset: 0xb8d8)  44d9b2:       48 8b 3b                mov    (%rbx),%rdi  44d9b5:       e8 ce e0 fb ff          callq  40ba88 <fflush@plt> (File Offset: 0xba88)  44d9ba:       c6 05 af aa 59 00 01    movb   $0x1,0x59aaaf(%rip)        # 9e8470 <_ZZ30print_cmdline_password_warningE26password_warning_announced> (File Offset: 0x5e8470)  44d9c1:       48 83 c4 08             add    $0x8,%rsp  44d9c5:       5b                      pop    %rbx  44d9c6:       c9                      leaveq  44d9c7:       c3                      retq  44d9c8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)  44d9cf:       00

我们看到44d990行,上一行比较了password_warning_announced的值,jne表示不等于就跳转到函数尾44d9c1(退出堆栈),我们把汇编指令修改成无论如何都跳转jmp不就解决了这个问题吗?

 44d990:       75 2f                   jne    44d9c1 <print_cmdline_password_warning+0x41> (File Offset: 0x4d9c1)

所以修改的策略就是把jne修改成jmp,对应的就是要把75修改为eb。汇编指令操作码可以查考csdn

  • 75是jne
  • eb是jmp

所以最终的修改方式就是这么一个诡异的命令:

printf '\xeb' | dd of=./mysql bs=1 seek=$((16#$(objdump --disassemble -F mysql |grep password_warning|grep jne|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g'))) count=1 conv=notrunc
  • objdump –disassemble -F mysql |grep password_warning|grep jne|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g' 获得要修改的mysql汇编文件字节偏移位置
  • seek=$((16#$(objdump –disassemble -F mysql |grep password_warning|grep jne|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g'))) 获得16进制“要修改的mysql汇编文件字节偏移位置”
  • printf '\xeb' | dd of=./mysql bs=1 seek=$((16#$(objdump –disassemble -F mysql |grep password_warning|grep jne|awk '{print $1}'|cut -d: -f1|sed -e 's/^.//g'))) count=1 conv=notrunc 将mysql汇编文件中print_cmdline_password_warning函数中jne修改为jmp,直接跳转,不打印错误信息

七、总结

MySQL出于安全的考虑,建议大家不要在命令行中写password,但是只是在命令行中提示,并且还不能关闭,确实比较坑,我们要做一个企业级的产品也需要对每一个细节和功能考虑的更加仔细和细致,避免出现类似的问题。

虽然官方也不知道啥时候能解决这个Warning的问题,但是各路大神各出奇招来解决这个问题,也给我们提供了很多思路,很有借鉴意义。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-06-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 沃趣科技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • mysql_config_editor
  • MYSQL_PWD
  • 5.2print_cmdline_password_warning函数逻辑修改
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档