Skip to content

Commit 1faae5c

Browse files
committed
Updates php/challenge-90.md
Auto commit by GitBook Editor
1 parent 395f0e6 commit 1faae5c

16 files changed

+253
-4
lines changed

SUMMARY.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,20 @@
8080
* [Challenge 74](php/challenge-74.md)
8181
* [Challenge 75](php/challenge-75.md)
8282
* [Challenge 76](php/challenge-76.md)
83-
* Challenge 77
83+
* [Challenge 77](php/challenge-77.md)
8484
* [Challenge 78](php/challenge-78.md)
8585
* [Challenge 79](php/challenge-79.md)
8686
* [Challenge 80](php/challenge-80.md)
87+
* [Challenge 81](php/challenge-81.md)
88+
* [Challenge 82](php/challenge-82.md)
89+
* [Challenge 83](php/challenge-83.md)
90+
* [Challenge 84](php/challenge-84.md)
91+
* [Challenge 85](php/challenge-85.md)
92+
* [Challenge 86](php/challenge-86.md)
93+
* [Challenge 87](php/challenge-87.md)
94+
* [Challenge 88](php/challenge-88.md)
95+
* [Challenge 89](php/challenge-89.md)
96+
* [Challenge 90](php/challenge-90.md)
8797

8898
## RUBY
8999

php/challenge-75.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,45 @@
11
# Challenge
22
```php
3+
class Template {
4+
public $cacheFile = '/tmp/cachefile';
5+
public $template = '<div>Welcome back %s</div>';
36

7+
public function __construct($data = null) {
8+
$data = $this->loadData($data);
9+
$this->render($data);
10+
}
11+
12+
public function loadData($data) {
13+
if (substr($data, 0, 2) !== 'O:'
14+
&& !preg_match('/O:\d:\/', $data)) {
15+
return unserialize($data);
16+
}
17+
return [];
18+
}
19+
20+
public function createCache($file = null, $tpl = null) {
21+
$file = $file ?? $this->cacheFile;
22+
$tpl = $tpl ?? $this->template;
23+
file_put_contents($file, $tpl);
24+
}
25+
26+
public function render($data) {
27+
echo sprintf(
28+
$this->template,
29+
htmlspecialchars($data['name'])
30+
);
31+
}
32+
33+
public function __destruct() {
34+
$this->createCache();
35+
}
36+
}
37+
38+
new Template($_COOKIE['data']);
439
```
540

641
# Solution
42+
This challenge contains an PHP object injection vulnerability. In line 13 an attacker is able to pass user input into the unserialize() function by altering his cookie data. There are two checks in line 11 and 12 that try to prevent the deserialization of objects. The first check can be easily circumvented, for example by injecting an object into an array, leading to a payload string beginning with a:1: instead of O:. The second check can be bypassed by abusing PHP's flexible serialization syntax. It is possible to use the syntax O:+1: to bypass this regex. Finally, this means an attacker can inject an object of class Template into the application. After the serialized form is deserialized and the Template object is instantiated, its destructor is called when the script terminates (line 31). Now, the attacker controlled properties cacheFile and template of the injected object are used to write to a file in line 21. Thus, the attacker can create arbitraries files on the file system, for example a PHP shell in the document root: a:1:{i:0;O:%2b8:"Template":2:{s:9:"cacheFile";s:14:"/var/www/a.php";s:8:"template";s:16:"<?php%20phpinfo();";}} More information about this attack can be found in our blog posts.
743

844
# Refference
9-
+ php-security-calendar-2017
45+
+ php-security-calendar-2017 Day 11 - Pumpkin Pie

php/challenge-76.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
# Challenge
22
```php
3+
$sanitized = [];
34

5+
foreach ($_GET as $key => $value) {
6+
$sanitized[$key] = intval($value);
7+
}
8+
9+
$queryParts = array_map(function ($key, $value) {
10+
return $key . '=' . $value;
11+
}, array_keys($sanitized), array_values($sanitized));
12+
13+
$query = implode('&', $queryParts);
14+
15+
echo "<a href='/images/size.php?" .
16+
htmlentities($query) . "'>link</a>";
417
```
518

619
# Solution
20+
There is a cross-site scripting vulnerability in line 13. This bug depends on the fact that the keys of the $_GET array (the GET parameter names) are not sufficiently sanitized in the code. Both the keys and the sanitized GET values are passed to the href attribute of the <a> tag as a concatenated string. The sanitizer htmlentities() is used, however, single quotes are not affected by default by this built-in function. Hence, an attacker is able to perform an XSS attack against the user, for example using the following query parameter that breaks the href attribute and appends an eventhandler with JavaScript code: /?a'onclick%3dalert(1)%2f%2f=c. Note that the payload is within the parameter name, not the parameter value.
721

822
# Refference
9-
+ php-security-calendar-2017
23+
+ php-security-calendar-2017 Day 12 - String Lights

