Table of Contents for
Python Web Penetration Testing Cookbook

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Python Web Penetration Testing Cookbook by Dave Mound Published by Packt Publishing, 2015
  1. Cover
  2. Table of Contents
  3. Python Web Penetration Testing Cookbook
  4. Python Web Penetration Testing Cookbook
  5. Credits
  6. About the Authors
  7. About the Reviewers
  8. www.PacktPub.com
  9. Disclamer
  10. Preface
  11. What you need for this book
  12. Who this book is for
  13. Sections
  14. Conventions
  15. Reader feedback
  16. Customer support
  17. 1. Gathering Open Source Intelligence
  18. Gathering information using the Shodan API
  19. Scripting a Google+ API search
  20. Downloading profile pictures using the Google+ API
  21. Harvesting additional results from the Google+ API using pagination
  22. Getting screenshots of websites with QtWebKit
  23. Screenshots based on a port list
  24. Spidering websites
  25. 2. Enumeration
  26. Performing a ping sweep with Scapy
  27. Scanning with Scapy
  28. Checking username validity
  29. Brute forcing usernames
  30. Enumerating files
  31. Brute forcing passwords
  32. Generating e-mail addresses from names
  33. Finding e-mail addresses from web pages
  34. Finding comments in source code
  35. 3. Vulnerability Identification
  36. Automated URL-based Directory Traversal
  37. Automated URL-based Cross-site scripting
  38. Automated parameter-based Cross-site scripting
  39. Automated fuzzing
  40. jQuery checking
  41. Header-based Cross-site scripting
  42. Shellshock checking
  43. 4. SQL Injection
  44. Checking jitter
  45. Identifying URL-based SQLi
  46. Exploiting Boolean SQLi
  47. Exploiting Blind SQL Injection
  48. Encoding payloads
  49. 5. Web Header Manipulation
  50. Testing HTTP methods
  51. Fingerprinting servers through HTTP headers
  52. Testing for insecure headers
  53. Brute forcing login through the Authorization header
  54. Testing for clickjacking vulnerabilities
  55. Identifying alternative sites by spoofing user agents
  56. Testing for insecure cookie flags
  57. Session fixation through a cookie injection
  58. 6. Image Analysis and Manipulation
  59. Hiding a message using LSB steganography
  60. Extracting messages hidden in LSB
  61. Hiding text in images
  62. Extracting text from images
  63. Enabling command and control using steganography
  64. 7. Encryption and Encoding
  65. Generating an MD5 hash
  66. Generating an SHA 1/128/256 hash
  67. Implementing SHA and MD5 hashes together
  68. Implementing SHA in a real-world scenario
  69. Generating a Bcrypt hash
  70. Cracking an MD5 hash
  71. Encoding with Base64
  72. Encoding with ROT13
  73. Cracking a substitution cipher
  74. Cracking the Atbash cipher
  75. Attacking one-time pad reuse
  76. Predicting a linear congruential generator
  77. Identifying hashes
  78. 8. Payloads and Shells
  79. Extracting data through HTTP requests
  80. Creating an HTTP C2
  81. Creating an FTP C2
  82. Creating an Twitter C2
  83. Creating a simple Netcat shell
  84. 9. Reporting
  85. Converting Nmap XML to CSV
  86. Extracting links from a URL to Maltego
  87. Extracting e-mails to Maltego
  88. Parsing Sslscan into CSV
  89. Generating graphs using plot.ly
  90. Index

Extracting text from images

In the previous recipe, we saw how to hide text in the RGBA values of an image. This recipe will let us extract that data out.

How to do it…

We saw in the previous recipe that we split up a characters byte into 8 bits and spread them over the LSBs of two pixels. Here's that diagram again as a refresher:

How to do it…

The following is the script that will do the extraction:

from PIL import Image
from itertools import izip

def get_pixel_pairs(iterable):
    a = iter(iterable)
    return izip(a, a)


def get_LSB(value):
    if value & 1 == 0:
        return '0'
    else:
        return '1'

def extract_message(carrier):
    c_image = Image.open(carrier)
    pixel_list = list(c_image.getdata())
    message = ""

    for pix1, pix2 in get_pixel_pairs(pixel_list):
        message_byte = "0b"
        for p in pix1:
            message_byte += get_LSB(p)

        for p in pix2:
            message_byte += get_LSB(p)

        if message_byte == "0b00000000":
            break

        message += chr(int(message_byte,2))
    return message

print extract_message('messagehidden.png')

How it works…

First, we import the Image module from PIL; we also import the izip module from itertools. The izip module will be used to return pairs of pixels:

from PIL import Image
from itertools import izip

Next, we create two helper functions. The get_pixel_pairs function takes in our pixel list and returns the pairs back; as each message character was split over two pixels, this makes extraction easier. The other helper function get_LSB will take in an R, G, B, or A value and use a bit mask to get the LSB value and return it in a string format:

def get_pixel_pairs(iterable):
    a = iter(iterable)
    return izip(a, a)


def get_LSB(value):
    if value & 1 == 0:
        return '0'
    else:
        return '1'

Next, we have our main extract_message function. This takes in the filename of our carrier image:

def extract_message(carrier):

We then create an image object from the filename passed in and then create an array of pixels from the image data. We also create an empty string called message; this will hold our extracted text:

c_image = Image.open(carrier)
pixel_list = list(c_image.getdata())
message = ""

Next, we create a for loop that will iterate over all of the pixel pairs returned using our helper function get_pixel_pairs; we set the returned pairs to pix1 and pix2:

for pix1, pix2 in get_pixel_pairs(pixel_list):

The next part of code that we will create is a string variable that will hold our binary string. Python knows that it'll be the binary representation of a string by the 0b prefix. We then iterate over the RGBA values in each pixel (pix1 and pix2) and pass that value to our helper function, get_LSB, the value that's returned is appended onto our binary string:

message_byte = "0b"
for p in pix1:
    message_byte += get_LSB(p)
for p in pix2:
    message_byte += get_LSB(p)

When the preceding code runs, we will get a string representation of the binary for the character that was hidden. The string will look like this 0b01100111, we placed a stop character at the end of the message that was hidden that will be 0x00, when this is outputted by the extraction part we need to break out of the for loop as we know we have hit the end of the hidden text. The next part does that check for us:

if message_byte == "0b00000000":
            break

If it's not our stop byte, then we can convert the byte to its original character and append it onto the end of our message string:

message += chr(int(message_byte,2))

All that's left to do is return the complete message string back from the function.

There's more…

Now that we have our hide and extract functions, we can put them together into a class that we will use for the next recipe. We will add a check to test if the class has been used by another or if it is being run on its own. The whole script looks like the following. The hide and extract functions have been modified slightly to accept an image URL; this script will be used in the C2 example in Chapter 8, Payloads and Shells:

#!/usr/bin/env python

import sys
import urllib
import cStringIO

from optparse import OptionParser
from PIL import Image
from itertools import izip

def get_pixel_pairs(iterable):
    a = iter(iterable)
    return izip(a, a)

def set_LSB(value, bit):
    if bit == '0':
        value = value & 254
    else:
        value = value | 1
    return value

def get_LSB(value):
    if value & 1 == 0:
        return '0'
    else:
        return '1'

def extract_message(carrier, from_url=False):
    if from_url:
        f = cStringIO.StringIO(urllib.urlopen(carrier).read())
        c_image = Image.open(f)
    else:
        c_image = Image.open(carrier)

    pixel_list = list(c_image.getdata())
    message = ""

    for pix1, pix2 in get_pixel_pairs(pixel_list):
        message_byte = "0b"
        for p in pix1:
            message_byte += get_LSB(p)

        for p in pix2:
            message_byte += get_LSB(p)
            
        if message_byte == "0b00000000":
            break

        message += chr(int(message_byte,2))
    return message

def hide_message(carrier, message, outfile, from_url=False):
    message += chr(0)
    if from_url:
        f = cStringIO.StringIO(urllib.urlopen(carrier).read())
        c_image = Image.open(f)
    else:
        c_image = Image.open(carrier)
        
    c_image = c_image.convert('RGBA')

    out = Image.new(c_image.mode, c_image.size)
    width, height = c_image.size
    pixList = list(c_image.getdata())
    newArray = []

    for i in range(len(message)):
        charInt = ord(message[i])
        cb = str(bin(charInt))[2:].zfill(8)
        pix1 = pixList[i*2]
        pix2 = pixList[(i*2)+1]
        newpix1 = []
        newpix2 = []

        for j in range(0,4):
            newpix1.append(set_LSB(pix1[j], cb[j]))
            newpix2.append(set_LSB(pix2[j], cb[j+4]))

        newArray.append(tuple(newpix1))
        newArray.append(tuple(newpix2))

    newArray.extend(pixList[len(message)*2:])

    out.putdata(newArray)
    out.save(outfile)
    return outfile   


if __name__ == "__main__":


    usage = "usage: %prog [options] arg1 arg2"
    parser = OptionParser(usage=usage)
    parser.add_option("-c", "--carrier", dest="carrier",
                help="The filename of the image used as the carrier.",
                metavar="FILE")
    parser.add_option("-m", "--message", dest="message",
                help="The text to be hidden.",
                metavar="FILE")
    parser.add_option("-o", "--output", dest="output",
                help="The filename the output file.",
                metavar="FILE")
    parser.add_option("-e", "--extract",
                action="store_true", dest="extract", default=False,
                help="Extract hidden message from carrier and save to output filename.")
    parser.add_option("-u", "--url",
                action="store_true", dest="from_url", default=False,
                help="Extract hidden message from carrier and save to output filename.")

    (options, args) = parser.parse_args()
    if len(sys.argv) == 1:
        print "TEST MODE\nHide Function Test Starting ..."
        print hide_message('carrier.png', 'The quick brown fox jumps over the lazy dogs back.', 'messagehidden.png')
        print "Hide test passed, testing message extraction ..."
        print extract_message('messagehidden.png')
    else:
        if options.extract == True:
            if options.carrier is None:
                parser.error("a carrier filename -c is required for extraction")
            else:
                print extract_message(options.carrier, options.from_url)
        else:
            if options.carrier is None or options.message is None or options.output is None:
                parser.error("a carrier filename -c, message filename -m and output filename -o are required for steg")
            else:
                hide_message(options.carrier, options.message, options.output, options.from_url)