bugku 变量

空扰寡人 提交于 2020-02-27 06:53:34

<?php  

error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
    $args $_GET['args'];
    if(!preg_match("/^\w+$/",$args)){
        die("args error!");
    }
    eval("var_dump($$args);");
}
?>

这是这道题目,不说了,先查函数功能。破局点就在函数的漏洞中。

error——reporting(0) 参数是0禁止报错。

highlight_file(_file_):

语法

 

highlight_file(filename,return)

 

参数描述
filename 必需。要进行高亮处理的 PHP 文件的路径。
return 可选。如果设置 true,则本函数返回高亮处理的代码。

 

说明

 

本函数通过使用 PHP 语法高亮程序中定义的颜色,输出或返回包含在 filename 中的代码的语法高亮版本。

 

许多服务器被配置为对带有 phps 后缀的文件进行自动高亮处理。例如,在查看 example.phps 时,将显示该文件被语法高亮显示的源代码。要启用该功能,请把下面这一行添加到 httpd.conf

 

AddType application/x-httpd-php-source .phps

 

返回值

 

如果 return 参数被设置为 true,那么该函数会返回被高亮处理的代码,而不是输出它们。否则,若成功,则返回 true,失败则返回 false。

 

提示和注释

警告:需要注意的是,在使用 highlight_file() 函数时,请不要因为疏忽而泄露诸如密码或其他类型的敏感信息,否则会出现潜在的安全风险。

例子

"test.php":

<html>
<body>
<?php
highlight_file("test.php");
?>
</body>
</html>

输出:

<html> 
<body> 
<?php 
highlight_file("test.php"); 
?>
</body> 
</html>

在浏览器中查看的结果类似这样:

<html>
<body>
<code>
<span style="color: #000000">&lt;html&gt;
<br />
&lt;body&gt;
<br />
<span style="color: #0000BB">&lt;?php
<br />highlight_file</span>
<span style="color: #007700">(</span>
<span style="color: #DD0000">"test.php"</span>
<span style="color: #007700">);<br /></span>
<span style="color: #0000BB">?&gt;<br /></span>
&lt;/body&gt;
<br />
&lt;/html&gt;</span>
</code>
</body>
</html>

preg_match

(PHP 4, PHP 5, PHP 7)

preg_match — 执行匹配正则表达式

说明

preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] ) : int

搜索subjectpattern给定的正则表达式的一个匹配.

参数

 

pattern

要搜索的模式,字符串类型。

subject

输入字符串。

matches

如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。

flags

flags可以被设置为以下标记值:

PREG_OFFSET_CAPTURE

如果传递了这个标记,对于每一个出现的匹配返回时会附加字符串偏移量(相对于目标字符串的)。 注意:这会改变填充到matches参数的数组,使其每个元素成为一个由 第0个元素是匹配到的字符串,第1个元素是该匹配字符串 在目标字符串subject中的偏移量。

<?php
preg_match('/(foo)(bar)(baz)/''foobarbaz'$matchesPREG_OFFSET_CAPTURE);
print_r($matches);
?>

以上例程会输出:

Array
(
    [0] => Array
        (
            [0] => foobarbaz
            [1] => 0
        )

    [1] => Array
        (
            [0] => foo
            [1] => 0
        )

    [2] => Array
        (
            [0] => bar
            [1] => 3
        )

    [3] => Array
        (
            [0] => baz
            [1] => 6
        )

)
offset

通常,搜索从目标字符串的开始位置开始。可选参数 offset 用于 指定从目标字符串的某个位置开始搜索(单位是字节)。

Note:

使用offset参数不同于向preg_match() 传递按照位置通过substr($subject, $offset)截取目标字符串结果, 因为pattern可以包含断言比如^$ 或者(?<=x)。 比较:

<?php
$subject "abcdef";
$pattern '/^def/';
preg_match($pattern$subject$matchesPREG_OFFSET_CAPTURE3);
print_r($matches);
?>

以上例程会输出:

Array
(
)

当这个示例使用截取后传递时

<?php
$subject "abcdef";
$pattern '/^def/';
preg_match($patternsubstr($subject,3), $matchesPREG_OFFSET_CAPTURE);
print_r($matches);
?>

将会产生匹配

Array
(
    [0] => Array
        (
            [0] => def
            [1] => 0
        )

)

返回值

preg_match()返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。 如果发生错误preg_match()返回 FALSE

