• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

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

    發布: 2007-7-02 21:50 | 作者: admin | 來源: | 查看: 8次 | 進入軟件測試論壇討論

    領測軟件測試網

    我們來看看apache出錯原因。

    下面是源代碼 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 "" 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);
    }
    }

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>