You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Understand how to approach input validation (useful for any input validation library)
Ex: Joi Bypass (Hint 1)
How can the schema be bypassed?
Hint 1
JSON input (with keys/values) is directly assigned into keys/values
in the database
What could this potentially override?
Ex: Joi Bypass (Hint 1 Answer)
It could override sensitive fields in the database
Ex: isAdmin: false (set by backend logic) could be overridden with isAdmin: true
Type of Mass Assignment vulnerability
Ex: Joi Bypass (Hint 2)
In the json that’s fed into Joi.validate(), find where isAdmin: true could be injected
Ex: Joi Bypass (Hint 2 Answer)
Add isAdmin: true to root level
constJoi=require('joi');constschema=Joi.object().keys({// Requires a given string valueusername: Joi.string().alphanum().min(3).max(30).required(),// Define password complexity requirements through regex (consider more complex regex)password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/).required(),// Force passwords to matchpassword_confirmation: Joi.any().equal(Joi.ref('password')).required(),// Accept different Joi types. Optional, unconstrained string or numberaccess_token: [Joi.string(),Joi.number()],// Required birthyear to be an int between rangebirthyear: Joi.number().integer().min(1900).max(2013).required(),// Validate email adress from example.com (remember spoofing considerations)email: Joi.string().email().regex(/example\.com$/),marketing_opt_out: Joi.boolean(),csrf_token: Joi.string().guid({version: 'uuidv4',}).required(),sex: Joi.string().equal(['M','F','MALE','FEMALE','DECLINE']).required(),time: Joi.date().timestamp('javascript'),roles: Joi.object().keys(),})// email must be accompanied by marketing_opt_out.with('email','marketing_opt_out');constresult=Joi.validate({username: 'Ronald',password: 'ZZZ',password_confirmation: 'ZZZ',birthyear: 2010,email: 'foo@example.com',marketing_opt_out: true,csrf_token: '6d4d8c14-ef12-45d9-ab3c-5dddf941fb76',sex: 'F',time: 1534942475121,roles: {},isAdmin: true,},schema);// If result.error === null, payload is validconsole.log(`The validation error is: ${result.error}`);
Ex: Joi Bypass (Hint 2 Answer CONT.)
The validation error is: ValidationError: "isAdmin" is not allowed
If schema is {} no keys are allowed. If schema is null or undefined,
any key is allowed
Ex: Joi Bypass (Answer)
constJoi=require('joi');constschema=Joi.object().keys({// Requires a given string valueusername: Joi.string().alphanum().min(3).max(30).required(),// Define password complexity requirements through regex (consider more complex regex)password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/).required(),// Force passwords to matchpassword_confirmation: Joi.any().equal(Joi.ref('password')).required(),// Accept different Joi types. Optional, unconstrained string or numberaccess_token: [Joi.string(),Joi.number()],// Required birthyear to be an int between rangebirthyear: Joi.number().integer().min(1900).max(2013).required(),// Validate email adress from example.com (remember spoofing considerations)email: Joi.string().email().regex(/example\.com$/),marketing_opt_out: Joi.boolean(),csrf_token: Joi.string().guid({version: 'uuidv4',}).required(),sex: Joi.string().equal(['M','F','MALE','FEMALE','DECLINE']).required(),time: Joi.date().timestamp('javascript'),roles: Joi.object().keys(),})// email must be accompanied by marketing_opt_out.with('email','marketing_opt_out');constresult=Joi.validate({username: 'Ronald',password: 'ZZZ',password_confirmation: 'ZZZ',// access_token: 1234,birthyear: 2010,email: 'foo@example.com',marketing_opt_out: true,csrf_token: '6d4d8c14-ef12-45d9-ab3c-5dddf941fb76',sex: 'F',time: 1534942475121,roles: {isAdmin: true,},},schema);// If result.error === null, payload is validconsole.log(`The validation error is: ${result.error}`);
Ex: Joi Bypass (Answer) CONT
The validation error is: null
Takeaways
Be very careful with library defaults when leveraging input validation
Easy for hackers to look for edge cases in validation