Download as pdf or txt
Download as pdf or txt
You are on page 1of 16

Security in FoxPro (protecting application and data)

by Christof Wollenhaupt, Foxpert

Login, Logout, Knock out


Microsoft has a lot of experience and knowledge in developing secure applications and
actually does so. What sounds like a failed attempt to be funny, is surprisingly true.
Microsoft spent hundred of millions dollars in the research of security, has got worldwide
recognized security experts and is permanently challenged by tens of thousands of
security experts and its competition.
This makes it even more surprising that most developers start from the ground with the
security aspects of their own applications. Hence, it's obvious that security is not the
primary focus of software developers. Without hesitation, they demand administrator
privileges for their application and implement their own login dialog to restrict access. They
write their own encryption routines to encrypt single field in a table. They spend a lot of
effort to protect tables in case of power failures.
For all these problems there are readily available solutions that are almost with certainty
- superior to the homemade solutions. Using the login dialog and password check I'd like
to show how many security leaks a Visual FoxPro application could have. Technically, such
a login dialog is very simple. The user enters user name and password. The application
executes a query. Execution continues if user name and password are valid. Otherwise the
application terminates, usually after a few unsuccessful attempts.
That's the theory. In reality, though, there's a lot that can go wrong. Let's start with some
particularities of Visual FoxPro. In the following samples I assume that the user name is
stored in lcUser and the password in lcPassword. A typical password validation could look
like this:
* ASSUME: We located the correct record in USER.DBF
IF NOT ALLTRIM(User.cPassword) == m.lcPassword
* invalid password
ELSE
* password is OK
ENDIF

That looks pretty safe, doesn't it? However, what happens if lcPassword is NULL? Every
expression that contains NULL is NULL itself. A condition that is NULL cannot be true,
never. If an IF condition results in NULL, Visual FoxPro always executes the ELSE branch. In
the sample above, the user can log on successfully, if he only knows a correct user name.
In the password textbox all he needs to do is to hit CTRL+0, and Visual FoxPro assigns
NULL to the Value property of the textbox. This way it's quite easy to log on as an
Administrator.
Check every IF command if the condition can be NULL
The sample above is only dangerous if the attacker knows a valid user name. Otherwise,
he wouldn't make it beyond the SEEK like that I omitted in the sample. Unfortunately, user
names are often easy to guess. It's particular easy for a stranger to guess a user name if
he doesn't have to enter them, but can comfortably pick one from a combobox. If then

as demonstrated in the VFP Tastrade sample a picture of each employee is included, no


one should be surprised if passwords or other information are quickly discovered and harm
is done. In Windows XP or MSN Messenger, all possible login names are even clearly listed,
as well. Since Microsoft's designs have always been copied in the past it's just a matter of
time to see similar login dialogs in other applications, too.
Comparing strings in Visual FoxPro is everything but a simple topic. If two strings are
considered to be equal depends on a number of factors. These are SET EXACT, SET NEAR,
SET COLLATE, SET ANSI, as well as various codepage related settings. Take a look at the
following sample and find out how to bypass the validation routine:
* ASSUME: We located the correct record in USER.DBF
lcPassword = NVL(m.lcPassword,"")
&& live and learn...
IF ALLTRIM(User.cPassword) = m.lcPassword
* invalid password
ELSE
* password is OK
ENDIF

And, have you been successful? Instead of using the == operator, the code above uses
the = operator. This operator respects the current SET EXACT setting. The default is OFF
which means that the left-hand string is only compared up to the length of the right-hand
string. The expression always returns .T. if the value on the right side is an empty string.
Logging on successfully is just a matter of not entering any password, at all!
Check all string operations for unwanted side effects, especially =, <=, <, >, =>,
#, != and <>.
Up to now we only focused on the actual string comparison. But what about the User.DBF
table itself? Maybe we can open the table outside the application. If the password is stored
in clear text, you don't need any further explanations. Mostly, the password is encrypted
before it's stored in a table. Surprisingly, only two algorithms cover most such encryptions.
Either, the password is XORed with a secret key, or the ASCII value each character in the
password is incremented or decremented by a fixed or variable value.
XOR is a very popular encryption mechanism. If you XOR a string with a secret key, you
get an encrypted text. If you XOR the encrypted text with the secret key, you get back
the original string. But if you XOR the original string with the encrypted text, you get the
secret key. Whoops. The addition/subtraction tricks, too, are easy to find, especially if the
same differences are used for all passwords. All you need is a pair of encrypted and plain
passwords. Those don't even have to be valid.
To get at them is often easier than necessary. If user data is stored in a SQL server, an
application typically uses an ODBC query to verify the password. If the query returns a
record, the password was correct. If, on the other hand, there's no match for the
password and user name entered, the password was wrong. That means, on the client
side, the password is encrypted and the assembled SELECT statement is sent to the
server using SQLEXEC() or REQUERY(). In other words, the encrypted password is sent
across the network without further protection. An ODBC Trace Tool or a Network Monitor
can easily reveal them.
With local data the opposite approach might be possible. To make it easier the application
might copy the user table into a cursor and decrypt it. All accesses go to the cursor

