100

I understand that you should NEVER trust user input from a form, mainly due to the chance of SQL injection.

However, does this also apply to a form where the only input is from a dropdown(s) (see below)?

I'm saving the $_POST['size'] to a Session which is then used throughout the site to query the various databases (with a mysqli Select query) and any SQL injection would definitely harm (possibly drop) them.

There is no area for typed user input to query the databases, only dropdown(s).

<form action="welcome.php" method="post">
<select name="size">
  <option value="All">Select Size</option> 
  <option value="Large">Large</option>
  <option value="Medium">Medium</option>
  <option value="Small">Small</option>
</select>
<input type="submit">
</form>
doppelgreener
  • 4,809
  • 10
  • 46
  • 63
Tatters
  • 1,187
  • 2
  • 9
  • 18
  • 113
    Yes. Nothing prevents an attacker from submitting whatever values they wish in your ` – Michael Berkowski Mar 20 '14 at 13:18
  • Bummer....if I was to dynamically bind params in a prepared statements with MySQLi would that protect my files? – Tatters Mar 20 '14 at 13:21
  • 13
    You should understand basic request/response things and the thing that it does not matter how the front-end is build over the request i.e. in this case dropdown – Royal Bg Mar 20 '14 at 13:22
  • 3
    Binding params would protect you from injection, yes. A whitelist is better though, for data integrity if you only wish to accept the values currently listed in ` – Michael Berkowski Mar 20 '14 at 13:26
  • Thanks Michael, I've never used a whitelist before but it sounds like the 'option' I'm looking for (more security)...know of any good online tutorials? I'm a bit of a MySQLi newbie – Tatters Mar 20 '14 at 13:30
  • 1
    @SamuelTattersfield if you look at the answer below I have explained briefly how to use a whitelist. – Oliver Bayes-Shelton Mar 20 '14 at 13:31
  • 13
    @YourCommonSense Because it's a good question. Not everyone realise how manipulatable a client is. This will provoke very valuable answers to this site. – Cruncher Mar 20 '14 at 14:46
  • 8
    @Cruncher I see. For an average stackoverflowian it's a rocket science they newer heard of before. Even despite of the most upvoted question under PHP tag. – Your Common Sense Mar 20 '14 at 14:52
  • 1
    haha..I had up vote both of these comments. I couldn't find a similar question so I asked it...never did rocket science – Tatters Mar 20 '14 at 14:57
  • 9
    "I understand that you should NEVER trust user input". No exceptions. – Prinzhorn Mar 20 '14 at 17:53
  • I know is in the related tab besides the question, but here it's, related: http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1 – Braiam Mar 21 '14 at 02:59
  • 1
    Always, always use parameterized queries (prepared statements or whatever you call them). There is no substitute. Having to manually scrub or check input, keeping track of what's clean and what's dirty, will always leave you vulnerable to mistakes. Parameterized queries are a simple best practice that can only improve your code. Seeing string concatenation in a SQL query should automatically trigger alarms in your head. – mcv Mar 21 '14 at 13:40
  • 1
    @mcv, "Seeing string concatenation in a SQL query should automatically trigger alarms in your head." -- It's still occasionally useful. For example, building a variable-length parameterized query string! (I have recently written some code which includes `$sql .= ' UNION ALL SELECT ?';` in a for loop, as an example ~_^) – Brian S Mar 21 '14 at 15:15
  • 1
    Do the `in_array` check *and* always use parametrized queries. If you have to worry about escaping anything, you’re doing it wrong. No matter how “trusted” something is, if it’s variable, it’s a parameter, and if it’s a parameter, you need a parametrized query. – Ry- Mar 22 '14 at 15:54
  • 1
    If this is a duplicate, vote to close instead of posting passive-aggressive comments. The question on its merits alone is perfectly acceptable. – Matthew Read Mar 22 '14 at 17:14
  • 3
    The input is not a dropdown box. It's a stream of bytes from the client. – R.. GitHub STOP HELPING ICE Mar 23 '14 at 04:05
  • 1
    If you're ever planning on dealing in multiple languages, the list item's `value` attribute should be a language-agnostic code (eh, you can designate your home-language for this in some cases, but look for existing standard codes when possible); that is, just use it as a key, and not for the value. Also, you can't always trust things _inside_ your database either - if you concatenate values from db entries a user has provided, you're in the same boat. – Clockwork-Muse Mar 23 '14 at 07:25
  • Checkout the basic Developer Tools that come with your browser -- you'll find you can easily modify the request data submitted to the server. If you really want to have fun checkout Fiddler http://www.telerik.com/fiddler – kingdango Mar 26 '14 at 12:07

