Top 5 Magento Secure Coding Best Practices

27
Top 5 Magento Secure Coding Best Practices Alex Zarichnyi, Magento ECG

description

 

Transcript of Top 5 Magento Secure Coding Best Practices

Page 1: Top 5 Magento Secure Coding Best Practices

Top 5 Magento Secure Coding Best

PracticesAlex Zarichnyi, Magento ECG

Page 2: Top 5 Magento Secure Coding Best Practices

Security in Magento

• Dedicated team

Page 3: Top 5 Magento Secure Coding Best Practices

Security in Magento

• Dedicated team• External audits

Page 4: Top 5 Magento Secure Coding Best Practices

Security in Magento

• Dedicated team• External audits• Awareness

about OWASP Top 10

Page 5: Top 5 Magento Secure Coding Best Practices

Security in Magento

http://magento.com/security

• Bug bounty program

• Dedicated team• External audits• Awareness about

OWASP Top 10

up to $10.00

0

Page 6: Top 5 Magento Secure Coding Best Practices

Security in Magento

• Built-in security mechanisms

• Bug bounty program

• Dedicated team• External audits• Awareness about

OWASP Top 10

Page 7: Top 5 Magento Secure Coding Best Practices

Top 5 Secure Coding Practices

Page 8: Top 5 Magento Secure Coding Best Practices

#1. Validate input as strictly as possible

Page 9: Top 5 Magento Secure Coding Best Practices

Input Validation

Do not trust:

• all input parameters

• cookie names and values

• HTTP header content

• Some $_SERVER parameters (e.g.

HTTP_X_FORWARDED,

HTTP_X_FORWARDED_FOR)

Page 10: Top 5 Magento Secure Coding Best Practices

Zend_Validate

• Alpha-numeric values• Credit Carts• Host names• IPs• Custom validators

(Mage_Core_Model_Url_Validator)• and many more

Page 11: Top 5 Magento Secure Coding Best Practices

