英雄背景无分隔线
指导方针

SQL 注入

Es ist Zeit, die SQL-Injection zu betrachten. Lange Zeit war der unangefochtene König der OWASP Top 10, wir sprechen von Jahren hintereinander. Obwohl es so alt ist (etwa über 20 Jahre), und obwohl es leicht vom ersten Platz auf dieser Liste gefallen ist, ist es immer noch eine unglaublich beliebte und gefährliche Sicherheitslücke.

Als Sicherheitslücke im Internet ist SQL Injection (SQLi) immer noch eine der häufigsten Hacking-Techniken, die von Angreifern verwendet werden, da sie ihnen ermöglichen, eine Datenbank zu manipulieren und wichtige Informationen daraus zu extrahieren. Es ist immer noch alarmierend, dass ein Angreifer selbst zum Administrator des Datenbankservers machen kann und einige wirklich verheerende Dinge tun können, z. B. Datenbanken zerstören, Transaktionen manipulieren, Daten preisgeben und sie anfällig für weitere Probleme machen.

Schauen wir uns kurz an, wie es passiert

SQL (or Structured Query Language) is the language, that is used for the communication with relationalen databases; it is the query language, that is used by Developer, database administrators and applications, to manage the big data mengen, die täglich generiert werden.

In einer Anwendung gibt es zwei Kontexte: einen für Daten, den anderen für Code. The code context teilt Computer mit, was sie ausführen sollten, und trennt ihn von den zu verarbeitenden Daten. A SQL Injection is, if an provider data input, that are used from SQL interpreter, as code can be used as code, as the value information of the application can be access.

Wirkt auf eine SQL Injection Agreist

Eine SQL-Injection kann für jede Webanwendung extrem schädlich sein und war die bevorzugte Technik hinter so vielen aufsehenerregenden Sicherheitslücken, da sie unbefugten Zugriff auf wichtige Daten bietet. Sie können so viele Informationen einsehen, von Dingen wie Benutzernamen und Passwörtern bis hin zu Kreditkartendaten und persönlichen Identifikationsnummern.

When the access to these data has lost, they can allow to reset the password, a increased online purchase company or other (much worst) types of betrug.

Aber das ist vielleicht alarmierendste an SQLi, dass ein Angreifer, wenn er unentdeckt bleibt, über lange Zeiträume eine Hintertür im System aufrechterhalten kann. Wie Sie sich vorstellen können, würde dies zu wiederholten Datenschutzverletzungen führen, unabhängig davon, wie lange die Hintertür offen gehalten wird. Gruseliges Zeug.

Wir schauen uns ein paar Beispiele an, um besser zu verstehen, wie das in Aktion aussieht.

SQLi 示例

SQLi beinhaltet verschiedene Schwachstellentechniken, mit denen verschiedene Situationen bewältigt werden können. Im Folgenden sind nur einige der gängigsten SQLI-Beispiele aufgeführt:

技术 说明
检索隐藏数据 利用这种技术,攻击者可以修改任何 SQL 查询,从数据库中收集更多信息。
数据检查 攻击者可以提取有关数据库版本和结构的信息,这有助于他们利用更多信息。这种技术可能因数据库而异。
工会攻击 攻击者可以提取有关数据库版本和结构的信息,这有助于他们利用更多信息。这种技术可能因数据库而异。
盲 SQLi 利用 Blind SQLi,攻击者可以在数据库中实现查询。但问题是,攻击者控制着这个查询,而且它不会在应用程序的响应中返回任何结果。
颠覆应用逻辑 攻击者会干扰或操纵查询,从而破坏应用程序的逻辑。要篡改查询,攻击者可以将 SQL 注释序列"--"和 WHERE 子句结合起来。

SQLI-types

Okay, wir schauen uns jetzt die drei verschiedenen SQLI-Typen an.

In-Band-SQLI

