安全矩阵

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

网络安全编程:开发后台登录地址扫描工具

[复制链接]

221

主题

233

帖子

792

积分

高级会员

Rank: 4

积分
792
发表于 2021-7-12 08:45:52 | 显示全部楼层 |阅读模式
网络安全编程:开发后台登录地址扫描工具[url=]计算机与网络安全[/url] 昨天
一次性付费进群,长期免费索取资料。
回复公众号:微信群 可查看进群流程。



本文来完成一个后台扫描工具。在进行Web安全活动时通常会去查找后台登录页面,找到登录页面以后可能会使用暴力破解密码或者SQL注入等一系列的方法去尝试登录。

对于一个扫描后台登录地址的工具来说,常用的方法是通过字典去尝试。这里使用字典中保存的后台页面来逐个地进行尝试,不过后台登录页面通常都有一些俗称的命名方式,虽然没有规范,但是大多都使用诸如“login”、“index”这类的文件名,相比密码而言它的组合就少许多了。

下面看一下扫描后台工具的界面,界面如图1所示。

图1  后台登录扫描工具

图1中最常见的编辑框用于输入要扫描网站的URL,下拉框用于选择扫描的类型,这里扫描的类型分为“PHP”和“ASP”两种。填入扫描网站的URL,并选择相应的扫描类型单击“扫描”按钮就可以开始进行扫描,扫描的结果会显示在程序下方的列表框中。

在程序启动的时候,需要在窗口初始化时初始化程序下方的列表框,代码如下:
  1. m_ScanList.InsertColumn(0, "扫描结果");
  2. m_ScanList.SetColumnWidth(0, 400);
复制代码
m_ScanList是与CListCtrl关联的控件变量,相关的定义包括:

  1. CListCtrl m_ScanList; // 列表框控件变量
  2. HANDLE m_hEvent; // 事件变量,用于多线程传递参数时使用
  3. afx_msg void OnBnClickedButton1();
  4. // 扫描线程
  5. static DWORD WINAPI ScanThread(LPVOID lpParam);
  6. // 检查 URL 是否有效,即检查登录后台页面是否有效
  7. BOOL CheckUrl(CString strUrl);
复制代码
填写好URL地址和选择了下拉列表以后,单击“扫描”按钮就可以开始扫描了,由于扫描任务不能和程序的主程序为同一个线程,那么就需要再启动一个线程启动扫描任务,“扫描”按钮的代码如下:
  1. void CScanAdminPageDlg::OnBnClickedButton1()
  2. {
  3.   // TODO: 在此添加控件通知处理程序代码
  4.   // 清除列表框内容
  5.   m_ScanList.DeleteAllItems();
  6.   // 获取输入的 URL 内容
  7.   CString strURL;
  8.   GetDlgItemText(IDC_EDIT1, strURL);
  9.   // 创建事件
  10.   m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  11.   // 创建扫描线程
  12.   HANDLE hThread = NULL;
  13.   hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ScanThread, this, 0, NULL);
  14.   WaitForSingleObject(m_hEvent, INFINITE);
  15.   ResetEvent(m_hEvent);
  16. }
复制代码
单击“扫描”按钮时会创建扫描线程来进行扫描后台,线程函数的函数名为ScanThread。代码如下所示:
  1. DWORD WINAPI CScanAdminPageDlg::ScanThread(LPVOID lpParam)
  2. {
  3.   CScanAdminPageDlg *pThis = (CScanAdminPageDlg*)lpParam;
  4.   SetEvent(pThis->m_hEvent);
  5.   // 在线程函数中获取下拉选框的内容
  6.   // 下拉选项是 asp 和 php 两项
  7.   CString strWebType;
  8.   pThis->GetDlgItemText(IDC_COMBO1, strWebType);
  9.   // 在线程函数中获取扫描 URL 地址
  10.   CString strUrl;
  11.   pThis->GetDlgItemText(IDC_EDIT1, strUrl);
  12.   // 通过下拉选项来构造字典
  13.   // asp.dic 或 php.dic
  14.   char szFileName[MAX_PATH] = { 0 };
  15.   wsprintf(szFileName, "%s.dic", strWebType);
  16.   // 打开字典文件
  17.   // 从中读取可能的后台页面
  18.   FILE *DicFile = NULL;
  19.   fopen_s(&DicFile, szFileName, "r");
  20.   char szDic[MAXBYTE] = { 0 };
  21.   while ( fgets(szDic, MAXBYTE, DicFile) )
  22.   {
  23.     if ( szDic[lstrlen(szDic) - 1] == '\n' )
  24.     {
  25.       szDic[lstrlen(szDic) - 1] = NULL;
  26.     }
  27.     // 扫描 URL 地址和字典中的页面文件进行拼接
  28.     CString strCheckUrl = strUrl + szDic;
  29.     // 判断页面是否存在
  30.     // 存在则在地址的结尾增加“[OK]”字样
  31.     if ( pThis->CheckUrl(strCheckUrl) )
  32.     {
  33.       strCheckUrl += "[OK]";
  34.       pThis->m_ScanList.InsertItem(0, strCheckUrl);
  35.       continue;
  36.     }
  37.     // 将扫描的地址添加至字典
  38.     pThis->m_ScanList.InsertItem(pThis->m_ScanList.GetItemCount(), strCheckUrl);
  39.   }
  40.   return 0;
  41. }
