Improper error handling in Stack traces in SolarWinds Orion Platform

INTRODUCTION

eSecForte Technologies Security Researcher – Shashank Chaurasia found a Stored HTML Injection vulnerability in the SolarWinds Orion Platform 2018.4 HF3 (Network Performance Monitor 12.4, NetPath 1.1.4) and it has been assigned CVE-2019-12864 by the MITRE.

SolarWinds® Network Performance Monitor (NPM) is a powerful and affordable network monitoring software that enables you to quickly detect, diagnose, and resolve network performance problems and outages. Network Performance Monitor is a Multi-vendor network monitoring that scales and expands with the needs of your network, Key Features includes  Multi-vendor network monitoring, Network Insights for deeper visibility, Intelligent maps, NetPath and PerfStack for easy troubleshooting, Smarter scalability for large environments and Advanced alerting.

Vulnerable to Information Leakage, because of improper error handling in Stack traces. Information Leak / Disclosure (CWE-200) Error Handling (CWE-388)

Description: SolarWinds Orion Platform 2018.4 HF3 (NPM 12.4, NetPath 1.1.4) is vulnerable to Information Leakage, because of improper error handling with stack traces, as demonstrated by discovering a full pathname upon a 500 Internal Server Error via the api2/swis/query?lang=en-us&swAlertOnError=false query parameter.

Platform/Product: SolarWinds Orion Platform 2018.4 HF3 (NPM 12.4, NetPath 1.1.4)

Vulnerability Name: Vulnerable to Information Leakage, because of improper error handling in Stack traces. Information Leak / Disclosure (CWE-200) Error Handling (CWE-388)

Affected Component: Solarwinds Network Performance Monitor – Orion Platform 2018.4 HF3, NPM 12.4, NetPath 1.1.4

[Affected Component]
vulnerable url: /api2/swis/query?lang=en-us&swAlertOnError=false
vulnerable parameter: query

Attack Type: Local

Impact

Vulnerable to Information Leakage, because of improper error handling in Stack traces, as demonstrated by discovering a full pathname. This could be especially dangerous because it gives, several information about the server itself.

Method of Exploitation

Steps to Reproduce :-

1. Login to console with default creds “admin:blank-password”

Network Performance Monitor

2. Intercept this request in proxy tool from login process, as you can see now we have a normal 200 server response:

Network Performance Monitor

3. Now change the parameter to “null”, Here you can see we have received the response as 500 internal server error with stack trace and disclosing full path.

Network Performance Monitor

4. Here is the response in browser, click on Learn more.

Network Performance Monitor

5. Now click on error details:

Network Performance Monitor
Network Performance Monitor
Responsible Responsibility Disclosure
Responsible Responsibility Disclosure

Below Is the full stack trace received :