php/challenge-77.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Challenge
2+
```php
3+
class LoginManager {
4+
private $em;
5+
private $user;
6+
private $password;
7+
8+
public function __construct($user, $password) {
9+
$this->em = DoctrineManager::getEntityManager();
10+
$this->user = $user;
11+
$this->password = $password;
12+
}
13+
14+
public function isValid() {
15+
$user = $this->sanitizeInput($this->user);
16+
$pass = $this->sanitizeInput($this->password);
17+
18+
$queryBuilder = $this->em->createQueryBuilder()
19+
->select("COUNT(p)")
20+
->from("User", "u")
21+
->where("user = '$user' AND password = '$pass'");
22+
$query = $queryBuilder->getQuery();
23+
return boolval($query->getSingleScalarResult());
24+
}
25+
26+
public function sanitizeInput($input, $length = 20) {
27+
$input = addslashes($input);
28+
if (strlen($input) > $length) {
29+
$input = substr($input, 0, $length);
30+
}
31+
return $input;
32+
}
33+
}
34+
35+
$auth = new LoginManager($_POST['user'], $_POST['passwd']);
36+
if (!$auth->isValid()) {
37+
exit;
38+
}
39+
```
40+
41+
# Solution
42+
Today's challenge contains a DQL (Doctrine Query Language) injection vulnerability in line 19. A DQL injection is similar to a SQL injection but more limited, nonetheless the where() method of Doctrine is vulnerable. In line 13 and 14 sanitization is added to the input, however, the sanitizeInput() method has a bug. First, it uses addslashes() for escaping relevant characters by adding a backslash \ infront of them. In this case if we pass a \ as input, it get escaped to \\. But then, the substr() function is used to truncate the escaped string. This enables an attacker to send a string that is long enough that the escaped backslash is cut off and we are left with a single \ at the end of the string. This will then break the WHERE statement and allows the injection of own DQL syntax, for example the condition OR 1=1 that is always true and bypasses the authentication: user=1234567890123456789\&passwd=%20OR%201=1-. The resulting WHERE statement will look like user = '1234567890123456789\' AND password = ' OR 1=1-' in DQL. Note how the backslash confuses the quotes and allows to inject DQL into the password value. The resulting query does not look valid because of the trailing slash. Fortunately, Doctrine closes the last single quote on its own, so the resulting query looks like OR 1=1-''.
43+
To avoid DQL injections always use bound parameters for dynamic conditions. Never try to secure a DQL query with addslashes() or similar functions. Additionally, the password should be stored hashed in the database, for example in the BCrypt format.
44+
45+
# Refference
46+
+ php-security-calendar-2017 Day 13 - Turkey Baster

php/challenge-78.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Challenge
2+
```php
3+
class Carrot {
4+
const EXTERNAL_DIRECTORY = '/tmp/';
5+
private $id;
6+
private $lost = 0;
7+
private $bought = 0;
8+
9+
public function __construct($input) {
10+
$this->id = rand(1, 1000);
11+
12+
foreach ($input as $field => $count) {
13+
$this->$field = $count++;
14+
}
15+
}
16+
17+
public function __destruct() {
18+
file_put_contents(
19+
self::EXTERNAL_DIRECTORY . $this->id,
20+
var_export(get_object_vars($this), true)
21+
);
22+
}
23+
}
24+
25+
$carrot = new Carrot($_GET);
26+
```
27+
28+
# Solution
29+
30+
# Refference
31+
+ php-security-calendar-2017 Day 14 - Snowman

php/challenge-79.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
# Challenge
22
```php
3+
class Redirect {
4+
private $websiteHost = 'www.example.com';
35

6+
private function setHeaders($url) {
7+
$url = urldecode($url);
8+
header("Location: $url");
9+
}
10+
11+
public function startRedirect($params) {
12+
$parts = explode('/', $_SERVER['PHP_SELF']);
13+
$baseFile = end($parts);
14+
$url = sprintf(
15+
"%s?%s",
16+
$baseFile,
17+
http_build_query($params)
18+
);
19+
$this->setHeaders($url);
20+
}
21+
}
22+
23+
if ($_GET['redirect']) {
24+
(new Redirect())->startRedirect($_GET['params']);
25+
}
426
```
527

628
# Solution
729

830
# Refference
9-
+ php-security-calendar-2017
31+
+ php-security-calendar-2017 Day 15 - Sleigh Ride

php/challenge-81.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Challenge
2+
```php
3+
4+
```
5+
6+
# Solution
7+
8+
# Refference
9+
+ php-security-calendar-2017

php/challenge-82.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Challenge
2+
```php
3+
4+
```
5+
6+
# Solution
7+
8+
# Refference
9+
+ php-security-calendar-2017

php/challenge-83.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Challenge
2+
```php
3+
4+
```
5+
6+
# Solution
7+
8+
# Refference
9+
+ php-security-calendar-2017

php/challenge-84.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Challenge
2+
```php
3+
4+
```
5+
6+
# Solution
7+
8+
# Refference
9+
+ php-security-calendar-2017

0 commit comments

Comments
 (0)