目前大多数应用程序都会包含:服务器端逻辑、影响t应用客户端逻辑、大漏洞数据存储、影响t应用数据传输 、大漏洞以及API等多个组件。影响t应用与此同时,大漏洞每种语言 、影响t应用框架、大漏洞以及环境的影响t应用使用 ,都会让应用程序暴露于一组独特的大漏洞漏洞之中。为了保证这些组件的影响t应用安全,第一时间发现应用的大漏洞漏洞,进而构建出一个安全态势较高的源码库影响t应用应用,往往需要我们付出不懈的大漏洞努力。
值得庆幸的影响t应用是 ,大多应用程序的漏洞都有着相似、甚至相同的底层原因 。研究这些常见的漏洞类型、以及背后的原因,将有助于我们对应用程序进行恰当的防护 。服务器租用 下面,我将和您一起讨论影响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 { }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22. 访问控制不当攻击者会想方设法绕过那些访问权限控制实施不当的应用程序。访问控制不仅仅只包括身份验证 。也就是说,我们除了需要证明用户的身份(即“你是谁?”),还要通过应用程序授予相应的权限(即“你可以做什么?”)。只有通过两者双管齐下,才能共同确保用户不会访问到超出其权限的源码下载服务与功能 。 目前,我们有多种方式为用户配置授权 ,其中包括:基于角色的访问控制、基于所有权的访问控制、以及访问控制列表等 。而开发人员常犯的一种错误是在客户端执行授权检查 。由于攻击者可以操控和覆盖客户端的检查,因此这是不安全的 。亿华云可见,此类授权检查必须使用服务器端的代码来执行。请参考如下代码段: 复制export class AdministratorGuard implements CanActivate{ constructor(private authService: AuthService, private router: Router) { } canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<true | UrlTree>{ // 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 users name and role. Will be set user: User | null = null // Check whether the current user is an administrator. isAdmin(): Observable<boolean>{ 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<User | null>{ if (this.loggedIn !== null) { return of(this.user) } return this.http.get<User>(/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}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56. 开放式重定向例如,当未经身份验证的用户尝试着访问需要登录后才能看到的页面时,网站就需要将该用户自动重定向到登录页面,并在他们通过了身份验证之后 ,再让其返回到原来的位置。 在开放式重定向攻击发生时 ,攻击者通过向用户提供来自合法站点的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]) }) } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.当然 ,我们还有许多其他方法可以防止开放式重定向的发生 。例如 :对请求引用方予以检查、或使用页面索引进行重定向。不过,正因为验证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{ } 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15. 模板注入类似于HTML文件的Web模板,为开发人员提供了一种通过将应用数据与静态模板相结合,以指定如何呈现页面的方法。此功能允许开发人员将从数据库或HTTP请求中检索到的动态内容,插入到网页中。 顾名思义 ,模板注入需要注入到网页的模板中。根据受感染应用的权限,攻击者可以通过使用模板注入的漏洞 ,来读取敏感文件、执行恶意代码、或提升他们在系统上的各种权限 。下面展示了Angular模板的不安全用法。它允许攻击者通过URL的哈希值 ,来恶意注入代码 : 复制@Component({ selector: app-header, template: <h1> + (window.location.hash || Home) + </h1>}) export class HeaderComponent{ } 1.2.3.4.5.注意 :请千万不要直接将用户提供的输入连接到模板中,而应该使用模板引擎的内置替换机制,来安全地嵌入动态输入。请参考如下代码段 : 复制@Component({ selector: app-header, template: <h1>{ { title }}</h1>}) export class HeaderComponent{ title = ngOnInit() { this.title = window.location.hash || Home; } }1.2.3.4.5.6.7.8.9.10.11. 跨站点脚本跨站点脚本包含的攻击也称为XSSI(Cross-Site Script Inclusion) 。此类攻击发生在当恶意站点包含了来自受害者站点的Javascript ,并通过脚本提取其敏感信息时。 同源策略(same-origin policy ,SOP)通常可以起到控制数据跨源(cross-origins)访问的作用。不过 ,SOP并不能限制JavaScript代码,而且HTML<script>标签会允许从任何来源加载JavaScript代码。从技术角度来说 ,该功能方便了允许跨域重用的JavaScript文件,但是会带来新的安全风险 :攻击者可以通过加载受害者的JS文件,来窃取写入JavaScript文件的数据。 例如,某网站通过Javascript文件 ,为登录用户存储和传输敏感数据。如果用户在同一浏览器中访问了恶意站点,那么恶意站点可以导入该JavaScript文件 ,并访问与该用户会话相关的敏感信息。而这一切都归因于存储在浏览器中的用户Cookie。 因此,为避免XSSI攻击,请勿在JavaScript文件中传输敏感数据 。下面是如何使用JSON文件(会受到SOP的限制)在Angular中安全地加载API令牌的示例 : 复制// The configuration information we will retrieve from the server.export interface Config{ username : string accessToken : string role : string} @Injectable() export class ConfigService{ constructor(private http: HttpClient) { } // Retrieve configuration information from the server. getConfig() { return this.http.get<Config>(api/config) .pipe( catchError(this.handleError) ) } private handleError(error: HttpErrorResponse) { if (error.status === 0) { // A client-side or network error occurred. Handle it accordingly. log.error(An error occurred:, error.error) } else{ // The server returned an unsuccessful response code. log.error(`Backend returned code ${ error.status}, body was: `, error.error) } return throwError(An unexpected error occurred loading configuration.) } } 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31. 译者介绍陈峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式 ,分享前沿技术与新知;经常以线上 、线下等方式,开展信息安全类培训与授课 。 原文标题 :Angular + React: Vulnerability Cheatsheet,作者: Vickie Li |