# XXE via lxml.etree.fromstring External Entity Resolution

Language: Python
Severity: High
CWE: CWE-611

## Source
6

## Flow
6-6

## Sink
6

## Vulnerable Code
```python
from lxml import etree
import boto3

def process_iot_device_config(device_xml_payload):
    s3_client = boto3.client('s3')
    parsed_config = etree.fromstring(device_xml_payload)
    device_id = parsed_config.find('.//deviceId').text
    firmware_ver = parsed_config.find('.//firmware').text
    config_data = etree.tostring(parsed_config, encoding='unicode')
    s3_client.put_object(Bucket='iot-device-configs', Key=f'{device_id}.xml', Body=config_data)
    return {'status': 'configured', 'device': device_id, 'version': firmware_ver}
```

## Explanation

The code uses lxml.etree.fromstring() to parse untrusted XML from IoT devices without disabling external entity resolution. An attacker can inject malicious XML with external entity declarations to read arbitrary files from the server, perform SSRF attacks, or cause denial of service through entity expansion attacks.

## Remediation

The fix creates a secure XMLParser instance with resolve_entities=False, no_network=True, dtd_validation=False, and load_dtd=False, which prevents external entity resolution, network access during parsing, and DTD loading. This parser is then passed to etree.fromstring() to ensure all XML parsing is performed securely against XXE attacks.

## Secure Code
```python
from lxml import etree
import boto3

def process_iot_device_config(device_xml_payload):
    s3_client = boto3.client('s3')
    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)
    parsed_config = etree.fromstring(device_xml_payload, parser=parser)
    device_id = parsed_config.find('.//deviceId').text
    firmware_ver = parsed_config.find('.//firmware').text
    config_data = etree.tostring(parsed_config, encoding='unicode')
    s3_client.put_object(Bucket='iot-device-configs', Key=f'{device_id}.xml', Body=config_data)
    return {'status': 'configured', 'device': device_id, 'version': firmware_ver}
```
