小常识
摘要
小常识
1.$$可变变量
$$a
是 PHP 中的一种特殊变量引用语法,被称为”可变变量”(variable variables)。它允许您使用一个变量的值作为另一个变量的名称。
让我们详细解释 $$a
的含义:
$a
是一个普通的变量,其中存储了一个字符串值,通常用于表示变量的名称。$$a
使用$a
的值作为变量名称,并尝试访问这个变量。
例如,如果 $a
的值为 “myVar”,那么 $$a
将尝试访问名为 $myVar
的变量。
下面是一个示例:
1 | $a = "myVar"; |
在这个示例中,$a
包含字符串 “myVar”,然后 $$a
将根据 $a
的值尝试访问 $myVar
,并将 “Hello, world!” 打印出来。
需要注意的是,使用可变变量时要格外小心,因为它们可能会导致代码的可读性变差,并且在不慎使用时可能引发错误或安全问题。通常情况下,最好使用数组来管理变量,而不是可变变量,以提高代码的可维护性和安全性。
- 满足条件之后以数组形式打印出变量$$a。
- $$a可以理解为$($a),就是让$a的值成为这个大变量的变量名。
- 由此我们可以想到$GLOBALS — 引用全局作用域中可用的全部变量。
- 利用它,我们可以输出所有变量,所以构造payload:?c=GLOBALS
这时候$$a就变成了$GLOBALS。
2.X-Forwarded-For
X-Forwarded-For
是一个HTTP请求头,通常用于表示HTTP请求经过的代理服务器链中的客户端IP地址。这个头字段的值是一个逗号分隔的IP地址列表,最左边的IP地址表示最初的客户端IP,而最右边的IP地址表示最后一个代理服务器的IP。这是一个示例:
1 | X-Forwarded-For: client, proxy1, proxy2 |
在这个示例中,client
是最初的客户端IP地址,proxy1
和 proxy2
是两个代理服务器的IP地址,它们按顺序处理了HTTP请求。
X-Forwarded-For
头的作用是帮助后端服务器了解请求的真实客户端IP地址,尤其在请求通过代理服务器、负载均衡器或反向代理服务器时很有用。默认情况下,HTTP请求的源IP地址是代理服务器的IP地址,而不是最初客户端的IP地址。通过查看X-Forwarded-For
头,后端服务器可以获取到客户端的真实IP地址。
然而,需要注意以下几点:
- 安全性问题:
X-Forwarded-For
头是可伪造的。客户端可以在请求中添加自己构造的X-Forwarded-For
头,因此不能完全信任它来确定客户端的真实IP地址。因此,不应将其用于安全性相关的操作,如访问控制或身份验证。 - 代理链: 如果请求经过多个代理服务器,
X-Forwarded-For
头中的IP地址列表可能会很长。您可能需要解析这个头来提取最初客户端的IP地址。 - 代理配置: 代理服务器必须正确配置以传递
X-Forwarded-For
头。如果代理服务器没有传递这个头或错误地修改了它,后端服务器将无法获取真实的客户端IP地址。
总之,X-Forwarded-For
头是有用的,但必须小心使用,特别是在考虑安全性时。在合适的情况下,它可以帮助您了解请求的来源。
3.POST请求(BP)
Content-Type: application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
是一个HTTP头,通常用于指示HTTP请求的主体(body)数据格式。这个特定的Content-Type
值表示请求主体中包含的数据采用了经典的URL编码格式,通常用于HTML表单提交数据。
在 application/x-www-form-urlencoded
格式中,数据以键值对的形式发送,键值对之间使用 &
符号分隔,而键和值之间使用 =
符号分隔。例如,一个简单的表单提交可能会创建以下形式的数据:
1 | name=John+Doe&age=30&city=New+York |
4.foreach配合$$是典型变量覆盖漏洞
使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。
5.POST传参写shell
1.为什么利用base64编码一句话木马,因为如果直接写入,<?php exit();会截断。
2.利用a补位,如果不用a补位,一句话木马就解析不出来。
6.extract()函数变量覆盖漏洞
例题:
1 |
|
@parse_str($_SERVER[‘QUERY_STRING’]);
extract($_POST);
$_SERVER
是 PHP 的一个超全局数组,用于存储有关服务器和当前脚本的信息。它包含了许多有用的键值对,可以用于访问和管理服务器环境的各种信息。以下是一些 $_SERVER
超全局数组中常见的键和其含义:
$_SERVER['HTTP_USER_AGENT']
:包含用户代理字符串,用于识别用户的浏览器和操作系统。$_SERVER['HTTP_REFERER']
:包含引导用户到当前页面的 URL。$_SERVER['SERVER_NAME']
:包含当前服务器的主机名。$_SERVER['SERVER_ADDR']
:包含服务器的 IP 地址。$_SERVER['REQUEST_METHOD']
:包含当前请求的 HTTP 方法,如 GET、POST、或其他。$_SERVER['QUERY_STRING']
:包含查询字符串,即 URL 中问号后的部分。$_SERVER['REMOTE_ADDR']
:包含客户端的 IP 地址。$_SERVER['SCRIPT_FILENAME']
:包含当前执行的脚本的文件路径。$_SERVER['REQUEST_URI']
:包含当前请求的 URI(Uniform Resource Identifier),包括路径和查询字符串。$_SERVER['HTTP_HOST']
:包含当前 HTTP 请求中的主机名和端口。
例如
http://www.xxx.com/index.php?p=123&q=456
结果:$_SERVER[“QUERY_STRING”]=“p=123&q=456”
parse_str
是 PHP 中的一个内置函数,其主要作用是将查询字符串解析为变量并放入当前作用域中。它的一般语法如下:
1 | parse_str(string $str, array &$arr) |
$str
是包含查询字符串的字符串。$arr
是一个可选参数,如果提供,解析后的变量将被存储在该数组中。
parse_str
的主要作用包括:
- 解析查询字符串:它可以将一个包含查询字符串的字符串(通常是 URL 查询参数部分)分解成单个变量,并将它们放入当前作用域中。
- 设置变量:它可以根据查询字符串中的名称和值创建对应的 PHP 变量,并将这些变量的值设置为查询字符串中的值。
- 处理表单数据:通常在处理 HTML 表单提交时,
parse_str
可以用来将表单数据提取为 PHP 变量,以便在服务器端进行处理。
示例:
1 | $queryString = "name=John&age=30&city=NewYork"; |
需要注意的是,parse_str
在将查询字符串解析为变量时,会覆盖已经存在的同名变量,因此要小心不要覆盖现有的变量。此外,为了安全性考虑,应该谨慎处理用户提供的查询字符串,以防止潜在的安全风险。
extract($_POST)
:这一行代码尝试将所有 POST 参数提取为独立的 PHP 变量。这将 POST 参数的名称作为变量名,其值作为变量的值,使它们在当前作用域中可用。
1 | ?_POST[flag1]=8gen1&_POST[flag2]=8gen1 |
"_POST[flag1]=8gen1&_POST[flag2]=8gen1"
和 "flag1=8gen1&flag2=8gen1"
这两种查询字符串的格式之间确实有区别。
_POST
部分:在"_POST[flag1]=8gen1&_POST[flag2]=8gen1"
查询字符串中,参数名被放在_POST
数组中,这似乎模拟了 POST 请求中的参数结构,但实际上并不是标准的查询字符串格式。这样的查询字符串通常需要额外的处理来提取其中的参数。extract
函数是用来将数组的键作为变量名,键对应的值作为变量的值,引入到当前作用域中。它可以处理任何关联数组,包括$_POST
数组。标准查询字符串:而
"flag1=8gen1&flag2=8gen1"
查询字符串是标准的查询字符串格式,其中参数名和值直接由等号分隔,并且参数之间使用和号&
分隔。这是常见的 URL 查询字符串格式,适用于 GET 请求和一般的数据传递。
众所周知,php变量名只能是数字字母下划线,传进去的变量名会将 , +,.,[转换成_,若变量中有.,[替换成_后,之后的字符不会再被替换成_,例如a[b.c a_b.c,所以我们post传入504[SYS.COM=123&echo $flag;,得到flag
7.hextobin
1 |
|
8.sql注入时
1 | select * from `123456789`; |
1 | 关于在这里使用 ` 而不是 ’ 的一些解释: |
9.Referer伪造访问来源
伪造访问来源,Referer协议就是告诉服务器我从哪里来。所以抓包修改。
10.User-Agent伪造访问浏览器
用User-Agent
协议来伪造访问工具为 Syclover 浏览器,这个协议就是告诉服务器我是用什么访问的 .修改 User-Agent 为User-Agent: Syclover
11.X-Forwarded-For伪造ip访问
伪造本地ip 127.0.0.1,所以我们可以利用X-Forwarded-For
协议来伪造只需要在 header 添加 X-Forwarded-For:127.0.0.1
12.参数类型只能为数字,怎么办?如何绕过
答案:在变量名前面加空格。
? num**=2;var_dump(scandir(chr(47)))**
? num**=var_dump(scandir(chr(47)))**
为什么要在num前加一个空格?
答:假如waf不允许num变量传递字母,可以在num前加个空格,这样waf就找不到num这个变量了,因为现在的变量叫“ num”,而不是“num”。但php在解析的时候,会先把空格给去掉,这样我们的代码还能正常运行,还上传了非法字符。
PHP的字符串解析特性是什么?
答: PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:1.删除空白符 2.将某些字符转换为下划线(包括空格)【当waf不让你过的时候,php却可以让你过】
13./ ‘’ flag被过滤
1 | ? num=print_r(scandir('/')); |
①:scandir — 列出指定路径中的文件和目录。
②:var_dump()/print_r — 函数用于输出变量的相关信息。
③:chr(47) — 是指ascii码为47的字符为/而/在linux中指的是根目录。
总结:输出并列出指定路径中的文件和根目录。
1 | ? num=print_r(file_get_contents('/flagg')); |
①:file_get_contents() — 函数是用于将文件的内容读入到一个字符串中的首选方法。如果操作系统支持,还会使用内存映射技术来增强性能。
②:var_dump()/print_r — 函数用于输出变量的相关信息。
④:chr(47).chr(102).chr(49).chr(97).chr(103).chr(103) — 指的是ascii码转换为f1agg
总结:输出calc.php文件中f1agg目录的字符串内容。
14.SQL注入 select * from ‘admin’ where password=md5($pass,true)
ffifdyop
129581926211651571912466741651878684928
下面就说明这道题的sql注入的原理,我们可以直接看到后台里面的php判断代码:
1 | <!-- $password=$_POST['password']; |
从代码很容易知道,用mysqli_num_rows()函数来判断是否sql语句查询结果有返回值,那么重点就是那条sql语句。那么唯一可以sql注入的地方就是md5($password,true)这个地方。
那么首先介绍一下md5这个函数。
语法
md5(string,raw)
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: ‘or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: ‘or’6]!r,b
这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 ‘or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。
上面的’ffifdyop‘字符串对应的16位原始二进制的字符串就是” 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c “ 。 ' \ '后面的3个字符连同' \ '算一个字符,比如’ \xc9 ‘,所以上述一共16个。当然,像’ \xc9 ‘这种字符会显示乱码。