Sql vulnerable script needs fixing - mysql

function SetLastCharacter(source, charid)
   MySQLAsyncExecute("UPDATE `user_lastcharacter` SET `charid` = '"..charid.."' WHERE `steamid` = '"..GetPlayerIdentifiers(source)[1].."'")
end
This is the code that is vulnerable I need to still be able to use the script however I need this to be fixed any help would be greatly appreciated.

Just double every single quote and backslash in the text:
function SetLastCharacter(source, charid)
charid = string.gsub(charid, "['\\]", "%0%0")
local text = GetPlayerIdentifiers(source)[1]
text = string.gsub(text, "['\\]", "%0%0")
MySQLAsyncExecute("UPDATE `user_lastcharacter` SET `charid` = '"..charid.."' WHERE `steamid` = '"..text.."'")
end

Related

Backslashes in MySql update query not working

Running the following query in MySql workbench as \ is an escape character.
UPDATE midshared.SETUP
SET DATAVALUE = 'C:\Documents and Settings\ADMINISTRATOR\Desktop\'
WHERE CODE = 'SAGEPATH'
manually changing to this does work.
UPDATE midshared.SETUP
SET DATAVALUE = 'C:\\Documents and Settings\\ADMINISTRATOR\\Desktop\\'
WHERE CODE = 'SAGEPATH'
However trying these methods that I've found on Stack Overflow don't work either -
UPDATE midshared.SETUP
SET DATAVALUE = REPLACE('C:\Settings\ADMINISTRATOR\Desktop\','\','\\')
WHERE CODE = 'SAGEPATH'
or
UPDATE midshared.SETUP
SET DATAVALUE = QUOTE('C:\Documents and Settings\ADMINISTRATOR\Desktop\')
WHERE CODE = 'SAGEPATH'
Can anyone point me in the right direction to fix it please?
Thanks
A
I tried the queries listed above
You can use double quotes safely and escape slashes as follows:
UPDATE midshared.SETUP
SET DATAVALUE = "'C:\\Documents and Settings\\ADMINISTRATOR\\Desktop\\'"
WHERE CODE_ = 'SAGEPATH'
Check the demo here.

How to omit html tags in a mysql table attribute while doing a select

I have a table where each row consist of an attribute which consist of html data with like this.
<div className="single_line"><p>New note example</p></div>
I need to omit the html tags and extract only the data inside the tags using sql query. Any idea on how to achieve this?. I tried out different regex but they didnt work.
There are 2 solutions based on mysql version.
If you are using MySQL 8.0 then you can use REGEXP_REPLACE() directly inside the select statement.
SELECT REGEXP_REPLACE('<div><p>New note example</p></div>', '(<[^>]*>)|( )', '');
If you are using MySQL 5.7 then you have to create a user define function in database to strip html tags.
DROP FUNCTION IF EXISTS fn_strip_html_tags;
CREATE FUNCTION fn_strip_html_tags( html_text TEXT ) RETURNS TEXT
BEGIN
DECLARE start,end INT DEFAULT 1;
DECLARE text_without_nbsp TEXT;
LOOP
SET start = LOCATE("<", html_text, start);
IF (!start) THEN RETURN html_text; END IF;
SET end = LOCATE(">", html_text, start);
IF (!end) THEN SET end = start; END IF;
SET text_without_nbsp = REPLACE(html_text, " ", " ");
SET html_text = INSERT(text_without_nbsp, start, end - start + 1, "");
END LOOP;
END
For example
SELECT fn_strip_html_tags('<div><p>New note example</p></div>');

How to improve performance for REGEXP string matching in MySQL?

Preface:
I've done quite a bit of (re)searching on this, and found the following SO post/answer: https://stackoverflow.com/a/5361490/6095216 which was pretty close to what I'm looking for. The same code, but with somewhat more helpful comments, appears here: http://thenoyes.com/littlenoise/?p=136 .
Problem Description:
I need to split 1 column of MySQL TEXT data into multiple columns, where the original data has this format (N <= 7):
{"field1":"value1","field2":"value2",...,"fieldN":"valueN"}
As you might guess, I only need to extract the values, putting each one into a separate (predefined) column. The problem is that the number and order of the fields is not guaranteed to be the same for all records. Thus, solutions using SUBSTR/LOCATE, etc. don't work, and I need to use regular expressions. Another restriction is that 3rd party libraries such as LIB_MYSQLUDF_PREG (suggested in the answer from my 1st link above) cannot be used.
Solution/Progress so far:
I've modified the code from the above links such that it returns the first/shortest match, left-to-right; otherwise, NULL is returned. I also refactored it a bit and made the identifiers more reader/maintainer-friendly :)
Here's my version:
CREATE FUNCTION REGEXP_EXTRACT_SHORTEST(string TEXT, exp TEXT)
RETURNS TEXT DETERMINISTIC
BEGIN
DECLARE adjustStart, adjustEnd BOOLEAN DEFAULT TRUE;
DECLARE startInd INT DEFAULT 1;
DECLARE endInd, strLen INT;
DECLARE candidate TEXT;
IF string NOT REGEXP exp THEN
RETURN NULL;
END IF;
IF LEFT(exp, 1) = '^' THEN
SET adjustStart = FALSE;
ELSE
SET exp = CONCAT('^', exp);
END IF;
IF RIGHT(exp, 1) = '$' THEN
SET adjustEnd = FALSE;
ELSE
SET exp = CONCAT(exp, '$');
END IF;
SET strLen = LENGTH(string);
StartIndLoop: WHILE (startInd <= strLen) DO
IF adjustEnd THEN
SET endInd = startInd;
ELSE
SET endInd = strLen;
END IF;
EndIndLoop: WHILE (endInd <= strLen) DO
SET candidate = SUBSTRING(string FROM startInd FOR (endInd - startInd + 1));
IF candidate REGEXP exp THEN
RETURN candidate;
END IF;
IF adjustEnd THEN
SET endInd = endInd + 1;
ELSE
LEAVE EndIndLoop;
END IF;
END WHILE EndIndLoop;
IF adjustStart THEN
SET startInd = startInd + 1;
ELSE
LEAVE StartIndLoop;
END IF;
END WHILE StartIndLoop;
RETURN NULL;
END;
I then added a helper function to avoid having to repeat the regex pattern, which, as you can see from above, is the same for all the fields. Here is that function (I left my attempt to use a lookbehind - unsupported in MySQL - as a comment):
CREATE FUNCTION GET_MY_FLD_VAL(inputStr TEXT, fldName TEXT)
RETURNS TEXT DETERMINISTIC
BEGIN
DECLARE valPattern TEXT DEFAULT '"[^"]+"'; /* MySQL doesn't support lookaround :( '(?<=^.{1})"[^"]+"'*/
DECLARE fldNamePat TEXT DEFAULT CONCAT('"', fldName, '":');
DECLARE discardLen INT UNSIGNED DEFAULT LENGTH(fldNamePat) + 2;
DECLARE matchResult TEXT DEFAULT REGEXP_EXTRACT_SHORTEST(inputStr, CONCAT(fldNamePat, valPattern));
RETURN SUBSTRING(matchResult FROM discardLen FOR LENGTH(matchResult) - discardLen);
END;
Currently, all I'm trying to do is a simple SELECT query using the above code. It works correctly, BUT IT. IS. SLOOOOOOOW... There are only 7 fields/columns to split into, max (not all records have all 7)! Limited to 20 records, it takes about 3 minutes - and I have about 40,000 records total (not very much for a database, right?!) :)
And so, finally, we get to the actual question: [how] can the above algorithm/code (pretty much a brute search at this point) be improved SIGNIFICANTLY performance-wise, such that it can be run on the actual database in a reasonable amount of time? I started looking into the major known pattern-matching algorithms, but quickly got lost trying to figure out what would be appropriate here, in large part due to the number of available options and their respective restrictions, conditions for use, etc. Plus, it seems like implementing one of these in SQL just to see if it would help, might be a lot of work.
Note: this is my first post ever(!), so please let me know (nicely) if something is not clear, etc. and I will do my best to fix it. Thanks in advance.
I was able to solve this by parsing the JSON, as suggested by tadman and Matt Raines above. Being new to the concept of JSON, I just didn't realize it could be done this way at all...a little embarrassing, but lesson learned!
Anyway, I used the get_option function in the common_schema framework: https://code.google.com/archive/p/common-schema/ (found through this post, which also demonstrates how to use the function: Parse JSON in MySQL ). As a result, my INSERT query took about 15 minutes to run, vs the 30+ hours it would've taken with the REGEXP solution. Thanks, and until next time! :)
Don't do it in SQL; do it in PHP or some other language that has builtin tools for parsing JSON.

magic_quotes_gpc setting for ColdFusion? ColdBox?

I am new to ColdFusion and want to remove single quotes from the values of my input fields. I tried to search on google and what I found is to use "magic_quotes_gpc" or "mysql_real_escape_string" but those functions do not exist in ColdFusion. Is there any way to handle this kind of mysql query injection in ColdFusion?
Updated:
Thank you for reply but please look at my code
<div class="form-group">
<label for="jobDesc">Job description</label>
<textarea name="description" class="form-control" rows="3" id="jobDesc">
<cfif isdefined('userTime')>#userTime.description#</cfif>
</textarea>
</div>
I just want to use single quotes in the text area and my form is submitting to event. The query is:
sqlstr = "";
sqlstr = "insert into usertime set
userid = '#arguments.userTimeParams.userid#',
projectid = '#arguments.userTimeParams.projectid#',
timesheetdate = '#arguments.userTimeParams.timesheetdate#',
estimatedtimespent = '#arguments.userTimeParams.jobhours * 60 + arguments.userTimeParams.jobMins#',
description = '#arguments.userTimeParams.description#',
timeentered = #arguments.userTimeParams.timeentered#;";
queryObj = new query();
queryObj.setDatasource("timesheet");
queryObj.setName("adduserTime");
result = queryObj.execute(sql=sqlstr);
adduserTime = result.getResult();
return result.getPrefix().generatedKey;
I have one option that I can add slashes to my string, but then I have to add slashes in all strings. So is there any function or way to do this with less lines of code?
Sorry for asking much with limited knowledge.
Um... just don't pass your user input (or any other data ~) values hard-coded in your SQL statements, pass them as parameter values instead.
Example:
coloursViaQueryExecute = queryExecute("
SELECT en AS english, mi AS maori
FROM colours
WHERE id BETWEEN :low AND :high
",
{low=URL.low, high=URL.high},
{datasource="scratch_mssql"}
);
Where low and high are your parameters.
See relevant docs # QueryExecute()
And further reading on the topic:
What one can and cannot do with <cfqueryparam>
Query.cfc / queryExecute() have a good feature <cfquery> lacks
Without parameterizing the user data, you are opening yourself to SQL injection. The REReplace() may not catch everything. Here is how you should rewrite that code to use cfqueryparam. You may need to tweak the addParam() method calls to add the correct cfsqltype.
sqlstr = "";
sqlstr = "insert into usertime set
userid = :userid,
projectid = :projectid,
timesheetdate = :timesheetdate,
estimatedtimespent = :estimatedtimespent,
description = :description,
timeentered = :timeentered";
queryObj = new query();
queryObj.setDatasource("timesheet");
queryObj.setName("adduserTime");
queryObj.addParam( name="userid", value=arguments.usertimeparams.userid);
queryObj.addParam( name="projectid", value=arguments.usertimeparams.projectid);
queryObj.addParam( name="timesheetdate", value=arguments.usertimeparams.timesheetdate, cfsqltype="CF_SQL_TIMESTAMP");
queryObj.addParam( name="estimatedtimspent", value=arguments.userTimeParams.jobhours * 60 + arguments.userTimeParams.jobMins, cfsqltype="CF_SQL_INTEGER");
queryObj.addParam( name="description", value=arguments.usertimeparams.description);
queryObj.addParam( name="timeentered", value=arguments.usertimeparams.timeentered, cfsqltype="CF_SQL_INTEGER");
result = queryObj.execute(sql=sqlstr);
adduserTime = result.getResult();
return result.getPrefix().generatedKey;

mysql update 2 blobs at once not working

i'm having an issue when trying to update two BLOB fields in a row using mysql and php commands.
Inserting the BLOBs into the row seems to work no problem, here is what I do.
$logotemp = $_FILES['eventlogo']['tmp_name'];
$thumbnailtemp = $_FILES['eventthumbnail']['tmp_name'];
$openlogo = fopen($logotemp, 'r');
$openthumbnail = fopen($thumbnailtemp, 'r');
$logo = fread($openlogo, filesize($logotemp));
$logo = addslashes($logo);
$thumbnail = fread($openthumbnail, filesize($thumbnailtemp));
$thumbnail = addslashes($thumbnail);
fclose($openlogo);
fclose($openthumbnail);
So I have two form file inputs, and those files are read, and then set as the variables $log and $thumbnail. I then use the following command to enter this into the DB:
$qry = "INSERT INTO $table (`Event Logo`, `Venue Logo`) VALUES ('$logo', '$thumbnail')";
$result = mysql_query($qry);
if(!$result) {
die(mysql_error());
}
The above works fine, although I have trimmed out the rest of the fields that also get filled. The query works, and I can return the images to a page, and then display them along with all of the other information from that row.
I then want to edit the row, so created a new php file called edit.php, which is a copy of the php file used above, called new.php.
This means that the form is identical, and when the page is displayed, the value for each input is prefilled with the info from the database, the logo and thumbnail are shown next to the upload fields.
If I then run a query to update the row, using almost the same code as above, it always enteres an empty value into both blobs, essentially deleting the uploaded images. Here is what happens:
$id = $_POST['eventid'];
$logotemp = $_FILES['eventlogo']['tmp_name'];
$openlogo = fopen($logotemp, 'r');
$logo = fread($openlogo, filesize($logotemp));
$thumbnailtemp = $_FILES['eventthumbnail']['tmp_name'];
$openthumbnail = fopen($thumbnailtemp, 'r');
$thumbnail = fread($openthumbnail, filesize($thumbnailtemp));
fclose($openlogo);
fclose($openthumbnail);
So once again, the form fields are still called eventlogo and eventthumbnail, and the variables are still $logo and $thumbnail. I then use the following query to update the row:
$qry = "UPDATE $table SET `Event Name` = '$name', `Date` = '$date', `Time` = '$time', `Venue` = '$venue', `Price` = '$price', `Open To` = '$opento', `Rep Name` = '$repname', `Rep Email` = '$repemail', `Address` = '$address', `Website` = '$website', `Phone` = '$phone', `Description` = '$description', `Event Logo` = '$logo', `Venue Logo` = '$thumbnail' WHERE `Event ID` = '$id'";
I have left in the other variables that are updated this time.
$result = mysql_query($qry);
if(!$result) {
die(mysql_error());
}
When the query runs, it will update any other fields I want, except for the two image BLOB fields at the end. Considering I copied and pasted the code for the upload fields, the code to read the contents of that field, and then manually typed out a query to update those fields, I can't see what's going wrong.
Am I missing something obvious? Any help is greatly appreciated.
Thanks, Eds
Cant find the code I sorted this with, but I think I ended up just updating one at a time.