ENGLISH

脆弱性

コードインジェクションの脆弱性
情報公開日:2013年 06月 26日
危険度:
対象:Ver 2.11.2以降(2.11.2 ~2.12.4)
-------------------------------------------------------------------
■脆弱性の種類
-------------------------------------------------------------------
コードインジェクションに関する脆弱性

-------------------------------------------------------------------
■不具合が存在するEC-CUBEのバージョン
-------------------------------------------------------------------
EC-CUBE 2.11.2 以降

-------------------------------------------------------------------
■修正方法について(以下は Ver2.12.4 の修正となっております。)
-------------------------------------------------------------------

ディレクトリトラバーサルの脆弱性と同じ修正方法となります。
http://www.ec-cube.net/info/weakness/weakness.php?id=45

/data/class/SC_CheckError.php::EXIST_CHECK_REVERSE
/data/class/SC_CheckError.php::EQUAL_CHECK
/data/class/SC_CheckError.php::DIFFERENT_CHECK
/data/class/SC_CheckError.php::GREATER_CHECK
/data/class/SC_CheckError.php::CHECK_SET_TERM
/data/class/SC_CheckError.php::CHECK_SET_TERM2
/data/class/SC_CheckError.php::CHECK_SET_TERM3
/data/class/SC_CheckError.php::EVAL_CHECK
/data/class/SC_CheckError.php::createParam
/data/class/SC_FormParam.php::recursionCheck
に以下の変更を加えます。


※修正ファイルの詳細はこちらをご確認ください
http://www.ec-cube.net/info/weakness/20130626/index.php

▽SC_FormParam.php
279行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
$objErr = new SC_CheckError_Ex(array(0 => $value));
$objErr->doFunc(array($disp_name, 0, $length), array($func))
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
$objErr = new SC_CheckError_Ex(array(($error_last_key ? $error_last_key : $error_key) => $value));
$objErr->doFunc(array($disp_name, ($error_last_key ? $error_last_key : $error_key), $length), array($func)); 
-------------------------------------------------------------------

▽SC_CheckError.php
102行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function EXIST_CHECK_REVERSE($value) {
    if (isset($this->arrErr[$value[0]])) {
        return;
    }
    $this->createParam($value);
    if (strlen($this->arrParam[$value[0]]) == 0) {
        $this->arrErr[$value[0]] = '※ ' . $value[0] . 'が入力されていません。<br />';
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function EXIST_CHECK_REVERSE($value) {
    if (isset($this->arrErr[$value[0]])) {
        return;
    }
    // $this->createParam($value);
    if (strlen($this->arrParam[$value[0]]) == 0) {
        $this->arrErr[$value[0]] = '※ ' . $value[0] . 'が入力されていません。<br />';
    }
}
-------------------------------------------------------------------

185行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function EQUAL_CHECK( $value ) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    $this->createParam($value);
    // 文字数の取得
    if( $this->arrParam[$value[2]] != $this->arrParam[$value[3]]) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "と" . $value[1] . "が一致しません。<br />";
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function EQUAL_CHECK( $value ) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    // $this->createParam($value);
    // 文字数の取得
    if( $this->arrParam[$value[2]] != $this->arrParam[$value[3]]) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "と" . $value[1] . "が一致しません。<br />";
    }
}
-------------------------------------------------------------------

203行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function DIFFERENT_CHECK( $value ) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    $this->createParam($value);
    // 文字数の取得
    if( $this->arrParam[$value[2]] == $this->arrParam[$value[3]]) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "と" . $value[1] . "は、同じ値を使用できません。<br />";
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function DIFFERENT_CHECK( $value ) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    // $this->createParam($value);
    // 文字数の取得
    if( $this->arrParam[$value[2]] == $this->arrParam[$value[3]]) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "と" . $value[1] . "は、同じ値を使用できません。<br />";
    }
}
-------------------------------------------------------------------

221行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function GREATER_CHECK($value) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    $this->createParam($value);
    // 文字数の取得
    if($this->arrParam[$value[2]] != "" && $this->arrParam[$value[3]] != "" && ($this->arrParam[$value[2]] > $this->arrParam[$value[3]])) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "は" . $value[1] . "より大きい値を入力できません。<br />";
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function GREATER_CHECK($value) {
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[3]])) {
        return;
    }
    // $this->createParam($value);
    // 文字数の取得
    if($this->arrParam[$value[2]] != "" && $this->arrParam[$value[3]] != "" && ($this->arrParam[$value[2]] > $this->arrParam[$value[3]])) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "は" . $value[1] . "より大きい値を入力できません。<br />";
    }
}
-------------------------------------------------------------------

