Xml External Entities in Echo Go
How Xml External Entities Manifests in Echo Go
XML External Entity (XXE) vulnerabilities in Echo Go applications typically arise when XML parsers process untrusted XML input without proper configuration. In Echo Go, this often occurs when using the encoding/xml package to parse XML requests or configuration files.
The core issue stems from XML's ability to define external entities using the <!ENTITY> syntax. When an Echo Go application accepts XML input (common in SOAP APIs, XML-based configuration, or legacy integrations) and parses it without disabling external entity processing, attackers can craft malicious XML documents that:
- Read local files using
<!ENTITY>withfile://URLs - Access internal network resources via
<!ENTITY>withhttp://orhttps://URLs - Perform SSRF attacks by forcing the server to make outbound requests
- Exhaust memory or CPU through recursive entity expansion (Billion Laughs attack)
Here's a vulnerable Echo Go endpoint that demonstrates the issue:
package main
import (
"encoding/xml"
"github.com/labstack/echo/v4"
)
type Person struct {
Name string `xml:"name"`
Age int `xml:"age"`
}
func main() {
e := echo.New()
e.POST("/person", func(c echo.Context) error {
var p Person
if err := xml.NewDecoder(c.Request().Body).Decode(&p); err != nil {
return err
}
return c.JSON(200, p)
})
e.Start(":8080")
}
This code is vulnerable because xml.NewDecoder processes external entities by default. An attacker could send:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<person>
<name>&xxe;</name>
<age>30</age>
</person>
The parser would replace &xxe; with the contents of /etc/passwd, potentially exposing sensitive data through error messages or application behavior.
Echo Go-Specific Detection
Detecting XXE vulnerabilities in Echo Go applications requires both static analysis and runtime scanning. middleBrick's API security scanner specifically tests for XXE vulnerabilities by submitting crafted XML payloads to endpoints that accept XML content types.
middleBrick scans Echo Go APIs for XXE by:
- Identifying endpoints that accept
application/xmlortext/xmlcontent types - Submitting payloads that attempt to read local files (
file://URLs) - Testing for SSRF by using
http://URLs pointing to internal services - Checking for recursive entity expansion that could cause DoS
- Analyzing error responses for leaked file contents or system information
To manually test an Echo Go application for XXE:
# Test with curl
curl -X POST http://localhost:8080/person \
-H "Content-Type: application/xml" \
-d "@xxe_payload.xml"
# Or use middleBrick CLI for automated scanning
npm install -g middlebrick
middlebrick scan http://localhost:8080 --type api
middleBrick provides specific findings for XXE in Echo Go applications, including:
- Which endpoints are vulnerable
- The exact attack vector that succeeded
- Recommendations for XML parser configuration
- Risk severity based on the potential impact
The scanner's XML analysis includes checking for common XXE patterns and testing against known attack vectors, providing Echo Go developers with actionable remediation steps specific to their Go application structure.
Echo Go-Specific Remediation
Remediating XXE vulnerabilities in Echo Go requires configuring XML parsers to disable external entity processing. The Go standard library's encoding/xml package doesn't provide direct configuration options, so developers must use alternative approaches.
Here's the secure implementation using Go's xml.Decoder with entity substitution disabled:
package main
import (
"encoding/xml"
"github.com/labstack/echo/v4"
)
type Person struct {
Name string `xml:"name"`
Age int `xml:"age"`
}
func secureXMLDecoder(r io.Reader) *xml.Decoder {
// Create decoder with entity substitution disabled
dec := xml.NewDecoder(r)
dec.Entity = xml.HTMLEntity
dec.Strict = true
return dec
}
func main() {
e := echo.New()
e.POST("/person", func(c echo.Context) error {
var p Person
dec := secureXMLDecoder(c.Request().Body)
if err := dec.Decode(&p); err != nil {
return c.JSON(400, map[string]string{"error": err.Error()})
}
return c.JSON(200, p)
})
e.Start(":8080")
}
For more robust XML processing, consider using third-party libraries like github.com/antchfx/xmlquery with proper configuration:
import (
"github.com/antchfx/xmlquery"
"golang.org/x/net/html/charset"
)
func parseSecureXML(r io.Reader) (*xmlquery.Node, error) {
r, err := charset.NewReader(r, "")
if err != nil {
return nil, err
}
doc, err := xmlquery.Parse(r)
if err != nil {
return nil, err
}
// Additional validation can be added here
return doc, nil
}
Additional security measures for Echo Go applications:
- Validate XML schema before processing
- Implement size limits on XML payloads using Echo's middleware
- Use content security policies to restrict outbound connections
- Monitor for unusual XML parsing patterns in logs
For applications that must process XML from trusted sources only, implement strict input validation and consider using a whitelist approach for XML processing endpoints.