11 Answers11

198

Yes you need to protect against this.

Let me show you why, using Firefox's developer console:

i've edited one of the values in the dropdown to be a drop table statement

If you don't cleanse this data, your database will be destroyed. (This might not be a totally valid SQL statement, but I hope I've gotten my point across.)

Just because you've limited what options are available in your dropdown does not mean you've limited the data I can send your server.

If you tried to restrict this further using behaviour on your page, my options include disabling that behaviour, or just writing a custom HTTP request to your server which imitates this form submission anyway. There's a tool called curl used for exactly that, and I think the command to submit this SQL injection anyway would look something like this:

curl --data "size=%27%29%3B%20DROP%20TABLE%20*%3B%20--"  http://www.example.com/profile/save

(This might not be a totally valid curl command, but again, I hope I've gotten my point across.)

So, I'll reiterate:

NEVER trust user input. ALWAYS protect yourself.

Don't assume any user input is ever safe. It's potentially unsafe even if it arrives through some means other than a form. None of it is ever trustworthy enough to forgo protecting yourself from SQL injection.

doppelgreener
  • 4,809
  • 10
  • 46
  • 63
  • 24
    Not to mention crafting a custom payload with `curl`. ***ALWAYS*** sanitize input *server-side*! – recursion.ninja Mar 21 '14 at 21:35
  • 14
    An image says more than a thousand words. – davidkonrad Mar 22 '14 at 06:08
  • 4
    This should be the default answer. Also should include something about `curl`. People don't understand that you can send an HTTP request from anywhere to anywhere using any format and passing any values, it is up to the server to make sure the request is valid before processing it. – retrohacker Mar 25 '14 at 21:05
  • 3
    How cute! It's little Bobby Tables! – xubia May 22 '14 at 18:26
69

You could do something as simple as the following example to make sure the posted size is what you expect.

$possibleOptions = array('All', 'Large', 'Medium', 'Small');

if(in_array($_POST['size'], $possibleOptions)) {
    // Expected
} else {
    // Not Expected
}

Then use mysqli_* if you are using a version of php >= 5.3.0 which you should be, to save your result. If used correctly this will help with sql injection.

Oliver Bayes-Shelton
  • 6,135
  • 11
  • 52
  • 88
  • is this a shorthand version of a 'whitelist' OliverBS? – Tatters Mar 20 '14 at 13:33
  • Not really just a very basic version of one, you could add the values into a database to check against to make it easier and reusable.Or maybe make a whitelist class with a specific method for each whitelist to check against. if you didn't want to use a database the whitelist properties could be inside an array property in your whitelist class. – Oliver Bayes-Shelton Mar 20 '14 at 13:35
  • 9
    Nonetheless, you must use Prepared Statements (recommended) or [`mysqli_real_escape_string`](http://php.net/mysqli_real_escape_string). Also properly escape the values when outputting them (e.g. use [htmlspecialchars()](http://php.net/htmlspecialchars) in a HTML document). – ComFreek Mar 20 '14 at 18:12
  • 4
    I'd suggest setting the third parameter of `in_array` to `true` for strict comparison. I'm not sure what could go wrong, but loose comparison's pretty quirky. – Brilliand Mar 20 '14 at 18:53
  • 1
    @OliverBS $_POST values can also be arrays. Numeric strings compare as numbers ('5'=='05'). I don't think you have a security hole in your specific example, but the rules are complex, and holes could open up for reasons I don't even understand. Strict comparison is easier to reason about, and therefore easier to use securely. – Brilliand Mar 21 '14 at 16:15
  • Use PDO and bound params. Use frameworks like Yii. All you try to do is done already. – George Sovetov Mar 25 '14 at 21:16
  • Definitely set the third parameter to `true` when calling `in_array()`. See here why: http://stackoverflow.com/questions/37080581/why-does-in-array-return-unexpected-strange-results – Andreas May 16 '16 at 08:37
46

As this question was tagged with , here is an answer regarding this particular kind of attack:

As you've been told in the comments, you have to use prepared statements for the every single query involving any variable data, with no exceptions.

Regardless of any HTML stuff!
It is essential to understand that SQL queries have to be formatted properly regardless of any external factors, be it HTML input or anything else.

Although you can use white-listing suggested in other answers for the input validation purpose, it shouldn't affect any SQL-related actions - they have to remain the same, no matter if you validated HTML input or not. It means you still have to use prepared statements when adding any variables into the query.

Here you may find a thorough explanation, why prepared statements is a must and how to properly use them and where they aren't applicable and what to do in such case: The Hitchhiker's Guide to SQL Injection protection

Also, this question was tagged with . Mostly by accident, I presume, but anyway, I have to warn you that raw mysqli is not an adequate substitution for the old mysq_* functions. Simply because if used in the old style, it will add no security at all. While it's support for the prepared statements is painful and troublesome, to the point that average PHP user is just unable to endeavor them at all. Thus, if no ORM or some sort of abstraction library is option, then PDO is your only choice.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 5
    i = random(0, 15); //some query using i. Do I still need to prepared statement here? – Cruncher Mar 20 '14 at 14:52
  • 1
    Do you have any defense for that? – Cruncher Mar 20 '14 at 14:54
  • 2
    What's the implementation of `random`? – Slicedpan Mar 20 '14 at 14:55
  • 2
    @Slicedpan excellent question! Though it is still beatable from that narrow-viewed position he's trying to pull. – Your Common Sense Mar 20 '14 at 14:56
  • 9
    @YourCommonSense narrow-viewed? To me "Always do X, and I will provide no reasoning for it" is narrow-viewed. – Cruncher Mar 20 '14 at 14:59
  • 2
    @Slicedpan If your random isn't working, then even any of your encryption is unsafe... in which case SQL Injection is not your biggest problem. – Cruncher Mar 20 '14 at 15:01
  • 2
    So be it. It would be ridiculous to argue with someone on *such* a topic. – Your Common Sense Mar 20 '14 at 15:01
  • 2
    @YourCommonSense Also to mention that this answer is grossly incomplete. Your god of preparedstatements is not enough here. They can still potentially inject values into your database, which may be problematic later. This is my problem with people just say "always do X". It makes them not think about actual security problems. The best is to analyse and determine what security measures are necessary. – Cruncher Mar 20 '14 at 15:03
  • @Cruncher why not use prepared statements then? If used correctly they protect you against a wide range of SQL injection attacks, even if you don't do any other validation. – Slicedpan Mar 20 '14 at 15:05
  • 5
    @Cruncher I can't think of any reason not to *always* use prepared statements, every time, for everything, always. Can you tell me one? – Wesley Murch Mar 20 '14 at 15:08
  • 1
    @WesleyMurch When you use a PreparedStatement it sends 2 different requests to the DBMS, a Prepare, and an Execute. That doubles the time for easy queries(as the execution time for simple queries is negligible compared to the network access). – Cruncher Mar 20 '14 at 15:13
  • @Slicedpan See above ^ – Cruncher Mar 20 '14 at 15:14
  • 2
    @Cruncher Have you ever heard of the evils of premature optimization? I can't imagine a scenario where the doubling of requests would be the bottleneck for performance. (Unless you have 500 million users) – Slicedpan Mar 20 '14 at 15:17
  • 1
    @Cruncher Doubling `0.001` is worth your app being secure. I do get your point though, but always err on the side of caution, espetially when guiding young programmers who don't know what they're doing yet. – Wesley Murch Mar 20 '14 at 15:17
  • 2
    @WesleyMurch 0.001 is a GIANT assumption. You told me to find you a case. Not find a case that fits some pre-existing conditions that you didn't tell me about. Of course you change the rules when people win. And if your app is secure without it, you gain nothing. – Cruncher Mar 20 '14 at 15:18
  • 2
    @WesleyMurch AACK. When guiding young programmers it is better to teach them WHY they do these things. Not just tell them to do it. – Cruncher Mar 20 '14 at 15:19
  • 3
    @Cruncher That I agree with, it just seems like you're playing Devil's Advocate. The stipulation in the answer is also *"involving any variable data"*. There are a few cases like PHP int casting maybe but it seems better to just use prepared statements. Telling (unexperienced) people that a minor performance "boost" is more important than security is way off. The answer is "incomplete" but it sends a strong message that the others are ignoring. I'll rest my case. – Wesley Murch Mar 20 '14 at 15:20
  • 1
    @WesleyMurch My biggest point, is that this kind of idea gives people a false sense of them having a secure application. Limiting the possible things that can go in that spot is something that you need often need to do regardless. And this would be considered "involving variable data" and I see no reason for a prepared statement, if you validate input properly. – Cruncher Mar 20 '14 at 15:26
  • 1
    @Cruncher The question is about SQL injection (security). The idea of "validating data" such as which dropdown options are OK (data integrity) is a separate issue. However your poem has touched my heart and I will think it over ;) – Wesley Murch Mar 20 '14 at 15:28
  • @WesleyMurch You get 2 in 1 with oliver's answer though! It is sufficient for security. – Cruncher Mar 20 '14 at 15:30
  • 1
    @Cruncher I would argue that teaching developers about the importance of using prepared statements may introduce them to the idea that they should not trust user input, and does not imbue them with (as much of) a false sense of security as you claim. This argument is now really about how to teach secure development. – Slicedpan Mar 20 '14 at 15:36
  • 3
    @AnonymousPi nope, not a slightest idea. After this question got into "hot" or something - yes, it's comprehensible. But this is a question - *how* it got there. It is not different from hundreds of thousands other questions which passes unnoticed. – Your Common Sense Mar 21 '14 at 06:43
  • THe question was not about prepared statements. The question was not aan attmept to argue against prepared statements. The question was : _does this also apply to a form where the only input is from a dropdown(s) ?_ – davidkonrad Mar 21 '14 at 09:17
  • 1
    @davidkonrad and the answer is stating that prepared statements and sql injections has absolutely nothing to do with any HTML stuff – Your Common Sense Mar 21 '14 at 09:35
  • @Cruncher a) You should *always* use prepared statements - even if you think you've validated your inputs properly - it's much easier and almost impossible to get wrong, unlike input validation b) In this specific case, if invalidated inputs gets through, the user gets no results (the expected behaviour) and nothing bad happens (provided you use prepared statements) – OrangeDog Mar 21 '14 at 11:38
  • @Cruncher and even if you don't accept prepared statements would make the example in your first comment more secure, they will make it more efficient, so you should use them anyway – OrangeDog Mar 21 '14 at 11:40
  • 1
    @OrangeDog in fact, prepared statement scarcely can make database interaction more efficient, at least in PHP. – Your Common Sense Mar 21 '14 at 11:43
  • If PHP adds so much overhead then that's PHP's fault. At the SQL server, repeated calls to a prepared statement will have better performance than if they're all submitted as separate queries. – OrangeDog Mar 21 '14 at 13:21
  • 1
    @OrangeDog it is not overhead but just the way PHP works. PDP is dying after serving each request. Such behavior has its advantages, yet it makes impossible to reuse a statement which was prepared in another request. The gain is not that significant though. – Your Common Sense Mar 21 '14 at 13:27
  • I would suggest an ORM. RedBeanPHP is pretty awesome these days. – Aristides Mar 22 '14 at 21:58
