Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automatic Detection of Inadequate Authorization Checks in Web Applications

Alvaro
March 22, 2016

Automatic Detection of Inadequate Authorization Checks in Web Applications

Gaps in the enforcement of access control policy of a software system can lead to privilege escalation, allowing unauthorized access to sensitive resources and operations. We describe a novel technique to automatically detect missing and inconsistent authorization checks in web applications with static analysis and conclude with empirical results of using our approach on real-world applications.

The concept of granting different users different privileges dates back to early software systems. Gaps in the enforcement of access control policies can lead to privilege escalation, allowing unauthorized access to sensitive resources and operations. As software becomes more ubiquitous and is used for tasks ranging from shopping to scheduling doctor’s appointments, providing bulletproof access control remains an imperative.

Correct placement of authorization checks is a non-trivial task for developers that requires intimate knowledge of the system, its users, and their roles. These challenges are evidenced by the fact that missing authorization checks—like the one that allowed Bloomberg News to leak NetApps’s earnings results in 2010—are still among the most widespread and impactful vulnerabilities. Manually weeding out access control violations is cumbersome and requires a lot of expertise. Existing automated techniques are also inadequate and require either substantial human intervention or are effective only on very targeted code bases, such as operating systems.

This talk focuses on ensuring well-placed authorization checks in web applications. We discuss different ways access control requirements are specified in web applications, including configuration- and annotation-based approaches. Next, we describe a novel technique to automatically detect missing and inconsistent authorization checks. Our approach lets us detect missing checks statically rather than at runtime and allows us to provide remediation suggestions that allow developers to fix code before it goes to production.

We conclude with empirical results of our successful application of this approach to a number of real-world web applications. We discuss the classes of issues we found and review specific examples to shed light on the kinds of authorization mistakes developers are making today.

Alvaro

March 22, 2016
Tweet

More Decks by Alvaro

Other Decks in Research

