知道创宇

值得一提的是:在我们分析过程发现通过MicrosoftAzure提供的以太坊节点自动化部署方案仍然使用的1.7.3版本的geth这个版本里UnlockAccount函数:

wiki中对personal_unlockAccount方法的定义:

在实际测试分析过程发现使用MicrosoftAzure提供的以太坊节点自动化部署方案更多的是联盟链或私有链,部署共有链的情况较少,所以这个安全事件实际可能给共有链的带来的影响相对不大。对于联盟链或私有链的影响需要根据其本身的情况去衡量量评估。

区块链虚拟货币安全事件频发,安全刻不不容。通过这次的案例可以得几点建议:

针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。

通过下面的例子对比三种调用方式,在remix部署调试,部署地址为0xca35b7d915458ef540ade6068dfe2f44e8fa733c:

在部署后可以看到合约A的变量值:temp1=0x0,temp2=0x0,同样合约B的变量值也是:temp1=0x0,temp2=0x0。

现在调用语句1call方式,观察变量的值发现合约A中变量值为0x0,而被调用者合约B中的temp1=address(A),temp2=100:

现在调用语句2delegatecall方式,观察变量的值发现合约B中变量值为0x0,而调用者合约A中的temp1=0xca35b7d915458ef540ade6068dfe2f44e8fa733c,temp2=100:

现在调用语句3callcode方式,观察变量的值发现合约B中变量值为0x0,而调用者合约A中的temp1=address(A),temp2=100:

delegatecall:调用后内置变量msg的值不会修改为调用者,但执行环境为调用者的运行环境。

在智能合约的开发过程中,合约的相互调用是经常发生的。开发者为了实现某些功能会调用另一个合约的函数。比如下面的例子,调用一个合约A的test()函数,这是一个正常安全的调用。

但是在实际开发过程中,开发者为了兼顾代码的灵活性,往往会有下面这种写法:

这将引起任意public函数调用的问题:合约中的delegatecall的调用地址和调用的字符序列都由用户传入,那么完全可以调用任意地址的函数。

除此之外,由于delegatecall的执行环境为调用者环境,当调用者和被调用者有相同变量时,如果被调用的函数对变量值进行修改,那么修改的是调用者中的变量。

下面的例子中B合约是业务逻辑合约,其中存在一个任意地址的delegatecall调用。

攻击者对应这种合约可以编写一个Attack合约,然后精心构造字节序列(将注释部分的攻击代码转换为字节序列),通过调用合约B的delegatecall,最终调用Attack合约中的函数,下面是Attack合约的例子:

对于delegatecall「滥用」的问题,实际的漏洞效果取决于Attack合约中的攻击代码,可能造成的安全问题包括:

ParityMultiSig钱包事件

2017.7.20,ParityMultisig电子钱包版本1.5+的漏洞被发现,使得攻击者从三个高安全的多重签名合约中窃取到超过15万ETH,按照当时的ETH价格来算,大约为3000万美元。

其事件原因是由于未做限制的delegatecall可以调用WalletLibrary合约的任意函数,并且其钱包初始化函数未做校验,导致初始化函数可以重复调用。攻击者利用这两个条件,通过delegatecall调用initWallet()函数,最终修改了合约拥有者,并将合约中的以太币转到自己的账户下。

a.delegatecall调用代码:(contractWalletisWalletEvents)

b.initWallet()与initMultiowned()代码片段:(contractWalletLibraryisWalletEvents)

其中钱包初始化函数initMultiowned()未做校验,可以被多次调用,存在安全隐患,但由于其位于WalletLibrary合约下,是不能直接调用的。黑客利用Wallet合约中的delegatecall调用WalletLibrary合约的initWallet()函数,初始化整个钱包,将合约拥有者修改为仅黑客一人,随后进行转账操作。

黑客攻击链:

call:最常用的调用方式,调用后内置变量msg的值会修改为调用者,执行环境为被调用者的运行环境。

call注入是一种新的攻击场景,由「隐形人真忙」在先知大会上演讲「智能合约消息调用攻防」议题上提出,原因是对call调用处理不当,配合一定的应用场景的一种攻击手段。

call调用修改msg.sender值通常情况下合约通过call来执行来相互调用执行,由于call在相互调用过程中内置变量msg会随着调用方的改变而改变,这就成为了一个安全隐患,在特定的应用场景下将引发安全问题。

外部用户通过call函数再调用合约函数:

高度自由的call调用

在某些应用场景下,调用函数可以由用户指定;下面是call函数的调用方式:

从上面可以看出,call函数拥有极大的自由度:

为了便于理解,可以将智能合约中的call函数类比为其他语言中的eval函数,call函数相当于给用户提供了随意调用合约函数的入口,如果合约中有函数以msg.sender作为关键变量,那么就会引发安全问题。

call函数簇调用自动忽略多余参数call函数簇在调用函数的过程中,会自动忽略多余的参数,这又额外增加了call函数簇调用的自由度。下面的例子演示call自动忽略多余参数:

例子中test()函数仅接收一个uint256的参数,但在callFunc()中传入了三个参数,由于call自动忽略多余参数,所以成功调用了test()函数。

call注入引起的最根本的原因就是call在调用过程中,会将msg.sender的值转换为发起调用方的地址,下面的例子描述了call注入的攻击模型。

在合约B中存在info()和secret()函数,其中secret()函数只能由合约自己调用,在info()中有用户可以控制的call调用,用户精心构造传入的数据(将注释转为字节序列),即可绕过require()的限制,成功执行下面的代码。

对于call注入的问题,实际造成的漏洞影响取决于被调用的函数,那么可能的安全问题包括:

1.权限绕过如同上面的例子,合约将合约本身的地址作为权限认证的条件之一,但由于call的调用会导致msg.sender变量值更新为调用方的值,所以就会引起权限绕过的问题。

上述例子表示了权限绕过导致的任意用户提取货币。,withdraw()函数设计的初衷为只能有合约拥有者和合约本身可以发起取款的操作;但由于call的问题,只要用户精心拼接字符序列调用call,从而调用withdraw()函数,就可以绕过isAuth()并取款。

2.窃取代币在代币合约中,往往会加入一个call回调函数,用于通知接收方以完成后续的操作。但由于call调用的特性,用户可以向call传入transfer()函数调用,即可窃取合约地址下代币。

下面的例子表示了用户传入transfer()函数导致窃取代币。

该例子是代币合约的代码片段,用户传入精心构造的字符序列以通过call来调用transfer()函数,并传入transfer()的参数_to为自己的地址;通过call调用后,transfer()函数执行时的msg.sender的值已经是合约地址了,_to地址是用户自己的地址,那么用户就成功窃取了合约地址下的代币。

1.ATN代币增发

2018.5.11,ATN技术人员收到异常监控报告,显示ATNToken供应量出现异常,通过分析发现Token合约由于存在漏洞受到攻击。该事件对应了上文中的第一种利用模型,由于ATN代币的合约中的疏漏,该事件中call注入不但绕过了权限认证,同时还可以更新合约拥有者。