instead of the table. That's secure as long as Visual FoxPro has enough memory. If that
ceases to be the case, Visual FoxPro starts swapping cursors to disk as .TMP files. You can
analyze these files to your heart's content, if you kill VFP in the task manager or turn off
the computer abnormally. Nonetheless, there are much easier approaches for Visual
FoxPro based data that are discussed later in this article.
The problem is the same in all cases: The encrypted password is stored in the table. The
solution cannot be to encrypt the password even better. The solution must be not to save
the password in the first place! But how to validate a password if it's not stored
somewhere? Think about what you actually want to accomplish. The content of the
password doesn't matter, at all. All you want to know is if the entered password matches
the stored value. For that, you don't need the password itself; a place holder is just as
good.
Such a place holder is called a hash. A hash algorithm converts a string of arbitrary length
into a single number that is most likely different for different input strings. We all know
such functions for checksum calculations. The Windows CryptAPI provides functions to
obtain such hash values using very secure algorithms. To make it easier to use this API,
Visual FoxPro contains a class library named _CRYPTAPI.VCX since version 7. To validate
the password you compare the hash value of the entered password against the stored
hash value in the user table. Even if an attacker has both values, he can not conclude from
those of other passwords. Better, even if he knows the algorithm that was used to obtain
the password, that's of no use. To obtain a password for a known hash, he would have to
invert the algorithm. Most hash algorithms are asymmetric, though. While it's easy to
obtain a hash value, you need to calculate the hash value for any possible password to get
the opposite. This method is called a brute force attack, and is usually the last resort as it
is takes a very, very long time. For good algorithms on today's computers this can be
millions of billion years. On the other hand, brute force attacks have a 100% chance of
success if you have enough time.
Never store secret information, just place holders.
That's not only true for data, but also for the contents of the memory. If there's an error
in an application, Visual FoxPro makes it extremely easy to collect information about the
current state and environment. You cannot only get the line number and error code, but
information about every aspect of Visual FoxPro using
LIST STATUS | MEMORY | OBJECT | CONNECTIONS | DLLS

Such information are often stored in error logs. You can really make a hacker happy if you
store the password of the user in a variable. He only has to wade through the LIST
MEMORY logs to find a considerable number of passwords with no effort at all. That's even
true if you only store the password temporarily in a procedure. It's much harder to cause
an error just in this moment, but often this is possible by deleting an index tag or a file.
Unencrypted system information do not belong into an error log.
In general, deleting of files is one possibility to gain access to a system. In cases of an
error, many applications pick a default value that is comfortable to the developer or user,
but hardly secure. Suppose, you have the following function to obtain the return value of a
modal VCX form:

loForm = CREATEOBJECT(tcForm)
loForm.Show()
uRetVal = loForm.uRetVal
RETURN uRetVal

And call this function from the main program like this
llLoginOK = CallModalVCX("frmLogin")

In your tests, this function works flawlessly every time. But, what happens if there's an
error while loading the form? If you, for instance, bind a textbox to a table and that table
doesn't exist, Visual FoxPro doesn't create the form at all. In the code above, loForm
would be .F. in the first line and cause errors in the next two lines. Hence, uRetVal would
never be defined and the RETURN line would fail, too. Visual FoxPro always returns a value
from a function and a procedure. If you don't provide Visual FoxPro with a value, Visual
FoxPro uses its default value: .T. Since .T. is also the return value for a successful login,
the user can login by renaming a file.
Error handling is always critical. In case of an error you should always think carefully about
which options a user may have. Ignoring an error can be an option during development,
but not at runtime. You should always cancel the current function. That means, either
terminate the application immediately, or use RETURN TO or TRYCATCH at the READ
EVENTS to continue execution at a predetermined point. If you log the error, you shouldn't
store information that aren't absolutely necessary. If you have the possibility and need
these data, better encrypt error logs.
Don't let the user continue program execution in case of an error.
Admittedly, causing an error to bypass a security check can be called an advanced
technique. So far, we focused on comparing the value. But locating the record, too, could
cause security issues. One variation of causing an error is
SEEK lcUser

While SEEK can search NULL values, this is only true if the indexed field also allows NULL
values. Otherwise, SEEK cancels out with an error. If that error is ignored, the record
pointer is still on the first record and the password validated. The hacker therefore doesn't
have to know the name of the user. Since typically the first record contains a test user for
the developer or the administrator, there're good chances that this attack results in using
a privileged account.
More and more applications, though, do not save data in FoxPro tables, but in a SQL
server database. To send a query to the SQL server, the application assembles SQL
statements and often sends them with SQL Pass-Through to the SQL server. The following
code tries to determine, if the password is correct. How long do you need to crack the
following code?
lcSQL = "SELECT * FROM User WHERE cUsername='"+;
NVL(m.lcUser,"")+"' AND nHash="+TRANSFORM(NVL(lnHash,0))
IF SQLEXEC(lnHandle,m.lcSQL)>0 and RECCOUNT("SQLResult")>0
* OK
ELSE
* Error
ENDIF

