WLED has SPIFFS support, it can be enabled via headers in wled00.ino. I considered switching to an SPIFFS configuration file and will likely do soon-ish. The main problem would the high memory usage of using descriptive JSON keys. However I believe it would drastically increase transparency and code legibility. Do you know whether it's possible to have F() (or similar, store in flash) strings as JSON keys with ArduinoJSON 6? In that case, i'd highly prefer to switch to a config file in SPIFFS. Another issue is cleartext passwords, I'd rather not store them in an accessable file (at least not the home WiFi password). Maybe not storing them at all explicitely and making use of WiFi.persistant() would work, so we could get rid of the current EEPROM implementation entirely.
Hello Aircoookie :)
If I understand correctly what you mean, try to take a look on https://github.com/toblum/McLighting.
You probably already know about this project, and I studied this project a while ago, and he is using SPIFFS to store json config file right there. He also using JSON to handle everything, including the webUI. Maybe you can switch from xml to json this way in future also ;)
@Aircoookie Yes, I believe you can do that ArduinoJSON 6. I’ll take a lot over the docs today.
Aren’t we already physically storing the password in flash? (AFAIK the “EEPROM” library emulates an EEPROM using a segment of the flash; it exists to retain sketch compatibility with older Atmel chips that actually did have onboard EEPROM storage. That’s my understanding at least, I may be mistaken.)
Personally, I don’t think storing the WiFi passphrase in cleartext is that big of a deal anyway. I’m just thinking out loud here:
Aside from some glaring security hole that allows an attacker to dump the flash via OTA, they would need physical access to your device to dump the flash. But, for the sake of argument, let’s say they could somehow dump the flash remotely (across the internet) and get your password. What does the attacker gain? He still has to be in physical proximity to your WiFi router to actually use the password. So I don’t see that as a very big threat.
So the above is the worst case scenario, however the majority of these devices won’t be accessible from the internet, just your LAN. In order to do that they would already have to be on your local network. So now they’ve dumped your flash and gotten the password, to a network they’re already on, so they’re not really gaining anything there, either.
If they’re already on your LAN then they could have physical access to the device, so I suppose if they shielded and rebooted it, it would come up in SoftAP mode and they could connect to it and then dump the flash. However, if they have physical access to the device anyway it’s also likely they have physical access to your router as too, at which point they could just plug an Ethernet cable in and bypass WiFi all together.
Another thing we could maybe do is just compute and store the PSK instead of the actual passphrase. (If I recall correctly you use the SSID as the salt and do 4096 iterations of SHA1 to get the PSK.) Obviously the device has to already be doing this at some point, so there might be a way to access it. Though, now that I think about it I’m not sure what this gets you security wise as the PSK is just as useful as the passphrase for gaining access to your WiFi.
Something else to consider is that the WiFi.persistent() function must be storing the passphrase or PSK somewhere on the device. So you run into the same issue as above (if the attacker requires physical proximity to use the WiFi password, they’ve already got physical access to your device, which means they can dump the flash with a $20 piece of hardware).
I’m of the school of thought that passwords are like the lock on your front door. They keep casual intruders out (crimes of opportunity) but don’t keep a determined attacker (someone kicking the door down, or climbing through a window) away.
Again, just thinking out loud and running through the possible attack vectors in my head. (I spent years in network security, so it’s hard to resist!)
@Aircoookie doesn’t setting WiFi.persistent(true) cause a write to eeprom(flash) upon each boot? I know there had been some issue with both its behavior not matching documentation 3641 & 1393 and also with wearing out the flash due to excessive writes 5147.
Not sure if these are still, or truly ever were, issues that would concern this project but thought I would mention them
Okay, so I did a bit more research. First off, there is indeed a function to return the PSK that's part of the station class:
psk
Return current pre shared key (password) associated with the Wi-Fi network.
WiFi.psk()
Function returns value of theStringtype.
So, we could indeed simply store the PSK and use it instead of the passphrase. Now, an attacker could still use this PSK to gain access to your WiFi network, however, it would still obfuscate the passphrase itself. (As far as I know, there's no way to reverse the PBKDF2 hashing process and extract the passphrase from the PSK, aside from a brute force approach. If you had a very large array of GPUs you could maybe do it given a few days or weeks.)
So, if the goal is to just not have the passphrase easily visible from a flash dump, then we could just store the PSK. Basically, we use the passphrase to immediately call the WiFi connection functions, then store the PSK that's returned via the above function. Future connections would use the PSK instead of the passphrase.
Thanks for all the detailed insights! No, I don't think that we have to worry about a flash dump too much - the risk for that is even lower with SPIFFS then with EEPROM as the exact memory location in SPIFFS is potentially harder to figure out. I should have been clearer about what I mean, which is not SPIFFS per se but rather a built-in "file browser" function (which can be enabled in wled00.ino with #define WLED_ENABLE_FS_EDITOR), which would allow the user direct access to the contents of the filesystem (which I believe is useful not only for debugging, but also for manually making changes to presets, playlists and palettes that will be saved there in the future) which will also contain the config.json with all the settings.
That said, access to this editor is disabled if the OTA lock feature is set. I believe we could improve security by activating the OTA lock by default again - just need to figure out how to set an unique password by default that is not based on the MAC... will look into that in due time!
About the PSK, that would certainly be an option (although I couldn't find a function to connect to a network using the PSK, WiFi.psk() is just for obtaining it). We'll see, but I believe the OTA lock is secure enough, given that there are other potential attack vectors regardless, like an attacker connecting to WLED-AP during initial configuration and obtaining the password from the unencrypted POST request that is sent after the user saves the WiFi settings (although this is highly unlikely of course).
@Aircoookie Ah, I understand, sorry about that, the file browser didn’t even occur to me. (Like I said, I spent a few years in network security so my mind immediately starts processing all the scenarios and I can go off on a bit of a tangent...) Anyway, the file browser would still require someone to already have direct access to either the device or network, so I agree with your thoughts, especially in light of the OTA lock function.
As for the PSK, I believe you can simply use it in place of the passphrase with the standard WiFi connect function. I’ll double check that tonight as it applies to the ESP8266 WiFi library, but I know this is the case under some other platforms as it’s part of the WPA specification. Going by the standard, it is the technically correct method to use (calculate the PSK once from the passphrase, then only store and use the PSK). In practice I’m not sure it really matters that much either way. It might speed up the connection process by a small amount (maybe a second) as the device doesn’t have to generate the key each time.
Hey! This issue has been open for quite some time without any new comments now. It will be closed automatically in a week if no further activity occurs.
Thank you for using WLED!
Most helpful comment
@Aircoookie Yes, I believe you can do that ArduinoJSON 6. I’ll take a lot over the docs today.
Aren’t we already physically storing the password in flash? (AFAIK the “EEPROM” library emulates an EEPROM using a segment of the flash; it exists to retain sketch compatibility with older Atmel chips that actually did have onboard EEPROM storage. That’s my understanding at least, I may be mistaken.)
Personally, I don’t think storing the WiFi passphrase in cleartext is that big of a deal anyway. I’m just thinking out loud here:
Aside from some glaring security hole that allows an attacker to dump the flash via OTA, they would need physical access to your device to dump the flash. But, for the sake of argument, let’s say they could somehow dump the flash remotely (across the internet) and get your password. What does the attacker gain? He still has to be in physical proximity to your WiFi router to actually use the password. So I don’t see that as a very big threat.
So the above is the worst case scenario, however the majority of these devices won’t be accessible from the internet, just your LAN. In order to do that they would already have to be on your local network. So now they’ve dumped your flash and gotten the password, to a network they’re already on, so they’re not really gaining anything there, either.
If they’re already on your LAN then they could have physical access to the device, so I suppose if they shielded and rebooted it, it would come up in SoftAP mode and they could connect to it and then dump the flash. However, if they have physical access to the device anyway it’s also likely they have physical access to your router as too, at which point they could just plug an Ethernet cable in and bypass WiFi all together.
Another thing we could maybe do is just compute and store the PSK instead of the actual passphrase. (If I recall correctly you use the SSID as the salt and do 4096 iterations of SHA1 to get the PSK.) Obviously the device has to already be doing this at some point, so there might be a way to access it. Though, now that I think about it I’m not sure what this gets you security wise as the PSK is just as useful as the passphrase for gaining access to your WiFi.
Something else to consider is that the WiFi.persistent() function must be storing the passphrase or PSK somewhere on the device. So you run into the same issue as above (if the attacker requires physical proximity to use the WiFi password, they’ve already got physical access to your device, which means they can dump the flash with a $20 piece of hardware).
I’m of the school of thought that passwords are like the lock on your front door. They keep casual intruders out (crimes of opportunity) but don’t keep a determined attacker (someone kicking the door down, or climbing through a window) away.
Again, just thinking out loud and running through the possible attack vectors in my head. (I spent years in network security, so it’s hard to resist!)