Improve view bypass lab before and after flow
Some checks failed
Repo Quality / structure (push) Has been cancelled
Some checks failed
Repo Quality / structure (push) Has been cancelled
This commit is contained in:
@@ -12,6 +12,7 @@ Before Oracle Deep Data Security, a legacy view can expose rows that should be p
|
|||||||
|
|
||||||
- `emma`: account owner.
|
- `emma`: account owner.
|
||||||
- `marvin`: account owner.
|
- `marvin`: account owner.
|
||||||
|
- `erik`: account owner.
|
||||||
|
|
||||||
## Where To Run The Commands
|
## Where To Run The Commands
|
||||||
|
|
||||||
@@ -49,15 +50,25 @@ sql "<connect_string>"
|
|||||||
@scenarios/04-view-bypass-mac/sql/02_identities.sql
|
@scenarios/04-view-bypass-mac/sql/02_identities.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Query the legacy view:
|
4. Connect as `emma` and query both access paths:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sql 'emma/Welcome1_DDS!@ddslab_tunnel'
|
||||||
|
```
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
|
ALTER SESSION SET CURRENT_SCHEMA = ADMIN;
|
||||||
|
|
||||||
|
SELECT account_id, account_name, owner_name, region, balance
|
||||||
|
FROM dds_mac_accounts
|
||||||
|
ORDER BY account_id;
|
||||||
|
|
||||||
SELECT account_id, account_name, owner_name, region, balance
|
SELECT account_id, account_name, owner_name, region, balance
|
||||||
FROM dds_mac_accounts_view
|
FROM dds_mac_accounts_view
|
||||||
ORDER BY account_id;
|
ORDER BY account_id;
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected result before protection: the view may show accounts owned by other users.
|
Expected result before protection: both direct table access and the legacy view may show accounts owned by other users.
|
||||||
|
|
||||||
## Step By Step - After, With Deep Data Security
|
## Step By Step - After, With Deep Data Security
|
||||||
|
|
||||||
@@ -73,12 +84,13 @@ Expected result before protection: the view may show accounts owned by other use
|
|||||||
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Repeat the test by simulating `emma` and `marvin`.
|
3. Repeat the test by simulating `emma`, `marvin`, and `erik`.
|
||||||
|
|
||||||
Expected result after protection:
|
Expected result after protection:
|
||||||
|
|
||||||
- The table returns only the authorized account.
|
- The table returns only the authorized account.
|
||||||
- The view returns the same authorized subset.
|
- The view returns the same authorized subset.
|
||||||
|
- `emma` sees `Account Alpha`, `marvin` sees `Account Beta`, and `erik` sees `Account Gamma`.
|
||||||
- The alternate access path no longer works as a bypass.
|
- The alternate access path no longer works as a bypass.
|
||||||
|
|
||||||
## Optional Automated Execution
|
## Optional Automated Execution
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ This workshop demonstrates why access rules should be enforced on the protected
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `emma` | Account owner | Only accounts owned by Emma. |
|
| `emma` | Account owner | Only accounts owned by Emma. |
|
||||||
| `marvin` | Account owner | Only accounts owned by Marvin. |
|
| `marvin` | Account owner | Only accounts owned by Marvin. |
|
||||||
|
| `erik` | Account owner | Only accounts owned by Erik. |
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
@@ -75,12 +76,43 @@ The script creates:
|
|||||||
```sql
|
```sql
|
||||||
CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!";
|
CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!";
|
||||||
CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!";
|
CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!";
|
||||||
|
CREATE END USER erik IDENTIFIED BY "Welcome1_DDS!";
|
||||||
CREATE DATA ROLE account_owner_role;
|
CREATE DATA ROLE account_owner_role;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Lab 2 - Demonstrate The View Bypass Risk
|
## Lab 2 - Demonstrate The View Bypass Risk
|
||||||
|
|
||||||
### Task 2.1 - Query The Legacy View
|
### Task 2.1 - Connect As Emma Before DDS
|
||||||
|
|
||||||
|
Exit the administrator session:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
Connect as Emma:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sql 'emma/Welcome1_DDS!@ddslab_tunnel'
|
||||||
|
```
|
||||||
|
|
||||||
|
Emma represents an account owner. Before DDS enforcement, she still has a broad legacy role, so this section demonstrates why view-based controls and object grants can be risky.
|
||||||
|
|
||||||
|
### Task 2.2 - Query The Base Table Directly Before DDS
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER SESSION SET CURRENT_SCHEMA = ADMIN;
|
||||||
|
|
||||||
|
SELECT account_id, account_name, owner_name, region, balance
|
||||||
|
FROM dds_mac_accounts
|
||||||
|
ORDER BY account_id;
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected result before DDS: Emma can see `Account Alpha`, `Account Beta`, and `Account Gamma`, even though only `Account Alpha` belongs to her.
|
||||||
|
|
||||||
|
This is the direct table access path.
|
||||||
|
|
||||||
|
### Task 2.3 - Query The Legacy View Before DDS
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SELECT account_id, account_name, owner_name, region, balance
|
SELECT account_id, account_name, owner_name, region, balance
|
||||||
@@ -88,11 +120,34 @@ FROM dds_mac_accounts_view
|
|||||||
ORDER BY account_id;
|
ORDER BY account_id;
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected result before DDS: the view may expose accounts belonging to multiple owners.
|
Expected result before DDS: the view also returns accounts owned by multiple users.
|
||||||
|
|
||||||
|
This is the alternate access path. The important point is not that the view itself is bad; the risk is relying on a specific access path as the only security boundary.
|
||||||
|
|
||||||
|
### Customer Message
|
||||||
|
|
||||||
|
Before DDS, Emma can reach the same overexposed data through both paths:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Direct table query -> all accounts
|
||||||
|
Legacy view query -> all accounts
|
||||||
|
```
|
||||||
|
|
||||||
|
The business rule "Emma should only see Emma's account" is not being enforced at the protected data boundary yet.
|
||||||
|
|
||||||
## Lab 3 - Apply Oracle Deep Data Security
|
## Lab 3 - Apply Oracle Deep Data Security
|
||||||
|
|
||||||
### Task 3.1 - Apply Data Grants
|
### Task 3.1 - Reconnect As ADMIN
|
||||||
|
|
||||||
|
```sql
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sql admin@ddslab_tunnel
|
||||||
|
```
|
||||||
|
|
||||||
|
### Task 3.2 - Apply Data Grants
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
@scenarios/04-view-bypass-mac/sql/03_data_grants.sql
|
@scenarios/04-view-bypass-mac/sql/03_data_grants.sql
|
||||||
@@ -110,9 +165,17 @@ CREATE OR REPLACE DATA GRANT mac_account_owner
|
|||||||
|
|
||||||
This filters accounts to the authenticated owner. The script enables DDS on `DDS_MAC_ACCOUNTS`.
|
This filters accounts to the authenticated owner. The script enables DDS on `DDS_MAC_ACCOUNTS`.
|
||||||
|
|
||||||
|
In this lab, the predicate compares the account owner with the active DDS end-user context:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
WHERE UPPER(owner_name) = ORA_END_USER_CONTEXT.username
|
||||||
|
```
|
||||||
|
|
||||||
|
That means Emma, Marvin, and Erik can run the same SQL, but the database returns different rows for each persona.
|
||||||
|
|
||||||
## Lab 4 - Validate Table And View Access
|
## Lab 4 - Validate Table And View Access
|
||||||
|
|
||||||
### Task 4.1 - Test Emma
|
### Task 4.1 - Test Emma After DDS
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
exit
|
exit
|
||||||
@@ -126,9 +189,18 @@ sql 'emma/Welcome1_DDS!@ddslab_tunnel'
|
|||||||
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected result: Emma sees only her authorized account from both table and view paths.
|
Expected result: Emma sees only `Account Alpha` from both table and view paths.
|
||||||
|
|
||||||
### Task 4.2 - Test Marvin
|
The same two access paths are tested again:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Direct table query -> only Account Alpha
|
||||||
|
Legacy view query -> only Account Alpha
|
||||||
|
```
|
||||||
|
|
||||||
|
The SQL did not become smarter. The database security boundary became mandatory.
|
||||||
|
|
||||||
|
### Task 4.2 - Quick Validation With Marvin
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
exit
|
exit
|
||||||
@@ -142,7 +214,35 @@ sql 'marvin/Welcome1_DDS!@ddslab_tunnel'
|
|||||||
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected result: Marvin sees only his authorized account.
|
Expected result: Marvin sees only `Account Beta` from both paths.
|
||||||
|
|
||||||
|
### Task 4.3 - Quick Validation With Erik
|
||||||
|
|
||||||
|
```sql
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sql 'erik/Welcome1_DDS!@ddslab_tunnel'
|
||||||
|
```
|
||||||
|
|
||||||
|
```sql
|
||||||
|
@scenarios/04-view-bypass-mac/sql/04_test_queries.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected result: Erik sees only `Account Gamma` from both paths.
|
||||||
|
|
||||||
|
### Customer Message
|
||||||
|
|
||||||
|
After DDS, the result is consistent regardless of the path:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Emma -> Account Alpha only
|
||||||
|
Marvin -> Account Beta only
|
||||||
|
Erik -> Account Gamma only
|
||||||
|
```
|
||||||
|
|
||||||
|
This shows the value of DDS versus relying only on view logic, application SQL, BI filters, or agent-generated SQL.
|
||||||
|
|
||||||
## Lab 5 - Clean Up
|
## Lab 5 - Clean Up
|
||||||
|
|
||||||
@@ -165,7 +265,7 @@ exit
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `DDS_MAC_ACCOUNTS` | Protected base table. |
|
| `DDS_MAC_ACCOUNTS` | Protected base table. |
|
||||||
| `DDS_MAC_ACCOUNTS_VIEW` | Legacy view used to demonstrate alternate access paths. |
|
| `DDS_MAC_ACCOUNTS_VIEW` | Legacy view used to demonstrate alternate access paths. |
|
||||||
| `END USER` | `emma`, `marvin`; account owner personas. |
|
| `END USER` | `emma`, `marvin`, `erik`; account owner personas. |
|
||||||
| `DATA ROLE` | `account_owner_role`; owner authorization profile. |
|
| `DATA ROLE` | `account_owner_role`; owner authorization profile. |
|
||||||
| `DATA GRANT` | Filters rows by `owner_name = ORA_END_USER_CONTEXT.username`. |
|
| `DATA GRANT` | Filters rows by `owner_name = ORA_END_USER_CONTEXT.username`. |
|
||||||
| `SET USE DATA GRANTS ONLY` | Enforces DDS on the base table. |
|
| `SET USE DATA GRANTS ONLY` | Enforces DDS on the base table. |
|
||||||
@@ -177,4 +277,3 @@ The trust chain is: **end-user identity -> account owner role -> owner data gran
|
|||||||
- Views are useful, but they should not be the only security boundary.
|
- Views are useful, but they should not be the only security boundary.
|
||||||
- DDS protects the data regardless of the access path.
|
- DDS protects the data regardless of the access path.
|
||||||
- This reduces bypass risk from direct SQL, legacy views, and reporting tools.
|
- This reduces bypass risk from direct SQL, legacy views, and reporting tools.
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,28 @@
|
|||||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
EXECUTE IMMEDIATE q'[
|
||||||
CREATE TABLE dds_mac_accounts (
|
CREATE TABLE dds_mac_accounts (
|
||||||
account_id NUMBER PRIMARY KEY,
|
account_id NUMBER PRIMARY KEY,
|
||||||
account_name VARCHAR2(100),
|
account_name VARCHAR2(100),
|
||||||
owner_name VARCHAR2(60),
|
owner_name VARCHAR2(60),
|
||||||
region VARCHAR2(30),
|
region VARCHAR2(30),
|
||||||
balance NUMBER(12,2)
|
balance NUMBER(12,2)
|
||||||
);
|
)
|
||||||
|
]';
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN
|
||||||
|
IF SQLCODE != -955 THEN
|
||||||
|
RAISE;
|
||||||
|
END IF;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
|
||||||
CREATE VIEW dds_mac_accounts_view AS
|
BEGIN
|
||||||
|
EXECUTE IMMEDIATE q'[
|
||||||
|
CREATE OR REPLACE VIEW dds_mac_accounts_view AS
|
||||||
SELECT account_id, account_name, owner_name, region, balance
|
SELECT account_id, account_name, owner_name, region, balance
|
||||||
FROM dds_mac_accounts;
|
FROM dds_mac_accounts
|
||||||
|
]';
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||||
|
|
||||||
|
DELETE FROM dds_mac_accounts;
|
||||||
|
|
||||||
INSERT INTO dds_mac_accounts VALUES (1, 'Account Alpha', 'emma', 'LATAM', 100000);
|
INSERT INTO dds_mac_accounts VALUES (1, 'Account Alpha', 'emma', 'LATAM', 100000);
|
||||||
INSERT INTO dds_mac_accounts VALUES (2, 'Account Beta', 'marvin', 'LATAM', 250000);
|
INSERT INTO dds_mac_accounts VALUES (2, 'Account Beta', 'marvin', 'LATAM', 250000);
|
||||||
INSERT INTO dds_mac_accounts VALUES (3, 'Account Gamma', 'erik', 'EMEA', 900000);
|
INSERT INTO dds_mac_accounts VALUES (3, 'Account Gamma', 'erik', 'EMEA', 900000);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE
|
|||||||
|
|
||||||
CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!";
|
CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!";
|
||||||
CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!";
|
CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!";
|
||||||
|
CREATE END USER erik IDENTIFIED BY "Welcome1_DDS!";
|
||||||
|
|
||||||
CREATE DATA ROLE account_owner_role;
|
CREATE DATA ROLE account_owner_role;
|
||||||
|
|
||||||
@@ -9,5 +10,13 @@ CREATE ROLE mac_session_role;
|
|||||||
GRANT CREATE SESSION TO mac_session_role;
|
GRANT CREATE SESSION TO mac_session_role;
|
||||||
GRANT mac_session_role TO account_owner_role;
|
GRANT mac_session_role TO account_owner_role;
|
||||||
|
|
||||||
|
-- Vulnerable baseline: this broad role simulates legacy direct table and view
|
||||||
|
-- access before DDS mandatory enforcement is enabled.
|
||||||
|
CREATE ROLE mac_legacy_broad_access_role;
|
||||||
|
GRANT SELECT ON dds_mac_accounts TO mac_legacy_broad_access_role;
|
||||||
|
GRANT SELECT ON dds_mac_accounts_view TO mac_legacy_broad_access_role;
|
||||||
|
GRANT mac_legacy_broad_access_role TO account_owner_role;
|
||||||
|
|
||||||
GRANT DATA ROLE account_owner_role TO emma;
|
GRANT DATA ROLE account_owner_role TO emma;
|
||||||
GRANT DATA ROLE account_owner_role TO marvin;
|
GRANT DATA ROLE account_owner_role TO marvin;
|
||||||
|
GRANT DATA ROLE account_owner_role TO erik;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE
|
|||||||
CREATE OR REPLACE DATA GRANT mac_account_owner
|
CREATE OR REPLACE DATA GRANT mac_account_owner
|
||||||
AS SELECT
|
AS SELECT
|
||||||
ON dds_mac_accounts
|
ON dds_mac_accounts
|
||||||
WHERE owner_name = ORA_END_USER_CONTEXT.username
|
WHERE UPPER(owner_name) = ORA_END_USER_CONTEXT.username
|
||||||
TO account_owner_role;
|
TO account_owner_role;
|
||||||
|
|
||||||
CREATE OR REPLACE DATA GRANT mac_accounts_view_broad
|
CREATE OR REPLACE DATA GRANT mac_accounts_view_broad
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ BEGIN EXECUTE IMMEDIATE 'DROP DATA ROLE account_owner_role'; EXCEPTION WHEN OTHE
|
|||||||
/
|
/
|
||||||
BEGIN EXECUTE IMMEDIATE 'DROP ROLE mac_session_role'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
BEGIN EXECUTE IMMEDIATE 'DROP ROLE mac_session_role'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||||
/
|
/
|
||||||
|
BEGIN EXECUTE IMMEDIATE 'DROP ROLE mac_legacy_broad_access_role'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||||
|
/
|
||||||
BEGIN EXECUTE IMMEDIATE 'DROP END USER emma'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
BEGIN EXECUTE IMMEDIATE 'DROP END USER emma'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||||
/
|
/
|
||||||
BEGIN EXECUTE IMMEDIATE 'DROP END USER marvin'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
BEGIN EXECUTE IMMEDIATE 'DROP END USER marvin'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||||
/
|
/
|
||||||
|
BEGIN EXECUTE IMMEDIATE 'DROP END USER erik'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||||
|
/
|
||||||
|
|||||||
Reference in New Issue
Block a user