# Broken Access Control

#### Insecure Direct Object Reference in Python

**Vulnerability:** Insecure Direct Object Reference

**Vulnerable Code:**

```python
pythonCopy code@app.route('/profile/<user_id>')
def profile(user_id):
    user = db.get_user(user_id)
    return render_template('profile.html', user=user)
```

**Reason for vulnerability:** Directly accessing user data by `user_id` without verifying that the current user has permission to view that data.

**Fixed Code:**

```python
pythonCopy code@app.route('/profile/<user_id>')
@login_required
def profile(user_id):
    if user_id != current_user.id:
        abort(403)
    user = db.get_user(user_id)
    return render_template('profile.html', user=user)
```

**Reason for fix:** Adding access control checks ensures that users can only access their own data, preventing unauthorized access.

***

**Vulnerable Code:**

```java
javaCopy codeString userId = request.getParameter("userId");
User user = userService.getUserById(userId);
```

**Reason for vulnerability:** No access control check, allowing any user to access any user data.

**Fixed Code:**

```java
javaCopy codeString userId = request.getParameter("userId");
if (!currentUser.getId().equals(userId)) {
    throw new UnauthorizedException();
}
User user = userService.getUserById(userId);
```

**Reason for fix:** Check if the current user is authorized to access the requested user data.

***

```php
$user_id = $_GET['user_id'];
$user_data = $db->query("SELECT * FROM users WHERE id = '$user_id'");
```

**Reason for vulnerability:** The code uses user-input to directly access a database record without proper authorization. Fixed Code 1 (PHP):

```php
$user_id = $_GET['user_id'];
if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user_id) {
$user_data = $db->query("SELECT * FROM users WHERE id = '$user_id'");
} else {
// handle unauthorized access
}
```

**Reason for fix:** The code checks if the user is authenticated and authorized to access the requested user data. Vulnerable Code 2 (Java):

```java
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String userId = request.getParameter("userId");
User user = userDao.getUser(userId);
// ...
}
```

**Reason for vulnerability:** The code uses user-input to directly access a user object without proper authorization. Fixed Code 2 (Java):

```java
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String userId = request.getParameter("userId");
if (request.isUserInRole("admin") || userId.equals(request.getRemoteUser())) {
User user = userDao.getUser(userId);
// ...
} else {
// handle unauthorized access
}
}
```

**Reason for fix:** The code checks if the user is authenticated and authorized to access the requested user data.

***

#### Vulnerable Code

```java
@RestController
public class UserController {
    @GetMapping("/api/users/{userId}/profile")
    public ResponseEntity<UserProfile> getUserProfile(@PathVariable Long userId) {
        UserProfile profile = userService.getUserProfile(userId);
        return ResponseEntity.ok(profile);
    }
}
```

#### Reason for Vulnerability:

This endpoint doesn't check if the requesting user has permission to access the profile for the given userId, allowing any authenticated user to access any profile.

#### Fixed Code:

```java
javaCopy@RestController
public class UserController {
    @GetMapping("/api/users/{userId}/profile")
    public ResponseEntity<UserProfile> getUserProfile(@PathVariable Long userId, Authentication authentication) {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        if (!userService.canAccessProfile(userDetails.getUsername(), userId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        UserProfile profile = userService.getUserProfile(userId);
        return ResponseEntity.ok(profile);
    }
}
```

#### Reason for Fix:

The fixed code checks if the authenticated user has permission to access the requested profile before returning it, preventing unauthorized access.

### Java Example

#### Vulnerable Code:

```java
javaCopy@WebServlet("/downloadFile")
public class FileDownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String fileName = request.getParameter("file");
        File file = new File("/path/to/files/" + fileName);
        // Code to send file as response
    }
}
```

#### Reason for Vulnerability:

This servlet allows downloading any file by specifying its name, potentially exposing sensitive files.

#### Fixed Code:

```java
javaCopy@WebServlet("/downloadFile")
public class FileDownloadServlet extends HttpServlet {
    private static final String FILE_PATH = "/path/to/files/";
    private static final Set<String> ALLOWED_FILES = Set.of("public1.pdf", "public2.pdf");

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String fileName = request.getParameter("file");
        if (!ALLOWED_FILES.contains(fileName)) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        File file = new File(FILE_PATH + fileName);
        if (!file.getCanonicalPath().startsWith(FILE_PATH)) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        // Code to send file as response
    }
}
```

#### Reason for Fix:

The fixed code checks if the requested file is in the allowed list and uses canonical path checking to prevent path traversal, ensuring only authorized files can be downloaded.

### Python Example

#### Vulnerable Code:

```python
pythonCopyfrom flask import Flask, request, jsonify
import json

app = Flask(__name__)

@app.route('/api/notes/<int:note_id>', methods=['GET'])
def get_note(note_id):
    with open('notes.json', 'r') as f:
        notes = json.load(f)
    if str(note_id) in notes:
        return jsonify(notes[str(note_id)])
    return jsonify({'error': 'Note not found'}), 404

if __name__ == '__main__':
    app.run(debug=True)
```

#### Reason for Vulnerability:

This endpoint allows any user to access any note by its ID without checking ownership or permissions.

#### Fixed Code:

```python
pythonCopyfrom flask import Flask, request, jsonify
import json
from functools import wraps

app = Flask(__name__)

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not request.headers.get('Authorization'):
            return jsonify({'error': 'No authorization token provided'}), 401
        # Implement proper token verification here
        return f(*args, **kwargs)
    return decorated_function

@app.route('/api/notes/<int:note_id>', methods=['GET'])
@login_required
def get_note(note_id):
    user_id = get_user_id_from_token(request.headers.get('Authorization'))
    with open('notes.json', 'r') as f:
        notes = json.load(f)
    if str(note_id) in notes and notes[str(note_id)]['owner_id'] == user_id:
        return jsonify(notes[str(note_id)])
    return jsonify({'error': 'Note not found or access denied'}), 404

def get_user_id_from_token(token):
    # Implement token verification and return user_id
    pass

if __name__ == '__main__':
    app.run(debug=True)
```

#### Reason for Fix:

The fixed code adds authentication and checks if the requesting user is the owner of the note before returning it, preventing unauthorized access.

***

## Open Redirect

**Example 1: Java**

**Vulnerable Code:**

```java
javaCopy codeString url = request.getParameter("url");
response.sendRedirect(url);
```

**Reason for vulnerability:** No validation of the URL, allowing open redirect attacks.

**Fixed Code:**

```java
javaCopy codeString url = request.getParameter("url");
if (!isValidRedirectUrl(url)) {
    throw new IllegalArgumentException("Invalid URL");
}
response.sendRedirect(url);
```

**Reason for fix:** Validate the URL before redirecting to ensure it is an allowed destination.

**Example 2: Python**

**Vulnerable Code:**

```python
pythonCopy code@app.route('/redirect')
def redirect():
    url = request.args.get('url')
    return redirect(url)
```

**Reason for vulnerability:** No validation of the URL, allowing open redirect attacks.

**Fixed Code:**

```python
pythonCopy code@app.route('/redirect')
def redirect():
    url = request.args.get('url')
    if not is_valid_redirect_url(url):
        abort(400)
    return redirect(url)
```

**Reason for fix:** Validate the URL before redirecting to ensure it is an allowed destination.

***

### Java Example

#### Vulnerable Code:

```java
javaCopy@Controller
public class RedirectController {
    @GetMapping("/redirect")
    public String redirect(@RequestParam("url") String url) {
        return "redirect:" + url;
    }
}
```

#### Reason for Vulnerability:

This code allows redirection to any URL specified in the parameter, which can be exploited for phishing attacks.

#### Fixed Code:

```java
javaCopy@Controller
public class RedirectController {
    private static final List<String> ALLOWED_DOMAINS = Arrays.asList("example.com", "safe-site.com");

    @GetMapping("/redirect")
    public String redirect(@RequestParam("url") String url) {
        if (isValidRedirectUrl(url)) {
            return "redirect:" + url;
        }
        return "redirect:/error";
    }

    private boolean isValidRedirectUrl(String url) {
        try {
            URL parsedUrl = new URL(url);
            return ALLOWED_DOMAINS.contains(parsedUrl.getHost());
        } catch (MalformedURLException e) {
            return false;
        }
    }
}
```

#### Reason for Fix:

The fixed code validates the redirect URL against a whitelist of allowed domains, preventing redirection to potentially malicious sites.

### Java Example

#### Vulnerable Code:

```java
javaCopy@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String redirectUrl = request.getParameter("redirect");

        if (isValidUser(username, password)) {
            response.sendRedirect(redirectUrl);
        } else {
            response.sendRedirect("/login?error=1");
        }
    }

    private boolean isValidUser(String username, String password) {
        // Authentication logic
    }
}
```

#### Reason for Vulnerability:

This servlet allows redirection to any URL after successful login, which can be exploited for phishing attacks.

#### Fixed Code:

```java
javaCopy@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final String DEFAULT_REDIRECT = "/dashboard";

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String redirectUrl = request.getParameter("redirect");

        if (isValidUser(username, password)) {
            if (isValidRedirectUrl(redirectUrl)) {
                response.sendRedirect(redirectUrl);
            } else {
                response.sendRedirect(DEFAULT_REDIRECT);
            }
        } else {
            response.sendRedirect("/login?error=1");
        }
    }

    private boolean isValidUser(String username, String password) {
        // Authentication logic
    }

    private boolean isValidRedirectUrl(String url) {
        return url != null && url.startsWith("/") && !url.contains("://");
    }
}
```

#### Reason for Fix:

The fixed code validates that the redirect URL is a relative path within the same domain, preventing open redirects to external sites.

### Python Example

#### Vulnerable Code:

```python
pythonCopyfrom flask import Flask, request, redirect

app = Flask(__name__)

@app.route('/redirect')
def redirect_url():
    url = request.args.get('url')
    return redirect(url)

if __name__ == '__main__':
    app.run(debug=True)
```

#### Reason for Vulnerability:

This Flask route allows redirection to any URL specified in the query parameter, which can be exploited for phishing attacks.

#### Fixed Code:

```python
pythonCopyfrom flask import Flask, request, redirect, abort
from urllib.parse import urlparse, urljoin

app = Flask(__name__)

def is_safe_url(target):
    ref_url = urlparse(request.host_url)
    test_url = urlparse(urljoin(request.host_url, target))
    return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc

@app.route('/redirect')
def redirect_url():
    url = request.args.get('url')
    if url and is_safe_url(url):
        return redirect(url)
    return abort(400)

if __name__ == '__main__':
    app.run(debug=True)
```

#### Reason for Fix:

The fixed code validates that the redirect URL is within the same domain as the application, preventing open redirects to external sites.
