I have a html file that contains a submit form ,which asks the users the fill in their personal info .
Then it will post and store into the DB by method of PHP SQL .
i.e.
// Check input errors before inserting in database
if (empty($CName_err) && empty($Address_err) && empty($amount_err) && empty($Phone_err)) {
// Prepare an insert statement
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO database (CName, Address, Phone, Amount ,Ticket, Purpose) VALUES (?, ?, ?, ? ,?, ?)";
$q = $pdo->prepare($sql);
$q->execute(array($CName, $Address, $Phone, $amount ,$Ticket ,$Purpose));
Database::disconnect();
Hence, Any risks of being SQL injection attack in this case?
What should I do to improve my coding ?
Related
I am trying to update my sql table with some new values entered into the user. For some reason the sql command is not updating my db. I am getting the correct values I verified. Here is my code
#!/usr/bin/perl
#This is going to be the user login check and will set a cookie
use DBI;
use CGI qw(:standard);
use strict;
#Connection error
sub showErrorMsgAndExit {
print header(), start_html(-title=>shift);
print (shift);
print end_html();
exit;
}
#Connecting to the database
my $dbUsername = "root";
my $dbPassword = "password";
my $dsn = "DBI:mysql:f18final:localhost";
my $dbh = DBI->connect($dsn, $dbUsername, $dbPassword, {PrintError => 0});
#error checking
if(!$dbh) {
print header(), start_html(-title=>"Error connecting to DB");
print ("Unable to connec to the database");
print end_html();
exit;
}
print header;
print start_html(-title=>'Add Classes');
#Get the information the user entered
my $id = param('classid');
my $className = param('classname');
my $department = param('department');
my $classnum = param('classnum');
my $grade = param('grade');
my $credits = param('credit');
print "$id $className, $department, $classnum, $grade, $credits";
#first sql check to see if username is already taken
my $check = "UPDATE tblclasses(classname, department, classnum, grade, credits) VALUES (?, ?, ?, ?, ?) WHERE classID = $id";
my $sth = $dbh->prepare($check);
$sth->execute($className, $department, $classnum, $grade,$credits);
print "<h1>Success</h1>";
print "<form action=http://localhost/cgi-bin/edit.pl method = 'post'>";
print "<input type = 'submit' name = 'submit' value = 'Update Another'>";
print "</form>";
print "<form action=http://localhost/cgi-bin/actions.pl method = 'post'>";
print "<input type = 'submit' name = 'submit' value = 'Back to actions'>";
print "</form>";
print end_html();
exit;
When I try to run the sql command in mysql workbench it successfuly updates the row. What is my issue?
There is an error in the syntax of your SQL statement :
UPDATE tblclasses(classname, department, classnum, grade, credits)
VALUES (?, ?, ?, ?, ?)
WHERE classID = $id
Should be written :
UPDATE tblclasses
SET classname = ?,
department = ?,
classnum = ?,
grade = ?,
credits = ?
WHERE classID = ?
See the mysql docs.
Side notes (as commented also by #Grinnz) :
you should always « use strict »
you should set DBI attribute « RaiseError » to 1 on your database or statement handle(s) ; hence all DBI errors become fatal ; disabling both « RaiseError » and « PrintErrror » results in DBI neither dying on errors nor reporting them, hence you must manually check the return code of each and every DBI call to make sure that it worked - see the DBI docs
you should bind all variables in your SQL statement to void SQL injection (you did not bind $id, I changed that in the above query)
Without knowing the DBMS I can't be 100% certain, but it appears as though you blended the syntax for an insert and an update command. The correct syntax for an update should be:
UPDATE tblclasses
set
classname = ?,
department = ?,
classum = ?,
grade = ?,
credits = ?
WHERE classID = $id
Also, for what it's worth, you should also be able to pass the $id variable as a parameter also rather than interpolating it. This, in theory, will be kinder to the database as it will be compiling once and executing the same SQL statement over and over, only with different bind variable values:
my $check = qq{
UPDATE tblclasses
set
classname = ?,
department = ?,
classum = ?,
grade = ?,
credits = ?
WHERE classID = ?
};
my $sth = $dbh->prepare($check);
$sth->execute($className, $department, $classnum, $grade,$credits, $id);
I am a VOIP administrator and I have script for updating directory database in Perl which was purchased from vendor before I was employed here.
The script is working fine on all of the servers except for one.
#!/usr/bin/perl
use lib "/opt/asterisk/lib/";
use DBI;
use Asterisk::config;
sub trim($);
# database information
$db="kesc";
$host="sip-ho.kesc.com.pk";
$userid="foo";
$passwd="bar";
$connectionInfo="dbi:mysql:$db;$host";
$hubname = "";
# make connection to database
$dbh = DBI->connect($connectionInfo,$userid,$passwd);
# Perl trim function to remove whitespace from the start and end of the string
sub trim($)
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
my $rc = new Asterisk::config (file=>'/etc/asterisk/sip.conf',keep_resource_array=>0);
#list = $rc->fetch_sections_list();
$n = 1;
foreach (#list)
{
if ($_ ne "general") {
$entry = $rc->fetch_keys_hashref(section=>$_);
while ( my ($key, #value) = each(%$entry) )
{
if ($key eq "callerid") {
#vars = split('<',$value[0][0]);
$query = "insert into directory (extension,name,hub) values (" . trim($_) . ", '" . trim($vars[0]) . "', '$hubname') ON DUPLICATE KEY UPDATE hub='$hubname'";
$sth = $dbh->prepare($query);
$sth->execute();
}
}
}
$n++;
}
Now I get below mentioned error when executing it.
DBD::mysql::st execute failed: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near 's Office', '') ON DUPLICATE KEY UPDATE hub=''' at line 1 at ./directory line 39.
I have also replaced it from other server with same MySQL version where it works perfectly.
Please guide me.
Thank you for the code. It is as I suspected; you really shouldn't insert values directly into an SQL statement
Change line 37, 38, and 39 to this and it should work for you
$query = 'INSERT INTO directory (extension, name, hub) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE hub = ?';
$sth = $dbh->prepare($query);
$sth->execute( trim($_), trim($vars[0]), $hubname, $hubname );
Beware that the same problem is likely to exist elsewhere in the code base, so it really should be completely reviewed
How do I insert the following string into MySQL:
$myValue ouputs: [Hey, this is a multi text file that has special characters like this ' and this '' and this ,,"", and this ''' and this '''' and this !#$ and whatever]
But the following will not work because of special characters:
$sql = "UPDATE `mytable` SET NEWS=('$myValue') WHERE _id='1'";
I do not want to manually escape every character (like adding an ' before every ')
Update/Insert should should start at [ and end at ] (as seen in $myValue)
EDIT (mysqli)
$_myValue = mysqli_real_escape_string($myValue);
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE `mytable` SET NEWS='$_myValue' WHERE _id='1'";
if ($conn->query($sql) === TRUE) {
echo "Record updated successfully";
} else {
echo "Error updating record: " . $conn->error;
}
From the syntax of your code I assume that php is used to submit the queries to mysql.
If you just want to escape special characters in a string variable passed to a field, then use
PDO::quote() (if you use PDO)
mysqli_real_escape_string() (if you use mysqli)
mysql_real_escape_string() (if you use mysql, although you should not)
If you are looking for a more generic solution gainst sql injection, then consider using prepared statements. See this landmark SO topic on how to prevent SQL injection in php-mysql environment.
If your using php you could look at using PDO;
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE `mytable` SET NEWS=:myValue WHERE _id=1";
$st = $conn->prepare( $sql );
$st->bindValue(":myValue", $myValue, PDO::PARAM_STR);
$st->execute();
This will input all the data stored in $myValue. I would look at sanatising the input too.
I've tried searching forums for a solution, however most of the answers were either too difficult to understand. SO I'm in the process of making a website for a small community, and currently we have our database and html design layout, but I'm getting snagged on how to push my Perl CGI form into another Perl program to then alter my database.
Here is the Perl controller that alters the database tables (and it works):
#!/usr/bin/perl -w
#!/usr/bin/perl -wT
# DBI is the standard database interface for Perl
# DBD is the Perl module that we use to connect to the <a href=http://mysql.com/>MySQL</a> database
use DBI;
use DBD::mysql;
use warnings;
#----------------------------------------------------------------------
# open the accessDB file to retrieve the database name, host name, user name and password
open(ACCESS_INFO, "accessDB.txt") || die "Can't access login credentials";
# assign the values in the accessDB file to the variables
my $database = <ACCESS_INFO>;
my $host = <ACCESS_INFO>;
my $userid = <ACCESS_INFO>;
my $passwd = <ACCESS_INFO>;
my $tablename = "Article";
# the chomp() function will remove any newline character from the end of a string
chomp ($database, $host, $userid, $passwd);
# close the accessDB file
close(ACCESS_INFO);
#----------------------------------------------------------------------
# invoke the ConnectToMySQL sub-routine to make the database connection
$connection = ConnectToMySql($database);
if ($tablename == "Article"){
$connection = InsertArticle($database);
}
elsif ($tablename == "Category"){
$connection = InsertCategory($database);
}
elsif ($tablename == "Comment"){
$connection = InsertComment($database);
}
elsif ($tablename == "User"){
$connection = InsertUser($database);
}
else {
print "No such table found. Contact website administrator.\n"
}
sub InsertArticle{
$query = "insert into $tablename (Id, CategoryId, UserId, Title, Content) values(?, ?, ?, ?, ?)";
$statement = $connection->prepare($query);
$statement->execute('undef', '1', '1029', 'Dota2>League', 'textfromarticle');
}
sub InsertCategory{
$query = "insert into $tablename (Id, CategoryId, UserId, Title, Content) values(?, ?, ?, ?, ?)";
$statement = $connection->prepare($query);
$statement->execute('undef', '1', '1029', 'Dota2>League', 'textfromarticle');
}
sub InsertComment{
$query = "insert into $tablename (Id, CategoryId, UserId, Title, Content) values(?, ?, ?, ?, ?)";
$statement = $connection->prepare($query);
$statement->execute('undef', '1', '1029', 'Dota2>League', 'textfromarticle');
}
sub InsertUser{
$query = "insert into $tablename (Id, CategoryId, UserId, Title, Content) values(?, ?, ?, ?, ?)";
$statement = $connection->prepare($query);
$statement->execute('undef', '1', '1029', 'Dota2>League', 'textfromarticle');
}
exit;
#--- start sub-routine ------------------------------------------------
sub ConnectToMySql {
#----------------------------------------------------------------------
my ($db) = #_;
# assign the values to your connection variable
my $connectionInfo="dbi:mysql:$db;$host";
# make connection to database
my $l_connection = DBI->connect($connectionInfo,$userid,$passwd);
# the value of this connection is returned by the sub-routine
return $l_connection;
}
#--- end sub-routine --------------------------------------------------
In the future, I'll define the other tables in my database through global variables that depend on what button the user presses on the correct webpage. As in, if they're viewing a list of articles, an option at the top would be "submit an article". And from there, the form CGI would be sent to them that they can fill out.
And here is the CGI that makes the form that would be submitted to the above controller script to alter the table:
#!/usr/bin/perl
#!/usr/bin/perl -wT
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser); #remove this in production
my $q = new CGI;
print $q->header; #Content-Type: text/html; charset=ISO-8859-1
print $q->start_html(
-title => 'submit an Article', #page name
-style => {'src' => '/dmrwebsite/dmrwebsite/userinterface'}, #link to style sheet
);
print $q->start_form(
-name => 'submitting an Article',
-method => 'POST',
enctype => &CGI::URL_ENCODED,
-onsubmit => 'return true',
-action => '/dmrwebsite/dmrwebsite/controller.addtotable.pl',
);
print $q-.textfield(
-name => 'title',
-value => 'default value',
-required,
-size => 20,
-maxlength =>50,
);
print $q->textarea(
-name => 'content',
-value => 'default value',
-required,
-maxlength => 1000,
-cols => 60,
);
print $q->textarea(
-name => 'url',
-value => 'default value',
maxlength => 100,
cols =>60,
);
print $q-checkbox(
-name => 'humancheck',
-checked => 1,
-value => 'two',
-label => 'The number two',
);
print $q-submit(
-name => 'submit_Article',
-value => 'submit Article',
-onsumbit => 'javascript: validate_form()',
);
if ($q->param()) {
submit_form($q);
} else {
print "Please check your form for inaccuracies.";
}
sub submit_form($){
my ($q) = #_;
}
print $q->end_form; #ends the form html
print $q->end_html; #end the html document
So basically what I'm stuck at is understand how to send the form data to the perl script in which I can then define the table data in my $tablename = "Article"; and $statement->execute('undef', '1', '1029', 'Dota2>League', 'textfromarticle');.
Also, I don't have a javascript program to send to the parameter -onsubmit => javaapplication(),. Is that needed? Can I substitute my own Perl program to check the user inputted fields? And how would I call this function? IN the same file or can it just be in the parent directory like /website/perlchecker.pl?
Any help would be greatly appreciated as I'm only a couple days into using Perl let alone CGI and html. Got a couple people helping me on the front end of the website though.
Thanks,
-Ori
So many suggestions...
Firstly, your DB insertion program seems to just insert fixed data, so I'm not sure how you think that it works. Also, the if ($tablename == "Article") (and similar) line doesn't do what you want it to. You need to use eq instead of ==.
To answer the question that you asked - you need to change your database program so that it accepts input (probably command line arguments) containing the data that you want inserted into the database. You would then add to your CGI program a line that calls this program (probably using system()) passing it the data from the CGI parameters on the command line.
The code would look something like this:
my $title = $q->param('title');
my $content = $q->param('title');
# ... other params ...
system('db_script.pl', 'Article', $title, $content, ...)';
But please don't do that. That's a terrible idea.
Instead, I highly recommend that you re-write your database manipulation program as a module. That way, you can load the module into any program that needs to talk to the database and access the database by calling functions rather than by calling an external program. If it was down to me, then I'd definitely use DBIx::Class to produce this library - but I realise that might well be seen as rather advanced.
Then there's the elephant in the room. You're still using CGI to write your web interface. The CGI module has been removed from the latest version of Perl as it is no longer considered best practice for writing web applications. I recommend looking at CGI::Alternatives to find out about other, more modern, tools.
But if you're determined to carry on writing your program as a CGI program, then at the very least, please don't use the HTML generation functions. We've known that including your HTML in your program source code is a terrible idea for at least fifteen years. There's no reason to still be doing it in 2015. You should really be using some kind of templating engine to separate your HTML from your Perl code. I recommend the Template Toolkit.
I'm not sure where you are learning these techniques from, but your source seems to be a good ten years behind accepted best practice.
How to insert text into mysql having quotes using perl ?
It seems difficult to insert text containing ' & ".
I'm using Perl DBI module & DB is mysql.
UPDATE:
here is my query
my $s = "INSERT INTO comment(guid,review_id) VALUES ('$guid','$review_id')";
You should read section 'Placeholders and Bind Values' in man DBI
EDIT: added example
my $s = "insert into comment(guid,review_id) values (?, ?)";
$dbh->do( $s, undef, $guid, $review_id) or die $dbh->errstr;
Your old query would have been something like this:
my $s = "insert into comment(guid,review_id) values ('$guid','$review_id')";
$dbh->do($s);
The better way, using placeholders and bind values as per #AlexD's answer, would look like this:
my $sth = $dbh->prepare("insert into comment(guid,review_id) values (?, ?)";);
$sth->execute($guid, $review_id);
To learn about the security risks of your first approach, have a look at SQL injection attacks on Wikipedia.