ROADtools Azure AD Assessment Framework Cheat Sheet
Überblick
ROADtools (The Azure AD Exploration Framework) ist eine Sammlung von Werkzeugen, die von Dirk-Jan Mollema für die Erkundung und Bewertung von Azure Active Directory entwickelt wurden. Es bietet umfassende Möglichkeiten, um Azure AD Umgebungen zu erkunden, Konfigurationen zu analysieren und Sicherheitsprobleme zu identifizieren.
ZEIT Warnung: Dieses Tool ist nur für autorisierte Penetrationstests und Sicherheitsbewertungen gedacht. Stellen Sie sicher, dass Sie eine ordnungsgemäße Genehmigung vor der Verwendung in jeder Umgebung haben.
Installation
Pip Installation
```bash
Install ROADtools
pip3 install roadtools
Install specific components
pip3 install roadrecon roadlib
Install from GitHub (latest)
pip3 install git+https://github.com/dirkjanm/ROADtools ```_
Manuelle Installation
```bash
Clone repository
git clone https://github.com/dirkjanm/ROADtools.git cd ROADtools
Install dependencies
pip3 install -r requirements.txt
Install ROADtools
python3 setup.py install ```_
Docker Installation
```bash
Build Docker image
git clone https://github.com/dirkjanm/ROADtools.git cd ROADtools docker build -t roadtools .
Run ROADtools in Docker
docker run -it -v $(pwd):/data roadtools ```_
Basisnutzung
Authentifizierungsmethoden
```bash
Username/password authentication
roadrecon auth -u user@domain.com -p password
Device code authentication
roadrecon auth --device-code
Access token authentication
roadrecon auth --access-token
Refresh token authentication
roadrecon auth --refresh-token
Certificate authentication
roadrecon auth --cert-thumbprint
Daten sammeln
```bash
Gather all available data
roadrecon gather
Gather specific data types
roadrecon gather --users --groups --applications
Gather with specific authentication
roadrecon gather --tokens roadtokens.json
Gather with rate limiting
roadrecon gather --rate-limit 10 ```_
Befehlsnummer
Authentication Commands
| | Command | Description | |
| --- | --- |
| | roadrecon auth
| Authenticate to Azure AD | |
| | roadrecon auth --device-code
| Use device code flow | |
| | roadrecon auth --refresh-token
| Use refresh token | |
| | roadrecon auth --access-token
| Use access token | |
Daten sammeln Befehle
| | Command | Description | |
| --- | --- |
| | roadrecon gather
| Gather Azure AD data | |
| | roadrecon gather --users
| Gather user data only | |
| | roadrecon gather --groups
| Gather group data only | |
| | roadrecon gather --applications
| Gather application data | |
| | roadrecon gather --devices
| Gather device data | |
Analysekommandos
| | Command | Description | |
| --- | --- |
| | roadrecon gui
| Start web interface | |
| | roadrecon plugin
| Run analysis plugins | |
| | roadrecon dump
| Export data to files | |
Datenerhebung
Benutzeraufzählung
```bash
Collect all users
roadrecon gather --users
Collect users with specific attributes
roadrecon gather --users --include-attributes displayName,mail,userPrincipalName
Collect guest users only
roadrecon gather --users --filter "userType eq 'Guest'"
Collect privileged users
roadrecon gather --users --filter "assignedLicenses/any(x:x/skuId eq guid'6fd2c87f-b296-42f0-b197-1e91e994b900')" ```_
Gruppenaufzählung
```bash
Collect all groups
roadrecon gather --groups
Collect security groups only
roadrecon gather --groups --filter "securityEnabled eq true"
Collect groups with members
roadrecon gather --groups --expand members
Collect administrative groups
roadrecon gather --groups --filter "displayName eq 'Global Administrators'" ```_
Antragsnummer
```bash
Collect all applications
roadrecon gather --applications
Collect service principals
roadrecon gather --servicePrincipals
Collect application permissions
roadrecon gather --applications --expand appRoles,oauth2PermissionScopes
Collect enterprise applications
roadrecon gather --servicePrincipals --filter "servicePrincipalType eq 'Application'" ```_
Gerätezählung
```bash
Collect all devices
roadrecon gather --devices
Collect managed devices
roadrecon gather --devices --filter "isManaged eq true"
Collect compliant devices
roadrecon gather --devices --filter "isCompliant eq true"
Collect device owners
roadrecon gather --devices --expand registeredOwners ```_
Erweiterte Datenerhebung
Kundenspezifische Abfragen
```bash
Custom OData filter
roadrecon gather --users --filter "department eq 'IT'"
Multiple filters
roadrecon gather --users --filter "department eq 'IT' and accountEnabled eq true"
Select specific attributes
roadrecon gather --users --select displayName,mail,department,jobTitle
Expand related objects
roadrecon gather --users --expand manager,directReports ```_
Großbetrieb
```bash
Gather all data types
roadrecon gather --all
Gather with pagination
roadrecon gather --users --top 100 --skip 0
Gather with retry logic
roadrecon gather --retry-count 3 --retry-delay 5
Parallel gathering
roadrecon gather --threads 5 ```_
Token Management
```bash
Save tokens for reuse
roadrecon auth --save-tokens tokens.json
Load saved tokens
roadrecon gather --tokens tokens.json
Refresh expired tokens
roadrecon auth --refresh-token
Web Interface Analyse
Beginn der GUI
```bash
Start web interface
roadrecon gui
Start on specific port
roadrecon gui --port 8080
Start with specific database
roadrecon gui --database roadrecon.db
Start with authentication
roadrecon gui --auth ```_
Navigation und Analyse
```bash
Access web interface
http://localhost:5000
Main sections:
- Users: User accounts and attributes
- Groups: Group memberships and roles
- Applications: App registrations and permissions
- Devices: Device information and compliance
- Roles: Administrative roles and assignments
```_
Benutzerdefinierte Abfragen in GUI
```sql -- Find users with administrative roles SELECT u.displayName, u.userPrincipalName, r.displayName as role FROM users u JOIN roleAssignments ra ON u.id = ra.principalId JOIN directoryRoles r ON ra.roleDefinitionId = r.id
-- Find applications with high privileges SELECT sp.displayName, sp.appId, p.value as permission FROM servicePrincipals sp JOIN appRoleAssignments ara ON sp.id = ara.resourceId JOIN appRoles p ON ara.appRoleId = p.id WHERE p.value LIKE '%All%'
-- Find guest users with group memberships SELECT u.displayName, u.userPrincipalName, g.displayName as groupName FROM users u JOIN groupMembers gm ON u.id = gm.memberId JOIN groups g ON gm.groupId = g.id WHERE u.userType = 'Guest' ```_
Plugin System
Verfügbare Plugins
```bash
List available plugins
roadrecon plugin --list
Run specific plugin
roadrecon plugin --name privileged-users
Run all plugins
roadrecon plugin --all
Run plugin with parameters
roadrecon plugin --name custom-plugin --param value ```_
Benutzerdefinierte Plugin Entwicklung
```python
Example plugin structure
from roadtools.roadrecon.plugins import PluginBase
class CustomPlugin(PluginBase): name = "custom-analysis" description = "Custom Azure AD analysis"
def run(self):
# Access database
users = self.db.query("SELECT * FROM users WHERE accountEnabled = 1")
# Perform analysis
results = []
for user in users:
if self.is_privileged_user(user):
results.append(\\\\{
'user': user['displayName'],
'upn': user['userPrincipalName'],
'risk': 'High'
\\\\})
return results
def is_privileged_user(self, user):
# Custom logic to identify privileged users
privileged_roles = ['Global Administrator', 'Security Administrator']
user_roles = self.get_user_roles(user['id'])
return any(role in privileged_roles for role in user_roles)
```_
Datenexport und Reporting
Exportoptionen
```bash
Export to JSON
roadrecon dump --format json --output azure_data.json
Export to CSV
roadrecon dump --format csv --output azure_data.csv
Export specific data types
roadrecon dump --users --format json --output users.json
Export with filters
roadrecon dump --users --filter "department eq 'IT'" --format csv ```_
Zollberichte
```python
Generate custom reports
import json import sqlite3
def generate_security_report(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor()
report = \\\\{
'summary': \\\\{\\\\},
'findings': [],
'recommendations': []
\\\\}
# Count users
cursor.execute("SELECT COUNT(*) FROM users WHERE accountEnabled = 1")
report['summary']['active_users'] = cursor.fetchone()[0]
# Count guest users
cursor.execute("SELECT COUNT(*) FROM users WHERE userType = 'Guest'")
report['summary']['guest_users'] = cursor.fetchone()[0]
# Find users without MFA
cursor.execute("""
SELECT displayName, userPrincipalName
FROM users
WHERE accountEnabled = 1
AND id NOT IN (
SELECT userId FROM strongAuthenticationMethods
)
""")
no_mfa_users = cursor.fetchall()
if no_mfa_users:
report['findings'].append(\\\\{
'title': 'Users without MFA',
'severity': 'High',
'count': len(no_mfa_users),
'users': no_mfa_users
\\\\})
return report
Usage
report = generate_security_report('roadrecon.db') print(json.dumps(report, indent=2)) ```_
Visualisierung
```python
Create visualizations
import matplotlib.pyplot as plt import sqlite3
def create_user_distribution_chart(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor()
# Get user distribution by department
cursor.execute("""
SELECT department, COUNT(*) as count
FROM users
WHERE department IS NOT NULL
GROUP BY department
ORDER BY count DESC
LIMIT 10
""")
data = cursor.fetchall()
departments = [row[0] for row in data]
counts = [row[1] for row in data]
plt.figure(figsize=(12, 6))
plt.bar(departments, counts)
plt.title('User Distribution by Department')
plt.xlabel('Department')
plt.ylabel('Number of Users')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('user_distribution.png')
```_
Sicherheitsanalyse
Vorrechte Eskalation Pfade
```sql -- Find potential privilege escalation paths WITH RECURSIVE privilege_paths AS ( -- Base case: direct role assignments SELECT u.displayName as user_name, u.userPrincipalName, r.displayName as role_name, 1 as depth, u.userPrincipalName as path FROM users u JOIN roleAssignments ra ON u.id = ra.principalId JOIN directoryRoles r ON ra.roleDefinitionId = r.id
UNION ALL
-- Recursive case: group memberships leading to roles
SELECT
pp.user_name,
pp.userPrincipalName,
r.displayName as role_name,
pp.depth + 1,
| pp.path | | ' -> ' | | g.displayName | | ' -> ' | | r.displayName | FROM privilege_paths pp JOIN groupMembers gm ON pp.userPrincipalName = ( SELECT userPrincipalName FROM users WHERE id = gm.memberId ) JOIN groups g ON gm.groupId = g.id JOIN roleAssignments ra ON g.id = ra.principalId JOIN directoryRoles r ON ra.roleDefinitionId = r.id WHERE pp.depth < 5 ) SELECT * FROM privilege_paths ORDER BY depth, user_name; ```_
Anwendungsberechtigungsanalyse
sql
-- Find applications with excessive permissions
SELECT
sp.displayName as app_name,
sp.appId,
COUNT(DISTINCT ara.appRoleId) as permission_count,
GROUP_CONCAT(ar.value) as permissions
FROM servicePrincipals sp
JOIN appRoleAssignments ara ON sp.id = ara.principalId
JOIN appRoles ar ON ara.appRoleId = ar.id
GROUP BY sp.id, sp.displayName, sp.appId
HAVING permission_count > 10
ORDER BY permission_count DESC;
_
Bedingte Zugriffsanalyse
```python
Analyze Conditional Access policies
def analyze_conditional_access(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor()
# Get Conditional Access policies
cursor.execute("SELECT * FROM conditionalAccessPolicies")
policies = cursor.fetchall()
analysis = \\\\{
'total_policies': len(policies),
'enabled_policies': 0,
'mfa_policies': 0,
'location_policies': 0,
'device_policies': 0
\\\\}
for policy in policies:
if policy['state'] == 'enabled':
analysis['enabled_policies'] += 1
# Check for MFA requirements
if 'mfa' in policy['grantControls'].lower():
analysis['mfa_policies'] += 1
# Check for location conditions
if policy['conditions'] and 'locations' in policy['conditions']:
analysis['location_policies'] += 1
# Check for device conditions
if policy['conditions'] and 'devices' in policy['conditions']:
analysis['device_policies'] += 1
return analysis
```_
Evasion und Stealth
Grenzwerte
```bash
Use rate limiting to avoid detection
roadrecon gather --rate-limit 5 --delay 2
Random delays between requests
roadrecon gather --random-delay 1-5
Spread requests over time
roadrecon gather --duration 3600 # 1 hour ```_
User Agent Rotation
```python
Custom user agent rotation
import random
user_agents = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' ]
def get_random_user_agent(): return random.choice(user_agents)
Use with roadrecon
roadrecon gather --user-agent "$(python3 -c 'import random; print(random.choice(["Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"]))')" ```_
Proxy-Nutzung
```bash
Use proxy for requests
roadrecon gather --proxy http://proxy:8080
Use SOCKS proxy
roadrecon gather --proxy socks5://proxy:1080
Rotate proxies
roadrecon gather --proxy-list proxies.txt ```_
Fehlerbehebung
Authentifizierungsfragen
```bash
Clear cached tokens
rm -rf ~/.roadtools/
Debug authentication
roadrecon auth --debug
Check token validity
roadrecon auth --validate-token
Manual token refresh
roadrecon auth --refresh-token
API Rate Limiting
```bash
Handle rate limiting
roadrecon gather --rate-limit 1 --retry-count 5
Monitor rate limit headers
| roadrecon gather --debug | grep -i "rate\ | limit" |
Use exponential backoff
roadrecon gather --backoff-strategy exponential ```_
Probleme der Datenerhebung
```bash
Verify permissions
roadrecon auth --check-permissions
Test connectivity
roadrecon gather --test-connection
Debug API calls
roadrecon gather --debug --verbose
Check for API changes
roadrecon gather --api-version beta ```_
Datenbankprobleme
```bash
Repair database
sqlite3 roadrecon.db "PRAGMA integrity_check;"
Backup database
cp roadrecon.db roadrecon_backup.db
Reset database
rm roadrecon.db roadrecon gather ```_
Integration mit anderen Tools
BlutHound Integration
```python
Convert ROADtools data to BloodHound format
def convert_to_bloodhound(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor()
# Get users and groups
cursor.execute("SELECT * FROM users")
users = cursor.fetchall()
cursor.execute("SELECT * FROM groups")
groups = cursor.fetchall()
# Create BloodHound JSON
bloodhound_data = \\\\{
'users': [],
'groups': [],
'computers': [],
'domains': []
\\\\}
for user in users:
bloodhound_data['users'].append(\\\\{
'ObjectIdentifier': user['id'],
'PrimaryGroupSID': user['primaryGroupId'],
'Properties': \\\\{
'name': user['userPrincipalName'],
'displayname': user['displayName'],
'enabled': user['accountEnabled']
\\\\}
\\\\})
return bloodhound_data
```_
Integration von PowerShell
```powershell
Use ROADtools data in PowerShell
$roadData = Get-Content -Path "azure_data.json"|ConvertFrom-Json
Find privileged users
$privilegedUsers = $roadData.users|Where-Object \\{ $_.assignedRoles -contains "Global Administrator" \\}
Export to CSV
$privilegedUsers|Export-Csv -Path "privileged_users.csv" -NoTypeInformation ```_
Ressourcen
- ROADtools GitHub Repository
- ROADtools Dokumentation
- [Dirk-Jan Mollema Blog](_LINK_5__ -%20(__LINK_5___)
- Angriff und Verteidigung Azure AD
--
*Dieses Betrügereiblatt bietet eine umfassende Referenz für die Verwendung von ROADtools. Stellen Sie immer sicher, dass Sie eine ordnungsgemäße Genehmigung haben, bevor Sie Azure AD Bewertungen durchführen. *