The password query has been replaced through a hash value query, but the user name is
still inserted into the query unchanged. That allows the hacker to modify the query as he
wishes, for instance, when he enters the following user name:
' or 1=1 or 1=1

The resulting query always returns records. Additionally, the code checks if the SQL server
returns records at all. The correct verification would be to check if exactly one record is
returned. Multiple records in the result set would mean that there are multiple records for
the same user and the same password. Such a constellation should have been prevented
by the database. The possibilities are not limited to altering a simple query. Depending on
the backend you can send multiple commands in a single command string. A hacker could
create new users, change passwords and execute stored procedure in one pass from the
login dialog.
Always validate user input before using it any further.
Another tendency of developers plays an important role in security. Most SQL servers
have a very powerful user right management system. For each table and each column you
can specify if a user can read or write to it. You can specify if records can be deleted or
added. You can precisely define who can alter the database, like adding a new table, adding
a stored procedure, adding or deleteing users, and so forth.
In reality, though, these features are hardly used. Typically all users of the application share
a common user account that has been created for the application. This user often has got
the rights that the administrator of the application - or even the developer - needs.
Sometimes, developers even use the sysadmin account provided by the SQL server.
Often, such a configuration doesn't seem to be a problem as the application controls
access and only the developer and the system administrator know the password. Let me
rephrase this for you: The only protection of the database is the login dialog of the
application. You have seen on the last few pages how little security that could mean. If the
user can control the SQL server right from the login dialog, it might be the safest solution
to drop that dialog completely.
Use the security mechanisms that you server offers.
Similar problems do not only exist with SQLEXEC(). In Visual FoxPro, too, there are many
possibilities to shoot oneself into the foot: macro substitution, EVALUATE() and
SCRIPTEXEC(). If input values are used in conjunction with these features without further
validation, a hacker has the entire arsenal of Visual FoxPro at his hands. As we will see
later, you only need a single point in the application to execute code to turn off most
conventional security mechanisms.
All input values have to be validated if they are in an acceptable form. The most important
rule is to strip off all terminating characters. In Visual FoxPro this is the quotation mark, the
single quotation mark, and square brackets that are used as string delimiters. With HTML
these are mostly "<" and ">" which you should remove from the input stream. In FoxPro
you can easily use the CHRTRAN() function for that. For security reasons, you should
focus on valid characters and remove all others:
CHRTRAN(cString,CHRTRAN(cString,"ABCDEZ1234567890",""),"")

The inner CHRTRAN removes all valid characters. The remaining characters are invalid. The

outer CHRTRAN uses this string to remove invalid characters from the original string.

App Attack!
In the previous chapter you have learned how easy it is to bypass many security
mechanisms in many Visual FoxPro applications. Someone attacking my application?
Impossible! You are right, if you think of terrorist activities, evil former employees or
prestige-addicted script kiddies. In reality, though, the much smaller dimensions are those
that are a risk to your application.
That could be a competitor who wants to learn about the inner workings of your
application or, purely, wants to perform a data conversion for one of your former
customers. If the core of your application is the database that you provided, your client
might want to use that data in a different way than he is allowed to. When using address
databases for mail merge letters, such a user could try to avoid the cost associated with
every address he uses. Or, you have a colleague who believes to be smarter than you and
feels forced to prove that. The worst group, however, is called the "power user". When
the possibilities of the application are not sufficient, this group of users tries to user
alternative applications to modify data, typically using Excel or Access. Upon saving you
quickly end up with invalid values or memo fields that are truncated to 254 characters. Of
course, no body did anything.
The frequency with which developers ask in online forums for encryption tools for
application and data proofs a steadily increasing need for security. The increasing
consciousness of security issues becomes an issue especially for independent consultants.
More and more customers want to know how secure an application is and even let
developers sign that somehow. If a developer signs such a paper believing in the security
of tools like Refox or Cryptor, and there is an attack, this at least weakens the own
position, or can be very expensive at max.
More over, there's a trend to distributed applications even in the FoxPro universe. This
trend is not as far as many papers from Microsoft want to make us believe, but at least
the integration of the internet is widely a fact, already. An automatic update via FTP or
sending an email in case of an error doesn't sound like an unreasonable request of
customers, anymore. For internal applications used by bigger companies another common
request is to access the application with a browser via the intranet. The reason is usually a
strategic decision of the management, even though technically such a solution might not
make sense. Increasingly, SQL server is discovered and accepted as a more reliable data
storage for Visual FoxPro applications.
The most common security mechanisms in Visual FoxPro applications try to protect
against an external attack. To secure data developers often use an encryption library.
There are two fundamental approaches to data encryption in Visual FoxPro: file and field
based encryption. With the field based encryption, the program encrypts the content
before each write access. Reading is done the opposite way: The content of the field is
passed to a decryption function. Such a field can only be indexed on the encrypted
contents. Creating an index on the decryption function would put the clear text of the
protected fields into the CDX file where they can be recovered easily. Due to this
restriction, you can only search for exact matches on encrypted fields. Searching on
anything else involves the decryption function and disables Rushmore.

