security: SVG 및 SVGZ 파일 업로드 차단
게시판, 1:1문의, 폼메일 및 쇼핑몰 설정의 클라이언트와 서버 검증에서 SVG 계열 파일 업로드를 거부한다.
This commit is contained in:
@@ -15,6 +15,16 @@ if(! (isset($_POST['de_admin_company_tel']) && check_vaild_callback($_POST['de_a
|
|||||||
// 로그인을 바로 이 주소로 하는 경우 쇼핑몰설정값이 사라지는 현상을 방지
|
// 로그인을 바로 이 주소로 하는 경우 쇼핑몰설정값이 사라지는 현상을 방지
|
||||||
if (!$_POST['de_admin_company_owner']) goto_url("./configform.php");
|
if (!$_POST['de_admin_company_owner']) goto_url("./configform.php");
|
||||||
|
|
||||||
|
$logo_img_fields = array('logo_img', 'logo_img2', 'mobile_logo_img', 'mobile_logo_img2');
|
||||||
|
foreach ($logo_img_fields as $logo_img_field) {
|
||||||
|
if (isset($_FILES[$logo_img_field]['name']) && $_FILES[$logo_img_field]['name']) {
|
||||||
|
$filename = get_safe_filename($_FILES[$logo_img_field]['name']);
|
||||||
|
if (is_disallowed_svg_filename($filename)) {
|
||||||
|
alert('허용되지 않는 파일 확장자입니다. (svg, svgz)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! empty($_POST['logo_img_del'])) @unlink(G5_DATA_PATH."/common/logo_img");
|
if (! empty($_POST['logo_img_del'])) @unlink(G5_DATA_PATH."/common/logo_img");
|
||||||
if (! empty($_POST['logo_img_del2'])) @unlink(G5_DATA_PATH."/common/logo_img2");
|
if (! empty($_POST['logo_img_del2'])) @unlink(G5_DATA_PATH."/common/logo_img2");
|
||||||
if (! empty($_POST['mobile_logo_img_del'])) @unlink(G5_DATA_PATH."/common/mobile_logo_img");
|
if (! empty($_POST['mobile_logo_img_del'])) @unlink(G5_DATA_PATH."/common/mobile_logo_img");
|
||||||
|
|||||||
+16
-3
@@ -28,9 +28,22 @@ if (!preg_match("/([0-9a-zA-Z_-]+)@([0-9a-zA-Z_-]+)\.([0-9a-zA-Z_-]+)/", $to)){
|
|||||||
}
|
}
|
||||||
|
|
||||||
$file = array();
|
$file = array();
|
||||||
|
|
||||||
|
// 첨부파일을 이동하기 전에 모든 파일명을 먼저 확인한다.
|
||||||
for ($i=1; $i<=$attach; $i++) {
|
for ($i=1; $i<=$attach; $i++) {
|
||||||
if ($_FILES['file'.$i]['name'])
|
$file_key = 'file'.$i;
|
||||||
$file[] = attach_file($_FILES['file'.$i]['name'], $_FILES['file'.$i]['tmp_name']);
|
if (isset($_FILES[$file_key]['name']) && $_FILES[$file_key]['name']) {
|
||||||
|
$filename = get_safe_filename($_FILES[$file_key]['name']);
|
||||||
|
if (is_disallowed_svg_filename($filename)) {
|
||||||
|
alert_close('허용되지 않는 파일 확장자입니다. (svg, svgz)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i=1; $i<=$attach; $i++) {
|
||||||
|
$file_key = 'file'.$i;
|
||||||
|
if (isset($_FILES[$file_key]['name']) && $_FILES[$file_key]['name'])
|
||||||
|
$file[] = attach_file($_FILES[$file_key]['name'], $_FILES[$file_key]['tmp_name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = stripslashes($content);
|
$content = stripslashes($content);
|
||||||
@@ -78,4 +91,4 @@ include_once(G5_PATH.'/head.sub.php');
|
|||||||
|
|
||||||
alert_close('메일을 정상적으로 발송하였습니다.');
|
alert_close('메일을 정상적으로 발송하였습니다.');
|
||||||
|
|
||||||
include_once(G5_PATH.'/tail.sub.php');
|
include_once(G5_PATH.'/tail.sub.php');
|
||||||
|
|||||||
@@ -133,6 +133,15 @@ if($w == 'u' || $w == 'a' || $w == 'r') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($_FILES['bf_file']['name']) && is_array($_FILES['bf_file']['name'])) {
|
||||||
|
foreach ($_FILES['bf_file']['name'] as $filename) {
|
||||||
|
$filename = get_safe_filename($filename);
|
||||||
|
if (is_disallowed_svg_filename($filename)) {
|
||||||
|
alert('허용되지 않는 파일 확장자입니다. (svg, svgz)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 파일개수 체크
|
// 파일개수 체크
|
||||||
$file_count = 0;
|
$file_count = 0;
|
||||||
$upload_count = isset($_FILES['bf_file']['name']) ? count($_FILES['bf_file']['name']) : 0;
|
$upload_count = isset($_FILES['bf_file']['name']) ? count($_FILES['bf_file']['name']) : 0;
|
||||||
|
|||||||
@@ -137,6 +137,15 @@ for ($i=1; $i<=10; $i++) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($_FILES['bf_file']['name']) && is_array($_FILES['bf_file']['name'])) {
|
||||||
|
foreach ($_FILES['bf_file']['name'] as $filename) {
|
||||||
|
$filename = get_safe_filename($filename);
|
||||||
|
if (is_disallowed_svg_filename($filename)) {
|
||||||
|
alert('허용되지 않는 파일 확장자입니다. (svg, svgz)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@include_once($board_skin_path.'/write_update.head.skin.php');
|
@include_once($board_skin_path.'/write_update.head.skin.php');
|
||||||
|
|
||||||
run_event('write_update_before', $board, $wr_id, $w, $qstr);
|
run_event('write_update_before', $board, $wr_id, $w, $qstr);
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
|||||||
// 예) https://도메인/css/default.css?ver=220620
|
// 예) https://도메인/css/default.css?ver=220620
|
||||||
// 예) https://도메인/js/common.js?ver=220620
|
// 예) https://도메인/js/common.js?ver=220620
|
||||||
define('G5_CSS_VER', '2303229');
|
define('G5_CSS_VER', '2303229');
|
||||||
define('G5_JS_VER', '2605291');
|
define('G5_JS_VER', '2608311');
|
||||||
|
|||||||
+91
-1
@@ -59,6 +59,72 @@ function trim(s)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SVG/SVGZ 업로드 파일 차단
|
||||||
|
function is_disallowed_svg_filename(filename)
|
||||||
|
{
|
||||||
|
// 서버의 파일명 정규화와 동일하게 특수문자를 제거
|
||||||
|
filename = (filename || "").replace(/[\0"'<>=#&!%\\()*+?]/g, "");
|
||||||
|
filename = filename.substring(filename.lastIndexOf("/") + 1);
|
||||||
|
filename = filename.replace(/[ .\t\n\r\v]+$/, "");
|
||||||
|
|
||||||
|
return /\.(svg|svgz)$/i.test(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_svg_upload_target(input)
|
||||||
|
{
|
||||||
|
var name = input.name || "";
|
||||||
|
|
||||||
|
if (name.indexOf("bf_file[") === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.form && input.form.name == "fformmail" && (name == "file1" || name == "file2")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input.form && input.form.name == "fconfig" &&
|
||||||
|
(name == "logo_img" || name == "logo_img2" || name == "mobile_logo_img" || name == "mobile_logo_img2");
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_disallowed_svg_file(input)
|
||||||
|
{
|
||||||
|
var i;
|
||||||
|
|
||||||
|
if (input.files && input.files.length) {
|
||||||
|
for (i=0; i<input.files.length; i++) {
|
||||||
|
if (is_disallowed_svg_filename(input.files[i].name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_disallowed_svg_filename(input.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_disallowed_svg_upload(form)
|
||||||
|
{
|
||||||
|
var invalid_file = null;
|
||||||
|
|
||||||
|
$(form).find("input[type=file]").each(function() {
|
||||||
|
if (is_svg_upload_target(this) && has_disallowed_svg_file(this)) {
|
||||||
|
invalid_file = this;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!invalid_file) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
alert("허용되지 않는 파일 확장자입니다. (svg, svgz)");
|
||||||
|
$(form).find("input:submit, button:submit, input:image").prop("disabled", false);
|
||||||
|
invalid_file.focus();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 자바스크립트로 PHP의 number_format 흉내를 냄
|
// 자바스크립트로 PHP의 number_format 흉내를 냄
|
||||||
// 숫자에 , 를 출력
|
// 숫자에 , 를 출력
|
||||||
function number_format(data)
|
function number_format(data)
|
||||||
@@ -728,6 +794,30 @@ function get_write_token(bo_table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
$(document).on("change", "input[type=file]", function() {
|
||||||
|
if (!is_svg_upload_target(this) || !has_disallowed_svg_file(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
alert("허용되지 않는 파일 확장자입니다. (svg, svgz)");
|
||||||
|
this.value = "";
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (document.addEventListener) {
|
||||||
|
document.addEventListener("submit", function(event) {
|
||||||
|
if (!check_disallowed_svg_upload(event.target)) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
} else {
|
||||||
|
$(document).on("submit", "form", function() {
|
||||||
|
return check_disallowed_svg_upload(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$(document).on("click", "form[name=fwrite] input:submit, form[name=fwrite] button:submit, form[name=fwrite] input:image", function() {
|
$(document).on("click", "form[name=fwrite] input:submit, form[name=fwrite] button:submit, form[name=fwrite] input:image", function() {
|
||||||
var f = this.form;
|
var f = this.form;
|
||||||
|
|
||||||
@@ -752,4 +842,4 @@ $(function() {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4011,6 +4011,26 @@ function get_safe_filename($name)
|
|||||||
return $name;
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 업로드 파일명이 SVG 또는 SVGZ 확장자인지 확인
|
||||||
|
function is_disallowed_svg_filename($filename)
|
||||||
|
{
|
||||||
|
if (!is_string($filename) || $filename === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = str_replace(array("\0", '\\'), array('', '/'), $filename);
|
||||||
|
$filename = basename($filename);
|
||||||
|
$filename = rtrim($filename, " .\t\n\r\0\x0B");
|
||||||
|
|
||||||
|
if ($filename === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
return in_array($extension, array('svg', 'svgz'), true);
|
||||||
|
}
|
||||||
|
|
||||||
// 파일명 치환
|
// 파일명 치환
|
||||||
function replace_filename($name)
|
function replace_filename($name)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user