Tag: linux

automx howto ergaenzung

damit ich es irgendwann mal wieder finde… als ergรคnzung zu dem automx howto:

auf einem debian system werden noch folgende, zusaetzliche python module benoetigt:

apt-get install libapache2-mod-wsgi python-mysqldb python-dateutil python-ipaddr python-lxml python-memcache python-m2crypto python-sqlalchemy

in der apache konfiguration wird ausserdem noch diese option benoetigt:

Options +MultiViews

wheezy, apache2, nscd und die startreihenfolge

in debian ist mittlerweile im header jedes init scriptes eine LSB section zu finden. damit koennen u.a. die abhaengigkeiten zwischen den verschiedenen diensten abgebildet werden.

ich hatte einen fall, in dem die user eines webservers in einer mydsql datenbank stehen und der start des apache nach einem reboot fehlschlaegt, wenn nscd noch nicht gestartet ist. in diesem falle sieht die quick and dirty loesung so aus, dass muss ein “nscd” ans ende der “Required-Start”-Zeile haengt… in der datei /etc/init.d/apache2 …also so:

(scrollen zum zeilenende)

#!/bin/sh
### BEGIN INIT INFO
# Provides:          apache2
# Required-Start:    $local_fs $remote_fs $network $syslog $named nscd
# Required-Stop:     $local_fs $remote_fs $network $syslog $named nscd
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# X-Interactive:     true
# Short-Description: Start/stop apache2 web server
### END INIT INFO

danach muss man noch diesen befehl ausfuehren:

update-rc.d apache2 defaults

und beim naechsten reboot ist alles gut ๐Ÿ˜‰

wenn die mysql replikation mal klemmt

wenn die mysql replikation aufgrund eines fehlers in einem statement mal aussteigt, dann muss man dieses statement einfach weg lassen ๐Ÿ˜‰

im logfile (bei debian /var/log/daemon.log) steht dann so ein kram:

Query caused different errors on master and slave. Error on 
master: 'Table '%-.64s' already exists' (1050), Error on 
slave: 'You have an error in your SQL syntax; check the manual 
that corresponds to your MySQL server version for the right 
syntax to use near '' at line 1' (1064). 
[...]
[ERROR] Error running query, slave SQL thread aborted. Fix 
the problem, and restart the slave SQL thread with "SLAVE 
START". We stopped at log 'mysql-bin.003535' position 91778974

oder wenn man sich den slave status auf der commandline ansieht:

SHOW SLAVE STATUS \G

was solch einen output liefert.

mysql> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: xxx.xxxxxx.xxx
                Master_User: replication
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysql-bin.003535
        Read_Master_Log_Pos: 97111481
             Relay_Log_File: host-relay-bin.007674
              Relay_Log_Pos: 91779321
      Relay_Master_Log_File: mysql-bin.003535
           Slave_IO_Running: Yes
          Slave_SQL_Running: No
                       [...]

wenn da nun “Slave_SQL_Running” auf “No” steht, weiss man, dass die replikation nicht laeuft.

wenn man sich nun sicher ist, dass das naechste statement vom master nicht benoetigt wird (weils wie in diesem falle hier zu einem fehler fuehrt), kann man dieses kommando ausfuehren, um ein statement zu ueberspringen:

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; 
START SLAVE;

weitere hilfe und bemerkungen dazu auf den mysql development seiten.

backup der owncloud kalender per cron

fรผr den export bzw backup mehrerer kalender einfach das script fuer das backup des adressbuches abwandeln. das funktioniert nach dem gleichen prinzip wie beim adressbuch. da ich aber mehrere kalender habe, musste dazu noch eine for schleife rein.

sofern man mehrere adressbuecher hat, kann man mit anpassungen dieses scriptes auch diese sichern.

#!/bin/bash

OCUSER=meinusername
OCPASS=meinpasswort
OCHOST=https://owncloud.domain.tld
# die calid am ende wird in der for schleife angehaengt
OCCALENDARURL=$OCHOST'/index.php/apps/calendar/export.php?calid='
# das "--no-check-certificate" ist unschoen
WGETPARAMS='--no-check-certificate --auth-no-challenge'
WGETAUTH='--http-user='$OCUSER' --http-password='$OCPASS
MYDATE=`date +%Y%m%d%H%M%S`
# in diesen ordner werden die backups abgelegt
OUTFOLDER=/home/ich/ocbackup

# array mit den calendar id's
declare -a array=(2 3 4 5 6 9 10 11 12)

# einfuegen der calid in dateiname und url. dann runterladen und packen
for i in ${array[@]}
do
    OUTFILE=$OUTFOLDER'/calendar_'$OCUSER'_id'$i'_'$MYDATE'.ics'
    wget $WGETPARAMS $WGETAUTH -O $OUTFILE $OCCALENDARURL$i
    gzip $OUTFILE
