something died inside your git repo
TRANSCRIPT
Something Died Inside Your Git Repo:Recognizing the Smell of Insecure Code
Cliff Smith, Parameter SecurityBSides HuntsvilleFebruary 4, 2017
Intro• Ethical Hacker at Parameter Security in St. Louis, MO• Co-lead of OWASP Saint Louis• Programmer with 20+ years’ experience writing bad code (and
nonnegligible experience writing good code)• Recovering lawyer
Code Smells and Refactoring• “[Kent Beck and I] have learned
to look for certain structures in the code that suggest (sometimes they scream for) the possibility of refactoring.” Martin Fowler, Refactoring, p. 63• Something is wrong and likely to
cause maintenance problems• Poorly conceived design OR code
that has deviated from its original design
Code Smells and Security• Patterns in thought, code structure and application behavior• Gaps in understanding of security OR bad habits that lead to mistakes• Something is wrong and is likely to get breached:• You chose the wrong approach, thereby making the problem harder than it is• You probably don’t understand the problem, so you probably screwed it up• You may have shown attackers the weak spots in your code
Code Smells and Security
https://xkcd.com/463/
Pen Test Story - Stored XSS• Attack: <script>alert(‘XSS’)</script>
Pen Test Story - Stored XSS• Attack: <script>alert(‘XSS’)</script>• Fix: reject input containing <script
Pen Test Story - Stored XSS• Attack: <script>alert(‘XSS’)</script>• Fix: reject input containing <script• Attack: <img onerror=“alert(‘XSS’)” src=“error.jpg” />• Fix: reject input matching /<[a-zA-Z].*>/
Pen Test Story - Stored XSS• Attack: <script>alert(‘XSS’)</script>• Fix: reject input containing <script• Attack: <img onerror=“alert(‘XSS’)” src=“error.jpg” />• Fix: reject input matching /<[a-zA-Z].*>/• Attack: <img onerror=“alert(‘XSS’)” src=“error.jpg” (simply omit the
closing bracket)• Fix: reject input matching /<[a-zA-Z]+ / (space at end)
Pen Test Story - Stored XSS• Attack: <script>alert(‘XSS’)</script>• Fix: reject input containing <script• Attack: <img onerror=“alert(‘XSS’)” src=“error.jpg” />• Fix: reject input matching /<[a-zA-Z].*>/• Attack: <img onerror=“alert(‘XSS’)” src=“error.jpg” (simply omit the
closing bracket)• Fix: reject input matching /<[a-zA-Z]+ / (space at end)• Attack: insert <img/onmouseover=“alert(‘XSS’)” (use a slash instead of
a space)
Cat-and-Mouse Games• Bad guy breaks in, good guy designs a
narrow defense against the exact method used by the bad guy• Design your defenses based on the
vulnerability, not based on the attack• Implement provably, theoretically correct
solutions
Another Stored XSS Example<script type=“text/javascript”>$.ready(function() {
Map.init(‘123 Main St.’);});</script>
Another Stored XSS Example<script type=“text/javascript”>$.ready(function() {
Map.init(‘123 Main St.’);});</script>
User data interpolated
directly into code – this is as bad as
eval()!
Another Stored XSS Example<script type=“text/javascript”>$.ready(function() {
$.get({ /* ... */,function(response) {
Map.init(response.data);});
});</script>
<script type=“text/template” id=“address”>MTIzIE1haW4gU3Qu</script><script type=“text/javascript”>$.ready(function() {
var address = $(‘#address’).text();
address = atob(address);Map.init(address);
});</script>
Provably correct and safeWorks, but hurts performance
Church and State
Don’t mix the two!
Code Data
Church and State• Separate data from code whenever possible (and it’s always possible)• Use prepared SQL statements• Use <script type=“text/template”> tags and base 64 encoding
• Never rely on rejecting bad input• Escaping control characters is a last resort!
Still More Stored XSS Defenses...• Existing application escaped < > “ with HTML entity encoding before
saving user data to database• Today I watched "The Pirates of Penzance" by Gilbert & Sullivan.
• Form elements changed from <input> to <textarea> and vice-versa during page redesigns• JavaScript replaces form elements with <span>s for printing• $span.html($textarea.text())?• $span.text($textarea.html())?
• Like an airport with all security checkpoints at the highway off-ramp
Solutions Decoupled from Problems• Poor modularity; poor delineation of responsibilities• Each component has to be aware of the needs of every other component!
• Injection attacks are presentation-layer problems, so solve them in the presentation layer!• Data integrity and model state should be enforced in the model• Easier to maintain, harder to break
Junior’s First Database• Single text file• Entire contents rewritten to disk
on every save• Save operations took about 30
seconds• Zero concurrency
ENTRYtype=employeeid=1firstname=JohnENTRYtype=timeentryid=1date=20030811project_id=7
Junior’s First Database• Single text file• Entire contents rewritten to disk
on every save• Save operations took about 30
seconds• Zero concurrency• MySQL was eight years old at
this point
ENTRYtype=employeeid=1firstname=JohnENTRYtype=timeentryid=1date=20030811project_id=7
Solving Important Problems From Scratch
• Important problems are (1) fundamental, (2) easy to get wrong, or (3) likely to create a vulnerability if you get them wrong• Or they leave you thinking, “Surely someone has done this before…”• Stand on the shoulders of giants (or at least on stilts)• Consider using a reliable, proven third-party solution• Study the literature• Examples:• Parsing HTTP requests and responses• Crypto and authentication• OWASP Top 10
The Abstraction Trap• Abstraction allows the application programmer to interact with an
object at a convenient level of complexity• That level of complexity defines the object’s interface• Implementation details are abstracted away
The Abstraction Trap• Vulnerabilities can be hidden in the details we abstract away• Examples:• Plugin that can set the user’s session ID – session fixation• Mobile applications that inadvertently cache HTTP responses• RSA Chinese remainder theorem timing leak
• “Not my code” != “not my responsibility”• Book up on APIs, libraries and other third-party code• Look out for features you don’t need or don’t expect
• Subject matter knowledge and security expertise are important
Vulnerability in FOSS CMSdef list_users():
authorize_request()users = User.find(…)…
def save_user(id):authorize_request()user = User.find({‘id’:id})…
def delete_user(id):user = User.find({‘id’:id})…
WET Code• DRY = don’t repeat yourself• WET = write everything twice• WET code leaves you one forgetful moment away from a vulnerability• DRY code is set it and forget it – solve problems once, not over and again• TIMTOWTDI versus The Zen of Python• Make the obvious solution the safe solution
Pen Test Story - Vulnerability in Commercial OSS
function validate_slug($slug) {if (strpos($slug, ‘<‘) != FALSE || strpos($slug, ‘”’) != FALSE) {return FALSE;}return TRUE;
}/* … */<script>showImage(“<?php echo $slug; ?>”);</script>
Pen Test Story - Vulnerability in Commercial OSS
function validate_slug($slug) {if (strpos($slug, ‘<‘) != FALSE || strpos($slug, ‘”’) != FALSE) {return FALSE;}return TRUE;
}/* … */<script>showImage(“<?php echo $slug; ?>”);</script>
Code Secured by a Single Set of Eyes
• Mistakes happen, but mistakes like this should be caught• This issue could have been caught with:• PHPLint• BurpSuite Scanner, nikto, WebScarab, any other vulnerability scanner or fuzzer• Unit testing• Manual code review
• Every organization should have some process in place
Pen Test Story – Mobile ApplicationGET /account/details?account_number=111111111
HTTP/1.1 200 OK {“message”:”success”,“ssn”:”123-45-6789”}
GET /account/details?account_number=222222222
HTTP/1.1 404 Not Found {“message”:”Invalid account number.”}
GET /account/details?account_number=333333333
HTTP/1.1 403 Access Denied {“message”:”Access violation.”}
Pen Test Story – Mobile ApplicationPOST /account/reticulateSplines {“foo”:”bar”}
HTTP/1.1 200 OK {“message”:”success”}
POST /account/reticulateSplines {“foo”:”</bar>”}
HTTP/1.1 500 Internal Server Error {“message”:”Uncaught exception in java.xml.parsers.documentbuilder: unexpected closing tag </bar>; expected
</ACCOUNT_OPERATION> at line 3, colum 94.
Stack trace:
…”}
Mind the Information Gap• Client and server are on a mutual need-to-know basis• The server should never tell the client something it doesn’t need to know
• Leakage of sensitive information• Giving the attacker a roadmap
• The client should never tell the server something it already knows• Access control errors
• Limit detail in error messages• The fact of the error; how to fix it; how to get help• Interpreter error messages are for developers, not users
• The client is untrusted!
Summary• Cat-and-mouse games• Church and state• Solutions decoupled from problems• Solving important problems from scratch• The abstraction trap• WET code• Code secured by a single set of eyes• Mind the information gap
Final Thoughts• Understand the conceptual root of each type of vulnerability• Safe handling of user data is a major source of vulnerabilities• All exploits run on information, assumptions and trust• Information should be carefully controlled and rationed• Identify and manage assumptions
• Don’t be afraid to Google simple questions• Study the specs• Programming is an art and a science• Good code is secure code
Questions?
[email protected]@BismthSalamandr