{

        “data”: {

                      “message”: “An error has occurred.”,

                      “exceptionMessage”: “RunQuery failed, check fault information.\nno viable alternative at input ‘NotificationTypeID’ in Select clause”,

                     “exceptionType”:

“System.ServiceModel.FaultException`1[[SolarWinds.InformationService.Contract2.InfoServiceFaultContract, SolarWinds.InformationService.Contract2, Version=2017.5.0.2118, Culture=neutral, PublicKeyToken=null]]”,

                     “stackTrace”: ”   at

SolarWinds.InformationService.InformationServiceClient.InformationServiceCommand.CreateFaultException(Message message)\r\n   at SolarWinds.InformationService.InformationServiceClient.InformationServiceCommand.HandleQueryResponse(Message message)\r\n   at SolarWinds.InformationService.InformationServiceClient.InformationServiceCommand.ExecuteReader(CommandBehavior behavior)\r\n   at SolarWinds.InformationService.InformationServiceClient.InformationServiceCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)\r\n   at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)\r\n   at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)\r\n   at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)\r\n   at SolarWinds.Orion.Core.Common.InformationService.InformationServiceProxy.<>c__DisplayClass8_0.<Query>b__0(InfoServiceProxy n)\r\n   at SolarWinds.Orion.Core.Common.ChannelProxy`1.CallMethodWithPool[TResult](Func`2 fnc, Boolean retryCall)\r\n   at SolarWinds.Orion.Core.Common.ChannelProxy`1.Invoke[TResult](Func`2 fnc, ChannelProxyBehavior behavior, String methodName)\r\n   at SolarWinds.Orion.Core.Common.ChannelProxy`1.Invoke[TResult](Func`2 fnc, ChannelProxyBehavior behavior)\r\n   at SolarWinds.Orion.Core.Common.InformationService.InformationServiceProxy.Query(String query, IDictionary`2 parameters)\r\n   at SolarWinds.Orion.Core.Common.InformationService.InformationServiceProxyImpersonate.Query(String query, IDictionary`2 parameters)\r\n   at SolarWinds.Orion.Web.Platform.Data.SwisRepository.Query(ISwisQuery query) in C:\\buildAgent\\work\\ba8b951e4f151874\\Src\\Lib\\SolarWinds.Orion.Web.Platform\\Data\\SwisRepository.cs:line 146\r\n   at SolarWinds.Orion.Web.Platform.Data.SwisRepository.Query(SwisQuery query) in C:\\buildAgent\\work\\ba8b951e4f151874\\Src\\Lib\\SolarWinds.Orion.Web.Platform\\Data\\SwisRepository.cs:line 132\r\n   at SolarWinds.Orion.Web.Services.Data.SwisQueryRepository.Query(String query) in C:\\buildAgent\\work\\ba8b951e4f151874\\Src\\Lib\\SolarWinds.Orion.Web.Services\\Data\\SwisQueryRepository.cs:line 20\r\n   at SolarWinds.Orion.Web.Services.SwisService.Query(String query) in C:\\buildAgent\\work\\ba8b951e4f151874\\Src\\Lib\\SolarWinds.Orion.Web.Services\\SwisService.cs:line 20\r\n   at SolarWinds.Orion.Api.Host.Controllers.SwisController.Query(QueryParam query) in C:\\buildAgent\\work\\a094ce66eb045248\\Src\\Web\\SolarWinds.Orion.Api.Host\\Controllers\\SwisController.cs:line 50\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Tracing.Tracers.HttpControllerTracer.<ExecuteAsyncCore>d__5.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()”

                },

                “status”: 500,

                “config”: {

                              “method”: “POST”,

                              “transformRequest”: [

                                      null

], 

                              “transformResponse”: [

                                     null

],

                            “jsonpCallbackParam”: “callback”,

                            “params”: {

                                           “swAlertOnError”: false,

                                           “lang”: “en-in”,

                                           “viewId”: 1,

                                          “swLogOnError”: [

                                                     401,

                                                    403,

                                                    500,

                                                    501,

                                                    502,

                                                    503,

                                                    504,

                                                    505,

                                                    506,

                                                    507,

                                                    508,

                                                    509,

                                                    510

                            ],

                            “swToastOnError”: [

                                                    401,

                                                    403,

                                                    500,

                                                    501,

                                                    502,

                                                    503,

                                                    504,

                                                    505,

                                                    506,

                                                    507,

                                                    508,

                                                    509,

                                                    510

                            ]

               },

               “headers”: {

                            “Accept”: “application/json, text/plain, */*”,

                            “Content-Type”: “application/json;charset=utf-8”,

                            “X-XSRF-TOKEN”: “Tqz8P+BGitQ7w25UsxhD4Ey5nM2ovCp9aR3WaJSjcic=”

              },

             “cache”: false,

             “url”: “http://esec-0165:8787/api2/swis/query”,

             “data”: {

                             “query”: “\nSELECT\n    NotificationTypeID,\n    RequiredRoleID\nFROM Orion.NotificationTypePermission\n”,

                             “parameters”: null

               }

},

“statusText”: “Internal Server Error”,

“xhrStatus”: “complete”

}