• 代码审计中XSS挖掘一些体会


    0x01 XSS的挖掘思路

    1.1 反射型

    直接搜索 echo print_r print之类的函数即可也可以寻找$_GET变量来判断是否存在输出(不过对于代码审计来说除非实在挖不出漏洞,否则没必要关注反射xss)

    202406171639969.png

    1.2 dom型

    和反射型差不多需要看网站的前端javascript(一般安装好网页直接查看源代码即可,和反射xss一样代码审计没必要太过于关注)。但是也和反射型有区别,domxss是不经过服务器处理的,也就是不需要经过后端代码,需要审计javascript。

    202406171639970.png

    1.3 存储型xss

    对于代码审计,存储型xss才是需要关注的重点。

    存储型xss一般是存在有数据库交互的地方,因为需要把数据写入进去数据库中才能长期储存数据。

    所以我们在审计存储型xss的时候会关注数据库交互的地方。

    这里举例两种思路:

    思路一 : 从数据库类文件中开始审计

    什么是数据库类文件呢?其实在实际开发项目过程中,通常程序员都会把数据库操作封装成一个类来提供操作。

    比如说我们需要设计一个留言板,留言板最基本得有这几个功能吧。比如说发表留言,查看留言,回复留言,删除留言,修改留言等等功能。

    而这些是不是需要使用数据库来实现这类功能(下面用代码配合伪代码示意,注意代码可以不用理解功能,但是要能够理解代码为什么要这样写。)

    # 比如用户发表一条留言

    # uname就是用户名也就是"小明",content就是内容也就是"你好"

    insert into text(id, uname, content) value(1, '小明', '你好');
    # 然后用户发现你好不太恰当,想删掉替换成您好
    delete from text where id = 1;
    # id就是数据库用于区分不同数据的字段, delete from 表示删除表里面的内容
    text表示需要删除的表
    # 表示删除id=1的数据
    where id = 1

    # 那么php中的代码是这样看小明的:
    $sql = "insert into text(id, uname, content) value(1, '小明',
    '你好')";
    // $conn就是我们数据库的链接
    mysqli_query($conn, $sql);
    $sql = "delete from text where id = 1";
    mysqli_query($conn, $sql);
    // 小明换成了您好
    $sql = "insert into text(id, uname, content) value(2, '小明',
    '您好')";
    mysqli_query($conn, $sql);
    $sql = "delete from text where id = 2";
    mysqli_query($conn, $sql);

    # 这样的代码是不是特别麻烦 把他简化一下(把sql查询做成一个函数)
    function sql_insert($name, $content){
    $sql = "insert into text(id, uname, content) value(1, '{$name}',
    '{$content}',哈哈哈哈')";
    mysqli_query($conn,$sql);
    }

    function sql_delete($id){
    $sql = "delete from text where id = '{$id}'";
    mysqli_query($conn,$sql);
    }

    // 好的封装完成了 这时候小明发送你好
    sql_insert('小明', "你好");
    sql_delete(1); // 想删除
    // 发送您好
    sql_insert('小明', "您好");
    sql_delete(2); // 又删除

    # 这样是不是无论小明发多少条留言都能够很轻松的删除插入
    # 好了 这就是封装成的作用(把重复的操作放在一起)
    #
    这里是写完了,但是还是有一个问题,比如遇到sql注入怎么办。遇到xss怎么办。
    # 很简单!只需要修改我们定义的两个操作函数即可
    function sql_insert($name, $content){
    $name = htmlspecialchars(addslashes($name));
    $content = htmlspecialchars(addslashes($content)); // 添加了转义
    $sql = "insert into text(id, uname, content) value(1, '{$name}',
    '{$content}')";
    mysqli_query($conn,$sql);
    }

    function sql_delete($id){
    $id = intval($id); // 强制转换
    $sql = "delete from text where id = '{$id}'";
    mysqli_query($conn,$sql);
    }

    #
    是不是这样的写法很方便,如果我们不定义一个函数集中操作的话每次拼接sql语句都需要添加htmlspecialchars和addlashes
    #
    这就是我们为什么要寻找数据库操作文件的意义。(因为程序员很有可能把过滤函数写在sql类中)

    好了,进入正题。 关于如何找到sql封装文件,很简单。

    搜索关键字即可(new mysqli, mysqli,pdo)这里拿其他cms来实例(phpems架构比较复杂也就是上课时用的cms)这里我使用yixuncms_v2.0.3

    打开文件,全局搜索

    202406171639971.png

    第二步 分析文件的功能 查找需要的关键函数

    202406171639973.png

    直接跟进query函数 查看是否有过滤

    202406171639974.png

    右键定位函数 定位escape_string_array函数

    202406171639975.png

    然后跟进审计

    202406171639976.png

    思路二: 使用输出函数进行动态输出查看是否过滤

    因为源代码在我们服务器上,我们可以使用echo或者var_dump查看过滤后的结果来判断过滤了什么。

    由于我们不知道在程序在哪个页面做了sql查询,所以选择登录功能作为测试点

    因为可以知道一点,那就是登陆功能一定是做了sql查询的,除非是前端登陆,而前端登陆本身也就是一个漏洞...

    知道了这一点,登陆抓包,登陆账号密码有没有都不要紧。

    我这里使用错误的账号密码登陆:

    202406171639977.png

    返回了一个操作失败

    202406171639978.png

    然后我们根据提示去全局搜索: 操作失败

    202406171639979.png

    至于为什么是这三个呢? 因为我们抓到的数据表访问的就是这个路径

    202406171639980.png

    进入app.php

    202406171639981.png

    然后定位getUserByUserName函数

    202406171639982.png

    然后就可以添加代码进行调试了(修改后记得保存 快捷键 ctrl + s)

    202406171639983.png

    再次发包进行调试发现已经返回sql语句了

    202406171639984.png

    202406171639985.png

    思路在这里完结了。下面是漏洞复现

    【----帮助网安学习,以下所有学习资料免费领!加vx:dctintin,备注“freebuf”获取!】

    ① 网安学习成长路径思维导图
    ② 60+网安经典常用工具包
    ③ 100+SRC漏洞分析报告
    ④ 150+网安攻防实战技术电子书
    ⑤ 最权威CISSP 认证考试指南+题库
    ⑥ 超1800页CTF实战技巧手册
    ⑦ 最新网安大厂面试题合集(含答案)
    ⑧ APP客户端安全检测指南(安卓+IOS)

    0x02 漏洞的复现

    因为上面已经知道了xss和sql在普通参数里面不存在,然后正常注册后登陆发现

    202406171639986.png

    那么直接根据注册ip搜索

    202406171639987.png

    跟进后再次全局搜索

    202406171639988.png

    202406171639989.png

    202406171639991.png

    202406171639992.png

    由于程序开发中默认ip地址是安全的一般很少会进行过滤,所以这里直接猜测ip地址不存在过滤。

    然后注册账号进行测试

    payload:Client-ip:

    202406171639993.png

    然后放包,发现个人中心已经存储了我们的xss

    202406171639994.png

    202406171639995.png

    同理,这里没有经过过滤也是存在注入的。这里就不在演示

    0x03 总结

    xss加固可以在前端或者后端实体编码 同时也要注意对单双引号的转义。

    不要以为获取ip就是安全的,获取ip往往是不安全的。

    思路 -》 找过滤函数 -》测试过滤是否有遗漏 -》 测试可能没有经过过滤的参数

    有些网站会把在属性内的参数使用反斜杠编码.比如你输入 &url="onerror=alert(1) 双引号会被转义成/",这时如果网站的编码是gb2312...之类的可以使用宽字节 %df"的方式绕过

    202406171639996.png

    202406171639997.png


  • 相关阅读:
    第六章 图 四、图的广度优先遍历(BFS算法、广度优先生成树、广度优先生成森林)
    Elastic Agent 的安装及使用
    【前端设计模式】之访问者模式
    SpringBoot项目实现发布订阅模式,真的很简单
    2022-11-18 mysql-filesort-分析
    (13.1)Latex符号表示及公式撰写
    nginx——不同前端项目共用一个端口
    mybatis bean属性识别丢失【NoSuchPropertyException】
    MySQL更新一条已经存在的sql语句是怎么执行的
    【2-Docker安装部署ElasticSearch和Kibanan详细步骤】
  • 原文地址:https://www.freebuf.com/vuls/403863.html