File based encryption doesn't suffer from this restriction. Depending on your needs you
have multiple possibilities. If you want to prevent unauthorized users from reading data,
the easiest solution is the Encryption File System (EFS). Such a file system comes with
Windows 2000 and Windows XP. To enable it, set the file attribute "encrypted" in the file
properties dialog. You access the file like before, because encryption works transparently.
The application only sees decrypted data, on the hard disk there are only encrypted files.
If more than the current user should access these files, for instance, across a network you
must have a Domain Controller. The Domain Controller manages the keys used for
encryption. Windows EFS uses the DES algorithm. Depending on the Windows version, this
is 40 Bit DES, 56 Bit DES, DESX or 3DES. The last one is currently considered to be quite
safe and is the same used in bank transactions and ATM machines across Europe.
EFS is a good solution for internal applications running on the company network. Activating
EFS is not a developer, rather an administrative decision and can be performed
independently of the application. The administrator, and not the developer, controls file
access rights. Those without access cannot read any data, even if they steal the hard disk
and use NTFS file systems for DOS, or similar low-level tools. To read data, you need the
keys that are stored on the Domain Controller. On that machine, the keys only become
available when the hacker knows the administrator password. Decryption of these files
therefore requires the computer with the desired data, the domain controller and access
as an administrator. Nothing is perfectly secure, though. Since 2003 there are tools
available that use a brute force attack in a reasonable time frame if part of the password is
known.
If you need to protect data in a peer-to-peer network or you want to encrypt files before
sending them to your users, there's only one tool available for FoxPro: Cryptor from
XiTech. When Windows loads a DLL it creates a list of all functions and their addresses in
memory. For each DLL there's such a jump list. Cryptor works by altering these jump lists.
For instance, the function at index #224 in NTDLL.DLL is the NtReadFile() function that is
used to read files. Cryptor has its own version of NtReadFile. In the list it changes the
address at position 224 to point to its own version and saves the old address in some list.
When now Visual FoxPro calls the NtReadFile function, it takes the function pointer at
position 224 and calls Cryptor this way. Cryptor, on the other hand, calls the original
function, decrypts all data and returns them to Visual FoxPro.
Calling the function is therefore entirely transparently and works for all utilities that run in
the VFP process including third-party libraries and ActiveX controls. The disadvantage is
that Cryptor has to be updated for each version of Windows. If Microsoft implements a
new file access function, Cryptor has to implement it, as well. Otherwise, some functions
would return decrypted, some encrypted contents. Should that happen at a write access,
the file would be lost for ever. A further disadvantage of these tools is that Cryptor has to
modify the jump list of DLLs. There are tools designed to prevent exactly this, because
they either use the same trick, or because this behavior is typical for bad programs like
viruses or worms. For instance, as of writing this, Cryptor does not work together with
KonXise, even though both are from the same company. Additionally, Cryptor has to be
loaded into its own process. This is the case when you launch an EXE. When creating a DLL
you have to live with potential restrictions, though.
When protecting the application the goal is usually to prevent that someone can decompile
the application and recover the sources. All products that don't produce machine code, but

so-called P-code are especially vulnerable for de-compilation. If names like class names,
method names, etc. are stored in clear text, because they are used to resolve
dependencies, there are usually very good chances to restore the sources completely.
There's a difference if the restored code reads
PROCEDURE _1(_2,_3)
_1 = _2 * _3
RETURN _1*_1._1

Or
PROCEDURE LineTotal(tnAmount,tnPrice)
lnSum = tnAmount * tnPrice
RETURN lnSum * Tax.Rate

Products like Visual FoxPro, Java and .NET are especially vulnerable for this kind of decompilation. The approaches to protect applications are different in these products. In
FoxPro the most common approaches are branding and encryption. In .NET the mostly
used technique is obfuscation. That means that all variables, methods, etc. are renamed
so that they don't make any sense. Obfuscators try specifically to reuse names as much
as possible. In the sample above, "_1" was used in four different places: as a procedure
name, a variable, an alias and a field name. Additionally, obfuscators alter the code in a
way that it does the same, but doesn't look anymore like the code produced by the
compiler.
The first approach in FoxPro was branding. That means that a brander writes a specific tag
into the compiled file, like a password hash, for instance (yes, the manufacturers, too,
know now to save passwords). When the same tool is used to decompile a program, this
tag is checked and eventually the tool refuses to decompile the code. It's important to
understand that it is the responsibility of the decompiler to respect this tag. Because the
only thing changed in the program is this tag, Visual FoxPro doesn't notice this modification
and can execute the application as usual. Here's a list of de-compilation tools for FoxPro:
product
ReFox
AntiPro
UnFox
SecurityFox

Web site
http://www.xitech-europe.co.uk/ReFox.html
http://www.frog.cz/prod02.htm
http://asm001.home.chinaren.com/source.htm
http://www.weihong.com/tools.htm
http://www.taketech.com

