Files
Gnuboard5/adm/qa_config_update.php
T
thisgunandClaude Opus 4.7 f4f8c57a74 [security] 관리자 영역 권한 검증 누락 및 CSRF 토큰 누락 수정
- adm/qa_config_update.php / adm/contentformupdate.php :
  qa_include_head/tail, co_include_head/tail 가 super 가드 없이 변경 가능해
  하위 관리자가 임의 PHP 경로를 include 시킬 수 있던 LFI 위험을
  board_form_update.php 와 동일한 패턴(super 외에는 기존 값 유지)으로 차단.

- adm/member_form_update.php / adm/member_list_update.php :
  신규 회원 생성·일괄 수정 시 부여하려는 mb_level 상한 검증이 없어
  하위 관리자가 자기보다 높은 등급을 부여할 수 있던 권한 상승을 차단.

- adm/shop_admin/categorylistupdate.php /
  adm/shop_admin/itemformupdate.php :
  is_include_path_check 호출에서 두 번째 인자(is_input=1) 누락으로
  rar/php/zip wrapper 등 경로 wrapper 차단이 동작하지 않던 부분을
  is_include_path_check($file, 1) 로 강화.

- adm/shop_admin/orderdeliveryupdate.php /
  adm/shop_admin/orderpartcancelupdate.php /
  adm/sendmail_test.php :
  상태 변경 동작에 check_admin_token() 누락으로 발생하던 CSRF 위험을
  토큰 검증 추가로 차단. sendmail_test 폼에는 hidden token 필드 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 03:35:29 +00:00