黑客通过调用transferFrom()函数,并传入黑客自己的地址作为_from参数,ATN合约的地址作为_to参数,并传入setOwner()作为回调函数;在执行过程中,由于call调用自动忽略多余的参数,黑客的地址将作为setOwner()的参数成功执行到函数内部,与此同时,call调用已经将msg.sender转换为了合约本身的地址,也就绕过了isAuthorized()的权限认证,黑客成功将合约的拥有者改为了自己;随后调用Mint()函数为自己发行代币,最后黑客再次调用setOwner()将权限还原,企图销毁作案现场。

得力于ATN代币团队及时发现问题,并高效的解决问题,此次事件并未对ATN代币造成较大的波动;ATN代币团队封锁了黑客账户,也销毁了由黑客发行的1100W个代币,最后在交易所的配合下追踪黑客。

2.大量代币使用不安全代码

对于第二种利用模型,在目前公开的智能合约中,仍有不少合约使用这种不安全的代码,为了实现通知接收方以完成后续的操作,加入了一个高度自由的回调函数方法。以下是存在安全隐患的代码片段:

黑客通过调用approveAndCallcode()函数,将合约地址作为_spender参数,并将transfer()的调用转换为字节序列作为_extraData参数,最终调用transfer()函数。在transfer()函数中,_to参数为黑客的地址,而此时msg.sender的值已经是合约本身的地址了,黑客通过这种方式,成功窃取了合约地址中的代币。

callcode:调用后内置变量msg的值会修改为调用者,但执行环境为调用者的运行环境。

由于callcode同时包含了call和delegatecall的特性,通过上文对call和delegatecall的安全问题进行了分析和举例,可以得出的结论是call和delegatecall存在的安全问题将同时存在于callcode中,这里不再进行详细的分析。

目前,区块链技术极高的热度促使该技术不断的投入到了生产环境中,但还没有完整的技术流水线,也没有统一的行业规范,同时Solidity语言现在版本为0.4.25,还没有发布第一个正式版本,导致基于区块链技术的产品出现各种安全漏洞,部分漏洞可以直接造成经济损失。

针对文中所提到的安全隐患,这里给开发者几个建议:

基于已知的欺骗手段,我们通过内部的以太坊智能合约审计系统一共寻找到118个蜜罐智能合约地址,一共骗取了34.7152916个以太币(2018/06/26价值102946元人民币),详情请移步文末附录部分。

对于该类蜜罐合约来说,仅仅使用最原始的欺骗手法。这种手法是拙劣的,但也有着一定的诱导性。

在github上看到的合约代码如下:

细读代码会发现GetFreebie()的条件很容易被满足:

只要转账金额大于1ether,就可以取走该智能合约里所有的以太币。

但事实绝非如此,让我们做出错误判断的原因在于github在显示超长行时不会自动换行。下图是设置了自动换行的本地编辑器截图:

图中第21行和第29行就是蜜罐作者通过超长空格隐藏起来的代码。所以实际的脆弱点是这样的:

先将账户余额转给合约的创立者,然后再将剩余的账户余额(也就是0)转给转账的用户(受害者)

与之类似的智能合约还有TestToken,留待有兴趣的读者继续分析:

该类蜜罐合约用2012年春晚小品《天网恢恢》中这么一段来表现最为合适:

送餐员:外卖一共30元骗子B:没零的,100!送餐员:行,我找你......70!(送餐员掏出70给骗子B)骗子A:哎,等会儿等会儿,我这有零的,30是吧,把那100给我吧!给,30!(骗子A拿走了B给送餐员的100元,又给了送餐员30元)送餐员:30元正好,再见!

该类漏洞也是如此,在看起来正常的逻辑下,总藏着这样那样的陷阱。

整个智能合约的逻辑很简单,三个关键函数功能如下:

如果我们想取走合约里所有的以太币,只需要按照如下流程进行操作:

但实际场景中,受害者转入一个以太币后并没有获取到整个智能合约的余额,这是为什么呢?

这是因为在合约创立之后,任何人都可以对合约进行操作,包括合约的创建者:

合约创建者在合约被攻击前,设置一个只有创建者知道的密码并将passHasBeenSet置为True,将只有合约创建者可以取出智能合约中的以太币。

与之类似的智能合约还有NEW_YEARS_GIFT:

对于multiplicate()而言,只要你转账的金额大于账户余额,就可以把账户余额和你本次转账的金额都转给一个可控的地址。

在这里我们需要知道:在调用multiplicate()时,账户余额=之前的账户余额+本次转账的金额。所以msg.value>=this.balance只有在原余额为0,转账数量为0的时候才会成立。也就意味着,账户余额永远不会比转账金额小。

与之类似的智能合约还有PINCODE:

根据关键代码的内容,如果我们可以通过useEmergencyCode()中的判断,那就可以将owner设置为我们的地址,然后通过withdraw()函数就可以取出合约中的以太币。

该部分引用自参考链接5重点:Solidity的继承原理是代码拷贝,因此换句话说,继承的写法总是能够写成一个单独的合约。情况五:子类父类有相同名字的变量。父类A的test1操纵父类中的variable,子类B中的test2操纵子类中的variable,父类中的test2因为没被调用所以不存在。解释:对EVM来说,每个storagevariable都会有一个唯一标识的slotid。在下面的例子说,虽然都叫做variable,但是从bytecode角度来看,他们是由不同的slotid来确定的,因此也和变量叫什么没有关系。

根据样例中的代码,我们将该合约的核心代码修改如下:

变量owner1是父类Owner中的owner变量,而owner2是子类TestBank中的变量。useEmergencyCode()函数只会修改owner2,而非owner1,自然无法调用withdraw()。由于调用useEmergencyCode()时需要转作者设置的evaluewei的以太币,所以只会造成以太币白白丢失。

区块链的去中心化给博彩行业带来了新的机遇,然而久赌必输这句话也不无道理。本章将会给介绍四个基于区块链的赌博游戏并分析庄家如何赢钱的。

该合约设置了一个1-20的随机数:secretNumber,玩家通过调用play()去尝试竞猜这个数字,如果猜对,就可以取走合约中所有的钱并重新设置随机数secretNumber。

这里存在两层猫腻。第一层猫腻就出在这个play()。play()需要满足两个条件才会运行:

由于生成的随机数在1-20之间,而竞猜的数字不能大于10,那么如果随机数大于10呢?将不会有人能竞猜成功!所有被用于竞猜的以太币都会一直存储在智能合约中。最终合约拥有者可以通过kill()函数取出智能合约中所有的以太币。

OpenAddressLottery的逻辑很简单,每次竞猜,都会根据竞猜者的地址随机生成0或者1,如果生成的值和LuckyNumber相等的话(LuckyNumber初始值为1),那么竞猜者将会获得1.9倍的奖金。

对于安全研究人员来说,这个合约可能是这些蜜罐智能合约中价值最高的一个。在这里,我将会使用一个demo来说一说Solidity编译器的一个bug:

在运行test()之前,addr、b、c、d的值如下图所示:

在运行了test()之后,各值均被覆盖。

