CVE-2018-12067及相似破绽剖析与相干思索 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

CVE-2018-12067及相似破绽剖析与相干思索

申博_新闻事件 申博 101次浏览 已收录 0个评论

一、媒介

近来审计了一波以太坊CVE,本章中说起的破绽包含了浩瀚题目,不只包罗代码上的破绽,还包罗由于函数设想题目而致使的金融学上的破绽。在剖析破绽之余,我也对本文涌现的题目举行进一步思索,并将感受分享给读者。

该破绽仅为这一类破绽的代表,与其相干的相似合约另有许多,这里仅运用最有代表性一个来举行剖析演示。

起首须要简朴的引见一下相干配景。本文平安隐患是以PolyAI 、Substratum为代表的一类项目。Substratum项目主若是打造基于区块链的收集, 简而言之,就是重构如今的互联网效劳,包罗 DNS, 收集空间存储等,个中处理“国际性收集封闭” ,完全为中国定制,可以或许处理国内须要经由历程VPN效劳才可以或许翻墙接见外洋网站的题目。从官网看来,开辟者应该很相识中国国情,网站和白皮书的中文都下了许多工夫,做得很隧道,证实开辟团队异常重视中国市场。

POLY AI 聚焦于基于深度进修的人工智能,谷歌、苹果、Facebook近来在这个范畴贡献了伟大的结果,POLY AI 运用区块链手艺来处理深度进修练习历程当中的盘算斲丧和数据源题目,而且区块链也比一切传统手艺更可以或许供应平安保证。

这些币种的实用性很强,均为某个范畴供应支撑。

二、题目所在

该范例的运用包罗三类题目。起首为可逾额铸币。

为了轻易治理员对运用举行治理,设想者在设想此类运用的时刻添加了发币接口。此类发币接口的运用者为owner而且可以或许没有限定的增添本身发币数目。

function mintToken(address target, uint256 mintedAmount) onlyOwner {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

该函数具有两个参数,包罗目的地点与发币数目。当owner挪用此函数的时刻,其可传入待处理钱包地点并可以或许恣意为钱包账户增添余额。这类要领看似增添了合约的灵活性,可以或许更自立的去修正合约中的种种变量,然则我们都晓得,关于泉币来讲,这类无代价的逾额增发会致使种种题目。虽然此类函数是owner所用, 若是歹意owner存在,那末他便可以或许恣意增添账户泉币数目,当其数目增多时,泉币的市场代价便会受到影响。

其次,该范例合约均存在严峻的破绽,即乘法溢出。

下面我将举例两个例子。

起首我们来看Substratum合约中的函数。

在合约的症结转账函数中,设想者对溢出做出了推断。

function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        if (frozenAccount[msg.sender]) throw;                // Check if frozen
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
    }

即:if (balanceOf[_to] + _value < balanceOf[_to]) throw;当转账金额溢出时实行throw操纵。

但是在后面的卖出函数中却没有举行溢出推断。

function mintToken(address target, uint256 mintedAmount) onlyOwner {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

    function freezeAccount(address target, bool freeze) onlyOwner {
        frozenAccount[target] = freeze;
        FrozenFunds(target, freeze);
    }

    function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

    function buy() payable {
        uint amount = msg.value / buyPrice;                // calculates the amount
        if (balanceOf[this] < amount) throw;               // checks if it has enough to sell
        balanceOf[msg.sender] += amount;                   // adds the amount to buyer's balance
        balanceOf[this] -= amount;                         // subtracts amount from seller's balance
        Transfer(this, msg.sender, amount);                // execute an event reflecting the change
    }

    function sell(uint256 amount) {
        if (balanceOf[msg.sender] < amount ) throw;        // checks if the sender has enough to sell
        balanceOf[this] += amount;                         // adds the amount to owner's balance
        balanceOf[msg.sender] -= amount;                   // subtracts the amount from seller's balance
        if (!msg.sender.send(amount * sellPrice)) {        // sends ether to the seller. It's important
            throw;                                         // to do this last to avoid recursion attacks
        } else {
            Transfer(msg.sender, this, amount);            // executes an event reflecting on the change
        }               
    }
}

