Schlagwort-Archive: SQL

Gute Bücher (XV): Stuttard,Pinto – The Web Application Hacker’s Handbook

Dafydd Stuttard - The Web Application Hacker's Handbood

Dieses über 700 Seiten starke Buch zur Sicherheit von Web Anwendungen sollte jeder gelesen haben, der Web Anwendungen programmiert. Ich zumindest hätte dieses Buch viel früher lesen sollen, denn es wird einem nicht nur erklärt, welche Sicherheitsmechanismen es gibt, auf was man achten muss und wieso andere Vorgehensweisen in einem gewissen Kontext keinen Sinn machen, sondern auch wie ein typischer Hacker vorgeht, um Schwachstellen auszuspähen und zu benutzen.

Die Autoren arbeiten in einer Sicherheitssoftware-Firma, so dass das Buch durchweg praxisorientiert geschrieben ist. Neben den Standardschwächen wie SQL Injection, XSS, Command Injection oder Path Traversal wird auch darauf eingegangen, was ein Angreifer aus Fehlermeldungen ableiten kann. Auf Angriffspunkte von ActiveX und Java Applets wird genauso eingegangen wie auf die unterschiedlichen Methoden, mit denen ein Hacker relativ automatisiert eine Web Anwendung inklusive ihrer „versteckten“ Funktionalitäten erfassen kann.

Besonders interessant sind für mich solche SQL Injections, die keine Rückmeldung geben, da Fehlermeldungen und Ausgaben unterdrückt werden, aber mit Verzögerungen (Wait For-Anweisungen) Rückschlüsse auf das Ergebnis einer SQL-Anweisung ermöglichen.

Sehr ausführlich werden die zusammen gehörenden Bereiche Authentication, Session Management und Access Control besprochen. Und hier wird nicht zu unrecht darauf hingewiesen, dass Funktionen wie Zugangsdaten vergessen oder neues Passwort setzen generell Schwachstellen bieten können, um die Authentifizierung zu umgehen und zu verifizieren, welche User es in der Anwendung gibt.

Um es auf den Punkt zu bringen:
Ein absoluter Kaufbefehl!

(Jepp Felix, dieser Eintrag ist auch an dich gerichtet! ;o))

SQL IN und =

Da erschafft man einen völlig neuen Wettkampf, der von 31 Teams weltweit wahrgenommen wird. Hunderte von Menschen diskutieren in zig Foren in deutsch, englisch, französisch, russisch, chinesisch, spanisch, japanisch, tschechisch etc. über die beste Taktik, um diese Challenge zu gewinnen. Und man selber ist heilfroh, dass alles funktioniert: die Statistiken werden korrekt erstellt, die Daten werden richtig importiert, man hat sogar die Muße den Importvorgang in der laufenden Challenge noch ein wenig zu optimieren – Operation am offenen Herzen quasi…

Selbst der alte Server (im nächsten Monat gibt’s einen neuen) funktioniert trotz fast doppelt so hohen Besucherzahlen. Und man denkt: Mensch, wat biste fürn dufter Typ?! Klappt ja alles 1A!

Und dann kommt die Hiobsbotschaft der Serverload ist manchmal 10.00. Irgendetwas stimmt nicht. Irgendeine Anfrage dauert zu lange. Man überprüft die Seiten und stellt fest, dass eine Abfrage dabei ist, die anfangs nur wenige Millisekunden gebraucht hat, jetzt aber 70 Sekunden braucht.. Eine typische Anfrage:
[code lang=’sql‘]SELECT
[…]
output_24h
FROM
pentathlon_score
INNER JOIN
pentathlon_team
ON pentathlon_score.teamid = pentathlon_team.teamid
WHERE
zeitpunkt IN (SELECT max(zeitpunkt) FROM pentathlon_score WHERE disziplinid= 1) AND
disziplinid = 1 AND
Rank > 0
ORDER BY Rank ASC[/code]
Und schließlich stellt man fest, dass wenn man das IN durch ein = ersetzt, die Anfrage plötzlich nur noch 0,05 Sekunden dauert.
[code lang=’sql‘]SELECT
[…]
output_24h
FROM
pentathlon_score
INNER JOIN
pentathlon_team
ON pentathlon_score.teamid = pentathlon_team.teamid
WHERE
zeitpunkt = (SELECT max(zeitpunkt) FROM pentathlon_score WHERE disziplinid= 1) AND
disziplinid = 1 AND
Rank > 0
ORDER BY Rank ASC[/code]
und das, obwohl die Unterabfrage SELECT max(zeitpunkt) […] nur einen Wert zurück gibt..!?!

Komplizierteste SQL-Query ever

Es gibt so ein tolles Zitat:

“Was nicht auf einer einzigen Manuskriptseite zusammengefasst werden kann, ist nicht durchdacht und nicht entscheidungsreif.”

Wenn man das auf meine SQL-Abfrage überträgt, muss ich wohl eingestehen, dass diese Abfrage undurchdacht wäre. Ist sie aber nicht! Ich habe 3 Tage an dieser Abfrage zugebracht, damit sie das Ergebnis ausgibt, welches sie jetzt ausgibt.

Die Abfrage ist für ein Wettkampf, der aus mehreren Einzeldisziplinen besteht, die an unterschiedlichen Tagen veranstaltet werden (zeitgleich und hintereinander). Der Wettkampf ist für Teams. Für jede Einzeldisziplin ist die DisziplinId, TeamId, Platz, Datum, Punktestand vorhanden. Allerdings wird für die Gesamtwertung nicht der Punktestand in der Einzeldisziplin genommen, sondern inder Gesamtwertung werden neue Punkte anhand der Platzierung in der Einzeldisziplin vergeben – z.B. so: Platz 1 – 100 Punkte, Platz 2 – 90 Punkte, usw.

