未授权访问(高危)

未授权访问漏洞,是在攻击者没有获取到登录权限或未授权的情况下,不需要输入密码,即可通过输入网站控制台主页面地址或者不允许查看的连接便可进行访问。

参考Nginx使用OpenResty+Lua+Redis进行token鉴权 (opens new window)

平台出现未授权访问高危漏洞,静态资源都是通过nginx代理,于是从这个思路在网上找到了类似案例

流程

获取url或者cookie中的token,然后去redis中查找token是否存在,如果存在就能访问,不存在就提示不能访问。这样对原本项目影响不大,后台逻辑不需要修改,直接使用现有token,前端需要看到图片的位置增加token参数或者直接增加cookie

OpenResty文档 (opens new window)

OpenResty最佳实践 (opens new window)

Lua参考手册 (opens new window)

安装OpenResty

# add the yum repo:
wget https://openresty.org/package/centos/openresty.repo
sudo mv openresty.repo /etc/yum.repos.d/

# update the yum index:
sudo yum check-update

sudo yum install -y openresty

编写Lua

local ngx = require "ngx"

--输出到页面
local function printOut(str)
    ngx.header.content_type = "text/plain;charset=utf-8"
    ngx.print(str)
    ngx.exit(200)
    return
end
--获取token,如果cookie中没有就从url上获取
local function getToken()
    -- 从cookie中获取token值key为token
    local token = ngx.var.cookie_token
    --判断token是否为空,为空跳转
    if not token then
        --从url中获取token
        token = ngx.req.get_uri_args()["token"]
    end
    return token
end

local token = getToken()

-- 测试输出
if not token then
    printOut("没有权限,无法访问")
    return
end

--有token走下面的
local function close_redis(red)
    if not red then
        return
    end
    local pool_max_idle_time = 10000 --毫秒
    local pool_size = 100 --连接池大小
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx.say("close redis error : ", err);
    end
end

-- 连接redis
local redis = require "resty.redis";
local red = redis:new();
red:set_timeout(2000)

local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
end

-- 请注意这里 auth 的调用过程 这是redis设置密码的
local res, err = red:auth("666666")
if not res then
    ngx.say("failed to authenticate: ", err)
end

local ok, err = red:select(2)
if not ok then
    ngx.log(ngx.ERR, "failed to select redis db: ", err)
    return ok, err
end

-- redis中若 key 存在返回 1 ,否则返回 0
local resp, err = red:exists("user_token:" .. token)
if not resp then
    ngx.say("get msg error : ", err)
end

if resp == ngx.null then
    resp = ''
end

if resp == 0 then
    printOut("没有权限,无法访问")
else
    if resp == 1 then
        -- 这里是redis中有值,不做任何操作
    end
end
close_redis(red)

nginx配置

# 如果开发的时候需要实时看到代码变化后的效果,就关闭lua_code_cache即可,默认开启
lua_code_cache on;
# lua文件路径
rewrite_by_lua_file /home/testredis.lua;

验证

openresty -s reload重启

直接访问提示无法访问,通过cookie或url传参可以访问