Skip to content

Commit f3fc702

Browse files
Merge pull request #760 from doyensec:omnilab-ats-exposed-ui
PiperOrigin-RevId: 842303731 Change-Id: Ica960a231a11881e3079b5808ee3095d16a108a6
2 parents 107447f + 1bcc05f commit f3fc702

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# proto-file: proto/templated_plugin.proto
2+
# proto-message: TemplatedPlugin
3+
4+
###############
5+
# PLUGIN INFO #
6+
###############
7+
8+
info: {
9+
type: VULN_DETECTION
10+
name: "OmnilabATS_ExposedUI"
11+
author: "Giacomo Coluccelli <giacomo@doyensec.com>"
12+
version: "0.1"
13+
}
14+
15+
finding: {
16+
main_id: {
17+
publisher: "GOOGLE"
18+
value: "OMNILAB_ATS_EXPOSED_UI"
19+
}
20+
title: "Exposed Omnilab Android Test Station instance"
21+
description: "OmniLab ATS (Android Test Station) is publicly accessible without authentication. This exposes device management, test execution capabilities, and potentially sensitive configuration data. Attackers can access connected Android devices, execute arbitrary tests, view test results, and manage the testing infrastructure."
22+
recommendation:
23+
"1. Implement authentication using a reverse proxy (nginx/Apache) with HTTP Basic Auth or OAuth"
24+
"2. Restrict network access using firewall rules to trusted IP ranges only"
25+
"3. Deploy behind VPN for remote access"
26+
"4. Use SSH tunneling for administrative access"
27+
"5. Enable TLS/HTTPS with valid certificates"
28+
severity: CRITICAL
29+
}
30+
31+
###########
32+
# ACTIONS #
33+
###########
34+
35+
actions {
36+
name: "omnilab_ats_exposed_ui_fingerprint"
37+
http_request: {
38+
method: GET
39+
uri: "/"
40+
response: {
41+
http_status: 200
42+
expect_all: {
43+
conditions: [
44+
{ body {} contains: "Android Test Station" },
45+
{ body {} contains: "OmniLab" }
46+
]
47+
}
48+
}
49+
}
50+
}
51+
52+
actions {
53+
name: "omnilab_ats_exposed_ui_create_build"
54+
http_request: {
55+
method: POST
56+
uri: "/_ah/api/mtt/v1/builds"
57+
headers: [
58+
{ name: "Content-Type" value: "application/json" }
59+
]
60+
data: "{\"name\":\"Tsunami Build\",\"fingerprint\":\"Tsunami Fingerprint\",\"file_url\":\"\",\"size\":0,\"labels\":[]}"
61+
response: {
62+
http_status: 200
63+
expect_all: {
64+
conditions: { body {} contains: "\"id\":"}
65+
}
66+
extract_all: {
67+
patterns: { from_body: {} regexp: "\"id\": \"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\"" variable_name: "BUILD_ID" }
68+
}
69+
}
70+
}
71+
cleanup_actions: "omnilab_ats_exposed_ui_delete_build"
72+
}
73+
74+
actions {
75+
name: "omnilab_ats_exposed_ui_delete_build"
76+
http_request: {
77+
method: DELETE
78+
uri: "/_ah/api/mtt/v1/builds?build_ids={{ BUILD_ID }}"
79+
response: {
80+
http_status: 204
81+
}
82+
}
83+
}
84+
85+
actions {
86+
name: "omnilab_ats_exposed_ui_verify_build_creation"
87+
http_request: {
88+
method: GET
89+
uri: "/_ah/api/mtt/v1/builds/{{ BUILD_ID }}"
90+
response: {
91+
http_status: 200
92+
expect_all: {
93+
conditions: [
94+
{ body {} contains: "\"fingerprint\": \"Tsunami Fingerprint\"" },
95+
{ body {} contains: "\"id\": \"{{ BUILD_ID }}\"" },
96+
{ body {} contains: "\"name\": \"Tsunami Build\"" }
97+
]
98+
}
99+
}
100+
}
101+
}
102+
103+
#############
104+
# WORKFLOWS #
105+
#############
106+
107+
workflows: {
108+
actions: [
109+
"omnilab_ats_exposed_ui_fingerprint",
110+
"omnilab_ats_exposed_ui_create_build",
111+
"omnilab_ats_exposed_ui_verify_build_creation"
112+
]
113+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# proto-file: proto/templated_plugin_tests.proto
2+
# proto-message: TemplatedPluginTests
3+
4+
config: {
5+
tested_plugin: "OmnilabATS_ExposedUI"
6+
}
7+
8+
tests: {
9+
name: "whenNotATS_returnsFalse"
10+
expect_vulnerability: false
11+
12+
mock_http_server: {
13+
mock_responses: [
14+
{
15+
uri: "/"
16+
status: 200
17+
}
18+
]
19+
}
20+
}
21+
22+
tests: {
23+
name: "whenATSAndVulnerable_returnsTrue"
24+
expect_vulnerability: true
25+
26+
mock_http_server: {
27+
mock_responses: [
28+
{
29+
uri: "/"
30+
status: 200
31+
body_content: "<html><head><title>Android Test Station</title></head><body><mtt></mtt><script>window.APP_DATA = {isOmniLabBased: \"False\" === \"True\",};</script></body></html>"
32+
},
33+
{
34+
uri: "/_ah/api/mtt/v1/builds"
35+
status: 200
36+
body_content: "{\"fingerprint\": \"Tsunami Fingerprint\",\"id\": \"0a0fd6f0-8241-4f76-abfc-493a245b37fd\",\"name\": \"Tsunami Build\"}"
37+
},
38+
{
39+
uri: "/_ah/api/mtt/v1/builds/0a0fd6f0-8241-4f76-abfc-493a245b37fd"
40+
status: 200
41+
body_content:"{\"fingerprint\": \"Tsunami Fingerprint\",\"id\": \"0a0fd6f0-8241-4f76-abfc-493a245b37fd\",\"name\": \"Tsunami Build\"}"
42+
},
43+
{
44+
uri: "/_ah/api/mtt/v1/builds?build_ids=0a0fd6f0-8241-4f76-abfc-493a245b37fd"
45+
status: 204
46+
}
47+
]
48+
}
49+
}
50+
51+
tests: {
52+
name: "whenATSAndNotVulnerable_returnsFalse"
53+
expect_vulnerability: false
54+
55+
mock_http_server: {
56+
mock_responses: [
57+
{
58+
uri: "/"
59+
status: 401
60+
body_content: "<html><head><title>401 Authorization Required</title></head><body></body></html>"
61+
}
62+
]
63+
}
64+
}

0 commit comments

Comments
 (0)