Skip to content

Commit

Permalink
Merge pull request #2474 from QuizandSurveyMaster/result-template-enc…
Browse files Browse the repository at this point in the history
…oding-sanitizing

encode result template and sanitize
  • Loading branch information
zubairraeen authored Feb 26, 2024
2 parents a56bbc9 + 26e4f36 commit aa63282
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 5 deletions.
58 changes: 58 additions & 0 deletions js/qsm-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,64 @@ if(current_id == 'qsm_variable_text'){ jQuery(".current_variable")[0].click();}
}

});

function sanitizeHtml(content) {

// Match <img> tags with src attributes
content = content.replace(/<img\b.*?src\s*=\s*['"]([^'"]+)['"].*?>/gi, function(match, src) {
src = ( 'undefined' === typeof src || null === src ) ? '': src.split('?')[0];
// Check if the src URL is valid (ends with .jpg, .jpeg, .png, or .gif)
if (src.match(/\.(jpg|jpeg|png|gif|webp)$/i)) {
return match; // Valid src, keep the <img> tag
} else {
return ''; // Invalid src, remove the <img> tag
}
});

// Remove style attribute
content = content.replace(/style\s*=\s*(['"])(.*?)\1/gi, '');

// Remove background attribute
content = content.replace(/background\s*=\s*(['"])(.*?)\1/gi, '');

// Remove 'javascript:' injection, alert, prompt, confirm
content = content.replace(/javascript:/gi, '');
content = content.replace(/alert\(/gi, '');
content = content.replace(/prompt\(/gi, '');
content = content.replace(/confirm\(/gi, '');

// Remove unwanted HTML tags like script, svg, title, meta, input etc.
content = content.replace(/<script\b[^>]*>.*?<\/script>/gi, '');
content = content.replace(/<svg\b[^>]*>.*?<\/svg>/gi, '');
content = content.replace(/<title\b[^>]*>.*?<\/title>/gi, '');
content = content.replace(/<meta\b[^>]*>/gi, '');
content = content.replace(/<input\b[^>]*>/gi, '');
content = content.replace(/<link\b[^>]*>/gi, '');

// Remove any on event attributes
content = content.replace(/on\w+\s*=\s*(['"][^'"]*['"]|[^>\s]+)/gi, '');

return content;
}

// On change : sanitize content
editor.on('change', function(e) {

//Only for result template
if ( -1 != editor.id.indexOf('results-page') ) {

var content = editor.getContent();
var newContent = sanitizeHtml( content );
//if sanitize string and content are not same
if ( content != newContent ) {
//Set content
editor.setContent( newContent );
// Move the cursor to the end
editor.selection.select(editor.getBody(), true);
editor.selection.collapse(false);
}
}
});
});
}
}
Expand Down
57 changes: 54 additions & 3 deletions php/classes/class-qsm-results-pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ public static function generate_pages( $response_data ) {

// Decodes special characters, runs through our template
// variables, and then outputs the text.
$page = htmlspecialchars_decode( $content, ENT_QUOTES );
//$page = htmlspecialchars_decode( $content, ENT_QUOTES );
$page = wp_kses_post( $content );

//last chance to filter $page
$page = apply_filters( 'qsm_template_variable_results_page', $page, $response_data );
Expand Down Expand Up @@ -320,6 +321,51 @@ public static function convert_to_new_system( $quiz_id ) {
return $pages;
}

public static function sanitize_html( $html = '' ) {

//Decode Html
$html = htmlspecialchars_decode( $html, ENT_QUOTES );

// Remove unwanted html tags
$html = preg_replace('/<(script|form|textarea|div|body|title|svg|link|meta)[^>]*>.*?<\/\1>/is', '', $html);

// Remove styles attributes
$html = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $html);

// Remove background attributes
$html = preg_replace('/(<[^>]+) background=".*?"/i', '$1', $html);

// Remove input tags
$html = preg_replace('/<input\b[^>]*>/i', '', $html);

// Remove any on event attributes
$html = preg_replace('/\s*on\w+\s*=\s*("[^"]*"|\'[^\']*\'|[^\s>]+)/i', '', $html);

// Remove any alert, confirm, or prompt calls
$html = preg_replace('/\b(alert|confirm|prompt)\s*\(\s*[^;]*\s*\)\s*;?/i', '', $html);

// Remove any javascript: URLs
$html = preg_replace('/javascript:/i', '', $html);

// Filter image src for possible image types, safe URL, and no $_GET parameters
$html = preg_replace_callback('/<img\s+src\s*=\s*["\']([^"\']+?)["\'][^>]*>/i', function($matches) {
$src = $matches[1];
$valid_image_types = array('jpg', 'jpeg', 'png', 'gif', 'webp' );
$file_extension = pathinfo($src, PATHINFO_EXTENSION);
$url_parts = parse_url($src);

if (in_array(strtolower($file_extension), $valid_image_types) &&
isset($url_parts['scheme']) && in_array(strtolower($url_parts['scheme']), array('http', 'https')) &&
empty($url_parts['query'])) {
return $matches[0];
} else {
return '';
}
}, $html);

return $html;
}

/**
* Saves the results pages for a quiz.
*
Expand Down Expand Up @@ -367,8 +413,13 @@ public static function save_pages( $quiz_id, $pages ) {

// Sanitize template data
if ( isset( $pages[ $i ]['page'] ) && $is_not_allow_html ) {
$pages[ $i ]['page'] = wp_kses_post( preg_replace( '/<span class="qsm-highlight-variables">([^<]+)<\/span>/', '%$1%', $pages[ $i ]['page'] ) );

$pages[ $i ]['page'] = QSM_Results_Pages::sanitize_html( $pages[ $i ]['page'] );
//Check if encoded html string given
if ( false === stripos( $pages[ $i ]['page'] ,'&lt;span class=&quot;qsm-highlight-variables&quot;&gt;') ) {
$pages[ $i ]['page'] = wp_kses_post( preg_replace( '/<span class="qsm-highlight-variables">([^<]+)<\/span>/', '%$1%', $pages[ $i ]['page'] ) );
} else {
$pages[ $i ]['page'] = wp_kses_post( preg_replace('/&lt;span class=&quot;qsm-highlight-variables&quot;&gt;([^&]+)&lt;\/span&gt;/i', '%$1%', $pages[ $i ]['page'] ) );
}
}
$pages[ $i ]['default_mark'] = sanitize_text_field( $pages[ $i ]['default_mark'] );

Expand Down
8 changes: 6 additions & 2 deletions php/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ function qsm_register_rest_routes() {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => 'qsm_rest_save_question',
'permission_callback' => '__return_true',
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
)
);
register_rest_route(
Expand All @@ -67,7 +69,9 @@ function qsm_register_rest_routes() {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => 'qsm_rest_save_results',
'permission_callback' => '__return_true',
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
)
);
register_rest_route(
Expand Down

0 comments on commit aa63282

Please sign in to comment.