【问题标题】:How to prevent WiFi Password from being leaked from Lua code?如何防止 WiFi 密码从 Lua 代码中泄露?
【发布时间】:2016-03-10 14:41:04
【问题描述】:

我有一个连接到 wifi 网络的 Lua 程序。 wifi 密码是硬编码在 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 脚本并获取我的 WiFi 密码。

  1. 有什么地方可以用 Lua 加密 ESP8266 上的密码吗?
  2. 是否可以使用一些外部加密单元?
  3. 编译的 Lua 代码有什么改变吗?

【问题讨论】:

  • 物理访问是完全访问。您无法在攻击者无法逆向工程的同一台设备上同时加密和使用密码。
  • 将您的程序存储为字节码,但不要将您的密码公开为字符串文字:wifi.sta.config("SSID",(('948197979B939684'):gsub('..',function(s)return s.char(tonumber(s,12))end)))
  • @EgorSkriptunoff 你是什么意思我的“作为字节码”你的意思是把代码编译成.lc?您能否详细回答一下您将如何处理密码问题?
  • @confile - 编译字节码:luac -s -o program.luac program.lua。您可以使用对密码进行评估的任何重要表达式。这不是一个完整的解决方案,它只会让您的密码更难提取。
  • @confile - 您不能在字符串文字中插入密码,因为它会在 .luac 文件中可见。这就是为什么您需要一些表达式,它将在运行时进行评估以获取您的密码。

标签: lua esp8266 nodemcu


【解决方案1】:

(更新)

在 Lua 代码中,物理访问没有安全性。除了其他答案:ESP 可以选择保存 wifi 设置。因此,这将允许您不将凭据放入 lua 文件中。对凭据进行一次编程,然后删除凭据代码。这将使获取凭据变得更加困难。至少阅读代码的人不会看到它。 (但由于this,当然不是一个完整的安全选项。) 每次 esp 重新启动或 wifi 网络在范围内时,它都会连接到相同的 ssid 和网络。这是默认开启的。

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

另一种方法是注册 MAC 地址。如果您的 AP 允许您注册站点的 mac 地址,那么它将提供多一层安全性,因为获取密码不足以连接 wifi 网络。这不是保护您的密码!您需要配置您的 AP 来执行此操作。

另一种方法: 这将需要更多代码。我不能说它更安全,但它会让它更难被发现。你应该编译你的 lua 文件来使用它。只需使用 ssid 异或您的密码,然后将异或后的版本放入您的代码中。调查网络并为每个网络创建密码。尝试将每个人与制作的通行证联系起来。匹配对将成功连接。其他人将失败。这将使连接序列更长一点。

--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

【讨论】:

  • 能否请您添加一个代码示例来说明如何做到这一点?
  • @confile 是哪一个? 1? 2? 3?
  • 我会的。但我要到明天才能完成。明天我会编辑帖子。
  • 那就完美了。
  • 这并不比@egor-skriptunoff 最初的 cmets 好。默认情况下启用自动连接,MAC 地址注册是与 NodeMCU/ESP8266 无关的标准 WiFi 安全措施,并且将密码与其他东西进行异或就像使用不同算法的 radix 12 方法一样。这一切都只是默默无闻。
【解决方案2】:

连接后,ESP8266 会在内部存储密码,之后无需重新连接,只需省略密码参数或传递 nil。

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

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

我将它加载到 init.lua 中的全局表中,如下所示:

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

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

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 放弃密码可能并非不可能,但无论您如何尝试混淆,这肯定比将其存储在代码中要困难得多。

【讨论】:

    【解决方案3】:

    任何类型的密码加密和 Lua 编译都是隐蔽的安全性(因此没有安全性)。

    我建议你不要把密码放在 Lua 代码中,而是在运行时设置。至少有 3 个选项:

    注意:虽然这避免了将密码放在源代码中,但它会带来轻微的风险,因为当密码从浏览器发送时,与 ESP 的连接是加密的(不能进行 SSL )。

    【讨论】:

    • 有没有办法在 C 上调用和配置最终用户设置(使用 Visual Studio / Atmel Studio / Arduino Studio)?
    【解决方案4】:

    我还考虑使用 I2C EEPROM 来存储密钥,因此任何妥协也需要硬件,而不仅仅是 Lua/Flash,如果机器受到物理损坏,即使这样也能够被“窥探”,正如我想象的那样,通过使用数据范围探测电路可能会出现这种情况。

    有一个答案,或者至少是“你不能”的答案的一部分,这在逆向工程的其他警告中没有涉及:

    严格来说:(我是作为在该领域工作了几十年的人这么说的)您不应该将任何“物联网”类型的设备放在没有连接到自己的可公开访问的地方“物联网”接入点真的。虽然这听起来有点矫枉过正(如果只是为了一个简短的测试,可能是这样),但这是真正保护自己免受逆向工程发生可能性的唯一方法。

    然后,您当然应该使用 DMZ 网络机器从您的家庭“私有”网络中对接入点网络进行防火墙,以便与“事物”进行通信。一台带有几个 NIC 的备用旧 PC,运行类似 IPCop 发行版的东西,这使得这相当简单且相对便宜。

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

    同样,这可能对于您的用例来说似乎有点过头了,我同意在快速测试情况下,但如果您认真对待网络安全并且想要释放 Things,那么它就是更好的方式 - 长期。

    附带说明:我确实认为家庭 AP/路由器需要尽快内置类似的东西,以便未来的物联网家庭拥有这种能力,而无需额外的技能或硬件。

    【讨论】:

      猜你喜欢
      • 2011-08-31
      • 1970-01-01
      • 2014-09-01
      • 2011-01-06
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      相关资源
      最近更新 更多