If you use a different decompiler, you can de-compile an application without problems that
has been branded by other tools. For complete protection you would have to brand your
application with all tools. In the past when only few of such tools existed, that was not a
big issue, but today developers in many countries around the world have been created
decompilers that ignore other tags. Via the internet these tools are now available to all
developers worldwide. Additionally, you can find patches on the internet that remove these
tags. To find them simply search Google for "Refox" in combination with words like
"warez", "crack" or "hack". Most pages are Russian or in various Asian languages, though.
Contemporary protection tools therefore encrypt the compiled EXE. An application treated
in this manner is not recognized by Visual FoxPro anymore. In addition it's therefore
necessary to add a loader program that decrypts the application and then calls the Visual

FoxPro runtime. This technique is used by tools like ReFox with Level II, KonXise or
Armadillo. A lot of new tools are currently under development or just out in their first
releases. Differences among the tools are if decryption happens in memory or into a file, if
the file is additionally compressed, and so on. The basic principle doesn't change, though.
Even though there are cracks for these tools and hacker constantly try to bypass their
protection or to hack their encryption algorithm, all of these tools do their job quite well.
However, just because one part is working you shouldn't expect that your application is
secure. All these tools have one thing in common: they protect the application or data
against external access. The Visual FoxPro application typically doesn't notice it is
protected. Visual FoxPro can read files encrypted with Cryptor and execute application
protected with KonXise.
All of these tools do not protect against attacks from the inside. The most successful
strategy for internal attacks can be summarized as Code Injection meaning that code is
executed inside the application. Visual FoxPro is extremely vulnerable for this kind of
manipulation

Code Injection
Let me make some legal remarks. Decompilation and modification of executable files is
prohibited by the license agreement of most products. Additionally, most countries have
laws that make decompilation illegal even if such a clause is missing from the license
agreement. In Europe there are only few legal exceptions for decompilation without the
permission of the intellectual property owner. Should you need to decompile or modify
(patch) an application, you should, in any case, contact the owner of the rights of this
application and, eventually, a lawyer specialized in this subject. The following explanations
are meant to give you an idea of what others could do with your code and to enable you
to protect against that.
Code injection means that external code is executed inside the application. That doesn't
have to be a negative thing, though. A Debugger in Windows, for example, loads one of its
own DLLs into the debugged application to control the flow of execution in that process.
How the external code gets into the application differs.
If a FoxPro application uses a FLL to encrypt data, it's quite easy to bypass this. The FLL
has to exist physically on the disk for FoxPro being able to load it. In contrast to their
counterparts in DOS, the PLB libraries, FLLs cannot be included into the application and
loaded from their. In most cases the FLL remains on disk and is therefore easy to
manipulate. The same applies to DLL in all Windows applications. In a Windows application
you could write your own DLL that provides the same functions as the original DLL. Then
you could capture all function calls and forward them to the actual DLL. Creating such a
DLL can be automated if the interface definition is available. Now you are in the position to
capture passwords passed on to that DLL, save them and use them later as needed. To
protect against such a manipulation, you should create a checksum of FLL and DLL files,
for instance, using the MD5 hash algorithm. Before loading a library verify the current
checksum against one embedded in your application.
In Visual FoxPro you don't have to work that hard. When calling a function Visual FoxPro
searches in the current program, in procedure files, in FLLs, in API declarations, in stored
procedures, as external EXEs or APPs, or external FXP's. The exact search order varies

between different versions of FoxPro. In any case, though, Visual FoxPro executes a FXP
in the current directory when it didn't find any other procedure of that name anywhere
else. Hence, if you change function names in a FLL and at the same time provide an FXP
with that name in the current directory of the application, then the FXP is loaded and
executed.
You don't have to be that clever to get at secret data. Imagine you had encrypted all
tables with a tool like Cryptor. With an external attack the user has virtually no chance of
decrypting these data if you picked a good password. Inside the application, however, you
give the password to Cryptor. Visual FoxPro can then read all registered files without
limitation. Developers tend to use the same password for all tables which is, moreover,
stored inside the application somewhere. Because of its support of file masks, usually all
tables are registered at once. The only remaining protection is therefore that only
approved user get into the application. You might remember from the first chapter what
the probability of this is like. If all tables are registered and not those only to which the
current user has access to, you only need minimal rights to have access to all data.
Sufficient is including the report designer. If a user can modify reports in an application, he
can open the data environment of the report and add any arbitrary table. The report
designer offers even more surprises. Not only can you open tables on the disk. In the file
open dialog you may enter any name of an included table that will then be opened in readonly mode. That might be useless for regular tables.
Class libraries and forms are nothing but tables. If you know the name of a class library,
you can open it in the report designer. You find that name typically in the error messages.
That's another reason to encrypt error logs and to not to display more than absolutely
necessary. Even if you encrypted your application with any of the available protection tools
this still works. The VCX in the report designer is decrypted and unprotected (how else
should VFP be able to execute it).
There are many possibilities to execute code in your Visual FoxPro application. For
instance, a user could write FoxPro code into a text file and then enter the following
expression in the report designer:
SCRIPTEXEC(FILETOSTR("Datei.TXT"))

