diff --git a/lib/shop.lib.php b/lib/shop.lib.php index 4211c8a90..ce27d0114 100644 --- a/lib/shop.lib.php +++ b/lib/shop.lib.php @@ -26,6 +26,56 @@ function get_shop_uid($type, $id, $time, $ip) return hash_hmac('sha256', $payload, $key); } +/** + * 현금영수증 발급 또는 조회에 대한 검증 + * + * 다음 셋 중 하나여야 접근 허용: + * 1. 관리자 + * 2. 본인 주문/개인결제 (로그인 회원이고 mb_id 일치) + * 3. 비회원이지만 정당한 세션 uid 보유 (orderinquiry.php에서 비밀번호 검증 통과 후 + * 또는 주문 완료 직후 세션에 저장된 ss_orderview_uid / ss_personalpay_uid가 + * 현재 주문/개인결제의 HMAC uid와 일치) + * + * @param array $od 주문 또는 개인결제 행 (DB에서 fetch한 결과) + * @param string $type 'order' (g5_shop_order) 또는 'personalpay' (g5_shop_personalpay) + * @return bool + */ +function is_shop_order_owner($od, $type = 'order') +{ + global $is_admin, $is_member, $member; + + if (!is_array($od)) { + return false; + } + + // 관리자 + if ($is_admin) { + return true; + } + + // 본인 주문/개인결제 (로그인 회원) + if ($is_member && isset($od['mb_id']) && $od['mb_id'] !== '' && $od['mb_id'] === $member['mb_id']) { + return true; + } + + // 세션 uid 검증 + if ($type === 'personalpay') { + if (empty($od['pp_id'])) { + return false; + } + $expected = get_shop_uid('personalpay', $od['pp_id'], $od['pp_time'], $_SERVER['REMOTE_ADDR']); + $session_uid = get_session('ss_personalpay_uid'); + } else { + if (empty($od['od_id'])) { + return false; + } + $expected = get_shop_uid('order', $od['od_id'], $od['od_time'], $od['od_ip']); + $session_uid = get_session('ss_orderview_uid'); + } + + return ($session_uid !== '' && $expected === $session_uid); +} + /* 간편 사용법 : 상품유형을 1~5 사이로 지정합니다. $disp = new item_list(1); diff --git a/shop/inicis/taxsave_result.php b/shop/inicis/taxsave_result.php index be7aa3c00..d88d099d5 100644 --- a/shop/inicis/taxsave_result.php +++ b/shop/inicis/taxsave_result.php @@ -17,12 +17,19 @@ if (strlen($iv) !== 16){ */ $companynumber = isset($_REQUEST['companynumber']) ? clean_xss_tags($_REQUEST['companynumber'], 1, 1) : ''; +$od_id = isset($_REQUEST['od_id']) ? safe_replace_regex($_REQUEST['od_id'], 'od_id') : ''; +$tx = isset($_REQUEST['tx']) ? clean_xss_tags($_REQUEST['tx'], 1, 1) : ''; if($tx == 'personalpay') { $od = sql_fetch(" select * from {$g5['g5_shop_personalpay_table']} where pp_id = '$od_id' "); if (!$od) die('
개인결제 내역이 존재하지 않습니다.
'); + // IDOR 방지: 본인 개인결제거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'personalpay')) { + alert('해당 개인결제 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + if($od['pp_cash'] == 1) alert('이미 등록된 현금영수증 입니다.'); @@ -37,6 +44,11 @@ if($tx == 'personalpay') { if (!$od) die('주문서가 존재하지 않습니다.
'); + // IDOR 방지: 본인 주문이거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'order')) { + alert('해당 주문 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + if($od['od_cash'] == 1) alert('이미 등록된 현금영수증 입니다.'); diff --git a/shop/lg/taxsave_result.php b/shop/lg/taxsave_result.php index 28dd3fdee..45119a223 100644 --- a/shop/lg/taxsave_result.php +++ b/shop/lg/taxsave_result.php @@ -11,6 +11,11 @@ if($tx == 'personalpay') { if (!$od) die('개인결제 내역이 존재하지 않습니다.
'); + // IDOR 방지: 본인 개인결제거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'personalpay')) { + alert('해당 개인결제 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + $od_tno = $od['pp_tno']; $goods_name = $od['pp_name'].'님 개인결제'; $settle_case = $od['pp_settle_case']; @@ -21,6 +26,11 @@ if($tx == 'personalpay') { if (!$od) die('주문서가 존재하지 않습니다.
'); + // IDOR 방지: 본인 주문이거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'order')) { + alert('해당 주문 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + $od_tno = $od['od_tno']; $goods = get_goods($od['od_id']); $goods_name = $goods['full_name']; diff --git a/shop/nicepay/taxsave_result.php b/shop/nicepay/taxsave_result.php index 3d4ccb04f..b679da7b5 100644 --- a/shop/nicepay/taxsave_result.php +++ b/shop/nicepay/taxsave_result.php @@ -8,11 +8,19 @@ include_once(G5_SHOP_PATH.'/settle_nicepay.inc.php'); * */ +$od_id = isset($_REQUEST['od_id']) ? safe_replace_regex($_REQUEST['od_id'], 'od_id') : ''; +$tx = isset($_REQUEST['tx']) ? clean_xss_tags($_REQUEST['tx'], 1, 1) : ''; + if($tx == 'personalpay') { $od = sql_fetch(" select * from {$g5['g5_shop_personalpay_table']} where pp_id = '$od_id' "); if (!$od) die('개인결제 내역이 존재하지 않습니다.
'); + // IDOR 방지: 본인 개인결제거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'personalpay')) { + alert('해당 개인결제 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + if($od['pp_cash'] == 1) alert('이미 등록된 현금영수증 입니다.'); @@ -27,6 +35,11 @@ if($tx == 'personalpay') { if (!$od) die('주문서가 존재하지 않습니다.
'); + // IDOR 방지: 본인 주문이거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'order')) { + alert('해당 주문 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + if($od['od_cash'] == 1) alert('이미 등록된 현금영수증 입니다.'); diff --git a/shop/taxsave.php b/shop/taxsave.php index 98de1c15f..916e25351 100644 --- a/shop/taxsave.php +++ b/shop/taxsave.php @@ -16,6 +16,11 @@ if($tx == 'personalpay') { if (!$od) die('개인결제 내역이 존재하지 않습니다.
'); + // IDOR 방지: 본인 개인결제거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'personalpay')) { + alert('해당 개인결제 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + $goods_name = $od['pp_name'].'님 개인결제'; $amt_tot = (int)$od['pp_receipt_price']; $dir = $od['pp_pg']; @@ -32,6 +37,11 @@ if($tx == 'personalpay') { if (!$od) die('주문서가 존재하지 않습니다.
'); + // IDOR 방지: 본인 주문이거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'order')) { + alert('해당 주문 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + if ( ! $is_admin && ! (shop_is_taxsave($od)) ){ die('해당 주문은 현금영수증을 발급할수 없습니다.'); } diff --git a/shop/toss/taxsave_result.php b/shop/toss/taxsave_result.php index 188c0a283..d86f057a6 100644 --- a/shop/toss/taxsave_result.php +++ b/shop/toss/taxsave_result.php @@ -10,6 +10,11 @@ if($tx == 'personalpay') { if (!$od) die('개인결제 내역이 존재하지 않습니다.
'); + // IDOR 방지: 본인 개인결제거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'personalpay')) { + alert('해당 개인결제 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + $od_tno = $od['pp_tno']; $goods_name = $od['pp_name'].'님 개인결제'; $settle_case = $od['pp_settle_case']; @@ -23,6 +28,11 @@ if($tx == 'personalpay') { if (!$od) die('주문서가 존재하지 않습니다.
'); + // IDOR 방지: 본인 주문이거나 정당한 세션 uid 보유 시에만 허용 + if (function_exists('is_shop_order_owner') && !is_shop_order_owner($od, 'order')) { + alert('해당 주문 정보에 접근 권한이 없습니다.', G5_SHOP_URL); + } + $od_tno = $od['od_tno']; $goods = get_goods($od['od_id']); $goods_name = $goods['full_name'];