CVE-2018-18678: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: GNUBOARD5 before 5.3.2.0 has XSS that allows remote attackers to inject arbitrary web script or HTML via the "board group extra contents" parameter, aka the adm/boardgroup_form_update.php gr_1~10 parameter.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2019-10-30T18:15Z
Repository: https://github.com/gnuboard/gnuboard5
Language: PHP
Files changed: adm/board_form_update.php, adm/boardgroup_form.php, adm/config_form.php, adm/config_form_update.php, adm/menu_list.php, adm/menu_list_update.php, bbs/board_head.php, bbs/board_tail.php, bbs/password.php
Commit date: 2018-10-30 09:42:48 +0900
Commit message: XSS 취약점 수정

Diff: diff --git a/adm/board_form_update.php b/adm/board_form_update.php
index 91288776..2222baad 100644
--- a/adm/board_form_update.php
+++ b/adm/board_form_update.php
@@ -70,10 +70,13 @@ $src_char = array('&', '=');
 $dst_char = array('＆', '〓');
 $bo_category_list = str_replace($src_char, $dst_char, $bo_category_list);
 //https://github.com/gnuboard/gnuboard5/commit/f5f4925d4eb28ba1af728e1065fc2bdd9ce1da58 에 따른 조치
 $str_bo_category_list = isset($_POST['bo_category_list']) ? preg_replace("/[\<\>\'\"\\\'\\\"\%\=\(\)\/\^\*]/", "", $_POST['bo_category_list']) : '';
 
+$_POST['bo_subject'] = strip_tags($_POST['bo_subject']);
+$_POST['bo_mobile_subject'] = strip_tags($_POST['bo_mobile_subject']);
+
 $sql_common = " gr_id               = '{$_POST['gr_id']}',
                 bo_subject          = '{$_POST['bo_subject']}',
                 bo_mobile_subject   = '{$_POST['bo_mobile_subject']}',
                 bo_device           = '{$_POST['bo_device']}',
                 bo_admin            = '{$_POST['bo_admin']}',
diff --git a/adm/boardgroup_form.php b/adm/boardgroup_form.php
index 73e162d9..c9e8338b 100644
--- a/adm/boardgroup_form.php
+++ b/adm/boardgroup_form.php
@@ -115,11 +115,11 @@ include_once('./admin.head.php');
         <th scope="row">여분필드<?php echo $i ?></th>
         <td class="td_extra">
             <label for="gr_<?php echo $i ?>_subj">여분필드 <?php echo $i ?> 제목</label>
             <input type="text" name="gr_<?php echo $i ?>_subj" value="<?php echo get_text($group['gr_'.$i.'_subj']) ?>" id="gr_<?php echo $i ?>_subj" class="frm_input">
             <label for="gr_<?php echo $i ?>">여분필드 <?php echo $i ?> 내용</label>
-            <input type="text" name="gr_<?php echo $i ?>" value="<?php echo $gr['gr_'.$i] ?>" id="gr_<?php echo $i ?>" class="frm_input">
+            <input type="text" name="gr_<?php echo $i ?>" value="<?php echo get_sanitize_input($gr['gr_'.$i]); ?>" id="gr_<?php echo $i ?>" class="frm_input">
         </td>
     </tr>
     <?php } ?>
     </tbody>
     </table>
diff --git a/adm/config_form.php b/adm/config_form.php
index 00915fe7..e4daee96 100644
--- a/adm/config_form.php
+++ b/adm/config_form.php
@@ -1315,11 +1315,11 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) {
             <th scope="row">여분필드<?php echo $i ?></th>
             <td class="td_extra">
                 <label for="cf_<?php echo $i ?>_subj">여분필드<?php echo $i ?> 제목</label>
                 <input type="text" name="cf_<?php echo $i ?>_subj" value="<?php echo get_text($config['cf_'.$i.'_subj']) ?>" id="cf_<?php echo $i ?>_subj" class="frm_input" size="30">
                 <label for="cf_<?php echo $i ?>">여분필드<?php echo $i ?> 값</label>
-                <input type="text" name="cf_<?php echo $i ?>" value="<?php echo $config['cf_'.$i] ?>" id="cf_<?php echo $i ?>" class="frm_input" size="30">
+                <input type="text" name="cf_<?php echo $i ?>" value="<?php echo get_sanitize_input($config['cf_'.$i]); ?>" id="cf_<?php echo $i ?>" class="frm_input" size="30">
             </td>
         </tr>
         <?php } ?>
         </tbody>
         </table>
