打开题目发现是一个登录注册页面,然后利用sql注入的方法进行测试结果没有反应,于是使用dirsearch去扫一下网站看看有没有什么东西,扫到了register.php和www.zip,看到有网站源码就会顺利很多了
下载下源码来分析一下,
register.php
这是注册页面的php代码,只是限制了username和password的长度和是否存在。
注册登录成功以后跳转到了update.php
分析一下update.php的代码
可以通过post方式上传phone、email、nickname、photo,并且限制phone 长度为11位,nickname长度小于10位,且只能为字母和数字;对上传的phone,email,nickname,photo进行序列化
class.php 中的限制:
<?php
......
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}
.....
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
......
update_profile 中对 new_profile 用 filter 进行了过滤;
filter 中将 ‘select’, ‘insert’, ‘update’, ‘delete’, ‘where’ 等词用 ‘hacker’ 替换掉.
profile.php
将上传的内容反序列化,并读取photo的内容,然后并将photo中的内容用base64编码显示出来。
config.php
里面有flag变量但是flag的值我们看不到。
解题思路:
所以现在的解题点就是利用profile.php中的file_get_contents()函数将config.php中的flag读取出来。但是file_get_contents()函数读取的是photo,所以我们要把$profile[‘photo’]替换为config.php这里用到了字符串逃逸,也就是要让config,php成为序列化的一部分,可以利用的是反序列化字符串逃逸。
这个数据被序列化之下是:
a:4:{s:5:"phone";s:11:"11223344556";s:5:"email";s:10:"123@qq.com";s:8:"nickname";s:3:"123";s:5:"photo";s:39:"upload/07cc694b9b3fc636710fa08b6922c42b";}
我们可以将";}s:5:“photo”;s:10:“config.php”;}写入到nickname中形成字符串逃逸,变为:
a:4:{s:5:"phone";s:11:"11223344556";s:5:"email";s:10:"123@qq.com";s:8:"nickname"";}s:5:“photo”;s:10:“config.php”;};s:3:"123";s:5:"photo";s:39:"upload/07cc694b9b3fc636710fa08b6922c42b";}
我们想要写入正因为在传入数据库时会进行正则匹配导致where会变为hacker由5个字符变为6个字符,";}s:5:“photo”;s:10:“config.php”;}一共有34个字符,我们想要将";}s:5:“photo”;s:10:“config.php”;}写入到nickname中而不不被解析为nickname的值,所以需要在nickname中写入34个where,这样长度就增加了34个,所以会把";}s:5:“photo”;s:10:“config.php”;}挤出nickname中而被当做photo来解析。这样就可以达到我们想要的效果去读取config.php的内容。
而在updata中对nickname进行了过滤这里先对它进行了正则,这个正则的意思是匹配除了a-zA-Z0-9_之外的字符,因为 “^” 符号是在 “[]” 里面,所以是非的意思,不是开始的意思。然后 “||” 后面判断了它的长度是否大于10。我们上传的参数肯定大于10了,所以这里需要绕过
这两个判断的绕过就要引出神奇的数组了,这里我牵了张表:
md5(Array()) = null
sha1(Array()) = null
ereg(pattern,Array()) =null
preg_match(pattern,Array()) = false
strcmp(Array(), “abc”) =null
strpos(Array(),“abc”) = null
strlen(Array()) = null
所以我们传入数组,就能绕过。
传参
注意需要将nickname变为数组nickname[]