This is a the gebräuchlichsten, einfachsten and efficient types of SQL injection. This art of angriffs is used the same communication canal, to access and call the result or the results.

Im Folgenden sind die beiden Arten von In-Band-SQLI-angriffen aufgeführt:

  • Union-basiertes SQLi - The Union based attack used the Union Operator, to combine two or more SQL questions as SELECT instructions, to call the required information and receive a http-get response.
  • Fail-basiertes SQLi - Der Angreifer nutzt die Fehlermeldungen der Datenbank, um deren Struktur zu verstehen. Bei diesem Angriff sendet der Angreifer möglicherweise falsche Anfragen oder Aktionen, sodass der Server fehlermeldungen anzeigt, sodass er Datenbankinformationen empfangen kann. Aus diesem Grund ist es wichtig, dass Entwickler vermeiden, Fehler senden oder Meldungen in der Live-Umgebung protokollieren. Stattdessen sollten sie mit eingeschränktem Zugriff gespeichert werden.

Inferenz-SQLI

Inferenzielle or blind SQLI-attacks are complicated and can take more time in request. Darüber hinaus erhält der Angreifer die Angriffsergebnisse nicht sofort, was es zu einem blinden Angriff macht.

The provider has sent the payloads per HTTP request to the database server, to change the database of the user. Anschliessend beobachtet er die Reaktion und das Verhalten der Anwendung, um festzustellen, ob der Angriff erfolgreich war oder nicht.

Es gibt zwei Arten von Inferenz-SQLI-angriffen:

  • Boolesche Blind-SQLI - Bei diesem Angriff wird eine Abfrage an die Datenbank gesendet, die das boolesche Ergebnis (wahr oder falsch) erhält, und der Angreifer beobachtet die HTTP-Antwort, um das boolesche Ergebnis vorherzusagen.
  • Zeitbasiertes blindes SQLi - Bei diesem Angriff sendet der Angreifer eine Anfrage an die Datenbank, bis sie einige Sekunden warten, bevor die Antwort gesendet wird. The attack, the query results from the response time of the HTTP request.

Out-of-Band-SQLI

This is a seltenere art of SQLI-Attacke, which used the activated functions of the database server. This happen in cases, when the attack types can not use other attack types.

Zum Beispiel, if they can not use same communication canal for the In-Band attack or the http response is not clear enough to determine the request results.
Darüber hinaus ist es nicht so häufig, da es stark auf die Fähigkeit des Datenbankservers angewiesen ist, HTTP- oder DNS-Anfragen zu stellen, um die benötigten Daten an den Angreifer zu senden.

So verteidigen Sie sich gegen SQLi

Zum Glück ist der Silberstreif am Horizont, dass SQL-Injection so alt und so verbreitet ist, dass es Möglichkeiten gibt, dies zu verhindern. The use such prevention procedure is not only an good programming gewohnheit, but also increases security of a company against SQLi.

Es gibt mehrere Möglichkeiten, Datenbankserver vor solchen Angriffen zu schützen, z. B. durch Eingabevalidierung, die Verwendung einer Web Application Firewall (WAF), die Sicherung von Datenbanken, den Einsatz von Sicherheitsteams oder Systemen von Dritten und das Schreiben von sicheren SQL-Abfragen.

Wir schauen uns ein Beispiel für die Verhinderung von SQL-Injections in Python an, indem Sie eine der oben genannten Sicherheitsmaßnahmen anwenden.

Python example

In this example used the provider a boolean blind sql injection to call important information from the system.

Python: Verwundbar

Angenommen, es gibt eine Tabelle mit dem Namen „sample_data“ in der Datenbank. In this table are saved the user names and the password for the users of the application.

You allow the users now to find a value from this database table with the following order:

