- 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>
128 lines
6.0 KiB
PHP
128 lines
6.0 KiB
PHP
<?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');
|
||
}
|