Quelltexte durchsuchen mit grep

07.01.2020 Jonas L. Analysemethode

Open Source bedeutet leider nicht automatisch Datenschutz und Sicherheit. Aber weil man den Quelltext bekommen kann, kann man ihn untersuchen.

Zuerst die Einschränkungen: Wenn man in einem Quelltext Nichts böses findet (insbesondere dann, wenn man ein einfaches Suchwerkzeug wie grep verwendet) bedeutet das in keinem Fall, dass dort Nichts böses ist. Umgekehrt kann man auch etwas finden, das Böse aussieht und es nicht ist.

Ein Beispiel für das Nicht-Finden ist JSFuck. Jedes JavaScript lässt sich mit den sechs Symbolen []()!+ darstellen. Nun könnte man eine Einbindung von Google Analytics o.ä. auf diese Art kodieren. Dann würde man es mit einer einfachen Suche nicht finden. Erst bei einer manuellen Betrachtung des Quelltextes würde so etwas wahrscheinlich auffallen, da das einen sehr langen und unverständlichen Quelltext ergibt. Nun sollte man aber auch nicht nach einer Konzentration dieser 6 Symbole suchen, da es noch andere Wege gibt, die Funktionalitäten eines Quelltextes zu verschleiern.

Sofern der Autor keine bösen Absichten hat, sondern nur unwissend oder grob fahrlässig war, kann eine Suche natürlich helfen.

Zum Suchen gibt es das Kommandozeilenwerkzeug grep. Das sollte bei jeder Standardlinuxinstallation dabei sein. Die grundlegende Benutzung ist auch einfach: grep MUSTER DATEI. Ein Muster wäre z.B. analytics, facebook, google oder gstatic.com, wenn man nach Datenschutzproblemen sucht. Wenn man bei einer Laufzeitanalyse etwas auffälliges entdeckt hat, kann man auch direkt nach dieser Domain im Quelltext suchen.

Dabei wird allerdings die Groß- und Kleinschreibung beachtet. Dadurch werden dann einige Vorkommen nicht gefunden. Insofern sollte man grep -i MUSTER DATEI verwenden, damit die Groß- und Kleinschreibung ignoriert wird.

Wenn der Quelltext nur eine Datei umfassen würde, dann wäre es wahrscheinlich noch realistisch möglich, den Quelltext durchzulesen. Aber das ist oft nicht der Fall. Meistens hat man einen ganzen Ordner. Daher gibt es die rekursive Suche. Dann kann man einen Ordner angeben und den Ordner mit den direkt und indirekt (in Unterordnern) enthaltenen Dateien durchsuchen - grep -r MUSTER ORDNER.

Beides kann man kombinieren - also grep -ri MUSTER ORDNER.


Genug Theorie, jetzt ein Praxisbeispiel - das Monitoringtool Netdata.

Damit kann man auf Servern Messwerte wie z.B. die CPU-Auslastung erfassen, ansehen und auswerten.

Ganz unbedeutend scheint es nicht zu sein - Netdata gibt es in den Paketquellen von Debian und Arch Linux.

Den Quelltext gibt es bei Microsoft/ GitHub unter https://github.com/netdata/netdata.

Dann kann man sich den Quelltext holen mittels git clone https://github.com/netdata/netdata.git und in den Ordner wechseln mit cd netdata.

Mit grep -ri analytics . findet man nicht wenig.

Bei dieser Vorgehensweise durchsucht man auch den Ordner .git, obwohl die Dateien dort komprimiert sind, sodass man dort meistens Nichts findet - also kann grep --exclude-dir=.git -ri analytics vorteilhaft sein. In diesem Fall ist es egal, weil der git-Ordner vergleichsweise klein ist.

Auch muss man beachten, dass man damit im Fall von git nur den aktuellen Commit des gewählten Branches bzw. nur den gewählten Commit betrachtet.

Nun zurück zum grep-Aufruf und dessen Ausgabe. Hier ist nur der Anfang:

./health/README.md:[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fhealth%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)
./health/REFERENCE.md:[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fhealth%2Freference%2F&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)
./health/notifications/README.md:[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fhealth%2Fnotifications%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)
./health/notifications/syslog/README.md:[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fhealth%2Fnotifications%2Fsyslog%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>)

Hier sieht man, dass scheinbar die Markdown-Dateien verwanzt wurden. Diese haben ein Google-Analytics-Tracking-Pixel. Das ist doch sehr einladend. Da erwartet man natürlich, dass es da noch mehr Datenschutzprobleme gibt.

Da die Markdown-Dateien jetzt nicht mehr interessant sind, werden diese nun bei der Suche ignoriert - mittels grep --exclude-dir=.git --exclude=*.md -ri analytics ..

