# Vulnerability Research - Status Report

## What We Know
1. Challenge: Find NEW vulnerability in web2py related to react2shell (CVE-2025-55182)
2. Target: Stock web2py v3.1.1 from GitHub
3. Goal: Execute `/readflag` to retrieve flag from `/root/flag.txt`
4. React2Shell Pattern: Unsafe deserialization in React's Flight protocol

## Comprehensive Code Analysis Completed

### 1. Template Rendering Engine (✓ SAFE)
- **Files analyzed**: `gluon/template.py`, `gluon/compileapp.py`
- **Findings**: Templates compiled to Python via `compile2()` and executed in restricted environment
- **Verdict**: User input doesn't directly flow into template compilation

### 2. eval/exec/compile Usage (✓ ALL INTERNAL)
- **`compileapp.py:632`**: `eval(key)` - Used in doctest, not user-accessible
- **`restricted.py:214`**: `exec(ccode, environment)` - Executes PRE-COMPILED code only
- **`languages.py:101`**: `eval(text, {}, {})` - In `safe_eval()`, processes language files
- **`scheduler.py:529`**: `eval(task.function)` - Internal scheduler, not HTTP-accessible
- **Verdict**: None accept direct user input

### 3. Error Handling & JavaScript Injection (✓ SAFE)
- **ajax_error_500 variable**: Contains URL with request params via `ASSIGNJS()`
- **Tested**: Proper JSON encoding (`\u003c` for `<`, etc.) prevents XSS
- **Verdict**: No injection possible

### 4. Deserialization Analysis (✓ KEY-PROTECTED)
#### Session Handling:
- **Cookie-based**: `secure_loads()` requires `cookie_key` + HMAC validation
- **File-based**: `pickle.load()` from server-side files only
- **DB-based**: `pickle.loads()` from database only
- **Verdict**: All pickle deserialization is server-side or key-protected

#### Utils Functions:
- **`utils.py:174,234`**: `pickle.loads()` in `secure_loads()`
- **Requires**: Valid encryption_key + HMAC signature
- **Verdict**: Cannot exploit without knowing the key

### 5. JSON/Request Processing (✓ SAFE)
- **`globals.py:257-290`**: Uses `json_parser.load()` (Python standard library)
- **Verdict**: No unsafe deserialization

## What We've Tested (All FAILED)
1. ✗ Query parameter SSTI (`?test={{=...}}`) - URL-encoded, not evaluated
2. ✗ `_next` parameter SSTI - Same as above
3. ✗ Session cookie deserialization - Requires encryption key
4. ✗ Form field injection - Fields sanitized
5. ✗ HTTP header injection - Headers not rendered unsafely
6. ✗ Post-login redirect - Normal 303 redirects
7. ✗ Generic views (.json, .xml) - Return 404
8. ✗ JSON deserialization - Uses safe json library
9. ✗ JavaScript injection (ajax_error_500) - Properly escaped

## Key Insight
React2Shell exploited **unauthenticated RCE via unsafe deserialization**. The pattern:
1. User sends crafted serialized payload
2. Server deserializes without validation
3. Gadget chain triggers RCE

For web2py to have a similar vuln, we need:
- An endpoint that accepts serialized data from user
- Deserialization without proper validation (pickle/eval/exec)
- No authentication required

## Areas Investigated (DEAD ENDS)

### 6. Spreadsheet Controller (✗ BROKEN IN PYTHON 3)
**Location**: `gluon/contrib/spreadsheet.py` line 836
```python
def compute(self, node):
    if node.value[:1] == "=" and not node.locked:
        exec("__value__=" + node.value[1:], {}, self.environment)
```

**Issue**: 
- Line 537 uses `xrange()` which doesn't exist in Python 3
- Docker container runs Python 3.13-slim
- All requests to `/examples/spreadsheet/` return 500 errors
- **Verdict**: Code has RCE vulnerability but is NOT exploitable due to Python 2/3 incompatibility

**Testing**:
- Confirmed `/examples/spreadsheet/index` returns 500 (NameError: xrange)
- Confirmed `/examples/spreadsheet/callback` returns 500
- Module never initializes, cannot reach exec() at line 836

### 7. SOAP Services (✓ ACCESSIBLE BUT SAFE)
**Location**: `applications/examples/controllers/soap_examples.py`

**Findings**:
- SOAP endpoint `/examples/soap_examples/call/soap` is accessible without auth
- Exposes functions: AddIntegers, SubIntegers, Division, AddStrings
- Uses `xml.dom.minidom.parseString()` for XML parsing (potential XXE, but not deserialization RCE)
- Functions only perform basic math operations
- **Verdict**: Accessible but no code execution path

**Testing**:
- Confirmed WSDL accessible at `/examples/soap_examples/call/soap?WSDL`
- Successfully called AddIntegers(5,3) = 8
- No dangerous functionality exposed

