如何防止 WiFi 密码从 Lua 代码中泄漏?

我有一个 Lua 程序,可以连接到一个 Wi-Fi 网络。Wi-Fi 密码是硬编码在 Lua 代码中的。我将 Lua 代码放到运行在 NodeMCU 固件上的 ESP8266 上。

这是我使用的代码:

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID", "password")
wifi.sta.connect()

srv = net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive", function(conn, payload)
        print(payload)
        local response = "HTTP/1.1 200 OK\r\n\r\n<h1> Hello, NodeMcu.</h1>"
        conn:send(response, function()
            conn:close()
        end)
    end)
end)

当我将这个设置用于户外传感器时,任何人都可以获取 ESP8266,并读取 Lua 脚本以获取我的 Wi-Fi 密码。

  1. 有没有地方可以用 Lua 在 ESP8266 上加密密码?
  2. 是否可以使用一些外部加密单元?
  3. 编译后的 Lua 代码改变了什么?
点赞
用户131929
用户131929

任何类型的密码加密和 Lua 编译都是“安全通过观察性”(security by obscurity,指依靠信息难以获取来保证安全)。因此,它并不能提供安全保障。

我建议您根本不要将密码放入 Lua 代码中,而是在运行时设置密码。至少有三种选择:

请注意:虽然这种方法避免了在源代码中放置密码,但在从浏览器发送密码时,与 ESP 的连接不会加密(无法进行 SSL),存在一定风险。

2015-12-13 13:00:57
用户745049
用户745049

在 Lua 代码中,物理访问没有安全性。除其他回答外:ESP 有一个保存 WiFi 设置的选项。因此,这将使您无需将凭据放入 Lua 文件中。只需编程一次凭据,然后删除凭据代码。这将使获取凭据更加困难。至少读取代码的人看不到它。(但当然不是完全的安全选项,因为 这个。) 每次 ESP 重新启动或者 WiFi 网络在范围内时,它都会连接到相同的 SSID 和网络。这是默认设置。

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID", "password")
wifi.sta.connect()

另一种方法是 MAC 地址注册。如果你的 AP 允许你注册站点的 MAC 地址,那么它将提供一层更安全的保护,因为获取密码不足以连接 WiFi 网络。这并不保护您的密码!您需要配置您的 AP 来这样做。

还有一种方法: 这将需要更多的代码。我不能说它更安全,但它会使它更难发现。您应该编译您的 Lua 文件以使用此功能。只需使用 SSID 对密码进行 XOR 处理,并在代码中放置 xor'ed 版本。调查网络并为每个网络创建密码。尝试以生成的密码连接所有人。匹配的一对将成功连接。其他人则失败。这将使连接序列变得稍微长一些。

--encode
--retuns a table containing bytes
--also prints what should be in code
-- s is ssid, p is password
function encode(s,p)
    key = s..s --encoding key, must be longer than password
    enc = {} --new table
    uart.write(0,"Key output: {")

    for i=1,string.len(p) do
        c = bit.bxor(p:byte(i),key:byte(i))
        table.insert(enc,c)
        if i == string.len(p) then
            uart.write(0,c.."}")
        else
            uart.write(0,c..",")
        end
    end
    return enc
end

--decode
--tries to decode password with table enc
--s is ssid (got from survey) encval is byte table
function decode(s,encval)
    key=s..s
    pass=""
    for ii,i in ipairs(encval) do
        c = bit.bxor( key:byte(ii),i)
        pass = pass..string.char(c)
    end
    print("password: "..pass)
    return pass
end

-- lets say ssid="network" and password="psswrd12"
encodedpass = encode("network","psswrd12")
-- this will print: Key output: {30,22,7,0,29,22,90,92}
-- this will be included in code
-- and to decode
print(decode("network",encodedpass))
-- will print: password: psswrd12
2015-12-14 10:52:04
用户3634232
用户3634232

我还考虑使用I2C EEPROM来存储密钥,这样任何妥协也需要硬件而不仅仅是Lua / Flash,但即使机器已被物理破坏,也可以“窃听”它,就像通过数据范围探测电路一样。

有一个答案,或者至少是“不能”的一部分,它没有在其他反向工程警告中提到:

严格来说:(我作为一个在这个领域工作了几十年的人说)你不应该把任何“物联网”类型的设备放在公共可访问的地方,除非它真正连接到自己的“物联网”接入点。虽然这听起来可能有些过度了(如果只是为了进行简短的测试,那就是过度了),但这是真正保护自己免受反向工程可能发生的唯一方法。

然后,您当然应该将该访问点网络从您的家庭“私人”网络中的DMZ网络机器防火墙隔离开。拥有一台带有几个NIC的备用旧PC即可运行类似IPCop的发行版,这使得这一步相对简单且成本较低。

但即使只是在同一网络上使用不同的访问点/密码组合,也可以对该AP实施更严格的策略

同样,在您的使用情况下,这可能看起来有些过度,但如果您真的关心网络安全并且想要释放“物品”,这是更好的选择-长期。

作为副笔:我确实认为家用AP /路由器需要很快内置这样的功能,以便未来的Things Home能够无需额外的技能或硬件进行操作。

2015-12-21 09:03:17
用户1241224
用户1241224

当你连接ESP8266之后,它会在内部存储密码,因此在之后的重新连接时你无需再输入密码,你可以省略密码参数或者传递空值。

我将所有的运行时设置保存在一个名为settings.lua的文件中,格式如下:

cfg.WiFiAP = "myAP"
cfg.WiFiPwd = "*****"

我在init.lua中加载到一个全局表中,代码如下:

cfg = {}
dofile("settings.lua")

当我初始化WiFi时,我检查密码是否为空。如果不为空,我用它连接WiFi,然后将其设置为空,并覆盖设置文件:

if cfg.WiFiPwd ~= nil then
    wifi.sta.config(cfg.WiFiSSID, cfg.WiFiPwd, 0)
    cfg.WiFiPwd = nil
    require("writecfg")()
end

writecfg.lua的代码如下:

local module =...
return function()
    print("[writecfg]")
    file.open("settings.lua", "w+")
    for k,v in pairs(cfg) do
        if v == nil then
            v = ""
        end
        local buf = "cfg." .. k .. " = \"" .. v .. "\""
        file.writeline(buf)
        buf = nil
    end
    file.close()
    file.remove("settings.lc")
    package.loaded[module] = nil
    module = nil
end

可能不太可能让ESP8266放弃密码,但确实比存储在代码中更加困难,无论你怎样模糊它。

2016-03-10 06:41:04