Menu
O mnie Kontakt

Na swoim kanale, "apalrd's adventures", autor przyjrzał się nowemu urządzeniu KVM Nano KVM od firmy Cypeed, które umożliwia zdalne zarządzanie komputerem. W przeszłości autor przeglądał już wiele urządzeń, ale ten model był szczególnie interesujący z powodu licznych rekomendacji od widzów. Ostatecznie, producent skontaktował się z nim, oferując wysyłkę trzech modeli: Lite, Regular i PCIe, w celu przeprowadzenia recenzji. Od razu zaznacza, że nie otrzymał za to wynagrodzenia, a opinia, którą podzieli się, jest niezależna.

Każda z wersji KVM ma różne cechy. Na przykład, model Lite charakteryzuje się niewielkimi wymiarami i zawiera wszystkie niezbędne porty, takie jak Ethernet i HDMI. Mimo niewielkich rozmiarów układ oparty jest na nowoczesnym chipie RISC-V, co autor uważa za pozytywny aspekt, ponieważ RISC-V zdobywa coraz większą popularność. Wersja Regular dodaje dodatkowe funkcje, takie jak kontrola zasilania i dodatkowe przyciski, natomiast model PCIe jest przeznaczony do montażu wewnętrznego w komputerze, co prawda efektywnie nie wykorzystywał magistrali PCIe, a jedynie porty USB.

Autor przeprowadził testy każdego z modeli, zaczynając od wersji Lite. Po podłączeniu i skonfigurowaniu urządzenia, udało mu się zdalnie uzyskać dostęp do systemu operacyjnego na „komputerze ofierze”. Autor zauważył, że w trakcie działania urządzenie próbuje połączyć się z serwerami zewnętrznymi, co wzbudziło jego obawy o prywatność i bezpieczeństwo. Po zidentyfikowaniu, że KVM łączy się z serwerem NTP oraz Tailscale, autor postanowił przetestować urządzenie w izolowanej sieci, aby lepiej zrozumieć jego działanie oraz potencjalne zagrożenia.

Podczas analizy kodu i wyników działania, autor wskazał na potencjalne problemy z bezpieczeństwem, takie jak domyślne hasła, które były zbyt łatwe do odgadnięcia oraz brak odpowiednich zabezpieczeń w komunikacji z serwerem. Wspomniał również, że producent nie dba o aktualizacje oprogramowania, a starsze wersje są niedostatecznie wspierane, co może prowadzić do dalszych luk bezpieczeństwa.

Na koniec, autor zwrócił uwagę, że mimo ambitnego opakowania urządzenie wymaga wielu poprawek, zwłaszcza w zakresie bezpieczeństwa. Stylistyka są zachęcające, a cena jest atrakcyjna, ale w praktyce jakość oprogramowania pozostawia wiele do życzenia. Na czas pisania tego artykułu film został obejrzany 173399 razy i zdobył 5529 polubień, co sugeruje, że społeczność jest zainteresowana tematyką zdalnego zarządzania i bezpieczeństwa w IT.

Toggle timeline summary

  • 00:00 Wprowadzenie do zdalnego zarządzania komputerami za pomocą urządzeń KVM.
  • 00:13 Przegląd modeli KVM Cypeed Nano po otrzymaniu jednostek do recenzji.
  • 00:41 Przegląd trzech modeli: Lite, Regular i PCIe.
  • 01:09 Opis i komponenty modelu Lite, w tym porty i sprzęt.
  • 02:00 Wprowadzenie do modelu Regular z większą ilością komponentów.
  • 02:26 Badanie połączeń USB i HDMI oraz ich konfiguracji.
  • 03:00 Omówienie modelu PCIe i jego różnych funkcji.
  • 03:20 Proces konfiguracji do testowania modelu Lite z systemem Linux.
  • 06:12 Testowanie funkcjonalności modelu Lite i połączenia sieciowego.
  • 08:15 Analiza zachowania sieci, w tym obawy dotyczące dowodów danych osiągających zagraniczne serwery.
  • 09:39 Omówienie kwestii bezpieczeństwa związanych z urządzeniem łączącym się z zewnętrznymi serwerami NTP.
  • 17:54 Przegląd zidentyfikowanych luk w zabezpieczeniach w oprogramowaniu NanoKVM.
  • 19:39 Omówienie wyzwań związanych z doświadczeniami użytkowników związanymi z urządzeniem.
  • 45:50 Stwierdzenie, że produkt jest przystępny cenowo, ale wyrażenie obaw co do reputacji firmy.
  • 48:02 Ostateczne przemyślenia na temat jakości sprzętu, ale krytyka ogólnego bezpieczeństwa oprogramowania.
  • 55:04 Zamknięte uwagi i zachęta do feedbacku, w tym dane kontaktowe do dalszej dyskusji.

Transcription

