欢迎来到智能合约审计初学者指南! 开始进行智能合约审计的最佳方法之一是进入并查看智能合约中的一些常见漏洞类型。
如果您已经对以太坊的 Solidity 编程语言有基本的了解,那将会很有帮助。 我们将看看 Noob solidity 程序员编写的一些代码。
重入攻击
真实场景:
想象一下,你有 50 块巧克力。 你有一个顽皮的小妹妹,你只允许她在任何时候从你那里拿走 2 块巧克力。 你也不想一天给她超过 10 块巧克力,担心她会蛀牙。 为确保这一点,您每天晚上都会数一数您还剩多少巧克力。 你认为这行得通吗? 或者你会被你的小妹妹黑掉吗?
不幸的是,它不会工作! 你姐姐发现你直到晚上才知道你有多少巧克力。 所以就在第二天,你的小妹妹在晚上前来看你6次,每次吃2块巧克力! 这就是我们所说的重入攻击。
在这里,您正在更新您晚上拥有的巧克力数量,而不是每次您姐姐从您那里拿走 2 块巧克力时都更新该数量。 这也是智能合约发生的情况。 智能合约假设一个特定的平衡,而攻击者实际上正忙于从合约中多次提取一定数量的加密货币。
真实世界的代码示例:
这段代码属于一个名为的智能合约 没有银行账户. 只要 msg.sender 的余额(即调用者 withdraw
function ) 大于或等于要求提款的金额。
function withdraw(uint _amount) { require(balances[msg.sender] >= _amount); msg.sender.call.value(_amount)(); balances[msg.sender] -= _amount;
}
请注意,有一个 call 关键字用于将所需数量的以太币发送到 msg.sender
. 攻击者可以通过创建一个名为 Thief 的合约来利用这一点,在该合约中,他在 fallback()
功能。 一种 fallback()
Solidity 中的函数是一个特殊函数,当以太币发送到智能合约时会被执行。
这意味着攻击者能够 递归调用withdraw函数. 因此,在智能合约更新之前, msg.sender
在最后一行代码中,攻击者已经多次提取以太币。 如果在使用 call 关键字之前更新余额,则可以避免这种情况,因此遵循 检查效果交互 格局。
影响:
首次重入攻击 2016 年发生在一个 DAO(去中心化自治组织)上,导致大约 50 万美元的黑客攻击。 为了扭转这种黑客行为,以太坊社区分裂了以太坊区块链,从而产生了 ETC(以太坊经典)和 ETH(以太坊)。
算术上溢和下溢
真实场景:
让我们玩一个思维游戏。 它由一个旋转轮子组成,获胜者是根据他在旋转轮子时能够获得的最大数字来决定的。 车轮从 256 到 -256 都标有标记。
游戏规则是所有玩家的指针在每次旋转开始时都停留在 0 上。 并且玩家只能向负数方向旋转。 你将如何赢得这场比赛?
每次赢得这场比赛的一个好策略是用如此大的力量旋转轮盘,使轮盘旋转到 -256,然后一次转到 256。 这是可能的,因为 256 就在车轮上的 -256 之后。 这就是我们所说的算术下溢。 算术溢出正好相反。
真实世界的代码示例:
An 下溢或上溢 当算术运算达到其最小值或最大值时发生。
function withdraw(uint _amount) public { require(balances[msg.sender] - _amount > 0); address payable to = payable(msg.sender); to.transfer(_amount); balances[msg.sender] -= _amount;
}
_amount
撤回函数的参数是一个无符号整数。 余额映射的值(类似于 python 中的字典或 C++ 或 Java 中的键值对)也是一个无符号整数。
mapping(address => uint256) public balances
所需的报表检查是否余额 msg.sender
是积极的与否。 但即使金额大于 msg.sender
. 这是因为两者 balances
和 _amount
变量是无符号整数类型,它们的算术结果(下溢之后)也将是无符号整数!
您可能还记得,无符号整数始终为正数。 这意味着攻击者可以从智能合约中提取无限量的以太币! 您可以找到该漏洞的详细示例和实现代码 点击此处.
这里要注意的另一个关键点是,两个无符号整数之间的算术运算也是一个无符号整数。 如果在智能合约中忽略这一点可能会很危险,因为它可能导致不必要的安全漏洞!
function votes(uint postId, uint upvote, uint downvotes) { if (upvote - downvote < 0) { deletePost(postId) }
}
正如您在上面的示例中可能已经注意到的那样,if 语句毫无意义 upvote - downvote
总是积极的。 而且帖子会被删除,即使 downvotes
大于 upvotes
. 为避免此类攻击,建议使用大于等于的 Solidity 编译器版本 0.8.0.
影响:
一枚硬币叫 PoWH 币 于 2017 年推出。虽然它是一款庞氏游戏,但由于算术溢出错误,它本身被黑客入侵,导致当时损失约 866 ETH 或 950,000 美元。 您可以详细阅读此内容 点击此处.
必读: 攻击 Tinyman 的教训,Algorand 上最大的 DEX
拒绝服务攻击
真实场景:
想象一下你在比特币科技大学。 一切似乎都很好,只是每个人都有一张公共餐桌。 不幸的是,很少有其他班的人总是比你们班的任何人先占据餐桌。
在实际情况下,他们拒绝为每个人提供基本服务,从而导致宝贵的时间损失。 这就是我们所说的“拒绝服务攻击”。
真实世界的代码示例:
在游戏中 以太之王,任何人都可以成为国王。 但成为国王的规则是,一个人应该存入比现任国王更多的以太币。 这可以通过调用 claimThrone()
以太之王合约的功能,其中人将以太币直接发送给前任国王并成为新国王。
function claimThrone() external payable { require(msg.value > balance, "Need to pay more to become the king"); (bool sent, ) = king.call{value: balance}(""); require(sent, "Failed to send Ether"); balance = msg.value; king = msg.sender; }
正如您可能已经猜到的那样,这段代码很容易受到 DoS 攻击,但是如何呢? 为此,您需要了解以太坊中有两种类型的地址 - 首先是 外部地址 拥有账户或只是钱包的地址,第二个是 合同地址. 现在可以从这些地址类型中的任何一种发送以太币。
如果这样,以太币是由合约地址发送的,那么合约将成为国王。 但是让我们假设这个新合同没有 fallback()
如果合约想要接受以太币,这是必要的功能。 然后,如果一个新人出现并试图打电话给 claimThrone()
功能,它总是会失败!
请注意,发生这种情况的部分原因是 claimThrone()
函数在第二个必需语句中显式检查以太币的转移是否成功。 您可以找到完整的代码并对其进行 DoS 攻击 点击此处.
如果代码在大数组上存在循环,则代码也可能容易受到 DoS 攻击。 发生这种情况是因为 气体限制 在这种情况下可以超过。 你可以阅读它 点击此处.
影响:
所谓的游戏 政府部门,这显然是一个庞氏骗局,因为处理支付需要大量的气体,所以被 1100 以太币卡住了。
不安全的随机性
真实场景:
从前有一个叫赫斯基的人,他的猴子佩斯基总是陪伴着他。 赫斯基进行彩票游戏并获得了丰厚的利润。 有一天,爱丽丝注意到赫斯基正专注地盯着他的猴子佩斯基。 然后她看到他在一张纸上写了些什么,然后把它封在一个信封里。 出于好奇,她决定进一步调查。
那天晚上晚些时候,爱丽丝看到彩票的中奖者是通过公开打开密封的信封来决定的。 看了几天之后,Alice 发现 Hesky 是通过看 Pesky 的手势来决定中奖号码的(例如如果猴子挠头,Hesky 会记下 10)! 现在爱丽丝有了赢得每张彩票的公式,只需购买正确号码的彩票!
赫斯基曾假设永远无法弄清楚他决定彩票中奖者的“随机”方式,但他确实是错误的。
真实世界的代码示例:
在这个例子中,随机数是根据区块编号和区块时间戳组合的哈希值生成的。 然后将此哈希分配给答案变量。 现在,任何猜到这个(看似)随机数的人,都会得到 1 个以太币的奖励。 你认为这是不可破解的吗?
function guess(uint _guess) public { uint answer = uint( keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)) ); if (_guess == answer) { (bool sent, ) = msg.sender.call{value: 1 ether}(""); require(sent, "Failed to send Ether"); } }
没有! 攻击者仍然可以通过简单地复制粘贴代码来生成分配给答案变量的值,并将相同的答案变量传递给 guess()
功能,你可以自由选择你想了解的本国机构 !
guessTheRandomNumber.guess(answer);
你可以找到完整的代码 点击此处. 为避免这种攻击,建议使用可验证随机函数,例如 链式VRF.
影响:
大约 400 ETH 因对 智能十亿彩票 合同。 令人惊讶的是,甚至合同彩票本身也是一个庞氏骗局(哎哟!)。
时间操纵
真实场景:
中本聪喜欢吃饼干。 他喜欢他妈妈做的各种饼干。 但他妈妈很严格,觉得饼干吃多了对他不好。 所以他的母亲规定他只能在晚上 8 点得到饼干。
那天晚上 7 点 45 分,中本聪跑向他的母亲要饼干。 他的母亲询问——“现在几点了?”
“现在是 8 点钟!” ——他回答。
“好的。 然后把我橱柜里的饼干拿走。”
因此,Satoshi 成功地将时间操纵了 15 分钟,从而获得了他的饼干! 多么渴望饼干的家伙啊!
真实世界的代码示例:
一个区块的时间戳可以通过大约 15秒 由矿工。 通过这种方式,矿工可以设置一个有利的时间戳,并将他的交易包含在他开采的同一个区块中。 功能 play()
属于名为 G-Dot 的游戏合约。
function play() public { require(now > 1640392200 && neverPlayed == true); neverPlayed = false; msg.sender.transfer(1500 ether);
}
该合约奖励第一个调用 play 函数的玩家 1500 以太币。 但是正如你所看到的,播放函数只有在交易的 now 或 block.timestamp 包含对 play()
函数,大于 时代 1640392200.
矿工可以很容易地操纵这个时间戳,并包括他调用 play()
在同一块中发挥作用,这样他自己就是第一个玩家。 这样就保证了矿工会赢得比赛!
影响:
block.timestamp 用于在 政府 因此容易受到时间操纵攻击。
联系 QuillAudits
QuillAudits 是一个安全的智能合约审计平台,由 羽毛笔散列
技术。
它是一个审计平台,通过使用静态和动态分析工具、气体分析仪和模拟器进行有效的人工审查,严格分析和验证智能合约以检查安全漏洞。 此外,审计过程还包括广泛的单元测试和结构分析。
我们进行智能合约审计和渗透测试以发现潜力
可能损害平台完整性的安全漏洞。
如果您在智能合约审计方面需要任何帮助,请随时联系我们的专家 在这里!
要了解我们的最新工作,请加入我们的社区:-
Twitter | LinkedIn | Facebook | Telegram
该职位 智能合约审计初学者指南:第 1 部分 最早出现 Quillhash博客.
资料来源:https://blog.quillhash.com/2022/01/19/beginners-guide-to-smart-contract-auditing-part-1/
- "
- &
- 000
- 2016
- 7
- 关于我们
- 账号管理
- 地址
- 所有类型
- 已经
- 尽管
- 分析
- 审计
- 自主性
- 开始
- 最佳
- 比特币
- blockchain
- 问题
- 购买
- 呼叫
- 例
- 支票
- 经典
- 码
- 组合
- 相当常见
- 社体的一部分
- 包含
- 合同
- 合同的
- 曲奇饼
- 可以
- 创造
- 加密
- 电流
- DAO
- 天
- 分散
- 拒绝服务
- 细节
- 地塞米松
- 向下
- 容易
- 吃
- ETH
- 以太币
- 复仇
- 燕窝块
- 复仇经典
- 例子
- 利用
- 结束
- 姓氏:
- Free
- 功能
- 游戏
- Games
- 天然气
- 生成
- GitHub上
- 去
- 非常好
- 指南
- 破解
- 黑客
- 哈希
- 头
- 点击此处
- 创新中心
- HTTPS
- 调查
- IT
- 爪哇岛
- 加入
- 跳
- 国王
- 语言
- 大
- Line
- 长
- 寻找
- 抽奖
- 男子
- 百万
- 母亲
- 数字
- 组织
- 纸类
- 模式
- 员工
- 片
- 平台
- 播放
- 播放机
- 庞氏骗局
- 庞氏骗局
- 功率
- 过程
- 程序员
- 代码编程
- 国家
- 反转
- 检讨
- 奖励
- 定位、竞价/采购和分析/优化数字媒体采购,但算法只不过是解决问题的操作和规则。
- 聪
- 保安
- 集
- 智能
- 聪明的合同
- 智能合同
- So
- 坚固
- 东西
- 纺
- 分裂
- 开始
- 个人陈述
- 策略
- 成功
- 顺利
- 科技
- 测试
- 通过
- 次
- 工具
- 交易
- 没有银行账户
- 大学
- 最新动态
- 折扣值
- 漏洞
- 漏洞
- 脆弱
- 钱包
- 什么是
- 轮
- WHO
- 赢
- 工作
- 写作