看各路神仙如何大战MySQL Insecure Warning报警有感

栏目: 数据库 · Mysql · 发布时间: 6年前

内容简介:看各路神仙如何大战MySQL Insecure Warning报警有感

问题由来

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_PWDmysql_config_editor 解决

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

mysql_config_editor

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

mysql_config_editor set --login-path=woqutech --host=10.10.30.18 --user=woqutech --password
mysql --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提供了在汇编层面解决这个问题的办法!

删除汇编中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信息了。

print_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 Of
fset: 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。汇编指令操作码可以查考此处。

  • 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的问题,但是各路大神各出奇招来解决这个问题,也给我们提供了很多思路,很有借鉴意义。

来源:沃趣科技(woqutech)

作者:董红禹


以上所述就是小编给大家介绍的《看各路神仙如何大战MySQL Insecure Warning报警有感》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数学之美 (第二版)

数学之美 (第二版)

吴军 / 人民邮电出版社 / 2014-11 / 49.00元

几年前,“数学之美”系列文章原刊载于谷歌黑板报,获得上百万次点击,得到读者高度评价。读者说,读了“数学之美”,才发现大学时学的数学知识,比如马尔可夫链、矩阵计算,甚至余弦函数原来都如此亲切,并且栩栩如生,才发现自然语言和信息处理这么有趣。 在纸本书的创作中,作者吴军博士几乎把所有文章都重写了一遍,为的是把高深的数学原理讲得更加通俗易懂,让非专业读者也能领略数学的魅力。读者通过具体的例子学到的......一起来看看 《数学之美 (第二版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试