importiere mysql.connector
db = mysql.connector.connect
#Bad -Praxis. Vermeide das! Das ist nur zum Lernen.
(host="localhost „, user="newuser „, passwd="pass „, db="sample „)
cur = db.cursor ()
name = raw_input ('Name eingeben: ')
cur.execute („SELECT * FROM Sample_DATA WHERE Name = '%s';“% name) für Zeile in cur.fetchall (): print (row)
db.schließen ()

SQL 注入

If the users in the search a name, for example Alicia, is the no problem with the output.

Wenn der Benutzer jedoch etwas wie Alicia'; DROP TABLE sample_data; eingibt, hat dies erhebliche Auswirkungen auf die Datenbank.

Python: Problembehebung

The SQL instruction should be changed how following to prevent the attack:

cur.execute („SELECT SIE * AUS BEISPIELDATEN AUS, WOBEI Name = %s;“, (name,))

Now processing the system the user input as a zeichenfolge, also if the user has entered SQL questions, and processing the user input only as value of the name.

This simple change can prevent böswillige aktivitäten at future questions and the system before angriffs by user input.

Java-Example

For this example we also use a database table with the name „sample_data“, are saved in the user data of the application.

A simple login page requires an user name and a password as the java file that an servlet (loginServlet) from the database is valid, to allow the login process.

Java: Anfälliges Beispiel

The system users, using the table „sample_data“ in the database, enable the system users to use their protocol data as access.

In der LoginServlet-Datei befindet sich eine Anfrage, die den Anmeldevorgang berücksichtigt. Das ist:

//Schlechtes Beispiel. Use keine Verkettung von Zeichenketten.
String query = „Wähle Sie* aus den Beispieldaten, wobei Benutzername='“ + Nutzername + „'und Passwort ='“ + Passwort + „'“;
Connection conn = null;
Ausdrücke stmt = null;
versuche {
conn = DriverManager.getConnection („jdbc: mysql: //127.0.0. 1:3306 /user“, „root“, „root“);
stmt = conn.createStatement ();
ResultSet rs = stmt.executeQuery (Abfrage);
wenn (rs.next ()) {
//Anmeldung erfolgreich, wenn ein Match gefunden wurde
erfolg = wahr;
}
} catch (Ausnahme e) {
e. printStackTrace ();
} endlich {
versuche {
stmt.close ();
conn.close ();
} catch (Ausnahme e) {}
}
wenn (erfolg) {
response.sendRedirect („home.html „);
} sonst {
response.sendRedirect („login.html? fehler=1");
}
}

Es folgt die Anfrage für die Benutzeranmeldung:

wähle * aus den Beispieldaten, wobei Benutzername='Benutzername' und Passwort ='Passwort'

SQL 注入

Das System funktioniert einwandfrei, wenn die Eingabe gültig ist. As example we, the user name is wieder Alicia and the password is geheim.

The system is back the data of the user with this login information. Ein Angreifer kann die Benutzeranfrage jedoch mithilfe von Postman und cURL für die SQL-Injection manipulieren.

Zum Beispiel kann der Hacker einen Dummy user name (Alicia) and the password 'or' 1 '=' 1 'senden.

In diesem Fall stimmen der Benutzername und das Passwort nicht überein, aber die Bedingung '1='1' ist immer wahr, sodass der Anmeldevorgang erfolgreich ist.

Java: Provention

Zur Vorbeugung müssen wir den LogInvalidation-Code ändern und PreparedStatement statt Statement for the question verwenden. This change prevent the connection of user and password in the question and use as Setter data, to prevent a SQL injection.

Unten ist der geänderte Code für LogInvalidation:

Zeichenkettenabfrage = „Wählen Sie* aus den Beispieldaten, wobei Benutzername=? and password =? „;
Connection conn = null;
PreparedStatement stmt = null;
versuche {
conn = DriverManager.getConnection („jdbc: mysql: //127.0.0. 1:3306 /user“, „root“, „root“);
stmt = conn.prepareStatement (Abfrage);
stmt.setString (1, Nutzername);
stmt.setString (2, Passwort);
Ergebnissatz rs = stmt.executeQuery ();
wenn (rs.next ()) {
erfolg = wahr;
}
rs.close ();
} catch (Ausnahme e) {
e. printStackTrace ();
} endlich {
versuche {
stmt.close ();
conn.close ();
} catch (Ausnahme e) {
}
}

This case are the PreparedStatement, the Setter and the base jdbc api for user input and prevent the SQL injection.

实例

Jetzt schauen wir uns noch ein paar Beispiele in verschiedenen Sprachen, um besser zu verstehen, wie das in Aktion aussieht.

C# - Unsicher

This example is unsicher, da es `fromRawSQL` benutzt. This method binds the parameter not and versucht nicht, sie zu maskieren. This method should be avoid by any price.

var blogs = Context.Beiträge
.fromRawSQL („WÄHLE DICH AUS * AUS BEITRÄGEN AUS, WITH THE STATE = {0} UND author = {1}“, Bundesland, Autor)
.toList ();

C# - Sicher

This example is safe by `fromSQLInterpolated`, that the interpolierten values and their parameters.

Obwohl das im Allgemeinen sicher ist, besteht die Gefahr, dass `fromRawSQL` sehr ähnlich ist, was nicht sicher ist.

var blogs = Context.Beiträge
.fromSQLInterpolated ($"SELECT * FROM Posts WHERE state = {state} AND author = {author} „)
.toList ();

Java - Sicher: Hibernate - Benannte Abfrage + Native Abfrage

Hibernate bietet mit `Native Query` und `Named Query` zwei Methoden, um Abfragen auf sichere Weise zu erstellen. Beide ermöglichen die Angabe von Speicherorten für Parameter.

@NamedNativeQuery (
name = „find_post_by_state_and_author“,
abfrage =
„BITTE AUSWÄHLEN*“ +
„AUS DEM BEITRAG“ +
„WO state =:state“ +
„UND author =:author“,
Ergebnisklasse = Post.class)

Java
<Post>Beiträge auflisten = session.createNativeQuery (
„BITTE AUSWÄHLEN*“ +
„AUS DEM BEITRAG“ +
„WO state =:state“ +
„UND Autor =:author“)
.Identity hinzufügen (Post.class)
.setParameter („Zustand“, Zustand)
.setParameter („Autor“, Autor)
.liste ();

Java - Sicher: jplq

Durch das Kommentieren eines `Query`-Attributs auf einer Jplq-Repository-Schnittstelle können sie auf mehrere Formen zugreifen und sind parametrisiert.

@Query („WÄHLE P AUS“) Beitrag P WO u.state =? 1 und u.author =? 2")
Beitrag findPostByStateAndAuthor (String state, int author);
@Query („WÄHLE P AUS POST P AUS, WO u.state =:state und u.author =:author“)
Benutzer findPostByStateAndAuthor (@Param („state“) String state, @Param („author“) int author);

Javascript - Sicher: pg

The use of `PG`-library allows the `Query`-method of the parametrierung, if you specify parameter values over their second parameters.

const {posts} = await db.query ('SELECT * FROM POST WHERE state = $1 AND author = $2', [state, author])

Javascript - Sicher: Sequelize

The `Sequelize`-Bibliothek offers a possible, a question after your second argument for parametrierung, the settings for the question. Dazu gehört eine Liste von Werten, die als Parameter an die Abfrage gebunden sein sollten, entweder nach Namen oder Index.

warte auf sequelize.query (
'WÄHLE * AUS DEM BEITRAG WO state = $state = $state AND author = $author = $author',
{
binden: {Bundesland: Bundesland, Author: Author},
Typ: QueryTypes.Select
}
);
warte auf sequelize.query (
'CHOOSE * FROM THE POST, WITH THE STATUS = $1 AND THE AUTHOR = $2 IS ',
{
binden: [Bundesland, Autor],
Typ: QueryTypes.Select
}
);