### 8. Session Cookie Analysis (✓ FILE-BASED, NO USER DATA)
**Welcome Application**:
- Does NOT call `session.connect()` with cookie_key
- Uses file-based sessions (session data stored on server)
- Only `session_id_welcome` cookie sent to client
- Session files stored in `applications/welcome/sessions/`
- **Verdict**: No pickle deserialization from user-controlled cookies

**Examples Application**:
- Uses `cookie_key = cache.ram('cookie_key', lambda: web2py_uuid(), None)`
- Calls `session.connect(request, response, cookie_key=cookie_key)`
- Cookie key is randomly generated and cached in RAM
- If cookie-based, would require knowing the random key
- **Verdict**: Cannot forge session cookies without key

**Testing**:
- Confirmed welcome app only sends `session_id` cookie, no `session_data`
- Session storage confirmed as file-based via `response.session_storage_type = "file"`

### 9. Contrib Modules Search (✓ NO EXPLOITABLE CODE)
**Searched for dangerous patterns**:
- `from gluon.contrib` imports in controllers
- Only found: spreadsheet (broken), pysimplesoap (safe), login_methods (admin only)
- Checked shell.py (GAE only, not used), simplejsonrpc (admin only)
- **Verdict**: No accessible contrib modules with RCE vulnerabilities

### 10. Additional Endpoint Enumeration (✓ NO NEW VECTORS)
**Welcome Application**:
- `/welcome/default/index` - 200 (safe)
- `/welcome/default/user/login` - 200 (safe)
- `/welcome/default/user/register` - 200 (safe)
- `/welcome/default/download` - requires filename args
- `/welcome/default/wiki` - 404 (not exposed)

**Examples Application**:
- `/examples/default/*` - various static pages
- `/examples/ajax_examples/*` - safe AJAX demos
- `/examples/cache_examples/*` - cache demos (no input handling)
- All checked, no dangerous user input handling found

## VULNERABILITY IDENTIFIED (Requires Auth Bypass)

### Primary Finding: RCE in appadmin via eval_in_global_env()
**Location**: `web2py/applications/*/controllers/appadmin.py` lines 92-115

**Vulnerability**:
```python
def eval_in_global_env(text):
    exec ('_ret=%s' % text, {}, global_env)
    return global_env['_ret']

def get_query(request):
    try:
        return eval_in_global_env(request.vars.query)  # Line 115 - USER INPUT!
    except Exception:
        return None
```

**Exploitable Endpoints**:
- `/*/appadmin/select/db?query=<payload>`
- `/*/appadmin/csv/db?query=<payload>`

**Authentication Status**: ⚠️ **REQUIRES CREDENTIALS** or localhost access
- All appadmin endpoints require `check_credentials()` OR admin session
- Tested: Returns 303 redirect to admin login when unauthenticated

**Impact**: Remote Code Execution as www-data user
**Payload Example**: `?query=__import__('os').popen('/readflag').read()`

## Current Status: Auth Bypass Needed
The eval_in_global_env RCE exists but is protected by authentication.
For this to be the target vulnerability, we need either:
1. An authentication bypass in admin/appadmin
2. Default/weak credentials (unlikely with random password)
3. A different unauthenticated entry point that calls eval_in_global_env
4. The actual 0-day is elsewhere entirely

## Next Actions Required
1. ✓ Found RCE in appadmin (authenticated)
2. ✓ Confirmed spreadsheet exec() broken in Python 3
3. ✓ Tested SOAP services (safe)
4. ✓ Analyzed session handling (file-based, secure)
5. ✓ Searched all contrib modules (none exploitable)
6. ❓ **Need new approach or additional hints**

## Current Research Status

**Confirmed Vulnerabilities**:
1. Appadmin RCE via `eval_in_global_env()` - **REQUIRES AUTHENTICATION**
2. Spreadsheet exec() at line 836 - **BROKEN (Python 2 code, uses xrange)**

**Dead Ends Confirmed**:
- Template injection (properly escaped)
- Session deserialization (file-based or key-protected)
- SOAP/XMLRPC services (accessible but safe)
- Contrib modules (broken or safe)
- All eval/exec/compile paths (authenticated or internal)

**Comprehensive Search Complete**:
After analyzing:
- All controllers in welcome, examples, admin applications  
- All gluon core modules (globals.py, compileapp.py, restricted.py, tools.py, cache.py, utils.py)
- All contrib modules (spreadsheet.py, pysimplesoap, shell.py, etc.)
- All @service decorated endpoints (SOAP, JSONRPC, XMLRPC)
- Session handling mechanisms (cookie-based and file-based)
- File upload/download functionality
- 300+ files searched for eval/exec/pickle patterns

**Result**: No unauthenticated RCE vulnerability found in stock web2py v3.1.1 codebase.

**Possible Unexplored Areas**:
- Request routing edge cases or web server (Rocket) specific vulnerabilities
- HTTP header processing issues
- Admin password generation/storage weaknesses  
- File path traversal in download/upload handlers
- Race conditions in session/cache handling

## Local Testing

- Docker container running on https://localhost:5000
- Can exec into container: `docker exec -it web2py-vuln-test /bin/sh`
- Logs: `docker logs web2py-vuln-test`

