Posts Tagged “python”

easy_install for python3 simple

1
2
curl -O http://python-distribute.org/distribute_setup.py
python3 distribute_setup.py

Enjoy!

Tags: , ,

Comments No Comments »

Before you read any further note, I will not be including the original hack file, simply due to peoples stupidity in putting this on a production environment to play with, if you use the code you do so at your own risk, and by reading this blog entry / using the code provided you agree to accept all liability upon yourself for your own actions. Don’t be an idiot.

Around 10 days ago I came across this seemingly innocuous little file.

What I am going to cover in this entry is dissecting the ‘payload’ and not so much the web app in question or methods used to compromise it,

Whereas I will not at this time provide the original file, I will provide you with the md5 and sha1 hashes of the file so you can check it’s not lurking on your systems:

md5: 9ee3e6523d154114460d320477a8665a
sha1: 9c64fecea5620d70a716bbd74f6e89612a4a79c7

The bit we are interested in is the last line of the file:

Were you to run this line you would get

Confused yet? now I can appreciate the thinking behind packing a payload to avoid detection, but in this case the payload is packed 12 times, and no before you ask I did not manually run each returned statement to find this out.

Enter Python-Fu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/env python
# saiweb.co.uk payload unpack script 26/05/2010
# copy the eval(gzinflate()) line to payload.raw, place in same directory as this file.

"""
Copyright (C) 2010 Buzz saiweb.co.uk.co.uk

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   
    Additional Terms as Per section 7

    Attribution:

    Redistribution/Reuse of this code is permitted under the GNU v3 license, as an additional term ALL code must carry the original Author(s) credit in comment form.
"""


import base64, zlib, re, sys

def main():
    print 'Running ...'
    f = open('payload.raw')
    php = f.read()
    f.close()
    iteration = 0
    while re.search('eval\(gzinflate\(base64_decode\(\'',php):
        iteration += 1
        print 'Iteration: %d' % iteration
        raw = re.sub('eval\(gzinflate\(base64_decode\(\'','',php)
        raw = re.sub('\'\)\)\);','',raw)
       
        gstring = base64.b64decode(raw.strip())
        php = zlib.decompressobj().decompress('x\x9c' + gstring)
        #print payload
        #sys.exit()
    print php
if __name__ == '__main__':
    main()

Copy the first payload lines into a file named payload.raw, take the above code and copy it into a file named dissect.py.

When dissect.py is run you will get the following output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
python ./dissect.py
Running ...
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Iteration: 5
Iteration: 6
Iteration: 7
Iteration: 8
Iteration: 9
Iteration: 10
Iteration: 11
Iteration: 12
<?php
...

As such you may want to run it using the following command:

1
python ./dissect.py > r57.php

And what you will find after unpacking 12 times in total, the “payload” is the r57shell, this script is an information gathering tool and pseudo shell, meaning it will run any command on the host server that php can, providing in most cases ssh esq access to the exploited host, allowing you to do pretty much anything you wanted at this point, some of the features also include /etc/passwd /etc/shadow dumping, aswell as searching for a tirade of common file *.sql* admin* etc, it’s a one stop script for information gathering on a LAMP/WAMP based host.


Defense: modify php.ini to disable eval(), exec, shell_exec and all none essential functions.

And of course, ensure your web apps are patched and up to date as well as the host they are running on.

Tags: , , , , ,

Comments No Comments »

Following on from the python bindings post I found myself with a real problem,

the netsnmp bindings I could not for the life of me get to take the redhat cluste MIB files, so what did that leave me with, walking the entire parent cluster OID, manually matching the returned OID’s to their MIB names based on the value returned as I couldn’t find a decent mib browser or script to convert them …

At any rate here is a subset of OID’s for polling the redhat cluster service using snmp, please note that are more OID’s but these vary on your cluster config.

Python code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
rhc_oid = '.1.3.6.1.4.1.2312.8'
        data_oids = {
                                'rhcMIBVersion':'.1.1',
                                'rhcClusterName':'.2.1',
                                'rhcClusterStatusCode':'.2.2',
                                'rhcClusterStatusDesc':'.2.3',
                                'rhcClusterVotesNeededForQuorum':'.2.4',
                                'rhcClusterVotes':'.2.5',
                                'rhcClusterQuorate':'.2.6',
                                'rhcClusterNodesNum':'.2.7',
                                'rhcClusterNodesNames':'.2.8',
                                'rhcClusterAvailNodesNum':'.2.9',
                                'rhcClusterAvailNodesNames':'.2.10',
                                'rhcClusterUnavailNodesNum':'.2.11',
                                'rhcClusterUnavailNodesNames':'.2.12',
                                'rhcClusterServicesNum':'.2.13',
                                'rhcClusterServicesNames':'.2.14',
                                'rhcClusterRunningServicesNum':'.2.15',
                                'rhcClusterRunningServicesNames':'.2.16',
                                'rhcClusterStoppedServicesNum':'.2.17',
                                'rhcClusterStoppedServicesNames':'.2.18',
                                'rhcClusterFailedServicesNum':'.2.19',
                                'rhcClusterFailedServicesNames':'.2.20'}

        for item in data_oids:
                oid = '%s%s' % (rhc_oid,data_oids[item])
                print item,oid

Tags: , , ,

Comments No Comments »

UPDATE 28/06/10: added –libdir=/usr/lib64 –enable-shared otherwise shared libs are not built at all!

Having spent a few hours trying to get this working on CentOS 5.4 x64 I am posting this blog entry for others to reference:

Download and complie net-snmp >= 5.4.2.1 http://net-snmp.sourceforge.net/

1
2
3
4
5
./configure --with-python-modules --libdir=/usr/lib64 --enable-shared
make && make install
cd /path/to/net-snmp-src/python/
python ./setup.py build
python ./setup.py test