在上文函数中,我们可以或许看到用户可以或许实行buy()函数并传入肯定金额,以后经由历程owner预设的buyprice转换为对应的详细代币额度,以后增添用户余额。而在sell函数中,我们能看到合约仅对用户余额是不是足够做了推断,当足够时,用户便可出卖代币。合约地点代币数额总量增添而且削减用户余额。但是在实行msg.sender.send(amount * sellPrice)时涌现了题目,由于amount与sellPrice是可设置的,且合约并没有对其举行溢出检测,以是此处存在异常严峻的破绽。倘使owner为作歹节点,或许sellPrice确切异常大,又由因而乘法的情愿,以是当amount到达肯定额度后,amount * sellPrice就会增添到一个异常大的数额,当此数额重大到超越uint256限定后,变会发生溢出,此时关于用户来讲,其花费了伟大的代价却没有获得报答,是非常不友好的。

相比较来讲,用户一样可以或许应用相似的破绽举行作歹。比方SEC代币:

function buy() payable returns (uint256 amount){
        if(!usersCanTrade && !canTrade[msg.sender]) revert();
        amount = msg.value * buyPrice;                    // calculates the amount

        require(balanceOf[this] >= amount);               // checks if it has enough to sell
        balanceOf[msg.sender] += amount;                  // adds the amount to buyer's balance
        balanceOf[this] -= amount;                        // subtracts amount from seller's balance
        Transfer(this, msg.sender, amount);               // execute an event reflecting the change
        return amount;                                    // ends function and returns
    }

    //user is selling us grx, we are selling eth to the user
    function sell(uint256 amount) returns (uint revenue){
        require(!frozen[msg.sender]);
        if(!usersCanTrade && !canTrade[msg.sender]) {
            require(minBalanceForAccounts > amount/sellPrice);
        }
        require(balanceOf[msg.sender] >= amount);         // checks if the sender has enough to sell
        balanceOf[this] += amount;                        // adds the amount to owner's balance
        balanceOf[msg.sender] -= amount;                  // subtracts the amount from seller's balance
        revenue = amount / sellPrice;
        require(msg.sender.send(revenue));                // sends ether to the seller: it's important to do this last to prevent recursion attacks
        Transfer(msg.sender, this, amount);               // executes an event reflecting on the change
        return revenue;                                   // ends function and returns
    }

我们可以或许看到,在此合约中一样存在相似的乘法溢出题目。在buy()函数中,我们能发明合约对用户的合法性举行了提早的推断,并盘算出购置金额。而此处的购置金额运用函数:amount = msg.value * buyPrice。即传入代币数目*购置金额。当用户须要实行大批购置的要求时,amount变会涌现溢出从而用高金额猎取到低代币数目。

详细的操纵流程我们将在下章举行演示。

除存在乘法溢出破绽之外,该合约还存在不合理的函数设想,比方合约中均存在设置代币购置卖出的金额。

CVE-2019-1003031:[Jenkins]Matrix Project Plugin沙箱绕过漏洞

[1] CVE-2019-1003031:[Jenkins]Matrix Project Plugin 沙箱绕过 Matrix Project插件用于构建“多配置项目”,如多环境测试、平台指定构建等。 在其配置过程中接受用户指定的Groovy Script,在Matrix Project Plugin <= 1.13中存在沙箱被绕过的漏洞。 影响版本:Matrix Project Plugin <= 1.13 利用条件:具有Job/Configure 权限的用户 修复建议:升级到1.14或以上 [2] CVE-2019-1003029:[Jenkins]Script Security Plugin 沙箱绕过 Script Security插件集成在Jenkins的各种功能插件(比如Matrix Project插件)中,可以用来管理普通用户执行Groovy脚本的权限。 Jenkins的Script Security插件 <= 1.53中存在沙箱被绕过的漏洞。 影响版本:Script Security Plugin <= 1.53 利用条件:具有Overall/Read 权限的用户 修复建议:升级到1.54或以上(考虑到CVE-2019-1003040,需升级到1.56或以上) 参考: https://jenkins.io/security/advisory/2019-03-06/#SECURITY-1336 https://nvd.nist.gov/vuln/detail/CVE-2019-1003029 前一段时间,Jenkins官方的安全通告报了好几个严重漏洞,但是可能大家在狂欢Orange大佬的那个未授权RCE 看了Matrix Project Plugin相关的介绍 得知这个插件

