Graphql Introspection in Cockroachdb
How Graphql Introspection Manifests in Cockroachdb
GraphQL introspection in Cockroachdb environments typically emerges through misconfigured GraphQL servers that expose database schemas directly. When GraphQL APIs are built on top of Cockroachdb, developers often enable introspection by default, allowing attackers to retrieve the complete database schema including table structures, field types, and relationships.
# Introspection query that exposes entire schema
{
__schema {
types {
name
fields {
name
type {
name
kind
}
}
}
}
}
In Cockroachdb-specific implementations, introspection often reveals the distributed nature of the database through schema definitions that show crdb_internal tables, crdb_internal.cluster_id, and distributed transaction metadata. These details can help attackers understand the database topology and identify potential attack vectors.
A common manifestation occurs when GraphQL servers use Cockroachdb's pgwire protocol with reflection enabled. The server might expose internal Cockroachdb-specific types like INT8, DECIMAL, and INTERVAL along with Cockroachdb's unique timestamp and geographic data types. This level of detail is particularly dangerous because it reveals the exact data types being used, enabling attackers to craft more precise injection attacks.
Another specific pattern in Cockroachdb environments is the exposure of crdb_internal system tables through GraphQL resolvers. These tables contain critical metadata about the cluster's state, node information, and transaction details. When introspection is enabled, attackers can discover:
- Cluster configuration and node addresses
- Transaction IDs and timestamps
- Replication factor and range distribution
- Storage usage and hot ranges
- Lease holder information
Developers building GraphQL APIs on Cockroachdb often use ORMs like Prisma or Hasura that automatically generate schemas. These tools may enable introspection by default, exposing the entire Cockroachdb schema without proper access controls. The combination of Cockroachdb's distributed architecture and GraphQL's introspection creates a perfect storm where attackers can map the entire database topology across multiple nodes.
Cockroachdb-Specific Detection
Detecting GraphQL introspection vulnerabilities in Cockroachdb requires examining both the GraphQL layer and the underlying database configuration. The first step is to test the GraphQL endpoint with standard introspection queries. A simple test involves sending a POST request with the introspection query shown above and examining the response for detailed schema information.
# Test introspection endpoint
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query":"{\n __schema {\n types {\n name\n fields {\n name\n type {\n name\n kind\n }\n }\n }\n }\n}"}' \
https://your-api.com/graphql
For Cockroachdb-specific detection, examine the response for Cockroachdb-specific types and system tables. Look for crdb_internal prefixes, crdb_internal.cluster_id, and Cockroachdb's unique data types like INTERVAL, TIMESTAMPTZ, and OID. The presence of these indicates that the GraphQL server is directly exposing Cockroachdb's internal schema.
middleBrick's GraphQL security scanner specifically detects introspection vulnerabilities in Cockroachdb environments by:
- Testing for standard introspection queries and measuring response completeness
- Identifying Cockroachdb-specific schema elements in the introspection response
- Checking for exposed
crdb_internaltables and system metadata - Analyzing the GraphQL schema for unnecessary field exposure
- Verifying authentication requirements for introspection queries
The scanner also tests for Cockroachdb-specific attack patterns, such as queries that might trigger distributed query execution across multiple nodes, potentially exposing performance characteristics or timing information that could aid in further attacks.
Another detection method involves examining the GraphQL server's configuration files. Look for settings like introspection: true, playground: true, or debug: true in Apollo Server, Express GraphQL, or other GraphQL implementations. In Cockroachdb environments, also check for database connection configurations that might be exposing internal system tables through GraphQL resolvers.
Cockroachdb-Specific Remediation
Remediating GraphQL introspection vulnerabilities in Cockroachdb requires a multi-layered approach. The first and most critical step is to disable introspection in production environments. For Apollo Server with Cockroachdb:
const { ApolloServer } = require('apollo-server');
const resolvers = require('./resolvers');
const typeDefs = require('./schema');
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: false, // Disable introspection in production
playground: false, // Disable GraphQL playground
debug: false, // Disable debug mode
});
const dbConfig = {
connectionString: process.env.DATABASE_URL,
ssl: {
mode: 'require',
cert: process.env.COCKROACHDB_CERT,
},
};
// Explicitly exclude crdb_internal tables from resolvers
const safeResolvers = {
Query: {
// Only expose necessary queries
users: async (_, args, { db }) => {
return db.query('SELECT id, name, email FROM users WHERE active = true');
},
// Don't expose system tables
// crdb_internal: () => { throw new Error('Access denied') },
},
};
For Express GraphQL with Cockroachdb, implement similar protections:
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
const { Pool } = require('@cockroachdb/pg-pool');
const db = new Pool({
host: process.env.COCKROACHDB_HOST,
port: process.env.COCKROACHDB_PORT,
database: process.env.COCKROACHDB_DATABASE,
user: process.env.COCKROACHDB_USER,
password: process.env.COCKROACHDB_PASSWORD,
ssl: true,
});
const schema = buildSchema(`
type Query {
users: [User]
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
}
`);
const root = {
users: async () => {
const result = await db.query('SELECT id, name, email FROM users');
return result.rows;
},
user: async ({ id }) => {
const result = await db.query('SELECT id, name, email FROM users WHERE id = $1', [id]);
return result.rows[0];
},
};
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: false, // Disable GraphiQL in production
customFormatErrorFn: (error) => {
// Don't expose internal error details
return { message: 'Internal server error' };
},
}));
app.listen(4000);
For Cockroachdb-specific security, implement row-level security (RLS) to prevent unauthorized access to sensitive data:
-- Enable row-level security on sensitive tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- Create policies that restrict access based on user roles
CREATE POLICY users_policy ON users
FOR SELECT USING (
current_user = 'admin' OR
(current_user != 'admin' AND active = true)
);
-- For Cockroachdb-specific system tables, create restrictive policies
-- Note: crdb_internal tables are generally not accessible through RLS
-- but this demonstrates the principle for custom schemas
CREATE POLICY crdb_policy ON crdb_internal.
FOR SELECT USING (false); -- Deny all access
Additionally, implement query cost limiting to prevent expensive introspection queries from affecting your Cockroachdb cluster's performance:
const costAnalyzer = require('graphql-cost-analysis');
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [
costAnalyzer({
maximumCost: 100, // Limit query complexity
createListCost: (list) => list.length * 10,
}),
],
});
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |
Frequently Asked Questions
Why is GraphQL introspection particularly dangerous in Cockroachdb environments?
GraphQL introspection is especially dangerous in Cockroachdb environments because it can expose the distributed nature of the database through crdb_internal tables and system metadata. Cockroachdb's unique distributed architecture, with features like range distribution, lease holders, and cluster IDs, reveals critical information about the database topology when exposed through introspection. This information helps attackers understand how to target specific nodes or exploit distributed query execution patterns unique to Cockroachdb.
How does middleBrick detect GraphQL introspection vulnerabilities in Cockroachdb?
middleBrick detects GraphQL introspection vulnerabilities by sending standard introspection queries to the target endpoint and analyzing the response completeness. For Cockroachdb specifically, it identifies Cockroachdb-specific schema elements like crdb_internal tables, crdb_internal.cluster_id, and Cockroachdb's unique data types (INT8, INTERVAL, TIMESTAMPTZ). The scanner also tests for authentication bypass by attempting introspection queries without credentials and checks if the GraphQL server exposes unnecessary system metadata that could aid attackers in understanding the database architecture.