Es werden Daten hinter oder vor den Bereich des Puffers geschrieben.
C /C++
Hoch
Speichermodifikation; DoS: Crash, Beendigung oder Neustart; Ausführen von nicht autorisiertem Code oder Befehlen
1int id_sequence[3];
23
/* Populate the id array. */
45
id_sequence[0] = 123;
6id_sequence[1] = 234;
7id_sequence[2] = 345;
8id_sequence[3] = 456;
1int returnChunkSize(void *) {
23
/* if chunk info is valid, return the size of usable memory,
45
* else, return -1 to indicate an error
67
*/
8...
9}
1011
int main() {
12...
13memcpy(destBuf, srcBuf, (returnChunkSize(destBuf)-1));
14...
15}
1void host_lookup(char *user_supplied_addr){
2struct hostent *hp;
3in_addr_t *addr;
4char hostname[64];
5in_addr_t inet_addr(const char *cp); // function prototype
67
/* routine that ensures user_supplied_addr is in the right format for
8conversion */
910
validate_addr_form(user_supplied_addr);
11addr = inet_addr(user_supplied_addr);
12hp = gethostbyaddr( addr, sizeof(struct in_addr), AF_INET);
13strcpy(hostname, hp->h_name);
14}
1char * copy_input(char *user_supplied_string){
2int i, dst_index;
3char *dst_buf = (char*)malloc(4*sizeof(char) * MAX_SIZE);
4if ( MAX_SIZE <= strlen(user_supplied_string) ) die("string too long");
5dst_index = 0;
6for ( i = 0; i < strlen(user_supplied_string); i++ ){
7if( '&' == user_supplied_string[i] ){
8dst_buf[dst_index++] = '&';
9dst_buf[dst_index++] = 'a';
10dst_buf[dst_index++] = 'm';
11dst_buf[dst_index++] = 'p';
12dst_buf[dst_index++] = ';';
13}
14else if ( '<' == user_supplied_string[i] ){ /* encode to < */ }
15else dst_buf[dst_index++] = user_supplied_string[i];
16}
17return dst_buf;
18}
1char* trimTrailingWhitespace(char *strMessage, int length) {
2char *retMessage;
3char message[length+1]; // copy input string to a
4int index; // temporary string
5for (index = 0; index < length; index++) { //
6message[index] = strMessage[index]; //
7} //
8message[index] = '\0'; //
910
int len = index-1; // trim trailing whitespace
11while (isspace(message[len])) { //
12message[len] = '\0'; //
13len--; //
14} //
1516
retMessage = message;
17return retMessage; // return trimmed string
18}
If an argument (character) passed to the isspace() function is a white-space character, it returns non-zero integer. If not, it returns 0.
1int i;
2unsigned int numWidgets;
3Widget **WidgetList;
45
numWidgets = GetUntrustedSizeValue();
6if ((numWidgets == 0) || (numWidgets > MAX_NUM_WIDGETS)) {
7ExitError("Incorrect number of widgets requested!");
8}
9WidgetList = (Widget **)malloc(numWidgets * sizeof(Widget *));
10printf("WidgetList ptr=%p\n", WidgetList);
11for(i=0; i<numWidgets; i++) {
12WidgetList[i] = InitializeWidget();
13}
14WidgetList[numWidgets] = NULL;
15showWidgets(WidgetList);
Verwendung einer sicheren Programmiersprache (Java, ...)
Verwendung von Bibliotheken, die sicherer sind (z. B. strncpy
statt strcpy
)
Kompilierung mit entsprechenden Flags, die entsprechende Prüfung aktivieren (z. B. -D_FORTIFY_SOURCE=2
)
Kompilierung als Position-Independent-Code
Dies löst nicht das Problem, aber es macht es schwerer eine Schwachstelle auszunutzen.
Statische Analyse Werkzeuge
Dynamische Analyse Werkzeuge (z. B. Fuzzing, Fault Injection, ...)
Nutzereingaben werden nicht oder falsch bereinigt, bevor sie in die Ausgabe eingefügt werden, die als Webseite für andere Benutzer verwendet wird.
Hoch
Speichermodifikation; DoS: Crash, Beendigung oder Neustart; Ausführen von nicht autorisiertem Code oder Befehlen
Zugriffskontrolle, Vertraulichkeit
Stored XSS (Typ 2), Reflected XSS (Typ 1), DOM-based XSS (Typ 0)
Durch eine XSS Lücke werden häufig Informationen abgegriffen (z. B. Session Cookies). Allerdings ist es ggf. auch möglich, dass der Angreifer die Session des Nutzers übernimmt und sich als dieser ausgibt.
Reflected XSS ist häufig schwerer auszunutzen, da der Angreifer den Nutzer dazu bringen muss, einen Link zu klicken, der den Angriffsvektor enthält. Bei Stored XSS ist dies nicht notwendig, da der Angriffsvektor bereits auf dem Server gespeichert ist.
Dom-based XSS ist am schwersten Auszunutzen, da der Angreifer den Nutzer dazu bringen muss den Schadcode in die Informationen einzubringen, die von dem Script verarbeitet werden (z. B. durch das Eingeben in ein Formular).
1# Rückgabe einer Willkommensnachricht basierend auf dem
2# HTTP Get username Parameter
3$username = $_GET['username'];
4echo '<div class="header"> Welcome, ' . $username . '</div>';
1<% String eid = request.getParameter("eid");
2Statement stmt = conn.createStatement();
3ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);
4if (rs != null) {
5rs.next();
6String name = rs.getString("name");
7}
8%>
910
Employee Name: <%= name %>
1$username = mysql_real_escape_string($username);
2$fullName = mysql_real_escape_string($fullName);
3$query = sprintf('Insert Into users (uname,pwd,fname) Values ("%s","%s","%s")',
4$username,
5crypt($password),
6$fullName) ;
7mysql_query($query);
8...
Verwendung von geprüften/sicheren APIs
Verringerung der Angriffsfläche mit dem Ziel möglichst wenig Daten in Cookies etc. zu speichern.
Prüfung dass alle auf dem Client durchgeführten Prüfungen auch auf dem Server vorgenommen werden.
Prüfe jeden Input.
Verwendung von HttpOnly Cookies (d. h. Cookies, die nicht über JavaScript ausgelesen werden können)
Statische Analyse Werkzeuge
Beherzigen von Best Practices (XSS Prevention Cheat Sheet)
Ein SQL-Befehl wird ganz oder teilweise unter Verwendung extern beeinflusster Eingaben von einer vorgelagerten Komponente erzeugt. Dabei werden aber spezielle Elemente nicht oder falsch bereinigt, die den beabsichtigten SQL-Befehl verändern könnten, wenn er an eine nachgelagerte Komponente gesendet wird.
Hoch
Datenbanken
Zugriffskontrolle, Vertraulichkeit, Integrität
1SELECT ITEM,PRICE
2FROM PRODUCT
3WHERE ITEM_CATEGORY='$user_input'
4ORDER BY PRICE
1$id = $_COOKIE["mid"];
2mysql_query(
3"SELECT MessageID, Subject FROM messages WHERE MessageID = '$id'"
4);
Verwendung von geprüften/sicheren APIs.
Verwendung von Prepared Statements.
Datenbank nur mit den notwendigen Rechten betreiben
(Principle of Least Privilege)
Sollte es notwendig sein einen dynamischen SQL Befehl zu erstellen, dann sollten geprüfte Escapefunktionen verwendet werden.
Statische Analyse Werkzeuge
ggf. Application-level Firewall einsetzen
Referenzierung von Speicher nach der Freigabe kann dazu führen, dass ein Programm abstürzt, unerwartete Werte verwendet oder Code ausführt.
Hoch
C, C++
Verfügbarkeit, Vertraulichkeit, Integrität
1char* ptr = (char*)malloc (SIZE);
2if (err) {
3abrt = 1;
4free(ptr);
5}
6// ... somewhere else in the code
7// char* otherPtr = (char*)malloc (SIZE);
8// otherPtr* = <HACKER CONTROLLED VALUE>;
9// ...
10if (abrt) {
11// Next: use of ptr after free which uses the hacker controlled value
12logError("operation aborted before commit", ptr);
13}
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#define BUFSIZER1 512
5int main(int argc, char **argv) {
6char *buf1R1, *buf2R1, *buf2R2;
7buf2R1 = (char *) malloc(BUFSIZER1);
8printf("buf2R1 -> %p\n",buf2R1);
9free(buf2R1);
10printf("[FREED] %p\n",buf2R1);
1112
buf2R2 = (char *) malloc(BUFSIZER1);
13strncpy(buf2R2, argv[1], BUFSIZER1-1);
14printf("buf2R2 -> %p\n",buf2R2);
15printf("buf2R2 = %s\n",buf2R2);
16printf("!!! buf2R1 = %s\n",buf2R1);
17free(buf2R2);
18}
Fragen:
Wird dieses Program bis zum Ende laufen oder abstürzen?
Welche Ausgabe erzeugt das Programm?
Ist die Ausgabe bei jedem Lauf gleich?
// clip_mkip (clip.c):
198 static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) {
...
234 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
235 netif_rx(skb);
236 }
... // PROBLEMATIC CODE STARTS HERE:
510 clip_push(vcc,skb);
511 PRIV(skb->dev)->stats.rx_packets--;
512 PRIV(skb->dev)->stats.rx_bytes -= len;
// netif_rx (dev.c):
1392 int netif_rx(struct sk_buff *skb) {
...
1428 kfree_skb(skb); //drop skb
1429 return NET_RX_DROP;
Wahl einer sicheren Programmiersprache (z. B. RUST)
explizites NULL
setzen, nachdem der Speicherbereich freigegeben wurde
Fuzzing
Statische Analyse Werkzeuge
Empfohlene Lektüre: One day short of a full chain: Real world exploit chains explained (In Teil 1 wird eine UAF Schwachstelle genutzt.)
Alles oder zumindest ein Teil eines Betriebssystembefehls hängt von extern beeinflussten Eingaben ab. Es erfolgt jedoch keine Bereinigung spezieller Elemente, die den beabsichtigten Betriebssystembefehl verändern könnten.
Hoch
Verfügbarkeit, Vertraulichkeit, Integrität
Ein bestimmtes Program wird ausgeführt und die Nutzerdaten werden als Parameter übergeben.
Die Anwendung bestimmt basierend auf den Nutzerdaten welches Program mit welchen Parametern ausgeführt wird.
1...
2String btype = request.getParameter("backuptype");
3String cmd = new String(
4"cmd.exe /K \"c:\\util\\rmanDB.bat "
5+btype+
6"&&c:\\utl\\cleanup.bat\"")
78
System.Runtime.getRuntime().exec(cmd);
9...
Verwendung von geprüften/sicheren APIs.
Anwendung bzw. Befehl nur mit den notwendigen Rechten betreiben (Principle of Least Privilege) bzw. in einer Sandbox ausführen.
Statische Analyse Werkzeuge
Dynammische Analyse in Kombination mit Fuzzing
Manuelle Code Reviews/Statische Analyse
ggf. Application-level Firewall einsetzen
Empfangene Eingaben oder Daten werden nicht nicht oder falsch validiert in Hinblick darauf, dass die Eingaben die Eigenschaften haben, die für eine sichere und korrekte Verarbeitung der Daten erforderlich sind.
Hoch
Verfügbarkeit, Vertraulichkeit, Integrität
Rohdaten - Strings, Zahlen, Parameter, Dateiinhalte, etc.
Metadaten - Information über die Rohdaten, wie zum Beispiel Header oder Größe
Größen wie Größe, Länge, Häufigkeit, Preis, Rate, Anzahl der Vorgänge, Zeit usw.
implizite oder abgeleitete Größen, wie z. B. die tatsächliche Größe einer Datei anstelle einer angegebenen Größe
Indizes, Offsets oder Positionen in komplexeren Datenstrukturen
Schlüssel von Hashtabellen, assoziativen Feldern usw.
syntaktische Korrektheit - Übereinstimmung mit der erwarteten Syntax
Bestimmung des tatsächlichen Typs der Eingabe (oder das, was die Eingabe zu sein scheint)
Konsistenz zwischen den Rohdaten und Metadaten, zwischen Referenzen usw.
semantische Korrektheit bzw. Konformität mit domänenspezifischen Regeln, z. B. Geschäftslogik
Authentizität von z. B. kryptografischen Signaturen
C:
1#define MAX_DIM 100
2int m,n, error; /* m,n = board dimensions */
3board_square_t *board;
4printf("Please specify the board height: \n");
5error = scanf("%d", &m);
6if ( EOF == error ) die("No integer passed!\n");
7printf("Please specify the board width: \n");
8error = scanf("%d", &n);
9if ( EOF == error ) die("No integer passed!\n");
10if ( m > MAX_DIM || n > MAX_DIM ) die("Value too large!\n");
1112
board = (board_square_t*) malloc( m * n * sizeof(board_square_t));
13...
(begrenzt) Statische Analyse Werkzeuge
Manuelle statische Analyse insbesondere in Hinblick auf die zugrundeliegende Semantik
Dynamische Analyse mit Fuzzing
Daten vor oder nach einem Puffer werden gelesen.
Hoch
C, C++
Vertraulichkeit
Umgehung von Schutzmaßnahmen; Lesen von Speicher
Die Ausnutzung dieser Schwachstelle ist häufig schwierig, da nicht immer bekannt ist welche und wie viele Daten gelesen werden können. Es kann allerdings möglich sein Speicheradressen auszulesen. Dies kann ggf. genutzt werden, um Mechanismen wie ASLR zu umgehen.
C:
1int getValueFromArray(int *array, int len, int index) {
2int value;
34
// check that the array index is less than the maximum length of the array
5if (index < len) {
6// get the value at the specified index of the array
7value = array[index];
8}
9// if array index is invalid then output error message
10// and return value indicating error
11else {
12printf("Value is: %d\n", array[index]);
13value = -1;
14}
15return value;
16}
eine sichere Programmiersprache verwenden
Fuzzing
Statische Analyse Werkzeuge welche Kontroll- und Datenflussanalyse durchführen
Externe Eingaben werden für die Konstruktion eines Pfadnamens verwendet, der eine Datei oder ein Verzeichnis identifizieren soll, das sich unterhalb eines eingeschränkten übergeordneten Verzeichnisses befindet. Eine Bereinigung spezieller Elemente innerhalb des Pfadnamens erfolgt jedoch nicht ordnungsgemäß, was dazu führen kann, dass der Pfadname zu einem Ort außerhalb des eingeschränkten Verzeichnisses aufgelöst wird.
Hoch
Vertraulichkeit, Integrität, Verfügbarkeit
PHP:
1<?php
2$file = $_GET['file'];
3include("/home/www-data/$file");
4?>
Perl:
1my $Username = GetUntrustedInput();
2$Username =~ s/\.\.\///; # Remove ../
3my $filename = "/home/user/" . $Username;
4ReadAndSendFile($filename);
Java:
1String path = getInputPath();
2if (path.startsWith("/safe_dir/")) {
3File f = new File(path);
4f.delete()
5}
1import os
2import sys
3def main():
4filename = sys.argv[1]
5path = os.path.join(os.getcwd(),
6filename)
7try:
8with open(path, 'r') as f:
9file_data = f.read()
10except FileNotFoundError as e:
11print("Error - file not found")
1213
# do something with file_data
Dokumentation os.path.join
Join one or more path components intelligently. The return value is the concatenation of path and any members of *paths with exactly one directory separator following each non-empty part except the last, meaning that the result will only end in a separator if the last part is empty.
If a component is an absolute path [...], all previous components are thrown away and joining continues from the absolute path component.
Eingabe vollständig validieren; zum Beispiel über kanonische Pfade
Sandboxen
Umgebung härten
Bei Fehlerausgaben darauf achten, dass keine Informationen über das Dateisystem preisgegeben werden
den Code mit minimalen Rechten ausführen
Die Webanwendung prüft nicht bzw. kann nicht prüfen, ob eine Anfrage absichtlich von dem Benutzer gestellt wurde, von dessen Browser sie übermittelt wurde.
D. h. eine CSRF Schwachstelle nutzt das Vertrauen aus, das eine Webseite in den Browser eines Nutzers hat. Bei einem CSRF-Angriff wird ein legitimer Nutzer von einem Angreifer dazu gebracht, ohne sein Wissen eine Anfrage zu übermitteln, die er nicht beabsichtigt hat und auch nicht bemerkt.
Mittel
Hängt von den Nutzerrechten ab
Vertraulichkeit, Integrität, Verfügbarkeit
Fiber ist ein von Express inspiriertes Web-Framework, das in Go geschrieben wurde. In der Anwendung wurde eine Cross-Site Request Forgery (CSRF)-Schwachstelle entdeckt, die es einem Angreifer ermöglicht, beliebige Werte zu injizieren und bösartige Anfragen im Namen eines Benutzers zu fälschen. Diese Schwachstelle kann es einem Angreifer ermöglichen, beliebige Werte ohne Authentifizierung einzuschleusen oder verschiedene böswillige Aktionen im Namen eines authentifizierten Benutzers durchzuführen, wodurch die Sicherheit und Integrität der Anwendung gefährdet werden kann. Die Schwachstelle wird durch eine unsachgemäße Validierung und Durchsetzung von CSRF-Tokens innerhalb der Anwendung verursacht.
—CVE-2023-45128 (übersetzt mit DeepL)
Identifizierte Schwachstellen: CWE-20 Improper Input Validation, CWE-807 Reliance on Untrusted Inputs in a Security Decision, CWE-565 Reliance on Cookies without Validation and Integrity Checking, CWE-352 Cross-Site Request Forgery
Standardtechniken, die CSRF verhindern sollen:
Same-site Cookies (für Authentifizierung)
CSRF-Tokens, wenn diese die folgenden Eigenschaften haben:
Einmalig pro Nutzersession
Geheim
nicht vorhersagbar (z. B. eine sehr große, sicher erzeugte Zufallszahl)
Validierung des Referer-Header
Custom Request Header, da diese nur vom JavaScript Code gesetzt werden können, der den gleichen Ursprung hat (siehe Same Origin Policy (SOP)).
Auch diese Techniken lassen sich ggf. (alle zusammen) aushebeln, wenn die Anwendung weitere Schwachstellen aufweist. So gibt/gab es Anwendungen, die Anfragen, die nur über ein POST request gestellt werden sollten, auch bei einem GET akzeptiert haben.
In allen Browsern wird in der Zwischenzeit für Cookies die Same-site Policy angewandt mit dem Wert Lax
. Dieser Wert hat zur Folge, dass Cookies nur dann gesendet werden, wenn der Nutzer explizit auf einen Link klickt oder sich innerhalb der selben Seite befindet.
Es ist möglich potentiell gefährliche Dateien hochzuladen bzw. zu transferieren, die von der Anwendung automatisch im Kontext der Anwendung verarbeitet werden.
Mittel
Bis hin zur Ausführung von beliebigen Befehlen
Vertraulichkeit, Integrität, Verfügbarkeit
HTML:
1<form action="upload_picture.php" method="post" enctype="multipart/form-data">
2Choose a file to upload:
3<input type="file" name="filename"/>
4<br/>
5<input type="submit" name="submit" value="Submit"/>
6</form>
PHP:
1// Define the target location where the picture being
2// uploaded is going to be saved.
3$target = "pictures/" . basename($_FILES['uploadedfile']['name']);
45
// Move the uploaded file to the new location.
6move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target)
Beim Speichern von Dateien niemals den ursprünglichen Dateinamen verwenden sondern einen vom Server generierten.
Speicher die Daten nicht im Kontext der Webanwendung sondern außerhalb des Webroots.
Prüfe die Dateiendung. Prüfe den Inhalt der Datei gegen die Erwartung.
Ausführen der Webanwendung mit minimalen Rechten.
Sandbox.
Ein Pufferüberlauf, bei dem der Puffer, der überschrieben wird, auf dem Heap alloziiert wurde, was im Allgemeinen bedeutet, dass der Puffer mit einer Routine wie malloc() allloziiert wurde.
Hoch
C/C++
Bis hin zur Ausführung von beliebigen Befehlen
Vertraulichkeit, Integrität, Verfügbarkeit, Zugriffskontrolle
„Basisbeispiel“ in C:
1#define BUFSIZE 256
2int main(int argc, char **argv) {
3char *buf;
4buf = (char *)malloc(sizeof(char)*BUFSIZE);
5strcpy(buf, argv[1]);
6}
Verwendung einer sicheren Programmiersprache
Verwendung von sicheren APIs
Kompilierung unter Verwendung entsprechender Schutzmechanismen (Position-Independent Executables (PIE), Canaries, ...)
Härtung der Umgebung (z. B. ASLR)
Statische Analyse Werkzeuge
Fuzzing
Nicht vertrauenswürdige Daten werden deserialisiert ohne - je nach Bibliothek notwendige vorhergehende - Prüfung, dass die Daten die erwarteten Eigenschaften haben.
Mittel
Java, Ruby, Python, PHP, JavaScript, ...
Insbesondere: Integrität und Verfügbarkeit (DoS); weitere Effekte sind vom Kontext abhängig.
(Un-)Marshalling, (Un-)Pickling
Bei der Serialisierung werden programminterne Objekte so verpackt, dass die Daten extern gespeichert und/oder übertragen werden können. Die Deserialisierung kehrt diesen Prozess um.
Java
1File file = new File("object.obj");
2try ( FileInputStream fin = new FileInputStream(file);
3ObjectInputStream oin = new ObjectInputStream(fin)
4) {
5javax.swing.JButton button = (javax.swing.JButton) oin.readObject();
6...
7}
In diesem Beispiel wird ein Objekt aus einer Datei gelesen und in eine Variable vom Typ javax.swing.JButton
geschrieben. Der Typ des Objekts wird nicht geprüft. Es ist möglich, dass die Datei ein Objekt enthält, welches vom Typ javax.swing.JButton
ist, aber nicht die Eigenschaften hat, die ein Button haben sollte. In diesem Fall wird keine Exception geworfen, aber das Objekt kann nicht wie erwartet verwendet werden bzw. es kommt zur Ausführung von beliebigem Code.
Python
1class ExampleProtocol(protocol.Protocol):
23
def dataReceived(self, data):
4# ... parse the incoming data and
5# after receiving headers, call confirmAuth() to authenticate
67
def confirmAuth(self, headers):
8try:
9token = cPickle.loads(base64.b64decode(headers['AuthToken']))
10if not check_hmac(token['signature'], token['data'], getSecretKey()):
11raise AuthFail
12self.secure_data = token['data']
13except:
14raise AuthFail
ggf. Einsatz von Signaturen, um sicherzustellen, dass der serialisierte Code nicht manipuliert wurde
Serialisiere nur Daten, die auch wirklich serialisiert werden müssen
Verwendung von sicheren Formaten (z. B. JSON)
statische Analyse
Empfohlene Lektüre: Deserialization Vulnerabilities
Der Webserver erhält eine URL oder eine ähnliche Anfrage und ruft den Inhalt dieser URL ab, stellt aber nicht sicher, dass die Anfrage an das erwartete Ziel gesendet wird.
Webserver
Vetraulichkeit, Integrität
Beispiel: CVE-2002-1484
Wenn der DB4Web-Server so konfiguriert ist, dass er ausführliche Debug-Meldungen verwendet, können entfernte Angreifer DB4Web als Proxy verwenden und über eine Anfrage an eine URL, die die Ziel-IP-Adresse und den Port angibt, TCP-Verbindungen zu anderen Systemen (Port-Scan) versuchen, was einen Verbindungsstatus in der resultierenden Fehlermeldung erzeugt.
Um die Ausnutzung dieses Features zu verhindern, muss die Standardfehlerseite durch eine benutzerdefinierte ersetzt werden.
Der Hersteller betrachtet die Funktionalität nicht als Fehler, sondern als Feature für Entwickler.
JavaScript:
1var base = "http://orange.tw/sandbox/";
2var path = req.query.path;
3if (path.indexOf("..") == -1) { // check for no directory traversal
4http.get(base + path, callback);
5}
Beispiel URL (U+FF2E Full width Latin capital letter N):
http://orange.tw/sandbox/NN/passwd
≙ http://orange.tw/sandbox/\xFF\x2E\xFF\x2E/passwd
≙ http://orange.tw/sandbox/\x2E\x2E/passwd
≙ http://orange.tw/sandbox/../passwd
PHP (> 7.0.13):
1$url = 'http://foo@127.0.0.1⬜@google.com:11211/'; // ⬜ is "just" a space
2$parsed = parse_url($url);
3var_dump($parsed[host]); // string(10) "google.com"
4var_dump($parsed[port]); // int(11211)
5curl($url);
Ergebnis:
curl fragt die URL 127.0.0.1:11211 ab.
D. h. curl und php interpretieren die URL unterschiedlich.
Variante: Blind SSRF
Bei Blind SSRF-Schwachstellen werden auch Back-End-HTTP-Anfragen an eine bereitgestellte URL gestellt, die Antwort der Back-End-Anfrage jedoch nicht an die Front-End-Antwort der Anwendung zurückgegeben.
Empfohlene Lektüre: Blind Server-Side Request Forgery (SSRF)
keine (Wieder-)Verwendung der Eingabe URL
sichere APIs
statische Analyse (insbesondere Datenflußanalysen)
Behandlung von Zugriffen von lokalen Maschinen sollte mit der gleichen sorgfalt überprüft werden wie Zugriffe von externen Maschinen; andernfalls können kritische SSRF Angriffe durchgeführt werden
Firewall/Network Policy, um Zugriff auf interne Systeme zu verhindern
Eine Anwendung initialisiert eine Ressource mit einem bestimmten Typ (z. B. Zeiger (Pointer), Objekt, etc.). Später wird auf die Ressource (Variable) dann mit einem anderen Typ zugegriffen.
insbesondere (aber nicht ausschließlich) C/C++; im Prinzip in jeder Sprache, die automatische Typkonvertierungen durchführt.
Integrität, Verfügbarkeit, Vertraulichkeit
1#define NAME_TYPE 1
2#define ID_TYPE 2
34
struct MessageBuffer {
5int msgType;
6union {
7char *name;
8int nameID;
9}; };
1011
int main (int argc, char **argv) {
12struct MessageBuffer buf;
13char *defaultMessage = "Hello World";
14buf.msgType = NAME_TYPE;
15buf.name = defaultMessage; // printf("*buf.name %p", buf.name);
16buf.nameID = (int)(defaultMessage + 1); // printf("*buf.name %p", buf.name);
17if (buf.msgType == NAME_TYPE) printf("%s\n", buf.name);
18else printf("ID %d\n", buf.nameID);
19}
Welche Ausgabe erzeugt das Programm?
1my $UserPrivilegeArray = ["user", "user", "admin", "user"];
2my $userID = get_current_user_ID();
3if ($UserPrivilegeArray eq "user") {
4print "Regular user!\n";
5}
6else {
7print "Admin!\n";
8}
910
print "\$UserPrivilegeArray = $UserPrivilegeArray\n";
Eine Anwendung führt eine kritische Funktion aus, ohne die Identität des Nutzers zu überprüfen. Kritischer Funktionen sind solche, die entweder signifikante Ressourcen verbrauchen oder nur von privilegierten Nutzern ausgeführt werden sollten.
"alle"
manuelle Code Reviews
statische Analyse (Binärcode und/oder Quellcode)
gemeinnützige Stiftung, die sich für die Verbesserung der Sicherheit von Software einsetzt
2001 gegründet
weltweit tätig
Stellt insbesondere Foren, Dokumente und Werkzeuge bereit
Dokumente, die bei der Entwicklung sicherer Anwendungen unterstützen:
Ausgewählte Projekte:
malloc verstehen
Benenne die Schwachstelle(n) entsprechend der CWEs (ohne ID).
Identifiziere die für die Schwachstelle(n) relevanten Zeilen im Code.
Gebe - falls möglich - einen Angriffsvektor an.
Skizziere mögliche Auswirkung der Schwachstelle(n) (z. B. Verlust der Vertraulichkeit, Integrität oder Verfügbarkeit; Umgehung der Zugriffskontrolle; beliebige Codeausführung, ...)
1#include <stdio.h>
2#include <string.h>
3void process(char *str) {
4char *buffer = malloc(16);
5strcpy(buffer, str);
6...
7// ... definitively executed in the future: free(buffer);
8}
9int main(int argc, char *argv[]) {
10if (argc < 2) { printf("Usage: %s <string>\n", argv[0]); return 1; }
11process(argv[1]);
12return 0;
13}
REST API
Sie analysieren eine REST API die folgendes Verhalten aufweist, wenn man einem Blog einen Kommentar hinzufügen möchte:
1POST /post/comment HTTP/1.1
2Host: important-website.com
3Content-Length: 100
45
postId=3&comment=This+<post>+was+helpful.&name=Karl+Gustav
Fragt man danach den Webservice nach dem Kommentar, dann erhält man folgendes zurück:
1<div class="comment">
2<div class="name">Karl Gustav</div>
3<div class="comment">This <post> was helpful.</div>
4</div>
Bewerten Sie die Schwachstelle: CWE Name, problematische Codestelle(n), möglicher Angriffsvektor und mögliche Auswirkung.
SQL Abfrage mit Java
Java:
1String query =
2"SELECT account_balance FROM user_data WHERE user_name = "
3+ request.getParameter("customerName");
4try {
5Statement statement = connection.createStatement( ... );
6ResultSet results = statement.executeQuery( query );
7}
Bewerten Sie die Schwachstelle: CWE Name, problematische Codestelle(n), möglicher Angriffsvektor und mögliche Auswirkung.
Bemerkung
URL Encoding
Leerzeichen
"
<
>
/
Verwendung von HTTP Query Parametern
Sie beobachten folgendes Verhalten einer Webseite:
Anfrage
1https://my-website.com/search?
2term=This%20is%20a%20%3C%22%3Egift%3C%2F%22%3E
Antwort
1<div class="search-result">
2<div class="title">This is a <">gift</"></div>
3</div>
Bewerten Sie die Schwachstelle: CWE Name, problematische Codestelle(n), möglicher Angriffsvektor und mögliche Auswirkung.