NDC Security is a 4-day conference in Oslo in January with 2 days of workshops and 2 days of talks.
Here are my main takeaways from the workshop (Identity and Access Control):
ReturnUrl
before redirecting in order to prevent open redirectionHere are my main takeaways from the talks:
Every single session I went to was interesting and informative. The list above is one bullet point per session. For all of my notes and links, expand the collapsible section below, but be warned, they’re not in a very comprehensible form.
Apparently the workshop has been going for 10 years, but it’s constantly updated and still very much relevant.
Standard training is a 3-day course,
but this is condensed into a 2-day workshop.
He goes a bit quick sometimes.
Browser talks to webapp, services. Services talk to each other. Assume zero trust, unlike 10 years ago when we trusted everything inside the firewall.
IIdentity
and
IPrincipal
have been around since the start of .Net and are still the basis of authentication and authorization,
but they’re based on a name and roles, which is not very flexible.
Identity name should be:
So don’t use things like email address, or a social security number that’s based on gender (like Norway does/did). Use a guid.
.Net 4.5 introduced claims into .Net framework in 2012. Claims are a key/value pair, with an optional issuer.
ClaimsIdentity
implements IIdentity
.
ClaimsPrincipal
implements IPrincipal
and contains a collection of ClaimsIdentity
s.
Claim key:
sub
is kinda like Name
in original IIdentity
Claim type - eg to tie name to a well-known name. Or can specify the type in the constructor.
IIdentity.IsAuthenticated
is read-only. It’s set by defining authenticationType
in the constructor.
Tip: always use the
4 parameter constructor
(second parameter is authenticationType
).
ASP.NET middleware can handle request, or just part of it (ie process and continue). Defined in order, eg first static files, then HSTS, then authentication, then authorization.
Auth middleware extension methods are badly named:
SignInAsync
-
creates a session - provider creates a principal which is the parameter to this methodChallengeAsync
- initiates sign inAuthenticateAsync
- queries if authenticatedAlways validate ReturnUrl
when redirecting.
LocalRedirect
does that, or manually check with
IsLocalUrl
and handle if it’s not.
Data protection (DPAPI) in ASP.NET Core:
In our IdentityServer we skipped key management “for now”. There are examples in IdentityServer4 source.
[Authorize("policy")]
attribute (new way).
Or can check in code.
Or in a view.
[Authorize(Roles="roles")]
attribute (old way).
AddPolicy("policy", options => {...})]
RequireAssertions
- but then can only check in code, not attributeRequireAssertion
gets too complex, use the authorization handler framework - see the labRemoteAuthenticationHandler
for delegated auth.
SignInAsync
not implemented - use ChallengeAsync
instead.
eg Google doesn’t implement SignOutAsync
because they don’t want you to sign out.
Redirect from Google assumes ReturnUrl
is safe - se we should validate it to prevent open redirection.
Google handler writes directly to the cookie handler that we define first in the pipeline.
Scheme - eg Google, OpenId Connect, cookie, etc - is a configuration plus a handler.
OpenId Connect (oidc) “using IdentityServer as an example”.
Terms:
Endpoints:
/.well-known/openid-configuration
- static jsonnonce (number used once) is OpenId Connect’s way of doing XSS protection, ie checking that the response is for my request.
Identity token contains header, payload, signature.
Discovery endpoint includes jwks_uri
- list of keys so that we can validate the signature.
There’s a list of validations that we should do on the token - defined in
OpenId spec.
Use
JsonWebTokenHandler.ValidateTokenAsync
to do it - using properties from the key.
But then also validate nonce:
AAD can also be used as identity provider, but it’s not very customizable. IdentityServer lets you fully customize.
IdentityServer is just a place to put all the code we’ve been writing up to now
so that it can be shared across multiple clients.
The client code to use it is very simple - just configuration in Startup
.
One IdentityServer that multiple clients use - SSO.
Tip: always use https, even locally, because it’s handled differently to http.
Use multiple cookie schemes for intermediate sign in steps.
Each scheme must be complete when signed in to it.
A reason why you’re often asked to enter a code that’s sent in an email,
rather than clicking a link in the email,
may be to make sure user stays in the same browser (session).
oidc builds on oauth2.
response_type=token
: implicit flow.
scope
: requested claims - no guarantee that they’ll be returned.
But the provider should at least know about them.
[Authorize]
triggers challenge.
SingleSignOut
Config.Clients
NB: don’t sign out on get (OnGet
) request - unless we add XSS protection manually.
LoggedOut
page
Logout
promptLogout
page could maybe be an iframe on client - Anders couldn’t think of any reason why not.
Federation Gateway
Multiple clients talk to FG.
FG manages auth with multiple identity providers - AAD, Google, etc.
Can have many providers and user has to choose.
In order to reduce the list,
do a customer-specific start page and filter based on where you came from.
Or first ask for email,
and then only show list of relevant providers on next screen.
This is called home realm discovery.
Client sets acr_values
in request - how it does that is up to client.
Server app (cf browser app with user) sends client_secret
(among other things) in request to STS.
Gets an access token back.
Access token is used to call API.
Access token is usually transmitted in Authorization
header as Bearer
token.
No signin/signout/challenge because we just use the token.
Client shouldn’t need to inspect the token.
Properties from the token that are needed for validation
are also returned in the response along with the token - scope, expiry.
API should validate token, eg scope, client id.
Scope is a set of information about resource.
Only introduce scopes when you need them - start with just one (for each app).
User-centric - token on behalf of user. Delegation/impersonation. Mainly skipped this part of the course, but mentioned a bit in the discussion - doesn’t seem particularly difficult.
Access token cf id token:
offline_access
Code flow
token_type=code
code_challenge=hash(code_verifier)
code_verifier
is used when exchanging code for access tokenOAuth2.1 - the next version - will only have code flow with PKCE - the others are deprecated.
Implicit flow doesn’t allow refresh tokens - use hidden iframe to refresh access token instead
BFF - backend for frontend - client only talks to one backend
Native apps can open broswer for SSO so that user can trust it. Return URI is an app-specific URI that goes back to app.
I arrived early to secure a good seat (Boom! Boom!)
There were surprisingly few people - I guessed 200 - although Troy said this was the biggest NDC Security ever with 350 attendees.
The keynote was some stories from 10 years of running HaveIBeenPwned.
Encrypted data is safe unless the key is compromised.
politie.nl have a service similar to HaveIBeenPwned, but for a very limited dataset.
OTP in 1Password is okay for the less critical sites.
He’s from the Netherlands - MVP and Regional Director.
HumOR - human operated ransomware:
Threat actors:
2010:
now:
In The Netherlands, 41% pay the ransom.
ft.com has a ransomware negotiation simulator.
Ransomware as a service:
Mitre Att&ack - see slides - stages.
47 minutes average from initial access to full encryption.
Identity attack.
Microsoft Defender for Cloud
Microsoft
Microsoft Defender Deception
I asked him about the risk of local admin - he said that wasn’t really a problem - need to look at the big picture and make sure it can’t do damage on the network. I guess that ties in with assume breach.
SameSite=Strict
- don’t send in iframe
SameSite=Lax
- GET
only - not POST
or iframe
HttpOnly
- not accessible to javascript
Same site - domain - subdomain can be different. Subdomain defined by public suffix list.
There’s no way to query properties of cookie:
oidc spec says to use iframe (to refresh token?)
Chrome makes money from ads, so has mixed interests. More flexible - can enable/disable.
Cross-site cookies are problematic and will become more so.
I changed my mind about going to this talk at the last minute, mainly because the previous talk said that front channel is dead, and went to this instead:
Mutation-based.
Don’t do Type.GetType(string)
.
Polymorphic serializers are bad - self-describing data.
Exploit - hack a type that has side-effects, eg:
AssemblyInstaller
ObjectDataProvider
Deserialize json with a type property, eg
{"$type": "..."}
Read/write object - db, cache, etc.
Deserialize<T>()
- T
sometimes doesn’t matter to deserializer - it’s just a cast afterwards.
But even when it does matter, can also have an inner type.
Mutation:
Dictionary
Exploited when deserialized - what happens next is irrelevant.
Attacker needs to be able to control, eg one key of dictionary.
Serialization binder
BinaryFormatter won’t serialize boxed value types assigned to an interface. The only interfaces that allow this are:
IConvertible
IComparable
IFormattable
These are not common types, but can work around with generics again.
These vulnerablities are not fixed - for various reasons.
System.Text.Json.JsonSerializer
is the only good one.
Most NoSQL engines are vulnerable.
He mostly talked about .Net FF - he had a hard time finding some for .Net Core.
Talk was largely based on the Security Chaos Engineering (SCE) mind map.
Chaos Monkey was introduced by Netflix.
Security Chaos Engineering:
Why:
Practise ransomware scenario.
It will test the monitoring - SIEM etc - so if we don’t have them it’s a bit pointless.
Example - AKS security compromised - leads to AWS S3 bucket ransomware.
EDR -> NDR -> XDR -> CDR
Mitigant tool can, eg emulate AndroxGhost malware attack. DataDog only gives a low severity alert.
They have a set of attacks that I can try. Check what they have for Azure.
Starts with a compromised account
They have a tab “evidence” - will be less if we have less monitoring.
This assumes hackers are in, and then what will happen next?
Could run continuously, but most don’t because the human element is also important.
Add chaos testing to my list of concerns.
Purple team - helping red team and blue team collaborate.
Red team - hackers - very popular (eg lots of movies).
Blue team - less sexy - eg incident response.
Zero trust is the opposite of human nature.
Assume breach.
Classify all the data - so if it’s breached we know how bad it is.
Talk was aimed at security professionals - not developers.
She mentioned “security as code” and I asked her what she meant by that. I think she explained that it meant, eg the pipeline can add security headers when it sees it’s missing, but later I think I misunderstood and that’s not what she meant.
RSA was the first asymetrics scheme in 1977.
She explained it in a clear way, but I lost it after that. But it was still an entertaining talk.
Elliptic curves replaced RSA for a couple of decades.
Shor’s algorithm solve the difficult problems that they rely on.
Quantum computers - harder problems.
Encrypt now for schemes that quantum computers can solve in the future - traffic could be stored and decrypted later - Dilithium/Kyber.
RSA is asymetric - only used for exchanging symetric key - because it’s expensive.
1994
Snowden - 2013:
Heartbleed - 2014:
This is a flaw in RSA key exchange.
Diffie-Hellman key exchange
was invented in 1977, but not used until after heartbleed.
DHKX, or DHEKX - E=ephemeral - new key for each session.
So in case one session is cracked, impact is limited.
Forward Secrecy - 2008:
Another Dutch speaker.
Average code base is 20% yours, 80% other people’s.
Veracode publishes State of Software Security report annually.
79% of third party packages are never updated.
All packages have same access rights as the app they’re in.
dotnet listpackage --vulnerable
: direct dependencies.
dotnet listpackage --vulnerable --include-transitive
: also transient dependencies.
dotnet 8 restore does this by default.
OpenSSF scorecard - give open source projects a score based on various criteria:
RestorePackagesWithLockFile
option in MSBuild will create a package.lock.json
file.
Build provenance - info about environment used for the build - packaged in the package.
deps.dev is a similar service - from Google
OpenSSF is part of Linux Foundation.
SharpFuzz - fuzz input.
Microsoft Application Inspector
Tip: use OpenSSF to get score of our repos, and see the worst dependencies and see if we can remove/update them.
CSRF has always been a problem - recognised around the year 2000.
Simple mitigation - send secret in cookie that’s also validated:
SameSite cookies:
none
lax
is a good choice for most appsBFF uses cookies to talk to API.
It’s possible to post form data that looks like json:
Cross-origin but same site - TLD + 2
Cross-origin request forgery:
CORS => preflight (OPTIONS
request).
js no-cors
mode = “2008 mode”.
API should require custom header:
no-cors
client can’t send itDuence BFF library does all this.
Technique used to get a person to perform action or disclose information.
Phishing test - very simple example.
There’s an ethical responsibility.
OSINT:
Phishing - email.
Vishing - voice phishing - eg phone call.
Smishing - SMS phishing.
Quishing - QR code phishing.
Zero Trust doesn’t work with humans. Trust but Verify instead.
Security culture. Awareness.
A test done poorly can have negative consequences. Even phishing tests can cause hostility
Report:
The failure of an individual is not the individual’s fault - it’s a system failure.
Debrief is important:
Culture:
Practise - eg:
Generic SAST/DAST tools can find generic vulnerabilities. There are lots of such tools.
App specific mitigations are not recognised by generic tools, and so we’ll get used to ignoring the warnings.
Security decorators
Rules - check we’re not calling vulnerable methods in libraries.
DAST
Can run SemGrep in the pipeline - not free.
Problems with passwords:
MFA is technical solution.
Passkeys use existing technologies in a user-friendly, non-technical solution.
passkeys.io has a demo.
Passkey is linked to device
Use passkey on phone:
Passkey is resistent to phishing - there’s nothing to steal (on client).
Passkeys is still optional (like biometrics)
passkeys.directory - list of sites that support passkeys.
passkeys.dev - how to implement front end code.
Public key on client (sign in flow)