Vogelspotten
Tijdens mijn scriptieonderzoek naar honeypots heb ik het MySQL-authenticatieprotocol bestudeerd. Ik ben begonnen met het vergelijken van implementaties van reeds beschikbare honeypots, waaronder die van OpenCanary. Tijdens deze vergelijking merkte ik echter een discrepantie op tussen de foutmeldingen van een authentieke MySQL-server en die van OpenCanary.
Initiële bevinding
Als je met ongeldige inloggegevens probeert in te loggen op een MySQL server, krijg je een foutmelding terug met een zogeheten “SQL state”. Deze states staan beschreven in de documentatie van MySQL zelf. De sectie in dit pakketje moet starten met een hekje (#
) en wordt gevolgd door exact vijf karakters die de “SQL state” beschrijven. De implementatie van OpenCanary maakt echter gebruik van twee hekjes waardoor de rest van het bericht één byte verschuift.
Standaard MySQL-foutmelding:
OpenCanary-foutmelding (het hekje past de syntax highlighting aan):
De code
Onderstaand de code die de foutcode binnen OpenCanary afhandelt:
Het probleem zit in de \x23#
, aangezien de code voor een hekje 23 is. Nu staat er dus een feitelijk ##
terwijl het maar een hekje moet zijn. Dan is er nog een foutje met de “SQL state” die gegeven wordt na het inloggen met foutieve inloggegevens. Deze staat in de code als 2800
terwijl dat 28000
moet zijn.
Het foutje gebruiken als aanval
Een honeypot kan voor meerdere dingen gebruikt worden, in wezen is het een apparaat dat doet alsof hij een interessante server is. Dit maakt zo’n honeypot een aantrekkelijk doelwit voor hackers. Over het algemeen is het doel van een honeypot dus ook om aangevallen te worden. Dit heeft namelijk een aantal voordelen:
- Je weet dat er hackers aanwezig zijn in je netwerk waardoor je er meteen op kan acteren.
- Je kan uitvinden wat voor exploits ze gebruiken of naar wat voor data ze op zoek zijn door de informatie uit je honeypot te analyseren.
- Aanvallers verdoen hun tijd met het hacken van je honeypot in plaats van het hacken van je daadwerkelijke infrastructuur.
In het kort: als de honeypot wordt aangevallen zat deze hiervan een melding maken. Zo kan je de hackers aanpakken terwijl de aanval nog bezig is. Het is daarom ook belangrijk dat het niet duidelijk is dat jouw honeypot een honeypot is. Vergelijk het met een lokauto van de politie: het zou het doel erg teniet doen als een dief van buiten kon zien dat hij met een lokauto te maken heeft.
Het foutje in deze implementatie zorgt er dus voor dat we kunnen zien dat we niet met een echte MySQL server te maken hebben. We moeten hiervoor wel inloggen wat er weer voor zorgt dat de beheerders van de honeypot op de hoogte worden gebracht.
Is er dan een manier om een foutmelding terug te krijgen zonder dat we het alarm activeren? Het blijkt van wel! Het protocol van MySQL stelt dat pakketjes genummerd dienen te worden. De server start met de conversatie en stuurt een pakketje met alle mogelijkheden. Dit is pakketje nul:
De client stuurt dan een antwoord naar de server met z’n eigen mogelijkheden en de gebruikersnaam waar deze mee wil inloggen. Dit pakketje moet nummer een hebben:
Wanneer een client een pakketje stuurt dat niet de juiste nummering hanteert zal MySQL antwoorden met een foutmelding: Got packets out of order
, deze heeft dan een SQL state van 08S01
. Maar door de dubbele haakjes in de foutmelding kunnen we twee dingen opmerken:
- De dubbele haakjes zelf.
- De foutmelding start met het laatste getal van de SQL state
De code hierachter is als volgt:
We zien een if
-statement, deze kijkt of het pakket dat binnengekomen is het juiste nummer heeft. Zo niet dan geeft de server een foutmelding terug aan de client. Alleen is de logica die een log stuurt naar de beheerders pas na deze check. Op regel drie wordt er dus een foutmelding gegenereerd en de connectie wordt opgeheven. We kunnen dus een pakket met het verkeerde pakketnummer sturen om zo een Got packets out of order
te forceren. Dan kunnen we kijken of we de dubbele hashtag zien, als dat zo is dan weten we dat we met een OpenCanary te maken hebben.
Mitigatie
Ik heb een patch gemaakt met 2 kleine aanpassingen aan de module:
Er is een extra nul toegevoegd aan de SQL_STATE_ACCESS_DENIED
en de \x23
is uit de byte string gehaald in de foutmelding-logica.
Ik heb contact gezocht met de mensen van Thinkst (die het OpenCanary project beheren) en de patch is binnen twee dagen uitgerold
Conclusie
Er is een manier gevonden om een OpenCanary te identificeren de de MySQL-module draait. Deze detectie kan worden uitgevoerd zonder dat dat een alarm activeert en omzeilt daarmee het doel van een honeypot.
Het team van Thinkst heeft snel gereageerd op mijn mail en het probleem is binnen twee dagen verholpen. Als je OpenCanary gebruikt is het advies om zo snel mogelijk te upgraden naar versie 0.6.1! Mocht dat niet mogelijk zijn op dit moment dan is het belangrijk om de MySQL-module uit te schakelen.
Referentie: https://nielsvangijzen.com/nl/post/birdwatching/