932行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function CHECK_SET_TERM ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[5]])) {
        return;
    }
    $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0 || strlen($this->arrParam[$value[4]] ) > 0) && ! checkdate($this->arrParam[$value[3]], $this->arrParam[$value[4]], $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[5]]) > 0 || strlen($this->arrParam[$value[6]]) > 0 || strlen($this->arrParam[$value[7]] ) > 0) && ! checkdate($this->arrParam[$value[6]], $this->arrParam[$value[7]], $this->arrParam[$value[5]]) ) {
        $this->arrErr[$value[5]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && strlen($this->arrParam[$value[4]] ) > 0) &&  (strlen($this->arrParam[$value[5]]) > 0 || strlen($this->arrParam[$value[6]]) > 0 || strlen($this->arrParam[$value[7]] ) > 0) ){

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]) .sprintf("%02d",$this->arrParam[$value[4]]) ."000000";
        $date2 = $this->arrParam[$value[5]] .sprintf("%02d", $this->arrParam[$value[6]]) .sprintf("%02d",$this->arrParam[$value[7]]) ."235959";

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[5]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function CHECK_SET_TERM ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[5]])) {
        return;
    }
    // $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0 || strlen($this->arrParam[$value[4]] ) > 0) && ! checkdate($this->arrParam[$value[3]], $this->arrParam[$value[4]], $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[5]]) > 0 || strlen($this->arrParam[$value[6]]) > 0 || strlen($this->arrParam[$value[7]] ) > 0) && ! checkdate($this->arrParam[$value[6]], $this->arrParam[$value[7]], $this->arrParam[$value[5]]) ) {
        $this->arrErr[$value[5]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && strlen($this->arrParam[$value[4]] ) > 0) &&  (strlen($this->arrParam[$value[5]]) > 0 || strlen($this->arrParam[$value[6]]) > 0 || strlen($this->arrParam[$value[7]] ) > 0) ){

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]) .sprintf("%02d",$this->arrParam[$value[4]]) ."000000";
        $date2 = $this->arrParam[$value[5]] .sprintf("%02d", $this->arrParam[$value[6]]) .sprintf("%02d",$this->arrParam[$value[7]]) ."235959";

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[5]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
    }
}
-------------------------------------------------------------------

982行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function CHECK_SET_TERM2 ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[8]])) {
        return;
    }
    $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0 || strlen($this->arrParam[$value[4]] ) > 0 || strlen($this->arrParam[$value[5]]) > 0) && ! checkdate($this->arrParam[$value[3]], $this->arrParam[$value[4]], $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[8]]) > 0 || strlen($this->arrParam[$value[9]]) > 0 || strlen($this->arrParam[$value[10]] ) > 0 || strlen($this->arrParam[$value[11]] ) > 0) && ! checkdate($this->arrParam[$value[9]], $this->arrParam[$value[10]], $this->arrParam[$value[8]]) ) {
        $this->arrErr[$value[8]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && strlen($this->arrParam[$value[4]] ) > 0 && strlen($this->arrParam[$value[5]] ) > 0) &&  (strlen($this->arrParam[$value[8]]) > 0 || strlen($this->arrParam[$value[9]]) > 0 || strlen($this->arrParam[$value[10]] ) > 0 || strlen($this->arrParam[$value[11]] ) > 0) ){

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]) .sprintf("%02d",$this->arrParam[$value[4]]) .sprintf("%02d",$this->arrParam[$value[5]]).sprintf("%02d",$this->arrParam[$value[6]]).sprintf("%02d",$this->arrParam[$value[7]]);
        $date2 = $this->arrParam[$value[8]] .sprintf("%02d", $this->arrParam[$value[9]]) .sprintf("%02d",$this->arrParam[$value[10]]) .sprintf("%02d",$this->arrParam[$value[11]]).sprintf("%02d",$this->arrParam[$value[12]]).sprintf("%02d",$this->arrParam[$value[13]]);

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[8]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
        if($date1 == $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }

    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function CHECK_SET_TERM2 ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[8]])) {
        return;
    }
    // $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0 || strlen($this->arrParam[$value[4]] ) > 0 || strlen($this->arrParam[$value[5]]) > 0) && ! checkdate($this->arrParam[$value[3]], $this->arrParam[$value[4]], $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[8]]) > 0 || strlen($this->arrParam[$value[9]]) > 0 || strlen($this->arrParam[$value[10]] ) > 0 || strlen($this->arrParam[$value[11]] ) > 0) && ! checkdate($this->arrParam[$value[9]], $this->arrParam[$value[10]], $this->arrParam[$value[8]]) ) {
        $this->arrErr[$value[8]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && strlen($this->arrParam[$value[4]] ) > 0 && strlen($this->arrParam[$value[5]] ) > 0) &&  (strlen($this->arrParam[$value[8]]) > 0 || strlen($this->arrParam[$value[9]]) > 0 || strlen($this->arrParam[$value[10]] ) > 0 || strlen($this->arrParam[$value[11]] ) > 0) ){

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]) .sprintf("%02d",$this->arrParam[$value[4]]) .sprintf("%02d",$this->arrParam[$value[5]]).sprintf("%02d",$this->arrParam[$value[6]]).sprintf("%02d",$this->arrParam[$value[7]]);
        $date2 = $this->arrParam[$value[8]] .sprintf("%02d", $this->arrParam[$value[9]]) .sprintf("%02d",$this->arrParam[$value[10]]) .sprintf("%02d",$this->arrParam[$value[11]]).sprintf("%02d",$this->arrParam[$value[12]]).sprintf("%02d",$this->arrParam[$value[13]]);

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[8]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
        if($date1 == $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }

    }
}
-------------------------------------------------------------------

