阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

影响Angular和React应用安全的漏洞分析

31次阅读
没有评论

共计 5015 个字符,预计需要花费 13 分钟才能阅读完成。

导读 目前大多数应用程序都会包含:服务器端逻辑、客户端逻辑、数据存储、数据传输、以及 API 等多个组件。

目前大多数应用程序都会包含:服务器端逻辑、客户端逻辑、数据存储、数据传输、以及 API 等多个组件。与此同时,每种语言、框架、以及环境的使用,都会让应用程序暴露于一组独特的漏洞之中。为了保证这些组件的安全,第一时间发现应用的漏洞,进而构建出一个安全态势较高的应用,往往需要我们付出不懈的努力。

影响 Angular 和 React 应用安全的漏洞分析

Happy girl is playing with group of books in studio

值得庆幸的是,大多应用程序的漏洞都有着相似、甚至相同的底层原因。研究这些常见的漏洞类型、以及背后的原因,将有助于我们对应用程序进行恰当的防护。

下面,我将和您一起讨论影响 Angular 和 React 应用的如下六种最常见的漏洞,以及如何发现和预防它们:

  • 身份验证绕过
  • 访问控制不当
  • 开放式重定向
  • 跨站请求伪造 (CSRF)
  • 模板注入
  • 跨站点脚本包含 (XSSI)
  • 身份验证绕过

    身份验证是指在执行敏感操作、或访问敏感数据之前,先验明身份的合法性。如果在应用程序上未能正确地实施身份验证,那么攻击者将可以利用此类错误配置,来访问他们本不该能够访问到的服务与功能。例如,Angular 通常使用 AppRoutingModule 来进行路由。在将用户引导至应用程序中的敏感路由之前,您应该检查用户是否已通过了身份验证,并被授权了访问该资源。请参考如下代码段:

    @NgModule({
        imports: [RouterModule.forRoot([
        
            // These paths are available to all users.
            {path: '', component: HomeComponent},
            {path: 'features', component: FeaturesComponent},
            {path: 'login', component: LoginComponent},
        
            // These routes are only available to users after logging in.
            {path: 'feed', component: FeedComponent, canActivate: [ AuthGuard]},
            {path: 'profile', component: ProfileComponent, canActivate: [ AuthGuard]},
        
            // This is the fall-through component when the route is not recognized.
            {path: '**', component: PageNotFoundComponent}
        
     ])],
            
        exports: [RouterModule]
            
     })
        
     export class AppRoutingModule {}
    访问控制不当

    攻击者会想方设法绕过那些访问权限控制实施不当的应用程序。访问控制不仅仅只包括身份验证。也就是说,我们除了需要证明用户的身份(即“你是谁?”),还要通过应用程序授予相应的权限(即“你可以做什么?”)。只有通过两者双管齐下,才能共同确保用户不会访问到超出其权限的服务与功能。

    目前,我们有多种方式为用户配置授权,其中包括:基于角色的访问控制、基于所有权的访问控制、以及访问控制列表等。而开发人员常犯的一种错误是在客户端执行授权检查。由于攻击者可以操控和覆盖客户端的检查,因此这是不安全的。可见,此类授权检查必须使用服务器端的代码来执行。请参考如下代码段:

    export class AdministratorGuard implements CanActivate {constructor(private authService: AuthService, private router: Router) {}
      canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
        // Check whether this user is an administratoor.  
        return this.authService.isAdmin().pipe(
          map(isAdmin => {if (!isAdmin) {return this.router.parseUrl('/')
            }
            return isAdmin
          })
        )
      }
    }
    export class AuthService {constructor(private http: HttpClient) {}
      // Whether the user is currently logged in.
      loggedIn: boolean | null = null
      // The user object object encompassing the user's name and role. Will be set
      user: User | null = null
      // Check whether the current user is an administrator.
      isAdmin(): Observable {return this.getCurrentUser().pipe(map(user => {return user != null && user.role === 'admin'}))
      }
      // Get the user definition from local state, or the server (if this is the first time we are checking).
      getCurrentUser(): Observable {if (this.loggedIn !== null) {return of(this.user)
        }
        return this.http.get('/api/auth', {responseType: 'json'}).pipe(
          tap({
            next: user => {
              // If we get a user definition from the server it indicates this user is logged in.  
              this.user     = user
              this.loggedIn = true
            },
            error: error => {
              // A 401 response from the server indicates this user is not logged in.  
              this.user     = null
              this.loggedIn = false
            }
          }),
          catchError(() => {return of(null)
          })
        )
      }
    }
    export interface User {
        username: string
        role:     string
    }
    
    开放式重定向

    例如,当未经身份验证的用户尝试着访问需要登录后才能看到的页面时,网站就需要将该用户自动重定向到登录页面,并在他们通过了身份验证之后,再让其返回到原来的位置。

    在开放式重定向攻击发生时,攻击者通过向用户提供来自合法站点的 URL,以欺骗用户访问某个外部站点。也就是说,该 URL 会将其重定到其他站点。而该站点一面设法让用户相信他们仍然在原始网站上,一面帮助攻击者构建出更加看似可信的网络钓鱼活动。

    为了防止开放式重定向,您需要确保应用程序不会轻易将用户重定向到那些恶意站点的位置。例如,您可以通过验证重定向 URL,来完全禁止离站重定向行为。请参考如下代码段:

    export class LoginComponent {
        
      // The username and password entered by the user in the login form.
      username = '';
      password = '';
        
      // The destination URL to redirect the user to once they log in successfully.
      destinationURL = '/feed'
        
      constructor(private authService : AuthService,
                  private route       : ActivatedRoute,
                  private router      : Router) { }
        
      ngOnInit() {this.destinationURL = this.route.snapshot.queryParams['destination'] || '/feed';
      }
        
      onSubmit() {this.authService.login(this.username, this.password)
          .subscribe(() => {
              // After the user has lgged in, redirect them to their desired destination.
              let url = this.destinationURL
        
              // Confirm that the URL is a relative path - i.e. starting with a single '/' characters.
              if (!url.match(/^\/[^\/\\]/)) {url = '/feed'}
        
              this.router.navigate([url])
            })
      }
    }

    当然,我们还有许多其他方法可以防止开放式重定向的发生。例如:对请求引用方予以检查、或使用页面索引进行重定向。不过,正因为验证 URL 相对比较困难,因此开放式重定向仍然是当代 Web 应用普遍存在的问题。

    跨站请求伪造

    跨站点请求伪造 (Cross-Site Request Forgery,CSRF) 是一种客户端技术,可用于攻击 Web 应用的其他用户。使用 CSRF,攻击者可以发送虚假的、来自受害者的 HTTP 请求,去执行攻击者的危害性操作。例如,攻击者会在未经许可的情况下,更改受害者的密码、或从其银行账户里转账。

    与开放式重定向不同,我们目前已有一种行之有效的对抗 CSRF 的方法,即:使用 CSRF 令牌和 SameSite Cookie 的组合,以避免使用 GET 请求进行各项状态更改的操作。例如,Angular 允许您使用 HttpClientXsrfModule 模块,向 HTTP 请求添加防伪的令牌。请参考如下代码段:

    @NgModule({declarations: [],
      imports: [
        BrowserModule,
        HttpClientModule,
        HttpClientXsrfModule.withOptions({
          cookieName: 'XSRF-TOKEN',
          headerName: 'X-CSRF-TOKEN'
        }),
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    模板注入

    类似于 HTML 文件的 Web 模板,为开发人员提供了一种通过将应用数据与静态模板相结合,以指定如何呈现页面的方法。此功能允许开发人员将从数据库或 HTTP 请求中检索到的动态内容,插入到网页中。

    顾名思义,模板注入需要注入到网页的模板中。根据受感染应用的权限,攻击者可以通过使用模板注入的漏洞,来读取敏感文件、执行恶意代码、或提升他们在系统上的各种权限。下面展示了 Angular 模板的不安全用法。它允许攻击者通过 URL 的哈希值,来恶意注入代码:

    @Component({
      selector: 'app-header',
      template: 'h1' + (window.location.hash || 'Home') + '/h1'
    })
    export class HeaderComponent {}

    注意:请千万不要直接将用户提供的输入连接到模板中,而应该使用模板引擎的内置替换机制,来安全地嵌入动态输入。请参考如下代码段:

    @Component({
      selector: 'app-header',
      template: 'h1{{title}}/h1'
    })
    export class HeaderComponent {
      title = ''  
            
      ngOnInit() {this.title = window.location.hash || 'Home';}
    }
    跨站点脚本

    跨站点脚本包含的攻击也称为 XSSI(Cross-Site Script Inclusion)。此类攻击发生在当恶意站点包含了来自受害者站点的 Javascript,并通过脚本提取其敏感信息时。

    同源策略(same-origin policy,SOP)通常可以起到控制数据跨源(cross-origins)访问的作用。不过,SOP 并不能限制 JavaScript 代码,而且 HTML

    阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

    腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

    代金券:在阿里云专用满减优惠券

    正文完
    星哥说事-微信公众号
    post-qrcode
     0
    星锅
    版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计5015字。
    转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
    【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
    阿里云-最新活动爆款每日限量供应
    评论(没有评论)
    验证码
    【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中