渗透测试-04:PHP
PHP 学习
语言规则
-
在
HTML
的body
标签里的<?php ?>
标签里写语句 -
语句末尾要加
;
-
注释:
// 单行注释
# 单行注释
/*多行注释*/
-
换行符可用
PHP_EOL
替代 -
不区分大小写:关键词、类名、函数名
-
区分大小写:变量名
-
0
和null
值相等,类型不相等 -
变量定义:
$变量名
-
变量作用域:
local
:函数内部声明的变量,仅能在函数内部访问global $变量名
:函数内部调用外部全局变量,也可以使用$GLOBALS[变量名]
访问全局变量static $变量名
:函数执行结束后变量的值不被删除 -
常量定义:
define("__大写常量名__", 常量值)
-
$x <=> $y
:x<y返回-1,x=y返回0,x>y返回+1
-
打印输出:
echo
输出的速度比print
快,可以使用括号,也可以不用括号echo $变量名
:可以输出一个或多个字符串,没有返回值print $变量名
:只允许输出一个字符串,返回值总为 1print_r()
:可以结构化打印数组变量,可以设置返回值var_dump()
:打印数据类型和值,可以结构化打印数组变量 -
用
.
拼接字符串 -
引号的区别:
单引号
:不解析字符串里的$变量名
双引号
:解析字符串里的$变量名
-
数组:可以用
array()
和[]
两种方法定义索引数组
:["orange", "apple", "banana"]
关联数组
:["a"=>"星期一", "b"=>"星期二", "c"=>"星期三"]
数据类型
标准类型 - String、Integer、Float、Boolean
复合类型 - Array、Object
特殊类型 - Resource、NULL
自动类型转换:2+"2abc"=4
严格类型要求:<?php declare(strict_types=1); ?>
函数返回类型声明:(严格类型条件下)
<?php declare(strict_types=1); // strict requirement
function addNumbers(float $a, float $b) : float {
return $a + $b;
}
echo addNumbers(1.2, 5.2); // 报错
?>
变量引用
<?php
function add_five(&$value) {
$value += 5;
}
$num = 2;
add_five($num);
echo $num; // 7
?>
字符串函数
字符串长度 - strlen()
字符串反转 - strrev()
字符串截取 - substr()
字符串替换 - str_replace('要替换的字符串','新字符串','原字符串')
字符串的单词数 - str_word_count()
在原字符串中寻找新字符串并返回新字符串的索引 - strpos('原字符串','新字符串')
删除左边空格 - ltrim()
删除右边空格 - rtrim()
删除两边空格 - trim()
转小写 - strtolower()
转大写 - strtoupper()
删除 html 标签 - strip_tags()
转义 html 标签 - htmlspecialchars()
去除数据中的反斜杠(\) - stripslashes()
数组迭代器
foreach($names as $name){echo $name, "<br>";}
foreach($arr as $key=>$value){echo $key, $value;}
数组函数
数组元素个数 - count($数组变量名)
数组添加元素 - array_push($数组变量名, 值)
获取所有键名 - array_keys($数组名)
获取所有值 - array_values($数组名)
判断值是否存在于数组 - in_array(值, $数组名, true) // 第三个参数为是否开启严格模式(可选)
常用函数
升序排序 - sort()
降序排序 - rsort()
根据值升序排序 - asort()
根据键升序排序 - ksort()
根据值降序排序 - arsort()
根据键降序排序 - krsort()
查看类型 - gettype()
序列化 - serialize()
反序列化 - unserialize()
URL编码 - urlencode()
URL解码 - urldecode()
判断变量是否已被设置 - isset()
释放给定的变量 - unset()
判断变量是否为空 - empty()
字符串转数组 - expload()
数组转字符串 - impload()
输出一条消息,并停止往下执行 - exit() 或 die()
时间戳转格式化时间 - date('Y-m-d H:i:s', time())
设置中国时区 - date_default_timezone_set('PRC')
函数检查某常量是否存在 - defined()
输出当前文件的绝对路径 - __DIR__
函数解析URL,返回其组成部分 - parse_url()
函数用于检测变量是否是字符串 - is_string()
字符串 md5 加密 - md5()
单向字符串散列加密 - crypt('字符串', '盐值')
可防止时序攻击的字符串比较 - hash_equals(string $known_string, string $user_string)
获取文件名后缀 - pathinfo('文件名')['extension']
require 和 include
// 通常放在 PHP 脚本程序的最前面,在一开始就加载
// 出错时产生 E_ERROR 级别的错误,导致脚本中止
// 如果可能执行多次的代码,则使用 require() 效率比较高
require("文件.php")
// 检查该文件是否已经被包含过,如果是则不会再次包含
require_once("文件.php")
// 一般是放在流程控制的处理区段中,在用到时加载
// 出错时产生警告 E_WARNING,脚本会继续运行
// 如果每次执行代码时是读取不同的文件,或者有通过一组文件迭代的循环,就使用 include() 语句
include("文件.php")
// 唯一区别是如果该文件中已经被包含过,则不会再次包含,且 include_once 会返回 true
include_once("文件.php")
文件操作
文件操作函数
// 文件
fopen('文件名或url','打开模式')
fread('文件名','读取的最大字节数')
filesize('文件名')
fwrite('文件名','写入的内容')
copy('原文件','目标文件') // 如果目标文件已存在,将会被覆盖
rename('原文件名','新文件名')
unlink('原文件') // 删除文件
fclose($打开的文件变量)
// 目录
opendir('目录路径') // 打开一个目录,读取它的内容,然后关闭
readdir($打开的目录变量)
rmdir('目录路径')
mkdir('目录名','权限')
closedir($打开的目录变量)
scandir() // 返回指定目录中的文件和目录的数组
文件打开模式
正则表达式
$exp = "/toki/i";
toki 为要比配的正则表达式,i
为不区分大小写,界定符通常使用 /
,也可以用 #
~
代替
Function | Description |
---|---|
preg_match($pattern, $str) | 匹配到返回1,否则返回0 |
preg_match_all($pattern, $str) | 返回匹配到的次数 |
preg_replace() | 返回被替换的整个字符串 |
Modifier | Description |
---|---|
i | Performs a case-insensitive search |
m | Performs a multiline search (patterns that search for the beginning or end of a string will match the beginning or end of each line) |
u | Enables correct matching of UTF-8 encoded patterns |
Metacharacter | Description |
---|---|
| | Find a match for any one of the patterns separated by | as in: cat|dog|fish |
. | Find just one instance of any character |
^ | Finds a match as the beginning of a string as in: ^Hello |
$ | Finds a match at the end of the string as in: World$ |
\d | Find a digit |
\s | Find a whitespace character |
\b | Find a match at the beginning of a word like this: \bWORD, or at the end of a word like this: WORD\b |
\uxxxx | Find the Unicode character specified by the hexadecimal number xxxx |
Quantifier | Description |
---|---|
n+ | Matches any string that contains at least one n |
n* | Matches any string that contains zero or more occurrences of n |
n? | Matches any string that contains zero or one occurrences of n |
n | Matches any string that contains a sequence of X n's |
n | Matches any string that contains a sequence of X to Y n's |
n | Matches any string that contains a sequence of at least X n's |
preg_match()
<?php
$str = "Apples and bananas.";
$pattern = "/ba(na){2}/i";
echo preg_match($pattern, $str); // Outputs 1
?>
preg_match_all()
<?php
$str = "The rain in SPAIN falls mainly on the plains.";
$pattern = "/ain/i";
echo preg_match_all($pattern, $str); // Outputs 4
?>
preg_replace()
<?php
$str = "Visit Microsoft!";
$pattern = "/microsoft/i";
echo preg_replace($pattern, "W3Schools", $str); // Outputs "Visit W3Schools!"
?>
PHP 爬虫
file_get_contents() 和 file_put_contents()
// 把整个文件读入一个字符串中
file_get_contents('文件名或url')
// 把一个字符串写入文件中,写入模式有:FILE_USE_INCLUDE_PATH、FILE_APPEND、LOCK_EX
// 如果设置了 FILE_USE_INCLUDE_PATH,那么将检查 filename 副本的内置路径
// 如果设置了 LOCK_EX,那么将锁定文件
// 如果设置了 FILE_APPEND,那么将移至文件末尾。否则,将会清除文件的内容
file_put_contents('文件名','字符串',写入模式)
Note:如果要打开有特殊字符的 URL,就需要使用
urlencode()
进行 URL 编码。
file_get_contents() 函数超时处理
在使用 file_get_contents
函数读取文件或URL的时候,经常会出现超时的情况,我们可以通过一些方法来尽量的避免或者解决。
增加超时的时间限制
这里需要注意:set_time_limit(0)
只是设置你的PHP程序的超时时间,而不是 file_get_contents
函数读取URL的超时时间。
想通过 set_time_limit(0)
影响到 file_get_contents
来增加超时时间,经测试,是无效的。真正的修改 file_get_contents
延时可以用 resource $context
的 timeout
参数,timeout
参数的单位是 s(秒)。
实例:
$opts = array(
'http'=>array(
'method'=>"GET",
'timeout'=>30,
)
);
$html = file_get_contents('http://www.baidu.com', false, stream_context_create($opts));
echo $html;
超过几秒就重新执行,多次重试直到成功
file_get_contents
超时有时候失败是因为网络等因素造成,没有解决办法,但是可以修改程序,失败时重试几次,仍然失败就放弃,因为 file_get_contents()
如果失败将返回 FALSE,所以可以下面这样编写代码:
$cnt=0;
while($cnt < 3 && ($str=@file_get_contents('http://www.w3cschool.cn'))===FALSE) $cnt++;
注意:如果执行时间过长,还需要用函数
set_time_limit(0);
就不会超时了。
file_get_contents() 函数代理设置处理
设置代理 IP 去获取页面数据
$context = array(
'http' => array(
'proxy' => 'tcp://192.168.0.1:3128', //这里设置你要使用的代理ip及端口号
'request_fulluri' => true,
),
'ssl' => array(
"verify_peer" => false, // 取消ssl验证
"verify_peer_name" => false
),
);
$context = stream_context_create($context);
$html = file_get_contents("http://www.baidu.com", false, $context);
echo $html;
设置需要验证的代理 IP 去采集获取页面数据
$auth = base64_encode('USER:PASS'); //LOGIN:PASSWORD 这里是代理服务器的账户名及密码
$context = array(
'http' => array(
'proxy' => 'tcp://192.168.0.1:3128', //这里设置你要使用的代理ip及端口号
'request_fulluri' => true,
'header' => "Proxy-Authorization: Basic $auth",
),
);
$context = stream_context_create($context);
$html = file_get_contents("http://www.baidu.com", false, $context);
echo $html;
超全局变量
$GLOBALS["变量名"] 存放所有全局变量的数组,可全局调用
$_SERVER 服务器信息变量,该全局变量包含着服务器和客户端配置及当前请求环境的有关信息
$_SERVER['SERVER_NAME'] - 当前运行脚本所在的服务器的主机名
$_SERVER['REMOTE_ADDR'] - 客户端 IP 地址
$_SERVER['REQUEST_URI'] - URL 的路径部份
$_SERVER['HTTP_USER_AGENT'] - 操作系统和浏览器的有关信息
$_SERVER["PHP_SELF"] - 返回当前正在执行脚本的文件名
$_SERVER["REQUEST_METHOD"] - 检测表单是否被提交,返回POST或空
$_FILES 与上传文件有关的变量数组
<input type="file" name="userfile">
$_FILES['userfile']['name'] - 上传文件的名称
$_FILES['userfile']['type'] - 上传文件的类型
$_FILES['userfile']['size'] - 上传文件的大小,以字节计
$_FILES['userfile']['tmp_name'] - 存储在服务器的文件的临时副本的名称
$_FILES["file"]["error"] - 由文件上传导致的错误代码
$_REQUEST 用来收集通过 GET 和 POST 等方法发送的表单数据
$_GET 用于收集来自 method="get" 的表单中的值,是一个数组,大小不能超过 2000 个字符
$_POST 用于收集来自 method="post" 的表单中的值,$_POST 也常用于传递变量,大小没有限制
$_ENV 环境变量
$_COOKIE 存放 cookie 变量的数组
$_SESSION 存放 session 变量的数组
$_SERVER
Element/Code | Description |
---|---|
$_SERVER['PHP_SELF'] | Returns the filename of the currently executing script |
$_SERVER['GATEWAY_INTERFACE'] | Returns the version of the Common Gateway Interface (CGI) the server is using |
$_SERVER['SERVER_ADDR'] | Returns the IP address of the host server |
$_SERVER['SERVER_NAME'] | Returns the name of the host server (such as www.w3schools.com) |
$_SERVER['SERVER_SOFTWARE'] | Returns the server identification string (such as Apache/2.2.24) |
$_SERVER['SERVER_PROTOCOL'] | Returns the name and revision of the information protocol (such as HTTP/1.1) |
$_SERVER['REQUEST_METHOD'] | Returns the request method used to access the page (such as POST) |
$_SERVER['REQUEST_TIME'] | Returns the timestamp of the start of the request (such as 1377687496) |
$_SERVER['QUERY_STRING'] | Returns the query string if the page is accessed via a query string |
$_SERVER['HTTP_ACCEPT'] | Returns the Accept header from the current request |
$_SERVER['HTTP_ACCEPT_CHARSET'] | Returns the Accept_Charset header from the current request (such as utf-8,ISO-8859-1) |
$_SERVER['HTTP_HOST'] | Returns the Host header from the current request |
$_SERVER['HTTP_REFERER'] | Returns the complete URL of the current page (not reliable because not all user-agents support it) |
$_SERVER['HTTPS'] | Is the script queried through a secure HTTP protocol |
$_SERVER['REMOTE_ADDR'] | Returns the IP address from where the user is viewing the current page |
$_SERVER['REMOTE_HOST'] | Returns the Host name from where the user is viewing the current page |
$_SERVER['REMOTE_PORT'] | Returns the port being used on the user's machine to communicate with the web server |
$_SERVER['SCRIPT_FILENAME'] | Returns the absolute pathname of the currently executing script |
$_SERVER['SERVER_ADMIN'] | Returns the value given to the SERVER_ADMIN directive in the web server configuration file (if your script runs on a virtual host, it will be the value defined for that virtual host) (such as someone@w3schools.com) |
$_SERVER['SERVER_PORT'] | Returns the port on the server machine being used by the web server for communication (such as 80) |
$_SERVER['SERVER_SIGNATURE'] | Returns the server version and virtual host name which are added to server-generated pages |
$_SERVER['PATH_TRANSLATED'] | Returns the file system based path to the current script |
$_SERVER['SCRIPT_NAME'] | Returns the path of the current script |
$_SERVER['SCRIPT_URI'] | Returns the URI of the current page |
$_REQUEST
<html>
<body>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Name: <input type="text" name="fname">
<input type="submit">
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// collect value of input field
$name = $_REQUEST['fname'];
if (empty($name)) {
echo "Name is empty";
} else {
echo $name;
}
}
?>
</body>
</html>
$_POST
<html>
<body>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Name: <input type="text" name="fname">
<input type="submit">
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// collect value of input field
$name = $_POST['fname'];
if (empty($name)) {
echo "Name is empty";
} else {
echo $name;
}
}
?>
</body>
</html>
$_GET
<html>
<body>
<a href="test_get.php?subject=PHP&web=W3schools.com">Test $GET</a>
<?php
echo "Study " . $_GET['subject'] . " at " . $_GET['web'];
?>
</body>
</html>
header() 函数
作用:发送一个原始 HTTP 标头到客户端,服务器以 HTTP 协义传 HTML 到浏览器前所送出的字串,在 PHP 中送回 HTML 资料前,需先传完所有的标头。
内容类型
header('Content-Type: text/html; charset=utf-8'); //网页编码
header('Content-Type: text/plain'); //纯文本格式
header('Content-Type: image/jpeg'); //JPG、JPEG
header('Content-Type: application/zip'); // ZIP文件
header('Content-Type: application/pdf'); // PDF文件
header('Content-Type: audio/mpeg'); // 音频文件
header('Content-type: text/css'); //css文件
header('Content-type: text/javascript'); //js文件
header('Content-type: application/json'); //json
header('Content-type: application/pdf'); //pdf
header('Content-type: text/xml'); //xml格式文件
页面功能
header('HTTP/1.1 200 OK'); // ok 正常访问
header('HTTP/1.1 301 Moved Permanently'); //设置地址被永久的重定向 301
header('HTTP/1.1 304 Not Modified'); //告诉浏览器文档内容没有发生改变
header('HTTP/1.1 404 Not Found'); //通知浏览器 页面不存在
header('Location: http://www.ithhc.cn/'); //重定向到一个新的地址
header('Refresh:10; url=http://www.baidu.cn/'); //延迟跳转
header('X-Powered-By: PHP/6.0.0'); //修改 X-Powered-By 信息
header('Content-language: en'); //文档语言
header('Content-Length: 1234'); //设置内容长度
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); //告诉浏览器最后一次修改时间
数据传输
传值
form 表单 - <form method="GET"></form>
a 标签 - <a href="blog.toki.plus?name=toki">
href 属性 - <script>location.href="blog.toki.plus?name=toki"</script>
assign() 方法 - <script>location.assign("blog.toki.plus?name=toki")</script>
window.location.href
:返回当前页面 urlwindow.location.hostname
:返回网站域名window.location.pathname
:放回当前 url 的相对路径window.location.protocol
:返回网页端口号window.location.assign("新的 url")
:加载新的页面
取值
GET - $name = $_GET["username"];
POST - $name = $_POST["username"];
表单写法
<form method="POST" enctype="multipart/form-data" action="test.php"></form>
method 属性 - 表单提交方式必须为 POST
enctype 属性 - form 表单属性,主要是规范表单数据的编码方式
- application/x-www-form-urlencoded 在发送前编码所有字符(默认)
- multipart/form-data 不对字符编码,包含文件上传的表单必须使用该值
- text/plain 空格转换为“+”加号,但不对特殊字符编码
(可以在表单中添加 MAX_FILE_SIZE 隐藏域,通过设置其 value 值可以限制上传文件的大小)
文件上传校验
// 检查指定的文件是否是通过 HTTP POST 上传的
// 该函数的结果会被缓存。请使用 clearstatcache() 来清除缓存
bool is_uploaded_file(string filename)
// 把上传的文件移动到新位置
bool move_uploaded_file(string filename, string destination)
Cookie 和 Session
Session 的工作机制是:为每个访客创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,或者通过 URL 进行传导。
Cookie 和 Session 的区别
- 安全性
Session:存储服务器端,安全性高
Cookie:存储浏览器端,安全性低 - 数据大小
Cookie:的数量和大小都有限制
Session:数据存储不限 - 可用数据类型
Cookie:只能存储简单数据,数值 字符串
Session:可以存储复杂数据(自动序列化) - 保存位置
Cookie:保存在浏览器上
Session:保存在服务器上
设置 Cookie
setcookie("字段", "值", 生命周期, "存放路径", "有效域名", 是否只允许https, 是否不允许脚本访问);
时间戳
:默认为 0
,代表浏览器关闭就删除 cookie
存放路径
:父目录中设置过的 cookie
可以在子目录中获取到,反之不行,一般用 '/'
增/改 - setcookie("name", "Toki", time()+60*60*24*30);
删 - setcookie("name", "", time()-3600);
- unset($_COOKIE['name']);
查 - if (isset($_COOKIE["name"]));
判断是否已设置了cookie - isset($_COOKIE["name"])
设置 Session
-
session_set_cookie_params(lifetime, path, domain, secure, httponly)
:在调用session_start()
函数之前调用,PHP 7.3 版本以上才有效 -
session_start()
:启动会话,必须位于<html>
标签之前 -
unset($_SESSION["name"])
-
$_SESSION = array()
-
session_unset()
释放当前在内存中已经创建的所有$_SESSION
变量,但不删除session
文件以及不释放对应的session id
-
session_destroy()
:删除当前用户对应的session
文件以及释放session id
,内存中的$_SESSION
变量内容依然保留
增/改 - $_SESSION["name"] = "Toki";
删 - unset($_SESSION["name"]); 或 session_destroy();
查 - if(isset($_SESSION['name']));
判断 - isset($_SESSION['name']))
常用过滤条件
if ($_POST) {}
if (!isset($_SESSION['']) || empty($_SESSION[''])) {}
if ($_FILES['']['error'] == 1-7) {}
if (!in_array('字符串', '数组')) {}
if (!is_dir('路径')) {}
if (file_exists($upload_path)) {}
if (is_uploaded_file($tmp_name)) {}
if (move_uploaded_file($tmp_name, $img_path)) {}
$_FILES['']['error']
-
UPLOAD_ERR_OK
其值为 0,没有错误发生,文件上传成功。 -
UPLOAD_ERR_INI_SIZE
其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值。 -
UPLOAD_ERR_FORM_SIZE
其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。 -
UPLOAD_ERR_PARTIAL
其值为 3,文件只有部分被上传。 -
UPLOAD_ERR_NO_FILE
其值为 4,没有文件被上传。 -
UPLOAD_ERR_NO_TMP_DIR
其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。 -
UPLOAD_ERR_CANT_WRITE
其值为 7,文件写入失败。PHP 5.1.0 引进。
数据库连接
面向对象
-
类的变量用
var
声明 -
类的常量用
const
声明,常量不需要用$符 -
静态、常量、重写的属性与方法 调用:
::
-
对象的属性与方法 调用:
->
-
类:
Class
-
继承:
extends
-
接口:
interface
、implements
-
this关键字:
$this -> name
-
构造函数:
__construct()
- 实例化对象时自动调用 -
析构函数:
__destruct()
- 对象被释放时自动调用 -
访问修饰符:
public(默认)
、private
、protected
算法
冒泡排序
<?php
$numbers = [9,8,7,6,5,4,3,2,1,0];
bubble($numbers);
function bubble($numbers){
// 冒泡的轮数
for($round=0; $round<count($numbers)-1; $round++){
// 两两比较的次数
for($index=0; $index<count($numbers)-1-$round; $index++){
if($numbers[$index]>$numbers[$index+1]){
$tmp = $numbers[$index];
$numbers[$index] = $numbers[$index+1];
$numbers[$index+1] = $tmp;
}
}
}
foreach ($numbers as $number) {
echo $number;
}
}
?>