PHP 记录

PHP 知识点以及遇到的不正确使用可能导致的漏洞或者绕过

知识点

可变变量

php 可变变量

eval()

eval

file_put_contents()

PHP file_put_contents() 函数

SERVER 变量

HTTP_X_FORWARDED_FOR:浏览当前页面的用户计算机的 ip 地址
HTTP_CLIENT_IP:客户端的 ip
HTTP_HOST:获取当前域名
HTTP_USER_AGENT:浏览器类型
HTTP_ACCEPT_LANGUAGE:浏览器语言

1
2
3
4
在 PHP 中使用 $_SERVER["REMOTE_ADDR"] 来取得客户端的 IP 地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取。

不过要注意的事,并不是每个代理服务器都能用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取客户端的真实 IP,有些用此方法读取到的仍然是代理服务器的 IP。
还有一点需要注意的是:如果客户端没有通过代理服务器来访问,那么用 $_SERVER["HTTP_X_FORWARDED_FOR"] 取到的值将是空的。
1
所以,在实际程序中,应尽量使用_SERVER["HTTP_HOST"] ,比较保险和可靠。

$_SERVER[’REQUEST_URI’]

1
如:index.php?str=1234    PHP_SELF   是 index.php。

$_SERVER[‘QUERY_STRING’]

1
$_SERVER[’REQUEST_URI’]会原封不动的反映网址本身,网址中如果有%3C,那么你得到的也将会是%3C,而$ _SERVER[’PHP_SELF’]会对网址进行一次urldecode操作,网址中的%3C将会变成字符“<”,所以就产生了漏洞。

PHP 伪静态

PHP 伪静态的图文代码详细介绍

静态网页就是,比如知乎网站上放了一个 abc.html 文件,你想访问它就直接输入 zhihu. com/abc.html。Web 服务器看到这样的地址就直接找到这个文件输出给客户端。

动态网页就是,假如你想做一个显示当前时间的页面,那么就可以写个 PHP 文件,然后访问 zhihu. com/abc.php。Web 服务器看到这样的地址,找到 abc.php 这个文件,会交给 PHP 执行后返回给客户端。而动态网页往往要输入参数,所以地址就变成 zhihu. com/abc.php?a=1&b=2。

搜索引擎比较烦这种带问号的动态网页,因为参数可以随便加,而返回内容却不变,所以会对这种网页降权。

于是有了 mod_rewrite,它可以重新映射地址。比如当前这个页面的地址 htt p://www.zhihu. com/question/20153311,Web 服务器收到请求后会重新映射为 www.zhihu. com/question.php?n=20153311,然后再执行那个 PHP 程序。(以上网址均为假设)这样,在内部不改变的情况下,对外呈现出来的网址变成了没有问号的象静态网页的网址一样。

empty()

1
2
3
4
5
6
7
* 格式:bool empty ( mixed var )
* 功能:检查一个变量是否为空
* 返回值:
* 若变量不存在则返回 TRUE
* 若变量存在且其值为""0"0"NULL、、FALSEarray()、var $var; 以及没有任何属性的对象,则返回 TURE
* 若变量存在且值不为""0"0"NULL、、FALSEarray()、var $var; 以及没有任何属性的对象,则返回 FALSE
* 版本:PHP 3, PHP 4, PHP 5

in_array()

1
in_array(search,array,type)

如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

如果没有在数组中找到参数,函数返回 false。

注释:如果 search 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