128 lines
6.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
$sub_menu = "300500";
require_once './_common.php';
check_demo();
auth_check_menu($auth, $sub_menu, 'w');
check_admin_token();
$error_msg = '';
$qaconfig = get_qa_config();
$check_keys = array('qa_title', 'qa_category', 'qa_skin', 'qa_mobile_skin', 'qa_use_email', 'qa_req_email', 'qa_use_hp', 'qa_req_hp', 'qa_use_sms', 'qa_send_number', 'qa_admin_hp', 'qa_admin_email', 'qa_subject_len', 'qa_mobile_subject_len', 'qa_page_rows', 'qa_mobile_page_rows', 'qa_image_width', 'qa_upload_size');
foreach ($check_keys as $key) {
$$key = $_POST[$key] = isset($_POST[$key]) ? strip_tags(clean_xss_attributes($_POST[$key])) : '';
}
$qa_include_head = isset($qa_include_head) ? preg_replace(array("#[\\\]+$#", "#(<\?php|<\?)#i"), "", substr($qa_include_head, 0, 255)) : '';
$qa_include_tail = isset($qa_include_tail) ? preg_replace(array("#[\\\]+$#", "#(<\?php|<\?)#i"), "", substr($qa_include_tail, 0, 255)) : '';
// 최고 관리자가 아니면 include 경로 변경 불가 (board_form_update.php 와 동일 정책)
if ($is_admin !== 'super') {
$qa_include_head = isset($qaconfig['qa_include_head']) ? $qaconfig['qa_include_head'] : '';
$qa_include_tail = isset($qaconfig['qa_include_tail']) ? $qaconfig['qa_include_tail'] : '';
}
// 관리자가 자동등록방지를 사용해야 할 경우
if ($board && ($qaconfig['qa_include_head'] !== $qa_include_head || $qaconfig['qa_include_tail'] !== $qa_include_tail) && function_exists('get_admin_captcha_by') && get_admin_captcha_by()) {
include_once G5_CAPTCHA_PATH . '/captcha.lib.php';
if (!chk_captcha()) {
alert('자동등록방지 숫자가 틀렸습니다.');
}
}
if ($qa_include_head) {
$file_ext = pathinfo($qa_include_head, PATHINFO_EXTENSION);
if (!$file_ext || !in_array($file_ext, array('php', 'htm', 'html')) || !preg_match('/^.*\.(php|htm|html)$/i', $qa_include_head)) {
alert('상단 파일 경로의 확장자는 php, htm, html 만 허용합니다.');
}
}
if ($qa_include_tail) {
$file_ext = pathinfo($qa_include_tail, PATHINFO_EXTENSION);
if (!$file_ext || !in_array($file_ext, array('php', 'htm', 'html')) || !preg_match('/^.*\.(php|htm|html)$/i', $qa_include_tail)) {
alert('하단 파일 경로의 확장자는 php, htm, html 만 허용합니다.');
}
}
if ($qa_include_head && !is_include_path_check($qa_include_head, 1)) {
$qa_include_head = '';
$error_msg = '/data/file/ 또는 /data/editor/ 포함된 문자를 상단 파일 경로에 포함시킬수 없습니다.';
}
if ($qa_include_tail && !is_include_path_check($qa_include_tail, 1)) {
$qa_include_tail = '';
$error_msg = '/data/file/ 또는 /data/editor/ 포함된 문자를 하단 파일 경로에 포함시킬수 없습니다.';
}
if (function_exists('filter_input_include_path')) {
$qa_include_head = filter_input_include_path($qa_include_head);
$qa_include_tail = filter_input_include_path($qa_include_tail);
}
// 분류에 & 나 = 는 사용이 불가하므로 2바이트로 바꾼다.
$src_char = array('&', '=');
$dst_char = array('&', '〓');
$qa_category = str_replace($src_char, $dst_char, $_POST['qa_category']);
//https://github.com/gnuboard/gnuboard5/commit/f5f4925d4eb28ba1af728e1065fc2bdd9ce1da58 에 따른 조치
$qa_category = preg_replace("/[\<\>\'\"\\\'\\\"\%\=\(\)\/\^\*]/", "", (string)$qa_category);
$sql = " update {$g5['qa_config_table']}
set qa_title = '{$_POST['qa_title']}',
qa_category = '{$qa_category}',
qa_skin = '{$_POST['qa_skin']}',
qa_mobile_skin = '{$_POST['qa_mobile_skin']}',
qa_use_email = '{$_POST['qa_use_email']}',
qa_req_email = '{$_POST['qa_req_email']}',
qa_use_hp = '{$_POST['qa_use_hp']}',
qa_req_hp = '{$_POST['qa_req_hp']}',
qa_use_sms = '{$_POST['qa_use_sms']}',
qa_send_number = '{$_POST['qa_send_number']}',
qa_admin_hp = '{$_POST['qa_admin_hp']}',
qa_admin_email = '{$_POST['qa_admin_email']}',
qa_use_editor = '{$_POST['qa_use_editor']}',
qa_subject_len = '{$_POST['qa_subject_len']}',
qa_mobile_subject_len = '{$_POST['qa_mobile_subject_len']}',
qa_page_rows = '{$_POST['qa_page_rows']}',
qa_mobile_page_rows = '{$_POST['qa_mobile_page_rows']}',
qa_image_width = '{$_POST['qa_image_width']}',
qa_upload_size = '{$_POST['qa_upload_size']}',
qa_insert_content = '{$_POST['qa_insert_content']}',
qa_include_head = '{$qa_include_head}',
qa_include_tail = '{$qa_include_tail}',
qa_content_head = '{$_POST['qa_content_head']}',
qa_content_tail = '{$_POST['qa_content_tail']}',
qa_mobile_content_head = '{$_POST['qa_mobile_content_head']}',
qa_mobile_content_tail = '{$_POST['qa_mobile_content_tail']}',
qa_1_subj = '{$_POST['qa_1_subj']}',
qa_2_subj = '{$_POST['qa_2_subj']}',
qa_3_subj = '{$_POST['qa_3_subj']}',
qa_4_subj = '{$_POST['qa_4_subj']}',
qa_5_subj = '{$_POST['qa_5_subj']}',
qa_1 = '{$_POST['qa_1']}',
qa_2 = '{$_POST['qa_2']}',
qa_3 = '{$_POST['qa_3']}',
qa_4 = '{$_POST['qa_4']}',
qa_5 = '{$_POST['qa_5']}' ";
sql_query($sql);
run_event('admin_qa_config_updated');
if (function_exists('get_admin_captcha_by')) {
get_admin_captcha_by('remove');
}
if ($error_msg) {
alert($error_msg, './qa_config.php');
} else {
goto_url('./qa_config.php');
}