更新日志

 

版本说明
5.3.6 如果 offsetsubject 的长度还要大则返回 FALSE
5.2.2

命名子组可以接受(?<name>)(?'name') 以及(?P<name>)语法。之前版本仅接受(?P<name>)语法。

 

if(!preg_match("/^\w+$/",$args)){

 

作者的话(引用)

正则表达式的定义可以这样简单概括:“正则表达式描述了一种字符串匹配的模式,通过这个模式在特定的函数中对字符串进行匹配、查找、替换及分割等操作。作为一个匹配模板,是由原子、特有功能字符及模式修正符三部分组成的文字模式。”这里是我总结PHP正则表达式的定义及简单使用。
术语概念

    元字符:具有特殊含义的字符,如^(开始)和$(结束);
    原子:用来匹配的字符,如果 \d(匹配0到9);

定界符

除了字母、数字和反斜线‘\’以外的任何字符都可以作为定界符,如 #、!等都是可以作为定界符,但是行业习惯这样做:/正则表达式/。
元字符
元字符     含义
*     0次1次或多次
+     1次或多次
?     0次或1次
.     除了除了换行外的其他字符
|     或选择
{n}     正好n次
{n,}     不少于n次
{n,m}     区间,>=n,<=m
^或\A     正则的开始
$或\Z     正则的结束
\b     单词的边界
\B     单词边界以外
[]     其中任意一个
[^]     除了[]中的以外
()     作为一个整体
原子

一些特殊符号,如:* ’ ” + \等,需要使用 \ 来进行转义。
原子字符     含义     举例
\cx     匹配由x指明的控制字符     如 \cM匹配一个回车符,x的值必须为A~Z或a~z之一,否则将c视为匹配‘c’
\f     匹配一个换页符     
\n     匹配一个换行符     
\r     匹配一个回车符     
\t     匹配一个指标符     在不使用表格的情况下在垂直方向按列对齐文本
\v     匹配一个垂直制表符     
        
\d     0到9任意一个数字     等价于[0-9]
\D     除0到9之外的字符     等价于[^0-9]
\s     空白字符     等价于[\f\n\r\t\v]
\S     除了空白字符     
\w     数字、字母或下划线     [0-9a-zA-Z]
\W     除了数字、字符或下划线     可以理解为特殊字符,如*、$等

示例:匹配139开头的手机号码

    $str = '13912345678';
    $pattern = '/^139\d{8}$/';
    $res_int = preg_match($pattern, $str, $matches);
    if ($res_int) {
        var_dump($matches);
    } else {
        var_dump('无法匹配');
    }

    1
    2
    3
    4
    5
    6
    7
    8

模式修正符

在最后一个细线‘/’之后使用,如 /php/i
模式修正符     含义
i     不区分大小写
m     将字符视为多行
s     将字符串视为单行,换行符作为普通的字符
x     忽略空白
U     取消贪婪模式,等同于在数量符之后添加一个问号,比如 .*?
后向引用

使用()时,会将其相关的匹配存储到一个临时的缓存区,缓存区编号从1-99,使用 \1(“\1”)来获取缓存区内容,可以使用 ?: 或 ?= 或 ?! 来忽略相关的缓存内容。
/(windows)(linxu)\2/ 这样是使用第二个缓存区的内容,linux;
/(?:windows)(linux)\1/,忽略了第一缓存区的内容,linux。
贪婪模式

概念不好解释,直接上代码去理解

    $str = '发财123发财发财456发财发财abc发财';
    $pattern = '/发财.*发财/'; // 匹配始末发财中的内容
    $pattern2 = '/发财.*?发财/'; // 匹配所有发财中的内容
    $pattern3 = '/发财.*发财/U'; // 效果等同上一行
    preg_match_all($pattern, $str, $matches);
    preg_match_all($pattern2, $str, $matches2);
    preg_match_all($pattern3, $str, $matches3);
    var_dump($matches);
    var_dump($matches2);
    var_dump($matches3);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

结果是这样的
这里写图片描述
中文匹配

这个不常用到,知道要点即可。
- UTF-8汉字编码范围是:0x4e00–0x9fa5,使用 u 模式修正符使字符串被当成UTF-8。
- gb2312汉字编码范围是:0xb0–0xf7,0xa1–0xfe,使用 chr 将其转为字符串。
常用函数

preg_match
preg_match_all

preg_match返回0或者1,它在完成第一次匹配后停止搜索;preg_match_all会一直匹配目标到结束;如果如果发生错误preg_match()返回 FALSE。

    1

preg_replace
preg_split
使用命名子组

有多个匹配条件,获取其中的某个条件下的匹配结果。

$str = 'foobar: 2008';

preg_match('/(?P<name>\w+): (?P<digit>\d+)/', $str, $matches);

/* 下面例子在php 5.2.2(pcre 7.0)或更新版本下工作, 然而, 为了后向兼容, 上面的方式是推荐写法. */
// preg_match('/(?<name>\w+): (?<digit>\d+)/', $str, $matches);

var_dump($matches);

    1
    2
    3
    4
    5
    6
    7
    8

输出结果:
这里写图片描述

或者不使用 ?P name 这样的语法:

$str = 'foobar: 2008';
preg_match('/(\w+): (\d+)/', $str, $matches2);
// 这样会把结果直接保存到内容中
var_dump($matches2);

    1
    2
    3
    4

输出结果:
这里写图片描述
---------------------
作者:wmw1464228354
来源:CSDN
原文:https://blog.csdn.net/wmw1464228354/article/details/81276715
版权声明:本文为博主原创文章,转载请附上博文链接!

一、校验数字的表达式 

1 数字:
^[0-9]*$
2 n位的数字:
^\d{n}$
3 至少n位的数字:
^\d{n,}$
4 m-n位的数字:
^\d{m,n}$
5 零和非零开头的数字:
^(0|[1-9][0-9]*)$
6 非零开头的最多带两位小数的数字:
^([1-9][0-9]*)+(.[0-9]{1,2})?$
7 带1-2位小数的正数或负数:
^(\-)?\d+(\.\d{1,2})?$
8 正数、负数、和小数:
^(\-|\+)?\d+(\.\d+)?$
9 有两位小数的正实数:
^[0-9]+(.[0-9]{2})?$
10 有1~3位小数的正实数:
^[0-9]+(.[0-9]{1,3})?$
11 非零的正整数:
^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
12 非零的负整数:
^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
13 非负整数:
^\d+$ 或 ^[1-9]\d*|0$
14 非正整数:
^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
15 非负浮点数:
^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
16 非正浮点数:
^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
17 正浮点数:
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
18 负浮点数:
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
19 浮点数:
^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ 

二、校验字符的表达式


三、特殊需求表达式 

1、 Email地址:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2 、域名:
[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3 、InternetURL:
[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4 、手机号码:
^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
5 、电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):
^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
6 国内电话号码(0511-4405222、021-87888822):
\d{3}-\d{8}|\d{4}-\d{7}
7 、身份证号:
15或18位身份证:
^\d{15}|\d{18}$
15位身份证:
^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位身份证:
^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
8、 短身份证号码(数字、字母x结尾):
^([0-9]){7,18}(x|X)?$

^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
9 、帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):
^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10 、密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):
^[a-zA-Z]\w{5,17}$
11 、强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
12、 日期格式:
^\d{4}-\d{1,2}-\d{1,2}
13、 一年的12个月(01~09和1~12):
^(0?[1-9]|1[0-2])$
14 、一个月的31天(01~09和1~31):
^((0?[1-9])|((1|2)[0-9])|30|31)$
15 、钱的输入格式:
16 、1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":
^[1-9][0-9]*$
17、 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:
^(0|[1-9][0-9]*)$
18 、3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:
^(0|-?[1-9][0-9]*)$
19 、4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:
^[0-9]+(.[0-9]+)?$
20 、5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:
^[0-9]+(.[0-9]{2})?$
21、 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:
^[0-9]+(.[0-9]{1,2})?$
22、 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:
^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
23 、8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:
^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
24 、备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
25 、xml文件:
^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
26 、中文字符的正则表达式:
[\u4e00-\u9fa5]
27 、双字节字符:
[^\x00-\xff]
(包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
28 、空白行的正则表达式:\n\s*\r (可以用来删除空白行)
29 、HTML标记的正则表达式:
<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
30 、首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
31 、腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
32 、中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
33、 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用

eval()

把字符串当成 PHP 代码来计算:

<?php $string = "beautiful"; $time = "winter"; $str = 'This is a $string $time morning!'; echo $str. PHP_EOL; eval("\$str = \"$str\";"); echo $str; ?>

以上代码执行输出结果为:

This is a $string $time morning!
This is a beautiful winter morning!

 


定义和用法

eval() 函数把字符串按照 PHP 代码来计算。

该字符串必须是合法的 PHP 代码,且必须以分号结尾。

注释:return 语句会立即终止对字符串的计算。

提示:该函数对于在数据库文本字段中供日后计算而进行的代码存储很有用。


语法

eval(phpcode)

 

参数描述
phpcode 必需。规定要计算的 PHP 代码。

技术细节

返回值: 除非在代码字符串中调用 return 语句,则返回传给 return 语句的值,否则返回 NULL。如果代码字符串中存在解析错误,则 eval() 函数返回 FALSE。
PHP 版本: 4+

 开始做题:

遇见这种情况咋办?是eval()函数执行不了var_dump($$agrs);所以有三个分析方向:

第一:preg_match 存在漏洞。

第二:eval()存在漏洞。

第三:var_dumo($$args);存在错误。

$$这是啥?原来是可变变量,改变变量的名称。

可变变量

有时候使用可变变量名是很方便的。就是说,一个变量的变量名可以动态的设置和使用。一个普通的变量通过声明来设置,例如:

<?php
$a 'hello';
?>

一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。在上面的例子中 hello 使用了两个美元符号($)以后,就可以作为一个可变变量的变量了。例如:

<?php
$$a 'world';
?>

这时,两个变量都被定义了:$a 的内容是“hello”并且 $hello 的内容是“world”。因此,以下语句:

<?php
echo "$a ${$a}";
?>

与以下语句输出完全相同的结果:

<?php
echo "$a $hello";
?>

它们都会输出:hello world。

要将可变变量用于数组,必须解决一个模棱两可的问题。这就是当写下 $$a[1] 时,解析器需要知道是想要 $a[1] 作为一个变量呢,还是想要 $$a 作为一个变量并取出该变量中索引为 [1] 的值。解决此问题的语法是,对第一种情况用 ${$a[1]},对第二种情况用 ${$a}[1]

类的属性也可以通过可变属性名来访问。可变属性名将在该调用所处的范围内被解析。例如,对于 $foo->$bar 表达式,则会在本地范围来解析 $bar 并且其值将被用于 $foo 的属性名。对于 $bar 是数组单元时也是一样。

也可使用花括号来给属性名清晰定界。最有用是在属性位于数组中,或者属性名包含有多个部分或者属性名包含有非法字符时(例如来自 json_decode()SimpleXML)。

 

Example #1 可变属性示例

<?php
class foo {
    var $bar 'I am bar.';
    var $arr = array('I am A.''I am B.''I am C.');
    var $r   'I am r.';
}

$foo = new foo();
$bar 'bar';
$baz = array('foo''bar''baz''quux');
echo $foo->$bar "\n";
echo $foo->$baz[1] . "\n";

$start 'b';
$end   'ar';
echo $foo->{$start $end} . "\n";

$arr 'arr';
echo $foo->$arr[1] . "\n";
echo $foo->{$arr}[1] . "\n";

?>

以上例程会输出:


I am bar.
I am bar.
I am bar.
I am r.
I am B.
Warning

注意,在 PHP 的函数和类的方法中,超全局变量不能用作可变变量。$this 变量也是一个特殊变量,不能被动态引用。

仿佛无计可施,咋办?破局点——全局变量。

最关键的是最后的$$args,这是可变变量的意思,如$args的值是另一个变量的变量名。那么$$args就代表另一个变量。所以我们就给args赋值一个变量名,那么PHP的九大全局变量,一个一个试。

  • $_POST [用于接收post提交的数据]
  • $_GET [用于获取url地址栏的参数数据]
  • $_FILES [用于文件就收的处理img 最常见]
  • $_COOKIE [用于获取与setCookie()中的name 值]
  • $_SESSION [用于存储session的值或获取session中的值]
  • $_REQUEST [具有get,post的功能,但比较慢]
  • SERVER[是预定义服务器变量的一种,所有SERVER[是预定义服务器变量的一种,所有_SERVER [是预定义服务器变量的一种,所有_SERVER开头的都
  • $GLOBALS [一个包含了全部变量的全局组合数组]
  • $_ENV [ 是一个包含服务器端环境变量的数组。它是PHP中一个超级全局变量,我们可以在PHP 程序的任何地方直接访问它]

当args=GLOBALS时,flag出现。

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!