Using php://filter for local file inclusion
I came across a website where the site was vulnerable to LFI (local file inclusion) however the inclusion was done using a require_once and the script appended a .php extension to the end of the file; furthermore it was not vulnerable to null byte injection which meant that if I did include a file that:
- The file would have to be valid PHP syntax
- I would not be able to see anything contained between <? ?> tags
- Anything I could include would be executed.
- The file would have to end in the PHP extension
I tried to see if I could include remote files by specifying a URL as the parameter, sadlyallow_url_include was turned off so that failed. When I specified a valid PHP page it simply returned the normal page as expected.
The solution that allowed me to view the source of any PHP file was to use the functionphp://filter/convert.base64_encode/resource which has been available since PHP 5.0.0
1 | http: //www.example.com/index.php?m=php://filter/convert.base64-encode/resource=index |
This forces PHP to base64 encode the file before it is used in the require statement. From this point its a matter of then decoding the base64 string to obtain the source code for the PHP files. Simple yet effective..
Once you’ve got the source code for one file you can inspect it for further vulnerabilities such as SQL injections and additional PHP files referenced via include or require.
3 Responses to Using php://filter for local file inclusion
'Web_Hacking' 카테고리의 다른 글
웹쉘 에사용되는 함수 점검하는 스크립트~ (Script, Finding using function in webshell) (0) | 2012.11.29 |
---|---|
Zeroboard XE 1.5.3.3 admin 페이지의 webshell 인젝션 취약점 (0) | 2012.11.26 |
SQL injection 중 괜찮은 방법들.. (0) | 2012.08.12 |
sql injection awk 를 이용하여 빠르게 점검하기. (0) | 2012.08.12 |
XSS 다양한 우회 패턴 (0) | 2012.08.08 |
That’s pretty slick ;)
I have a feeling that this can be prevented by using basename();
1
<?php
2
if
(isset(
$_GET
[
'm'
])){
3
$file
=
basename
(
$_GET
[
'm'
]);
4
require_once
'$file'
;
5
}
What are your thoughts on that?
If you just use basename the strings going to end up as “resource=index.php”, checking to see if the file exists (using file_exists) is probably a safer method as it will return false for any php://filter files. A quick preg_match couldn’t hurt either…
1
if
(preg_match(
"/^[A-Z0-9]+$/i"
,
$_GET
[
'm'
])) {
2
if
(
file_exists
(
$_GET
[
'm'
])) {
3
require_once
(
$_GET
[
'm'
]);
4
}
5
}
Why not just have a white list array, even the `$_GET['m']` could produce unwanted results, and better to not leave it up to that.
1
$whiteList
=
array
(
'index'
=>
'index.php'
,
'about'
=>
'about.php'
);
2
if
(in_array(
$_GET
[
'm'
],
$whiteList
)) {
3
require_once
(
$whiteList
[
$_GET
[
'm'
]]);
4
}
else
{
5
require_once
(
$whiteList
[
'index'
]);
6
}
This way, you can easily default it, you know the files that will be included and you leave nothing up to chance. And, if you wanted to, you could name the names of the actual files different to prevent direct access.