1025行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function CHECK_SET_TERM3 ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[4]])) {
        return;
    }
    $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0) && ! checkdate($this->arrParam[$value[3]], 1, $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[4]]) > 0 || strlen($this->arrParam[$value[5]]) > 0) && ! checkdate($this->arrParam[$value[5]], 1, $this->arrParam[$value[4]]) ) {
        $this->arrErr[$value[4]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && (strlen($this->arrParam[$value[4]]) > 0 || strlen($this->arrParam[$value[5]]) > 0 ))) {

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]);
        $date2 = $this->arrParam[$value[4]] .sprintf("%02d", $this->arrParam[$value[5]]);

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[5]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function CHECK_SET_TERM3 ($value) {

    // 期間指定
    if(isset($this->arrErr[$value[2]]) || isset($this->arrErr[$value[4]])) {
        return;
    }
    // $this->createParam($value);
    $error = 0;
    if ( (strlen($this->arrParam[$value[2]]) > 0 || strlen($this->arrParam[$value[3]]) > 0) && ! checkdate($this->arrParam[$value[3]], 1, $this->arrParam[$value[2]]) ) {
        $this->arrErr[$value[2]] = "※ " . $value[0] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[4]]) > 0 || strlen($this->arrParam[$value[5]]) > 0) && ! checkdate($this->arrParam[$value[5]], 1, $this->arrParam[$value[4]]) ) {
        $this->arrErr[$value[4]] = "※ " . $value[1] . "を正しく指定してください。<br />";
    }
    if ( (strlen($this->arrParam[$value[2]]) > 0 && strlen($this->arrParam[$value[3]]) > 0 && (strlen($this->arrParam[$value[4]]) > 0 || strlen($this->arrParam[$value[5]]) > 0 ))) {

        $date1 = $this->arrParam[$value[2]] .sprintf("%02d", $this->arrParam[$value[3]]);
        $date2 = $this->arrParam[$value[4]] .sprintf("%02d", $this->arrParam[$value[5]]);

        if (($this->arrErr[$value[2]] == "" && $this->arrErr[$value[5]] == "") && $date1 > $date2) {
            $this->arrErr[$value[2]] = "※ " .$value[0]. "と" .$value[1]. "の期間指定が不正です。<br />";
        }
    }
}
-------------------------------------------------------------------

1137行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function EVAL_CHECK($value) {
    if (isset($this->arrErr[$value[0]])) {
        return;
    }
    $this->createParam($value);
    if ($this->evalCheck($value[1]) === false) {
        $this->arrErr[$value[0]] = '※ ' . $value[0] . ' の形式が不正です。<br />';
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function EVAL_CHECK($value) {
    if (isset($this->arrErr[$value[0]])) {
        return;
    }
    // $this->createParam($value);
    if ($this->evalCheck($value[1]) === false) {
        $this->arrErr[$value[0]] = '※ ' . $value[0] . ' の形式が不正です。<br />';
    }
}
-------------------------------------------------------------------

1165行目付近
-------------------------------------------------------------------
 変更前
-------------------------------------------------------------------
function createParam($value) {
    foreach ($value as $key) {
        if (is_string($key) || is_int($key)) {
            if (!isset($this->arrParam[$key]))  $this->arrParam[$key] = '';
        }
    }
}
-------------------------------------------------------------------

-------------------------------------------------------------------
 変更後
-------------------------------------------------------------------
function createParam($value) {
     foreach ($value as $val_key => $key) {
         if ($val_key != 0 && (is_string($key) || is_int($key))) {
             if (!is_numeric($key) && preg_match('/^[a-z0-9_]+$/i', $key)) {
                 if (!isset($this->arrParam[$key])) $this->arrParam[$key] = '';
                 if (strlen($this->arrParam[$key]) > 0
                       && (preg_match('/^[[:alnum:]\-\_]*[\.\/\\\\]*\.\.(\/|\\\\)/', $this->arrParam[$key]))
                       ) {
                     $this->arrErr[$value[1]] = '※ ' . $value[0] . 'に禁止された記号の並びまたは制御文字が入っています。<br />';
                 }
             } else if (preg_match('/[^a-z0-9_]/i', $key)) {
                 trigger_error('', E_USER_ERROR);
             }
         }
     }
}
-------------------------------------------------------------------

下記のリビジョンで修正
http://svn.ec-cube.net/open_trac/changeset/22891