PHP安全特性分析


过滤函数缺陷绕过

== 与 ===

  • == 赋值,弱类型对比

  • === 对比,类型也会对比

本地示例演示:

==的情况:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
//1、== ===缺陷绕过 == 弱类型对比 ===还会比较类型
$a=1;
if($a==$_GET['x']){
 echo $flag;
}
?>

这种属于==的情况,在参数中输入+1 1.0 1a 这三种方式都可以输出flag

===的情况:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
//1、== ===缺陷绕过 == 弱类型对比 ===还会比较类型
$a='1';
if($a===$_GET['y']){
 echo $flag;
}
?>

这种情况输入参数为1能获取flag

md5

md5()属于md5加密函数

因为处理hash字符串时,PHP会将每一个以 0E开头的哈希值解释为0,那么只要传入的不同字符串经过哈希以后是以 0E开头的,那么PHP会认为它们相同

基本的原理是这样的,但更严谨的字符串格式是,0e 开头,同时后面都是数字,不能包含其他字符的字符串,md5 值才会相等(== 的结果为 True,但 === 的结果为 False)

参考文章:https://www.cnblogs.com/ainsliaea/p/15126218.html

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
if($_GET['name'] != $_GET['password']){
    if(MD5($_GET['name']) == MD5($_GET['password'])){
        echo $flag;
    }else{
         echo '?';
    }  
}
?>

这种情况有两种方式绕过:

  1. echo MD5(‘QNKCDZO’);
    echo MD5(‘240610708’);

  2. 利用数组绕过:name[]=1&password[]=2

intval

intval()函数的作用是获取变量的整数

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
$i='666';
$ii=$_GET['n'];
if(intval($ii==$i,0)){
 echo $flag;
}
?>

参数输入0x29a进行绕过

strpos

strpos()函数查找字符串在另一个字符串汇中第一次出现的位置(区分大小写)

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
$i='666';
$ii=$_GET['h'];
if(strpos($ii,$i,"0")){
 echo $flag;
}
?>

输入参数h=%0a666进行绕过

in_array

从数组里搜索特定词注:strict 可选,如果该参数设置未TRUE,则in_array()函数检查搜索的数据组的值类型是否相同,也就是没有true,就是相当于==

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
$whitelist = [1,2,3];
$page=$_GET['i'];
if (in_array($page, $whitelist)) {
 echo $flag;
}
?>

preg_match

执行匹配正则表达式可以利用数组绕过

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$flag='You can get the flag!';
if(isset($_GET['num'])){
	$num = $_GET['num'];
	if(preg_match("/[0-9]/", $num)){
		die("no no no!");
	}
	if(intval($num)){
		echo $flag;
	}
}
?>

利用数组进行绕过

这个报错属于代码没有处理,但不要紧,理解就行

isset() 函数用于检测变量是否已设置并且非 NULL

str_replace

过滤字符串,把字符串替换成另一个字符串存在一个问题:无法迭代循环,只能一次过滤

本地代码示例演示:

代码:

<?php
header("Content-Type:text/html;charset=utf-8");
$sql=$_GET['s'];
$sql=str_replace('select','',$sql);
echo $sql;
?>

这种常用于sql注入双写绕过

小结

  • == 与 ===

    • 不比较类型
    • 比较类型
    • md5
  • intval

    取整数,进制或小数等绕过

  • strops

    查看字符串,换行绕过

  • in_array

    第三个参数设置安全

  • preg_match

    • 数组绕过
    • 不带M正则表达,可用换行
  • str_replace

    无递归,双写绕过

实践-CTFShow-PHP 特性-89 关卡

web89

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);

if(isset($_GET['num'])){
    $num = $_GET['num'];
    if(preg_match("/[0-9]/", $num)){
        die("no no no!");
    }
    if(intval($num)){
        echo $flag;
    }
}
?>

这一关可以利用数组绕过

web90

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}
?>

这一关利用进制绕过

web91

题目的关键代码:

<?php
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
    if(preg_match('/^php$/i', $a)){
        echo 'hacker';
    }
    else{
        echo $flag;
    }
}
else{
    echo 'nonononono';
}
>    

/^php$/im中的m是指换行,这一关利用换行绕过

web92

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}
?>

这一关可以利用进制绕过,输入参数num=4476.1也能绕过,两种方式都可以

web93

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}
?>

这一关用上一关的方式同样能绕过

web94

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(!strpos($num, "0")){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}
?>

这一关用换行或者空格都可以绕过

?num=%0a010574 或 ?num=%20010574

这也可以使用参数浮点型绕过 num=4476.0

web95

题目的关键代码:

<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]|\./i", $num)){
        die("no no no!!");
    }
    if(!strpos($num, "0")){
        die("no no no!!!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}
?>

这一关用换行或者空格都可以绕过

?num=%0a010574 或 ?num=%20010574

web96

题目的关键代码:

<?php
highlight_file(__FILE__);

if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }
}
?>

这一关可以用num=./flag.php绕过

./flag.php指读取当前目录的flag.php

web97

题目的关键代码:

<?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[]=1&b[]=2

注意:要用post方式提交参数

免责声明:本文章涉及的知识和技能仅用于学习研究,如有用于非法途径或未被授权的真实网络环境,所造成的后果及连带责任自行承担,与本文作者无关,倡导把安全知识和技能用于正当、正规、正义的途径。


文章作者: 阿浩
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿浩 !
评论
  目录