done

# backups aelter 30 tage loeschen
find $OUTFOLDER -maxdepth 1 -type d -name 'calendar*' -mtime +30 -exec rm -rf {} \;

script abspeichern, die “calid”s in dem array an die eigenen gegebenheiten anpassen, ausfuehrbar machen und einen cronjob anlegen. die “calid” findet man in den einstellungen des kalenders. einfach mit der rechten maustaste den link bei “herunterladen” kopieren.

20130628_occalendar

(stand: ownCloud 5.0.7)

backup des owncloud adressbuches per cron

hier ein kleines script, um vom owncloud adressbuch eines users ein backup zu erstellen. bei einer selbst gehosteten owncloud macht man normalerweise ein mysql backup und hat damit auch gleich das adressbuch gesichert. wenn man allerdings keinen shellzugriff hat, kann man sich mit diesem kleinen script behelfen, welches die exportfunktion von owncloud nutzt. gerade wenn man noch im “testbetrieb” ist und mit zig geraeten (mit durchaus unterschiedlichem verhalten) gleichzeitig auf das adressbuch zugreift, will man vielleicht auch mal ein solches backup haben – fuer den fall, dass doch etwas schief geht. gebraucht habe ich das bis jetzt noch nicht, aber wer weiss…

#!/bin/bash

OCUSER=meinusername
OCPASS=meinpasswort
OCHOST=https://owncloud.domain.tld
# die "bookid" am ende anpassen!
OCABOOKURL=$OCHOST'/index.php/apps/contacts/export.php?bookid=2'

# das "--no-check-certificate" ist unschoen
WGETPARAMS='--no-check-certificate --auth-no-challenge'
WGETAUTH='--http-user='$OCUSER' --http-password='$OCPASS
MYDATE=`date +%Y%m%d%H%M%S`
# in diesen ordner werden die backups abgelegt
OUTFOLDER=/home/ich/ocbackup
OUTFILE=$OUTFOLDER'/abook_'$OCUSER'_'$MYDATE'.vcf'

wget $WGETPARAMS $WGETAUTH -O $OUTFILE $OCABOOKURL
# packen und das original loeschen
gzip $OUTFILE

# backups aelter 30 tage loeschen
find $OUTFOLDER -maxdepth 1 -type d -name 'abook*' -mtime +30 -exec rm -rf {} \;

20130628_ocexportdie url bzw speziell die “bookid” muss man sich in seinem owncloud account raussuchen. dazu geht man im adressbuch in die einstellungen und kopiert sich die export url mit der rechten maustaste und passt das script an:

das “find” am ende loescht die backupdateien, die aelter als 30 tage sind. das script speichert man sich ab, macht es ausfuehrbar und fuehrt es so oft wie es beliebt per crojob aus.

(stand: ownCloud 5.0.7)

apache autschn?

das bedeutet bestimmt nix gutes…

Bildschirmfoto 2013-06-14 um 10.00.37

dns amplification (2)

den kram von gestern wollte ich noch ein wenig verfeinern. im logfile des bind konnte ich auf einen blick erkennen, dass diese beiden die groesste menge der (mittlerweile “sinnlosen”) abfragen darstellt:

[...] query: deniedstresser.com IN ANY +E
[...] query: . IN RRSIG +E

um nur genau diese per iptables raus zu filtern, muss man erstmal im netzwerkverkehr mithorchen, um sich dann die genauen strings rauszusuchen. das macht man am einfachsten mit dem tool tcpdump, welches anders als der name vermuten laesst auch udp und icmp mitschneiden kann ๐Ÿ˜‰

tcpdump -i eth0 -s 0 -w /tmp/tcpdump.dump udp port 53

die damit erzeugte datei schaut man sich am besten mit wireshark an und sucht sich die entsprechenden teile der pakete raus:

20130521_iptables_string2

20130521_iptables_string1

die relevanten (im screenshot markierten) teile, nach denen ich filtern wollte, sind dann in hexadezimaler schreibweise diese:

# hex fuer "deniedstresser.com: type ANY, class IN"
0e 64 65 6e 69 65 64 73 74 72 65 73 73 65 72 03 63 6f 6d 00 00 ff 00 01 00
# hex fuer ": type RRSIG, class IN"
00 00 2E 00 01 00 00 29

die abfrage des typs ANY kann ich bedenkenlos komplett rausfiltern, da ich den abgefragten namen (deniedstresser.com) mit reingenommen habe. niemals hat dieser dns server genau diese abfrage zu beantworten.