截止笔者发文,Solidity0.5.0依旧没有推出。这也就意味着,目前所有的智能合约都可能会受到该bug的影响。我们将会在3.2.2节中说一说这个bug可能的影响面。想了解蜜罐智能合约而非bug攻击面的读者可以跳过这一小节

对于该蜜罐智能合约而言,当forceReseed()被调用后,s.component4=tx.gasprice*7;将会覆盖掉LuckyNumber的值,使之为7。而用户生成的竞猜数字只会是1或者0,这也就意味着用户将永远不可能赢得彩票。

在3.2.1节中,介绍了OpenAddressLottery智能合约使用未初始化的结构体局部变量直接覆盖智能合约中定义的前几个变量,从而达到修改变量值的目的。

按照这种思路,特意构造某些参数的顺序,比如将智能合约的余额值放在首部,那么通过变量覆盖就可以修改余额值;除此之外,如果智能合约中常用的owner变量定义在首部,便可以造成权限提升。

示例代码1如下(编译器选择最新的0.4.25-nightly.2018.6.22+commit.9b67bdb3.Emscripten.clang):

如图所示,攻击者0x583031d1113ad414f02576bd6afabfb302140225在调用fake_foo()之后,成功将owner修改成自己。

在2.3节中,介绍了Solidity的继承原理是代码拷贝。也就是最终都能写成一个单独的合约。这也就意味着,该bug也会影响到被继承的父类变量,示例代码2如下:

相比于示例代码1,示例代码2更容易出现在现实生活中。由于示例代码2配合复杂的逻辑隐蔽性较高,更容易被不良合约发布者利用。比如利用这种特性留后门。

solidity开发者将在0.5.0版本将该类问题归于错误处理。

这个合约的逻辑是:每次请求fallback(),变量jackopt就是加上本次传入的金额。如果你传入的金额大于之前的jackopt,那么owner就会变成你的地址。

看到这个代码逻辑,你是否感觉和2.2节、2.3节有一定类似呢?

让我们先看第一个问题:msg.value>jackopt是否可以成立?答案是肯定的,由于jackopt+=msg.value在msg.value>jackopt判断之后,所以不会出现2.2节合约永远比你钱多的情况。

然而这个合约存在与2.3节同样的问题。在msg.value>jackopt的情况下,KingOfTheHill中的owner被修改为发送者的地址,但Owned中的owner依旧是合约创建人的地址。这也就意味着取钱函数takeAll()将永远只有庄家才能调用,所有的账户余额都将会进入庄家的口袋。

与之类似的智能合约还有RichestTakeAll:

这个智能合约有趣的地方在于它设置了最大转账上限是50finney,最小转账下限是2wei(条件是大于1wei,也就是最小2wei)。每次转账之后,最大转账上限都会缩小成原来的一半,当总转账数量大于等于100finney,那就可以取出庄家在初始化智能合约时放进的钱。

假设我们转账了x次,那我们最多可以转的金额如下:

根据高中的知识可以知道,该数字将会永远小于100

而智能合约中设置的赢取条件就是总转账数量大于等于100finney。这也就意味着,没有人可以达到赢取的条件!

了解过DAO事件以及重入漏洞可以很明显地看出,CashOut()存在重入漏洞。

在了解重入漏洞之前,让我们先了解三个知识点:

如果我们调用合约中的CashOut(),关键代码的调用过程如下图:

由于回退函数可控,如果我们在回退函数中再次调用CashOut(),由于满足_am<=balances[msg.sender],将会再次转账,因此不断循环,直至合约中以太币被转完或gas消耗完。

根据上述分析写出攻击的代码如下:

模拟的攻击步骤如下:

虽然此时用户A的余额仍然存在,但由于合约中已经没有以太币了,所以A将无法取出其存入的50个以太币

根据以上的案例可以得出如下结论:当普通用户将以太币存取该蜜罐智能合约地址,他的代币将会被恶意攻击者通过重入攻击取出,虽然他依旧能查到在该智能合约中存入的代币数量,但将无法取出相应的代币。

逻辑看起去很简单,只要在调用withdrawal()时发送超过1ether,该合约就会把余额全部转给发送者。至于通过delegatecall()调用的logEvent(),谁在意呢?

在DASPTOP10的漏洞中,排名第二的就是访问控制漏洞,其中就说到delegatecall()。

delegatecall()和call()功能类似,区别仅在于delegatecall()仅使用给定地址的代码,其它信息则使用当前合约(如存储,余额等等)。这也就意味着调用的logEvent()也可以修改该合约中的参数,包括adr。

举个例子,在第一个合约中,我们定义了一个变量adr,在第二个合约中通过delegatecall()调用第一个合约中的logEvent()。第二个合约中的第一个变量就变成了0x1111。这也就意味着攻击者完全有能力在logEvent()里面修改adr的值。

为了验证我们的猜测,使用evmdis逆向0x25df6e3da49f41ef5b99e139c87abc12c3583d13地址处的opcode。logEvent()处的关键逻辑如下:

翻译成Solidity的伪代码大致是:

这也就意味着,在调用蜜罐智能合约firstTest中的withdrawal()时,emails.delegatecall(bytes4(sha3("logEvent()")));将会判断第一个变量Owner是否是0x46FEEB381E90F7E30635B4F33CE3F6FA8EA6ED9B,如果相等,就把adr设置为当前合约的地址。最终将会将该合约中的余额转给当前合约而非消息的发送者。adr参数被偷梁换柱!

在说逻辑之前,我们需要明白两个概念:

如同官方文档所说,当i=255后,执行i++,将会发生整数溢出,i的值重新变成0,这样循环将不会结束。

根据这个智能合约的内容,只要转超过0.1ether并调用Test(),将会进入循环最终得到amountToTransfer的值,并将amountToTransferwei发送给访问者。在不考虑整数溢出的情况下,amountToTransfer将会是msg.value*2。这也是这个蜜罐合约吸引人的地方。

正是由于for循环中的i存在整数溢出,在i=255执行i++后,i=0导致multi=0

细细算来,转账至少了0.1ether(100000000000000000wei)的以太币,该智能合约转回510wei以太币。损失巨大。

与之类似的智能合约还有Test1:

该智能合约大致有存钱、计算利息、取钱等操作。在最开始的分析中,笔者并未在整个合约中找到任何存在漏洞、不正常的地方,使用Remix模拟也没有出现任何问题,一度怀疑该合约是否真的是蜜罐。直到打开了智能合约地址对应的页面:

举例:当我们调用了send(from,to,"",amount),经过编译器处理后的调用则是send(from,to,amount)。编写测试代码如下:

在Remix中将编译器版本修改为0.4.11+commit.68ef5810.Emscripten.clang后,执行divest()函数结果如下:

在这个智能合约中也是如此。当我们需要调用divest()取出我们存进去的钱,最终将会调用this.loggedTransfer(amount,"",msg.sender,owner);。

因为编译器的bug,最终调用的是this.loggedTransfer(amount,msg.sender,owner);,具体的转账函数处就是owner.call.value(amount)。成功的将原本要转给msg.sender()的以太币转给合约的拥有者。合约拥有者成功盗币!