Es klingt schon so natürlich sprachlich kompliziert und ehe ich hier weitere Einzelheiten versuche zu erklären, platziere ich hier einfach die 117 Zeilen lange SQL-Abfrage:
[code lang=’sql‘]
SELECT
@anzTeam := (SELECT COUNT(*) FROM pentathlon_team WHERE freigeschaltet=’1′),
@seq := @anzTeam + 1,
@rank := @anzTeam,
@letzteDatum := (SELECT DISTINCT SUBSTR(MIN(zeitpunkt),1,10) FROM pentathlon_score WHERE pentathlon_credits != 0),
@letztePunkte := 999999;
SELECT
gesamt.teamid,
@seq := IF(@letzteDatum = gesamt.zeitpunkt, @seq – 1, @anzTeam) AS seq, /*Sequenz …,3,2,1 je Datum*/
@rank := IF(@letztePunkte = gesamt.punkte, @rank, @seq) AS rank, /*Der Rank eines Teams (wenn gleiche Punktzahl gleicher Rank)*/
@letztePunkte := gesamt.punkte AS punkte,
@letzteDatum := gesamt.zeitpunkt AS zeitpunkt
FROM
(SELECT
einzelgesamt.teamid,
SUM(einzelgesamt.punkte) AS punkte,
einzelgesamt.zeitpunkt AS zeitpunkt
FROM
(SELECT DISTINCT
normale_daten.zeitpunkt,
normale_daten.teamid,
normale_daten.disziplinid,
IF(normale_daten.punkte IS NOT NULL,
normale_daten.punkte,
IF((SELECT von FROM pentathlon_disziplin WHERE disziplinid = normale_daten.disziplinid) > normale_daten.zeitpunkt,
0, /*Disziplin noch nicht gestartet*/
(SELECT DISTINCT /*Disziplin ist beendet: Punkte des letzten Stands*/
IF (pentathlon_score.rank > 25,
0, /*Keine Punkte mehr ab Platz 25*/
pentathlon_punkte.punkte
) AS punkte
FROM
pentathlon_score
LEFT JOIN
pentathlon_punkte
ON
pentathlon_score.rank = pentathlon_punkte.rank
WHERE
pentathlon_score.disziplinid = normale_daten.disziplinid AND
pentathlon_score.teamid = normale_daten.teamid AND
pentathlon_score.zeitpunkt = (SELECT DISTINCT
MAX(zeitpunkt)
FROM pentathlon_score
WHERE disziplinid = normale_daten.disziplinid)
)
)
) AS punkte,
IF(normale_daten.rank IS NOT NULL,
normale_daten.rank,
IF((SELECT von FROM pentathlon_disziplin WHERE disziplinid = normale_daten.disziplinid) > normale_daten.zeitpunkt,
0, /*Disziplin noch nicht gestartet*/
(SELECT DISTINCT /*Disziplin ist beendet: Punkte des letzten Stands*/
pentathlon_score.rank
FROM
pentathlon_score
WHERE
pentathlon_score.disziplinid = normale_daten.disziplinid AND
pentathlon_score.teamid = normale_daten.teamid AND
pentathlon_score.zeitpunkt = (SELECT DISTINCT
MAX(zeitpunkt)
FROM pentathlon_score
WHERE disziplinid = normale_daten.disziplinid)
)
)
) AS rank
FROM
(SELECT DISTINCT
alle_daten.zeitpunkt,
alle_daten.teamid,
alle_daten.disziplinid,
pentathlon_score.rank,
IF (pentathlon_score.rank > 25,
0, /*Keine Punkte mehr ab Platz 25*/
pentathlon_punkte.punkte
) AS punkte
FROM
(SELECT DISTINCT
SUBSTR(pentathlon_score.zeitpunkt,1,10) as zeitpunkt,
pentathlon_team.teamid,
pentathlon_disziplin.disziplinid,
pentathlon_teamdisziplin.webrpc
FROM
pentathlon_score
JOIN
pentathlon_team
JOIN
pentathlon_disziplin
INNER JOIN
pentathlon_teamdisziplin
ON pentathlon_disziplin.disziplinid = pentathlon_teamdisziplin.disziplinid
WHERE
pentathlon_score.pentathlon_credits != 0 AND
pentathlon_team.freigeschaltet = ‚1‘) AS alle_daten
LEFT JOIN
pentathlon_score
ON
alle_daten.teamid = pentathlon_score.teamid AND
alle_daten.disziplinid = pentathlon_score.disziplinid AND
IF(SUBSTR(alle_daten.webrpc,1,33) = ‚http://www.worldcommunitygrid.org‘,
alle_daten.zeitpunkt = SUBSTR(pentathlon_score.zeitpunkt,1,10),
alle_daten.zeitpunkt = DATE_ADD(SUBSTR(pentathlon_score.zeitpunkt,1,10), INTERVAL -1 DAY) AND
SUBSTR(pentathlon_score.zeitpunkt,12,2)=’01‘
)

LEFT JOIN
pentathlon_punkte
ON
pentathlon_score.rank = pentathlon_punkte.rank) AS normale_daten

) AS einzelgesamt
GROUP BY
einzelgesamt.zeitpunkt,
einzelgesamt.teamid
) AS gesamt
ORDER BY
gesamt.zeitpunkt,
gesamt.punkte DESC
[/code]
Natürlich hätte ich das auch alles durch einfache Abfragen lösen können, die ich dann in PHP zusammenfüge, aber in PHP ist das einfügen und sortieren der Daten so ineffizient.

Die @variable sind User-Variablen in MySQL, mit denen man die Platzierung in der Abfrage berechnen kann.

Jetzt würde ich meine Fähigkeiten in SQL mit einer 1,2 benoten.. ;)