iptables -I INPUT 1 -i eth0 -d xx.xx.xx.xx -p udp --dport 53 -m string --from 30 --algo bm --hex-string '|0e 64 65 6e 69 65 64 73 74 72 65 73 73 65 72 03 63 6f 6d 00 00 ff 00 01 00|' -j DROP

die abfrage nach der “recource record signature” der root zone darf ich nicht komplett rausfilter, da dem dns server vertrauete ipadressen sehr wohl genau diese abfrage machen koennen und duerfen. dafuer ist diese loesung mit iptables eigentlich eher ungeeignet. aber da ich weiss, dass die server mit den “vertrauten” ipadressen noch nichts mit DNSSEC am hut haben, nutze ich die regel erstens nur temporaer und zweitens sicherheitshalber nur wenn “geflutet” wird – sprich mehr als vier abfragen pro minuten von einer ipadresse kommt.

erst wieder die ip “taggen”:

iptables -I INPUT 2 -i eth0 -d xx.xx.xx.xx -p udp --dport 53 -m string --from 35 --algo bm --hex-string '|00 00 2E 00 01 00 00 29|' -m recent --name dnsrootrrsig --set

und die anfrage wegschmeissen, wenn der counter in 60 sekunden die vier erreicht hat, :

iptables -I INPUT 3 -i eth0 -d xx.xx.xx.xx -p udp --dport 53 -m string --from 35 --algo bm --hex-string '|00 00 2E 00 01 00 00 29|' -m recent --name dnsrootrrsig --rcheck --seconds 60 --hitcount 4 -j DROP

klar muessen die “angreifer” nur eine kleinigkeit an einer der abfragen aendern, um diese regeln zu umgehen. aber so schickt der dns server wenigstens nicht mal das “REFUSED” an den gefaelschten absender zurueck. ich hoffe ja, dass dieser “angriff” irgendwann vorueber ist, da der bind sowieso kein offener resolver mehr ist und somit fuer die angreifer uninteressant wird.

dns amplification und pfingsten

der nameserver eines kunden war versehentlich noch offen fuer anfragen aus aller welt und wurde fuer ddos attacken missbraucht. er kriegt eine kleine anfrage rein und schickt eine grosse antwort an die gefaelschte absende ip raus. dieses “verfahren” ist auch als “dns amplification” bekannt.

