-------------------------------------------------------------------
■脆弱性の種類
-------------------------------------------------------------------
ディレクトリトラバーサルに関する脆弱性
-------------------------------------------------------------------
■不具合が存在するEC-CUBEのバージョン
-------------------------------------------------------------------
EC-CUBE 2.12.0 以降
-------------------------------------------------------------------
■修正方法について(以下は Ver2.12.4 の修正となっております。)
-------------------------------------------------------------------
コードインジェクションの脆弱性と同じ修正方法となります。
http://www.ec-cube.net/info/weakness/weakness.php?id=49
/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