Auch wenn die verarbeiteten Abfragen im Proxy bereits modifiziert wurden, besteht oft der Wunsch, die ermittelten Ergebnisse zu modifizieren oder gegebenenfalls Teilergebnisse zu unterbinden. Ermöglich wird dies durch die Lua-Funktion
»read_query_result()
«
.
Wichtig ist an dieser Stelle, das ohne vorherigen Aufruf der Funktion
»read_query()
«
die Funktion
»read_query_result()
«
nicht aufgerufen wird. So können Ergebnisse in Abhängigkeit zur Append-ID unter Verwendung der Directive
»proxy.PROXY_IGNORE_RESULT
«
wieder aus dem Ergebnis gefiltert werden. Der Code-Ausschnitt in
Listing 3
stellt den Zusammenhang zwischen Query-Injection und Änderung des Ergebnisses dar.
Listing 3
add_remove.lua
-- add_remove.lua function read_query( packet ) if packet:byte() == proxy.COM_QUERY then proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()" ) proxy.queries:append(1, packet ) proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()" ) return proxy.PROXY_SEND_QUERY end end function read_query_result(inj) if inj.id == 2 then for row in inj.resultset.rows do print("injected query returned: " .. row[0]) end return proxy.PROXY_IGNORE_RESULT else print("query-time: " .. (inj.query_time / 1000) .. "ms") print("response-time: " .. (inj.response_time / 1000) .. "ms") end end
Fügt der Datenbankprogrammierr in der ersten Funktion vor dem eigentlichen Befehl ein
»select now()
«
ein, um zum Beispiel entsprechende Performance-Werte zu protokollieren, so entfernt der Proxy dieses Queries in der zweiten Funktion wieder, sodass der Benutzer nichts von diesen Dingen mitbekommt.
Auf diese Weise können Vorgänge transparent innerhalb des Proxies ablaufen – ganz ohne Patch oder Update der vorhandenen Originalversion. Architektonisch betrachtet ist der Proxy nicht die richtige Stelle für die Weiterentwicklung der Datenbankanwendung. Der richtige Eingriffspunkt, um kurzfristigen Fehler zu beheben, ist es auf jeden Fall.
Bei der Auswertung der Abfrageergebnisse kann die Protokollierung der Abläufe helfen. Da alle Statements über die Funktion
»read_query()
«
zu ermitteln sind, bleiben hier nur die Ausgabeverarbeitung und etwaige Formatierungen zu klären. In den Proxy-Skripts steht dazu der ganze Sprachumfang von Lua zur Verfügung. Das Skript in
Listing 4
implementiert eine einfache Log-Datei.
Listing 4
write_logfile.lua
-- write_logfile.lua local file_log = 'myproxy.log' local fh = io.open(file_log, "a+") function read_query( packet ) if string.byte(packet) == proxy.COM_QUERY then local query = string.sub(packet, 2) fh:write( string.format("%s %6d -- %s \n", os.date('%Y-%m-%d %H:%M:%S'), proxy.connection["thread_id"], query)) fh:flush() end end
Nach Start des Proxies unter Angabe des Lua-Scripts könnte das MySQL-Log so aussehen wie in Listing 5 .
Listing 5
Logfile
2008-05-14 15:14:50 30 -- select @@version_comment limit 1 2008-05-14 15:14:53 30 -- SELECT DATABASE() 2008-05-14 15:14:56 31 -- select @@version_comment limit 1 2008-05-14 15:14:59 31 -- select USER() ...