addslashes()

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  1. 单引号(')
  2. 双引号(")
  3. 反斜杠()
  4. NULL

注释:默认地,PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。所以您不应对已转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测(php 6 移除)

mysqli_escape_string — 别名 mysqli_real_escape_string()

字符串变量解析

用单引号括住的输出,并没有解析字符串变量,而使用双引号括住的输出,则解析了变量了,输出变量的值。

mysql_escape_string()

1
2
mysql_escape_string():转义字符串中的特殊字符(编码的字符是 NUL(ASCII 0)、\n、\r、\、'、" 和 Control-Z)
新版:mysqli_escape_string — 别名 mysqli_real_escape_string()

mysql_real_escape_string 和 mysql_escape_string 区别

两者都是过滤字符串,防止 sql 注入,但两者有一些区别

mysql_real_escape_string:

1.具有两个参数,其中第二个为选填参数,默认为上一个数据库链接 connection

2.使用之前要先连接上数据库,否则会出错

3.在过滤字符串的时候,会考虑当前链接 connection 字符集,(set names 'utf-8')

mysql_escapte_string 是处理单个字符串函数.

不过从 PHP5.4 开始,PHP 官方就鼓励使用 mysqli 和 PDO 来操作数据库了。

intval()

intval (var[, base])

获取变量的整数值,允许以使用特定的进制返回。默认 10 进制
注:如果参数为整数,则不做任何处理。

var: 必须。可以是任何标量类型。 intval() 不能用于数组 或 对象(类)。在此我得提一下标量类型包含四种:boolean(布尔型)integer(整型) float(浮点型, 也称作 double) string (字符串)

base: 可选。转化所使用的进制,默认 10 进制如果 base 是 0,通过检测 var 参数的格式来决定使用的进制:如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制如果字符串以 “0” 开始,使用 8 进制其他使用 10 进制

如果参数是字符串,则返回字符串中第一个不是数字的字符之前的数字串所代表的整数值。如果字符串第一个是‘-',则从第二个开始算起。

1
2
3
4
5
6
7
<?php 
echo intval("A"); echo "<br>";
echo intval("A", 16); echo "<br>";
echo intval(12.3223); echo "<br>";
echo intval("1123Asdfka3243"); echo "<br>";
echo intval("sdf1123Asdfka3243"); echo "<br>";
?>
1
2
3
4
5
0
10
12
1123
0

Bypass

编写对标签的过滤

PHP 中自编写对标签的过滤或关键字过滤,应放在 strip_tags 等去除函数之后,否则引起过滤绕过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php 
function checkSQLi($string)
{
if(strpos("select", $string)){return 1;}
}

function mystrip_tags($string)
{
if(checkSQLi($string)){
echo "caught by waf!";
return 0;
}
$string = strip_tags($string);//checkSQLi()在 strip_tags 之前调用,所以很明显可以利用 strip_tags 函数绕过,在关键字中插入 html 标记.
return $string;
}

echo mystrip_tags($_GET['id'])."<br>\n";
?>
1
?id=user/**/W<a>HERE/**/IF((S<a>ELECT/**/A<a>SCII(S<a>UBSTRING(PASSWORD,1,1))F<a>ROM/**/ts_user/**/L<a>IMIT%201)=101, 1=S<a>LEEP(2.02),0)%23

$_SERVER[]使用不当

$_SERVER[‘QUERY_STRING’]与 $_SERVER[’PHP_SELF’]

使用不但会造成 xss 与 sqli:

1
<form action="<?php echo $_SERVER['PHP_SELF']; ?>"> <input type="submit" name="submit" value="submit" /> </form>
1
http://127.0.0.1/test.php/%22%3E%20%3Cscript%3Ealert('xss')%3C/script%3E

未定义常量

if(IN_ADMIN != TRUE) 等式不成立,非 0null 都为 true

1
2
3
4
5
6
7
<?php
if(IN_ADMIN == TRUE)
{
echo "string";
}
?>
//输出 string

弱类型验证

由于 PHP 弱类型验证机制,导致==、in_array()等可通过强制转换绕过验证。

1
2
3
<?php
var_dump("1'aaaa"==1);
?>

为 True

urldecode 与 rawurldecode

二次编码绕过

1
2
3
4
5
6
7
<?php
$a=addslashes($_GET['p']);
$b=urldecode($a);
echo '$a=' .$a;
echo '<br />';
echo '$b=' .$b;
?>

?p=1%25%27

Win 下 php 的<问题

My Blog


来呀快活呀


PHP 记录
https://www.tr0y.wang/2018/04/08/PHPFunc/
作者
Tr0y
发布于
2018年4月8日
更新于
2024年4月19日
许可协议