apache的..%5c漏洞原因源代码分析

原创 2004年10月24日 08:56:00
下面是源代码 src/main/http_request.c: 的处理请求的代码:


static void process_request_internal(request_rec *r)
{
int access_status;

/* Ignore embedded %2F's in path for proxy requests */
if (r->proxyreq == NOT_PROXY && r->parsed_uri.path) {
/* 如果不是代理 */
access_status = ap_unescape_url(r->parsed_uri.path);
/* 解码%,rfc要求 */
if (access_status) {
ap_die(access_status, r);
return;
}
}

ap_getparents(r->uri); /* OK --- shrinking transformations... */
/* 处理/../,出错,没考虑windows下面的/../ */

if ((access_status = location_walk(r))) {
ap_die(access_status, r);
return;
}

if ((access_status = ap_translate_name(r))) {
decl_die(access_status, "translate", r);
return;
}

if (r->proxyreq == NOT_PROXY) {
/*
* We don't want TRACE to run through the normal handler set, we
* handle it specially.
*/
if (r->method_number == M_TRACE) {
if ((access_status = ap_send_http_trace(r)))
ap_die(access_status, r);
else
ap_finalize_request_protocol(r);
return;
}
}

if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) {
r->proto_num = HTTP_VERSION(1,0);
}

/*
* NB: directory_walk() clears the per_dir_config, so we don't inherit
* from location_walk() above
*/

if ((access_status = directory_walk(r))) {
ap_die(access_status, r);
return;
}

if ((access_status = file_walk(r))) {
ap_die(access_status, r);
return;
}

if ((access_status = location_walk(r))) {
ap_die(access_status, r);
return;
}

if ((access_status = ap_header_parse(r))) {
ap_die(access_status, r);
return;
}

switch (ap_satisfies(r)) {
case SATISFY_ALL:
case SATISFY_NOSPEC:
if ((access_status = ap_check_access(r)) != 0) {
decl_die(access_status, "check access", r);
return;
}
if (ap_some_auth_required(r)) {
if (((access_status = ap_check_user_id(r)) != 0)    !ap_auth_type(r)) {
decl_die(access_status, ap_auth_type(r)
? "check user. No user file?"
: "perform authentication. AuthType not set!", r);
return;
}
if (((access_status = ap_check_auth(r)) != 0)    !ap_auth_type(r)) {
decl_die(access_status, ap_auth_type(r)
? "check access. No groups file?"
: "perform authentication. AuthType not set!", r);
return;
}
}
break;
case SATISFY_ANY:
if (((access_status = ap_check_access(r)) != 0)    !ap_auth_type(r)) {
if (!ap_some_auth_required(r)) {
decl_die(access_status ? access_status :
HTTP_INTERNAL_SERVER_ERROR,
ap_auth_type(r) ? "check access"
: "perform authentication. AuthType not set!", r);
return;
}
if (((access_status = ap_check_user_id(r)) != 0)    !ap_auth_type(r)) {
decl_die(access_status, ap_auth_type(r)
? "check user. No user file?"
: "perform authentication. AuthType not set!", r);
return;
}
if (((access_status = ap_check_auth(r)) != 0)    !ap_auth_type(r)) {
decl_die(access_status, ap_auth_type(r)
? "check access. No groups file?"
: "perform authentication. AuthType not set!", r);
return;
}
}
break;
}

if (! (r->proxyreq != NOT_PROXY
&& r->parsed_uri.scheme != NULL
&& strcmp(r->parsed_uri.scheme, "http") == 0) ) {
if ((access_status = ap_find_types(r)) != 0) {
decl_die(access_status, "find types", r);
return;
}
}

if ((access_status = ap_run_fixups(r)) != 0) {
ap_die(access_status, r);
return;
}

if ((access_status = ap_invoke_handler(r)) != 0) {
ap_die(access_status, r);
return;
}

/* Take care of little things that need to happen when we're done */
ap_finalize_request_protocol(r);
}


下面是源代码 src/main/util.c 处理/../的代码:


API_EXPORT(void) ap_getparents(char *name)
{
int l, w;

/* Four paseses, as per RFC 1808 */
/* a) remove ./ path segments */

for (l = 0, w = 0; name[l] != '/0';) {
if (name[l] == '.' && name[l + 1] == '/' && (l == 0    name[l - 1] == '/'))
l += 2;
else
name[w++] = name[l++];
}

/* b) remove trailing . path, segment */
if (w == 1 && name[0] == '.')
w--;
else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
w--;
name[w] = '/0';

/* c) remove all xx/../ segments. (including leading ../ and /../) */
l = 0;

while (name[l] != '/0') {
if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' &&
(l == 0    name[l - 1] == '/')) {
register int m = l + 3, n;

l = l - 2;
if (l >= 0) {
while (l >= 0 && name[l] != '/')
l--;
l++;
}
else
l = 0;
n = l;
while ((name[n] = name[m]))
(++n, ++m);
}
else
++l;
}

/* d) remove trailing xx/.. segment. */
if (l == 2 && name[0] == '.' && name[1] == '.')
name[0] = '/0';
else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') {
l = l - 4;
if (l >= 0) {
while (l >= 0 && name[l] != '/')
l--;
l++;
}
else
l = 0;
name[l] = '/0';
}
}