So, if you do any sort of work with computers, IT, home web kind of stuff, you know how revolutionary it is to be able to remotely manage a computer with, say, a virtual keyboard, video, and mouse solution. And lucky you, I have reviewed a number of these devices on my channel in the past. Maybe I'll have some links down below to some of my other reviews. And every time I do one of those, I get a comment telling me I should take a look at the Cypeed Nano KVM, because it's really cheap. And believe it or not, I thought that too. So I went to buy my own a few months ago, only to find out that they can't be sold in the US or Russia. But buying one is no longer a problem, because Cypeed offered to send me three of them to make a review video. So today, I'm taking a look at the Nano KVM, the Lite, the Regular, and the PCIe. So if that sounds good to you, then come along on this adventure. Quick disclosure, Cypeed did send me these three units for review. No money changed hands. They won't see the review before you do. I did do some homework, though, and read their GitHub issues. So this is going to be a bit spicy. So anyway, here's what I got. So I got the Lite, the Regular, and PCIe. So first off, the Lite, it's in a very tiny little package with the tiniest little bubble wrap ever. Comes with a heatsink. Very tiny. And here is the unit itself. So this says Wired Ethernet. I'm pretty sure it's 100 megabit. On the other side, we have an HDMI and a USB Type-C. So you plug these two into your victim computer. You can capture in the HDMI from the device, and you can output keyboard and mouse emulation. So you can completely remotely control a computer as if you were plugged right into it. It's also got a little micro SD card where the operating system is on, and that's pretty much it. And it's based on this tiny little board here, the Leechi RV Nano, which is a RISC-V system on chip. Now, I really like RISC-V, and I'm glad to see RISC-V getting more adoption. So this is the Nano. Next up we have the Regular-sized one. So this one should have a few more parts. What is this thing? KVM-B. KVM-A. Okay, so this looks like a power control board. It's got a pin out here where it plugs into a power switch, reset switch, power LED, hard drive LED. And it probably sends it back over USB. It has a microcontroller on it, so I'm not sure what type of USB it's doing. Next up we've got the unit itself, and I believe this is actually the same as the light, if I pull my light back out of the box. So this should be the same as the light, at least the baseboard, but it comes with a box and an extra layer on top with some other buttons and stuff. Also included I've got two USB cables. I'm assuming one of them is for this guy, and the other is for your target computer. So those are going to plug into the two Type-C ports here. No HDMI cable, but that's fine, HDMI is a pretty common standard. It's got these guys, which are probably for this header. So you're going to find some wires, plug them into this header, and then match them up with the corresponding pins on your motherboard. Also got this little thing here, which I guess is for pushing the button somehow? I don't know what that does, but I guess we'll figure that out later. So on the side they've got a pinout here, so HDMI and HID, that's the target computer, Ethernet, goes to our network. They have accessory pinouts here, which is labeled as UART1, UART2, so those are both serial, 5V and ground, and then KVMB is on this Type-C port. So again, it's probably not really USB. This is not actually a USB peripheral, they're just reusing that USB connector, which is kind of weird. And they have an AUX USB, which I think is actually a Type-C, or maybe it's just power, I can't tell. External additional power supply, I guess, that might just be power input. And last up, I got the PCIe model, so this one says PoE and WiFi, which is cool, they have versions without, I guess. I didn't even look. Okay, so here we got the card in quite a piece of foam. Get out of there. Here's the card, so we've got the NanoVM PCIe, it's got the Ethernet again, Ethernet, HDMI, tiny, tiny little display, USB head and power in. So somehow they didn't manage to take power from the PCIe bus, probably because that resets with the computer. They're also not acting as a display, because you gotta loop HDMI back in, so they're really just using the PCIe form factor just to sit in the machine as a slot. It's not actually connecting to any of these guys on the finger, I don't think. And if I look closely, I can see that even though the fingers are there, there's only one trace going to them. So I bet it's just using that for a reset signal. And they've even got these internal jumpers that go between this board and the top board, which appear to be for, they're actually labeled, 5V, GND, 5V, DNDP, those are USB data, and GND. So they couldn't even bother with some standoffs here, they used cable instead. We do have pin headers here that can go to the motherboard, so I could use some of these guys to run these connectors over the motherboard for power reset, power LED, hardware LED. And underneath here there's a built-in Wi-Fi module, with Wi-Fi, if you don't want to use wired Ethernet. And up here is the header for the two serial ports, UART1 and UART2. What kind of accessories do we have with this one? HDMI cable, tiny little screwdriver, Wi-Fi antenna, cap that probably went with that cable, USB A to C, a low height bracket if you're into the low height life, which also by the way, does not fit the Wi-Fi radio antenna. So if you're using a half height card slot, you won't be able to fit the antenna. Another USB and some power and reset cables, these actually look pretty nice. They're actually labeled and everything, cool. So anyway, that's what came in the box for these three models. I'm going to start with the low end, the light version. We're going to try out the light version and work our way up from there. So I got a test setup. This guy here is my victim computer, he's what we're going to try to access remotely. So it's just a basic Linux box, nothing special. I've got the Nano KVM light here. This didn't come with any cables, I didn't put the heat sink on that it came with, but I took an HDMI cable and a type C cable from the other models, so you'll just have to get your own cables. I've also got a tiny little router here that runs a DHCP server, so I can take a look at what IP address it's got and connect to it. So let's give it Ethernet, HDMI, and get in there, okay this is really tight. What the heck is going on? It won't look like HDMI, just get in there. And power. Okay, it lights up when it turns on, so that's good. Now let's connect to it and see what we've got. So it's on port 3, looks like it got the address 192.168.88.253. Log in, I actually don't remember the account, admin, admin. Looks like that, okay. Change password, okay we've got to change the password, admin, okay, so we are connected, is it working? Hello? Hello sir? Try restarting the target computer, see if that helps. There we go, Kali GNU Linux, okay, well we're logged in, seems to work. That's something, on screen keyboard, I can paste, okay, well, seems to be doing its job. Could upload an image, maybe, yeah, sound basic seems to work right. So like I said earlier, I did my homework and I noticed some people were complaining about it reaching out to servers in other countries. So that is why I have this guy connected to an isolated network here with just the router. Now the router is providing everything it should need, DHCP, DNS, router advertisements, that kind of stuff, but it doesn't have an internet connection. So I want to see what it's trying to connect to, I've got a packet capture for us to look at. So right out the gate it does a DHCP discover, very normal thing, it gets an offer back from the router, the router has offered it 192.168.88.253, and also gave it some other information like the subnet mask, the router address, and domain name server. So 192.168.88.1, that should be where DNS queries are going. So if I filter on that address as the source or destination, we see all the traffic to or from the device on IPv4. So it is starting off by joining SSDP and sending out SSDP frames, which is a pretty normal thing to do. It's then sending out MDNS frames to advertise itself, I guess it named itself KVMDF2A.local. It is pinging the gateway, I don't know why it's pinging the gateway, but it is, and it gets a reply back. And then we get our first interesting thing, it's doing a DNS query for an A record, an A quad A record, for pool.ntp.org. Now for those of you guys that don't know, the NTP pool is essentially a global project to maintain time across the internet. It's not sketchy at all, thousands of volunteers around the world are running servers in the NTP pool. If you're an open source project, really anyone, you can get your own subdomains, they can track your usage statistics. But pool.ntp.org is a really, really reasonable thing to hard code into a device as like a time server. In this case, it didn't request a time server over DHCP, most networks probably aren't operating their own time servers anyway, so going to the pool makes sense. But check out that destination address. So it didn't ask my router at 192.168.88.1, it asked 192.168.0.1, which sounds like a default, and it also asked 8.8.4.4, which is Google, and it also asked 8.8.8.8, which is Google, and it asked all three of those guys again for the quad A. And it got a response back from the router that says destination unreachable, because it can't route to this subnet, or this subnet, or that subnet, which makes sense, and I guess it didn't care, because it kept going on anyway. Next up, we come down here, and we get this NAT PNP external address request, then it secondarily asks for a map UDP request, so it is asking for UDP port 41641 to be mapped to the outside for two hours. It's asking to punch a hole through the IPv4 NAT firewall on this port, and in both cases the router replies port unreachable, because it's not running a NAT PNP server. So after trying to configure its time from the NTP pool, it is now trying to punch a hole in your firewall with NAT PNP. NAT PNP is a fantastic technology for stuff like game consoles or stuff that actually needs to do peer-to-peer devices, but I'm not sure why this would need to do it. I have an idea that I know from other reasons, but let's keep looking. So we're going back to the pool, this time we're trying 1, because our queries to 0 failed, because we're not looking at the right DNS server, we're just using Google. So we keep going, now we're looking for log.tailscale.io. That's probably why we're doing a NAT PNP request. My guess is that they're running a tailscale daemon, and it's trying to do NAT PNP, and it's also reaching out to the wrong DNS server to try to log into tailscale. I should probably note at this point, I haven't even connected to it in a web browser and changed my default password. We're only so far like four seconds into this thing being booted up and on the network, and it's already reaching out to tailscale. I didn't configure a tailscale tunnel, I know a lot of people like tailscale, but that doesn't mean you should enable it out of the box before you've even done the first setup wizard. We keep hammering the pool again, and again, it's going to the wrong DNS server, because it's not going to the network DNS server, so it's not getting anything back. What are we going to do next? So now we're going to ping the gateway, I guess, because we don't like it, so we'll try pinging it, and trying tailscale again, trying NTP again. So this goes on for a while, until we eventually see something new. So at this point I've connected to it, so TCP starts popping up. So now I've actually gone and started to do my first login, so this is like 45 seconds after I plugged into the network here. So now at this point, I've actually connected to it in a web browser, now it's going to cdn.cyp.com over both A and quad A, so it's looking for IPv4, IPv6. It's again going to the wrong DNS server, but let's see what this query looks like. So we're going for cdn.cyp.com, it asks for an A and also a quad A, and it also asks for an OPT record, I'm not sure why it would want an OPT record, but it's looking for it. And then we're now looking for thislongaddress.local, and it didn't find it, I'm not actually sure what this is or why it'd be looking for it, but that looks like a UUID, and it's going there to that .local, and it's definitely coming from this device. It's then looking for turn.cloudflare.com, stun.google.com, turn.cloudflare.com, etc., A and quad A, so this could be tail scale again, trying to punch its way out using stun and turn, or it could be something Cypd is doing, I don't know. But again, it gets a bunch of unreachable back because it's going to the wrong DNS server still. So up until now, this actually hasn't had internet access, so it's just doing DNS queries, again for the wrong place, it's going to Google DNS because they hard-coded Google DNS. So, now I'm going to connect this router up to the network so this can route to the internet and do another packet capture so we can see what that traffic actually looks like. Let's see if it's booted back up again, if I refresh the page, looks like that's a no. Okay, we're loading again, come on, you can do it. Hope I don't have to reboot this thing, I unplugged power from the Nano KVM, and I left my victim PC running, so I hope that it can handle that kind of reset without having to restart. Sometimes devices turn off their HDMI when you unplug them, but given that I booted it up with HDMI, I think it'd be able to handle that. But if I wiggle the keyboard a bit, come back, okay, we're rebooting the victim, let's see if it comes back up this time. You do not appear to be working. I don't know, we'll look at the PCAP anyway and I'll figure out what's wrong. So we're going to stop the capture, and we're going to download the PCAP, save, so again we've got a DHCP discover, offer, request, hack, that's normal. So then it goes in again to asking for NTP. So we have now set ourselves up with some MBS, we've done NTP, we again did the external address request and MAP PDP request, we're now PMP, we're doing a lot more queries now. Okay, who are we connecting to this time, 55 to 161, where did that come from? Log.tailscale.io, okay, so we're actually connecting to Tailscale over TLS 1.3, so I can't see the traffic. We do NTP again, so now we're querying Cypede, and we also somehow are doing STUN at the same time, so I must have found the STUN server and I just didn't notice it. Actually probably got that from the TLS session. So now it's doing STUN to whoever that is, for 74 for STUN and a 141 for TURN, and this CloudFlare server is, let's see, what are we looking for for the CloudWare server? We end up with onlyv4.oversearchcdnweb.qnu.com, that's a fun one, and we're looking for 8.48.85.239. So here's where it's connecting to cdn.cypede.qnu, so it's doing that connection here over TCP, and that turns into TLS 1.3, so it looks like that's reset, so it took it like 40 seconds to do this TLS connection here. Here's the reset at 140, here's the initial connection here, so that took a whole hundred seconds, a minute and a half to download this file, or whatever it's doing at the API. So given this is encrypted with TLS, I guess my next stop is to either break the encryption or to set up my own server, see if it's actually checking certificates, or I could just read the code because it's open source and we'll see what it's doing. And by the way, it still doesn't work. I don't know why, it's, uh, try unplugging and replugging HDMI, I guess, maybe we try a different resolution. So it worked once, now that I gave it access to the internet, it reached out to the cloud and stopped working. What the fuck. So to give a bit of context to what's going on, let's take a look at the NanoKVM GitHub together. So this issue was brought to my attention by some followers, it's just called some security issues, and it's in the NanoKVM repo. And I guess some is an understatement, it's got 14 security issues here, some of which I've already pointed out, and some of the devs and other people go through and talk about them. I haven't actually tried to compile the code myself, there were some other issues here that people had a hard time compiling the code and getting it to run on their own, and I guess it's related, but I didn't try compiling it, so I'm just taking everything in this issue at face value, mostly, you'll see. So issues he's brought up, there's no credentials found, then it defaults to admin admin, and they actually did fix this one, so now you have to enter a password your first time. Next up he said by default SSH is enabled, it has a root password of root, and they also resolved this, so now it inherits the root password from the first time you change the password, it also sets the SSH password. Encrypt secret key is hardcoded, that's a sketchy thing we're going to look at later. CSRF protection, that's also kind of sketchy. Auth tokens not expiring, also sketchy. Not validating sessions, also kind of sketchy. Using sleep functions, also not good. Why is NanoKVM sending your device key to SIPPY? This is what I'm going to look at specifically. They also had some issues with WireGuard, I'm assuming this is related to tail scale. NanoKVM is connecting to the wiki, I actually didn't see this one, but maybe it is. Having TCP'd up an aircrack installed, that is very sketchy for an embedded system to have aircrack especially. TCP'd up is useful for debugging, I mean, so is aircrack, but these are not the kind of things you generally leave in production. Downloaded code doesn't check integrity, that's also not good. API running as root, also not good. And custom DNS servers, which again is something I really hate. So the conclusion of this GitHub author is that a lot needs to be done in terms of security. So these kinds of issues are relatively basic in terms of embedded software design, web app development, things like that. And so a lot of these authentication things and stuff like that are kind of things that should have been taken care of. And so to him and to me, it feels like the web app is very much a minimum viable product and not something that's like actually good. So he suggested using Debian instead of whatever the heck they're using now, which would probably be a good idea. Someone else suggested opt-in modules, I would like that as well, I definitely don't like tail scale starting up and doing its own done and turned stuff on its own. And so here is the one that I want to take a look at in more detail, because it fits with what I'm good at. It says it's very insecure, which is obviously true, downloading a lib from the internet and then executing it is like terrifyingly bad security, especially because they don't check the checksums or anything. So this guy responded and he said this is required by the server to generate the downloaded libmixcamlib.so, which is locked to only work with this device. So I am pretty good at binary reverse engineering, so I took a crack at reverse engineering this sketchy libmixcamlib binary that gets downloaded on every update with the unique serial number of the device. Let's take a look at what I found. So I started by just disassembling the ELF file. So it's ELF64, little NE and RISC-V, we expected that. Obviously I have two different versions from two different serial numbers. I can just take a look at what the differences are. So some regions here that have different bytes, there's actually seven of them. And coming down to where they actually are in the disassembled code, so here we're in makes and nnmixcam, that's the destructor. And these 64 bytes don't appear to be anything useful. Obviously it disassembled them as code, but they're not actually code, they're just data. Interpreting that data as code, you get a bunch of errors like this. So that takes me to Ghidra. I identified all the memory locations in the binary in Ghidra, and they're all preceded by a jump and link to the preauth function, followed by a jump that skips around it. So this jump just scrolls down to where the end of the data is. So essentially that means this data is not being executed as code, it's just being used as data. But it's not referenced anywhere, so there's no pointers anywhere in the binary that are looking at this address here. So the only way we could know what the address is, is if preauth function uses the return address where it was called from. And since all of the calls appear the same, it looks like that's what's happening. So jump and link means we're doing a function call, we're storing the return value in RA, c.j is an unconditional jump. So we come to the preauth function here, and we can see that it's referenced from 7 places, and these all directly correspond to where there is that weird data. So here it does a j.al jump and link to the preauth function, followed by an unconditional jump and 64 bytes of garbage. So the preauth function, it's an indirect call, so it's loading the address of auth function from a pointer table and jumping to it. So auth function here, we have essentially two other functions we're calling, getuid and getuidl. And we're taking the return address, and aside from actually returning to it with ret, we are using it here as s1, and then we add 2 to it, which ends up being the direct address of the data we were passed. So that gets passed as an argument to tuidgetl. So here it says unaffected return address plus 2. It's plus 2 because we had 2 bytes up here at the unconditional jump. So jump and link stores the address to return to, which would be 142224. The address of the data is actually 142226, that's why we have to add 2. So then these two functions here do some things. So I guess I'll go through getuid first, so this is again an indirect call. We have to find the address in a pointer table and jump to it. And this one decompiled well, so we're going to look at the C code now in the decompiler. So first it has a global variable that's a file descriptor. It checks if it's less than 1, which means it hasn't been initialized yet, it's 0. And then it opens a file descriptor to devmem. So it's directly memory mapping memory. Then it has this custom opcode here. So in binary it's 8BB7077C. And I couldn't find what this opcode is in RISC-V. So they're either doing an instruction set option that this version of GCC doesn't have, or they've done something entirely custom. Now it is allowable in RISC-V to do custom instruction set options. Normally they would be published somewhere. I didn't dig through CVI text documentation on this. But it seems like these are proprietary to CVI tech, which is the maker of the chip in this thing. So I don't like seeing custom instructions that are undocumented. Usually this leads to a bunch of security vulnerabilities, but who knows. It's just, it's a nightmare. So we open, so if we haven't already opened it before from the global variable, we open that file descriptor. We then do some custom magic here, which we don't know what it is. Then we mmap two regions of memory. I'll give you guys a little more space here. So the first one we call region 1, or I call region 1. This goes into a global variable. The second one we call region 2. If either of these fail, by the way, then we close our file. Which actually we should have done before. We actually never close this file descriptor otherwise. So here we dereference this pointer and we flip a single bit. So we OR it with 0x800. We're setting a bit in whatever region of memory this is, 0x300, 0x2000. And then we again have some custom opcode. It's the same one as up here, but it's doing something from the dereference value offset by 0x110 from our base region, which is 0x305, 0x0000. Then we return some data here, ORed. So we get from data 0x10C shifted by 0x20 plus 0x110. So we're reading in a long integer it looks like. So that's what actually happens with that return value. I don't see it going anywhere here. So unless we needed that return value somewhere before auth function, then I don't know what happened to it. Well, what's more exciting is TUIDL. So remember we saved RA into S1 and we added 2 to it. So A0 currently has the address of the weird data. We again do an indirect call from the pointer table, and we end up here. This one does not decompile well. It's clearly a for loop, so we set I to 0, and then we increment I, and then we check until I is 8. But it doesn't decompile this custom instruction. So again we have a custom opcode that's unique to SciTech I think. So 8B57C700. I couldn't find an instruction with this opcode, so I don't know what it does. But we take the address at A0, we read off byte 0 and 1, so the first 2 bytes. We read them as unsigned bytes, and then we add them together. Then we increment our pointer by 8, and then we get 6 more of them. So these addresses all work out to address 0, 1, 2, 3, 4, 5, 6, 7. So we read 8 bytes as unsigned, we add them together, and that ends up in A5. As to what happens to A5, it just disappears. So this custom instruction has to be doing something with A5, which is the sum of 8 bytes. And then we do this 8 times to get 8 copies of this loop. So I actually did some adding up. So there's 7 locations here, so there's 7 columns, and then there's 8 chunks which get added. And I noticed that in all 7 cases, the last byte is the same. So we have 4D1, 3D1, 4D1, 2D1, etc. And also, these guys here, if I select this column, that makes my serial number. So the serial number I tested with was D1, C9, 4D, A2, 1, 3, 5, 9, C2, 6, 2. And that shows up here, D1, C9, 4D, A2, 1, 3, 5, 9, C2, 6, 2. So we started with 7 locations, each of which had 64 bytes of seemingly random data. They added those 8 chunks of 8 bytes up, so we lost a bunch of data there because we're adding bytes. We ended up with essentially 88 bits of randomness. But then it looks like we just take the lower 8 bits of those numbers, and that gives us 64 bits of data, which just happens to exactly match the serial number of the chip. So somehow, they took the serial number of the chip, they expanded it to take 64 bytes, and they're generating a custom library that has 7 locations of these 64 bytes of random data in it. And then they're somehow using some custom RISC-V opcode that's not documented to authenticate the chip somehow. And that seems extremely sketchy to me. So anyway, this library is obviously not open source. You're not going to just go and download this version of the library from anyone. And they can't even bundle it in the images, which also are not entirely open as well. It's just a closed source nightmare all around. As to why they did this, I can speculate, but it's terrifying and you shouldn't accept it. So if downloading an unsigned binary off random places on the internet and running it without any verification was bad enough, let's see what else it can do. I'm going to log in over SSH now and see what sort of environment we have running on the Nano KVM. So right as I logged in, I ran PS so I can see what's going on here. Not a lot of processes running. I don't think I'll have GED. I don't actually know what that is. Bluetooth. I don't think we actually have Bluetooth. I don't know what that's going on about. We have NTP, Avahi Daemon, SSHD, SSD, PD, so simple service to every protocol. And KVM system, Getty. So this would be on the UART serial. Tailscale-D, which again, I never configured, never asked it to use, Nano KVM server. And then for some reason, it sometimes pings my gateway. I don't know why. I don't know which process is doing this ping, but someone is pinging the gateway every few seconds. How about IP? Do we do IPv6? Let's see. So we have loopback, 8.0, IPv4 via DHCP, and no, no IPv6 configured. IPv6 tunnel at none. I don't know where this tunnel is going, but yeah, I don't know what's up with that. USB 0, looks like it has a static IPv4 that's relatively normal for USB interfaces. And Tailscale 0, which again, I never configured and never told it to use. So nope, we don't do IPv6 either, because we can't do networking. So it looks like we're using BusyBox IFUpDown, which is etcnetworkinterfaces, and etcnetworkinterfaces is not configure interfaces. So who is if it's not BusyBox? So it is udhcpd, and that is our config, and this is super basic. It's handing out leases on USB 0 that last a heck of a long time. So here is the file that runs Ethernet, reserve inet 192.168.0.1.24, that's a weird thing to hard code, because that's probably a whole bunch of people's address. Looking for a file called eth0dhcp, then it's doing awful shell hackery to call IPA directly to set the static address in Bash. It sets the name servers to gateway, which would be the static gateway, and 8.8.8.8, and 114.114.114.114. So that is part of this guy, who is owned by Nanjing Xingfen Information Technologies Inc. ZenLayer Inc., okay, that's an interesting one. So this was all if you had a no DHCP configuration, otherwise we start up udhcpc, otherwise, otherwise we set reserve inet if we don't have an address at all. So here's instructions on how to do it, and then this is in Chinese, so I should probably translate that. Okay, that's all the same information that was there in English, just in Chinese. So as I expected, they have hardcode and resolve.conf, all of these IP addresses, so 1.2.168.0.1, 8.8.4.4, 8.8.8.8, 114.114.114.114. This guy, 119.29, who's he? He is owned by Tencent, it looks like, yeah, so he's being originated by Tencent to a whole bunch of tier 1s. What about our last one, 223.55.55, Alibaba, yes, so it's being originated by Alibaba to a number of Chinese networks, and then to the tier 1s. I don't know about you, I don't like when devices on the network go out to Google DNS, especially because they hardcoded it, they can't be bothered to read the network DNS over DHCP, and this doesn't even do IPv6, there's no RDNSS involved, it's just hardcoded like a bunch of random DNS servers they found on the internet. This is very, very sketchy, don't do this. And with that, I think I've investigated everything that the little light nano KVM can do, so it's time to move on to the bigger ones. What I decided up next, I'm going to try the PCIe version. Like I mentioned earlier, it doesn't actually speak PCIe, this is more just a mechanical bracket, what it does speak is USB, HDMI, and Ethernet, so we're going to hook all those things up to our target computer. Initially I thought this wire jumper cable was like an incredibly jank solution, then I realized what they're intending, you're supposed to unplug this here if you want to plug into the USB header on your motherboard, so I guess for some reason they couldn't have a USB hub to have multiple ports, so you have to unplug the USB HID port from the back, and you can plug that into the motherboard. Now this does have a pinout label on it, 5VDNDP, ground, so USB negative, USB positive, and that means that this pin here, my thumb is on, becomes the 5V power, so I can plug that in right here, and this guy will power up immediately, because USB power is always provided. So if I sit this guy in the slot, see he doesn't even use a PCIe x1, he just uses that little thing at the beginning of the PCIe slot, which is, I mean clearly he's not doing PCIe data here. I almost forgot, I can use one of these wires to connect to the power button, and then I can push it remotely. Log in to the KVM, security, please change your password, okay, okay, so I can see my computer, it's working. Another neat trick I got for you guys for the web UI here, this thing doesn't use HTTPS, that's right, it didn't even generate a self-signed cert, it just doesn't believe in security. So we're here in Wireshark, I can look up HTTP, looks like it called the endpoint API auth login, again this is just regular HTTP, it's not secure. It's doing some JSON exchange, API stream H.264, etc. So what does this login look like? So it's HTTP, the connection details are JavaScript, in JavaScript we have a key called username with a value of admin, and a key called password with a value of that. So at least it's encrypted, I guess, right? The response it gets back is JSON also, and it includes an auth token here, which is this long string. This is also a JWT, by the way, so you can see based on the format. Remember earlier how I said that GitHub issue said there was bad password security? Let's take a look at the code that actually generated that password. So that code is here, it's called EncryptFTS, it uses this super secret key called nanoKVMSIP2024, and then it just completely raw dogs AES to encrypt the data, which is just the literal plain text password, using the plain text secret key. So it didn't use a key derivation function either for the key or for the data, so they're basically doing this all wrong. I'm not sure if any of you guys are familiar with all the cryptographic research that goes into passwords, but passwords are a big challenge for cryptography. And one of the big reasons is that in cryptography, the closer your data is to random, the better it is for everyone involved. So it's harder to do a large section of attacks, like if you know that the string is eight characters long and the rest of it's padded with zeros, that makes your search space significantly smaller. So if you're doing AES-256 with an eight-character password, for example, you know that a whole bunch of the bytes come out as zero, so you can try a bunch of decryption keys knowing that those bytes are zero, and you've gained information here. So in the sense of storing passwords, it doesn't matter what the password is. Once the user enters their password, the actual bytes of the password should be gone. They should never leave the user's computer, because you don't actually care what the password was, you just care that you can compare it later. So the best practices of managing passwords is to, on the user's client side, take the password and hash it with a password hash function, or a key derivation function. You can also salt the password with the username, and some salt that's specific to your application. So a hash function takes a block of data, and generates a hash that is a fixed number of bits long, that represents the data, but is not a way that can be converted back. So when you take a hash, you can only go one way, you can't go backwards, theoretically you could have a hash collision where two blocks of data represent the same hash, that's just like incredibly unlikely due to probabilities, but it's technically possible. So why do we add the username and the salt? The salt is there so that if somehow all of your passwords were to leak, your entire password database was to leak, someone couldn't take a hashed password and use it on a different website because it's salted specific to your website. And the other reason to add the username is so that if two users have the same password, they don't have the same password hash. So the server side of this is very easy, the client does all of the hashing, gives it to the server, the server then adds it to the database, compares the database, the end. What they're doing here instead is they're taking the password plain text and a string that is completely not random, it's literally a string of letters, and using that as the key into AES. And you never ever want to use a string of letters as a key, you always want to use some key derivation function, which is like a password hash function, and same for the password, you don't need to use AES here, you need to use a password hash function. So password hash functions, I've mentioned a few times now, are essentially a special class of hash functions that take a long time. So with hash functions, if we were to say use SHA-1 for all of our passwords, SHA-1, in theory we can solve it backwards, which is really hard to do, but it's been done a couple times in history, which is why cryptographers consider it broken now, even though it's still quite secure. But what we could do is take a database of 6,000 random passwords, change all the zeros into ones, all the i's into ones, etc., mutate these passwords into maybe a million guesses, and try hashing them each time. And SHA-1 doesn't take very long to run, so you could probably run a million guesses in a couple minutes on a computer. So a password hash function is designed to take the password data that's very definitively not random, because some user came up with it, and turn it into hash data in a way that takes a lot of computational power. And this way, brute force attacking the passwords of the dictionary becomes really hard, because it might take you half a second to do each hash. Most of those hashes take a long time on a computer, that's why modern hash functions like Argon2 and stuff, they take a long time, but that's for password security. Obviously Cypedia's doing none of that, they're using AES in completely the wrong way, and this is really bad. So because this password was sent in the clear using a well-known encryption algorithm and a well-known key, anyone could decrypt your plain-tech password just from this unencrypted HTTP transport. So I have not succeeded yet in capturing the sketchy binary download, and I think that's because it already has it on it. So on GitHub, the latest version of the image file for the SD cards is dated November 2024. However, the latest version of the app is dated only two weeks ago, which would be January 2025. So I think what happened is these guys that they sent me were already updated with the latest version of the app. Now that is logical, that makes sense, you want to ship products with the latest software version. What doesn't make sense is why they haven't updated the image file on GitHub for two months. So I took the image file from GitHub, flashed it on here, we're going to try the Lite again with the image file so we can capture a software update. If I go to Update Runtime Library, please try again. That's an interesting failure. I'd also like to point out that the Lite version does not include a pre-installed SD card. So if you buy the Lite version, you'll have to be flashing the two- or three-month-old software from GitHub, and it will have problems. Oh my god, the password's just root. Root root. That's dumb. So anyway, since the default password used to just be root root, which is a terrible default password for an SSH root account, I got in, I added my CA certificate, so we're going to look at the update process, finally. He requested a zip file from cdn.cyp.com, and he requested latest.zip at, I think at a time. So this is a zip file that should contain some firmware. But anyway, download lib, yeah, so here's the function that actually does the downloading of the lib. So read device key, that must be a file, then it's calling maxivision.cp.com slash apiv1nkvm encryption is device key, it does a request, well at least it's using SSL when it downloads the sketchy lib from the internet. It doesn't check the lib itself or anything, but it does at least validate the server's CA certificate. So here's what it downloaded, so it downloaded the ELF file just directly, that's the file I already showed you guys earlier. So the GitHub users were not lying, it does in fact connect to a server in China where it downloads a custom ELF file that was custom built just for this device, by giving it its serial number. However, it only does that if you didn't buy the SD card from Cepede, because it seems they already do that for you on images they produce. So I guess that's better than nothing, maybe? It uses SSL too, so I guess it could be worse. It's not like a wide open HTTP remote code execution, you actually have to do a little bit of work. And it's still reaching out to Tailscale periodically, even though I again never configured Tailscale. It just really really wants to tell Tailscale everything that's going on in my life. Again nothing wrong with Tailscale here, Tailscale is doing what it's supposed to be doing. I don't like to use Tailscale, I have other solutions that I like better, and I don't like Tailscale reaching out on a device that I never told it to, and opening holes in my firewall just because it's there. And so now that we've solved that problem with the sketchy library download, let's look at the sketchy abuse of the USB Type-C connector and the USB Type-A connector both. So this little guy lets you connect ATX power to this thing, and USB-C is a connector that already has far too many things wrong with it, so we're going to need to add more weird modes to it. I really hate when people use a connector that has a well defined use like USB-C, better to use something else that's not well defined like an RJ-11, that's got all kinds of weird uses. So anyway there's three chips here, allegedly this can do power, power switch, hard drive, LED reset switch, so that's four functions, two in, two out, but there's only four wires on a USB, so either they're using a shield, or one of those is not actually going to anything, and I did read the name off of these three chips here, and I found what they are. They appear to be this guy, Photomass, so that would be a optical isolator, if I look at my datasheet here, come on, we're not ever going to be able to download a file. But anyway, it's a phototransistor, so that's what it is. So given that there's only three of them, clearly one of these four functions must be missing. I'm going to suspect that's hard drive LED. So we probably could have just left it out of the pinout, but I guess we'll ohm out and see what goes to what. So we're doing beep test mode, so I'm going to pick a random pin here, this pin right here, which is labeled what? Power switch. Power LED. Okay, so hard drive LED is not included. So that means that three of these pins on the USB connector are data, and the last one must be ground. So let's see. I'm using the shell as the ground, which I guess is pretty normal. So anyway, don't plug this thing into a USB port, don't try to use this USB type C port as a USB type C, because it's not type C, it's just digital lines pretending to be a USB port in trench code. So not good. Honestly, I don't know why they just didn't put some of these headers in here, like you could have put these headers here, and it would have been perfectly fine and normal. But no, we got to make use of improper USB connectors here. I almost forgot, these guys have a last trick. There should be some sort of LCD on here, there's one on the PCIe card too, but it's hard to get a video of. It's like they screwed through the peel with their screws, so I can't peel the peel. Nano KVM, so it shows my IP address, IPv4, because we don't support IPv6 of course, resolution H.264, 27 frames per second, middle quality. So I can't actually change anything here, I can just look at it, but it's still nice to see that we got an IP address, and I guess that's better than nothing. Up there too, it shows we have Ethernet, we don't have HDMI, can't really plug any of those in right now without turning it back off, but you get the idea. So I guess that little screen might be a slightly redeeming quality for some people. So anyway, should you buy one of these products? I guess they didn't do a great job demonstrating when you might need to use a KVM, I feel like people that watch my channel have seen one of these things before, I mean, you use this for remotely managing a computer, this computer doesn't have IPMI, so with one of these three devices I can hook up its HDMI and its USB port, and I can control it remotely, so I have access to the desktop or terminal or whatever, keyboard, mouse, and it's like complete remote access in a tiny little package. So would I buy one of these? Absolutely not. Now we're going to talk about that in great detail. And before you go down in the comments section, I don't want you saying anything negative about the country of China. You are welcome to talk about all of the problems that Sapeed has done, but I'd like to make it clear that they're not the only company doing this, for sure. This sort of bad IoT security is extremely common in the IoT industry, and we shouldn't let anyone get away with it, no matter what country they're from. So anyway, one of the big selling points is that it's cheap, so I click pre-order here, you can see it's not available in the US and Russia, so I guess I can't buy one anyway. But yeah, fun. If I go on Taobao here, it says it's 36 yuan, which seems too cheap, but I can't read it to tell what the rest of the page says. I'm guessing that's just like an option, and not the price of the lite version. It actually does show up on AliExpress, and it will let me buy it. It says release on February 28th, so I guess they can't ship it until then, so they must have gotten their FCC certification done. 49.72, which is 17% off, or 59.90. That's not really a good deal. So lite version is only 20.42, which also does not include an SD card that mine came with, so remember that. Does not contain system image card. The case is 5 bucks, that's probably what is 36 yuan on Taobao, the cheapest option. This little guy here, the lite, he's selling for about 30 bucks right now, plus shipping from China, direct from China. It's got 100 meg ethernet, RISC-V processor, boots off an SD card, has an HDMI input that goes into a GPU that does some proprietary shenanigans to get us our image, that's what that library download is used for, it's for HDMI input, and it has a USB that can emulate a keyboard and mouse. So hardware wise, for 20 or 30 bucks, I think this piece of hardware is nice. I really like the hardware. The lite hardware. And for the full version, I honestly like the hardware too. So this is black, we have the same boards as the lite version, but we have another board on top that has the display. They screwed over the screws for peeling the peel, so I can't peel the peel off, but you get the idea. And aside from absolutely abusing the USB type C connector in a way that it was never intended for and could potentially damage other devices, possibly, I think the hardware is fine too. I don't think the price is outrageous for what it is, I think it's a pretty good price for the HDMI input, the hardware you get. How much is the PCIe version? I don't see the PCIe version here. How much are you? So I have Wi-Fi PoE, so 55 bucks. So as for the PCIe, which is the computer over there, I think it's relatively misleading to say that it is a PCIe device. It does not actually connect to a PCI Express bus at all. It simply sits in the slot where it gets mechanical support and lives inside of your computer. So it goes inside the computer, I guess, but it's not connecting to the PCIe slot. If you want something that actually connects to the PCIe slot, I've done a review on an ASRock Rackboard that it's really hard to get, that actually does connect to PCIe and emulate a video card. But this doesn't do that, so you still have to have these outside jumper cables that look jank AF, and the whole point of having it inside the machine is to have it not jank. But we end up with that anyway. It does take USB and power from the internal USB header, which is A+, I guess. I think it supports remote power on it, it has the buttons for it. I actually didn't test it because I didn't want to shut down this computer, because it's doing important things. But other than that, it seems like the PCIe version works fine. It has Wi-Fi as an option. It stores your password in plain text on the SD card, which I guess is... There's not really a lot of other options it had, but it does. So that's fun. There's nothing wrong with a PCIe card to me, I just find it misleading when companies put devices in the PCIe slot that are not using PCI Express and call them PCIe devices. This does not show up in any way to the target computer over PCIe. It's not emulating a graphics card, which I think is what a lot of people expect it to do when it plugs into the PCIe bus. It's not somehow communicating with the computer. Just beware of that. So despite me liking the hardware, it's nice, it's compact, it has all the features that you'd want for a tiny little KVM. The software is a disaster. So the software did work. This particular one, the one that got stuck not working after an update, never did work again. But when I re-imaged the card, it works again now. So something goofy happened when it tried to automatically update itself and it broke itself. I don't know what happened. I didn't debug it, I just re-imaged it. If that were to happen to this one, I would have to unscrew it to take it apart to get to the SD card, which would be a pain. Not hard, but a pain. And if I want to re-image it, the image available on GitHub is currently about 3 months old, and the software is currently only 2 weeks old, so that means they're shipping an image that is not released. And that's not inherently a problem, except they're claiming this is open source. And so if they're not releasing their new build images as they build them, they're just, I don't know, updating them internally or something, then they're not really releasing all of the open source commitments that I think they are. I think that the reason that they're using the word open source for this is so they can get other people to do their development work. So I mean, this is kind of a big problem in the open source community. If a company comes and they make an open source product, and they're actually committed to open source, then other people should be able to work on it and use it in other ways. And like with PyKVM, for example, that's a project that was truly open source. And so the PyKVM developer sold hats that connected to a Raspberry Pi, and you could use them as a KVM, and he made the software too. And now there's a whole ecosystem of different companies that are making that different hardware that works for that case. But at the same time, you get a lot of development effort from different people that are all contributing to the project and making it better. And this is not using PyKVM. They've homebrewed their own thing, which is fine as a product. There's nothing wrong with that, except they did a bad job at it. But I think that by making it open source, they're hoping to get people to help them fix their big firmware problems. So like, if you follow their GitHub, there's all kinds of issues submitted about this big security issues. There's the thread that I followed. And it seems like the software was just kind of thrown together as a bare minimum functionality with like no thought to security or any data, things like that. So I really don't like the software on these little guys. I also really do not like that they're using a library that has to be compiled for a specific chip to get this HDMI input. And I'm not sure if that's a limitation of the fact that they're using a library that does neural network processing, like AI computer vision. And that's just a side effect of those functions being in the same library. Allegedly, you can compile an open source version of that library that doesn't have those neural net functions in it, and it will work for this use case. But the fact that they went through all this effort to build a web server that compiles the image for this specific unit means that they didn't see that that was a problem. And that's a problem to me. So I think I know why we ended up here. So basically, this is a post from Hacker News. Someone here is basically saying, why the hell didn't they use PyKVM? Why are they doing something special? They just have a basic SOC. It has JPEG codec. Why don't you just use V4L2? And one of the developers says, well, that'd be great. And we want to use PyKVM, but the BSP doesn't support V4L2. So we have to build the software from scratch. And so I guess they're going down this rabbit hole of developing their own KVM solution because they couldn't choose a chip that already had Linux support. And instead of adding Linux support for the chip, they're just using the vendor's API. And so this commenter here says, this just seems like you should have waited for Linux to upstream. Personally, I don't see why anyone would want to waste time with some random vendor's media API, because basically, video for Linux is the way to go. So anyway, enough ranting about this thing. I've been talking about it for like an hour now. So if you want to buy one, I have links down below to Taobao. If you buy them on AliExpress, you might not get them because they are currently still banned in the US, which I've been told is due to FCC, EMI, and EMC compliance. So electromagnetic compatibility. It's a pretty basic thing to sell a product with EMC compliance. I understand they have to do testing and they might still be in a prototyping phase or whatever, but you have to have a compliant product to sell in the US, basically. So they either already got certification in the EU or they get around it by shipping direct from China, which is how a lot of things on AliExpress get shipped, by the way. They are not FCC compliant or not CE compliant in the EU, and they get shipped anyway. So anyway, yeah, that's the NanoKVM. If you want to chat with me more about the NanoKVM, about RISC-V or Ghidra or any of these tools that I use, Discord server, got it on the link below. If you like the work I do and want to support me personally, again, I did not pay for these units so please send them to me. I did actually try to go out and buy my own unit a couple months ago and I couldn't because they're banned in the US. So I guess I had to get them by them sending them to me. But yeah, if you want to support the work I do, I have a Ko-Fi link down below for that. It's kind of like a Patreon except it's only a one-time thing, so I appreciate that. And as always, I'll see you guys on the next adventure. Transcribed by https://otter.ai