13

Yes.

Anyone can spoof anything for the values that actually get sent --

SO, for validating dropdown menus, you can just check to make sure that the value that you're working with was in the dropdown - something like this would be the best(most sanely paranoid) way:

if(in_array($_POST['ddMenu'], $dropDownValues){

    $valueYouUseLaterInPDO = $dropDownValues[array_search("two", $arr)];

} else {

    die("effin h4x0rs! Keep off my LAMP!!"); 

}
rm-vanda
  • 3,122
  • 3
  • 23
  • 34
  • 5
    This answer is incomplete, additionally you should use prepared statements, so that injection is not possible regardless of what the value is set to – Slicedpan Mar 20 '14 at 13:20
  • 7
    @Slicedpan Really? That sounds like you're jumping on the bandwagon without knowing why... If I have a handful of possible inputs into a query, such that I can verify that they're all okay (which I know, because I made them), then you accrue no additional *security* benefits from using a prepared statement – Cruncher Mar 20 '14 at 14:48
  • 3
    Except that enforcing the use of prepared statements as a convention protects you from introducing SQL injection vulnerabilities in the future. – Slicedpan Mar 20 '14 at 14:52
  • 1
    @Cruncher in fact, you have to learn to separate responsibilities. At the time of query building/execution the program should be totally ignorant of the source or nature of input data (save for its role in the query). So, you are free to verify your HTML data the way you like, but it should never affect any SQL interaction. – Your Common Sense Mar 20 '14 at 15:10
  • @YourCommonSense Well you can pass whether or not the data is from a trusted source. Then it still handles the responsibility on its own. – Cruncher Mar 20 '14 at 15:34
  • 1
    @Cruncher Making a promise "all values in the drop-down will always be safe" is a very unsafe promise to make. Values are changed, code is not necessarily updated. The one updating the values might not even know what is unsafe value! Especially in the realm of web programming, which is rife with all kinds of security concerns, skimping on something like this is just plain irresponsible (and other less nice words). – hyde Mar 20 '14 at 19:56
  • 1
    @Cruncher If you properly handle your SQL stuff, you can accept *any* input without interfering with the properly working of the SQL. The SQL part should be prepared and ready to accept anything no matter where it comes from. Everything else is error-prone. – glglgl Mar 21 '14 at 08:46
8

One way of protecting against users changing your drop downs using the console is to only use integer values in them. Then you can validate that the POST value contains an integer, and use an array to convert that to text when needed. E.g:

<?php
// No, you don't need to specify the numbers in the array but as we're using them I always find having them visually there helpful.
$sizes = array(0 => 'All', 1 => 'Large', 2 => 'Medium', 3 => 'Small');
$size = filter_input(INPUT_POST, "size", FILTER_VALIDATE_INT);

echo '<select name="size">';
foreach($sizes as $i => $s) {
    echo '<option value="' . $i . '"' . ($i == $size ? ' selected' : '') . '>' . $s . '</option>';
}
echo '</select>';

Then you can use $size in your query with knowledge that it will only ever contain FALSE or an integer.

Styphon
  • 10,304
  • 9
  • 52
  • 86
  • 2
    @OliverBS What is `filter_input` if not a check on the server side? No one can post anything except an integer. – Styphon Mar 20 '14 at 14:09
  • Thanks Styphon, So this replaces the form in the OP? And would this be applicable to larger forms with multiple dropdowns? If I added another dropdown to it for say 'colour'? – Tatters Mar 20 '14 at 14:19
  • @SamuelTattersfield Yes and yes. You can use this for as many dropdowns as you like, with as many options as you like. You just create a new array for each dropdown and put in all the options for the dropdown in the array. – Styphon Mar 20 '14 at 14:21
  • Nice! I like it. I'll give it a shot and see what I get in testing. – Tatters Mar 20 '14 at 14:22
  • @SamuelTattersfield Great, just make sure to use the `filter_input` part as well for the validation, otherwise it's as useful as a chocolate teapot for security. – Styphon Mar 20 '14 at 14:24
7

The other answers already cover what you need to know. But maybe it helps to clarify some more:

There are TWO THINGS you need to do:

1. Validate form data.

As Jonathan Hobbs' answer shows very clearly, the choice of html element for the form input does not do any reliable filtering for you.

Validation is usually done in a way that does not alter the data, but that shows the form again, with the fields marked as "Please correct this".

Most frameworks and CMSes have form builders that help you with this task. And not just that, they also help against CSRF (or "XSRF"), which is another form of attack.

2. Sanitize/Escape variables in SQL statements..

.. or let prepared statements do the job for you.

If you build a (My)SQL statement with any variables, user-provided or not, you need to escape and quote these variables.

Generally, any such variable you insert into a MySQL statement should be either a string, or something that PHP can be reliably turn into a string that MySQL can digest. Such as, numbers.

For strings, you then need to choose one of several methods to escape the string, that means, replace any characters that would have side effects in MySQL.

  • In old-school MySQL + PHP, mysql_real_escape_string() does the job. The problem is that it is far too easy to forget, so you should absolutely use prepared statements or query builders.
  • In MySQLi, you can use prepared statements.
  • Most frameworks and CMSes provide query builders that help you with this task.

If you are dealing with a number, you could omit the escaping and the quotes (this is why the prepared statements allow to specify a type).

It is important to point out that you escape the variables for the SQL statement, and NOT for the database itself. The database will store the original string, but the statement needs an escaped version.

What happens if you omit one of these?

If you don't use form validation, but you do sanitize your SQL input, you might see all kinds of bad stuff happening, but you won't see SQL injection! (*)

First, it can take your application into a state you did not plan for. E.g. if you want to calculate the average age of all users, but one user gave "aljkdfaqer" for the age, your calculation will fail.

Secondly, there can be all kinds of other injection attacks you need to consider: E.g. the user input could contain javascript or other stuff.

There can still be problems with the database: E.g. if a field (database table column) is limited to 255 characters, and the string is longer than that. Or if the field only accepts numbers, and you attempt to save a non-numeric string instead. But this is not "injection", it is just "crashing the application".

But, even if you have a free text field where you allow any input with no validation at all, you could still save this to the database just like that, if you properly escape it when it goes to a database statement. The problem comes when you want to use this string somewhere.

(*) or this would be something really exotic.

If you don't escape variables for SQL statements, but you did validate form input, then you can still see bad stuff happening.

First, you risk that when you save data to the database and load it again, it won't be the same data anymore, "lost in translation".

Secondly, it can result in invalid SQL statements, and thus crash your application. E.g. if any variable contains a quote or double quote character, depending which type of quote you use, you will get invalid MySQL statement.

Thirdly, it can still cause SQL injection.

If your user input from forms is already filtered / validated, intentional SQl injection may become less likely, IF your input is reduced to a hardcoded list of options, or if it is restricted to numbers. But any free text input can be used for SQL injection, if you don't properly escape the variables in SQL statements.

And even if you have no form input at all, you could still have strings from all kinds of sources: Read from the filesystem, scraped from the internet, etc. Noone can guarantee that these strings are safe.

Community
  • 1
  • 1
donquixote
  • 4,877
  • 3
  • 31
  • 54
  • Neither too long data not a string into numeric field will crash anything – Your Common Sense Mar 22 '14 at 15:21
  • hmm, just tried this now, and indeed it shows a warning instead of an error. I think it is PDO that turns this into an error. I am sure I discussed in a dozen of issues on drupal.org where some string is too long for a varchar. – donquixote Mar 22 '14 at 15:35
6

Your web browser does not "know" that it is receiving a page from php, all it sees is html. And the http layer knows even less than that. You need to be able to handle nearly any kind of input that can cross the http layer (luckily for most input php will already give an error). If you are trying to prevent malicious requests from messing up your db, then you need to assume that the guy on the other end knows what he is doing, and that he is not limited to what you can see in your browser under normal circumstances (not to mention what you can fiddle with a browser's developer tools). So yes, you need to cater for any input from your dropdown, but for most input you can give an error.

Nameless One
  • 1,615
  • 2
  • 23
  • 39
6

The fact that you have restricted the user to only using values from a certain drop-down list is irrelevant. A technical user can capture the http request sent to your server before it leaves their network, alter it using a tool such as a local proxy server, and then continue it on it's way. Using the altered request, they can send parameter values that are not ones that you have specified in the drop down list. Developers have to have the mindset that client restrictions are often meaningless, as anything on a client can be altered. Server validation is required at every single point that client data enters. Attackers rely on the naivety of developers in this sole aspect.

Jason Higgins
  • 1,516
  • 1
  • 17
  • 37
5

It's best to use a parameterized query in order to ensure against SQL injection. In that case the look of the query would be this:

SELECT * FROM table WHERE size = ?

When you supply a query like the above with text that is unverified for integrity (the input isn't validated on the server) and it contains SQL injection code it will be handled correctly. In other words, the request will result in something like this happening in the database layer:

SELECT * FROM table WHERE size = 'DROP table;'

This will simply select 0 results as it returns which will make the query ineffective in actually causing harm to the database without the need for a whitelist, a verification check or other techniques. Please note that a responsible programmer will do security in layers, and will often validate in addition to parameterizing queries. However, there is very little cause to not parameterize your queries from a performance perspective and the security added by this practice is a good reason to familiarize yourself with parameterized queries.

Dan Smith
  • 763
  • 9
  • 14
4

Whatever is submitted from your form comes to your server as text across the wires. There is nothing stopping anyone from creating a bot to mimic the client or type it in from a terminal if they wanted to. Never assume that because you programmed the client it will act like you think it will. This is really easy to spoof.

Example of what can and will happen when you trust the client.

GenericJam
  • 2,915
  • 5
  • 31
  • 33
4

A hacker can bypass the browser completely, including Javascript form checking, by sending a request using Telnet. Of course, he will look at the code of your html page to get the field names he has to use, but from then on it's 'everything goes' for him. So, you must check all values submitted on the server as if they did not originate from your html page.