function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

比方上述代码中许可owner举行对代币购置价钱、卖出价钱举行设置。而我们晓得,关于代币来讲,泉币的价钱须要经由历程市场来举行界说,而很大水平须要制止工资设定。

而在合约中我们发明用户购置、卖出代币均有响应的函数,而且此函数均运用先前owner界说的价钱。如许将会涌现异常大的题目。起首我们会假定owner作歹的状况,当owner作歹时将会歹意调高或许下降购置或许卖出代币的单价,此时会致使市场价钱的杂沓;其次,我们可以或许假定owner不举行作歹行动,然则只需合约中存在购置或卖出代币的单价状况,那末不可比曼的会带来其他题目。比方:

我们晓得以太坊运用的代币在市场上一样存在相对应的兑换汇率,即以太币兑换响应Token。但是此处又多出来了第二种兑换体式格局。这也就致使了中心存在哪种兑换更适宜的状况。比方:

  • 1 当合约卖出>市场购置价钱时,我们可以或许在市场上举行购置,并在合约中举行卖出。
  • 2 当合约购置价钱<市场卖出价钱时,我们经由历程合约举行对token举行购置并将此token卖出到市场上。

因而我们可以或许运用以上两种要领举行轮回套利。详细要领如图所示:

CVE-2018-12067及相似破绽剖析与相干思索

三、破绽模仿

我们将在本章模仿溢出历程。本次模仿我们运用测试情况并运用两个钱包地点举行交互测试。起首我们布置合约:

我们运用测试情况且地点为0xca35b7d915458ef540ade6068dfe2f44e8fa733c的账户举行。 肇端赋值给msg.sender账户余额为100000 。

CVE-2018-12067及相似破绽剖析与相干思索

以后我们模仿作歹owner,实验修正种种代币参数。

起首我们设置代币购置金额为100 。卖出金额为57896044618658097711785492504343953926634992332820282019728792003956564819969 。为何设置这个数字呢?我们经由历程盘算0xfff……fff(32个)为115792089237316195423570985008687907853269984665640564039457584007913129639935,而115792089237316195423570985008687907853269984665640564039457584007913129639935/2 = 57896044618658097711785492504343953926634992332820282019728792003956564819967。以是我们设置末尾数为9轻易我们检察。

我们可以或许看到我们这里取了极度状况后,sellPrice如图:

CVE-2018-12067及相似破绽剖析与相干思索

以后我们挪用sell函数卖出2个token,由于缺少溢出检查,以是这里天经地义会发生溢出题目。因而我们可以或许检察log日记纪录。

当卖出2token时,我们应该猎取2*57896044618658097711785492504343953926634992332820282019728792003956564819969的以太币,但是这里却只获得了2 wei的以太币。从而令用户蒙冤。

一样,本溢出适用于以下代码,测试一样可以或许杀青结果。这里就不再过多演示。

function buy() payable returns (uint256 amount){
        if(!usersCanTrade && !canTrade[msg.sender]) revert();
        amount = msg.value * buyPrice;                    // calculates the amount

        require(balanceOf[this] >= amount);               // checks if it has enough to sell
        balanceOf[msg.sender] += amount;                  // adds the amount to buyer's balance
        balanceOf[this] -= amount;                        // subtracts amount from seller's balance
        Transfer(this, msg.sender, amount);               // execute an event reflecting the change
        return amount;                                    // ends function and returns
    }

本合约存在代码层面以及设想方面的题目,现在来看隐患并非很大,然则存在了犯错误的能够。由于区块链信仰“代码即执法”的理念,以是不应该涌现这类题目隐患。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明CVE-2018-12067及相似破绽剖析与相干思索
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址