复制代码
下拉框选项中有“asp”和“php”两项,分别是常见的关于ASP系统和PHP系统后台登录页面的文件名,这些文件名可以从其他的安全工具中获取,也可以自己收集。这里将ASP和PHP的字典文件分别命名为“asp.idc”和“php.dic”,在扫描线程函数中通过获取下拉选项“asp”或“php”与“.dic”字符串进行拼接,从而合并成完整的字典的名称。打开字典以后逐行地读取页面文件,读取的页面文件类似“admin/login.asp”“wp-login.php”等,将扫描的URL地址和字典文件进行拼接后,构成一个完整的扫描页面进行测试,如果该页面文件存在,则在后面拼接“[OK]”字符串表示后台页面存在。最后,无论页面文件是否存在都会添加到程序的列表框中。
在程序中,判断页面文件是否存在的函数是CheckUrl函数,该函数的代码如下:
  1. BOOL CScanAdminPageDlg::CheckUrl(CString strUrl)
  2. {
  3.   // 建立一个 SESSION
  4.   CInternetSession session("ScanAdminPage");
  5.   // 建立一个 HTTP 连接
  6.   CHttpConnection *pServer = NULL;
  7.   // 获取一个 HTTP 文件
  8.   CHttpFile *pFile = NULL;
  9.   // 检测输入的 URL 是否符合格式,并把 URL 解析
  10.   CString strServerName; // 服务器地址
  11.   CString strObject; // URL 指向的对象
  12.   INTERNET_PORT nPort; // 端口号
  13.   DWORD dwServiceType; // 服务类型
  14.   // URL 解析失败则返回
  15.   // 解析扫描的 URL
  16.   if ( !AfxParseURL(strUrl, dwServiceType, strServerName, strObject, nPort) )
  17.   {
  18.     return NULL;
  19.   }
  20.   // 服务类型错误
  21.   if ( dwServiceType != INTERNET_SERVICE_HTTP )
  22.   {
  23.     return NULL;
  24.   }
  25.   // 配置连接服务器的地址、端口,并获取该 HTTP 连接
  26.   pServer = session.GetHttpConnection(strServerName, nPort);
  27.   // 打开该 HTTP 连接
  28.   pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject, NULL, 1,
  29.     NULL, NULL, INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT);
  30.   try
  31.   {
  32.     // 发起请求
  33.     pFile->SendRequest();
  34.   }
  35.   catch (CException* e)
  36.   {
  37.     return NULL;
  38.   }
  39.   DWORD dwRet;
  40.   // 获取该请求的回应状态码
  41.   pFile->QueryInfoStatusCode(dwRet);
  42.   BOOL bRet = FALSE;
  43.   // HTTP 返回值为 200 表示成功
  44.   if ( dwRet == 200 )
  45.   {
  46.     bRet = TRUE;
  47.   }
  48.   // 释放指针
  49.   if ( pFile != NULL )
  50.   {
  51.     delete pFile;
  52.   }
  53.   if ( pServer != NULL )
  54.   {
  55.     delete pServer;
  56.   }
  57.   // 关闭会话
  58.   session.Close();
  59.   return bRet;
  60. }
复制代码

在代码中CInternetSession类方法GetHttpConnection是用来使程序和服务器建立会话的,这步算是建立了一个TCP的连接,并没有真正地与Web进行通信。使用CInternetSession:: GetHttpConnection方法建立会话后返回了CHttpConnection类的指针,通过CHttpConnection类方法OpenRequest来发起HTTP请求,这部分就是HTTP的真正操作了,可以发起POST或GET等常用的HTTP请求。ChttpConnection::OpenRequest方法发起HTTP请求后就返回了CHttpFile指针,通过CHttpFile类方法QueryInfoStatusCode来获取服务器的返回码。如果返回码是200,表示页面存在,如果返回其他值则表示页面不存在。

Web通信最常使用的就是HTTP协议,出于安全的考虑又发展了HTTPS协议。通过浏览器来浏览网页时就是通过HTTP协议来发起GET或POST请求,然后Web服务器会将响应和结果返回给浏览器。浏览器在向Web服务器发起HTTP请求时通常被称为request,Web服务器返回数据给浏览器时被称为response。HTTP协议也有它相关的头部,通过CHttpFile类的QueryInfoStatusCode可以获得服务器的返回码,这里给出MSDN中对于HTTP返回值的描述,如表1所示,常见的返回值如表2所示。

表1  HTTP状态码分组


表2  常用的HTTP状态码

下面用编写的扫描工具来扫描DVWA的后台页面地址,虽然打开DVWA系统后直接可以显示它的登录页面,但这里只是用来进行演示,如图2所示。

图2  扫描DVWA后台的登录页面


回复

使用道具 举报

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

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 10:56 , Processed in 0.012867 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

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