Provide a detailed summary of the following web content, including what type of content it is (e.g. news article, essay, technical report, blog post, product documentation, content marketing, etc). If the content looks like an error message, respond 'content unavailable'. If there is anything controversial please highlight the controversy. If there is something surprising, unique, or clever, please highlight that as well: Title: IPinside: Korea’s Mandatory Spyware Site: palant.info Note : This article is also available in Korean . On our tour of South Korea’s so-called security applications we’ve already took a look at TouchEn nxKey , an application meant to combat keyloggers by … checks notes … making keylogging easier. Today I want to shed some light on another application that many people in South Korea had to install on their computers: IPinside LWS Agent by Interezen. The stated goal of the application is retrieving your “real” IP address to prevent online fraud. I found however that it collects way more data. And while it exposes this trove of data to any website asking politely, it doesn’t look like it is all too helpful for combating actual fraud. How does it work? Similarly to TouchEn nxKey, the IPinside LWS Agent application also communicates with websites via a local web server. When a banking website in South Korea wants to learn more about you, it will make a JSONP request to localhost:21300 . If this request fails, the banking website will deny entry and ask that you install IPinside LWS Agent first. So in South Korea running this application isn’t optional. On the other hand, if the application is present the website will receive various pieces of data in the wdata , ndata and udata fields. Quite a bit of data actually: This data is supposed to contain your IP address. But even from the size of it, it’s obvious that it cannot be only that. In fact, there is a whole lot more data being transmitted. What data is it? wdata Let’s start with wdata which is the most interesting data structure here. When decrypted, you get a considerable amount of binary data: As you can see from the output, I am running IPinside in a virtual machine. It even says VirtualBox at the end of the output, even though this particular machine is no longer running on VirtualBox. Another obvious thing are the two hard drives of my virtual machine, one with the serial number QM00001 and another with the serial number abcdef . That F0129A45 is the serial number of the primary hard drive volume. You can also see my two network cards, both listed as Intel(R) 82574L Gigabit Network Connection . There is my keyboard model (Standard PS/2 Keyboard) and keyboard layout (de-de). And if you look closely, you’ll even notice the byte sequences c0 a8 7a 01 (standing for my gateway’s IP address 192.168.122.1), c0 a8 7a 8c (192.168.122.140, the local IP address of the first network card) and c0 a8 7a 0a (192.168.122.10, the local IP address of the second network card). But there is way more. For example, that 65 (letter e ) right before the hard drive information is the result of calling GetProductInfo() function and indicates that I’m running Windows 10 Home. And 74 (letter t ) before it encodes my exact Windows version. Information about running processes One piece of the data is particularly interesting. Don’t you wonder where the firefox.exe comes from here? It indicates that the Mozilla Firefox process is running in the background. This information is transmitted despite the active application being Google Chrome. See, websites give IPinside agent a number of parameters that determine the output produced. One such parameter is called winRemote . It’s mildly obfuscated, but after removing the obfuscation you get: TeamViewer_Desktop.exe|rcsemgru.exe|rcengmgru.exe|teamviewer_Desktop.exe So banking websites are interested in whether you are running remote access tools. If a process is detected that matches one of these strings, the match is added to the wdata response. And of course this functionality isn’t limited to searching for remote access tools. I replaced the winRemote parameter by AGULAAAAAAtmaXJlZm94LmV4ZQA= and got the information back whether Firefox is currently running. So this can be abused to look for any applications of interest. And even that isn’t the end of it. IPinside agent will match substrings as well! So it can tell you whether a process with fire in its name is currently running. That is enough for a website to start searching your process list without knowing what these processes could be. I created a page that would start with the .exe suffix and do a depth-first search. The issue here was mostly IPinside response being so slow, each request taking half a second. I slightly optimized the performance by testing multiple guesses with one request and got a proof of concept page that would turn up a process name every 40-50 seconds: With sufficient time, this page could potentially enumerate every process running on the system. ndata The ndata part of the response is much simpler. It looks like this: ��HDATAIP=▚▚▚.▚▚▚.▚▚▚.▚▚▚��VD1NATIP=▚▚▚.▚▚▚.▚▚▚.▚▚▚��VD1CLTIP=192.168.122.140��VD2NATIP=��VD2CLTIP=192.168.122.10��VPN=2��ETHTYPE=ETH1 No, I didn’t mess up decoding the data. Yes, � is really in the response. The idea here was actually to use ∽ (reverse tilde symbol) as a separator. But since my operating system isn’t Korean, the character encoding for non-Unicode applications (like IPinside LWS Agent) isn’t set to EUC-KR. The application doesn’t expect this and botches the conversion to UTF-8. ▚▚▚.▚▚▚.▚▚▚.▚▚▚ on the other hand was me censoring my public IP address. The application gets it by two different means. VD1NATIP appears to come from my home router. HDATAIP on the other hand comes from a web server. Which web server? That’s determined by the host_info parameter that the website provides to the application. It is also obfuscated, the actual value is: www.securetrueip.co.kr:80:/vbank_01.jsc:_INSIDE_AX_H= Only the first two parts appear to be used, the application makes a request to http://www.securetrueip.co.kr:80/androidagent.jsc . One of the response headers is RESPONSE_IP . You guessed it: that’s your IP address as this web server sees it. The application uses low-level WS2_32.DLL APIs here, probably as an attempt to prevent this traffic from being routed through some proxy server or VPN. After all, the goal is deanonymizing you. udata Finally, there is udata where “u” stands for “unique.” There are several different output types here, this is type 13: [52-54-00-A7-44-B5:1:0:Intel(R) 82574L Gigabit Network Connection];[52-54-00-4A-FD-6E:0:0:Intel(R) 82574L Gigabit Network Connection #2];$[QM00001:QEMU HARDDISK:];[abcdef:QEMU HARDDISK:];[::];[::];[::]; Once again a list of network cards and hard drives, but this time MAC addresses of the network cards are listed as well. Other output types are mostly the same data in different formats, except for type 30. This one contains a hexadecimal CPU identifier, representing 16 bytes generated by mashing together the results of 15 different CPUID calls . How is this data protected? So there is a whole lot of data which allows deanonymizing users, learning about the hardware and software they use, potentially facilitating further attacks by exposing which vulnerabilities are present on their systems. Surely this kind of data is well-protected, right? I mean: sure, every Korean online banking website has access to it. And Korean government websites. And probably more Interezen customers. But nobody else, right? Well, the server under localhost:21300 doesn’t care who it responds to. Any website can request the data. But it still needs to know how to decode it. When talking about wdata , there are three layers of protection being applied: obfuscation, compression and encryption. Yes, obfuscating data by XOR’ing it with a single random byte probably isn’t adding much protection. And compression doesn’t really count as protection either if people can easily find the well-known GPL-licensed source code that Interezen used without complying with the license terms. But there is encryption, and it is even using public-key cryptography! So the application only contains the public RSA key, that’s not sufficient to decrypt the data. The private key is only known to Interezen. And any of their numerous customers. Let’s hope that all these customers sufficiently protect this private key and don’t leak it to some hackers. Otherwise RSA encryption can be considered secure even with moderately sized keys. Except… we aren’t talking about a moderately sized key here. We aren’t even talking about a weak key. We are talking about a 320 bits key. That’s shorter than the very first key factored in the RSA Factoring Challenge. And that was in April 1991 , more than three decades ago. Sane RSA libraries don’t even work with keys this short. I downloaded msieve and let it run on my laptop CPU, occupying a single core of it: $ ./msieve 108709796755756429540066787499269637… sieving in progress (press Ctrl-C to pause) 86308 relations (21012 full + 65296 combined from 1300817 partial), need 85977 sieving complete, commencing postprocessing linear algebra completed 80307 of 82231 dimensions (97.7%, ETA 0h 0m) elapsed time 02:36:55 Yes, it took me 2 hours and 36 minutes to calculate the private key on very basic hardware. That’s how much protection this RSA encryption provides. When talking about ndata and udata , things look even more dire. The only protection layer here is encryption. No, not public-key cryptography but symmetric encryption via AES-256. And of course the encryption key is hardcoded in the application, there is no other way. To add insult to injury, the application produces identical ciphertext on each run. At first I thought this to be the result of the deprecated ECB block chaining mode being used. But: no, the application uses CBC block chaining mode. But it fails to pass in an initialization vector, so the cryptography library in question always fills the initialization vector with zeroes. Which is a long and winded way of saying: the encryption would be broken regardless of whether one can retrieve the encryption key from the application. To sum up: no, this data isn’t really protected. If the user has the IPinside LWS Agent installed, any website can access the data it collects. The encryption applied is worthless. And the overall security of the application? That web server the application runs on port