From efaefbbd0eb3334aba16ef729bac62cb82aeed83 Mon Sep 17 00:00:00 2001 From: thisgun Date: Fri, 24 Apr 2026 09:26:48 +0000 Subject: [PATCH] =?UTF-8?q?[security]KVE-2026-0687=20=EC=87=BC=ED=95=91?= =?UTF-8?q?=EB=AA=B0=20=EC=BF=A0=ED=8F=B0=20=EB=8B=A4=EC=9A=B4=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20TOCTOU=20Race=20Condition=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MySQL GET_LOCK 으로 동일 회원·동일 쿠폰 다운로드 요청을 직렬화하여, 동시 요청 시 is_coupon_downloaded() 체크를 중복 통과해 쿠폰이 중복 발급되는 문제를 방지함. Co-Authored-By: Claude Opus 4.7 (1M context) --- shop/ajax.coupondownload.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/shop/ajax.coupondownload.php b/shop/ajax.coupondownload.php index cd18f01e1..e827cc410 100644 --- a/shop/ajax.coupondownload.php +++ b/shop/ajax.coupondownload.php @@ -18,13 +18,23 @@ if(!$cp['cz_id']) if(!($cp['cz_start'] <= G5_TIME_YMD && $cp['cz_end'] >= G5_TIME_YMD)) die(json_encode(array('error' => '다운로드할 수 없는 쿠폰입니다.'))); -// 발급여부 -if(is_coupon_downloaded($member['mb_id'], $cp['cz_id'])) +// 동시 요청으로 인한 쿠폰 중복 발급 방지 +$lock_key = 'g5_coupon_dl_'.$cz_id.'_'.addslashes($member['mb_id']); +$lock_row = sql_fetch(" select get_lock('$lock_key', 5) as lk "); +if(empty($lock_row['lk'])) + die(json_encode(array('error' => '잠시 후 다시 시도해 주십시오.'))); + +// 발급여부 (락 획득 후 재확인) +if(is_coupon_downloaded($member['mb_id'], $cp['cz_id'])) { + sql_query(" do release_lock('$lock_key') "); die(json_encode(array('error' => '이미 다운로드하신 쿠폰입니다.'))); +} // 포인트 쿠폰은 회원포인트 체크 -if($cp['cz_type'] && ($member['mb_point'] - $cp['cz_point']) < 0) +if($cp['cz_type'] && ($member['mb_point'] - $cp['cz_point']) < 0) { + sql_query(" do release_lock('$lock_key') "); die(json_encode(array('error' => '보유하신 포인트가 부족하여 쿠폰을 다운로드할 수 없습니다.'))); +} // 쿠폰발급 $j = 0; @@ -37,8 +47,10 @@ do { if(!$row3['cnt']) break; else { - if($j > 20) + if($j > 20) { + sql_query(" do release_lock('$lock_key') "); die(json_encode(array('error' => 'Coupon ID Error'))); + } } $j++; } while(1); @@ -65,4 +77,6 @@ if($result && $cp['cz_type']) // 다운로드 증가 sql_query(" update {$g5['g5_shop_coupon_zone_table']} set cz_download = cz_download + 1 where cz_id = '$cz_id' "); +sql_query(" do release_lock('$lock_key') "); + die(json_encode(array('error' => '')));