$attributeCode = $this->getRequest()->getParam('attribute_code');$validator = new Zend_Validate_Regex(array( 'pattern' => '/^[a-z][a-z_0-9]{1,254}$/'));if (!$validator->isValid($attributeCode)) { //stop execution and add a session error}

Validate attribute code

1.

2. $attributeCode = $this->getRequest()->getParam('attribute_code');$validatorChain = new Zend_Validate();$validatorChain->addValidator(new Zend_Validate_StringLength( array('min' => 1, 'max' => 254))) ->addValidator(new Zend_Validate_Alnum());if (!$validatorChain->isValid($attributeCode)) { //stop execution and add a session error}

Page 12: Top 5 Magento Secure Coding Best Practices

$email = $this->getRequest()->getParam('email'); if (Zend_Validate::is($email, 'EmailAddress')) {   //continue execution} else {   $this->_getSession()->addError($this->__('Invalid email address.')); //redirect back}

Validate email

Page 13: Top 5 Magento Secure Coding Best Practices

#2. Use parameterized queries(?, :param1)

Page 14: Top 5 Magento Secure Coding Best Practices

Working with Data in Magento

$id = $this->getRequest()->getParam(‘id’);$model->load($id);

$q = $this->getRequest()->getParam(‘q’);$collection->addFieldToFilter(‘name’, ‘%’ . $q . ‘%’));

secure

secure

Page 15: Top 5 Magento Secure Coding Best Practices

$select->where("region.code = '{$requestParam}'");$res = $this->_getReadAdapter()->fetchRow($select);

$select->where('region.code = ?', $requestParam);$res = $this->_getReadAdapter()->fetchRow($select);

Bad code

Good code

1.

$select->where('region.code= :regionCode');$bind = array('regionCode' => $requestParam);$res = $this->getReadAdapter()->fetchRow($select, $bind));

2.

name' ); UPDATE admin_user SET password = '34e159c98148ff85036e239866a8e053:v6' WHERE username = 'admin';

Page 16: Top 5 Magento Secure Coding Best Practices

$select->joinInner( array('i' => $this->getTable('enterprise_giftregistry/item')), 'e.entity_id = i.entity_id AND i.item_id = ' . $requestParam, array());

$select->joinInner( array('i' => $this->getTable('enterprise_giftregistry/item')), 'e.entity_id = i.entity_id AND i.item_id = ' . (int) $requestParam, array());

Bad code

Good code

1; DROP TABLE customer_entity;

Page 17: Top 5 Magento Secure Coding Best Practices

$result = "IF (COUNT(*) {$operator} {$requestParam}, 1, 0)";$select->from( array('order' => $this->getResource()->getTable('sales/order')), array(new Zend_Db_Expr($result));

$value = $select->getAdapter()->quote($requestParam);$result = "IF (COUNT(*) {$operator} {$value}, 1, 0)";$select->from( array('order' => $this->getResource()->getTable('sales/order')), array(new Zend_Db_Expr($result)));

Bad code

Good code

Page 18: Top 5 Magento Secure Coding Best Practices

#3. Escape user input

Page 19: Top 5 Magento Secure Coding Best Practices

SQL Query Parameters Escaping

$db->quoteInto("WHERE date < ?", "2005-01-02")

WHERE date < '2005-01-02’

Zend_Db_Adapter_Abstract

quote($value, $type = null)

quoteInto($text, $value, $type = null, $count = null)

quoteIdentifier($ident, $auto=false)

quoteColumnAs($ident, $alias, $auto=false)

quoteTableAs($ident, $alias = null, $auto = false)

$db->quote("O'Reilly"); O\'Reilly

$db->quote("' or '1'='1' -- “, Zend_Db::FLOAT_TYPE);

0.000000

Page 20: Top 5 Magento Secure Coding Best Practices

Mage::helper(‘core’)->escapeHtml($data, $allowedTags = null)

Mage_Core_Block_Abstract::escapeHtml($data, $allowedTags =

null)

String Replacement

& &amp;

" &quot;

' &#039;

< &lt;

> &gt;

HTML Special Characters Escaping

https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

Never insert untrusted data except in allowed locations

Use both on frontend & backend

Page 21: Top 5 Magento Secure Coding Best Practices

#4. Use CSRF tokens (form keys)

Page 22: Top 5 Magento Secure Coding Best Practices

<form name="myForm" id="myForm" method="post" action="..."> <?php echo $this->getBlockHtml('formkey')?> <!-- ... --></form>

public function saveAction(){ if (!$this->_validateFormKey()) { //stop and throw an exception or redirect back }}

<input type="hidden" value="Bcp957eKYP48XL0Y" name="form_key">

in template

in controller

Page 23: Top 5 Magento Secure Coding Best Practices

#5. Use security headers

Page 24: Top 5 Magento Secure Coding Best Practices

HTTP security headers

https://www.owasp.org/index.php/List_of_useful_HTTP_headers

Header Description Example

X-XSS-Protection Protects from XSS X-XSS-Protection: 1; mode=block

X-Frame-Options Protects from Clickjacking X-Frame-Options: deny

X-Content-Type-Options

Prevents Internet Explorer and Google Chrome from MIME-sniffing a response away from the declared content-type

X-Content-Type-Options: nosniff

Content-Security-Policy,X-WebKit-CSP

Lets you specify a policy for where content can be loadedLets you put restrictions on script execution

X-WebKit-CSP: default-src 'self'

Page 25: Top 5 Magento Secure Coding Best Practices

/*** Add security headers to the response** @listen controller_action_predispatch* @param Varien_Event_Observer $observer*/public function processPreDispatch(Varien_Event_Observer $observer){   $response = $observer->getControllerAction()->getResponse();   $response->setHeader(‘X-XSS-Protection’, ‘1; mode=block’) ->setHeader(‘X-Frame-Options’, ‘DENY’) ->setHeader(‘X-Content-Type-Options’, ‘nosniff’);}

Page 26: Top 5 Magento Secure Coding Best Practices

Additional Resources• https://www.owasp.org – The Open Web Application

Security Project

• http://websec.io/ – Securing PHP-based applications

• http://cwe.mitre.org/ – Common Weakness Enumeration

• https://www.youtube.com/watch?v=aGnV7P8NXtA –Magento Security Presentation, Imagine 2012

• http://www.developers-paradise.com/wp-content/uploads/eltrino-paradise-2013-roman_stepanov.pdf - Magento Security and Vulnerabilities Presentation, Magento Developer Paradise 2013

Page 27: Top 5 Magento Secure Coding Best Practices

[email protected]/in/ozarichnyi

Дякую!