文件上传漏洞靶场源码关键语句分析

  • 漏洞靶场是进行渗透技术学习和提高的利器,可以学习到很多基本的Payload和渗透思路,但是学习Payload只是应该达到的基本目标,对过滤本身设置的思路以及对应的绕过思路进行思考和总结才是更为重要的。也就是“渔”和“鱼”的关系。
  • 过滤代码可以使用很多种语言来编写,如javascript、PHP等,代码很多时候是相通或可以类比的,因此对于很多代码功底不是很深的初学者,可以对基本代码进行分析和学习,在遇到其它代码时即使无法做到每行都能看懂,也能够看清楚代码的行文逻辑以及整体框架,只需要对一些关键部分进行精读就可以获取代码防御的核心,进而进行击破。本篇通过对靶场代码的关键语句解读来分析关卡的设置思路。对几个关卡的源代码进行仔细分析,来获取关卡设置的逻辑框架,并分析核心部分的代码语句,这对于后续的闯关以及思路的拓展是很有帮助的。
    在这里插入图片描述
    这是upload第5关的源代码,相信payload很容易就可以搜到,下面我们对它的源码框架进行分析:
    科普一下基础知识,该源码是用PHP语言进行编写的,代码中可以看到很多$符号,这是PHP语言中表示变量的,同时,PHP语言是一种弱类型语言,也就是说它再创建变量时不需要进行声明,直接赋值即可,这一点与C等强类型的语言有区别。
    1.可以看到源码中有很多的变量,我们需要搞清楚其中比较重要的变量的含义:
    $is_upload:用来定义我们上传文件是否成功,布尔型变量,TRUE代表成功,反之代表失败。
    $msg:用来进行提示的变量,一般是在文件上传出问题的时候进行的提示,在这里是文字性的提示,如:上传出错,文件类型不允许上传等。
    $_POST:变量用于收集来自 method=“post” 的表单中的值,需与HTML中的表单进行配合,本处用来获取提交(submit)的文件。
    $deny_ext:该源代码的核心变量之一,用来定义扩展名黑名单,不同关卡定义的黑名单可能不同,需要注意的是这里仅仅定义的是后缀名的黑名单,及时后缀名全部被意义封死,还是可以想办法绕过,因为服务器不会只验证完后缀名就完事了,还会对你的后缀名进行各种处理(见之后的变量)。
    $file_name:定义文件名称,这里配合了一个 trim函数,作用是移除某个字符串中的某些字符。
    $file_ext :定义了文件后缀名这个变量,因为上面的 $deny_ext仅仅定义了后缀名黑名单,后缀名本身这个变量还没有进行定义(赋值)。
    $_FILES:PHP中的全局数组变量,一般会有2个参数,第一个参数是表单的 input name,第二个下标可以是 “name”, “type”, “size”, “tmp_name” 或 “error”。例如:
  • $_FILES[“file”][“name”] - 被上传文件的名称
  • $_FILES[“file”][“type”] - 被上传文件的类型
  • $_FILES[“file”][“size”] - 被上传文件的大小,以字节计
  • $_FILES[“file”][“tmp_name”] - 存储在服务器的文件的临时副本的名称
  • $_FILES[“file”][“error”] - 由文件上传导致的错误代码
    $img_path :定义文件的上传路径(这个变量非常关键,直接决定着上传后的文件能否被执行,重点关注

了解了每个变量的作用,我们对关键语句进行分析:
1.第3-10行,用了一个if条件语句,如果上传的路径存在,继续执行后面的语句,下面的几行都是对文件的后缀名进行处理的,定义了一系列_ext结尾的变量,其中最重要的是第五行定义的$deny_ext,这个是后缀黑名单,这个数组中的字符串都是不允许上传的后缀。之后的trim函数是删除指定的字符,这里把文件中的name删掉,也就是留下后缀,strchr是一个函数,它的功能是查询某个字符第一次出现的位置并返回剩下的部分,这里是查询第一次出现“.”的位置并把右侧的部分返回。后面几句话是针对我们常用的绕过方法的,比如去掉末尾的点,去掉空格等等。在这里可以去看哪些常用操作没有被过滤,就可以用来做payload了(比如这里没有转换大小写)。这个if对应的是第24行的else,提示手工创建文件夹。
2.12-18行,用了另一个if语句,插在上一个if中(因为只是定义了一些用来过滤的后缀名的变量,还没有函数或者条件语句来使用这些变量来触发过滤规则),这些行就是嵌入了一个if语句来引用上述的过滤变量,真正对我们的后缀名下手了,12行的if条件用了in_arry函数,也就是当第一个参数中包含 $deny_ext这个黑名单但数组中的值的时候,if内的语句就会执行(这里加了叹号,也就是没有出发黑名单才执行上传操作)。如果!inarry函数检测到文件后缀中有非法值就会跳转到21行,提示文件类型不允许上传。
当语句通过!inarry函数的检测发现不在黑名单中,那么我们的文件就可以顺利上传啦!这时候还有非常关键的一步,就是我们的文件后缀是经过处理的,最终它上传之后是以什么后缀来存在的呢?这些是由13-14行这两行关键语句来确定的,13行先定义了一个临时文件,给我们上传的文件换了一个身份,便于函数进行长传处理。14行是最为关键的,这行定义了上传的路径,而路径中包含文件夹的路径,以及文件的名称和后缀,这一点很重要(可以看出实际上这个路径是几个东西拼接起来的,分别是上传的文件夹路径、文件名称、后缀三个东西)。可以看出这里对文件进行了重命名,命名的内容是当前的日期以及一个1000到9999的随机数字的组合。最后一项是后缀名 $file_ext,核心在于这个变量是经过上面一个if中各种处理的,如果它被处理的不成样子(不是服务器认识的脚本后缀),上传脚本文件也就没有意义了,因为它的后缀无法被当做脚本执行。
这里的拼接方法是拼接后缀名的,有时候会直接拼接文件名,如第9关
在这里插入图片描述
知道了关键的一点,就产生了一种绕过方法,就是构造 xxx.php.空格.****的结构来绕过,这样有什么效果呢,结合上面的过滤语句,首先文件名xxx被去掉,留下“后缀”,然后末尾的点被删掉,留下PHP.空格,最后一句收尾去空把空格删掉,处理后的后缀就变成了PHP.,相当于点绕过了。
但是有个前提,路径拼接方法一定是文件名才行,如果拼接的是后缀名,就会造成没有后缀名,为什么呢?回到第7行,去掉文件末尾的点,假设我们文件名为1.php. .文件名被处理之后变成1.php.空格 ,而后缀呢?因为识别后缀的函数是strchr,它会从右向左找到第一个点,这个点以及之后的东西会被认为是后缀,如果我们用这种办法,后缀就变成了空格,那么现在梳理一下:
1.文件名file_name为1.php.
2.后缀是空
问题就集中在最后的路径拼接上,如果使用的是文件名拼接,那么我上传之后的后缀就是.php.(这里被函数截取取出的后缀只是为了绕过验证,并没有被用在最后上传的文件上);而如果路径拼接的是后缀名,就不行了,我们上传的文件后缀就变成空(没有后缀)了。
关键点:路径拼接的方法决定我们上传文件的后缀,前面被处理的“后缀”指的是 $file_ext这个变量,它不一定是真实的后缀,关键取决于拼接方法,路径拼接的是 $file_ext那么它就是真实后缀,如果拼接的是 $file_name,那么不管 $file_ext被处理成什么样子,都不影响文件的后缀名,因为后缀名是由file_name变量决定的。
事实证明,第9关可以用这种办法绕过,如果在路径拼接使用后缀名的关卡用的话,上传的文件是没有后缀的(无法解析)。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值