今天学习了一下PHP中filter_var()函数漏洞,来写下自己的第一篇博客,记录一下自己的菜鸟时光。
首先看看filter_var吧:
filter_var: (PHP 5 >= 5.2.0, PHP 7)
功能 :使用特定的过滤器过滤一个变量
定义 :`mixed filter_var ( mixed$variable [, int $filter = FILTER_DEFAULT [, mixed$options ]] )`
常用的过滤器有:
FILTER_SANITIZE_EMAIL:删除所有字符,除了字母、数字以及 !#$%&'*+-/=?^_{|}~@.[]
FILTER_SANITIZE_URL:删除所有字符,除了字母、数字以及 $-_.+!*'(),{}|\\^~[]<>#%";/?:@&=
网上找了道CTF练习题,是红日安全的PHP代码审计中的Day2,题目如下:
// index.php
You have curl {$site_info['host']} successfully!
搭建好环境后访问一下:
看到有提示,直接把?url=http://sec-redclub.com粘在后边:
发现直接包含了网站源码,看了下index.php发现第三行用了filter_var函数的FILTER_VALIDATE_URL过滤器,过滤了get到的url,接着又用了parse_url过滤url。再往下面看,看到了preg_match正则表达式,居然要求url必须以sec-redclub.com结尾。之后,看到了exec,?命令执行。
然后想怎么去把我想要执行的命令在url中不被过滤,首先就是绕过fliter_var,网上看了各大佬的帖子,发现用 ; & ? / , @ #这几个符号可以有命令分隔符的作用,如:http://localhost/index.php?url=http://demo.com&sec-redclub.com,就可以只包含demo.com的源码。
接着要绕过 parse_url 函数,并且满足 $site_info['host'] 的值以 sec-redclub.com 结尾,payload如下:
http://192.168.139.129/day/day2/?url=0://";ls;%23;sec-redclub.com:80
解释一下:我所理解的parse_url在这里的作用是提取url中的有效字段,比如http://和:80就被过滤了。然而,为什么在ls前加了 " 在ls后加了 %23呢?首先,看exec那一行,输入 " 是为了与第一个 “ 闭合,输入 %23 是为了 解析为#注释掉后面的字符,如果直接写#的话会被parse_url过滤。
发现了flag.php,直接cat,payload如下:
http://192.168.139.129/day/day2/?url=0://%22;cat 这里要注意cat flag.php时,空格要用特殊字符绕过,不然也会被过滤。