base64_* 函数已禁用,现在该怎么办?

5
当我尝试使用base64_decode()函数时,我收到以下警告:
"Warning: base64_decode() has been disabled for security reasons"

看起来我的主机已经禁用了base64_*功能。

我有几个问题:

  1. 我认为在php中,base64_*函数默认可以启用,是这样的吗?
  2. 是否因为安全原因才禁用了base64_*函数?有任何安全漏洞吗?
  3. 除了base64_*函数之外,还有哪些默认可用的替代函数?
  4. 在哪里可以找到base64_*实现的自定义类/函数,这样如果PHP的base64_*函数不可用,我就可以在我的PHP文件中使用它们?

谢谢帮助。


很多恶意脚本都被base_64编码到eval函数中。如果你真的需要它,请更改主机。 - Lawrence Cherone
5
如果您的主机相信“偏执安全”策略...换掉主机。 - Ignacio Vazquez-Abrams
他们的间谍软件不兼容Base64吗? :) - Hajo
3
他们可能认为所有使用base64_decode的代码都与混淆代码有关。当然,这是完全错误的。 - user149341
使用这里提供的信息,我在PHP中编写了一个糟糕的base32库(https://github.com/NTICompass/PHP-Base32)。我相信也不难让它同时支持base64。我现在正在工作,但如果下班后没什么事情做,我可以尝试添加base64支持。 - gen_Eric
4个回答

9

我已经为所有base64的用途编写了替代函数。

看这里:

function base64_decode($input) {
    $keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    $chr1 = $chr2 = $chr3 = "";
    $enc1 = $enc2 = $enc3 = $enc4 = "";
    $i = 0;
    $output = "";

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    $filter = $input;
    $input = preg_replace("[^A-Za-z0-9\+\/\=]", "", $input);
    if ($filter != $input) {
        return false;
    }

    do {
        $enc1 = strpos($keyStr, substr($input, $i++, 1));
        $enc2 = strpos($keyStr, substr($input, $i++, 1));
        $enc3 = strpos($keyStr, substr($input, $i++, 1));
        $enc4 = strpos($keyStr, substr($input, $i++, 1));
        $chr1 = ($enc1 << 2) | ($enc2 >> 4);
        $chr2 = (($enc2 & 15) << 4) | ($enc3 >> 2);
        $chr3 = (($enc3 & 3) << 6) | $enc4;
        $output = $output . chr((int) $chr1);
        if ($enc3 != 64) {
            $output = $output . chr((int) $chr2);
        }
        if ($enc4 != 64) {
            $output = $output . chr((int) $chr3);
        }
        $chr1 = $chr2 = $chr3 = "";
        $enc1 = $enc2 = $enc3 = $enc4 = "";
    } while ($i < strlen($input));
    return urldecode($output);
}

function base64_encode($data) {
    $b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    $o1 = $o2 = $o3 = $h1 = $h2 = $h3 = $h4 = $bits = $i = 0;
    $ac = 0;
    $enc = '';
    $tmp_arr = array();
    if (!$data) {
        return data;
    }
    do {
    // pack three octets into four hexets
    $o1 = charCodeAt($data, $i++);
    $o2 = charCodeAt($data, $i++);
    $o3 = charCodeAt($data, $i++);
    $bits = $o1 << 16 | $o2 << 8 | $o3;
    $h1 = $bits >> 18 & 0x3f;
    $h2 = $bits >> 12 & 0x3f;
    $h3 = $bits >> 6 & 0x3f;
    $h4 = $bits & 0x3f;
    // use hexets to index into b64, and append result to encoded string
    $tmp_arr[$ac++] = charAt($b64, $h1).charAt($b64, $h2).charAt($b64, $h3).charAt($b64, $h4);
    } while ($i < strlen($data));
    $enc = implode($tmp_arr, '');
    $r = (strlen($data) % 3);
    return ($r ? substr($enc, 0, ($r - 3)) . substr('===', $r) : $enc);
}

function charCodeAt($data, $char) {
    return ord(substr($data, $char, 1));
}

function charAt($data, $char) {
    return substr($data, $char, 1);
}

但不要忘记使用 charCodeAtcharAt 函数。它们都是对于 base64_encode 必不可少的。这两个函数 base64_encodebase64_decode 的工作方式与内置的 PHP 函数相同。但仅在内置函数不可用时使用它们,因为它们不如内置函数快速。
希望这可以帮到您!

我爱你!这是你在紧急情况下想要找到的答案,没有时间编码 =P - Leopoldo Sanczyk
1
感谢 @Ivan Shatsky return ($r ? substr($enc, 0, ($r - 3)) . substr('===', $r) : $enc); - jankal
如果您需要像我一样模仿_base64_decode_的确切行为,则必须“如果输入包含来自base64字母表之外的字符,则返回FALSE。”(正如PHP手册所述)。为了做到这一点,我将$input名称更改为$filter(保留参数的原始值),然后添加了以下行:if($filter!=$input) return false; - Leopoldo Sanczyk
@Leopoldo Sanczyk 谢谢!已添加。 - jankal
哇!非常感谢。这太棒了。实际上,这对其他函数非常有帮助。 - AlphaDx

1

我刚刚注册想评论jankal的回答,但是由于声望不够无法进行评论。

jankal的回答中base64_encode代码的最后一行是:

return ($r ? substr($enc, 0, ($r - 3)) : $enc) . substr('===', ($r || 3));

$r可以是0、1或2。据我所知,当$r=0时,($r || 3)表达式的值必须是3,而在其他两种情况下,$r的值为该表达式的值。但实际上(在PHP 5.6/7.0中),该表达式的值始终等于1,因此我们的BASE64编码字符串总是以两个“=”符号结尾,这显然是错误的。

我的解决方案:

return ($r ? substr($enc, 0, ($r - 3)) . substr('===', $r) : $enc);

1
当我编辑时,我可以使用您的更改吗? - jankal
2
刚刚完成了... 如果有任何抱怨:请评论或发信息给我。 - jankal

0
function myencode($input)
    {
    $CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    // the result/encoded string, the padding string, and the pad count
    $r = "";
    $p= "";
    $c = strlen($input) % 3;

    // add a right zero pad to make this string a multiple of 3 characters
    if ($c > 0) 
    {
        for (; $c < 3; $c++)
     {
        $p .= "=";
        $input .= "\0";
     }
    }

    // increment over the length of the string, three characters at a time
    for ($c = 0; $c < strlen($input); $c += 3) {

// we add newlines after every 76 output characters, according to the MIME specs

        if ($c > 0 && ($c / 3 * 4) % 76 == 0)
        $r += "\r\n";

// these three 8-bit (ASCII) characters become one 24-bit number
$n = (ord($input[$c]) << 16) + (ord($input[$c +1]) << 8) + (ord($input[$c +2]));


        // this 24-bit number gets separated into four 6-bit numbers
        $n1 = $n >> 18 & 63;
        $n2 = $n >> 12 & 63;
        $n3 = $n >> 6 & 63;
        $n4 = $n & 63;

 // those four 6-bit numbers are used as indices into the base64 character list

 $r .= "" . $CODES[$n1] . $CODES[$n2] . $CODES[$n3] . $CODES[$n4];

    }
    return substr($r,0,(strlen($r)-strlen($p))) . $p;
    }  



 function mydecode($input) {

 $CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

// remove/ignore any characters not in the base64 characters list
    // or the pad character -- particularly newlines

    $input= str_replace("[^" . $CODES . "=]","",$input);

    // replace any incoming padding with a zero pad (the 'A' character is  zero)
    $p = ($input[strlen($input) - 1] == '=' ?($input[strlen($input) - 2] == '=' ? "AA" : "A") : "");

    $r = "";
    $input = substr($input,0,(strlen($input) - strlen($p))) . $p;
// increment over the length of this encoded string, four characters at a time
    for ($c = 0; $c < strlen($input); $c += 4) {

// each of these four characters represents a 6-bit index in the
// base64 characters list which, when concatenated, will give the
// 24-bit number for the original 3 characters

         $n=(strpos($CODES,$input[$c]) << 18)
         +  (strpos($CODES,$input[$c+1]) << 12)
         +  (strpos($CODES,$input[$c+2]) << 6)
         +  (strpos($CODES,$input[$c+3]));


// split the 24-bit number into the original three 8-bit (ASCII) characters
$r .= "" . chr(($n >> 16) & 0xFF) . chr((($n >> 8) & 0xFF)) . chr(($n & 0xFF));

    }
    // remove any zero pad that was added to make this a multiple of 24 bits
        return substr($r,0, strlen($r)- strlen($p));
    }

-2
这是一个主机问题。 请更换您的主机或要求他们解决这个安全问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接