From d2b2da3eed4b85f7aa5c246089ab7e41c5107785 Mon Sep 17 00:00:00 2001 From: ozh Date: Thu, 2 Jan 2014 19:22:46 +0100 Subject: [PATCH] Escape all the things. Damnit, it's ashaming. Fixes #1475, #1532 & #1531 --- includes/functions-formatting.php | 40 ++++++++++++++++++++++++++++--- includes/functions.php | 30 +++++++++++++---------- yourls-infos.php | 2 +- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/includes/functions-formatting.php b/includes/functions-formatting.php index e66493f..f16219f 100644 --- a/includes/functions-formatting.php +++ b/includes/functions-formatting.php @@ -120,12 +120,46 @@ function yourls_sanitize_int( $in ) { } /** - * Escape a string + * Escape a string or an array of strings before DB usage. ALWAYS escape before using in a SQL query. Thanks. * + * @param string|array $data string or array of strings to be escaped + * @return string|array escaped data */ -function yourls_escape( $in ) { +function yourls_escape( $data ) { + if( is_array( $data ) ) { + foreach( $data as $k => $v ) { + if( is_array( $v ) ) { + $data[ $k ] = yourls_escape( $v ); + } else { + $data[ $k ] = yourls_escape_real( $v ); + } + } + } else { + $data = yourls_escape_real( $data ); + } + + return $data; +} + +/** + * "Real" escape. This function should NOT be called directly. Use yourls_escape() instead. + * + * This function uses a "real" escape if possible, using PDO, MySQL or MySQLi functions, + * with a fallback to a "simple" addslashes + * If you're implementing a custom DB engine or a custom cache system, you can define an + * escape function using filter 'custom_escape_real' + * + * @since 1.7 + * @param string $a string to be escaped + * @return string escaped string + */ +function yourls_escape_real( $string ) { global $ydb; - return $ydb->escape( $in ); + if( isset( $ydb ) && is_a( $ydb, 'ezSQLcore' ) ) + return $ydb->escape( $string ); + + // YOURLS DB classes have been bypassed by a custom DB engine or a custom cache layer + return yourls_apply_filters( 'custom_escape_real', addslashes( $string ), $string ); } /** diff --git a/includes/functions.php b/includes/functions.php index 2c6ee6b..eb74aa7 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -138,7 +138,7 @@ function yourls_delete_link_by_keyword( $keyword ) { global $ydb; $table = YOURLS_DB_TABLE_URL; - $keyword = yourls_sanitize_string( $keyword ); + $keyword = yourls_escape( yourls_sanitize_string( $keyword ) ); $delete = $ydb->query("DELETE FROM `$table` WHERE `keyword` = '$keyword';"); yourls_do_action( 'delete_link', $keyword, $delete ); return $delete; @@ -177,8 +177,8 @@ function yourls_url_exists( $url ) { global $ydb; $table = YOURLS_DB_TABLE_URL; - $strip_url = stripslashes($url); - $url_exists = $ydb->get_row("SELECT * FROM `$table` WHERE `url` = '".$strip_url."';"); + $url = yourls_escape( yourls_sanitize_url( $url) ); + $url_exists = $ydb->get_row( "SELECT * FROM `$table` WHERE `url` = '".$url."';" ); return yourls_apply_filter( 'url_exists', $url_exists, $url ); } @@ -332,7 +332,7 @@ function yourls_edit_link( $url, $keyword, $newkeyword='', $title='' ) { // Check if new URL is not here already if ( $old_url != $url && !yourls_allow_duplicate_longurls() ) { - $new_url_already_there = intval($ydb->get_var("SELECT COUNT(keyword) FROM `$table` WHERE `url` = '$strip_url';")); + $new_url_already_there = intval($ydb->get_var("SELECT COUNT(keyword) FROM `$table` WHERE `url` = '$url';")); } else { $new_url_already_there = false; } @@ -413,7 +413,7 @@ function yourls_keyword_is_taken( $keyword ) { return $pre; global $ydb; - $keyword = yourls_sanitize_keyword( $keyword ); + $keyword = yourls_escape( yourls_sanitize_keyword( $keyword ) ); $taken = false; $table = YOURLS_DB_TABLE_URL; $already_exists = $ydb->get_var( "SELECT COUNT(`keyword`) FROM `$table` WHERE `keyword` = '$keyword';" ); @@ -471,7 +471,7 @@ function yourls_xml_encode( $array ) { */ function yourls_get_keyword_infos( $keyword, $use_cache = true ) { global $ydb; - $keyword = yourls_sanitize_string( $keyword ); + $keyword = yourls_escape( yourls_sanitize_string( $keyword ) ); yourls_do_action( 'pre_get_keyword', $keyword, $use_cache ); @@ -566,7 +566,7 @@ function yourls_update_clicks( $keyword, $clicks = false ) { return $pre; global $ydb; - $keyword = yourls_sanitize_string( $keyword ); + $keyword = yourls_escape( yourls_sanitize_string( $keyword ) ); $table = YOURLS_DB_TABLE_URL; if ( $clicks !== false && is_int( $clicks ) && $clicks >= 0 ) $update = $ydb->query( "UPDATE `$table` SET `clicks` = $clicks WHERE `keyword` = '$keyword'" ); @@ -643,6 +643,8 @@ function yourls_get_link_stats( $shorturl ) { global $ydb; $table_url = YOURLS_DB_TABLE_URL; + $shorturl = yourls_escape( yourls_sanitize_keyword( $shorturl ) ); + $res = $ydb->get_row( "SELECT * FROM `$table_url` WHERE keyword = '$shorturl';" ); $return = array(); @@ -673,6 +675,9 @@ function yourls_get_link_stats( $shorturl ) { /** * Get total number of URLs and sum of clicks. Input: optional "AND WHERE" clause. Returns array * + * IMPORTANT NOTE: make sure arguments for the $where clause have been sanitized and yourls_escape()'d + * before calling this function. + * */ function yourls_get_db_stats( $where = '' ) { global $ydb; @@ -853,11 +858,11 @@ function yourls_log_redirect( $keyword ) { global $ydb; $table = YOURLS_DB_TABLE_LOG; - $keyword = yourls_sanitize_string( $keyword ); - $referrer = ( isset( $_SERVER['HTTP_REFERER'] ) ? yourls_sanitize_url( $_SERVER['HTTP_REFERER'] ) : 'direct' ); - $ua = yourls_get_user_agent(); - $ip = yourls_get_IP(); - $location = yourls_geo_ip_to_countrycode( $ip ); + $keyword = yourls_escape( yourls_sanitize_string( $keyword ) ); + $referrer = ( isset( $_SERVER['HTTP_REFERER'] ) ? yourls_escape( yourls_sanitize_url( $_SERVER['HTTP_REFERER'] ) ) : 'direct' ); + $ua = yourls_escape( yourls_get_user_agent() ); + $ip = yourls_escape( yourls_get_IP() ); + $location = yourls_escape( yourls_geo_ip_to_countrycode( $ip ) ); return $ydb->query( "INSERT INTO `$table` (click_time, shorturl, referrer, user_agent, ip_address, country_code) VALUES (NOW(), '$keyword', '$referrer', '$ua', '$ip', '$location')" ); } @@ -1372,6 +1377,7 @@ function yourls_check_IP_flood( $ip = '' ) { } $ip = ( $ip ? yourls_sanitize_ip( $ip ) : yourls_get_IP() ); + $ip = yourls_escape( $ip ); yourls_do_action( 'check_ip_flood', $ip ); diff --git a/yourls-infos.php b/yourls-infos.php index acb2af0..ed3873c 100644 --- a/yourls-infos.php +++ b/yourls-infos.php @@ -54,7 +54,7 @@ $keyword_list = yourls_get_longurl_keywords( $longurl ); $keyword_range = "IN ( '" . join( "', '", $keyword_list ) . "' )"; // IN ( 'blah', 'bleh', 'bloh' ) } else { - $keyword_range = "= '$keyword'"; + $keyword_range = sprintf( "= '%s'", yourls_escape( $keyword ) ); } -- 2.45.0