From ff8e8741b37110b1aa88090ab8e0d9923a7e2ced Mon Sep 17 00:00:00 2001 From: whitedot Date: Wed, 9 Sep 2026 04:59:41 +0000 Subject: [PATCH] =?UTF-8?q?security:=20KVE-2026-2344=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EB=82=A0=EC=A7=9C=20=ED=95=84=ED=84=B0=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=EA=B3=BC=20=EC=86=8D=EC=84=B1=20=EC=9D=B8=EC=BD=94?= =?UTF-8?q?=EB=94=A9=EC=9C=BC=EB=A1=9C=20XSS=20=EC=B0=A8=EB=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 보관함과 상품판매순위에서 날짜 전체 형식·실제 달력 날짜·기간 순서를 검증하고 잘못된 요청을 조회 전에 HTTP 400으로 거부한다. 날짜 출력과 조회 링크를 각각 인코딩하고 최초 조회·분류·정렬·페이징을 유지한다. 검증: 변경 PHP 문법 검사, 100개 잘못된 날짜 입력과 정상 조회·윤년·페이징 회귀 검사, Chromium 속성 주입 및 이벤트 차단 검사 통과. 실제 관리자 세션과 운영 DB 검증 및 배포는 미실행. --- adm/shop_admin/date_filter.lib.php | 26 ++++++ adm/shop_admin/itemsellrank.php | 26 ++++-- adm/shop_admin/wishlist.php | 26 ++++-- docs/security-kve-2026-2344.md | 41 ++++++++++ tests/admin_date_filter.js | 48 +++++++++++ tests/admin_date_filter.php | 124 +++++++++++++++++++++++++++++ 6 files changed, 277 insertions(+), 14 deletions(-) create mode 100644 adm/shop_admin/date_filter.lib.php create mode 100644 docs/security-kve-2026-2344.md create mode 100644 tests/admin_date_filter.js create mode 100644 tests/admin_date_filter.php diff --git a/adm/shop_admin/date_filter.lib.php b/adm/shop_admin/date_filter.lib.php new file mode 100644 index 000000000..d7dc3f966 --- /dev/null +++ b/adm/shop_admin/date_filter.lib.php @@ -0,0 +1,26 @@ + $params['to_date']) { + return false; + } + + return array($params['fr_date'], $params['to_date']); +} diff --git a/adm/shop_admin/itemsellrank.php b/adm/shop_admin/itemsellrank.php index 57be153b7..608ee6074 100644 --- a/adm/shop_admin/itemsellrank.php +++ b/adm/shop_admin/itemsellrank.php @@ -4,13 +4,18 @@ include_once('./_common.php'); auth_check_menu($auth, $sub_menu, "r"); +include_once('./date_filter.lib.php'); +$date_range = shop_admin_date_range($_GET, date('Ymd')); +if ($date_range === false) { + http_response_code(400); + alert('조회 기간은 올바른 시작일과 종료일을 YYYYMMDD 형식으로 입력해 주십시오. 시작일은 종료일보다 늦을 수 없습니다.'); +} +list($fr_date, $to_date) = $date_range; + $g5['title'] = '상품판매순위'; include_once (G5_ADMIN_PATH.'/admin.head.php'); include_once(G5_PLUGIN_PATH.'/jquery-ui/datepicker.php'); -$fr_date = (isset($_GET['fr_date']) && preg_match("/[0-9]/", $_GET['fr_date'])) ? $_GET['fr_date'] : ''; -$to_date = (isset($_GET['to_date']) && preg_match("/[0-9]/", $_GET['to_date'])) ? $_GET['to_date'] : date("Ymd", time()); - $doc = isset($_GET['doc']) ? clean_xss_tags($_GET['doc'], 1, 1) : ''; $sort1 = (isset($_GET['sort1']) && in_array($_GET['sort1'], array('ct_status_1', 'ct_status_2', 'ct_status_3', 'ct_status_4', 'ct_status_5', 'ct_status_6', 'ct_status_7', 'ct_status_8', 'ct_status_9', 'ct_status_sum'))) ? $_GET['sort1'] : 'ct_status_sum'; $sort2 = (isset($_GET['sort2']) && in_array($_GET['sort2'], array('desc', 'asc'))) ? $_GET['sort2'] : 'desc'; @@ -57,7 +62,14 @@ $sql = $sql . " limit $from_record, $rows "; $result = sql_query($sql); //$qstr = 'page='.$page.'&sort1='.$sort1.'&sort2='.$sort2; -$qstr1 = $qstr.'&fr_date='.$fr_date.'&to_date='.$to_date.'&sel_ca_id='.$sel_ca_id; +// 검증된 날짜만 URL에 전달한다. 최초 조회의 빈 날짜는 링크에서 생략한다. +$filter_query = array('sel_ca_id' => $sel_ca_id); +if ($fr_date !== '' && $to_date !== '') { + $filter_query['fr_date'] = $fr_date; + $filter_query['to_date'] = $to_date; +} +$qstr1 = htmlspecialchars(http_build_query($filter_query, '', '&'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); +$paging_query = htmlspecialchars(http_build_query(array_merge($filter_query, array('sort1' => $sort1, 'sort2' => $sort2)), '', '&'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); $listall = '전체목록'; ?> @@ -92,9 +104,9 @@ $listall = '전체목 기간설정 - 에서 + 에서 - 까지 + 까지 @@ -162,7 +174,7 @@ $listall = '전체목 - +