Jump to content

A new way of web development in LAMP(Linux, Apache,Mysql,Php) technology


Recommended Posts

Posted (edited)

That was code injected to run on your site.

 

Code Injection

 

post something like:

<?php  "<span><font color="red" size="20">Owned</font></span>" ?>

into the name field and click "Send Message".

 

Your approach is unsafe as everyone has been trying to tell you.

Edited by Endy0816
Posted (edited)

That was code injected to run on your site.

 

Code Injection

 

post something like:

<?php  "<span><font color="red" size="20">Owned</font></span>" ?>

into the name field and click "Send Message".

 

Your approach is unsafe as everyone has been trying to tell you.

You are a foolish one. In message section what ever you want you could add, it may be html, php, css , what ever you want. My system is still safe. Although i did not put safe guard , its a different side.

What you are trying to show , you are a great hacker?

See maan, if you dont have interest , please dont disturb here.

I am here to show you all some thing.

 

Look here:

post-103722-0-53713700-1395031239_thumb.png

post-103722-0-13843900-1395031338_thumb.png

Edited by Samiul Haque
Posted (edited)

As i have already posted a different way to write the code in your sample, i see no reason to redo work (albeit a small amount).

 

Here's the first problem that i can think there is a good chance of runing into with your model.

 

Suppose i am serving a site where suppose i need to serve multiple forms, for example if you want to use one form to collect and handle files specifically, and the second form to capture some other information. Lets say form definitions are passed to me from the designers in like a json, so that should make it easy to build a function for building forms. The challenge is that sometimes the forms are served by themselves, but they are also served together, so that depends on some state somewhere. Now here's a problem. (see pseudo-code)

// Definitions
$form = 'form generator';
 
$file_form_definition = 'file form definition';
$user_form_definition = 'user form definition';
 
// Forms
$file_form = 'form_generator($file_form_definition);'.$form;
$user_form = 'form_generator($user_form_definition);'.$form
// Other forms defined here
 
// Sometime later when we are deciding what to serve for HTML
switch($page){
case 1:
?>
<h2>Files</h2>
<?php echo eval($file_form); ?>
<h2>User Info</h2>
<?php echo eval($user_form); ?>
<?php
break;
case 2:
?>
<h2>Files</h2>
<?php echo eval($file_form); ?>
<?php
break;
case 3:
?>
<h2>User Info</h2>
<?php echo eval($user_form); ?>
<!-- And so forth -->
<?php 
}

I believe that i am following your model pretty closely, correct me if i made a mistake model-wise, but of course this pseudo-code runs into a problem, so how do you suggest resolving it?

Edited by AtomicMaster
Posted

I was trying to show you that your site could be quite trivially hacked. I don't like doing permanent damage myself, but there are many others who think differently.

 

That was the same basic method used in a number of cross site scripting attacks on major companies. You get a user to run your code on top of the site's and proceed to steal their information.

 

Do some penetration testing, look at the online resources available on the subject, maybe even try a few "Hack this site" challenges. At the very least you would have a better understanding of the risks you are recommending others take.

Posted

I was trying to show you that your site could be quite trivially hacked. I don't like doing permanent damage myself, but there are many others who think differently.

 

That was the same basic method used in a number of cross site scripting attacks on major companies. You get a user to run your code on top of the site's and proceed to steal their information.

 

Do some penetration testing, look at the online resources available on the subject, maybe even try a few "Hack this site" challenges. At the very least you would have a better understanding of the risks you are recommending others take.

See , no site in the world is 100% hacker safe. Besides it we could add some penetration preventing code that will save primarily.

And I am not expert of this side, its the task of others. Here I want to show you an approach that may help web developer for certain type of task. Thats it.

And protecting the site is the job of others.

I am really happy that you gave time and showed whats the wrong side of it although i was aware before of that but its not a great deal to get ride of it.

Thank you Endy

As i have already posted a different way to write the code in your sample, i see no reason to redo work (albeit a small amount).

 

Here's the first problem that i can think there is a good chance of runing into with your model.

 

Suppose i am serving a site where suppose i need to serve multiple forms, for example if you want to use one form to collect and handle files specifically, and the second form to capture some other information. Lets say form definitions are passed to me from the designers in like a json, so that should make it easy to build a function for building forms. The challenge is that sometimes the forms are served by themselves, but they are also served together, so that depends on some state somewhere. Now here's a problem. (see pseudo-code)

// Definitions
$form = 'form generator';
 
$file_form_definition = 'file form definition';
$user_form_definition = 'user form definition';
 
// Forms
$file_form = 'form_generator($file_form_definition);'.$form;
$user_form = 'form_generator($user_form_definition);'.$form
// Other forms defined here
 
// Sometime later when we are deciding what to serve for HTML
switch($page){
case 1:
?>
<h2>Files</h2>
<?php echo eval($file_form); ?>
<h2>User Info</h2>
<?php echo eval($user_form); ?>
<?php
break;
case 2:
?>
<h2>Files</h2>
<?php echo eval($file_form); ?>
<?php
break;
case 3:
?>
<h2>User Info</h2>
<?php echo eval($user_form); ?>
<!-- And so forth -->
<?php 
}

I believe that i am following your model pretty closely, correct me if i made a mistake model-wise, but of course this pseudo-code runs into a problem, so how do you suggest resolving it?

I will write code for you. Just write me some lines what you want to accomplish , and seeing your requirement, i will write complete php, css, html code for you. So that it will help you clearly to understand. Go it ?

