Introducing Qwiet AI AutoFix! Reduce the time to secure code by 95% Read More

# Improper Access Control

Correctly applied access control rules are key to keeping your data secure. Almost all applications need to protect sensitive data and operations, so putting careful thought into how to restrict access is important when designing a system.

Your access control strategy should cover three aspects:

* **Authentication** – correctly identifying a user when they return to the application.
* **Authorization** – deciding what actions a user should and should not be able to perform once they have been authenticated.
* **Permission Checking** – evaluating authorization at the point-in-time when a user attempts to perform an action.

## Access Control in React

Routing in JavaScript frameworks is usually done with a routing library that will update the browser URL and the page contents as the user interacts with your application. You should check whether the user has sufficient permission before permitting them access to sensitive routes. Here’s how to implement this using *Role-Based Access Control* and redirects:

=== Angular

“`typescript
@NgModule({
imports: [RouterModule.forRoot([// These routes are available to all users.
{ path: ”, component: HomeComponent },
{ path: ‘news’, component: NewsComponent },
{ path: ‘login’, component: LoginComponent },

// These routes are only available to administrative users.
{ path: ‘admin/users’, component: UsersComponent, canActivate: [ AdminGuard ]},
{ path: ‘admin/invites’, component: InvitesComponent, canActivate: [ AdminGuard ]},

// This is the fall-through component when the route is not recognized.
{ path: ‘**’, component: PageNotFoundComponent}

])],
exports: [RouterModule]
})
export class AppRoutingModule {}
“`

=== React

“`jsx
function Routes(props) {
return (
<Router>
<Switch><!– These routes are available to all users. –>
<Route exact path=”/”>
<Home/>
</Route>
<Route path=”/news”>
<News/>
</Route>
<Route exact path=”/login”>
<Login/>
</Route>

<!– These routes are only available to administrative users. –>
<AdminRoute path=”/admin/users” role={props.role}>
<Users/>
</AdminRoute>

<AuthenticatedRoute path=”/admin/invites” role={props.role}>
<Invites/>
</AuthenticatedRoute>

<Route path=”*”>
<NotFound/>
</Route>

</Switch>
</Router>
)
}

/**
* A wrapper for <Route> that redirects to the home page if the user is not an administrator.
*/
function AuthenticatedRoute(props) {
if (props.role === ‘admin’) {
return <Route {…props} />
}

return <Redirect to={{ pathname: `/` }} />
}
“`

Authorization checks on the client-side can be overridden by an attacker, however, so it is important to check whether the user has sufficient permission when you load the data for a code component or update state on the server. These authorization checks **must be performed in server-side code**. Your code should handful an authorization failure gracefully:

=== Angular

“`typescript
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
})
)
}
}
“`

“`typescript
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<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
}
“`

=== React

“`jsx
class Users extends React.Component {
constructor(props) {
super(props)this.state = {
loading : true,
users : [],
error : null
}
}

async componentDidMount() {

// Load a list of all users so an administrator can view them.
const response = await fetch(‘/api/users’)
const data = await response.json()

if (response.ok && data.success) {

// Set the user data in the state so we can render the page.
this.setState({
loading : false,
users : data.users
})
}
else {

// Shown an error message if the user list cannot be loaded –
// for instance, if an authorization check failed.
this.setState({
loading : false,
error : data.error || ‘There was a problem loading the user list.’
})
}
}

render() {
const error = this.state.error ? <div className=”error”>{this.state.error}</div> : null

let body
if (this.state.loading) {
body = <div className=”loading”>Loading…</div>
}
else {

// Render the user list returned from the server.
body = this.state.users.map(user => {
return <User user={user}/>
})
}

return (
<div>
{error}
{body}
</div>
)
}
}
“`

 

# Further Considerations

Access control vulnerabilities tend to occur when mistakes are made during the design phase. To avoid this, make sure you:

* Design your access control upfront and document it.
* Write unit tests to validate that only authorized users can access sensitive resources. These unit tests should cover client-side routes *and* server-side logic.
* Think like an attacker: focus on the biggest risks your organization faces and prioritize securing those.
* Record user activity in server-side logs, so you have audit trails of who did what and when.

# CWEs

* [CWE-284](https://cwe.mitre.org/data/definitions/284.html)

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit: www.shiftleft.io.

Share

See for yourself – run a scan on your code right now