Transcript

  1.  Automa(c  Detec(on  of  Inadequate   Authoriza(on  Checks  in  Web  Applica(ons

       
  2. About  Me   Name   Alvaro  Muñoz   Organiza(on  

    HP  SoCware  Security  Research   Currently   Researching  the  security  impact  of  new   technologies.  Especially  interested  in  Web,  any   language,  any  framework.   In  previous  episodes   Applica(on  Security  Consultant   Pentester   Other  Stuff   CTF  player,  OSCP,  GWAPT,  CISSP  …   Loca(on   Madrid,  Spain   Contact   alvaro.munoz@hp.com   @pwntester  
  3. About  Me   Name   Dyvia  Muthukumaran   Organiza(on  

    Imperial  College     Currently   Postdoctoral  researcher  at  Imperial  College   Working  on  security  issues  in  Cloud  Compu(ng   In  previous  episodes   Ph.D  at  Penn  State.   Thesis  work  entailed  automated  authoriza(on   hook  placement.     Loca(on   London,  UK   Contact   dmuthuku@imperial.ac.uk    
  4. Agenda   •  Agenda   – Design  Flaws  vs  Code  Level

     Bugs   – Why  should  we  care?   – Current  detec(on  techniques   – Proposed  solu(on  
  5. Applica(on  Security     Duality   Code   Bugs  

    Design   Flaws  
  6. None
  7. Admin view User view

  8. Is there anything wrong here? Any user can delete an

    account!!! Even if its not shown in the UI …
  9. Any user can delete an account!!! Even if its not

    shown in the UI …
  10. Detec(on   Code   Bugs   Design   Flaws  

  11. Detec(on   Code   Bugs   Design   Flaws  

  12. OpenSAMM   Source:  hWp://www.opensamm.org/  

  13. Code  Review   Source:  hWp://www.opensamm.org/  

  14. Design  Review   Source:  hWp://www.opensamm.org/  

  15. OWASP  Top  Ten   Source:  hWp://h30499.www3.hp.com/t5/HP-­‐Security-­‐Research-­‐Blog/OWASP-­‐Top-­‐Ten-­‐2013/ba-­‐p/6046369  

  16. OWASP  Top-­‐10  2013   A4-­‐Insecure  Direct  Object  References   A

     direct  object  reference  occurs  when  a  developer   exposes  a  reference  to  an  internal  implementa(on   object,  such  as  a  file,  directory,  or  database  key.  Without   an  access  control  check  or  other  protec(on,  aWackers   can  manipulate  these  references  to  access  unauthorized   data.  Many  web  applica(ons  check  URL  access  rights   before  rendering  protected  links  and  buWons.  However,   applica(ons  need  to  perform  similar  access  control   checks  each  (me  these  pages  are  accessed,  or  aWackers   will  be  able  to  forge  URLs  to  access  these  hidden  pages   anyway.     Source:  hWps://www.owasp.org/index.php/Top_10_2013-­‐Top_10  
  17. Is  this  the  real  life?  Is  this  just   fantasy?

        Source:  hWp://irwebreport.com/20101118/bloomberg-­‐grabs-­‐netapps-­‐earnings-­‐early-­‐second-­‐case-­‐in-­‐a-­‐week/    
  18. OWASP  Top-­‐10  2013   A7-­‐Missing  FuncBon  Level  Access  Control  

    Most  web  applica(ons  verify  func(on  level  access   rights  before  making  that  func(onality  visible  in  the   UI.  However,  applica(ons  need  to  perform  the  same   access  control  checks  on  the  server  when  each   func(on  is  accessed.  If  requests  are  not  verified,   aWackers  will  be  able  to  forge  requests  in  order  to   access  func(onality  without  proper  authoriza(on.     Source:  hWps://www.owasp.org/index.php/Top_10_2013-­‐Top_10  
  19. Is  this  the  real  life?  Is  this  just   fantasy?

        Source:  hWp://www.theregister.co.uk/2011/06/14/ci(group_website_hack_simple/  
  20. Current  Approaches   •  Dynamic  approach   – Scan  applica(on  with

     two  or  more  roles   – Compare  results   – Limita(ons:   •  Dynamic   –  Set  up   •  Can  only  detect  missing  checks  
  21. A  beWer  solu(on   •  Requirements   – Works  on  Web

     Applica(ons   – Sta(c   – Finds  both  missing  and  inconsistent  checks   – Does  not  require  any  training  or  preparaBon  
  22. Iden(fying  inadequate  access   checks   3.  Suggest  RemediaBon  

      What  checks  should  be  added  or  modified?   2.  IdenBfy  Anomalies   What  similar  opera6ons  are  not  been  checked  or  checked  differently?   1.  Create  SpecificaBon   What  is  currently  being  access  checked?    
  23. 1.  Create  Specifica(on  

  24. Create  Specifica(on   IdenBfy  access  checked  methods   – Configura(on  Files:

      •  URLs   •  PointCuts   – Source  Code:   •  Annota(ons   •  if-­‐else  checks   – Consider  super  classes  and  call  traces  
  25. Intercep(ng  URLs   <hWp  use-­‐expressions="true">          <intercept-­‐url

         paWern="/admin*"        access="hasRole('admin')            />          <intercept-­‐url      paWern=”/index*"        access=”isAuthen(cated()”            />      </hWp>  
  26. Pointcut-­‐based   <global-­‐method-­‐security>          <protect-­‐pointcut  expression="execu(on(*  com.*Service.*(..))"

                       access="ROLE_USER"/>      </global-­‐method-­‐security>  
  27. Pointcut-­‐based   <bean  id="methodInterceptor"  class="_MethodSecurityInterceptor">      <property  name="authen(ca(onManager"  ref="authManager"/>

         <property  name="securityMetadataSource">                        <value>        org.demo.AccountService.createAccount=ROLE_USER        org.demo.AccountService.delete*=ROLE_ADMIN                        </value>      </property>   </bean>   <bean  id="accountService"  class="ord.demo.AccountServiceImpl">      <sec:intercept-­‐methods>        <sec:protect  access="ROLE_USER"  method="createAccount">        <sec:protect  access="ROLE_ADMIN"  method="delete*">      </property>   </bean>  
  28. Annota(ons          public  interface  BankService  {  

                   @RequiresRole(“teller”)                  public  Account  post(Account  account,  double  amount);                  @RequiresPermission(“account:create”)                  public  Account[]  findAccounts();            }            public  interface  BankService  {                  @Secured("IS_AUTHENTICATED_ANONYMOUSLY")                  public  Account  readAccount(Long  id);                    @PreAuthorize(isAuthen(cated()  and  hasRole(“ROLE_USER”))                  @PreFilter(hasPermission(filterObject,’read’))                  public  Account[]  findAccounts();            }    
  29. Hiding/Disabling  func(onality   <p>Hi  <shiro:guest>Guest</shiro:guest>   <shiro:user><c:out  value="${account.givenName}"/></shiro:user>!   <security:authorize

     ifAnyGranted="ROLE_ADMIN">              <input  type="submit"  value="<spring:message  code="label.add"/>"/>   </security:authorize>   <sec:accesscontrollist  hasPermission="1,2"  domainObject="someObject">          This  will  be  shown  if  the  user  has  either  of  the  permissions          represented  by  the  values  "1"  or  "2"  on  the  given  object.   </sec:accesscontrollist>    
  30. Programma(c   //  get  the  current  subject   Subject  currentUser

     =  SecurityU(ls.getSubject();     If  (currentUser.hasRole(“administrator”))  {          do_something();   }  else  {          do_something_different();   }    
  31. Gather  all  protected   opera(ons   Gather  all  protected  operaBons

      – What  objects,  classes,  methods  are  accessed   within  access  checked  methods?     – For  each  opera(on:   •  Func(on   •  Variable  (instance  object,  argument)   – Discard:   •  U(lity/Helper  func(on  calls   •  Common  Func(on  calls  (Heuris(cally  detected)  
  32. Example   public  class  CocktailServiceImpl  implements  CocktailService{      

                   List<Cocktail>  cocktails=new  ArrayList<Cocktail>();            @PreAuthorize(hasRole(‘ADMIN’))            public  Cocktail  getCocktail(int  id)  {                    return  cocktails.get(int  );                }              public  Cocktail  deleteCocktail(int  id)  {                    Cocktail  cocktail  =  cocktails.get(int  );                    cocktails.remove(int);                    return  cocktail;                }   }      
  33. Example   CocktailServiceImpl.java   @RequestMapping(“/admin/getDrink)   public  getCocktail(int  id)  {

           return  lookupCocktail(id);       }     CocktailServiceImpl.java   private  lookupCocktail()    {            Cocktail  c  =  cocktails.get();            return  c;     }     CocktailService.java   public  interface  CocktailService      {   {        @PreAuthorize(hasRole(‘ADMIN’))          Cocktail  getCocktail(int  );                ….       }     @PreAuthorize(hasRole(‘ADMIN’))   @PreAuthorize(hasRole(‘ADMIN’))  &&  isAuthenBcated()   URL  -­‐>  Access  Check   Security-­‐config.xml   <hWp>   <intercept-­‐url        paWern=“/admin/*”      access=“isAuthenBcated()”     />   Method  -­‐>  URL   •  AnnotaBon   @RequestMapping     •  ConfiguraBon                  PointCuts,  …   isAuthenBcated()   Method  -­‐>  URL  -­‐>  Access  Check   X  
  34. 2.  Iden(fy  Anomalies  

  35. Iden(fy  Anomalies   •  Given  a  class  c  where  some

     of  methods  have  access   checks,  are  there  methods  that  do  not?   •  If  so,  are  they  performing  any  of  the  same  types  of   accesses  as  the  ones  that  do?    
  36. Iden(fy  Anomalies   •  For  each  non-­‐access  controlled  method  

    examine  all  opera(ons  performed  within   func(on  scope:     •  Iden(fy  Func(on   •  Iden(fy  Variable   –  Instance  object,  argument   •  Fine  Tune  opera(ons:   – Map  opera(ons  with  CRUD  ac(ons  
  37. Iden(fy  Anomalies   Same  variable  and  same  method   [SAMEVAR+SAMEMETHOD]

        Same  variable  and  different  method   [SAMEVAR+DIFFMETHOD]     Same  variable  type  and  same  method   [SAMETYPE+SAMEMETHOD]     Same  variable  type  and  different  method     [SAMETYPE+DIFFMETHOD]     •  deleteCocktail()   • Opera(ons:     •   this.cocktails  +  get()     •  getCocktail()   • Opera(ons:     • this.cocktails  +  get()     • Access  Checks:       • PreAuthorize(hasRole(‘Admin’)).    
  38. Iden(fy  Anomalies:   Inconsistency     private  lookupCocktail()    {

               Cocktail  =  cocktails.get();     }       public  getCocktail(int  id)  {        return  lookupCocktail(id);       }       Public  deleteCocktail(int  id)  {        return  lookupCocktail(id);       }     @PreAuthorize(hasRole(‘ADMIN’))   isAuthen(cated()  
  39. 3.  Suggest  Remedia(on  

  40. Suggest  Remedia(on   •  Present  the  developer  with  precise  details

     of   the  anomalies  found  and  the  evidences   suppor(ng  the  finding   •  If  several  evidences  are  found,  present  the   most  similar  in  terms  of  opera(ons  performed   •  Provide  developers  with  a  set  of  access   control  checks  based  on  evidences  
  41. Summary   Create   Specifica(on     •  getCocktail()  

    • Opera(ons:     • CocktailServiceImpl  +  this.cocktails  +  get()     • Access  Checks:       • PreAuthorize(hasRole(‘Admin’)).     Iden(fy   Anomalies   •  deleteCocktail()   • Opera(ons:  CocktailServiceImpl  +  this.cocktails  +  get()     Remedia(on   •  deleteCocktail()   • Add  Check:     • PreAuthorize(hasRole(‘Admin’))   • Evidence:  getCocktail()  
  42. None
  43. In  the  wild   •  Mifos:   – Very  large  open

     source  microfinance  applica(on.   – 323,007  Java  LOC   – 122224  XML  LOC   – It  uses  spring  annota(ons  in  addi(on  to  custom   checks   – 77  anomalies  were  found  
  44. In  the  wild:  mifos     Anomaly   LocaBon:  

      ClientServiceFacadeWebTier:859   FuncBon  Signature:     public  String  transferClientToBranch(String,  Short)   Suspicious   operaBons   [SAMEVAR+SAMEMETHOD]     this.customerService  +  transferClientTo  @  842   Evidence   FuncBon  Signature:     public  String  transferClientToGroup(Integer,  String,  Integer)   Protected  OperaBons:     this.customerService+  transferClientTo  @  733     Recommended   AnnotaBon  Set   @PreAuthorize("isFullyAuthen(cated()  and   hasRole('ROLE_CAN_UPDATE_GROUP_MEMBERSHIP_OF_CLIENT ')")  
  45. Source:  hWps://github.com/mifos/head/blob/0d9cdffeb07bcbeb75ffa4f9107272c6694a00a2/appdomain/src/main/java/org/mifos/applica(on/servicefacade/ClientServiceFacadeWebTier.java  

  46. Source:  hWps://github.com/mifos/head/blob/0d9cdffeb07bcbeb75ffa4f9107272c6694a00a2/serviceInterfaces/src/main/java/org/mifos/applica(on/servicefacade/ClientServiceFacade.java  

  47. In  the  wild:  mifos     Anomaly   LocaBon:  

      Ques(onnaireServiceFacadeImpl:94   FuncBon  Signature:     public  Ques(onGroupDetail  createQues(onGroup   (Ques(onGroupDetail)   Suspicious   operaBons   [SAMEVAR+SAMEMETHOD]     this.ques(onnaireService  +  defineQues(onGroup  @  94   Evidence   FuncBon  Signature:     public  Ques(onGroupDetail   createAc(veQues(onGroup(Ques(onGroupDetail)   Protected  OperaBons:     this.ques(onnaireService  +  defineQues(onGroup  @  100   Recommended   AnnotaBon  Set   @PreAuthorize("isFullyAuthen(cated()  and   hasRole('ROLE_CAN_ACTIVATE_QUESTION_GROUPS')")  
  48. Source:  hWps://github.com/mifos/head/blob/aa1d2ac985b‚e7ea4e07a0eb7a22cef7ba92bc1/appdomain/src/main/java/org/mifos/plaƒorm/ques(onnaire/service/ Ques(onnaireServiceFacadeImpl.java    

  49. Source:  hWps://github.com/mifos/head/blob/6fe9141e4491194181c7ec85ef0adc3773208dcd/serviceInterfaces/src/main/java/org/mifos/plaƒorm/ques(onnaire/service/ Ques(onnaireServiceFacade.java    

  50. In  the  wild:  mifos     Anomaly   LocaBon:  

      SystemInforma(onServiceFacadeWebTier:90   FuncBon  Signature:     public  String  getServerInforma(on(ServletContext,  Locale)   Suspicious   operaBons   [SAMETYPE+SAMEMETHOD]     org.mifos.applica(on.admin.SystemInfo  +  SystemInfo  @  90   Evidence   FuncBon  Signature:     public  SystemInfor  getSystemInforma(on(ServletContext,  Locale)   Protected  OperaBons:     org.mifos.applica(on.admin.SystemInfo  +  SystemInfo  @  46     Recommended   AnnotaBon  Set   PreAuthorize(isFullyAuthen(cated()  and   hasRole(‘ROLE_VIEW_SYSTEM_INFO’)      
  51. Source:  hWps://github.com/mifos/head/blob/e271189b8ec71e5724ffcf189f0aef7249896e13/applica(on/src/main/java/org/mifos/applica(on/admin/servicefacade/ SystemInforma(onServiceFacadeWebTier.java    

  52. Source:  hWps://github.com/mifos/head/blob/0d9cdffeb07bcbeb75ffa4f9107272c6694a00a2/serviceInterfaces/src/main/java/org/mifos/applica(on/admin/servicefacade/ SystemInforma(onServiceFacade.java  

  53. In  the  wild   •  pgGallery   – Small  photo  sharing

     applica(on   •  1897  Java  LOC   •  419  XML  LOC   – 8  anomalies  iden(fied  
  54. In  the  wild:  pgGallery   Anomaly   LocaBon:    

    AlbumService.java:42   FuncBon  Signature:     public  List<Album>  getBreadcrumbById  (BigDecimal)   Suspicious   operaBons   [SAMEVAR+DIFFMETHOD]     this.albumMapper  +  getBreadcrumbById  @  42   Evidence  1   FuncBon  Signature:     public  List<Album>  getByParent  (BigDecimal)   Protected  OperaBons:     this.albumMapper  +  getByParent  @  30   Evidence  2   FuncBon  Signature:     public  List<Album>  getRoot()   Protected  OperaBons:     this.albumMapper  +  getRoot  @  25   Recommended   AnnotaBon  Set   PostFilter  (  hasAnyRole('ROLE_USER','ROLE_ADMIN'))   PostFilter  (filterObject.isPublic()  ==  true)  
  55. Source:  hWps://github.com/chotchki/pgGallery/blob/master/src/main/java/pgGallery/db/service/AlbumService.java  

  56. Next  steps   •  Handle  custom  authoriza(on  checks.    

    •  Reduce  false  posi(ves:     – Increase  granularity  of  opera(ons.       – Map  opera(ons  to  CRUD  ac(ons.   •  Extending  to  other  frameworks/languages  
  57. Thanks       alvaro.munoz@hp.com   @pwntester