记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

审计通达OA时的一些记录

2020-08-15 23:45

学习审计通达OA时发现的一些有意思的事

全局变量覆盖

审计时发现前辈们提到了这个问题,跟了下存在问题的文件

比如存在变量覆盖的文件是pdavotelist.php,

require_once "pda/auth.php";
include_once "inc/conn.php";
include_once "inc/utility_all.php";
include_once "mobile/api/qyapp.vote.class.php";

if ($P == "") {
$P = $_COOKIE["PHPSESSID"];
}
else {
$P = $_GET["P"];
}

这里包含了inc/conn.php数据库连接文件

image-20200723103126920

继续跟,发现包含了inc/td_config.php

<?php

include_once "inc/common.inc.php";
$ROOT_PATH = ($_SERVER["DOCUMENT_ROOT"] ? $_SERVER["DOCUMENT_ROOT"] : "");

if ($ROOT_PATH == "") {
$ROOT_PATH = str_replace("\", "/", realpath(dirname(__FILE__) . "/../"));
}

if (substr($ROOT_PATH, -1) != "/") {
$ROOT_PATH .= "/";
}

包含了inc/common.inc.php

<?php

//......代码省略

if (0 < count($_COOKIE)) {
foreach ($_COOKIE as $s_key => $s_value ) {
if ((substr($s_key, 0, 7) == "_SERVER") || (substr($s_key, 0, 8) == "_SESSION") || (substr($s_key, 0, 7) == "_COOKIE") || (substr($s_key, 0, 4) == "_GET") || (substr($s_key, 0, 5) == "_POST")) {
continue;
}

if (!is_array($s_value)) {
$_COOKIE[$s_key] = addslashes(strip_tags($s_value));//<---
}

$s_key = $_COOKIE[$s_key];
}

reset($_COOKIE);
}

if (0 < count($_POST)) {
$arr_html_fields = array();

foreach ($_POST as $s_key => $s_value ) {
if ((substr($s_key, 0, 7) == "_SERVER") || (substr($s_key, 0, 8) == "_SESSION") || (substr($s_key, 0, 7) == "_COOKIE") || (substr($s_key, 0, 4) == "_GET") || (substr($s_key, 0, 5) == "_POST")) {
continue;
}

if (substr($s_key, 0, 15) != "TD_HTML_EDITOR_") {
if (!is_array($s_value)) {
$_POST[$s_key] = addslashes(strip_tags($s_value));//<---
}

$s_key = $_POST[$s_key];
}
else {
if (($s_key == "TD_HTML_EDITOR_FORM_HTML_DATA") || ($s_key == "TD_HTML_EDITOR_PRCS_IN") || ($s_key == "TD_HTML_EDITOR_PRCS_OUT") || ($s_key == "TD_HTML_EDITOR_QTPL_PRCS_SET") || ($_POST["ACTION_TYPE"] && (($_POST["ACTION_TYPE"] == "approve_center") || ($_POST["ACTION_TYPE"] == "workflow") || ($_POST["ACTION_TYPE"] == "sms") || ($_POST["ACTION_TYPE"] == "wiki")) && (($s_key == "CONTENT") || ($s_key == "TD_HTML_EDITOR_CONTENT") || ($s_key == "TD_HTML_EDITOR_TPT_CONTENT")))) {
unset($_POST[$s_key]);
$s_key = ($s_key == "CONTENT" ? $s_key : substr($s_key, 15));
$s_key = addslashes($s_value);
$arr_html_fields[$s_key] = $s_key;
}
else {
$encoding = mb_detect_encoding($s_value, "GBK,UTF-8");
unset($_POST[$s_key]);
$s_key = substr($s_key, 15);
$s_key = addslashes(rich_text_clean($s_value, $encoding));
$arr_html_fields[$s_key] = $s_key;
}
}
}

reset($_POST);
$_POST = array_merge($_POST, $arr_html_fields);
}

if (0 < count($_GET)) {
foreach ($_GET as $s_key => $s_value ) {
if ((substr($s_key, 0, 7) == "_SERVER") || (substr($s_key, 0, 8) == "_SESSION") || (substr($s_key, 0, 7) == "_COOKIE") || (substr($s_key, 0, 4) == "_GET") || (substr($s_key, 0, 5) == "_POST")) {
continue;
}

if (!is_array($s_value)) {
$_GET[$s_key] = addslashes(strip_tags($s_value));//<---
}

$s_key = $_GET[$s_key];
}

reset($_GET);
}

unset($s_key);
unset($s_value);

?>

只要包含了这个文件,就会存在该问题

注入过滤规则

笔者对比了2013~2019(V11)的过滤SQL注入的代码,高版本的防注代码在incconn.php的sql_injection函数,低版本的在exequery处理,都是基于黑名单模式进行防注处理,80sec的软waf

2013-exequery

function exequery( $C, $Q, $LOG = FALSE )
{
    if ( !$LOG )
    {
        $POS = ( $Q, "union" );
        if ( $POS !== FALSE && ( $Q, "select", $POS ) !== FALSE )
        {
            exit( );
        }
        $POS = ( $Q, "into" );
        if ( $POS !== FALSE && ( ( $Q, "outfile", $POS ) !== FALSE || ( $Q, "dumpfile", $POS ) !== FALSE ) )
        {
            exit( );
        }
    }
    if ( ( $C ) )
    {
    }
    if ( !( $C ) )
    {
        if ( ( $C ) )
        {
            ( $C );
        }
        $C = ( $C );
    }
    if ( !( $C ) )
    {
        ( ( "无效的数据库连接" )."
".( "SQL语句:" )." ".$Q, $LOG );
        return FALSE;
    }
    $cursor = @( $Q, $C );
    if ( !$cursor )
    {
        ( "".( "SQL语句:" )." ".$Q, $LOG );
    }
    return $cursor;
}

可以看到早年的通达仅仅检测了union、select、into、outfile、dumpfile这几个关键字,导致可绕过的方式很多,比如常用于盲注的sleep等

2013adv-sql_injection

function sql_injection( $db_string )
{
    $clean = "";
    $error = "";
    $old_pos = 0;
    $pos = -1;
    do
    {
        $pos = ( $db_string, "'", $pos + 1 );
        $clean .= ( $db_string, $old_pos, $pos - $old_pos );
        do
        {
            $pos1 = ( $db_string, "'", $pos + 1 );
            $pos2 = ( $db_string, "\", $pos + 1 );
            if ( !$pos2 && $pos1 < $pos2 )
            {
                $pos = $pos1;
                break;
            }
            else
            {
                $pos = $pos2 + 1;
            }
        } while ( 1 );
        $clean .= "$s$";
        $old_pos = $pos + 1;
    } while ( 1 );
    $clean .= ( $db_string, $old_pos );
    $clean = ( ( ( array( "~\s+~s" ), array( " " ), $clean ) ) );
    $fail = FALSE;
    if ( ( $clean, "union" ) !== FALSE && ( "~(^|[^a-z])union($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = ( "联合查询" );
    }
    else if ( 2 < ( $clean, "/*" ) || ( $clean, "--" ) !== FALSE || ( $clean, "#" ) !== FALSE )
    {
        $fail = TRUE;
        $error = ( "注释代码" );
    }
    else if ( ( $clean, "sleep" ) !== FALSE && ( "~(^|[^a-z])sleep($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "sleep";
    }
    else if ( ( $clean, "benchmark" ) !== FALSE && ( "~(^|[^a-z])benchmark($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "benchmark";
    }
    else if ( ( $clean, "load_file" ) !== FALSE && ( "~(^|[^a-z])load_file($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = ( "Load文件" );
    }
    else if ( ( $clean, "cast" ) !== FALSE && ( "~(^|[^a-z])mid($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "cast";
    }
    else if ( ( $clean, "ord" ) !== FALSE && ( "~(^|[^a-z])ord($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "ord";
    }
    else if ( ( $clean, "ascii" ) !== FALSE && ( "~(^|[^a-z])ascii($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "ascii";
    }
    else if ( ( $clean, "extractvalue" ) !== FALSE && ( "~(^|[^a-z])extractvalue($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "extractvalue";
    }
    else if ( ( $clean, "updatexml" ) !== FALSE && ( "~(^|[^a-z])updatexml($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = "updatexml";
    }
    else if ( ( $clean, "into outfile" ) !== FALSE && ( "~(^|[^a-z])into\s+outfile($|[^[a-z])~s", $clean ) != 0 )
    {
        $fail = TRUE;
        $error = ( "生成文件" );
    }
    if ( $fail )
    {
        echo ( "不安全的SQL语句:" ).$error."
";
        echo ( $db_string );
        exit( );
    }
    return $db_string;
}

2013adv的使用了sql_injection函数进行防注处理(过滤了updatexml、into outfile、extractvalue、ascii、ord、cast、sleep、benchmark、load_file、union关键字)

2015~2016

这两个版本没什么变化,2015相对2013adv新增exp黑名单

2017

2017相对2016新增处理 ,查表后是对应的ascii是空格

image-20200723110633783

V11

与2017相同,不放代码了

td_framework数据库查询处理流程

通达的td_framework框架(可能看的不是太清,建议新开标签页查看)

未命名表单

总结

由于数据库是GBK编码(2013~V11都是),虽然使用了addslashes函数进行处理引号等字符,但是可使用宽字节%df%27进行绕过。通达OA这个产品由于架构比较老导致问题比较多,考虑到市场份额和影响,不放用于攻击的EXP。


知识来源: https://0x20h.com/p/9367.html

阅读:134151 | 评论:0 | 标签:审计

想收藏或者和大家分享这篇好文章→复制链接地址

“审计通达OA时的一些记录”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

黑帝公告 📢

永久免费持续更新精选优质黑客技术文章Hackdig,帮你成为掌握黑客技术的英雄

↓赞助商 🙇🧎

标签云 ☁