Here are my notes for the first 9 chapters of Security Principles for PHP Applications: A php[architect] guide by Eric Mann, published in 2017. This book is one of the few modern books on php 7 security that I could find. I’m generally happy with my purchase here. It’s very readable, combining a good amount of technical details with real life stories about vulnerabilities and solutions. While not WordPress centric, it does cover some topics from a WordPress perspective. There are also sections that cover the system administration side of php security. I definitely recommend this book for the a php software developer.
Some background on myself:
I’m a php developer mainly writing software for php 7, but also I maintain older code that was built for php 5. I have a lot of experience in WordPress backend development. I do a lot of code review and am experienced at flagging escaping/sanitization issues. I understand nonces and XSS attacks. But I bought this book looking for a more advanced dive into security concepts, because I have a nagging feeling that there’s something I don’t understand. I’m concerned about missing something critical because of something I don’t know that I don’t know. The unknown unknowns.
My Notes on Chapters 1-8
Chapter 1
The importance of a security first mindset is discussed. The JOSE tool allowing “none” for an encryption algorithm is given as an example of how not having a security first mindset in development caused huge security concerns. See this article: Critical vulnerabilities in JSON Web Token libraries
Chapter 2 – 3
These chapters are “About this book” chapters. He introduces the OWASP Top Ten Application Securities Risks List and discusses the controversies around that.
Chapter 4 – ASR1: Injection
- Example of vulnerable code where the cookie value is not sanitized (only sanitized with addslashes which is insufficient) and therefore it was possible to delete the WP options table.
- Unsanitized Shell Input – Book gives a couple of interesting use cases and how they were vulnerable. The 2011 TimThumb vulnerability is described. The problem there was that preg_match() was being used to check if a host name matched a whitelist, but preg_match() will return true for a partial match, so a hacker could use a subdomain to trick this conditional check and then they could upload arbitrary files.
- For fixing the above issue, an exact match needs to be used for checking the host name, and also separately there was a server misconfiguration issue because PHP scripts were executable in the TimThumb cache directory. The server configuration should only allow serving of static assets.
- Book recommends using readfile() instead of passthru() but does demonstrate how to properly sanitize and escape a filename with basename() and escapeshellarg()
- Both WordPress and PDO code examples are given.
Chapter 5 – ASR2: Broken Authentication and Session Management
- Overview of how native php sessions work.
- Session IDs are now in a cookie, which means they are sent in the header and encrypted over HTTPS. In PHP4, session IDs were in the URL as a query parameter, which exposed them in log files.
- If an application is served from more than one server, sessions become unstable. Load balancing and sticky sessions have to be used.
- Sessions can’t be managed securely client side, because the user can manipulate the client side data.
- The user state has to always live on the server.
- Timing vulnerabilities are discussed. See: Timing Oracle Attack
- Php and Mysql string comparison functions use C’s memcmp, which has a weakness, in that is returns early, as it evaluates one character at a time.
- Php provides SessionHandlerInterface for providing your own handler of session data. For example, you could store the session data in a Memcached cluster.
- The author wrote the package Sessionz – middleware for checking Memcached if the session data isn’t in memory or on disk, and handles encryption.
- In php.ini cookies should be set to “secure” and “httponly” This can also be set at runtime. “Secure” means that they will only be sent over https, and “httponly” prevents javascript from accessing them.
- Passwords should always be hashed. “Hashed” means transforming the data in such a way that the original data cannot be recovered. This is different from encryption.
- If a site limits the length of the password, that may indicate that the password is not being hashed. This limit could be because it’s being saved directly in the database in a fixed length field.
- password_hash() and password_verify()
- to prevent timing attacks, use hash_equals() and move business logic out of MYSQL
Chapter 6 – ASR3: Sensitive Data Exposure
- Don’t store more data than your application needs.
- Don’t confuse encoding ( i.e. base 64 encoding) with encryption
- The developer who writes the code shouldn’t be the one who reviews it or deploys it. Having another developer review and deploy can prevent security issues caused by a “rogue engineer”. QA on a staging environment is also mentioned.
- Always encrypt data. It should only be unencrypted when being actively used by the application.
- Don’t use shared credentials. Also describes the “Principal of Least Privilege”
- Amazon RDS offers encrypted instances, encrypted at AES-256 algorithm. MySQL has table level encryption.
- Avoid storing authentication information by using OAuth or OpenID
- Php 7.2+ Libsodium is a native component. Industry standard cryptography library. Don’t use your own solution.
Chapter 7 – ASR4 – XML External Entities
- This chapter describes how there is an XML feature which allows loading external elements as entities and the security issues here.
- libxml_disable_entity_loader(true) will disable this feature.
- PHP’s default XML parsers rely on libxml2. Recent versions of libxml2 default to blocking the loading of recursive element entities. Check which version of libxml you’re using.
Chapter 8 – ASR5: Broken Access Control
- Difference between authentication and authorization is described.
- Role-based access control in WordPress is explained.
- “Insecure Direct Object References” is described. This is when once authenticated, a user can directly access objects that they shouldn’t have access to. This kind of vulnerability was discovered during a 2015 United Airlines bug bounty program. The issue was that the client side mobile app was being used to control the state, and authenticated users could send any Mileage Plus number and the app could get information about anyone’s flights, including cancelling anyone’s flight.