[security]sql_query() 에러 노출 시 SQL/스키마 정보 차단

sql_query()의 에러 처리가 die()로 SQL 쿼리 전문, MySQL 에러 메시지,
스크립트 파일 경로를 사용자에게 그대로 노출하고 있었음. 기본값
G5_DISPLAY_SQL_ERROR=false 덕분에 일반 호출에서는 트리거되지 않으나,
일부 admin 파일이 명시적으로 sql_query(\$sql, true)로 호출하여
관리자에게 raw SQL을 노출했고, SQLi 공격 시도 중 발생한 에러로 DB
구조(테이블/컬럼명)가 학습되어 정밀 공격에 활용될 수 있었음.

조치:
- 서버 로그(error_log)에는 항상 상세 기록 → 운영자가 디버깅 가능
- \$is_debug 모드(G5_DEBUG=true 또는 super admin)에서만 상세 표시
  + XSS 방지를 위해 htmlspecialchars로 escape
- 그 외 환경에서는 "데이터베이스 처리 중 오류가 발생했습니다." 만 표시
- mysqli/mysql 폴백 분기 둘 다 동일하게 적용

변경:
- lib/common.lib.php:1932 (mysqli 분기)
- lib/common.lib.php:1942 (mysql 분기, 레거시 PHP 5.x 폴백)

PHP 5.2.17 호환 유지 (htmlspecialchars + ENT_QUOTES 모두 PHP 4.0+).
This commit is contained in:
thisgun
2026-04-16 02:48:31 +00:00
parent 79f915988b
commit 5331aa8be5
+33 -2
View File
@@ -1929,7 +1929,24 @@ function sql_query($sql, $error=G5_DISPLAY_SQL_ERROR, $link=null)
if(function_exists('mysqli_query') && G5_MYSQLI_USE) {
if ($error) {
$result = @mysqli_query($link, $sql) or die("<p>$sql<p>" . mysqli_errno($link) . " : " . mysqli_error($link) . "<p>error file : {$_SERVER['SCRIPT_NAME']}");
$result = @mysqli_query($link, $sql);
if (!$result) {
$err_no = mysqli_errno($link);
$err_msg = mysqli_error($link);
$err_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
// 서버 로그에는 항상 상세 기록 (운영자가 추적 가능하도록)
@error_log("[g5 sql_query] {$err_no}: {$err_msg} | SQL: {$sql} | file: {$err_file}");
if ($is_debug) {
// 디버그 모드: 상세 표시 (XSS 방지를 위해 escape)
die("<p>" . htmlspecialchars($sql, ENT_QUOTES, 'UTF-8')
. "<p>" . (int)$err_no . " : " . htmlspecialchars($err_msg, ENT_QUOTES, 'UTF-8')
. "<p>error file : " . htmlspecialchars($err_file, ENT_QUOTES, 'UTF-8'));
}
// 운영 환경: 일반 메시지로만 처리하여 DB 구조/경로 정보 노출 방지
die('데이터베이스 처리 중 오류가 발생했습니다.');
}
} else {
try {
$result = @mysqli_query($link, $sql);
@@ -1939,7 +1956,21 @@ function sql_query($sql, $error=G5_DISPLAY_SQL_ERROR, $link=null)
}
} else {
if ($error) {
$result = @mysql_query($sql, $link) or die("<p>$sql<p>" . mysql_errno() . " : " . mysql_error() . "<p>error file : {$_SERVER['SCRIPT_NAME']}");
$result = @mysql_query($sql, $link);
if (!$result) {
$err_no = mysql_errno();
$err_msg = mysql_error();
$err_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
@error_log("[g5 sql_query] {$err_no}: {$err_msg} | SQL: {$sql} | file: {$err_file}");
if ($is_debug) {
die("<p>" . htmlspecialchars($sql, ENT_QUOTES, 'UTF-8')
. "<p>" . (int)$err_no . " : " . htmlspecialchars($err_msg, ENT_QUOTES, 'UTF-8')
. "<p>error file : " . htmlspecialchars($err_file, ENT_QUOTES, 'UTF-8'));
}
die('데이터베이스 처리 중 오류가 발생했습니다.');
}
} else {
$result = @mysql_query($sql, $link);
}