I need some help on a REGEX in php (Symfony).
I want to match values 1 to 60 or string all.
For number I've use this : ^([1-5]?[0-9]|60) but It match 0 ... And I don't now how can match "all".
Can you help me ?
Many thanks before
You should be able to divide it into possibilities as follows:
^([1-9]|[1-5][0-9]|60|all)$
This gives you four possibilities:
[1-9] the single-digit values.
[1-5][0-9]: everything from ten to fifty-nine.
60: sixty.
all: your "all" option.
But keep in mind that regular expressions are not always the answer to every question.
Sometimes they're less useful for complicated value checks (though, in this case, it's a fairly simple one). Something like the following (pseudo-code):
def isAllOrOneThruSixty(str):
if str == "all":
return OK
if str.matches ("[0-9]+"):
val = str.convertToInt()
if val >= 1 and val <= 60:
return OK
return BAD
can sometimes be, while more verbose, also more readable and maintainable.
This will match all you need
^([1-9]|[1-5]\d|60|all)$
You are making the [1-5] optional; turn it around, like so: [1-5][0-9]?. Also you need to cover the single-digit [6-9].
The problem is that you are missing some parenthesis and you should switch the 60 and the rest, because otherwise it will only match the 6 in 60:
^((60|([1-5]?[0-9]))|all)
Related
I am trying to solve a CTF in which the juggling type should be used. The code is:
if ($_GET["hash"] == hash("ripemd160", $_GET["hash"]))
{
echo $flag;
}
else
{
echo "<h1>Bad Hash</h1>";
}
I made a script in python which checks random hashes in ripemd160 that begins with "0e" and ends with only numbers. The code is:
def id_generator(size, chars=string.digits):
return ''.join(random.choice(chars) for _ in range(size))
param = "0e"
results = []
while True:
h = hashlib.new('ripemd160')
h.update("{0}".format(str(param)).encode('utf-8'))
hashed = h.hexdigest()
if param not in results:
print(param)
if hashed.startswith("0e") and hashed[2:].isdigit():
print(param)
print(hashed)
break
results.append(param)
else:
print("CHECKED")
param = "0e" + str(id_generator(size=10))
Any suggestions on how to solve it? Thank you!
There seems to be a bit of misunderstanding in the comments, so I'll start by explaining the problem a little more:
Type juggling refers to the behaviour of PHP whereby variables are implicitly cast to different data types under certain conditions. For example, all the following logical expressions will evaluate to true in PHP:
0 == 0 // int vs. int
"0" == 0 // str -> int
"abc" == 0 // any non-numerical string -> 0
"1.234E+03" == "0.1234E+04" // string that looks like a float -> float
"0e215962017" == 0 // another string that looks like a float
The last of these examples is interesting because its MD5 hash value is another string consisting of 0e followed by a bunch of decimal digits (0e291242476940776845150308577824). So here's another logical expression in PHP that will evaluate to true:
"0e215962017" == md5("0e215962017")
To solve this CTF challenge, you have to find a string that is "equal" to its own hash value, but using the RIPEMD160 algorithm instead of MD5. When this is provided as a query string variable (e.g., ?hash=0e215962017), then the PHP script will disclose the value of a flag.
Fake hash collisions like this aren't difficult to find. Roughly 1 in every 256 MD5 hashes will start with '0e', and the probability that the remaining 30 characters are all digits is (10/16)^30. If you do the maths, you'll find that the probability of an MD5 hash equating to zero in PHP is approximately one in 340 million. It took me about a minute (almost 216 million attempts) to find the above example.
Exactly the same method can be used to find similar values that work with RIPEMD160. You just need to test more hashes, since the extra hash digits mean that the probability of a "collision" will be approximately one in 14.6 billion. Quite a lot, but still tractable (in fact, I found a solution to this challenge in about 15 minutes, but I'm not posting it here).
Your code, on the other hand, will take much, much longer to find a solution. First of all, there is absolutely no point in generating random inputs. Sequential values will work just as well, and will be much faster to generate.
If you use sequential input values, then you also won't need to worry about repeating the same hash calculations. Your code uses a list structure to store previously hashed values. This is a terrible idea. Searching for an item in a list is an O(n) operation, so once your code has (unsuccessfully) tested a billion inputs, it will have to compare every new input against each of these billion inputs at each iteration, causing your code to grind to a complete standstill. Your code would actually run a lot faster if you didn't bother checking for duplicates. When you have time, I suggest you learn when to use lists, dicts and sets in Python.
Another problem is that your code only tests 10-digit numbers, which means it can only test a maximum of 10 billion possible inputs. Based on the numbers given above, are you sure this is a sensible limit?
Finally, your code is printing every single input string before you calculate its hash. Before your program outputs a solution, you can expect it to print out somewhere in the order of a billion screenfuls of incorrect guesses. Is there any point in doing this? No.
Here's the code I used to find the MD5 collision I mentioned earlier. You can easily adapt it to work with RIPEMD160, and you can convert it to Python if you like (although the PHP code is much simpler):
$n = 0;
while (1) {
$s = "0e$n";
$h = md5($s);
if ($s == $h) break;
$n++;
}
echo "$s : $h\n";
Note: Use PHP's hash_equals() function and strict comparison operators to avoid this sort of vulnerability in your own code.
I have referred to several SO webpages for the answer to my question, but I keep reading that regex should not be used for validating numbers which are less than or greater than a certain range. I want to ensure that a user enters numbers within the following ranges: 11--20 and 65-100. Anything less than 11 will not be allowed, anything between 21 and 64 will not be allowed and anything from 101 above will not be allowed. I realize I can write something like
if ($num <=10 and $num >= 21 and $num <=64 and $num >=101) {
$num = "";
$numErr = "Number must be within specified ranges";
}
But what I really want is to use regex to preclude the range of numbers I do not want from being entered but I have not seen any satisfactory answers on SO. Can someone please help?
The regex would be less readable but like
/^(1[1-9]|20|6[5-9]|[7-9][0-9]|100)$/
Regex Demo
SCENARIO:
A) You have a charset of 100 in which the first characters are A, B, C and the last characters are -, _.
B) The encode function returns a string of length 10.
C) The encode converts a number into the correlating number in the charset
Example: A == 0 || B == 1 || C == 2 || - == 98 || _ == 99
Amount of possibilities: 100 ^ 10 = 1e+20 || 100,000 Quadrillion || 100,000,000,000 Billion.
PROBLEM: How would you figure out whether 999 is iii, _i or i_?
Note: The solution to the problem sketched above should work for every possible situation
looks like homework...
lets have a look at our problem:
999 can not be represented as a single char in our charset
we can encode it in 3 different ways
9 9 9 => I I I
99 9 => _I
9 99 => I_
now... a charset alone does not make an encoding ... at this point you should probably read up about what a "code" is ... http://en.wikipedia.org/wiki/Code
please notice that this has absolutely nothing to do with encryption ...
so ... we need a ruleset for encoding/decoding our code
since we are supposed to make that ruleset, it is our free choice how we handle things, as long as we keep in mind what other key rules we have to follow...
the code shall be 10 characters long ... at max from what i see, or else III wouldn't possibly be a valid example of our code ... AAAAAAAAIII would be ... so lets assume that we may drop leading zeros, or As in this case, and further assume that III and AAAAAAAIII are identical
now we have the given fact that our code has 100^10 possible codewords, which can only be achived if every combination of our charset with a length of 10 is a valid codeword
so all three ... III and I_ and _I ... have to be valid codewords ...
does that mean that all three have the value of 999?
short: no
long:
as mentioned earlier, there is a ruleset needed to give the code a meaning...
since there is no encoding ruleset given, we seem to be free to create one...
lets have a look at the ruleset to encode our regular base 10 numbers ...
we have a charset from 0 to 9 -> 10 digits
the position of a digit in a number contains information...
123 for example can be written as 1*10^10 + 2*10^1 + 3*10^0
if we transfer this to our new encoding ... let's call it base 100 ... it would look like this:
123 -> 1*100^1 + 23*100^0
=> 1=B ... 23=X => 123 -> BX
999 -> 9*100^1 + 99*100^0 -> I_
but who says we have to declare the left most digit in our code to be the most siginificant digit?
what if we would interpret it otherwise?
isn't 99*100^0 + 9*100^1 = 999 too?
yes ... therefore we could write it as _I too ...
which one is the correct one now? ... that ONLY depends on the ruleset of our code ... if it says the leftmost digit ist the most significant one, the answer is I_ ... if the rightmost digit ist the most significant one, the answer is _I
as long as the ruleset for the encoding is not specified, the answer to this question cannot be solved ... you can only try to make an educated guess, and use the same convention as in our "normal" base 10 encoding ... leftmost digit = most significant digit -> I_
but please keep in mind ... this is a guess ... if i'd get such a question in a test, i'd explain why there is no answer unless the encoding rules have been specified.
tldr:
with the provided information, it's a free choice if it is i_ or _i
I need to check that a string
contains only digits and
the first digit is 0, and
the whole string has at least 8 digits and maximum 25
I have tried this, but it doesn't work:
if (!preg_match('/^[0][0-9]\d{8-25}$/', $ut_tel))
Try this regex:
/^0\d{7,24}$/
It seemed to work here.
Use this regex pattern
^(0[0-9]{7,24})$
Demo
If I was you, I'd do each check separately. This way you won't have issues in the future, should you decide to remove one of them or add additional checks.
(Note to all potential downvoters: I realize the question asked for a regex way, but since that was already provided in other answers - I think it is good to have a different approach as an answer as well.)
function validateNumber($number){
if(!is_numeric($number))
return false;
if(strlen($number)>25 || strlen($number)<8)
return false;
if(substr($number, 0, 1) != 0)
return false;
return true;
}
var_dump(validateNumber('0234567')); // shorter than 8
var_dump(validateNumber('02345678')); // valid
var_dump(validateNumber('12345678')); // doesn't start with 0
var_dump(validateNumber('02345678901234567890123456')); // longer than 25
So I am trying to add a decimal point in front of a whole in (10) The issue is I'm trying to use sprintf(); but it seems to not be working for me :(.
Code:
sprintf(".",($percentamount));
Let me know what I am doing wrong thanks!
I have already tried "%.f"
if i understand you correctly you will take $percentamount variable which have to contain 10 as its value and just put '.' in front of it to make string '0.1' out of it - is it right? If yes than you could take 10 as digit and place it within a string as follows:
sprintf('.%d', 10); // %d stands for digit and means digit should be your second parameter
if you want to have 10 as string input you could write it as follows:
sprintf('.%s', '10');
if it is not the solution you looking for please describe it better and i'll try to help