Posted (edited)

See , no site in the world is 100% hacker safe.

 

But most try to be pretty close.

 

Besides it we could add some penetration preventing code that will save primarily.

 

Problem here is 2-fold.

First problem is that there are unnecessary risks that are exposed by the way that your code is written. Evaluating user input is a very error-prone endeavor, and for any complex website (you mentioned thousands of lines of code, thats a pretty much a very small project, tools i write often fall in that range, most actual projects i work on involve order(s) of magnitude more code) where there are multiple people developing in parallel, working on multiple parts of the project, with every user input, having a potential to be exploited.

Second problem is a computer-science one. Most typical example is 2 ways to approach a firewall rule-set. You can have a deny unless open set, where the firewall specifically opens ports with the bottom governing rule being deny all, and a open unless denied set, where you deny specific ports with a bottom rule that allows all. So the problem with "we could add some prevention code" is that you have an open unless denied system, which when mapped to Godels' incompleteness theorem, states that there is always potential for some input that will bypass "prevention code" and will still be interpreted by as code by PHP (or JS or SQL)... Because you don't maintain a clear Code/Data separation the second you eval.

 

 

And I am not expert of this side, its the task of others.

 

No you are not an expert, but it is NOT the task of others. It is YOUR primary duty as a programmer to provide a safe and secure environment for the people who are to use it. Since you are proposing a design paradigm, you have to think about how one using your development paradigm could provide a safe and secure environment for their users; really poor security is almost always the result of an afterthought. We have already outlined multiple ways in which your way of executing server-side code is insecure, you have yet to provide an actual solution. So why would anyone want to write code in a paradigm that is inherently insecure and has no defined ways, no solutions to make it secure?

 

Here I want to show you an approach that may help web developer for certain type of task. Thats it.

 

So what you provided was a way to fix a "service can not access file a" issue with a "just run the service as root" solution...

 

i will write complete php, css, html code for you. So that it will help you clearly to understand. Go it ?

 

Why waste the time? I am quite ok with some pseudo code, I highly doubt that you can express something in code that you can't express in pseudo-code. I do not have a use for the code, i mean unless you do.

Edited by AtomicMaster
Posted (edited)

@AtomicMaster, Yes, thats a talking of real programmer..I am expecting it from long time thats why I posted my approach to this science forum.

I am 100% agree with you and what you have discussed here.

But again, i believe , if we get some facility from some thing , then we of course have to sacrifice some thing for it.

 

Here I have just showed a way............so if any one got interested on it then he may add his effort to remove the drawbacks of it. I cant alone change the world. I need all of you so that we could do something for computer science world.

 

Now I am writing complete code for you. Look the post below.

 

<?php
/*
* Please copy and paste and execute the following code
*/

/*Look, form_generator_file and form_generator_usr are complete pages that has all properties of a PHP page
* that means it could contain everything a php page may contain.
* the variable $form hold the code of the page.
* So if I echo the variable $form , you will see it will print the code.
* But if you want to execute it , you need to use eval().
*
*/

$form = '
//page 1
function form_generator_file($form_defination = "")
{
$to_day = @date("m/d/y");
?>

<div style="border: #ff0000 solid 1px;">
<span>Today:</span> <span><?php echo $to_day;?></span>
<p style="background-color:#404040; ">File: <?php echo $form_defination;?></p>
</div>

<?php
}
?>
';

$form_usr = '
//page2
function form_generator_usr($form_defination = "")
{
$to_day = @date("m/d/y");
?>
<style>
div{
font-size:12pt;
background-color:#bcbcbc;
color:#fff;
width:50%;
}
</style>
<div style="border: #ff0000 solid 1px;">
<span>Today:</span> <span><?php echo $to_day;?></span>
<p style="background-color:#404040; ">User : <?php echo $form_defination;?></p>
</div>

<?php
}
?>
';
?>

<html>
<style>
span{
font-weight: bolder;
}
p{
color:#fff;
}
</style>
<body>
<?php
$file_form_definition = "file form definition";
$user_form_definition = "user form definition";
?>


<?php
$page = 1;
switch($page){
case 1:
?>
<h2>Files</h2>
<?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
<h2>User Info</h2>
<?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
<?php
break;
case 2:
?>
<h2>Files</h2>
<?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
<?php
break;
case 3:
?>
<h2>User Info</h2>
<?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
<!-- And so forth -->
<?php
}?>
</body>
</html>

Edited by Samiul Haque
Posted

!

Moderator Note

Samiul Haque,

 

Comments such as this:

 


@AtomicMaster: oh my God! , I thought you are expert of php but now its clear you dont know any thing, and even php language grammer.

And I think you should go throughly about the manual of PHP eval().

 

Do not fly here. Refrain from insulting other members in your posts and if you could, please educate yourself on the use of the quote function.

Posted

!

Moderator Note

We encourage everyone to remember that the methodology described in this thread is controversial, and does NOT have the kind of support from our membership that the title might imply.

 

Please take all necessary precautions when taking advice over the internet about medicine and computers. Codeine and coding are both potentially dangerous.

Posted

What is your aversion to using normal functions and maintaining code/data barrier?

You also didn't solve the problem i outlined above and abstracted it away...

 

Also by the way, your code:

<?php
/*
 * Please copy and paste and execute the following code
 */