um eine gute amplification attacke zu machen, braucht es zwei dinge. das protokoll sollte keinen handshake benoetigen, damit man die absendeadresse faelschen kann. also entweder icmp oder udp um die (gefaelschte abfrage nach dem motto “fire and forget” los zu jagen. und dann sollte natuerlich die antwort um ein vielfaches groesser sein als die abfrage selber.

in dem mir vorliegenden falle wurde z.b. eine abfrage vom typ “ANY” auf die domain “deniedstresser.com” gemacht. so schaut das ganze dann aus: (das x.x.x.x repraesentiert den “offenen resolver”)

dig ANY deniedstresser.com @x.x.x.x

20130520_dnsddosdie antwort habe ich als verkleinertes bild (klick zum vergroessern) eingefuegt und auch noch etwas gekuerzt, weils einfach noch viel mehr ist. aufgrund der etwas ausgefallenen antwort vermute ich mal, dass diese domain genau fuer diesen einen zweck uebrhaupt existiert.

solche anfragen kamenzwischen 10 und 50 stueck pro sekunde von unterschiedlichen ipadressen (die gefaelschten natuerlich), wobei ungefaehr immer 10 die gleiche absende ip hatten. die menge ist nichts, womit ein einzelner dns server mit bind nicht fertig wuerde. aber da es wahrscheinlich noch hunderttausende offene dns resolver gibt, koennen die angreifer damit wunderbare attacken fahren.

aber wie wird man diese dinger nach dem beseitigen des problems wieder los? selbst wenn man den dns server so konfiguriert, dass er diese rekursiven anfragen nicht mehr aufloest, sendet er immerhin noch ein “REFUSED” mit ein bischen overhaed drumherum zurueck. das ist dann immernoch eine ddos attacke, aber wenigstens ohne nennenswerte “amplification”.

ein einfaches blocken per iptables ist auch nicht das wahre, denn:
die gefaelschten ips des absenders sind halt einfach gefaelscht. man blockt also jemanden, der eigentlich garnichts dafuer kann, sondern das opfer ist. den traffic auf der leitung mindert das etwas, da die antworten nicht mehr raus geschickt werden. beobachtungen haben aber gezeigt, dass sofort neue ipadressen als absender erschienen, sobald man welche geblockt hat.

beim suchen bin ich auf eine loesung gestossen, die in meinem falle erst einmal ausreichend ist. dabei wird mit iptables in das paket “reingeschaut”.

die erste regel schaut in die udp pakete an port 53, ob darin eine dns any anfrage steckt und setzt fuer die ip einen tag “dnsanyquery”:

iptables -I INPUT 1 -i eth0 -d xx.xx.xx.xx -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --set

die zweite regel prueft, ob die erste regel noch weitere vier mal in der letzten minute angewandt wurde. wenn ja, dann wird die anfrage weggeworfen:

iptables -I INPUT 2 -i eth0 -d xx.xx.xx.xx -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 60 --hitcount 5 -j DROP

mit diesen regel funktionieren “normale” dns any abfragen weiterhin und alle anderen abfragen bleiben davon sowieso unberuehrt. da die absender ips ohnehin gefaelscht sind, wird auch niemand “unnoetig” ausgesperrt.

leider bekommen die “angreifer” nicht mit, dass der dns server kein offener resolver mehr ist und feuern steandig weiter. so habe ich naemlich gerade eben den naechsten mist im logfile gefunden, der sich im sekundentakt vermehrt:

20-May-2013 22:43:08.459 client 69.140.111.56#27203: view external: query: . IN RRSIG +E

na toll.. da wird als “amplification packet” der “signature resource record” der root zone abgefragt. *seufz* …darum kuemmere ich mich aber heute nicht mehr.

und was hat das ganze nun mit pfingsten zu tun? nix.. war halt nur heute passiert und so musste ich mich wenigestens nicht ueber das wetter aufregen, weil ich einen guten teil des tages vor der kiste gesessen habe ๐Ÿ˜‰

wiedermal kacka serva hacka

irgendein trojaner hat scheinbar die ftp kennwoerter eines anderen geklaut und irgedein automatismus kompromittiert dann die dazu gehoerigen webpraesenzen. nein, nicht mir… ich darfs nur wieder bereinigen ๐Ÿ˜‰

in alle html dateien z.b. wurde dieser code eingefuegt:

20130410_kackaservahacka

bei allen php und js-dateien sah es aehnlich aus, nur eben an die gegebenheiten der sprache angepasst.

ich kriegs im nachhinein nicht mehr zusammen, was ich alles gemacht habe, um das malheur zu beseitigen. hier nur ein paar codeschnipsel von der bash, damit ich die wieder finde, falls ich sie doch noch mal brauchen sollte.

ein backup gab es selbstverstaendlich, doch nur fuer 5 tage in der vergangenheit. der befall wurde leider erst am sechsten tage entdeckt. die erste idee war natuerlich, die infizierten dateien aus den original sourcen des cms wiederherzustellen. also husch eine liste gemacht mit den dateien, welche geaendert wurde und auch in der sourcen vorhanden sind. mit dieser liste dann aus den sourcen die auf dem webserver ueberschrieben:

for i in `cat liste.txt`; do scp contao-2.11.5/$i host:/var/www/$i; done 

leider war das insgesamt nur ein bruchteil der betroffenen dateien. also musste eine andere loesung her. da alle diese dateien den gleichen code beinhalteten, habe ich erst einmal eine liste dieser dateien erstell:

grep -l -R '9f61a5' * > /tmp/infected.txt 

anhand dieser liste habe ich dann mit sed den ganzen betroffenen block in der datei entfernt. im falle der javascript dateien sah das so aus:

for i in `cat /tmp/infected.txt|grep .js`; do sed -i '/*9f61a5*/,/a65*/d' /var/www/$i; done 

und bei den html dateien so:

for i in `cat /tmp/infected.txt|grep .html`; do sed -i 's///' /var/www/$i; done

wie schon geschrieben… drumherum fehlt noch einiges an arbeit ๐Ÿ˜‰

bash, find, alter einer datei

damit ich mir es vielleicht irgendwann mal merken kann…

dateien suchen, die juenger oder aelter sind als x tage (bzw. geaendert wurden)

find PFAD -type f -name '*.html' -mtime +TAGE -exec BEFEHL {} \;

TAGE ist die anzahl tage, die betrachtet werden soll. mit einem plus davor bedeutet es “aelter als”. mit einem minus davor bedeutet es “juenger als”.

beispiel1: sucht im verzeichnis /tmp nach dateien, die vor mehr als 5 tage geaendert worden sind und loescht diese:

find /tmp -type f -name '*' -mtime +5 -exec rm {} \;

beispiel2: sucht im verzeichnis /var/www nach html dateien, die vor einem tag und weniger geaendert wurden und gibt diese aus:

find /var/www -type f -name '*.html' -mtime -1 -exec echo {} \;

die sacche mit den zeitstempeln ist so:

-ctime x : findet dateien, die in dieser zeit erzeugt (c wie created) wurden.
-mtime x : findet dateien, die in dieser zeit modifiziert (m wie modified) wurden.
-atime x : findet dateien, die in dieser zeit geoeffnet (a wie accessed) wurden.