You may get ImportError: libnetsnmp.so.20, this is due to x64 build creating as /usr/lib64/libnetsnmp.so.10

1
2
ln -s /usr/lib64/libnetsnmp.so.10.0.3 /usr/lib64/libnetsnmp.so.20
python ./setup.py install

And you are done, you can now use the netsnmp python bindings, I’d recomend seeing the examples here: http://www.ibm.com/developerworks/aix/library/au-netsnmpnipython/

Tags: , , ,

Comments No Comments »

Following on from Linux – Generating file manifests and then checking them I was always getting the same questions …

How long left on the manifest Buzz ?
How long left on the verification Buzz ?

And I HATE having to turn around an say … I don’t know …

The problem with the usual command line method is that it give no indication of progress, and by extension no indication that it was infact running and not ‘hung’ …

As such I have now added the ‘manifest’ command set to the Sysadmin toolset

The manifest command take two data types, the first is a folder path from which to build the file manifest from, the manifest itself is also compatible with the “md5sum –check” function.

The second is the path to the manifest itself, in this case the manifest command will verify each file against it’s entry in the manifest:

At each point the command give you an indication of it’s current status, however this does come at a small cost, the script has no concept of the size of you console and as such will always render out the same number of character meaning if you console is not wide enough it will not render correctly, in the videos I have the console on a high resolution monitor as can be seen each video itself is 900 pixels wide.

This process is CPU intensive (20-45% on one core of a intel core2duo 2.8GHZ) and uses around 140KB of memory.

Tags: , , , , , , , ,

Comments No Comments »

I had a major issue facing the iconv functionality of the sysadmin toolset namely due to rushed coding.

When loading a file to be re-encoded the entire file was loaded into the buffer, encoded as whole and written out to the new file, this of course meant the  memory usage was roughly double the size of the file to be converted plus any overheads to do with the encoding itself.

Today I had need to convert a 1.3GB sql file, needles to say the script was crashing out with a memory error.

As such I have now completely re-written the function it now processes the file in 1kb ‘chunks’, moving the load to the CPU, this process is now very cpu intensive the the memory overhead is minimal (during test processed the 1.3GB file using 113kb of memory!!!).

Also I have now added BOM (Byte order mark) detection:

Tags: , , , ,

Comments No Comments »

I meant to write this up over a week ago now, basically the need arose for one of my Python scripts to use HTTP Basic authentication when grabbing the output from a URL.

An example script can be seen below:

Quick description, the script will attempt to connect to a URL and read the data supplied by the webserver, if a HTTP 401 error is returned (Authentication required) the script will then go on to attempt to authenticate using the credentials supplied.

Printing out to the console at each point.

Subversion: http://svn.saiweb.co.uk/branches/python/urllib2_httpbasic_auth.py

Highlighted source (at the time of writing)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python
"""
    Author: David Busby (http://saiweb.co.uk)
    Program: Python HTTP Basic Auth Exa
    Copyright: David Busby 2009. All rights reserved.
    License: http://creativecommons.org/licenses/by-sa/2.0/uk/
"""


import urllib2, base64

""" URL List """
urls = {
               0:{"url":"www.saiweb.co.uk/some/fictional/auth/area","user":"someuser","pass":"somepass"}
}

def main():
   ulen = len(urls)
   for i in range(0,ulen):
       url = "http://%s" % (urls[i]["url"])
       req = urllib2.Request(url)
       try:
           res = urllib2.urlopen(req)
           headers = res.info().headers
           data = res.read()
       except IOError, e:
            if hasattr(e, 'reason'):
                err = "%s ERROR(%s)" % (urls[i]["url"],e.reason)
                print err
            elif hasattr(e, 'code'):
                if e.code != 401:
                    err = "%s ERROR(%s)" % (urls[i]["url"],e.code)
                    print err
                #401 = auth required error
                elif e.code == 401:
                    base64string = base64.encodestring('%s:%s' % (urls[i]["user"], urls[i]["pass"]))[:-1]
                    authheader =  "Basic %s" % base64string
                    req.add_header("Authorization", authheader)
                    try:
                        res = urllib2.urlopen(req)
                        headers = res.info().headers
                        data = res.read()
                    except IOError, e:
                        if hasattr(e, 'reason'):
                            err = "%s:%s@%s ERROR(%s)" % (urls[i]["user"],urls[i]["pass"],urls[i]["url"],e.reason)
                            print err
                        elif hasattr(e, 'code'):
                            err = "%s:%s@%s ERROR(%s)" % (urls[i]["user"],urls[i]["pass"],urls[i]["url"],e.code)
                            print err
                    else:
                        err = "%s query complete" % (urls[i]["url"])
                        print err
       else:
            err = "%s query complete" % (urls[i]["url"])
            print err
                       
if __name__ == "__main__":
    main()

NOTES: This script does not check the authentication type, it always assumes it is HTTP BASIC, HTTP DIGEST for example is not compatible with this script, though there is no reason why you can not get the Auth type form the headers returned by the server and write in a Digest auth method.

Tags: , , , ,

Comments No Comments »

After taking another look at Python I am quickly coming to love it, as an “exercise” in re-learning python I decided to write a very simple command line “tweeter” this uses the Twitter API to update your twitter status, extending from the “update twitter in a single line

You can grab a copy of the script from here: http://svn.saiweb.co.uk/branches/python/tweet.py

UPDATE 24/03/2011:Oauth version here

Example usage:

1
./tweet.py -u username -p password -t your tweet goes here

If you want to parse the JSON data normally returned after submitting a new tweet simply add the -j flag.

If you are prompted for a username and password when running this script the username and password supplied using the -u and -p flags was incorrect.

Tags: ,

Comments 3 Comments »