在分析过程中,我愈发认识到这些蜜罐智能合约与原始的蜜罐概念是有一定差别的。相较于蜜罐是诱导攻击者进行攻击,智能合约蜜罐的目的变成了诱导别人转账到合约地址。在欺骗手法上,也有了更多的方式,部分方式具有强烈的参考价值,值得学习。

这些蜜罐智能合约的目的性更强,显著区别与普通的钓鱼行为。相较于钓鱼行为面向大众,蜜罐智能合约主要面向的是智能合约开发者、智能合约代码审计人员或拥有一定技术背景的黑客。因为蜜罐智能合约门槛更高,需要能够看懂智能合约才可能会上当,非常有针对性,所以使用蜜罐这个词,我认为是非常贴切的。

这也对智能合约代码审计人员提出了更高的要求,不能只看懂代码,要了解代码潜在的逻辑和威胁、了解外部可能的影响面(例如编辑器bug等),才能知其然也知其所以然。

对于智能合约代码开发者来说,先知攻才能在代码写出前就拥有一定的警惕心理,从源头上减少存在漏洞的代码。

欢迎扫码咨询:

基于已知的欺骗手段,我们通过内部的以太坊智能合约审计系统一共寻找到118个蜜罐智能合约地址,具体结果如下:

首先,我们先假设自己就是Owner,来研究该漏洞的利用流程,以下是存在漏洞的函数:

该合约相当于一个代币分配的协议,Owner可以随意给人分配代币,但是不能超过如下的限制:

代币的总额:uint256constantINITIAL_AMOUNT=100*onePercent;给顾问5%:uint256constantADVISORS_AMOUNT=5*onePercent;创始人要15%:uint256constantFOUNDERS_AMOUNT=15*onePercent;销售出了60%:uint256constantHOLDERS_AMOUNT=60*onePercent;保留了20%:uint256constantRESERVE_AMOUNT=20*onePercent;

对应到下面三个判断:

跟上一个CVE一样,该漏洞本质上也是整型上溢出,但是上一个漏洞,用户可控的变量来至于向合约转账的以太币的数值,所以在实际情况中,基本不可能利用。但是在该漏洞中,用户可控的变量_amount,是由用户任意输入,使得该漏洞得以实现

下面,利用漏洞给顾问分配超过5%的代币:

经过后续的审计,发现该合约代码中的own变量只能由Owner修改,所以该漏洞只能被Owner利用

该漏洞被称为:”超额铸币“,但实际和之前的漏洞没啥区别

存在漏洞的函数:

比上一个漏洞的代码还更简单,只有ico(相当于之前的owner)能执行该函数,阅读全篇代码,ico是在合约部署的时候由创建人设置的,后续无法更改,所以该漏洞只能被ico(owner)利用

该合约本身的意图是,ico能随意给人分配代币,但是发行代币的总额度不能超过tokenLimit,但是通过整型上溢出漏洞,能让ico发行无限个代币,利用流程如下:

该漏洞被称为:“随意铸币”

具有漏洞的函数:

这个漏洞很简单,也很好理解,Owner可以随意增加任意账户的代币余额,可以想象成,银行不仅能随心所欲的印钞票,还能随心所以的扣你的钱

因为Owner是在合约部署的时候被设置成合约部署者的账户地址,之后也只有Owner能修改Own账户地址,所以该漏洞只能被Owner利用

这个我觉得与其说是漏洞,不如说是Owner留下的“后门”

该漏洞被称为:“下溢增持”

该合约限制了发行代币的上限:uint256_totalSupply=21000000*10**8;

并且在合约部署的时候把能发行的合约都分配给了Owner:balances[owner]=21000000*10**8;

然后Owner可以把自己账户的代币,任意分配给其他账户,分配的代码就是上面的函数,给别人分配一定额度的代币时,自己减去相应额度的代币,保证该合约总代币数不变

但是因为没有判断Owner的账户是否有足够的余额,所以导致了减法的整型下溢出,同样也存在整型上溢出,但是因为uint256的上限是2^256-1,但是利用过于繁琐,需要运行非常多次的balances[addresses[i]]+=2000*10**8;

而减法的利用就很简单了,或者我们可以根本不考虑这个减法,Owner可以给任意账户分配2000*10**8倍数的代币,该漏洞的功能和上一个漏洞的基本一致,可以任意发行代币或者减少其他账户的代币数

因为Owner是在合约部署的时候被设置为部署合约人的账户地址,后续没有修改own的功能,所以该漏洞也只有Owner可以利用

该漏洞被称为:“高卖低收”

在该CVE的描述中,存在漏洞的函数是:

并且描述的漏洞原理是:

sellPrice被修改为精心构造的大数后,可导致amount*sellPrice的结果大于整数变量(uint256)最大值,发生整数溢出,从而变为一个极小值甚至归零`

该漏洞的利用流程如下:

表面上看这个漏洞还是有危害的,但是我们仔细想想,这个漏洞其实是比较多余的,我们可以使用更简单的步骤达到相同的目的:

我认为该合约最大的问题在于Owner可以随意设置代币的买入和卖出价格。

如果我们把智能合约类比为传统合同,智能合约代码就是传统合同的内容,但是和传统的合同相比,智能合约拥有三个利益团体,一个是编写合约代码的人(智能合约中的Owner,或者我们可以称为甲方),使用该合约的其他人(我们可以称为乙方),跟该智能合约无关的其他人(比如利用合约漏洞获利的黑客)。从这个角度来看Owner条件下触发的漏洞在理论上是可以损害到乙方的利益,如对于存在“恶意”的owner或者黑客配合其他漏洞获取到owner权限的场景上来说,还是有一定意义的。

由此可见合约审计对于“甲方”、“乙方”、交易所都有重要的意义。

在大多数情况下,MEWKit实例的后端服务器为攻击者提供了他们正在从事的工作的概况。

虽然MyEtherWallet支持各种硬件钱包,如Trezor8,LedgerWallet9,Digital,Bitbox10和Secalot11,但却不支持从这些钱包中获取密钥。这意味着那些在使用硬件钱包时被MEWKit钓鱼的人不会受到MEWKit的ATS的影响,但仍然需要在处理之前确认其钱包上的交易。因为硬件钱包的私钥存储在内部,因此不会暴露于MEWKit。

以下部分概述了我们在RiskIQ数据库中集中观察到的所有数据攻击。以下各节中提到的AnyIOC也可以在本报告末尾的妥协指标(IOC)部分中找到。

请注意,我们没有描述观察到的每个MEWKit钓鱼网站,只列出了那些因各小节中描述的原因而可以进行钓鱼攻击的钓鱼网站。我们观察到的所有主机的完整列表可以在本报告结尾附近的“妥协指标”部分找到。

通常在亚马逊的AS16509下宣布(并维护)的以下IP块已由eNet在AS1029713下公布:

205.251.192.0/24205.251.193.0/24205.251.195.0/24205.251.197.0/24205.251.199.0/24

这些IP地址是AmazonRoute53为通过此服务维护的任何域执行DNS路由的一部分。驻留在AS10297中的上述IP块的新端点开始路由预定用于路由53的一些流量并回复来自用户的DNS查询。

实际上,我们可以看到这个AS宣布的前缀相对于它通常所宣称的非常固定的一组块而言:

最终处理通常用于Route53的流量的DNS服务器只设置了一个域来解决:myetherwallet.com。任何其他请求的域名都会被SERVFAIL响应,这是人们已经注意到的。新的DNS服务器响应一个新的IP地址MyEtherWallet,46.161.42.42,驻留在AS41995。根据地理位置,这台服务器来自俄罗斯。如果我们提供一些有关此AS的WHOIS信息,会发现它并不是一个好兆头。

在东欧分配一个AS,并在WHOIS中使用Gmail等免费服务的电子邮件地址通常是一个不好的迹象。我们可以从组织WHOISdetails中获得更多有关此地址的信息:

根据WHOIS信息,自2014年底以来,电子邮件地址的域名一直存在,并且其详细信息始终存在于WHOIS隐私服务之后。目前,主网站onweb-shield.biz处于离线状态,但通过查看档案数据,我们可以找到一个旧的托管公司网站:

Webshield对我们行业中的许多人来说都很熟悉,因为在他们的网站中有许多用于恶意目的的网站IP空间,其中一个例子是Rescator15。我们最感兴趣的是拥有这个AS的主机却已经关闭了它的网站托管网站,但仍然提供了托管机会。我们可以将Webshield定义为一个防弹主机。

虽然对亚马逊Route53的攻击非常复杂,但攻击者用于托管在WebshieldAS上的服务器上的钓鱼站点的设置却不复杂。他们在服务器上放置的证书实际上并不是有效的证书,他们使用WHOIS隐私服务背后的myetherwallet[.]com创建了自己的自签名证书。这里是以太钱包WHOIS:

以下是我们在使用MEWKit的Webshield主机上观察到的SSL证书:

攻击者只需根据WHOIS详细信息生成证书,该证书由几乎任何现代Web浏览器标记。然而,人们好像还是忽略了这些警告选择了点击,即使有人报告资金被MEWKit从他们的以太钱包中撤出。

MEWKit页面本身与任何正确构建钓鱼页面一样,看起来与正常的以太钱包网站完全相同:

然而,我们在这次攻击中看到的设置与我们在正常MEWKitinstall上看到的不同。如果我们看一下文档对象模型(DOM),我们会看到正常的MEWKit脚本(顶部MEWKit,底部MyEtherWallet.com):

注意,脚本没有以任何方式混淆,看起来他们似乎是正确的。如果我们看看wallet.js,其中包含日志记录配置和后端位置,我们得到这个:

正如上面MEWKit的功能所解释的,eth_recipient变量与被盗资金的接收者有关。如果我们检查get_state_address函数通常设置(单个)的eth_recipient变量值,我们看到开发者一直在实现多个收件人地址。该代码仍然包含注释部分,开发者忘记将添加的eth_recipient_n变量注释掉,因为它们没有被使用。

该函数还包含一个注释掉的console.log调用,该调用会将消息记录到控制台。这让我们更加确定开发者正在测试用于脚本攻击的新功能。

上面的文字‘проверяемдоступностьсекциистраншем’提到在代码段中检查‘траншем’的可用性,这是一个有趣的用词和重要的发现。该注释是关于下面的代码将通过钱包地址来获得钱包中资金的总余额的事实。‘траншем’这个词是‘ranche’的俄语,来自法语单词,表示交易的一部分或一部分。

第一条注释‘получаембаланс’,即’得到平衡’,第二条注释’баланс’是平衡’一词,第三条注释,’стопработ’,意为’停止工作’,这能说得通是因为当程序检查到余额为0的时候来到了这条正确的分支,意味着ATS没有资金可以转移而程序可以停止工作了。

第一条注释,’оставитькошелекполучателя’,翻译过来就是’设置收款人的钱包’,这与设置从钓鱼受害者的钱包中转移资金的交易收款人钱包地址的函数有关。第二条注释,’отправитьвесьбалансвэмаунт’,翻译过来就是’将全部余额转移’。这句话中的最后一个单词’эмаунт’是拼写为西里尔文的非俄语单词。

这些注释的出现意味着脚本的作者是一个以俄语为母语并至少拥有一定财务知识的人。

自事件发生以来,已经发布了很多关于这次具体攻击的具体细节,但我们决定更深入地了解到底发生了什么,并挖掘出与MEWKit相联系的额外见解。亚马逊Route53劫持(事件)只有一个目标。虽然这次袭击的范围相对较小,但其范围可以更为巨大。

互联网是在几十年前创建的,并不是所有的构建模块都已经过时了-BGP和DNS仍然是我们全球互联网中存在问题但至关重要的一部分。与大多数网络安全问题一样,针对这些类型的攻击也有解决方案,但它们的效果取决于链中的每个人都加强安全性并部署解决方案。

几乎所有MEWKit实例都要注意的一点是攻击者利用国际化域名(IDNs)。国际化域名攻击并不新鲜,但遗憾的是,它们在利用MEWKit的攻击中似乎非常有效。

浏览器正在迎头赶上去解决这个问题,Firefox和Chrome都实现了一个非常简单的算法来检查域名中的所有字符是否属于同一种语言。如果不是,则显示以'xn--'开头的IDNA符号。这个过滤器确实可以防止MEWKit的大量攻击,因为攻击者们使用来自西里尔文,希腊文,亚美尼亚文和希伯来文的特殊语言字符来替换带有特殊字符变体的字母。

MEWKit战役中使用的大多数域和主机都使用非常特定的格式来模仿MyEtherWallet。然而一个运行MEWKit的主机却不一样,经过仔细检查后发现其运行了一些令人好奇的脚本。有问题的主机是tikkiepayment.info,托管在31.31.196.186。4月9日,MEWKit实例被托管在myyetherwallett.com/myether/,它从以下位置加载它的MEWKit脚本:

我们还发现位于同一主机上其他MEWKit的后台路径地址:

尽管网络犯罪中窃贼之间通常不存在荣誉,但该工具是其他人可以使用的精简版MyEtherWallet,它检查帐户是否有效并且有一些余额。根据服务器上存在的工具以及它是我们曾经观察过MEWKit上的第一台主机的事实,我们认为这台主机是由MEWKit的创建者设置的。此外,根据本报告底部IOC部分显示的注册信息,域名会在任何MEWKit主机设置之前一个月进行登记。

尽管我们不能确切的说MEWKit操作是单一攻击者,但我们确实发现了MEWKit实例和其他加密货币和加密货币交易所的钓鱼页面之间的一些有趣链接。

4月17日,MEWKit实例在www.xn--myetherwalle-occ.com上正式运行,它的MEWKit脚本从以下位置加载:

后端位置托管在,但另一个MEWKit实例直接托管在cdnsfiles.com上,其资源从上述同一位置加载,后端位置设置为cdns文件的.com/ADM/。

MEWKit自今年年初就一直被广泛使用了,尽管我们在2018年以前都没见过它,但或许MEWKit在外界早已以不同的功能或形式活跃了。BGP劫持亚马逊Route53的行为显示了它驱动的攻击者和活动的持续性,执行其攻击的成本表明MEWKit异常成功,技术虽然简单,但却有效地窃取了以太坊。

正如我们在MEWKit的技术分析中所解释的那样,我们无法估计攻击者的收益,因为我们无法知道攻击者控制了多少钱包和地址,这是由于MyEtherWallet的设置方式是以每个受害者为基础发放的地址的。区块链的架构,特别是以太坊允许每个人通过公簿洞察钱包地址余额,但它也维护了所有者的完全匿名性。直到攻击者被抓获或执法部门提供MEWKit攻击中使用的精确地址的见解前,我们永远不会知道其确切的运作。

我们确实知道,各种钱包已经在社交媒体和论坛上发布,表面上收入可能达数百万美元,但我们无法高度自信地将其与MEWKit联系起来。然而,随着注册域名数量的增加,服务器维护的增多以及活动水平的提高,我们可以推测这次攻击的收入必须足够丰厚,不仅能够维持运营,而且还能盈利。

以下是包含注册日期及用于注册的电子邮件地址的详细域名列表。如果电子邮件地址丢失,这意味着该字段默认由隐私服务或注册商填写。由MEWKit建立和用于活动的域名的注册日期紧密重合。

由于该恶意样本拥有生成随机进程名、对外爆破23端口等特征,故可能是Mirai僵尸网络或其变种。

2018/05/07,我们发现了少量该样本的感染痕迹,通过进一步研究,我们认为该僵尸网络已经回归。由于该样本直接在1.1中的CNC主机上传播,运行时依旧会生成随机进程名,对外爆破23端口,故我们将两者归为同一僵尸网络家族。

新的CNC上线包如下

根据这个上线包,我们将该僵尸网络称为Mirai变种僵尸网络THANOS

但该样本和源码依然有很多地方不同:

该样本在对外扫描时,只会扫描表格中的这些IP

该样本会检测路由器中已有的进程,如果遇到下列可能属于其它僵尸网络的进程,将会进行kill操作(匹配的关键词远比源码中的丰富)

该样本的CNC为:185.33.145.92:252,该CNC依旧处于活跃状态

需要注意的是

利用脚本如下:

该样本的感染逻辑没有太大变化,CNC与上文相同,为:185.33.145.92:252,所以我们认为这与上文同属于Qbot僵尸网络家族的变种。

新的样本看起来更像是Mirai僵尸网络的新变种,具体的感染细节我们仍在持续跟进中。

该样本的CNC为linuxusaarm.com:443

由于该僵尸网络样本众多,多条命令有多次重复感染。故我们通过下图展示各样本和各IP的联系:

图中红点代表各IP,灰点代表感染的bash脚本,黄点代表各恶意样本,蓝点代表出现的链接,红线代表从bash脚本中下载的样本

该样本会连接ztccds.freesfocss.com:23364,样本具体功能仍在研究中。

该样本会连接185.246.152.173:1000,但该端口已经关闭(2018/05/09)。

注:由于仅探测了diag.html页面,故在多轮探测中我们只能确定哪些主机被攻击,无法判断攻击者是否攻击成功

在对探测到的主机进行地域划分时,三轮探测中被攻击的IP都位于墨西哥。对受影响最多的五个国家进行抽样测试,结果如下:

该漏洞存在与墨西哥和哈萨克斯坦,但是由于固件不同,只有墨西哥的路由器会返回diag_host,所以我们仅监测到墨西哥的路由器受影响情况。

由于2018/05/05第一轮探测中只统计了存在/tmp字段的diag_host的内容,所以第一轮探测的数据具有一定的局限性。

可以很明显看出:

近年来,僵尸网络逐渐盯上攻击简单但危害巨大的物联网漏洞。从去年的GoAhead到今年的GPON事件,无不在提醒我们物联网安全的重要性。能结合ZoomEye网络空间搜索引擎了解到GPON事件背后活跃的僵尸网络动态,对我们来说就是一种收获。

关于ZoomEyeDork,欢迎加入小密圈(免费):

这里简单的说下几个有公开利用方式的Weblogic反序列化漏洞。

但是这种修复方式很被动,存在被绕过的风险,只要发现可用并且未在黑名单之外的反序列化类,那么之前的防护就会被打破,系统遭受攻击。而后的漏洞也证明了这一点。

Weblogic的反序列化的点有着三个,黑名单ClassFilter.class也作用于这三个位置。

有人发现利用weblogic.jms.common.StreamMessageImpl的readExternal()也是可以进行反序列化操作的,而且这个不受黑名单限制,所以可以绕过了之前的补丁。

原理是将反序列化的对象封装进了weblogic.corba.utils.MarshalledObject,然后再对MarshalledObject进行序列化,生成payload字节码。反序列化时MarshalledObject不在WebLogic黑名单里,可正常反序列化,在反序列化时MarshalledObject对象调用readObject时对MarshalledObject封装的序列化对象再次反序列化,这样就逃过了黑名单的检查。

Java远程消息交换协议JRMP即JavaRemoteMessagingProtocol,是特定于Java技术的、用于查找和引用远程对象的协议。这是运行在Java远程方法调用RMI之下、TCP/IP之上的线路层协议。

这个漏洞就是利用RMI机制的缺陷,通过JRMP协议达到执行任意反序列化payload的目的。使用ysoserial的JRMPLister,这将会序列化一个RemoteObjectInvocationHandler,该RemoteObjectInvocationHandler使用UnicastRef建立到远端的TCP连接获取RMIregistry。此连接使用JRMP协议,因此客户端将反序列化服务器响应的任何内容,从而实现未经身份验证的远程代码执行。

仿照JRMPClient写一个JRMPClient2,重新编译。

生成payload:

除了RMI接口不一样,其他都是一样的。

JRMPLister开启

我测试的Weblogic版本是10.3.6.0.170117,即已修复了CVE-2017-3248漏洞,在我本地的环境中,CommonsCollections这个payload已经失效了。Weblogic的commons-collections.jar版本已经升级,所以我这里payload用的是Jdk7u21(这个payload只有在JRE版本小于等于1.7u21才起作用)。在commons-collections.jar版本没有升级的Weblogic中,使用CommonsCollections这个payload是可以的。

作为对比,将JRMPClient生成的p_client也发送过去,可以看到报错信息Unauthorizedproxydeserialization,正是黑名单拦截抛出的错误。

可见java.rmi.activation.Activator是绕过了CVE-2017-3248的补丁了。

这种方式是我在复现漏洞时尝试payload的时候发现的,绕过的方式和CVE-2016-0638有关。

StreamMessageImpl这个点在反序列化的时候没有resolveProxyClass检查。所以可以使用StreamMessageImpl将RemoteObjectInvocationHandler序列化,以此来绕过resolveProxyClass函数。相当于使用CVE-2016-0638的利用方式加上CVE-2017-3248的payload来绕过补丁。

将JRMPClient生成的payloadObject用StreamMessageImpl封装生成新的payload——p_stream。

初步比对补丁(p27395085_1036_Generic),发现WeblogicFilterConfig.class的黑名单多了一个sun.rmi.server.UnicastRef。

总的来说,Weblogic反序列化漏洞就是在不停的修复-绕过-修复-绕过……最精彩的永远是下一个!

还有一些隐藏的条件

1、CSP

挺有趣的写法,经过我的测试,两个CSP分开写,是同时生效并且单独生效的,也就是与的关系。

换个说法就是,假设我们通过动态生成script标签的方式,成功绕过了第二个CSP,但我们引入了,就会被第一条CSP拦截,很有趣的技巧。

从CSP我们也可以简单窥得一些利用思路,base-uri'none'代表我们没办法通过修改根域来实现攻击,default-src'none'这其中包含了frame-src,这代表攻击方式一定在站内实现,script-src的双限制代表我们只能通过,那么中间的代码就会被视为js代码,被CSP拦截。

我们成功的覆盖了effects变量,紧接着我们需要覆盖effects[$("#effect").val()],这里我们选择id属性(这里其实是为了id会使用两次,可以更省位数),

所以我们尝试传入

成功执行

接下来的问题就在于怎么构造获取flag了,这里最大的问题在于怎么解决位数不够的问题,我们可以简单计算一下。

上面的payload最简化可以是

下面写一种来自@超威蓝猫的解法,非常有趣的思路,payload大概是这样的

通过jqueryget获取flag内容,通过箭头函数将返回赋值给window.name,紧接着,我们需要想办法获取这里的window.name。

这里用到一个特殊的跨域操作

这里用到了一个特殊的特性,就是window.name不跟随域变化而变化,通过window.name我们可以缓存原本的数据。

完整payload

然后通过loginnext=这里来跳转到这里,成功理顺

这个思路受限于当前页面CSP没有unsafe-eval,刚才说到window.name不随域变化而变化,那么我们传入payload

然后在自己的服务器上设置

这样我们就能设置window.name了,如果允许eval的话,就可以通过这种方式绕过长度限制。

下面顺着思路一起来看看这题。

站内差不多是一个答题站点,用了比较多的第三方库,站内的功能比较有限。

还有一些特别的点

1、user.php页面的CSP为

非常严格,只允许nonceCSP的script解析

index.php页面的CSP为

允许sdCSP动态执行script(这里的出发点可能是index.php是加载游戏的地方,为了适应CSP,必须加入strict-dynamic。)

2、站内有两个xss点

第一个是user.php的profile,储存型xss,没有任何过滤。

第二个是index.php的msg参数,反射性xss,没有任何过滤,但是受限于xssauditor

顺着思路向下

因为user.php页面的CSP非常严格,我们需要跳出这个严格的地方,于是可以通过插入meta标签,跳转到index.php,在这里进一步操作

当然这里我们也可以利用储存型xss和页面内的一段js来构造a标签跳转。

在user.php的查看profile页面,我们可以看到

当我们插入

并请求

那么这里的a标签就会被点击,同样可以实现跳转。

接着我们探究index.php,这里我们的目标就是怎么能够绕过sdCSP了,当时的第一个想法是,通过修改当前页面的根域,我们可以加载其他域的js(听起来很棒!

可惜如果我们请求

会被xssauditor拦截,最后面没办法加/">,一个非常有趣的情况出现了

最后的中的/被转换成了路径,前面的左尖括号被拼入了域名中,后面的右尖括号闭合标签…一波神奇的操作…

不过这里因为没法处理尖括号域名的事情,所以置于后话不谈。

我们继续讨论绕过sdCSP的思路,这种CSP已知只有一种办法,就是通过现在已有的js代码构造xss,这是一种在去年blackhat大会上google团队公布的CSPBypass技巧,叫做ScriptGadgets。

这里的漏洞点和ppt中的思路不完全一致,但核心思路一样,都是要利用已有js代码中的一些点来构造利用。

站内关于游戏的代码在app.js中的最下面,加载了client.js

client.js中的代码不多,有一些值得注意的点,就是客户端是通过postMessage和服务端交互的。

ps:这是一个呆子不开口在2016年乌云峰会上提到的攻击手法,通过postMessage来伪造请求

这样我们可以使用iframe标签来向beckend页面发送请求,通过这种方式来控制返回的消息。

这里我盗用了一张别的wp中的图,来更好的描述这种手法

这里我们的exploit.html充当了中间人的决赛,代替客户端向服务端发送请求,来获取想要的返回

如果我们能控制data.title,通过这里的domxss,我们可以成功的绕过index.php下的sdCSP限制。

值得注意的是,如果我们试图通过index.php页面的反射性xss来引入iframe标签的话,如果iframe标签中的链接是外域,会被xssauditor拦截。

所以这里需要用user.php的储存型xss跳出。这样利用链比较完整了。

1、首先我们需要注册两个账号,这里使用ddog123和ddog321两个账号。

2、在ddog321账号中设置profile公开,并设置内容为

4、在ddog123账户中设置profile为

5、最后在1.js中加入利用代码,发送report给后台等待返回即可。

TCTF/0CTF中的压轴题目,整个题目的利用思路都是近几年才被人们提出来的,这次比赛我也是第一次遇到环境,其中关于Appcache以及ServiceWorker的利用方式非常有趣,能在特殊环境下起到意想不到的作用。

下面的Writeup主要来自于

先简单说一下整个题目逻辑

2、站内开启CSP,而且是比较严格的nonceCSP

值得注意的是这里有一个特例

值得注意的是,embed.php中的embed这里存在反射性xss点,只要闭合注释就可以插入标签,遗憾的是这里仍然会被CSP限制。

5、图片上传的接口可以上传SVG,图片在站内同源,并且不受到CSP的限制,我们可以在SVG中执行js代码,来绕过CSP,而重点就是,我们只能提交blogid,我们需要找到一个办法来让它执行。

在提示中,我们很明显可以看到cache这个提示,这里的提示其实是说,利用appcache来加载svg的方式。

这是一种在数年前随H5诞生的一种可以让开发人员指定浏览器缓存哪些文件以供离线访问,在缓存情况下,即使用户在离线状态刷新页面也同样不会影响访问。

Appcache的开启方法是在html标签下添加manifest属性

这里的example.appcache可以是相对路径也可以是绝对路径,清单文件的结构大致如下:

CACHE:这是条目的默认部分。系统会在首次下载此标头下列出的文件(或紧跟在CACHEMANIFEST后的文件)后显式缓存这些文件。

NETWORK:此部分下列出的文件是需要连接到服务器的白名单资源。无论用户是否处于离线状态,对这些资源的所有请求都会绕过缓存。可使用通配符。

这里有一点儿很重要,关于Appcache,您必须修改清单文件本身才能让浏览器刷新缓存文件。

这里正是使用了Appcache的FALLBACK文件,我们可以通过上传恶意的svg文件,形似

然后将manifest设置为相对目录的svg文件路径,形似

在这种情况下,如果我们能触发页面500,那么页面就会跳转至FALLBACK指定页面,我们成功引入了一个任意文件跳转。

紧接着,我们需要通过引入[ig]a#[/ig],通过拼接url的方式,这里的#会使后面的&instagram无效,使页面返回500错误,缓存就会将其引向FALLBACK设置页面。

这里的payload形似

上面的iframe标签会引入我们提前上传好的manfiest文件

并将FALLBACK设置为/blog/untrusted_files/[SVG_HAVING_XSS_PAYLOAD].svg

然后下面的iframe标签会访问/blog/untrusted_files/embed/embed.phpembed=a并处罚500错误,跳转为提前设置好的svg页面,成功逃逸CSP。

当我们第一次读取到document.cookie时,返回为

大致意思是说,bot会在5秒后访问flag页面,我们需要获取这个id。

在不具有窗口引用办法的情况下,这里只有使用ServiceWorker来做持久化利用。

关于ServiceWorker忽然发现以前很多人提到过,但好像一直都没有被重视过。这种一种用来替代Appcache的离线缓存机制,他是基于WebWorker的事件驱动的,他的执行机制都是通过新启动线程解决,比起Appcache来说,它可以针对同域下的整站生效,而且持续保存至浏览器重启都可以重用。

下面是两篇关于serviceworker的文档:

使用ServiceWorker有两个条件:

当我们满足上述条件,并且有一个xss利用点时,我们可以尝试构造一个持久化xss利用点,但在利用之前,我们需要更多条件。

1、如果我们使用navigator.serviceWorker.register来注册js,那么这里请求的url必须同源而且请求文件返回头必须为text/javascript,application/x-javascript,application/javascript中的一种。

2、假设站内使用onfetch接口获取内容,我们可以通过hookfetch接口,控制返回来触发持久化控制。

对于第一种情况来说,或许我们很难找到上传js的接口,但不幸的是,jsonp接口刚好符合这样的所有条件~~

最后的这个ppt最详细,但他是日语的,读起来非常吃力。

这里回到题目,我们可以注意到站内刚好有一个jsonp接口

值得注意的是,这里的callback接口有字数限制,这里可以通过和title的配合,通过注释来引入任何我们想要的字符串。

这里需要注意的是,在serviceWorker线程中,我们并不能获取所有的对象,所以这里直接获取当前请求的url。

THE END
1.微信涉嫌网赌但是我没有网赌怎么办微信涉嫌网赌但是我没有网赌怎么办 在面临微信账号被质疑涉入网络赌博活动,而事实上您本人并未涉及其中时,请勿慌乱失措。首先,您应该保持冷静并积极与有关部门进行合作,向他们真实详细地说明自己无任何参与网络赌博行为的经过。同时,务必竭力保存所有可以证明您未曾涉足相关事件的各类证据材料,包括但不限于各种聊天记录https://www.64365.com/special/24762346
2.欢乐斗地主算不算赌博欢乐斗地主算不算赌博法律分析:算赌钱,不算赌博。赌博可区分为三种: 第一种是作为犯罪的赌博,我国刑法规定了赌博罪,即以营利为目的,聚众赌博、开设赌场或者以赌博为业的行为。 第二种是指作为违法的赌博,是指违反社会治安管理处罚条例的行为。 这种赌博主要针对赌博活动的参与者,或者为赌博提供条件、尚不够刑事处罚的行为,而不是组织https://www.findlaw.cn/wenda/q_40251973.html
3.震惊,网赌被黑不给提现的你是被黑了,别傻傻的等待平台给你提!网上被黑几乎分为三种步骤:第一,你的账号异常第二,限制你的账号部分功能,额数不能转换,出款通道关闭,套利等借口不出款第三,客服客服会以各种理由,系统维护,审核注单,风控审核,银行维护给你带来不便提款,一直拖延你不让出款,等等你信心没有了。挽回损失的方法技巧步骤:第一,被黑后要冷静下来,不要和平台客服理https://www.renrendoc.com/paper/196785111.html
4.pg网赌软件下载官方版下载【pg网赌软件下载】APP下载(2024全站)?系统类型:pg网赌软件下载(官方)官方网站·IOS/安卓通用版/手机APP下载首存送大礼是一款非常好玩的卡牌手游。上百名三国名将陪你战斗到底、感受不一样的精彩、更多策略对决、完美配合带你玩转其中、多种游戏战斗模式可供http://dbpb.fsyyjgc.com/
5.“网络赌博”之刑法定性研究不作为行为的“开设(网络)赌场”,是指行为人(网主)以营利为目的,明知赌徒利用其所开合法网站的某一功能进行赌博,在有能力停止提供服务的情况下仍为犯罪行为提供服务的行为,即被动的自愿提供,成立不作为形式的“开设(网络)赌场”,应当同时具备以下条件:一是网主在主观上以营利为目的,无论其是直接获取赌徒的会员费https://www.360doc.cn/article/819919_846420698.html
6.煤矿基础知识考试试题库带答案14、局部通风机必须安设在进风巷道中,距巷道回风口不得小于10米。 15、矿井通风方式可分为中央式、对角式、混合式三种。 16、矿井气候条件是井下温度、湿度和风速三者综合作用的结果。 17、冒顶处理的特殊施工方法有撞楔法、探板法、木垛法、搭凉棚法。 https://www.mkaq.org/html/2010/11/27/68365.shtml
7.pg网赌软件下载pg网赌软件正版最新版大全游戏TOP热榜:pg网赌软件下载-APP下载支持:64/128bit系统类型:pg网赌软件下载官方网站-App下载(2024全站)最新版本IOS/安卓通用版V.5.2.42支持winall/win7/win10/win11安全平台【下载次数63796】APP,现在下载为您提供官网认证:手机版、app下载、登录http://m.tecoaminor.com/
8.?pg网赌软件下载pg网赌软件正版最新版大全5分钟前pg网赌软件下载APP下载支持:64/128bit位系统类型:pg网赌软件下载官方网站-App下载(2024全站)最新版本IOS/安卓通用版V.0.6.29支持winall/win7/win10/win11安全平台【下载次数607541】APP,现在下载,新用户还送新人礼包是一款非常有趣http://uem.gmdanbao.com/
9.为什么黑客不黑攻击赌博网站?如何入门黑客?自学能成为黑客吗我见过很多因赌博输钱想请黑客帮忙渗透网站的人,在被拒后,同样也有人生出极端心理,问我怎么学习黑客,想学成之后自己去渗透博彩网站,但真正因这个原因自学黑客技术并成功进去的,李四算一个,既不是擅长计算机的工科男,也没有很深的计算机运用知识,只有高中文化水平的李四,又是如何成为黑客的呢? https://blog.csdn.net/m0_61869253/article/details/133813430
10.老王带你搞定社交网络分析三种重要结构:环、簇、树 环 三元闭包构成了一个最小的稳定结构:包含3个节点的环(Loop)。 对一般社交网络来说,环形结构不算特别。在有些场景,环形意味着风险和欺诈。 比如收集一个年度所有车辆受损和理赔案件信息,构成一个理赔网络。因为车辆事故是低概率事件, 这个网络必定是节点数量远远超过边的数量的稀疏图。https://www.51cto.com/article/518897.html