Introduction to Systems Security<br />Ben Livshits<br />10/16/2010<br />Some slides are borrowed from CS 155 at Stanford<b...
Organization<br />General introduction to security<br />What is system security?<br />Threats<br />Trends<br />Approaches ...
What is Security?<br />System correctness<br />If user supplies expected input, system generates desired output<br />Secur...
What is security?<br />System correctness<br />Good input  Good output<br />Think “verification”<br />Security<br />Bad i...
What is security?<br />System correctness<br />More features: better<br />Security<br />More features: can be worse<br />
Security properties<br />Confidentiality	<br />Information about system or its users cannot be learned by an attacker<br /...
General picture<br />System<br />Attacker<br />Alice<br />Security is about<br />Honest user (e.g., Alice, Bob, …)<br />Di...
Network security<br />Network Attacker<br />Intercepts and controls network communication<br />System<br />Alice<br />
Web security<br />System<br />Web Attacker<br />Sets up malicious site visited by victim; no control of network<br />Alice...
Operating system security<br />OS Attacker<br />Controls malicious files and applications<br />Alice<br />
System<br />Attacker<br />Alice<br />Confidentiality: Attacker does not learn Alice’s secrets<br />Integrity: Attacker doe...
Current Trends<br />
Historical hackers  (prior to 2000)<br />Profile:<br />Male<br />Between 14 and 34 years of age<br />Computer addicted<br ...
Typical Botherder: 0x80" (pronounced X-eighty)<br />Washington Post: Invasion of the Computer Snatchers<br />High school d...
Some things in the news<br />Nigerian letter (419 Scams) still works:<br />Michigan Treasurer Sends 1.2MUSD of State Funds...
Trends for 2010<br />Malware, worms, and Trojan horses<br />spread by email, instant messaging, malicious or infected webs...
Trends<br />
Operating system vulnerabilities<br />
Reported Web Vulnerabilities "In the Wild"<br />Data from aggregator and validator of  NVD-reported vulnerabilities<br />
Web vs System vulnerabilities<br />XSS peak<br />
Web attack toolkit: MPack<br />Basic setup<br />Toolkit hosted on web server<br />Infects pages on that server<br />Page v...
Finding Vulnerabilities <br />Static analysis<br />Abstract interpretation<br />Dataflow<br />Pointer analysis<br />etc.<b...
Necessary BackgroundonMemory Exploits and Web Application Vulnerabilities<br />23<br />
Outline<br />24<br />Memory safety attacks<br />Buffer overruns<br />Format string vulnerabilities<br />Web application vu...
Buffer Overflows<br />25<br />
Buffer Overrun Example<br />26<br />Frame 1<br />Frame 2<br />str<br />ret<br />sfp<br />local<br />str<br />ret<br />sfp<...
Input Validation<br />Classifying vulnerabilities:<br />Buffer overflows can be viewed as an example of improper input val...
Secure Programming Techniques<br />Validate all input<br />Easier said than done<br />Why is that?<br />Avoid buffer overf...
Validating Input<br />Determine acceptable input, check for match --- don’t just check against list of “non-matches”<br />...
Avoid strcpy, …<br />We have seen that strcpy is unsafe<br />strcpy(buf, str) simply copies memory contents into buf start...
Static and Dynamic Analysis<br />Static analysis: run on the source code prior to deployment; check for known flaws<br />e...
Dynamic analysis: Libsafe<br />Very simple example of what can be done at runtime<br />Intercepts all calls to, e.g., strc...
Preventing Buffer Overflows<br />Operating system support:<br />Can mark stack segment as non-executable<br />Randomize st...
Heap-based Buffer Overruns and Heap Spraying<br />34<br />Buffer overruns consist of two steps<br />Introduce the payload<...
StackGuard<br />Embed random “canaries” in stack frames and verify their integrity prior to function return<br />This is a...
More Methods …<br /> Address obfuscation<br />Encrypt return address on stack by XORing with random string.  Decrypt just ...
More Input Validation Flaws<br />37<br />
Format String Vulnerabilities<br />What is the difference between printf(buf);andprintf(“%s”, buf);?<br />What if buf hold...
Format String Exploits<br />Technique:<br />Declare a variable of type int in line 4 and call it bytes_formatted<br />Line...
Other Input Validation Bugs<br />Integer overflow…<br />Consider the code:strncpy(msg+offset, str, slen);<br />	where the ...
Web Application Vulnerabilities<br />41<br />
SQL Injection Attacks<br />Affect applications that use untrusted input as part of an SQL query to a back-end database<br ...
SQL Injection: Example<br />Consider a browser form, e.g.:<br />When the user enters a number and clicks the button, this ...
Example Continued…<br />Upon receiving the request, a Java program might produce an SQL query as follows:<br />A normal qu...
Example Continued…<br />What if the user makes a modified http request:https://www.pizza.com/show_orders?month=0%20OR%201%...
Example Continued<br />So the script generates the following SQL query:<br />Since AND takes precedence over OR, the above...
Even Worse…<br />Craft an http request that generates an SQL query like the following:<br />Attacker gets the entire credi...
More Damage…<br />SQL queries can encode multiple commands, separated by ‘;’<br />Craft an http request that generates an ...
More Damage…<br />Craft an http request that generates an SQL query like the following:<br />User (with chosen password) e...
May Need to be More Clever…<br />Consider the following script for text queries:<br />Previous attacks will not work direc...
Example Continued…<br />Craft an http request where          request.getParameter(“topping”)is set toabc’; DROP TABLE cred...
Source: http://xkcd.com/327/<br />52<br />
Solutions?<br />Blacklisting<br />Whitelisting<br />Encoding routines<br />Prepared statements/bind variables<br />Mitigat...
Blacklisting?<br />I.e., searching for/preventing ‘bad’ inputs<br />E.g., for previous example:<br />…where kill_chars() d...
Drawbacks of Blacklisting<br />How do you know if/when you’ve eliminated all possible ‘bad’ strings?<br />If you miss one,...
Whitelisting<br />Check that user-provided input is in some set of values known to be safe<br />E.g., check that month is ...
Prepared Statements/bind Variables<br />Prepared statements: static queries with bind variables<br />Variables not involve...
A SQL Injection Example in Java<br />PreparedStatementps =<br />db.prepareStatement(                "SELECT pizza, quantit...
There’s Even More<br />59<br />Practical SQL Injection: Bit by Bit<br />Overall, SQL injection is easy to fix by banning c...
Cross-site Scripting<br />60<br />If the application is not careful to encode its output data, an attacker can inject scri...
Upcoming SlideShare
Loading in...5
×

20101017 program analysis_for_security_livshits_lecture03_security

589

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
589
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
11
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

20101017 program analysis_for_security_livshits_lecture03_security

  1. 1. Introduction to Systems Security<br />Ben Livshits<br />10/16/2010<br />Some slides are borrowed from CS 155 at Stanford<br />
  2. 2. Organization<br />General introduction to security<br />What is system security?<br />Threats<br />Trends<br />Approaches to finding vulnerabilities<br />Security vulnerabilities<br />Memory-based exploits<br />Web application vulnerabilities<br />
  3. 3. What is Security?<br />System correctness<br />If user supplies expected input, system generates desired output<br />Security<br />If attacker supplies unexpected input, system does not fail in certain ways<br />Goal of the attacker is to make the system fail in “interesting ways”<br />
  4. 4. What is security?<br />System correctness<br />Good input  Good output<br />Think “verification”<br />Security<br />Bad input  Bad output<br />Think “not exploitable”<br />
  5. 5. What is security?<br />System correctness<br />More features: better<br />Security<br />More features: can be worse<br />
  6. 6. Security properties<br />Confidentiality <br />Information about system or its users cannot be learned by an attacker<br />Integrity<br />The system continues to operate properly, only reaching states that would occur if there were no attacker<br />Availability<br />Actions by an attacker do not prevent users from having access to use of the system<br />
  7. 7. General picture<br />System<br />Attacker<br />Alice<br />Security is about<br />Honest user (e.g., Alice, Bob, …)<br />Dishonest Attacker<br />How the Attacker <br />Disrupts honest user’s use of the system (Integrity, Availability)<br />Learns information intended for Alice only (Confidentiality)<br />
  8. 8. Network security<br />Network Attacker<br />Intercepts and controls network communication<br />System<br />Alice<br />
  9. 9. Web security<br />System<br />Web Attacker<br />Sets up malicious site visited by victim; no control of network<br />Alice<br />
  10. 10. Operating system security<br />OS Attacker<br />Controls malicious files and applications<br />Alice<br />
  11. 11. System<br />Attacker<br />Alice<br />Confidentiality: Attacker does not learn Alice’s secrets<br />Integrity: Attacker does not undetectably corrupt system’s function for Alice<br />Availability: Attacker does not keep system from being useful to Alice<br />
  12. 12. Current Trends<br />
  13. 13. Historical hackers (prior to 2000)<br />Profile:<br />Male<br />Between 14 and 34 years of age<br />Computer addicted<br />No permanent girlfriend<br />No Commercial Interest !!!<br />Source: Raimund Genes<br />
  14. 14. Typical Botherder: 0x80" (pronounced X-eighty)<br />Washington Post: Invasion of the Computer Snatchers<br />High school dropout<br />“…most of these people I infect are so stupid they really ain't got no business being on the Internet in the first place.“<br />Working hours: approx. 2 minutes/day to manage Botnet<br />Monthly earnings: $6,800 on average<br />Daily Activities: <br />Chatting with people while his bots make him money<br />Recently paid $800 for an hour alone in a VIP room with several dancers<br />Job Description: <br />Controls 13,000+ computers in more than 20 countries <br />Infected Bot PCs download Adware then search for new victim PCs<br />Adware displays ads and mines data on victim's online browsing habits.<br />Bots collect password, e-mail address, SS#, credit and banking data<br />Gets paid by companies like TopConverting.com, GammaCash.com, Loudcash, or 180Solutions.<br />14<br />
  15. 15. Some things in the news<br />Nigerian letter (419 Scams) still works:<br />Michigan Treasurer Sends 1.2MUSD of State Funds !!!<br />Many zero-day attacks<br />Google, Excel, Word, Powerpoint, Office …<br />Criminal access to important devices<br />Numerous lost, stolen laptops, storage media, containing customer information<br />Second-hand computers (hard drives) pose risk<br />Vint Cerf estimates ¼ of PCs on Internet are bots<br />15<br />
  16. 16. Trends for 2010<br />Malware, worms, and Trojan horses<br />spread by email, instant messaging, malicious or infected websites<br />Botnets and zombies<br />improving their encryption capabilities, more difficult to detect<br />Scareware – fake/rogue security software <br />Attacks on client-side software<br />browsers, media players, PDF readers, etc. <br />Ransom attacks<br />malware encrypts hard drives, or DDOS attack<br />Social network attacks <br />Users’ trust in online friends makes these networks a prime target. <br />Cloud Computing - growing use will make this a prime target for attack. <br />Web Applications - developed with inadequate security controls <br />Budget cuts - problem for security personnel and a boon to cyber criminals. <br />Texas CISO, Feb 2010<br />Same list in Oklahoma Monthly Security Tips Newsletter<br />
  17. 17. Trends<br />
  18. 18. Operating system vulnerabilities<br />
  19. 19. Reported Web Vulnerabilities "In the Wild"<br />Data from aggregator and validator of  NVD-reported vulnerabilities<br />
  20. 20. Web vs System vulnerabilities<br />XSS peak<br />
  21. 21. Web attack toolkit: MPack<br />Basic setup<br />Toolkit hosted on web server<br />Infects pages on that server<br />Page visitors get infected<br />Features<br />Customized: determines exploit on the fly, based on user’s OS, browser, etc<br />Easy to use: management console provides stats on infection rates<br />Customer care toolkit can be purchased with one-year support contract!<br />21<br />
  22. 22. Finding Vulnerabilities <br />Static analysis<br />Abstract interpretation<br />Dataflow<br />Pointer analysis<br />etc.<br />Runtime analysis <br />Fuzzing<br />Testing<br />Simulation<br />Symbolic execution<br />Model checking<br />
  23. 23. Necessary BackgroundonMemory Exploits and Web Application Vulnerabilities<br />23<br />
  24. 24. Outline<br />24<br />Memory safety attacks<br />Buffer overruns<br />Format string vulnerabilities<br />Web application vulnerabilities<br />SQL injections<br />Cross-site scripting attacks<br />
  25. 25. Buffer Overflows<br />25<br />
  26. 26. Buffer Overrun Example<br />26<br />Frame 1<br />Frame 2<br />str<br />ret<br />sfp<br />local<br />str<br />ret<br />sfp<br />local<br />void lame (void) { <br />char small[30]; <br /> gets(small); <br />printf("%s ", small); <br />}<br />
  27. 27. Input Validation<br />Classifying vulnerabilities:<br />Buffer overflows can be viewed as an example of improper input validation<br />Another related type of vulnerability is information leaks<br />Other notable examples:<br />Format string vulnerabilities<br />SQL injection attacks<br />Cross-site scripting attacks<br />Mechanisms to prevent attacks<br />Better input validation<br />Safe programming techniques<br />Techniques for detecting potential buffer overflows in code<br />Static analysis<br />Runtime analysis<br />Fuzzing/penetration testing<br />Write-box fuzzing<br />etc.<br />27<br />
  28. 28. Secure Programming Techniques<br />Validate all input<br />Easier said than done<br />Why is that?<br />Avoid buffer overflows<br />Use safe string manipulation functions <br />Careful length checking<br />Avoid statically declared arrays<br />etc.<br />Or use a memory-safe language<br />Java or C#<br />JavaScript (not type-safe)<br />28<br />
  29. 29. Validating Input<br />Determine acceptable input, check for match --- don’t just check against list of “non-matches”<br />Limit maximum length<br />Watch out for special characters, escape chars.<br />Check bounds on integer values<br />Check for negative inputs<br />Check for large inputs that might cause overflow!<br />29<br />
  30. 30. Avoid strcpy, …<br />We have seen that strcpy is unsafe<br />strcpy(buf, str) simply copies memory contents into buf starting from *str until “” is encountered, ignoring the size of buf<br />Avoid strcpy(), strcat(), gets(), etc.<br />Use strncpy(), strncat(), instead<br />Still, computing proper bounds is difficult in practice<br />Easy to mess up, off-by-one errors are common<br />30<br />
  31. 31. Static and Dynamic Analysis<br />Static analysis: run on the source code prior to deployment; check for known flaws<br />e.g., flawfinder, cqual<br />Or Prefix/Prefast<br />Or Coverityor Fortify tools<br />Will look at some more recent work in this course as well as older stuff<br />Dynamic analysis: try to catch (potential) buffer overflows during program execution<br />Soundness<br />Precision<br />Comparison?<br />Static analysis very useful, but not perfect<br />False positives<br />False negatives<br />Dynamic analysis can be better (in tandem with static analysis), but can slow down execution<br />Historically of great importance, drove adoption of type-safe languages such as Java and C#<br />31<br />
  32. 32. Dynamic analysis: Libsafe<br />Very simple example of what can be done at runtime<br />Intercepts all calls to, e.g., strcpy(dest, src)<br />Validates sufficient space in current stack frame: |frame-pointer – dest| > strlen(src)<br />If so, executes strcpy; otherwise, terminates application<br />32<br />
  33. 33. Preventing Buffer Overflows<br />Operating system support:<br />Can mark stack segment as non-executable<br />Randomize stack location<br />Problems:<br />Does not defend against `return-to-libc’ exploit<br />Overflow sets ret-addr to address of libc function<br />Does not prevent general buffer overflow flaws, or heap overflow<br />Basic heap overflows can be helped with ALSR<br />33<br />
  34. 34. Heap-based Buffer Overruns and Heap Spraying<br />34<br />Buffer overruns consist of two steps<br />Introduce the payload<br />Cause the program to jump to it<br />Can put the payload/shellcode in the heap<br />Arbitrary amounts of code<br />Doesn’t work with heap randomization<br />Location of the payload changes every time<br />Heap spraying:<br />Allocate multiple copies of the payload<br />When the jump happens, it hits the payload with a high probability<br />
  35. 35. StackGuard<br />Embed random “canaries” in stack frames and verify their integrity prior to function return<br />This is actually used!<br />Helpful, but not foolproof…<br />Frame 1<br />Frame 2<br />str<br />ret<br />sfp<br />local<br />canary<br />str<br />ret<br />sfp<br />local<br />canary<br />35<br />
  36. 36. More Methods …<br /> Address obfuscation<br />Encrypt return address on stack by XORing with random string. Decrypt just before returning from function<br />Attacker needs decryption key to set return address to desired value<br />36<br />
  37. 37. More Input Validation Flaws<br />37<br />
  38. 38. Format String Vulnerabilities<br />What is the difference between printf(buf);andprintf(“%s”, buf);?<br />What if buf holds %x ?<br />Look at memory, and what printf expects…<br />38<br />
  39. 39. Format String Exploits<br />Technique:<br />Declare a variable of type int in line 4 and call it bytes_formatted<br />Line 6 the format string specifies that 20 characters should be formatted in hexadecimal (“%.20x”) using buffer<br />When this is done, due to the “%n” specifier write the value 20 to bytes_formatted<br />Result:<br />This means that we have written a value to another memory location<br />Very definition of violating memory safety<br />May be possible to gain control over a program’s execution<br />#include <stdio.h><br />int main() {<br />intbytes_formatted=0;<br /> char buffer[28]=”ABCDEFGHIJKLMNOPQRSTUVWXYZ”;<br /> printf(“%.20x%n”,buffer,&bytes_formatted);<br />printf(<br /> “ The number of bytes formatted in the previous printf statement <br /> was %d ”,bytes_formatted);  return 0;<br />} <br />39<br />
  40. 40. Other Input Validation Bugs<br />Integer overflow…<br />Consider the code:strncpy(msg+offset, str, slen);<br /> where the adversary may control offset<br />By setting the value high enough, it will wrap around and be treated as a negative integer!<br />Write into the msg buffer instead of after it<br />40<br />
  41. 41. Web Application Vulnerabilities<br />41<br />
  42. 42. SQL Injection Attacks<br />Affect applications that use untrusted input as part of an SQL query to a back-end database<br />Specific case of a more general problem: using untrusted input in commands<br />42<br />
  43. 43. SQL Injection: Example<br />Consider a browser form, e.g.:<br />When the user enters a number and clicks the button, this generates an http request like https://www.pizza.com/show_orders?month=10<br />43<br />
  44. 44. Example Continued…<br />Upon receiving the request, a Java program might produce an SQL query as follows:<br />A normal query would look like:<br />sql_query<br /> = "SELECT pizza, quantity, order_day "<br /> + "FROM orders " <br /> + "WHERE userid=" + session.getCurrentUserId() + " AND order_month= "<br /> + request.getParameter("month");<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND order_month=10<br />44<br />
  45. 45. Example Continued…<br />What if the user makes a modified http request:https://www.pizza.com/show_orders?month=0%20OR%201%3D1<br />(Parameters transferred in URL-encoded form, where meta-characters are encoded in ASCII)<br />This has the effect of settingrequest.getParameter(“month”)equal to the string0 OR 1=1<br />45<br />
  46. 46. Example Continued<br />So the script generates the following SQL query:<br />Since AND takes precedence over OR, the above always evaluates to TRUE<br />The attacker gets every entry in the database!<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND order_month=0 OR 1=1<br />(<br />)<br />46<br />
  47. 47. Even Worse…<br />Craft an http request that generates an SQL query like the following:<br />Attacker gets the entire credit card database as well!<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND order_month=0 OR 1=0UNION SELECT cardholder, number, exp_dateFROM creditcards<br />47<br />
  48. 48. More Damage…<br />SQL queries can encode multiple commands, separated by ‘;’<br />Craft an http request that generates an SQL query like the following:<br />Credit card table deleted!<br />DoS attack<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND order_month=0 ;DROP TABLE creditcards<br />48<br />
  49. 49. More Damage…<br />Craft an http request that generates an SQL query like the following:<br />User (with chosen password) entered as an administrator!<br />Database owned!<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND order_month=0 ;INSERT INTO admin VALUES (‘hacker’, ...)<br />49<br />
  50. 50. May Need to be More Clever…<br />Consider the following script for text queries:<br />Previous attacks will not work directly, since the commands will be quoted<br />But easy to deal with this…<br />sql_query<br /> = "SELECT pizza, quantity, order_day "<br /> + "FROM orders " <br /> + "WHERE userid=" + session.getCurrentUserId() + " AND topping= ‘ "<br /> + request.getParameter(“topping") + “’”<br />50<br />
  51. 51. Example Continued…<br />Craft an http request where request.getParameter(“topping”)is set toabc’; DROP TABLE creditcards; --<br />The effect is to generate the SQL query:<br />(‘--’ represents an SQL comment)<br />SELECT pizza, quantity, order_day<br />FROM orders<br />WHERE userid=4123 AND toppings=‘abc’;DROP TABLE creditcards ; --’<br />51<br />
  52. 52. Source: http://xkcd.com/327/<br />52<br />
  53. 53. Solutions?<br />Blacklisting<br />Whitelisting<br />Encoding routines<br />Prepared statements/bind variables<br />Mitigate the impact of SQL injection<br />53<br />
  54. 54. Blacklisting?<br />I.e., searching for/preventing ‘bad’ inputs<br />E.g., for previous example:<br />…where kill_chars() deletes, e.g., quotes and semicolons<br />sql_query<br /> = "SELECT pizza, quantity, order_day "<br /> + "FROM orders " <br /> + "WHERE userid=" + session.getCurrentUserId() + " AND topping= ‘ "<br /> + kill_chars(request.getParameter(“topping")) + “’”<br />54<br />
  55. 55. Drawbacks of Blacklisting<br />How do you know if/when you’ve eliminated all possible ‘bad’ strings?<br />If you miss one, could allow successful attack<br />Does not prevent first set of attacks (numeric values)<br />Although similar approach could be used, starts to get complex!<br />May conflict with functionality of the database<br />E.g., user with name O’Brien<br />55<br />
  56. 56. Whitelisting<br />Check that user-provided input is in some set of values known to be safe<br />E.g., check that month is an integer in the right range<br />If invalid input detected, better to reject it than to try to fix it<br />Fixes may introduce vulnerabilities<br />Principle of fail-safe defaults<br />56<br />
  57. 57. Prepared Statements/bind Variables<br />Prepared statements: static queries with bind variables<br />Variables not involved in query parsing<br />Bind variables: placeholders guaranteed to be data in correct format<br />57<br />
  58. 58. A SQL Injection Example in Java<br />PreparedStatementps =<br />db.prepareStatement( "SELECT pizza, quantity, order_day "<br /> + "FROM orders WHERE userid=? AND order_month=?");<br />ps.setInt(1, session.getCurrentUserId());<br />ps.setInt(2, Integer.parseInt(request.getParameter("month")));<br />ResultSet res = ps.executeQuery();<br />Bind variables<br />58<br />
  59. 59. There’s Even More<br />59<br />Practical SQL Injection: Bit by Bit<br />Overall, SQL injection is easy to fix by banning certain APIs<br />Prevent queryExecute-type calls with non-constant arguments<br />Very easy to automate<br />See a tool like LAPSE that does it for Java<br />
  60. 60. Cross-site Scripting<br />60<br />If the application is not careful to encode its output data, an attacker can inject script into the output<br />out.writeln(“<div>”);<br />out.writeln(req.getParameter(“name”));<br />out.writeln(“</div>”);<br />name: <br /><script>…; xhr.send(document.cookie);</script><br />Simplest version called reflected or type-1 XSS<br />
  61. 61. Memory Exploits and Web App Vulnerabilities Compared<br />Buffer overruns<br />Stack-based<br />Return-to-libc, etc.<br />Heap-based<br />Heap spraying attacks<br />Requires careful programming or memory-safe languages <br />Don’t always help as in the case of JavaScript-based spraying<br />Static analysis tools<br />Format string vulnerabilies<br />Generally, better, more restrictive APIs are enough<br />Simple static tools help<br />Cross-site scripting<br />XSS-0, -1, -2, -3<br />Requires careful programming<br />Static analysis tools<br />SQL injection<br />Generally, better, more restrictive APIs are enough<br />Simple static tools help<br />61<br />
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×