diff --git a/adm/config_form_update.php b/adm/config_form_update.php
index 03179c34..12678638 100644
--- a/adm/config_form_update.php
+++ b/adm/config_form_update.php
@@ -24,10 +24,12 @@ if(!$_POST['cf_cert_use']) {
     $_POST['cf_cert_hp'] = '';
 }
 
 $cf_social_servicelist = !empty($_POST['cf_social_servicelist']) ? implode(',', $_POST['cf_social_servicelist']) : '';
 
+$_POST['cf_title'] = strip_tags($_POST['cf_title']);
+
 $sql = " update {$g5['config_table']}
             set cf_title = '{$_POST['cf_title']}',
                 cf_admin = '{$_POST['cf_admin']}',
                 cf_admin_email = '{$_POST['cf_admin_email']}',
                 cf_admin_email_name = '{$_POST['cf_admin_email_name']}',
diff --git a/adm/menu_list.php b/adm/menu_list.php
index ffe88aee..4a6c2512 100644
--- a/adm/menu_list.php
+++ b/adm/menu_list.php
@@ -194,10 +194,24 @@ function base_convert(number, frombase, tobase) {
     .toString(tobase | 0);
 }
 
 function fmenulist_submit(f)
 {
+
+    var me_links = document.getElementsByName('me_link[]');
+    var reg = /^javascript/; 
+
+	for (i=0; i<me_links.length; i++){
+        
+	    if( reg.test(me_links[i].value) ){ 
+        
+            alert('링크에 자바스크립트문을 입력할수 없습니다.');
+            me_links[i].focus();
+            return false;
+        }
+    }
+
     return true;
 }
 </script>
 
 <?php
