很多人说 Web 应用渗透测试是一个应用已有工具和方法的已知区域,但其实每个项目都会遇到一些新的技术和令人感兴趣的新场景,这些挑战令人兴奋。我们从相对简单的 SQL 盲注入手,展现其如何被利用到可以执行远程代码。我们在测试的过程中会用到 Dunacn ,这是我们用来辅助 SQL 盲注利用的简单框架。
最初的漏洞存在于应用编辑器,提交的参数之一只是简单的连接成了 SQL 查询语句,而没有进行检查和过滤。但是我不能通过应用程序的响应或错误信息来得到注入的结果。因此,这是一个简单的盲注场景,但是对于从数据库中提取想要的数据仍然不容易。为了简单起见我使用了 SQLmap,但是我无法得到工具可识别的注射参数。像往常一样,我还是使用了 Duncan,Duncan 可以提取像这样场景下的数据。我创建了一个简单的模块,使用下列表达式来执行请求(后端使用的数据库是 PostgreSQL):
"ascii(substr(cast((%s) as varchar),%d,1))<%d"
Duncan 会用可执行的请求参数来代替第一个占位符(%s),第二个占位符指明了我要猜测的字符位置,第三个占位符是猜测的字符值。Duncan 会开始执行多线程的请求来检索注入请求的结果。在映射数据库结构后,我就有希望快速得到能登录应用管理交互界面的密码。
$ wc -l mytarget.py # Including blank lines, imports, and everything... 22 mytarget.py $ python run_duncan.py --use mytarget.SimpleDuncan --query "select password from users where id=1" --pos-end 33 --threads 5 --charset 0123456789abcdef deadbeefdeadbabedeadbea7deadc0de
为了提高效率,我使用自定义的字符集,并且基于之前测试的结果设置了最大长度,看起来该应用程序以十六进制存储了密码的 MD5 哈希值。我成功的得到了一些重要用户的密码哈希值,我也得到了我自己的哈希值以便进行验证。我尝试了帐号、密码、相关信息的多种组合,但是这都和数据库中存储的不一致。
很明显,在密码的哈希过程中有“盐”的参与,但我不知道“盐”是什么。有可能是前缀形式、后缀形式或者级联哈希构造(如 MD5(MD5(password)||salt)
)等,但是没办法猜出它使用的是哪种方法。幸运的是,我记起我看过的 一篇文章
,讲的是如何使用数据库的元数据来 SELECT
当前执行的请求,他称之为 SQL inception
。如果哈希的计算在数据库中而不是在应用程序中计算,这就是一个机会,我可以捕捉设置哈希过的密码的请求,从而了解哈希值是如何生成的。首先,我必须要找出我注入了什么。尽管我猜测我使用 UPDATE
指令 修改了用户表,但有些其他请求被我的注入破坏也是有可能的,那么在这种情况下这个方法就是不切实际的。幸运的是我是正确的,看起来我确实成功注入了 UPDATE
指令:
注:事实上,我可以利用并行执行来检索 UPDATE
,但是我选择了用另一个请求注入,虽然这样的利用过程变得效率更低。
$ python run_duncan.py --user mytarget.SimpleDuncan --query "select upper(query) from pg_stat_activity" --pos-end 6 ascii-end 97 UPDAT
我试图找到设置密码的那部分请求,但有趣的是我得到了完全不可信的结果。几经测试后,我决定找出更多关于 pg_stat_activity
表的信息:
$ python run_duncan.py --user mytarget.SimpleDuncan --query "select cast(count(*) as varchar) from pg_stat_activity" --pos-end 4 --charset 0123456789 35
似乎其他人也在使用数据库,最初的请求得到了错误的数据。为了解决这个问题,我使用 WHERE
来限制我请求得到的结果:
$ python run_duncan.py --user mytarget.SimpleDuncan --query "select cast(strpos(upper(query),'MD5') as varchar) from pg_stat_activity WHERE query like '%S2S2S2%'" --pos-end 4 --charset 0123456789 156
由于 WHERE
子句将会被包含在 ps_stat_activity
表的查询属性中,它保证了查询请求可以包含它本身。找到调用 MD5 函数的位置我就可以查看参数了:
$ python run_duncan.py --user mytarget.SimpleDuncan --query "select upper(query) from pg_stat_activity WHERE query like '%S2S2S2%'" --pos-end 4 --ascii-end 97 --pos-start 150 --pos-end 180 --threads 10 ORD = MD5('MYPASS#SOMESALT#'
清楚了哈希值是如何构建的,我就可以在基于 GPU 的破解器中加载之前收集的管理员哈希。 oclHashcat 在破解 MD5 时的表现很好,大部分的密码都可以通过暴力破解得到,特别是在“盐”不变的情况下。现在我可以使用破解后的密码,加上用 WPScan 枚举的用户名可以登录一个 WordPress 博客的管理面板。在 WordPress 的管理页面,我以 PHP 模版的名义上传了一个后门程序,此时我就可以以服务器高级权限来执行远程代码了。
在这篇文章中,我展示了 SQL inception
这项技术应用到渗透测试中如何解决实际问题,以及如何根据 Duncan 的结果进行微调来得到最佳结果。我们也想强调密码的管理和存储仍然是简单 Web 应用和复杂企业系统的主要弱点。我们给开发者和管理员的建议:
*参考来源: silentsignal ,FB 小编 Avenger 编译,转载请注明来自FreeBuf(FreeBuf.COM)