对于flask/php来说,如果waf解析方式和后端不相同,也可能会错误判断文件和非文件参数,但是Java后端很难使用,因为对于name的取值会导致后端无法正确获取。但是这个取值特性依旧有用,下文文件扩展名将进行介绍。
文件扩展名
前文主要提出一些mutlipart整体上的waf绕过,在源站后端解析正常的情况下让waf解析失败不进入规则匹配,或者waf解析与后端有差异,判断是否为文件失败,导致规则无法匹配,或者filename参数根本没有进入waf的规则匹配。无论是在CTF比赛中还是在实际渗透测试中,如何绕过文件扩展名是大家很关注的一个点,所以这一段内容主要介绍,在waf解析到filename参数的情况下,从协议和后端解析的层面如何绕过文件扩展名。
其实这种绕过就一个思路,举个简单的例子filename="file_name.php",对于一个正常的waf来说取到file_name.php,发现扩展名为php,接着进行拦截,此处并不讨论waf规则中不含有php关键字等等waf规则本身不完善的情况,我们只有一个目标,那就是waf解析出的filename不出现php关键字,并且后端程序在验证扩展名的时候会认为这是一个php文件。
从各种程序解析的代码来看,为了让waf解析出现问题,干扰的字符除了上文说的引号,空格,转义符,还有:;,这里还是要分为两种形式的测试。
a. token形式Content-Disposition: form-data; name=key3; filename=file_name:.phpContent-Disposition: form-data; name=key3; filename=file_name'.php
Content-Disposition: form-data; name=key3; filename=file_name".php
Content-Disposition: form-data; name=key3; filename=file_name\".php
Content-Disposition: form-data; name=key3; filename=file_name .php
Content-Disposition: form-data; name=key3; filename=file_name;.php
前五种情况flask/Java解析结果都是一致的,会取整体作为filename的值,都是含有php关键字的,这也说明如果waf解析存在差异,将特殊字符直接截断取值,会导致waf被绕过。
最后一种情况,flask/Java/php解析都会直接截断,filename=file_name,这样后端获取不了,无论waf解析方式如何,无法绕过。
对于php而言,前三种会如flask以一样,将整体作为filename的值,第五种空格类型,php会截断,最终取filename=file_name,这种容易理解,当没出现引号时,出现空格,即认为参数值结束。
然后再测试转义符号的时候,出现了从\开始截断,并去\后面的值最为filename的值,这种解析方式和boundary解析也不相同,当然双引号和单引号相同效果。、
看代码才发现,php并没有把\当作转义符号,而是贴心地将filename看做一个路径,并取路径中文件的名称,毕竟参数名是filename啊:)
所以这个解析方式和引号跟本没关系,只是php在解析filename时,会取最后的\或者/后面的值作为文件名。
b. quoted string形式
Content-Disposition: form-data; name=key3; filename="file_name:.php"
Content-Disposition: form-data; name=key3; filename="file_name'.php"
Content-Disposition: form-data; name=key3; filename="file_name".php"
Content-Disposition: form-data; name=key3; filename="file_name\".php"
Content-Disposition: form-data; name=key3; filename="file_name .php"
Content-Disposition: form-data; name=key3; filename="file_name;.php"
flask解析结果还是依照_option_header_piece_re正则,除第三种filename取file_name之外,其他都会取双引号内整体的值作为filename,转义符具有转义作用。php第三种也会解析出file_name,但是在第四种转义符是具有转义作用的,所以进入上文的*php_ap_basename函数时,是没有\的,所以其解析结果也会是file_name".php,使用单引号的情况和上文引号部分分析一致。
对于Java来说,除第三种情况外,都是会取引号内整体作为filename值,但是第三种情况就非常有趣,上文引号部分已经分析,Java会继续取值,那么最后filename取值为"file_name".php"。
所以对于Java这个异常的特性来说,通常waf会像php/flask那样在第一次出现闭合双引号时,直接取双引号内内容作为filename的取值,这样就可以绕过文件扩展名的检测。