diff --git a/adm/menu_list_update.php b/adm/menu_list_update.php
index f05e2ec2..4244d334 100644
--- a/adm/menu_list_update.php
+++ b/adm/menu_list_update.php
@@ -21,12 +21,12 @@ for ($i=0; $i<$count; $i++)
 {
     $_POST = array_map_deep('trim', $_POST);
 
     $code    = $_POST['code'][$i];
     $me_name = $_POST['me_name'][$i];
-    $me_link = $_POST['me_link'][$i];
-
+    $me_link = preg_match('/^javascript/', $_POST['me_link'][$i]) ? G5_URL : strip_tags($_POST['me_link'][$i]);
+    
     if(!$code || !$me_name || !$me_link)
         continue;
 
     $sub_code = '';
     if($group_code == $code) {
diff --git a/bbs/board_head.php b/bbs/board_head.php
index 04b60450..a62706a2 100644
--- a/bbs/board_head.php
+++ b/bbs/board_head.php
@@ -3,15 +3,15 @@ if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
 
 // 게시판 관리의 상단 내용
 if (G5_IS_MOBILE) {
     // 모바일의 경우 설정을 따르지 않는다.
     include_once(G5_BBS_PATH.'/_head.php');
-    echo stripslashes($board['bo_mobile_content_head']);
+    echo html_purifier(stripslashes($board['bo_mobile_content_head']));
 } else {
     if(is_include_path_check($board['bo_include_head'])) {  //파일경로 체크
         @include ($board['bo_include_head']);
     } else {    //파일경로가 올바르지 않으면 기본파일을 가져옴
         include_once(G5_BBS_PATH.'/_head.php');
     }
-    echo stripslashes($board['bo_content_head']);
+    echo html_purifier(stripslashes($board['bo_content_head']));
 }
 ?>
\ No newline at end of file
diff --git a/bbs/board_tail.php b/bbs/board_tail.php
index 57b81b46..436e2cc3 100644
--- a/bbs/board_tail.php
+++ b/bbs/board_tail.php
@@ -1,15 +1,15 @@
 <?php
 if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
 
 // 게시판 관리의 하단 파일 경로
 if (G5_IS_MOBILE) {
-    echo stripslashes($board['bo_mobile_content_tail']);
+    echo html_purifier(stripslashes($board['bo_mobile_content_tail']));
     // 모바일의 경우 설정을 따르지 않는다.
     include_once(G5_BBS_PATH.'/_tail.php');
 } else {
-    echo stripslashes($board['bo_content_tail']);
+    echo html_purifier(stripslashes($board['bo_content_tail']));
     if(is_include_path_check($board['bo_include_tail'])) {  //파일경로 체크
         @include ($board['bo_include_tail']);
     } else {    //파일경로가 올바르지 않으면 기본파일을 가져옴
         include_once(G5_BBS_PATH.'/_tail.php');
     }
diff --git a/bbs/password.php b/bbs/password.php
index e5e0a4d4..646f3b64 100644
--- a/bbs/password.php
+++ b/bbs/password.php
@@ -41,12 +41,12 @@ switch ($w) {
         alert('w 값이 제대로 넘어오지 않았습니다.');
 }
 
 include_once(G5_PATH.'/head.sub.php');
 
-//if ($board['bo_include_head']) { @include ($board['bo_include_head']); }
-//if ($board['bo_content_head']) { echo stripslashes($board['bo_content_head']); }
+//if ($board['bo_include_head'] && is_include_path_check($board['bo_content_head'])) { @include ($board['bo_include_head']); }
+//if ($board['bo_content_head']) { echo html_purifier(stripslashes($board['bo_content_head'])); }
 
 /* 비밀글의 제목을 가져옴 지운아빠 2013-01-29 */
 $sql = " select wr_subject from {$write_table}
                       where wr_num = '{$write['wr_num']}'
                       and wr_reply = ''
@@ -55,10 +55,10 @@ $row = sql_fetch($sql);
 
 $g5['title'] = get_text($row['wr_subject']);
 
 include_once($member_skin_path.'/password.skin.php');
 
-//if ($board['bo_content_tail']) { echo stripslashes($board['bo_content_tail']); }
-//if ($board['bo_include_tail']) { @include ($board['bo_include_tail']); }
+//if ($board['bo_content_tail']) { echo html_purifier(stripslashes($board['bo_content_tail'])); }
+//if ($board['bo_include_tail'] && is_include_path_check($board['bo_content_tail'])) { @include ($board['bo_include_tail']); }
 
 include_once(G5_PATH.'/tail.sub.php');
 ?>

Vulnerable code:             <input type="text" name="gr_<?php echo $i ?>" value="<?php echo $gr['gr_'.$i] ?>" id="gr_<?php echo $i ?>" class="frm_input">
                <input type="text" name="cf_<?php echo $i ?>" value="<?php echo $config['cf_'.$i] ?>" id="cf_<?php echo $i ?>" class="frm_input" size="30">
    $me_link = $_POST['me_link'][$i];

    echo stripslashes($board['bo_mobile_content_head']);
    echo stripslashes($board['bo_content_head']);
    echo stripslashes($board['bo_mobile_content_tail']);
    echo stripslashes($board['bo_content_tail']);
//if ($board['bo_include_head']) { @include ($board['bo_include_head']); }
//if ($board['bo_content_head']) { echo stripslashes($board['bo_content_head']); }
//if ($board['bo_content_tail']) { echo stripslashes($board['bo_content_tail']); }
//if ($board['bo_include_tail']) { @include ($board['bo_include_tail']); }
Fixed code: $_POST['bo_subject'] = strip_tags($_POST['bo_subject']);
$_POST['bo_mobile_subject'] = strip_tags($_POST['bo_mobile_subject']);

            <input type="text" name="gr_<?php echo $i ?>" value="<?php echo get_sanitize_input($gr['gr_'.$i]); ?>" id="gr_<?php echo $i ?>" class="frm_input">
                <input type="text" name="cf_<?php echo $i ?>" value="<?php echo get_sanitize_input($config['cf_'.$i]); ?>" id="cf_<?php echo $i ?>" class="frm_input" size="30">
$_POST['cf_title'] = strip_tags($_POST['cf_title']);


    var me_links = document.getElementsByName('me_link[]');
    var reg = /^javascript/; 

	for (i=0; i<me_links.length; i++){
        
	    if( reg.test(me_links[i].value) ){ 
        
            alert('링크에 자바스크립트문을 입력할수 없습니다.');
            me_links[i].focus();
            return false;
        }
    }

    $me_link = preg_match('/^javascript/', $_POST['me_link'][$i]) ? G5_URL : strip_tags($_POST['me_link'][$i]);
    
    echo html_purifier(stripslashes($board['bo_mobile_content_head']));
    echo html_purifier(stripslashes($board['bo_content_head']));
    echo html_purifier(stripslashes($board['bo_mobile_content_tail']));
    echo html_purifier(stripslashes($board['bo_content_tail']));
//if ($board['bo_include_head'] && is_include_path_check($board['bo_content_head'])) { @include ($board['bo_include_head']); }
//if ($board['bo_content_head']) { echo html_purifier(stripslashes($board['bo_content_head'])); }
//if ($board['bo_content_tail']) { echo html_purifier(stripslashes($board['bo_content_tail'])); }
//if ($board['bo_include_tail'] && is_include_path_check($board['bo_content_tail'])) { @include ($board['bo_include_tail']); }