In Visual FoxPro 6.0 and earlier this requires to create an FXP, but that's not really an
issue. The report designer is really unreliable. Therefore either leave it out or isolate the
designer into a separate application that is launched with RUN. If the report designer isn't
available, what can you do to inject code into the application? The next easiest way is to
run the application in the development environment. Put SET STEP ON onto an ON KEY
LABEL to suspend the application at any time. If the application is encrypted this isn't an
option as Visual FoxPro won't recognize the EXE as a Visual FoxPro application in the IDE.
What we are looking for are ways to execute code that is not included into the EXE. If you
can't imagine such a way here are some examples:
_STARTUP or COMMAND line in the config.FPW
Index expressions in tables
Stored procedures

Triggers
Field validation rules
Database events
Reports
External forms, classes, queries or programs
All kind of scripts that are executed by the application
Macro substitution, EXECSCRIPT(), EVALUATE() or name expressions that are not
validated.
Some options are not available in all versions or the runtime libraries. For instance, the
COMMAND line is ignored in the runtime version of the more recent Visual FoxPro versions.
One trick, though, works almost every time. A free table used by the application is added
to a database. Depending on the version of Visual FoxPro that you are using, you can now
use trigger, validation rules and database events in that new database to add your own
code. If you open a table in Visual FoxPro that is part of a database and you haven't
opened the database yet, then Visual FoxPro kindly opens the database for you. If
database events are enabled Visual FoxPro triggers the DBC_OpenData event before even
the table is opened. This event can contain arbitrary code that, for instance, copies all
tables into unencrypted files onto a huge removable disk.
If plain tables are insecure, OK, let's use SQL server. That secures data and your code is
safe, anyway, you might think. Unfortunately, that's wrong. All class libraries, that is, VCX
files, are tables. When loading a class Visual FoxPro opens them in the system data
session. If you manage to execute code in the system data session, there's nothing that
stops you from copying all loaded VCX files. While accessing the system data session (#0)
sounds impossible at first, it's actually not a big issue. When evaluating an index
expression, a field validation rule or a trigger, Visual FoxPro always activates the correct
work area. Such a work area is always in a data session. All you need is a trigger in a table
that Visual FoxPro opens in the system data session. As soon as Visual FoxPro starts
making changes to that table, it executes the trigger code in the system data session.
The following program uses this trick to automatically copy all loaded VCX files onto the
hard disk. In contrast to FXP files you cannot encrypt VCX files. Therefore they can not be
protected by branding tools. VCXes extracted this way are entirely unprotected and can be
decompiled by any decompiler available on the market. If you compiled the application with
debug information that is not even necessary as the entire source code is still contained in
the VCX! That's true even if you used any available encryption tool that can't be cracked
externally.
It's very important to notice that this is not a problem with these products. They work as
advertised. The reason is simply that the code below exploits a design in Visual FoxPro
against which those tools were never designed to protect. These tools prevent
decompilation from the outside. For technical reasons they can't do anything against code
injection. There's no way for them to distinguish good code from bad code as far as
security is concerned.
*========================================================

* Monitor the system datasession for loaded VCX libraries


* and save them to disk.
*========================================================
If Version(2) == 2
Return
Endif
MessageBox("Starting...")
* Create an empty Resource file in a new database
Local lnSelect
Set Safety off
lnSelect = Select()
Select 0
Create Database ExtractVCX
USE Sys(2005) Again
Copy Structure to ExtractVCX Database ExtractVCX
Select (m.lnSelect)
* Add a trigger to the resource file
Create Trigger On ExtractVCX For Insert as ExtrVCX()
Create Trigger On ExtractVCX For Update as ExtrVCX()
Create Trigger On ExtractVCX For Delete as ExtrVCX()
Set Resource to ExtractVCX

Procedure ExtrVCX
If Set("DataSession") == 0
Activate Screen
? "..."
Local laTables[1], lnTable, lnSelect
lnSelect = Select()
For lnTable=1 to AUsed(laTables)
Select (laTables[m.lnTable,2])
If JustExt(Dbf()) == "VCX"
If not File("__"+JustFname(Dbf()))
Activate Screen
? "Extracting: "+JustFname(Dbf())
Copy To ("__"+JustFname(Dbf()))
Endif
Endif
Endfor
Select (m.lnSelect)
Endif
Return .T.

If you can modify the database, you could put this code into the DBC_OpenData event.
The EXTRVCX function is called by a trigger. The trigger gets called on any write access to
the resource file. That happens, for instance, when you close a report preview or a
BROWSE window. Since most applications use a report designer, bets are good for you.
Terminating an application, too, writes to the resource file. You might have to move
EXTRVCX to a different location in this case, though, as the database might have been
closed already.

Proactive protective

Maybe the previous pages left you with a minor bad feeling, as most applications have at
least one of these security leaks. Don't panic! Analyze the situation of your application and
you might find out that there's not much of a problem, or lots of reasons to panic NOW!
This analysis doesn't have to be a professional security risk analysis if you don't work in a
security relevant area. As a starter it's often sufficient to think about the various aspects
of security. The most common reason for security risks in applications is not the stupidity
of the developer. They simply exist because nobody has thought about them. The most
important questions for you to ask are:
Who could be interested in getting at my code or data?
Who has got the possibility to do that?
What abilities and knowledge do these persons have?
With the first question you find those that have an interest in attacking your application.
The second question covers those that have (even a theoretically) possibility to do so. If
you have a web shop, everyone with internet access could potentially break into your
computer, but only a limited group, like the competitor, actually has an interest in
specifically hacking into your application. This is an important difference, because FoxPro is
more a niche product, and maybe even your application. That makes it much less probable
that there are tools for automated attacks that Script Kiddies might use. On the one side
this means that you less likely get into a broad attack in which you just happen to be the
victim by chance. On the other hand it means that each attack is most likely targeted at
you specifically. A hacker needs to have a certain amount of knowledge about FoxPro to
compromise your application. That's different for ASP.NET applications running on IIS, for
instance. Security leaks in that configuration spread quickly and tools are created that use
them automatically. To attack a computer that is vulnerable to this attack you don't need
to know how the attack works, just where to get the programs to perform the attack.
In most cases it's sufficient to protect the application against decompilation using ReFox or
similar tools, to encrypt data files and to ensure that the LogIn dialog is really secure. That
protects against the curious persons who simply have to try if the application can be
decompiled or files be modified in Excel. A professional hacker won't stop that, but without
these measurements your application would be completely unprotected. So even if ReFox
might not protect against all types of attack, it's wrong not to use ReFox or a similar tool.
The big question is: how paranoid you should get? No matter what you do, there's a way
round it. It's only a matter of time and effort. On the other hand, security measurements
often lead to inconveniences for the honest user. And security costs money. Before you
start protecting your application in many months' of work, you should clarify how much
security is needed. For security issues the same is true as for all design issues. The early in
the life cycle you start thinking about it, the cheaper it is. Try to achieve secure habits.
Most solutions, like removing invalid characters from a string, take only minutes or less if
you apply them right from the beginning.
Once you have figured out against whom you need to protect and how effort you want to
spend on that, you could go through the following list of solutions. This list is neither
complete, nor are these solutions fail-safe.
The rule, the most important rule, is: Avoid any access from the outside. For the code this
means to use branding and encryption tools. For data this means to control access.

Encrypt data if you cannot trust the administrator. Work with the administrator to limit
access to data.
All security boundaries in your data should match those of the storage system. If you
store data on a SQL server, this is usually not an issue no matter what the design looks
like since you can control access down to the field level. You only have to use these
possibilities! Try to collaborate with the system administrator right from the beginning to
find a design that not only makes data retrieval easy, but also allows for easy
maintenance.
When using DBF files the smallest unit is a file. Hence, a user should either be allowed to
access all or no data in a file. If a user is only allowed to see certain fields, you immediately
have security issue. In this case, the application has to control access which makes it
vulnerable for code injection attacks. If certain fields can only be seen by administrators,
put these fields into a second table. Use the primary key to create a one-to-one
relationship. Restrict access to the administrator table to the administrator group on the
operating system level.
For programs, as well, there are simply techniques to make them more secure. For
instance, you could use an include file to replace names in the program with other strings.
That's especially easy if you use PRG files for the class definitions. In a .H file you could
define, for example:
#DEFINE
#DEFINE
#DEFINE
#DEFINE

LineTotal kfjewaoirujsoidfjhoiasdj9424hrfjskjgfhiu943894sfdhkycvnmcxbvxcjh
lnCount kfjewaoirujsoidfjhoiasdj9424hrfjskjdgfhiu943894sfdhkycvnmcxbvxcjh
lnPrice kfjewaoirujsoidfjhoiasdj9424hrfjskjgfhiu943894sfdhkycqvnmcxbvxcjh
lnSum kfjewaoirujsoiidfjhoiasdj9424hrfjskjgfhiu943894sfdhkycvnmcxbvxcjh

If you include this file into all your programs, Visual FoxPro replaces the names when
compiling your code. If therefore a user decompiles your application he doesn't see the
easy names on the left side, but the slightly more complex ones on the right side. As you
probably have quickly noticed, those names have only minor difference which makes them
hard to distinguish. This way you make decompilation even easier, especially if some
names are contained in other names. Then a hacker can't even easily use search and
replace features to replace variables with clear text.
You have to follow some rules, though. There are some things you can't redefine. This
includes all property names of VCX based classes, the names of database objects and all
names belonging to a table. Since you can only replace generically, you have to exclude
such names from the list of #DEFINEs. Pay attention when using macro substitution as the
name has been replaced upon compilation and you need to use the long name to access
variables. If such a name is used in a string, use [] as string delimiter instead of "" or ''. If
your application encounters an error, the error message also contains the long name. If
your users should be able to report errors on the phone, you need to use simpler names.
Best start with _1 and count upwards.
After you prevented external access through encryption and replacing names
(obfuscation), or at least raised the bar significantly, you should work on preventing that
unauthorized code is executed in your application. The only way to protect against
execution of machine code is the integrated user and security management of the
operating system. If you give the program and the computer out of your hands, there's
nothing you can do. But you have a certain level of control over the execution of VFP
code. Especially Visual FoxPro code usually offers the easiest way to access data.

Preventing that execution is a huge step forward to securing the application.


First of all, you should include a Config.FPW into your application as this file has precedence
over external files. The Config.FPW file is one possibility to execute code before your
application run. Especially you can redirect system files to files that are modified and
included index expressions, triggers, etc.
If your application happens to notice that the environment is different from what it should
look like, immediately quit the application. As this hinders debugging, create special debug
versions that do not have this limitation. Never release versions that include debug code.
You can be assured that someone finds out how to activate that debug mode. When
checking the environment pay attention to the Config.FPW and FoxUser.DBF files, that no
tables are open that shouldn't be open, that no settings have been changed, that no FLLs
are loaded that shouldn't be loaded and that no ON KEY LABEL are active. In the
development environment quit the application immediately, otherwise you risk that the
application runs in the debugger. Even if the code is not visible, a hacker can still step
through the code line by line and check the contents and the changes of variables and
properties.
Verify all inputs before you process them. Remove invalid characters from a string,
especially delimiting characters. Check all calls to SQLEXEC(), EXECSCRIPT(), EVALUATE()
and the usage of macro substitution.
Before you access a file you should ensure that it hasn't been manipulated. For tables
verify the table header and if a table has been added to a database. For index check the
expressions. Open a database as a table and validate stored procedures if there are added
database events and validation rules have been added to tables. Libraries (FLLs) should be
included and copied to disk with a random name before it is loaded. Alternatively use a
hash code (MD5) to determine a finger print of the file and validate this hash value every
time you load the DLL. This all is quite a lot of work. You rather be sure that you need that
level of security.
FoxPro specific files require special attention. VCX, but also SCX, files are easy to extract.
Important algorithms therefore belong into a PRG. To extract those from an encrypted
application is significantly more difficult.
If you have to use Visual FoxPro reports, check the report file for manipulation like an
index. Parse all expressions. Expressions that you can't uniquely identify indicate a potential
manipulation. Remove them as they might call external FXP files that perform malicious
actions. It's best to include FRX files into the application, too, and copy them out as
needed.
To securely use the Visual FoxPro report designer, create a COM EXE server. Instead of
accessing encrypted, real data, this EXE accesses a second data directory with test data.
These files can be empty or contain sample data. If the user tries to access tables through
the report designer, he fails since the COM EXE server has never decrypted the original set
of tables. Executing code is limited to the report designer. All saved reports need to be
checked for manipulations before they are execute in the real application environment.
Remember that you can add reports to a database, too, to execute code before the
report is opened. That means, before you open it with USE, you must check the header
for manipulations, just like any table.

Even if it's quite tempting to store certain things as VFP programs, be very, very careful
with that. Just as easy as you can change these data driven programs, others can make
changes not in your interests. Don't assume that such configuration files only contain valid
date. If you need to create programs, encrypt them or calculate a checksum using a
relatively secure algorithm such as MD5.
If you encrypt files never decrypt them longer than necessary. If, for example, you encrypt
the user table, register it only after the user entered a password and deregister it once you
have checked the password. Tables for which a user has no rights should not be
registered, at all. This might result in each file having a different password, but this method
increases security significantly.
Passwords are another critical part. As soon as a password is known, it can be used to
compromise your application. Such passwords are often vulnerable to brute force attacks.
If a user can take an encrypted file back home, he can use a program to try all possible
passwords without being disturbed. Short passwords or passwords that have a meaning
as a word are taboo. In the internet there are word lists with hundred of thousands of
commonly used passwords (ever wondered how some dubious web sites make their
money when there content is free after you registered with a password?). Such lists are
used by hackers, but you, too, should use them to search for your password. Consider
that one can check between hundred thousand and several millions Windows passwords
per minute if one has certain hash keys from the registry. Especially for passwords used by
applications there's absolutely no reason not to use difficult, hard to remember passwords
with digits and special characters.
FoxPro tables are inherently insecure as the entire content can be accessed. If you need
more security, either use a SQL server, or encapsulate data access into a DCOM/COM EXE
server, or use web services to access tables. Then you always have full control about who
access which data.
If you have expensive algorithms you should consider not giving the binary code out of
your hands. Usually you can't avoid that. If you could offer your application as a web
service on your own machine and your client only access the web service, use this
possibility. There's no better protection against decompilation.
Consider non-technical aspects, too. If you encounter a violation of the license agreement,
you might want to sue the violator. Usually that is only possible in the country of residence
of that user. Before you compete with Russian or Chinese lawyers, check with your own
lawyer if you can restrict sales and re-sales to countries in which you can use legal actions.
Security is a topic we all should think about more and we will be forced think about more in
the future. A lot can be done with zero to nothing efforts if you consider security right
from the beginning. Not only web applications are affected, but all kind of applications.
Visual FoxPro makes it attackers very easy. A very high degree of security in a Visual
FoxPro application is only possible with extremely high efforts and additional tools, if at all.

You might also like