大家看到了,显然没有考虑windows下面的“/../”,看来编写这个函数的人不熟悉WINDOWS的特性,是个长期在*UNIX下面编程的人员。其实没考虑WINDOWS下面的“/../”已经出过很多问题的了。那为什么直接telnet 用“/../”不行呢?看来在解码之前把所有“/”替换成了“/”。显然这个转换是该在解码之后,估计上面没有检测“/../”的原因就是认为先已经转换了,这个就与IIS的%c1%1c漏洞一样。照这样就一定得注意如果有什么编码、解码的,一定得重新考虑前面的一些检测,因为弄不好就能重新编码出不符合前面检测的东西来。


看这是源代码 src/main/http_protocol.c 中将URI中的“/”转化成“/”的处理模块:

/* parse_uri: break apart the uri
* Side Effects:
* - sets r->args to rest after '?' (or NULL if no '?')
* - sets r->uri to request uri (without r->args part)
* - sets r->hostname (if not set already) from request (scheme://host:port)
*/
CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
{
int status = HTTP_OK;

r->unparsed_uri = ap_pstrdup(r->pool, uri);

if (r->method_number == M_CONNECT) {
status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
} else {
/* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
}

if (ap_is_HTTP_SUCCESS(status)) {
/* if it has a scheme we may need to do absoluteURI vhost stuff */
if (r->parsed_uri.scheme
&& !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
r->hostname = r->parsed_uri.hostname;
} else if (r->method_number == M_CONNECT) {
r->hostname = r->parsed_uri.hostname;
}
r->args = r->parsed_uri.query;
r->uri = r->parsed_uri.path ? r->parsed_uri.path
: ap_pstrdup(r->pool, "/");
#if defined(OS2)    defined(WIN32)
/* Handle path translations for OS/2 and plug security hole.
* This will prevent "http://www.enet.com.cn/../..//" from
* returning a directory for the root drive.
*/
{
char *x;

for (x = r->uri; (x = strchr(x, '//')) != NULL; )
*x = '/';
/* /转换成/ */

}
#endif /* OS2    WIN32 */
}
else {
r->args = NULL;
r->hostname = NULL;
r->status = status; /* set error status */
r->uri = ap_pstrdup(r->pool, uri);
}
}

%5c暴库原理

%5c暴库原理 作者:sasa 发布于:2012-5-21 20:26 Monday 分类:Web渗透         暴库有两个方法,第一个就是利用%5c,另外一个conn.asp暴库。而且...
  • eldn__
  • eldn__
  • 2012年12月07日 15:21
  • 3585

暴库漏洞

之前做过这样的教材,这个是文字说明,有兴趣的去搜索观看 SQL注入流行很久了,我们找漏洞注入目的无非是想得到数据库内的东西,比如用户名密码等,更进一步的MSSQL数据库还可以借此获得权限。基于A...
  • u010640023
  • u010640023
  • 2014年04月16日 00:52
  • 942

Apache漏洞利用与安全加固实例分析

Apache 作为Web应用的载体,一旦出现安全问题,那么运行在其上的Web应用的安全也无法得到保障,所以,研究Apache的漏洞与安全性非常有意义。本文将结合实例来谈谈针对Apache的漏洞利用和安...
  • xysoul
  • xysoul
  • 2015年08月21日 13:41
  • 2394

i春秋:警惕Apache站上的解析缺陷绕过上传漏洞

实验环境 实验环境 操作机:Windows XP 目标机:Windows 2003 目标网址:www.test.com实验工具:中国菜刀 实验目的 本课程带领大家...
  • hope_smile
  • hope_smile
  • 2015年06月01日 04:09
  • 8354

文件解析漏洞总结-Apache

本文详细论述、测试了Apache的三种文件解析漏洞:多后缀名、罕见后缀和利用.htaccess...
  • wn314
  • wn314
  • 2017年08月10日 22:35
  • 828

apache漏洞修复(绿盟科技漏洞)

apache 漏洞 检测到目标主机可能存在缓慢的http拒绝服务攻
  • qshpeng
  • qshpeng
  • 2016年02月19日 22:30
  • 7161

%5C 暴库漏洞

/的UNICODE是%5c,主要就是暴库漏洞那么,我看到下面四种情况:1,直接暴库,解决方法在conn.asp中加入On Error Resume Nextwww.duoluo.com/webdrea...
  • zhcool
  • zhcool
  • 2004年12月19日 20:59
  • 1325

%5c暴库漏洞

今天在黑基又看到了关于%5c暴库的文章。呵呵,这招真的很管用,大概10个网站里会有一个会暴库吧。。 关于这个漏洞。绿盟有相关的资料。Microsoft IIS CGI文件名错误解码漏洞发布日期:200...
  • wsp1
  • wsp1
  • 2005年02月05日 14:51
  • 2353

今天发现,apache被人漏洞检测了

今天突然查看PHP的访问日志,其中有这样的条目: ★- 58.68.234.233 - - [01/Jan/2014:22:34:36 +0800] "POST /cgi-bin/php.c...
  • cmoooo
  • cmoooo
  • 2014年01月06日 19:23
  • 3701

SQL漏洞分析

本文转载。 随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代...
  • u013283956
  • u013283956
  • 2017年04月04日 12:45
  • 524
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:apache的..%5c漏洞原因源代码分析
举报原因:
原因补充:

(最多只允许输入30个字)