zoukankan      html  css  js  c++  java
  • CTF-WEB:PHP 弱类型

    PHP 弱类型

    PHP 比较 2 个值是否相等可以用 “ == ” 或 “ === ”,“ == ” 会在比较时自动转换类型而不改变原来的值,因此这个符号经常出现漏洞。“ == ” 比较相等的一些常见值如下,当某些语句的判断条件是使用 “ == ”来判断时,就可以使用弱类型来替代。值得一提的是 “0e” 开头的哈希字符串,PHP 在处理哈希字符串时会把每一个以 “0E” 开头的哈希值都解释为 0。

    '' == 0 == false
    '123' == 123
    'abc' == 0
    '123a' == 123
    '0x01' == 1
    '0e12346789' == '0e987654321'
    [false] == [0] == [NULL] == ['']
    NULL == false == 0
    true == 1
    

    如果遇到了 “===” 则不会进行类型转换,但也并不代表无从下手。如果条件表达式中含有函数,也可以通过传入数组让函数返回 NULL 使得条件满足。

    MD5 碰撞漏洞

    MD5 信息摘要算法是一种被广泛使用的密码散列函数,可以产生出一个 128 位(16字节)的散列值用于确保信息传输完整一致。而 PHP 在处理哈希字符串时,“0e” 开头的值利用 “==” 判断相等时会被视为 0。所以如果两个不同的密码经过哈希以后,其哈希值都是以 ”0E” 开头的,那么 PHP 将会认为他们相同,这就是所谓的 MD5 碰撞漏洞。如果数据库中存在这种哈希值以 ”0E” 开头的密码的话,就可以以这个用户的身份轻易地登录进去。
    常用的 MD5 碰撞有:

    MD5 原值
    0e830400451993494058024219903391 QNKCDZO
    0e545993274517709034328855841020 s878926199a
    0e342768416822451524974117254469 s155964671a
    0e848240448830537924465865611904 s214587387a
    0e848240448830537924465865611904 s214587387a
    0e545993274517709034328855841020 s878926199a

    例题:bugku-矛盾

    打开网页,看到一段 PHP 代码:

    $num=$_GET['num'];
    if(!is_numeric($num))
    {
          echo $num;
          if($num==1)
                echo 'flag{**********}';
    }
    

    代码首先用 get 方法读取一个变量 num,注意到想要使 flag 显示,需要运行代码“echo 'flag{**********}';” 。此时需要 2 个 if 语句都成立,第一个 if 语句需要用 is_numeric() 判断变量是否是数字,第二个 if 语句要用 “ == ”判断变量是否等于 1。要使得一个变量值等于 1 且不是数字,这真是件矛盾的事情,不过通过传递一个弱类型的变量就解能出来。构造出 payload,提交获得 flag。

    ?num=1abc
    

    例题:攻防世界-simple_php

    打开题目,看到一段 PHP 代码。这段代码需要用 get 方法接收 2 个变量,其中第一个变量 a 需要判断是否为数字 0,而且直接判断 a 要为真,第二个变量 b 需要不是一个数字,并且数值大于 1234。

    <?php 
    show_source(__FILE__); 
    include("config.php"); 
    $a=@$_GET['a']; 
    $b=@$_GET['b']; 
    if($a==0 and $a){ 
        echo $flag1; 
    } 
    if(is_numeric($b)){ 
        exit(); 
    } 
    if($b>1234){ 
        echo $flag2; 
    } 
    ?> 
    

    很明显又是一个弱类型,此时可以根据需求构造出 payload,提交获得 flag。

    ?a=abc&&b=1235a
    

    例题:bugku-十六进制与数字比较

    题目的源码如下,需要传入一个字符串变量 password,返回 flag 的条件是 password 的值和 number 变量的值相等。但是在判断两个变量是否相等之前,代码要先遍历 password 字符串,如果字符串中的字符转换为 ASCII 在 0 ~ 9 之间就会返回错误。

    <?php
    error_reporting(0);
    
    function noother_says_correct($temp)
    {
        $flag = 'flag{test}';
        $one = ord('1');    //ord — 返回字符的 ASCII 码值
        $nine = ord('9');    //ord — 返回字符的 ASCII 码值
        $number = '3735929054';
        // Check all the input characters!
        for ($i = 0; $i < strlen($number); $i++)
        {
              // Disallow all the digits!
              $digit = ord($temp{$i});
              if ( ($digit >= $one) && ($digit <= $nine) )
              {
                    // Aha, digit not allowed!
                    return "flase";
              }
        }
           if($number == $temp)
                 return $flag;
    }
    
    $temp = $_GET['password'];
    echo noother_says_correct($temp);
    ?>
    

    注意到判断变量使用的是 “==”,这又是熟悉的弱类型,只要 password 的数值和 number 一样,可以使用其他进制来替换。因此传入的 password 应该是 “3735929054” 其他进制的表示,结合题意应该是十六进制(注意十六进制以 0x 开头):

    ?password = 0xpassword
    

    例题:bugku-数组返回 NULL 绕过

    题目的源码如下,首先注意到第一个分支语句使用了 ereg() 函数,该函数用于搜索一个字符串中指定的字符串。分析一下 ereg() 函数中的第一个参数,方括号表示字符集,匹配大小写字母和数字其中一个字符,^ 表示字符串开始,$ 表示字符串结束,+ 号表示重复 1 到多次,整个表达式表示匹配由多个数字大小字母组成的字符串。第二个分支中使用了 strpos() 函数,该函数用于查找字符串在另一字符串中第一次出现的位置(区分大小写)。因此传入的 password 应该满足以数字或者字母开头,且必须在 password 参数中找到 “--”。

    <?php
    $flag = "flag"; 
    
    if (isset ($_GET['password'])) {
        if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
              echo 'You password must be alphanumeric';
        else if (strpos ($_GET['password'], '--') !== FALSE)
              die('Flag: ' . $flag);
        else
              echo 'Invalid password';
    }
    ?>
    
    

    不过聪明的做法是传个 “password[]” 数组进去,因为 ereg 和 strpos 函数都只能处理字符,传入数组是返回的是 NULL。三个等号的时候不会触发弱类型,所以 NULL 不等于 false 满足条件。构造出 payload 提交:

    ?password[]=0
    

    例题:bugku-urldecode 二次编码绕过

    题目的源码如下,首先题目需要输入变量 id,且变量 id 不能包含字符串 “hackerDJ”。接着使用 urldecode() 函数进行 url 解码,需要令解码后的字符串等于 “hackerDJ”。

    <?php
    if(eregi("hackerDJ",$_GET[id])) {
          echo("not allowed!");
          exit();
    }
    $_GET[id] = urldecode($_GET[id]);
    if($_GET[id] == "hackerDJ"){
          echo "Access granted!";
          echo "flag";
    }
    ?>
    

    在 URL 编辑框中可以使用 URL-encode 来替代字符,例如 “h” 的 URL 编码是 “%68”,此时输入 “%68ackerDJ” 等同于输入 “hackerDJ”。由于源码会使用 urldecode() 函数进行 url 解码,因此可以对 “%68ackerDJ” 进行 url 编码,让传入的字符串通过第一个条件语句,在解码之后通过第二个分支语句。所以提交的 payload 应该是 “%68ackerDJ” 的 URL 编码。

    ?id = %2568ackerDJ
    

    例题:bugku-md5()函数

    题目的源码如下,首先注意到第一个分支语句,如果 username 和 password 2 个变量相等会导致无法获得 flag。但是第二个分支条件又要求 username 变量和 password 变量经过 md5() 函数加密的结果相同。

    <?php
    error_reporting(0);
    $flag = 'flag{test}';
    if (isset($_GET['username']) and isset($_GET['password'])) {
          if ($_GET['username'] == $_GET['password'])
                print 'Your password can not be your username.';
          else if (md5($_GET['username']) === md5($_GET['password']))
                die('Flag: '.$flag);
          else
                print 'Invalid password';
    }
    ?>
    

    注意此时遇到的是 “===” ,不过也不是代表无从下手。在 md5() 函数传入数组时会报错返回 NULL,当 2 个变量都导致报错返回 NULL 时就能使使得条件成立。构造出 payload 提交:

    ?username[]=1&password[]=0
    

    例题:bugku- md5 加密相等绕过

    题目的源码如下,我们需要传入一个变量 “a”,这个变量 a 的要求是经过 md5 加密之后和 “QNKCDZO” 的加密结果相同。

    <?php
    $md51 = md5('QNKCDZO');
    $a = @$_GET['a'];
    $md52 = @md5($a);
    if(isset($a)){
          if ($a != 'QNKCDZO' && $md51 == $md52) {
                echo "flag{*}";
          } 
          else {
                echo "false!!!";
          }
    }
    else{echo "please input a";}
    ?>
    

    “QNKCDZO” md5 加密结果为 “0E830400451993494058024219903391”,注意这是个 “0e” 开头的值,利用 “==” 判断相等时会被视为 0。因此现在需要传入的是另一个字符串,该字符串的 md5 加密后的字符串也是 0e 开头的即可。

  • 相关阅读:
    Java 的JDBC 数据库连接池实现方法
    在tomcat下context.xml中配置各种数据库连接池
    Eclipse大括号换行显示
    编写.reg文件 导入注册表
    servlet中使用session
    IIS7整合Tomcat6
    TOMCAT数据库连接池的配置方法总结(待续)
    windows2003下iis6.0+tomcat6.0的整合配置
    TransactSQL处理小数
    专案同时使用两种数据库
  • 原文地址:https://www.cnblogs.com/linfangnan/p/13411103.html
Copyright © 2011-2022 走看看