AyeCode /
invoicing
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
| 1 | <?php |
||||
| 2 | /** |
||||
| 3 | * GetPaid Anonymization Logs Admin |
||||
| 4 | * |
||||
| 5 | * @package GetPaid |
||||
| 6 | * @subpackage Admin |
||||
| 7 | * @since 2.8.22 |
||||
| 8 | */ |
||||
| 9 | |||||
| 10 | defined( 'ABSPATH' ) || exit; |
||||
| 11 | |||||
| 12 | /** |
||||
| 13 | * GetPaid_Anonymization_Logs Class |
||||
| 14 | */ |
||||
| 15 | class GetPaid_Anonymization_Logs { |
||||
| 16 | |||||
| 17 | /** |
||||
| 18 | * Anonymization logs page |
||||
| 19 | */ |
||||
| 20 | public function display_logs() { |
||||
| 21 | // Check user capabilities |
||||
| 22 | if ( ! current_user_can( 'manage_options' ) ) { |
||||
| 23 | return; |
||||
| 24 | } |
||||
| 25 | |||||
| 26 | // Get current page number |
||||
| 27 | $page = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1; |
||||
| 28 | $per_page = 20; |
||||
| 29 | |||||
| 30 | // Fetch logs |
||||
| 31 | $logs = $this->get_logs( $page, $per_page ); |
||||
| 32 | $total_logs = $this->get_total_logs(); |
||||
| 33 | |||||
| 34 | // Prepare pagination |
||||
| 35 | $pagination = paginate_links( |
||||
| 36 | array( |
||||
|
0 ignored issues
–
show
|
|||||
| 37 | 'base' => add_query_arg( 'paged', '%#%' ), |
||||
| 38 | 'format' => '', |
||||
| 39 | 'prev_text' => __( '«', 'invoicing' ), |
||||
| 40 | 'next_text' => __( '»', 'invoicing' ), |
||||
| 41 | 'total' => ceil( $total_logs / $per_page ), |
||||
| 42 | 'current' => $page, |
||||
| 43 | ) |
||||
| 44 | ); |
||||
| 45 | |||||
| 46 | ?> |
||||
| 47 | <div class="wrap getpaid-anonymization-logs"> |
||||
| 48 | <h1><?php echo esc_html( get_admin_page_title() ); ?></h1> |
||||
| 49 | <div class="tablenav top"> |
||||
| 50 | <div class="alignleft actions"> |
||||
| 51 | <form method="get"> |
||||
| 52 | <input type="hidden" name="page" value="wpinv-anonymization-logs"> |
||||
| 53 | <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date', 'invoicing' ); ?></label> |
||||
| 54 | <select name="m" id="filter-by-date"> |
||||
| 55 | <option value="0"><?php _e( 'All dates', 'invoicing' ); ?></option> |
||||
| 56 | <?php |
||||
| 57 | $months = $this->get_log_months(); |
||||
| 58 | foreach ( $months as $month ) { |
||||
| 59 | $selected = ( isset( $_GET['m'] ) && $_GET['m'] == $month->month ) ? ' selected="selected"' : ''; |
||||
| 60 | echo '<option value="' . esc_attr( $month->month ) . '"' . $selected . '>' . esc_html( $month->month_name . ' ' . $month->year ) . '</option>'; |
||||
| 61 | } |
||||
| 62 | ?> |
||||
| 63 | </select> |
||||
| 64 | <?php submit_button( __( 'Filter', 'invoicing' ), '', 'filter_action', false ); ?> |
||||
| 65 | </form> |
||||
| 66 | </div> |
||||
| 67 | </div> |
||||
| 68 | <table class="wp-list-table widefat fixed striped"> |
||||
| 69 | <thead> |
||||
| 70 | <tr> |
||||
| 71 | <th><?php _e( 'Log ID', 'invoicing' ); ?></th> |
||||
| 72 | <th><?php _e( 'User', 'invoicing' ); ?></th> |
||||
| 73 | <th><?php _e( 'Action', 'invoicing' ); ?></th> |
||||
| 74 | <th><?php _e( 'Date', 'invoicing' ); ?></th> |
||||
| 75 | <th><?php _e( 'Details', 'invoicing' ); ?></th> |
||||
| 76 | </tr> |
||||
| 77 | </thead> |
||||
| 78 | <tbody> |
||||
| 79 | <?php if ( empty( $logs ) ) : ?> |
||||
| 80 | <tr> |
||||
| 81 | <td colspan="5"><?php _e( 'No anonymization logs found.', 'invoicing' ); ?></td> |
||||
| 82 | </tr> |
||||
| 83 | <?php else : ?> |
||||
| 84 | <?php |
||||
| 85 | foreach ( $logs as $log ) : |
||||
| 86 | $additional_info = json_decode( $log->additional_info, true ); |
||||
| 87 | ?> |
||||
| 88 | <tr> |
||||
| 89 | <td><?php echo esc_html( $log->log_id ); ?></td> |
||||
| 90 | <td> |
||||
| 91 | <?php |
||||
| 92 | $user_edit_link = get_edit_user_link( $log->user_id ); |
||||
| 93 | if ( $user_edit_link ) { |
||||
| 94 | echo '<a href="' . esc_url( $user_edit_link ) . '">' . esc_html( $log->user_id ) . '</a>'; |
||||
| 95 | } else { |
||||
| 96 | echo esc_html( $log->user_id ); |
||||
| 97 | } |
||||
| 98 | ?> |
||||
| 99 | </td> |
||||
| 100 | <td><?php echo esc_html( ucfirst( $log->action ) ); ?></td> |
||||
| 101 | <td><?php echo esc_html( get_date_from_gmt( $log->timestamp, 'F j, Y g:i a' ) ); ?></td> |
||||
| 102 | <td> |
||||
| 103 | <button class="button-link toggle-details" type="button" aria-expanded="false"> |
||||
| 104 | <span class="screen-reader-text"><?php _e( 'Show more details', 'invoicing' ); ?></span> |
||||
| 105 | <span class="dashicons dashicons-arrow-down-alt2"></span> |
||||
| 106 | </button> |
||||
| 107 | </td> |
||||
| 108 | </tr> |
||||
| 109 | <tr class="log-details" style="display:none;"> |
||||
| 110 | <td colspan="5"> |
||||
| 111 | <div class="log-details-content"> |
||||
| 112 | <table class="widefat fixed"> |
||||
| 113 | <tbody> |
||||
| 114 | <tr> |
||||
| 115 | <th><?php _e( 'Data Type', 'invoicing' ); ?></th> |
||||
| 116 | <td><?php echo esc_html( $log->data_type ); ?></td> |
||||
| 117 | </tr> |
||||
| 118 | <?php if ( is_array( $additional_info ) ) : ?> |
||||
| 119 | <tr> |
||||
| 120 | <th><?php _e( 'Additional Information', 'invoicing' ); ?></th> |
||||
| 121 | <td> |
||||
| 122 | <table class="widefat fixed"> |
||||
| 123 | <tbody> |
||||
| 124 | <?php foreach ( $additional_info as $key => $value ) : ?> |
||||
| 125 | <tr> |
||||
| 126 | <th><?php echo esc_html( $key ); ?></th> |
||||
| 127 | <td><?php echo esc_html( $value ); ?></td> |
||||
| 128 | </tr> |
||||
| 129 | <?php endforeach; ?> |
||||
| 130 | </tbody> |
||||
| 131 | </table> |
||||
| 132 | </td> |
||||
| 133 | </tr> |
||||
| 134 | <?php endif; ?> |
||||
| 135 | </tbody> |
||||
| 136 | </table> |
||||
| 137 | </div> |
||||
| 138 | </td> |
||||
| 139 | </tr> |
||||
| 140 | <?php endforeach; ?> |
||||
| 141 | <?php endif; ?> |
||||
| 142 | </tbody> |
||||
| 143 | </table> |
||||
| 144 | <?php if ( $pagination ) : ?> |
||||
| 145 | <div class="tablenav bottom"> |
||||
| 146 | <div class="tablenav-pages"> |
||||
| 147 | <?php echo $pagination; ?> |
||||
|
0 ignored issues
–
show
Are you sure
$pagination of type string|string[] can be used in echo?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
Security
Cross-Site Scripting
introduced
by
$pagination can contain request data and is used in output context(s) leading to a potential security vulnerability.
2 paths for user data to reach this point
1. Path:
Read tainted data from array, and
$_SERVER['REQUEST_URI'] is assigned to $uri
in wordpress/wp-includes/functions.php on line 1132
2. Path:
Read tainted data from array, and
$_SERVER['REQUEST_URI'] is assigned to $uri
in wordpress/wp-includes/functions.php on line 1138
Preventing Cross-Site-Scripting AttacksCross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user. In order to prevent this, make sure to escape all user-provided data:
// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);
// for URLs
$sanitized = urlencode($tainted);
General Strategies to prevent injectionIn general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
throw new \InvalidArgumentException('This input is not allowed.');
}
For numeric data, we recommend to explicitly cast the data: $sanitized = (integer) $tainted;
Loading history...
|
|||||
| 148 | </div> |
||||
| 149 | </div> |
||||
| 150 | <?php endif; ?> |
||||
| 151 | </div> |
||||
| 152 | <?php |
||||
| 153 | } |
||||
| 154 | |||||
| 155 | /** |
||||
| 156 | * Get logs from the database |
||||
| 157 | * |
||||
| 158 | * @param int $page Current page number |
||||
| 159 | * @param int $per_page Number of logs per page |
||||
| 160 | * @return array |
||||
| 161 | */ |
||||
| 162 | private function get_logs( $page, $per_page ) { |
||||
| 163 | global $wpdb; |
||||
| 164 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
| 165 | $offset = ( $page - 1 ) * $per_page; |
||||
| 166 | |||||
| 167 | $query = $wpdb->prepare( |
||||
| 168 | "SELECT * FROM $table_name ORDER BY timestamp DESC LIMIT %d OFFSET %d", |
||||
| 169 | $per_page, |
||||
| 170 | $offset |
||||
| 171 | ); |
||||
| 172 | |||||
| 173 | return $wpdb->get_results( $query ); |
||||
| 174 | } |
||||
| 175 | |||||
| 176 | /** |
||||
| 177 | * Get total number of logs |
||||
| 178 | * |
||||
| 179 | * @return int |
||||
| 180 | */ |
||||
| 181 | private function get_total_logs() { |
||||
| 182 | global $wpdb; |
||||
| 183 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
| 184 | return $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" ); |
||||
| 185 | } |
||||
| 186 | |||||
| 187 | /** |
||||
| 188 | * Get log months for filtering |
||||
| 189 | * |
||||
| 190 | * @return array |
||||
| 191 | */ |
||||
| 192 | private function get_log_months() { |
||||
| 193 | global $wpdb; |
||||
| 194 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
| 195 | |||||
| 196 | $months = $wpdb->get_results( |
||||
| 197 | "SELECT DISTINCT YEAR(timestamp) AS year, MONTH(timestamp) AS month, |
||||
| 198 | DATE_FORMAT(timestamp, '%M') AS month_name, |
||||
| 199 | DATE_FORMAT(timestamp, '%Y%m') AS month |
||||
| 200 | FROM $table_name |
||||
| 201 | ORDER BY year DESC, month DESC" |
||||
| 202 | ); |
||||
| 203 | |||||
| 204 | return $months; |
||||
| 205 | } |
||||
| 206 | } |
array('base' => add_quer...e), 'current' => $page)can contain request data and is used in variable name context(s) leading to a potential security vulnerability.2 paths for user data to reach this point
$_SERVER['REQUEST_URI']is assigned to$uriin wordpress/wp-includes/functions.php on line 1132$_SERVER['REQUEST_URI']is assigned to$uriin wordpress/wp-includes/functions.php on line 1132
$uri . '?'is assigned to$basein wordpress/wp-includes/functions.php on line 1165
$protocol . $base . $ret . $fragis assigned to$retin wordpress/wp-includes/functions.php on line 1191
rtrim(), andrtrim($ret, '?')is assigned to$retin wordpress/wp-includes/functions.php on line 1192
str_replace(), andstr_replace('?#', '#', $ret)is assigned to$retin wordpress/wp-includes/functions.php on line 1193
$retis returnedin wordpress/wp-includes/functions.php on line 1194
$_SERVER['REQUEST_URI']is assigned to$uriin wordpress/wp-includes/functions.php on line 1138$_SERVER['REQUEST_URI']is assigned to$uriin wordpress/wp-includes/functions.php on line 1138
$uri . '?'is assigned to$basein wordpress/wp-includes/functions.php on line 1165
$protocol . $base . $ret . $fragis assigned to$retin wordpress/wp-includes/functions.php on line 1191
rtrim(), andrtrim($ret, '?')is assigned to$retin wordpress/wp-includes/functions.php on line 1192
str_replace(), andstr_replace('?#', '#', $ret)is assigned to$retin wordpress/wp-includes/functions.php on line 1193
$retis returnedin wordpress/wp-includes/functions.php on line 1194
Used in variable context
paginate_links()is calledin includes/admin/class-getpaid-anonymization-logs.php on line 36
$argsin wordpress/wp-includes/general-template.php on line 4469
wp_parse_args()is calledin wordpress/wp-includes/general-template.php on line 4506
$argsin wordpress/wp-includes/functions.php on line 4821
wp_parse_str()is calledin wordpress/wp-includes/functions.php on line 4827
$input_stringin wordpress/wp-includes/formatting.php on line 5148
parse_str()is calledin wordpress/wp-includes/formatting.php on line 5149
General Strategies to prevent injection
In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) { throw new \InvalidArgumentException('This input is not allowed.'); }For numeric data, we recommend to explicitly cast the data: