Erstellung von unveränderlichem Text mit String-Verkettung
Beschreibung
Erstellung von unveränderlichem Text mit String-Verkettung tritt auf, wenn Software unveränderliche Textstrings unter Verwendung wiederholter String-Verkettungsoperationen erstellt, typischerweise innerhalb von Schleifen. In Sprachen, in denen Strings unveränderlich sind (wie Java, C#, Python), erstellt jede Verkettungsoperation ein neues String-Objekt im Speicher, wobei der gesamte existierende Inhalt plus der neue Inhalt kopiert wird. Bei wiederholter Ausführung, insbesondere in Schleifen, führt dies zu O(n²) Zeitkomplexität und exzessiver Speicherallokation, was sowohl Leistungs- als auch potenzielle Sicherheitsbedenken erzeugt.
Risiko
Obwohl hauptsächlich ein Leistungsproblem, kann diese Schwäche Sicherheitsimplikationen haben. Angreifer, die Codepfade mit ineffizienter String-Verkettung auslösen können, könnten dies für Denial-of-Service-Angriffe ausnutzen, indem sie exzessive CPU-Nutzung und Speicherallokation verursachen. Die Verarbeitung größer Eingaben durch ineffiziente String-Erstellung kann Serverressourcen erschöpfen. In Webanwendungen kann dies zu langsamen Reaktionszeiten führen, was das System anfällig für Slowloris-artige Angriffe macht.
Lösung
Verwenden Sie veränderbare String-Builder-Klassen anstelle von Verkettung: StringBuilder in Java/C#, StringBuffer für thread-sichere Szenarien, List-Joining in Python oder String-Streams in C++. Allokieren Sie Kapazität vor, wenn die endgültige Größe bekannt ist oder geschätzt werden kann. Für einfache Fälle mit wenigen Verkettungen ist die Leistungsauswirkung vernachlässigbar, aber verwenden Sie immer Builder in Schleifen oder bei der Verarbeitung von Eingaben variabler Länge.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Ressourcenverbrauch (CPU) - Wiederholte String-Verkettung in Schleifen verursacht O(n²) Zeitkomplexität und verbraucht exzessive CPU-Zyklen. |
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Ressourcenverbrauch (Speicher) - Jede Verkettung erstellt neue String-Objekte und erschöpft möglicherweise den Speicher. |
| Andere | Bereich: Ändere Leistungsreduktion - Allgemeine Leistungsverschlechterung, die Denial-of-Service-Angriffe ermöglichen kann. |
Beispielcode
Anfälliger Code
// ANFÄLLIG: String-Verkettung in Schleife (Java)
public class VulnerableStringBuilder {
public String vulnerableBuildHTML(List<String> items) {
String html = "<ul>";
// ANFÄLLIG: Jedes += erstellt ein neues String-Objekt
// O(n²) Komplexität: für n Elemente kopiert ca. n²/2 Zeichen
for (String item : items) {
html += "<li>" + item + "</li>"; // Erstellt mehrere neue Strings
}
html += "</ul>";
return html;
}
// Mit 10.000 Elementen erstellt dies ~50 Millionen Zeichenkopien
}
# ANFÄLLIG: String-Verkettung in Python
def vulnerable_build_csv(records):
csv_data = ""
# ANFÄLLIG: Python-Strings sind unveränderlich
# Jedes += erstellt ein neues String-Objekt
for record in records:
line = ""
for field in record:
line += str(field) + "," # Mehrere Allokationen pro Feld
line = line[:-1] # Entferne nachfolgendes Komma
csv_data += line + "\n" # Mehr Allokationen
return csv_data
# Verarbeitung von 100.000 Datensätzen wird extrem langsam
Korrigierter Code
// KORRIGIERT: StringBuilder in Java verwenden
public class FixedStringBuilder {
public String fixedBuildHTML(List<String> items) {
// KORRIGIERT: StringBuilder ist veränderbar, O(n) Komplexität
StringBuilder html = new StringBuilder();
// Kapazität vorallokieren wenn Größe bekannt
html.ensureCapacity(items.size() * 25 + 10);
html.append("<ul>");
for (String item : items) {
html.append("<li>")
.append(escapeHtml(item)) // XSS auch beheben!
.append("</li>");
}
html.append("</ul>");
return html.toString();
}
// Thread-sichere Version mit StringBuffer
public String fixedBuildHTMLThreadSafe(List<String> items) {
StringBuffer html = new StringBuffer();
html.append("<ul>");
for (String item : items) {
synchronized (html) {
html.append("<li>")
.append(escapeHtml(item))
.append("</li>");
}
}
html.append("</ul>");
return html.toString();
}
}
# KORRIGIERT: List-Join in Python verwenden
def fixed_build_csv(records):
# KORRIGIERT: Liste von Zeilen erstellen, dann einmal verbinden
lines = []
for record in records:
# Join für Felder innerhalb jeder Zeile verwenden
line = ",".join(str(field) for field in record)
lines.append(line)
# Einzelne Join-Operation am Ende
return "\n".join(lines)
# Alternativ: StringIO für stream-ähnliches Erstellen verwenden
from io import StringIO
def fixed_build_csv_stringio(records):
buffer = StringIO()
for record in records:
buffer.write(",".join(str(field) for field in record))
buffer.write("\n")
return buffer.getvalue()
# Am besten für CSV: csv-Modul verwenden
import csv
from io import StringIO
def fixed_build_csv_proper(records):
buffer = StringIO()
writer = csv.writer(buffer)
writer.writerows(records)
return buffer.getvalue()
// KORRIGIERT: strings.Builder in Go verwenden
import (
"strings"
"fmt"
)
func fixedBuildLog(entries []LogEntry) string {
// KORRIGIERT: strings.Builder ist effizient für String-Erstellung
var builder strings.Builder
// Puffer vorvergrößern wenn Größe bekannt
builder.Grow(len(entries) * 100)
for _, entry := range entries {
fmt.Fprintf(&builder, "[%s] %s: %s\n",
entry.Timestamp, entry.Level, entry.Message)
}
return builder.String()
}
CVE-Beispiele
Diese CWE ist hauptsächlich ein Leistungs-/Qualitätsproblem. Obwohl keine direkten CVEs spezifisch der String-Verkettung zugeschrieben werden, haben Leistungsschwachstellen durch ineffiziente String-Handhabung zu Denial-of-Service-Bedingungen in verschiedenen Anwendungen beigetragen.
Verwandte CWEs
- CWE-1176: Inefficient CPU Computation (Eltern)
- CWE-1006: Bad Coding Practices (Kategoriemitglied)
- CWE-400: Uncontrolled Resource Consumption (kann führen zu)
Referenzen
-
MITRE Corporation. "CWE-1046: Creation of Immutable Text Using String Concatenation." https://cwe.mitre.org/data/definitions/1046.html
-
Oracle. "Java StringBuilder Class Documentation."
-
Microsoft. "StringBuilder Class (System.Text)."