# XML Entity Expansion DoS via Billion Laughs in lxml

Language: Python
Severity: High
CWE: CWE-776

## Source
3

## Flow
3-4-5-6

## Sink
6

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

def process_iot_device_config(xml_payload):
    parser = etree.XMLParser(resolve_entities=True)
    config_stream = io.BytesIO(xml_payload.encode('utf-8'))
    device_tree = etree.parse(config_stream, parser)
    root = device_tree.getroot()
    device_id = root.find('.//device_id').text
    firmware_ver = root.find('.//firmware').text
    settings = {child.tag: child.text for child in root.find('.//settings')}
    return {'device': device_id, 'firmware': firmware_ver, 'config': settings}
```

## Explanation

The function accepts untrusted XML input and explicitly enables entity resolution with `resolve_entities=True`, making it vulnerable to XML Entity Expansion attacks (Billion Laughs). An attacker can craft malicious XML with recursive entity definitions that exponentially expand during parsing, causing memory exhaustion and DoS.

## Remediation

The fix disables entity resolution by setting `resolve_entities=False` and adds additional hardening options (`no_network=True`, `dtd_validation=False`, `load_dtd=False`, `huge_tree=False`) to prevent XML entity expansion attacks and other XML-based exploits. This ensures that recursive entity definitions in DTDs are not expanded, preventing the Billion Laughs DoS attack.

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

def process_iot_device_config(xml_payload):
    parser = etree.XMLParser(
        resolve_entities=False,
        no_network=True,
        dtd_validation=False,
        load_dtd=False,
        huge_tree=False
    )
    config_stream = io.BytesIO(xml_payload.encode('utf-8'))
    device_tree = etree.parse(config_stream, parser)
    root = device_tree.getroot()
    device_id = root.find('.//device_id').text
    firmware_ver = root.find('.//firmware').text
    settings = {child.tag: child.text for child in root.find('.//settings')}
    return {'device': device_id, 'firmware': firmware_ver, 'config': settings}
```