/*Look, form_generator_file and form_generator_usr are complete pages that has all properties of a PHP page
 * that means it could contain everything a php page may contain.
 * the variable $form hold the code of the page.
 * So if I echo  the variable $form , you will see it will print the code.
 * But if you  want to execute it , you need to use eval().
 *
 */

$form = '
    //page 1
function form_generator_file($form_defination = "")
{
 $to_day = @date("m/d/y");
?>

<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day;?></span>
    <p style="background-color:#404040; ">File: <?php echo $form_defination;?></p>
</div>
    
<?php
}
?>
';

$form_usr = '
    //page2
function form_generator_usr($form_defination = "")
{
 $to_day = @date("m/d/y");
?>
<style>
div{
    font-size:12pt;
    background-color:#bcbcbc;
    color:#fff;
    width:50%;
}
</style>
<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day;?></span>
    <p style="background-color:#404040; ">User : <?php echo $form_defination;?></p>
</div>
    
<?php
}
?>
';
?>

<html>
    <style>
        span{
            font-weight: bolder;           
        }
        p{
            color:#fff;
        }
    </style>
    <body>
        <?php
            $file_form_definition = "file form definition";
            $user_form_definition = "user form definition";
        ?>
        
        
        <?php
        $page = 1;
        switch($page){
            case 1:
            ?>
            <h2>Files</h2>
            <?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
            <h2>User Info</h2>
            <?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
            <?php
            break;
            case 2:
            ?>
            <h2>Files</h2>
            <?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
            <?php
            break;
            case 3:
            ?>
            <h2>User Info</h2>
            <?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
            <!-- And so forth -->
            <?php
            }?>
    </body>
</html>

could just as effectively be written as

<?php
/*
 * Please copy and paste and execute the following code
 */

/*Look, form_generator_file and form_generator_usr are complete pages that has all properties of a PHP page
 * that means it could contain everything a php page may contain.
 * the variable $form hold the code of the page.
 * So if I echo  the variable $form , you will see it will print the code.
 * But if you  want to execute it , you need to use eval().
 *
 */

function form_generator_file($form_defination = "")
{
 $to_day = @date("m/d/y");
?>

<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day; ?></span>
    <p style="background-color:#404040; ">File: <?php echo $form_defination; ?></p>
</div>
    
<?php
}

function form_generator_usr($form_defination = "")
{
 $to_day = @date("m/d/y");
?>
<style>
div{
    font-size:12pt;
    background-color:#bcbcbc;
    color:#fff;
    width:50%;
}
</style>
<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day; ?></span>
    <p style="background-color:#404040; ">User : <?php echo $form_defination; ?></p>
</div>
    
<?php
}

$file_form_definition = "file form definition";
$user_form_definition = "user form definition";

?>

<html>
    <style>
        span{
            font-weight: bolder;           
        }
        p{
            color:#fff;
        }
    </style>
    <body>        

        <?php
        $page = 1;
        switch($page){
            case 1:
            ?>
            <h2>Files</h2>
            <?php form_generator_file($file_form_definition); ?>
            <h2>User Info</h2>
            <?php form_generator_usr($user_form_definition); ?>
            <?php
            break;
            case 2:
            ?>
            <h2>Files</h2>
            <?php form_generator_file($file_form_definition); ?>
            <?php
            break;
            case 3:
            ?>
            <h2>User Info</h2>
            <?php form_generator_usr($user_form_definition); ?>
            <!-- And so forth -->
            <?php
            }?>
    </body>
</html>

