I'm currently tinkering with a hacking challenge where the goal is to output phpinfo() on the page. After some poking around I've found that the injection point is the search page as it runs preg_replace with the 'e' modifier on the search query. I've been able to trigger errors with inputs such as ") blah" and "b|exit(phpinfo());" but unfortunately I'm not sure how to phrase my injection so that preg_replace actually runs it.
The confusing part I haven't wrapped my head entirely around is that the regular expression seems to be matching names that correspond to those listed on the page, but only if said input is 3 characters or greater in length. I deduced that I would have to find a way to both match the regular expression and then append some code to the end so it evaluates phpinfo() as a command instead of a string.
Does anyone have some more insight to what is going on, and how to crack this?
The /e modifier allows a second argument to be evaluated as a PHP expression.
So if you were to do something like:
$string = "phpinfo()";
print preg_replace('/^(.*)/e', 'strtoupper(\\1)', $string);
This would fire the function and print the PHP info. Depending on how the search is set up, you can modify to print properly. Hope this helps.
Related
I am stuck trying to create a regex that will allow for letters, numbers, and the following chars: _ - ! ? . ,
Here is what I have so far:
/^[-\'a-zA-Z0-9_!\?,.\s]+$/ //not escaping the ?
and this version too:
/^[-\'a-zA-Z0-9_!\?,.\s]+$/ //attempting to escape the ?
Neither of these seem to be able to match the following:
"Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?"
Can somebody point out what I am doing wrong? I must point out that my script takes the user input (the paragraph in quotes in this case) and strips all white space so actual input has no white space.
Thanks!
UPDATE:
Thanks to Lix's advice, this is what I have so far:
/^[-\'a-zA-Z0-9_!\?,\.\s]+$/
However, it's still not working??
UPDATE2
Ok, based on input this is what's happening.
User inputs string, then I run the string through following functions:
$comment = preg_replace('/\s+/', '',
htmlspecialchars(strip_tags(trim($user_comment_orig))));
So in the end, user input is just a long string of chars without any spaces. Then that string of chars is run using:
preg_match("#^[-_!?.,a-zA-Z0-9]+$#",$comment)
What could possibly be causing trouble here?
FINAL UPDATE:
Ended up using this regex:
"#[-'A-Z0-9_?!,.]+#i"
Thanks all! lol, ya'll are going to kill me once you find out where my mistake was!
Ok, so I had this piece of code:
if(!preg_match($pattern,$comment) || strlen($comment) < 2 || strlen($comment) > 60){
GEEZ!!! I never bothered to look at the strlen part of the code. Of course it was going to fail every time...I only allowed 60 chars!!!!
When in doubt, it's always safe to escape non alphanumeric characters in a class for matching, so the following is fine:
/^[\-\'a-zA-Z0-9\_\!\?\,\.\s]+$/
When run through a regular expression tester, this finds a match with your target just fine, so I would suggest you may have a problem elsewhere if that doesn't take care of everything.
I assume you're not including the quotes you used around the target when actually trying for a match? Since you didn't build double quote matching in...
Can somebody point out what I am doing wrong? I must point out that my script takes the user input (the paragraph in quotes in this case) and strips all white space so actual input has no white space.
in which case you don't need the \s if it's working correctly.
I got the following code to work as expected to (running php5):
<?php
$pattern = "#[-'A-Z0-9_?!,.\s]+#i";
$string = "Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?";
$results = array();
preg_match($pattern, $string, $results);
echo '<pre>';
print_r($results);
echo '</pre>';
?>
The output from print_r($results) was as following:
Array
(
[0] => Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?
)
Tested on http://writecodeonline.com/php/.
It's not necessary to escape most characters inside []. However, \s will not do what you want inside the expression. You have two options: either manually expand (/^[-\'a-zA-Z0-9_!?,. \t\n\r]+$/) or use alternation (/^(?:[-\'a-zA-Z0-9_!?,.]|\s)+$/).
Note that I left the \ before the ' because I'm assuming you're putting this in a PHP string and I wouldn't want to suggest a syntax error.
The only characters with a special meaning within a character class are:
the dash (since it can be used as a delimiter for ranges), except if it is used at the beginning (since in this case it is no part of any range),
the closing bracket,
the backslash.
In "pure regex parlance", your character class can be written as:
[-_!?.,a-zA-Z0-9\s]
Now, you need to escape whatever needs to be escaped according to your language and how strings are written. Given that this is PHP, you can take the above sample as is. Note that \s is interpreted in character classes as well, so this will match anything which is matched by \s outside of a character class.
While some manuals recommend using escapes for safety, knowing the general regex rules for character classes and applying them leads to shorter and easier to read results ;)
I am using a Regular Expression to perform a find and replace with dreamweaver. I am running into some difficulty. This is what I have in my page (note that there is a syntax error because I need an additional parenthesis at the end of the string).
$email=htmlspecialchars(mysql_real_escape_string($_POST['email']);
$name=htmlspecialchars(mysql_real_escape_string($_POST['name']);
I am trying to performa a find and replace that will produce this:
$email=htmlspecialchars(mysql_real_escape_string($_POST['email']));
$name=htmlspecialchars(mysql_real_escape_string($_POST['name']));
This is what I am using to perform the find. It seems to be replacing too much text (it starts with the $_POST from the $email variable, but continues all the way down to the $_POST for the $name variable)
Find: \$_POST['([^<]*)']
Replace: $_POST['$1'])
I end up with this:
$email=htmlspecialchars(mysql_real_escape_string($_POST['email']);
$name=htmlspecialchars(mysql_real_escape_string($_POST['name']));
As you can see, it only fixes the last instance (this is because the find function is selecting both lines from $_POST['email'] all the way to $_POST['name']). Any ideas on how to fix this? Thank you!
Add a question mark to make it non-greedy. Also, you need to escape the [ and ] characters that you want to match.
Find: \$_POST\['([^<]*?)'\]
Replace: $_POST['$1'])
Or, alternatively, user a ' character instead of a < character to match the value within the quotes:
Find: \$_POST\['([^']*)'\]
Replace: $_POST['$1'])
I'm confused by a difference I found between the way JavaScript and PHP handle the following regex.
In JavaScript,
'foobar'.replace(/(?=(bar))/ , '$1');
'foobar'.replace(/(?=(bar))?/ , '$1');
'foobar'.replace(/(?:(?=(bar)))?/, '$1');
results in, respectively,
foobarbar
foobar
foobar
as shown in this jsFiddle.
However, in PHP,
echo preg_replace('/(?=(bar))/', '$1', "foobar<br/>");
echo preg_replace('/(?=(bar))?/', '$1', "foobar<br/>");
echo preg_replace('/(?:(?=(bar)))?/', '$1', "foobar<br/>");
results in,
foobarbar
Warning: preg_replace() [function.preg-replace]: Compilation failed: nothing to repeat at offset 9 in /homepages/26/d94605010/htdocs/lz/writecodeonline.com/php/index.php(201) : eval()'d code on line 2
foobarbar
I'm not so much worried about the warning. But it appears that in JavaScript, lookahead assertions are somehow "lazier" than in PHP. Why the difference? Is this a bug in one of the engines? Which is theoretically more "correct"?
The real difference is actually very simple:
In JavaScript, replace will only replace the first match, unless using the /g flag (global).
In PHP, preg_replace replaces all matches.
The third pattern, (?:(?=(bar)))?, can match the empty string in every position, and captures "bar" in some positions. Without the /g flag, it only matches once, at the beginning of the string.
You would have easily seen the difference had you used a more visible replacement string, like [$1].
PHP Example: http://ideone.com/8Mjg6
JavaScript Example, no /g: http://jsfiddle.net/qKb4b/3/
JavaScript Example, with /g: http://jsfiddle.net/qKb4b/2/
I would also note that "laziness" is a different concept in regular expressions, not related to this question.
I'm trying to find the correct Regular Expression to match all RT scenarios on Twitter (can't wait to Twitter's new retweet API).
The way I see it, RT's can be at the beginning, middle, or end of the string returned from Twitter.
So, I need something at the beginning and end of this Regular Expression:
([Rr])([Tt])
No matter what I try, I cannot match all scenarios in one Regular Expression. I tried
[^|\s+]
to match the scenario where the RT will appear either at the beginning of the string or after one or more whitespace characters, but it didn't work the same for the end of the string or RT. I tried
[\s+|$]
to match a case when the RT appear either in the end of the string or there's one or more whitespace characters following it, same as with the 'pre' -- it didn't work.
Can someone please explain what am I doing wrong here? Any help or suggestions will be highly appreciated (as always :) )
You'll probably be happiest with something like:
/\brt\b/i
Which will find isolated instances of RT (that is, surrounded by word-boundaries), and use the /i modifier at the end of the regex to make it case-insensitive.
You want the word boundaries so that you don't end up thinking random tweets containing words like "Art" and "Quartz" are actually retweets. Even then, it's going to have false positives.
By default, a regular expression can (and will) match anywhere inside a string, so you don't need to account for what may precede or follow your match if indeed you don't care what it is or if it is present.
if(preg_match('/\brt\s*#(\w+)/i', $tweet, $match))
echo 'Somebody retweeted ' . $match[1] . "\n";
im new to regular expressions in php.
I have some data in which some of the values are stored as zero(0).What i want to do is to replace them with '-'. I dont know which value will get zero as my database table gets updated daily thats why i have to place that replace thing on all the data.
$r_val=preg_replace('/(0)/','-',$r_val);
The code im using is replacing all the zeroes that it finds for eg. it is even replacing zero from 104.67,giving the output 1-4.56 which is wrong. i want that data where value is exact zero that must be replaced by '-' not every zero that it encounter.
Can anyone please help!!
Example of the values that $r_val is having :-
10.31,
391.05,
113393,
15.31,
1000 etc.
This depends alot on how your data is formatted inside $r_val, but a good place to start would be to try:
$r_val = preg_replace('/(?<!\.)\b0\b(?!\.)/', '-', $r_val);
Where \b is a 0-length character representing the start or end of a 'word'.
Strange as it may sound, but the Perl regex documentation is actually really good for explaining the regex part of the preg_* functions, since Perl is where the functionality is actually implemented.
Again, it would be more than helpful if you could supply an example of what the $r_val string really looks like.
Note that \b matches at word boundaries, which would also turn a string like "0.75" into "-.75". Not a desirable result, I guess.
Whilst the other answer does work, it seems overly complex to me. I think you need only to use the ^ and $ chars either side of 0.
$r_val = preg_replace('/^0+$/', '-', $r_val);
^ indicates the regex should match from the beginning of the line.
$ indicates the regex should match to the end of the line.
+ means match this pattern 1 or more times
I altered the minus sign to it's html code equivalent too. Paranoid, yes, but we are dealing with numbers after all, so I though throwing a raw minus sign in there might not be the best idea.
Why not just do this?
if ( $r_val == 0 )
$r_val = '-';
You do not need to use a regex for this. In fact, I'd advise against doing so for performance reasons. The operation above is approximately 20x faster than the regex solution.
Also, the PHP manual advises against using regexes for simple replacements:
If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of ereg_replace() or preg_replace().
http://us.php.net/manual/en/function.str-replace.php
Hope that helps!