OpenWrt系统安全改进<二>中所做的尝试,是为了增强用户登录的鉴权机制(密码输错三次就禁用用户一段时间),PAM可以实现对用户登录的控制,但是进一步操作中发现WebUI的登录并没有支持PAM,前功尽弃......
了解了一下OpenWrt的luci机制,参见http://www.360doc.com/content/14/0312/20/1964482_360072189.shtml,简单来说,就是使用uhttpd来解析http报文,一些具体的操作都由lua来实现。
本来是想修改uhttpd来实现这个功能,但是抓包看了一下,uhttpd并不关心luc程序的操作结果,虽然能够识别到用户登录,但是要获取密码认证结果却并不方便,于是只好硬着头皮上lua。
下面是最基本的实现,多用户,信息安全都没有考虑,以后可以改进一下。
另外,密码输错三次后,用户继续输入,返回在web页面的信息还是密码错误而不是用户被限制,也需要修改。
FORBIDEN_EXPIRE = 180
MAX_TRY = 3
local UserErrorCount = 0
local UserForbidenTime = 0
function writeErrCount(username,count)
os.execute("echo %s > /var/ErrCount" % count)
end
function readErrCount(username)
if fs.access("/var/ErrCount") then
return (tonumber(fs.readfile("/var/ErrCount")))
else
return 0
end
end
function writeForbidenTime(username,ftime)
os.execute("echo %s > /var/ForbidenTime" % ftime)
end
function readForbidenTime(username)
if fs.access("/var/ForbidenTime") then
return (tonumber(fs.readfile("/var/ForbidenTime")))
else
return 0
end
end
function fnsrDbg(string)
os.execute("echo %s >> /luaDbg" % string)
end
function isForbidenExpired(username)
curTime = uptime()
UserForbidenTime = readForbidenTime(username)
if curTime - UserForbidenTime > FORBIDEN_EXPIRE then
fnsrDbg("Forbiden Expired")
return true
else
fnsrDbg("Forbiden Not Expired")
return false
end
end
function isAllowed(username)
if readForbidenTime(username) == 0 then
fnsrDbg("UserAllowed")
return true
else
if isForbidenExpired(username) then
writeForbidenTime(username,0)
fnsrDbg("UserAllowed After ForbidenExpired")
return true
end
end
fnsrDbg("User Not Allowed")
return false
end
function updateAllowed(username,validate)
if validate then
writeErrCount(username,0)
else
UserErrorCount = readErrCount(username)
UserErrorCount = UserErrorCount + 1
writeErrCount(username,UserErrorCount)
if UserErrorCount == MAX_TRY then
UserAllowed = false
writeErrCount(username,0)
writeForbidenTime(username,uptime())
end
end
end