Jetzt wird die Ausgabe deutlich übersichtlicher:

./web/gui/demosites.html:            t.GoogleAnalyticsObject = n, t[n] || (t[n] = function () {
./web/gui/demosites.html:            }), t[n].l = +new Date, o = e.createElement(a), i = e.getElementsByTagName(a)[0], o.src = "//www.google-analytics.com/analytics.js", i.parentNode.insertBefore(o, i)
./web/gui/demosites2.html:    // google analytics when this is used for the home page of the demo sites
./web/gui/demosites2.html:        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
./web/gui/demosites2.html:        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
./web/gui/main.js:// control the welcome modal and analytics
./web/gui/main.js:        // google analytics when this is used for the home page of the demo sites
./web/gui/main.js:                i['GoogleAnalyticsObject'] = r;
./web/gui/main.js:            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
./web/gui/infographic.html:            t.GoogleAnalyticsObject = n, t[n] || (t[n] = function () {
./web/gui/infographic.html:            }), t[n].l = +new Date, o = e.createElement(a), i = e.getElementsByTagName(a)[0], o.src = "//www.google-analytics.com/analytics.js", i.parentNode.insertBefore(o, i)
./packaging/makeself/makeself-help-header.txt:  Anonymous stat collection and reporting to Google Analytics is enabled
./docs/generator/buildhtml.sh:find ${SRC_DIR} -name "*.md" -print0 | xargs -0 sed -i -e 's/\[!\[analytics.*UA-64295674-3)\]()//g'
./docs/generator/custom/themes/material/partials/footer.html:<script>!function(e,a,t,n,o,c,i){e.GoogleAnalyticsObject=o,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),i=a.getElementsByTagName(t)[0],c.async=1,c.src="https://www.google-analytics.com/analytics.js",i.parentNode.insertBefore(c,i)}(window,document,"script",0,"ga"),ga("create","UA-64295674-3",""),ga("set","anonymizeIp",!0),ga("send","pageview","/doc"+window.location.pathname);var links=document.getElementsByTagName("a");if(Array.prototype.map.call(links,function(a){a.host!=document.location.host&&a.addEventListener("click",function(){var e=a.getAttribute("data-md-action")||"follow";ga("send","event","outbound",e,a.href)})}),document.forms.search){var query=document.forms.search.query;query.addEventListener("blur",function(){if(this.value){var e=document.location.pathname;ga("send","pageview",e+"?q="+this.value)}})}</script>
./netdata-installer.sh:  Anonymous usage stats will be collected and sent to Google Analytics.
./daemon/anonymous-statistics.sh.in:# https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
./daemon/anonymous-statistics.sh.in:		"https://www.google-analytics.com/collect" >/dev/null 2>&1
./daemon/anonymous-statistics.sh.in:	wget -q -O - --timeout=1 "https://www.google-analytics.com/collect?\

(Ja, das ist die ganze Ausgabe)

Da sehen zwei Dateien besonders interessant aus - web/gui/main.js und daemon/anonymous-statistics.sh.in.

Wenn man sich die erste Datei ansieht und nach Google sucht gibt es nicht nur Google Analytics. Dort gibt es eine Updateprüffunktion, die eine Anfrage an https://www.googleapis.com/storage/v1/b/netdata-nightlies/o/latest-version.txt sendet. Direkt darüber ist eine andere Funktion, die das gleiche mit einer Anfrage an https://api.github.com/repos/netdata/netdata/releases/latest macht. Dann gibt es noch einen Google-Analytics-Init-Block, der angeblich nur bei Demo-Seiten ausgeführt wird.

Die zweite Datei ist ein Shellskript, dass - sofern keine Opt-Out-Datei existiert - eine Anfrage an Google Analytics sendet. Damit werden serverseitig Statistiken gesendet.

Positiv ist anzumerken, dass die Google Analytics Nutzung zumindest dokumentiert ist. Negativ anzumerken ist aber, dass hier ein Tracker genutzt wird.

The Google Tag Manager Javascript snippet will remain in the page, but the linked tag will not be fired. The effect is that no data will ever be sent to GA.


Sehr schön. Zwar wird Google Analytics abgeschaltet, aber eine Anfrage an Google gibt es dennoch.

Dazu kommt noch die zentrale Registry von Netdata, worauf hier hingewiesen wird.

Das kann man nicht abschalten, stattdessen kann man nur eine eigene Registry benutzen.

Schlussfolgerung in diesem Fall: Netdata ist zwar ein Open Source Monitoring Werkzeug, aber in der vorliegenden Form sollte man es nicht einsetzen, da man dann auch selbst überwacht wird.