And this maintains code/data separation in PHP, also plays a lot better with syntax highlighting (as i don't have any sections of php defined as a string).

 

So i don't know what problem you are trying to solve with eval, but i know for sure that it does not require eval to be solved.

 

Again in the words of the creator of PHP

 

If eval() is the answer, you're almost certainly asking the wrong question.

-- Rasmus Lerdorf

 

Posted

What is your aversion to using normal functions and maintaining code/data barrier?

You also didn't solve the problem i outlined above and abstracted it away...

 

Also by the way, your code:

<?php
/*
 * Please copy and paste and execute the following code
 */

/*Look, form_generator_file and form_generator_usr are complete pages that has all properties of a PHP page
 * that means it could contain everything a php page may contain.
 * the variable $form hold the code of the page.
 * So if I echo  the variable $form , you will see it will print the code.
 * But if you  want to execute it , you need to use eval().
 *
 */

$form = '
    //page 1
function form_generator_file($form_defination = "")
{
 $to_day = @date("m/d/y");
?>

<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day;?></span>
    <p style="background-color:#404040; ">File: <?php echo $form_defination;?></p>
</div>
    
<?php
}
?>
';

$form_usr = '
    //page2
function form_generator_usr($form_defination = "")
{
 $to_day = @date("m/d/y");
?>
<style>
div{
    font-size:12pt;
    background-color:#bcbcbc;
    color:#fff;
    width:50%;
}
</style>
<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day;?></span>
    <p style="background-color:#404040; ">User : <?php echo $form_defination;?></p>
</div>
    
<?php
}
?>
';
?>

<html>
    <style>
        span{
            font-weight: bolder;           
        }
        p{
            color:#fff;
        }
    </style>
    <body>
        <?php
            $file_form_definition = "file form definition";
            $user_form_definition = "user form definition";
        ?>
        
        
        <?php
        $page = 1;
        switch($page){
            case 1:
            ?>
            <h2>Files</h2>
            <?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
            <h2>User Info</h2>
            <?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
            <?php
            break;
            case 2:
            ?>
            <h2>Files</h2>
            <?php echo eval("form_generator_file(\"$file_form_definition\");".$form); ?>
            <?php
            break;
            case 3:
            ?>
            <h2>User Info</h2>
            <?php echo eval("form_generator_usr(\"$user_form_definition\");".$form_usr); ?>
            <!-- And so forth -->
            <?php
            }?>
    </body>
</html>

could just as effectively be written as

<?php
/*
 * Please copy and paste and execute the following code
 */

/*Look, form_generator_file and form_generator_usr are complete pages that has all properties of a PHP page
 * that means it could contain everything a php page may contain.
 * the variable $form hold the code of the page.
 * So if I echo  the variable $form , you will see it will print the code.
 * But if you  want to execute it , you need to use eval().
 *
 */

function form_generator_file($form_defination = "")
{
 $to_day = @date("m/d/y");
?>

<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day; ?></span>
    <p style="background-color:#404040; ">File: <?php echo $form_defination; ?></p>
</div>
    
<?php
}

function form_generator_usr($form_defination = "")
{
 $to_day = @date("m/d/y");
?>
<style>
div{
    font-size:12pt;
    background-color:#bcbcbc;
    color:#fff;
    width:50%;
}
</style>
<div style="border: #ff0000 solid 1px;">
    <span>Today:</span> <span><?php echo $to_day; ?></span>
    <p style="background-color:#404040; ">User : <?php echo $form_defination; ?></p>
</div>
    
<?php
}

$file_form_definition = "file form definition";
$user_form_definition = "user form definition";

?>

<html>
    <style>
        span{
            font-weight: bolder;           
        }
        p{
            color:#fff;
        }
    </style>
    <body>        

        <?php
        $page = 1;
        switch($page){
            case 1:
            ?>
            <h2>Files</h2>
            <?php form_generator_file($file_form_definition); ?>
            <h2>User Info</h2>
            <?php form_generator_usr($user_form_definition); ?>
            <?php
            break;
            case 2:
            ?>
            <h2>Files</h2>
            <?php form_generator_file($file_form_definition); ?>
            <?php
            break;
            case 3:
            ?>
            <h2>User Info</h2>
            <?php form_generator_usr($user_form_definition); ?>
            <!-- And so forth -->
            <?php
            }?>
    </body>
</html>

And this maintains code/data separation in PHP, also plays a lot better with syntax highlighting (as i don't have any sections of php defined as a string).

 

So i don't know what problem you are trying to solve with eval, but i know for sure that it does not require eval to be solved.

 

Again in the words of the creator of PHP

 

-- Rasmus Lerdorf

 

The way you are showings its perfect.

but if i want the above 3 case condition and i have to use only two <h2> tag in html body instead of using 4 <h2> tag (that you use ) in different cases and want the same out put that your code printing now then how will you do that?

 

lets say:

 

<?php

-

-

-

-

your php code

 

?>

 

<html>

<body>

<h2>Files</h2>

<?php //your code?>

<h2>User Info</h2>

<?php //your code?>

 

</body>

</html>

 

and i want the same out put after changing $page value(1/2/3).

Please write the code in your way.

Posted

WAT? I have no idea what you are asking...

I just barely changed your code to not use eval. This is not how i would write this at all most likely...

I know using eval is not good. But in real world , means when we had to deal with big project and need to create dynamic page then this eval is only the solution.

 

Now come to the prob:

 

when we put different value to $page then according to its value "case" will match , right ? then the code within that case statement will be executed.

What you have done, you put <h2> tag to all case statement, but in reality we likely to use <h2> only once , not put every time under all case block.

 

You are continuously trying to show that, it could be written with out eval but you did not ever try to understand why i have used it.

I have already created 2 big project with this approach and its running successfully and serving very good.

 

Its my bad luck that am not able to make understand the world what i want to share with them. And even the creator does not know how a powerful thing he has created.

We the software engineer who works on real project always want to use HTML only once, not multiple time. The php section will be used as much as possible.

Good luck my friend. Hope one day you will understand what i wanna tried to make you all understand.

Posted

But in real world , means when we had to deal with big project and need to create dynamic page then this eval is only the solution.

 

Nonsense. We have given to you alternative solutions. And you completely ignored them. You showed that discussion with you is waste of time, and pointless.

Mine the biggest PHP project have 222 KB of pure PHP code (no comments). With the main index.php with size 177 KB (6000 rows of code).

And there was just one <?php and beginning and one ?> and the end. Everything generated dynamically.

No single reason to use such silly function as eval() I have found in mine entire life.

In your example you should be echo-ing, or printf-ing from php code instead of constantly switching back and forth between php and html.

What you earned on lack of echo "", you will lose on writing <?php and then ?> and code will look like a crap, unreadable.

 

Other example. You can have f.e.

 

function web_begin($params="")

{

?>

<html><head>...</head><body><div>....

<?php

}

 

function web_end()

{

?>

</div></body></html>

<?php

}

 

or if some wants (like me):

 

function web_begin($params="")

{

printf( "<html><head>...</head><body><div>...." );

}

 

function web_end()

{

printf( "</div></body></html>" );

}

 

(It doesn't matter how it's implemented (good old OOP black-boxing idea at work) )

 

Then call

 

web_begin();

[...]

web_end();

 

from one or multiple index.php, article.php etc.

and changes to these two functions will have effect in entire website instantly.

You don't have to worry how functions were implemented.

 

The same with generation of common elements. Instead of repeating <h2>File Info</h2> multiple times, make function which is generating it. Then call just function. Then change to that function will have effect in entire website, without having to rewrite everything in multiple places! That's how most of people are making multi language websites on the world. Strings are loaded from external file (or php script with right suffix strings_en.php for English, strings_it.php for Italian etc), and found by their identifiers. So code would actually looks like f.e.:

 

function file_info()

{

printf( "<h2>%s</h2>, $strings[ 'FileInfo' ] );

}

 

What is source of definition that you are executing in eval()?

Is it loaded from external file?

Is it loaded from SQL database record?

If it's hardcoded in script like in examples that you gave, there is no single good reason to use eval()..

 

If you need to execute code that's unknown at building website stage you can create temp file.

http://pl.php.net/manual/pl/function.tmpfile.php

Then write php code there, loaded from HTML GET/POST.

And from code execute require_once($tempfile);

Then delete file.

But such techniques are for home made websites for yourself.

Hacker would immediately utilize it in public available website.

Posted (edited)

one thing you all people kept in your mind that eval is bad, but you never tried to see the good side of it. I dont wanna argue with any one.

I could only give to thanks AtomicMaster that at least he has tried to go to deep of it before commenting. And none other than he did ever try to look into it from different angle. I never said this is the solution of every problem , but in certain type of project this is really helpful. As i got it thats why i wanna share with you people.

 

@Sensei before commenting and making any thing worthless please try to understand first what it is ...... then comment like what AtomicMaster did.

Knowing his(AtomicMaster) question and comments i could understand clearly that he has at least tried to understand and went throughly in deep of it .

 

I am sorry to say you(@Sensei) that i will be honored if you keep yourself away from my post.

 

@AtomicMaster : I am happy to discuss with you so if you have any more question then please ask .

 

Thank you all

Edited by Samiul Haque
Posted

Samiul, you have not answered the questions i have asked, namely how do you deal with separate form builders that use the same underlying function to build code if you eval code, how do you deal with syntax highlighting in the strings, and lastly how do you deal with securing your code once you blur data/code barrier.

 

Also what's a "big project" for you?

Personally something within 4000 lines of code is what i often write for a tool, often as a relatively quick exercise, most of my web-based projects are within 50k lines of code, and most of the "big project"s i have worked on had in excess of 500k LOC where my commits can exceede a tool's worth of code. And i work on projects typically in a group of up to 8 people. If you work on projects that exceed that, perhaps i am not understanding something. The only thing I can say from my experience is that no matter how you spin it, eval always makes code a lot less manageable. It only introduces new headaches and issues which complicate usually already-complicated code. Furthermore it decreases inherent security, makes the evaluable code unreadable because syntax highlighting highlights the whole string as a string, and as soon as you add some ability for someone to push code to a database, now you cant even grep for whatever you need to find in a project. These are all unnecessary headaches that can be avoided with good design.

 

Eval has no good side, it is an extremely dangerous mechanism that must be avoided at all cost, it is ok to use it only when no other option is available and it must be very carefully tamed. As i have shown time and time again options that are available this is not the "no other option exists" use. Here is some sample code where while I wont claim it shows the "good side" of eval, but at least in this code i wrote a few years ago, i could not find any other way to approach the solution, thus i had no choice but to use it. I was working on some research, so this is unpolished, but still:

/*
Explanation:
Before inline interpolation (example from Mike Samuel):
 
$stmt = $db->prepare(   'I met a ? in the ? who had a ? full of ?.  He said'
.' "Hello, ?, How are you today\?"  "Fine," I replied'
.' "but I can't seem to find my ?."  "Hmm," he said.'
.' "I Can\'t help you with that."  "How about ? ? to'
.' make you feel ?\?"');
$stmt->bind_param("sssssiss", $profession, $landmark, $container, $species_of_monkey, $proper_name, $common_household_item, $some_number, $beverage, $state_of_mind);
 
It is secure, but its as much of a pain to read as it is to write...
 
But what if we could just say
$db->query(     'I met a ^^profession in the ^^landmark who had a ^^container full of ^^species_of_monkey.  He said'
.' "Hello, ^^proper_name, How are you today\?"  "Fine," I replied'
.' "but I can't seem to find my ^^common_household_item."  "Hmm," he said.'
.' "I Can\'t help you with that."  "How about ^^number ^^beverage to'
.' make you feel ^^state_of_mind\?"');
and still be secure without adding anything that we don't already have (like b64d function in mysql)? well, we can 
In addition to determining and passing data and query via separate channels, if someone tries to inline inject strings into the code or something in the query, it will fail.

*/
 
// An attempt at forcing developers to use secure string interpolation in mysql queries with some integrated caching and direct csv output.
class SSIMysqli extends mysqli
{
  // Members
  protected static $mysqli;
  protected $memcache=false, $result=false, $bind_arr=array(), $row=0, $data=null, $key=null, $vars=null;
  
  // Private Methods
  private function clean($vars) {
    $clean = array('GLOBALS', 'argc', 'argv', '_GET', '_POST', '_COOKIE', '_FILES', '_SERVER');
    foreach($clean as $key) {
      if(@array_key_exists($key, $vars)) { unset($vars[$key]); }
    }
    return $vars;
  }
  
  private function output_csv(&$vals, $key, $stream) { fputcsv($stream, $vals, ',', '"'); }
  
  //Public Methods
  public function __construct($db = MYSQLI_DB, $host = MYSQLI_HOST, $user = MYSQLI_USER, $pass = MYSQLI_PASS, $port = MYSQLI_PORT, $mhost = MEM_SERVER, $mport = MEM_PORT, $mtime = MEM_TIMEOUT, $mctime = MEM_CONNECT_TIMEOUT, $mrtime = MEM_RETRY_TIMEOUT, $mcomp = MEM_COMPRESSION)
  {
    parent::__construct($host, $user, $pass, $db, $port);
    if(mysqli_connect_errno()) {
      error_log("Could not connect to database! Repent! The end is neigh!");
      die();
    }
    if(extension_loaded('memcached.so') && $mtime != 0){
      $this->memcache = new Memcached();
      if (!$this->memcache->addServer($mhost, $mport)) {
        error_log('Could not connect to MemCache server');
        $obj = false;
      }
      else {
        $this->memcache->setOption(Memcached::OPT_CONNECT_TIMEOUT, $mctime); // connection timeout in milliseconds
        $this->memcache->setOption(Memcached::OPT_RETRY_TIMEOUT, $mrtime); // retry timeout in seconds
        $this->memcache->setOption(Memcached::OPT_COMPRESSION, $mcomp); // Set this to false if you ever start using memcached append
      }
    }
  }
  
  public function __clone() { error_log("Can't clone Mysqli!"); die(); }
  
  public function query($query, $backtrace=array(), $vars=null) {
    // I need this here to check cache so that i dont have to do that crazy thing down below every time before checking for cache
    $this->vars = (is_null($this->vars)) ? $this->clean($GLOBALS) : $this->vars; // globally defined vars
    $qvars = array(); // globally defined vars used in the query
    
    preg_match_all('/\^\^[a-zA-Z0-9\-_]+/m', $query, $matches);
    
    foreach($matches[0] as $var) {
      $var = substr($var, 2);
      if(array_key_exists($var, $this->vars)) {
        $qvars[$var] = $this->vars[$var];
      }
    }
    
    // Check cache first
    if($this->memcache) {
      $this->key = $query;
      foreach($qvars as $name=>$var) {
        $this->key = preg_replace("/\^\^".$name."/", $var, $key_query);
      }
      $this->key = "mysql_".md5($this->key);
      $obj = $memcache->get($this->key); //check cache
      if($obj !== false) {
        $this->data = unserialize($obj);
        return true;
      }
    }
    
    // Because the point of this function is to prevent inline string concatenation, i am going to check for it.
    // If you remove this section, know that you are playing with fire and making the code insecure, so if anyone asks you to do it
    // DON'T!. I DO NOT ALLOW THE USE OF THIS CODE IF THIS SECTION IS REMOVED! This section may be modified to better fulfill its function
    // which is to detect and prevent concatenation of strings, specifically strings and variables in the line calling this function.
    // BEGIN
    
    if(!is_array($backtrace) || count($backtrace)>=0) { $backtrace = debug_backtrace(); }
    if(array_key_exists(0, $backtrace)) { $backtrace=$backtrace[0]; }
    if(!array_key_exists("file", $backtrace)) { error_log("We don't seem to have the right globals data"); return false; }
    
    $fh = file($backtrace["file"]);
    
    // All this just to deal with multi-line input and convert it to a single line (note line returns the last line in a multi-line split so this reads backwards
    $i=$backtrace["line"]-1;
    $line = "";
    do {
      $line = preg_replace('/\s+/', ' ', $fh[$i].$line);
      $i--;
    } while(!preg_match('/[;}]\s*$/', $fh[$i]) || $i<=0);
    
    
    // This pulls quoted strings from a magic function call (yeah i know that wond do multi-level very well, but it will have to do for now)
    // then it evals it to get the value, basically this is a cheasy way to run it through php interpreter and determine if there is any
    // string concatenation happening there by checking the $ count before and after
    $pre = 0;
    $post = 0;
    if(preg_match_all('/'.$backtrace['function'].'\((.*)\)/', $line, $matches)) {
      foreach($matches[0] as $line) {
        if(preg_match_all('/["\'].*["\']/', $line, $query_matches)) {
          foreach($query_matches[0] as $query_match) {
            $pre = preg_match('/\$/', $query_match);
            @eval('$post='.$query_match.';'); // This should be safe as it will reference local scope variables which dont exist. and if they do, its programmer's fault and this will still not work in terms of code injection
            if($pre != preg_match('/\$/', $post)){
              error_log("There seems to be some string concatenation in the function call in {$backtrace['file']}, at line {$backtrace['line']}, around {$query_match}");
              return false;
            }
          }
        } else {
          error_log("invalid file format, please call {$backtrace['function']}(\$this_link, \"query\")");
          return false;
        }
      }
    } else {
      error_log("Invalid calling line format");
      return false;
    }
    // END
    
    $bind_str = "";
    $bind_params = array();
    $query = preg_replace('/\s+/', ' ', $query);
    
    foreach($qvars as $var => $val) {
      if(is_null($val)) {
        if(preg_match('/where.*\^\^'.$var.'/', $query)) {
          preg_match('/(\s[=<>!\s]*(not|is|like)*)*(\^\^'.$var.')/', $query, $matches);
          $comp = (preg_match('/(!|not)/',$matches[0])) ? " is not " : " is ";
          $query = preg_replace('/(\s[=<>!\s]*(not|is|like)*)*(\^\^'.$var.')/', $comp."NULL", $query);
        } else {
          $query = preg_replace('/(\^\^'.$var.')/', "?", $query);
        }
      } else {
        $query = preg_replace('/(\^\^'.$var.')/', "?", $query);
        switch($val){
        case (is_int($val)):
          $bind_str .= "i";
          break;
        case (is_float($val)):
          $bind_str .= "d";
          break;
        default:
          $bind_str .= "s";
          break;
        }
        array_push($bind_params, &$qvars[$var]);
      }
    }
    // Prepare and execute the query
    if(!$this || !preg_match('/.*mysqli.*/i',get_class($this))) { error_log("Didn't get a legitimate mysqli resource"); return false; }
    $this->result=$this->prepare($query);
    if($this->errno) { error_log($this->error); return false; } // check for mysql errors
    if(count($bind_params)>0) {
      array_unshift($bind_params, $bind_str);
      call_user_func_array(array($this->result,'bind_param'), $bind_params);
      if($this->result->errno) { error_log($this->result->error); return false; } // again
    }
    $this->result->execute();
    if($this->result->errno) { error_log($this->result->error); return false; } // and again
    $this->result->store_result();
    
    // This will bind the result array
    if(!$fields = $this->result->result_metadata()) { error_log("The result contains no data." . $this->result->error); return false; }
    if(!$fields = $fields->fetch_fields()) { error_log("Could not fetch fields: " . $this->result->error); return false;}
    $bind_cmd = '$this->result->bind_result(';
    foreach($fields as $field)  { $bind_cmd .='$this->bind_arr[\''.$field->name.'\'],'; }
    $bind_cmd = substr($bind_cmd, 0, -1).");";
    eval($bind_cmd);
    return true;
  }
  
  private function fetch_array($type=NULL, $prefix=NULL, $postfix=NULL, $join="_", $drop=false) //drop will allow you to drop the pre/postfix
  {
    // This actually magically fetches data
    if($this->result->num_rows <= 0) { error_log("We need one or more results in the result set first."); return false; }
    if(!$this->result->fetch()) return FALSE;
    while (list($key, $val) = each($this->bind_arr))  { $ret[$key] =  $val; }
    reset($this->bind_arr);
    if( is_null($type) || strtoupper($type)=="MYSQLI_NUM" || $type==MYSQLI_NUM) $ret=array_values($ret);
    
    if($prefix || $postfix) {
      if(!$drop) {
        if($prefix == "MYSQLI_ROW")  { $prefix = $this->row; }
        if($postfix == "MYSQLI_ROW")  { $postfix = $this->row; }
        foreach($ret as $key=>$val)  { $ret[(($prefix||$prefix=="0")?$prefix.$join:"").$key.(($postfix||$postfix=="0")?$join.$postfix:"")] = $val; unset($ret[$key]); }
      } else {
        foreach($ret as $key=>$val)  { $ret[preg_replace('/('.(($prefix||$prefix=="0")?$prefix.$join:"").'|'.(($postfix||$postfix=="0")?$join.$postfix:"").')', '',$key)] = $val; unset($ret[$key]); }
      }
    }
    $this->row++;
    return $ret;
  }
  
  public function fetch_all($type=NULL, $prefix=NULL, $postfix=NULL, $join=NULL, $drop=false)
  {
    if($this->memcache && !empty($this->data)) {
      $data = $this->data;
      unset($this->data);
      return $data;
    }
    
    $tmp = array(); $ret = array(); // It's nice to initilaize arrays
    if($type==MYSQLI_DOC){
      $tmp = $this->fetch_array(MYSQLI_ASSOC,$prefix,$postfix,$join,$drop);
      array_push($ret, array_keys($tmp), array_values($tmp));
      $type=MYSQLI_NUM;
    }
    while($tmp = $this->fetch_array($type,$prefix,$postfix,$join,$drop)) { $ret[] = $tmp; }
    
    $this->result->free_result(); // Free the original result set (note on change, in mysqli query free is aliased to free_result, always free the result as per the documentation
    $this->bind_arr = array();
    
    if($this->memcache) {   // Store data in cache if its not there yet
      $timeout = (defined(MEM_TIMEOUT)) ? MEM_TIMEOUT : 3600 ;
      if(!$memcache->replace($key, serialize($res), $timeout)) {
        if(!$memcache->add($key, serialize($res),$timeout)) {
          error_log('Failed to store data in MemCache');
        }
      }
    }
    
    return $ret;
  }
  
  public function get_csv($type=NULL, $prefix=NULL, $postfix=NULL, $join=NULL, $drop=false)
  {
    $stream = fopen("php://output", 'w');
    if($this->memcache && !empty($this->data)) {
      $this->arr_csv($this->data, $stream);
    } else {
      $tmp=array();
      while($tmp = $this->fetch_array($type,$prefix,$postfix,$join,$drop)) { $this->arr_csv($tmp, $stream); }
    }
    fclose($stream);
  }
  
  public function arr_csv($data, $stream)
  {
    if(!is_array($data) || gettype($stream) != "resource") { return false; }
    if(is_array($data[0])) { array_walk($data, get_class($this).'::outputCSV', $stream); }
    else { $this->output_csv($data, null, $stream); }
  }
 
  public function num_rows()
  {
    return $this->result->num_rows;
  }
}
Posted

@AtomicMaster

 

$bind_cmd = '$this->result->bind_result(';
foreach($fields as $field) { $bind_cmd .='$this->bind_arr[\''.$field->name.'\'],'; }
$bind_cmd = substr($bind_cmd, 0, -1).");";
eval($bind_cmd);

 

 

 

switch( count( $array ) )

{

case 1: { bind_result( $array[ 0 ] ); break; }

case 2: { bind_result( $array[ 0 ],$array[ 1 ] ); break; }

case 3: { bind_result( $array[ 0 ],$array[ 1 ],$array[ 2 ] ); break; }

[...repeat as many times as needed... ]

}

 

Mine version without eval()...

Posted

That doesn't work when you have "n" amount of fields returned though, i have pulled back queries with almost 100 fields, and doing this would just be silly when you have those kinds of numbers... I felt that this was safe as it only pulls back the names of the fields in the database, which can not very easily be used as a code injection point.

 

I think there may be a different way to do this, I just dont have the time or energy necessary to spend time on this.

Posted (edited)

If DNS were intercepted, and SQL database is external (different domain than PHP server; everything that's not 'localhost'), PHP code asking for connection to database might try to connect to SQL that's fake.

Field names, databases, tables might be all fake. If fake database will have weird column names with string '); [....code to execute...]' hacker will intercept also PHP server (if PHP executable/SQL modules don't do special checks for verifications of database field names obtained from SQL from net).

Edited by Sensei
Posted

So you can own the code if you already own the back-end system... hmm... one can hope that nobody would be silly enough to expose database servers to the web, and also internal dns servers. I am not claiming that this is not a problem, as hypothetically you can break that trust, and technically you can have a more easily exploitabile system, once you have already exploited the system and control 1/2 of its back end already, but i think it solves more of a problem than it creates in regards to security by simply disallowing string interpolated queries. I just don't know of another way to solve this problem of dynamic bind of the results. Unfortunately I don't know if you can meta-program PHP, like Python or Ruby where I can do this at a level where i will not require to use eval...

Posted (edited)

I just don't know of another way to solve this problem of dynamic bind of the results.

 

Simple solution is not using bind_result() when number of columns is unknown at code writing time, and rely only on get_result() and fetch_array() and problem is gone.

 

This can be nicely packed up in OOP method taking call-back as parameter. Call call-back for each row with $row as param. Internal implementation will be not revealed to using it code.

 

$stmt->execute();

$result = $stmt->get_result();

while ($row = $result->fetch_array(MYSQLI_NUM))

{

call_user_func( $func, $row );

}

one can hope that nobody would be silly enough to expose database servers to the web,

 

They are almost always available to users from the net - after all you can use MySQLadmin from home, isn't?

 

It might not be the case only in really large companies having everything, all kind of servers.

 

I can write PHP code (and run at mine home PHP server, not accessible to anybody else), which is connecting to MySQL with bought by me external server at servage.net.

So it's for sure available from the net. In mine case it's domain like mysql[number].servage.net.

 

Now if some intruder would get between mine machine and ISP (intercept wifi *)? intercept provider?), and make fake DNS (simplest one code that I wrote in C/C++ in couple minutes is working like proxy server, listening for packets at 53 port, then logging stuff to file, and passing to some real DNS server, and returning answers to caller. After some time they learn what domains machine is asking. Can prepare fake HTTP(S), fake MySQLdb, fake FTP - check for f.e. "mysql1099.servage.net" and instead of returning true IP, return their own IP where is custom made server. If they will be transparent - pass everything to real one, without any modifications, and vice versa, such server can be unnoticed for months or years by anybody.

 

*) mine ex- neighbour was uploading code to Linux-based Wifi router (typical one router for 50$), and executing his code on it.

Edited by Sensei
Posted

Ah, you see i wrote this code before php 5.3, when they implemented get_result into prepared statement, probably because of these very problems, which is why i had to go that crazy way to get results out of the stmt. Of course this is much cleaner solution than what could be done back then. This code would have to be changed in light of these updates, but i have no use for it, and i have other problems to spend my time on for the time being. That said, I think you will agree that this still works as an example of eval used cautiously; there is no user input that can lead to code injection, so it maintains code/data separation on the front end pretty well.

 

Database servers in most deployments are almost always not directly accessible from the net, because database connections are not done over ssl or with any keying, you can almost always replay the handshake and authenticate to the database server. You don't need to open the servers to the web to run mysqladmin. And what you later describe is not a common (not even big enough to have a measurable percentage point in all deployments) deployment. I can tell you that someone trying to inject code into your applications is the least of your troubles if they are already hijacking your dns, for example marcan was dropping root on some european DSL modems with dns hijacking using built-in functionality...

 

Besides there are other issues with that code that need work. For example better caching ids, scoping issues, better reverse-viewing for better detection of string concatenation, perhaps a way to turn the normal syntax into securely interpolated code (metaprogramming may now be available in PHP? shrug). I am certain i would approach this a bit differently today than i did years ago ;) If you would like, I suppose we could work on that in a different thread, this discussion in this thread has gone far enough off topic to leave it here.

 

My only note back on the original discussion is that if you notice, I understand that even though this is only a theoretical threat, this is one all the same, and it is dangerous. I am happy that there is now a much better solution that contains no eval; since one is possible. And I know how dangerous eval is even when the eval is not acting on user input, my answer to your security inquiry contains understanding the described vector, and does not contain the words "not my problem" or "filter". And most importantly, I am not dismissing everything everyone said in critique, in fact i point out even more limitations and issues that would have to be worked out before this could even be considered production-worthy.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.