ai_root_shield 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -4
- data/README.md +191 -14
- data/bindings/python/README.md +304 -0
- data/bindings/python/ai_root_shield.py +438 -0
- data/bindings/python/setup.py +65 -0
- data/examples/device_logs/android_safetynet_device.json +148 -0
- data/examples/device_logs/ios_jailbroken_device.json +172 -0
- data/exe/ai_root_shield +220 -7
- data/lib/ai_root_shield/ci_cd/security_test_module.rb +743 -0
- data/lib/ai_root_shield/dashboard/web_dashboard.rb +441 -0
- data/lib/ai_root_shield/enterprise/alert_system.rb +601 -0
- data/lib/ai_root_shield/enterprise/hybrid_detection_engine.rb +650 -0
- data/lib/ai_root_shield/enterprise/performance_optimizer.rb +613 -0
- data/lib/ai_root_shield/enterprise/policy_manager.rb +637 -0
- data/lib/ai_root_shield/integrations/siem_connector.rb +695 -0
- data/lib/ai_root_shield/platform/android_security_module.rb +263 -0
- data/lib/ai_root_shield/platform/hardware_security_analyzer.rb +452 -0
- data/lib/ai_root_shield/platform/ios_security_module.rb +513 -0
- data/lib/ai_root_shield/platform/unified_report_generator.rb +613 -0
- data/lib/ai_root_shield/version.rb +1 -1
- data/lib/ai_root_shield.rb +152 -1
- data/security_test_artifacts/security_report.json +124 -0
- data/security_test_artifacts/security_results.sarif +16 -0
- data/security_test_artifacts/security_tests.xml +3 -0
- metadata +20 -1
@@ -0,0 +1,172 @@
|
|
1
|
+
{
|
2
|
+
"platform": "ios",
|
3
|
+
"timestamp": 1640995200,
|
4
|
+
"device_info": {
|
5
|
+
"model": "iPhone 13 Pro",
|
6
|
+
"manufacturer": "Apple",
|
7
|
+
"os_version": "15.6.1",
|
8
|
+
"device_identifier": "iPhone14,3"
|
9
|
+
},
|
10
|
+
"code_signing": {
|
11
|
+
"mainBundleSigned": false,
|
12
|
+
"embeddedProvisioning": true,
|
13
|
+
"teamIdentifier": "ABCD123456",
|
14
|
+
"codeDirectoryHash": "sha256:1234567890abcdef...",
|
15
|
+
"entitlementsValid": false,
|
16
|
+
"signatureVersion": 2,
|
17
|
+
"certificateChainValid": false,
|
18
|
+
"certificate": {
|
19
|
+
"isDevelopment": true,
|
20
|
+
"isDistribution": false,
|
21
|
+
"isEnterprise": false,
|
22
|
+
"isAdhoc": false,
|
23
|
+
"expirationDate": "2024-12-31T23:59:59Z",
|
24
|
+
"issuer": "Apple Development"
|
25
|
+
}
|
26
|
+
},
|
27
|
+
"sandbox": {
|
28
|
+
"containerIntegrity": false,
|
29
|
+
"fileAccessViolations": [
|
30
|
+
"/private/var/mobile/Library/Preferences",
|
31
|
+
"/Applications/Cydia.app"
|
32
|
+
],
|
33
|
+
"networkAccessViolations": [],
|
34
|
+
"ipcViolations": ["com.apple.springboard"],
|
35
|
+
"entitlementViolations": ["get-task-allow"],
|
36
|
+
"sandboxProfileValid": false
|
37
|
+
},
|
38
|
+
"dyld": {
|
39
|
+
"loadedLibraries": [
|
40
|
+
"/usr/lib/libSystem.B.dylib",
|
41
|
+
"/Library/MobileSubstrate/MobileSubstrate.dylib",
|
42
|
+
"/Library/MobileSubstrate/DynamicLibraries/PreferenceLoader.dylib",
|
43
|
+
"/usr/lib/substitute-inserter.dylib"
|
44
|
+
],
|
45
|
+
"injectedLibraries": [
|
46
|
+
"/Library/MobileSubstrate/MobileSubstrate.dylib",
|
47
|
+
"/usr/lib/substitute-inserter.dylib"
|
48
|
+
],
|
49
|
+
"runtimeModifications": [
|
50
|
+
{
|
51
|
+
"library": "MobileSubstrate",
|
52
|
+
"function": "MSHookFunction",
|
53
|
+
"target": "objc_msgSend"
|
54
|
+
}
|
55
|
+
],
|
56
|
+
"methodSwizzling": {
|
57
|
+
"detected": true,
|
58
|
+
"swizzledMethods": [
|
59
|
+
"UIApplication.openURL:",
|
60
|
+
"NSFileManager.fileExistsAtPath:"
|
61
|
+
]
|
62
|
+
}
|
63
|
+
},
|
64
|
+
"hardware_security": {
|
65
|
+
"secureEnclaveAvailable": true,
|
66
|
+
"touchIdAvailable": true,
|
67
|
+
"faceIdAvailable": false,
|
68
|
+
"processorType": "A15 Bionic",
|
69
|
+
"secureBootChain": true,
|
70
|
+
"uidAvailable": true,
|
71
|
+
"gidAvailable": true,
|
72
|
+
"biometricKeysProtected": true,
|
73
|
+
"keychainHardwareProtection": true,
|
74
|
+
"sepFirmwareVersion": "4.0.0",
|
75
|
+
"biometrics": {
|
76
|
+
"touchIdEnrolled": true,
|
77
|
+
"faceIdEnrolled": false,
|
78
|
+
"biometricChangesDetected": false,
|
79
|
+
"hardwareTamperDetected": false
|
80
|
+
}
|
81
|
+
},
|
82
|
+
"system_integrity": {
|
83
|
+
"systemVersionAuthentic": false,
|
84
|
+
"kernelIntegrity": false,
|
85
|
+
"amfiEnabled": false,
|
86
|
+
"sipEnabled": false,
|
87
|
+
"codeInjectionProtection": false,
|
88
|
+
"libraryValidation": false,
|
89
|
+
"runtimeProtections": []
|
90
|
+
},
|
91
|
+
"file_system": {
|
92
|
+
"files": [
|
93
|
+
{
|
94
|
+
"path": "/Applications/Cydia.app",
|
95
|
+
"exists": true,
|
96
|
+
"permissions": "755"
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"path": "/Library/MobileSubstrate/MobileSubstrate.dylib",
|
100
|
+
"exists": true,
|
101
|
+
"permissions": "755"
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"path": "/usr/bin/ssh",
|
105
|
+
"exists": true,
|
106
|
+
"permissions": "755"
|
107
|
+
},
|
108
|
+
{
|
109
|
+
"path": "/private/var/lib/cydia",
|
110
|
+
"exists": true,
|
111
|
+
"permissions": "755"
|
112
|
+
},
|
113
|
+
{
|
114
|
+
"path": "/bin/bash",
|
115
|
+
"exists": true,
|
116
|
+
"permissions": "755"
|
117
|
+
}
|
118
|
+
]
|
119
|
+
},
|
120
|
+
"url_schemes": [
|
121
|
+
"cydia://",
|
122
|
+
"sileo://",
|
123
|
+
"zbra://",
|
124
|
+
"filza://",
|
125
|
+
"activator://"
|
126
|
+
],
|
127
|
+
"symbolic_links": [
|
128
|
+
{
|
129
|
+
"source": "/Applications",
|
130
|
+
"target": "/var/stash/Applications"
|
131
|
+
},
|
132
|
+
{
|
133
|
+
"source": "/usr/include",
|
134
|
+
"target": "/var/stash/usr/include"
|
135
|
+
}
|
136
|
+
],
|
137
|
+
"fork_test": {
|
138
|
+
"forkAllowed": true
|
139
|
+
},
|
140
|
+
"system_calls": {
|
141
|
+
"ptraceDetected": true,
|
142
|
+
"sysctlBypass": true,
|
143
|
+
"dlopenHooking": true
|
144
|
+
},
|
145
|
+
"runtime_manipulation": {
|
146
|
+
"methodSwizzlingDetected": true,
|
147
|
+
"classDumpDetected": true,
|
148
|
+
"runtimeInjection": true
|
149
|
+
},
|
150
|
+
"network": {
|
151
|
+
"proxy_enabled": false,
|
152
|
+
"vpn_active": false,
|
153
|
+
"custom_certificates": [],
|
154
|
+
"tls_version": "1.3"
|
155
|
+
},
|
156
|
+
"risk_score": 85,
|
157
|
+
"factors": [
|
158
|
+
"IOS_JAILBREAK_FILES_DETECTED",
|
159
|
+
"IOS_JAILBREAK_URL_SCHEMES_DETECTED",
|
160
|
+
"IOS_JAILBREAK_LIBRARIES_DETECTED",
|
161
|
+
"IOS_SANDBOX_VIOLATIONS_DETECTED",
|
162
|
+
"IOS_FORK_RESTRICTIONS_BYPASSED",
|
163
|
+
"IOS_MAIN_BUNDLE_NOT_SIGNED",
|
164
|
+
"IOS_INVALID_CERTIFICATE_CHAIN",
|
165
|
+
"IOS_DEVELOPMENT_CERTIFICATE",
|
166
|
+
"IOS_DYLD_INJECTION_DETECTED",
|
167
|
+
"IOS_HOOKING_FRAMEWORKS_DETECTED",
|
168
|
+
"IOS_AMFI_DISABLED",
|
169
|
+
"IOS_SIP_DISABLED",
|
170
|
+
"IOS_LIBRARY_VALIDATION_DISABLED"
|
171
|
+
]
|
172
|
+
}
|
data/exe/ai_root_shield
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require "optparse"
|
5
5
|
require "json"
|
6
|
+
require "fileutils"
|
6
7
|
require_relative "../lib/ai_root_shield"
|
7
8
|
|
8
9
|
# Command line interface for AI Root Shield
|
@@ -24,13 +25,37 @@ class AiRootShieldCLI
|
|
24
25
|
enable_certificate_pinning: false,
|
25
26
|
enable_proxy_detection: false,
|
26
27
|
target_ip: nil,
|
27
|
-
target_url: nil
|
28
|
+
target_url: nil,
|
29
|
+
# v0.5.0 new options
|
30
|
+
platform: nil,
|
31
|
+
safetynet_api_key: nil,
|
32
|
+
package_name: nil,
|
33
|
+
ci_mode: false,
|
34
|
+
artifacts_path: './security_test_artifacts',
|
35
|
+
siem_platform: nil,
|
36
|
+
siem_endpoint: nil,
|
37
|
+
siem_token: nil,
|
38
|
+
start_dashboard: false,
|
39
|
+
dashboard_port: 4567,
|
40
|
+
generate_ci_config: nil,
|
41
|
+
enable_unified_reporting: false
|
28
42
|
}
|
29
43
|
end
|
30
44
|
|
31
45
|
def run(args)
|
32
46
|
parse_options(args)
|
33
47
|
|
48
|
+
# Handle special commands first
|
49
|
+
if @options[:start_dashboard]
|
50
|
+
start_dashboard
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
if @options[:generate_ci_config]
|
55
|
+
generate_ci_config
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
34
59
|
if args.empty?
|
35
60
|
puts "Error: Please provide a device logs file path"
|
36
61
|
puts "Usage: ai_root_shield [options] <device_logs.json>"
|
@@ -45,6 +70,15 @@ class AiRootShieldCLI
|
|
45
70
|
end
|
46
71
|
|
47
72
|
begin
|
73
|
+
# Configure SIEM if provided
|
74
|
+
if @options[:siem_platform] && @options[:siem_endpoint] && @options[:siem_token]
|
75
|
+
puts "Configuring SIEM integration (#{@options[:siem_platform]})..." if @options[:verbose]
|
76
|
+
AiRootShield.configure_siem(@options[:siem_platform].to_sym, {
|
77
|
+
api_endpoint: @options[:siem_endpoint],
|
78
|
+
api_key: @options[:siem_token]
|
79
|
+
})
|
80
|
+
end
|
81
|
+
|
48
82
|
# Configure enterprise policy if provided
|
49
83
|
if @options[:policy_file]
|
50
84
|
puts "Loading enterprise policy from #{@options[:policy_file]}..." if @options[:verbose]
|
@@ -83,7 +117,23 @@ class AiRootShieldCLI
|
|
83
117
|
sleep(@options[:rasp_monitoring_time])
|
84
118
|
end
|
85
119
|
|
86
|
-
|
120
|
+
# Run analysis based on mode
|
121
|
+
if @options[:ci_mode]
|
122
|
+
result = run_ci_cd_analysis(device_logs_path)
|
123
|
+
elsif @options[:platform]
|
124
|
+
result = run_platform_specific_analysis(device_logs_path)
|
125
|
+
else
|
126
|
+
result = AiRootShield.scan_device_with_config(device_logs_path, @options)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Send to SIEM if configured
|
130
|
+
if @options[:siem_platform]
|
131
|
+
puts "Sending results to SIEM..." if @options[:verbose]
|
132
|
+
AiRootShield.send_to_siem(result, {
|
133
|
+
cli_version: AiRootShield::VERSION,
|
134
|
+
scan_timestamp: Time.now.utc.iso8601
|
135
|
+
})
|
136
|
+
end
|
87
137
|
|
88
138
|
# Add RASP status to result if enabled
|
89
139
|
if @options[:enable_rasp_protection] && AiRootShield.rasp_active?
|
@@ -184,6 +234,70 @@ class AiRootShieldCLI
|
|
184
234
|
@options[:target_url] = url
|
185
235
|
end
|
186
236
|
|
237
|
+
# v0.5.0 Platform-specific options
|
238
|
+
opts.separator ""
|
239
|
+
opts.separator "Platform-specific Analysis (v0.5.0):"
|
240
|
+
|
241
|
+
opts.on("--platform PLATFORM", ["android", "ios"], "Platform-specific analysis (android, ios)") do |platform|
|
242
|
+
@options[:platform] = platform
|
243
|
+
end
|
244
|
+
|
245
|
+
opts.on("--safetynet-key KEY", "Google SafetyNet API key for Android analysis") do |key|
|
246
|
+
@options[:safetynet_api_key] = key
|
247
|
+
end
|
248
|
+
|
249
|
+
opts.on("--package-name NAME", "Android package name for analysis") do |name|
|
250
|
+
@options[:package_name] = name
|
251
|
+
end
|
252
|
+
|
253
|
+
opts.on("--unified-report", "Generate unified cross-platform report") do
|
254
|
+
@options[:enable_unified_reporting] = true
|
255
|
+
end
|
256
|
+
|
257
|
+
# CI/CD Integration options
|
258
|
+
opts.separator ""
|
259
|
+
opts.separator "CI/CD Integration (v0.5.0):"
|
260
|
+
|
261
|
+
opts.on("--ci-mode", "Run in CI/CD mode with test artifacts") do
|
262
|
+
@options[:ci_mode] = true
|
263
|
+
end
|
264
|
+
|
265
|
+
opts.on("--artifacts-path PATH", "Path for CI/CD test artifacts (default: ./security_test_artifacts)") do |path|
|
266
|
+
@options[:artifacts_path] = path
|
267
|
+
end
|
268
|
+
|
269
|
+
opts.on("--generate-ci-config PLATFORM", ["github", "gitlab", "jenkins", "azure"], "Generate CI config for platform") do |platform|
|
270
|
+
@options[:generate_ci_config] = platform
|
271
|
+
end
|
272
|
+
|
273
|
+
# SIEM Integration options
|
274
|
+
opts.separator ""
|
275
|
+
opts.separator "SIEM Integration (v0.5.0):"
|
276
|
+
|
277
|
+
opts.on("--siem-platform PLATFORM", ["splunk", "elastic", "qradar", "sentinel", "datadog", "chronicle", "arcsight"], "SIEM platform") do |platform|
|
278
|
+
@options[:siem_platform] = platform
|
279
|
+
end
|
280
|
+
|
281
|
+
opts.on("--siem-endpoint URL", "SIEM API endpoint URL") do |url|
|
282
|
+
@options[:siem_endpoint] = url
|
283
|
+
end
|
284
|
+
|
285
|
+
opts.on("--siem-token TOKEN", "SIEM API authentication token") do |token|
|
286
|
+
@options[:siem_token] = token
|
287
|
+
end
|
288
|
+
|
289
|
+
# Dashboard options
|
290
|
+
opts.separator ""
|
291
|
+
opts.separator "Dashboard (v0.5.0):"
|
292
|
+
|
293
|
+
opts.on("--start-dashboard", "Start web dashboard server") do
|
294
|
+
@options[:start_dashboard] = true
|
295
|
+
end
|
296
|
+
|
297
|
+
opts.on("--dashboard-port PORT", Integer, "Dashboard port (default: 4567)") do |port|
|
298
|
+
@options[:dashboard_port] = port
|
299
|
+
end
|
300
|
+
|
187
301
|
opts.on("-h", "--help", "Show this help message") do
|
188
302
|
puts opts
|
189
303
|
exit
|
@@ -280,14 +394,113 @@ class AiRootShieldCLI
|
|
280
394
|
end
|
281
395
|
|
282
396
|
def output_summary_format(result)
|
283
|
-
|
397
|
+
# Handle unified report format
|
398
|
+
if result[:executive_summary]
|
399
|
+
risk_level = result[:executive_summary][:overall_risk_level]
|
400
|
+
security_score = result[:executive_summary][:security_posture_score]
|
401
|
+
threat_count = result[:executive_summary][:critical_findings]&.length || 0
|
402
|
+
|
403
|
+
puts "Risk Level: #{risk_level} (Security Score: #{security_score}/100)"
|
404
|
+
puts "Threats: #{threat_count} critical findings detected"
|
405
|
+
|
406
|
+
if result[:executive_summary][:key_recommendations]&.any?
|
407
|
+
puts "Primary Concerns: #{result[:executive_summary][:key_recommendations].first(3).join(', ')}"
|
408
|
+
end
|
409
|
+
else
|
410
|
+
# Handle regular analysis format
|
411
|
+
risk_level = AiRootShield::RiskCalculator.risk_level_description(result[:risk_score])
|
412
|
+
|
413
|
+
puts "Risk Level: #{risk_level} (#{result[:risk_score]}/100)"
|
414
|
+
puts "Threats: #{result[:factors]&.length || 0} detected"
|
415
|
+
|
416
|
+
if result[:factors]&.any?
|
417
|
+
puts "Primary Concerns: #{result[:factors].first(3).join(', ')}"
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# v0.5.0 New Methods
|
423
|
+
def run_platform_specific_analysis(device_logs_path)
|
424
|
+
puts "Running #{@options[:platform]} platform-specific analysis..." if @options[:verbose]
|
284
425
|
|
285
|
-
|
286
|
-
|
426
|
+
case @options[:platform]
|
427
|
+
when 'android'
|
428
|
+
config = {}
|
429
|
+
config[:safetynet_api_key] = @options[:safetynet_api_key] if @options[:safetynet_api_key]
|
430
|
+
config[:package_name] = @options[:package_name] if @options[:package_name]
|
431
|
+
|
432
|
+
result = AiRootShield.analyze_android_device(device_logs_path, config)
|
433
|
+
when 'ios'
|
434
|
+
result = AiRootShield.analyze_ios_device(device_logs_path)
|
435
|
+
else
|
436
|
+
raise "Unsupported platform: #{@options[:platform]}"
|
437
|
+
end
|
287
438
|
|
288
|
-
if
|
289
|
-
puts "
|
439
|
+
if @options[:enable_unified_reporting]
|
440
|
+
puts "Generating unified cross-platform report..." if @options[:verbose]
|
441
|
+
case @options[:platform]
|
442
|
+
when 'android'
|
443
|
+
unified_result = AiRootShield.generate_unified_report(android_results: result)
|
444
|
+
when 'ios'
|
445
|
+
unified_result = AiRootShield.generate_unified_report(ios_results: result)
|
446
|
+
end
|
447
|
+
return unified_result
|
290
448
|
end
|
449
|
+
|
450
|
+
result
|
451
|
+
end
|
452
|
+
|
453
|
+
def run_ci_cd_analysis(device_logs_path)
|
454
|
+
puts "Running CI/CD security analysis..." if @options[:verbose]
|
455
|
+
|
456
|
+
# Create artifacts directory
|
457
|
+
Dir.mkdir(@options[:artifacts_path]) unless Dir.exist?(@options[:artifacts_path])
|
458
|
+
|
459
|
+
# Run CI/CD tests
|
460
|
+
result = AiRootShield.run_ci_cd_tests(device_logs_path, {
|
461
|
+
artifacts_path: @options[:artifacts_path],
|
462
|
+
verbose: @options[:verbose]
|
463
|
+
})
|
464
|
+
|
465
|
+
puts "CI/CD test artifacts saved to: #{@options[:artifacts_path]}" if @options[:verbose]
|
466
|
+
result
|
467
|
+
end
|
468
|
+
|
469
|
+
def start_dashboard
|
470
|
+
puts "Starting AI Root Shield Dashboard on port #{@options[:dashboard_port]}..."
|
471
|
+
puts "Dashboard will be available at: http://localhost:#{@options[:dashboard_port]}"
|
472
|
+
puts "Press Ctrl+C to stop the dashboard"
|
473
|
+
|
474
|
+
begin
|
475
|
+
AiRootShield.start_dashboard(@options[:dashboard_port])
|
476
|
+
rescue Interrupt
|
477
|
+
puts "\nDashboard stopped."
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def generate_ci_config
|
482
|
+
puts "Generating CI/CD configuration for #{@options[:generate_ci_config]}..."
|
483
|
+
|
484
|
+
config_content = AiRootShield.generate_ci_config(@options[:generate_ci_config].to_sym)
|
485
|
+
|
486
|
+
filename = case @options[:generate_ci_config]
|
487
|
+
when 'github'
|
488
|
+
'.github/workflows/security-scan.yml'
|
489
|
+
when 'gitlab'
|
490
|
+
'.gitlab-ci.yml'
|
491
|
+
when 'jenkins'
|
492
|
+
'Jenkinsfile'
|
493
|
+
when 'azure'
|
494
|
+
'azure-pipelines.yml'
|
495
|
+
end
|
496
|
+
|
497
|
+
# Create directory if needed
|
498
|
+
dir = File.dirname(filename)
|
499
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir) || dir == '.'
|
500
|
+
|
501
|
+
File.write(filename, config_content)
|
502
|
+
puts "CI/CD configuration saved to: #{filename}"
|
503
|
+
puts "Please review and customize the configuration as needed."
|
291
504
|
end
|
292
505
|
end
|
293
506
|
|