发现PHP审计和利用的一些漏洞利用场景挺有意思的,来学习一下php基础内容,大部分概念和代码和Java或c++的差不多,挑些php独有的特性来做记录。
PHP中预定义了几个超级全局变量(superglobals) ,这意味着它们在一个脚本的全部作用域中都可用。
$GLOBAL 是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
<?php $x = 75; $y = 25; function addition() { $GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y']; } addition(); echo $z; ?> //结果:100
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。不能保证每个服务器都提供全部项目;
<?php echo $_SERVER['PHP_SELF']; // /try/demo_source/demo_global_server.php echo "<br>"; echo $_SERVER['SERVER_NAME']; // runoob.com echo "<br>"; echo $_SERVER['HTTP_HOST']; // www.runoob.com echo "<br>"; echo $_SERVER['HTTP_REFERER']; //来由 echo "<br>"; echo $_SERVER['HTTP_USER_AGENT']; //浏览器 echo "<br>"; echo $_SERVER['SCRIPT_NAME']; // /try/demo_source/demo_global_server.php //另外$_SERVER对象还包括 SERVER_ADDR, SERVER_PROTOCOL ,REQUEST_METHOD..等属性 ?>
$_REQUEST 用于收集HTML表单提交的数据。
<html> <body> <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>"> Name: <input type="text" name="fname"> <input type="submit"> </form> <?php $name = $_REQUEST['fname']; echo $name; ?> </body> </html>
$_POST 被广泛应用于收集表单数据,在HTML form标签的指定该属性:"method="post"
<html> <body> <!--页面post给自己--> <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>"> Name: <input type="text" name="fname"> <input type="submit"> </form> <?php $name = $_POST['fname']; echo $name; ?> </body> </html>
$_GET 同样被广泛应用于收集表单数据,在HTML form标签的指定该属性:"method="get"。
$_GET 也可以收集URL中发送的数据
<html> <body> <a href="test_get.php?subject=PHP&web=runoob.com">Test $GET</a> </body> </html> //test_get.php <html> <body> <?php echo "Study " . $_GET['subject'] . " at " . $_GET['web']; ?> </body> </html>
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。
_LINE__
__FILE__
__DIR__
__FUNCTION__
__CLASS__
类的名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。__NAMESPACE__
当前命名空间的名称(区分大小写)。此常量是在编译时定义的(PHP 5.3.0 新增)__METHOD__
类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)<?php //打开文件 $file = fopen("welcome.txt", "r") or exit("Unable to open file!"); //Output a line of the file until the end is reached //是否到达文件末尾 while(!feof($file)) { echo fgets($file). "<br>"; //逐行读取文件 //echo fgetc($file); //逐字符读取 } //关闭文件 fclose($file); ?>
<?php class phpClass { var $var1; var $var2 = "constant string"; function myfunc ($arg1, $arg2) { [..] } [..] } ?> $runoob = new phpClass; $runoob->getUrl();
function __construct( $par1, $par2 ) { $this->url = $par1; $this->title = $par2; }
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
<?php class MyDestructableClass { function __construct() { print "构造函数\n"; $this->name = "MyDestructableClass"; } function __destruct() { print "销毁 " . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?>
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
<?php // 声明一个'iTemplate'接口 interface iTemplate { public function setVariable($name, $var); public function getHtml($template); } // 实现接口 class Template implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } }
<?php abstract class AbstractClass { // 强制要求子类定义这些方法 abstract protected function getValue(); abstract protected function prefixValue($prefix); // 普通方法(非抽象方法) public function printOut() { print $this->getValue() . PHP_EOL; } } class ConcreteClass1 extends AbstractClass { protected function getValue() { return "ConcreteClass1"; } public function prefixValue($prefix) { return "{$prefix}ConcreteClass1"; } } class ConcreteClass2 extends AbstractClass { public function getValue() { return "ConcreteClass2"; } public function prefixValue($prefix) { return "{$prefix}ConcreteClass2"; } } $class1 = new ConcreteClass1; $class1->printOut(); echo $class1->prefixValue('FOO_') . PHP_EOL; $class2 = new ConcreteClass2; $class2->printOut(); echo $class2->prefixValue('FOO_') . PHP_EOL; ?>